From: WanBingjiang Date: Mon, 27 Apr 2026 06:51:25 +0000 (+0800) Subject: bits: add --expand option to output individual bit IDs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8033c13501b504d938dad3ebc7fcaccb67c61d63;p=thirdparty%2Futil-linux.git bits: add --expand option to output individual bit IDs Add -e/--expand output mode that prints each set bit as a comma-separated list without range compression. This is useful for scripting when individual IDs are needed (e.g., CPU ID iteration). Example: bits --expand 1,3-5,7 → 1,3,4,5,7 Signed-off-by: WanBingjiang --- diff --git a/include/cpuset.h b/include/cpuset.h index 119c1a04c..dbdbe691e 100644 --- a/include/cpuset.h +++ b/include/cpuset.h @@ -93,6 +93,7 @@ extern cpu_set_t *cpuset_alloc(int ncpus, size_t *setsize, size_t *nbits); extern void cpuset_free(cpu_set_t *set); extern char *cpulist_create(char *str, size_t len, cpu_set_t *set, size_t setsize); +extern char *cpulist_flat_create(char *str, size_t len, cpu_set_t *set, size_t setsize); extern int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail); extern char *cpumask_create(char *str, size_t len, cpu_set_t *set, size_t setsize); diff --git a/lib/cpuset.c b/lib/cpuset.c index c5679888e..aba5d5056 100644 --- a/lib/cpuset.c +++ b/lib/cpuset.c @@ -220,6 +220,38 @@ char *cpulist_create(char *str, size_t len, return str; } +/* + * cpulist_flat_create - Convert cpumask to flat comma-separated list + * Output: ONLY single CPUs, NO ranges (e.g. "0,1,2,3,4") + */ +char *cpulist_flat_create(char *str, size_t len, + cpu_set_t *set, size_t setsize) +{ + char *ptr = str; + int entry_made = 0; + size_t max = cpuset_nbits(setsize); + size_t cpu; + int rlen; + + for (cpu = 0; cpu < max; cpu++) { + if (!CPU_ISSET_S(cpu, setsize, set)) + continue; + + rlen = snprintf(ptr, len, "%zu,", cpu); + if (rlen < 0 || (size_t)rlen >= len) + return NULL; + + ptr += rlen; + len -= rlen; + entry_made = 1; + } + ptr -= entry_made; + *ptr = '\0'; + + return str; +} + + /* * Returns string with CPU mask. */ diff --git a/text-utils/bits.1.adoc b/text-utils/bits.1.adoc index 770ad363e..534bcf0e9 100644 --- a/text-utils/bits.1.adoc +++ b/text-utils/bits.1.adoc @@ -91,6 +91,9 @@ Print the combined arguments as a binary mask value. Print the combined arguments as a hexadecimal mask value in 32-bit comma-separated groups. +*-e*, *--expand*:: +Print the combined arguments as a list of individual bit IDs. + *-l*, *--list*:: Print the combined arguments as a list of bit IDs. Consecutive IDs are compressed to ranges. @@ -122,6 +125,9 @@ Print the combined arguments as a hexadecimal mask value (default). ~$ bits --grouped-mask 2,22,74,79 8400,00000000,00400004 +~$ bits --expand 1,3-5,7 +1,3,4,5,7 + ~$ bits --width 64 --list 2,22,74,79 2,22 .... diff --git a/text-utils/bits.c b/text-utils/bits.c index dbeaa09b7..9b55583b3 100644 --- a/text-utils/bits.c +++ b/text-utils/bits.c @@ -110,6 +110,7 @@ static size_t num_digits(size_t value) enum output_mode { MODE_BINARY, + MODE_EXPAND, MODE_GROUPED_MASK, MODE_LIST, MODE_MASK, @@ -134,6 +135,7 @@ static void print_bits(cpu_set_t *bits, size_t width, enum output_mode mode) case MODE_BINARY: printf("0b0\n"); break; + case MODE_EXPAND: case MODE_LIST: break; } @@ -189,13 +191,14 @@ static void print_bits(cpu_set_t *bits, size_t width, enum output_mode mode) printf("\n"); break; + case MODE_EXPAND: case MODE_LIST: - /* Maximum number of digits (larger bit number) plus 1 - * to account for a separating comma, times the number of bits - * set to 1. */ buf_size = (num_digits(width - 1) + 1) * CPU_COUNT_S(size, bits); buf = xmalloc(buf_size); - cpulist_create(buf, buf_size, bits, size); + if (mode == MODE_EXPAND) + cpulist_flat_create(buf, buf_size, bits, size); + else + cpulist_create(buf, buf_size, bits, size); printf("%s\n", buf); break; } @@ -233,6 +236,7 @@ static void __attribute__((__noreturn__)) usage(void) " comma separated groups"), stdout); fputsln(_(" -b, --binary display bits as a binary mask value"), stdout); + fputsln(_(" -e, --expand display bits as an expanded list of bit IDs"), stdout); fputsln(_(" -l, --list display bits as a compressed list of bit IDs"), stdout); @@ -249,7 +253,7 @@ int main(int argc, char **argv) size_t alloc_size; int c; -#define FLAGS "Vhw:mgbl" +#define FLAGS "Vhw:mgble" static const struct option longopts[] = { { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, @@ -257,6 +261,7 @@ int main(int argc, char **argv) { "mask", no_argument, NULL, 'm' }, { "grouped-mask", no_argument, NULL, 'g' }, { "binary", no_argument, NULL, 'b' }, + { "expand", no_argument, NULL, 'e' }, { "list", no_argument, NULL, 'l' }, { NULL, 0, NULL, 0 } }; @@ -277,6 +282,9 @@ int main(int argc, char **argv) case 'b': mode = MODE_BINARY; break; + case 'e': + mode = MODE_EXPAND; + break; case 'l': mode = MODE_LIST; break;