Home | History | Annotate | Line # | Download | only in time
strptime.c revision 1.2
      1 /*	$NetBSD: strptime.c,v 1.2 1997/05/06 13:06:48 kleink Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1994 Powerdog Industries.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer
     13  *    in the documentation and/or other materials provided with the
     14  *    distribution.
     15  * 3. All advertising materials mentioning features or use of this
     16  *    software must display the following acknowledgement:
     17  *      This product includes software developed by Powerdog Industries.
     18  * 4. The name of Powerdog Industries may not be used to endorse or
     19  *    promote products derived from this software without specific prior
     20  *    written permission.
     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,
     30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     31  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     32  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 #ifndef lint
     36 #if 0
     37 static char copyright[] =
     38 "@(#) Copyright (c) 1994 Powerdog Industries.  All rights reserved.";
     39 static char sccsid[] = "@(#)strptime.c  0.1 (Powerdog) 94/03/27";
     40 #else
     41 static char rcsid[] = "$NetBSD: strptime.c,v 1.2 1997/05/06 13:06:48 kleink Exp $";
     42 #endif
     43 #endif /* not lint */
     44 
     45 #include <sys/localedef.h>
     46 #include <locale.h>
     47 #include <time.h>
     48 #include <ctype.h>
     49 #include <string.h>
     50 
     51 char *
     52 strptime(buf, fmt, tm)
     53 	const char *buf, *fmt;
     54 	struct tm *tm;
     55 {
     56 	const char *ptr;
     57         char c;
     58 	int i, len;
     59 
     60 	ptr = fmt;
     61 	while (*ptr != 0) {
     62 		if (*buf == 0)
     63 			break;
     64 
     65 		c = *ptr++;
     66 
     67 		if (c != '%') {
     68 			if (isspace(c))
     69 				while (*buf != 0 && isspace(*buf))
     70 					buf++;
     71 			else if (c != *buf++)
     72 				return (NULL);
     73 			continue;
     74 		}
     75 
     76 		c = *ptr++;
     77 		switch (c) {
     78 		case 0:
     79 		case '%':
     80 			if (*buf++ != '%')
     81 				return (NULL);
     82 			break;
     83 
     84 		case 'c':
     85 			buf = strptime(buf, _CurrentTimeLocale->d_t_fmt, tm);
     86 			if (buf == 0)
     87 				return (NULL);
     88 			break;
     89 
     90 		case 'D':
     91 			buf = strptime(buf, "%m/%d/%y", tm);
     92 			if (buf == 0)
     93 				return (NULL);
     94 			break;
     95 
     96 		case 'R':
     97 			buf = strptime(buf, "%H:%M", tm);
     98 			if (buf == 0)
     99 				return (NULL);
    100 			break;
    101 
    102 		case 'r':
    103 			buf = strptime(buf, _CurrentTimeLocale->t_fmt_ampm,tm);
    104 			if (buf == 0)
    105 				return (NULL);
    106 			break;
    107 
    108 		case 'T':
    109 			buf = strptime(buf, "%H:%M:%S", tm);
    110 			if (buf == 0)
    111 				return (NULL);
    112 			break;
    113 
    114 		case 'X':
    115 			buf = strptime(buf, _CurrentTimeLocale->t_fmt, tm);
    116 			if (buf == 0)
    117 				return (NULL);
    118 			break;
    119 
    120 		case 'x':
    121 			buf = strptime(buf, _CurrentTimeLocale->d_fmt, tm);
    122 			if (buf == 0)
    123 				return (NULL);
    124 			break;
    125 
    126 		case 'j':
    127 			if (!isdigit(*buf))
    128 				return (NULL);
    129 
    130 			for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
    131 				i *= 10;
    132 				i += *buf - '0';
    133 			}
    134 			if (i > 366)
    135 				return (NULL);
    136 
    137 			tm->tm_yday = i;
    138 			break;
    139 
    140 		case 'M':
    141 		case 'S':
    142 			if (*buf == 0 || isspace(*buf))
    143 				break;
    144 
    145 			if (!isdigit(*buf))
    146 				return (NULL);
    147 
    148 			for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
    149 				i *= 10;
    150 				i += *buf - '0';
    151 			}
    152 			if (i > 59)
    153 				return (NULL);
    154 
    155 			if (c == 'M')
    156 				tm->tm_min = i;
    157 			else
    158 				tm->tm_sec = i;
    159 
    160 			if (*buf != 0 && isspace(*buf))
    161 				while (*ptr != 0 && !isspace(*ptr))
    162 					ptr++;
    163 			break;
    164 
    165 		case 'H':
    166 		case 'I':
    167 		case 'k':
    168 		case 'l':
    169 			if (!isdigit(*buf))
    170 				return (NULL);
    171 
    172 			for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
    173 				i *= 10;
    174 				i += *buf - '0';
    175 			}
    176 			if (c == 'H' || c == 'k') {
    177 				if (i > 23)
    178 					return (NULL);
    179 			} else if (i > 11)
    180 				return (NULL);
    181 
    182 			tm->tm_hour = i;
    183 
    184 			if (*buf != 0 && isspace(*buf))
    185 			while (*ptr != 0 && !isspace(*ptr))
    186 				ptr++;
    187 			break;
    188 
    189 		case 'p':
    190 			len = strlen(_CurrentTimeLocale->am_pm[0]);
    191 			if (strncasecmp(buf, _CurrentTimeLocale->am_pm[0],
    192 			                len) == 0) {
    193 				if (tm->tm_hour > 12)
    194 					return (NULL);
    195 				if (tm->tm_hour == 12)
    196 					tm->tm_hour = 0;
    197 				buf += len;
    198 				break;
    199 			}
    200 
    201 			len = strlen(_CurrentTimeLocale->am_pm[1]);
    202 			if (strncasecmp(buf, _CurrentTimeLocale->am_pm[1],
    203 			                len) == 0) {
    204 				if (tm->tm_hour > 12)
    205 					return (NULL);
    206 				if (tm->tm_hour != 12)
    207 					tm->tm_hour += 12;
    208 				buf += len;
    209 				break;
    210 			}
    211 
    212                         return (NULL);
    213 
    214 		case 'A':
    215 		case 'a':
    216 			for (i = 0; i < 7; i++) {
    217 				len = strlen(_CurrentTimeLocale->day[i]);
    218 				if (strncasecmp(buf,
    219 				                _CurrentTimeLocale->day[i],
    220 				                len) == 0)
    221 					break;
    222 
    223 				len = strlen(_CurrentTimeLocale->abday[i]);
    224 				if (strncasecmp(buf,
    225 				                _CurrentTimeLocale->abday[i],
    226 				                len) == 0)
    227 					break;
    228 			}
    229 			if (i == 7)
    230 				return (NULL);
    231 
    232 			tm->tm_wday = i;
    233 			buf += len;
    234 			break;
    235 
    236 		case 'd':
    237 		case 'e':
    238 			if (!isdigit(*buf))
    239 				return (NULL);
    240 
    241 			for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
    242 				i *= 10;
    243 				i += *buf - '0';
    244 			}
    245 			if (i > 31)
    246 				return (NULL);
    247 
    248 			tm->tm_mday = i;
    249 
    250 			if (*buf != 0 && isspace(*buf))
    251 				while (*ptr != 0 && !isspace(*ptr))
    252 					ptr++;
    253 			break;
    254 
    255 		case 'B':
    256 		case 'b':
    257 		case 'h':
    258 			for (i = 0; i < 12; i++) {
    259 				len = strlen(_CurrentTimeLocale->mon[i]);
    260 				if (strncasecmp(buf,
    261 				                _CurrentTimeLocale->mon[i],
    262 				                len) == 0)
    263 					break;
    264 
    265 				len = strlen(_CurrentTimeLocale->abmon[i]);
    266 				if (strncasecmp(buf,
    267 				                _CurrentTimeLocale->abmon[i],
    268 				                len) == 0)
    269 					break;
    270 			}
    271 			if (i == 12)
    272 				return (NULL);
    273 
    274 			tm->tm_mon = i;
    275 			buf += len;
    276 			break;
    277 
    278 		case 'm':
    279 			if (!isdigit(*buf))
    280 				return (NULL);
    281 
    282 			for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
    283 				i *= 10;
    284 				i += *buf - '0';
    285 			}
    286 			if (i < 1 || i > 12)
    287 				return (NULL);
    288 
    289 			tm->tm_mon = i - 1;
    290 
    291 			if (*buf != 0 && isspace(*buf))
    292 				while (*ptr != 0 && !isspace(*ptr))
    293 					ptr++;
    294 			break;
    295 
    296 		case 'Y':
    297 		case 'y':
    298 			if (*buf == 0 || isspace(*buf))
    299 				break;
    300 
    301 			if (!isdigit(*buf))
    302 				return (NULL);
    303 
    304 			for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
    305 				i *= 10;
    306 				i += *buf - '0';
    307 			}
    308 			if (c == 'Y')
    309 				i -= 1900;
    310 			if (i < 0)
    311 				return (NULL);
    312 
    313 			tm->tm_year = i;
    314 
    315 			if (*buf != 0 && isspace(*buf))
    316 				while (*ptr != 0 && !isspace(*ptr))
    317 					ptr++;
    318 			break;
    319 		}
    320 	}
    321 
    322 	return ((char *)buf);
    323 }
    324