This is an update related to bug #259.
struct srd_decoder_inst *di;
GVariant *var;
void *probe_id;
struct srd_decoder_inst *di;
GVariant *var;
void *probe_id;
- void *probe_target;
- struct sr_probe *probe;
+ void *channel_target;
+ struct sr_channel *ch;
probe_map = value;
probe_list = user_data;
probe_map = value;
probe_list = user_data;
(GDestroyNotify)g_variant_unref);
g_hash_table_iter_init(&iter, probe_map);
(GDestroyNotify)g_variant_unref);
g_hash_table_iter_init(&iter, probe_map);
- while (g_hash_table_iter_next(&iter, &probe_id, &probe_target)) {
- probe = find_probe(probe_list, probe_target);
- if (!probe) {
- g_printerr("cli: No probe with name \"%s\" found.\n",
- (char *)probe_target);
+ while (g_hash_table_iter_next(&iter, &probe_id, &channel_target)) {
+ ch = find_channel(probe_list, channel_target);
+ if (!ch) {
+ g_printerr("cli: No channel with name \"%s\" found.\n",
+ (char *)channel_target);
- if (!probe->enabled)
- g_printerr("cli: Target probe \"%s\" not enabled.\n",
- (char *)probe_target);
+ if (!ch->enabled)
+ g_printerr("cli: Target channel \"%s\" not enabled.\n",
+ (char *)channel_target);
- var = g_variant_new_int32(probe->index);
+ var = g_variant_new_int32(ch->index);
g_variant_ref_sink(var);
g_hash_table_insert(probe_indices, g_strdup(probe_id), var);
}
g_variant_ref_sink(var);
g_hash_table_insert(probe_indices, g_strdup(probe_id), var);
}
- num_probes = g_slist_length(probe_list);
- srd_inst_probe_set_all(di, probe_indices, (num_probes + 7) / 8);
+ num_channels = g_slist_length(probe_list);
+ srd_inst_probe_set_all(di, probe_indices, (num_channels + 7) / 8);
}
void map_pd_probes(struct sr_dev_inst *sdi)
{
if (pd_probe_maps) {
g_hash_table_foreach(pd_probe_maps, &map_pd_inst_probes,
}
void map_pd_probes(struct sr_dev_inst *sdi)
{
if (pd_probe_maps) {
g_hash_table_foreach(pd_probe_maps, &map_pd_inst_probes,
g_hash_table_destroy(pd_probe_maps);
pd_probe_maps = NULL;
}
g_hash_table_destroy(pd_probe_maps);
pd_probe_maps = NULL;
}
0:ffff ffff ffff ffff ffff ffff ffff ffff
1:ff00 ff00 ff00 ff00 ff00 ff00 ff00 ff00
.sp
0:ffff ffff ffff ffff ffff ffff ffff ffff
1:ff00 ff00 ff00 ff00 ff00 ff00 ff00 ff00
.sp
-The lines always start with the probe number (or name, if defined), followed by a colon. If no format is specified, it defaults to
+The lines always start with the channel number (or name, if defined), followed by a colon. If no format is specified, it defaults to
.BR bits:width=64 ,
like this:
.sp
.BR bits:width=64 ,
like this:
.sp
1:11111111 00000000 11111111 00000000 [...]
.TP
.BR "\-p, \-\-probes " <probelist>
1:11111111 00000000 11111111 00000000 [...]
.TP
.BR "\-p, \-\-probes " <probelist>
-A comma-separated list of probes to be used in the session.
+A comma-separated list of channels to be used in the session.
-Note that sigrok always names the probes according to how they're shown on
-the enclosure of the hardware. If your logic analyzer numbers the probes 0-15,
-that's how you must specify them with this option. An oscilloscope's probes
+Note that sigrok always names the channels according to how they're shown on
+the enclosure of the hardware. If your logic analyzer numbers the channels 0-15,
+that's how you must specify them with this option. An oscilloscope's channels
would generally be referred to as "CH1", "CH2", and so on.
would generally be referred to as "CH1", "CH2", and so on.
-Use the \fB\-\-show\fP option to see a list of probe names for your device.
+Use the \fB\-\-show\fP option to see a list of channel names for your device.
-The default is to use all the probes available on a device. You can name
-a probe like this:
+The default is to use all the channels available on a device. You can name
+a channel like this:
-A range of probes can also be given, in the form
+A range of channels can also be given, in the form
.BR "1\-5" .
.sp
Example:
.BR "1\-5" .
.sp
Example:
The comma-separated list is processed from left to right, i.e. items farther
to the right override previous items. For example
.B "1=CS,1=MISO"
The comma-separated list is processed from left to right, i.e. items farther
to the right override previous items. For example
.B "1=CS,1=MISO"
-will set the name of probe 1 to
+will set the name of channel 1 to
.BR "MISO" .
.sp
Also, while
.B "5=MOSI,6=MISO"
.BR "MISO" .
.sp
Also, while
.B "5=MOSI,6=MISO"
-will only select probes 5 and 6, and set their names to MISO and MOSI, the
+will only select channels 5 and 6, and set their names to MISO and MOSI, the
command line
.B "5=MOSI,6=MISO,1\-8"
command line
.B "5=MOSI,6=MISO,1\-8"
-will select probes 1\-8 (including 5 and 6, of course), but the names specified
-for probes 5 and 6 will be reset to the defaults by the
+will select channels 1\-8 (including 5 and 6, of course), but the names specified
+for channels 5 and 6 will be reset to the defaults by the
.TP
.BR "\-g, \-\-channel\-group "<channel\ group>
Specify the channel group to operate on.
.TP
.BR "\-g, \-\-channel\-group "<channel\ group>
Specify the channel group to operate on.
.TP
.BR "\-t, \-\-triggers " <triggerlist>
A comma-separated list of triggers to use, of the form
.TP
.BR "\-t, \-\-triggers " <triggerlist>
A comma-separated list of triggers to use, of the form
-.BR "<probe>=<trigger>" .
-You can use the name or number of the probe, and the trigger itself is a
+.BR "<channel>=<trigger>" .
+You can use the name or number of the channel, and the trigger itself is a
series of characters:
.sp
.BR "0 or 1" :
series of characters:
.sp
.BR "0 or 1" :
protocol decoder has different options it supports.
.sp
Any "options" specified for a protocol decoder which are not actually
protocol decoder has different options it supports.
.sp
Any "options" specified for a protocol decoder which are not actually
-supported options, will be interpreted as being probe name/number assignments.
+supported options, will be interpreted as being channel name/number assignments.
is an option supported by the
.B spi
protocol decoder. Additionally, the user tells sigrok to decode the SPI
is an option supported by the
.B spi
protocol decoder. Additionally, the user tells sigrok to decode the SPI
-protocol using probe 1 as MISO signal for SPI, probe 5 as MOSI, probe 3
-as SCK, and probe 0 as CS# signal.
+protocol using channel 1 as MISO signal for SPI, channel 5 as MOSI, channel 3
+as SCK, and channel 0 as CS# signal.
.TP
.BR "\-S, \-\-protocol\-decoder\-stack " <stack>
This option allows the user to specify a protocol decoder stack, i.e.
.TP
.BR "\-S, \-\-protocol\-decoder\-stack " <stack>
This option allows the user to specify a protocol decoder stack, i.e.
is stacked on top of the
.BR i2c " decoder."
.sp
is stacked on top of the
.BR i2c " decoder."
.sp
-The respective protocol decoder options and probe name/number assignments
+The respective protocol decoder options and channel name/number assignments
must be given using the
.B \-P
option (you cannot specify them in the
must be given using the
.B \-P
option (you cannot specify them in the
.br
The following devices were found:
.br
.br
The following devices were found:
.br
- Demo device with 8 probes: 0 1 2 3 4 5 6 7
+ Demo device with 8 channels: 0 1 2 3 4 5 6 7
- ChronoVu LA8 with 8 probes: 0 1 2 3 4 5 6 7
+ ChronoVu LA8 with 8 channels: 0 1 2 3 4 5 6 7
- ALSA: HDA ATI SB ALC270 Analog with 2 probes: Ch_0 Ch_1
+ ALSA: HDA ATI SB ALC270 Analog with 2 channels: Ch_0 Ch_1
- Saleae Logic with 8 probes: 0 1 2 3 4 5 6 7
+ Saleae Logic with 8 channels: 0 1 2 3 4 5 6 7
.sp
However, not all devices are auto-detectable (e.g. serial port based ones).
For those you'll have to provide a \fBconn\fP option, see above.
.sp
However, not all devices are auto-detectable (e.g. serial port based ones).
For those you'll have to provide a \fBconn\fP option, see above.
.br
The following devices were found:
.br
.br
The following devices were found:
.br
- Digitek DT4000ZC with 1 probe: P1
+ Digitek DT4000ZC with 1 channel: P1
.TP
.BR "\-\-time " <ms>
Sample for
.TP
.BR "\-\-time " <ms>
Sample for
.TP
.B " sigrok\-cli \-\-driver fx2lafw \-\-time 3s"
.TP
.TP
.B " sigrok\-cli \-\-driver fx2lafw \-\-time 3s"
.TP
-To capture data from the first 4 probes using the Openbench Logic Sniffer lasting 100ms at 10 MHz starting at the trigger condition
+To capture data from the first 4 channels using the Openbench Logic Sniffer lasting 100ms at 10 MHz starting at the trigger condition
0:high, 1:rising, 2:low, 3:high, use:
.TP
.nf
0:high, 1:rising, 2:low, 3:high, use:
.TP
.nf
- if (select_probes(in->sdi) != SR_OK)
+ if (select_channels(in->sdi) != SR_OK)
return;
sr_session_new();
return;
sr_session_new();
return;
}
sdi = sessions->data;
return;
}
sdi = sessions->data;
- if (select_probes(sdi) != SR_OK) {
+ if (select_channels(sdi) != SR_OK) {
sr_session_destroy();
return;
}
sr_session_destroy();
return;
}
-int select_probes(struct sr_dev_inst *sdi)
+int select_channels(struct sr_dev_inst *sdi)
- struct sr_probe *probe;
- GSList *selected_probes, *l;
+ struct sr_channel *ch;
+ GSList *selected_channels, *l;
- if (!(selected_probes = parse_probestring(sdi, opt_probes)))
+ if (!(selected_channels = parse_channelstring(sdi, opt_probes)))
- for (l = sdi->probes; l; l = l->next) {
- probe = l->data;
- if (g_slist_find(selected_probes, probe))
- probe->enabled = TRUE;
+ for (l = sdi->channels; l; l = l->next) {
+ ch = l->data;
+ if (g_slist_find(selected_channels, ch))
+ ch->enabled = TRUE;
- probe->enabled = FALSE;
- g_slist_free(selected_probes);
+ g_slist_free(selected_channels);
}
#ifdef HAVE_SRD
map_pd_probes(sdi);
}
#ifdef HAVE_SRD
map_pd_probes(sdi);
#include <string.h>
#include <glib.h>
#include <string.h>
#include <glib.h>
-struct sr_probe *find_probe(GSList *probelist, const char *probename)
+struct sr_channel *find_channel(GSList *channellist, const char *channelname)
- struct sr_probe *probe;
- probe = NULL;
- for (l = probelist; l; l = l->next) {
- probe = l->data;
- if (!strcmp(probe->name, probename))
+ ch = NULL;
+ for (l = channellist; l; l = l->next) {
+ ch = l->data;
+ if (!strcmp(ch->name, channelname))
- probe = l ? l->data : NULL;
+ ch = l ? l->data : NULL;
-GSList *parse_probestring(struct sr_dev_inst *sdi, const char *probestring)
+GSList *parse_channelstring(struct sr_dev_inst *sdi, const char *channelstring)
- struct sr_probe *probe;
- GSList *probelist;
+ struct sr_channel *ch;
+ GSList *channellist;
int ret, n, b, e, i;
char **tokens, **range, **names, *eptr, str[8];
int ret, n, b, e, i;
char **tokens, **range, **names, *eptr, str[8];
- if (!probestring || !probestring[0])
- /* Use all probes by default. */
- return g_slist_copy(sdi->probes);
+ if (!channelstring || !channelstring[0])
+ /* Use all channels by default. */
+ return g_slist_copy(sdi->channels);
ret = SR_OK;
range = NULL;
names = NULL;
ret = SR_OK;
range = NULL;
names = NULL;
- probelist = NULL;
- tokens = g_strsplit(probestring, ",", 0);
+ channellist = NULL;
+ tokens = g_strsplit(channelstring, ",", 0);
for (i = 0; tokens[i]; i++) {
if (tokens[i][0] == '\0') {
for (i = 0; tokens[i]; i++) {
if (tokens[i][0] == '\0') {
- g_critical("Invalid empty probe.");
+ g_critical("Invalid empty channel.");
ret = SR_ERR;
break;
}
if (strchr(tokens[i], '-')) {
ret = SR_ERR;
break;
}
if (strchr(tokens[i], '-')) {
- /* A range of probes in the form a-b. This will only work
- * if the probes are named as numbers -- so every probe
- * in the range must exist as a probe name string in the
+ /* A range of channels in the form a-b. This will only work
+ * if the channels are named as numbers -- so every channel
+ * in the range must exist as a channel name string in the
* device. */
range = g_strsplit(tokens[i], "-", 2);
if (!range[0] || !range[1] || range[2]) {
/* Need exactly two arguments. */
* device. */
range = g_strsplit(tokens[i], "-", 2);
if (!range[0] || !range[1] || range[2]) {
/* Need exactly two arguments. */
- g_critical("Invalid probe syntax '%s'.", tokens[i]);
+ g_critical("Invalid channel syntax '%s'.", tokens[i]);
ret = SR_ERR;
goto range_fail;
}
b = strtol(range[0], &eptr, 10);
if (eptr == range[0] || *eptr != '\0') {
ret = SR_ERR;
goto range_fail;
}
b = strtol(range[0], &eptr, 10);
if (eptr == range[0] || *eptr != '\0') {
- g_critical("Invalid probe '%s'.", range[0]);
+ g_critical("Invalid channel '%s'.", range[0]);
ret = SR_ERR;
goto range_fail;
}
e = strtol(range[1], NULL, 10);
if (eptr == range[1] || *eptr != '\0') {
ret = SR_ERR;
goto range_fail;
}
e = strtol(range[1], NULL, 10);
if (eptr == range[1] || *eptr != '\0') {
- g_critical("Invalid probe '%s'.", range[1]);
+ g_critical("Invalid channel '%s'.", range[1]);
ret = SR_ERR;
goto range_fail;
}
if (b < 0 || b >= e) {
ret = SR_ERR;
goto range_fail;
}
if (b < 0 || b >= e) {
- g_critical("Invalid probe range '%s'.", tokens[i]);
+ g_critical("Invalid channel range '%s'.", tokens[i]);
ret = SR_ERR;
goto range_fail;
}
ret = SR_ERR;
goto range_fail;
}
while (b <= e) {
n = snprintf(str, 8, "%d", b);
if (n < 0 || n > 8) {
while (b <= e) {
n = snprintf(str, 8, "%d", b);
if (n < 0 || n > 8) {
- g_critical("Invalid probe '%d'.", b);
+ g_critical("Invalid channel '%d'.", b);
- probe = find_probe(sdi->probes, str);
- if (!probe) {
- g_critical("unknown probe '%d'.", b);
+ ch = find_channel(sdi->channels, str);
+ if (!ch) {
+ g_critical("unknown channel '%d'.", b);
- probelist = g_slist_append(probelist, probe);
+ channellist = g_slist_append(channellist, ch);
names = g_strsplit(tokens[i], "=", 2);
if (!names[0] || (names[1] && names[2])) {
/* Need one or two arguments. */
names = g_strsplit(tokens[i], "=", 2);
if (!names[0] || (names[1] && names[2])) {
/* Need one or two arguments. */
- g_critical("Invalid probe '%s'.", tokens[i]);
+ g_critical("Invalid channel '%s'.", tokens[i]);
g_strfreev(names);
ret = SR_ERR;
break;
}
g_strfreev(names);
ret = SR_ERR;
break;
}
- probe = find_probe(sdi->probes, names[0]);
- if (!probe) {
- g_critical("unknown probe '%s'.", names[0]);
+ ch = find_channel(sdi->channels, names[0]);
+ if (!ch) {
+ g_critical("unknown channel '%s'.", names[0]);
g_strfreev(names);
ret = SR_ERR;
break;
}
if (names[1]) {
g_strfreev(names);
ret = SR_ERR;
break;
}
if (names[1]) {
- /* Rename probe. */
- g_free(probe->name);
- probe->name = g_strdup(names[1]);
+ /* Rename channel. */
+ g_free(ch->name);
+ ch->name = g_strdup(names[1]);
- probelist = g_slist_append(probelist, probe);
+ channellist = g_slist_append(channellist, ch);
g_strfreev(names);
}
}
if (ret != SR_OK) {
g_strfreev(names);
}
}
if (ret != SR_OK) {
- g_slist_free(probelist);
- probelist = NULL;
+ g_slist_free(channellist);
+ channellist = NULL;
}
GHashTable *parse_generic_arg(const char *arg, gboolean sep_first)
}
GHashTable *parse_generic_arg(const char *arg, gboolean sep_first)
const struct sr_datafeed_logic *logic;
const struct sr_datafeed_analog *analog;
struct sr_config *src;
const struct sr_datafeed_logic *logic;
const struct sr_datafeed_analog *analog;
struct sr_config *src;
- struct sr_probe *probe;
static struct sr_output *o = NULL;
static uint64_t rcvd_samples_logic = 0;
static uint64_t rcvd_samples_analog = 0;
static struct sr_output *o = NULL;
static uint64_t rcvd_samples_logic = 0;
static uint64_t rcvd_samples_analog = 0;
uint64_t output_len, input_len;
uint8_t *output_buf;
int i;
uint64_t output_len, input_len;
uint8_t *output_buf;
int i;
/* Saving to a session file. */
if (rcvd_samples_logic == 0) {
/* First packet with logic data, init session file. */
/* Saving to a session file. */
if (rcvd_samples_logic == 0) {
/* First packet with logic data, init session file. */
- probes = g_malloc(sizeof(char *) * g_slist_length(sdi->probes));
- for (i = 0, l = sdi->probes; l; l = l->next) {
- probe = l->data;
- if (probe->enabled && probe->type == SR_PROBE_LOGIC)
- probes[i++] = probe->name;
+ channels = g_malloc(sizeof(char *) * g_slist_length(sdi->channels));
+ for (i = 0, l = sdi->channels; l; l = l->next) {
+ ch = l->data;
+ if (ch->enabled && ch->type == SR_CHANNEL_LOGIC)
+ channels[i++] = ch->name;
sr_session_save_init(opt_output_file, samplerate,
sr_session_save_init(opt_output_file, samplerate,
- probes);
- g_free(probes);
+ channels);
+ g_free(channels);
}
save_chunk_logic(logic->data, input_len, logic->unitsize);
} else {
}
save_chunk_logic(logic->data, input_len, logic->unitsize);
} else {
GVariant *gvar;
struct sr_dev_inst *sdi;
uint64_t min_samples, max_samples;
GVariant *gvar;
struct sr_dev_inst *sdi;
uint64_t min_samples, max_samples;
char **triggerlist;
devices = device_scan();
char **triggerlist;
devices = device_scan();
- if (select_probes(sdi) != SR_OK) {
- g_critical("Failed to set probes.");
+ if (select_channels(sdi) != SR_OK) {
+ g_critical("Failed to set channels.");
sr_session_destroy();
return;
}
sr_session_destroy();
return;
}
sr_session_destroy();
return;
}
sr_session_destroy();
return;
}
- max_probes = g_slist_length(sdi->probes);
- for (i = 0; i < max_probes; i++) {
+ max_channels = g_slist_length(sdi->channels);
+ for (i = 0; i < max_channels; i++) {
if (triggerlist[i]) {
sr_dev_trigger_set(sdi, i, triggerlist[i]);
g_free(triggerlist[i]);
if (triggerlist[i]) {
sr_dev_trigger_set(sdi, i, triggerlist[i]);
g_free(triggerlist[i]);
-static gint sort_probes(gconstpointer a, gconstpointer b)
+static gint sort_channels(gconstpointer a, gconstpointer b)
- const struct sr_probe *pa = a, *pb = b;
+ const struct sr_channel *pa = a, *pb = b;
return pa->index - pb->index;
}
static void print_dev_line(const struct sr_dev_inst *sdi)
{
return pa->index - pb->index;
}
static void print_dev_line(const struct sr_dev_inst *sdi)
{
- struct sr_probe *probe;
GSList *sl, *l;
GString *s;
GVariant *gvar;
GSList *sl, *l;
GString *s;
GVariant *gvar;
g_string_append_printf(s, "%s ", sdi->model);
if (sdi->version && sdi->version[0])
g_string_append_printf(s, "%s ", sdi->version);
g_string_append_printf(s, "%s ", sdi->model);
if (sdi->version && sdi->version[0])
g_string_append_printf(s, "%s ", sdi->version);
- if (sdi->probes) {
- if (g_slist_length(sdi->probes) == 1) {
- probe = sdi->probes->data;
- g_string_append_printf(s, "with 1 probe: %s", probe->name);
+ if (sdi->channels) {
+ if (g_slist_length(sdi->channels) == 1) {
+ ch = sdi->channels->data;
+ g_string_append_printf(s, "with 1 channel: %s", ch->name);
- sl = g_slist_sort(g_slist_copy(sdi->probes), sort_probes);
- g_string_append_printf(s, "with %d probes:", g_slist_length(sl));
+ sl = g_slist_sort(g_slist_copy(sdi->channels), sort_channels);
+ g_string_append_printf(s, "with %d channels:", g_slist_length(sl));
for (l = sl; l; l = l->next) {
for (l = sl; l; l = l->next) {
- probe = l->data;
- g_string_append_printf(s, " %s", probe->name);
+ ch = l->data;
+ g_string_append_printf(s, " %s", ch->name);
{
struct sr_dev_inst *sdi;
const struct sr_config_info *srci;
{
struct sr_dev_inst *sdi;
const struct sr_config_info *srci;
- struct sr_probe *probe;
struct sr_channel_group *channel_group, *cg;
struct sr_channel_group *channel_group, *cg;
- GSList *devices, *cgl, *prl;
+ GSList *devices, *cgl, *chl;
GVariant *gvar_opts, *gvar_dict, *gvar_list, *gvar;
gsize num_opts, num_elements;
double dlow, dhigh, dcur_low, dcur_high;
GVariant *gvar_opts, *gvar_dict, *gvar_list, *gvar;
gsize num_opts, num_elements;
double dlow, dhigh, dcur_low, dcur_high;
/* Selected channels and channel group may affect which options are
* returned, or which values for them. */
/* Selected channels and channel group may affect which options are
* returned, or which values for them. */
channel_group = select_channel_group(sdi);
if ((sr_config_list(sdi->driver, sdi, channel_group, SR_CONF_DEVICE_OPTIONS,
channel_group = select_channel_group(sdi);
if ((sr_config_list(sdi->driver, sdi, channel_group, SR_CONF_DEVICE_OPTIONS,
cg = cgl->data;
printf(" %s: channel%s", cg->name,
g_slist_length(cg->channels) > 1 ? "s" : "");
cg = cgl->data;
printf(" %s: channel%s", cg->name,
g_slist_length(cg->channels) > 1 ? "s" : "");
- for (prl = cg->channels; prl; prl = prl->next) {
- probe = prl->data;
- printf(" %s", probe->name);
+ for (chl = cg->channels; chl; chl = chl->next) {
+ ch = chl->data;
+ printf(" %s", ch->name);
} else if (srci->datatype == SR_T_DOUBLE_RANGE) {
printf(" %s: ", srci->id);
} else if (srci->datatype == SR_T_DOUBLE_RANGE) {
printf(" %s: ", srci->id);
- if (sr_config_list(sdi->driver, sdi, probe_group, srci->key,
+ if (sr_config_list(sdi->driver, sdi, channel_group, srci->key,
&gvar_list) != SR_OK) {
printf("\n");
continue;
&gvar_list) != SR_OK) {
printf("\n");
continue;
#define SAVE_CHUNK_SIZE 524288
/* main.c */
#define SAVE_CHUNK_SIZE 524288
/* main.c */
-int select_probes(struct sr_dev_inst *sdi);
+int select_channels(struct sr_dev_inst *sdi);
/* show.c */
void show_version(void);
/* show.c */
void show_version(void);
-struct sr_probe *find_probe(GSList *probelist, const char *probename);
-GSList *parse_probestring(struct sr_dev_inst *sdi, const char *probestring);
+struct sr_channel *find_channel(GSList *channellist, const char *channelname);
+GSList *parse_channelstring(struct sr_dev_inst *sdi, const char *channelstring);
GHashTable *parse_generic_arg(const char *arg, gboolean sep_first);
int canon_cmp(const char *str1, const char *str2);
GHashTable *parse_generic_arg(const char *arg, gboolean sep_first);
int canon_cmp(const char *str1, const char *str2);