You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2022/04/11 07:52:34 UTC

[GitHub] [incubator-nuttx] anjiahao1 opened a new pull request, #6029: add strptime support

anjiahao1 opened a new pull request, #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029

   ## Summary
   add strptime support
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848084288


##########
include/time.h:
##########
@@ -200,6 +200,8 @@ FAR struct tm *localtime_r(FAR const time_t *timep, FAR struct tm *result);
 
 size_t strftime(FAR char *s, size_t max, FAR const char *format,
                 FAR const struct tm *tm) strftimelike(3);
+FAR char *strptime(FAR const char *s, FAR const char *format,
+                   FAR struct tm *tm);

Review Comment:
   ```suggestion
   #ifdef _XOPEN_SOURCE
   FAR char *strptime(FAR const char *s, FAR const char *format,
                      FAR struct tm *tm);
   #endif
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 merged pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 merged PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r847552771


##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: strptime
+ *
+ * Description:
+ *   Convert a string to a time type according to a specific time format
+ *   The strptime() function processes the input string from left to
+ *   right.  Each of the three possible input elements (whitespace,
+ *   literal, or format) are handled one after the other.  If the
+ *   input cannot be matched to the format string, the function stops.
+ *   The remainder of the format and input strings are not processed.
+ *   The supported input field descriptors are listed below.  In case
+ *   a text string (such as the name of a day of the week or a month
+ *   name) is to be matched, the comparison is case insensitive.  In
+ *   case a number is to be matched, leading zeros are permitted but
+ *   not required.
+ *   %a     The abbreviated weekday name according to the current locale.
+ *   %A     The full weekday name according to the current locale.
+ *   %b     The abbreviated month name according to the current locale.
+ *   %B     The full month name according to the current locale.
+ *   %C     The century number (year/100) as a 2-digit integer. (SU)
+ *   %d     The day of the month as a decimal number (range 01 to 31).
+ *   %e     Like %d, the day of the month as a decimal number, but a leading
+ *          zero is replaced by a space.
+ *   %h     Equivalent to %b.  (SU)
+ *   %H     The hour as a decimal number using a 24-hour clock
+ *          (range 00 to 23).
+ *   %I     The  hour as a decimal number using a 12-hour clock
+ *          (range 01 to 12).
+ *   %j     The day of the year as a decimal number (range 001 to 366).
+ *   %k     The hour (24-hour clock) as a decimal number (range  0  to  23);
+ *          single digits are preceded by a blank.  (See also %H.)  (TZ)
+ *   %l     The  hour  (12-hour  clock) as a decimal number (range 1 to 12);
+ *          single digits are preceded by a blank.  (See also %I.)  (TZ)
+ *   %m     The month as a decimal number (range 01 to 12).
+ *   %M     The minute as a decimal number (range 00 to 59).
+ *   %n     A newline character. (SU)
+ *   %p     Either "AM" or "PM" according to the given time  value, or the
+ *          corresponding  strings  for the current locale.  Noon is treated
+ *          as "PM" and midnight as "AM".
+ *   %P     Like %p but in lowercase: "am" or "pm" or a corresponding string
+ *          for the current locale. (GNU)
+ *   %S     The second as a decimal number (range 00 to 60).  (The range is
+ *          up to 60 to allow for occasional leap seconds.)
+ *   %t     A tab character. (SU)
+ *   %y     The year as a decimal number without a century (range 00 to 99).
+ *   %Y     The year as a decimal number including the century.
+ *   %%     A literal '%' character.
+ *
+ * Returned Value:
+ *   The return value of the function is a pointer to the first
+ *   character not processed in this function call.  In case the input
+ *   string contains more characters than required by the format
+ *   string, the return value points right after the last consumed
+ *   input character.  In case the whole input string is consumed, the
+ *   return value points to the null byte at the end of the string.
+ *   If strptime() fails to match all of the format string and
+ *   therefore an error occurred, the function returns NULL.
+ *
+ ****************************************************************************/
+
+char *strptime(const char *buf, const char *fmt, struct tm *tm)

Review Comment:
   ```suggestion
   char *strptime(FAR const char *buf, FAR const char *fmt, FAR struct tm *tm)
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: strptime
+ *
+ * Description:
+ *   Convert a string to a time type according to a specific time format
+ *   The strptime() function processes the input string from left to
+ *   right.  Each of the three possible input elements (whitespace,
+ *   literal, or format) are handled one after the other.  If the
+ *   input cannot be matched to the format string, the function stops.
+ *   The remainder of the format and input strings are not processed.
+ *   The supported input field descriptors are listed below.  In case
+ *   a text string (such as the name of a day of the week or a month
+ *   name) is to be matched, the comparison is case insensitive.  In
+ *   case a number is to be matched, leading zeros are permitted but
+ *   not required.
+ *   %a     The abbreviated weekday name according to the current locale.
+ *   %A     The full weekday name according to the current locale.
+ *   %b     The abbreviated month name according to the current locale.
+ *   %B     The full month name according to the current locale.
+ *   %C     The century number (year/100) as a 2-digit integer. (SU)
+ *   %d     The day of the month as a decimal number (range 01 to 31).
+ *   %e     Like %d, the day of the month as a decimal number, but a leading
+ *          zero is replaced by a space.
+ *   %h     Equivalent to %b.  (SU)
+ *   %H     The hour as a decimal number using a 24-hour clock
+ *          (range 00 to 23).
+ *   %I     The  hour as a decimal number using a 12-hour clock
+ *          (range 01 to 12).
+ *   %j     The day of the year as a decimal number (range 001 to 366).
+ *   %k     The hour (24-hour clock) as a decimal number (range  0  to  23);
+ *          single digits are preceded by a blank.  (See also %H.)  (TZ)
+ *   %l     The  hour  (12-hour  clock) as a decimal number (range 1 to 12);
+ *          single digits are preceded by a blank.  (See also %I.)  (TZ)
+ *   %m     The month as a decimal number (range 01 to 12).
+ *   %M     The minute as a decimal number (range 00 to 59).
+ *   %n     A newline character. (SU)
+ *   %p     Either "AM" or "PM" according to the given time  value, or the
+ *          corresponding  strings  for the current locale.  Noon is treated
+ *          as "PM" and midnight as "AM".
+ *   %P     Like %p but in lowercase: "am" or "pm" or a corresponding string
+ *          for the current locale. (GNU)
+ *   %S     The second as a decimal number (range 00 to 60).  (The range is
+ *          up to 60 to allow for occasional leap seconds.)
+ *   %t     A tab character. (SU)
+ *   %y     The year as a decimal number without a century (range 00 to 99).
+ *   %Y     The year as a decimal number including the century.
+ *   %%     A literal '%' character.
+ *
+ * Returned Value:
+ *   The return value of the function is a pointer to the first
+ *   character not processed in this function call.  In case the input
+ *   string contains more characters than required by the format
+ *   string, the return value points right after the last consumed
+ *   input character.  In case the whole input string is consumed, the
+ *   return value points to the null byte at the end of the string.
+ *   If strptime() fails to match all of the format string and
+ *   therefore an error occurred, the function returns NULL.
+ *
+ ****************************************************************************/
+
+char *strptime(const char *buf, const char *fmt, struct tm *tm)
+{
+  struct century_relyear cr;
+  cr.century = TM_YEAR_BASE;
+  cr.relyear = -1;
+  return (char *)(_strptime((const unsigned char *)buf, fmt, tm, &cr));

Review Comment:
   ```suggestion
     return (FAR char *)(_strptime((FAR const unsigned char *)buf, fmt, tm, &cr));
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848095160


##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,622 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (g_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
+}
+
+static unsigned char *_strptime(FAR const unsigned char *buf,
+                                FAR const char *fmt,
+                                FAR struct tm *tm,
+                                struct century_relyear *cr)
+{
+  unsigned char c;
+  FAR const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (FAR const unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              {
+                return NULL;
+              }
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              {
+                return NULL;
+              }
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  {
+                    break;
+                  }
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  {
+                    break;
+                  }
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              {
+                return NULL;
+              }
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              {
+                return (NULL);
+              }
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              {
+                return (NULL);
+              }
+
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              {
+                return (NULL);
+              }
+
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              {
+                return NULL;
+              }
+
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              {
+                return NULL;
+              }
+
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  {
+                    return NULL;
+                  }
+                else if (tm->tm_hour == 12)
+                  {
+                    tm->tm_hour = 0;
+                  }
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  {
+                    return NULL;
+                  }
+                else if (tm->tm_hour < 12)
+                  {
+                    tm->tm_hour += 12;
+                  }
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return NULL;
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              {
+                return NULL;
+              }
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              {
+                return NULL;
+              }
+
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              {
+                bp++;
+              }
+
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return NULL;
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        {
+          tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+        }
+      else
+        {
+          tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+        }
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (FAR unsigned char *)bp;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: strptime
+ *
+ * Description:
+ *   Convert a string to a time type according to a specific time format
+ *   The strptime() function processes the input string from left to
+ *   right.  Each of the three possible input elements (whitespace,
+ *   literal, or format) are handled one after the other.  If the
+ *   input cannot be matched to the format string, the function stops.
+ *   The remainder of the format and input strings are not processed.
+ *   The supported input field descriptors are listed below.  In case
+ *   a text string (such as the name of a day of the week or a month
+ *   name) is to be matched, the comparison is case insensitive.  In
+ *   case a number is to be matched, leading zeros are permitted but
+ *   not required.
+ *   %a     The abbreviated weekday name according to the current locale.
+ *   %A     The full weekday name according to the current locale.
+ *   %b     The abbreviated month name according to the current locale.
+ *   %B     The full month name according to the current locale.
+ *   %C     The century number (year/100) as a 2-digit integer. (SU)
+ *   %d     The day of the month as a decimal number (range 01 to 31).
+ *   %e     Like %d, the day of the month as a decimal number, but a leading
+ *          zero is replaced by a space.
+ *   %h     Equivalent to %b.  (SU)
+ *   %H     The hour as a decimal number using a 24-hour clock
+ *          (range 00 to 23).
+ *   %I     The  hour as a decimal number using a 12-hour clock
+ *          (range 01 to 12).
+ *   %j     The day of the year as a decimal number (range 001 to 366).
+ *   %k     The hour (24-hour clock) as a decimal number (range  0  to  23);
+ *          single digits are preceded by a blank.  (See also %H.)  (TZ)
+ *   %l     The  hour  (12-hour  clock) as a decimal number (range 1 to 12);
+ *          single digits are preceded by a blank.  (See also %I.)  (TZ)
+ *   %m     The month as a decimal number (range 01 to 12).
+ *   %M     The minute as a decimal number (range 00 to 59).
+ *   %n     A newline character. (SU)
+ *   %p     Either "AM" or "PM" according to the given time  value, or the
+ *          corresponding  strings  for the current locale.  Noon is treated
+ *          as "PM" and midnight as "AM".
+ *   %P     Like %p but in lowercase: "am" or "pm" or a corresponding string
+ *          for the current locale. (GNU)
+ *   %S     The second as a decimal number (range 00 to 60).  (The range is
+ *          up to 60 to allow for occasional leap seconds.)
+ *   %t     A tab character. (SU)
+ *   %y     The year as a decimal number without a century (range 00 to 99).
+ *   %Y     The year as a decimal number including the century.
+ *   %%     A literal '%' character.
+ *
+ * Returned Value:
+ *   The return value of the function is a pointer to the first
+ *   character not processed in this function call.  In case the input
+ *   string contains more characters than required by the format
+ *   string, the return value points right after the last consumed
+ *   input character.  In case the whole input string is consumed, the
+ *   return value points to the null byte at the end of the string.
+ *   If strptime() fails to match all of the format string and
+ *   therefore an error occurred, the function returns NULL.
+ *
+ ****************************************************************************/
+
+char *strptime(FAR const char *buf, FAR const char *fmt, struct tm *tm)

Review Comment:
   ```suggestion
   FAR char *strptime(FAR const char *buf, FAR const char *fmt, FAR struct tm *tm)
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848202084


##########
libs/libc/time/lib_strptime.c:
##########
@@ -53,382 +67,556 @@ static const struct {
     const char *d_fmt;
     const char *t_fmt;
     const char *t_fmt_ampm;
-} _DefaultTimeLocale = {
-    {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
-    },
-    {
-        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-        "Friday", "Saturday"
-    },
-    {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    },
-    {
-        "January", "February", "March", "April", "May", "June", "July",
-        "August", "September", "October", "November", "December"
-    },
-    {
-        "AM", "PM"
-    },
-    "%a %b %d %H:%M:%S %Y",
-    "%m/%d/%y",
-    "%H:%M:%S",
-    "%I:%M:%S %p"
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
 };
 
-#define _ctloc(x) (_DefaultTimeLocale.x)
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
 
-/*
- * We do not implement alternate representations. However, we always
- * check whether a given modifier is allowed for a certain conversion.
- */
-#define _ALT_E          0x01
-#define _ALT_O          0x02
-#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
 
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
 
-struct century_relyear {
-    int century;
-    int relyear;
-};
-static  int _conv_num(const unsigned char **, int *, int, int);
-static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
-        struct century_relyear *);
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
 
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
 
-char *
-strptime(const char *buf, const char *fmt, struct tm *tm)
-{
-    struct century_relyear cr;
-    cr.century = TM_YEAR_BASE;
-    cr.relyear = -1;
-    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
 }
 
-static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
+static FAR unsigned char *_strptime(FAR const unsigned char *buf,

Review Comment:
   change to:
   ```
   static FAR const unsigned char *_strptime(...
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -53,382 +67,556 @@ static const struct {
     const char *d_fmt;
     const char *t_fmt;
     const char *t_fmt_ampm;
-} _DefaultTimeLocale = {
-    {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
-    },
-    {
-        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-        "Friday", "Saturday"
-    },
-    {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    },
-    {
-        "January", "February", "March", "April", "May", "June", "July",
-        "August", "September", "October", "November", "December"
-    },
-    {
-        "AM", "PM"
-    },
-    "%a %b %d %H:%M:%S %Y",
-    "%m/%d/%y",
-    "%H:%M:%S",
-    "%I:%M:%S %p"
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
 };
 
-#define _ctloc(x) (_DefaultTimeLocale.x)
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
 
-/*
- * We do not implement alternate representations. However, we always
- * check whether a given modifier is allowed for a certain conversion.
- */
-#define _ALT_E          0x01
-#define _ALT_O          0x02
-#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
 
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
 
-struct century_relyear {
-    int century;
-    int relyear;
-};
-static  int _conv_num(const unsigned char **, int *, int, int);
-static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
-        struct century_relyear *);
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
 
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
 
-char *
-strptime(const char *buf, const char *fmt, struct tm *tm)
-{
-    struct century_relyear cr;
-    cr.century = TM_YEAR_BASE;
-    cr.relyear = -1;
-    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
 }
 
-static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
+static FAR unsigned char *_strptime(FAR const unsigned char *buf,
+                                    FAR const char *fmt,
+                                    FAR struct tm *tm,
+                                    FAR struct century_relyear *cr)
 {
-    unsigned char c;
-    const unsigned char *bp;
-    size_t len = 0;
-    int alt_format, i;
-
-    bp = (unsigned char *)buf;
-    while ((c = *fmt) != '\0') {
-        /* Clear `alternate' modifier prior to new conversion. */
-        alt_format = 0;
-
-        /* Eat up white-space. */
-        if (isspace(c)) {
-            while (isspace(*bp))
-                bp++;
+  unsigned char c;
+  FAR const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (FAR const unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
 
-            fmt++;
-            continue;
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
         }
 
-        if ((c = *fmt++) != '%')
-            goto literal;
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              {
+                return NULL;
+              }
 
-again:      switch (c = *fmt++) {
-        case '%':   /* "%%" is converted to "%". */
-literal:
-        if (c != *bp++)
-            return (NULL);
+            break;
 
-        break;
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
 
-        /*
-         * "Alternative" modifiers. Just set the appropriate flag
-         * and start over again.
-         */
-        case 'E':   /* "%E?" alternative conversion modifier. */
+          case 'E': /* "%E?" alternative conversion modifier. */
             _LEGAL_ALT(0);
             alt_format |= _ALT_E;
             goto again;
 
-        case 'O':   /* "%O?" alternative conversion modifier. */
+          case 'O': /* "%O?" alternative conversion modifier. */
             _LEGAL_ALT(0);
             alt_format |= _ALT_O;
             goto again;
 
-        /*
-         * "Complex" conversion rules, implemented through recursion.
-         */
-        case 'c':   /* Date and time, using the locale's format. */
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'D':   /* The date as "%m/%d/%y". */
+          case 'D': /* The date as "%m/%d/%y". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'R':   /* The time as "%H:%M". */
+          case 'R': /* The time as "%H:%M". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'r':   /* The time as "%I:%M:%S %p". */
+          case 'r': /* The time as "%I:%M:%S %p". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'T':   /* The time as "%H:%M:%S". */
+          case 'T': /* The time as "%H:%M:%S". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'X':   /* The time, using the locale's format. */
+          case 'X': /* The time, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'x':   /* The date, using the locale's format. */
+          case 'x': /* The date, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        /*
-         * "Elementary" conversion rules.
-         */
-        case 'A':   /* The day of week, using the locale's form. */
-        case 'a':
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
             _LEGAL_ALT(0);
-            for (i = 0; i < 7; i++) {
+            for (i = 0; i < 7; i++)
+              {
                 /* Full name. */
+
                 len = strlen(_ctloc(day[i]));
-                if (strncasecmp(_ctloc(day[i]), (const char*)bp, len) == 0)
-                    break;
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
 
                 /* Abbreviated name. */
+
                 len = strlen(_ctloc(abday[i]));
-                if (strncasecmp(_ctloc(abday[i]), (const char*)bp, len) == 0)
-                    break;
-            }
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
 
             /* Nothing matched. */
+
             if (i == 7)
-                return (NULL);
+              {
+                return NULL;
+              }
 
             tm->tm_wday = i;
             bp += len;
             break;
 
-        case 'B':   /* The month, using the locale's form. */
-        case 'b':
-        case 'h':
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
             _LEGAL_ALT(0);
-            for (i = 0; i < 12; i++) {
+            for (i = 0; i < 12; i++)
+              {
                 /* Full name. */
+
                 len = strlen(_ctloc(mon[i]));
-                if (strncasecmp(_ctloc(mon[i]), (const char*)bp, len) == 0)
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  {
                     break;
+                  }
 
                 /* Abbreviated name. */
+
                 len = strlen(_ctloc(abmon[i]));
-                if (strncasecmp(_ctloc(abmon[i]), (const char*)bp, len) == 0)
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  {
                     break;
-            }
+                  }
+              }
 
             /* Nothing matched. */
+
             if (i == 12)
-                return (NULL);
+              {
+                return NULL;
+              }
 
             tm->tm_mon = i;
             bp += len;
             break;
 
-        case 'C':   /* The century number. */
+          case 'C': /* The century number. */
             _LEGAL_ALT(_ALT_E);
             if (!(_conv_num(&bp, &i, 0, 99)))
+              {
                 return (NULL);
+              }
 
             cr->century = i * 100;
             break;
 
-        case 'd':   /* The day of month. */
-        case 'e':
+          case 'd': /* The day of month. */
+          case 'e':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              {
                 return (NULL);
+              }
+
             break;
 
-        case 'k':   /* The hour (24-hour clock representation). */
+          case 'k': /* The hour (24-hour clock representation). */
             _LEGAL_ALT(0);
+
             /* FALLTHROUGH */
-        case 'H':
+
+          case 'H':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'l':   /* The hour (12-hour clock representation). */
+          case 'l': /* The hour (12-hour clock representation). */
             _LEGAL_ALT(0);
+
             /* FALLTHROUGH */
-        case 'I':
+
+          case 'I':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              {
                 return (NULL);
+              }
+
             break;
 
-        case 'j':   /* The day of year. */
+          case 'j': /* The day of year. */
             _LEGAL_ALT(0);
             if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             tm->tm_yday--;
             break;
 
-        case 'M':   /* The minute. */
+          case 'M': /* The minute. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'm':   /* The month. */
+          case 'm': /* The month. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             tm->tm_mon--;
             break;
 
-        case 'p':   /* The locale's equivalent of AM/PM. */
+          case 'p': /* The locale's equivalent of AM/PM. */
             _LEGAL_ALT(0);
+
             /* AM? */
+
             len = strlen(_ctloc(am_pm[0]));
-            if (strncasecmp(_ctloc(am_pm[0]), (const char*)bp, len) == 0) {
-                if (tm->tm_hour > 12)   /* i.e., 13:00 AM ?! */
-                    return (NULL);
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  {
+                    return NULL;
+                  }
                 else if (tm->tm_hour == 12)
+                  {
                     tm->tm_hour = 0;
+                  }
 
                 bp += len;
                 break;
-            }
+              }
+
             /* PM? */
+
             len = strlen(_ctloc(am_pm[1]));
-            if (strncasecmp(_ctloc(am_pm[1]), (const char*)bp, len) == 0) {
-                if (tm->tm_hour > 12)   /* i.e., 13:00 PM ?! */
-                    return (NULL);
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  {
+                    return NULL;
+                  }
                 else if (tm->tm_hour < 12)
+                  {
                     tm->tm_hour += 12;
+                  }
 
                 bp += len;
                 break;
-            }
+              }
 
             /* Nothing matched. */
-            return (NULL);
 
-        case 'S':   /* The seconds. */
+            return NULL;
+
+          case 'S': /* The seconds. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'U':   /* The week of year, beginning on sunday. */
-        case 'W':   /* The week of year, beginning on monday. */
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
             _LEGAL_ALT(_ALT_O);
-            /*
-             * XXX This is bogus, as we can not assume any valid
-             * information present in the tm structure at this
-             * point to calculate a real value, so just check the
-             * range for now.
-             */
-             if (!(_conv_num(&bp, &i, 0, 53)))
-                return (NULL);
-             break;
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              {
+                return NULL;
+              }
 
-        case 'w':   /* The day of week, beginning on sunday. */
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'Y':   /* The year. */
+          case 'Y': /* The year. */
             _LEGAL_ALT(_ALT_E);
             if (!(_conv_num(&bp, &i, 0, 9999)))
-                return (NULL);
+              {
+                return NULL;
+              }
 
             cr->relyear = -1;
             tm->tm_year = i - TM_YEAR_BASE;
             break;
 
-        case 'y':   /* The year within the century (2 digits). */
+          case 'y': /* The year within the century (2 digits). */
             _LEGAL_ALT(_ALT_E | _ALT_O);
             if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        /*
-         * Miscellaneous conversions.
-         */
-        case 'n':   /* Any kind of white-space. */
-        case 't':
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
             _LEGAL_ALT(0);
             while (isspace(*bp))
+              {
                 bp++;
-            break;
+              }
 
+            break;
 
-        default:    /* Unknown/unsupported conversion. */
-            return (NULL);
+          default: /* Unknown/unsupported conversion. */
+            return NULL;
         }
-
-
     }
 
-    /*
-     * We need to evaluate the two digit year spec (%y)
-     * last as we can get a century spec (%C) at any time.
-     */
-    if (cr->relyear != -1) {
-        if (cr->century == TM_YEAR_BASE) {
-            if (cr->relyear <= 68)
-                tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
-            else
-                tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
-        } else {
-            tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        {
+          tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+        }
+      else
+        {
+          tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
         }
     }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
 
-    return (unsigned char*)bp;
+  return (FAR unsigned char *)bp;

Review Comment:
   remove the cast



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r847549566


##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;

Review Comment:
   ```suggestion
     while (isspace(**buf))
       {
         (*buf)++;
       }
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);

Review Comment:
   ```suggestion
               if (c != *bp++)
                 {
                   return NULL;
                 }
   ```



##########
include/time.h:
##########
@@ -200,6 +200,8 @@ FAR struct tm *localtime_r(FAR const time_t *timep, FAR struct tm *result);
 
 size_t strftime(FAR char *s, size_t max, FAR const char *format,
                 FAR const struct tm *tm) strftimelike(3);
+FAR char *strptime(FAR const char *s, FAR const char *format,
+                FAR struct tm *tm);

Review Comment:
   ```suggestion
   FAR char *strptime(FAR const char *s, FAR const char *format,
                      FAR struct tm *tm);
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;

Review Comment:
   ```suggestion
     int century;
     int relyear;
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);

Review Comment:
   ```suggestion
         return 0;
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)

Review Comment:
   ```suggestion
   static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
                        int llim, int ulim)
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');

Review Comment:
   ```suggestion
     while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);

Review Comment:
   ```suggestion
         return 0;
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);

Review Comment:
   ```suggestion
     return 1;
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;

Review Comment:
   ```suggestion
     bp = (const unsigned char *)buf;
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;

Review Comment:
   ```suggestion
     FAR const unsigned char *bp;
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,

Review Comment:
   ```suggestion
   static unsigned char * _strptime(FAR const unsigned char *buf,
                                    FAR const char *fmt,
                                    FAR struct tm *tm,
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;

Review Comment:
   why `const` is discarded?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848092294


##########
include/time.h:
##########
@@ -200,6 +200,8 @@ FAR struct tm *localtime_r(FAR const time_t *timep, FAR struct tm *result);
 
 size_t strftime(FAR char *s, size_t max, FAR const char *format,
                 FAR const struct tm *tm) strftimelike(3);
+FAR char *strptime(FAR const char *s, FAR const char *format,
+                   FAR struct tm *tm);

Review Comment:
   The convention of _XOPEN_SOURCE, GNU_SOURCE... is never used in nuttx before. It's better to convert the usage in one patch If this convention is our target.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848094764


##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,622 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (g_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
+}
+
+static unsigned char *_strptime(FAR const unsigned char *buf,
+                                FAR const char *fmt,
+                                FAR struct tm *tm,
+                                struct century_relyear *cr)

Review Comment:
   ```suggestion
                                   FAR struct century_relyear *cr)
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,622 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (g_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
+}
+
+static unsigned char *_strptime(FAR const unsigned char *buf,

Review Comment:
   ```suggestion
   static FAR unsigned char *_strptime(FAR const unsigned char *buf,
   ```



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,622 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (g_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
+}
+
+static unsigned char *_strptime(FAR const unsigned char *buf,
+                                FAR const char *fmt,
+                                FAR struct tm *tm,
+                                struct century_relyear *cr)
+{
+  unsigned char c;
+  FAR const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (FAR const unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              {
+                return NULL;
+              }
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              {
+                return NULL;
+              }
+
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              {
+                return NULL;
+              }
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  {
+                    break;
+                  }
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  {
+                    break;
+                  }
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              {
+                return NULL;
+              }
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              {
+                return (NULL);
+              }
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              {
+                return (NULL);
+              }
+
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              {
+                return (NULL);
+              }
+
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              {
+                return NULL;
+              }
+
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              {
+                return NULL;
+              }
+
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  {
+                    return NULL;
+                  }
+                else if (tm->tm_hour == 12)
+                  {
+                    tm->tm_hour = 0;
+                  }
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  {
+                    return NULL;
+                  }
+                else if (tm->tm_hour < 12)
+                  {
+                    tm->tm_hour += 12;
+                  }
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return NULL;
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              {
+                return NULL;
+              }
+
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              {
+                return NULL;
+              }
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              {
+                return NULL;
+              }
+
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              {
+                bp++;
+              }
+
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return NULL;
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        {
+          tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+        }
+      else
+        {
+          tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+        }
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (FAR unsigned char *)bp;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: strptime
+ *
+ * Description:
+ *   Convert a string to a time type according to a specific time format
+ *   The strptime() function processes the input string from left to
+ *   right.  Each of the three possible input elements (whitespace,
+ *   literal, or format) are handled one after the other.  If the
+ *   input cannot be matched to the format string, the function stops.
+ *   The remainder of the format and input strings are not processed.
+ *   The supported input field descriptors are listed below.  In case
+ *   a text string (such as the name of a day of the week or a month
+ *   name) is to be matched, the comparison is case insensitive.  In
+ *   case a number is to be matched, leading zeros are permitted but
+ *   not required.
+ *   %a     The abbreviated weekday name according to the current locale.
+ *   %A     The full weekday name according to the current locale.
+ *   %b     The abbreviated month name according to the current locale.
+ *   %B     The full month name according to the current locale.
+ *   %C     The century number (year/100) as a 2-digit integer. (SU)
+ *   %d     The day of the month as a decimal number (range 01 to 31).
+ *   %e     Like %d, the day of the month as a decimal number, but a leading
+ *          zero is replaced by a space.
+ *   %h     Equivalent to %b.  (SU)
+ *   %H     The hour as a decimal number using a 24-hour clock
+ *          (range 00 to 23).
+ *   %I     The  hour as a decimal number using a 12-hour clock
+ *          (range 01 to 12).
+ *   %j     The day of the year as a decimal number (range 001 to 366).
+ *   %k     The hour (24-hour clock) as a decimal number (range  0  to  23);
+ *          single digits are preceded by a blank.  (See also %H.)  (TZ)
+ *   %l     The  hour  (12-hour  clock) as a decimal number (range 1 to 12);
+ *          single digits are preceded by a blank.  (See also %I.)  (TZ)
+ *   %m     The month as a decimal number (range 01 to 12).
+ *   %M     The minute as a decimal number (range 00 to 59).
+ *   %n     A newline character. (SU)
+ *   %p     Either "AM" or "PM" according to the given time  value, or the
+ *          corresponding  strings  for the current locale.  Noon is treated
+ *          as "PM" and midnight as "AM".
+ *   %P     Like %p but in lowercase: "am" or "pm" or a corresponding string
+ *          for the current locale. (GNU)
+ *   %S     The second as a decimal number (range 00 to 60).  (The range is
+ *          up to 60 to allow for occasional leap seconds.)
+ *   %t     A tab character. (SU)
+ *   %y     The year as a decimal number without a century (range 00 to 99).
+ *   %Y     The year as a decimal number including the century.
+ *   %%     A literal '%' character.
+ *
+ * Returned Value:
+ *   The return value of the function is a pointer to the first
+ *   character not processed in this function call.  In case the input
+ *   string contains more characters than required by the format
+ *   string, the return value points right after the last consumed
+ *   input character.  In case the whole input string is consumed, the
+ *   return value points to the null byte at the end of the string.
+ *   If strptime() fails to match all of the format string and
+ *   therefore an error occurred, the function returns NULL.
+ *
+ ****************************************************************************/
+
+char *strptime(FAR const char *buf, FAR const char *fmt, struct tm *tm)

Review Comment:
   ```suggestion
   FAR char *strptime(FAR const char *buf, FAR const char *fmt, struct tm *tm)
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848093375


##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;

Review Comment:
   Ok, @anjiahao1 let's add const for the internal _strptime function.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848643830


##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;

Review Comment:
   I saw that the POSIX prototype returns `char *` but not `const char*`, so it seems we have to accept this inconsistency.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#issuecomment-1097481269

   ci error is fixed by #6055, let's merge this PR directly to save the resource.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848093537


##########
include/time.h:
##########
@@ -200,6 +200,8 @@ FAR struct tm *localtime_r(FAR const time_t *timep, FAR struct tm *result);
 
 size_t strftime(FAR char *s, size_t max, FAR const char *format,
                 FAR const struct tm *tm) strftimelike(3);
+FAR char *strptime(FAR const char *s, FAR const char *format,
+                   FAR struct tm *tm);

Review Comment:
   agree



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r847068969


##########
libs/libc/time/lib_strptime.c:
##########
@@ -53,382 +67,474 @@ static const struct {
     const char *d_fmt;
     const char *t_fmt;
     const char *t_fmt_ampm;
-} _DefaultTimeLocale = {
-    {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
-    },
-    {
-        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-        "Friday", "Saturday"
-    },
-    {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    },
-    {
-        "January", "February", "March", "April", "May", "June", "July",
-        "August", "September", "October", "November", "December"
-    },
-    {
-        "AM", "PM"
-    },
-    "%a %b %d %H:%M:%S %Y",
-    "%m/%d/%y",
-    "%H:%M:%S",
-    "%I:%M:%S %p"
+} _defaulttimelocale =

Review Comment:
   _defaulttimelocale ->g_defaulttimelocale 



##########
libs/libc/time/lib_strptime.c:
##########
@@ -23,27 +25,39 @@
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
 
 #include <ctype.h>
 #include <locale.h>
 #include <strings.h>
 #include <time.h>
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
 #define TM_YEAR_BASE        1900
+#define _ctloc(x) (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E          0x01
+#define _ALT_O          0x02

Review Comment:
   "0x02" align to "1900" at line 44



##########
libs/libc/time/lib_strptime.c:
##########
@@ -23,27 +25,39 @@
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
 
 #include <ctype.h>
 #include <locale.h>
 #include <strings.h>
 #include <time.h>
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
 #define TM_YEAR_BASE        1900
+#define _ctloc(x) (_defaulttimelocale.x)

Review Comment:
   align _defaulttimelocale too



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848068658


##########
libs/libc/time/lib_strptime.c:
##########
@@ -53,382 +67,556 @@ static const struct {
     const char *d_fmt;
     const char *t_fmt;
     const char *t_fmt_ampm;
-} _DefaultTimeLocale = {
-    {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
-    },
-    {
-        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-        "Friday", "Saturday"
-    },
-    {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    },
-    {
-        "January", "February", "March", "April", "May", "June", "July",
-        "August", "September", "October", "November", "December"
-    },
-    {
-        "AM", "PM"
-    },
-    "%a %b %d %H:%M:%S %Y",
-    "%m/%d/%y",
-    "%H:%M:%S",
-    "%I:%M:%S %p"
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
 };
 
-#define _ctloc(x) (_DefaultTimeLocale.x)
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
 
-/*
- * We do not implement alternate representations. However, we always
- * check whether a given modifier is allowed for a certain conversion.
- */
-#define _ALT_E          0x01
-#define _ALT_O          0x02
-#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
 
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
 
-struct century_relyear {
-    int century;
-    int relyear;
-};
-static  int _conv_num(const unsigned char **, int *, int, int);
-static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
-        struct century_relyear *);
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
 
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
 
-char *
-strptime(const char *buf, const char *fmt, struct tm *tm)
-{
-    struct century_relyear cr;
-    cr.century = TM_YEAR_BASE;
-    cr.relyear = -1;
-    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
 }
 
-static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
+static unsigned char * _strptime(FAR const unsigned char *buf,

Review Comment:
   add FAR before unsigned char and remove the space before _strptime



##########
libs/libc/time/lib_strptime.c:
##########
@@ -53,382 +67,556 @@ static const struct {
     const char *d_fmt;
     const char *t_fmt;
     const char *t_fmt_ampm;
-} _DefaultTimeLocale = {
-    {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
-    },
-    {
-        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-        "Friday", "Saturday"
-    },
-    {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    },
-    {
-        "January", "February", "March", "April", "May", "June", "July",
-        "August", "September", "October", "November", "December"
-    },
-    {
-        "AM", "PM"
-    },
-    "%a %b %d %H:%M:%S %Y",
-    "%m/%d/%y",
-    "%H:%M:%S",
-    "%I:%M:%S %p"
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
 };
 
-#define _ctloc(x) (_DefaultTimeLocale.x)
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
 
-/*
- * We do not implement alternate representations. However, we always
- * check whether a given modifier is allowed for a certain conversion.
- */
-#define _ALT_E          0x01
-#define _ALT_O          0x02
-#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
 
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
 
-struct century_relyear {
-    int century;
-    int relyear;
-};
-static  int _conv_num(const unsigned char **, int *, int, int);
-static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
-        struct century_relyear *);
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
 
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
 
-char *
-strptime(const char *buf, const char *fmt, struct tm *tm)
-{
-    struct century_relyear cr;
-    cr.century = TM_YEAR_BASE;
-    cr.relyear = -1;
-    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
 }
 
-static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
+static unsigned char * _strptime(FAR const unsigned char *buf,
+                                 FAR const char *fmt,
+                                 FAR struct tm *tm,
+                                 struct century_relyear *cr)
 {
-    unsigned char c;
-    const unsigned char *bp;
-    size_t len = 0;
-    int alt_format, i;
-
-    bp = (unsigned char *)buf;
-    while ((c = *fmt) != '\0') {
-        /* Clear `alternate' modifier prior to new conversion. */
-        alt_format = 0;
-
-        /* Eat up white-space. */
-        if (isspace(c)) {
-            while (isspace(*bp))
-                bp++;
+  unsigned char c;
+  FAR const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (const unsigned char *)buf;

Review Comment:
   add FAR



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: strptime
+ *
+ * Description:
+ *   Convert a string to a time type according to a specific time format
+ *   The strptime() function processes the input string from left to
+ *   right.  Each of the three possible input elements (whitespace,
+ *   literal, or format) are handled one after the other.  If the
+ *   input cannot be matched to the format string, the function stops.
+ *   The remainder of the format and input strings are not processed.
+ *   The supported input field descriptors are listed below.  In case
+ *   a text string (such as the name of a day of the week or a month
+ *   name) is to be matched, the comparison is case insensitive.  In
+ *   case a number is to be matched, leading zeros are permitted but
+ *   not required.
+ *   %a     The abbreviated weekday name according to the current locale.
+ *   %A     The full weekday name according to the current locale.
+ *   %b     The abbreviated month name according to the current locale.
+ *   %B     The full month name according to the current locale.
+ *   %C     The century number (year/100) as a 2-digit integer. (SU)
+ *   %d     The day of the month as a decimal number (range 01 to 31).
+ *   %e     Like %d, the day of the month as a decimal number, but a leading
+ *          zero is replaced by a space.
+ *   %h     Equivalent to %b.  (SU)
+ *   %H     The hour as a decimal number using a 24-hour clock
+ *          (range 00 to 23).
+ *   %I     The  hour as a decimal number using a 12-hour clock
+ *          (range 01 to 12).
+ *   %j     The day of the year as a decimal number (range 001 to 366).
+ *   %k     The hour (24-hour clock) as a decimal number (range  0  to  23);
+ *          single digits are preceded by a blank.  (See also %H.)  (TZ)
+ *   %l     The  hour  (12-hour  clock) as a decimal number (range 1 to 12);
+ *          single digits are preceded by a blank.  (See also %I.)  (TZ)
+ *   %m     The month as a decimal number (range 01 to 12).
+ *   %M     The minute as a decimal number (range 00 to 59).
+ *   %n     A newline character. (SU)
+ *   %p     Either "AM" or "PM" according to the given time  value, or the
+ *          corresponding  strings  for the current locale.  Noon is treated
+ *          as "PM" and midnight as "AM".
+ *   %P     Like %p but in lowercase: "am" or "pm" or a corresponding string
+ *          for the current locale. (GNU)
+ *   %S     The second as a decimal number (range 00 to 60).  (The range is
+ *          up to 60 to allow for occasional leap seconds.)
+ *   %t     A tab character. (SU)
+ *   %y     The year as a decimal number without a century (range 00 to 99).
+ *   %Y     The year as a decimal number including the century.
+ *   %%     A literal '%' character.
+ *
+ * Returned Value:
+ *   The return value of the function is a pointer to the first
+ *   character not processed in this function call.  In case the input
+ *   string contains more characters than required by the format
+ *   string, the return value points right after the last consumed
+ *   input character.  In case the whole input string is consumed, the
+ *   return value points to the null byte at the end of the string.
+ *   If strptime() fails to match all of the format string and
+ *   therefore an error occurred, the function returns NULL.
+ *
+ ****************************************************************************/
+
+char *strptime(const char *buf, const char *fmt, struct tm *tm)

Review Comment:
   add FAR at the beginning



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;

Review Comment:
   add FAR in the cast



##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;

Review Comment:
   > why `const` is discarded?
   
   since _strptime and strptime return non-const pointer



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848082419


##########
libs/libc/time/lib_strptime.c:
##########
@@ -0,0 +1,540 @@
+/****************************************************************************
+ * libs/libc/time/lib_strptime.c
+ *
+ *  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $
+ *  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $
+ *
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <nuttx/config.h>
+
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+#include <time.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TM_YEAR_BASE        1900
+#define _ctloc(x)           (_defaulttimelocale.x)
+
+/* We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+
+#define _ALT_E              0x01
+#define _ALT_O              0x02
+#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct
+{
+    const char *abday[7];
+    const char *day[7];
+    const char *abmon[12];
+    const char *mon[12];
+    const char *am_pm[2];
+    const char *d_t_fmt;
+    const char *d_fmt;
+    const char *t_fmt;
+    const char *t_fmt_ampm;
+} _defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
+};
+
+struct century_relyear
+{
+    int century;
+    int relyear;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int _conv_num(const unsigned char **buf, int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
+
+  while (isspace(**buf))
+    (*buf)++;
+
+  if (**buf < '0' || **buf > '9')
+    {
+      return (0);
+    }
+
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+      while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return (0);
+    }
+
+  *dest = result;
+  return (1);
+}
+
+static unsigned char * _strptime(const unsigned char *buf,
+                                 const char *fmt,
+                                 struct tm *tm,
+                                 struct century_relyear *cr)
+{
+  unsigned char c;
+  const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
+
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
+        }
+
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              return (NULL);
+
+            break;
+
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
+
+          case 'E': /* "%E?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_E;
+            goto again;
+
+          case 'O': /* "%O?" alternative conversion modifier. */
+            _LEGAL_ALT(0);
+            alt_format |= _ALT_O;
+            goto again;
+
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'D': /* The date as "%m/%d/%y". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'R': /* The time as "%H:%M". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'r': /* The time as "%I:%M:%S %p". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'T': /* The time as "%H:%M:%S". */
+            _LEGAL_ALT(0);
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
+              return (NULL);
+            break;
+
+          case 'X': /* The time, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+          case 'x': /* The date, using the locale's format. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
+              return (NULL);
+            break;
+
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 7; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(day[i]));
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abday[i]));
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 7)
+              return (NULL);
+
+            tm->tm_wday = i;
+            bp += len;
+            break;
+
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
+            _LEGAL_ALT(0);
+            for (i = 0; i < 12; i++)
+              {
+                /* Full name. */
+
+                len = strlen(_ctloc(mon[i]));
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+
+                /* Abbreviated name. */
+
+                len = strlen(_ctloc(abmon[i]));
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
+
+            /* Nothing matched. */
+
+            if (i == 12)
+              return (NULL);
+
+            tm->tm_mon = i;
+            bp += len;
+            break;
+
+          case 'C': /* The century number. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 99)))
+              return (NULL);
+
+            cr->century = i * 100;
+            break;
+
+          case 'd': /* The day of month. */
+          case 'e':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              return (NULL);
+            break;
+
+          case 'k': /* The hour (24-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'H':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+              return (NULL);
+            break;
+
+          case 'l': /* The hour (12-hour clock representation). */
+            _LEGAL_ALT(0);
+
+            /* FALLTHROUGH */
+
+          case 'I':
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              return (NULL);
+            break;
+
+          case 'j': /* The day of year. */
+            _LEGAL_ALT(0);
+            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+              return (NULL);
+            tm->tm_yday--;
+            break;
+
+          case 'M': /* The minute. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+              return (NULL);
+            break;
+
+          case 'm': /* The month. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+              return (NULL);
+            tm->tm_mon--;
+            break;
+
+          case 'p': /* The locale's equivalent of AM/PM. */
+            _LEGAL_ALT(0);
+
+            /* AM? */
+
+            len = strlen(_ctloc(am_pm[0]));
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  return (NULL);
+                else if (tm->tm_hour == 12)
+                  tm->tm_hour = 0;
+
+                bp += len;
+                break;
+              }
+
+            /* PM? */
+
+            len = strlen(_ctloc(am_pm[1]));
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  return (NULL);
+                else if (tm->tm_hour < 12)
+                  tm->tm_hour += 12;
+
+                bp += len;
+                break;
+              }
+
+            /* Nothing matched. */
+
+            return (NULL);
+
+          case 'S': /* The seconds. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+              return (NULL);
+            break;
+
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
+            _LEGAL_ALT(_ALT_O);
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              return (NULL);
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
+            _LEGAL_ALT(_ALT_O);
+            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+              return (NULL);
+            break;
+
+          case 'Y': /* The year. */
+            _LEGAL_ALT(_ALT_E);
+            if (!(_conv_num(&bp, &i, 0, 9999)))
+              return (NULL);
+
+            cr->relyear = -1;
+            tm->tm_year = i - TM_YEAR_BASE;
+            break;
+
+          case 'y': /* The year within the century (2 digits). */
+            _LEGAL_ALT(_ALT_E | _ALT_O);
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
+              return (NULL);
+            break;
+
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
+            _LEGAL_ALT(0);
+            while (isspace(*bp))
+              bp++;
+            break;
+
+          default: /* Unknown/unsupported conversion. */
+            return (NULL);
+        }
+    }
+
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+      else
+        tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
+    }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
+
+  return (unsigned char *)bp;

Review Comment:
   > > why `const` is discarded?
   > 
   > since _strptime and strptime return non-const pointer
   
   Yeah, that is obvious. My question is if `bp` points to RO memory (flash) and the result is casted then caller may `p = strptime(...)` -> `p[0] = '1';` that will lead to crash. I hope that will not happen. I understand that thre is no `_r` variant, but probably the global holder should be used in this case and not dropping of `const`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a diff in pull request #6029: libc:add strptime support

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 commented on code in PR #6029:
URL: https://github.com/apache/incubator-nuttx/pull/6029#discussion_r848266015


##########
libs/libc/time/lib_strptime.c:
##########
@@ -53,382 +67,556 @@ static const struct {
     const char *d_fmt;
     const char *t_fmt;
     const char *t_fmt_ampm;
-} _DefaultTimeLocale = {
-    {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
-    },
-    {
-        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-        "Friday", "Saturday"
-    },
-    {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    },
-    {
-        "January", "February", "March", "April", "May", "June", "July",
-        "August", "September", "October", "November", "December"
-    },
-    {
-        "AM", "PM"
-    },
-    "%a %b %d %H:%M:%S %Y",
-    "%m/%d/%y",
-    "%H:%M:%S",
-    "%I:%M:%S %p"
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
 };
 
-#define _ctloc(x) (_DefaultTimeLocale.x)
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
 
-/*
- * We do not implement alternate representations. However, we always
- * check whether a given modifier is allowed for a certain conversion.
- */
-#define _ALT_E          0x01
-#define _ALT_O          0x02
-#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
 
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
 
-struct century_relyear {
-    int century;
-    int relyear;
-};
-static  int _conv_num(const unsigned char **, int *, int, int);
-static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
-        struct century_relyear *);
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
 
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
 
-char *
-strptime(const char *buf, const char *fmt, struct tm *tm)
-{
-    struct century_relyear cr;
-    cr.century = TM_YEAR_BASE;
-    cr.relyear = -1;
-    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
 }
 
-static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
+static FAR const unsigned char *_strptime(FAR const unsigned char *buf,
+                                          FAR const char *fmt,
+                                          FAR struct tm *tm,
+                                          FAR struct century_relyear *cr)
 {
-    unsigned char c;
-    const unsigned char *bp;
-    size_t len = 0;
-    int alt_format, i;
-
-    bp = (unsigned char *)buf;
-    while ((c = *fmt) != '\0') {
-        /* Clear `alternate' modifier prior to new conversion. */
-        alt_format = 0;
-
-        /* Eat up white-space. */
-        if (isspace(c)) {
-            while (isspace(*bp))
-                bp++;
+  unsigned char c;
+  FAR const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (FAR const unsigned char *)buf;

Review Comment:
   remove the cast



##########
libs/libc/time/lib_strptime.c:
##########
@@ -53,382 +67,556 @@ static const struct {
     const char *d_fmt;
     const char *t_fmt;
     const char *t_fmt_ampm;
-} _DefaultTimeLocale = {
-    {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
-    },
-    {
-        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-        "Friday", "Saturday"
-    },
-    {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    },
-    {
-        "January", "February", "March", "April", "May", "June", "July",
-        "August", "September", "October", "November", "December"
-    },
-    {
-        "AM", "PM"
-    },
-    "%a %b %d %H:%M:%S %Y",
-    "%m/%d/%y",
-    "%H:%M:%S",
-    "%I:%M:%S %p"
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
 };
 
-#define _ctloc(x) (_DefaultTimeLocale.x)
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
 
-/*
- * We do not implement alternate representations. However, we always
- * check whether a given modifier is allowed for a certain conversion.
- */
-#define _ALT_E          0x01
-#define _ALT_O          0x02
-#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
 
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
 
-struct century_relyear {
-    int century;
-    int relyear;
-};
-static  int _conv_num(const unsigned char **, int *, int, int);
-static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
-        struct century_relyear *);
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
 
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
 
-char *
-strptime(const char *buf, const char *fmt, struct tm *tm)
-{
-    struct century_relyear cr;
-    cr.century = TM_YEAR_BASE;
-    cr.relyear = -1;
-    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
 }
 
-static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
+static FAR const unsigned char *_strptime(FAR const unsigned char *buf,
+                                          FAR const char *fmt,
+                                          FAR struct tm *tm,
+                                          FAR struct century_relyear *cr)
 {
-    unsigned char c;
-    const unsigned char *bp;
-    size_t len = 0;
-    int alt_format, i;
-
-    bp = (unsigned char *)buf;
-    while ((c = *fmt) != '\0') {
-        /* Clear `alternate' modifier prior to new conversion. */
-        alt_format = 0;
-
-        /* Eat up white-space. */
-        if (isspace(c)) {
-            while (isspace(*bp))
-                bp++;
+  unsigned char c;
+  FAR const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (FAR const unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
 
-            fmt++;
-            continue;
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
         }
 
-        if ((c = *fmt++) != '%')
-            goto literal;
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              {
+                return NULL;
+              }
 
-again:      switch (c = *fmt++) {
-        case '%':   /* "%%" is converted to "%". */
-literal:
-        if (c != *bp++)
-            return (NULL);
+            break;
 
-        break;
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
 
-        /*
-         * "Alternative" modifiers. Just set the appropriate flag
-         * and start over again.
-         */
-        case 'E':   /* "%E?" alternative conversion modifier. */
+          case 'E': /* "%E?" alternative conversion modifier. */
             _LEGAL_ALT(0);
             alt_format |= _ALT_E;
             goto again;
 
-        case 'O':   /* "%O?" alternative conversion modifier. */
+          case 'O': /* "%O?" alternative conversion modifier. */
             _LEGAL_ALT(0);
             alt_format |= _ALT_O;
             goto again;
 
-        /*
-         * "Complex" conversion rules, implemented through recursion.
-         */
-        case 'c':   /* Date and time, using the locale's format. */
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'D':   /* The date as "%m/%d/%y". */
+          case 'D': /* The date as "%m/%d/%y". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'R':   /* The time as "%H:%M". */
+          case 'R': /* The time as "%H:%M". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'r':   /* The time as "%I:%M:%S %p". */
+          case 'r': /* The time as "%I:%M:%S %p". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'T':   /* The time as "%H:%M:%S". */
+          case 'T': /* The time as "%H:%M:%S". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'X':   /* The time, using the locale's format. */
+          case 'X': /* The time, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'x':   /* The date, using the locale's format. */
+          case 'x': /* The date, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        /*
-         * "Elementary" conversion rules.
-         */
-        case 'A':   /* The day of week, using the locale's form. */
-        case 'a':
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
             _LEGAL_ALT(0);
-            for (i = 0; i < 7; i++) {
+            for (i = 0; i < 7; i++)
+              {
                 /* Full name. */
+
                 len = strlen(_ctloc(day[i]));
-                if (strncasecmp(_ctloc(day[i]), (const char*)bp, len) == 0)
-                    break;
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
 
                 /* Abbreviated name. */
+
                 len = strlen(_ctloc(abday[i]));
-                if (strncasecmp(_ctloc(abday[i]), (const char*)bp, len) == 0)
-                    break;
-            }
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
 
             /* Nothing matched. */
+
             if (i == 7)
-                return (NULL);
+              {
+                return NULL;
+              }
 
             tm->tm_wday = i;
             bp += len;
             break;
 
-        case 'B':   /* The month, using the locale's form. */
-        case 'b':
-        case 'h':
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
             _LEGAL_ALT(0);
-            for (i = 0; i < 12; i++) {
+            for (i = 0; i < 12; i++)
+              {
                 /* Full name. */
+
                 len = strlen(_ctloc(mon[i]));
-                if (strncasecmp(_ctloc(mon[i]), (const char*)bp, len) == 0)
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  {
                     break;
+                  }
 
                 /* Abbreviated name. */
+
                 len = strlen(_ctloc(abmon[i]));
-                if (strncasecmp(_ctloc(abmon[i]), (const char*)bp, len) == 0)
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  {
                     break;
-            }
+                  }
+              }
 
             /* Nothing matched. */
+
             if (i == 12)
-                return (NULL);
+              {
+                return NULL;
+              }
 
             tm->tm_mon = i;
             bp += len;
             break;
 
-        case 'C':   /* The century number. */
+          case 'C': /* The century number. */
             _LEGAL_ALT(_ALT_E);
             if (!(_conv_num(&bp, &i, 0, 99)))
+              {
                 return (NULL);
+              }
 
             cr->century = i * 100;
             break;
 
-        case 'd':   /* The day of month. */
-        case 'e':
+          case 'd': /* The day of month. */
+          case 'e':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              {
                 return (NULL);
+              }
+
             break;
 
-        case 'k':   /* The hour (24-hour clock representation). */
+          case 'k': /* The hour (24-hour clock representation). */
             _LEGAL_ALT(0);
+
             /* FALLTHROUGH */
-        case 'H':
+
+          case 'H':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'l':   /* The hour (12-hour clock representation). */
+          case 'l': /* The hour (12-hour clock representation). */
             _LEGAL_ALT(0);
+
             /* FALLTHROUGH */
-        case 'I':
+
+          case 'I':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              {
                 return (NULL);
+              }
+
             break;
 
-        case 'j':   /* The day of year. */
+          case 'j': /* The day of year. */
             _LEGAL_ALT(0);
             if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             tm->tm_yday--;
             break;
 
-        case 'M':   /* The minute. */
+          case 'M': /* The minute. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'm':   /* The month. */
+          case 'm': /* The month. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             tm->tm_mon--;
             break;
 
-        case 'p':   /* The locale's equivalent of AM/PM. */
+          case 'p': /* The locale's equivalent of AM/PM. */
             _LEGAL_ALT(0);
+
             /* AM? */
+
             len = strlen(_ctloc(am_pm[0]));
-            if (strncasecmp(_ctloc(am_pm[0]), (const char*)bp, len) == 0) {
-                if (tm->tm_hour > 12)   /* i.e., 13:00 AM ?! */
-                    return (NULL);
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  {
+                    return NULL;
+                  }
                 else if (tm->tm_hour == 12)
+                  {
                     tm->tm_hour = 0;
+                  }
 
                 bp += len;
                 break;
-            }
+              }
+
             /* PM? */
+
             len = strlen(_ctloc(am_pm[1]));
-            if (strncasecmp(_ctloc(am_pm[1]), (const char*)bp, len) == 0) {
-                if (tm->tm_hour > 12)   /* i.e., 13:00 PM ?! */
-                    return (NULL);
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  {
+                    return NULL;
+                  }
                 else if (tm->tm_hour < 12)
+                  {
                     tm->tm_hour += 12;
+                  }
 
                 bp += len;
                 break;
-            }
+              }
 
             /* Nothing matched. */
-            return (NULL);
 
-        case 'S':   /* The seconds. */
+            return NULL;
+
+          case 'S': /* The seconds. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'U':   /* The week of year, beginning on sunday. */
-        case 'W':   /* The week of year, beginning on monday. */
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
             _LEGAL_ALT(_ALT_O);
-            /*
-             * XXX This is bogus, as we can not assume any valid
-             * information present in the tm structure at this
-             * point to calculate a real value, so just check the
-             * range for now.
-             */
-             if (!(_conv_num(&bp, &i, 0, 53)))
-                return (NULL);
-             break;
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              {
+                return NULL;
+              }
 
-        case 'w':   /* The day of week, beginning on sunday. */
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'Y':   /* The year. */
+          case 'Y': /* The year. */
             _LEGAL_ALT(_ALT_E);
             if (!(_conv_num(&bp, &i, 0, 9999)))
-                return (NULL);
+              {
+                return NULL;
+              }
 
             cr->relyear = -1;
             tm->tm_year = i - TM_YEAR_BASE;
             break;
 
-        case 'y':   /* The year within the century (2 digits). */
+          case 'y': /* The year within the century (2 digits). */
             _LEGAL_ALT(_ALT_E | _ALT_O);
             if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        /*
-         * Miscellaneous conversions.
-         */
-        case 'n':   /* Any kind of white-space. */
-        case 't':
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
             _LEGAL_ALT(0);
             while (isspace(*bp))
+              {
                 bp++;
-            break;
+              }
 
+            break;
 
-        default:    /* Unknown/unsupported conversion. */
-            return (NULL);
+          default: /* Unknown/unsupported conversion. */
+            return NULL;
         }
-
-
     }
 
-    /*
-     * We need to evaluate the two digit year spec (%y)
-     * last as we can get a century spec (%C) at any time.
-     */
-    if (cr->relyear != -1) {
-        if (cr->century == TM_YEAR_BASE) {
-            if (cr->relyear <= 68)
-                tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
-            else
-                tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
-        } else {
-            tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        {
+          tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+        }
+      else
+        {
+          tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
         }
     }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
 
-    return (unsigned char*)bp;
+  return (FAR unsigned char *)bp;
 }
 
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
 
-static int
-_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
-{
-    int result = 0;
-    int rulim = ulim;
-
-    while (isspace(**buf))
-        (*buf)++;
-
-    if (**buf < '0' || **buf > '9')
-        return (0);
-
-    /* we use rulim to break out of the loop when we run out of digits */
-    do {
-        result *= 10;
-        result += *(*buf)++ - '0';
-        rulim /= 10;
-    } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
-
-    if (result < llim || result > ulim)
-        return (0);
+/****************************************************************************
+ * Name: strptime
+ *
+ * Description:
+ *   Convert a string to a time type according to a specific time format
+ *   The strptime() function processes the input string from left to
+ *   right.  Each of the three possible input elements (whitespace,
+ *   literal, or format) are handled one after the other.  If the
+ *   input cannot be matched to the format string, the function stops.
+ *   The remainder of the format and input strings are not processed.
+ *   The supported input field descriptors are listed below.  In case
+ *   a text string (such as the name of a day of the week or a month
+ *   name) is to be matched, the comparison is case insensitive.  In
+ *   case a number is to be matched, leading zeros are permitted but
+ *   not required.
+ *   %a     The abbreviated weekday name according to the current locale.
+ *   %A     The full weekday name according to the current locale.
+ *   %b     The abbreviated month name according to the current locale.
+ *   %B     The full month name according to the current locale.
+ *   %C     The century number (year/100) as a 2-digit integer. (SU)
+ *   %d     The day of the month as a decimal number (range 01 to 31).
+ *   %e     Like %d, the day of the month as a decimal number, but a leading
+ *          zero is replaced by a space.
+ *   %h     Equivalent to %b.  (SU)
+ *   %H     The hour as a decimal number using a 24-hour clock
+ *          (range 00 to 23).
+ *   %I     The  hour as a decimal number using a 12-hour clock
+ *          (range 01 to 12).
+ *   %j     The day of the year as a decimal number (range 001 to 366).
+ *   %k     The hour (24-hour clock) as a decimal number (range  0  to  23);
+ *          single digits are preceded by a blank.  (See also %H.)  (TZ)
+ *   %l     The  hour  (12-hour  clock) as a decimal number (range 1 to 12);
+ *          single digits are preceded by a blank.  (See also %I.)  (TZ)
+ *   %m     The month as a decimal number (range 01 to 12).
+ *   %M     The minute as a decimal number (range 00 to 59).
+ *   %n     A newline character. (SU)
+ *   %p     Either "AM" or "PM" according to the given time  value, or the
+ *          corresponding  strings  for the current locale.  Noon is treated
+ *          as "PM" and midnight as "AM".
+ *   %P     Like %p but in lowercase: "am" or "pm" or a corresponding string
+ *          for the current locale. (GNU)
+ *   %S     The second as a decimal number (range 00 to 60).  (The range is
+ *          up to 60 to allow for occasional leap seconds.)
+ *   %t     A tab character. (SU)
+ *   %y     The year as a decimal number without a century (range 00 to 99).
+ *   %Y     The year as a decimal number including the century.
+ *   %%     A literal '%' character.
+ *
+ * Returned Value:
+ *   The return value of the function is a pointer to the first
+ *   character not processed in this function call.  In case the input
+ *   string contains more characters than required by the format
+ *   string, the return value points right after the last consumed
+ *   input character.  In case the whole input string is consumed, the
+ *   return value points to the null byte at the end of the string.
+ *   If strptime() fails to match all of the format string and
+ *   therefore an error occurred, the function returns NULL.
+ *
+ ****************************************************************************/
 
-    *dest = result;
-    return (1);
+char *strptime(FAR const char *buf, FAR const char *fmt, FAR struct tm *tm)

Review Comment:
   add FAR before char



##########
libs/libc/time/lib_strptime.c:
##########
@@ -53,382 +67,556 @@ static const struct {
     const char *d_fmt;
     const char *t_fmt;
     const char *t_fmt_ampm;
-} _DefaultTimeLocale = {
-    {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
-    },
-    {
-        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-        "Friday", "Saturday"
-    },
-    {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    },
-    {
-        "January", "February", "March", "April", "May", "June", "July",
-        "August", "September", "October", "November", "December"
-    },
-    {
-        "AM", "PM"
-    },
-    "%a %b %d %H:%M:%S %Y",
-    "%m/%d/%y",
-    "%H:%M:%S",
-    "%I:%M:%S %p"
+} g_defaulttimelocale =
+{
+  {
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+  },
+  {
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+    "Friday", "Saturday"
+  },
+  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  },
+  {
+    "January", "February", "March", "April", "May", "June", "July",
+    "August", "September", "October", "November", "December"
+  },
+  {
+    "AM", "PM"
+  },
+  "%a %b %d %H:%M:%S %Y",
+  "%m/%d/%y",
+  "%H:%M:%S",
+  "%I:%M:%S %p"
 };
 
-#define _ctloc(x) (_DefaultTimeLocale.x)
+struct century_relyear
+{
+  int century;
+  int relyear;
+};
 
-/*
- * We do not implement alternate representations. However, we always
- * check whether a given modifier is allowed for a certain conversion.
- */
-#define _ALT_E          0x01
-#define _ALT_O          0x02
-#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
 
+static int _conv_num(FAR const unsigned char **buf, FAR int *dest,
+                     int llim, int ulim)
+{
+  int result = 0;
+  int rulim = ulim;
 
-struct century_relyear {
-    int century;
-    int relyear;
-};
-static  int _conv_num(const unsigned char **, int *, int, int);
-static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
-        struct century_relyear *);
+  while (isspace(**buf))
+    {
+      (*buf)++;
+    }
 
+  if (**buf < '0' || **buf > '9')
+    {
+      return 0;
+    }
 
-char *
-strptime(const char *buf, const char *fmt, struct tm *tm)
-{
-    struct century_relyear cr;
-    cr.century = TM_YEAR_BASE;
-    cr.relyear = -1;
-    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
+  /* we use rulim to break out of the loop when we run out of digits */
+
+  do
+    {
+      result *= 10;
+      result += *(*buf)++ - '0';
+      rulim /= 10;
+    }
+  while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+  if (result < llim || result > ulim)
+    {
+      return 0;
+    }
+
+  *dest = result;
+  return 1;
 }
 
-static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
+static FAR const unsigned char *_strptime(FAR const unsigned char *buf,
+                                          FAR const char *fmt,
+                                          FAR struct tm *tm,
+                                          FAR struct century_relyear *cr)
 {
-    unsigned char c;
-    const unsigned char *bp;
-    size_t len = 0;
-    int alt_format, i;
-
-    bp = (unsigned char *)buf;
-    while ((c = *fmt) != '\0') {
-        /* Clear `alternate' modifier prior to new conversion. */
-        alt_format = 0;
-
-        /* Eat up white-space. */
-        if (isspace(c)) {
-            while (isspace(*bp))
-                bp++;
+  unsigned char c;
+  FAR const unsigned char *bp;
+  size_t len = 0;
+  int alt_format;
+  int i;
+
+  bp = (FAR const unsigned char *)buf;
+  while ((c = *fmt) != '\0')
+    {
+      /* Clear `alternate' modifier prior to new conversion. */
+
+      alt_format = 0;
+
+      /* Eat up white-space. */
+
+      if (isspace(c))
+        {
+          while (isspace(*bp))
+            bp++;
+
+          fmt++;
+          continue;
+        }
 
-            fmt++;
-            continue;
+      if ((c = *fmt++) != '%')
+        {
+          goto literal;
         }
 
-        if ((c = *fmt++) != '%')
-            goto literal;
+    again:
+      switch (c = *fmt++)
+        {
+          case '%': /* "%%" is converted to "%". */
+          literal:
+            if (c != *bp++)
+              {
+                return NULL;
+              }
 
-again:      switch (c = *fmt++) {
-        case '%':   /* "%%" is converted to "%". */
-literal:
-        if (c != *bp++)
-            return (NULL);
+            break;
 
-        break;
+            /* "Alternative" modifiers. Just set the appropriate flag
+            * and start over again.
+            */
 
-        /*
-         * "Alternative" modifiers. Just set the appropriate flag
-         * and start over again.
-         */
-        case 'E':   /* "%E?" alternative conversion modifier. */
+          case 'E': /* "%E?" alternative conversion modifier. */
             _LEGAL_ALT(0);
             alt_format |= _ALT_E;
             goto again;
 
-        case 'O':   /* "%O?" alternative conversion modifier. */
+          case 'O': /* "%O?" alternative conversion modifier. */
             _LEGAL_ALT(0);
             alt_format |= _ALT_O;
             goto again;
 
-        /*
-         * "Complex" conversion rules, implemented through recursion.
-         */
-        case 'c':   /* Date and time, using the locale's format. */
+            /* "Complex" conversion rules, implemented through recursion. */
+
+          case 'c': /* Date and time, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'D':   /* The date as "%m/%d/%y". */
+          case 'D': /* The date as "%m/%d/%y". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'R':   /* The time as "%H:%M". */
+          case 'R': /* The time as "%H:%M". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'r':   /* The time as "%I:%M:%S %p". */
+          case 'r': /* The time as "%I:%M:%S %p". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'T':   /* The time as "%H:%M:%S". */
+          case 'T': /* The time as "%H:%M:%S". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'X':   /* The time, using the locale's format. */
+          case 'X': /* The time, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'x':   /* The date, using the locale's format. */
+          case 'x': /* The date, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
             if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        /*
-         * "Elementary" conversion rules.
-         */
-        case 'A':   /* The day of week, using the locale's form. */
-        case 'a':
+            /* "Elementary" conversion rules. */
+
+          case 'A': /* The day of week, using the locale's form. */
+          case 'a':
             _LEGAL_ALT(0);
-            for (i = 0; i < 7; i++) {
+            for (i = 0; i < 7; i++)
+              {
                 /* Full name. */
+
                 len = strlen(_ctloc(day[i]));
-                if (strncasecmp(_ctloc(day[i]), (const char*)bp, len) == 0)
-                    break;
+                if (strncasecmp(_ctloc(day[i]),
+                                (const char *)bp, len) == 0)
+                  break;
 
                 /* Abbreviated name. */
+
                 len = strlen(_ctloc(abday[i]));
-                if (strncasecmp(_ctloc(abday[i]), (const char*)bp, len) == 0)
-                    break;
-            }
+                if (strncasecmp(_ctloc(abday[i]),
+                                (const char *)bp, len) == 0)
+                  break;
+              }
 
             /* Nothing matched. */
+
             if (i == 7)
-                return (NULL);
+              {
+                return NULL;
+              }
 
             tm->tm_wday = i;
             bp += len;
             break;
 
-        case 'B':   /* The month, using the locale's form. */
-        case 'b':
-        case 'h':
+          case 'B': /* The month, using the locale's form. */
+          case 'b':
+          case 'h':
             _LEGAL_ALT(0);
-            for (i = 0; i < 12; i++) {
+            for (i = 0; i < 12; i++)
+              {
                 /* Full name. */
+
                 len = strlen(_ctloc(mon[i]));
-                if (strncasecmp(_ctloc(mon[i]), (const char*)bp, len) == 0)
+                if (strncasecmp(_ctloc(mon[i]),
+                                (const char *)bp, len) == 0)
+                  {
                     break;
+                  }
 
                 /* Abbreviated name. */
+
                 len = strlen(_ctloc(abmon[i]));
-                if (strncasecmp(_ctloc(abmon[i]), (const char*)bp, len) == 0)
+                if (strncasecmp(_ctloc(abmon[i]),
+                                (const char *)bp, len) == 0)
+                  {
                     break;
-            }
+                  }
+              }
 
             /* Nothing matched. */
+
             if (i == 12)
-                return (NULL);
+              {
+                return NULL;
+              }
 
             tm->tm_mon = i;
             bp += len;
             break;
 
-        case 'C':   /* The century number. */
+          case 'C': /* The century number. */
             _LEGAL_ALT(_ALT_E);
             if (!(_conv_num(&bp, &i, 0, 99)))
+              {
                 return (NULL);
+              }
 
             cr->century = i * 100;
             break;
 
-        case 'd':   /* The day of month. */
-        case 'e':
+          case 'd': /* The day of month. */
+          case 'e':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+              {
                 return (NULL);
+              }
+
             break;
 
-        case 'k':   /* The hour (24-hour clock representation). */
+          case 'k': /* The hour (24-hour clock representation). */
             _LEGAL_ALT(0);
+
             /* FALLTHROUGH */
-        case 'H':
+
+          case 'H':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'l':   /* The hour (12-hour clock representation). */
+          case 'l': /* The hour (12-hour clock representation). */
             _LEGAL_ALT(0);
+
             /* FALLTHROUGH */
-        case 'I':
+
+          case 'I':
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+              {
                 return (NULL);
+              }
+
             break;
 
-        case 'j':   /* The day of year. */
+          case 'j': /* The day of year. */
             _LEGAL_ALT(0);
             if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             tm->tm_yday--;
             break;
 
-        case 'M':   /* The minute. */
+          case 'M': /* The minute. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'm':   /* The month. */
+          case 'm': /* The month. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             tm->tm_mon--;
             break;
 
-        case 'p':   /* The locale's equivalent of AM/PM. */
+          case 'p': /* The locale's equivalent of AM/PM. */
             _LEGAL_ALT(0);
+
             /* AM? */
+
             len = strlen(_ctloc(am_pm[0]));
-            if (strncasecmp(_ctloc(am_pm[0]), (const char*)bp, len) == 0) {
-                if (tm->tm_hour > 12)   /* i.e., 13:00 AM ?! */
-                    return (NULL);
+            if (strncasecmp(_ctloc(am_pm[0]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
+                  {
+                    return NULL;
+                  }
                 else if (tm->tm_hour == 12)
+                  {
                     tm->tm_hour = 0;
+                  }
 
                 bp += len;
                 break;
-            }
+              }
+
             /* PM? */
+
             len = strlen(_ctloc(am_pm[1]));
-            if (strncasecmp(_ctloc(am_pm[1]), (const char*)bp, len) == 0) {
-                if (tm->tm_hour > 12)   /* i.e., 13:00 PM ?! */
-                    return (NULL);
+            if (strncasecmp(_ctloc(am_pm[1]), (const char *)bp, len) == 0)
+              {
+                if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
+                  {
+                    return NULL;
+                  }
                 else if (tm->tm_hour < 12)
+                  {
                     tm->tm_hour += 12;
+                  }
 
                 bp += len;
                 break;
-            }
+              }
 
             /* Nothing matched. */
-            return (NULL);
 
-        case 'S':   /* The seconds. */
+            return NULL;
+
+          case 'S': /* The seconds. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'U':   /* The week of year, beginning on sunday. */
-        case 'W':   /* The week of year, beginning on monday. */
+          case 'U': /* The week of year, beginning on sunday. */
+          case 'W': /* The week of year, beginning on monday. */
             _LEGAL_ALT(_ALT_O);
-            /*
-             * XXX This is bogus, as we can not assume any valid
-             * information present in the tm structure at this
-             * point to calculate a real value, so just check the
-             * range for now.
-             */
-             if (!(_conv_num(&bp, &i, 0, 53)))
-                return (NULL);
-             break;
+            /* XXX This is bogus, as we can not assume any valid
+            * information present in the tm structure at this
+            * point to calculate a real value, so just check the
+            * range for now.
+            */
+
+            if (!(_conv_num(&bp, &i, 0, 53)))
+              {
+                return NULL;
+              }
 
-        case 'w':   /* The day of week, beginning on sunday. */
+            break;
+
+          case 'w': /* The day of week, beginning on sunday. */
             _LEGAL_ALT(_ALT_O);
             if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        case 'Y':   /* The year. */
+          case 'Y': /* The year. */
             _LEGAL_ALT(_ALT_E);
             if (!(_conv_num(&bp, &i, 0, 9999)))
-                return (NULL);
+              {
+                return NULL;
+              }
 
             cr->relyear = -1;
             tm->tm_year = i - TM_YEAR_BASE;
             break;
 
-        case 'y':   /* The year within the century (2 digits). */
+          case 'y': /* The year within the century (2 digits). */
             _LEGAL_ALT(_ALT_E | _ALT_O);
             if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
-                return (NULL);
+              {
+                return NULL;
+              }
+
             break;
 
-        /*
-         * Miscellaneous conversions.
-         */
-        case 'n':   /* Any kind of white-space. */
-        case 't':
+            /* Miscellaneous conversions. */
+
+          case 'n': /* Any kind of white-space. */
+          case 't':
             _LEGAL_ALT(0);
             while (isspace(*bp))
+              {
                 bp++;
-            break;
+              }
 
+            break;
 
-        default:    /* Unknown/unsupported conversion. */
-            return (NULL);
+          default: /* Unknown/unsupported conversion. */
+            return NULL;
         }
-
-
     }
 
-    /*
-     * We need to evaluate the two digit year spec (%y)
-     * last as we can get a century spec (%C) at any time.
-     */
-    if (cr->relyear != -1) {
-        if (cr->century == TM_YEAR_BASE) {
-            if (cr->relyear <= 68)
-                tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
-            else
-                tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
-        } else {
-            tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+  /* We need to evaluate the two digit year spec (%y)
+   * last as we can get a century spec (%C) at any time.
+   */
+
+  if (cr->relyear != -1)
+  {
+    if (cr->century == TM_YEAR_BASE)
+    {
+      if (cr->relyear <= 68)
+        {
+          tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
+        }
+      else
+        {
+          tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
         }
     }
+    else
+    {
+      tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
+    }
+  }
 
-    return (unsigned char*)bp;
+  return (FAR unsigned char *)bp;
 }
 
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
 
-static int
-_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
-{
-    int result = 0;
-    int rulim = ulim;
-
-    while (isspace(**buf))
-        (*buf)++;
-
-    if (**buf < '0' || **buf > '9')
-        return (0);
-
-    /* we use rulim to break out of the loop when we run out of digits */
-    do {
-        result *= 10;
-        result += *(*buf)++ - '0';
-        rulim /= 10;
-    } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
-
-    if (result < llim || result > ulim)
-        return (0);
+/****************************************************************************
+ * Name: strptime
+ *
+ * Description:
+ *   Convert a string to a time type according to a specific time format
+ *   The strptime() function processes the input string from left to
+ *   right.  Each of the three possible input elements (whitespace,
+ *   literal, or format) are handled one after the other.  If the
+ *   input cannot be matched to the format string, the function stops.
+ *   The remainder of the format and input strings are not processed.
+ *   The supported input field descriptors are listed below.  In case
+ *   a text string (such as the name of a day of the week or a month
+ *   name) is to be matched, the comparison is case insensitive.  In
+ *   case a number is to be matched, leading zeros are permitted but
+ *   not required.
+ *   %a     The abbreviated weekday name according to the current locale.
+ *   %A     The full weekday name according to the current locale.
+ *   %b     The abbreviated month name according to the current locale.
+ *   %B     The full month name according to the current locale.
+ *   %C     The century number (year/100) as a 2-digit integer. (SU)
+ *   %d     The day of the month as a decimal number (range 01 to 31).
+ *   %e     Like %d, the day of the month as a decimal number, but a leading
+ *          zero is replaced by a space.
+ *   %h     Equivalent to %b.  (SU)
+ *   %H     The hour as a decimal number using a 24-hour clock
+ *          (range 00 to 23).
+ *   %I     The  hour as a decimal number using a 12-hour clock
+ *          (range 01 to 12).
+ *   %j     The day of the year as a decimal number (range 001 to 366).
+ *   %k     The hour (24-hour clock) as a decimal number (range  0  to  23);
+ *          single digits are preceded by a blank.  (See also %H.)  (TZ)
+ *   %l     The  hour  (12-hour  clock) as a decimal number (range 1 to 12);
+ *          single digits are preceded by a blank.  (See also %I.)  (TZ)
+ *   %m     The month as a decimal number (range 01 to 12).
+ *   %M     The minute as a decimal number (range 00 to 59).
+ *   %n     A newline character. (SU)
+ *   %p     Either "AM" or "PM" according to the given time  value, or the
+ *          corresponding  strings  for the current locale.  Noon is treated
+ *          as "PM" and midnight as "AM".
+ *   %P     Like %p but in lowercase: "am" or "pm" or a corresponding string
+ *          for the current locale. (GNU)
+ *   %S     The second as a decimal number (range 00 to 60).  (The range is
+ *          up to 60 to allow for occasional leap seconds.)
+ *   %t     A tab character. (SU)
+ *   %y     The year as a decimal number without a century (range 00 to 99).
+ *   %Y     The year as a decimal number including the century.
+ *   %%     A literal '%' character.
+ *
+ * Returned Value:
+ *   The return value of the function is a pointer to the first
+ *   character not processed in this function call.  In case the input
+ *   string contains more characters than required by the format
+ *   string, the return value points right after the last consumed
+ *   input character.  In case the whole input string is consumed, the
+ *   return value points to the null byte at the end of the string.
+ *   If strptime() fails to match all of the format string and
+ *   therefore an error occurred, the function returns NULL.
+ *
+ ****************************************************************************/
 
-    *dest = result;
-    return (1);
+char *strptime(FAR const char *buf, FAR const char *fmt, FAR struct tm *tm)
+{
+  struct century_relyear cr;
+  cr.century = TM_YEAR_BASE;
+  cr.relyear = -1;
+  return (char *)(_strptime((FAR const unsigned char *)buf, fmt, tm, &cr));

Review Comment:
   add FAR to (char *)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org