#include <../../nrnconf.h> /* /local/src/master/nrn/src/oc/regexp.c,v 1.1.1.1 1994/10/12 17:22:13 hines Exp */ /* regexp.c,v * Revision 1.1.1.1 1994/10/12 17:22:13 hines * NEURON 3.0 distribution * * Revision 2.19 93/02/02 10:34:37 hines * static functions declared before used * * Revision 1.3 92/07/31 12:11:31 hines * following merged from hoc * The regular expression has been augmented with * {istart-iend} where istart and iend are integers. The expression matches * any integer that falls in this range. * * Revision 1.2 92/01/30 08:17:19 hines * bug fixes found in hoc incorporated. if()return, no else, objectcenter * warnings. * * Revision 1.1 91/10/11 11:12:16 hines * Initial revision * * Revision 3.108 90/10/24 09:44:14 hines * saber warnings gone * * Revision 3.58 90/05/17 16:30:52 jamie * changed global functions to start with hoc_ * moved regexp.c from project 'neuron' to 'hoc' * * Revision 1.25 89/08/31 10:28:46 mlh * regular expressions for issection() * differences between standard regular expressions are: * allways match from beginning to end of target (implicit ^ and $) * change [] to <> * eliminate \( * * Revision 1.2 89/08/31 09:22:17 mlh * works as in e.c and lint free * * Revision 1.1 89/08/31 08:24:59 mlh * Initial revision * */ /* regular expression match for section names grabbed prototype from e.c Use by first compiling the search string with hoc_regexp_compile(pattern) Then checking target strings one at a time with hoc_regexp_search(target) */ #include #define CABLESECTION 1 /* Always match from beginning of string (implicit ^), Always match end of string (implicit $), change [] to <>, eliminate \( */ #define STAR 01 #define SUFF '.' #define TILDE '~' #define EREGEXP 24 #define error(enum) hoc_execerror("search string format error", pattern) #define CBRA 1 #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define CKET 12 #if CABLESECTION #define INTRANGE 14 #endif #define NBRA 5 #define ESIZE 128 #define eof '\0' static char expbuf[ESIZE+4]; static char *pattern = ""; static char *loc1; static char *loc2; static char *locs; static char *braslist[NBRA]; static char *braelist[NBRA]; static int circfl; #if CABLESECTION static int int_range_start[NBRA]; static int int_range_stop[NBRA]; #endif static int advance(); hoc_regexp_compile(cp) char *cp; { register c; register char *ep; char *lastep; #if (!CABLESECTION) char bracket[NBRA], *bracketp; int nbra; #else int int_range_index = 0; #endif int cclcnt; int tempc; if (!cp) { pattern = ""; error(EREGEXP); } if (pattern == cp && strcmp(pattern, cp)) { /* if previous pattern != cp then may have been freed */ return; } pattern = cp; ep = expbuf; #if (!CABLESECTION) bracketp = bracket; nbra = 0; #endif if ((c = *cp++)== '\n') { cp--; c = eof; } if (c==eof) { if (*ep==0) error(EREGEXP); return; } #if CABLESECTION circfl = 1; #else circfl = 0; if (c=='^') { c = *cp++; circfl++; } #endif if (c=='*') goto cerror; cp--; for (;;) { if (ep >= &expbuf[ESIZE]) goto cerror; c = *cp++; if (c=='\n') { cp--; c = eof; } if (c==eof) { #if CABLESECTION *ep++ = CDOL; #endif *ep++ = CEOF; return; } if (c!='*') lastep = ep; switch (c) { case '\\': #if (!CABLESECTION) if ((c = *cp++)=='(') { if (nbra >= NBRA) goto cerror; *bracketp++ = nbra; *ep++ = CBRA; *ep++ = nbra++; continue; } if (c == ')') { if (bracketp <= bracket) goto cerror; *ep++ = CKET; *ep++ = *--bracketp; continue; } #endif *ep++ = CCHR; if (c=='\n') goto cerror; *ep++ = c; continue; case '.': *ep++ = CDOT; continue; case '\n': goto cerror; case '*': if (*lastep==CBRA || *lastep==CKET) error(EREGEXP); *lastep |= STAR; continue; #if (!CABLESECTION) case '$': tempc = *cp; if (tempc != eof && tempc != '\n') goto defchar; *ep++ = CDOL; continue; #endif #if CABLESECTION case '{': { char* cp1 = cp; if (int_range_index >= NBRA) goto cerror; *ep++ = INTRANGE; do { if (!(*cp >= '0' && *cp <= '9') && *cp != '-') { error(EREGEXP); } }while (*(++cp) != '}'); cp++; if (2 != sscanf(cp1, "%d-%d", int_range_start + int_range_index, int_range_stop + int_range_index)) { error(EREGEXP); } *ep++ = int_range_index++; } continue; #endif #if CABLESECTION case '<': #else case '[': #endif *ep++ = CCL; *ep++ = 0; cclcnt = 1; if ((c = *cp++) == '^') { c = *cp++; ep[-2] = NCCL; } do { if (c == '\n') goto cerror; /* * Handle the escaped '-' */ if (c == '-' && *(ep-1) == '\\') *(ep-1) = '-'; /* * Handle ranges of characters (e.g. a-z) */ else if ( (tempc = *cp++) != ']' && c == '-' && cclcnt > 1 && tempc != '\n' && (c = *(ep-1)) <= tempc ) { while (++c <= tempc) { *ep++ = c; cclcnt++; if (ep >= &expbuf[ESIZE]) goto cerror; } } /* * Normal case. Add character to buffer */ else { cp--; *ep++ = c; cclcnt++; if (ep >= &expbuf[ESIZE]) goto cerror; } #if CABLESECTION } while ((c = *cp++) != '>'); #else } while ((c = *cp++) != ']'); #endif lastep[1] = cclcnt; continue; #if (!CABLESECTION) defchar: #endif default: *ep++ = CCHR; *ep++ = c; } } cerror: expbuf[0] = 0; error(EREGEXP); } int hoc_regexp_search(target) /*return true if target matches pattern*/ char *target; { register char *p1, *p2, c; #if 1 if (target == (char *)0) { return(0); } p1 = target; locs = (char *)0; #else /* in e, apparently for searches within or at begining of string */ if (gf) { if (circfl) return(0); p1 = linebuf; p2 = genbuf; while (*p1++ = *p2++); locs = p1 = loc2; } else { if (addr==zero) return(0); p1 = getline(*addr); locs = NULL; } #endif p2 = expbuf; if (circfl) { loc1 = p1; return(advance(p1, p2)); } /* fast check for first character */ if (*p2==CCHR) { c = p2[1]; do { if (*p1!=c) continue; if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } /* regular algorithm */ do { if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } static int advance(lp, ep) register char *lp, *ep; { register char *curlp; for (;;) switch (*ep++) { case CCHR: if (*ep++ == *lp++) continue; return(0); case CDOT: if (*lp++) continue; return(0); case CDOL: if (*lp==0) continue; return(0); case CEOF: loc2 = lp; return(1); #if CABLESECTION case INTRANGE: { int start, stop, num; start = int_range_start[*ep]; stop = int_range_stop[*ep++]; num = *lp++ - '0'; if (num < 0 || num > 9) { return(0); } while(*lp >= '0' && *lp <= '9') { num = 10*num + *lp - '0'; ++lp; } if (num >= start && num <= stop) { continue; } } return(0); #endif case CCL: if (hoc_cclass(ep, *lp++, 1)) { ep += *ep; continue; } return(0); case NCCL: if (hoc_cclass(ep, *lp++, 0)) { ep += *ep; continue; } return(0); case CBRA: braslist[*ep++] = lp; continue; case CKET: braelist[*ep++] = lp; continue; case CDOT|STAR: curlp = lp; /*EMPTY*/ while (*lp++); goto star; case CCHR|STAR: curlp = lp; /*EMPTY*/ while (*lp++ == *ep); ep++; goto star; case CCL|STAR: case NCCL|STAR: curlp = lp; /*EMPTY*/ while (hoc_cclass(ep, *lp++, ep[-1]==(CCL|STAR))); ep += *ep; goto star; star: do { lp--; if (lp==locs) break; if (advance(lp, ep)) return(1); } while (lp > curlp); return(0); default: error(EREGEXP); } } hoc_cclass(set, c, af) register char *set, c; { register n; if (c == 0) return(0); n = *set++; while (--n) if (*set++ == c) return(af); return(!af); }