1: # include <stdio.h> 2: # include <ingres.h> 3: # include <aux.h> 4: # include <symbol.h> 5: # include <tree.h> 6: # include "../decomp/globs.h" 7: # include <sccs.h> 8: # include <errors.h> 9: 10: char *malloc(); 11: 12: SCCSID(@(#)string.c 8.3 2/8/85) 13: 14: /* 15: ** This file contains the string 16: ** manipulation routines 17: */ 18: 19: 20: 21: 22: 23: 24: 25: /* 26: ** Concat takes the two character strings in 27: ** s1 and s2 and concatenates them together 28: ** into a new location. 29: ** 30: ** trailing blanks are removed from the first symbol. 31: ** The size of the concatenation equals the sum of 32: ** the two original strings. 33: */ 34: 35: concatsym(s1, s2) 36: register SYMBOL *s1, *s2; 37: { 38: register char *p; 39: int size1, size2, i; 40: char *px; 41: extern char *need(); 42: 43: /* size1 = size(s1);*/ /* compute size w/o trailing blanks */ 44: size1 = s1->len & I1MASK; 45: if (size1 == 0 && s1->len != 0) 46: size1++; /* don't allow string to be trunc to zero length */ 47: size2 = s2->len & I1MASK; /* size of second string remains the same */ 48: i = (s1->len & I1MASK) + size2; /* i equals sum of original sizes */ 49: if (i > MAXFIELD) 50: i = MAXFIELD; /* a string can't exceed this size */ 51: if (size2 + size1 > MAXFIELD) 52: size2 = MAXFIELD - size1; /* adjust size2 to not exceed MAXFIELD */ 53: 54: px = p = need(De.ov_ovqpbuf, i); /* request the needed space */ 55: bmove(s1->value.sym_data.cptype, p, size1); /* copy first string */ 56: p = &p[size1]; 57: bmove(s2->value.sym_data.cptype, p, size2); 58: p = &p[size2]; 59: s1->value.sym_data.cptype = px; 60: s1->len = i; 61: /* pad with blanks if necessary */ 62: i -= size1 - size2; 63: while (i--) 64: *p++ = ' '; 65: 66: # ifdef xOTR1 67: if (tTf(82, 0)) 68: { 69: printf("Concat:"); 70: prstack(s1); 71: } 72: # endif 73: } 74: /* 75: ** Size determines the size of a character symbol 76: ** without trailing blanks. 77: */ 78: 79: size(s) 80: register SYMBOL *s; 81: { 82: register char *c; 83: register int i; 84: 85: c = s->value.sym_data.cptype; 86: i = s->len & I1MASK; 87: 88: for (c += i; i; i--) 89: if(*--c != ' ') 90: break; 91: 92: return (i); 93: } 94: /* 95: ** Converts the numeric symbol to 96: ** ascii. Formats to be used are determined 97: ** by Out_arg. 98: */ 99: 100: ascii(s) 101: register SYMBOL *s; 102: { 103: register int i; 104: register char *p; 105: char temp[MAXFIELD]; 106: extern struct out_arg Out_arg; /* used for float conversions */ 107: char *locv(); 108: 109: p = temp; 110: switch(s->type) 111: { 112: 113: case INT: 114: if (s->len == 4) 115: { 116: i = Out_arg.i4width; 117: p = locv(s->value.sym_data.i4type); 118: } 119: else 120: { 121: itoa(s->value.sym_data.i2type, p); 122: if (s->len == 2) 123: i = Out_arg.i2width; 124: else 125: i = Out_arg.i1width; 126: } 127: break; 128: 129: case CHAR: 130: return; 131: 132: case FLOAT: 133: if (s->len == 4) 134: { 135: i = Out_arg.f4width; 136: ftoa(s->value.sym_data.f8type, p, i, Out_arg.f4prec, Out_arg.f4style); 137: } 138: else 139: { 140: i = Out_arg.f8width; 141: ftoa(s->value.sym_data.f8type, p, i, Out_arg.f8prec, Out_arg.f8style); 142: } 143: } 144: s->value.sym_data.cptype = need(De.ov_ovqpbuf, i); 145: pmove(p, s->value.sym_data.cptype, i, ' '); /* blank pad to fixed length i */ 146: s->type = CHAR; 147: s->len = i; 148: } 149: /* 150: ** LEXCOMP performs character comparisons between the two 151: ** strings ss1 and ss2. All blanks and null are ignored in 152: ** both strings. In addition pattern matching is performed 153: ** using the "shell syntax". Pattern matching characters 154: ** are converted to the pattern matching symbols PAT_ANY etc. 155: ** by the scanner. 156: ** 157: ** Pattern matching characters can appear in either or 158: ** both strings. Since they cannot be stored in relations, 159: ** pattern matching chars in both strings can only happen 160: ** if the user types in such an expression. 161: ** 162: ** examples: 163: ** 164: ** "Smith, Homer" = "Smith,Homer" 165: ** 166: ** "abcd" < "abcdd" 167: ** 168: ** "abcd" = "aPAT_ANYd" 169: ** 170: ** returns <0 if s1 < s2 171: ** 0 if s1 = s2 172: ** >0 if s1 > s2 173: */ 174: 175: char *S1,*S2; 176: int L1,L2; 177: 178: lexcomp(s1, l1, s2, l2, x) 179: register char *s1, *s2; 180: register int l1, l2; 181: int x; 182: { 183: char c1, c2; 184: int howmany = Patnum; /* howmany PAT_SPEC char matchings so far */ 185: int retval; 186: int i; 187: char *t1, *t2; 188: 189: # ifdef xOTR1 190: if (tTf(82, 0)) 191: { 192: printf("LEXCOMP: starting...\n"); 193: t1 = s1; 194: t2 = s2; 195: printf("howmany = %d\n", howmany); 196: printf("first string= '"); 197: for (i = 0; i < l1; i++) 198: printf("%c", *t1++); 199: printf("'\n"); 200: printf("length = %d\n", l1); 201: printf("second string= '"); 202: for (i = 0; i < l2; i++) 203: printf("%c", *t2++); 204: printf("'\n"); 205: printf("length = %d\n", l2); 206: } 207: # endif 208: /* save initial information in case a PAT_GLOB is found */ 209: if (x==0) 210: { 211: S1 = s1; 212: S2 = s2; 213: L1 = l1; 214: L2 = l2; 215: } 216: loop: 217: while (l1--) 218: { 219: switch (c1 = *s1++) 220: { 221: 222: /* case ' ': */ 223: case '\0': 224: break; 225: 226: case PAT_GLOB: 227: { 228: return(gmatch(S1,L1,S2,L2)); 229: } 230: 231: case PAT_ANY: 232: return (pmatch(FALSE, s1, l1, s2, l2)); 233: 234: case PAT_SPEC: 235: retval = pmatch(*(s1-1),++s1, --l1, s2, l2); 236: 237: /* 238: ** If there was no match in pmatch, 239: ** reset Patnum to previous value 240: */ 241: 242: # ifdef xOTR1 243: if (tTf(82,0)) 244: printf("lexcomp: return %d\n", retval); 245: 246: # endif 247: if (retval) 248: Patnum = howmany; 249: return (retval); 250: 251: case PAT_LBRAC: 252: return (lmatch(s1, l1, s2, l2)); 253: 254: default: 255: while (l2--) 256: { 257: switch (c2 = *s2++) 258: { 259: 260: /* case ' ': */ 261: case '\0': 262: continue; 263: 264: case PAT_GLOB: 265: { 266: return(gmatch(S2,L2,S1,L1)); 267: } 268: 269: case PAT_ANY: 270: return( pmatch(FALSE,s2,l2,--s1,++l1)); 271: 272: case PAT_SPEC: 273: retval = pmatch(*(s2-1),++s2, --l2, --s1, ++l1); 274: 275: # ifdef xOTR1 276: if (tTf(82,0)) 277: printf("lexcomp: retval = %d\n", retval); 278: # endif 279: 280: if (retval) 281: Patnum = howmany; 282: return (retval); 283: 284: case PAT_LBRAC: 285: return (lmatch(s2, l2, --s1, ++l1)); 286: 287: default: 288: if (c1 == c2) 289: goto loop; 290: if (c1 == PAT_ONE || c2 == PAT_ONE) 291: goto loop; 292: # ifdef xOTR1 293: if (tTf(82,0)) 294: printf("lexcomp: 2.return %d\n",c1 - c2); 295: # endif 296: return (c1 - c2); 297: } 298: } 299: # ifdef xOTR1 300: if (tTf(82,0)) 301: printf("lexcomp: returning 1\n"); 302: # endif 303: return (1); /* s1 > s2 */ 304: } 305: } 306: 307: /* examine remainder of s2 for any characters */ 308: while (l2) { 309: l2--; 310: if ((c1 = *s2++) == PAT_SPEC) 311: { 312: pat_insert("",0,*s2,0); /* insert empty string */ 313: *s2++,l2--; /* get rid of index */ 314: } 315: /* if (((c1 = *s2) != ' ') && (c1 != '\0') */ 316: if ((c1 != ' ') && (c1 != '\0') 317: && (c1 != PAT_ANY) && (c1 != PAT_SPEC)) 318: { 319: # ifdef xOTR1 320: if (tTf(82,0)) 321: printf("lexcomp: returning -1\n"); 322: # endif 323: Patnum = howmany; 324: return (-1); /* s1 < s2 */ 325: } 326: } 327: # ifdef xOTR1 328: if (tTf(82,0)) 329: printf("lexcomp: returning 0\n"); 330: # endif 331: return (0); 332: } 333: 334: 335: /* 336: ** PMATCH 337: ** 338: ** Checks if a pattern containing a pattern matching character 339: ** (either PAT_ANY or PAT_SPEC) is found in a string. 340: ** 341: ** Returns: 342: ** 0 -- if pattern found in string 343: ** -1 -- if no match 344: ** 345: ** Called By: 346: ** lexcomp 347: ** 348: ** Calls: 349: ** pat_insert, lexcomp 350: */ 351: 352: pmatch(patarg,pat, plen, str, slength) 353: char patarg; /* index for pattern matching--FALSE when no indices 354: used */ 355: char *pat; /* the string holding the pattern matching char */ 356: char *str; /* the string to be checked */ 357: int plen, slength; /* the lengths */ 358: { 359: register char d, *s; 360: register int slen,count; 361: char c; 362: 363: # ifdef xOTR1 364: if (tTf(82,0)) 365: { 366: printf("PMATCH: starting\n"); 367: printf("patarg = %c\n",patarg); 368: printf("string with pattern char = %s\n", pat); 369: printf("string len = %d \n", plen); 370: printf("string to check = %s\n", str); 371: printf("string len = %d\n", slength); 372: } 373: # endif 374: s = str; 375: slen = slength; 376: 377: if (plen == 0) 378: { 379: if ( patarg ) 380: { 381: pat_insert(str,slength,patarg,1); 382: } 383: return (0); /* a match if no more chars in p */ 384: } 385: 386: /* 387: ** If the next character in "pat" is not another 388: ** pattern matching character, then scan until 389: ** first matching char and continue comparison. 390: */ 391: if ((c = *pat) != PAT_ANY && c != PAT_SPEC 392: && c != PAT_LBRAC && c != PAT_ONE) 393: { 394: count = 0; 395: while (slen--) 396: { 397: if ((d = *s) == c || d == PAT_ANY || d == PAT_SPEC 398: || d == PAT_LBRAC && d != PAT_ONE) 399: { 400: if ( patarg ) 401: { 402: pat_insert(str,count,patarg,0); 403: } 404: if (lexcomp(s, slen + 1,pat, plen, 1) == 0) 405: { 406: return (0); 407: } 408: } 409: s++; 410: count++; 411: } 412: } 413: else 414: { 415: while (slen) 416: { 417: if (lexcomp(s++, slen--,pat, plen, 1) == 0) 418: return (0); /* match */ 419: } 420: } 421: return (-1); /* no match */ 422: } 423: 424: 425: lmatch(pat, plen, str, slen) 426: char *pat; /* the string holding the pattern matching char */ 427: char *str; /* the other string */ 428: int plen, slen; /* their respective sizes */ 429: { 430: register char *p, *s; 431: register int cc; 432: int oldc, c, found; 433: 434: # ifdef xOTR1 435: if (tTf(82,0)) 436: { 437: printf("LMATCH: starting...\n"); 438: printf("Pat = %s, length = %d\n", pat, plen); 439: printf("Str = %s, length = %d\n", str, slen); 440: } 441: # endif 442: p = pat; 443: s = str; 444: 445: /* find a non-blank, non-null char in s */ 446: while (slen--) 447: { 448: if ((c = *s++) != ' ' && c != '\0') 449: { 450: /* search for a match on 'c' */ 451: found = 0; /* assume failure */ 452: oldc = 0777; /* make previous char large */ 453: 454: while (plen--) 455: { 456: 457: switch(cc = *p++) 458: { 459: 460: case PAT_RBRAC: 461: if (found) 462: { 463: return (lexcomp(s, slen,p, plen, 1)); 464: } 465: return (-1); 466: 467: case '-': 468: if (plen-- == 0) 469: return (-1); /* not found */ 470: if (oldc <= c && c <= (cc = *p++)) 471: found++; 472: break; 473: 474: default: 475: if (c == (oldc = cc)) 476: found++; 477: } 478: } 479: return (-1); /* no match */ 480: } 481: } 482: return (1); 483: } 484: 485: 486: 487: /* 488: ** GMATCH: checks for string matches while grabbing all instances 489: ** of the string delimited by PAT_GLOB. 490: ** 491: */ 492: 493: gmatch(s1,l1,s2,l2) 494: register char *s1,*s2; 495: register int l1,l2; 496: { 497: char *start,*end,*pat,*c,*temps2; 498: int slen=0,elen=0,plen=0; 499: int index,stindex,endex; 500: int retval,templ2,smlen,first; 501: GLIST *g; 502: 503: # ifdef xOTR1 504: if (tTf(82,0)) 505: { 506: printf("GMATCH: s1 = %s\n", s1); 507: printf("GMATCH: l1 = %d\n", l1); 508: printf("GMATCH: s2= %s\n", s2); 509: printf("GMATCH: l2 = %d\n", l2); 510: } 511: # endif 512: c = s2; 513: for (c += l2; l2; l2--) 514: if(*--c != ' ') 515: break; 516: c = s1; 517: for (c += l1; l1; l1--) 518: if(*--c != ' ') 519: break; 520: 521: if (*s1 == PAT_SPEC) 522: { 523: s1 += 2; 524: l1 -= 2; 525: } 526: else if (*s1 == PAT_ANY) 527: { 528: s1++; 529: l1--; 530: } 531: c = (start = malloc(l1)); 532: while (l1-- && PAT_GLOB != *s1++) { 533: *c++ = *(s1-1); 534: slen++; 535: } 536: c = (pat = malloc(l1)); 537: while ( l1-- && *s1++ != PAT_GLOB) { 538: *c++ = *(s1-1); 539: plen++; 540: } 541: end = s1; 542: elen = l1; 543: 544: if (slen != elen && (!slen || !elen)) 545: { 546: return(-1); 547: } 548: 549: Globs = NULL; 550: if (!slen) 551: { 552: index = scanstr(s2,l2,pat,plen,1,1); 553: if (index == -1) 554: { 555: return(-1); 556: } 557: add_glob(s2,index); 558: for (;;) { /* this loop ends when index is -1 */ 559: s2 += index + plen; 560: l2 -= index + plen; 561: index = scanstr(s2, l2,pat,plen,1,1); 562: if (index == -1) 563: { /* since string is finite, guaranteed to happen */ 564: add_glob(s2,l2); 565: Globfoot->next = NULL; 566: return(0); 567: } 568: add_glob(s2,index); 569: } 570: } 571: else { 572: retval = 1; 573: first = 0; 574: temps2 = s2; 575: templ2 = 0; 576: for(;;) { 577: if (first) { 578: s2 += smlen + elen; 579: l2 -= smlen + elen; 580: templ2 += smlen + elen; 581: } 582: else 583: first = 1; 584: if ((stindex=scanstr(s2,l2,start,slen,1,1)) == -1 || 585: (endex = scanstr(s2+stindex+slen,l2-stindex-slen,end,elen,1,1)) == -1) 586: { 587: if (!retval) 588: { 589: templ2 += l2; 590: add_glob(temps2,templ2); 591: } 592: return(retval); 593: } 594: s2 += stindex + slen; 595: l2 -= stindex + slen; 596: templ2 += stindex + slen; 597: smlen = endex; 598: for (;(index = scanstr(s2,smlen,pat,plen,1,1)) != -1;) 599: { 600: retval = 0; 601: templ2 += index; 602: add_glob(temps2,templ2); 603: temps2 += templ2 + plen; 604: templ2 = 0; 605: s2 += index + plen; 606: l2 -= index + plen; 607: smlen -= index + plen; 608: } 609: } 610: } 611: 612: } 613: 614: 615: add_glob(str,slen) 616: char *str; 617: int slen; 618: { 619: # ifdef xOTR1 620: if (tTf(82,0)) 621: printf("ADD_GLOB: str = %s, slen = %d\n", str, slen); 622: # endif 623: if (Globs == NULL) { 624: Globs = (Globfoot = (GLIST *) malloc(sizeof(GLIST))); 625: Globs->string = malloc(slen); 626: bmove(str,Globs->string,slen); 627: Globlen = Globs->len = slen; 628: Globnum = 1; 629: } 630: else { 631: Globfoot->next = (GLIST *) malloc(sizeof(GLIST)); 632: Globfoot = Globfoot->next; 633: Globfoot->string = malloc(slen); 634: bmove(str,Globfoot->string,slen); 635: Globlen += (Globfoot->len = slen); 636: Globnum++; 637: } 638: 639: } 640: 641: /* 642: ** PAT_INSERT 643: ** 644: ** Moves str and its corresponding length into Pats[index] 645: ** where index refers to the PAT_SPEC index. 646: ** 647: ** May be called even though the Pats[index] string is not the one 648: ** which will eventually be used for the replace. For instance, 649: ** if the pattern matching coincides but the line number doesn't. 650: ** 651: ** Side Effects: 652: ** Patnum is incremented indicating an insertion was done. 653: ** Pats[index] record gets a new string and length. 654: ** 655: ** Returns: none 656: ** 657: ** Calls: bmove 658: ** 659: ** Called By: 660: ** pmatch, lexcomp 661: */ 662: 663: pat_insert(str,slen,where,no_blanks) 664: char *str; /* the string being moved to Pats[where] */ 665: int slen; /* length of str */ 666: char where; /* index into Pats */ 667: int no_blanks; 668: { 669: int index; /* integer value of Pats' index */ 670: int i; 671: 672: index = where - '0'; 673: if (no_blanks) /* get rid of blanks */ 674: while (*(str + slen - 1) == ' ') 675: slen--; 676: 677: if (Pats[index].string) /* for overwriting string */ 678: { 679: free(Pats[index].string); 680: Pats[index].string = NULL; /* Not really necessary, but helps with debugging */ 681: } 682: Patnum++; 683: 684: Pats[index].string = malloc(slen); 685: bmove(str,Pats[index].string,slen); /* move str to Pats[].string */ 686: Pats[index].len = slen; 687: # ifdef xOTR1 688: if (tTf(82,0)) 689: { 690: for (i = 0; i < PATNUM; i++) 691: printf("Pats[%d] = %s, len = %d\n", i,Pats[i].string, Pats[i].len); 692: } 693: # endif 694: 695: } 696: 697: 698: /* 699: ** 700: ** INSERT_CHARS replaces all [PAT_SPEC, index] pairs with strings from 701: ** the Pats[] array. The PAT_SPEC index corresponds to the index into 702: ** the Pats[] array. 703: ** 704: ** Calls: bmove 705: ** 706: ** Called by: interpret 707: ** 708: ** Returns: none 709: */ 710: 711: insert_chars(op) 712: SYMBOL *op; 713: { 714: char *st, *s, /* pointers to SYMBOL string */ 715: *new; /* pointer to new string being formed */ 716: int l, /* length of SYMBOL string */ 717: size = 0; /* size of new string being formed */ 718: int tot, /* total size of new string being formed */ 719: index, /* PAT_SPEC index */ 720: flag=0; 721: 722: # ifdef xOTR1 723: if (tTf(82,0)) 724: printf("INSERT_CHARS: starting...\n"); 725: # endif 726: l = op->len & I1MASK; 727: st = s = op->value.sym_data.cptype; 728: while (*(s+l-1) == ' ') 729: l--; /* don't worry about blanks */ 730: tot = l; 731: while (l--) { 732: if (*st == PAT_GLOB) 733: { 734: insert_glob(&s,++st,&tot,l); 735: break; 736: } 737: if (*st++ == PAT_SPEC) { 738: index = *st++ - '0'; 739: l--; 740: 741: /* subtract 2 for PAT_SPEC and corresponding index */ 742: tot += Pats[index].len - 2; 743: 744: new = malloc(tot); 745: if (size) 746: bmove(s,new,size); 747: 748: /* append the Pats[] string to the currently forming string */ 749: bmove(Pats[index].string,new+size,Pats[index].len); 750: 751: if (!flag) 752: flag = 1; 753: else 754: free(s); 755: s = new; 756: size += Pats[index].len; 757: if (l) { 758: bmove(st,new+size,l); 759: st = new + size; 760: } 761: } 762: else 763: size++; 764: } /* while */ 765: 766: /* 767: ** replace SYMBOL string with 768: ** new string and length 769: */ 770: op->value.sym_data.cptype = s; 771: op->len = tot; 772: } 773: 774: 775: insert_glob(start,rest,slen,rlen) 776: char **start,*rest; 777: int *slen,rlen; 778: { 779: char *pat = rest,*new; 780: int plen = 0,newlen,i; 781: GLIST *g; 782: 783: while (rlen-- && *rest++ != PAT_GLOB) 784: plen++; 785: /* put in error checking about 2nd PAT_GLOB */ 786: *slen -= plen + 2 + rlen; 787: newlen = *slen + rlen + Globlen + (Globnum-1)*plen; 788: new = malloc(newlen); 789: bmove(*start,new,*slen); 790: *start = new; 791: new += *slen; 792: for (i = Globnum,g=Globs;i>1;i--,g=g->next) { 793: bmove(g->string,new,g->len); 794: new += g->len; 795: bmove(pat,new,plen); 796: new += plen; 797: } 798: bmove(g->string,new,g->len); 799: new += g->len; 800: bmove(rest,new,rlen); 801: *slen = newlen; 802: } 803: 804: 805: 806: int flink[MAXFIELD]; /* array for storing failure points in string */ 807: 808: newstring(op1,op2) 809: register SYMBOL *op1,*op2; 810: { 811: int stsize,psize,index,index2; 812: 813: psize = op2->len & I1MASK; /* ignore trailing blanks */ 814: stsize = op1->len & I1MASK; 815: if (op2->start != -1) 816: { 817: index = op2->start; 818: } 819: else 820: index = scanstr(op1->value.sym_data.cptype,stsize, 821: op2->value.sym_data.cptype,psize, 822: CLOSED,(char) 1); /* get start of string */ 823: if (index != -1) { 824: index2 = index + psize; 825: bmove(op1->value.sym_data.cptype + index2, 826: op1->value.sym_data.cptype + index, stsize - index2); 827: for (index += stsize - index2; index < stsize; index++) 828: *(op1->value.sym_data.cptype + index) = ' '; 829: } 830: } 831: 832: 833: 834: createlink(pat,plen) 835: char *pat; 836: int plen; 837: { 838: int i,j; 839: 840: flink[0] = -1; 841: i = 1; 842: while (i < plen) 843: { 844: j = flink[i-1]; 845: while (j != -1 && pat[j] != pat[i-1]) 846: j = flink[j]; 847: flink[i] = j + 1; 848: i += 1; 849: } 850: } 851: 852: 853: backlink(pat,plen) 854: char *pat; 855: int plen; 856: { 857: int i,j; 858: 859: flink[plen - 1] = plen; 860: i = plen - 2; 861: while (i >= 0) 862: { 863: j = flink[i+1]; 864: while (j != plen && pat[j] != pat[i+1]) 865: j = flink[j]; 866: flink[i] = j - 1; 867: i -= 1; 868: } 869: } 870: 871: 872: 873: /* 874: ** SCANSTR: Scan a string for a pattern. 875: ** 876: ** Returns: 877: ** -1 -- couldn't find pattern in string 878: ** index in string to start of pattern -- if getstart is true 879: ** index in string following pattern -- if getstart is false 880: */ 881: 882: scanstr(str,slen,pat,plen,getstart,num) 883: char *str, /* string being scanned */ 884: *pat; /* pattern being searched for */ 885: int slen, /* str length */ 886: plen; /* pat length */ 887: int getstart; /* if true, include pat in the string to be returned */ 888: char num; /* number of occurance to look for */ 889: { 890: int i, /* index into str */ 891: j, /* index into pat */ 892: k, 893: found; /* true when pattern found in string */ 894: 895: # ifdef xOTR1 896: if (tTf(82,0)) 897: { 898: printf("SCANSTR: \n"); 899: printf("str = %s, len = %d\n", str, slen); 900: printf("pat = %s, len = %d\n", pat, plen); 901: } 902: # endif 903: 904: createlink(pat,plen); 905: i = -1; 906: 907: /* for each occurance of pattern in string */ 908: for (k = 0; k < num & I1MASK; k++) { 909: i += 1; 910: j = 0; 911: found = 0; 912: while (i < slen) { 913: 914: /* keep searching str until a potential match for pat is found */ 915: while ( j != -1 && pat[j] != str[i]) 916: j = flink[j]; 917: 918: if (j == plen-1) /* found pat in str */ 919: { 920: found = 1; 921: break; 922: } 923: else { /* else check that rest of pat matches */ 924: i += 1; 925: j += 1; 926: } 927: } 928: if (!found || i == slen) return(-1); /* didn't find pat in str */ 929: } 930: 931: /** at this point, found pattern in string **/ 932: if (getstart) 933: { 934: return(i-plen+1); 935: } 936: else 937: { 938: return(i+1); 939: } 940: } /* scanstr */ 941: 942: /* 943: ** BACKSCAN 944: ** 945: ** Searches backwards through string for pattern. 946: ** 947: ** Returns: 948: ** -1 -- if pattern not found 949: ** index in string where pattern starts -- if getstart is true 950: ** index in string right after pattern ends -- if getstart is false 951: */ 952: 953: backscan(str,slen,pat,plen,getstart,num) 954: char *str, /* string being scanned */ 955: *pat; /* pattern being searched for */ 956: int slen, /* length of string */ 957: plen; /* length of pattern */ 958: int getstart; /* if true, return pointer which includes pat */ 959: /* if false, return pointer following pat */ 960: char num; /* which occurance of pat in string */ 961: { 962: int i, /* index into string */ 963: j, /* index into pat and flink */ 964: k, /* number of occurance found */ 965: found; /* true if pattern found in string */ 966: 967: # ifdef xOTR1 968: if (tTf(82,0)) 969: { 970: printf("BACKSCAN: \n"); 971: printf("str = %s, len = %d\n", str, slen); 972: printf("pat = %s, len = %d\n", pat, plen); 973: } 974: # endif 975: backlink(pat,plen); /* set up flink for backwards scanning */ 976: i = slen ; 977: 978: /* for each occurance of pat in string */ 979: for (k = 0; k < num & I1MASK; k++) { 980: i -= 1; 981: j = plen - 1; 982: found = 0; 983: 984: /* search for pat from end of string until whole string is examined */ 985: while (i >= 0) { 986: while ( j != plen && pat[j] != str[i]) 987: j = flink[j]; 988: if (j == 0) { 989: found = 1; 990: break; 991: } 992: else { 993: i -= 1; 994: j -= 1; 995: } 996: } 997: if (!found || i < 0) return(-1); 998: } 999: /* return pointers to pattern in string */ 1000: if (getstart) 1001: { 1002: return(i); 1003: } 1004: else 1005: { 1006: return(i+plen); 1007: } 1008: } /* backscan */ 1009: 1010: getend(len,dropend,howmany) 1011: int len,dropend,howmany; 1012: { 1013: int i; 1014: 1015: for (i=0;i<howmany & I1MASK;i++) 1016: len--; 1017: if (dropend) 1018: len--; 1019: return(len); 1020: } 1021: 1022: 1023: 1024: /* 1025: ** GRABSTRING grabs a string described by a pattern matching 1026: ** interval in a query. 1027: ** 1028: ** Called by: getsymbol 1029: ** 1030: ** Calls: scanstr, backscan, getend, specdelim 1031: ** 1032: ** Returns: 1033: ** NULL -- if pattern was not found in string 1034: ** ptr to pattern which matches interval -- otherwise 1035: */ 1036: 1037: char * 1038: grabstring(strinfo,str,len,startptr) 1039: STRKEEPER *strinfo; /* info about delimitors */ 1040: char *str; /* string to search */ 1041: int *len; /* length of string */ 1042: int *startptr; 1043: { 1044: int start=0,end=0; /* start and end of substring */ 1045: int done = 0; 1046: char *s; 1047: char leftint, rightint; /* type of interval */ 1048: char leftnum, rightnum; /* number of occurrence to find */ 1049: char leftspec, rightspec; /* special chars 1= special delim */ 1050: /* 2 = search backwards */ 1051: char *leftpat, *rightpat; /* left and right patterns */ 1052: int stsearch; /* where to start searching 2nd time */ 1053: int leftlen, rightlen; /* lengths of patterns returned from specdelim*/ 1054: 1055: /* initialization */ 1056: leftint = strinfo->type[0]; 1057: rightint = strinfo->type[1]; 1058: leftnum = strinfo->number[0]; 1059: rightnum = strinfo->number[1]; 1060: leftspec = strinfo->flag[0]; 1061: rightspec = strinfo->flag[1]; 1062: leftpat = strinfo->string[0]; 1063: rightpat = strinfo->string[1]; 1064: 1065: *len &= I1MASK; /* only look at lower byte */ 1066: 1067: while (*(str+*len-1) == ' ') /* find last nonblank char of string */ 1068: *len -= 1; 1069: 1070: # ifdef xOTR1 1071: if (tTf(82,0)) 1072: { 1073: printf("GRABSTRING:\n"); 1074: printf("str = %s, len = %d\n", str, *len); 1075: printf("leftint = %d, leftnum = %d, leftspec = %d\n", leftint, leftnum, leftspec); 1076: printf("left pattern = %s, len = %d\n", leftpat, strlen(leftpat)); 1077: printf("rightint = %d, rightnum = %d, rightspec = %d\n", rightint, rightnum, rightspec); 1078: printf("right pattern = %s, len = %d\n", rightpat, strlen(rightpat)); 1079: } 1080: # endif 1081: 1082: 1083: 1084: /* search for left endpoint */ 1085: 1086: /* CASE 1: special chars */ 1087: if (leftspec & 1) 1088: { 1089: start = specdelim(str,*len,leftpat,leftint,leftnum,&leftlen); 1090: if (leftint == CLOSED) 1091: stsearch = start + leftlen; 1092: else 1093: { 1094: start += leftlen; 1095: stsearch = start; 1096: } 1097: } 1098: /* CASE 2: backwards searching */ 1099: else if (leftspec & 2) 1100: { 1101: if (leftpat == NULL) 1102: start = 1 + getend(*len,leftint,leftnum); 1103: else 1104: start = backscan(str , *len, leftpat, 1105: strlen(leftpat),leftint,leftnum); 1106: 1107: } 1108: /* CASE 3: forwards searching */ 1109: else 1110: { 1111: start = scanstr(str + start, *len, leftpat, 1112: strlen(leftpat),leftint,leftnum); 1113: if (leftint == CLOSED) 1114: stsearch = start + strlen(leftpat); 1115: else 1116: stsearch = start; 1117: } 1118: 1119: 1120: 1121: if (start == -1) /* if pattern was not found in str */ 1122: { 1123: return(NULL); 1124: } 1125: 1126: /* search for right endpoint */ 1127: 1128: /* CASE 1: special chars */ 1129: if (rightspec & 1) 1130: { 1131: if ((end = specdelim(str + stsearch,*len - stsearch,rightpat,1 - rightint,rightnum, &rightlen)) == -1) 1132: return(NULL); 1133: else 1134: { 1135: if (rightint == CLOSED) 1136: end = end + stsearch + rightlen; 1137: else 1138: end += stsearch; 1139: } 1140: } 1141: /* Backwards searching */ 1142: else if (rightspec & 2) 1143: { 1144: if (rightpat == NULL) 1145: end = 1 + getend(*len,1-rightint,rightnum); 1146: else 1147: end = backscan(str, *len, rightpat, 1148: strlen(rightpat),1 - rightint, 1149: rightnum); 1150: } 1151: /* Forwards searching */ 1152: else 1153: { 1154: 1155: if ((end = scanstr(str + stsearch, *len,rightpat, 1156: strlen(rightpat),1 - rightint, 1157: rightnum)) == -1) 1158: return(NULL); 1159: else 1160: { 1161: end += stsearch; 1162: } 1163: 1164: } 1165: 1166: 1167: if (end == -1 || end - start <= 0) /* if end of interval couldn't 1168: ** be found or end did not come 1169: ** after start */ 1170: { 1171: return(NULL); 1172: } 1173: else 1174: { 1175: *len = end - start; 1176: s = malloc(*len); 1177: bmove (str + start, s, *len); 1178: *startptr = start; 1179: } 1180: 1181: 1182: return(s); 1183: } /* grabstring */ 1184: 1185: /* 1186: ** SPECDELIM -- scan a string for a pattern specified by a special 1187: ** delimiter 1188: ** 1189: ** Parameters: 1190: ** str - string to be scanned 1191: ** slen - length of string 1192: ** dname - name of delimitor 1193: ** getstart - type of interval 1194: ** num - occurrence of pattern to look for 1195: ** 1196: ** Returns: 1197: ** index into string of pattern 1198: ** -1 if pattern not found 1199: ** -2 if delimitor was never defined 1200: ** 1201: ** Called by: 1202: ** grabstring 1203: ** 1204: */ 1205: specdelim(str, slen, dname, getstart, num, plen) 1206: char *str; 1207: int slen; 1208: char *dname; 1209: int getstart; 1210: char num; 1211: int *plen; 1212: { 1213: extern DELIMLIST *Delimhead; /* ptr to queue of delims */ 1214: DELIMLIST *d; 1215: DMAP *map; /* ptr to bitmap */ 1216: char patch; 1217: int start = -1; /* index to start of pattern */ 1218: int match; /* true while a pattern is matching */ 1219: char *savestr; 1220: int savelen; 1221: int k; 1222: int i; 1223: 1224: 1225: # ifdef xOTR1 1226: if (tTf(82,0)) 1227: { 1228: printf("SPECDELIM: starting...\n"); 1229: printf("str = %s\n",str); 1230: printf("slen = %d\n",slen); 1231: printf("delim = %s\n",dname); 1232: } 1233: # endif 1234: 1235: savestr = str; 1236: savelen = slen; 1237: *plen = 0; 1238: /* find correct delimiter in the queue */ 1239: for (d = Delimhead; d != NULL && strcmp(d->delim,dname);d = d->back) 1240: continue; 1241: 1242: if (d == NULL) 1243: { 1244: ov_err(BADDELIM); 1245: } 1246: 1247: for(k = 0;k < (num & I1MASK); k++) 1248: { 1249: if(k) 1250: { 1251: start = start - 1 + *plen; 1252: /* savestr = &savestr[start]; */ 1253: 1254: for ( i = 0; i < *plen - 1; i++) 1255: { 1256: *savestr++; 1257: savelen--; 1258: } 1259: 1260: } 1261: while (savelen > 0) 1262: { 1263: map = d->maptr; 1264: start++; 1265: *plen = 0; 1266: str = savestr; 1267: slen = savelen; 1268: *savestr++; 1269: savelen--; 1270: patch = *str++; 1271: match = TRUE; 1272: 1273: while ((map != NULL) && (slen >= 0) && (match)) 1274: { 1275: switch (map->type) 1276: { 1277: case ONE: 1278: if (test(map->bits, patch)) 1279: { 1280: map = map->next; 1281: patch = *str++; 1282: slen--; 1283: (*plen)++; 1284: } 1285: else 1286: match = FALSE; 1287: break; 1288: 1289: case ZEROMORE: 1290: while((slen >= 0) && (test(map->bits,patch))) 1291: { 1292: patch = *str++; 1293: slen--; 1294: (*plen)++; 1295: } 1296: map = map->next; 1297: break; 1298: } 1299: } 1300: 1301: if ((map == NULL)) 1302: { 1303: /* pattern was found */ 1304: break; 1305: } 1306: } 1307: if ((slen <= 1) && (map != NULL)) 1308: return(-1); 1309: } 1310: return(start); 1311: }