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