Merge patch series "some string cleanup, and a tweak of the "config" command"

Rasmus Villemoes <rv@rasmusvillemoes.dk> says:

This started by me wanting something like what patch 8 does. That
wasn't too hard, except we had no strcasestr(), and also our regex
engine (which I didn't really want to pull into the mix anyway)
doesn't have a flag that requests case-insensitive matching. So I
wanted to add strcasestr(), but then I stumbled on a bunch of stuff
that should be cleaned up in str-land.

Link: https://lore.kernel.org/r/20260708203711.849489-1-rv@rasmusvillemoes.dk
This commit is contained in:
Tom Rini
2026-07-21 13:52:00 -06:00
8 changed files with 146 additions and 107 deletions
-51
View File
@@ -8,8 +8,6 @@
* from linux kernel code.
*/
#ifdef __KERNEL__ /* only set these up for kernel code */
#define __HAVE_ARCH_STRCPY
static inline char *strcpy(char *__dest, const char *__src)
{
@@ -81,53 +79,4 @@ static inline int strcmp(const char *__cs, const char *__ct)
return __res;
}
#undef __HAVE_ARCH_STRNCMP
extern int strncmp(const char *__cs, const char *__ct, size_t __n);
#undef __HAVE_ARCH_MEMSET
extern void *memset(void *__s, int __c, size_t __count);
#undef __HAVE_ARCH_MEMCPY
extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
#undef __HAVE_ARCH_MEMMOVE
extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
#undef __HAVE_ARCH_MEMCHR
extern void *memchr(const void *__s, int __c, size_t __n);
#undef __HAVE_ARCH_STRLEN
extern size_t strlen(const char *);
/* arch/sh/lib/strcasecmp.c */
extern int strcasecmp(const char *, const char *);
#else /* KERNEL */
/*
* let user libraries deal with these,
* IMHO the kernel has no place defining these functions for user apps
*/
#define __HAVE_ARCH_STRCPY 1
#define __HAVE_ARCH_STRNCPY 1
#define __HAVE_ARCH_STRCAT 1
#define __HAVE_ARCH_STRNCAT 1
#define __HAVE_ARCH_STRCMP 1
#define __HAVE_ARCH_STRNCMP 1
#define __HAVE_ARCH_STRNICMP 1
#define __HAVE_ARCH_STRCHR 1
#define __HAVE_ARCH_STRRCHR 1
#define __HAVE_ARCH_STRSTR 1
#define __HAVE_ARCH_STRLEN 1
#define __HAVE_ARCH_STRNLEN 1
#define __HAVE_ARCH_MEMSET 1
#define __HAVE_ARCH_MEMCPY 1
#define __HAVE_ARCH_MEMMOVE 1
#define __HAVE_ARCH_MEMSCAN 1
#define __HAVE_ARCH_MEMCMP 1
#define __HAVE_ARCH_MEMCHR 1
#define __HAVE_ARCH_STRTOK 1
#endif /* KERNEL */
#endif /* __ASM_SH_STRING_H */
+23 -3
View File
@@ -6,6 +6,7 @@
#include <command.h>
#include <gzip.h>
#include <malloc.h>
#include <linux/string.h>
#include "config_data_gz.h"
#include "config_data_size.h"
@@ -29,7 +30,23 @@ static int do_config(struct cmd_tbl *cmdtp, int flag, int argc,
}
dst[data_size] = 0;
puts(dst);
if (argc > 1) {
const char *s = argv[1];
char *b = dst, *e = dst + data_size, *n;
while (b < e) {
n = strchrnul(b, '\n');
*n = '\0';
if (strcasestr(b, s)) {
puts(b);
puts("\n");
}
b = n + 1;
}
} else {
puts(dst);
}
free:
free(dst);
@@ -38,7 +55,10 @@ free:
}
U_BOOT_CMD(
config, 1, 1, do_config,
config, 2, 1, do_config,
"print .config",
""
"[str]\n"
"\n"
"When the optional argument is given, only lines containing\n"
"that string are printed. Matching is case-insensitive."
);
+40
View File
@@ -0,0 +1,40 @@
.. SPDX-License-Identifier: GPL-2.0
.. index::
single: config (command)
config command
==============
Synopsis
--------
::
config [<str>]
Description
-----------
The config command prints the `.config` file used when building U-Boot
to the console. Note that the `.config` file is usually several 1000
lines long.
If the optional argument is given, only lines containing that string
(case insensitively) are printed. That can be useful if one wants to
check whether a specific option is enabled, or just to limit the
output to the subsystem of interest.
The `.config` file is stored inside the U-Boot binary in
gzip-compressed format.
Examples
--------
.. code-block:: bash
# Print the entire .config
config
# Print all lines related to pinctrl
config pinctrl
+3 -10
View File
@@ -43,12 +43,8 @@ extern int strcmp(const char *,const char *);
#ifndef __HAVE_ARCH_STRNCMP
extern int strncmp(const char *,const char *,__kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRCASECMP
int strcasecmp(const char *s1, const char *s2);
#endif
#ifndef __HAVE_ARCH_STRNCASECMP
extern int strncasecmp(const char *s1, const char *s2, __kernel_size_t len);
#endif
int strncasecmp(const char *s1, const char *s2, __kernel_size_t len);
#ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int);
#endif
@@ -63,7 +59,7 @@ extern char * strchr(const char *,int);
* @c: character to search for
* Return: position of @c in @s, or end of @s if not found
*/
const char *strchrnul(const char *s, int c);
char *strchrnul(const char *s, int c);
#ifndef __HAVE_ARCH_STRRCHR
extern char * strrchr(const char *,int);
@@ -75,6 +71,7 @@ extern char * strstr(const char *,const char *);
#ifndef __HAVE_ARCH_STRNSTR
extern char *strnstr(const char *, const char *, size_t);
#endif
char *strcasestr(const char *, const char *);
#ifndef __HAVE_ARCH_STRLEN
extern __kernel_size_t strlen(const char *);
#endif
@@ -107,10 +104,6 @@ extern char * strndup(const char *, size_t);
extern const char *strdup_const(const char *s);
extern void kfree_const(const void *x);
#ifndef __HAVE_ARCH_STRSWAB
extern char * strswab(const char *);
#endif
#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,__kernel_size_t);
#endif
+30 -40
View File
@@ -263,12 +263,12 @@ char * strchr(const char * s, int c)
}
#endif
const char *strchrnul(const char *s, int c)
char *strchrnul(const char *s, int c)
{
for (; *s != (char)c; ++s)
if (*s == '\0')
break;
return s;
return (char *)s;
}
#ifndef __HAVE_ARCH_STRRCHR
@@ -399,7 +399,6 @@ void kfree_const(const void *x)
}
#ifndef __HAVE_ARCH_STRSPN
/**
* strspn - Calculate the length of the initial substring of @s which only
* contain letters in @accept
@@ -424,9 +423,7 @@ size_t strspn(const char *s, const char *accept)
return count;
}
#endif
#ifndef __HAVE_ARCH_STRPBRK
/**
* strpbrk - Find the first occurrence of a set of characters
* @cs: The string to be searched
@@ -444,9 +441,7 @@ char * strpbrk(const char * cs,const char * ct)
}
return NULL;
}
#endif
#ifndef __HAVE_ARCH_STRTOK
/**
* strtok - Split a string into tokens
* @s: The string to be searched
@@ -473,9 +468,7 @@ char * strtok(char * s,const char * ct)
___strtok = send;
return (sbegin);
}
#endif
#ifndef __HAVE_ARCH_STRSEP
/**
* strsep - Split a string into tokens
* @s: The string to be searched
@@ -501,35 +494,6 @@ char * strsep(char **s, const char *ct)
return sbegin;
}
#endif
#ifndef __HAVE_ARCH_STRSWAB
/**
* strswab - swap adjacent even and odd bytes in %NUL-terminated string
* s: address of the string
*
* returns the address of the swapped string or NULL on error. If
* string length is odd, last byte is untouched.
*/
char *strswab(const char *s)
{
char *p, *q;
if ((NULL == s) || ('\0' == *s)) {
return (NULL);
}
for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) {
char tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
return (char *) s;
}
#endif
#ifndef __HAVE_ARCH_MEMSET
/**
@@ -702,7 +666,7 @@ void *memdup(const void *src, size_t len)
*
* @s1: string to be searched
* @s2: string to search for
* @len: maximum number of characters in s2 to consider
* @len: maximum number of characters in s1 to consider
*
* Return: pointer to the first occurrence or NULL
*/
@@ -728,7 +692,6 @@ char *strnstr(const char *s1, const char *s2, size_t len)
*
* @s1: string to be searched
* @s2: string to search for
* @len: maximum number of characters in s2 to consider
*
* Return: pointer to the first occurrence or NULL
*/
@@ -738,6 +701,33 @@ char *strstr(const char *s1, const char *s2)
}
#endif
/**
* strcasestr() - Case insensitive substring search
*
* @haystack: string to be searched
* @needle: string to search for
*
* Return: pointer to the first occurrence or NULL
*
* The case of both strings are ignored.
*/
char *strcasestr(const char *haystack, const char *needle)
{
size_t l1, l2;
l1 = strlen(haystack);
l2 = strlen(needle);
while (l1 >= l2) {
if (!strncasecmp(haystack, needle, l2))
return (char *)haystack;
haystack++;
l1--;
}
return NULL;
}
#ifndef __HAVE_ARCH_MEMCHR
/**
* memchr - Find a character in an area of memory.
+1
View File
@@ -17,6 +17,7 @@ ifdef CONFIG_CONSOLE_RECORD
obj-$(CONFIG_CMD_ACPI) += acpi.o
endif
obj-$(CONFIG_CMD_BDI) += bdinfo.o
obj-$(CONFIG_CMD_CONFIG) += config.o
obj-$(CONFIG_COREBOOT_SYSINFO) += coreboot.o
obj-$(CONFIG_CMD_FDT) += fdt.o
obj-$(CONFIG_CMD_HASH) += hash.o
+28
View File
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Tests for config command
*/
#include <console.h>
#include <test/cmd.h>
#include <test/ut.h>
static int cmd_test_config(struct unit_test_state *uts)
{
ut_assertok(run_command("config", 0));
ut_assert_skip_to_line("# Automatically generated file; DO NOT EDIT.");
ut_assert_skip_to_linen("# Compiler:");
ut_assert_skip_to_line("CONFIG_CMD_CONFIG=y");
console_record_reset_enable();
ut_assertok(run_command("config cmd_config=y", 0));
ut_assert_nextline("CONFIG_CMD_CONFIG=y");
ut_assert_console_end();
ut_assertok(run_command("config 'this string never appears in .config'", 0));
ut_assert_console_end();
return 0;
}
CMD_TEST(cmd_test_config, UTF_CONSOLE);
+21 -3
View File
@@ -284,18 +284,36 @@ static int lib_strstr(struct unit_test_state *uts)
{
const char *s1 = "Itsy Bitsy Teenie Weenie";
const char *s2 = "eenie";
const char *s3 = "easy";
const char *s3 = "bits";
ut_asserteq_ptr(&s1[12], strstr(s1, s2));
ut_asserteq_ptr(&s1[13], strstr(&s1[3], &s2[1]));
ut_assertnull(strstr(s1, s3));
ut_asserteq_ptr(&s1[2], strstr(s1, &s3[2]));
ut_asserteq_ptr(&s1[8], strstr(&s1[5], &s3[2]));
ut_asserteq_ptr(&s1[1], strstr(s1, &s3[2]));
ut_asserteq_ptr(&s1[7], strstr(&s1[5], &s3[2]));
return 0;
}
LIB_TEST(lib_strstr, 0);
/** lib_strcasestr() - unit test for strcasestr() */
static int lib_strcasestr(struct unit_test_state *uts)
{
const char *s1 = "Itsy Bitsy Teenie Weenie";
const char *s2 = "eenie";
const char *s3 = "bits";
ut_asserteq_ptr(&s1[12], strcasestr(s1, s2));
ut_asserteq_ptr(&s1[13], strcasestr(&s1[3], &s2[1]));
ut_asserteq_ptr(&s1[5], strcasestr(s1, s3));
ut_asserteq_ptr(&s1[1], strcasestr(s1, &s3[2]));
ut_asserteq_ptr(&s1[7], strcasestr(&s1[5], &s3[2]));
ut_assertnull(strcasestr(&s1[6], s3));
return 0;
}
LIB_TEST(lib_strcasestr, 0);
static int lib_strim(struct unit_test_state *uts)
{
char buf[BUFLEN], *p;