Annotation of 43BSDReno/pgrm/dbx/printsym.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)printsym.c 5.7 (Berkeley) 6/1/90";
                     22: #endif /* not lint */
                     23: 
                     24: /*
                     25:  * Printing of symbolic information.
                     26:  */
                     27: 
                     28: #include "defs.h"
                     29: #include "symbols.h"
                     30: #include "languages.h"
                     31: #include "printsym.h"
                     32: #include "tree.h"
                     33: #include "eval.h"
                     34: #include "mappings.h"
                     35: #include "process.h"
                     36: #include "runtime.h"
                     37: #include "machine.h"
                     38: #include "names.h"
                     39: #include "keywords.h"
                     40: #include "main.h"
                     41: #include <ctype.h>
                     42: 
                     43: #ifndef public
                     44: #endif
                     45: 
                     46: /*
                     47:  * Maximum number of arguments to a function.
                     48:  * This is used as a check for the possibility that the stack has been
                     49:  * overwritten and therefore a saved argument pointer might indicate
                     50:  * to an absurdly large number of arguments.
                     51:  */
                     52: 
                     53: #define MAXARGSPASSED 20
                     54: 
                     55: /*
                     56:  * Return a pointer to the string for the name of the class that
                     57:  * the given symbol belongs to.
                     58:  */
                     59: 
                     60: private String clname[] = {
                     61:     "bad use", "constant", "type", "variable", "array", "array",
                     62:     "dynarray", "subarray", "fileptr", "record", "field",
                     63:     "procedure", "function", "funcvar",
                     64:     "ref", "pointer", "file", "set", "range", "label", "withptr",
                     65:     "scalar", "string", "program", "improper", "variant",
                     66:     "procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
                     67: };
                     68: 
                     69: public String classname(s)
                     70: Symbol s;
                     71: {
                     72:     return clname[ord(s->class)];
                     73: }
                     74: 
                     75: /*
                     76:  * Note the entry of the given block, unless it's the main program.
                     77:  */
                     78: 
                     79: public printentry(s)
                     80: Symbol s;
                     81: {
                     82:     if (s != program) {
                     83:        printf("\nentering %s ", classname(s));
                     84:        printname(stdout, s);
                     85:        printf("\n");
                     86:     }
                     87: }
                     88: 
                     89: /*
                     90:  * Note the exit of the given block
                     91:  */
                     92: 
                     93: public printexit(s)
                     94: Symbol s;
                     95: {
                     96:     if (s != program) {
                     97:        printf("leaving %s ", classname(s));
                     98:        printname(stdout, s);
                     99:        printf("\n\n");
                    100:     }
                    101: }
                    102: 
                    103: /*
                    104:  * Note the call of s from t.
                    105:  */
                    106: 
                    107: public printcall(s, t)
                    108: Symbol s, t;
                    109: {
                    110:     printf("calling ");
                    111:     printname(stdout, s);
                    112:     printparams(s, nil);
                    113:     printf(" from %s ", classname(t));
                    114:     printname(stdout, t);
                    115:     printf("\n");
                    116: }
                    117: 
                    118: /*
                    119:  * Note the return from s.  If s is a function, print the value
                    120:  * it is returning.  This is somewhat painful, since the function
                    121:  * has actually just returned.
                    122:  */
                    123: 
                    124: public printrtn(s)
                    125: Symbol s;
                    126: {
                    127:     register Symbol t;
                    128:     register int len;
                    129:     Boolean isindirect;
                    130: 
                    131:     printf("returning ");
                    132:     if (s->class == FUNC && (!istypename(s->type,"void"))) {
                    133:        len = size(s->type);
                    134:        if (canpush(len)) {
                    135:            t = rtype(s->type);
                    136:            isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
                    137:            pushretval(len, isindirect);
                    138:            printval(s->type);
                    139:            putchar(' ');
                    140:        } else {
                    141:            printf("(value too large) ");
                    142:        }
                    143:     }
                    144:     printf("from ");
                    145:     printname(stdout, s);
                    146:     printf("\n");
                    147: }
                    148: 
                    149: /*
                    150:  * Print the values of the parameters of the given procedure or function.
                    151:  * The frame distinguishes recursive instances of a procedure.
                    152:  *
                    153:  * If the procedure or function is internal, the argument count is
                    154:  * not valid so we ignore it.
                    155:  */
                    156: 
                    157: public printparams(f, frame)
                    158: Symbol f;
                    159: Frame frame;
                    160: {
                    161:     Symbol param;
                    162:     int n, m, s;
                    163: 
                    164:     n = nargspassed(frame);
                    165:     if (isinternal(f)) {
                    166:        n = 0;
                    167:     }
                    168:     printf("(");
                    169:     param = f->chain;
                    170:     if (param != nil or n > 0) {
                    171:        m = n;
                    172:        if (param != nil) {
                    173:            for (;;) {
                    174:                s = psize(param) div sizeof(Word);
                    175:                if (s == 0) {
                    176:                    s = 1;
                    177:                }
                    178:                m -= s;
                    179:                if (showaggrs) {
                    180:                    printv(param, frame);
                    181:                } else {
                    182:                    printparamv(param, frame);
                    183:                }
                    184:                param = param->chain;
                    185:            if (param == nil) break;
                    186:                printf(", ");
                    187:            }
                    188:        }
                    189:        if (m > 0) {
                    190:            if (m > MAXARGSPASSED) {
                    191:                m = MAXARGSPASSED;
                    192:            }
                    193:            if (f->chain != nil) {
                    194:                printf(", ");
                    195:            }
                    196:            for (;;) {
                    197:                --m;
                    198:                printf("0x%x", argn(n - m, frame));
                    199:            if (m <= 0) break;
                    200:                printf(", ");
                    201:            }
                    202:        }
                    203:     }
                    204:     printf(")");
                    205: }
                    206: 
                    207: /*
                    208:  * Test if a symbol should be printed.  We don't print files,
                    209:  * for example, simply because there's no good way to do it.
                    210:  * The symbol must be within the given function.
                    211:  */
                    212: 
                    213: public Boolean should_print(s)
                    214: Symbol s;
                    215: {
                    216:     Boolean b;
                    217:     register Symbol t;
                    218: 
                    219:     switch (s->class) {
                    220:        case VAR:
                    221:        case FVAR:
                    222:            if (isparam(s)) {
                    223:                b = false;
                    224:            } else {
                    225:                t = rtype(s->type);
                    226:                if (t == nil) {
                    227:                    b = false;
                    228:                } else {
                    229:                    switch (t->class) {
                    230:                        case FILET:
                    231:                        case SET:
                    232:                        case BADUSE:
                    233:                            b = false;
                    234:                            break;
                    235: 
                    236:                        default:
                    237:                            b = true;
                    238:                            break;
                    239:                    }
                    240:                }
                    241:            }
                    242:            break;
                    243: 
                    244:        default:
                    245:            b = false;
                    246:            break;
                    247:     }
                    248:     return b;
                    249: }
                    250: 
                    251: /*
                    252:  * Print out a parameter value.
                    253:  *
                    254:  * Since this is intended to be printed on a single line with other information
                    255:  * aggregate values are not printed.
                    256:  */
                    257: 
                    258: public printparamv (p, frame)
                    259: Symbol p;
                    260: Frame frame;
                    261: {
                    262:     Symbol t;
                    263: 
                    264:     t = rtype(p->type);
                    265:     switch (t->class) {
                    266:        case ARRAY:
                    267:        case OPENARRAY:
                    268:        case DYNARRAY:
                    269:        case SUBARRAY:
                    270:            t = rtype(t->type);
                    271:            if (compatible(t, t_char)) {
                    272:                printv(p, frame);
                    273:            } else {
                    274:                printf("%s = (...)", symname(p));
                    275:            }
                    276:            break;
                    277: 
                    278:        case RECORD:
                    279:            printf("%s = (...)", symname(p));
                    280:            break;
                    281: 
                    282:        default:
                    283:            printv(p, frame);
                    284:            break;
                    285:     }
                    286: }
                    287: 
                    288: /*
                    289:  * Print the name and value of a variable.
                    290:  */
                    291: 
                    292: public printv(s, frame)
                    293: Symbol s;
                    294: Frame frame;
                    295: {
                    296:     Address addr;
                    297:     int len;
                    298: 
                    299:     if (isambiguous(s) and ismodule(container(s))) {
                    300:        printname(stdout, s);
                    301:        printf(" = ");
                    302:     } else {
                    303:        printf("%s = ", symname(s));
                    304:     }
                    305:     if (isvarparam(s) and not isopenarray(s)) {
                    306:        rpush(address(s, frame), sizeof(Address));
                    307:        addr = pop(Address);
                    308:     } else {
                    309:        addr = address(s, frame);
                    310:     }
                    311:     len = size(s);
                    312:     if (not canpush(len)) {
                    313:        printf("*** expression too large ***");
                    314:     } else if (isreg(s)) {
                    315:        push(Address, addr);
                    316:        printval(s->type);
                    317:     } else {
                    318:        rpush(addr, len);
                    319:        printval(s->type);
                    320:     }
                    321: }
                    322: 
                    323: /*
                    324:  * Print out the name of a symbol.
                    325:  */
                    326: 
                    327: public printname(f, s)
                    328: File f;
                    329: Symbol s;
                    330: {
                    331:     if (s == nil) {
                    332:        fprintf(f, "(noname)");
                    333:     } else if (s == program) {
                    334:        fprintf(f, ".");
                    335:     } else if (isredirected() or isambiguous(s)) {
                    336:        printwhich(f, s);
                    337:     } else {
                    338:        fprintf(f, "%s", symname(s));
                    339:     }
                    340: }
                    341: 
                    342: /*
                    343:  * Print the fully specified variable that is described by the given identifer.
                    344:  */
                    345: 
                    346: public printwhich(f, s)
                    347: File f;
                    348: Symbol s;
                    349: {
                    350:     printouter(f, container(s));
                    351:     fprintf(f, "%s", symname(s));
                    352: }
                    353: 
                    354: /*
                    355:  * Print the fully qualified name of each symbol that has the same name
                    356:  * as the given symbol.
                    357:  */
                    358: 
                    359: public printwhereis(f, s)
                    360: File f;
                    361: Symbol s;
                    362: {
                    363:     register Name n;
                    364:     register Symbol t;
                    365: 
                    366:     checkref(s);
                    367:     n = s->name;
                    368:     t = lookup(n);
                    369:     printwhich(f, t);
                    370:     t = t->next_sym;
                    371:     while (t != nil) {
                    372:        if (t->name == n) {
                    373:            putc(' ', f);
                    374:            printwhich(f, t);
                    375:        }
                    376:        t = t->next_sym;
                    377:     }
                    378:     putc('\n', f);
                    379: }
                    380: 
                    381: private printouter(f, s)
                    382: File f;
                    383: Symbol s;
                    384: {
                    385:     Symbol outer;
                    386: 
                    387:     if (s != nil) {
                    388:        outer = container(s);
                    389:        if (outer != nil and outer != program) {
                    390:            printouter(f, outer);
                    391:        }
                    392:        fprintf(f, "%s.", symname(s));
                    393:     }
                    394: }
                    395: 
                    396: public printdecl(s)
                    397: Symbol s;
                    398: {
                    399:     Language lang;
                    400: 
                    401:     checkref(s);
                    402:     if (s->language == nil or s->language == primlang) {
                    403:        lang = findlanguage(".s");
                    404:     } else {
                    405:        lang = s->language;
                    406:     }
                    407:     (*language_op(lang, L_PRINTDECL))(s);
                    408: }
                    409: 
                    410: /*
                    411:  * Straight dump of symbol information.
                    412:  */
                    413: 
                    414: public psym(s)
                    415: Symbol s;
                    416: {
                    417:     printf("name\t%s\n", symname(s));
                    418:     printf("lang\t%s\n", language_name(s->language));
                    419:     printf("level\t%d\n", s->level);
                    420:     printf("class\t%s\n", classname(s));
                    421:     printf("type\t0x%x", s->type);
                    422:     if (s->type != nil and s->type->name != nil) {
                    423:        printf(" (%s)", symname(s->type));
                    424:     }
                    425:     printf("\nchain\t0x%x", s->chain);
                    426:     if (s->chain != nil and s->chain->name != nil) {
                    427:        printf(" (%s)", symname(s->chain));
                    428:     }
                    429:     printf("\nblock\t0x%x", s->block);
                    430:     if (s->block != nil and s->block->name != nil) {
                    431:        printf(" (");
                    432:        printname(stdout, s->block);
                    433:        putchar(')');
                    434:     }
                    435:     putchar('\n');
                    436:     switch (s->class) {
                    437:        case TYPE:
                    438:            printf("size\t%d\n", size(s));
                    439:            break;
                    440: 
                    441:        case VAR:
                    442:        case REF:
                    443:            switch (s->storage) {
                    444:                case INREG:
                    445:                    printf("reg\t%d\n", s->symvalue.offset);
                    446:                    break;
                    447: 
                    448:                case STK:
                    449:                    printf("offset\t%d\n", s->symvalue.offset);
                    450:                    break;
                    451: 
                    452:                case EXT:
                    453:                    printf("address\t0x%x\n", s->symvalue.offset);
                    454:                    break;
                    455:            }
                    456:            printf("size\t%d\n", size(s));
                    457:            break;
                    458: 
                    459:        case RECORD:
                    460:        case VARNT:
                    461:            printf("size\t%d\n", s->symvalue.offset);
                    462:            break;
                    463: 
                    464:        case FIELD:
                    465:            printf("offset\t%d\n", s->symvalue.field.offset);
                    466:            printf("size\t%d\n", s->symvalue.field.length);
                    467:            break;
                    468: 
                    469:        case PROG:
                    470:        case PROC:
                    471:        case FUNC:
                    472:            printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
                    473:            if (isinline(s)) {
                    474:                printf("inline procedure\n");
                    475:            }
                    476:            if (nosource(s)) {
                    477:                printf("does not have source information\n");
                    478:            } else {
                    479:                printf("has source information\n");
                    480:            }
                    481:            break;
                    482: 
                    483:        case RANGE:
                    484:            prangetype(s->symvalue.rangev.lowertype);
                    485:            printf("lower\t%d\n", s->symvalue.rangev.lower);
                    486:            prangetype(s->symvalue.rangev.uppertype);
                    487:            printf("upper\t%d\n", s->symvalue.rangev.upper);
                    488:            break;
                    489: 
                    490:        default:
                    491:            /* do nothing */
                    492:            break;
                    493:     }
                    494: }
                    495: 
                    496: private prangetype(r)
                    497: Rangetype r;
                    498: {
                    499:     switch (r) {
                    500:        case R_CONST:
                    501:            printf("CONST");
                    502:            break;
                    503: 
                    504:        case R_ARG:
                    505:            printf("ARG");
                    506:            break;
                    507: 
                    508:        case R_TEMP:
                    509:            printf("TEMP");
                    510:            break;
                    511: 
                    512:        case R_ADJUST:
                    513:            printf("ADJUST");
                    514:            break;
                    515:     }
                    516: }
                    517: 
                    518: /*
                    519:  * Print out the value on top of the stack according to the given type.
                    520:  */
                    521: 
                    522: public printval(t)
                    523: Symbol t;
                    524: {
                    525:     Symbol s;
                    526: 
                    527:     checkref(t);
                    528:     if (t->class == TYPEREF) {
                    529:        resolveRef(t);
                    530:     }
                    531:     switch (t->class) {
                    532:        case PROC:
                    533:        case FUNC:
                    534:            s = pop(Symbol);
                    535:            printf("%s", symname(s));
                    536:            break;
                    537: 
                    538:        default:
                    539:            if (t->language == nil or t->language == primlang) {
                    540:                (*language_op(findlanguage(".c"), L_PRINTVAL))(t);
                    541:            } else {
                    542:                (*language_op(t->language, L_PRINTVAL))(t);
                    543:            }
                    544:            break;
                    545:     }
                    546: }
                    547: 
                    548: /*
                    549:  * Print out the value of a record, field by field.
                    550:  */
                    551: 
                    552: public printrecord(s)
                    553: Symbol s;
                    554: {
                    555:     Symbol f;
                    556: 
                    557:     if (s->chain == nil) {
                    558:        error("record has no fields");
                    559:     }
                    560:     printf("(");
                    561:     sp -= size(s);
                    562:     f = s->chain;
                    563:     if (f != nil) {
                    564:        for (;;) {
                    565:            printfield(f);
                    566:            f = f->chain;
                    567:        if (f == nil) break;
                    568:            printf(", ");
                    569:        }
                    570:     }
                    571:     printf(")");
                    572: }
                    573: 
                    574: /*
                    575:  * Print out a field.
                    576:  */
                    577: 
                    578: private printfield(f)
                    579: Symbol f;
                    580: {
                    581:     Stack *savesp;
                    582:     register int off, len;
                    583: 
                    584:     printf("%s = ", symname(f));
                    585:     savesp = sp;
                    586:     off = f->symvalue.field.offset;
                    587:     len = f->symvalue.field.length;
                    588:     sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
                    589:     printval(f);
                    590:     sp = savesp;
                    591: }
                    592: 
                    593: /*
                    594:  * Print out the contents of an array.
                    595:  * Haven't quite figured out what the best format is.
                    596:  *
                    597:  * This is rather inefficient.
                    598:  *
                    599:  * The "2*elsize" is there since "printval" drops the stack by elsize.
                    600:  */
                    601: 
                    602: public printarray(a)
                    603: Symbol a;
                    604: {
                    605:     Stack *savesp, *newsp;
                    606:     Symbol eltype;
                    607:     long elsize;
                    608:     String sep;
                    609: 
                    610:     savesp = sp;
                    611:     sp -= (size(a));
                    612:     newsp = sp;
                    613:     eltype = rtype(a->type);
                    614:     elsize = size(eltype);
                    615:     printf("(");
                    616:     if (eltype->class == RECORD or eltype->class == ARRAY or
                    617:       eltype->class == VARNT) {
                    618:        sep = "\n";
                    619:        putchar('\n');
                    620:     } else {
                    621:        sep = ", ";
                    622:     }
                    623:     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
                    624:        if (sp - elsize != newsp) {
                    625:            fputs(sep, stdout);
                    626:        }
                    627:        printval(eltype);
                    628:     }
                    629:     sp = newsp;
                    630:     if (streq(sep, "\n")) {
                    631:        putchar('\n');
                    632:     }
                    633:     printf(")");
                    634: }
                    635: 
                    636: /*
                    637:  * Print out the value of a real number in Pascal notation.
                    638:  * This is, unfortunately, different than what one gets
                    639:  * from "%g" in printf.
                    640:  */
                    641: 
                    642: public prtreal(r)
                    643: double r;
                    644: {
                    645:     extern char *index();
                    646:     char buf[256];
                    647: 
                    648: #   ifdef IRIS
                    649:        sprintf(buf, "%lg", r);
                    650: #   else
                    651:        sprintf(buf, "%g", r);
                    652: #   endif
                    653:     if (buf[0] == '.') {
                    654:        printf("0%s", buf);
                    655:     } else if (buf[0] == '-' and buf[1] == '.') {
                    656:        printf("-0%s", &buf[1]);
                    657:     } else {
                    658:        printf("%s", buf);
                    659:     }
                    660:     if (index(buf, '.') == nil) {
                    661:        printf(".0");
                    662:     }
                    663: }
                    664: 
                    665: /*
                    666:  * Print out a character using ^? notation for unprintables.
                    667:  */
                    668: 
                    669: public printchar(c)
                    670: char c;
                    671: {
                    672:     if (c == 0) {
                    673:        putchar('\\');
                    674:        putchar('0');
                    675:     } else if (c == '\n') {
                    676:        putchar('\\');
                    677:        putchar('n');
                    678:     } else if (c > 0 and c < ' ') {
                    679:        putchar('^');
                    680:        putchar(c - 1 + 'A');
                    681:     } else if (c >= ' ' && c <= '~') {
                    682:        putchar(c);
                    683:     } else {
                    684:        printf("\\0%o",c&0xff);
                    685:     }
                    686: }
                    687: 
                    688: /*
                    689:  * Print out a value for a range type (integer, char, or boolean).
                    690:  */
                    691: 
                    692: public printRangeVal (val, t)
                    693: long val;
                    694: Symbol t;
                    695: {
                    696:     if (t == t_boolean->type or istypename(t->type, "boolean")) {
                    697:        if ((boolean) val) {
                    698:            printf("true");
                    699:        } else {
                    700:            printf("false");
                    701:        }
                    702:     } else if (t == t_char->type or istypename(t->type, "char")) {
                    703:        if (varIsSet("$hexchars")) {
                    704:            printf("0x%lx", val);
                    705:        } else {
                    706:            putchar('\'');
                    707:            printchar(val);
                    708:            putchar('\'');
                    709:        }
                    710:     } else if (varIsSet("$hexints")) {
                    711:        printf("0x%lx", val);
                    712:     } else if (t->symvalue.rangev.lower >= 0) {
                    713:        printf("%lu", val);
                    714:     } else {
                    715:        printf("%ld", val);
                    716:     }
                    717: }
                    718: 
                    719: /*
                    720:  * Print out an enumerated value by finding the corresponding
                    721:  * name in the enumeration list.
                    722:  */
                    723: 
                    724: public printEnum (i, t)
                    725: integer i;
                    726: Symbol t;
                    727: {
                    728:     register Symbol e;
                    729: 
                    730:     e = t->chain;
                    731:     while (e != nil and e->symvalue.constval->value.lcon != i) {
                    732:        e = e->chain;
                    733:     }
                    734:     if (e != nil) {
                    735:        printf("%s", symname(e));
                    736:     } else {
                    737:        printf("%d", i);
                    738:     }
                    739: }
                    740: 
                    741: /*
                    742:  * Print out a null-terminated string (pointer to char)
                    743:  * starting at the given address.
                    744:  */
                    745: 
                    746: public printString (addr, quotes)
                    747: Address addr;
                    748: boolean quotes;
                    749: {
                    750:     register Address a;
                    751:     register integer i, len;
                    752:     register boolean endofstring;
                    753:     register int unprintables;
                    754: #define        MAXGARBAGE      4
                    755:     union {
                    756:        char ch[sizeof(Word)];
                    757:        int word;
                    758:     } u;
                    759: 
                    760:     if (varIsSet("$hexstrings")) {
                    761:        printf("0x%x", addr);
                    762:     } else {
                    763:        if (quotes) {
                    764:            putchar('"');
                    765:        }
                    766:        a = addr;
                    767:        unprintables = 0;
                    768:        endofstring = false;
                    769:        while (not endofstring) {
                    770:            dread(&u, a, sizeof(u));
                    771:            i = 0;
                    772:            do {
                    773:                if (u.ch[i] == '\0') {
                    774:                    endofstring = true;
                    775:                } else {
                    776:                    printchar(u.ch[i]);
                    777:                    if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
                    778:                        endofstring = true;
                    779:                        printf("...");
                    780:                    }
                    781:                }
                    782:                ++i;
                    783:            } while (i < sizeof(Word) and not endofstring);
                    784:            a += sizeof(Word);
                    785:        }
                    786:        if (quotes) {
                    787:            putchar('"');
                    788:        }
                    789:     }
                    790: }

unix.superglobalmegacorp.com

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