]> sigrok.org Git - libsigrok.git/blobdiff - src/scpi/scpi.c
scpi: introduce string un-quote helper routine
[libsigrok.git] / src / scpi / scpi.c
index e2f5cd5870a8ec7d2fa61dc3eed6b2cb754246cc..a01e13e037da3575b37c42e935dc5cb91e932cdd 100644 (file)
@@ -150,12 +150,12 @@ static int scpi_send_variadic(struct sr_scpi_dev_inst *scpi,
 
        /* Get length of buffer required. */
        va_copy(args_copy, args);
-       len = vsnprintf(NULL, 0, format, args_copy);
+       len = sr_vsnprintf_ascii(NULL, 0, format, args_copy);
        va_end(args_copy);
 
        /* Allocate buffer and write out command. */
        buf = g_malloc0(len + 2);
-       vsprintf(buf, format, args);
+       sr_vsprintf_ascii(buf, format, args);
        if (buf[len - 1] != '\n')
                buf[len] = '\n';
 
@@ -587,6 +587,7 @@ SR_PRIV void sr_scpi_free(struct sr_scpi_dev_inst *scpi)
 
        scpi->free(scpi->priv);
        g_free(scpi->priv);
+       g_free(scpi->actual_channel_name);
        g_free(scpi);
 }
 
@@ -1138,6 +1139,48 @@ SR_PRIV void sr_scpi_hw_info_free(struct sr_scpi_hw_info *hw_info)
        g_free(hw_info);
 }
 
+/**
+ * Remove potentially enclosing pairs of quotes, un-escape content.
+ * This implementation modifies the caller's buffer when quotes are found
+ * and doubled quote characters need to get removed from the content.
+ *
+ * @param[in, out] s   The SCPI string to check and un-quote.
+ *
+ * @return The start of the un-quoted string.
+ */
+SR_PRIV const char *sr_scpi_unquote_string(char *s)
+{
+       size_t s_len;
+       char quotes[3];
+       char *rdptr;
+
+       /* Immediately bail out on invalid or short input. */
+       if (!s || !*s)
+               return s;
+       s_len = strlen(s);
+       if (s_len < 2)
+               return s;
+
+       /* Check for matching quote characters front and back. */
+       if (s[0] != '\'' && s[0] != '"')
+               return s;
+       if (s[0] != s[s_len - 1])
+               return s;
+
+       /* Need to strip quotes, and un-double quote chars inside. */
+       quotes[0] = quotes[1] = *s;
+       quotes[2] = '\0';
+       s[s_len - 1] = '\0';
+       s++;
+       rdptr = s;
+       while ((rdptr = strstr(rdptr, quotes)) != NULL) {
+               memmove(rdptr, rdptr + 1, strlen(rdptr));
+               rdptr++;
+       }
+
+       return s;
+}
+
 SR_PRIV const char *sr_vendor_alias(const char *raw_vendor)
 {
        unsigned int i;
@@ -1195,7 +1238,8 @@ SR_PRIV int sr_scpi_cmd(const struct sr_dev_inst *sdi,
        if (channel_cmd && channel_name &&
                        g_strcmp0(channel_name, scpi->actual_channel_name)) {
                sr_spew("sr_scpi_cmd(): new channel = %s", channel_name);
-               scpi->actual_channel_name = channel_name;
+               g_free(scpi->actual_channel_name);
+               scpi->actual_channel_name = g_strdup(channel_name);
                ret = scpi_send(scpi, channel_cmd, channel_name);
                if (ret != SR_OK)
                        return ret;
@@ -1239,7 +1283,8 @@ SR_PRIV int sr_scpi_cmd_resp(const struct sr_dev_inst *sdi,
        if (channel_cmd && channel_name &&
                        g_strcmp0(channel_name, scpi->actual_channel_name)) {
                sr_spew("sr_scpi_cmd_get(): new channel = %s", channel_name);
-               scpi->actual_channel_name = channel_name;
+               g_free(scpi->actual_channel_name);
+               scpi->actual_channel_name = g_strdup(channel_name);
                ret = scpi_send(scpi, channel_cmd, channel_name);
                if (ret != SR_OK)
                        return ret;