⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regexp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
intlex(void){	int c= *exprp++;	switch(c){	case '\\':		if(*exprp)			if((c= *exprp++)=='n')				c='\n';		break;	case 0:		c = END;		--exprp;	/* In case we come here again */		break;	case '*':		c = STAR;		break;	case '?':		c = QUEST;		break;	case '+':		c = PLUS;		break;	case '|':		c = OR;		break;	case '.':		c = ANY;		break;	case '(':		c = LBRA;		break;	case ')':		c = RBRA;		break;	case '^':		c = BOL;		break;	case '$':		c = EOL;		break;	case '[':		c = CCLASS;		bldcclass();		break;	}	return c;}longnextrec(void){	if(exprp[0]==0 || (exprp[0]=='\\' && exprp[1]==0))		regerror(Ebadclass);	if(exprp[0] == '\\'){		exprp++;		if(*exprp=='n'){			exprp++;			return '\n';		}		return *exprp++|0x10000;	}	return *exprp++;}voidbldcclass(void){	long c1, c2, n, na;	Rune *classp;	classp = emalloc(DCLASS*RUNESIZE);	n = 0;	na = DCLASS;	/* we have already seen the '[' */	if(*exprp == '^'){		classp[n++] = '\n';	/* don't match newline in negate case */		negateclass = TRUE;		exprp++;	}else		negateclass = FALSE;	while((c1 = nextrec()) != ']'){		if(c1 == '-'){    Error:			free(classp);			regerror(Ebadclass);		}		if(n+4 >= na){		/* 3 runes plus NUL */			na += DCLASS;			classp = erealloc(classp, na*RUNESIZE);		}		if(*exprp == '-'){			exprp++;	/* eat '-' */			if((c2 = nextrec()) == ']')				goto Error;			classp[n+0] = 0xFFFF;			classp[n+1] = c1;			classp[n+2] = c2;			n += 3;		}else			classp[n++] = c1;	}	classp[n] = 0;	if(nclass == Nclass){		Nclass += DCLASS;		class = erealloc(class, Nclass*sizeof(Rune*));	}	class[nclass++] = classp;}intclassmatch(int classno, int c, int negate){	Rune *p;	p = class[classno];	while(*p){		if(*p == 0xFFFF){			if(p[1]<=c && c<=p[2])				return !negate;			p += 3;		}else if(*p++ == c)			return !negate;	}	return negate;}/* * Note optimization in addinst: * 	*l must be pending when addinst called; if *l has been looked *		at already, the optimization is a bug. */voidaddinst(Ilist *l, Inst *inst, Rangeset *sep){	Ilist *p;	for(p = l; p->inst; p++){		if(p->inst==inst){			if((sep)->p[0].p1 < p->se.p[0].p1)				p->se= *sep;	/* this would be bug */			return;	/* It's already there */		}	}	p->inst = inst;	p->se= *sep;	(p+1)->inst = 0;}intexecute(File *f, Posn startp, Posn eof){	int flag = 0;	Inst *inst;	Ilist *tlp;	Posn p = startp;	int nnl = 0, ntl;	int c;	int wrapped = 0;	int startchar = startinst->type<OPERATOR? startinst->type : 0;	list[0][0].inst = list[1][0].inst = 0;	sel.p[0].p1 = -1;	/* Execute machine once for each character */	for(;;p++){	doloop:		c = filereadc(f, p);		if(p>=eof || c<0){			switch(wrapped++){			case 0:		/* let loop run one more click */			case 2:				break;			case 1:		/* expired; wrap to beginning */				if(sel.p[0].p1>=0 || eof!=INFINITY)					goto Return;				list[0][0].inst = list[1][0].inst = 0;				p = 0;				goto doloop;			default:				goto Return;			}		}else if(((wrapped && p>=startp) || sel.p[0].p1>0) && nnl==0)			break;		/* fast check for first char */		if(startchar && nnl==0 && c!=startchar)			continue;		tl = list[flag];		nl = list[flag^=1];		nl->inst = 0;		ntl = nnl;		nnl = 0;		if(sel.p[0].p1<0 && (!wrapped || p<startp || startp==eof)){			/* Add first instruction to this list */			if(++ntl >= NLIST)	Overflow:				error(Eoverflow);			sempty.p[0].p1 = p;			addinst(tl, startinst, &sempty);		}		/* Execute machine until this list is empty */		for(tlp = tl; inst = tlp->inst; tlp++){	/* assignment = */	Switchstmt:			switch(inst->type){			default:	/* regular character */				if(inst->type==c){	Addinst:					if(++nnl >= NLIST)						goto Overflow;					addinst(nl, inst->next, &tlp->se);				}				break;			case LBRA:				if(inst->subid>=0)					tlp->se.p[inst->subid].p1 = p;				inst = inst->next;				goto Switchstmt;			case RBRA:				if(inst->subid>=0)					tlp->se.p[inst->subid].p2 = p;				inst = inst->next;				goto Switchstmt;			case ANY:				if(c!='\n')					goto Addinst;				break;			case BOL:				if(p==0 || filereadc(f, p - 1)=='\n'){	Step:					inst = inst->next;					goto Switchstmt;				}				break;			case EOL:				if(c == '\n')					goto Step;				break;			case CCLASS:				if(c>=0 && classmatch(inst->rclass, c, 0))					goto Addinst;				break;			case NCCLASS:				if(c>=0 && classmatch(inst->rclass, c, 1))					goto Addinst;				break;			case OR:				/* evaluate right choice later */				if(++ntl >= NLIST)					goto Overflow;				addinst(tlp, inst->right, &tlp->se);				/* efficiency: advance and re-evaluate */				inst = inst->left;				goto Switchstmt;			case END:	/* Match! */				tlp->se.p[0].p2 = p;				newmatch(&tlp->se);				break;			}		}	}    Return:	return sel.p[0].p1>=0;}voidnewmatch(Rangeset *sp){	int i;	if(sel.p[0].p1<0 || sp->p[0].p1<sel.p[0].p1 ||	   (sp->p[0].p1==sel.p[0].p1 && sp->p[0].p2>sel.p[0].p2))		for(i = 0; i<NSUBEXP; i++)			sel.p[i] = sp->p[i];}intbexecute(File *f, Posn startp){	int flag = 0;	Inst *inst;	Ilist *tlp;	Posn p = startp;	int nnl = 0, ntl;	int c;	int wrapped = 0;	int startchar = bstartinst->type<OPERATOR? bstartinst->type : 0;	list[0][0].inst = list[1][0].inst = 0;	sel.p[0].p1= -1;	/* Execute machine once for each character, including terminal NUL */	for(;;--p){	doloop:		if((c = filereadc(f, p - 1))==-1){			switch(wrapped++){			case 0:		/* let loop run one more click */			case 2:				break;			case 1:		/* expired; wrap to end */				if(sel.p[0].p1>=0)			case 3:					goto Return;				list[0][0].inst = list[1][0].inst = 0;				p = f->nc;				goto doloop;			default:				goto Return;			}		}else if(((wrapped && p<=startp) || sel.p[0].p1>0) && nnl==0)			break;		/* fast check for first char */		if(startchar && nnl==0 && c!=startchar)			continue;		tl = list[flag];		nl = list[flag^=1];		nl->inst = 0;		ntl = nnl;		nnl = 0;		if(sel.p[0].p1<0 && (!wrapped || p>startp)){			/* Add first instruction to this list */			if(++ntl >= NLIST)	Overflow:				error(Eoverflow);			/* the minus is so the optimizations in addinst work */			sempty.p[0].p1 = -p;			addinst(tl, bstartinst, &sempty);		}		/* Execute machine until this list is empty */		for(tlp = tl; inst = tlp->inst; tlp++){	/* assignment = */	Switchstmt:			switch(inst->type){			default:	/* regular character */				if(inst->type == c){	Addinst:					if(++nnl >= NLIST)						goto Overflow;					addinst(nl, inst->next, &tlp->se);				}				break;			case LBRA:				if(inst->subid>=0)					tlp->se.p[inst->subid].p1 = p;				inst = inst->next;				goto Switchstmt;			case RBRA:				if(inst->subid >= 0)					tlp->se.p[inst->subid].p2 = p;				inst = inst->next;				goto Switchstmt;			case ANY:				if(c != '\n')					goto Addinst;				break;			case BOL:				if(c=='\n' || p==0){	Step:					inst = inst->next;					goto Switchstmt;				}				break;			case EOL:				if(p==f->nc || filereadc(f, p)=='\n')					goto Step;				break;			case CCLASS:				if(c>=0 && classmatch(inst->rclass, c, 0))					goto Addinst;				break;			case NCCLASS:				if(c>=0 && classmatch(inst->rclass, c, 1))					goto Addinst;				break;			case OR:				/* evaluate right choice later */				if(++ntl >= NLIST)					goto Overflow;				addinst(tlp, inst->right, &tlp->se);				/* efficiency: advance and re-evaluate */				inst = inst->left;				goto Switchstmt;			case END:	/* Match! */				tlp->se.p[0].p1 = -tlp->se.p[0].p1; /* minus sign */				tlp->se.p[0].p2 = p;				bnewmatch(&tlp->se);				break;			}		}	}    Return:	return sel.p[0].p1>=0;}voidbnewmatch(Rangeset *sp){        int  i;        if(sel.p[0].p1<0 || sp->p[0].p1>sel.p[0].p2 || (sp->p[0].p1==sel.p[0].p2 && sp->p[0].p2<sel.p[0].p1))                for(i = 0; i<NSUBEXP; i++){       /* note the reversal; p1<=p2 */                        sel.p[i].p1 = sp->p[i].p2;                        sel.p[i].p2 = sp->p[i].p1;                }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -