Annotation of researchv10dc/cmd/m4/m4.c, revision 1.1

1.1     ! root        1: #include       <stdio.h>
        !             2: #include       <signal.h>
        !             3: #include       "m4.h"
        !             4: 
        !             5: #define match(c,s)     (c==*s && (!s[1] || inpmatch(s+1)))
        !             6: 
        !             7: char   *xcalloc();
        !             8: 
        !             9: 
        !            10: main(argc,argv)
        !            11: char   **argv;
        !            12: {
        !            13:        register t;
        !            14: 
        !            15:        {
        !            16:        static  sigs[] = {SIGHUP, SIGINT, SIGPIPE, 0};
        !            17:        for (t=0; sigs[t]; ++t)
        !            18:                if (signal(sigs[t], SIG_IGN) != SIG_IGN)
        !            19:                        signal(sigs[t],catchsig);
        !            20:        }
        !            21: 
        !            22:        tempname = mktemp("/tmp/m4aXXXXXX");
        !            23:        close(creat(tempname,0));
        !            24: 
        !            25:        procnam = argv[0];
        !            26:        getflags(&argc,&argv);
        !            27:        initalloc();
        !            28: 
        !            29:        setfname("-");
        !            30:        if (argc>1) {
        !            31:                --argc;
        !            32:                ++argv;
        !            33:                if (strcmp(argv[0],"-")) {
        !            34:                        ifile[ifx] = xfopen(argv[0],"r");
        !            35:                        setfname(argv[0]);
        !            36:                }
        !            37:        }
        !            38: 
        !            39:        for (;;) {
        !            40:                token[0] = t = getchr();
        !            41:                token[1] = EOS;
        !            42: 
        !            43:                if (t==EOF) {
        !            44:                        if (ifx > 0) {
        !            45:                                fclose(ifile[ifx]);
        !            46:                                ipflr = ipstk[--ifx];
        !            47:                                continue;
        !            48:                        }
        !            49: 
        !            50:                        getflags(&argc,&argv);
        !            51: 
        !            52:                        if (argc<=1)
        !            53:                                if (Wrapstr) {
        !            54:                                        pbstr(Wrapstr);
        !            55:                                        Wrapstr = NULL;
        !            56:                                        continue;
        !            57:                                } else
        !            58:                                        break;
        !            59: 
        !            60:                        --argc;
        !            61:                        ++argv;
        !            62: 
        !            63:                        if (ifile[ifx]!=stdin)
        !            64:                                fclose(ifile[ifx]);
        !            65: 
        !            66:                        if (*argv[0]=='-')
        !            67:                                ifile[ifx] = stdin;
        !            68:                        else
        !            69:                                ifile[ifx] = xfopen(argv[0],"r");
        !            70: 
        !            71:                        setfname(argv[0]);
        !            72:                        continue;
        !            73:                }
        !            74: 
        !            75:                if (isalpha(t)) {
        !            76:                        register char   *tp = token+1;
        !            77:                        register        tlim = toksize;
        !            78: 
        !            79:                        while (alphanum(*tp++=getchr()))
        !            80:                                if (--tlim<=0)
        !            81:                                        error2("more than %d chars in word",
        !            82:                                                        toksize);
        !            83: 
        !            84:                        putbak(*--tp);
        !            85:                        *tp = EOS;
        !            86: 
        !            87:                        if (((struct nlist *)(*((struct nlist **)Ap)=lookup(token)))->def) {
        !            88:                                if (++Ap >= astklm) {
        !            89:                                        --Ap;
        !            90:                                        error2(astkof,stksize);
        !            91:                                }
        !            92: 
        !            93:                                if (Cp++==NULL)
        !            94:                                        Cp = callst;
        !            95: 
        !            96:                                Cp->argp = Ap;
        !            97:                                *Ap++ = op;
        !            98:                                puttok(token);
        !            99:                                stkchr(EOS);
        !           100:                                t = getchr();
        !           101:                                putbak(t);
        !           102: 
        !           103:                                if (t!='(')
        !           104:                                        pbstr("()");
        !           105:                                else    /* try to fix arg count */
        !           106:                                        *Ap++ = op;
        !           107: 
        !           108:                                Cp->plev = 0;
        !           109:                        } else {
        !           110:                                puttok(token);
        !           111:                        }
        !           112:                } else if (match(t,lquote)) {
        !           113:                        register        qlev = 1;
        !           114: 
        !           115:                        for (;;) {
        !           116:                                token[0] = t = getchr();
        !           117:                                token[1] = EOS;
        !           118: 
        !           119:                                if (match(t,rquote)) {
        !           120:                                        if (--qlev > 0)
        !           121:                                                puttok(token);
        !           122:                                        else
        !           123:                                                break;
        !           124:                                } else if (match(t,lquote)) {
        !           125:                                        ++qlev;
        !           126:                                        puttok(token);
        !           127:                                } else {
        !           128:                                        if (t==EOF)
        !           129:                                                error("EOF in quote");
        !           130: 
        !           131:                                        putchr(t);
        !           132:                                }
        !           133:                        }
        !           134:                } else if (match(t,lcom)) {
        !           135:                        puttok(token);
        !           136: 
        !           137:                        for (;;) {
        !           138:                                token[0] = t = getchr();
        !           139:                                token[1] = EOS;
        !           140: 
        !           141:                                if (match(t,rcom)) {
        !           142:                                        puttok(token);
        !           143:                                        break;
        !           144:                                } else {
        !           145:                                        if (t==EOF)
        !           146:                                                error("EOF in comment");
        !           147:                                        putchr(t);
        !           148:                                }
        !           149:                        }
        !           150:                } else if (Cp==NULL) {
        !           151:                        putchr(t);
        !           152:                } else if (t=='(') {
        !           153:                        if (Cp->plev)
        !           154:                                stkchr(t);
        !           155:                        else {
        !           156:                                /* skip white before arg */
        !           157:                                while (isspace(t=getchr()))
        !           158:                                        ;
        !           159: 
        !           160:                                putbak(t);
        !           161:                        }
        !           162: 
        !           163:                        ++Cp->plev;
        !           164:                } else if (t==')') {
        !           165:                        --Cp->plev;
        !           166: 
        !           167:                        if (Cp->plev==0) {
        !           168:                                stkchr(EOS);
        !           169:                                expand(Cp->argp,Ap-Cp->argp-1);
        !           170:                                op = *Cp->argp;
        !           171:                                Ap = Cp->argp-1;
        !           172: 
        !           173:                                if (--Cp < callst)
        !           174:                                        Cp = NULL;
        !           175:                        } else
        !           176:                                stkchr(t);
        !           177:                } else if (t==',' && Cp->plev<=1) {
        !           178:                        stkchr(EOS);
        !           179:                        *Ap = op;
        !           180: 
        !           181:                        if (++Ap >= astklm) {
        !           182:                                --Ap;
        !           183:                                error2(astkof,stksize);
        !           184:                        }
        !           185: 
        !           186:                        while (isspace(t=getchr()))
        !           187:                                ;
        !           188: 
        !           189:                        putbak(t);
        !           190:                } else
        !           191:                        stkchr(t);
        !           192:        }
        !           193: 
        !           194:        if (Cp!=NULL)
        !           195:                error("EOF in argument list");
        !           196: 
        !           197:        delexit(OK);
        !           198: }
        !           199: 
        !           200: char *
        !           201: inpmatch(s)
        !           202: register char  *s;
        !           203: {
        !           204:        register char   *tp = token+1;
        !           205: 
        !           206:        while (*s) {
        !           207:                *tp = getchr();
        !           208: 
        !           209:                if (*tp++ != *s++) {
        !           210:                        *tp = EOS;
        !           211:                        pbstr(token+1);
        !           212:                        return 0;
        !           213:                }
        !           214:        }
        !           215: 
        !           216:        *tp = EOS;
        !           217:        return token;
        !           218: }
        !           219: 
        !           220: getflags(xargc,xargv)
        !           221: register int   *xargc;
        !           222: register char  ***xargv;
        !           223: {
        !           224:        while (*xargc > 1) {
        !           225:                register char   *arg = (*xargv)[1];
        !           226: 
        !           227:                if (arg[0]!='-' || arg[1]==EOS)
        !           228:                        break;
        !           229: 
        !           230:                switch (arg[1]) {
        !           231:                case 'B':
        !           232:                        bufsize = atoi(&arg[2]);
        !           233:                        break;
        !           234:                case 'D':
        !           235:                        {
        !           236:                        register char *t;
        !           237:                        char *s[2];
        !           238: 
        !           239:                        initalloc();
        !           240: 
        !           241:                        for (t = s[0] = &arg[2]; *t; t++)
        !           242:                                if (*t=='=') {
        !           243:                                        *t++ = EOS;
        !           244:                                        break;
        !           245:                                }
        !           246: 
        !           247:                        s[1] = t;
        !           248:                        dodef(&s[-1],2);
        !           249:                        break;
        !           250:                        }
        !           251:                case 'H':
        !           252:                        hshsize = atoi(&arg[2]);
        !           253:                        break;
        !           254:                case 'S':
        !           255:                        stksize = atoi(&arg[2]);
        !           256:                        break;
        !           257:                case 'T':
        !           258:                        toksize = atoi(&arg[2]);
        !           259:                        break;
        !           260:                case 'U':
        !           261:                        {
        !           262:                        char *s[1];
        !           263: 
        !           264:                        initalloc();
        !           265:                        s[0] = &arg[2];
        !           266:                        doundef(&s[-1],1);
        !           267:                        break;
        !           268:                        }
        !           269:                case 'e':
        !           270:                        setbuf(stdout,NULL);
        !           271:                        signal(SIGINT,SIG_IGN);
        !           272:                        break;
        !           273:                case 's':
        !           274:                        /* turn on line sync */
        !           275:                        sflag = 1;
        !           276:                        break;
        !           277:                default:
        !           278:                        fprintf(stderr,"%s: bad option: %s\n",
        !           279:                                procnam,arg);
        !           280:                        delexit(NOT_OK);
        !           281:                }
        !           282: 
        !           283:                (*xargv)++;
        !           284:                --(*xargc);
        !           285:        }
        !           286: 
        !           287:        return;
        !           288: }
        !           289: 
        !           290: initalloc()
        !           291: {
        !           292:        static  done = 0;
        !           293:        register        t;
        !           294: 
        !           295:        if (done++)
        !           296:                return;
        !           297: 
        !           298:        hshtab = (struct nlist **)xcalloc(hshsize,sizeof(struct nlist *));
        !           299:        callst = (struct call *)xcalloc(stksize/3+1,sizeof(struct call));
        !           300:        Ap = argstk = (char **)xcalloc(stksize+3,sizeof(char *));
        !           301:        ipstk[0] = ipflr = ip = ibuf = xcalloc(bufsize+1,sizeof(char));
        !           302:        op = obuf = xcalloc(bufsize+1,sizeof(char));
        !           303:        token = xcalloc(toksize+1,sizeof(char));
        !           304: 
        !           305:        astklm = &argstk[stksize];
        !           306:        ibuflm = &ibuf[bufsize];
        !           307:        obuflm = &obuf[bufsize];
        !           308:        toklm = &token[toksize];
        !           309: 
        !           310:        for (t=0; barray[t].bname; ++t) {
        !           311:                static char     p[2] = {0, EOS};
        !           312: 
        !           313:                p[0] = t|~LOW7;
        !           314:                install(barray[t].bname,p,NOPUSH);
        !           315:        }
        !           316: 
        !           317:        install("unix",nullstr,NOPUSH);
        !           318: }
        !           319: 
        !           320: /*struct nlist * */
        !           321: install(nam,val,mode)
        !           322: char   *nam;
        !           323: register char  *val;
        !           324: {
        !           325:        register struct nlist *np;
        !           326:        register char   *cp;
        !           327:        int             l;
        !           328: 
        !           329:        if (mode==PUSH)
        !           330:                lookup(nam);    /* lookup sets hshval */
        !           331:        else
        !           332:                while (undef(nam))      /* undef calls lookup */
        !           333:                        ;
        !           334: 
        !           335:        np = (struct nlist *)xcalloc(1,sizeof(*np));
        !           336:        np->name = copy(nam);
        !           337:        np->next = hshtab[hshval];
        !           338:        hshtab[hshval] = np;
        !           339: 
        !           340:        cp = xcalloc((l=strlen(val))+1,sizeof(*val));
        !           341:        np->def = cp;
        !           342:        cp = &cp[l];
        !           343: 
        !           344:        while (*val)
        !           345:                *--cp = *val++;
        !           346: }
        !           347: 
        !           348: struct nlist   *
        !           349: lookup(str)
        !           350: char   *str;
        !           351: {
        !           352:        register char           *s1, *s2;
        !           353:        register struct nlist   *np;
        !           354:        static struct nlist     nodef;
        !           355: 
        !           356:        s1 = str;
        !           357: 
        !           358:        for (hshval = 0; *s1; )
        !           359:                hshval += *s1++;
        !           360: 
        !           361:        hshval %= hshsize;
        !           362: 
        !           363:        for (np = hshtab[hshval]; np!=NULL; np = np->next) {
        !           364:                s1 = str;
        !           365:                s2 = np->name;
        !           366:                while (*s1++==*s2)
        !           367:                        if (*s2++==EOS)
        !           368:                                return(np);
        !           369:        }
        !           370: 
        !           371:        return(&nodef);
        !           372: }
        !           373: 
        !           374: expand(a1,c)
        !           375: char   **a1;
        !           376: {
        !           377:        register char   *dp;
        !           378:        register struct nlist   *sp;
        !           379: 
        !           380:        sp = (struct nlist *)a1[-1];
        !           381: 
        !           382:        if (sp->tflag || trace) {
        !           383:                int     i;
        !           384: 
        !           385:                fprintf(stderr,"Trace(%d): %s",Cp-callst,a1[0]);
        !           386: 
        !           387:                if (c > 0) {
        !           388:                        fprintf(stderr,"(%s",chkbltin(a1[1]));
        !           389:                        for (i=2; i<=c; ++i)
        !           390:                                fprintf(stderr,",%s",chkbltin(a1[i]));
        !           391:                        fprintf(stderr,")");
        !           392:                }
        !           393: 
        !           394:                fprintf(stderr,"\n");
        !           395:        }
        !           396: 
        !           397:        dp = sp->def;
        !           398: 
        !           399:        for (; *dp; ++dp) {
        !           400:                if (*dp&~LOW7) {
        !           401:                        (*barray[*dp&LOW7].bfunc)(a1,c);
        !           402:                } else if (dp[1]=='$') {
        !           403:                        if (isdigit(*dp)) {
        !           404:                                register        n;
        !           405:                                if ((n = *dp-'0') <= c)
        !           406:                                        pbstr(a1[n]);
        !           407:                                ++dp;
        !           408:                        } else if (*dp=='#') {
        !           409:                                pbnum((long) c);
        !           410:                                ++dp;
        !           411:                        } else if (*dp=='*' || *dp=='@') {
        !           412:                                register i = c;
        !           413:                                char **a = a1;
        !           414: 
        !           415:                                if (i > 0)
        !           416:                                        for (;;) {
        !           417:                                                if (*dp=='@')
        !           418:                                                        pbstr(rquote);
        !           419: 
        !           420:                                                pbstr(a[i--]);
        !           421: 
        !           422:                                                if (*dp=='@')
        !           423:                                                        pbstr(lquote);
        !           424: 
        !           425:                                                if (i <= 0)
        !           426:                                                        break;
        !           427: 
        !           428:                                                pbstr(",");
        !           429:                                        }
        !           430:                                ++dp;
        !           431:                        } else
        !           432:                                putbak(*dp);
        !           433:                } else
        !           434:                        putbak(*dp);
        !           435:        }
        !           436: }
        !           437: 
        !           438: setfname(s)
        !           439: register char  *s;
        !           440: {
        !           441:        strcpy(fname[ifx],s);
        !           442:        fname[ifx+1] = fname[ifx]+strlen(s)+1;
        !           443:        fline[ifx] = 1;
        !           444:        nflag = 1;
        !           445:        lnsync(stdout);
        !           446: }
        !           447: 
        !           448: lnsync(iop)
        !           449: register FILE  *iop;
        !           450: {
        !           451:        static int cline = 0;
        !           452:        static int cfile = 0;
        !           453: 
        !           454:        if (!sflag || iop!=stdout)
        !           455:                return;
        !           456: 
        !           457:        if (nflag || ifx!=cfile) {
        !           458:                nflag = 0;
        !           459:                cfile = ifx;
        !           460:                fprintf(iop,"#line %d \"",cline = fline[ifx]);
        !           461:                fpath(iop);
        !           462:                fprintf(iop,"\"\n");
        !           463:        } else if (++cline != fline[ifx])
        !           464:                fprintf(iop,"#line %d\n",cline = fline[ifx]);
        !           465: }
        !           466: 
        !           467: fpath(iop)
        !           468: register FILE  *iop;
        !           469: {
        !           470:        register        i;
        !           471: 
        !           472:        fprintf(iop,"%s",fname[0]);
        !           473: 
        !           474:        for (i=1; i<=ifx; ++i)
        !           475:                fprintf(iop,":%s",fname[i]);
        !           476: }
        !           477: 
        !           478: catchsig()
        !           479: {
        !           480:        signal(SIGHUP,SIG_IGN);
        !           481:        signal(SIGINT,SIG_IGN);
        !           482: 
        !           483:        delexit(NOT_OK);
        !           484: }
        !           485: 
        !           486: delexit(code)
        !           487: {
        !           488:        register i;
        !           489: 
        !           490:        cf = stdout;
        !           491: 
        !           492: /*     if (ofx != 0) { /* quitting in middle of diversion */
        !           493: /*             ofx = 0;
        !           494: /*             code = NOT_OK;
        !           495: /*     }
        !           496: */
        !           497:        ofx = 0;        /* ensure that everything comes out */
        !           498:        for (i=1; i<10; i++)
        !           499:                undiv(i,code);
        !           500: 
        !           501:        tempname[7] = 'a';
        !           502:        unlink(tempname);
        !           503: 
        !           504:        if (code==OK)
        !           505:                exit(code);
        !           506: 
        !           507:        _exit(code);
        !           508: }
        !           509: 
        !           510: puttok(tp)
        !           511: register char *tp;
        !           512: {
        !           513:        if (Cp) {
        !           514:                while (*tp)
        !           515:                        stkchr(*tp++);
        !           516:        } else if (cf)
        !           517:                while (*tp)
        !           518:                        sputchr(*tp++,cf);
        !           519: }
        !           520: 
        !           521: pbstr(str)
        !           522: register char *str;
        !           523: {
        !           524:        register char *p;
        !           525: 
        !           526:        p = str;
        !           527: 
        !           528:        while (*p++)
        !           529:                ;
        !           530: 
        !           531:        --p;
        !           532: 
        !           533:        while (p > str)
        !           534:                putbak(*--p);
        !           535: }
        !           536: 
        !           537: undiv(i,code)
        !           538: register       i;
        !           539: {
        !           540:        register FILE *fp;
        !           541:        register        c;
        !           542: 
        !           543:        if (i<1 || i>9 || i==ofx || !ofile[i])
        !           544:                return;
        !           545: 
        !           546:        fclose(ofile[i]);
        !           547:        tempname[7] = 'a'+i;
        !           548: 
        !           549:        if (code==OK && cf) {
        !           550:                fp = xfopen(tempname,"r");
        !           551: 
        !           552:                while ((c=getc(fp)) != EOF)
        !           553:                        sputchr(c,cf);
        !           554: 
        !           555:                fclose(fp);
        !           556:        }
        !           557: 
        !           558:        unlink(tempname);
        !           559:        ofile[i] = NULL;
        !           560: }
        !           561: 
        !           562: char   *copy(s)
        !           563: register char *s;
        !           564: {
        !           565:        register char *p, *s1;
        !           566: 
        !           567:        p = s1 = xcalloc(strlen(s)+1,1);
        !           568: 
        !           569:        while (*s1++ = *s++)
        !           570:                ;
        !           571: 
        !           572:        return(p);
        !           573: }
        !           574: 
        !           575: pbnum(num)
        !           576: long num;
        !           577: {
        !           578:        pbnbr(num,10,1);
        !           579: }
        !           580: 
        !           581: pbnbr(nbr,base,len)
        !           582: long   nbr;
        !           583: register       base, len;
        !           584: {
        !           585:        register        neg = 0;
        !           586: 
        !           587:        if (base<=0)
        !           588:                return;
        !           589: 
        !           590:        if (nbr<0) {
        !           591:                neg = 1;
        !           592:                nbr = -nbr;
        !           593:        }
        !           594: 
        !           595:        while (nbr>0) {
        !           596:                int     i;
        !           597:                if (base>1) {
        !           598:                        i = nbr%base;
        !           599:                        nbr /= base;
        !           600:                } else {
        !           601:                        i = 1;
        !           602:                        --nbr;
        !           603:                }
        !           604:                putbak(itochr(i));
        !           605:                --len;
        !           606:        }
        !           607: 
        !           608:        while (--len >= 0)
        !           609:                putbak('0');
        !           610: 
        !           611:        if (neg)
        !           612:                putbak('-');
        !           613: }
        !           614: 
        !           615: itochr(i)
        !           616: register       i;
        !           617: {
        !           618:        if (i>9)
        !           619:                return i-10+'A';
        !           620:        else
        !           621:                return i+'0';
        !           622: }
        !           623: 
        !           624: long ctol(str)
        !           625: register char *str;
        !           626: {
        !           627:        register sign;
        !           628:        long num;
        !           629: 
        !           630:        while (isspace(*str))
        !           631:                ++str;
        !           632:        num = 0;
        !           633:        if (*str=='-') {
        !           634:                sign = -1;
        !           635:                ++str;
        !           636:        }
        !           637:        else
        !           638:                sign = 1;
        !           639:        while (isdigit(*str))
        !           640:                num = num*10 + *str++ - '0';
        !           641:        return(sign * num);
        !           642: }
        !           643: 
        !           644: min(a,b)
        !           645: {
        !           646:        if (a>b)
        !           647:                return(b);
        !           648:        return(a);
        !           649: }
        !           650: 
        !           651: FILE   *
        !           652: xfopen(name,mode)
        !           653: char   *name,
        !           654:        *mode;
        !           655: {
        !           656:        FILE    *fp;
        !           657: 
        !           658:        if ((fp=fopen(name,mode))==NULL)
        !           659:                error(badfile);
        !           660: 
        !           661:        return fp;
        !           662: }
        !           663: 
        !           664: char *
        !           665: xcalloc(nbr,size)
        !           666: {
        !           667:        register char   *ptr;
        !           668: 
        !           669:        if ((ptr=calloc(nbr,size)) == NULL)
        !           670:                error(nocore);
        !           671: 
        !           672:        return ptr;
        !           673: }
        !           674: 
        !           675: error(str)
        !           676:        char *str;
        !           677: {
        !           678:        fprintf(stderr,"\n%s:",procnam);
        !           679:        fpath(stderr);
        !           680:        fprintf(stderr,":%d %s\n",fline[ifx],str);
        !           681:        if (Cp) {
        !           682:                register struct call    *mptr;
        !           683: 
        !           684:                /* fix limit */
        !           685:                *op = EOS;
        !           686:                (Cp+1)->argp = Ap+1;
        !           687: 
        !           688:                for (mptr=callst; mptr<=Cp; ++mptr) {
        !           689:                        register char   **aptr, **lim;
        !           690: 
        !           691:                        aptr = mptr->argp;
        !           692:                        lim = (mptr+1)->argp-1;
        !           693:                        if (mptr==callst)
        !           694:                                fputs(*aptr,stderr);
        !           695:                        ++aptr;
        !           696:                        fputs("(",stderr);
        !           697:                        if (aptr < lim)
        !           698:                                for (;;) {
        !           699:                                        fputs(*aptr++,stderr);
        !           700:                                        if (aptr >= lim)
        !           701:                                                break;
        !           702:                                        fputs(",",stderr);
        !           703:                                }
        !           704:                }
        !           705:                while (--mptr >= callst)
        !           706:                        fputs(")",stderr);
        !           707: 
        !           708:                fputs("\n",stderr);
        !           709:        }
        !           710:        delexit(NOT_OK);
        !           711: }
        !           712: 
        !           713: error2(str,num)
        !           714:        char *str;
        !           715:        int num;
        !           716: {
        !           717:        char buf[500];
        !           718: 
        !           719:        fprintf(buf,str,num);
        !           720:        error(buf);
        !           721: }
        !           722: 
        !           723: char *
        !           724: chkbltin(s)
        !           725: char   *s;
        !           726: {
        !           727:        static char     buf[24];
        !           728: 
        !           729:        if (*s&~LOW7) {
        !           730:                sprintf(buf,"<%s>",barray[*s&LOW7].bname);
        !           731:                return buf;
        !           732:        }
        !           733:        return s;
        !           734: }

unix.superglobalmegacorp.com

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