Print this page
2964 need POSIX 2008 locale object support
   1 /*
   2  * Copyright 2011, Nexenta Systems, Inc.  All rights reserved.
   3  * Copyright (c) 1994 Powerdog Industries.  All rights reserved.
   4  *





   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  *
   9  * 1. Redistributions of source code must retain the above copyright
  10  *    notice, this list of conditions and the following disclaimer.
  11  *
  12  * 2. Redistributions in binary form must reproduce the above copyright
  13  *    notice, this list of conditions and the following disclaimer
  14  *    in the documentation and/or other materials provided with the
  15  *    distribution.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
  18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
  21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,


  31  * official policies, either expressed or implied, of Powerdog Industries.
  32  */
  33 
  34 #include "lint.h"
  35 #include <time.h>
  36 #include <ctype.h>
  37 #include <errno.h>
  38 #include <stdlib.h>
  39 #include <string.h>
  40 #include <pthread.h>
  41 #include <alloca.h>
  42 #include "timelocal.h"
  43 
  44 #define asizeof(a)      (sizeof (a) / sizeof ((a)[0]))
  45 
  46 #define F_GMT           (1 << 0)
  47 #define F_ZERO          (1 << 1)
  48 #define F_RECURSE       (1 << 2)
  49 
  50 static char *
  51 __strptime(const char *buf, const char *fmt, struct tm *tm, int *flagsp)

  52 {
  53         char    c;
  54         const char *ptr;
  55         int     i, len, recurse = 0;
  56         int Ealternative, Oalternative;
  57         struct lc_time_T *tptr = __get_current_time_locale();
  58 
  59         if (*flagsp & F_RECURSE)
  60                 recurse = 1;
  61         *flagsp |= F_RECURSE;
  62 
  63         if (*flagsp & F_ZERO)
  64                 (void) memset(tm, 0, sizeof (*tm));
  65         *flagsp &= ~F_ZERO;
  66 
  67         ptr = fmt;
  68         while (*ptr != 0) {
  69                 if (*buf == 0)
  70                         break;
  71 
  72                 c = *ptr++;
  73 
  74                 if (c != '%') {
  75                         if (isspace(c))
  76                                 while (isspace(*buf))
  77                                         buf++;
  78                         else if (c != *buf++)
  79                                 return (NULL);
  80                         continue;
  81                 }
  82 
  83                 Ealternative = 0;
  84                 Oalternative = 0;
  85 label:
  86                 c = *ptr++;
  87                 switch (c) {
  88                 case 0:
  89                 case '%':
  90                         if (*buf++ != '%')
  91                                 return (NULL);
  92                         break;
  93 
  94                 case '+':
  95                         buf = __strptime(buf, tptr->date_fmt, tm, flagsp);

  96                         if (buf == NULL)
  97                                 return (NULL);
  98                         break;
  99 
 100                 case 'C':
 101                         if (!isdigit(*buf))
 102                                 return (NULL);
 103 
 104                         /* XXX This will break for 3-digit centuries. */
 105                         len = 2;
 106                         for (i = 0; len && isdigit(*buf); buf++) {
 107                                 i *= 10;
 108                                 i += *buf - '0';
 109                                 len--;
 110                         }
 111                         if (i < 19)
 112                                 return (NULL);
 113 
 114                         tm->tm_year = i * 100 - 1900;
 115                         break;
 116 
 117                 case 'c':
 118                         buf = __strptime(buf, tptr->c_fmt, tm, flagsp);

 119                         if (buf == NULL)
 120                                 return (NULL);
 121                         break;
 122 
 123                 case 'D':
 124                         buf = __strptime(buf, "%m/%d/%y", tm, flagsp);

 125                         if (buf == NULL)
 126                                 return (NULL);
 127                         break;
 128 
 129                 case 'E':
 130                         if (Ealternative || Oalternative)
 131                                 break;
 132                         Ealternative++;
 133                         goto label;
 134 
 135                 case 'O':
 136                         if (Ealternative || Oalternative)
 137                                 break;
 138                         Oalternative++;
 139                         goto label;
 140 
 141                 case 'F':
 142                         buf = __strptime(buf, "%Y-%m-%d", tm, flagsp);

 143                         if (buf == NULL)
 144                                 return (NULL);
 145                         break;
 146 
 147                 case 'R':
 148                         buf = __strptime(buf, "%H:%M", tm, flagsp);

 149                         if (buf == NULL)
 150                                 return (NULL);
 151                         break;
 152 
 153                 case 'r':
 154                         buf = __strptime(buf, tptr->ampm_fmt, tm, flagsp);

 155                         if (buf == NULL)
 156                                 return (NULL);
 157                         break;
 158 
 159                 case 'T':
 160                         buf = __strptime(buf, "%H:%M:%S", tm, flagsp);

 161                         if (buf == NULL)
 162                                 return (NULL);
 163                         break;
 164 
 165                 case 'X':
 166                         buf = __strptime(buf, tptr->X_fmt, tm, flagsp);

 167                         if (buf == NULL)
 168                                 return (NULL);
 169                         break;
 170 
 171                 case 'x':
 172                         buf = __strptime(buf, tptr->x_fmt, tm, flagsp);

 173                         if (buf == NULL)
 174                                 return (NULL);
 175                         break;
 176 
 177                 case 'j':
 178                         if (!isdigit(*buf))
 179                                 return (NULL);
 180 
 181                         len = 3;
 182                         for (i = 0; len && isdigit(*buf); buf++) {
 183                                 i *= 10;
 184                                 i += *buf - '0';
 185                                 len--;
 186                         }
 187                         if (i < 1 || i > 366)
 188                                 return (NULL);
 189 
 190                         tm->tm_yday = i - 1;
 191                         break;
 192 


 518 
 519                         tm->tm_hour -= sign * (i / 100);
 520                         tm->tm_min -= sign * (i % 100);
 521                         *flagsp |= F_GMT;
 522                         }
 523                         break;
 524                 }
 525         }
 526 
 527         if (!recurse) {
 528                 if (buf && (*flagsp & F_GMT)) {
 529                         time_t t = timegm(tm);
 530                         (void) localtime_r(&t, tm);
 531                 }
 532         }
 533 
 534         return ((char *)buf);
 535 }
 536 
 537 char *



















 538 strptime(const char *buf, const char *fmt, struct tm *tm)
 539 {
 540         int     flags = F_ZERO;
 541 
 542         return (__strptime(buf, fmt, tm, &flags));

 543 }
 544 
 545 /*
 546  * This is used by Solaris, and is a variant that does not clear the
 547  * incoming tm.  It is triggered by -D_STRPTIME_DONTZERO.
 548  */
 549 char *
 550 __strptime_dontzero(const char *buf, const char *fmt, struct tm *tm)
 551 {
 552         int     flags = 0;

 553 
 554         return (__strptime(buf, fmt, tm, &flags));

 555 }
   1 /*
   2  * Copyright 2011, Nexenta Systems, Inc.  All rights reserved.
   3  * Copyright (c) 1994 Powerdog Industries.  All rights reserved.
   4  *
   5  * Copyright (c) 2011 The FreeBSD Foundation
   6  * All rights reserved.
   7  * Portions of this software were developed by David Chisnall
   8  * under sponsorship from the FreeBSD Foundation.
   9  *
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions
  12  * are met:
  13  *
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions and the following disclaimer.
  16  *
  17  * 2. Redistributions in binary form must reproduce the above copyright
  18  *    notice, this list of conditions and the following disclaimer
  19  *    in the documentation and/or other materials provided with the
  20  *    distribution.
  21  *
  22  * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
  23  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
  26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  29  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,


  36  * official policies, either expressed or implied, of Powerdog Industries.
  37  */
  38 
  39 #include "lint.h"
  40 #include <time.h>
  41 #include <ctype.h>
  42 #include <errno.h>
  43 #include <stdlib.h>
  44 #include <string.h>
  45 #include <pthread.h>
  46 #include <alloca.h>
  47 #include "timelocal.h"
  48 
  49 #define asizeof(a)      (sizeof (a) / sizeof ((a)[0]))
  50 
  51 #define F_GMT           (1 << 0)
  52 #define F_ZERO          (1 << 1)
  53 #define F_RECURSE       (1 << 2)
  54 
  55 static char *
  56 __strptime(const char *buf, const char *fmt, struct tm *tm, int *flagsp,
  57     int *GMTp, locale_t locale)
  58 {
  59         char    c;
  60         const char *ptr;
  61         int     i, len, recurse = 0;
  62         int Ealternative, Oalternative;
  63         struct lc_time_T *tptr = __get_current_time_locale(locale);
  64 
  65         if (*flagsp & F_RECURSE)
  66                 recurse = 1;
  67         *flagsp |= F_RECURSE;
  68 
  69         if (*flagsp & F_ZERO)
  70                 (void) memset(tm, 0, sizeof (*tm));
  71         *flagsp &= ~F_ZERO;
  72 
  73         ptr = fmt;
  74         while (*ptr != 0) {
  75                 if (*buf == 0)
  76                         break;
  77 
  78                 c = *ptr++;
  79 
  80                 if (c != '%') {
  81                         if (isspace(c))
  82                                 while (isspace(*buf))
  83                                         buf++;
  84                         else if (c != *buf++)
  85                                 return (NULL);
  86                         continue;
  87                 }
  88 
  89                 Ealternative = 0;
  90                 Oalternative = 0;
  91 label:
  92                 c = *ptr++;
  93                 switch (c) {
  94                 case 0:
  95                 case '%':
  96                         if (*buf++ != '%')
  97                                 return (NULL);
  98                         break;
  99 
 100                 case '+':
 101                         buf = __strptime(buf, tptr->date_fmt, tm, flagsp,
 102                             GMTp, locale);
 103                         if (buf == NULL)
 104                                 return (NULL);
 105                         break;
 106 
 107                 case 'C':
 108                         if (!isdigit(*buf))
 109                                 return (NULL);
 110 
 111                         /* XXX This will break for 3-digit centuries. */
 112                         len = 2;
 113                         for (i = 0; len && isdigit(*buf); buf++) {
 114                                 i *= 10;
 115                                 i += *buf - '0';
 116                                 len--;
 117                         }
 118                         if (i < 19)
 119                                 return (NULL);
 120 
 121                         tm->tm_year = i * 100 - 1900;
 122                         break;
 123 
 124                 case 'c':
 125                         buf = __strptime(buf, tptr->c_fmt, tm, flagsp,
 126                             GMTp, locale);
 127                         if (buf == NULL)
 128                                 return (NULL);
 129                         break;
 130 
 131                 case 'D':
 132                         buf = __strptime(buf, "%m/%d/%y", tm, flagsp,
 133                             GMTp, locale);
 134                         if (buf == NULL)
 135                                 return (NULL);
 136                         break;
 137 
 138                 case 'E':
 139                         if (Ealternative || Oalternative)
 140                                 break;
 141                         Ealternative++;
 142                         goto label;
 143 
 144                 case 'O':
 145                         if (Ealternative || Oalternative)
 146                                 break;
 147                         Oalternative++;
 148                         goto label;
 149 
 150                 case 'F':
 151                         buf = __strptime(buf, "%Y-%m-%d", tm, flagsp,
 152                             GMTp, locale);
 153                         if (buf == NULL)
 154                                 return (NULL);
 155                         break;
 156 
 157                 case 'R':
 158                         buf = __strptime(buf, "%H:%M", tm, flagsp,
 159                             GMTp, locale);
 160                         if (buf == NULL)
 161                                 return (NULL);
 162                         break;
 163 
 164                 case 'r':
 165                         buf = __strptime(buf, tptr->ampm_fmt, tm, flagsp,
 166                             GMTp, locale);
 167                         if (buf == NULL)
 168                                 return (NULL);
 169                         break;
 170 
 171                 case 'T':
 172                         buf = __strptime(buf, "%H:%M:%S", tm, flagsp,
 173                             GMTp, locale);
 174                         if (buf == NULL)
 175                                 return (NULL);
 176                         break;
 177 
 178                 case 'X':
 179                         buf = __strptime(buf, tptr->X_fmt, tm, flagsp,
 180                             GMTp, locale);
 181                         if (buf == NULL)
 182                                 return (NULL);
 183                         break;
 184 
 185                 case 'x':
 186                         buf = __strptime(buf, tptr->x_fmt, tm, flagsp,
 187                             GMTp, locale);
 188                         if (buf == NULL)
 189                                 return (NULL);
 190                         break;
 191 
 192                 case 'j':
 193                         if (!isdigit(*buf))
 194                                 return (NULL);
 195 
 196                         len = 3;
 197                         for (i = 0; len && isdigit(*buf); buf++) {
 198                                 i *= 10;
 199                                 i += *buf - '0';
 200                                 len--;
 201                         }
 202                         if (i < 1 || i > 366)
 203                                 return (NULL);
 204 
 205                         tm->tm_yday = i - 1;
 206                         break;
 207 


 533 
 534                         tm->tm_hour -= sign * (i / 100);
 535                         tm->tm_min -= sign * (i % 100);
 536                         *flagsp |= F_GMT;
 537                         }
 538                         break;
 539                 }
 540         }
 541 
 542         if (!recurse) {
 543                 if (buf && (*flagsp & F_GMT)) {
 544                         time_t t = timegm(tm);
 545                         (void) localtime_r(&t, tm);
 546                 }
 547         }
 548 
 549         return ((char *)buf);
 550 }
 551 
 552 char *
 553 strptime_l(const char * __restrict buf, const char * __restrict fmt,
 554     struct tm * __restrict tm, locale_t loc)
 555 {
 556         char *ret;
 557         int gmt;
 558         int flags = F_ZERO;
 559         FIX_LOCALE(loc);
 560 
 561         gmt = 0;
 562         ret = __strptime(buf, fmt, tm, &flags, &gmt, loc);
 563         if (ret && gmt) {
 564                 time_t t = timegm(tm);
 565                 localtime_r(&t, tm);
 566         }
 567 
 568         return (ret);
 569 }
 570 
 571 char *
 572 strptime(const char *buf, const char *fmt, struct tm *tm)
 573 {
 574         int     flags = F_ZERO;
 575 
 576         return (strptime_l(buf, fmt, tm, __get_locale()));
 577         // XXX return (__strptime(buf, fmt, tm, &flags));
 578 }
 579 
 580 /*
 581  * This is used by Solaris, and is a variant that does not clear the
 582  * incoming tm.  It is triggered by -D_STRPTIME_DONTZERO.
 583  */
 584 char *
 585 __strptime_dontzero(const char *buf, const char *fmt, struct tm *tm)
 586 {
 587         int     flags = 0;
 588         int     gmt = 0;
 589 
 590         return (__strptime(buf, fmt, tm, &flags, &gmt, __get_locale()));
 591         /* XXX */
 592 }