Annotation of 43BSD/ingres/source/ovqp/string.c, revision 1.1

1.1     ! root        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: }

unix.superglobalmegacorp.com

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