18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* -*- linux-c -*- ------------------------------------------------------- * 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 58c2ecf20Sopenharmony_ci * Copyright 2007 rPath, Inc. - All Rights Reserved 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * ----------------------------------------------------------------------- */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci/* 108c2ecf20Sopenharmony_ci * Very basic string functions 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/types.h> 148c2ecf20Sopenharmony_ci#include <linux/compiler.h> 158c2ecf20Sopenharmony_ci#include <linux/errno.h> 168c2ecf20Sopenharmony_ci#include <linux/limits.h> 178c2ecf20Sopenharmony_ci#include <asm/asm.h> 188c2ecf20Sopenharmony_ci#include "ctype.h" 198c2ecf20Sopenharmony_ci#include "string.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define KSTRTOX_OVERFLOW (1U << 31) 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* 248c2ecf20Sopenharmony_ci * Undef these macros so that the functions that we provide 258c2ecf20Sopenharmony_ci * here will have the correct names regardless of how string.h 268c2ecf20Sopenharmony_ci * may have chosen to #define them. 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci#undef memcpy 298c2ecf20Sopenharmony_ci#undef memset 308c2ecf20Sopenharmony_ci#undef memcmp 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ciint memcmp(const void *s1, const void *s2, size_t len) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci bool diff; 358c2ecf20Sopenharmony_ci asm("repe; cmpsb" CC_SET(nz) 368c2ecf20Sopenharmony_ci : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len)); 378c2ecf20Sopenharmony_ci return diff; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * Clang may lower `memcmp == 0` to `bcmp == 0`. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ciint bcmp(const void *s1, const void *s2, size_t len) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci return memcmp(s1, s2, len); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciint strcmp(const char *str1, const char *str2) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci const unsigned char *s1 = (const unsigned char *)str1; 518c2ecf20Sopenharmony_ci const unsigned char *s2 = (const unsigned char *)str2; 528c2ecf20Sopenharmony_ci int delta = 0; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci while (*s1 || *s2) { 558c2ecf20Sopenharmony_ci delta = *s1 - *s2; 568c2ecf20Sopenharmony_ci if (delta) 578c2ecf20Sopenharmony_ci return delta; 588c2ecf20Sopenharmony_ci s1++; 598c2ecf20Sopenharmony_ci s2++; 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciint strncmp(const char *cs, const char *ct, size_t count) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci unsigned char c1, c2; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci while (count) { 698c2ecf20Sopenharmony_ci c1 = *cs++; 708c2ecf20Sopenharmony_ci c2 = *ct++; 718c2ecf20Sopenharmony_ci if (c1 != c2) 728c2ecf20Sopenharmony_ci return c1 < c2 ? -1 : 1; 738c2ecf20Sopenharmony_ci if (!c1) 748c2ecf20Sopenharmony_ci break; 758c2ecf20Sopenharmony_ci count--; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci return 0; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cisize_t strnlen(const char *s, size_t maxlen) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci const char *es = s; 838c2ecf20Sopenharmony_ci while (*es && maxlen) { 848c2ecf20Sopenharmony_ci es++; 858c2ecf20Sopenharmony_ci maxlen--; 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci return (es - s); 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ciunsigned int atou(const char *s) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci unsigned int i = 0; 948c2ecf20Sopenharmony_ci while (isdigit(*s)) 958c2ecf20Sopenharmony_ci i = i * 10 + (*s++ - '0'); 968c2ecf20Sopenharmony_ci return i; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/* Works only for digits and letters, but small and fast */ 1008c2ecf20Sopenharmony_ci#define TOLOWER(x) ((x) | 0x20) 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic unsigned int simple_guess_base(const char *cp) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci if (cp[0] == '0') { 1058c2ecf20Sopenharmony_ci if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2])) 1068c2ecf20Sopenharmony_ci return 16; 1078c2ecf20Sopenharmony_ci else 1088c2ecf20Sopenharmony_ci return 8; 1098c2ecf20Sopenharmony_ci } else { 1108c2ecf20Sopenharmony_ci return 10; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/** 1158c2ecf20Sopenharmony_ci * simple_strtoull - convert a string to an unsigned long long 1168c2ecf20Sopenharmony_ci * @cp: The start of the string 1178c2ecf20Sopenharmony_ci * @endp: A pointer to the end of the parsed string will be placed here 1188c2ecf20Sopenharmony_ci * @base: The number base to use 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_ciunsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci unsigned long long result = 0; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (!base) 1258c2ecf20Sopenharmony_ci base = simple_guess_base(cp); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x') 1288c2ecf20Sopenharmony_ci cp += 2; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci while (isxdigit(*cp)) { 1318c2ecf20Sopenharmony_ci unsigned int value; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10; 1348c2ecf20Sopenharmony_ci if (value >= base) 1358c2ecf20Sopenharmony_ci break; 1368c2ecf20Sopenharmony_ci result = result * base + value; 1378c2ecf20Sopenharmony_ci cp++; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci if (endp) 1408c2ecf20Sopenharmony_ci *endp = (char *)cp; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci return result; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cilong simple_strtol(const char *cp, char **endp, unsigned int base) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci if (*cp == '-') 1488c2ecf20Sopenharmony_ci return -simple_strtoull(cp + 1, endp, base); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return simple_strtoull(cp, endp, base); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/** 1548c2ecf20Sopenharmony_ci * strlen - Find the length of a string 1558c2ecf20Sopenharmony_ci * @s: The string to be sized 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_cisize_t strlen(const char *s) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci const char *sc; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci for (sc = s; *sc != '\0'; ++sc) 1628c2ecf20Sopenharmony_ci /* nothing */; 1638c2ecf20Sopenharmony_ci return sc - s; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/** 1678c2ecf20Sopenharmony_ci * strstr - Find the first substring in a %NUL terminated string 1688c2ecf20Sopenharmony_ci * @s1: The string to be searched 1698c2ecf20Sopenharmony_ci * @s2: The string to search for 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_cichar *strstr(const char *s1, const char *s2) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci size_t l1, l2; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci l2 = strlen(s2); 1768c2ecf20Sopenharmony_ci if (!l2) 1778c2ecf20Sopenharmony_ci return (char *)s1; 1788c2ecf20Sopenharmony_ci l1 = strlen(s1); 1798c2ecf20Sopenharmony_ci while (l1 >= l2) { 1808c2ecf20Sopenharmony_ci l1--; 1818c2ecf20Sopenharmony_ci if (!memcmp(s1, s2, l2)) 1828c2ecf20Sopenharmony_ci return (char *)s1; 1838c2ecf20Sopenharmony_ci s1++; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci return NULL; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci/** 1898c2ecf20Sopenharmony_ci * strchr - Find the first occurrence of the character c in the string s. 1908c2ecf20Sopenharmony_ci * @s: the string to be searched 1918c2ecf20Sopenharmony_ci * @c: the character to search for 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_cichar *strchr(const char *s, int c) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci while (*s != (char)c) 1968c2ecf20Sopenharmony_ci if (*s++ == '\0') 1978c2ecf20Sopenharmony_ci return NULL; 1988c2ecf20Sopenharmony_ci return (char *)s; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic inline u64 __div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci union { 2048c2ecf20Sopenharmony_ci u64 v64; 2058c2ecf20Sopenharmony_ci u32 v32[2]; 2068c2ecf20Sopenharmony_ci } d = { dividend }; 2078c2ecf20Sopenharmony_ci u32 upper; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci upper = d.v32[1]; 2108c2ecf20Sopenharmony_ci d.v32[1] = 0; 2118c2ecf20Sopenharmony_ci if (upper >= divisor) { 2128c2ecf20Sopenharmony_ci d.v32[1] = upper / divisor; 2138c2ecf20Sopenharmony_ci upper %= divisor; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) : 2168c2ecf20Sopenharmony_ci "rm" (divisor), "0" (d.v32[0]), "1" (upper)); 2178c2ecf20Sopenharmony_ci return d.v64; 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic inline u64 __div_u64(u64 dividend, u32 divisor) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci u32 remainder; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci return __div_u64_rem(dividend, divisor, &remainder); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic inline char _tolower(const char c) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci return c | 0x20; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci if (*base == 0) { 2358c2ecf20Sopenharmony_ci if (s[0] == '0') { 2368c2ecf20Sopenharmony_ci if (_tolower(s[1]) == 'x' && isxdigit(s[2])) 2378c2ecf20Sopenharmony_ci *base = 16; 2388c2ecf20Sopenharmony_ci else 2398c2ecf20Sopenharmony_ci *base = 8; 2408c2ecf20Sopenharmony_ci } else 2418c2ecf20Sopenharmony_ci *base = 10; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x') 2448c2ecf20Sopenharmony_ci s += 2; 2458c2ecf20Sopenharmony_ci return s; 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci/* 2498c2ecf20Sopenharmony_ci * Convert non-negative integer string representation in explicitly given radix 2508c2ecf20Sopenharmony_ci * to an integer. 2518c2ecf20Sopenharmony_ci * Return number of characters consumed maybe or-ed with overflow bit. 2528c2ecf20Sopenharmony_ci * If overflow occurs, result integer (incorrect) is still returned. 2538c2ecf20Sopenharmony_ci * 2548c2ecf20Sopenharmony_ci * Don't you dare use this function. 2558c2ecf20Sopenharmony_ci */ 2568c2ecf20Sopenharmony_cistatic unsigned int _parse_integer(const char *s, 2578c2ecf20Sopenharmony_ci unsigned int base, 2588c2ecf20Sopenharmony_ci unsigned long long *p) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci unsigned long long res; 2618c2ecf20Sopenharmony_ci unsigned int rv; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci res = 0; 2648c2ecf20Sopenharmony_ci rv = 0; 2658c2ecf20Sopenharmony_ci while (1) { 2668c2ecf20Sopenharmony_ci unsigned int c = *s; 2678c2ecf20Sopenharmony_ci unsigned int lc = c | 0x20; /* don't tolower() this line */ 2688c2ecf20Sopenharmony_ci unsigned int val; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if ('0' <= c && c <= '9') 2718c2ecf20Sopenharmony_ci val = c - '0'; 2728c2ecf20Sopenharmony_ci else if ('a' <= lc && lc <= 'f') 2738c2ecf20Sopenharmony_ci val = lc - 'a' + 10; 2748c2ecf20Sopenharmony_ci else 2758c2ecf20Sopenharmony_ci break; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (val >= base) 2788c2ecf20Sopenharmony_ci break; 2798c2ecf20Sopenharmony_ci /* 2808c2ecf20Sopenharmony_ci * Check for overflow only if we are within range of 2818c2ecf20Sopenharmony_ci * it in the max base we support (16) 2828c2ecf20Sopenharmony_ci */ 2838c2ecf20Sopenharmony_ci if (unlikely(res & (~0ull << 60))) { 2848c2ecf20Sopenharmony_ci if (res > __div_u64(ULLONG_MAX - val, base)) 2858c2ecf20Sopenharmony_ci rv |= KSTRTOX_OVERFLOW; 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci res = res * base + val; 2888c2ecf20Sopenharmony_ci rv++; 2898c2ecf20Sopenharmony_ci s++; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci *p = res; 2928c2ecf20Sopenharmony_ci return rv; 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci unsigned long long _res; 2988c2ecf20Sopenharmony_ci unsigned int rv; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci s = _parse_integer_fixup_radix(s, &base); 3018c2ecf20Sopenharmony_ci rv = _parse_integer(s, base, &_res); 3028c2ecf20Sopenharmony_ci if (rv & KSTRTOX_OVERFLOW) 3038c2ecf20Sopenharmony_ci return -ERANGE; 3048c2ecf20Sopenharmony_ci if (rv == 0) 3058c2ecf20Sopenharmony_ci return -EINVAL; 3068c2ecf20Sopenharmony_ci s += rv; 3078c2ecf20Sopenharmony_ci if (*s == '\n') 3088c2ecf20Sopenharmony_ci s++; 3098c2ecf20Sopenharmony_ci if (*s) 3108c2ecf20Sopenharmony_ci return -EINVAL; 3118c2ecf20Sopenharmony_ci *res = _res; 3128c2ecf20Sopenharmony_ci return 0; 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci/** 3168c2ecf20Sopenharmony_ci * kstrtoull - convert a string to an unsigned long long 3178c2ecf20Sopenharmony_ci * @s: The start of the string. The string must be null-terminated, and may also 3188c2ecf20Sopenharmony_ci * include a single newline before its terminating null. The first character 3198c2ecf20Sopenharmony_ci * may also be a plus sign, but not a minus sign. 3208c2ecf20Sopenharmony_ci * @base: The number base to use. The maximum supported base is 16. If base is 3218c2ecf20Sopenharmony_ci * given as 0, then the base of the string is automatically detected with the 3228c2ecf20Sopenharmony_ci * conventional semantics - If it begins with 0x the number will be parsed as a 3238c2ecf20Sopenharmony_ci * hexadecimal (case insensitive), if it otherwise begins with 0, it will be 3248c2ecf20Sopenharmony_ci * parsed as an octal number. Otherwise it will be parsed as a decimal. 3258c2ecf20Sopenharmony_ci * @res: Where to write the result of the conversion on success. 3268c2ecf20Sopenharmony_ci * 3278c2ecf20Sopenharmony_ci * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. 3288c2ecf20Sopenharmony_ci * Used as a replacement for the obsolete simple_strtoull. Return code must 3298c2ecf20Sopenharmony_ci * be checked. 3308c2ecf20Sopenharmony_ci */ 3318c2ecf20Sopenharmony_ciint kstrtoull(const char *s, unsigned int base, unsigned long long *res) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci if (s[0] == '+') 3348c2ecf20Sopenharmony_ci s++; 3358c2ecf20Sopenharmony_ci return _kstrtoull(s, base, res); 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic int _kstrtoul(const char *s, unsigned int base, unsigned long *res) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci unsigned long long tmp; 3418c2ecf20Sopenharmony_ci int rv; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci rv = kstrtoull(s, base, &tmp); 3448c2ecf20Sopenharmony_ci if (rv < 0) 3458c2ecf20Sopenharmony_ci return rv; 3468c2ecf20Sopenharmony_ci if (tmp != (unsigned long)tmp) 3478c2ecf20Sopenharmony_ci return -ERANGE; 3488c2ecf20Sopenharmony_ci *res = tmp; 3498c2ecf20Sopenharmony_ci return 0; 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci/** 3538c2ecf20Sopenharmony_ci * kstrtoul - convert a string to an unsigned long 3548c2ecf20Sopenharmony_ci * @s: The start of the string. The string must be null-terminated, and may also 3558c2ecf20Sopenharmony_ci * include a single newline before its terminating null. The first character 3568c2ecf20Sopenharmony_ci * may also be a plus sign, but not a minus sign. 3578c2ecf20Sopenharmony_ci * @base: The number base to use. The maximum supported base is 16. If base is 3588c2ecf20Sopenharmony_ci * given as 0, then the base of the string is automatically detected with the 3598c2ecf20Sopenharmony_ci * conventional semantics - If it begins with 0x the number will be parsed as a 3608c2ecf20Sopenharmony_ci * hexadecimal (case insensitive), if it otherwise begins with 0, it will be 3618c2ecf20Sopenharmony_ci * parsed as an octal number. Otherwise it will be parsed as a decimal. 3628c2ecf20Sopenharmony_ci * @res: Where to write the result of the conversion on success. 3638c2ecf20Sopenharmony_ci * 3648c2ecf20Sopenharmony_ci * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. 3658c2ecf20Sopenharmony_ci * Used as a replacement for the simple_strtoull. 3668c2ecf20Sopenharmony_ci */ 3678c2ecf20Sopenharmony_ciint boot_kstrtoul(const char *s, unsigned int base, unsigned long *res) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci /* 3708c2ecf20Sopenharmony_ci * We want to shortcut function call, but 3718c2ecf20Sopenharmony_ci * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0. 3728c2ecf20Sopenharmony_ci */ 3738c2ecf20Sopenharmony_ci if (sizeof(unsigned long) == sizeof(unsigned long long) && 3748c2ecf20Sopenharmony_ci __alignof__(unsigned long) == __alignof__(unsigned long long)) 3758c2ecf20Sopenharmony_ci return kstrtoull(s, base, (unsigned long long *)res); 3768c2ecf20Sopenharmony_ci else 3778c2ecf20Sopenharmony_ci return _kstrtoul(s, base, res); 3788c2ecf20Sopenharmony_ci} 379