1*e2f6069cSDag-Erling Smørgrav /* $OpenBSD: strptime.c,v 1.12 2008/06/26 05:42:05 ray Exp $ */ 2*e2f6069cSDag-Erling Smørgrav /* $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $ */ 3*e2f6069cSDag-Erling Smørgrav 4*e2f6069cSDag-Erling Smørgrav /*- 5*e2f6069cSDag-Erling Smørgrav * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 6*e2f6069cSDag-Erling Smørgrav * All rights reserved. 7*e2f6069cSDag-Erling Smørgrav * 8*e2f6069cSDag-Erling Smørgrav * This code was contributed to The NetBSD Foundation by Klaus Klein. 9*e2f6069cSDag-Erling Smørgrav * 10*e2f6069cSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 11*e2f6069cSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 12*e2f6069cSDag-Erling Smørgrav * are met: 13*e2f6069cSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 14*e2f6069cSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 15*e2f6069cSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 16*e2f6069cSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 17*e2f6069cSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 18*e2f6069cSDag-Erling Smørgrav * 19*e2f6069cSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*e2f6069cSDag-Erling Smørgrav * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*e2f6069cSDag-Erling Smørgrav * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*e2f6069cSDag-Erling Smørgrav * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*e2f6069cSDag-Erling Smørgrav * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*e2f6069cSDag-Erling Smørgrav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*e2f6069cSDag-Erling Smørgrav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*e2f6069cSDag-Erling Smørgrav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*e2f6069cSDag-Erling Smørgrav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*e2f6069cSDag-Erling Smørgrav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*e2f6069cSDag-Erling Smørgrav * POSSIBILITY OF SUCH DAMAGE. 30*e2f6069cSDag-Erling Smørgrav */ 31*e2f6069cSDag-Erling Smørgrav 32*e2f6069cSDag-Erling Smørgrav /* OPENBSD ORIGINAL: lib/libc/time/strptime.c */ 33*e2f6069cSDag-Erling Smørgrav 34*e2f6069cSDag-Erling Smørgrav #include "includes.h" 35*e2f6069cSDag-Erling Smørgrav 36*e2f6069cSDag-Erling Smørgrav #ifndef HAVE_STRPTIME 37*e2f6069cSDag-Erling Smørgrav 38*e2f6069cSDag-Erling Smørgrav #define TM_YEAR_BASE 1900 /* from tzfile.h */ 39*e2f6069cSDag-Erling Smørgrav 40*e2f6069cSDag-Erling Smørgrav #include <ctype.h> 41*e2f6069cSDag-Erling Smørgrav #include <locale.h> 42*e2f6069cSDag-Erling Smørgrav #include <string.h> 43*e2f6069cSDag-Erling Smørgrav #include <time.h> 44*e2f6069cSDag-Erling Smørgrav 45*e2f6069cSDag-Erling Smørgrav /* #define _ctloc(x) (_CurrentTimeLocale->x) */ 46*e2f6069cSDag-Erling Smørgrav 47*e2f6069cSDag-Erling Smørgrav /* 48*e2f6069cSDag-Erling Smørgrav * We do not implement alternate representations. However, we always 49*e2f6069cSDag-Erling Smørgrav * check whether a given modifier is allowed for a certain conversion. 50*e2f6069cSDag-Erling Smørgrav */ 51*e2f6069cSDag-Erling Smørgrav #define _ALT_E 0x01 52*e2f6069cSDag-Erling Smørgrav #define _ALT_O 0x02 53*e2f6069cSDag-Erling Smørgrav #define _LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } 54*e2f6069cSDag-Erling Smørgrav 55*e2f6069cSDag-Erling Smørgrav 56*e2f6069cSDag-Erling Smørgrav static int _conv_num(const unsigned char **, int *, int, int); 57*e2f6069cSDag-Erling Smørgrav static char *_strptime(const char *, const char *, struct tm *, int); 58*e2f6069cSDag-Erling Smørgrav 59*e2f6069cSDag-Erling Smørgrav 60*e2f6069cSDag-Erling Smørgrav char * 61*e2f6069cSDag-Erling Smørgrav strptime(const char *buf, const char *fmt, struct tm *tm) 62*e2f6069cSDag-Erling Smørgrav { 63*e2f6069cSDag-Erling Smørgrav return(_strptime(buf, fmt, tm, 1)); 64*e2f6069cSDag-Erling Smørgrav } 65*e2f6069cSDag-Erling Smørgrav 66*e2f6069cSDag-Erling Smørgrav static char * 67*e2f6069cSDag-Erling Smørgrav _strptime(const char *buf, const char *fmt, struct tm *tm, int initialize) 68*e2f6069cSDag-Erling Smørgrav { 69*e2f6069cSDag-Erling Smørgrav unsigned char c; 70*e2f6069cSDag-Erling Smørgrav const unsigned char *bp; 71*e2f6069cSDag-Erling Smørgrav size_t len; 72*e2f6069cSDag-Erling Smørgrav int alt_format, i; 73*e2f6069cSDag-Erling Smørgrav static int century, relyear; 74*e2f6069cSDag-Erling Smørgrav 75*e2f6069cSDag-Erling Smørgrav if (initialize) { 76*e2f6069cSDag-Erling Smørgrav century = TM_YEAR_BASE; 77*e2f6069cSDag-Erling Smørgrav relyear = -1; 78*e2f6069cSDag-Erling Smørgrav } 79*e2f6069cSDag-Erling Smørgrav 80*e2f6069cSDag-Erling Smørgrav bp = (unsigned char *)buf; 81*e2f6069cSDag-Erling Smørgrav while ((c = *fmt) != '\0') { 82*e2f6069cSDag-Erling Smørgrav /* Clear `alternate' modifier prior to new conversion. */ 83*e2f6069cSDag-Erling Smørgrav alt_format = 0; 84*e2f6069cSDag-Erling Smørgrav 85*e2f6069cSDag-Erling Smørgrav /* Eat up white-space. */ 86*e2f6069cSDag-Erling Smørgrav if (isspace(c)) { 87*e2f6069cSDag-Erling Smørgrav while (isspace(*bp)) 88*e2f6069cSDag-Erling Smørgrav bp++; 89*e2f6069cSDag-Erling Smørgrav 90*e2f6069cSDag-Erling Smørgrav fmt++; 91*e2f6069cSDag-Erling Smørgrav continue; 92*e2f6069cSDag-Erling Smørgrav } 93*e2f6069cSDag-Erling Smørgrav 94*e2f6069cSDag-Erling Smørgrav if ((c = *fmt++) != '%') 95*e2f6069cSDag-Erling Smørgrav goto literal; 96*e2f6069cSDag-Erling Smørgrav 97*e2f6069cSDag-Erling Smørgrav 98*e2f6069cSDag-Erling Smørgrav again: switch (c = *fmt++) { 99*e2f6069cSDag-Erling Smørgrav case '%': /* "%%" is converted to "%". */ 100*e2f6069cSDag-Erling Smørgrav literal: 101*e2f6069cSDag-Erling Smørgrav if (c != *bp++) 102*e2f6069cSDag-Erling Smørgrav return (NULL); 103*e2f6069cSDag-Erling Smørgrav 104*e2f6069cSDag-Erling Smørgrav break; 105*e2f6069cSDag-Erling Smørgrav 106*e2f6069cSDag-Erling Smørgrav /* 107*e2f6069cSDag-Erling Smørgrav * "Alternative" modifiers. Just set the appropriate flag 108*e2f6069cSDag-Erling Smørgrav * and start over again. 109*e2f6069cSDag-Erling Smørgrav */ 110*e2f6069cSDag-Erling Smørgrav case 'E': /* "%E?" alternative conversion modifier. */ 111*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 112*e2f6069cSDag-Erling Smørgrav alt_format |= _ALT_E; 113*e2f6069cSDag-Erling Smørgrav goto again; 114*e2f6069cSDag-Erling Smørgrav 115*e2f6069cSDag-Erling Smørgrav case 'O': /* "%O?" alternative conversion modifier. */ 116*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 117*e2f6069cSDag-Erling Smørgrav alt_format |= _ALT_O; 118*e2f6069cSDag-Erling Smørgrav goto again; 119*e2f6069cSDag-Erling Smørgrav 120*e2f6069cSDag-Erling Smørgrav /* 121*e2f6069cSDag-Erling Smørgrav * "Complex" conversion rules, implemented through recursion. 122*e2f6069cSDag-Erling Smørgrav */ 123*e2f6069cSDag-Erling Smørgrav #if 0 124*e2f6069cSDag-Erling Smørgrav case 'c': /* Date and time, using the locale's format. */ 125*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_E); 126*e2f6069cSDag-Erling Smørgrav if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0))) 127*e2f6069cSDag-Erling Smørgrav return (NULL); 128*e2f6069cSDag-Erling Smørgrav break; 129*e2f6069cSDag-Erling Smørgrav #endif 130*e2f6069cSDag-Erling Smørgrav case 'D': /* The date as "%m/%d/%y". */ 131*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 132*e2f6069cSDag-Erling Smørgrav if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0))) 133*e2f6069cSDag-Erling Smørgrav return (NULL); 134*e2f6069cSDag-Erling Smørgrav break; 135*e2f6069cSDag-Erling Smørgrav 136*e2f6069cSDag-Erling Smørgrav case 'R': /* The time as "%H:%M". */ 137*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 138*e2f6069cSDag-Erling Smørgrav if (!(bp = _strptime(bp, "%H:%M", tm, 0))) 139*e2f6069cSDag-Erling Smørgrav return (NULL); 140*e2f6069cSDag-Erling Smørgrav break; 141*e2f6069cSDag-Erling Smørgrav 142*e2f6069cSDag-Erling Smørgrav case 'r': /* The time as "%I:%M:%S %p". */ 143*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 144*e2f6069cSDag-Erling Smørgrav if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0))) 145*e2f6069cSDag-Erling Smørgrav return (NULL); 146*e2f6069cSDag-Erling Smørgrav break; 147*e2f6069cSDag-Erling Smørgrav 148*e2f6069cSDag-Erling Smørgrav case 'T': /* The time as "%H:%M:%S". */ 149*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 150*e2f6069cSDag-Erling Smørgrav if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0))) 151*e2f6069cSDag-Erling Smørgrav return (NULL); 152*e2f6069cSDag-Erling Smørgrav break; 153*e2f6069cSDag-Erling Smørgrav #if 0 154*e2f6069cSDag-Erling Smørgrav case 'X': /* The time, using the locale's format. */ 155*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_E); 156*e2f6069cSDag-Erling Smørgrav if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0))) 157*e2f6069cSDag-Erling Smørgrav return (NULL); 158*e2f6069cSDag-Erling Smørgrav break; 159*e2f6069cSDag-Erling Smørgrav 160*e2f6069cSDag-Erling Smørgrav case 'x': /* The date, using the locale's format. */ 161*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_E); 162*e2f6069cSDag-Erling Smørgrav if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0))) 163*e2f6069cSDag-Erling Smørgrav return (NULL); 164*e2f6069cSDag-Erling Smørgrav break; 165*e2f6069cSDag-Erling Smørgrav #endif 166*e2f6069cSDag-Erling Smørgrav /* 167*e2f6069cSDag-Erling Smørgrav * "Elementary" conversion rules. 168*e2f6069cSDag-Erling Smørgrav */ 169*e2f6069cSDag-Erling Smørgrav #if 0 170*e2f6069cSDag-Erling Smørgrav case 'A': /* The day of week, using the locale's form. */ 171*e2f6069cSDag-Erling Smørgrav case 'a': 172*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 173*e2f6069cSDag-Erling Smørgrav for (i = 0; i < 7; i++) { 174*e2f6069cSDag-Erling Smørgrav /* Full name. */ 175*e2f6069cSDag-Erling Smørgrav len = strlen(_ctloc(day[i])); 176*e2f6069cSDag-Erling Smørgrav if (strncasecmp(_ctloc(day[i]), bp, len) == 0) 177*e2f6069cSDag-Erling Smørgrav break; 178*e2f6069cSDag-Erling Smørgrav 179*e2f6069cSDag-Erling Smørgrav /* Abbreviated name. */ 180*e2f6069cSDag-Erling Smørgrav len = strlen(_ctloc(abday[i])); 181*e2f6069cSDag-Erling Smørgrav if (strncasecmp(_ctloc(abday[i]), bp, len) == 0) 182*e2f6069cSDag-Erling Smørgrav break; 183*e2f6069cSDag-Erling Smørgrav } 184*e2f6069cSDag-Erling Smørgrav 185*e2f6069cSDag-Erling Smørgrav /* Nothing matched. */ 186*e2f6069cSDag-Erling Smørgrav if (i == 7) 187*e2f6069cSDag-Erling Smørgrav return (NULL); 188*e2f6069cSDag-Erling Smørgrav 189*e2f6069cSDag-Erling Smørgrav tm->tm_wday = i; 190*e2f6069cSDag-Erling Smørgrav bp += len; 191*e2f6069cSDag-Erling Smørgrav break; 192*e2f6069cSDag-Erling Smørgrav 193*e2f6069cSDag-Erling Smørgrav case 'B': /* The month, using the locale's form. */ 194*e2f6069cSDag-Erling Smørgrav case 'b': 195*e2f6069cSDag-Erling Smørgrav case 'h': 196*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 197*e2f6069cSDag-Erling Smørgrav for (i = 0; i < 12; i++) { 198*e2f6069cSDag-Erling Smørgrav /* Full name. */ 199*e2f6069cSDag-Erling Smørgrav len = strlen(_ctloc(mon[i])); 200*e2f6069cSDag-Erling Smørgrav if (strncasecmp(_ctloc(mon[i]), bp, len) == 0) 201*e2f6069cSDag-Erling Smørgrav break; 202*e2f6069cSDag-Erling Smørgrav 203*e2f6069cSDag-Erling Smørgrav /* Abbreviated name. */ 204*e2f6069cSDag-Erling Smørgrav len = strlen(_ctloc(abmon[i])); 205*e2f6069cSDag-Erling Smørgrav if (strncasecmp(_ctloc(abmon[i]), bp, len) == 0) 206*e2f6069cSDag-Erling Smørgrav break; 207*e2f6069cSDag-Erling Smørgrav } 208*e2f6069cSDag-Erling Smørgrav 209*e2f6069cSDag-Erling Smørgrav /* Nothing matched. */ 210*e2f6069cSDag-Erling Smørgrav if (i == 12) 211*e2f6069cSDag-Erling Smørgrav return (NULL); 212*e2f6069cSDag-Erling Smørgrav 213*e2f6069cSDag-Erling Smørgrav tm->tm_mon = i; 214*e2f6069cSDag-Erling Smørgrav bp += len; 215*e2f6069cSDag-Erling Smørgrav break; 216*e2f6069cSDag-Erling Smørgrav #endif 217*e2f6069cSDag-Erling Smørgrav 218*e2f6069cSDag-Erling Smørgrav case 'C': /* The century number. */ 219*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_E); 220*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &i, 0, 99))) 221*e2f6069cSDag-Erling Smørgrav return (NULL); 222*e2f6069cSDag-Erling Smørgrav 223*e2f6069cSDag-Erling Smørgrav century = i * 100; 224*e2f6069cSDag-Erling Smørgrav break; 225*e2f6069cSDag-Erling Smørgrav 226*e2f6069cSDag-Erling Smørgrav case 'd': /* The day of month. */ 227*e2f6069cSDag-Erling Smørgrav case 'e': 228*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_O); 229*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &tm->tm_mday, 1, 31))) 230*e2f6069cSDag-Erling Smørgrav return (NULL); 231*e2f6069cSDag-Erling Smørgrav break; 232*e2f6069cSDag-Erling Smørgrav 233*e2f6069cSDag-Erling Smørgrav case 'k': /* The hour (24-hour clock representation). */ 234*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 235*e2f6069cSDag-Erling Smørgrav /* FALLTHROUGH */ 236*e2f6069cSDag-Erling Smørgrav case 'H': 237*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_O); 238*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &tm->tm_hour, 0, 23))) 239*e2f6069cSDag-Erling Smørgrav return (NULL); 240*e2f6069cSDag-Erling Smørgrav break; 241*e2f6069cSDag-Erling Smørgrav 242*e2f6069cSDag-Erling Smørgrav case 'l': /* The hour (12-hour clock representation). */ 243*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 244*e2f6069cSDag-Erling Smørgrav /* FALLTHROUGH */ 245*e2f6069cSDag-Erling Smørgrav case 'I': 246*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_O); 247*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &tm->tm_hour, 1, 12))) 248*e2f6069cSDag-Erling Smørgrav return (NULL); 249*e2f6069cSDag-Erling Smørgrav break; 250*e2f6069cSDag-Erling Smørgrav 251*e2f6069cSDag-Erling Smørgrav case 'j': /* The day of year. */ 252*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 253*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &tm->tm_yday, 1, 366))) 254*e2f6069cSDag-Erling Smørgrav return (NULL); 255*e2f6069cSDag-Erling Smørgrav tm->tm_yday--; 256*e2f6069cSDag-Erling Smørgrav break; 257*e2f6069cSDag-Erling Smørgrav 258*e2f6069cSDag-Erling Smørgrav case 'M': /* The minute. */ 259*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_O); 260*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &tm->tm_min, 0, 59))) 261*e2f6069cSDag-Erling Smørgrav return (NULL); 262*e2f6069cSDag-Erling Smørgrav break; 263*e2f6069cSDag-Erling Smørgrav 264*e2f6069cSDag-Erling Smørgrav case 'm': /* The month. */ 265*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_O); 266*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &tm->tm_mon, 1, 12))) 267*e2f6069cSDag-Erling Smørgrav return (NULL); 268*e2f6069cSDag-Erling Smørgrav tm->tm_mon--; 269*e2f6069cSDag-Erling Smørgrav break; 270*e2f6069cSDag-Erling Smørgrav 271*e2f6069cSDag-Erling Smørgrav #if 0 272*e2f6069cSDag-Erling Smørgrav case 'p': /* The locale's equivalent of AM/PM. */ 273*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 274*e2f6069cSDag-Erling Smørgrav /* AM? */ 275*e2f6069cSDag-Erling Smørgrav len = strlen(_ctloc(am_pm[0])); 276*e2f6069cSDag-Erling Smørgrav if (strncasecmp(_ctloc(am_pm[0]), bp, len) == 0) { 277*e2f6069cSDag-Erling Smørgrav if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */ 278*e2f6069cSDag-Erling Smørgrav return (NULL); 279*e2f6069cSDag-Erling Smørgrav else if (tm->tm_hour == 12) 280*e2f6069cSDag-Erling Smørgrav tm->tm_hour = 0; 281*e2f6069cSDag-Erling Smørgrav 282*e2f6069cSDag-Erling Smørgrav bp += len; 283*e2f6069cSDag-Erling Smørgrav break; 284*e2f6069cSDag-Erling Smørgrav } 285*e2f6069cSDag-Erling Smørgrav /* PM? */ 286*e2f6069cSDag-Erling Smørgrav len = strlen(_ctloc(am_pm[1])); 287*e2f6069cSDag-Erling Smørgrav if (strncasecmp(_ctloc(am_pm[1]), bp, len) == 0) { 288*e2f6069cSDag-Erling Smørgrav if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */ 289*e2f6069cSDag-Erling Smørgrav return (NULL); 290*e2f6069cSDag-Erling Smørgrav else if (tm->tm_hour < 12) 291*e2f6069cSDag-Erling Smørgrav tm->tm_hour += 12; 292*e2f6069cSDag-Erling Smørgrav 293*e2f6069cSDag-Erling Smørgrav bp += len; 294*e2f6069cSDag-Erling Smørgrav break; 295*e2f6069cSDag-Erling Smørgrav } 296*e2f6069cSDag-Erling Smørgrav 297*e2f6069cSDag-Erling Smørgrav /* Nothing matched. */ 298*e2f6069cSDag-Erling Smørgrav return (NULL); 299*e2f6069cSDag-Erling Smørgrav #endif 300*e2f6069cSDag-Erling Smørgrav case 'S': /* The seconds. */ 301*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_O); 302*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &tm->tm_sec, 0, 61))) 303*e2f6069cSDag-Erling Smørgrav return (NULL); 304*e2f6069cSDag-Erling Smørgrav break; 305*e2f6069cSDag-Erling Smørgrav 306*e2f6069cSDag-Erling Smørgrav case 'U': /* The week of year, beginning on sunday. */ 307*e2f6069cSDag-Erling Smørgrav case 'W': /* The week of year, beginning on monday. */ 308*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_O); 309*e2f6069cSDag-Erling Smørgrav /* 310*e2f6069cSDag-Erling Smørgrav * XXX This is bogus, as we can not assume any valid 311*e2f6069cSDag-Erling Smørgrav * information present in the tm structure at this 312*e2f6069cSDag-Erling Smørgrav * point to calculate a real value, so just check the 313*e2f6069cSDag-Erling Smørgrav * range for now. 314*e2f6069cSDag-Erling Smørgrav */ 315*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &i, 0, 53))) 316*e2f6069cSDag-Erling Smørgrav return (NULL); 317*e2f6069cSDag-Erling Smørgrav break; 318*e2f6069cSDag-Erling Smørgrav 319*e2f6069cSDag-Erling Smørgrav case 'w': /* The day of week, beginning on sunday. */ 320*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_O); 321*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &tm->tm_wday, 0, 6))) 322*e2f6069cSDag-Erling Smørgrav return (NULL); 323*e2f6069cSDag-Erling Smørgrav break; 324*e2f6069cSDag-Erling Smørgrav 325*e2f6069cSDag-Erling Smørgrav case 'Y': /* The year. */ 326*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_E); 327*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &i, 0, 9999))) 328*e2f6069cSDag-Erling Smørgrav return (NULL); 329*e2f6069cSDag-Erling Smørgrav 330*e2f6069cSDag-Erling Smørgrav relyear = -1; 331*e2f6069cSDag-Erling Smørgrav tm->tm_year = i - TM_YEAR_BASE; 332*e2f6069cSDag-Erling Smørgrav break; 333*e2f6069cSDag-Erling Smørgrav 334*e2f6069cSDag-Erling Smørgrav case 'y': /* The year within the century (2 digits). */ 335*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(_ALT_E | _ALT_O); 336*e2f6069cSDag-Erling Smørgrav if (!(_conv_num(&bp, &relyear, 0, 99))) 337*e2f6069cSDag-Erling Smørgrav return (NULL); 338*e2f6069cSDag-Erling Smørgrav break; 339*e2f6069cSDag-Erling Smørgrav 340*e2f6069cSDag-Erling Smørgrav /* 341*e2f6069cSDag-Erling Smørgrav * Miscellaneous conversions. 342*e2f6069cSDag-Erling Smørgrav */ 343*e2f6069cSDag-Erling Smørgrav case 'n': /* Any kind of white-space. */ 344*e2f6069cSDag-Erling Smørgrav case 't': 345*e2f6069cSDag-Erling Smørgrav _LEGAL_ALT(0); 346*e2f6069cSDag-Erling Smørgrav while (isspace(*bp)) 347*e2f6069cSDag-Erling Smørgrav bp++; 348*e2f6069cSDag-Erling Smørgrav break; 349*e2f6069cSDag-Erling Smørgrav 350*e2f6069cSDag-Erling Smørgrav 351*e2f6069cSDag-Erling Smørgrav default: /* Unknown/unsupported conversion. */ 352*e2f6069cSDag-Erling Smørgrav return (NULL); 353*e2f6069cSDag-Erling Smørgrav } 354*e2f6069cSDag-Erling Smørgrav 355*e2f6069cSDag-Erling Smørgrav 356*e2f6069cSDag-Erling Smørgrav } 357*e2f6069cSDag-Erling Smørgrav 358*e2f6069cSDag-Erling Smørgrav /* 359*e2f6069cSDag-Erling Smørgrav * We need to evaluate the two digit year spec (%y) 360*e2f6069cSDag-Erling Smørgrav * last as we can get a century spec (%C) at any time. 361*e2f6069cSDag-Erling Smørgrav */ 362*e2f6069cSDag-Erling Smørgrav if (relyear != -1) { 363*e2f6069cSDag-Erling Smørgrav if (century == TM_YEAR_BASE) { 364*e2f6069cSDag-Erling Smørgrav if (relyear <= 68) 365*e2f6069cSDag-Erling Smørgrav tm->tm_year = relyear + 2000 - TM_YEAR_BASE; 366*e2f6069cSDag-Erling Smørgrav else 367*e2f6069cSDag-Erling Smørgrav tm->tm_year = relyear + 1900 - TM_YEAR_BASE; 368*e2f6069cSDag-Erling Smørgrav } else { 369*e2f6069cSDag-Erling Smørgrav tm->tm_year = relyear + century - TM_YEAR_BASE; 370*e2f6069cSDag-Erling Smørgrav } 371*e2f6069cSDag-Erling Smørgrav } 372*e2f6069cSDag-Erling Smørgrav 373*e2f6069cSDag-Erling Smørgrav return ((char *)bp); 374*e2f6069cSDag-Erling Smørgrav } 375*e2f6069cSDag-Erling Smørgrav 376*e2f6069cSDag-Erling Smørgrav 377*e2f6069cSDag-Erling Smørgrav static int 378*e2f6069cSDag-Erling Smørgrav _conv_num(const unsigned char **buf, int *dest, int llim, int ulim) 379*e2f6069cSDag-Erling Smørgrav { 380*e2f6069cSDag-Erling Smørgrav int result = 0; 381*e2f6069cSDag-Erling Smørgrav int rulim = ulim; 382*e2f6069cSDag-Erling Smørgrav 383*e2f6069cSDag-Erling Smørgrav if (**buf < '0' || **buf > '9') 384*e2f6069cSDag-Erling Smørgrav return (0); 385*e2f6069cSDag-Erling Smørgrav 386*e2f6069cSDag-Erling Smørgrav /* we use rulim to break out of the loop when we run out of digits */ 387*e2f6069cSDag-Erling Smørgrav do { 388*e2f6069cSDag-Erling Smørgrav result *= 10; 389*e2f6069cSDag-Erling Smørgrav result += *(*buf)++ - '0'; 390*e2f6069cSDag-Erling Smørgrav rulim /= 10; 391*e2f6069cSDag-Erling Smørgrav } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); 392*e2f6069cSDag-Erling Smørgrav 393*e2f6069cSDag-Erling Smørgrav if (result < llim || result > ulim) 394*e2f6069cSDag-Erling Smørgrav return (0); 395*e2f6069cSDag-Erling Smørgrav 396*e2f6069cSDag-Erling Smørgrav *dest = result; 397*e2f6069cSDag-Erling Smørgrav return (1); 398*e2f6069cSDag-Erling Smørgrav } 399*e2f6069cSDag-Erling Smørgrav 400*e2f6069cSDag-Erling Smørgrav #endif /* HAVE_STRPTIME */ 401*e2f6069cSDag-Erling Smørgrav 402