|
|
1.1 ! root 1: #include "regprog.h" ! 2: ! 3: /* ! 4: * Parser Information ! 5: */ ! 6: typedef struct Node{ ! 7: Inst *first; ! 8: Inst *last; ! 9: }Node; ! 10: #define NSTACK 20 ! 11: static Node andstack[NSTACK]; ! 12: static Node *andp; ! 13: static int atorstack[NSTACK]; ! 14: static int *atorp; ! 15: static int cursubid; /* id of current subexpression */ ! 16: static int subidstack[NSTACK]; /* parallel to atorstack */ ! 17: static int *subidp; ! 18: static int lastwasand; /* Last token was operand */ ! 19: static int nbra; ! 20: static char *exprp; /* pointer to next character in source expression */ ! 21: static int nclass; ! 22: static Class *classp; ! 23: static Inst *freep; ! 24: static int errors; ! 25: ! 26: /* predeclared crap */ ! 27: static void operator(); ! 28: static void pushand(); ! 29: static void pushator(); ! 30: static void evaluntil(); ! 31: static void bldcclass(); ! 32: ! 33: static void ! 34: rcerror(s) ! 35: char *s; ! 36: { ! 37: errors++; ! 38: regerror(s); ! 39: } ! 40: ! 41: static Inst * ! 42: newinst(t) ! 43: int t; ! 44: { ! 45: freep->type=t; ! 46: freep->left=0; ! 47: freep->right=0; ! 48: return freep++; ! 49: } ! 50: ! 51: static void ! 52: operand(t) ! 53: int t; ! 54: { ! 55: register Inst *i; ! 56: if(lastwasand) ! 57: operator(CAT); /* catenate is implicit */ ! 58: i=newinst(t); ! 59: if(t==CCLASS) /* ugh */ ! 60: i->right=(Inst *)&(classp[nclass-1]); /* UGH! */ ! 61: pushand(i, i); ! 62: lastwasand=TRUE; ! 63: } ! 64: ! 65: static void ! 66: operator(t) ! 67: int t; ! 68: { ! 69: if(t==RBRA && --nbra<0) ! 70: rcerror("unmatched right paren"); ! 71: if(t==LBRA) { ! 72: if (++cursubid >= NSUBEXP) ! 73: rcerror ("too many subexpressions"); ! 74: nbra++; ! 75: if (lastwasand) ! 76: operator(CAT); ! 77: } else ! 78: evaluntil(t); ! 79: if(t!=RBRA) ! 80: pushator(t); ! 81: lastwasand=FALSE; ! 82: if(t==STAR || t==QUEST || t==PLUS || t==RBRA) ! 83: lastwasand=TRUE; /* these look like operands */ ! 84: } ! 85: ! 86: static void ! 87: regerr2(s, c) ! 88: char *s; ! 89: { ! 90: char buf[100]; ! 91: char *cp = buf; ! 92: while(*s) ! 93: *cp++ = *s++; ! 94: *cp++ = c; ! 95: *cp = '\0'; ! 96: rcerror(buf); ! 97: } ! 98: ! 99: static void ! 100: cant(s) ! 101: char *s; ! 102: { ! 103: char buf[100]; ! 104: strcpy(buf, "can't happen: "); ! 105: strcat(buf, s); ! 106: rcerror(buf); ! 107: } ! 108: ! 109: static void ! 110: pushand(f, l) ! 111: Inst *f, *l; ! 112: { ! 113: if(andp >= &andstack[NSTACK]) ! 114: cant("operand stack overflow"); ! 115: andp->first=f; ! 116: andp->last=l; ! 117: andp++; ! 118: } ! 119: ! 120: static void ! 121: pushator(t) ! 122: int t; ! 123: { ! 124: if(atorp >= &atorstack[NSTACK]) ! 125: cant("operator stack overflow"); ! 126: *atorp++=t; ! 127: *subidp++=cursubid; ! 128: } ! 129: ! 130: static Node * ! 131: popand(op) ! 132: { ! 133: if(andp <= &andstack[0]) ! 134: regerr2("missing operand for", op); ! 135: return --andp; ! 136: } ! 137: ! 138: static int ! 139: popator() ! 140: { ! 141: if(atorp <= &atorstack[0]) ! 142: cant("operator stack underflow"); ! 143: --subidp; ! 144: return *--atorp; ! 145: } ! 146: ! 147: static void ! 148: evaluntil(pri) ! 149: register pri; ! 150: { ! 151: register Node *op1, *op2; ! 152: register Inst *inst1, *inst2; ! 153: ! 154: while(pri==RBRA || atorp[-1]>=pri){ ! 155: switch(popator()){ ! 156: default: ! 157: rcerror("unknown operator in evaluntil"); ! 158: break; ! 159: case LBRA: /* must have been RBRA */ ! 160: op1=popand(0); ! 161: inst2=newinst(RBRA); ! 162: inst2->subid = *subidp; ! 163: op1->last->next = inst2; ! 164: inst1=newinst(LBRA); ! 165: inst1->subid = *subidp; ! 166: inst1->next=op1->first; ! 167: pushand(inst1, inst2); ! 168: return; ! 169: case OR: ! 170: op2=popand('|'); ! 171: op1=popand('|'); ! 172: inst2=newinst(NOP); ! 173: op2->last->next=inst2; ! 174: op1->last->next=inst2; ! 175: inst1=newinst(OR); ! 176: inst1->right=op1->first; ! 177: inst1->left=op2->first; ! 178: pushand(inst1, inst2); ! 179: break; ! 180: case CAT: ! 181: op2=popand(0); ! 182: op1=popand(0); ! 183: op1->last->next=op2->first; ! 184: pushand(op1->first, op2->last); ! 185: break; ! 186: case STAR: ! 187: op2=popand('*'); ! 188: inst1=newinst(OR); ! 189: op2->last->next=inst1; ! 190: inst1->right=op2->first; ! 191: pushand(inst1, inst1); ! 192: break; ! 193: case PLUS: ! 194: op2=popand('+'); ! 195: inst1=newinst(OR); ! 196: op2->last->next=inst1; ! 197: inst1->right=op2->first; ! 198: pushand(op2->first, inst1); ! 199: break; ! 200: case QUEST: ! 201: op2=popand('?'); ! 202: inst1=newinst(OR); ! 203: inst2=newinst(NOP); ! 204: inst1->left=inst2; ! 205: inst1->right=op2->first; ! 206: op2->last->next=inst2; ! 207: pushand(inst1, inst2); ! 208: break; ! 209: } ! 210: } ! 211: } ! 212: ! 213: static void ! 214: optimize(pp) ! 215: Prog *pp; ! 216: { ! 217: register Inst *inst, *target; ! 218: ! 219: for(inst=pp->firstinst; inst->type!=END; inst++){ ! 220: target=inst->next; ! 221: while(target->type == NOP) ! 222: target=target->next; ! 223: inst->next=target; ! 224: } ! 225: } ! 226: ! 227: #ifdef DEBUG ! 228: static void ! 229: dumpstack(){ ! 230: Node *stk; ! 231: int *ip; ! 232: ! 233: printf("operators\n"); ! 234: for(ip=atorstack; ip<atorp; ip++) ! 235: printf("0%o\n", *ip); ! 236: printf("operands\n"); ! 237: for(stk=andstack; stk<andp; stk++) ! 238: printf("0%o\t0%o\n", stk->first->type, stk->last->type); ! 239: } ! 240: ! 241: static void ! 242: dump(pp) ! 243: Prog *pp; ! 244: { ! 245: Inst *l; ! 246: ! 247: l=pp->firstinst; ! 248: do{ ! 249: printf("%d:\t0%o\t%d\t%d\n", l-pp->firstinst, l->type, ! 250: l->left-pp->firstinst, l->right-pp->firstinst); ! 251: }while(l++->type); ! 252: } ! 253: #endif ! 254: ! 255: static void ! 256: startlex(s) ! 257: char *s; ! 258: { ! 259: exprp=s; ! 260: nclass=0; ! 261: nbra=0; ! 262: } ! 263: ! 264: static Class * ! 265: newclass(){ ! 266: register Class *p; ! 267: register n; ! 268: ! 269: if(nclass >= NCLASS) ! 270: regerr2("too many character classes; limit", NCLASS+'0'); ! 271: p=&(classp[nclass++]); ! 272: for(n=0; n<16; n++) ! 273: p->map[n]=0; ! 274: return p; ! 275: } ! 276: ! 277: static int ! 278: lex(){ ! 279: register c= *exprp++; ! 280: ! 281: switch(c){ ! 282: case '\\': ! 283: if(*exprp) ! 284: c= *exprp++; ! 285: break; ! 286: case 0: ! 287: c=END; ! 288: --exprp; /* In case we come here again */ ! 289: break; ! 290: case '*': ! 291: c=STAR; ! 292: break; ! 293: case '?': ! 294: c=QUEST; ! 295: break; ! 296: case '+': ! 297: c=PLUS; ! 298: break; ! 299: case '|': ! 300: c=OR; ! 301: break; ! 302: case '.': ! 303: c=ANY; ! 304: break; ! 305: case '(': ! 306: c=LBRA; ! 307: break; ! 308: case ')': ! 309: c=RBRA; ! 310: break; ! 311: case '^': ! 312: c=BOL; ! 313: break; ! 314: case '$': ! 315: c=EOL; ! 316: break; ! 317: case '[': ! 318: c=CCLASS; ! 319: bldcclass(); ! 320: break; ! 321: } ! 322: return c; ! 323: } ! 324: ! 325: static int ! 326: nextc(){ ! 327: if(exprp[0]==0 || (exprp[0]=='\\' && exprp[1]==0)) ! 328: rcerror("malformed '[]'"); ! 329: if(exprp[0]=='\\'){ ! 330: exprp++; ! 331: return *exprp++|0200; ! 332: } ! 333: return *exprp++; ! 334: } ! 335: ! 336: static void ! 337: bldcclass(){ ! 338: register c1, c2; ! 339: register Class *classp; ! 340: register negate=FALSE; ! 341: ! 342: classp=newclass(); ! 343: /* we have already seen the '[' */ ! 344: if(*exprp=='^'){ ! 345: negate=TRUE; ! 346: exprp++; ! 347: } ! 348: while((c1=c2=nextc()) != ']'){ ! 349: if(*exprp=='-'){ ! 350: exprp++; /* eat '-' */ ! 351: if((c2=nextc()) == ']') ! 352: rcerror("malformed '[]'"); ! 353: } ! 354: for((c1&=0177), (c2&=0177); c1<=c2; c1++) ! 355: classp->map[c1/8] |= 1<<(c1&07); ! 356: } ! 357: if(negate) ! 358: for(c1=0; c1<16; c1++) ! 359: classp->map[c1]^=0377; ! 360: classp->map[0]&=376; /* exclude NUL */ ! 361: } ! 362: ! 363: extern char * ! 364: regcomp(s) ! 365: char *s; ! 366: { ! 367: register token; ! 368: Prog *pp; ! 369: ! 370: /* get memory for the program */ ! 371: pp = (Prog *)malloc(sizeof(Prog) + sizeof(Inst)*strlen(s)); ! 372: if (pp == NULL) { ! 373: rcerror("out of memory"); ! 374: return NULL; ! 375: } ! 376: freep = pp->firstinst; ! 377: classp = pp->class; ! 378: errors = 0; ! 379: ! 380: /* go compile the sucker */ ! 381: startlex(s); ! 382: atorp=atorstack; ! 383: andp=andstack; ! 384: subidp=subidstack; ! 385: lastwasand=FALSE; ! 386: cursubid=0; ! 387: ! 388: /* Start with a low priority operator to prime parser */ ! 389: pushator(START-1); ! 390: while((token=lex()) != END){ ! 391: if((token&0300) == OPERATOR) ! 392: operator(token); ! 393: else ! 394: operand(token); ! 395: } ! 396: ! 397: /* Close with a low priority operator */ ! 398: evaluntil(START); ! 399: ! 400: /* Force END */ ! 401: operand(END); ! 402: evaluntil(START); ! 403: #ifdef DEBUG ! 404: dumpstack(); ! 405: #endif ! 406: if(nbra) ! 407: rcerror("unmatched left paren"); ! 408: --andp; /* points to first and only operand */ ! 409: pp->startinst=andp->first; ! 410: #ifdef DEBUG ! 411: dump(pp); ! 412: #endif ! 413: optimize(pp); ! 414: #ifdef DEBUG ! 415: printf("start: %d\n", andp->first-pp->firstinst); ! 416: dump(pp); ! 417: #endif ! 418: if (errors) { ! 419: free(pp); ! 420: pp = NULL; ! 421: } ! 422: return (char *)pp; ! 423: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.