|
|
1.1 ! root 1: ! 2: #line 1 "../test.y" ! 3: ! 4: /* ! 5: * Set return status based on ! 6: * various specified conditions, ! 7: * mostly related to files. ! 8: * Used mostly in shell files. ! 9: */ ! 10: ! 11: #include <stdio.h> ! 12: #include <sys/stat.h> ! 13: #include <access.h> ! 14: #include "testnode.h" ! 15: ! 16: #define NPRIM (sizeof(prims)/sizeof(prims[0])) ! 17: #define NFNAME 500 /* size of filename buffer */ ! 18: ! 19: #include "y.tab.h" ! 20: #define YYCLEARIN yychar = -1000 ! 21: #define YYERROK yyerrflag = 0 ! 22: extern int yychar; ! 23: extern short yyerrflag; ! 24: #ifndef YYMAXDEPTH ! 25: #define YYMAXDEPTH 150 ! 26: #endif ! 27: YYSTYPE yyval, yylval; ! 28: ! 29: #line 63 "../test.y" ! 30: ! 31: struct prim { ! 32: char *p_name; ! 33: int p_lval; ! 34: int p_bin; ! 35: } prims[] = { ! 36: "-r", _R, 0, ! 37: "-w", _W, 0, ! 38: "-f", _F, 0, ! 39: "-d", _D, 0, ! 40: "-s", _S, 0, ! 41: "-t", _T, 0, ! 42: "-z", _Z, 0, ! 43: "-n", _N, 0, ! 44: "-eq", _EQ, 1, ! 45: "-ne", _NE, 1, ! 46: "-gt", _GT, 1, ! 47: "-ge", _GE, 1, ! 48: "-lt", _LT, 1, ! 49: "-le", _LE, 1, ! 50: "-o", OR, 1, ! 51: "-a", AND, 1 ! 52: }; ! 53: ! 54: ! 55: char **gav; ! 56: int gac; ! 57: ! 58: struct stat sb; ! 59: ! 60: NODE *code; ! 61: ! 62: char *next(); ! 63: NODE *bnode(); ! 64: NODE *lnode(); ! 65: long atol(); ! 66: int xr(); ! 67: int xw(); ! 68: int xf(); ! 69: int xd(); ! 70: int xs(); ! 71: int xt(); ! 72: int xz(); ! 73: int xn(); ! 74: int xseq(); ! 75: int xsneq(); ! 76: int xeq(); ! 77: int xne(); ! 78: int xgt(); ! 79: int xge(); ! 80: int xlt(); ! 81: ! 82: main(argc, argv) ! 83: char *argv[]; ! 84: { ! 85: gav = argv+1; ! 86: gac = argc-1; ! 87: if (argv[0][0]=='[' && argv[0][1]=='\0') { ! 88: if (strcmp(argv[gac], "]") != 0) ! 89: tsterr("unbalanced [..]"); ! 90: gac--; ! 91: } ! 92: if (gac == 0) ! 93: exit(1); ! 94: yyparse(); ! 95: exit(!execute(code)); ! 96: } ! 97: ! 98: /* ! 99: * Lexical analyser ! 100: */ ! 101: yylex() ! 102: { ! 103: static char laststr = 0; /* 1 if last token was string */ ! 104: register char *ap; ! 105: register struct prim *pp; ! 106: ! 107: if ((yylval.fname = ap = next()) == NULL) ! 108: return ('\n'); ! 109: ! 110: if (*ap == '-') { ! 111: for (pp = prims; pp < &prims[NPRIM]; pp++) { ! 112: if (strcmp(pp->p_name, ap) == 0) { ! 113: if (!laststr && pp->p_bin) ! 114: break; ! 115: laststr = 0; ! 116: return (pp->p_lval); ! 117: } ! 118: } ! 119: } ! 120: else { ! 121: laststr = 0; ! 122: if (strcmp("!=", ap) == 0) ! 123: return (SNEQ); ! 124: ! 125: if (ap[1] == '\0') { ! 126: if (ap[0]==')') { ! 127: laststr = 1; ! 128: return(')'); ! 129: } ! 130: if (ap[0]=='(' || ap[0]=='!') ! 131: return (ap[0]); ! 132: if (ap[0]=='=') ! 133: return (SEQ); ! 134: } ! 135: } ! 136: laststr = 1; ! 137: return (STR); ! 138: } ! 139: ! 140: yyerror() ! 141: { ! 142: fprintf(stderr, "Test expression syntax error\n"); ! 143: usage(); ! 144: } ! 145: ! 146: /* ! 147: * Return the next argument from the arg list. ! 148: */ ! 149: char * ! 150: next() ! 151: { ! 152: if (gac < 1) ! 153: return (NULL); ! 154: gac--; ! 155: return (*gav++); ! 156: } ! 157: ! 158: /* ! 159: * Build an expression tree node (non-leaf) ! 160: */ ! 161: NODE * ! 162: bnode(op, left, right) ! 163: int op; ! 164: NODE *left, *right; ! 165: { ! 166: register NODE *np; ! 167: char *malloc(); ! 168: ! 169: if ((np = (NODE *)malloc(sizeof (NODE))) == NULL) ! 170: tsterr("Out of space"); ! 171: np->n_un.n_op = op; ! 172: np->n_left = left; ! 173: np->n_right = right; ! 174: return (np); ! 175: } ! 176: ! 177: /* ! 178: * Build a leaf node in expression tree. ! 179: */ ! 180: NODE * ! 181: lnode(fn, str1, str2) ! 182: int (*fn)(); ! 183: char *str1, *str2; ! 184: { ! 185: register NODE *np; ! 186: char *malloc(); ! 187: ! 188: if ((np = (NODE *)malloc(sizeof (NODE))) == NULL) ! 189: tsterr("Out of space"); ! 190: np->n_left = np->n_right = NULL; ! 191: np->n_un.n_fun = fn; ! 192: np->n_s1 = str1; ! 193: np->n_s2 = str2; ! 194: return (np); ! 195: } ! 196: ! 197: /* ! 198: * Execute compiled code. ! 199: */ ! 200: execute(np) ! 201: register NODE *np; ! 202: { ! 203: if (np->n_left != NULL) ! 204: switch (np->n_un.n_op) { ! 205: case AND: ! 206: if (execute(np->n_left) && execute(np->n_right)) ! 207: return (1); ! 208: return (0); ! 209: ! 210: case OR: ! 211: if (execute(np->n_left) || execute(np->n_right)) ! 212: return (1); ! 213: return (0); ! 214: ! 215: case '!': ! 216: return (!execute(np->n_left)); ! 217: ! 218: default: ! 219: tsterr("Panic: bad tree (op %d)", np->n_un.n_op); ! 220: } ! 221: else ! 222: return ((*np->n_un.n_fun)(np)); ! 223: /* NOTREACHED */ ! 224: } ! 225: ! 226: /* ! 227: * Check to see if the file exists ! 228: * and if readable. ! 229: */ ! 230: xr(np) ! 231: NODE *np; ! 232: { ! 233: return (access(np->n_s1, AREAD) >= 0); ! 234: } ! 235: ! 236: /* ! 237: * Check if the file exists and is ! 238: * writeable. ! 239: */ ! 240: xw(np) ! 241: NODE *np; ! 242: { ! 243: return (access(np->n_s1, AWRITE) >= 0); ! 244: } ! 245: ! 246: /* ! 247: * Check if the file exists and is not ! 248: * a directory. ! 249: */ ! 250: xf(np) ! 251: NODE *np; ! 252: { ! 253: return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)!=S_IFDIR); ! 254: } ! 255: ! 256: /* ! 257: * Check to see if the file exists ! 258: * and is a directory. ! 259: */ ! 260: xd(np) ! 261: NODE *np; ! 262: { ! 263: return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)==S_IFDIR); ! 264: } ! 265: ! 266: /* ! 267: * Check to see if the file exists ! 268: * and has a non-zero size. ! 269: */ ! 270: xs(np) ! 271: NODE *np; ! 272: { ! 273: return (stat(np->n_s1, &sb)>=0 && sb.st_size>0); ! 274: } ! 275: ! 276: /* ! 277: * Check to see if the file ! 278: * descriptor is associated ! 279: * with a terminal. ! 280: */ ! 281: xt(np) ! 282: NODE *np; ! 283: { ! 284: return (isatty(atoi(np->n_s1))); ! 285: } ! 286: ! 287: /* ! 288: * True if the length of the given ! 289: * string is zero. ! 290: */ ! 291: xz(np) ! 292: NODE *np; ! 293: { ! 294: return (np->n_s1[0] == '\0'); ! 295: } ! 296: ! 297: /* ! 298: * True if the length of the given ! 299: * string is non-zero. ! 300: */ ! 301: xn(np) ! 302: NODE *np; ! 303: { ! 304: return (np->n_s1[0] != '\0'); ! 305: } ! 306: ! 307: /* ! 308: * True if the two strings are ! 309: * lexicographically equal. ! 310: */ ! 311: xseq(np) ! 312: register NODE *np; ! 313: { ! 314: return (strcmp(np->n_s1, np->n_s2) == 0); ! 315: } ! 316: ! 317: /* ! 318: * True if the two strings are ! 319: * lexicographically unequal. ! 320: */ ! 321: xsneq(np) ! 322: register NODE *np; ! 323: { ! 324: return (strcmp(np->n_s1, np->n_s2) != 0); ! 325: } ! 326: ! 327: /* ! 328: * True if the two numbers are ! 329: * equal. ! 330: */ ! 331: xeq(np) ! 332: register NODE *np; ! 333: { ! 334: return (atol(np->n_s1) == atol(np->n_s2)); ! 335: } ! 336: ! 337: /* ! 338: * True if the two numbers are ! 339: * not equal. ! 340: */ ! 341: xne(np) ! 342: register NODE *np; ! 343: { ! 344: return (atol(np->n_s1) != atol(np->n_s2)); ! 345: } ! 346: ! 347: /* ! 348: * True if the first number is ! 349: * greater than the second. ! 350: */ ! 351: xgt(np) ! 352: register NODE *np; ! 353: { ! 354: return (atol(np->n_s1) > atol(np->n_s2)); ! 355: } ! 356: ! 357: /* ! 358: * True if the first number is ! 359: * greater than or equal to the second. ! 360: */ ! 361: xge(np) ! 362: register NODE *np; ! 363: { ! 364: return (atol(np->n_s1) >= atol(np->n_s2)); ! 365: } ! 366: ! 367: /* ! 368: * True if the first number is ! 369: * less than the second. ! 370: */ ! 371: xlt(np) ! 372: register NODE *np; ! 373: { ! 374: return (atol(np->n_s1) < atol(np->n_s2)); ! 375: } ! 376: ! 377: /* ! 378: * True if the first number is ! 379: * less than or equal to the second. ! 380: */ ! 381: xle(np) ! 382: register NODE *np; ! 383: { ! 384: return (atol(np->n_s1) <= atol(np->n_s2)); ! 385: } ! 386: ! 387: /* ! 388: * Error messages. ! 389: */ ! 390: /* VARARGS */ ! 391: tsterr(x) ! 392: { ! 393: fprintf(stderr, "test: %r\n", &x); ! 394: exit(1); ! 395: } ! 396: ! 397: usage() ! 398: { ! 399: fprintf(stderr, "Usage: test expression\n"); ! 400: exit(1); ! 401: } ! 402: #ifdef YYTNAMES ! 403: readonly struct yytname yytnames[26] = ! 404: { ! 405: "$end", -1, ! 406: "error", -2, ! 407: "OR", 256, ! 408: "AND", 257, ! 409: "'!'", 33, ! 410: "_R", 258, ! 411: "_W", 259, ! 412: "_F", 260, ! 413: "_D", 261, ! 414: "_S", 262, ! 415: "_T", 263, ! 416: "_Z", 264, ! 417: "_N", 265, ! 418: "SEQ", 266, ! 419: "SNEQ", 267, ! 420: "_EQ", 268, ! 421: "_NE", 269, ! 422: "_GT", 270, ! 423: "_GE", 271, ! 424: "_LT", 272, ! 425: "_LE", 273, ! 426: "STR", 275, ! 427: "'\\n'", 10, ! 428: "'('", 40, ! 429: "')'", 41, ! 430: NULL ! 431: } ; ! 432: #endif ! 433: #include <action.h> ! 434: unsigned char yypdnt[24] = { ! 435: 0, 1, 2, 2, 2, 2, 2, 2, ! 436: 2, 2, 2, 2, 2, 2, 2, 2, ! 437: 2, 2, 2, 2, 2, 2, 2, 2 ! 438: }; ! 439: unsigned char yypn[24] = { ! 440: 2, 2, 3, 2, 3, 3, 2, 2, ! 441: 2, 2, 2, 2, 1, 2, 2, 3, ! 442: 3, 3, 3, 3, 3, 3, 3, 1 ! 443: }; ! 444: unsigned char yypgo[3] = { ! 445: 0, 0, 2 ! 446: }; ! 447: unsigned int yygo[12] = { ! 448: -1000, 12, 1, 14, 11, 31, 33, 45, ! 449: 34, 46, -1000, 13 ! 450: }; ! 451: unsigned char yypa[47] = { ! 452: 0, 0, 24, 28, 32, 36, 40, 44, ! 453: 48, 52, 56, 0, 74, 78, 86, 88, ! 454: 90, 92, 94, 96, 98, 100, 102, 104, ! 455: 108, 112, 116, 120, 124, 128, 132, 136, ! 456: 144, 0, 0, 148, 150, 152, 154, 156, ! 457: 158, 160, 162, 164, 166, 168, 172 ! 458: }; ! 459: unsigned int yyact[174] = { ! 460: 1, 33, 2, 258, 3, 259, 4, 260, ! 461: 5, 261, 6, 262, 7, 263, 8, 264, ! 462: 9, 265, 10, 275, 11, 40, 24576, -1000, ! 463: 15, 275, 24576, -1000, 16, 275, 24576, -1000, ! 464: 17, 275, 24576, -1000, 18, 275, 24576, -1000, ! 465: 19, 275, 24576, -1000, 20, 275, 8204, -1000, ! 466: 21, 275, 24576, -1000, 22, 275, 24576, -1000, ! 467: 23, 266, 24, 267, 25, 268, 26, 269, ! 468: 27, 270, 28, 271, 29, 272, 30, 273, ! 469: 8215, -1000, 32, -1, 24576, -1000, 33, 256, ! 470: 34, 257, 35, 10, 24576, -1000, 8195, -1000, ! 471: 8198, -1000, 8199, -1000, 8200, -1000, 8201, -1000, ! 472: 8202, -1000, 8203, -1000, 8205, -1000, 8206, -1000, ! 473: 36, 275, 24576, -1000, 37, 275, 24576, -1000, ! 474: 38, 275, 24576, -1000, 39, 275, 24576, -1000, ! 475: 40, 275, 24576, -1000, 41, 275, 24576, -1000, ! 476: 42, 275, 24576, -1000, 43, 275, 24576, -1000, ! 477: 33, 256, 34, 257, 44, 41, 24576, -1000, ! 478: 16384, -1, 24576, -1000, 8193, -1000, 8207, -1000, ! 479: 8208, -1000, 8209, -1000, 8210, -1000, 8211, -1000, ! 480: 8212, -1000, 8213, -1000, 8214, -1000, 8194, -1000, ! 481: 34, 257, 8196, -1000, 8197, -1000 ! 482: }; ! 483: #define YYNOCHAR (-1000) ! 484: #define yyerrok yyerrflag=0 ! 485: #define yyclearin yylval=YYNOCHAR ! 486: int yystack[YYMAXDEPTH]; ! 487: YYSTYPE yyvstack[YYMAXDEPTH], *yyv; ! 488: int yychar; ! 489: ! 490: #ifdef YYDEBUG ! 491: int yydebug = 1; /* No sir, not in the BSS */ ! 492: #include <stdio.h> ! 493: #endif ! 494: ! 495: short yyerrflag; ! 496: int *yys; ! 497: ! 498: yyparse() ! 499: { ! 500: register YYSTYPE *yypvt; ! 501: int act; ! 502: register unsigned *ip, yystate; ! 503: int pno; ! 504: yystate = 0; ! 505: yychar = YYNOCHAR; ! 506: yyv = &yyvstack[-1]; ! 507: yys = &yystack[-1]; ! 508: ! 509: stack: ! 510: if( ++yys >= &yystack[YYMAXDEPTH] ) { ! 511: write(2, "Stack overflow\n", 15); ! 512: exit(1); ! 513: } ! 514: *yys = yystate; ! 515: *++yyv = yyval; ! 516: #ifdef YYDEBUG ! 517: if( yydebug ) ! 518: fprintf(stdout, "Stack state %d, char %d\n", yystate, yychar); ! 519: #endif ! 520: ! 521: read: ! 522: ip = &yyact[yypa[yystate]]; ! 523: if( ip[1] != YYNOCHAR ) { ! 524: if( yychar == YYNOCHAR ) { ! 525: yychar = yylex(); ! 526: #ifdef YYDEBUG ! 527: if( yydebug ) ! 528: fprintf(stdout, "lex read char %d, val %d\n", yychar, yylval); ! 529: #endif ! 530: } ! 531: while (ip[1]!=YYNOCHAR) { ! 532: if (ip[1]==yychar) ! 533: break; ! 534: ip += 2; ! 535: } ! 536: } ! 537: act = ip[0]; ! 538: switch( act>>YYACTSH ) { ! 539: case YYSHIFTACT: ! 540: if( ip[1]==YYNOCHAR ) ! 541: goto YYerract; ! 542: if( yychar != -1 ) ! 543: yychar = YYNOCHAR; /* dont throw away EOF */ ! 544: yystate = act&YYAMASK; ! 545: yyval = yylval; ! 546: #ifdef YYDEBUG ! 547: if( yydebug ) ! 548: fprintf(stdout, "shift %d\n", yystate); ! 549: #endif ! 550: if( yyerrflag ) ! 551: --yyerrflag; ! 552: goto stack; ! 553: ! 554: case YYACCEPTACT: ! 555: #ifdef YYDEBUG ! 556: if( yydebug ) ! 557: fprintf(stdout, "accept\n"); ! 558: #endif ! 559: return(0); ! 560: ! 561: case YYERRACT: ! 562: YYerract: ! 563: switch (yyerrflag) { ! 564: case 0: ! 565: yyerror("Syntax error"); ! 566: ! 567: case 1: ! 568: case 2: ! 569: ! 570: yyerrflag = 3; ! 571: while( yys >= & yystack[0] ) { ! 572: ip = &yyact[yypa[*yys]]; ! 573: while( ip[1]!=YYNOCHAR ) ! 574: ip += 2; ! 575: if( (*ip&~YYAMASK) == (YYSHIFTACT<<YYACTSH) ) { ! 576: yystate = *ip&YYAMASK; ! 577: goto stack; ! 578: } ! 579: #ifdef YYDEBUG ! 580: if( yydebug ) ! 581: fprintf(stderr, "error recovery leaves state %d, uncovers %d\n", *yys, yys[-1]); ! 582: #endif ! 583: yys--; ! 584: yyv--; ! 585: } ! 586: #ifdef YYDEBUG ! 587: if( yydebug ) ! 588: fprintf(stderr, "no shift on error; abort\n"); ! 589: #endif ! 590: return(1); ! 591: ! 592: case 3: ! 593: #ifdef YYDEBUG ! 594: if( yydebug ) ! 595: fprintf(stderr, "Error recovery clobbers char %o\n", yychar); ! 596: #endif ! 597: if( yychar==YYEOFVAL ) ! 598: return(1); ! 599: yychar = YYNOCHAR; ! 600: goto read; ! 601: } ! 602: ! 603: case YYREDACT: ! 604: pno = act&YYAMASK; ! 605: #ifdef YYDEBUG ! 606: if( yydebug ) ! 607: fprintf(stdout, "reduce %d\n", pno); ! 608: #endif ! 609: yypvt = yyv; ! 610: yyv -= yypn[pno]; ! 611: yys -= yypn[pno]; ! 612: yyval = yyv[1]; ! 613: switch(pno) { ! 614: ! 615: case 1: { ! 616: ! 617: #line 35 "../test.y" ! 618: code = yypvt[-1].nodeptr; return; }break; ! 619: ! 620: case 2: { ! 621: ! 622: #line 39 "../test.y" ! 623: yyval.nodeptr = yypvt[-1].nodeptr; }break; ! 624: ! 625: case 3: { ! 626: ! 627: #line 40 "../test.y" ! 628: yyval.nodeptr = bnode('!', yypvt[0].nodeptr, NULL); }break; ! 629: ! 630: case 4: { ! 631: ! 632: #line 41 "../test.y" ! 633: yyval.nodeptr = bnode(OR, yypvt[-2].nodeptr, yypvt[0].nodeptr); }break; ! 634: ! 635: case 5: { ! 636: ! 637: #line 42 "../test.y" ! 638: yyval.nodeptr = bnode(AND, yypvt[-2].nodeptr, yypvt[0].nodeptr); }break; ! 639: ! 640: case 6: { ! 641: ! 642: #line 43 "../test.y" ! 643: yyval.nodeptr = lnode(xr, yypvt[0].fname, NULL); }break; ! 644: ! 645: case 7: { ! 646: ! 647: #line 44 "../test.y" ! 648: yyval.nodeptr = lnode(xw, yypvt[0].fname, NULL); }break; ! 649: ! 650: case 8: { ! 651: ! 652: #line 45 "../test.y" ! 653: yyval.nodeptr = lnode(xf, yypvt[0].fname, NULL); }break; ! 654: ! 655: case 9: { ! 656: ! 657: #line 46 "../test.y" ! 658: yyval.nodeptr = lnode(xd, yypvt[0].fname, NULL); }break; ! 659: ! 660: case 10: { ! 661: ! 662: #line 47 "../test.y" ! 663: yyval.nodeptr = lnode(xs, yypvt[0].fname, NULL); }break; ! 664: ! 665: case 11: { ! 666: ! 667: #line 48 "../test.y" ! 668: yyval.nodeptr = lnode(xt, yypvt[0].fname, NULL); }break; ! 669: ! 670: case 12: { ! 671: ! 672: #line 49 "../test.y" ! 673: yyval.nodeptr = lnode(xt, "1", NULL); }break; ! 674: ! 675: case 13: { ! 676: ! 677: #line 50 "../test.y" ! 678: yyval.nodeptr = lnode(xz, yypvt[0].fname, NULL); }break; ! 679: ! 680: case 14: { ! 681: ! 682: #line 51 "../test.y" ! 683: yyval.nodeptr = lnode(xn, yypvt[0].fname, NULL); }break; ! 684: ! 685: case 15: { ! 686: ! 687: #line 52 "../test.y" ! 688: yyval.nodeptr = lnode(xseq, yypvt[-2].fname, yypvt[0].fname); }break; ! 689: ! 690: case 16: { ! 691: ! 692: #line 53 "../test.y" ! 693: yyval.nodeptr = lnode(xsneq, yypvt[-2].fname, yypvt[0].fname); }break; ! 694: ! 695: case 17: { ! 696: ! 697: #line 54 "../test.y" ! 698: yyval.nodeptr = lnode(xeq, yypvt[-2].fname, yypvt[0].fname); }break; ! 699: ! 700: case 18: { ! 701: ! 702: #line 55 "../test.y" ! 703: yyval.nodeptr = lnode(xne, yypvt[-2].fname, yypvt[0].fname); }break; ! 704: ! 705: case 19: { ! 706: ! 707: #line 56 "../test.y" ! 708: yyval.nodeptr = lnode(xgt, yypvt[-2].fname, yypvt[0].fname); }break; ! 709: ! 710: case 20: { ! 711: ! 712: #line 57 "../test.y" ! 713: yyval.nodeptr = lnode(xge, yypvt[-2].fname, yypvt[0].fname); }break; ! 714: ! 715: case 21: { ! 716: ! 717: #line 58 "../test.y" ! 718: yyval.nodeptr = lnode(xlt, yypvt[-2].fname, yypvt[0].fname); }break; ! 719: ! 720: case 22: { ! 721: ! 722: #line 59 "../test.y" ! 723: yyval.nodeptr = lnode(xle, yypvt[-2].fname, yypvt[0].fname); }break; ! 724: ! 725: case 23: { ! 726: ! 727: #line 60 "../test.y" ! 728: yyval.nodeptr = lnode(xn, yypvt[0].fname, NULL); }break; ! 729: ! 730: } ! 731: ip = &yygo[ yypgo[yypdnt[pno]] ]; ! 732: while( *ip!=*yys && *ip!=YYNOCHAR ) ! 733: ip += 2; ! 734: yystate = ip[1]; ! 735: goto stack; ! 736: } ! 737: } ! 738: ! 739: ! 740: ! 741:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.