All of lore.kernel.org
 help / color / mirror / Atom feed
From: Elliott Mitchell <ehem+xen@m5p.com>
To: xen-devel@lists.xenproject.org
Cc: Ian Jackson <iwj@xenproject.org>
Cc: Wei Liu <wl@xen.org>
Cc: Anthony PERARD <anthony.perard@citrix.com>
Subject: [WIP PATCH 09/16] WIP: tools/xl: Implement generalized output formatting for `xl list`
Date: Thu, 10 Dec 2020 15:09:06 -0800	[thread overview]
Message-ID: <b0211ac6542435ac2a2987e1e573150c21b1d719.1608663694.git.ehem+xen@m5p.com> (raw)
In-Reply-To: <cover.1608663694.git.ehem+xen@m5p.com>

Implement a generalized output formatting function for the `xl list`
subcommands.  Notably `xl list` and `xl vm-list` could make use of
alternative output list formats.

Signed-off-by: Elliott Mitchell <ehem+xen@m5p.com>
---
I'm a bit unsure of #include <xen-tools/libs.h>.  When looking for an
implementation of ARRAY_SIZE(), that was the header I found.  I can
readily write it myself, but rather than inlining, I looked for a copy in
a header and found that.
---
 tools/xl/xl_list.c | 285 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 285 insertions(+)

diff --git a/tools/xl/xl_list.c b/tools/xl/xl_list.c
index e30536fd9a..1c04f2126b 100644
--- a/tools/xl/xl_list.c
+++ b/tools/xl/xl_list.c
@@ -14,10 +14,14 @@
 
 #define _GNU_SOURCE
 
+#include <ctype.h>
 #include <inttypes.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <unistd.h>
 
+#include <xen-tools/libs.h>
+
 #include <libxl.h>
 #include <libxl_utils.h>
 
@@ -25,6 +29,287 @@
 #include "xl_utils.h"
 
 
+struct format_entry;
+
+typedef void (format_function_t)(const struct format_entry *,
+                                 const void *, const char *, size_t);
+
+typedef struct format_entry {
+    char *const header;
+    char formatc[3];
+    format_function_t *formatf;
+    ptrdiff_t offset;
+    union {
+        int i;
+        unsigned long lu;
+        float f;
+        void *v;
+        char *(*xlfunc)(libxl_ctx *, uint32_t);
+    } extra;
+} format_table_t['z' - 'A' + 1];
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+static void format_normal(const struct format_entry *entry,
+                          const void *info, const char *format,
+                          size_t len)
+{
+    char *buf = alloca(len + 3);
+    memcpy(buf, format, len);
+    if (info) {
+        const char *str;
+        int i;
+        unsigned long lu;
+        float f;
+        strcpy(buf + len, entry->formatc);
+        switch (entry->formatc[0]) {
+        case 's':
+            str = ((char **)info)[entry->offset];
+            if (!str) str = "-";
+            printf(buf, str);
+            break;
+        case 'f':
+            f = ((float *)info)[entry->offset];
+            if (entry->extra.f != 0) f /= entry->extra.f;
+            printf(buf, f);
+            break;
+        case 'l':
+            lu = ((unsigned long *)info)[entry->offset];
+            if (entry->extra.lu) lu /= entry->extra.lu;
+            printf(buf, lu);
+            break;
+        case 'd':
+        default:
+            i = ((int *)info)[entry->offset];
+            if (entry->extra.i) i /= entry->extra.i;
+            printf(buf, i);
+            break;
+        }
+    } else {
+        if (entry->formatc[0] == 'f') {
+            char *tmp;
+            buf[len] = '\0';
+            if ((tmp = rindex(buf, '.')))
+                len = tmp - buf - 1;
+        }
+        strcpy(buf + len, "s");
+        printf(buf, entry->header);
+    }
+}
+
+static void format_allocstr(const struct format_entry *entry,
+                            const void *info, const char *format,
+                            size_t len)
+{
+    char *fmt = alloca(len + 2);
+    char *outbuf;
+    memcpy(fmt, format, len);
+    strcpy(fmt + len, "s");
+
+    if (info) {
+        outbuf = entry->extra.xlfunc(ctx, ((uint32_t *)info)[entry->offset]);
+        printf(fmt, outbuf);
+        free(outbuf);
+    } else printf(fmt, entry->header);
+}
+
+static void format_uuid(const struct format_entry *entry,
+                        const void *info, const char *format,
+                        size_t len)
+{
+    if (info) printf(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(*(libxl_uuid *)((char *)info + entry->offset)));
+    else fputs(entry->header, stdout);
+}
+
+static void format_time(const struct format_entry *entry,
+                        const void *_info, const char *format,
+                        size_t len)
+{
+    const libxl_dominfo *info = _info;
+    char *fmt = alloca(len + 2);
+    memcpy(fmt, format, len);
+
+    if (info) {
+        strcpy(fmt + len, "f");
+        printf(fmt, ((float)info->cpu_time / 1e9));
+    } else {
+        char *tmp;
+        if (!(tmp = index(fmt, '.'))) tmp = fmt + len;
+        strcpy(tmp, "s");
+        printf(fmt, entry->header);
+    }
+}
+
+static void format_state(const struct format_entry *entry,
+                         const void *_info, const char *format,
+                         size_t len)
+{
+    const libxl_dominfo *info = _info;
+    if (info) {
+        const char shutdown_reason_letters[] = "-rscwS";
+        libxl_shutdown_reason shutdown_reason;
+        static const char letters[] = "rbps";
+        int i;
+	const bool *flags;
+
+	flags = &info->running;
+        for (i = 0; i < strlen(letters); ++i)
+            putchar(flags[i] ? letters[i] : '-');
+
+        shutdown_reason = info->shutdown ? info->shutdown_reason : 0;
+        putchar((shutdown_reason >= 0 &&
+            shutdown_reason < sizeof(shutdown_reason_letters)-1
+            ? shutdown_reason_letters[shutdown_reason] : '?'));
+
+        putchar(info->dying ? 'd' : '-');
+    } else printf("%6s", entry->header);
+}
+
+static void format_reason(const struct format_entry *entry,
+                          const void *_info, const char *format,
+                          size_t len)
+{
+    const libxl_dominfo *info = _info;
+    const char *output = entry->header;
+    if (info) {
+        if (info->shutdown) {
+            printf("%8x", info->shutdown_reason);
+            return;
+        }
+        output = "-";
+    }
+    printf("%8s", output);
+}
+
+static void format_memory(const struct format_entry *entry,
+                          const void *_info, const char *format,
+                          size_t len)
+{
+    const libxl_dominfo *info = _info;
+    char *fmt = alloca(len + 3);
+    memcpy(fmt, format, len);
+    if (info) {
+        strcpy(fmt + len, entry->formatc);
+        printf(fmt, (info->current_memkb + info->outstanding_memkb) >> 10);
+    } else {
+        strcpy(fmt + len, "s");
+        printf(fmt, "Mem");
+    }
+}
+
+static void format_node(const struct format_entry *entry,
+                        const void *_info, const char *format,
+                        size_t len)
+{
+    const libxl_dominfo *info = _info;
+    static bool need_init = true;
+    static libxl_bitmap nodemap;
+    static libxl_physinfo physinfo;
+
+    if (need_init) {
+        libxl_bitmap_init(&nodemap);
+        libxl_physinfo_init(&physinfo);
+        need_init = false;
+
+        if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
+            fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
+            exit(EXIT_FAILURE);
+        }
+        if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+            fprintf(stderr, "libxl_physinfo failed.\n");
+            libxl_bitmap_dispose(&nodemap);
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (info) {
+        libxl_domain_get_nodeaffinity(ctx, info->domid, &nodemap);
+
+        putchar(' ');
+        print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
+    } else fputs(entry->header, stdout);
+
+#if 0
+    /* unfortunately these get leaked on exit */
+    libxl_bitmap_dispose(&nodemap);
+    libxl_physinfo_dispose(&physinfo);
+#endif
+}
+
+#pragma GCC diagnostic pop
+
+static bool isfmtchar(int c)
+{
+    const bool opts[] = {
+        ['0'] = true,
+        ['1'] = true,
+        ['2'] = true,
+        ['3'] = true,
+        ['4'] = true,
+        ['5'] = true,
+        ['6'] = true,
+        ['7'] = true,
+        ['8'] = true,
+        ['9'] = true,
+        ['.'] = true,
+        ['#'] = true,
+        ['-'] = true,
+        ['+'] = true,
+        [' '] = true,
+        ['\''] = true,
+    };
+    if ((unsigned int)c < ARRAY_SIZE(opts) && opts[c]) return true;
+    else return false;
+}
+
+static void format(const format_table_t fmttab, const char *fmt,
+                   const void *info)
+{
+    while (fmt[0]) {
+        if (fmt[0] == '\\') {
+            switch (fmt[1]) {
+            case 0:
+                /* Uhm... */
+                return;
+            case '0':
+                putchar(0);
+                break;
+            case 'n':
+                fputs("\n", stdout);
+                break;
+            case 't':
+                putchar('\t');
+                break;
+            default:
+                putchar(fmt[1]);
+            }
+            fmt+=2;
+        } else if (fmt[0] == '%') {
+            size_t len=1;
+            unsigned char entryn;
+
+            while (isfmtchar(fmt[len])) ++len;
+
+            entryn = fmt[len] - 'A';
+            if (entryn < sizeof(format_table_t) / sizeof(fmttab[0]) &&
+                    fmttab[entryn].formatf)
+                fmttab[entryn].formatf(fmttab + entryn, info, fmt, len);
+            else {
+                fprintf(stderr, "Invalid conversion character \'%c\'\n",
+                        entryn);
+                exit(EXIT_FAILURE);
+            }
+
+            fmt += len + 1;
+        } else {
+            putchar(*fmt);
+            ++fmt;
+        }
+    }
+}
+
+
 static void list_vm(void)
 {
     libxl_vminfo *info;
-- 


-- 
(\___(\___(\______          --=> 8-) EHM <=--          ______/)___/)___/)
 \BS (    |         ehem+sigmsg@m5p.com  PGP 87145445         |    )   /
  \_CS\   |  _____  -O #include <stddisclaimer.h> O-   _____  |   /  _/
8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445





  parent reply	other threads:[~2021-01-04 22:59 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-22 19:01 [WIP PATCH 00/16] Addition of formatting options to `xl list` subcommands Elliott Mitchell
2020-12-09 22:34 ` [WIP PATCH 14/16] WIP: tools/xl: Enhance "list" command Elliott Mitchell
2020-12-09 22:34 ` [WIP PATCH 07/16] tools/xl: Sort list command options Elliott Mitchell
2020-12-09 22:45 ` [WIP PATCH 06/16] tools/xl: Split list commands off of xl_info.c Elliott Mitchell
2020-12-10 23:09 ` Elliott Mitchell [this message]
2020-12-10 23:09 ` [WIP PATCH 10/16] WIP: tools/xl: Implement output format option Elliott Mitchell
2020-12-10 23:09 ` [WIP PATCH 08/16] tools/xl: Fix potential deallocation bug Elliott Mitchell
2020-12-12  6:18 ` [WIP PATCH 11/16] WIP: tools/xl: Replace most of list_domains with use of format() Elliott Mitchell
2020-12-13  4:42 ` [WIP PATCH 12/16] WIP: UNTESTED: tools/xl: Replace remaining options with format() Elliott Mitchell
2020-12-13  5:14 ` [WIP PATCH 13/16] WIP: tools/xl: Purge list_domains() Elliott Mitchell
2020-12-18  1:42 ` [WIP PATCH 04/16] tools/xl: Rename printf_info()/list_domains_details() to dump_by_...() Elliott Mitchell
2020-12-18  1:42 ` [WIP PATCH 05/16] tools/xl: Merge down debug/dry-run section of create_domain() Elliott Mitchell
2020-12-18 21:32 ` [WIP PATCH 03/16] tools/xl: Mark libxl_domain_config * arg of printf_info_*() const Elliott Mitchell
2020-12-18 21:37 ` [WIP PATCH 01/16] tools/libxl: Mark pointer args of many functions constant Elliott Mitchell
2020-12-18 22:45 ` [WIP PATCH 02/16] tools/libxl: Tiny optimization of libxl__mac_is_default() Elliott Mitchell
2020-12-19  7:23 ` [WIP PATCH 15/16] WIP: tools/xl: Implement output format option for "vm-list" command Elliott Mitchell
2020-12-20  7:43 ` [WIP PATCH 16/16] WIP: tools/xl: Enhance " Elliott Mitchell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b0211ac6542435ac2a2987e1e573150c21b1d719.1608663694.git.ehem+xen@m5p.com \
    --to=ehem+xen@m5p.com \
    --cc=iwj@xenproject.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.