|
|
1.1 root 1: #include "regprog.h"
2:
3: /*
4: * Machine state
5: */
6: #define LISTINCREMENT 8
7: typedef struct List{
8: Inst *inst; /* Instruction of the thread */
9: Subexp se; /* matched subexpressions in this thread */
10: }List;
11: static List *tl, *nl; /* This list, next list */
12: static List *tle, *nle; /* ends of this and next list */
13: static List *list[2];
14: static List *liste[2];
15: static int listsize = LISTINCREMENT;
16:
17: static Subexp sempty; /* empty set of matches */
18: static int match; /* true if match is found */
19:
20: /*
21: * Note optimization in addinst:
22: * *lp must be pending when addinst called; if *l has been looked
23: * at already, the optimization is a bug.
24: */
25: static List *
26: newthread(lp, ip, sep)
27: List *lp; /* list to add to */
28: Inst *ip; /* instruction to add */
29: Subexp *sep; /* pointers to subexpressions */
30: {
31: register List *p;
32:
33: for(p=lp; p->inst != NULL; p++){
34: if(p->inst==ip){
35: if((sep)->startp[0] < p->se.startp[0])
36: p->se = *sep;
37: return NULL;
38: }
39: }
40: p->inst = ip;
41: p->se = *sep;
42: (++p)->inst = NULL;
43: return p;
44: }
45:
46: static
47: newmatch(subp, newp)
48: Subexp *subp;
49: Subexp *newp;
50: {
51: if(subp->startp[0]==0 || newp->startp[0]<subp->startp[0] ||
52: (newp->startp[0]==subp->startp[0] && newp->endp[0]>subp->endp[0]))
53: *subp = *newp;
54: match = 1;
55: }
56:
57: extern char *
58: regexec(progp, starts)
59: Prog *progp; /* program to run */
60: char *starts; /* string to run machine on */
61: {
62: register flag=0;
63: register Inst *inst;
64: register List *tlp;
65: register char *s;
66: int startchar=progp->startinst->type<OPERATOR? progp->startinst->type : 0;
67: int i, checkstart;
68:
69: restart:
70: match = 0;
71: checkstart = startchar;
72: sempty.startp[0] = NULL;
73: progp->se = sempty;
74: if (list[0] == NULL) {
75: list[0] = (List *)malloc(2*listsize*sizeof(List));
76: list[1] = list[0] + listsize;
77: liste[0] = list[0] + listsize - 1;
78: liste[1] = list[1] + listsize - 1;
79: if (list[0] == NULL)
80: regerror("list overflow");
81: }
82: list[0][0].inst = list[1][0].inst = NULL;
83:
84: /* Execute machine once for each character, including terminal NUL */
85: s=starts;
86: do{
87: /* fast check for first char */
88: if(checkstart && *s!=startchar)
89: continue;
90: tl=list[flag];
91: tle=liste[flag];
92: nl=list[flag^=1];
93: nle=liste[flag];
94: nl->inst=0;
95: /* Add first instruction to this list */
96: sempty.startp[0] = s;
97: (void)newthread(tl, progp->startinst, &sempty);
98: /* Execute machine until this list is empty */
99: for(tlp=tl; inst=tlp->inst; tlp++){ /* assignment = */
100: Switchstmt:
101: switch(inst->type){
102: default: /* regular character */
103: if(inst->type == *s){
104: Addinst:
105: if(newthread(nl, inst->next, &tlp->se)==nle)
106: goto realloc;
107: }
108: break;
109: case LBRA:
110: tlp->se.startp[inst->subid] = s;
111: inst=inst->next;
112: goto Switchstmt;
113: case RBRA:
114: tlp->se.endp[inst->subid] = s;
115: inst=inst->next;
116: goto Switchstmt;
117: case ANY:
118: goto Addinst;
119: case BOL:
120: if(s == starts){
121: inst=inst->next;
122: goto Switchstmt;
123: }
124: break;
125: case EOL:
126: if(*s=='\0'){
127: inst=inst->next;
128: goto Switchstmt;
129: }
130: break;
131: case CCLASS:
132: if(((char *)inst->right)[*s/8]&(1<<(*s&07)))
133: goto Addinst;
134: break;
135: case OR:
136: /* evaluate right choice later */
137: if (newthread(tlp, inst->right, &tlp->se) == tle)
138: goto realloc;
139: /* efficiency: advance and re-evaluate */
140: inst=inst->left;
141: goto Switchstmt;
142: case END: /* Match! */
143: tlp->se.endp[0] = s;
144: newmatch(&progp->se, &tlp->se);
145: break;
146: }
147: }
148: checkstart = startchar && nl->inst==NULL;
149: }while(*s++);
150: return match;
151: realloc:
152: free(list[0]);
153: list[0] = NULL;
154: listsize += LISTINCREMENT;
155: goto restart;
156: }
157:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.