Annotation of 43BSDReno/contrib/emacs-18.55/gdb/symmisc.c, revision 1.1

1.1     ! root        1: /* Do various things to symbol tables (other than lookup)), for GDB.
        !             2:    Copyright (C) 1986, 1987 Free Software Foundation, Inc.
        !             3: 
        !             4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY
        !             5: WARRANTY.  No author or distributor accepts responsibility to anyone
        !             6: for the consequences of using it or for whether it serves any
        !             7: particular purpose or works at all, unless he says so in writing.
        !             8: Refer to the GDB General Public License for full details.
        !             9: 
        !            10: Everyone is granted permission to copy, modify and redistribute GDB,
        !            11: but only under the conditions described in the GDB General Public
        !            12: License.  A copy of this license is supposed to have been given to you
        !            13: along with GDB so you can know your rights and responsibilities.  It
        !            14: should be in a file named COPYING.  Among other things, the copyright
        !            15: notice and this notice must be preserved on all copies.
        !            16: 
        !            17: In other words, go ahead and share GDB, but don't try to stop
        !            18: anyone else from sharing it farther.  Help stamp out software hoarding!
        !            19: */
        !            20: 
        !            21: 
        !            22: #include "defs.h"
        !            23: #include "initialize.h"
        !            24: #include "symtab.h"
        !            25: 
        !            26: #include <stdio.h>
        !            27: #include <obstack.h>
        !            28: 
        !            29: static void free_symtab ();
        !            30: 
        !            31: START_FILE
        !            32: 
        !            33: /* Free all the symtabs that are currently installed,
        !            34:    and all storage associated with them.
        !            35:    Leaves us in a consistent state with no symtabs installed.  */
        !            36: 
        !            37: void
        !            38: free_all_symtabs ()
        !            39: {
        !            40:   register struct symtab *s, *snext;
        !            41: 
        !            42:   /* All values will be invalid because their types will be!  */
        !            43: 
        !            44:   clear_value_history ();
        !            45:   clear_displays ();
        !            46:   clear_internalvars ();
        !            47:   clear_breakpoints ();
        !            48:   set_default_breakpoint (0, 0, 0, 0);
        !            49: 
        !            50:   current_source_symtab = 0;
        !            51: 
        !            52:   for (s = symtab_list; s; s = snext)
        !            53:     {
        !            54:       snext = s->next;
        !            55:       free_symtab (s);
        !            56:     }
        !            57:   symtab_list = 0;
        !            58:   obstack_free (symbol_obstack, 0);
        !            59:   obstack_init (symbol_obstack);
        !            60: 
        !            61:   if (misc_function_vector)
        !            62:     free (misc_function_vector);
        !            63:   misc_function_count = 0;
        !            64:   misc_function_vector = 0;
        !            65: }
        !            66: 
        !            67: /* Free a struct block <- B and all the symbols defined in that block.  */
        !            68: 
        !            69: static void
        !            70: free_symtab_block (b)
        !            71:      struct block *b;
        !            72: {
        !            73:   register int i, n;
        !            74:   n = BLOCK_NSYMS (b);
        !            75:   for (i = 0; i < n; i++)
        !            76:     {
        !            77:       free (SYMBOL_NAME (BLOCK_SYM (b, i)));
        !            78:       free (BLOCK_SYM (b, i));
        !            79:     }
        !            80:   free (b);
        !            81: }
        !            82: 
        !            83: /* Free all the storage associated with the struct symtab <- S.
        !            84:    Note that some symtabs have contents malloc'ed structure by structure,
        !            85:    while some have contents that all live inside one big block of memory,
        !            86:    and some share the contents of another symbol table and so you should
        !            87:    not free the contents on their behalf (except sometimes the linetable,
        !            88:    which maybe per symtab even when the rest is not).
        !            89:    It is s->free_code that says which alternative to use.  */
        !            90: 
        !            91: static void
        !            92: free_symtab (s)
        !            93:      register struct symtab *s;
        !            94: {
        !            95:   register int i, n;
        !            96:   register struct blockvector *bv;
        !            97:   register struct type *type;
        !            98:   register struct typevector *tv;
        !            99: 
        !           100:   switch (s->free_code)
        !           101:     {
        !           102:     case free_nothing:
        !           103:       /* All the contents are part of a big block of memory
        !           104:         and some other symtab is in charge of freeing that block.
        !           105:         Therefore, do nothing.  */
        !           106:       break;
        !           107: 
        !           108:     case free_contents:
        !           109:       /* Here all the contents were malloc'ed structure by structure
        !           110:         and must be freed that way.  */
        !           111:       /* First free the blocks (and their symbols.  */
        !           112:       bv = BLOCKVECTOR (s);
        !           113:       n = BLOCKVECTOR_NBLOCKS (bv);
        !           114:       for (i = 0; i < n; i++)
        !           115:        free_symtab_block (BLOCKVECTOR_BLOCK (bv, i));
        !           116:       /* Free the blockvector itself.  */
        !           117:       free (bv);
        !           118:       /* Free the type vector.  */
        !           119:       tv = TYPEVECTOR (s);
        !           120:       free (tv);
        !           121:       /* Also free the linetable.  */
        !           122:       
        !           123:     case free_linetable:
        !           124:       /* Everything will be freed either by our `free_ptr'
        !           125:         or by some other symbatb, except for our linetable.
        !           126:         Free that now.  */
        !           127:       free (LINETABLE (s));
        !           128:       break;
        !           129:     }
        !           130: 
        !           131:   /* If there is a single block of memory to free, free it.  */
        !           132:   if (s->free_ptr)
        !           133:     free (s->free_ptr);
        !           134: 
        !           135:   if (s->line_charpos)
        !           136:     free (s->line_charpos);
        !           137:   free (s->filename);
        !           138:   free (s);
        !           139: }
        !           140: 
        !           141: /* Convert a raw symbol-segment to a struct symtab,
        !           142:    and relocate its internal pointers so that it is valid.  */
        !           143: 
        !           144: /* This is how to relocate one pointer, given a name for it.
        !           145:    Works independent of the type of object pointed to.  */
        !           146: #define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0)
        !           147: 
        !           148: /* This is the inverse of RELOCATE.  We use it when storing
        !           149:    a core address into a slot that has yet to be relocated.  */
        !           150: #define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0)
        !           151: 
        !           152: /* During the process of relocation, this holds the amount to relocate by
        !           153:    (the address of the file's symtab data, in core in the debugger).  */
        !           154: static int relocation;
        !           155: 
        !           156: #define CORE_RELOCATE(slot) \
        !           157:   ((slot) += (((slot) < data_start) ? text_relocation          \
        !           158:              : ((slot) < bss_start) ? data_relocation : bss_relocation))
        !           159: 
        !           160: #define TEXT_RELOCATE(slot)  ((slot) += text_relocation)
        !           161: 
        !           162: /* Relocation amounts for addresses in the program's core image.  */
        !           163: static int text_relocation, data_relocation, bss_relocation;
        !           164: 
        !           165: /* Boundaries that divide program core addresses into text, data and bss;
        !           166:    used to determine which relocation amount to use.  */
        !           167: static int data_start, bss_start;
        !           168: 
        !           169: static void relocate_typevector ();
        !           170: static void relocate_blockvector ();
        !           171: static void relocate_type ();
        !           172: static void relocate_block ();
        !           173: static void relocate_symbol ();
        !           174: static void relocate_source ();
        !           175: 
        !           176: /* Relocate a file's symseg so that all the pointers are valid C pointers.
        !           177:    Value is a `struct symtab'; but it is not suitable for direct
        !           178:    insertion into the `symtab_list' because it describes several files.  */
        !           179: 
        !           180: static struct symtab *
        !           181: relocate_symtab (root)
        !           182:      struct symbol_root *root;
        !           183: {
        !           184:   struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab));
        !           185:   bzero (sp, sizeof (struct symtab));
        !           186: 
        !           187:   relocation = (int) root;
        !           188:   text_relocation = root->textrel;
        !           189:   data_relocation = root->datarel;
        !           190:   bss_relocation = root->bssrel;
        !           191:   data_start = root->databeg;
        !           192:   bss_start = root->bssbeg;
        !           193: 
        !           194:   sp->filename = root->filename;
        !           195:   sp->ldsymoff = root->ldsymoff;
        !           196:   sp->language = root->language;
        !           197:   sp->compilation = root->compilation;
        !           198:   sp->version = root->version;
        !           199:   sp->blockvector = root->blockvector;
        !           200:   sp->typevector = root->typevector;
        !           201: 
        !           202:   RELOCATE (TYPEVECTOR (sp));
        !           203:   RELOCATE (BLOCKVECTOR (sp));
        !           204:   RELOCATE (sp->version);
        !           205:   RELOCATE (sp->compilation);
        !           206:   RELOCATE (sp->filename);
        !           207: 
        !           208:   relocate_typevector (TYPEVECTOR (sp));
        !           209:   relocate_blockvector (BLOCKVECTOR (sp));
        !           210: 
        !           211:   return sp;
        !           212: }
        !           213: 
        !           214: static void
        !           215: relocate_blockvector (blp)
        !           216:      register struct blockvector *blp;
        !           217: {
        !           218:   register int nblocks = BLOCKVECTOR_NBLOCKS (blp);
        !           219:   register int i;
        !           220:   for (i = 0; i < nblocks; i++)
        !           221:     RELOCATE (BLOCKVECTOR_BLOCK (blp, i));
        !           222:   for (i = 0; i < nblocks; i++)
        !           223:     relocate_block (BLOCKVECTOR_BLOCK (blp, i));
        !           224: }
        !           225: 
        !           226: static void
        !           227: relocate_block (bp)
        !           228:      register struct block *bp;
        !           229: {
        !           230:   register int nsyms = BLOCK_NSYMS (bp);
        !           231:   register int i;
        !           232: 
        !           233:   TEXT_RELOCATE (BLOCK_START (bp));
        !           234:   TEXT_RELOCATE (BLOCK_END (bp));
        !           235: 
        !           236:   /* These two should not be recursively processed.
        !           237:      The superblock need not be because all blocks are
        !           238:      processed from relocate_blockvector.
        !           239:      The function need not be because it will be processed
        !           240:      under the block which is its scope.  */
        !           241:   RELOCATE (BLOCK_SUPERBLOCK (bp));
        !           242:   RELOCATE (BLOCK_FUNCTION (bp));
        !           243: 
        !           244:   for (i = 0; i < nsyms; i++)
        !           245:     RELOCATE (BLOCK_SYM (bp, i));
        !           246: 
        !           247:   for (i = 0; i < nsyms; i++)
        !           248:     relocate_symbol (BLOCK_SYM (bp, i));
        !           249: }
        !           250: 
        !           251: static void
        !           252: relocate_symbol (sp)
        !           253:      register struct symbol *sp;
        !           254: {
        !           255:   RELOCATE (SYMBOL_NAME (sp));
        !           256:   if (SYMBOL_CLASS (sp) == LOC_BLOCK)
        !           257:     {
        !           258:       RELOCATE (SYMBOL_BLOCK_VALUE (sp));
        !           259:       /* We can assume the block that belongs to this symbol
        !           260:         is not relocated yet, since it comes after
        !           261:         the block that contains this symbol.  */
        !           262:       BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp;
        !           263:       UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)));
        !           264:     }
        !           265:   else if (SYMBOL_CLASS (sp) == LOC_STATIC)
        !           266:     CORE_RELOCATE (SYMBOL_VALUE (sp));
        !           267:   else if (SYMBOL_CLASS (sp) == LOC_LABEL)
        !           268:     TEXT_RELOCATE (SYMBOL_VALUE (sp));
        !           269:   RELOCATE (SYMBOL_TYPE (sp));
        !           270: }
        !           271: 
        !           272: static void
        !           273: relocate_typevector (tv)
        !           274:      struct typevector *tv;
        !           275: {
        !           276:   register int ntypes = TYPEVECTOR_NTYPES (tv);
        !           277:   register int i;
        !           278: 
        !           279:   for (i = 0; i < ntypes; i++)
        !           280:     RELOCATE (TYPEVECTOR_TYPE (tv, i));
        !           281:   for (i = 0; i < ntypes; i++)
        !           282:     relocate_type (TYPEVECTOR_TYPE (tv, i));
        !           283: }
        !           284: 
        !           285: /* We cannot come up with an a priori spanning tree
        !           286:    for the network of types, since types can be used
        !           287:    for many symbols and also as components of other types.
        !           288:    Therefore, we need to be able to mark types that we
        !           289:    already have relocated (or are already in the middle of relocating)
        !           290:    as in a garbage collector.  */
        !           291: 
        !           292: static void
        !           293: relocate_type (tp)
        !           294:      register struct type *tp;
        !           295: {
        !           296:   register int nfields = TYPE_NFIELDS (tp);
        !           297:   register int i;
        !           298: 
        !           299:   RELOCATE (TYPE_NAME (tp));
        !           300:   RELOCATE (TYPE_TARGET_TYPE (tp));
        !           301:   RELOCATE (TYPE_FIELDS (tp));
        !           302:   RELOCATE (TYPE_POINTER_TYPE (tp));
        !           303: 
        !           304:   for (i = 0; i < nfields; i++)
        !           305:     {
        !           306:       RELOCATE (TYPE_FIELD_TYPE (tp, i));
        !           307:       RELOCATE (TYPE_FIELD_NAME (tp, i));
        !           308:     }
        !           309: }
        !           310: 
        !           311: static void
        !           312: relocate_sourcevector (svp)
        !           313:      register struct sourcevector *svp;
        !           314: {
        !           315:   register int nfiles = svp->length;
        !           316:   register int i;
        !           317:   for (i = 0; i < nfiles; i++)
        !           318:     RELOCATE (svp->source[i]);
        !           319:   for (i = 0; i < nfiles; i++)
        !           320:     relocate_source (svp->source[i]);
        !           321: }
        !           322: 
        !           323: static void
        !           324: relocate_source (sp)
        !           325:      register struct source *sp;
        !           326: {
        !           327:   register int nitems = sp->contents.nitems;
        !           328:   register int i;
        !           329: 
        !           330:   RELOCATE (sp->name);
        !           331:   for (i = 0; i < nitems; i++)
        !           332:     if (sp->contents.item[i] > 0)
        !           333:       TEXT_RELOCATE (sp->contents.item[i]);
        !           334: }
        !           335: 
        !           336: /* Read symsegs from file named NAME open on DESC,
        !           337:    make symtabs from them, and return a chain of them.
        !           338:    These symtabs are not suitable for direct use in `symtab_list'
        !           339:    because each one describes a single object file, perhaps many source files.
        !           340:    `symbol_file_command' takes each of these, makes many real symtabs
        !           341:    from it, and then frees it.
        !           342: 
        !           343:    We assume DESC is prepositioned at the end of the string table,
        !           344:    just before the symsegs if there are any.  */
        !           345: 
        !           346: struct symtab *
        !           347: read_symsegs (desc, name)
        !           348:      int desc;
        !           349:      char *name;
        !           350: {
        !           351:   struct symbol_root root;
        !           352:   register char *data;
        !           353:   register struct symtab *sp, *sp1, *chain = 0;
        !           354:   register int len;
        !           355: 
        !           356:   while (1)
        !           357:     {
        !           358:       len = myread (desc, &root, sizeof root);
        !           359:       if (len == 0 || root.format == 0)
        !           360:        break;
        !           361:       if (root.format != 1 ||
        !           362:          root.length < sizeof root)
        !           363:        error ("Invalid symbol segment format code");
        !           364:       data = (char *) xmalloc (root.length);
        !           365:       bcopy (&root, data, sizeof root);
        !           366:       len = myread (desc, data + sizeof root,
        !           367:                    root.length - sizeof root);
        !           368:       sp = relocate_symtab (data);
        !           369:       RELOCATE (((struct symbol_root *)data)->sourcevector);
        !           370:       relocate_sourcevector (((struct symbol_root *)data)->sourcevector);
        !           371:       sp->next = chain;
        !           372:       chain = sp;
        !           373:       sp->linetable = (struct linetable *) ((struct symbol_root *)data)->sourcevector;
        !           374:     }
        !           375: 
        !           376:   return chain;
        !           377: }
        !           378: 
        !           379: static int block_depth ();
        !           380: static void print_spaces ();
        !           381: static void print_symbol ();
        !           382: 
        !           383: print_symtabs (filename)
        !           384:      char *filename;
        !           385: {
        !           386:   FILE *outfile;
        !           387:   register struct symtab *s;
        !           388:   register int i, j;
        !           389:   int len, line, blen;
        !           390:   register struct linetable *l;
        !           391:   struct blockvector *bv;
        !           392:   register struct block *b;
        !           393:   int depth;
        !           394:   struct cleanup *cleanups;
        !           395:   extern int fclose();
        !           396: 
        !           397:   if (filename == 0)
        !           398:     error_no_arg ("file to write symbol data in");
        !           399:   outfile = fopen (filename, "w");
        !           400:   if (outfile == 0)
        !           401:     perror_with_name (filename);
        !           402: 
        !           403:   cleanups = make_cleanup (fclose, outfile);
        !           404:   immediate_quit++;
        !           405: 
        !           406:   for (s = symtab_list; s; s = s->next)
        !           407:     {
        !           408:       /* First print the line table.  */
        !           409:       fprintf (outfile, "Symtab for file %s\n\n", s->filename);
        !           410:       fprintf (outfile, "Line table:\n\n");
        !           411:       l = LINETABLE (s);
        !           412:       len = l->nitems;
        !           413:       for (i = 0; i < len; i++)
        !           414:        {
        !           415:          if (l->item[i] < 0)
        !           416:            line = - l->item[i] - 1;
        !           417:          else
        !           418:            fprintf (outfile, " line %d at %x\n", ++line, l->item[i]);
        !           419:        }
        !           420:       /* Now print the block info.  */
        !           421:       fprintf (outfile, "\nBlockvector:\n\n");
        !           422:       bv = BLOCKVECTOR (s);
        !           423:       len = BLOCKVECTOR_NBLOCKS (bv);
        !           424:       for (i = 0; i < len; i++)
        !           425:        {
        !           426:          b = BLOCKVECTOR_BLOCK (bv, i);
        !           427:          depth = block_depth (b) * 2;
        !           428:          print_spaces (depth, outfile);
        !           429:          fprintf (outfile, "block #%03d (object 0x%x) ", i, b);
        !           430:          fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b));
        !           431:          if (BLOCK_SUPERBLOCK (b))
        !           432:            fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b));
        !           433:          if (BLOCK_FUNCTION (b))
        !           434:            fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
        !           435:          fputc ('\n', outfile);
        !           436:          blen = BLOCK_NSYMS (b);
        !           437:          for (j = 0; j < blen; j++)
        !           438:            {
        !           439:              print_symbol (BLOCK_SYM (b, j), depth + 1, outfile);
        !           440:            }
        !           441:        }
        !           442: 
        !           443:       fprintf (outfile, "\n\n");
        !           444:     }
        !           445: 
        !           446:   immediate_quit--;
        !           447:   do_cleanups (cleanups);
        !           448: }
        !           449: 
        !           450: static void
        !           451: print_symbol (symbol, depth, outfile)
        !           452:      struct symbol *symbol;
        !           453:      int depth;
        !           454:      FILE *outfile;
        !           455: {
        !           456:   print_spaces (depth, outfile);
        !           457:   if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
        !           458:     {
        !           459:       fprintf (outfile, "label %s at 0x%x", SYMBOL_NAME (symbol),
        !           460:               SYMBOL_VALUE (symbol));
        !           461:       return;
        !           462:     }
        !           463:   if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
        !           464:     {
        !           465:       if (TYPE_NAME (SYMBOL_TYPE (symbol)))
        !           466:        {
        !           467:          type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
        !           468:        }
        !           469:       else
        !           470:        {
        !           471:          fprintf (outfile, "%s %s = ",
        !           472:               (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM
        !           473:                ? "enum"
        !           474:                : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT
        !           475:                   ? "struct" : "union")),
        !           476:               SYMBOL_NAME (symbol));
        !           477:          type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
        !           478:        }
        !           479:       fprintf (outfile, ";\n");
        !           480:     }
        !           481:   else
        !           482:     {
        !           483:       if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
        !           484:        fprintf (outfile, "typedef ");
        !           485:       if (SYMBOL_TYPE (symbol))
        !           486:        {
        !           487:          type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol),
        !           488:                        outfile, 1, depth);
        !           489:          fprintf (outfile, "; ");
        !           490:        }
        !           491:       else
        !           492:        fprintf (outfile, "%s ", SYMBOL_NAME (symbol));
        !           493: 
        !           494:       switch (SYMBOL_CLASS (symbol))
        !           495:        {
        !           496:        case LOC_CONST:
        !           497:          fprintf (outfile, "const %d (0x%x),",
        !           498:                   SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol));
        !           499:          break;
        !           500: 
        !           501:        case LOC_CONST_BYTES:
        !           502:          fprintf (outfile, "const %d hex bytes:",
        !           503:                   TYPE_LENGTH (SYMBOL_TYPE (symbol)));
        !           504:          {
        !           505:            int i;
        !           506:            for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++)
        !           507:              fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]);
        !           508:            fprintf (outfile, ",");
        !           509:          }
        !           510:          break;
        !           511: 
        !           512:        case LOC_STATIC:
        !           513:          fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol));
        !           514:          break;
        !           515: 
        !           516:        case LOC_REGISTER:
        !           517:          fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol));
        !           518:          break;
        !           519: 
        !           520:        case LOC_ARG:
        !           521:          fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol));
        !           522:          break;
        !           523: 
        !           524:        case LOC_LOCAL:
        !           525:          fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol));
        !           526:          break;
        !           527: 
        !           528:        case LOC_TYPEDEF:
        !           529:          break;
        !           530: 
        !           531:        case LOC_LABEL:
        !           532:          fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol));
        !           533:          break;
        !           534: 
        !           535:        case LOC_BLOCK:
        !           536:          fprintf (outfile, "block (object 0x%x) starting at 0x%x,",
        !           537:                   SYMBOL_VALUE (symbol),
        !           538:                   BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)));
        !           539:          break;
        !           540:        }
        !           541:     }
        !           542:   fprintf (outfile, "\n");
        !           543: }
        !           544: 
        !           545: /* Return the nexting depth of a block within other blocks in its symtab.  */
        !           546: 
        !           547: static int
        !           548: block_depth (block)
        !           549:      struct block *block;
        !           550: {
        !           551:   register int i = 0;
        !           552:   while (block = BLOCK_SUPERBLOCK (block)) i++;
        !           553:   return i;
        !           554: }
        !           555: 
        !           556: static
        !           557: initialize ()
        !           558: {
        !           559:   add_com ("printsyms", class_obscure, print_symtabs,
        !           560:           "Print dump of current symbol definitions to file OUTFILE.");
        !           561: }
        !           562: 
        !           563: END_FILE

unix.superglobalmegacorp.com

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