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

Joey Parrish joey at nicewarrior.org
Thu Sep 1 23:33:28 CEST 2005


Hello,

Attached is a patch that implements subconfig escaping Unix-style using
a backslash.  This revision addresses most of the issues that Reimer
brought up for my last revision, with the exception of his preference
for an entirely different escaping method.  :)  This one also includes
documentation in the man page.

So, please review and test, especially Reimer, because I've been using
this at home for weeks.  I'd like to commit soon.

Thanks,
--Joey

-- 
"The greatest thing you'll ever learn
is just to love and be loved in return." -- Darth Vader
-------------- next part --------------
diff -ur main.sofar/DOCS/man/en/mplayer.1 main.dev/DOCS/man/en/mplayer.1
--- main.sofar/DOCS/man/en/mplayer.1	2005-08-15 10:30:45.221556000 -0500
+++ main.dev/DOCS/man/en/mplayer.1	2005-08-29 10:51:34.961630400 -0500
@@ -425,6 +425,23 @@
 If you wish to have a configuration file for a file called 'movie.avi', create a file
 named 'movie.avi.conf' with the file-specific options in it and put it in
 ~/.mplayer/ or in the same directory as the file.
+.PP
+.I NOTE:
+The subconfig parser (used for example for MEncoder's -info) supports
+traditional backslash escaping.
+Any character preceded by a backslash is taken literally.
+This allows you to use the reserved : character in the keys or values
+of the -info option.
+.br
+.I EXAMPLE:
+.br
+mencoder dvd://1 -info "artist=Star Trek\\: The Next Generation"
+.PP
+You should also note that from the command line, many Unix shells
+will escape your arguments before passing them to the application.
+In this case, you should specify two backslashes.
+The shell will turn \\\\: into \\:, and then the application will
+treat the : as literal.
 .
 .
 .
diff -ur main.sofar/m_option.c main.dev/m_option.c
--- main.sofar/m_option.c	2005-08-05 20:02:44.680705000 -0500
+++ main.dev/m_option.c	2005-08-29 10:40:42.583556800 -0500
@@ -867,6 +867,57 @@
 #undef VAL
 #define VAL(x) (*(char***)(x))
 
+// strtokex behaves just like strtok with two exceptions.
+// 1) it handles empty fields.
+// 2) it allows an escape character to be specified
+//     so that properly escaped tokens can include the delimiter characters.
+// if you pass 0 for the escape character, no escaping will be done.
+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 (escape && *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 +936,16 @@
 
   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);
+
+      // \001 is used below to make sscanf match all other characters.
+      // this gives the effect of %s, but includes whitespace.
+      sscanf_ret = sscanf(token, "%[^=]=%[^\001]", 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 +975,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