Annotation of researchv9/jerq/sgs/ld/syms.c, revision 1.1.1.1

1.1       root        1: static char ID[] = "@(#) syms.c: 1.18 10/5/83";
                      2: #include "system.h"
                      3: #include <stdio.h>
                      4: #include <fatal.h>
                      5: #include <signal.h>
                      6: #if !NOSDP
                      7: #include "sdp1.h"
                      8: #include "sdpsrc/hd/define2.h"
                      9: #include "sdpsrc/hd/define4.h"
                     10: #include "sdpsrc/hd/struct.h"
                     11: #endif
                     12: #include "structs.h"
                     13: #include "paths.h"
                     14: #include "extrns.h"
                     15: #if TRVEC
                     16: #include "tv.h"
                     17: #include "ldtv.h"
                     18: #endif
                     19: #include "sgsmacros.h"
                     20: #include "instr.h"
                     21: #include "ldmacros.h"
                     22: 
                     23: 
                     24: 
                     25: /*
                     26:  * ***** NOTICE ***** NOTICE ***** NOTICE *******
                     27:  *                                             *
                     28:  *     This version of syms.c is designed to   *
                     29:  *     permit multiple aux entries per symbol  *
                     30:  *                                             *
                     31:  *     This version of syms.c uses a one-way   *
                     32:  *     circular list to link all symbols that  *
                     33:  *     hash to the same hashtab[] entry        *
                     34:  *                                             *
                     35:  * ***** NOTICE ***** NOTICE ***** NOTICE *******
                     36:  */
                     37: 
                     38: #if NOSDP && !UNIX
                     39: #define HASHSIZE       1021
                     40: #else
                     41: #define HASHSIZE       521
                     42: #endif
                     43: /*
                     44:  * VAX cc bug KLUDGE
                     45:  */
                     46: #define abs(x) (x < 0 ? -x : x)
                     47: 
                     48: ITEMID hashtab[HASHSIZE];
                     49: 
                     50: #if NOSDP
                     51: #if UNIX
                     52: #define MAXEXTRA       100
                     53: #define XSMTBSZ                100
                     54: #define XAXTBSZ                50
                     55: #define MYSMTBSZ       200
                     56: #define MYAXTBSZ       100
                     57: #else
                     58: #if AR16WR
                     59: #define MAXEXTRA       20
                     60: #define        XSMTBSZ         80
                     61: #define XAXTBSZ                40
                     62: #define MYSMTBSZ       400
                     63: #define MYAXTBSZ       200
                     64: #endif
                     65: #if AR32W
                     66: #define MAXEXTRA       100
                     67: #define XSMTBSZ                800
                     68: #define XAXTBSZ                400
                     69: #define MYSMTBSZ       4000
                     70: #define MYAXTBSZ       2000
                     71: #endif
                     72: #if AR32WR
                     73: #define        MAXEXTRA        10
                     74: #define XSMTBSZ                400
                     75: #define XAXTBSZ                200
                     76: #define MYSMTBSZ       2000
                     77: #define MYAXTBSZ       1000
                     78: #endif
                     79: #endif
                     80: int    xsymcnt = 0;
                     81: int    xauxcnt = 0;
                     82: SYMTAB *xsymptr[MAXEXTRA];
                     83: AUXTAB *xauxptr[MAXEXTRA];
                     84: SYMTAB mysymtab[MYSMTBSZ+1];
                     85: AUXTAB myauxtab[MYAXTBSZ+1];
                     86: #else
                     87: extern HEADER global_frames[MAXATTACH];
                     88: static char    sdpname[sizeof(TMPDIR)+20] = "";
                     89: static char    auxname[sizeof(TMPDIR)+20] = "";
                     90: 
                     91: static int     sdp_called = 0; /* indicates when syminit() has been called */
                     92: static int     aux_called = 0; /* indicates when auxinit() has been called */
                     93: /*eject*/
                     94: syminit()
                     95: {
                     96: 
                     97: /*
                     98:  * Initialize the Software Demand Paging System
                     99:  */
                    100: 
                    101:        if( sdp_called )
                    102:                lderror(2,0,NULL,"Attempt to re-initialize SDP symbol space");
                    103: 
                    104:        sprintf( sdpname, "%s/%s", TMPDIR, "ldXXXXXX" );
                    105:        mktemp( sdpname );
                    106: 
                    107:        sdp_called++;
                    108: 
                    109:        if( sdpinit(sdpname, CREATE, SYMSPACE) != SYMSPACE )
                    110:                lderror(2,0,NULL,"Failed to initialize SDP symbol space");
                    111:        else
                    112:                sdp_called++;
                    113: 
                    114:        auxinit();              /* initialize aux entry space */
                    115: }
                    116: 
                    117: 
                    118: 
                    119: symfini()
                    120: {
                    121:        char buf[sizeof(sdpname)*2 + 20];
                    122: 
                    123: /*
                    124:  * Ignore BREAK, HANGUP, and QUIT signals, to insure that the cleanup
                    125:  * is done
                    126:  */
                    127: 
                    128:        signal(SIGINT, SIG_IGN);
                    129:        signal(SIGQUIT, SIG_IGN);
                    130: 
                    131:        if( sdp_called == 2 ) {
                    132:                sdp_called--;
                    133:                if( sdpterm(SYMSPACE) < 0 )
                    134:                        lderror(2,0,NULL,"Failed to close SDP symbol space");
                    135:                }
                    136: 
                    137:        if( sdp_called != 1 )
                    138:                return;
                    139:        sdp_called--;
                    140: 
                    141: #if TS || RT
                    142:        sprintf(buf, "rm -r %s", sdpname);
                    143: #else
                    144:        sprintf(buf, "rm -r %s; rmdir %s", sdpname, sdpname);
                    145: #endif
                    146: 
                    147:        if( fork() == 0 ) {
                    148:                execl("/bin/sh", "sh", "-c", buf, 0);
                    149:                lderror(0,0,NULL, "Execl(%s) failed", buf);
                    150:                _exit(127);
                    151:                }
                    152: 
                    153:        auxfini();              /* close aux entry space */
                    154: }
                    155: /*eject*/
                    156: #endif
                    157: hash(name)
                    158: register char *name;
                    159: {
                    160: 
                    161: /*
                    162:  * Compute hash value for a symbol name
                    163:  */
                    164: 
                    165:        register unsigned hashval;
                    166:        register int tmp;       /* VAX CC BUG KLUDGE */
                    167: 
                    168:        hashval = 0;
                    169:        while (*name)
                    170:                hashval = hashval * 10 + *name++;       /*used to be 13*/
                    171: 
                    172: /*
                    173:  * Because of a bug in the current VAX compiler, the following
                    174:  * line has temporarily been replaced by the KLUDGE following
                    175:  * this comment.  The define of abs() is also added above
                    176:  *
                    177:  *     return( (int) (hashval % HASHSIZE) );
                    178:  */
                    179: 
                    180:        tmp = (int) hashval;
                    181:        tmp = abs(tmp);
                    182:        return ( tmp % HASHSIZE );
                    183: }
                    184: /*eject*/
                    185: SYMTAB *
                    186: findsym(name)
                    187: char *name;
                    188: {
                    189: 
                    190: /*
                    191:  * Return a pointer to the ld symbol table entry for a symbol.
                    192:  *
                    193:  * NULL indicates that the symbol does not exist
                    194:  */
                    195: 
                    196:        register SYMTAB *p;     /* ld symbol table entry        */
                    197:        register int chain;     /* size of a collision chain    */
                    198:        int hashval;            /* hashtab[] index for the sym  */
                    199:        register ITEMID acid,   /* SDP id for ld symbol entry   */
                    200:               base;            /* head of collision chain      */
                    201: 
                    202: 
                    203: /*
                    204:  * All symbols that hash to the same value are connected in a one-way,
                    205:  *     circular linked list.  The most recently referenced symbol on
                    206:  *     the chain is considered the head of the chain, and its id is
                    207:  *     stored in the hash table
                    208:  *
                    209:  * Get the head of the collision chain, and walk down it looking for
                    210:  *     a match
                    211:  */
                    212: 
                    213:        hashval = hash(name);
                    214:        if( (acid = hashtab[hashval]) == 0 )
                    215:                return( NULL );
                    216:        base = acid;
                    217:        chain = 1;
                    218: 
                    219:        do {
                    220:                char sym_space[9];
                    221:                char    *sym_name;
                    222: #if NOSDP
                    223:                p = getsym(acid);
                    224: #else
                    225:                p = (SYMTAB *) lock(acid, MISPARTITION, RNLY);
                    226: #endif
                    227:                if (p->smnamelength == 9)
                    228:                {
                    229:                        strncpy( sym_space, p->sment.n_name, 8 );
                    230:                        sym_space[8] = '\0';
                    231:                        sym_name = sym_space;
                    232:                }
                    233: #if FLEXNAMES
                    234:                else if (p->smnamelength > 9)
                    235:                        sym_name = p->sment.n_nptr;
                    236: #endif
                    237:                else
                    238:                        sym_name = p->sment.n_name;
                    239: 
                    240:                if (equal( sym_name, name, p->smnamelength ))
                    241:                {
                    242:                        maxchain = max(maxchain,chain);
                    243:                        nwalks += (chain - 1);
                    244:                        hashtab[hashval] = acid;
                    245:                        return( p );
                    246:                }
                    247: #if !NOSDP
                    248:                unlock(acid, RNLY);
                    249: #endif
                    250: 
                    251:                acid = p->smchainid;
                    252:                chain++;
                    253:                
                    254:                }
                    255:        while( acid != base );
                    256: 
                    257:        nfwalks += (chain - 1);
                    258: 
                    259:        return( NULL );         /* not found */
                    260: }
                    261: /*eject*/
                    262: AUXTAB *
                    263: findaux(sym, ndx)
                    264: SYMTAB *sym;
                    265: int ndx;
                    266: {
                    267: 
                    268: /*
                    269:  * Return a pointer to the ndx'th aux entry for the ld symbol table
                    270:  * entry given by sym
                    271:  *
                    272:  * NULL indicates that no such aux entry exists
                    273:  */
                    274: 
                    275:        register AUXTAB *a;     /* pointer to a symbol aux entry*/
                    276:        ITEMID acid;            /* SDP id for ld aux entry      */
                    277: 
                    278: #if DEBUG
                    279:        if( dflag > 15 )
                    280:                fprintf( stderr, "\nfindaux %s ", SYMNAME( sym->sment ));
                    281: #endif
                    282: 
                    283: /*
                    284:  * All aux entries belonging to a symbol are linked together in a
                    285:  *     one-way linked list.  The entries are ordered by aux-entry
                    286:  *     number: the first aux entry is the head of the list; it is
                    287:  *     linked to the 2'nd aux entry, which is linked to the 3'rd, etc
                    288:  *
                    289:  * Get the head of the aux entry list, and walk down it looking for
                    290:  *     the specified aux entry
                    291:  */
                    292: 
                    293:        acid = sym->smauxid;
                    294: 
                    295:        while( acid != 0 ) {
                    296: 
                    297: #if NOSDP
                    298:                a = getaux(acid);
                    299: #else
                    300:                a = (AUXTAB *) lock(acid, MISPARTITION, RNLY);
                    301: #endif
                    302: 
                    303:                if( a->axord == ndx )
                    304:                        return( a );
                    305: #if !NOSDP
                    306:                unlock(acid, RNLY);
                    307: #endif
                    308: 
                    309:                acid = a->axchainid;
                    310: 
                    311:                }
                    312: 
                    313:        return( NULL );         /* not found */
                    314: }
                    315: /*eject*/
                    316: SYMTAB *
                    317: makesym(sym, filp)
                    318: register SYMENT *sym;
                    319: INFILE *filp;
                    320: {
                    321: 
                    322: /*
                    323:  * Given a (new) *.o symbol table entry, add it to the ld
                    324:  * symbol table
                    325:  *
                    326:  * A ld symbol table entry is built and initialized. Appropriate
                    327:  * entries are made in the hash table and in the SDP address space
                    328:  *
                    329:  * The address of the ld symbol table entry is returned
                    330:  */
                    331: 
                    332:        register SYMTAB *p;     /* pointer to a ld symbol entry */
                    333:        register ITEMID acid;   /* SDP id of a ld symbol entry  */
                    334:        int hashval;            /* index into hash table for sym*/
                    335:        int auxcnt;
                    336:        char *name;
                    337: 
                    338:        name = PTRNAME( sym );
                    339:        if( (p = findsym(name)) == NULL ) {
                    340:                /*
                    341:                 * Case 1: The symbol is not in the ld symbol table.
                    342:                 *         Add a new entry, making it the head of the
                    343:                 *              collision chain
                    344:                 *         Update the hash table
                    345:                 */
                    346: #if NOSDP
                    347:                if (numldsyms >= MYSMTBSZ + (xsymcnt * XSMTBSZ)) {
                    348:                        if (xsymcnt >= MAXEXTRA)
                    349:                                lderror(2,0,"internal error: ","symbol table overflow");
                    350:                        xsymptr[xsymcnt++] = (SYMTAB *) myalloc(XSMTBSZ * SYMSIZ);
                    351:                        }
                    352:                acid = ++numldsyms;
                    353:                p = getsym(acid);
                    354: #else
                    355:                numldsyms++;
                    356:                acid = allocate(SYMSIZ, SYMSPACE, MISPARTITION);
                    357:                p = (SYMTAB *) lock(acid, MISPARTITION, WRTN);
                    358:                zero( p, SYMSIZ );
                    359: #endif
                    360:                p->sment = *sym;
                    361:                p->smnamelength = strlen( name ) + 1;
                    362: #if FLEXNAMES
                    363:                if ((sym->n_zeroes == 0L) && ((filp == NULL)
                    364:                                || (filp && (filp->flstrings == NULL))))
                    365:                        p->sment.n_nptr = savefn(sym->n_nptr);
                    366: #endif
                    367:                p->sment.n_numaux = 0;
                    368:                p->smmyacid = acid;
                    369: 
                    370:                hashval = hash(name);
                    371:                if( hashtab[hashval] > 0 ) {
                    372:                        SYMTAB *p2;
                    373: #if NOSDP
                    374:                        p2 = getsym(hashtab[hashval]);
                    375: #else
                    376:                        p2 = (SYMTAB *) lock(hashtab[hashval], HITPARTITION, WRTN);
                    377: #endif
                    378:                        p->smchainid = p2->smchainid;
                    379:                        p2->smchainid = acid;
                    380: #if !NOSDP
                    381:                        unlock(hashtab[hashval], WRTN);
                    382: #endif
                    383:                        ncolisns++;
                    384:                        }
                    385:                else
                    386:                        p->smchainid = acid;
                    387: 
                    388:                hashtab[hashval] = acid;
                    389:                return( p );
                    390:                }
                    391: 
                    392: /*
                    393:  * Case 2: The symbol is already in the symbol table
                    394:  *        Update the existing entry
                    395:  */
                    396: 
                    397:        if( sym->n_scnum != 0 ) {
                    398:                /*
                    399:                 * The makesym() argument 'sym' is the defining entry
                    400:                 * for the symbol
                    401:                 */
                    402:                if( p->sment.n_scnum == 0 ) {
                    403: 
                    404:                        /*
                    405:                         * The existing ld symbol table entry
                    406:                         * was from a reference
                    407:                         *
                    408:                         * Merge the information from the function
                    409:                         * argument and the ld symbol table
                    410:                         *
                    411:                         * The ld symbol table entry may have a ld-
                    412:                         * generated aux entry. If so, carry this
                    413:                         * entry over.
                    414:                         */
                    415: #if COMMON
                    416:                        if (Mflag && p->sment.n_value > 0)
                    417:                                lderror(0,0,NULL, "Symbol %s in %s is multiply defined.", 
                    418:                                        name,curfilnm );
                    419: #endif
                    420:                        p->sment.n_value = sym->n_value;
                    421:                        p->sment.n_scnum = sym->n_scnum;
                    422:                        p->sment.n_type = sym->n_type;
                    423:                        p->sment.n_sclass = sym->n_sclass;
                    424:                        }
                    425:                else if( p->sment.n_scnum != -1 )
                    426:                        lderror(1,0,NULL, "Symbol %s in %s is multiply defined. First defined in %s",
                    427:                                name, curfilnm, p->smscnptr->isfilptr->flname );
                    428:                }
                    429: 
                    430: #if COMMON
                    431:        else if (sym->n_value > 0)      /* & sym->n_scnum == 0 => common sym */
                    432:        {
                    433:                if (Mflag && (p->sment.n_scnum != 0 ||
                    434:                            (p->sment.n_scnum == 0 && p->sment.n_value > 0)))
                    435:                        lderror(0, 0, NULL, "Symbol %s in %s is multiply defined.",
                    436:                                name, curfilnm);
                    437: 
                    438:                /* set value for .common symbol */
                    439: 
                    440:                if ( p->sment.n_scnum == N_UNDEF )
                    441:                {
                    442:                        if ( !tflag && ( p->sment.n_value > 0 )
                    443:                                && ( p->sment.n_value != sym->n_value ))
                    444:                        {
                    445:                                lderror(0, 0, NULL,
                    446:                                        "Multiply defined symbol %s, in %s, has more than one size",
                    447:                                        PTRNAME(sym), curfilnm);
                    448:                        }
                    449: 
                    450:                        p->sment.n_value = /* max of old & new val */
                    451:                                (p->sment.n_value > sym->n_value) ?
                    452:                                 p->sment.n_value : sym->n_value;
                    453: 
                    454:                        if (sym->n_type != T_NULL && p->sment.n_type == T_NULL)
                    455:                                p->sment.n_type = sym->n_type;
                    456:                }
                    457:        }
                    458: #endif
                    459:        return( p );
                    460: }
                    461: /*eject*/
                    462: AUXTAB *
                    463: makeaux(sym, aux, ndx)
                    464: register SYMTAB *sym;  /* symbol table entry to which the aux entry belongs */
                    465: register AUXENT *aux;  /* new aux entry                                     */
                    466: int    ndx;    /* number of aux entries already added to entry      */
                    467: {
                    468: 
                    469: /*
                    470:  * Given a (*.o) aux entry, add it to an existing ld symbol
                    471:  * table entry
                    472:  *
                    473:  * The address of the ld aux entry is returned
                    474:  */
                    475: 
                    476:        register AUXTAB *a;
                    477:        register int tvndx;
                    478:        ITEMID acid;
                    479: 
                    480: #if DEBUG
                    481:        if( dflag > 15 )
                    482:                fprintf( stderr, "\nmakeaux %s ", SYMNAME( sym->sment ) );
                    483:        else if( dflag > 2 )
                    484:                fprintf(stderr, "makeaux: %s (%d) : %08lx %04x %04x %08lx %08lx %04x\n",
                    485:                        SYMNAME(sym->sment), ndx,
                    486:                        aux->x_sym.x_tagndx, aux->x_sym.x_misc.x_lnsz.x_lnno,
                    487:                        aux->x_sym.x_misc.x_lnsz.x_size,
                    488:                        aux->x_sym.x_fcnary.x_fcn.x_lnnoptr,
                    489:                        aux->x_sym.x_fcnary.x_fcn.x_endndx,
                    490:                        aux->x_sym.x_tvndx);
                    491: #endif
                    492: 
                    493: /*
                    494:  * Add the new aux entry to the symbol table entry
                    495:  */
                    496: 
                    497:        if( (acid = sym->smauxid) == 0 ) {
                    498:                /*
                    499:                 * Add the first aux entry for a symbol 
                    500:                 */
                    501:                if( ndx != 0 )
                    502:                        lderror(1,0,NULL,"Making aux entry %d for symbol %s out of sequence",
                    503:                                ndx+1, SYMNAME( sym->sment ));
                    504: #if NOSDP
                    505:                if (numldaux >= MYAXTBSZ + (xauxcnt * XAXTBSZ)) {
                    506:                        if (xauxcnt >= MAXEXTRA)
                    507:                                lderror(2,0,"internal error: ","aux table overflow");
                    508:                        xauxptr[xauxcnt++] = (AUXTAB *) myalloc(XAXTBSZ * AUXSIZ);
                    509:                        }
                    510:                acid = ++numldaux;
                    511:                a = getaux(acid);
                    512: #else
                    513:                numldaux++;
                    514:                acid = allocate(AUXSIZ, AUXSPACE, MISPARTITION);
                    515:                a = (AUXTAB *) lock(acid, MISPARTITION, WRTN);
                    516: 
                    517:                zero( a, AUXSIZ );
                    518: #endif
                    519:                a->axent = *aux;
                    520:                a->axord = 1;
                    521:                a->axmyacid = acid;
                    522:                a->axchainid = 0;
                    523: 
                    524:                sym->sment.n_numaux++;
                    525:                sym->smauxid = acid;
                    526: 
                    527:                return( a );
                    528:                }
                    529:        
                    530: #if NOSDP
                    531:        a = getaux(acid);
                    532: #else
                    533:        a = (AUXTAB *) lock(acid, MISPARTITION, WRTN);
                    534: #endif
                    535: 
                    536: 
                    537:        if( ndx == 0 ) {
                    538:                /*
                    539:                 * The symbol table entry already has a aux entry.
                    540:                 *
                    541:                 * This occurs when ld generates an aux entry for
                    542:                 * the symbol, to contain a tv slot index.
                    543:                 *
                    544:                 * Merge this ld-entry with the entry obtained from
                    545:                 * the input file
                    546:                 *
                    547:                 * Two cases: due to a tv ref in an earlier
                    548:                 *      input file, the aux entry in the symbol
                    549:                 *      table is a dummy one and should be
                    550:                 *      overwritten except for the tvndx.
                    551:                 *
                    552:                 *  (2) we are doing subsystem linking and
                    553:                 *      we are getting dummy and real auxents
                    554:                 *      in an unknown order.  in this case
                    555:                 *      we have to test to see which one is
                    556:                 *      the dummy and either overwrite it
                    557:                 *      or throw it away.  We have this info
                    558:                 *      in psymtab() and should be an arg
                    559:                 *      to makeaux().  However a KLUDGE is
                    560:                 *      to see which one is all 0's except
                    561:                 *      for the tvndx and call that one the
                    562:                 *      dummy.  This should be cleaned up
                    563:                 *      and made reasonable later.
                    564:                 */
                    565: 
                    566:                /* if incoming is not dummy */
                    567:                if ( ! ( (aux->x_sym.x_tagndx == 0L) &&
                    568:                        (aux->x_sym.x_misc.x_fsize == 0L) &&
                    569:                           (aux->x_sym.x_fcnary.x_fcn.x_lnnoptr == 0L) &&
                    570:                              (aux->x_sym.x_fcnary.x_fcn.x_endndx == 0L) ) ) {
                    571:                        tvndx = a->axent.x_sym.x_tvndx;
                    572:                        a->axent = *aux;
                    573:                        if (tvndx != N_TV)
                    574:                                a->axent.x_sym.x_tvndx = tvndx;
                    575:                        }
                    576: 
                    577:                return( a );
                    578:                }
                    579: 
                    580: /*
                    581:  * Step down the chain of aux entries, to the correct position for the
                    582:  * new entry
                    583:  */
                    584: 
                    585:        while( a->axord != ndx ) {
                    586: #if NOSDP
                    587:                acid = a->axchainid;
                    588:                a = getaux(acid);
                    589: #else
                    590:                unlock(acid, RNLY);
                    591:                acid = a->axchainid;
                    592:                a = (AUXTAB *) lock(acid, MISPARTITION, RNLY);
                    593: #endif
                    594:                }
                    595: 
                    596:        if( a->axchainid != 0 ) {
                    597:                /*
                    598:                 * Overwriting an existing aux entry (but not the first aux
                    599:                 * entry). Warn the user
                    600:                 */
                    601:                lderror(0,0,NULL,"Overwriting aux entry %d of symbol %s",
                    602:                        ndx+1, SYMNAME( sym->sment ));
                    603: 
                    604: #if NOSDP
                    605:                acid = a->axchainid;
                    606:                a = getaux(acid);
                    607: #else
                    608:                unlock(acid, RNLY);
                    609:                acid = a->axchainid;
                    610:                a = (AUXTAB *) lock(acid, MISPARTITION, WRTN);
                    611: #endif
                    612: 
                    613:                a->axent = *aux;
                    614: 
                    615:                return( a );
                    616:                }
                    617:        else {
                    618:                /*
                    619:                 * Add the new aux entry at the end of the list
                    620:                 */
                    621: #if NOSDP
                    622:                if (numldaux >= MYAXTBSZ + (xauxcnt * XAXTBSZ)) {
                    623:                        if (xauxcnt >= MAXEXTRA)
                    624:                                lderror(2,0,"internal error: ","aux table overflow");
                    625:                        xauxptr[xauxcnt++] = (AUXTAB *) myalloc(XAXTBSZ * AUXSIZ);
                    626:                        }
                    627:                acid = a->axchainid = ++numldsyms;
                    628:                a = getaux(acid);
                    629: #else
                    630:                numldaux++;
                    631:                a->axchainid = allocate(AUXSIZ, AUXSPACE, MISPARTITION);
                    632:                unlock(acid, WRTN);
                    633:                acid = a->axchainid;
                    634:                a = (AUXTAB *) lock(acid, MISPARTITION, WRTN);
                    635: 
                    636:                zero( a, AUXSIZ );
                    637: #endif
                    638:                a->axent = *aux;
                    639:                a->axord = ndx + 1;
                    640:                a->axmyacid = acid;
                    641:                a->axchainid = 0;
                    642: 
                    643:                sym->sment.n_numaux++;
                    644: 
                    645:                return( a );
                    646:                }
                    647: }
                    648: 
                    649: ITEMID
                    650: putsym(sym, changed)
                    651: SYMTAB *sym;
                    652: int changed;
                    653: {
                    654: 
                    655: /*
                    656:  * Return a ld symbol table entry to the SDP empire ("unlock")
                    657:  * Return the SDP access ID
                    658:  */
                    659: 
                    660: #if DEBUG
                    661:        if( dflag > 15 )
                    662:                fprintf( stderr, "\n putsym %s ", SYMNAME( sym->sment ));
                    663: #endif
                    664: 
                    665: #if !NOSDP
                    666:        unlock(sym->smmyacid, (changed ? WRTN : RNLY));
                    667: #endif
                    668:        return( sym->smmyacid );
                    669: }
                    670: 
                    671: 
                    672: ITEMID
                    673: putaux(aux, changed)
                    674: AUXTAB *aux;
                    675: int changed;
                    676: {
                    677: 
                    678: /*
                    679:  * Return an auxiliary entry to the SDP empire ("unlock")
                    680:  *
                    681:  * Return the SDP access ID
                    682:  */
                    683: 
                    684: #if DEBUG
                    685:        if( dflag > 15 )
                    686:                fprintf( stderr, "\n putaux %8lx ", aux->axmyacid );
                    687: #endif
                    688: 
                    689: #if !NOSDP
                    690:        unlock(aux->axmyacid, (changed ? WRTN : RNLY));
                    691: #endif
                    692:        return( aux->axmyacid );
                    693: }
                    694: 
                    695: 
                    696: 
                    697: SYMTAB *
                    698: getsym(acid)
                    699: register ITEMID acid;
                    700: {
                    701: 
                    702: /*
                    703:  * Return a pointer to an ld symbol table entry, given the
                    704:  * SDP access ID
                    705:  */
                    706: 
                    707: #if DEBUG
                    708:        if( dflag > 15 )
                    709:                fprintf( stderr, "\n getsym %8lx ", acid );
                    710: #endif
                    711: 
                    712: #if NOSDP
                    713:        if (acid <= 0)
                    714:                lderror(2,0,"internal error: ","negative symbol table id");
                    715:        if (acid <= MYSMTBSZ)
                    716:                return(&mysymtab[acid]);
                    717:        acid -= (MYSMTBSZ + 1);
                    718:        if (acid < xsymcnt * XSMTBSZ)
                    719:                return( (SYMTAB *) ( (long) xsymptr[acid/XSMTBSZ] + ((acid % XSMTBSZ) * SYMSIZ)) );
                    720:        lderror(2,0,"internal error: ","invalid symbol table id");
                    721: #else
                    722:        return( (SYMTAB *) lock(acid, MISPARTITION, RNLY) );
                    723: #endif
                    724: }
                    725: 
                    726: AUXTAB *
                    727: getaux(acid)
                    728: ITEMID acid;
                    729: {
                    730: 
                    731: /*
                    732:  * Return a pointer to a ld aux entry, given the
                    733:  * SDP access ID
                    734:  */
                    735: 
                    736: #if DEBUG
                    737:        if( dflag > 15 )
                    738:                fprintf( stderr, "\n getaux %8lx ", acid );
                    739: #endif
                    740: 
                    741: #if NOSDP
                    742:        if (acid <= 0)
                    743:                lderror(2,0,"internal error: ","negative aux table id");
                    744:        if (acid <= MYAXTBSZ)
                    745:                return(&myauxtab[acid]);
                    746:        acid -= (MYAXTBSZ + 1);
                    747:        if (acid < xauxcnt * XAXTBSZ)
                    748:                return( (AUXTAB *) ( (long) xauxptr[acid/XAXTBSZ] + ((acid % XAXTBSZ) * AUXSIZ)) );
                    749:        lderror(2,0,"internal error: ","invalid aux table id");
                    750: #else
                    751:        return( (AUXTAB *) lock(acid, MISPARTITION, RNLY) );
                    752: #endif
                    753: }
                    754: /*eject*/
                    755: long
                    756: #if FLEXNAMES
                    757: psymtab(fdes, numsyms, filp, symbuf,strtabptr)
                    758: char *strtabptr; /* pointer to string table with long symbol names, if
                    759:                     one exists */
                    760: #else
                    761: psymtab(fdes, numsyms, filp, symbuf, strtabptr)
                    762: #endif
                    763: FILE *fdes;    /* pointer to the file, positioned to the symbol table */
                    764: long numsyms;  /* total number of symbol table entries for the file   */
                    765: INFILE *filp;  /* pointer to the infilist entry for the file          */
                    766: register SYMENT *symbuf;
                    767: {
                    768: 
                    769: /*
                    770:  * This routine is called during the scanning of the LDFILE list.
                    771:  *
                    772:  * Every *.o and archive library member which is to be link edited
                    773:  * is processed exactly once by this function:
                    774:  *
                    775:  *     1. Add all ld symbols from the file to ld's cumulative
                    776:  *             ld symbol table
                    777:  *     ********** for FLEXNAMES ***********
                    778:  *     1a. When there is a long symbol name, change the
                    779:  *             offset of the name in the symbol table to a pointer
                    780:  *             to the name
                    781:  *     ************************************
                    782:  *     2. Compute and return the number of local symbol table
                    783:  *             entries (locals, statics, functions, etc.) for this
                    784:  *             file
                    785:  */
                    786: 
                    787: 
                    788:        register SYMENT *sym;           /* input file symbol table entry     */
                    789:        register AUXENT *aux;           /* symbol aux entry                  */
                    790:        register SYMTAB *symp;          /* ld symbol table entry pointer     */
                    791:        register long n;
                    792:        long locsyms,           /* nbr local symbols from input file */
                    793:             relsyms,           /* nbr relocatable symbols           */
                    794:             l;
                    795:        int  i;                 /* for-loop index                    */
                    796:        char tmp_numaux,
                    797:             tmp_sclass;
                    798:        SYMENT  lsymbuf;
                    799:        AUXENT  lauxbuf;
                    800: 
                    801:        sym = &lsymbuf;
                    802:        aux = &lauxbuf;
                    803: 
                    804:        locsyms = 0L;
                    805:        relsyms = 0L;
                    806: 
                    807:        for( n = 0L; n < numsyms; n++ ) {
                    808: 
                    809: #if !PORTAR && !PORT5AR
                    810:                if (symbuf != NULL) 
                    811:                        sym = symbuf++;
                    812:                else 
                    813: #endif
                    814:                        if (fread(sym,SYMESZ,1,fdes) != 1)
                    815:                                lderror(2,0,NULL,"fail to read symbol table of file %s",
                    816:                                filp->flname);
                    817: 
                    818: #if FLEXNAMES
                    819:                        /* this symbol has a long name - change offset to ptr */
                    820:                if (sym->n_zeroes == 0L)
                    821:                {
                    822:                        if (strtabptr == NULL)
                    823:                                lderror( 2, 90, NULL, "no string table in file %s", filp->flname );
                    824:                        sym->n_nptr = strtabptr + sym->n_offset;
                    825:                }
                    826: #endif
                    827: 
                    828:                switch( sym->n_sclass ) {
                    829: 
                    830:                /*
                    831:                 * Symbols of type C_EXT are global, and must be added
                    832:                 * to ld's cumulative symbol table
                    833:                 */
                    834:                case C_EXT:
                    835:                        relsyms++;
                    836:                        symp = makesym(sym, filp);
                    837: 
                    838:                        if( sym->n_scnum > 0 )
                    839:                                symp->smscnptr = sectnum(sym->n_scnum,filp);
                    840: 
                    841: 
                    842:                        /*
                    843:                         * Functions, although added to ld's symbol
                    844:                         * table, must be put in the "local symbol"
                    845:                         * section of the final output file
                    846:                         */
                    847:                        if( ISFCN(sym->n_type) ) {
                    848:                                symp->smoutndx = locsyms;
                    849:                                locsyms += (long) (sym->n_numaux + 1);
                    850:                                symp->smlocflg = 1;
                    851:                                }
                    852: 
                    853:                        n += (long) sym->n_numaux;
                    854:                        tmp_numaux = sym->n_numaux;
                    855:                        for( i = 0; i < tmp_numaux; i++ ) {
                    856: #if !PORTAR && !PORT5AR
                    857:                                if (symbuf != NULL) 
                    858:                                        aux = (AUXENT *) symbuf++;
                    859:                                else 
                    860: #endif
                    861:                                        if (fread(aux,AUXESZ,1,fdes) != 1)
                    862:                                                lderror(2,0,NULL,"fail to read aux entries of file %s",
                    863:                                                filp->flname);
                    864: 
                    865: #if TRVEC
                    866:                                if ( i == 0 && (ISFCN( sym->n_type ) || (sym->n_type == 0)))
                    867:                                     if (aux->x_sym.x_tvndx == N_TV) {
                    868:                                        aux->x_sym.x_tvndx = P_TV;
                    869:                                        tvspec.tvosptr->oshdr.s_size += TVENTSZ;
                    870:                                        }
                    871: #endif
                    872:                                putaux( makeaux(symp, aux, i), 1 );
                    873:                                }
                    874: 
                    875:                        PUTSYM(symp, 1);
                    876:                        break;
                    877: 
                    878:                case C_FILE:
                    879: #if DMERT || XL
                    880:                        if (!dmertplib)
                    881: #endif
                    882:                                locsyms += 1 + (long) sym->n_numaux;
                    883:                        if (sym->n_numaux) {
                    884:                                n += sym->n_numaux;
                    885: #if !PORTAR && !PORT5AR
                    886:                                if (symbuf != NULL)
                    887:                                        symbuf++;
                    888:                                else
                    889: #endif
                    890:                                        if (fseek( fdes, (long) (AUXESZ) * sym->n_numaux, 1 ) != 0)
                    891:                                                lderror( 2, 0, NULL, "fail to skip aux entry of %s", filp->flname);
                    892:                        }
                    893:                        break;
                    894: 
                    895:                case C_STAT:
                    896: #if UNIX
                    897:                        relsyms++;
                    898:                        locsyms += 1 + sym->n_numaux;
                    899:                        if (sym->n_numaux == 1) {
                    900:                                n++;
                    901: #if !PORTAR && !PORT5AR
                    902:                                if (symbuf != NULL)
                    903:                                        symbuf++;
                    904:                                else
                    905: #endif
                    906:                                        if (fseek( fdes, (long) AUXESZ, 1 ) != 0)
                    907:                                                lderror( 2, 0, NULL, "fail to skip the aux entry of %s", filp->flname);
                    908:                        };
                    909:                        continue;
                    910: #endif
                    911: 
                    912:                case C_HIDDEN:
                    913:                        relsyms++;
                    914: 
                    915:                default:
                    916: #if DMERT || XL
                    917:                        if (!dmertplib)
                    918: #endif
                    919: #if UNIX || XL
                    920:                        if (!xflag)
                    921: #endif
                    922:                                locsyms++;
                    923: 
                    924:                        if( sym->n_numaux > 0 ) {
                    925: 
                    926: #if DMERT || XL
                    927:                                if (!dmertplib)
                    928: #endif
                    929: #if UNIX || XL
                    930:                                if (!xflag)
                    931: #endif
                    932:                                        locsyms += (long) sym->n_numaux;
                    933:                                n += (long) sym->n_numaux;
                    934:                                tmp_sclass = sym->n_sclass;
                    935:                                tmp_numaux = sym->n_numaux;
                    936: #if !PORTAR && !PORT5AR
                    937:                                if (symbuf != NULL) 
                    938:                                        aux = (AUXENT *) symbuf++;
                    939:                                else 
                    940: #endif
                    941:                                        if (fread(aux,AUXESZ,1,fdes) != 1)
                    942:                                                lderror(2,0,NULL,"fail to read aux entries of %s",
                    943:                                                filp->flname);
                    944: 
                    945:                                /*
                    946:                                 * Skip all aux entries after the first
                    947:                                 */
                    948:                                if( tmp_numaux > 1 ) 
                    949: #if !PORTAR && !PORT5AR
                    950:                                        if (symbuf != NULL) 
                    951:                                                symbuf++;
                    952:                                        else
                    953: #endif
                    954:                                                if (fseek(fdes, (long) (AUXESZ * (tmp_numaux-1)), 1) != 0)
                    955:                                                        lderror(2,0,NULL,"fail to skip the aux entry of %s",
                    956:                                                        filp->flname);
                    957: 
                    958:                                /*
                    959:                                 * Skip all members of structures and
                    960:                                 * unions
                    961:                                 */
                    962:                                if( ISTAG(tmp_sclass) ) {
                    963:                                        l = aux->x_sym.x_fcnary.x_fcn.x_endndx - n - 1;
                    964: #if DMERT || XL
                    965:                                        if (!dmertplib)
                    966: #endif
                    967: #if UNIX || XL
                    968:                                        if (!xflag)
                    969: #endif
                    970:                                                locsyms += l;
                    971:                                        n = aux->x_sym.x_fcnary.x_fcn.x_endndx - 1;
                    972: #if !PORTAR && !PORT5AR
                    973:                                        if (symbuf != NULL) 
                    974:                                                symbuf += l;
                    975:                                        else 
                    976: #endif
                    977:                                                if (fseek(fdes, l * SYMESZ, 1) != 0)
                    978:                                                        lderror(2,0,NULL,"fail to skip the mem of struct of %s",
                    979:                                                        filp->flname);
                    980:                                        }
                    981: #if TRVEC
                    982: 
                    983:                                /*
                    984:                                 * Increment size of .tv if this
                    985:                                 * symbol needs a slot in the tv.
                    986:                                 */
                    987:                                if( aflag && tvflag && (tmp_sclass == C_STAT) && (aux->x_sym.x_tvndx == N_TV) )
                    988:                                        tvspec.tvosptr->oshdr.s_size += TVENTSZ;
                    989: #endif
                    990:                                }
                    991:                        }
                    992:                }
                    993: 
                    994:        if( relsyms > maxrelocsms )
                    995:                maxrelocsms = relsyms;
                    996: 
                    997:        return( locsyms );
                    998: }
                    999: /*eject*/
                   1000: SYMTAB *
                   1001: loopsym(sym, changed)
                   1002: SYMTAB *sym;
                   1003: int changed;
                   1004: {
                   1005: 
                   1006: /*
                   1007:  * Loop through all symbol table entries 
                   1008:  */
                   1009: 
                   1010: #if NOSDP
                   1011:        static  long    ndx;
                   1012:        if (sym == NULL) ndx = 0;
                   1013:        if (ndx < numldsyms)
                   1014:                return(getsym(++ndx));
                   1015:        else
                   1016:                return(NULL);
                   1017: #else
                   1018:        static long     offset,  /* offset of next symbol in page */
                   1019:                        page;    /* SDP page number               */
                   1020:        register ITEMID acid;
                   1021: /*
                   1022:  * WARNING: this implementation of loopsym() is extremely dependent
                   1023:  *     upon knowing exactly how SDP does things.  In particular, it
                   1024:  *     is dependent upon symbol table entries being in one SDP space,
                   1025:  *     separate from aux entries.  Anyone touching SDP 
                   1026:  *     defines or code should check this function for accuracy.
                   1027:  */
                   1028: 
                   1029: #if DEBUG
                   1030:        if( dflag > 15 )
                   1031:                fprintf( stderr, "\nloopsym %8s ", sym->sment.n_name );
                   1032: #endif
                   1033: 
                   1034: /*
                   1035:  * This routine is used as follows:
                   1036:  *
                   1037:  *     For the first call to this routine, sym is set to NULL.
                   1038:  *     For all subsequent calls, sym equals the value returned by
                   1039:  *             the previous call.
                   1040:  *     When sym again equals NULL, the entire table has been searched.
                   1041:  */
                   1042: 
                   1043:        if( sym == NULL ) {
                   1044:                /*
                   1045:                 * Build the itemid for first entry in symbol table
                   1046:                 */
                   1047:                page = 1L;
                   1048:                offset = 0L;
                   1049:                acid = BUILDPN(page, SYMSPACE) + offset;
                   1050:                if ( global_frames[SYMSPACE].maxpage == 0L )
                   1051:                        return( NULL ); /* no symbols */
                   1052:                return( (SYMTAB *) lock(acid, MISPARTITION, RNLY) );
                   1053:                }
                   1054: 
                   1055: /*
                   1056:  * Find the next symbol table entry:
                   1057:  *
                   1058:  */
                   1059: 
                   1060:        unlock(sym->smmyacid, (changed ? WRTN : RNLY));
                   1061: 
                   1062:        offset += (long) SYMSIZ;
                   1063:        if ( (offset + (long) SYMSIZ) > (long) PAGESIZE ) {
                   1064:                offset = 0L;
                   1065:                if ( ++page > global_frames[SYMSPACE].maxpage )
                   1066:                        return(NULL);
                   1067:        } else {
                   1068:                /*
                   1069:                 * are we past the last entry on the last page?
                   1070:                 */
                   1071:                if ( (page == global_frames[SYMSPACE].curpage) &&
                   1072:                    (offset == global_frames[SYMSPACE].curoffset) )
                   1073:                        return(NULL);
                   1074:                }
                   1075:        acid = BUILDPN(page, SYMSPACE) + offset;
                   1076:        return( (SYMTAB *) lock(acid, MISPARTITION, RNLY) );
                   1077: #endif
                   1078: }
                   1079: /*eject*/
                   1080: AUXTAB *
                   1081: loopaux(sym, aux, changed)
                   1082: SYMTAB *sym;
                   1083: AUXTAB *aux;
                   1084: int changed;
                   1085: {
                   1086: 
                   1087: /*
                   1088:  * Loop through all the aux entries for a given ld symbol table entry
                   1089:  *
                   1090:  *
                   1091:  * This routine is used as follows:
                   1092:  *
                   1093:  *     For the first call to this routine, aux is set to NULL.
                   1094:  *     For all subsequent calls, aux equals the value returned by
                   1095:  *             the previous call.
                   1096:  *     When aux again equals NULL, all aux entries have been returned
                   1097:  */
                   1098: 
                   1099: #if DEBUG
                   1100:        if( dflag > 15 )
                   1101:                fprintf( stderr, "\nloopaux %s ", SYMNAME( sym->sment ) );
                   1102: #endif
                   1103: 
                   1104:        if( aux == NULL ) {
                   1105:                /*
                   1106:                 * Get the first aux entry, pointed to by the ld symbol
                   1107:                 * table entry
                   1108:                 */
                   1109:                if( sym->smauxid != 0 )
                   1110: #if NOSDP
                   1111:                        return(getaux(sym->smauxid));
                   1112: #else
                   1113:                        return( (AUXTAB *) lock(sym->smauxid, MISPARTITION, WRTN) );
                   1114: #endif
                   1115: 
                   1116:                return( NULL );
                   1117:                }
                   1118: 
                   1119: /*
                   1120:  * Find the next aux entry
                   1121:  */
                   1122: 
                   1123: #if NOSDP
                   1124:        if (aux->axchainid != 0)
                   1125:                return(getaux(aux->axchainid));
                   1126: #else
                   1127:        unlock(aux->axmyacid, (changed ? WRTN : RNLY));
                   1128: 
                   1129:        if( aux->axchainid != 0 )
                   1130:                return( (AUXTAB *) lock(aux->axchainid, MISPARTITION, WRTN) );
                   1131: #endif
                   1132: 
                   1133:        return( NULL );
                   1134: }
                   1135: /*eject*/
                   1136: INSECT *
                   1137: sectnum(i, fp)
                   1138: int i;
                   1139: INFILE *fp;
                   1140: {
                   1141: 
                   1142: /*
                   1143:  * Called by psymtab to retrieve a pointer to the  i-th section header
                   1144:  */
                   1145: 
                   1146:        register INSECT *sptr;
                   1147: 
                   1148:        if (i == 0)
                   1149:                return(NULL);
                   1150: 
                   1151: 
                   1152:        for ( sptr = fp->flishead; sptr != NULL; sptr = sptr->isnext )
                   1153:                if ( sptr->isecnum == i)
                   1154:                        return(sptr);
                   1155:        return(NULL);
                   1156: }
                   1157: /*eject*/
                   1158: ITEMID
                   1159: add_dot(dot_val, dot_sec)
                   1160: long dot_val;
                   1161: INSECT *dot_sec;
                   1162: {
                   1163:        register SYMTAB *sym;
                   1164:        register ITEMID acid;
                   1165:        static int count = 0;
                   1166: 
                   1167: /*
                   1168:  * This is a special-purpose "makesym()" designed for exclusive use
                   1169:  * in assignment expressions. It will create a symbol table entry
                   1170:  * having the following characteristics:
                   1171:  *
                   1172:  *     n_name:         .dotnnn         001 <= nnn <= 999
                   1173:  *     n_value:        dot_val
                   1174:  *     n_scnum:        0
                   1175:  *     n_type:         T_NULL
                   1176:  *     n_sclass:       C_NULL
                   1177:  *     n_numaux:       0
                   1178:  *
                   1179:  *     smscnptr:       dot_sec
                   1180:  *     smlocflg:       1
                   1181:  *
                   1182:  * The symbol table entry will NOT appear in the hash table, and hence 
                   1183:  * will not be accessible except thorugh the stored itemid returned
                   1184:  * by this function
                   1185:  */
                   1186: 
                   1187: #if NOSDP
                   1188:        if (numldsyms >= MYSMTBSZ + (xsymcnt * XSMTBSZ)) {
                   1189:                if (xsymcnt >= MAXEXTRA)
                   1190:                        lderror(2,0,"internal error: ","symbol table overflow");
                   1191:                xsymptr[xsymcnt++] = (SYMTAB *) myalloc(XSMTBSZ * SYMSIZ);
                   1192:                }
                   1193:        acid = ++numldsyms;
                   1194:        sym = getsym(acid);
                   1195: #else
                   1196:        acid = allocate(SYMSIZ, SYMSPACE, MISPARTITION);
                   1197:        sym = (SYMTAB *) lock(acid, MISPARTITION, WRTN);
                   1198: 
                   1199:        zero(sym, SYMSIZ);
                   1200: #endif
                   1201:        sprintf(sym->sment.n_name, ".dot%03d", ++count);
                   1202:        sym->sment.n_value = dot_val;
                   1203:        sym->smscnptr = dot_sec;
                   1204:        sym->smmyacid = acid;
                   1205:        sym->smchainid = acid;
                   1206:        sym->smlocflg = 1;
                   1207: 
                   1208: #if !NOSDP
                   1209:        unlock(acid, WRTN);
                   1210: #endif
                   1211: 
                   1212:        return( acid );
                   1213: 
                   1214: }
                   1215: 
                   1216: #if !NOSDP
                   1217: auxinit()
                   1218: {
                   1219:        /* initialize SDP */
                   1220: 
                   1221:        if ( aux_called )
                   1222:                lderror(2,0,NULL,"attempt to re-initialize SDP aux space");
                   1223: 
                   1224:        sprintf( auxname, "%s/%s", TMPDIR, "ldXXXXXX");
                   1225:        mktemp(auxname);
                   1226:        aux_called++;
                   1227:        if ( sdpinit(auxname, CREATE, AUXSPACE) != AUXSPACE )
                   1228:                lderror(2,0,NULL,"failure to initialize SDP aux space");
                   1229:        else
                   1230:                aux_called++;
                   1231: }
                   1232: 
                   1233: auxfini()
                   1234: {
                   1235: 
                   1236:        char buf[sizeof(auxname)*2+20];
                   1237: 
                   1238:        if ( aux_called == 2 ) {
                   1239:                aux_called--;
                   1240:                if ( sdpterm(AUXSPACE) < 0 )
                   1241:                        lderror(2,0,NULL,"failure in closing SDP aux space");
                   1242:                }
                   1243: 
                   1244:        if ( aux_called != 1)
                   1245:                return;
                   1246:        aux_called--;
                   1247: 
                   1248: #if TS || RT
                   1249:        sprintf(buf, "rm -r %s", auxname);
                   1250: #else
                   1251:        sprintf(buf, "rm -r %s; rmdir %s", auxname, auxname);
                   1252: #endif
                   1253: 
                   1254:        if ( fork() == 0 ) {
                   1255:                execl("/bin/sh", "sh", "-c", buf, 0);
                   1256:                lderror(0,0,NULL, "failure in the execl of %s",buf);
                   1257:                _exit(127);
                   1258:                }
                   1259: }
                   1260: #endif

unix.superglobalmegacorp.com

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