|
|
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: register 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)->m[0].sp < p->se.m[0].sp)
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 void
47: newmatch(mp, ms, sp)
48: regsubexp *mp;
49: int ms;
50: register Subexp *sp;
51: {
52: register int i;
53:
54: if (mp==NULL || ms <=0)
55: return;
56: if(mp[0].sp==0 || sp->m[0].sp<mp[0].sp ||
57: (sp->m[0].sp==mp[0].sp && sp->m[0].ep>mp[0].ep)) {
58: for (i=0; i < ms; i++)
59: mp[i] = sp->m[i];
60: }
61: }
62:
63: extern int
64: regexec(progp, starts, mp, ms)
65: Prog *progp; /* program to run */
66: char *starts; /* string to run machine on */
67: regsubexp *mp; /* subexpression elements */
68: int ms; /* number of elements pointed to by mp */
69: {
70: register flag=0;
71: register Inst *inst;
72: register List *tlp;
73: register char *s;
74: int startchar=progp->startinst->type<OPERATOR? progp->startinst->type : 0;
75: int i, checkstart;
76:
77: restart:
78: match = 0;
79: checkstart = startchar;
80: sempty.m[0].sp = NULL;
81: if (mp!=NULL && ms >0)
82: mp[0].sp = mp[0].ep = NULL;
83: if (list[0] == NULL) {
84: list[0] = (List *)malloc(2*listsize*sizeof(List));
85: list[1] = list[0] + listsize;
86: liste[0] = list[0] + listsize - 1;
87: liste[1] = list[1] + listsize - 1;
88: if (list[0] == NULL)
89: regerror("list overflow");
90: }
91: list[0][0].inst = list[1][0].inst = NULL;
92:
93: /* Execute machine once for each character, including terminal NUL */
94: s=starts;
95: do{
96: /* fast check for first char */
97: if(checkstart && *s!=startchar)
98: continue;
99: tl=list[flag];
100: tle=liste[flag];
101: nl=list[flag^=1];
102: nle=liste[flag];
103: nl->inst=0;
104: /* Add first instruction to this list */
105: sempty.m[0].sp = s;
106: (void)newthread(tl, progp->startinst, &sempty);
107: /* Execute machine until this list is empty */
108: for(tlp=tl; inst=tlp->inst; tlp++){ /* assignment = */
109: Switchstmt:
110: switch(inst->type){
111: default: /* regular character */
112: if(inst->type == *s){
113: Addinst:
114: if(newthread(nl, inst->next, &tlp->se)==nle)
115: goto realloc;
116: }
117: break;
118: case LBRA:
119: tlp->se.m[inst->subid].sp = s;
120: inst=inst->next;
121: goto Switchstmt;
122: case RBRA:
123: tlp->se.m[inst->subid].ep = s;
124: inst=inst->next;
125: goto Switchstmt;
126: case ANY:
127: goto Addinst;
128: case BOL:
129: if(s == starts){
130: inst=inst->next;
131: goto Switchstmt;
132: }
133: break;
134: case EOL:
135: if(*s=='\0'){
136: inst=inst->next;
137: goto Switchstmt;
138: }
139: break;
140: case CCLASS:
141: if(((char *)inst->right)[*s/8]&(1<<(*s&07)))
142: goto Addinst;
143: break;
144: case OR:
145: /* evaluate right choice later */
146: if (newthread(tlp, inst->right, &tlp->se) == tle)
147: goto realloc;
148: /* efficiency: advance and re-evaluate */
149: inst=inst->left;
150: goto Switchstmt;
151: case END: /* Match! */
152: match = 1;
153: tlp->se.m[0].ep = s;
154: if (mp != NULL && ms > 0) newmatch(mp, ms, &tlp->se);
155: break;
156: }
157: }
158: checkstart = startchar && nl->inst==NULL;
159: }while(*s++);
160: return match;
161: realloc:
162: free(list[0]);
163: list[0] = NULL;
164: listsize += LISTINCREMENT;
165: goto restart;
166: }
167:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.