|
|
1.1 ! root 1: /* ! 2: * File: fstranl.c ! 3: * Contents: any, bal, find, many, match, move, pos, tab, upto ! 4: */ ! 5: ! 6: #include "../h/rt.h" ! 7: ! 8: /* ! 9: * any(c,s,i,j) - test if first character of s[i:j] is in c. ! 10: */ ! 11: ! 12: FncDcl(any,4) ! 13: { ! 14: register word i, j; ! 15: long l1, l2; ! 16: int *cs, csbuf[CsetSize]; ! 17: char sbuf[MaxCvtLen]; ! 18: ! 19: /* ! 20: * c must be a cset. s defaults to &subject; i defaults to &pos if s ! 21: * defaulted, 1 otherwise. j defaults to 0. ! 22: */ ! 23: if (cvcset(&Arg1, &cs, csbuf) == NULL) ! 24: runerr(104, &Arg1); ! 25: if (defstr(&Arg2, sbuf, &k_subject)) ! 26: defint(&Arg3, &l1, k_pos); ! 27: else ! 28: defint(&Arg3, &l1, (word)1); ! 29: defint(&Arg4, &l2, (word)0); ! 30: ! 31: /* ! 32: * Convert i and j to positions in s. If i == j then the specified ! 33: * substring of s is empty and any fails. Otherwise make i the smaller of ! 34: * the two. (j is of no further use.) ! 35: */ ! 36: i = cvpos(l1, StrLen(Arg2)); ! 37: if (i == 0) ! 38: Fail; ! 39: j = cvpos(l2, StrLen(Arg2)); ! 40: if (j == 0) ! 41: Fail; ! 42: if (i == j) ! 43: Fail; ! 44: if (i > j) ! 45: i = j; ! 46: ! 47: /* ! 48: * If s[i] is not in the cset c, fail. ! 49: */ ! 50: if (!Testb(StrLoc(Arg2)[i-1], cs)) ! 51: Fail; ! 52: ! 53: /* ! 54: * Return pos(s[i+1]). ! 55: */ ! 56: Arg0.dword = D_Integer; ! 57: IntVal(Arg0) = i + 1; ! 58: Return; ! 59: } ! 60: ! 61: ! 62: /* ! 63: * bal(c1,c2,c3,s,i,j) - find end of a balanced substring of s[i:j]. ! 64: * Generates successive positions. ! 65: */ ! 66: ! 67: FncDcl(bal,6) ! 68: { ! 69: register word i, j; ! 70: register cnt, c; ! 71: word t; ! 72: long l1, l2; ! 73: int *cs1, *cs2, *cs3; ! 74: int csbuf1[CsetSize], csbuf2[CsetSize], csbuf3[CsetSize]; ! 75: char sbuf[MaxCvtLen]; ! 76: static int lpar[CsetSize] = /* '(' */ ! 77: cset_display(0, 0, 0400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); ! 78: static int rpar[CsetSize] = /* ')' */ ! 79: cset_display(0, 0, 01000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); ! 80: ! 81: /* ! 82: * c1 defaults to &cset; c2 defaults to '(' (lpar); c3 defaults to ! 83: * ')' (rpar); s to &subject; i to &pos if s defaulted, 1 otherwise; ! 84: * j defaults to 0. ! 85: */ ! 86: defcset(&Arg1, &cs1, csbuf1, k_cset.bits); ! 87: defcset(&Arg2, &cs2, csbuf2, lpar); ! 88: defcset(&Arg3, &cs3, csbuf3, rpar); ! 89: if (defstr(&Arg4, sbuf, &k_subject)) ! 90: defint(&Arg5, &l1, k_pos); ! 91: else ! 92: defint(&Arg5, &l1, (word)1); ! 93: defint(&Arg6, &l2, (word)0); ! 94: ! 95: /* ! 96: * Convert i and j to positions in s and order them. ! 97: */ ! 98: i = cvpos(l1, StrLen(Arg4)); ! 99: if (i == 0) ! 100: Fail; ! 101: j = cvpos(l2, StrLen(Arg4)); ! 102: if (j == 0) ! 103: Fail; ! 104: if (i > j) { ! 105: t = i; ! 106: i = j; ! 107: j = t; ! 108: } ! 109: ! 110: /* ! 111: * Loop through characters in s[i:j]. When a character in cs2 is ! 112: * found, increment cnt; when a chracter in cs3 is found, decrement ! 113: * cnt. When cnt is 0 there have been an equal number of occurrences ! 114: * of characters in cs2 and cs3, i.e., the string to the left of ! 115: * i is balanced. If the string is balanced and the current character ! 116: * (s[i]) is in c1, suspend i. Note that if cnt drops below zero, ! 117: * bal fails. ! 118: */ ! 119: cnt = 0; ! 120: Arg0.dword = D_Integer; ! 121: while (i < j) { ! 122: c = StrLoc(Arg4)[i-1]; ! 123: if (cnt == 0 && Testb(c, cs1)) { ! 124: IntVal(Arg0) = i; ! 125: Suspend; ! 126: } ! 127: if (Testb(c, cs2)) ! 128: cnt++; ! 129: else if (Testb(c, cs3)) ! 130: cnt--; ! 131: if (cnt < 0) ! 132: Fail; ! 133: i++; ! 134: } ! 135: /* ! 136: * Eventually fail. ! 137: */ ! 138: Fail; ! 139: } ! 140: ! 141: ! 142: /* ! 143: * find(s1,s2,i,j) - find string s1 in s2[i:j] and return position in ! 144: * s2 of beginning of s1. ! 145: * Generates successive positions. ! 146: */ ! 147: ! 148: /* >find */ ! 149: FncDcl(find,4) ! 150: { ! 151: register word l; ! 152: register char *s1, *s2; ! 153: word i, j, t; ! 154: long l1, l2; ! 155: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen]; ! 156: ! 157: /* ! 158: * Arg1 must be a string. Arg2 defaults to &subject; Arg3 defaults ! 159: * to &pos if Arg2 is defaulted, or to 1 otherwise; Arg4 defaults ! 160: * to 0. ! 161: ! 162: */ ! 163: if (cvstr(&Arg1, sbuf1) == NULL) ! 164: runerr(103, &Arg1); ! 165: if (defstr(&Arg2, sbuf2, &k_subject)) ! 166: defint(&Arg3, &l1, k_pos); ! 167: else ! 168: defint(&Arg3, &l1, (word)1); ! 169: defint(&Arg4, &l2, (word)0); ! 170: ! 171: /* ! 172: * Convert i and j to absolute positions in s2 and order them ! 173: * so that i <= j. ! 174: */ ! 175: i = cvpos(l1, StrLen(Arg2)); ! 176: if (i == 0) ! 177: Fail; ! 178: j = cvpos(l2, StrLen(Arg2)); ! 179: if (j == 0) ! 180: Fail; ! 181: if (i > j) { ! 182: t = i; ! 183: i = j; ! 184: j = t; ! 185: } ! 186: ! 187: /* ! 188: * Loop through s2[i:j] trying to find s1 at each point, stopping ! 189: * when the remaining portion s2[i:j] is too short to contain s1. ! 190: */ ! 191: Arg0.dword = D_Integer; ! 192: while (i <= j - StrLen(Arg1)) { ! 193: s1 = StrLoc(Arg1); ! 194: s2 = StrLoc(Arg2) + i - 1; ! 195: l = StrLen(Arg1); ! 196: ! 197: /* ! 198: * Compare strings on a byte-wise basis; if end is reached ! 199: * before inequality is found, suspend the position of the string. ! 200: */ ! 201: do { ! 202: if (l-- <= 0) { ! 203: IntVal(Arg0) = i; ! 204: Suspend; ! 205: break; ! 206: } ! 207: } while (*s1++ == *s2++); ! 208: i++; ! 209: } ! 210: ! 211: Fail; ! 212: } ! 213: /* <find */ ! 214: ! 215: /* ! 216: * many(c,s,i,j) - find longest prefix of s[i:j] of characters in c. ! 217: */ ! 218: ! 219: FncDcl(many,4) ! 220: { ! 221: register word i, j, t; ! 222: int *cs, csbuf[CsetSize]; ! 223: long l1, l2; ! 224: char sbuf[MaxCvtLen]; ! 225: ! 226: /* ! 227: * c must be a cset. s defaults to &subject; i defaults to &pos if s ! 228: * defaulted, 1 otherwise; j defaults to 0. ! 229: */ ! 230: if (cvcset(&Arg1, &cs, csbuf) == NULL) ! 231: runerr(104, &Arg1); ! 232: if (defstr(&Arg2, sbuf, &k_subject)) ! 233: defint(&Arg3, &l1, k_pos); ! 234: else ! 235: defint(&Arg3, &l1, (word)1); ! 236: defint(&Arg4, &l2, (word)0); ! 237: ! 238: /* ! 239: * Convert i and j to absolute positions and order them. If i == j, ! 240: * then the specified substring of s is the empty string and many ! 241: * fails. ! 242: */ ! 243: i = cvpos(l1, StrLen(Arg2)); ! 244: if (i == 0) ! 245: Fail; ! 246: j = cvpos(l2, StrLen(Arg2)); ! 247: if (j == 0) ! 248: Fail; ! 249: if (i == j) ! 250: Fail; ! 251: if (i > j) { ! 252: t = i; ! 253: i = j; ! 254: j = t; ! 255: } ! 256: ! 257: /* ! 258: * Fail if first character of s[i:j] isn't in c. ! 259: */ ! 260: if (!Testb(StrLoc(Arg2)[i-1], cs)) ! 261: Fail; ! 262: ! 263: /* ! 264: * Move i along s[i:j] until a character that is not in c is found or ! 265: * the end of the string is reached. ! 266: */ ! 267: i++; ! 268: while (i < j && Testb(StrLoc(Arg2)[i-1], cs)) ! 269: i++; ! 270: ! 271: /* ! 272: * Return the position of the first character not in c. ! 273: */ ! 274: Arg0.dword = D_Integer; ! 275: IntVal(Arg0) = i; ! 276: Return; ! 277: } ! 278: ! 279: ! 280: /* ! 281: * match(s1,s2,i,j) - test if s1 is prefix of s2[i:j]. ! 282: */ ! 283: FncDcl(match,4) ! 284: { ! 285: register word i; ! 286: register char *s1, *s2; ! 287: word j, t; ! 288: long l1, l2; ! 289: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen]; ! 290: ! 291: /* ! 292: * s1 must be a string. s2 defaults to &subject; i defaults to &pos ! 293: * if s defaulted, 1 otherwise; j defaults to 0. ! 294: */ ! 295: if (cvstr(&Arg1, sbuf1) == NULL) ! 296: runerr(103, &Arg1); ! 297: if (defstr(&Arg2, sbuf2, &k_subject)) ! 298: defint(&Arg3, &l1, k_pos); ! 299: else ! 300: defint(&Arg3, &l1, (word)1); ! 301: defint(&Arg4, &l2, (word)0); ! 302: ! 303: /* ! 304: * Convert i and j to absolute positions and then make i the smaller ! 305: * of the two positions and make j the length of the substring. ! 306: */ ! 307: i = cvpos(l1, StrLen(Arg2)); ! 308: if (i == 0) ! 309: Fail; ! 310: j = cvpos(l2, StrLen(Arg2)); ! 311: if (j == 0) ! 312: Fail; ! 313: if (i > j) { ! 314: t = i; ! 315: i = j; ! 316: j = t - j; ! 317: } ! 318: else ! 319: j = j - i; ! 320: ! 321: /* ! 322: * Can't match unless s1 is as long as s2[i:j]. ! 323: */ ! 324: if (j < StrLen(Arg1)) ! 325: Fail; ! 326: ! 327: /* ! 328: * Compare s1 with s2[i:j] for *s1 characters; fail if an inequality ! 329: * if found. ! 330: */ ! 331: s1 = StrLoc(Arg1); ! 332: s2 = StrLoc(Arg2) + i - 1; ! 333: for (j = StrLen(Arg1); j > 0; j--) ! 334: if (*s1++ != *s2++) ! 335: Fail; ! 336: ! 337: /* ! 338: * Return position of end of matched string in s2. ! 339: */ ! 340: Arg0.dword = D_Integer; ! 341: IntVal(Arg0) = i + StrLen(Arg1); ! 342: Return; ! 343: } ! 344: ! 345: ! 346: /* ! 347: * move(i) - move &pos by i, return substring of &subject spanned. ! 348: * Reverses effects if resumed. ! 349: */ ! 350: FncDcl(move,1) ! 351: { ! 352: register word i, j; ! 353: long l; ! 354: word oldpos; ! 355: ! 356: /* ! 357: * i must be a (non-long) integer. ! 358: */ ! 359: switch (cvint(&Arg1, &l)) { ! 360: ! 361: case T_Integer: ! 362: j = (word)l; ! 363: break; ! 364: ! 365: case T_Longint: ! 366: Fail; ! 367: ! 368: default: ! 369: runerr(101, &Arg1); ! 370: } ! 371: ! 372: /* ! 373: * Save old &pos. Local variable i holds &pos before the move. ! 374: */ ! 375: oldpos = i = k_pos; ! 376: ! 377: /* ! 378: * If attempted move is past either end of the string, fail. ! 379: */ ! 380: if (i + j <= 0 || i + j > StrLen(k_subject) + 1) ! 381: Fail; ! 382: ! 383: /* ! 384: * Set new &pos. ! 385: */ ! 386: k_pos += j; ! 387: ! 388: /* ! 389: * Make sure j >= 0. ! 390: */ ! 391: if (j < 0) { ! 392: i += j; ! 393: j = -j; ! 394: } ! 395: ! 396: /* ! 397: * Suspend substring of &subject that was moved over. ! 398: */ ! 399: StrLen(Arg0) = j; ! 400: StrLoc(Arg0) = StrLoc(k_subject) + i - 1; ! 401: Suspend; ! 402: ! 403: /* ! 404: * If move is resumed, restore the old position and fail. ! 405: */ ! 406: k_pos = oldpos; ! 407: if (k_pos > StrLen(k_subject) + 1) ! 408: runerr(205, &tvky_pos.kyval); ! 409: Fail; ! 410: } ! 411: ! 412: ! 413: /* ! 414: * pos(i) - test if &pos is at position i in &subject. ! 415: */ ! 416: FncDcl(pos,1) ! 417: { ! 418: register word i; ! 419: long l; ! 420: ! 421: /* ! 422: * i must be an integer. ! 423: */ ! 424: if (cvint(&Arg1, &l) == NULL) ! 425: runerr(101, &Arg1); ! 426: ! 427: /* ! 428: * Fail if &pos isn't equivalent to i, return i otherwise. ! 429: */ ! 430: if ((i = cvpos(l, StrLen(k_subject))) != k_pos) ! 431: Fail; ! 432: Arg0.dword = D_Integer; ! 433: IntVal(Arg0) = i; ! 434: Return; ! 435: } ! 436: ! 437: ! 438: /* ! 439: * tab(i) - set &pos to i, return substring of &subject spanned. ! 440: * Reverses effects if resumed.. ! 441: */ ! 442: ! 443: /* >tab */ ! 444: FncDcl(tab,1) ! 445: { ! 446: register word i, j; ! 447: word t, oldpos; ! 448: long l1; ! 449: ! 450: /* ! 451: * Arg1 must be an integer. ! 452: */ ! 453: if (cvint(&Arg1, &l1) == NULL) ! 454: runerr(101, &Arg1); ! 455: /* <tab */ ! 456: ! 457: /* ! 458: * Convert j to an absolute position. ! 459: */ ! 460: j = cvpos(l1, StrLen(k_subject)); ! 461: if (j == 0) ! 462: Fail; ! 463: ! 464: /* ! 465: * Save old &pos. Local variable i holds &pos before the tab. ! 466: */ ! 467: oldpos = i = k_pos; ! 468: ! 469: /* ! 470: * Set new &pos. ! 471: */ ! 472: k_pos = j; ! 473: ! 474: /* ! 475: * Make j the length of the substring &subject[i:j] ! 476: */ ! 477: if (i > j) { ! 478: t = i; ! 479: i = j; ! 480: j = t - j; ! 481: } ! 482: else ! 483: j = j - i; ! 484: ! 485: /* ! 486: * Suspend the portion of &subject that was tabbed over. ! 487: */ ! 488: StrLoc(Arg0) = StrLoc(k_subject) + i - 1; ! 489: StrLen(Arg0) = j; ! 490: Suspend; ! 491: ! 492: /* ! 493: * If tab is resumed, restore the old position and fail. ! 494: */ ! 495: k_pos = oldpos; ! 496: if (k_pos > StrLen(k_subject) + 1) ! 497: runerr(205, &tvky_pos.kyval); ! 498: Fail; ! 499: } ! 500: ! 501: ! 502: /* ! 503: * upto(c,s,i,j) - find each occurrence in s[i:j] of a character in c. ! 504: * Generates successive positions. ! 505: */ ! 506: ! 507: FncDcl(upto,4) ! 508: { ! 509: register word i, j; ! 510: word t; ! 511: long l1, l2; ! 512: int *cs, csbuf[CsetSize]; ! 513: char sbuf[MaxCvtLen]; ! 514: ! 515: /* ! 516: * c must be a cset. s defaults to &subject; i defaults to &pos if ! 517: * s defaulted, 1 otherwise; j defaults to 0. ! 518: */ ! 519: if (cvcset(&Arg1, &cs, csbuf) == NULL) ! 520: runerr(104, &Arg1); ! 521: if (defstr(&Arg2, sbuf, &k_subject)) ! 522: defint(&Arg3, &l1, k_pos); ! 523: else ! 524: defint(&Arg3, &l1, (word)1); ! 525: defint(&Arg4, &l2, (word)0); ! 526: ! 527: /* ! 528: * Convert i and j to positions in s and order them. ! 529: */ ! 530: i = cvpos(l1, StrLen(Arg2)); ! 531: if (i == 0) ! 532: Fail; ! 533: j = cvpos(l2, StrLen(Arg2)); ! 534: if (j == 0) ! 535: Fail; ! 536: if (i > j) { ! 537: t = i; ! 538: i = j; ! 539: j = t; ! 540: } ! 541: ! 542: /* ! 543: * Look through s[i:j] and suspend position of each occurrence of ! 544: * of a character in c. ! 545: */ ! 546: while (i < j) { ! 547: if (Testb(StrLoc(Arg2)[i-1], cs)) { ! 548: Arg0.dword = D_Integer; ! 549: IntVal(Arg0) = i; ! 550: Suspend; ! 551: } ! 552: i++; ! 553: } ! 554: /* ! 555: * Eventually fail. ! 556: */ ! 557: Fail; ! 558: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.