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