strptime.c revision edbe7fc97bab7ff0684053d1be564330689bf3ad
1edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project/*  $OpenBSD: strptime.c,v 1.11 2005/08/08 08:05:38 espie Exp $ */
2edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project/*  $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $    */
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*-
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved.
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This code was contributed to The NetBSD Foundation by Klaus Klein.
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    documentation and/or other materials provided with the distribution.
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. All advertising materials mentioning features or use of this software
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    must display the following acknowledgement:
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *        This product includes software developed by the NetBSD
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *        Foundation, Inc. and its contributors.
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 4. Neither the name of The NetBSD Foundation nor the names of its
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    contributors may be used to endorse or promote products derived
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    from this software without specific prior written permission.
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * POSSIBILITY OF SUCH DAMAGE.
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project//#include <sys/localedef.h>
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h>
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <locale.h>
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <time.h>
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "tzfile.h"
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct {
47edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *abday[7];
48edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *day[7];
49edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *abmon[12];
50edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *mon[12];
51edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *am_pm[2];
52edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *d_t_fmt;
53edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *d_fmt;
54edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *t_fmt;
55edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const char *t_fmt_ampm;
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} _DefaultTimeLocale = {
57edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    {
58edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
59edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    },
60edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    {
61edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
62edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Friday", "Saturday"
63edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    },
64edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    {
65edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
66edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
67edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    },
68edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    {
69edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "January", "February", "March", "April", "May", "June", "July",
70edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "August", "September", "October", "November", "December"
71edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    },
72edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    {
73edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        "AM", "PM"
74edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    },
75edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%a %b %d %H:%M:%S %Y",
76edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%m/%d/%y",
77edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%H:%M:%S",
78edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    "%I:%M:%S %p"
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
81edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define _ctloc(x) (_DefaultTimeLocale.x)
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We do not implement alternate representations. However, we always
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * check whether a given modifier is allowed for a certain conversion.
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
87edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define _ALT_E          0x01
88edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define _ALT_O          0x02
89edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project#define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
92edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Projectstatic  int _conv_num(const unsigned char **, int *, int, int);
93edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Projectstatic  unsigned char *_strptime(const unsigned char *, const char *, struct tm *, int);
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectchar *
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstrptime(const char *buf, const char *fmt, struct tm *tm)
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
99edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, 1));
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
102edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Projectstatic unsigned char *
103edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, int initialize)
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
105edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    unsigned char c;
106edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    const unsigned char *bp;
107edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    size_t len = 0;
108edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    int alt_format, i;
109edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    static int century, relyear;
110edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
111edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (initialize) {
112edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        century = TM_YEAR_BASE;
113edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        relyear = -1;
114edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
115edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
116edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    bp = (unsigned char *)buf;
117edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    while ((c = *fmt) != '\0') {
118edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        /* Clear `alternate' modifier prior to new conversion. */
119edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        alt_format = 0;
120edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
121edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        /* Eat up white-space. */
122edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (isspace(c)) {
123edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            while (isspace(*bp))
124edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                bp++;
125edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
126edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            fmt++;
127edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            continue;
128edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        }
129edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
130edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if ((c = *fmt++) != '%')
131edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            goto literal;
132edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
133edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
134edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Projectagain:      switch (c = *fmt++) {
135edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case '%':   /* "%%" is converted to "%". */
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectliteral:
137edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (c != *bp++)
138edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            return (NULL);
139edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
140edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        break;
141edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
142edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        /*
143edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         * "Alternative" modifiers. Just set the appropriate flag
144edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         * and start over again.
145edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         */
146edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'E':   /* "%E?" alternative conversion modifier. */
147edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
148edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            alt_format |= _ALT_E;
149edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            goto again;
150edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
151edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'O':   /* "%O?" alternative conversion modifier. */
152edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
153edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            alt_format |= _ALT_O;
154edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            goto again;
155edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
156edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        /*
157edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         * "Complex" conversion rules, implemented through recursion.
158edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         */
159edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'c':   /* Date and time, using the locale's format. */
160edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_E);
161edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0)))
162edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
163edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
164edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
165edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'D':   /* The date as "%m/%d/%y". */
166edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
167edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0)))
168edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
169edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
170edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
171edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'R':   /* The time as "%H:%M". */
172edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
173edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(bp = _strptime(bp, "%H:%M", tm, 0)))
174edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
175edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
176edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
177edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'r':   /* The time as "%I:%M:%S %p". */
178edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
179edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0)))
180edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
181edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
182edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
183edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'T':   /* The time as "%H:%M:%S". */
184edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
185edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0)))
186edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
187edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
188edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
189edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'X':   /* The time, using the locale's format. */
190edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_E);
191edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0)))
192edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
193edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
194edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
195edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'x':   /* The date, using the locale's format. */
196edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_E);
197edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0)))
198edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
199edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
200edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
201edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        /*
202edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         * "Elementary" conversion rules.
203edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         */
204edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'A':   /* The day of week, using the locale's form. */
205edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'a':
206edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
207edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            for (i = 0; i < 7; i++) {
208edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /* Full name. */
209edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                len = strlen(_ctloc(day[i]));
210edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (strncasecmp(_ctloc(day[i]), (const char*)bp, len) == 0)
211edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    break;
212edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
213edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /* Abbreviated name. */
214edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                len = strlen(_ctloc(abday[i]));
215edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (strncasecmp(_ctloc(abday[i]), (const char*)bp, len) == 0)
216edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    break;
217edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            }
218edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
219edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /* Nothing matched. */
220edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (i == 7)
221edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
222edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
223edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            tm->tm_wday = i;
224edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            bp += len;
225edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
226edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
227edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'B':   /* The month, using the locale's form. */
228edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'b':
229edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'h':
230edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
231edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            for (i = 0; i < 12; i++) {
232edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /* Full name. */
233edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                len = strlen(_ctloc(mon[i]));
234edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (strncasecmp(_ctloc(mon[i]), (const char*)bp, len) == 0)
235edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    break;
236edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
237edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                /* Abbreviated name. */
238edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                len = strlen(_ctloc(abmon[i]));
239edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (strncasecmp(_ctloc(abmon[i]), (const char*)bp, len) == 0)
240edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    break;
241edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            }
242edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
243edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /* Nothing matched. */
244edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (i == 12)
245edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
246edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
247edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            tm->tm_mon = i;
248edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            bp += len;
249edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
250edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
251edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'C':   /* The century number. */
252edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_E);
253edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &i, 0, 99)))
254edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
255edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
256edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            century = i * 100;
257edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
258edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
259edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'd':   /* The day of month. */
260edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'e':
261edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_O);
262edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
263edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
264edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
265edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
266edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'k':   /* The hour (24-hour clock representation). */
267edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
268edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /* FALLTHROUGH */
269edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'H':
270edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_O);
271edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
272edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
273edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
274edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
275edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'l':   /* The hour (12-hour clock representation). */
276edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
277edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /* FALLTHROUGH */
278edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'I':
279edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_O);
280edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
281edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
282edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
283edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
284edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'j':   /* The day of year. */
285edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
286edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
287edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
288edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            tm->tm_yday--;
289edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
290edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
291edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'M':   /* The minute. */
292edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_O);
293edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
294edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
295edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
296edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
297edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'm':   /* The month. */
298edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_O);
299edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
300edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
301edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            tm->tm_mon--;
302edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
303edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
304edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'p':   /* The locale's equivalent of AM/PM. */
305edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
306edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /* AM? */
307edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            len = strlen(_ctloc(am_pm[0]));
308edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (strncasecmp(_ctloc(am_pm[0]), (const char*)bp, len) == 0) {
309edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (tm->tm_hour > 12)   /* i.e., 13:00 AM ?! */
310edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    return (NULL);
311edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                else if (tm->tm_hour == 12)
312edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    tm->tm_hour = 0;
313edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
314edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                bp += len;
315edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                break;
316edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            }
317edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /* PM? */
318edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            len = strlen(_ctloc(am_pm[1]));
319edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (strncasecmp(_ctloc(am_pm[1]), (const char*)bp, len) == 0) {
320edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                if (tm->tm_hour > 12)   /* i.e., 13:00 PM ?! */
321edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    return (NULL);
322edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                else if (tm->tm_hour < 12)
323edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                    tm->tm_hour += 12;
324edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
325edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                bp += len;
326edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                break;
327edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            }
328edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
329edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /* Nothing matched. */
330edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            return (NULL);
331edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
332edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'S':   /* The seconds. */
333edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_O);
334edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
335edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
336edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
337edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
338edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'U':   /* The week of year, beginning on sunday. */
339edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'W':   /* The week of year, beginning on monday. */
340edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_O);
341edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            /*
342edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project             * XXX This is bogus, as we can not assume any valid
343edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project             * information present in the tm structure at this
344edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project             * point to calculate a real value, so just check the
345edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project             * range for now.
346edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project             */
347edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project             if (!(_conv_num(&bp, &i, 0, 53)))
348edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
349edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project             break;
350edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
351edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'w':   /* The day of week, beginning on sunday. */
352edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_O);
353edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
354edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
355edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
356edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
357edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'Y':   /* The year. */
358edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_E);
359edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &i, 0, 9999)))
360edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
361edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
362edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            relyear = -1;
363edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            tm->tm_year = i - TM_YEAR_BASE;
364edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
365edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
366edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'y':   /* The year within the century (2 digits). */
367edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(_ALT_E | _ALT_O);
368edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (!(_conv_num(&bp, &relyear, 0, 99)))
369edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                return (NULL);
370edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
371edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
372edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        /*
373edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         * Miscellaneous conversions.
374edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project         */
375edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 'n':   /* Any kind of white-space. */
376edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        case 't':
377edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            _LEGAL_ALT(0);
378edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            while (isspace(*bp))
379edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                bp++;
380edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            break;
381edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
382edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
383edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        default:    /* Unknown/unsupported conversion. */
384edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            return (NULL);
385edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        }
386edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
387edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
388edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
389edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
390edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /*
391edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project     * We need to evaluate the two digit year spec (%y)
392edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project     * last as we can get a century spec (%C) at any time.
393edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project     */
394edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (relyear != -1) {
395edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        if (century == TM_YEAR_BASE) {
396edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            if (relyear <= 68)
397edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                tm->tm_year = relyear + 2000 - TM_YEAR_BASE;
398edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            else
399edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project                tm->tm_year = relyear + 1900 - TM_YEAR_BASE;
400edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        } else {
401edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project            tm->tm_year = relyear + century - TM_YEAR_BASE;
402edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        }
403edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    }
404edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project
405edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return (unsigned char*)bp;
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
412edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    int result = 0;
413edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    int rulim = ulim;
4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
415edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (**buf < '0' || **buf > '9')
416edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        return (0);
4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
418edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    /* we use rulim to break out of the loop when we run out of digits */
419edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    do {
420edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        result *= 10;
421edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        result += *(*buf)++ - '0';
422edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        rulim /= 10;
423edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
4241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
425edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    if (result < llim || result > ulim)
426edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project        return (0);
4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
428edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    *dest = result;
429edbe7fc97bab7ff0684053d1be564330689bf3adThe Android Open Source Project    return (1);
4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
431