--- /dev/null
+/* Kernel info for virtual domains.
+ * (C) Copyright 2008-2010 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Generic output routines which can write either plain
+ * text tables or CSV files.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "internal.h"
+
+static char *convert_fs_to_strings (const char *fs);
+static void output_to_csv (int to_strings, const char *fs, va_list args);
+
+void
+output_heading (const char *fs, ...)
+{
+ va_list args;
+
+ va_start (args, fs);
+
+ if (!csv) {
+ /* Convert each %..x in the format string into %..s */
+ char *fs2 = convert_fs_to_strings (fs);
+ vprintf (fs2, args);
+ free (fs2);
+ printf ("\n");
+ } else
+ output_to_csv (1, fs, args);
+
+ va_end (args);
+}
+
+void
+output_row (const char *fs, ...)
+{
+ va_list args;
+
+ va_start (args, fs);
+
+ if (!csv) {
+ vprintf (fs, args);
+ printf ("\n");
+ }
+ else
+ output_to_csv (0, fs, args);
+
+ va_end (args);
+}
+
+/* Return a newly allocated format string with each '%..x' sequence
+ * converted to '%..s'. We only attempt to parse simple format
+ * strings, and we assume the length of the format string won't
+ * change.
+ */
+static const char *end_of_specifier = "diouxXeEfFgGaAcsp%";
+
+static char *
+convert_fs_to_strings (const char *fs)
+{
+ char *fs2;
+ int i, len;
+
+ len = strlen (fs);
+ fs2 = strdup (fs);
+ for (i = 0; i < len; ++i) {
+ if (fs2[i] == '%') {
+ /* Search for the end of the %-sequence. */
+ do { i++; }
+ while (i < len && strchr (end_of_specifier, fs2[i]) == NULL);
+
+ if (i == len)
+ internal_error (_("unrecognized format string in output_heading function"));
+
+ fs2[i] = 's';
+ }
+ }
+
+ return fs2; /* caller frees */
+}
+
+/* Output a row to a CSV file. The format string is just used to
+ * get the correct types for each parameter - any non-%-specifiers
+ * in the format string are ignored. If to_strings is true, then
+ * each parameter is assumed to be a string.
+ *
+ * The CSV output is very conservative, designed to be correct
+ * rather than concise.
+ */
+static void
+output_to_csv (int to_strings, const char *fs, va_list args)
+{
+ int i, j, len, comma = 0;
+ char fs2[16];
+
+ len = strlen (fs);
+
+ for (i = 0; i < len; ++i) {
+ /* Look for the next %-specifier. */
+ if (fs[i] == '%') {
+ j = 0;
+ do { fs2[j++] = fs[i++]; }
+ while (j < sizeof (fs2) - 1 &&
+ i < len &&
+ strchr (end_of_specifier, fs[i]) == NULL);
+
+ if (j == sizeof (fs2) - 1 || i == len)
+ internal_error (_("unrecognized format string in output_* function"));
+
+ fs2[j] = fs[i++];
+ fs2[j+1] = '\0';
+ }
+
+ if (fs2[j] != '%') {
+ char *str;
+ int len2;
+
+ if (to_strings)
+ fs2[j] = 's';
+
+ /* Convert the next parameter into a string. */
+ if (vasprintf (&str, fs2, args) == -1)
+ internal_error (_("unable to convert next argument to string using '%s'"),
+ fs2);
+ len2 = strlen (str);
+
+ /* Output the next parameter as a CSV field. */
+ if (comma)
+ putchar (',');
+ comma = 1;
+
+ putchar ('"');
+ for (j = 0; j < len2; ++j) {
+ switch (str[j]) {
+ case '"':
+ putchar ('"');
+ putchar ('"');
+ break;
+ case '\0':
+ putchar ('"');
+ putchar ('0');
+ break;
+ default:
+ putchar (str[j]);
+ }
+ }
+ putchar ('"');
+
+ free (str);
+ }
+ }
+
+ putchar ('\n');
+}