|
|
1.1 ! root 1: /* ! 2: * File: fstr.c ! 3: * Contents: center, left, map, repl, reverse, right, trim ! 4: */ ! 5: ! 6: #include "../h/rt.h" ! 7: ! 8: /* ! 9: * center(s1,n,s2) - pad s1 on left and right with s2 to length n. ! 10: */ ! 11: ! 12: FncDcl(center,3) ! 13: { ! 14: register char *s, *st; ! 15: word cnt, slen, hcnt; ! 16: char *sbuf, *s3; ! 17: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen]; ! 18: extern char *alcstr(); ! 19: ! 20: /* ! 21: * s1 must be a string. n must be a non-negative integer and defaults ! 22: * to 1. s2 must be a string and defaults to a blank. ! 23: */ ! 24: if (cvstr(&Arg1, sbuf1) == NULL) ! 25: runerr(103, &Arg1); ! 26: defshort(&Arg2, 1); ! 27: if ((cnt = IntVal(Arg2)) < 0) ! 28: runerr(205, &Arg2); ! 29: defstr(&Arg3, sbuf2, &blank); ! 30: ! 31: strreq(cnt); ! 32: ! 33: if (StrLen(Arg3) == 0) { ! 34: /* ! 35: * The padding string is null, make it a blank. ! 36: */ ! 37: slen = 1; ! 38: s3 = " "; ! 39: } ! 40: else { ! 41: slen = StrLen(Arg3); ! 42: s3 = StrLoc(Arg3); ! 43: } ! 44: ! 45: /* ! 46: * Get n bytes of string space for the new string. Start at the right ! 47: * of the new string and copy s2 into it from right to left as ! 48: * many times as will fit in the right half of the new string. ! 49: */ ! 50: sbuf = alcstr(NULL, cnt); ! 51: hcnt = cnt / 2; ! 52: s = sbuf + cnt; ! 53: while (s > sbuf + hcnt) { ! 54: st = s3 + slen; ! 55: while (st > s3 && s > sbuf + hcnt) ! 56: *--s = *--st; ! 57: } ! 58: ! 59: /* ! 60: * Start at the left end of the new string and copy s1 into it from ! 61: * left to right as many time as will fit in the left half of the ! 62: * new string. ! 63: */ ! 64: s = sbuf; ! 65: while (s < sbuf + hcnt) { ! 66: st = s3; ! 67: while (st < s3 + slen && s < sbuf + hcnt) ! 68: *s++ = *st++; ! 69: } ! 70: ! 71: slen = StrLen(Arg1); ! 72: if (cnt < slen) { ! 73: /* ! 74: * s1 is larger than the field to center it in. The source for the ! 75: * copy starts at the appropriate point in s1 and the destination ! 76: * starts at the left end of of the new string. ! 77: */ ! 78: s = sbuf; ! 79: st = StrLoc(Arg1) + slen/2 - hcnt + (~cnt&slen&1); ! 80: } ! 81: else { ! 82: /* ! 83: * s1 is smaller than the field to center it in. The source for the ! 84: * copy starts at the left end of s1 and the destination starts at ! 85: * the appropriate point in the new string. ! 86: */ ! 87: s = sbuf + hcnt - slen/2 - (~cnt&slen&1); ! 88: st = StrLoc(Arg1); ! 89: } ! 90: /* ! 91: * Perform the copy, moving min(*s1,n) bytes from st to s. ! 92: */ ! 93: if (slen > cnt) ! 94: slen = cnt; ! 95: while (slen-- > 0) ! 96: *s++ = *st++; ! 97: ! 98: /* ! 99: * Return the new string. ! 100: */ ! 101: StrLen(Arg0) = cnt; ! 102: StrLoc(Arg0) = sbuf; ! 103: Return; ! 104: } ! 105: ! 106: ! 107: /* ! 108: * left(s1,n,s2) - pad s1 on right with s2 to length n. ! 109: */ ! 110: ! 111: FncDcl(left,3) ! 112: { ! 113: register char *s, *st; ! 114: word cnt, slen; ! 115: char *sbuf, *s3, sbuf1[MaxCvtLen], sbuf2[MaxCvtLen]; ! 116: extern char *alcstr(); ! 117: ! 118: /* ! 119: * s1 must be a string. n must be a non-negative integer and defaults ! 120: * to 1. s2 must be a string and defaults to a blank. ! 121: */ ! 122: if (cvstr(&Arg1, sbuf1) == NULL) ! 123: runerr(103, &Arg1); ! 124: defshort(&Arg2, 1); ! 125: if ((cnt = IntVal(Arg2)) < 0) ! 126: runerr(205, &Arg2); ! 127: defstr(&Arg3, sbuf2, &blank); ! 128: ! 129: strreq(cnt); ! 130: if (StrLen(Arg3) == 0) { ! 131: /* ! 132: * The padding string is null, make it a blank. ! 133: */ ! 134: slen = 1; ! 135: s3 = " "; ! 136: } ! 137: else { ! 138: slen = StrLen(Arg3); ! 139: s3 = StrLoc(Arg3); ! 140: } ! 141: ! 142: /* ! 143: * Get n bytes of string space. Start at the right end of the new ! 144: * string and copy s2 into the new string as many times as it fits. ! 145: * Note that s2 is copied from right to left. ! 146: */ ! 147: sbuf = alcstr(NULL, cnt); ! 148: s = sbuf + cnt; ! 149: while (s > sbuf) { ! 150: st = s3 + slen; ! 151: while (st > s3 && s > sbuf) ! 152: *--s = *--st; ! 153: } ! 154: ! 155: /* ! 156: * Copy s1 into the new string, starting at the left end. If *s1 > n, ! 157: * only copy n bytes. ! 158: */ ! 159: s = sbuf; ! 160: slen = StrLen(Arg1); ! 161: st = StrLoc(Arg1); ! 162: if (slen > cnt) ! 163: slen = cnt; ! 164: while (slen-- > 0) ! 165: *s++ = *st++; ! 166: ! 167: /* ! 168: * Return the new string. ! 169: */ ! 170: StrLen(Arg0) = cnt; ! 171: StrLoc(Arg0) = sbuf; ! 172: Return; ! 173: } ! 174: ! 175: /* ! 176: * map(s1,s2,s3) - map s1, using s2 and s3. ! 177: */ ! 178: ! 179: /* >map */ ! 180: FncDcl(map,3) ! 181: { ! 182: register int i; ! 183: register word slen; ! 184: register char *s1, *s2, *s3; ! 185: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen], sbuf3[MaxCvtLen]; ! 186: static char maptab[256]; ! 187: extern char *alcstr(); ! 188: ! 189: /* ! 190: * s1 must be a string; s2 and s3 default to &ucase and &lcase, ! 191: * respectively. ! 192: */ ! 193: if (cvstr(&Arg1, sbuf1) == NULL) ! 194: runerr(103, &Arg1); ! 195: if (ChkNull(Arg2)) ! 196: Arg2 = ucase; ! 197: if (ChkNull(Arg3)) ! 198: Arg3 = lcase; ! 199: ! 200: /* ! 201: * If s2 and s3 are the same as for the last call of map, ! 202: * the current values in maptab can be used. Otherwise, the ! 203: * mapping information must information must be recomputed. ! 204: */ ! 205: if (!EqlDesc(maps2,Arg2) || !EqlDesc(maps3,Arg3)) { ! 206: maps2 = Arg2; ! 207: maps3 = Arg3; ! 208: ! 209: /* ! 210: * Convert s2 and s3 to strings. They must be of the ! 211: * same length. ! 212: */ ! 213: if (cvstr(&Arg2, sbuf2) == NULL) ! 214: runerr(103, &Arg2); ! 215: if (cvstr(&Arg3, sbuf3) == NULL) ! 216: runerr(103, &Arg3); ! 217: if (StrLen(Arg2) != StrLen(Arg3)) ! 218: runerr(208, 0); ! 219: ! 220: /* ! 221: * The array maptab is used to perform the mapping. First, ! 222: * maptab[i] is initialized with i for i from 0 to 255. ! 223: * Then, for each character in s2, the position in maptab ! 224: * corresponding the value of the character is assigned ! 225: * the value of the character in s3 that is in the same ! 226: * position as the character from s2. ! 227: */ ! 228: s2 = StrLoc(Arg2); ! 229: s3 = StrLoc(Arg3); ! 230: for (i = 0; i <= 255; i++) ! 231: maptab[i] = i; ! 232: for (slen = 0; slen < StrLen(Arg2); slen++) ! 233: maptab[s2[slen]&0377] = s3[slen]; ! 234: } ! 235: ! 236: if (StrLen(Arg1) == 0) { ! 237: Arg0 = emptystr; ! 238: Return; ! 239: } ! 240: ! 241: /* ! 242: * The result is a string the size of s1; ensure that much space. ! 243: */ ! 244: slen = StrLen(Arg1); ! 245: strreq(slen); ! 246: s1 = StrLoc(Arg1); ! 247: ! 248: /* ! 249: * Create the result string, but specify no value for it. ! 250: */ ! 251: StrLen(Arg0) = slen; ! 252: StrLoc(Arg0) = alcstr(NULL, slen); ! 253: s2 = StrLoc(Arg0); ! 254: /* ! 255: * Run through the string using values in maptab to do the ! 256: * mapping. ! 257: */ ! 258: while (slen-- > 0) ! 259: *s2++ = maptab[(*s1++)&0377]; ! 260: Return; ! 261: } ! 262: /* <map */ ! 263: ! 264: /* ! 265: * repl(s,n) - concatenate n copies of string s. ! 266: */ ! 267: ! 268: /* >repl */ ! 269: FncDcl(repl,2) ! 270: { ! 271: register char *sloc; ! 272: register int cnt; ! 273: long len; ! 274: char sbuf[MaxCvtLen]; ! 275: extern char *alcstr(); ! 276: ! 277: /* ! 278: * Make sure that Arg1 is a string. ! 279: */ ! 280: if (cvstr(&Arg1, sbuf) == NULL) ! 281: runerr(103, &Arg1); ! 282: ! 283: /* ! 284: * Make sure that Arg2 is an integer. ! 285: */ ! 286: switch (cvint(&Arg2, &len)) { ! 287: ! 288: case T_Integer: ! 289: if ((cnt = (int)len) >= 0) /* make sure count is not negative */ ! 290: break; ! 291: runerr(205, &Arg2); ! 292: ! 293: case T_Longint: ! 294: runerr(205, &Arg2); ! 295: ! 296: default: ! 297: runerr(101, &Arg2); ! 298: } ! 299: ! 300: /* ! 301: * Make sure the resulting string will not be too long. ! 302: */ ! 303: if ((len * StrLen(Arg1)) > MaxStrLen) ! 304: runerr(205, 0); ! 305: ! 306: /* ! 307: * Return an empty string if Arg2 is 0. ! 308: */ ! 309: if (cnt == 0) ! 310: Arg0 = emptystr; ! 311: ! 312: else { ! 313: /* ! 314: * Ensure enough space for the replicated string and allocate ! 315: * a copy of s. Then allocate and copy s n - 1 times. ! 316: */ ! 317: strreq(cnt * StrLen(Arg1)); ! 318: sloc = alcstr(StrLoc(Arg1), StrLen(Arg1)); ! 319: cnt--; ! 320: while (cnt--) ! 321: alcstr(StrLoc(Arg1), StrLen(Arg1)); ! 322: ! 323: /* ! 324: * Make Arg0 a descriptor for the replicated string. ! 325: */ ! 326: StrLen(Arg0) = (int)len * StrLen(Arg1); ! 327: StrLoc(Arg0) = sloc; ! 328: } ! 329: Return; ! 330: } ! 331: /* <repl */ ! 332: ! 333: ! 334: /* ! 335: * reverse(s) - reverse string s. ! 336: */ ! 337: ! 338: /* >reverse */ ! 339: FncDcl(reverse,1) ! 340: { ! 341: register char c, *floc, *lloc; ! 342: register word slen; ! 343: char sbuf[MaxCvtLen]; ! 344: extern char *alcstr(); ! 345: ! 346: /* ! 347: * Make sure that Arg1 is a string. ! 348: */ ! 349: if (cvstr(&Arg1, sbuf) == NULL) ! 350: runerr(103, &Arg1); ! 351: /* <reverse */ ! 352: ! 353: /* ! 354: * Ensure that there is enough room and allocate a copy of s. ! 355: */ ! 356: slen = StrLen(Arg1); ! 357: strreq(slen); ! 358: StrLen(Arg0) = slen; ! 359: StrLoc(Arg0) = alcstr(StrLoc(Arg1), slen); ! 360: ! 361: /* ! 362: * Point floc at the start of s and lloc at the end of s. Work floc ! 363: * and sloc along s in opposite directions, swapping the characters ! 364: * at floc and lloc. ! 365: */ ! 366: floc = StrLoc(Arg0); ! 367: lloc = floc + --slen; ! 368: while (floc < lloc) { ! 369: c = *floc; ! 370: *floc++ = *lloc; ! 371: *lloc-- = c; ! 372: } ! 373: Return; ! 374: } ! 375: ! 376: ! 377: /* ! 378: * right(s1,n,s2) - pad s1 on left with s2 to length n. ! 379: */ ! 380: ! 381: FncDcl(right,3) ! 382: { ! 383: register char *s, *st; ! 384: word cnt, slen; ! 385: char *sbuf, *s3, sbuf1[MaxCvtLen], sbuf2[MaxCvtLen]; ! 386: extern char *alcstr(); ! 387: ! 388: /* ! 389: * s1 must be a string. n must be a non-negative integer and defaults ! 390: * to 1. s2 must be a string and defaults to a blank. ! 391: */ ! 392: if (cvstr(&Arg1, sbuf1) == NULL) ! 393: runerr(103, &Arg1); ! 394: defshort(&Arg2, 1); ! 395: if ((cnt = IntVal(Arg2)) < 0) ! 396: runerr(205, &Arg2); ! 397: defstr(&Arg3, sbuf2, &blank); ! 398: ! 399: strreq(cnt); ! 400: ! 401: if (StrLen(Arg3) == 0) { ! 402: /* ! 403: * The padding string is null, make it a blank. ! 404: */ ! 405: slen = 1; ! 406: s3 = " "; ! 407: } ! 408: else { ! 409: slen = StrLen(Arg3); ! 410: s3 = StrLoc(Arg3); ! 411: } ! 412: ! 413: /* ! 414: * Get n bytes of string space. Start at the left end of the new ! 415: * string and copy s2 into the new string as many times as it fits. ! 416: */ ! 417: sbuf = alcstr(NULL, cnt); ! 418: s = sbuf; ! 419: while (s < sbuf + cnt) { ! 420: st = s3; ! 421: while (st < s3 + slen && s < sbuf + cnt) ! 422: *s++ = *st++; ! 423: } ! 424: ! 425: /* ! 426: * Copy s1 into the new string, starting at the right end and copying ! 427: * s2 from right to left. If *s1 > n, only copy n bytes. ! 428: */ ! 429: s = sbuf + cnt; ! 430: slen = StrLen(Arg1); ! 431: st = StrLoc(Arg1) + slen; ! 432: if (slen > cnt) ! 433: slen = cnt; ! 434: while (slen-- > 0) ! 435: *--s = *--st; ! 436: ! 437: /* ! 438: * Return the new string. ! 439: */ ! 440: StrLen(Arg0) = cnt; ! 441: StrLoc(Arg0) = sbuf; ! 442: Return; ! 443: } ! 444: ! 445: ! 446: /* ! 447: * trim(s,c) - trim trailing characters in c from s. ! 448: */ ! 449: ! 450: FncDcl(trim,2) ! 451: { ! 452: char *sloc; ! 453: char sbuf[MaxCvtLen]; ! 454: int *cs, csbuf[CsetSize]; ! 455: extern char *alcstr(); ! 456: static int spcset[CsetSize] = /* just a blank */ ! 457: cset_display(0, 0, 01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); ! 458: ! 459: /* ! 460: * s must be a string; c defaults to a cset containing a blank. ! 461: */ ! 462: switch (cvstr(&Arg1, sbuf)) { ! 463: ! 464: case NULL: ! 465: runerr(103, &Arg1); ! 466: ! 467: case Cvt: ! 468: strreq(StrLen(Arg1)); ! 469: StrLoc(Arg1) = alcstr(StrLoc(Arg1), StrLen(Arg1)); ! 470: ! 471: } ! 472: ! 473: defcset(&Arg2, &cs, csbuf, spcset); ! 474: ! 475: /* ! 476: * Start at the end of s and then back up until a character that is ! 477: * not in c is found. The actual trimming is done by having a descriptor ! 478: * that points at the string of s, but has a reduced length. ! 479: */ ! 480: Arg0 = Arg1; ! 481: sloc = StrLoc(Arg1) + StrLen(Arg1) - 1; ! 482: while (sloc >= StrLoc(Arg1) && Testb(*sloc, cs)) { ! 483: sloc--; ! 484: StrLen(Arg0)--; ! 485: } ! 486: Return; ! 487: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.