+int setup_pd_stack(void)
+{
+ struct srd_decoder_inst *di_from, *di_to;
+ int ret, i;
+ char **pds, **ids;
+
+ /* Set up the protocol decoder stack. */
+ pds = g_strsplit(opt_pds, ",", 0);
+ if (g_strv_length(pds) > 1) {
+ if (opt_pd_stack) {
+ /* A stack setup was specified, use that. */
+ g_strfreev(pds);
+ pds = g_strsplit(opt_pd_stack, ",", 0);
+ if (g_strv_length(pds) < 2) {
+ g_strfreev(pds);
+ g_critical("Specify at least two protocol decoders to stack.");
+ return 1;
+ }
+ }
+
+ /* First PD goes at the bottom of the stack. */
+ ids = g_strsplit(pds[0], ":", 0);
+ if (!(di_from = srd_inst_find_by_id(ids[0]))) {
+ g_strfreev(ids);
+ g_critical("Cannot stack protocol decoder '%s': "
+ "instance not found.", pds[0]);
+ return 1;
+ }
+ g_strfreev(ids);
+
+ /* Every subsequent PD goes on top. */
+ for (i = 1; pds[i]; i++) {
+ ids = g_strsplit(pds[i], ":", 0);
+ if (!(di_to = srd_inst_find_by_id(ids[0]))) {
+ g_strfreev(ids);
+ g_critical("Cannot stack protocol decoder '%s': "
+ "instance not found.", pds[i]);
+ return 1;
+ }
+ g_strfreev(ids);
+ if ((ret = srd_inst_stack(di_from, di_to)) != SRD_OK)
+ return 1;
+
+ /* Don't show annotation from this PD. Only the last PD in
+ * the stack will be left on the annotation list (unless
+ * the annotation list was specifically provided).
+ */
+ if (!opt_pd_annotations)
+ g_hash_table_remove(pd_ann_visible,
+ di_from->inst_id);
+
+ di_from = di_to;
+ }
+ }
+ g_strfreev(pds);
+
+ return 0;
+}
+
+int setup_pd_annotations(void)
+{
+ GSList *l;
+ struct srd_decoder *dec;
+ int ann;
+ char **pds, **pdtok, **keyval, **ann_descr;
+
+ /* Set up custom list of PDs and annotations to show. */
+ if (opt_pd_annotations) {
+ pds = g_strsplit(opt_pd_annotations, ",", 0);
+ for (pdtok = pds; *pdtok && **pdtok; pdtok++) {
+ ann = 0;
+ keyval = g_strsplit(*pdtok, "=", 0);
+ if (!(dec = srd_decoder_get_by_id(keyval[0]))) {
+ g_critical("Protocol decoder '%s' not found.", keyval[0]);
+ return 1;
+ }
+ if (!dec->annotations) {
+ g_critical("Protocol decoder '%s' has no annotations.", keyval[0]);
+ return 1;
+ }
+ if (g_strv_length(keyval) == 2) {
+ for (l = dec->annotations; l; l = l->next, ann++) {
+ ann_descr = l->data;
+ if (!canon_cmp(ann_descr[0], keyval[1]))
+ /* Found it. */
+ break;
+ }
+ if (!l) {
+ g_critical("Annotation '%s' not found "
+ "for protocol decoder '%s'.", keyval[1], keyval[0]);
+ return 1;
+ }
+ }
+ g_debug("cli: showing protocol decoder annotation %d from '%s'", ann, keyval[0]);
+ g_hash_table_insert(pd_ann_visible, g_strdup(keyval[0]), GINT_TO_POINTER(ann));
+ g_strfreev(keyval);
+ }
+ g_strfreev(pds);
+ }
+
+ return 0;
+}
+
+int setup_output_format(void)
+{
+ GHashTable *fmtargs;
+ GHashTableIter iter;
+ gpointer key, value;
+ struct sr_output_format **outputs;
+ int i;
+ char *fmtspec;
+
+ if (!opt_output_format) {
+ opt_output_format = DEFAULT_OUTPUT_FORMAT;
+ /* we'll need to remember this so when saving to a file
+ * later, sigrok session format will be used.
+ */
+ default_output_format = TRUE;
+ }
+
+ fmtargs = parse_generic_arg(opt_output_format, TRUE);
+ fmtspec = g_hash_table_lookup(fmtargs, "sigrok_key");
+ if (!fmtspec) {
+ g_critical("Invalid output format.");
+ return 1;
+ }
+ outputs = sr_output_list();
+ for (i = 0; outputs[i]; i++) {
+ if (strcmp(outputs[i]->id, fmtspec))
+ continue;
+ g_hash_table_remove(fmtargs, "sigrok_key");
+ output_format = outputs[i];
+ g_hash_table_iter_init(&iter, fmtargs);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ /* only supporting one parameter per output module
+ * for now, and only its value */
+ output_format_param = g_strdup(value);
+ break;
+ }
+ break;
+ }
+ if (!output_format) {
+ g_critical("Invalid output format %s.", opt_output_format);
+ return 1;
+ }
+ g_hash_table_destroy(fmtargs);
+
+ return 0;
+}
+
+void show_pd_annotations(struct srd_proto_data *pdata, void *cb_data)