At Thu, 9 Aug 2012 17:44:12 +0300, Kaskinen Tanu wrote:
On Thu, 2012-08-09 at 16:07 +0200, Takashi Iwai wrote:
At Thu, 9 Aug 2012 16:43:31 +0300, Tanu Kaskinen wrote:
@@ -170,8 +170,23 @@ static int execute_cset(snd_ctl_t *ctl, char *cset) snd_ctl_elem_value_malloc(&value); snd_ctl_elem_info_malloc(&info);
- pos = strrchr(cset, ' ');
- if (pos == NULL) {
- /* Find the space after the element id, taking quoting with
single-quotes into account. */
- for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) {
if (*pos == ' ')
break;
if (*pos == '\'') {
A double-quote can be supported easily here...
True, I'll post v2 soon.
On the second thought, parsing the string intensively at that point doesn't make sense. The string will be parsed anyway in snd_ctl_ascii_elem_id_parse(), then why not just let it give the next pointer from there?
Below is a quick hack (untested at all!). Could you check whether it works?
Takashi
--- diff --git a/src/control/ctlparse.c b/src/control/ctlparse.c index a16f96a..b0c4ef3 100644 --- a/src/control/ctlparse.c +++ b/src/control/ctlparse.c @@ -143,21 +143,19 @@ char *snd_ctl_ascii_elem_id_get(snd_ctl_elem_id_t *id) return strdup(buf); }
-/** - * \brief parse ASCII string as CTL element identifier - * \param dst destination CTL identifier - * \param str source ASCII string - * \return zero on success, otherwise a negative error code - */ -int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str) +#ifndef DOC_HIDDEN +/* used by UCM parser, too */ +int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str, + const char **ret_ptr) { int c, size, numid; + int err = -EINVAL; char *ptr;
- while (*str == ' ' || *str == '\t') + while (isspace(*str)) str++; if (!(*str)) - return -EINVAL; + goto out; snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_MIXER); /* default */ while (*str) { if (!strncasecmp(str, "numid=", 6)) { @@ -165,7 +163,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str) numid = atoi(str); if (numid <= 0) { fprintf(stderr, "amixer: Invalid numid %d\n", numid); - return -EINVAL; + goto out; } snd_ctl_elem_id_set_numid(dst, atoi(str)); while (isdigit(*str)) @@ -191,7 +189,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str) snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_SEQUENCER); str += 9; } else { - return -EINVAL; + goto out; } } else if (!strncasecmp(str, "name=", 5)) { char buf[64]; @@ -239,11 +237,33 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str) if (*str == ',') { str++; } else { + /* when ret_ptr is given, allow to terminate gracefully + * at the next space letter + */ + if (ret_ptr && isspace(*str)) + break; if (*str) - return -EINVAL; + goto out; } } - return 0; + err = 0; + + out: + if (ret_ptr) + *ret_ptr = str; + return err; +} +#endif + +/** + * \brief parse ASCII string as CTL element identifier + * \param dst destination CTL identifier + * \param str source ASCII string + * \return zero on success, otherwise a negative error code + */ +int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str) +{ + return __snd_ctl_ascii_elem_id_parse(dst, str, NULL); }
static int get_ctl_enum_item_index(snd_ctl_t *handle, diff --git a/src/ucm/main.c b/src/ucm/main.c index 4b37776..bd5c348 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -31,6 +31,7 @@ */
#include "ucm_local.h" +#include <ctype.h> #include <stdarg.h> #include <pthread.h>
@@ -158,9 +159,13 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr, return 0; }
+extern int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, + const char *str, + const char **ret_ptr); + static int execute_cset(snd_ctl_t *ctl, char *cset) { - char *pos; + const char *pos; int err; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *value; @@ -170,16 +175,16 @@ static int execute_cset(snd_ctl_t *ctl, char *cset) snd_ctl_elem_value_malloc(&value); snd_ctl_elem_info_malloc(&info);
- pos = strrchr(cset, ' '); - if (pos == NULL) { + err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos); + if (err < 0) + goto __fail; + while (*pos && isspace(*pos)) + pos++; + if (!*pos) { uc_error("undefined value for cset >%s<", cset); err = -EINVAL; goto __fail; } - *pos = '\0'; - err = snd_ctl_ascii_elem_id_parse(id, cset); - if (err < 0) - goto __fail; snd_ctl_elem_value_set_id(value, id); snd_ctl_elem_info_set_id(info, id); err = snd_ctl_elem_read(ctl, value); @@ -188,7 +193,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset) err = snd_ctl_elem_info(ctl, info); if (err < 0) goto __fail; - err = snd_ctl_ascii_value_parse(ctl, value, info, pos + 1); + err = snd_ctl_ascii_value_parse(ctl, value, info, pos); if (err < 0) goto __fail; err = snd_ctl_elem_write(ctl, value); @@ -196,9 +201,6 @@ static int execute_cset(snd_ctl_t *ctl, char *cset) goto __fail; err = 0; __fail: - if (pos != NULL) - *pos = ' '; - if (id != NULL) free(id); if (value != NULL)