+#include <babeltrace/ctf-ir/metadata.h> /* for clocks */
+
+#define PARTIAL_ERROR_SLEEP 3 /* 3 seconds */
+
+#define DEFAULT_FILE_ARRAY_SIZE 1
+
+/*
+ * casting these to const char * to please libpopt. It allocates memory
+ * behind our back (this is of course not documented).
+ */
+static char *opt_input_format, *opt_output_format;
+
+static GPtrArray *opt_input_paths;
+static char *opt_output_path;
+
+static struct format *fmt_read;
+
+static
+void strlower(char *str)
+{
+ while (*str) {
+ *str = tolower((int) *str);
+ str++;
+ }
+}
+
+enum {
+ OPT_NONE = 0,
+ OPT_OUTPUT_PATH,
+ OPT_INPUT_FORMAT,
+ OPT_OUTPUT_FORMAT,
+ OPT_HELP,
+ OPT_LIST,
+ OPT_VERBOSE,
+ OPT_DEBUG,
+ OPT_NAMES,
+ OPT_FIELDS,
+ OPT_NO_DELTA,
+ OPT_CLOCK_OFFSET,
+ OPT_CLOCK_CYCLES,
+ OPT_CLOCK_SECONDS,
+ OPT_CLOCK_DATE,
+ OPT_CLOCK_GMT,
+ OPT_CLOCK_FORCE_CORRELATE,
+};
+
+/*
+ * We are _not_ using POPT_ARG_STRING ability to store directly into
+ * variables, because we want to cast the return to non-const, which is
+ * not possible without using poptGetOptArg explicitly.
+ */
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ { "output", 'w', POPT_ARG_STRING, NULL, OPT_NONE, NULL, NULL },
+ { "input-format", 'i', POPT_ARG_STRING, NULL, OPT_INPUT_FORMAT, NULL, NULL },
+ { "output-format", 'o', POPT_ARG_STRING, NULL, OPT_OUTPUT_FORMAT, NULL, NULL },
+ { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
+ { "list", 'l', POPT_ARG_NONE, NULL, OPT_LIST, NULL, NULL },
+ { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL },
+ { "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL },
+ { "names", 'n', POPT_ARG_STRING, NULL, OPT_NAMES, NULL, NULL },
+ { "fields", 'f', POPT_ARG_STRING, NULL, OPT_FIELDS, NULL, NULL },
+ { "no-delta", 0, POPT_ARG_NONE, NULL, OPT_NO_DELTA, NULL, NULL },
+ { "clock-offset", 0, POPT_ARG_STRING, NULL, OPT_CLOCK_OFFSET, NULL, NULL },
+ { "clock-cycles", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_CYCLES, NULL, NULL },
+ { "clock-seconds", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_SECONDS, NULL, NULL },
+ { "clock-date", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_DATE, NULL, NULL },
+ { "clock-gmt", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_GMT, NULL, NULL },
+ { "clock-force-correlate", 0, POPT_ARG_NONE, NULL, OPT_CLOCK_FORCE_CORRELATE, NULL, NULL },
+ { NULL, 0, 0, NULL, 0, NULL, NULL },
+};
+
+static void list_formats(FILE *fp)
+{
+ fprintf(fp, "\n");
+ bt_fprintf_format_list(fp);
+}
+
+static void usage(FILE *fp)
+{
+ fprintf(fp, "BabelTrace Trace Viewer and Converter %s\n\n", VERSION);
+ fprintf(fp, "usage : babeltrace [OPTIONS] FILE...\n");
+ fprintf(fp, "\n");
+ fprintf(fp, " FILE Input trace file(s) and/or directory(ies)\n");
+ fprintf(fp, " (space-separated)\n");
+ fprintf(fp, " -w, --output OUTPUT Output trace path (default: stdout)\n");
+ fprintf(fp, "\n");
+ fprintf(fp, " -i, --input-format FORMAT Input trace format (default: ctf)\n");
+ fprintf(fp, " -o, --output-format FORMAT Output trace format (default: text)\n");
+ fprintf(fp, "\n");
+ fprintf(fp, " -h, --help This help message\n");
+ fprintf(fp, " -l, --list List available formats\n");
+ fprintf(fp, " -v, --verbose Verbose mode\n");
+ fprintf(fp, " (or set BABELTRACE_VERBOSE environment variable)\n");
+ fprintf(fp, " -d, --debug Debug mode\n");
+ fprintf(fp, " (or set BABELTRACE_DEBUG environment variable)\n");
+ fprintf(fp, " --no-delta Do not print time delta between consecutive events\n");
+ fprintf(fp, " -n, --names name1<,name2,...> Print field names:\n");
+ fprintf(fp, " (payload OR args OR arg)\n");
+ fprintf(fp, " none, all, scope, header, (context OR ctx)\n");
+ fprintf(fp, " (default: payload,context)\n");
+ fprintf(fp, " -f, --fields name1<,name2,...> Print additional fields:\n");
+ fprintf(fp, " all, trace, trace:hostname, trace:domain,\n");
+ fprintf(fp, " trace:procname, trace:vpid, loglevel, emf, callsite.\n");
+ fprintf(fp, " (default: trace:hostname,trace:procname,trace:vpid)\n");
+ fprintf(fp, " --clock-cycles Timestamp in cycles\n");
+ fprintf(fp, " --clock-offset seconds Clock offset in seconds\n");
+ fprintf(fp, " --clock-seconds Print the timestamps as [sec.ns]\n");
+ fprintf(fp, " (default is: [hh:mm:ss.ns])\n");
+ fprintf(fp, " --clock-date Print clock date\n");
+ fprintf(fp, " --clock-gmt Print clock in GMT time zone (default: local time zone)\n");
+ fprintf(fp, " --clock-force-correlate Assume that clocks are inherently correlated\n");
+ fprintf(fp, " across traces.\n");
+ list_formats(fp);
+ fprintf(fp, "\n");
+}
+
+static int get_names_args(poptContext *pc)
+{
+ char *str, *strlist, *strctx;
+ int ret = 0;
+
+ opt_payload_field_names = 0;
+ opt_context_field_names = 0;
+ strlist = (char *) poptGetOptArg(*pc);
+ if (!strlist) {
+ return -EINVAL;
+ }
+ str = strtok_r(strlist, ",", &strctx);
+ do {
+ if (!strcmp(str, "all"))
+ opt_all_field_names = 1;
+ else if (!strcmp(str, "scope"))
+ opt_scope_field_names = 1;
+ else if (!strcmp(str, "context") || !strcmp(str, "ctx"))
+ opt_context_field_names = 1;
+ else if (!strcmp(str, "header"))
+ opt_header_field_names = 1;
+ else if (!strcmp(str, "payload") || !strcmp(str, "args") || !strcmp(str, "arg"))
+ opt_payload_field_names = 1;
+ else if (!strcmp(str, "none")) {
+ opt_all_field_names = 0;
+ opt_scope_field_names = 0;
+ opt_context_field_names = 0;
+ opt_header_field_names = 0;
+ opt_payload_field_names = 0;
+ } else {
+ fprintf(stderr, "[error] unknown field name type %s\n", str);
+ free(strlist);
+ ret = -EINVAL;
+ goto end;
+ }
+ } while ((str = strtok_r(NULL, ",", &strctx)));
+end:
+ free(strlist);
+ return ret;
+}
+
+static int get_fields_args(poptContext *pc)
+{
+ char *str, *strlist, *strctx;
+ int ret = 0;
+
+ strlist = (char *) poptGetOptArg(*pc);
+ if (!strlist) {
+ return -EINVAL;
+ }
+ str = strtok_r(strlist, ",", &strctx);
+ do {
+ opt_trace_default_fields = 0;
+ if (!strcmp(str, "all"))
+ opt_all_fields = 1;
+ else if (!strcmp(str, "trace"))
+ opt_trace_field = 1;
+ else if (!strcmp(str, "trace:hostname"))
+ opt_trace_hostname_field = 1;
+ else if (!strcmp(str, "trace:domain"))
+ opt_trace_domain_field = 1;
+ else if (!strcmp(str, "trace:procname"))
+ opt_trace_procname_field = 1;
+ else if (!strcmp(str, "trace:vpid"))
+ opt_trace_vpid_field = 1;
+ else if (!strcmp(str, "loglevel"))
+ opt_loglevel_field = 1;
+ else if (!strcmp(str, "emf"))
+ opt_emf_field = 1;
+ else if (!strcmp(str, "callsite"))
+ opt_callsite_field = 1;
+ else {
+ fprintf(stderr, "[error] unknown field type %s\n", str);
+ ret = -EINVAL;
+ goto end;
+ }
+ } while ((str = strtok_r(NULL, ",", &strctx)));
+end:
+ free(strlist);
+ return ret;
+}
+
+/*
+ * Return 0 if caller should continue, < 0 if caller should return
+ * error, > 0 if caller should exit without reporting error.
+ */
+static int parse_options(int argc, char **argv)