+ column_count += c;
+ if (format_is_analog(f))
+ analog_count += c;
+ else if (format_is_logic(f))
+ logic_count += c * b;
+ }
+ sr_dbg("Column format %s -> %zu columns, %zu logic, %zu analog channels.",
+ column_format, column_count, logic_count, analog_count);
+
+ /* Allocate and fill in "column processing" details. */
+ inc->column_want_count = column_count;
+ if (inc->column_seen_count < inc->column_want_count) {
+ sr_err("Insufficient input text width for desired data amount, got %zu but want %zu columns.",
+ inc->column_seen_count, inc->column_want_count);
+ g_strfreev(formats);
+ return SR_ERR_ARG;
+ }
+ inc->logic_channels = logic_count;
+ inc->analog_channels = analog_count;
+ inc->analog_datafeed_digits = g_malloc0(inc->analog_channels * sizeof(inc->analog_datafeed_digits[0]));
+ inc->analog_datafeed_channels = g_malloc0(inc->analog_channels * sizeof(inc->analog_datafeed_channels[0]));
+ inc->column_details = g_malloc0_n(column_count, sizeof(inc->column_details[0]));
+ column_idx = channel_idx = analog_idx = 0;
+ channel_name = g_string_sized_new(64);
+ for (format_idx = 0; format_idx < format_count; format_idx++) {
+ /* Process a format field, which can span multiple columns. */
+ format = formats[format_idx];
+ (void)split_column_format(format, &c, &f, &b);
+ if (f && !c)
+ c = auto_column_count;
+ while (c-- > 0) {
+ /* Fill in a column's processing details. */
+ detail = &inc->column_details[column_idx++];
+ detail->col_nr = column_idx;
+ detail->text_format = f;
+ if (format_is_analog(detail->text_format)) {
+ detail->channel_offset = analog_idx;
+ detail->channel_count = 1;
+ detail->analog_digits = b;
+ analog_idx += detail->channel_count;
+ } else if (format_is_logic(detail->text_format)) {
+ detail->channel_offset = channel_idx;
+ detail->channel_count = b;
+ channel_idx += detail->channel_count;
+ } else if (format_is_ignore(detail->text_format)) {
+ /* EMPTY */
+ continue;
+ } else {
+ /*
+ * Neither logic nor analog data, nor ignore.
+ * Format was noted. No channel creation involved.
+ */
+ continue;
+ }
+ /*
+ * Pick most appropriate channel names. Optionally
+ * use text from a header line (when requested by the
+ * user). In the absence of header text, channels are
+ * assigned rather generic names.
+ *
+ * Manipulation of the column's caption (when a header
+ * line is seen) is acceptable, because this header
+ * line won't get processed another time.
+ */
+ column = column_texts[detail->col_nr - 1];
+ if (inc->use_header && column && *column) {
+ column = g_strstrip(column);
+ caption = sr_scpi_unquote_string(column);
+ } else {
+ caption = NULL;
+ }
+ if (!caption || !*caption)
+ caption = NULL;
+ /*
+ * Collect channel creation details here, but defer
+ * actual creation of the channels such that all
+ * logic channels can get created first and analog
+ * channels only get created afterwards.
+ */
+ detail->channel_names = g_malloc0(detail->channel_count * sizeof(detail->channel_names[0]));
+ for (create_idx = 0; create_idx < detail->channel_count; create_idx++) {
+ if (caption && detail->channel_count == 1) {
+ g_string_assign(channel_name, caption);
+ } else if (caption) {
+ g_string_printf(channel_name, "%s[%zu]",
+ caption, create_idx);
+ } else {
+ g_string_printf(channel_name, "%zu",
+ detail->channel_offset + create_idx);
+ }
+ detail->channel_names[create_idx] = g_string_new_len(channel_name->str, channel_name->len);
+ }
+ }
+ }
+ g_string_free(channel_name, TRUE);
+ g_strfreev(formats);
+
+ /* Create channels in strict logic to analog order. */
+ channel_type = SR_CHANNEL_LOGIC;
+ for (column_idx = 0; column_idx < inc->column_want_count; column_idx++) {
+ detail = &inc->column_details[column_idx];
+ if (!format_is_logic(detail->text_format))
+ continue;
+ for (create_idx = 0; create_idx < detail->channel_count; create_idx++) {
+ caption = detail->channel_names[create_idx]->str;
+ channel_sdi_nr = g_slist_length(in->sdi->channels);
+ sr_channel_new(in->sdi, channel_sdi_nr, channel_type, TRUE, caption);
+ }
+ }
+ channel_type = SR_CHANNEL_ANALOG;
+ for (column_idx = 0; column_idx < inc->column_want_count; column_idx++) {
+ detail = &inc->column_details[column_idx];
+ if (!format_is_analog(detail->text_format))
+ continue;
+ caption = detail->channel_names[0]->str;
+ channel_sdi_nr = g_slist_length(in->sdi->channels);
+ channel = sr_channel_new(in->sdi, channel_sdi_nr, channel_type, TRUE, caption);
+ channel_idx = channel_sdi_nr - inc->logic_channels;
+ inc->analog_datafeed_digits[channel_idx] = detail->analog_digits;
+ inc->analog_datafeed_channels[channel_idx] = g_slist_append(NULL, channel);