]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
bits: add --expand option to output individual bit IDs
authorWanBingjiang <wanbingjiang@webray.com.cn>
Mon, 27 Apr 2026 06:51:25 +0000 (14:51 +0800)
committerWanBingjiang <wanbingjiang@webray.com.cn>
Wed, 29 Apr 2026 01:48:11 +0000 (09:48 +0800)
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 <wanbingjiang@webray.com.cn>
include/cpuset.h
lib/cpuset.c
text-utils/bits.1.adoc
text-utils/bits.c

index 119c1a04c6f79e50a98cadc391367be7850f4b27..dbdbe691e968ea2915b197e21f5ea0c632c47cff 100644 (file)
@@ -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);
index c5679888ed57a7e9188ff9df857823ba8c6d7de8..aba5d5056b3a13050e9aa7d5bdaba397fdd8a2ca 100644 (file)
@@ -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.
  */
index 770ad363e9d8cb463e504109983ae888f9b1f5c1..534bcf0e976260a545ee350aa84a1af2266ec0cf 100644 (file)
@@ -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
 ....
index dbeaa09b765c57fc9083a0ad32b0cd4e7a97f200..9b55583b306e01ac8d607e72aba5e4c75353de60 100644 (file)
@@ -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;