[MPlayer-dev-eng] [PATCH] suboption escaping

Joey Parrish joey at nicewarrior.org
Mon Aug 15 17:23:15 CEST 2005


On Sat, Aug 06, 2005 at 06:59:47PM -0500, Joey Parrish wrote:
> Attached is a patch to allow escaping of suboptions.
> The biggest reason for this is that without this patch, I keep wanting
> to do this:
>   $ mencoder -info "title=Star Trek: The Next Generation"
> With this patch, you can say:
>   $ mencoder -info "title=Star Trek\\: The Next Generation"
> One escape shown above is for the shell, one is for mencoder.
> 
> I've also attached a second patch with an alternative implementation.
> Please comment on the concept, and then one which patch you prefer.
> 
> I'd like to commit this soon.

If there are no other objections, I'm going to commit the second one
tomorrow.  If you'd like me to commit the first or not at all, speak up
now.  Patches re-attached in case you missed it the first time.

--Joey

-- 
"I can read it better than you can read it with your eyes closed." --Gu
-------------- next part --------------
Index: m_option.c
===================================================================
RCS file: /cvsroot/mplayer/main/m_option.c,v
retrieving revision 1.38
diff -u -r1.38 m_option.c
--- m_option.c	20 Jun 2005 23:07:34 -0000	1.38
+++ m_option.c	6 Aug 2005 23:11:06 -0000
@@ -875,6 +875,7 @@
   char *token;
   char *p;
   char** lst = NULL;
+  int len;
 
   if (param == NULL || strlen(param) == 0)
     return M_OPT_MISSING_PARAM;
@@ -886,13 +887,21 @@
   subopts = opt->p;
 
   token = strtok(p, (char *)&(":"));
+  while (token && (len = strlen(token)) && token[len - 1] == '\\')
+    {
+      // replace an escaped colon.
+      token[len - 1] = ':';
+      token[len] = 1; // to remove the nul for strlen next
+      memmove(&(token[len]), &(token[len + 1]), strlen(&(token[len])));
+      strtok(NULL, (char *)&(":"));
+    }
   while(token)
     {
       int sscanf_ret;
       /* clear out */
       subopt[0] = subparam[0] = 0;
-			    
-      sscanf_ret = sscanf(token, "%[^=]=%[^:]", subopt, subparam);
+
+      sscanf_ret = sscanf(token, "%[^=]=%[^=]", subopt, subparam);
 
       mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', subopt='%s', subparam='%s' (ret: %d)\n", token, subopt, subparam, sscanf_ret);
       switch(sscanf_ret)
@@ -923,6 +932,14 @@
 	  return M_OPT_INVALID;
 	}
       token = strtok(NULL, (char *)&(":"));
+      while (token && (len = strlen(token)) && token[len - 1] == '\\')
+        {
+          // replace an escaped colon.
+          token[len - 1] = ':';
+          token[len] = 1; // to remove the nul for strlen next
+          memmove(&(token[len]), &(token[len + 1]), strlen(&(token[len])));
+          strtok(NULL, (char *)&(":"));
+        }
     }
 
   free(subparam);
-------------- next part --------------
Index: m_option.c
===================================================================
RCS file: /cvsroot/mplayer/main/m_option.c,v
retrieving revision 1.38
diff -u -r1.38 m_option.c
--- m_option.c	20 Jun 2005 23:07:34 -0000	1.38
+++ m_option.c	6 Aug 2005 23:42:16 -0000
@@ -867,6 +867,52 @@
 #undef VAL
 #define VAL(x) (*(char***)(x))
 
+static char *strtokex(char *src, const char *delim, const char escape)
+{
+  static char *ptr = NULL;
+  char *ret;
+  char *tmp;
+  int ignore = 0;
+
+  if (src) ptr = src;
+
+  if (!ptr) return NULL;
+  if (!(*ptr)) return NULL;
+  if (!delim) return NULL;
+
+  ret = ptr;
+  while (*ptr)
+    {
+      if (*ptr == escape)
+        {
+          // move the string down, including the nul.
+          memmove(ptr, ptr + 1, strlen(ptr));
+          // advance past the escaped char, and continue.
+          ptr++;
+          continue;
+        }
+      tmp = (char *)delim;
+      while (*tmp)
+        {
+          if (*ptr == *tmp)
+            {
+              // nullify the delimiter, advance the pointer.
+              *ptr = '\0';
+              ptr++;
+              // if this is not the first char, return it.
+              if (ptr != ret + 1)
+                return ret;
+              // otherwise, we will try to return the first non-delim char.
+              ret = ptr;
+              continue;
+            }
+          tmp++;
+        }
+      ptr++;
+    }
+  return ret;
+}
+
 static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) {
   char *subparam;
   char *subopt;
@@ -885,14 +931,14 @@
 
   subopts = opt->p;
 
-  token = strtok(p, (char *)&(":"));
+  token = strtokex(p, (char *)&(":"), '\\');
   while(token)
     {
       int sscanf_ret;
       /* clear out */
       subopt[0] = subparam[0] = 0;
-			    
-      sscanf_ret = sscanf(token, "%[^=]=%[^:]", subopt, subparam);
+
+      sscanf_ret = sscanf(token, "%[^=]=%[^=]", subopt, subparam);
 
       mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', subopt='%s', subparam='%s' (ret: %d)\n", token, subopt, subparam, sscanf_ret);
       switch(sscanf_ret)
@@ -922,7 +968,7 @@
 	  mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token);
 	  return M_OPT_INVALID;
 	}
-      token = strtok(NULL, (char *)&(":"));
+      token = strtokex(NULL, (char *)&(":"), '\\');
     }
 
   free(subparam);


More information about the MPlayer-dev-eng mailing list