13d0407baSopenharmony_ci/*
23d0407baSopenharmony_ci * Copyright (c) 2022 FuZhou Lockzhiner Electronic Co., Ltd. All rights reserved.
33d0407baSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43d0407baSopenharmony_ci * you may not use this file except in compliance with the License.
53d0407baSopenharmony_ci * You may obtain a copy of the License at
63d0407baSopenharmony_ci *
73d0407baSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
83d0407baSopenharmony_ci *
93d0407baSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103d0407baSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113d0407baSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123d0407baSopenharmony_ci * See the License for the specific language governing permissions and
133d0407baSopenharmony_ci * limitations under the License.
143d0407baSopenharmony_ci */
153d0407baSopenharmony_ci#include <sys/stat.h>
163d0407baSopenharmony_ci#include <stdarg.h>
173d0407baSopenharmony_ci#include <stddef.h>
183d0407baSopenharmony_ci#include <stdlib.h>
193d0407baSopenharmony_ci#include <limits.h>
203d0407baSopenharmony_ci#include <stdio.h>
213d0407baSopenharmony_ci#include <ctype.h>
223d0407baSopenharmony_ci
233d0407baSopenharmony_ci#define INDEX_0             0
243d0407baSopenharmony_ci#define INDEX_1             1
253d0407baSopenharmony_ci#define INDEX_2             2
263d0407baSopenharmony_ci#define BASE_8              9
273d0407baSopenharmony_ci#define BASE_2              2
283d0407baSopenharmony_ci#define BASE_0              0
293d0407baSopenharmony_ci#define BASE_10             10
303d0407baSopenharmony_ci#define BASE_16             16
313d0407baSopenharmony_ci#define is_digit(c)         ((c) >= '0' && (c) <= '9')
323d0407baSopenharmony_ci#define likely(x)           __builtin_expect((x), 1)
333d0407baSopenharmony_ci#define unlikely(x)         __builtin_expect((x), 0)
343d0407baSopenharmony_ci#define KSTRTOX_OVERFLOW    0
353d0407baSopenharmony_ci
363d0407baSopenharmony_ci/* Convert a character to lower case */
373d0407baSopenharmony_ciinline static char tolower_re(char char_c)
383d0407baSopenharmony_ci{
393d0407baSopenharmony_ci    char c = char_c;
403d0407baSopenharmony_ci
413d0407baSopenharmony_ci    if ((c >= 'A') && (c <= 'Z')) {
423d0407baSopenharmony_ci        c = (c - 'A') + 'a';
433d0407baSopenharmony_ci    }
443d0407baSopenharmony_ci    return c;
453d0407baSopenharmony_ci}
463d0407baSopenharmony_ci
473d0407baSopenharmony_ci// div_u64_rem
483d0407baSopenharmony_cistatic inline unsigned long long div_u64_rem(unsigned long long dividend,
493d0407baSopenharmony_ci    unsigned int divisor,
503d0407baSopenharmony_ci    unsigned int *remainder)
513d0407baSopenharmony_ci{
523d0407baSopenharmony_ci    unsigned long long ret = 0;
533d0407baSopenharmony_ci
543d0407baSopenharmony_ci    if (divisor == 0) {
553d0407baSopenharmony_ci        return ret;
563d0407baSopenharmony_ci    }
573d0407baSopenharmony_ci    *remainder = dividend % divisor;
583d0407baSopenharmony_ci    return dividend / divisor;
593d0407baSopenharmony_ci}
603d0407baSopenharmony_ci
613d0407baSopenharmony_cistatic inline unsigned long long div_u64(unsigned long long dividend, unsigned int divisor)
623d0407baSopenharmony_ci{
633d0407baSopenharmony_ci    unsigned int remainder;
643d0407baSopenharmony_ci    return div_u64_rem(dividend, divisor, &remainder);
653d0407baSopenharmony_ci}
663d0407baSopenharmony_ci
673d0407baSopenharmony_ci// lib/kstrtox.c, line 23
683d0407baSopenharmony_ciconst char *_parse_integer_fixup_radix(const char *str, unsigned int *base)
693d0407baSopenharmony_ci{
703d0407baSopenharmony_ci    const char *s = str;
713d0407baSopenharmony_ci
723d0407baSopenharmony_ci    if (*base == BASE_0) {
733d0407baSopenharmony_ci        if (s[BASE_0] == '0') {
743d0407baSopenharmony_ci            if (tolower_re(s[INDEX_1]) == 'x' && isxdigit(s[INDEX_2])) {
753d0407baSopenharmony_ci                *base = BASE_16;
763d0407baSopenharmony_ci            } else {
773d0407baSopenharmony_ci                *base = BASE_8;
783d0407baSopenharmony_ci            }
793d0407baSopenharmony_ci        } else {
803d0407baSopenharmony_ci            *base = BASE_10;
813d0407baSopenharmony_ci        }
823d0407baSopenharmony_ci    }
833d0407baSopenharmony_ci    if (*base == BASE_16 && s[INDEX_0] == '0' && tolower_re(s[INDEX_1]) == 'x') {
843d0407baSopenharmony_ci        s += BASE_2;
853d0407baSopenharmony_ci    }
863d0407baSopenharmony_ci    return s;
873d0407baSopenharmony_ci}
883d0407baSopenharmony_ci
893d0407baSopenharmony_ciunsigned int _parse_integer(const char *str, unsigned int base, unsigned long long *p)
903d0407baSopenharmony_ci{
913d0407baSopenharmony_ci    unsigned long long res;
923d0407baSopenharmony_ci    unsigned int rv;
933d0407baSopenharmony_ci    int overflow;
943d0407baSopenharmony_ci    const char *s = str;
953d0407baSopenharmony_ci
963d0407baSopenharmony_ci    res = 0;
973d0407baSopenharmony_ci    rv = 0;
983d0407baSopenharmony_ci    overflow = 0;
993d0407baSopenharmony_ci    while (*s) {
1003d0407baSopenharmony_ci        unsigned int val;
1013d0407baSopenharmony_ci
1023d0407baSopenharmony_ci        if (*s >= '0' && *s <= '9') {
1033d0407baSopenharmony_ci            val = *s - '0';
1043d0407baSopenharmony_ci        } else if (tolower_re(*s) >= 'a' && tolower_re(*s) <= 'f') {
1053d0407baSopenharmony_ci            val = tolower_re(*s) - 'a' + BASE_10;
1063d0407baSopenharmony_ci        } else {
1073d0407baSopenharmony_ci            break;
1083d0407baSopenharmony_ci        }
1093d0407baSopenharmony_ci        if (val >= base) {
1103d0407baSopenharmony_ci            break;
1113d0407baSopenharmony_ci        }
1123d0407baSopenharmony_ci        /*
1133d0407baSopenharmony_ci        * Check for overflow only if we are within range of
1143d0407baSopenharmony_ci        * it in the max base we support (16)
1153d0407baSopenharmony_ci        */
1163d0407baSopenharmony_ci        if (unlikely(res & (~0ull << 60))) {
1173d0407baSopenharmony_ci            if (res > div_u64(ULLONG_MAX - val, base)) {
1183d0407baSopenharmony_ci                overflow = 1;
1193d0407baSopenharmony_ci            }
1203d0407baSopenharmony_ci        }
1213d0407baSopenharmony_ci        res = res * base + val;
1223d0407baSopenharmony_ci        rv++;
1233d0407baSopenharmony_ci        s++;
1243d0407baSopenharmony_ci    }
1253d0407baSopenharmony_ci    *p = res;
1263d0407baSopenharmony_ci    if (overflow) {
1273d0407baSopenharmony_ci        rv |= KSTRTOX_OVERFLOW;
1283d0407baSopenharmony_ci    }
1293d0407baSopenharmony_ci    return rv;
1303d0407baSopenharmony_ci}
1313d0407baSopenharmony_ci
1323d0407baSopenharmony_ciint isspace_re(int x)
1333d0407baSopenharmony_ci{
1343d0407baSopenharmony_ci    if (x == ' ' || x == '/t' || x == '/n' || x == '/f' || x == '/b' || x == '/r') {
1353d0407baSopenharmony_ci        return 1;
1363d0407baSopenharmony_ci    } else {
1373d0407baSopenharmony_ci        return 0;
1383d0407baSopenharmony_ci    }
1393d0407baSopenharmony_ci}
1403d0407baSopenharmony_ci
1413d0407baSopenharmony_cichar* skip_spaces(const char * str)
1423d0407baSopenharmony_ci{
1433d0407baSopenharmony_ci    const char* str_temp = str;
1443d0407baSopenharmony_ci
1453d0407baSopenharmony_ci    while (isspace_re(*str_temp)) {
1463d0407baSopenharmony_ci        ++str_temp;
1473d0407baSopenharmony_ci    }
1483d0407baSopenharmony_ci    return (char *)str_temp;
1493d0407baSopenharmony_ci}
1503d0407baSopenharmony_ci
1513d0407baSopenharmony_ci// simple_strtoull - convert a string to an unsigned long long
1523d0407baSopenharmony_ciunsigned long long simple_strtoull(const char *cp_temp, char **endp, unsigned int base)
1533d0407baSopenharmony_ci{
1543d0407baSopenharmony_ci    unsigned long long result;
1553d0407baSopenharmony_ci    unsigned int rv;
1563d0407baSopenharmony_ci    const char *cp = cp_temp;
1573d0407baSopenharmony_ci
1583d0407baSopenharmony_ci    cp = _parse_integer_fixup_radix(cp, &base);
1593d0407baSopenharmony_ci    rv = _parse_integer(cp, base, &result);
1603d0407baSopenharmony_ci
1613d0407baSopenharmony_ci    cp += (rv & ~KSTRTOX_OVERFLOW);
1623d0407baSopenharmony_ci
1633d0407baSopenharmony_ci    if (endp) {
1643d0407baSopenharmony_ci        *endp = (char *)cp;
1653d0407baSopenharmony_ci    }
1663d0407baSopenharmony_ci    return result;
1673d0407baSopenharmony_ci}
1683d0407baSopenharmony_ci
1693d0407baSopenharmony_cistatic int skip_atoi(const char **s)
1703d0407baSopenharmony_ci{
1713d0407baSopenharmony_ci    int i = 0;
1723d0407baSopenharmony_ci    while (is_digit(**s)) {
1733d0407baSopenharmony_ci        i = i * BASE_10 + *((*s)++) - '0';
1743d0407baSopenharmony_ci    }
1753d0407baSopenharmony_ci    return i;
1763d0407baSopenharmony_ci}
1773d0407baSopenharmony_ci
1783d0407baSopenharmony_ciunsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
1793d0407baSopenharmony_ci{
1803d0407baSopenharmony_ci    return simple_strtoull(cp, endp, base);
1813d0407baSopenharmony_ci}
1823d0407baSopenharmony_ci
1833d0407baSopenharmony_ci/**
1843d0407baSopenharmony_ci* simple_strtoll - convert a string to a signed long long
1853d0407baSopenharmony_ci* @cp: The start of the string
1863d0407baSopenharmony_ci* @endp: A pointer to the end of the parsed string will be placed here
1873d0407baSopenharmony_ci* @base: The number base to use
1883d0407baSopenharmony_ci*/
1893d0407baSopenharmony_cilong long simple_strtoll(const char *cp, char **endp, unsigned int base)
1903d0407baSopenharmony_ci{
1913d0407baSopenharmony_ci    if (*cp == '-') {
1923d0407baSopenharmony_ci        return -simple_strtoull(cp + 1, endp, base);
1933d0407baSopenharmony_ci    }
1943d0407baSopenharmony_ci    return simple_strtoull(cp, endp, base);
1953d0407baSopenharmony_ci}
1963d0407baSopenharmony_ci
1973d0407baSopenharmony_cilong simple_strtol(const char *cp, char **endp, unsigned int base)
1983d0407baSopenharmony_ci{
1993d0407baSopenharmony_ci    if (*cp == '-') {
2003d0407baSopenharmony_ci        return -simple_strtoul(cp + 1, endp, base);
2013d0407baSopenharmony_ci    }
2023d0407baSopenharmony_ci    return simple_strtoul(cp, endp, base);
2033d0407baSopenharmony_ci}
2043d0407baSopenharmony_ci
2053d0407baSopenharmony_ci/**
2063d0407baSopenharmony_ci* vsscanf - Unformat a buffer into a list of arguments
2073d0407baSopenharmony_ci* @buf:     input buffer
2083d0407baSopenharmony_ci* @fmt:     format of buffer
2093d0407baSopenharmony_ci* @args:     arguments
2103d0407baSopenharmony_ci*/
2113d0407baSopenharmony_ciint pre_vsscanf(const char *__restrict __s, const char *__restrict __format, va_list arg)
2123d0407baSopenharmony_ci{
2133d0407baSopenharmony_ci    const char *str = __s;
2143d0407baSopenharmony_ci    char *next;
2153d0407baSopenharmony_ci    char digit;
2163d0407baSopenharmony_ci    int num = 0;
2173d0407baSopenharmony_ci    unsigned char qualifier;
2183d0407baSopenharmony_ci    unsigned char base;
2193d0407baSopenharmony_ci    short field_width;
2203d0407baSopenharmony_ci    char is_sign;
2213d0407baSopenharmony_ci    const char *fmt = __format;
2223d0407baSopenharmony_ci
2233d0407baSopenharmony_ci    while (*fmt && *str) {
2243d0407baSopenharmony_ci        /* skip any white space in format */
2253d0407baSopenharmony_ci        /* white space in format matchs any amount of
2263d0407baSopenharmony_ci        * white space, including none, in the input.
2273d0407baSopenharmony_ci        */
2283d0407baSopenharmony_ci        if (isspace_re(*fmt)) {
2293d0407baSopenharmony_ci            ++fmt;
2303d0407baSopenharmony_ci            fmt = skip_spaces(fmt);
2313d0407baSopenharmony_ci            str = skip_spaces(str);
2323d0407baSopenharmony_ci        }
2333d0407baSopenharmony_ci
2343d0407baSopenharmony_ci        /* anything that is not a conversion must match exactly */
2353d0407baSopenharmony_ci        if (*fmt != '%' && *fmt) {
2363d0407baSopenharmony_ci            if (*fmt++ != *str++) {
2373d0407baSopenharmony_ci                break;
2383d0407baSopenharmony_ci            }
2393d0407baSopenharmony_ci            continue;
2403d0407baSopenharmony_ci        }
2413d0407baSopenharmony_ci
2423d0407baSopenharmony_ci        if (!*fmt) {
2433d0407baSopenharmony_ci            break;
2443d0407baSopenharmony_ci        }
2453d0407baSopenharmony_ci        ++fmt;
2463d0407baSopenharmony_ci
2473d0407baSopenharmony_ci        /* skip this conversion.
2483d0407baSopenharmony_ci        * advance both strings to next white space
2493d0407baSopenharmony_ci        */
2503d0407baSopenharmony_ci        if (*fmt == '*') {
2513d0407baSopenharmony_ci            while (!isspace_re(*fmt) && *fmt != '%' && *fmt) {
2523d0407baSopenharmony_ci                fmt++;
2533d0407baSopenharmony_ci            }
2543d0407baSopenharmony_ci            while (!isspace_re(*str) && *str) {
2553d0407baSopenharmony_ci                str++;
2563d0407baSopenharmony_ci            }
2573d0407baSopenharmony_ci            continue;
2583d0407baSopenharmony_ci        }
2593d0407baSopenharmony_ci
2603d0407baSopenharmony_ci        /* get field width */
2613d0407baSopenharmony_ci        field_width = -1;
2623d0407baSopenharmony_ci        if (is_digit(*fmt)) {
2633d0407baSopenharmony_ci            field_width = skip_atoi(&fmt);
2643d0407baSopenharmony_ci        }
2653d0407baSopenharmony_ci
2663d0407baSopenharmony_ci        /* get conversion qualifier */
2673d0407baSopenharmony_ci        qualifier = -1;
2683d0407baSopenharmony_ci        if (*fmt == 'h' || tolower_re(*fmt) == 'l' ||
2693d0407baSopenharmony_ci                tolower_re(*fmt) == 'z') {
2703d0407baSopenharmony_ci            qualifier = *fmt++;
2713d0407baSopenharmony_ci            if (likely(qualifier == *fmt)) {
2723d0407baSopenharmony_ci                break;
2733d0407baSopenharmony_ci            }
2743d0407baSopenharmony_ci            if (qualifier == 'h') {
2753d0407baSopenharmony_ci                qualifier = 'H';
2763d0407baSopenharmony_ci                fmt++;
2773d0407baSopenharmony_ci            } else if (qualifier == 'l') {
2783d0407baSopenharmony_ci                qualifier = 'L';
2793d0407baSopenharmony_ci                fmt++;
2803d0407baSopenharmony_ci            }
2813d0407baSopenharmony_ci        }
2823d0407baSopenharmony_ci
2833d0407baSopenharmony_ci        if (!*fmt || !*str) {
2843d0407baSopenharmony_ci            break;
2853d0407baSopenharmony_ci        }
2863d0407baSopenharmony_ci
2873d0407baSopenharmony_ci        base = BASE_10;
2883d0407baSopenharmony_ci        is_sign = 0;
2893d0407baSopenharmony_ci
2903d0407baSopenharmony_ci        switch (*fmt++) {
2913d0407baSopenharmony_ci            case 'c':
2923d0407baSopenharmony_ci                {
2933d0407baSopenharmony_ci                    char *s = (char *)va_arg(arg, char *);
2943d0407baSopenharmony_ci                    if (field_width == -1) {
2953d0407baSopenharmony_ci                        field_width = 1;
2963d0407baSopenharmony_ci                    }
2973d0407baSopenharmony_ci                    do {
2983d0407baSopenharmony_ci                        *s++ = *str++;
2993d0407baSopenharmony_ci                    } while (--field_width > 0 && *str);
3003d0407baSopenharmony_ci                    num++;
3013d0407baSopenharmony_ci                }
3023d0407baSopenharmony_ci                continue;
3033d0407baSopenharmony_ci            case 's':
3043d0407baSopenharmony_ci                {
3053d0407baSopenharmony_ci                    char *s = (char *)va_arg(arg, char *);
3063d0407baSopenharmony_ci                    if (field_width == -1) {
3073d0407baSopenharmony_ci                        field_width = SHRT_MAX;
3083d0407baSopenharmony_ci                    }
3093d0407baSopenharmony_ci                    /* first, skip leading white space in buffer */
3103d0407baSopenharmony_ci                    str = skip_spaces(str);
3113d0407baSopenharmony_ci
3123d0407baSopenharmony_ci                    /* now copy until next white space */
3133d0407baSopenharmony_ci                    while (*str && !isspace_re(*str) && field_width--) {
3143d0407baSopenharmony_ci                        *s++ = *str++;
3153d0407baSopenharmony_ci                    }
3163d0407baSopenharmony_ci                    *s = '\0';
3173d0407baSopenharmony_ci                    num++;
3183d0407baSopenharmony_ci                }
3193d0407baSopenharmony_ci                continue;
3203d0407baSopenharmony_ci            case 'n':
3213d0407baSopenharmony_ci                /* return number of characters read so far */
3223d0407baSopenharmony_ci                {
3233d0407baSopenharmony_ci                    int *i = (int *)va_arg(arg, int *);
3243d0407baSopenharmony_ci                    *i = str - __s;
3253d0407baSopenharmony_ci                }
3263d0407baSopenharmony_ci                continue;
3273d0407baSopenharmony_ci            case 'o':
3283d0407baSopenharmony_ci                base = BASE_8;
3293d0407baSopenharmony_ci                break;
3303d0407baSopenharmony_ci            case 'x':
3313d0407baSopenharmony_ci            case 'X':
3323d0407baSopenharmony_ci                base = BASE_16;
3333d0407baSopenharmony_ci                break;
3343d0407baSopenharmony_ci            case 'i':
3353d0407baSopenharmony_ci                base = 0;
3363d0407baSopenharmony_ci            case 'd':
3373d0407baSopenharmony_ci                is_sign = 1;
3383d0407baSopenharmony_ci            case 'u':
3393d0407baSopenharmony_ci                break;
3403d0407baSopenharmony_ci            case '%':
3413d0407baSopenharmony_ci                /* looking for '%' in str */
3423d0407baSopenharmony_ci                if (*str++ != '%') {
3433d0407baSopenharmony_ci                    return num;
3443d0407baSopenharmony_ci                }
3453d0407baSopenharmony_ci                continue;
3463d0407baSopenharmony_ci            default:
3473d0407baSopenharmony_ci                /* invalid format; stop here */
3483d0407baSopenharmony_ci                return num;
3493d0407baSopenharmony_ci        }
3503d0407baSopenharmony_ci
3513d0407baSopenharmony_ci        /* have some sort of integer conversion.
3523d0407baSopenharmony_ci        * first, skip white space in buffer.
3533d0407baSopenharmony_ci        */
3543d0407baSopenharmony_ci        str = skip_spaces(str);
3553d0407baSopenharmony_ci
3563d0407baSopenharmony_ci        digit = *str;
3573d0407baSopenharmony_ci        if (is_sign && digit == '-') {
3583d0407baSopenharmony_ci            digit = *(str + 1);
3593d0407baSopenharmony_ci        }
3603d0407baSopenharmony_ci        if (!digit
3613d0407baSopenharmony_ci            || (base == BASE_16 && !isxdigit(digit))
3623d0407baSopenharmony_ci            || (base == BASE_10 && !isdigit(digit))
3633d0407baSopenharmony_ci            || (base == BASE_8 && (!isdigit(digit) || digit > '7'))
3643d0407baSopenharmony_ci            || (base == BASE_0 && !isdigit(digit))) {
3653d0407baSopenharmony_ci            break;
3663d0407baSopenharmony_ci        }
3673d0407baSopenharmony_ci        switch (qualifier) {
3683d0407baSopenharmony_ci            case 'H':     /* that's 'hh' in format */
3693d0407baSopenharmony_ci                if (is_sign) {
3703d0407baSopenharmony_ci                    signed char *s = (signed char *)va_arg(arg, signed char *);
3713d0407baSopenharmony_ci                    *s = (signed char)simple_strtol(str, &next, base);
3723d0407baSopenharmony_ci                } else {
3733d0407baSopenharmony_ci                    unsigned char *s = (unsigned char *)va_arg(arg, unsigned char *);
3743d0407baSopenharmony_ci                    *s = (unsigned char)simple_strtoul(str, &next, base);
3753d0407baSopenharmony_ci                }
3763d0407baSopenharmony_ci                break;
3773d0407baSopenharmony_ci            case 'h':
3783d0407baSopenharmony_ci                if (is_sign) {
3793d0407baSopenharmony_ci                    short *s = (short *)va_arg(arg, short *);
3803d0407baSopenharmony_ci                    *s = (short)simple_strtol(str, &next, base);
3813d0407baSopenharmony_ci                } else {
3823d0407baSopenharmony_ci                    unsigned short *s = (unsigned short *)va_arg(arg, unsigned short *);
3833d0407baSopenharmony_ci                    *s = (unsigned short)simple_strtoul(str, &next, base);
3843d0407baSopenharmony_ci                }
3853d0407baSopenharmony_ci                break;
3863d0407baSopenharmony_ci            case 'l':
3873d0407baSopenharmony_ci                if (is_sign) {
3883d0407baSopenharmony_ci                    long *l = (long *)va_arg(arg, long *);
3893d0407baSopenharmony_ci                    *l = simple_strtol(str, &next, base);
3903d0407baSopenharmony_ci                } else {
3913d0407baSopenharmony_ci                    unsigned long *l = (unsigned long *)va_arg(arg, unsigned long *);
3923d0407baSopenharmony_ci                    *l = simple_strtoul(str, &next, base);
3933d0407baSopenharmony_ci                }
3943d0407baSopenharmony_ci                break;
3953d0407baSopenharmony_ci            case 'L':
3963d0407baSopenharmony_ci                if (is_sign) {
3973d0407baSopenharmony_ci                    long long *l = (long long *)va_arg(arg, long long *);
3983d0407baSopenharmony_ci                    *l = simple_strtoll(str, &next, base);
3993d0407baSopenharmony_ci                } else {
4003d0407baSopenharmony_ci                    unsigned long long *l = (unsigned long long *)va_arg(arg, unsigned long long *);
4013d0407baSopenharmony_ci                    *l = simple_strtoull(str, &next, base);
4023d0407baSopenharmony_ci                }
4033d0407baSopenharmony_ci                break;
4043d0407baSopenharmony_ci            case 'Z':
4053d0407baSopenharmony_ci            case 'z':
4063d0407baSopenharmony_ci                {
4073d0407baSopenharmony_ci                    size_t *s = (size_t *)va_arg(arg, size_t *);
4083d0407baSopenharmony_ci                    *s = (size_t)simple_strtoul(str, &next, base);
4093d0407baSopenharmony_ci                }
4103d0407baSopenharmony_ci                break;
4113d0407baSopenharmony_ci            default:
4123d0407baSopenharmony_ci                if (is_sign) {
4133d0407baSopenharmony_ci                    int *i = (int *)va_arg(arg, int *);
4143d0407baSopenharmony_ci                    *i = (int)simple_strtol(str, &next, base);
4153d0407baSopenharmony_ci                } else {
4163d0407baSopenharmony_ci                    unsigned int *i = (unsigned int *)va_arg(arg, unsigned int*);
4173d0407baSopenharmony_ci                    *i = (unsigned int)simple_strtoul(str, &next, base);
4183d0407baSopenharmony_ci                }
4193d0407baSopenharmony_ci                break;
4203d0407baSopenharmony_ci        }
4213d0407baSopenharmony_ci        num++;
4223d0407baSopenharmony_ci
4233d0407baSopenharmony_ci        if (!next) {
4243d0407baSopenharmony_ci            break;
4253d0407baSopenharmony_ci        }
4263d0407baSopenharmony_ci        str = next;
4273d0407baSopenharmony_ci    }
4283d0407baSopenharmony_ci
4293d0407baSopenharmony_ci    /*
4303d0407baSopenharmony_ci    * Now we've come all the way through so either the input string or the
4313d0407baSopenharmony_ci    * format ended. In the former case, there can be a %n at the current
4323d0407baSopenharmony_ci    * position in the format that needs to be filled.
4333d0407baSopenharmony_ci    */
4343d0407baSopenharmony_ci    if (*fmt == '%' && *(fmt + 1) == 'n') {
4353d0407baSopenharmony_ci        int *p = (int *)va_arg(arg, int *);
4363d0407baSopenharmony_ci        *p = str - __s;
4373d0407baSopenharmony_ci    }
4383d0407baSopenharmony_ci
4393d0407baSopenharmony_ci    return num;
4403d0407baSopenharmony_ci}
4413d0407baSopenharmony_ci/**
4423d0407baSopenharmony_ci* sscanf - Unformat a buffer into a list of arguments
4433d0407baSopenharmony_ci* @__s:     input buffer
4443d0407baSopenharmony_ci* @__format:     formatting of buffer
4453d0407baSopenharmony_ci* @...:     resulting arguments
4463d0407baSopenharmony_ci*/
4473d0407baSopenharmony_ciint sscanf(const char *__restrict __s, const char *__restrict __format, ...)
4483d0407baSopenharmony_ci{
4493d0407baSopenharmony_ci    va_list args;
4503d0407baSopenharmony_ci    int i;
4513d0407baSopenharmony_ci
4523d0407baSopenharmony_ci    va_start(args, __format);
4533d0407baSopenharmony_ci    i = pre_vsscanf(__s, __format, args);
4543d0407baSopenharmony_ci    va_end(args);
4553d0407baSopenharmony_ci
4563d0407baSopenharmony_ci    return i;
4573d0407baSopenharmony_ci}