Annotation of researchv10dc/cmd/icon/src/iconx/fstr.c, revision 1.1.1.1

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:    }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.