1*b7579f77SDag-Erling Smørgrav /** strptime workaround (for oa macos leopard) 2*b7579f77SDag-Erling Smørgrav * This strptime follows the man strptime (2001-11-12) 3*b7579f77SDag-Erling Smørgrav * conforming to SUSv2, POSIX.1-2001 4*b7579f77SDag-Erling Smørgrav * 5*b7579f77SDag-Erling Smørgrav * This very simple version of strptime has no: 6*b7579f77SDag-Erling Smørgrav * - E alternatives 7*b7579f77SDag-Erling Smørgrav * - O alternatives 8*b7579f77SDag-Erling Smørgrav * - Glibc additions 9*b7579f77SDag-Erling Smørgrav * - Does not process week numbers 10*b7579f77SDag-Erling Smørgrav * - Does not properly processes year day 11*b7579f77SDag-Erling Smørgrav * 12*b7579f77SDag-Erling Smørgrav * LICENSE 13*b7579f77SDag-Erling Smørgrav * Copyright (c) 2008, NLnet Labs, Matthijs Mekking 14*b7579f77SDag-Erling Smørgrav * All rights reserved. 15*b7579f77SDag-Erling Smørgrav * 16*b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 17*b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions are met: 18*b7579f77SDag-Erling Smørgrav * * Redistributions of source code must retain the above copyright notice, 19*b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 20*b7579f77SDag-Erling Smørgrav * * Redistributions in binary form must reproduce the above copyright 21*b7579f77SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 22*b7579f77SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 23*b7579f77SDag-Erling Smørgrav * * Neither the name of NLnetLabs nor the names of its 24*b7579f77SDag-Erling Smørgrav * contributors may be used to endorse or promote products derived from this 25*b7579f77SDag-Erling Smørgrav * software without specific prior written permission. 26*b7579f77SDag-Erling Smørgrav * 27*b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28*b7579f77SDag-Erling Smørgrav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29*b7579f77SDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30*b7579f77SDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31*b7579f77SDag-Erling Smørgrav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32*b7579f77SDag-Erling Smørgrav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33*b7579f77SDag-Erling Smørgrav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34*b7579f77SDag-Erling Smørgrav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35*b7579f77SDag-Erling Smørgrav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36*b7579f77SDag-Erling Smørgrav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37*b7579f77SDag-Erling Smørgrav * POSSIBILITY OF SUCH DAMAGE. 38*b7579f77SDag-Erling Smørgrav **/ 39*b7579f77SDag-Erling Smørgrav 40*b7579f77SDag-Erling Smørgrav #include "config.h" 41*b7579f77SDag-Erling Smørgrav 42*b7579f77SDag-Erling Smørgrav #ifndef HAVE_CONFIG_H 43*b7579f77SDag-Erling Smørgrav #include <time.h> 44*b7579f77SDag-Erling Smørgrav #endif 45*b7579f77SDag-Erling Smørgrav 46*b7579f77SDag-Erling Smørgrav #ifndef STRPTIME_WORKS 47*b7579f77SDag-Erling Smørgrav 48*b7579f77SDag-Erling Smørgrav #define TM_YEAR_BASE 1900 49*b7579f77SDag-Erling Smørgrav 50*b7579f77SDag-Erling Smørgrav #include <ctype.h> 51*b7579f77SDag-Erling Smørgrav #include <string.h> 52*b7579f77SDag-Erling Smørgrav 53*b7579f77SDag-Erling Smørgrav static const char *abb_weekdays[] = { 54*b7579f77SDag-Erling Smørgrav "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL 55*b7579f77SDag-Erling Smørgrav }; 56*b7579f77SDag-Erling Smørgrav static const char *full_weekdays[] = { 57*b7579f77SDag-Erling Smørgrav "Sunday", "Monday", "Tuesday", "Wednesday", 58*b7579f77SDag-Erling Smørgrav "Thursday", "Friday", "Saturday", NULL 59*b7579f77SDag-Erling Smørgrav }; 60*b7579f77SDag-Erling Smørgrav static const char *abb_months[] = { 61*b7579f77SDag-Erling Smørgrav "Jan", "Feb", "Mar", "Apr", "May", "Jun", 62*b7579f77SDag-Erling Smørgrav "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL 63*b7579f77SDag-Erling Smørgrav }; 64*b7579f77SDag-Erling Smørgrav static const char *full_months[] = { 65*b7579f77SDag-Erling Smørgrav "January", "February", "March", "April", "May", "June", 66*b7579f77SDag-Erling Smørgrav "July", "August", "September", "October", "November", "December", NULL 67*b7579f77SDag-Erling Smørgrav }; 68*b7579f77SDag-Erling Smørgrav static const char *ampm[] = { 69*b7579f77SDag-Erling Smørgrav "am", "pm", NULL 70*b7579f77SDag-Erling Smørgrav }; 71*b7579f77SDag-Erling Smørgrav 72*b7579f77SDag-Erling Smørgrav static int 73*b7579f77SDag-Erling Smørgrav match_string(const char **buf, const char **strs) 74*b7579f77SDag-Erling Smørgrav { 75*b7579f77SDag-Erling Smørgrav int i = 0; 76*b7579f77SDag-Erling Smørgrav 77*b7579f77SDag-Erling Smørgrav for (i = 0; strs[i] != NULL; i++) { 78*b7579f77SDag-Erling Smørgrav int len = strlen(strs[i]); 79*b7579f77SDag-Erling Smørgrav if (strncasecmp (*buf, strs[i], len) == 0) { 80*b7579f77SDag-Erling Smørgrav *buf += len; 81*b7579f77SDag-Erling Smørgrav return i; 82*b7579f77SDag-Erling Smørgrav } 83*b7579f77SDag-Erling Smørgrav } 84*b7579f77SDag-Erling Smørgrav return -1; 85*b7579f77SDag-Erling Smørgrav } 86*b7579f77SDag-Erling Smørgrav 87*b7579f77SDag-Erling Smørgrav static int 88*b7579f77SDag-Erling Smørgrav str2int(const char **buf, int max) 89*b7579f77SDag-Erling Smørgrav { 90*b7579f77SDag-Erling Smørgrav int ret=0, count=0; 91*b7579f77SDag-Erling Smørgrav 92*b7579f77SDag-Erling Smørgrav while (*buf[0] != '\0' && isdigit(*buf[0]) && count<max) { 93*b7579f77SDag-Erling Smørgrav ret = ret*10 + (*buf[0] - '0'); 94*b7579f77SDag-Erling Smørgrav (*buf)++; 95*b7579f77SDag-Erling Smørgrav count++; 96*b7579f77SDag-Erling Smørgrav } 97*b7579f77SDag-Erling Smørgrav 98*b7579f77SDag-Erling Smørgrav if (!count) 99*b7579f77SDag-Erling Smørgrav return -1; 100*b7579f77SDag-Erling Smørgrav return ret; 101*b7579f77SDag-Erling Smørgrav } 102*b7579f77SDag-Erling Smørgrav 103*b7579f77SDag-Erling Smørgrav /** Converts the character string s to values which are stored in tm 104*b7579f77SDag-Erling Smørgrav * using the format specified by format 105*b7579f77SDag-Erling Smørgrav **/ 106*b7579f77SDag-Erling Smørgrav char * 107*b7579f77SDag-Erling Smørgrav unbound_strptime(const char *s, const char *format, struct tm *tm) 108*b7579f77SDag-Erling Smørgrav { 109*b7579f77SDag-Erling Smørgrav int c, ret; 110*b7579f77SDag-Erling Smørgrav int split_year = 0; 111*b7579f77SDag-Erling Smørgrav 112*b7579f77SDag-Erling Smørgrav while ((c = *format) != '\0') { 113*b7579f77SDag-Erling Smørgrav /* whitespace, literal or format */ 114*b7579f77SDag-Erling Smørgrav if (isspace(c)) { /* whitespace */ 115*b7579f77SDag-Erling Smørgrav /** whitespace matches zero or more whitespace characters in the 116*b7579f77SDag-Erling Smørgrav * input string. 117*b7579f77SDag-Erling Smørgrav **/ 118*b7579f77SDag-Erling Smørgrav while (isspace(*s)) 119*b7579f77SDag-Erling Smørgrav s++; 120*b7579f77SDag-Erling Smørgrav } 121*b7579f77SDag-Erling Smørgrav else if (c == '%') { /* format */ 122*b7579f77SDag-Erling Smørgrav format++; 123*b7579f77SDag-Erling Smørgrav c = *format; 124*b7579f77SDag-Erling Smørgrav switch (c) { 125*b7579f77SDag-Erling Smørgrav case '%': /* %% is converted to % */ 126*b7579f77SDag-Erling Smørgrav if (*s != c) { 127*b7579f77SDag-Erling Smørgrav return NULL; 128*b7579f77SDag-Erling Smørgrav } 129*b7579f77SDag-Erling Smørgrav s++; 130*b7579f77SDag-Erling Smørgrav break; 131*b7579f77SDag-Erling Smørgrav case 'a': /* weekday name, abbreviated or full */ 132*b7579f77SDag-Erling Smørgrav case 'A': 133*b7579f77SDag-Erling Smørgrav ret = match_string(&s, full_weekdays); 134*b7579f77SDag-Erling Smørgrav if (ret < 0) 135*b7579f77SDag-Erling Smørgrav ret = match_string(&s, abb_weekdays); 136*b7579f77SDag-Erling Smørgrav if (ret < 0) { 137*b7579f77SDag-Erling Smørgrav return NULL; 138*b7579f77SDag-Erling Smørgrav } 139*b7579f77SDag-Erling Smørgrav tm->tm_wday = ret; 140*b7579f77SDag-Erling Smørgrav break; 141*b7579f77SDag-Erling Smørgrav case 'b': /* month name, abbreviated or full */ 142*b7579f77SDag-Erling Smørgrav case 'B': 143*b7579f77SDag-Erling Smørgrav case 'h': 144*b7579f77SDag-Erling Smørgrav ret = match_string(&s, full_months); 145*b7579f77SDag-Erling Smørgrav if (ret < 0) 146*b7579f77SDag-Erling Smørgrav ret = match_string(&s, abb_months); 147*b7579f77SDag-Erling Smørgrav if (ret < 0) { 148*b7579f77SDag-Erling Smørgrav return NULL; 149*b7579f77SDag-Erling Smørgrav } 150*b7579f77SDag-Erling Smørgrav tm->tm_mon = ret; 151*b7579f77SDag-Erling Smørgrav break; 152*b7579f77SDag-Erling Smørgrav case 'c': /* date and time representation */ 153*b7579f77SDag-Erling Smørgrav if (!(s = unbound_strptime(s, "%x %X", tm))) { 154*b7579f77SDag-Erling Smørgrav return NULL; 155*b7579f77SDag-Erling Smørgrav } 156*b7579f77SDag-Erling Smørgrav break; 157*b7579f77SDag-Erling Smørgrav case 'C': /* century number */ 158*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 159*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 99) { /* must be in [00,99] */ 160*b7579f77SDag-Erling Smørgrav return NULL; 161*b7579f77SDag-Erling Smørgrav } 162*b7579f77SDag-Erling Smørgrav 163*b7579f77SDag-Erling Smørgrav if (split_year) { 164*b7579f77SDag-Erling Smørgrav tm->tm_year = ret*100 + (tm->tm_year%100); 165*b7579f77SDag-Erling Smørgrav } 166*b7579f77SDag-Erling Smørgrav else { 167*b7579f77SDag-Erling Smørgrav tm->tm_year = ret*100 - TM_YEAR_BASE; 168*b7579f77SDag-Erling Smørgrav split_year = 1; 169*b7579f77SDag-Erling Smørgrav } 170*b7579f77SDag-Erling Smørgrav break; 171*b7579f77SDag-Erling Smørgrav case 'd': /* day of month */ 172*b7579f77SDag-Erling Smørgrav case 'e': 173*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 174*b7579f77SDag-Erling Smørgrav if (ret < 1 || ret > 31) { /* must be in [01,31] */ 175*b7579f77SDag-Erling Smørgrav return NULL; 176*b7579f77SDag-Erling Smørgrav } 177*b7579f77SDag-Erling Smørgrav tm->tm_mday = ret; 178*b7579f77SDag-Erling Smørgrav break; 179*b7579f77SDag-Erling Smørgrav case 'D': /* equivalent to %m/%d/%y */ 180*b7579f77SDag-Erling Smørgrav if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) { 181*b7579f77SDag-Erling Smørgrav return NULL; 182*b7579f77SDag-Erling Smørgrav } 183*b7579f77SDag-Erling Smørgrav break; 184*b7579f77SDag-Erling Smørgrav case 'H': /* hour */ 185*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 186*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 23) { /* must be in [00,23] */ 187*b7579f77SDag-Erling Smørgrav return NULL; 188*b7579f77SDag-Erling Smørgrav } 189*b7579f77SDag-Erling Smørgrav tm->tm_hour = ret; 190*b7579f77SDag-Erling Smørgrav break; 191*b7579f77SDag-Erling Smørgrav case 'I': /* 12hr clock hour */ 192*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 193*b7579f77SDag-Erling Smørgrav if (ret < 1 || ret > 12) { /* must be in [01,12] */ 194*b7579f77SDag-Erling Smørgrav return NULL; 195*b7579f77SDag-Erling Smørgrav } 196*b7579f77SDag-Erling Smørgrav if (ret == 12) /* actually [0,11] */ 197*b7579f77SDag-Erling Smørgrav ret = 0; 198*b7579f77SDag-Erling Smørgrav tm->tm_hour = ret; 199*b7579f77SDag-Erling Smørgrav break; 200*b7579f77SDag-Erling Smørgrav case 'j': /* day of year */ 201*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 202*b7579f77SDag-Erling Smørgrav if (ret < 1 || ret > 366) { /* must be in [001,366] */ 203*b7579f77SDag-Erling Smørgrav return NULL; 204*b7579f77SDag-Erling Smørgrav } 205*b7579f77SDag-Erling Smørgrav tm->tm_yday = ret; 206*b7579f77SDag-Erling Smørgrav break; 207*b7579f77SDag-Erling Smørgrav case 'm': /* month */ 208*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 209*b7579f77SDag-Erling Smørgrav if (ret < 1 || ret > 12) { /* must be in [01,12] */ 210*b7579f77SDag-Erling Smørgrav return NULL; 211*b7579f77SDag-Erling Smørgrav } 212*b7579f77SDag-Erling Smørgrav /* months go from 0-11 */ 213*b7579f77SDag-Erling Smørgrav tm->tm_mon = (ret-1); 214*b7579f77SDag-Erling Smørgrav break; 215*b7579f77SDag-Erling Smørgrav case 'M': /* minute */ 216*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 217*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 59) { /* must be in [00,59] */ 218*b7579f77SDag-Erling Smørgrav return NULL; 219*b7579f77SDag-Erling Smørgrav } 220*b7579f77SDag-Erling Smørgrav tm->tm_min = ret; 221*b7579f77SDag-Erling Smørgrav break; 222*b7579f77SDag-Erling Smørgrav case 'n': /* arbitrary whitespace */ 223*b7579f77SDag-Erling Smørgrav case 't': 224*b7579f77SDag-Erling Smørgrav while (isspace(*s)) 225*b7579f77SDag-Erling Smørgrav s++; 226*b7579f77SDag-Erling Smørgrav break; 227*b7579f77SDag-Erling Smørgrav case 'p': /* am pm */ 228*b7579f77SDag-Erling Smørgrav ret = match_string(&s, ampm); 229*b7579f77SDag-Erling Smørgrav if (ret < 0) { 230*b7579f77SDag-Erling Smørgrav return NULL; 231*b7579f77SDag-Erling Smørgrav } 232*b7579f77SDag-Erling Smørgrav if (tm->tm_hour < 0 || tm->tm_hour > 11) { /* %I */ 233*b7579f77SDag-Erling Smørgrav return NULL; 234*b7579f77SDag-Erling Smørgrav } 235*b7579f77SDag-Erling Smørgrav 236*b7579f77SDag-Erling Smørgrav if (ret == 1) /* pm */ 237*b7579f77SDag-Erling Smørgrav tm->tm_hour += 12; 238*b7579f77SDag-Erling Smørgrav break; 239*b7579f77SDag-Erling Smørgrav case 'r': /* equivalent of %I:%M:%S %p */ 240*b7579f77SDag-Erling Smørgrav if (!(s = unbound_strptime(s, "%I:%M:%S %p", tm))) { 241*b7579f77SDag-Erling Smørgrav return NULL; 242*b7579f77SDag-Erling Smørgrav } 243*b7579f77SDag-Erling Smørgrav break; 244*b7579f77SDag-Erling Smørgrav case 'R': /* equivalent of %H:%M */ 245*b7579f77SDag-Erling Smørgrav if (!(s = unbound_strptime(s, "%H:%M", tm))) { 246*b7579f77SDag-Erling Smørgrav return NULL; 247*b7579f77SDag-Erling Smørgrav } 248*b7579f77SDag-Erling Smørgrav break; 249*b7579f77SDag-Erling Smørgrav case 'S': /* seconds */ 250*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 251*b7579f77SDag-Erling Smørgrav /* 60 may occur for leap seconds */ 252*b7579f77SDag-Erling Smørgrav /* earlier 61 was also allowed */ 253*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 60) { /* must be in [00,60] */ 254*b7579f77SDag-Erling Smørgrav return NULL; 255*b7579f77SDag-Erling Smørgrav } 256*b7579f77SDag-Erling Smørgrav tm->tm_sec = ret; 257*b7579f77SDag-Erling Smørgrav break; 258*b7579f77SDag-Erling Smørgrav case 'T': /* equivalent of %H:%M:%S */ 259*b7579f77SDag-Erling Smørgrav if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) { 260*b7579f77SDag-Erling Smørgrav return NULL; 261*b7579f77SDag-Erling Smørgrav } 262*b7579f77SDag-Erling Smørgrav break; 263*b7579f77SDag-Erling Smørgrav case 'U': /* week number, with the first Sun of Jan being w1 */ 264*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 265*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 53) { /* must be in [00,53] */ 266*b7579f77SDag-Erling Smørgrav return NULL; 267*b7579f77SDag-Erling Smørgrav } 268*b7579f77SDag-Erling Smørgrav /** it is hard (and not necessary for nsd) to determine time 269*b7579f77SDag-Erling Smørgrav * data from week number. 270*b7579f77SDag-Erling Smørgrav **/ 271*b7579f77SDag-Erling Smørgrav break; 272*b7579f77SDag-Erling Smørgrav case 'w': /* day of week */ 273*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 1); 274*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 6) { /* must be in [0,6] */ 275*b7579f77SDag-Erling Smørgrav return NULL; 276*b7579f77SDag-Erling Smørgrav } 277*b7579f77SDag-Erling Smørgrav tm->tm_wday = ret; 278*b7579f77SDag-Erling Smørgrav break; 279*b7579f77SDag-Erling Smørgrav case 'W': /* week number, with the first Mon of Jan being w1 */ 280*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 281*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 53) { /* must be in [00,53] */ 282*b7579f77SDag-Erling Smørgrav return NULL; 283*b7579f77SDag-Erling Smørgrav } 284*b7579f77SDag-Erling Smørgrav /** it is hard (and not necessary for nsd) to determine time 285*b7579f77SDag-Erling Smørgrav * data from week number. 286*b7579f77SDag-Erling Smørgrav **/ 287*b7579f77SDag-Erling Smørgrav break; 288*b7579f77SDag-Erling Smørgrav case 'x': /* date format */ 289*b7579f77SDag-Erling Smørgrav if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) { 290*b7579f77SDag-Erling Smørgrav return NULL; 291*b7579f77SDag-Erling Smørgrav } 292*b7579f77SDag-Erling Smørgrav break; 293*b7579f77SDag-Erling Smørgrav case 'X': /* time format */ 294*b7579f77SDag-Erling Smørgrav if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) { 295*b7579f77SDag-Erling Smørgrav return NULL; 296*b7579f77SDag-Erling Smørgrav } 297*b7579f77SDag-Erling Smørgrav break; 298*b7579f77SDag-Erling Smørgrav case 'y': /* last two digits of a year */ 299*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 2); 300*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 99) { /* must be in [00,99] */ 301*b7579f77SDag-Erling Smørgrav return NULL; 302*b7579f77SDag-Erling Smørgrav } 303*b7579f77SDag-Erling Smørgrav if (split_year) { 304*b7579f77SDag-Erling Smørgrav tm->tm_year = ((tm->tm_year/100) * 100) + ret; 305*b7579f77SDag-Erling Smørgrav } 306*b7579f77SDag-Erling Smørgrav else { 307*b7579f77SDag-Erling Smørgrav split_year = 1; 308*b7579f77SDag-Erling Smørgrav 309*b7579f77SDag-Erling Smørgrav /** currently: 310*b7579f77SDag-Erling Smørgrav * if in [0,68] we are in 21th century, 311*b7579f77SDag-Erling Smørgrav * if in [69,99] we are in 20th century. 312*b7579f77SDag-Erling Smørgrav **/ 313*b7579f77SDag-Erling Smørgrav if (ret < 69) /* 2000 */ 314*b7579f77SDag-Erling Smørgrav ret += 100; 315*b7579f77SDag-Erling Smørgrav tm->tm_year = ret; 316*b7579f77SDag-Erling Smørgrav } 317*b7579f77SDag-Erling Smørgrav break; 318*b7579f77SDag-Erling Smørgrav case 'Y': /* year */ 319*b7579f77SDag-Erling Smørgrav ret = str2int(&s, 4); 320*b7579f77SDag-Erling Smørgrav if (ret < 0 || ret > 9999) { 321*b7579f77SDag-Erling Smørgrav return NULL; 322*b7579f77SDag-Erling Smørgrav } 323*b7579f77SDag-Erling Smørgrav tm->tm_year = ret - TM_YEAR_BASE; 324*b7579f77SDag-Erling Smørgrav break; 325*b7579f77SDag-Erling Smørgrav case '\0': 326*b7579f77SDag-Erling Smørgrav default: /* unsupported, cannot match format */ 327*b7579f77SDag-Erling Smørgrav return NULL; 328*b7579f77SDag-Erling Smørgrav break; 329*b7579f77SDag-Erling Smørgrav } 330*b7579f77SDag-Erling Smørgrav } 331*b7579f77SDag-Erling Smørgrav else { /* literal */ 332*b7579f77SDag-Erling Smørgrav /* if input cannot match format, return NULL */ 333*b7579f77SDag-Erling Smørgrav if (*s != c) 334*b7579f77SDag-Erling Smørgrav return NULL; 335*b7579f77SDag-Erling Smørgrav s++; 336*b7579f77SDag-Erling Smørgrav } 337*b7579f77SDag-Erling Smørgrav 338*b7579f77SDag-Erling Smørgrav format++; 339*b7579f77SDag-Erling Smørgrav } 340*b7579f77SDag-Erling Smørgrav 341*b7579f77SDag-Erling Smørgrav /* return pointer to remainder of s */ 342*b7579f77SDag-Erling Smørgrav return (char*) s; 343*b7579f77SDag-Erling Smørgrav } 344*b7579f77SDag-Erling Smørgrav 345*b7579f77SDag-Erling Smørgrav #endif /* STRPTIME_WORKS */ 346