Print this page
2964 need POSIX 2008 locale object support
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Approved by: TBD

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libc/port/locale/strptime.c
          +++ new/usr/src/lib/libc/port/locale/strptime.c
   1    1  /*
   2    2   * Copyright (c) 2014 Gary Mills
        3 + * Copyright 2014 Garrett D'Amore <garrett@damore.org>
   3    4   * Copyright 2011, Nexenta Systems, Inc.  All rights reserved.
   4    5   * Copyright (c) 1994 Powerdog Industries.  All rights reserved.
   5    6   *
   6    7   * Redistribution and use in source and binary forms, with or without
   7    8   * modification, are permitted provided that the following conditions
   8    9   * are met:
   9   10   *
  10   11   * 1. Redistributions of source code must retain the above copyright
  11   12   *    notice, this list of conditions and the following disclaimer.
  12   13   *
↓ open down ↓ 20 lines elided ↑ open up ↑
  33   34   */
  34   35  
  35   36  #include "lint.h"
  36   37  #include <time.h>
  37   38  #include <ctype.h>
  38   39  #include <errno.h>
  39   40  #include <stdlib.h>
  40   41  #include <string.h>
  41   42  #include <pthread.h>
  42   43  #include <alloca.h>
       44 +#include <locale.h>
  43   45  #include "timelocal.h"
       46 +#include "localeimpl.h"
  44   47  
  45   48  #define asizeof(a)      (sizeof (a) / sizeof ((a)[0]))
  46   49  
  47   50  #define F_GMT           (1 << 0)
  48      -#define F_ZERO          (1 << 1)
  49   51  #define F_RECURSE       (1 << 2)
  50   52  
  51   53  static char *
  52      -__strptime(const char *buf, const char *fmt, struct tm *tm, int *flagsp)
       54 +__strptime(const char *_RESTRICT_KYWD buf, const char *_RESTRICT_KYWD fmt,
       55 +    struct tm *_RESTRICT_KYWD tm, int *_RESTRICT_KYWD flagsp,
       56 +    locale_t _RESTRICT_KYWD loc)
  53   57  {
  54   58          char    c;
  55   59          const char *ptr;
  56   60          int     i, len, recurse = 0;
  57   61          int Ealternative, Oalternative;
  58      -        struct lc_time_T *tptr = __get_current_time_locale();
       62 +        const struct lc_time *tptr = loc->time;
  59   63  
  60   64          if (*flagsp & F_RECURSE)
  61   65                  recurse = 1;
  62   66          *flagsp |= F_RECURSE;
  63   67  
  64      -        if (*flagsp & F_ZERO)
  65      -                (void) memset(tm, 0, sizeof (*tm));
  66      -        *flagsp &= ~F_ZERO;
  67      -
  68   68          ptr = fmt;
  69   69          while (*ptr != 0) {
  70   70                  if (*buf == 0)
  71   71                          break;
  72   72  
  73   73                  c = *ptr++;
  74   74  
  75   75                  if (c != '%') {
  76   76                          if (isspace(c))
  77   77                                  while (isspace(*buf))
↓ open down ↓ 8 lines elided ↑ open up ↑
  86   86  label:
  87   87                  c = *ptr++;
  88   88                  switch (c) {
  89   89                  case 0:
  90   90                  case '%':
  91   91                          if (*buf++ != '%')
  92   92                                  return (NULL);
  93   93                          break;
  94   94  
  95   95                  case '+':
  96      -                        buf = __strptime(buf, tptr->date_fmt, tm, flagsp);
       96 +                        buf = __strptime(buf, tptr->date_fmt, tm, flagsp, loc);
  97   97                          if (buf == NULL)
  98   98                                  return (NULL);
  99   99                          break;
 100  100  
 101  101                  case 'C':
 102  102                          if (!isdigit(*buf))
 103  103                                  return (NULL);
 104  104  
 105  105                          /* XXX This will break for 3-digit centuries. */
 106  106                          len = 2;
↓ open down ↓ 2 lines elided ↑ open up ↑
 109  109                                  i += *buf - '0';
 110  110                                  len--;
 111  111                          }
 112  112                          if (i < 19)
 113  113                                  return (NULL);
 114  114  
 115  115                          tm->tm_year = i * 100 - 1900;
 116  116                          break;
 117  117  
 118  118                  case 'c':
 119      -                        buf = __strptime(buf, tptr->c_fmt, tm, flagsp);
      119 +                        buf = __strptime(buf, tptr->c_fmt, tm, flagsp, loc);
 120  120                          if (buf == NULL)
 121  121                                  return (NULL);
 122  122                          break;
 123  123  
 124  124                  case 'D':
 125      -                        buf = __strptime(buf, "%m/%d/%y", tm, flagsp);
      125 +                        buf = __strptime(buf, "%m/%d/%y", tm, flagsp, loc);
 126  126                          if (buf == NULL)
 127  127                                  return (NULL);
 128  128                          break;
 129  129  
 130  130                  case 'E':
 131  131                          if (Ealternative || Oalternative)
 132  132                                  break;
 133  133                          Ealternative++;
 134  134                          goto label;
 135  135  
 136  136                  case 'O':
 137  137                          if (Ealternative || Oalternative)
 138  138                                  break;
 139  139                          Oalternative++;
 140  140                          goto label;
 141  141  
 142  142                  case 'F':
 143      -                        buf = __strptime(buf, "%Y-%m-%d", tm, flagsp);
      143 +                        buf = __strptime(buf, "%Y-%m-%d", tm, flagsp, loc);
 144  144                          if (buf == NULL)
 145  145                                  return (NULL);
 146  146                          break;
 147  147  
 148  148                  case 'R':
 149      -                        buf = __strptime(buf, "%H:%M", tm, flagsp);
      149 +                        buf = __strptime(buf, "%H:%M", tm, flagsp, loc);
 150  150                          if (buf == NULL)
 151  151                                  return (NULL);
 152  152                          break;
 153  153  
 154  154                  case 'r':
 155      -                        buf = __strptime(buf, tptr->ampm_fmt, tm, flagsp);
      155 +                        buf = __strptime(buf, tptr->ampm_fmt, tm, flagsp, loc);
 156  156                          if (buf == NULL)
 157  157                                  return (NULL);
 158  158                          break;
 159  159  
 160  160                  case 'T':
 161      -                        buf = __strptime(buf, "%H:%M:%S", tm, flagsp);
      161 +                        buf = __strptime(buf, "%H:%M:%S", tm, flagsp, loc);
 162  162                          if (buf == NULL)
 163  163                                  return (NULL);
 164  164                          break;
 165  165  
 166  166                  case 'X':
 167      -                        buf = __strptime(buf, tptr->X_fmt, tm, flagsp);
      167 +                        buf = __strptime(buf, tptr->X_fmt, tm, flagsp, loc);
 168  168                          if (buf == NULL)
 169  169                                  return (NULL);
 170  170                          break;
 171  171  
 172  172                  case 'x':
 173      -                        buf = __strptime(buf, tptr->x_fmt, tm, flagsp);
      173 +                        buf = __strptime(buf, tptr->x_fmt, tm, flagsp, loc);
 174  174                          if (buf == NULL)
 175  175                                  return (NULL);
 176  176                          break;
 177  177  
 178  178                  case 'j':
 179  179                          if (!isdigit(*buf))
 180  180                                  return (NULL);
 181  181  
 182  182                          len = 3;
 183  183                          for (i = 0; len && isdigit(*buf); buf++) {
↓ open down ↓ 328 lines elided ↑ open up ↑
 512  512                  if (buf && (*flagsp & F_GMT)) {
 513  513                          time_t t = timegm(tm);
 514  514                          (void) localtime_r(&t, tm);
 515  515                  }
 516  516          }
 517  517  
 518  518          return ((char *)buf);
 519  519  }
 520  520  
 521  521  char *
 522      -strptime(const char *buf, const char *fmt, struct tm *tm)
      522 +strptime(const char *_RESTRICT_KYWD buf, const char *_RESTRICT_KYWD fmt,
      523 +    struct tm *_RESTRICT_KYWD tm)
 523  524  {
 524      -        int     flags = F_ZERO;
      525 +        int     flags = 0;
 525  526  
 526      -        return (__strptime(buf, fmt, tm, &flags));
      527 +        (void) memset(tm, 0, sizeof (*tm));
      528 +
      529 +        return (__strptime(buf, fmt, tm, &flags, uselocale(NULL)));
 527  530  }
 528  531  
 529  532  /*
 530  533   * This is used by Solaris, and is a variant that does not clear the
 531  534   * incoming tm.  It is triggered by -D_STRPTIME_DONTZERO.
 532  535   */
 533  536  char *
 534      -__strptime_dontzero(const char *buf, const char *fmt, struct tm *tm)
      537 +__strptime_dontzero(const char *_RESTRICT_KYWD buf,
      538 +    const char *_RESTRICT_KYWD fmt, struct tm *_RESTRICT_KYWD tm)
 535  539  {
 536  540          int     flags = 0;
 537  541  
 538      -        return (__strptime(buf, fmt, tm, &flags));
      542 +        return (__strptime(buf, fmt, tm, &flags, uselocale(NULL)));
      543 +}
      544 +
      545 +/*
      546 + * strptime_l is an extension that seems natural, and indeed, MacOS X
      547 + * includes it within their <xlocale.h> and it is part of GNU libc as well.
      548 + * For now we restrict it to the cases where strict namespaces are not
      549 + * included.  We expect to see it in a future version of POSIX.  locale_t is
      550 + * not a restrict, since the spec for it doesn't assume its a pointer.  We
      551 + * therefore pass it analagously to the way strftime_l is specified.
      552 + *
      553 + * We are not providing a non-zeroing version at this time.
      554 + */
      555 +char *
      556 +strptime_l(const char *_RESTRICT_KYWD buf, const char *_RESTRICT_KYWD fmt,
      557 +    struct tm *_RESTRICT_KYWD tm, locale_t loc)
      558 +{
      559 +        int     flags =  0;
      560 +
      561 +        (void) memset(tm, 0, sizeof (*tm));
      562 +
      563 +        return (__strptime(buf, fmt, tm, &flags, loc));
 539  564  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX