[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: gEDA-user: pcb: parameter escaping for commands



On Sat, Nov 22, 2008 at 01:49:57PM -0500, DJ Delorie wrote:

Is the supported syntax described anywhere?
Nope.  You get to write it!  :-)
As long as it can do everything in pcb-menu.res it will be fine.
That's what I wanted to hear (the latter part at least). <g>
Patch attached. I tried to follow the current coding style, including usage of libc string functions (DJB-style string buffer functions would have made it easier). If the style is fine with you, I can create a bug report and attach it.
It seems to work fine for me, but I could not find any test suite.

Two important changes:
1. Action chaining isn't supported anymore. Wasn't documented, isn't used by anything AFAIK (resource parser does its own splitting). 2. The sequence "\_" will now be parsed as "_", so if PCB did use that to create negation lines, it will be broken until gsch2pcb and possibly other tools are adapted. Special-casing that sequence is possible, but IMO ugly.

The patch is only for actions - haven't looked at footprint etc. formats yet.

PS: How do I display the pin names (besides "Generate object report" on a pin)? Neither "View -> Pins/Vias show Name/Number" nor "Window -> Pinout" show any effect (regardless of selection).

CU Sascha

--
http://sascha.silbe.org/
http://www.infra-silbe.de/
Index: src/hid/common/actions.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/common/actions.c,v
retrieving revision 1.12
diff -u -d -r1.12 actions.c
--- src/hid/common/actions.c	5 Jan 2008 05:37:08 -0000	1.12
+++ src/hid/common/actions.c	23 Nov 2008 20:56:14 -0000
@@ -219,123 +219,152 @@
   return a->trigger_cb (argc, argv, x, y);
 }
 
+static char *
+strip (const char *s)
+{
+  const char *sp = s;
+  unsigned int len;
+  char *res;
+
+  /* skip leading spaces and tabs */
+  while (*sp && isspace ((int) *sp))
+    sp++;
+
+  len = strlen(sp);
+
+  /* skip trailing spaces and tabs */
+  while (len && isspace((int) sp[len-1]))
+    len--;
+
+  if (!len)
+      return "";
+
+  res = (char *) malloc(len+1); // ENOMEM not checked
+  if (!res)
+    return NULL;
+
+  strncpy(res, sp, len);
+  res[len] = '\0';
+
+  return res;
+}
+
+static char *
+my_strndup(const char *s, size_t n)
+{
+  char *res = (char *) malloc(n+1);
+  strncpy(res, s, n);
+  res[n] = '\0';
+  return res;
+}
+
+/* returns copy of next parameter, updating sp to point behind separator */
+static char *
+get_next_param(char **sp)
+{
+  char *sep, *res;
+
+  sep = strpbrk(*sp, "\\,)");
+
+  if (!sep)
+    sep = *sp + strlen(*sp);
+
+  if (*sep == '\\' && *(sep+1))
+    {
+      /* recursively process remaining part, concatenate
+         escaping is considered to be rare, so we don't need to optimize it */
+      size_t curlen = sep-*sp;
+      char escaped = sep[1];
+      char *rem;
+      sep += 2;
+      rem = get_next_param(&sep);
+      res = (char *) malloc(curlen+1+strlen(rem)+1);
+      strncpy(res, *sp, curlen);
+      res[curlen] = escaped;
+      strcpy(res+curlen+1, rem);
+      free(rem);
+      *sp = sep;
+      return res;
+    }
+
+  /* ignore trailing whitespace */
+  while ((sep > *sp) && isspace((int) *(sep-1)))
+    sep--;
+
+  /* return copy of parameter */
+  res = my_strndup(*sp, sep-*sp);
+  *sp = (*sep) ? sep+1 : sep;
+  return res;
+}
+
 int
 hid_parse_actions (const char *rstr,
-		   int (*function) (const char *, int, char **))
+               int (*function) (const char *, int, char **))
 {
+  char *str, *sp, *aname;
+  int num = 0, max = 0;
   char **list = NULL;
-  int max = 0;
-  int num;
-  char *str = NULL;
-  char *sp, *aname, *sp2;
-  int maybe_empty = 0;
-  int retcode = 0;
+  char *paren_pos;
+  int retcode;
 
   if (function == NULL)
     function = hid_actionv;
 
-  /*fprintf(stderr, "invoke: `%s'\n", rstr); */
-
-  sp = str = strdup (rstr);
+  aname = sp = str = strip (rstr);
+  if (!sp || !*sp)
+    return 0;
 
-another:
-  num = 0;
-  /* eat leading spaces and tabs */
-  while (*sp && isspace ((int) *sp))
-    sp++;
-  
-  if (!*sp)
+  /* action names don't need to be escaped so strchr suffices */
+  paren_pos = strchr(sp, '(');
+  if (paren_pos)
     {
-      retcode = 0;
-      goto cleanup;
-    }
+      /* NUL-terminate action name */
+      *paren_pos = '\0';
+      sp = paren_pos+1;
+    
+      /* scan for parameters */
+      while (*sp && *sp != ')')
+        {
+          char *param;
+
+          /* ignore leading whitespace */
+          while (*sp && isspace ((int) *sp))
+            sp++;
+        
+          if (!*sp || (*sp == ')'))
+            break;
+
+          /* get_next_param updates sp */
+          param = get_next_param(&sp);
   
-  aname = sp;
+          /* ensure list is big enough */
+          if (num <= max)
+            {
+              max += 10;
+              if (list)
+                list = (char **) realloc (list, max * sizeof (char *));
+              else
+                list = (char **) malloc (max * sizeof (char *));
+            }
   
-  /* search for the leading ( */
-  while (*sp && *sp != '(')
-    sp++;
-
-  /*
-   * we didn't find a leading ( so invoke the action
-   * with no parameters or event.
-   */
-  if (!*sp)
-    {
-      if (function (aname, 0, 0))
-        {
-          retcode = 1;
-          goto cleanup;
+          list[num++] = param;
         }
-      goto another;
+    
     }
-  
-  /* 
-   * we found a leading ( so see if we have parameters to pass to the
-   * action 
-   */
-  *sp++ = 0;
-  while (1)
+
+  retcode = function (aname, num, list) ? 1 : 0;
+
+  if (list != NULL)
     {
-      /* 
-       * maybe_empty == 0 means that the last char examined was not a
-       * "," 
-       */
-      if (*sp == ')' && !maybe_empty)
-	{
-	  *sp++ = 0;
-	  if (function (aname, num, list))
-	    {
-	      retcode = 1;
-	      goto cleanup;
-	    }
-	  goto another;
-	}
-      else if (*sp == 0 && !maybe_empty)
-	break;
-      else
-	{
-	  maybe_empty = 0;
-	  /* 
-	   * if we have more parameters than memory in our array of
-	   * pointers, then either allocate some or grow the array
-	   */
-	  if (num >= max)
-	    {
-	      max += 10;
-	      if (list)
-		list = (char **) realloc (list, max * sizeof (char *));
-	      else
-		list = (char **) malloc (max * sizeof (char *));
-	    }
-	  /* Strip leading whitespace.  */
-	  while (*sp && isspace ((int) *sp))
-	    sp++;
-	  list[num++] = sp;
-	  
-	  /* search for a "," or a ")" */
-	  while (*sp && *sp != ',' && *sp != ')')
-	    sp++;
-	  sp2 = sp - 1;
-	  if (*sp == ',')
-	    {
-	      maybe_empty = 1;
-	      *sp++ = 0;
-	    }
-	  /* Strip trailing whitespace.  */
-	  for (; isspace ((int) *sp2) && sp2 >= list[num - 1]; sp2--)
-	    *sp2 = 0;
-	}
+      while (num)
+        free(list[--num]);
+
+      free(list);
     }
-  
- cleanup:
-  
-  if (list != NULL)
-    free(list);
-  
+
   if (str != NULL)
     free (str);
-  
+
   return retcode;
 }
 

Attachment: signature.asc
Description: Digital signature


_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user