xref: /kernel/linux/linux-6.6/arch/s390/boot/string.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/ctype.h>
362306a36Sopenharmony_ci#include <linux/kernel.h>
462306a36Sopenharmony_ci#include <linux/errno.h>
562306a36Sopenharmony_ci#undef CONFIG_KASAN
662306a36Sopenharmony_ci#undef CONFIG_KASAN_GENERIC
762306a36Sopenharmony_ci#include "../lib/string.c"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciint strncmp(const char *cs, const char *ct, size_t count)
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	unsigned char c1, c2;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci	while (count) {
1462306a36Sopenharmony_ci		c1 = *cs++;
1562306a36Sopenharmony_ci		c2 = *ct++;
1662306a36Sopenharmony_ci		if (c1 != c2)
1762306a36Sopenharmony_ci			return c1 < c2 ? -1 : 1;
1862306a36Sopenharmony_ci		if (!c1)
1962306a36Sopenharmony_ci			break;
2062306a36Sopenharmony_ci		count--;
2162306a36Sopenharmony_ci	}
2262306a36Sopenharmony_ci	return 0;
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cichar *skip_spaces(const char *str)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	while (isspace(*str))
2862306a36Sopenharmony_ci		++str;
2962306a36Sopenharmony_ci	return (char *)str;
3062306a36Sopenharmony_ci}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cichar *strim(char *s)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	size_t size;
3562306a36Sopenharmony_ci	char *end;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	size = strlen(s);
3862306a36Sopenharmony_ci	if (!size)
3962306a36Sopenharmony_ci		return s;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	end = s + size - 1;
4262306a36Sopenharmony_ci	while (end >= s && isspace(*end))
4362306a36Sopenharmony_ci		end--;
4462306a36Sopenharmony_ci	*(end + 1) = '\0';
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	return skip_spaces(s);
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* Works only for digits and letters, but small and fast */
5062306a36Sopenharmony_ci#define TOLOWER(x) ((x) | 0x20)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic unsigned int simple_guess_base(const char *cp)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	if (cp[0] == '0') {
5562306a36Sopenharmony_ci		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
5662306a36Sopenharmony_ci			return 16;
5762306a36Sopenharmony_ci		else
5862306a36Sopenharmony_ci			return 8;
5962306a36Sopenharmony_ci	} else {
6062306a36Sopenharmony_ci		return 10;
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/**
6562306a36Sopenharmony_ci * simple_strtoull - convert a string to an unsigned long long
6662306a36Sopenharmony_ci * @cp: The start of the string
6762306a36Sopenharmony_ci * @endp: A pointer to the end of the parsed string will be placed here
6862306a36Sopenharmony_ci * @base: The number base to use
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciunsigned long long simple_strtoull(const char *cp, char **endp,
7262306a36Sopenharmony_ci				   unsigned int base)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	unsigned long long result = 0;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	if (!base)
7762306a36Sopenharmony_ci		base = simple_guess_base(cp);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
8062306a36Sopenharmony_ci		cp += 2;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	while (isxdigit(*cp)) {
8362306a36Sopenharmony_ci		unsigned int value;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
8662306a36Sopenharmony_ci		if (value >= base)
8762306a36Sopenharmony_ci			break;
8862306a36Sopenharmony_ci		result = result * base + value;
8962306a36Sopenharmony_ci		cp++;
9062306a36Sopenharmony_ci	}
9162306a36Sopenharmony_ci	if (endp)
9262306a36Sopenharmony_ci		*endp = (char *)cp;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	return result;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cilong simple_strtol(const char *cp, char **endp, unsigned int base)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	if (*cp == '-')
10062306a36Sopenharmony_ci		return -simple_strtoull(cp + 1, endp, base);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	return simple_strtoull(cp, endp, base);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ciint kstrtobool(const char *s, bool *res)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	if (!s)
10862306a36Sopenharmony_ci		return -EINVAL;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	switch (s[0]) {
11162306a36Sopenharmony_ci	case 'y':
11262306a36Sopenharmony_ci	case 'Y':
11362306a36Sopenharmony_ci	case '1':
11462306a36Sopenharmony_ci		*res = true;
11562306a36Sopenharmony_ci		return 0;
11662306a36Sopenharmony_ci	case 'n':
11762306a36Sopenharmony_ci	case 'N':
11862306a36Sopenharmony_ci	case '0':
11962306a36Sopenharmony_ci		*res = false;
12062306a36Sopenharmony_ci		return 0;
12162306a36Sopenharmony_ci	case 'o':
12262306a36Sopenharmony_ci	case 'O':
12362306a36Sopenharmony_ci		switch (s[1]) {
12462306a36Sopenharmony_ci		case 'n':
12562306a36Sopenharmony_ci		case 'N':
12662306a36Sopenharmony_ci			*res = true;
12762306a36Sopenharmony_ci			return 0;
12862306a36Sopenharmony_ci		case 'f':
12962306a36Sopenharmony_ci		case 'F':
13062306a36Sopenharmony_ci			*res = false;
13162306a36Sopenharmony_ci			return 0;
13262306a36Sopenharmony_ci		default:
13362306a36Sopenharmony_ci			break;
13462306a36Sopenharmony_ci		}
13562306a36Sopenharmony_ci	default:
13662306a36Sopenharmony_ci		break;
13762306a36Sopenharmony_ci	}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	return -EINVAL;
14062306a36Sopenharmony_ci}
141