Annotation of researchv10dc/cmd/icon/src/iconx/fstr.c, revision 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.