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

1.1       root        1: /*
                      2:  * Copyright (c) 1983 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)c.c        5.10 (Berkeley) 6/1/90";
                     22: #endif /* not lint */
                     23: 
                     24: /*
                     25:  * C-dependent symbol routines.
                     26:  */
                     27: 
                     28: #include "defs.h"
                     29: #include "symbols.h"
                     30: #include "printsym.h"
                     31: #include "languages.h"
                     32: #include "c.h"
                     33: #include "tree.h"
                     34: #include "eval.h"
                     35: #include "operators.h"
                     36: #include "mappings.h"
                     37: #include "process.h"
                     38: #include "runtime.h"
                     39: #include "machine.h"
                     40: 
                     41: #ifndef public
                     42: #   include "tree.h"
                     43: #endif
                     44: 
                     45: #define isdouble(range) ( \
                     46:     range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \
                     47: )
                     48: 
                     49: #define isrange(t, name) (t->class == RANGE and istypename(t->type, name))
                     50: 
                     51: private Language langC;
                     52: private Language langCplpl;
                     53: 
                     54: /*
                     55:  * Initialize C language information.
                     56:  */
                     57: 
                     58: public c_init()
                     59: {
                     60:     langC = language_define("c", ".c");
                     61:     language_setop(langC, L_PRINTDECL, c_printdecl);
                     62:     language_setop(langC, L_PRINTVAL, c_printval);
                     63:     language_setop(langC, L_TYPEMATCH, c_typematch);
                     64:     language_setop(langC, L_BUILDAREF, c_buildaref);
                     65:     language_setop(langC, L_EVALAREF, c_evalaref);
                     66:     language_setop(langC, L_MODINIT, c_modinit);
                     67:     language_setop(langC, L_HASMODULES, c_hasmodules);
                     68:     language_setop(langC, L_PASSADDR, c_passaddr);
                     69: 
                     70:     langCplpl = language_define("c++", "..c");
                     71:     language_setop(langCplpl, L_PRINTDECL, c_printdecl);
                     72:     language_setop(langCplpl, L_PRINTVAL, c_printval);
                     73:     language_setop(langCplpl, L_TYPEMATCH, c_typematch);
                     74:     language_setop(langCplpl, L_BUILDAREF, c_buildaref);
                     75:     language_setop(langCplpl, L_EVALAREF, c_evalaref);
                     76:     language_setop(langCplpl, L_MODINIT, c_modinit);
                     77:     language_setop(langCplpl, L_HASMODULES, c_hasmodules);
                     78:     language_setop(langCplpl, L_PASSADDR, c_passaddr);
                     79: }
                     80: 
                     81: /*
                     82:  * Test if two types are compatible.
                     83:  */
                     84: 
                     85: public Boolean c_typematch(type1, type2)
                     86: Symbol type1, type2;
                     87: {
                     88:     Boolean b;
                     89:     register Symbol t1, t2, tmp;
                     90: 
                     91:     t1 = type1;
                     92:     t2 = type2;
                     93:     if (t1 == t2) {
                     94:        b = true;
                     95:     } else {
                     96:        t1 = rtype(t1);
                     97:        t2 = rtype(t2);
                     98:        if (t1 == t_char->type or t1 == t_int->type or t1 == t_real->type) {
                     99:            tmp = t1;
                    100:            t1 = t2;
                    101:            t2 = tmp;
                    102:        }
                    103:        b = (Boolean) (
                    104:            (
                    105:                isrange(t1, "int") and !isdouble(t1) /* sigh */ and
                    106:                (t2 == t_int->type or t2 == t_char->type)
                    107:            ) or (
                    108:                isrange(t1, "char") and
                    109:                (t2 == t_char->type or t2 == t_int->type)
                    110:            ) or (
                    111:                t1->class == RANGE and isdouble(t1) and t2 == t_real->type
                    112:            ) or (
                    113:                t1->class == RANGE and t2->class == RANGE and
                    114:                t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
                    115:                t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
                    116:            ) or (
                    117:                t1->class != RANGE and t1->type == t2->type and (
                    118:                    (t1->class == t2->class) or
                    119:                    (t1->class == SCAL and t2->class == CONST) or
                    120:                    (t1->class == CONST and t2->class == SCAL)
                    121:                )
                    122:            ) or (
                    123:                t1->class == PTR and c_typematch(t1->type, t_char) and
                    124:                t2->class == ARRAY and c_typematch(t2->type, t_char) and
                    125:                t2->language == primlang
                    126:            )
                    127:        );
                    128:     }
                    129:     return b;
                    130: }
                    131: 
                    132: /*
                    133:  * Print out the declaration of a C variable.
                    134:  */
                    135: 
                    136: public c_printdecl(s)
                    137: Symbol s;
                    138: {
                    139:     printdecl(s, 0);
                    140: }
                    141: 
                    142: private printdecl(s, indent)
                    143: register Symbol s;
                    144: Integer indent;
                    145: {
                    146:     register Symbol t;
                    147:     Boolean semicolon, newline;
                    148: 
                    149:     semicolon = true;
                    150:     newline = true;
                    151:     if (indent > 0) {
                    152:        printf("%*c", indent, ' ');
                    153:     }
                    154:     if (s->class == TYPE) {
                    155:        printf("typedef ");
                    156:     }
                    157:     switch (s->class) {
                    158:        case CONST:
                    159:            if (s->type->class == SCAL) {
                    160:                printf("enumeration constant with value ");
                    161:                eval(s->symvalue.constval);
                    162:                c_printval(s);
                    163:            } else {
                    164:                printf("const %s = ", symname(s));
                    165:                printval(s);
                    166:            }
                    167:            break;
                    168: 
                    169:        case TYPE:
                    170:        case VAR:
                    171:            if (s->class != TYPE and s->storage == INREG) {
                    172:                printf("register ");
                    173:            }
                    174:            if (s->type->class == ARRAY) {
                    175:                printtype(s->type, s->type->type, indent);
                    176:                t = rtype(s->type->chain);
                    177:                assert(t->class == RANGE);
                    178:                printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1);
                    179:            } else {
                    180:                printtype(s, s->type, indent);
                    181:                if (s->type->class != PTR) {
                    182:                    printf(" ");
                    183:                }
                    184:                printf("%s", symname(s));
                    185:            }
                    186:            break;
                    187: 
                    188:        case FIELD:
                    189:            if (s->type->class == ARRAY) {
                    190:                printtype(s->type, s->type->type, indent);
                    191:                t = rtype(s->type->chain);
                    192:                assert(t->class == RANGE);
                    193:                printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1);
                    194:            } else {
                    195:                printtype(s, s->type, indent);
                    196:                if (s->type->class != PTR) {
                    197:                    printf(" ");
                    198:                }
                    199:                printf("%s", symname(s));
                    200:            }
                    201:            if (isbitfield(s)) {
                    202:                printf(" : %d", s->symvalue.field.length);
                    203:            }
                    204:            break;
                    205: 
                    206:        case TAG:
                    207:            if (s->type == nil) {
                    208:                findtype(s);
                    209:                if (s->type == nil) {
                    210:                    error("unexpected missing type information");
                    211:                }
                    212:            }
                    213:            printtype(s, s->type, indent);
                    214:            break;
                    215: 
                    216:        case RANGE:
                    217:        case ARRAY:
                    218:        case RECORD:
                    219:        case VARNT:
                    220:        case PTR:
                    221:        case FFUNC:
                    222:            semicolon = false;
                    223:            printtype(s, s, indent);
                    224:            break;
                    225: 
                    226:        case SCAL:
                    227:            printf("(enumeration constant, value %d)", s->symvalue.iconval);
                    228:            break;
                    229: 
                    230:        case PROC:
                    231:            semicolon = false;
                    232:            printf("%s", symname(s));
                    233:            c_listparams(s);
                    234:            newline = false;
                    235:            break;
                    236: 
                    237:        case FUNC:
                    238:            semicolon = false;
                    239:            if (not istypename(s->type, "void")) {
                    240:                printtype(s, s->type, indent);
                    241:                printf(" ");
                    242:            }
                    243:            printf("%s", symname(s));
                    244:            c_listparams(s);
                    245:            newline = false;
                    246:            break;
                    247: 
                    248:        case MODULE:
                    249:            semicolon = false;
                    250:            printf("source file \"%s.c\"", symname(s));
                    251:            break;
                    252: 
                    253:        case PROG:
                    254:            semicolon = false;
                    255:            printf("executable file \"%s\"", symname(s));
                    256:            break;
                    257: 
                    258:        default:
                    259:            printf("[%s]", classname(s));
                    260:            break;
                    261:     }
                    262:     if (semicolon) {
                    263:        putchar(';');
                    264:     }
                    265:     if (newline) {
                    266:        putchar('\n');
                    267:     }
                    268: }
                    269: 
                    270: /*
                    271:  * Recursive whiz-bang procedure to print the type portion
                    272:  * of a declaration.
                    273:  *
                    274:  * The symbol associated with the type is passed to allow
                    275:  * searching for type names without getting "type blah = blah".
                    276:  */
                    277: 
                    278: private printtype(s, t, indent)
                    279: Symbol s;
                    280: Symbol t;
                    281: Integer indent;
                    282: {
                    283:     register Symbol i;
                    284:     long r0, r1;
                    285:     register String p;
                    286: 
                    287:     checkref(s);
                    288:     checkref(t);
                    289:     switch (t->class) {
                    290:        case VAR:
                    291:        case CONST:
                    292:        case PROC:
                    293:            panic("printtype: class %s", classname(t));
                    294:            break;
                    295: 
                    296:        case ARRAY:
                    297:            printf("array[");
                    298:            i = t->chain;
                    299:            if (i != nil) {
                    300:                for (;;) {
                    301:                    printtype(i, i, indent);
                    302:                    i = i->chain;
                    303:                    if (i == nil) {
                    304:                        break;
                    305:                    }
                    306:                    printf(", ");
                    307:                }
                    308:            }
                    309:            printf("] of ");
                    310:            printtype(t, t->type, indent);
                    311:            break;
                    312: 
                    313:        case RECORD:
                    314:        case VARNT:
                    315:            printf("%s ", c_classname(t));
                    316:            if (s->name != nil and s->class == TAG) {
                    317:                p = symname(s);
                    318:                if (p[0] == '$' and p[1] == '$') {
                    319:                    printf("%s ", &p[2]);
                    320:                } else {
                    321:                    printf("%s ", p);
                    322:                }
                    323:            }
                    324:            printf("{\n");
                    325:            for (i = t->chain; i != nil; i = i->chain) {
                    326:                assert(i->class == FIELD);
                    327:                printdecl(i, indent+4);
                    328:            }
                    329:            if (indent > 0) {
                    330:                printf("%*c", indent, ' ');
                    331:            }
                    332:            printf("}");
                    333:            break;
                    334: 
                    335:        case RANGE:
                    336:            r0 = t->symvalue.rangev.lower;
                    337:            r1 = t->symvalue.rangev.upper;
                    338:            if (istypename(t->type, "char")) {
                    339:                if (r0 < 0x20 or r0 > 0x7e) {
                    340:                    printf("%ld..", r0);
                    341:                } else {
                    342:                    printf("'%c'..", (char) r0);
                    343:                }
                    344:                if (r1 < 0x20 or r1 > 0x7e) {
                    345:                    printf("\\%lo", r1);
                    346:                } else {
                    347:                    printf("'%c'", (char) r1);
                    348:                }
                    349:            } else if (r0 > 0 and r1 == 0) {
                    350:                printf("%ld byte real", r0);
                    351:            } else if (r0 >= 0) {
                    352:                printf("%lu..%lu", r0, r1);
                    353:            } else {
                    354:                printf("%ld..%ld", r0, r1);
                    355:            }
                    356:            break;
                    357: 
                    358:        case PTR:
                    359:            printtype(t, t->type, indent);
                    360:            if (t->type->class != PTR) {
                    361:                printf(" ");
                    362:            }
                    363:            printf("*");
                    364:            break;
                    365: 
                    366:        case FUNC:
                    367:        case FFUNC:
                    368:            printtype(t, t->type, indent);
                    369:            printf("()");
                    370:            break;
                    371: 
                    372:        case TYPE:
                    373:            if (t->name != nil) {
                    374:                printname(stdout, t);
                    375:            } else {
                    376:                printtype(t, t->type, indent);
                    377:            }
                    378:            break;
                    379: 
                    380:        case TYPEREF:
                    381:            printf("@%s", symname(t));
                    382:            break;
                    383: 
                    384:        case SCAL:
                    385:            printf("enum ");
                    386:            if (s->name != nil and s->class == TAG) {
                    387:                printf("%s ", symname(s));
                    388:            }
                    389:            printf("{ ");
                    390:            i = t->chain;
                    391:            if (i != nil) {
                    392:                for (;;) {
                    393:                    printf("%s", symname(i));
                    394:                    i = i->chain;
                    395:                if (i == nil) break;
                    396:                    printf(", ");
                    397:                }
                    398:            }
                    399:            printf(" }");
                    400:            break;
                    401: 
                    402:        case TAG:
                    403:            if (t->type == nil) {
                    404:                printf("unresolved tag %s", symname(t));
                    405:            } else {
                    406:                i = rtype(t->type);
                    407:                printf("%s %s", c_classname(i), symname(t));
                    408:            }
                    409:            break;
                    410: 
                    411:        default:
                    412:            printf("(class %d)", t->class);
                    413:            break;
                    414:     }
                    415: }
                    416: 
                    417: /*
                    418:  * List the parameters of a procedure or function.
                    419:  * No attempt is made to combine like types.
                    420:  */
                    421: 
                    422: public c_listparams(s)
                    423: Symbol s;
                    424: {
                    425:     register Symbol t;
                    426: 
                    427:     putchar('(');
                    428:     for (t = s->chain; t != nil; t = t->chain) {
                    429:        printf("%s", symname(t));
                    430:        if (t->chain != nil) {
                    431:            printf(", ");
                    432:        }
                    433:     }
                    434:     putchar(')');
                    435:     if (s->chain != nil) {
                    436:        printf("\n");
                    437:        for (t = s->chain; t != nil; t = t->chain) {
                    438:            if (t->class != VAR) {
                    439:                panic("unexpected class %d for parameter", t->class);
                    440:            }
                    441:            printdecl(t, 0);
                    442:        }
                    443:     } else {
                    444:        putchar('\n');
                    445:     }
                    446: }
                    447: 
                    448: /*
                    449:  * Print out the value on the top of the expression stack
                    450:  * in the format for the type of the given symbol.
                    451:  */
                    452: 
                    453: public c_printval(s)
                    454: Symbol s;
                    455: {
                    456:     register Symbol t;
                    457:     register Address a;
                    458:     integer i, len;
                    459:     register String str;
                    460: 
                    461:     switch (s->class) {
                    462:        case CONST:
                    463:        case TYPE:
                    464:        case VAR:
                    465:        case REF:
                    466:        case FVAR:
                    467:        case TAG:
                    468:            c_printval(s->type);
                    469:            break;
                    470: 
                    471:        case FIELD:
                    472:            if (isbitfield(s)) {
                    473:                i = extractField(s);
                    474:                t = rtype(s->type);
                    475:                if (t->class == SCAL) {
                    476:                    printEnum(i, t);
                    477:                } else {
                    478:                    printRangeVal(i, t);
                    479:                }
                    480:            } else {
                    481:                c_printval(s->type);
                    482:            }
                    483:            break;
                    484: 
                    485:        case ARRAY:
                    486:            t = rtype(s->type);
                    487:            if ((t->class == RANGE and istypename(t->type, "char")) or
                    488:                t == t_char->type
                    489:            ) {
                    490:                len = size(s);
                    491:                str = (String) (sp -= len);
                    492:                if (s->language != primlang) {
                    493:                    putchar('"');
                    494:                }
                    495:                while (--len > 0 and *str != '\0') {
                    496:                    printchar(*str++);
                    497:                }
                    498:                if (*str != '\0') {     /* XXX - pitch trailing null */
                    499:                    printchar(*str);
                    500:                }
                    501:                if (s->language != primlang) {
                    502:                    putchar('"');
                    503:                }
                    504:            } else {
                    505:                printarray(s);
                    506:            }
                    507:            break;
                    508: 
                    509:        case RECORD:
                    510:            c_printstruct(s);
                    511:            break;
                    512: 
                    513:        case RANGE:
                    514:            if (s == t_boolean->type or istypename(s->type, "boolean")) {
                    515:                printRangeVal(popsmall(s), s);
                    516:            } else if (s == t_char->type or istypename(s->type, "char")) {
                    517:                printRangeVal(pop(char), s);
                    518:            } else if (s == t_real->type or isdouble(s)) {
                    519:                switch (s->symvalue.rangev.lower) {
                    520:                    case sizeof(float):
                    521:                        prtreal((double) (pop(float)));
                    522:                        break;
                    523: 
                    524:                    case sizeof(double):
                    525:                        prtreal(pop(double));
                    526:                        break;
                    527: 
                    528:                    default:
                    529:                        panic("bad real size %d", t->symvalue.rangev.lower);
                    530:                        break;
                    531:                }
                    532:            } else {
                    533:                printRangeVal(popsmall(s), s);
                    534:            }
                    535:            break;
                    536: 
                    537:        case PTR:
                    538:            t = rtype(s->type);
                    539:            a = pop(Address);
                    540:            if (a == 0) {
                    541:                printf("(nil)");
                    542:            } else if (t->class == RANGE and istypename(t->type, "char")) {
                    543:                printString(a, (boolean) (s->language != primlang));
                    544:            } else {
                    545:                printf("0x%x", a);
                    546:            }
                    547:            break;
                    548: 
                    549:        case SCAL:
                    550:            i = pop(Integer);
                    551:            printEnum(i, s);
                    552:            break;
                    553: 
                    554:        /*
                    555:         * Unresolved structure pointers?
                    556:         */
                    557:        case BADUSE:
                    558:            a = pop(Address);
                    559:            printf("@%x", a);
                    560:            break;
                    561: 
                    562:        default:
                    563:            if (ord(s->class) > ord(TYPEREF)) {
                    564:                panic("printval: bad class %d", ord(s->class));
                    565:            }
                    566:            sp -= size(s);
                    567:            printf("[%s]", c_classname(s));
                    568:            break;
                    569:     }
                    570: }
                    571: 
                    572: /*
                    573:  * Print out a C structure.
                    574:  */
                    575: 
                    576: private c_printstruct (s)
                    577: Symbol s;
                    578: {
                    579:     Symbol f;
                    580:     Stack *savesp;
                    581:     integer n, off, len;
                    582: 
                    583:     sp -= size(s);
                    584:     savesp = sp;
                    585:     printf("(");
                    586:     f = s->chain;
                    587:     for (;;) {
                    588:        off = f->symvalue.field.offset;
                    589:        len = f->symvalue.field.length;
                    590:        n = (off + len + BITSPERBYTE - 1) div BITSPERBYTE;
                    591:        sp += n;
                    592:        printf("%s = ", symname(f));
                    593:        c_printval(f);
                    594:        sp = savesp;
                    595:        f = f->chain;
                    596:     if (f == nil) break;
                    597:        printf(", ");
                    598:     }
                    599:     printf(")");
                    600: }
                    601: 
                    602: /*
                    603:  * Return the C name for the particular class of a symbol.
                    604:  */
                    605: 
                    606: public String c_classname(s)
                    607: Symbol s;
                    608: {
                    609:     String str;
                    610: 
                    611:     switch (s->class) {
                    612:        case RECORD:
                    613:            str = "struct";
                    614:            break;
                    615: 
                    616:        case VARNT:
                    617:            str = "union";
                    618:            break;
                    619: 
                    620:        case SCAL:
                    621:            str = "enum";
                    622:            break;
                    623: 
                    624:        default:
                    625:            str = classname(s);
                    626:     }
                    627:     return str;
                    628: }
                    629: 
                    630: public Node c_buildaref(a, slist)
                    631: Node a, slist;
                    632: {
                    633:     register Symbol t;
                    634:     register Node p;
                    635:     Symbol etype, atype, eltype;
                    636:     Node r, esub;
                    637: 
                    638:     t = rtype(a->nodetype);
                    639:     eltype = t->type;
                    640:     if (t->class == PTR) {
                    641:        p = slist->value.arg[0];
                    642:        if (not compatible(p->nodetype, t_int)) {
                    643:            beginerrmsg();
                    644:            fprintf(stderr, "subscript must be integer-compatible");
                    645:            enderrmsg();
                    646:        }
                    647:        r = build(O_MUL, p, build(O_LCON, (long) size(eltype)));
                    648:        r = build(O_ADD, build(O_RVAL, a), r);
                    649:        r->nodetype = eltype;
                    650:     } else if (t->class != ARRAY) {
                    651:        beginerrmsg();
                    652:        fprintf(stderr, "\"");
                    653:        prtree(stderr, a);
                    654:        fprintf(stderr, "\" is not an array");
                    655:        enderrmsg();
                    656:     } else {
                    657:        r = a;
                    658:        p = slist;
                    659:        t = t->chain;
                    660:        for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) {
                    661:            esub = p->value.arg[0];
                    662:            etype = rtype(esub->nodetype);
                    663:            atype = rtype(t);
                    664:            if (not compatible(atype, etype)) {
                    665:                beginerrmsg();
                    666:                fprintf(stderr, "subscript \"");
                    667:                prtree(stderr, esub);
                    668:                fprintf(stderr, "\" is the wrong type");
                    669:                enderrmsg();
                    670:            }
                    671:            r = build(O_INDEX, r, esub);
                    672:            r->nodetype = eltype;
                    673:        }
                    674:        if (p != nil or t != nil) {
                    675:            beginerrmsg();
                    676:            if (p != nil) {
                    677:                fprintf(stderr, "too many subscripts for \"");
                    678:            } else {
                    679:                fprintf(stderr, "not enough subscripts for \"");
                    680:            }
                    681:            prtree(stderr, a);
                    682:            fprintf(stderr, "\"");
                    683:            enderrmsg();
                    684:        }
                    685:     }
                    686:     return r;
                    687: }
                    688: 
                    689: /*
                    690:  * Evaluate a subscript index.
                    691:  */
                    692: 
                    693: public c_evalaref(s, base, i)
                    694: Symbol s;
                    695: Address base;
                    696: long i;
                    697: {
                    698:     Symbol t;
                    699:     long lb, ub;
                    700: 
                    701:     t = rtype(s);
                    702:     s = t->chain;
                    703:     lb = s->symvalue.rangev.lower;
                    704:     ub = s->symvalue.rangev.upper;
                    705:     if (i < lb or i > ub) {
                    706:        warning("subscript out of range");
                    707:     }
                    708:     push(long, base + (i - lb) * size(t->type));
                    709: }
                    710: 
                    711: /*
                    712:  * Initialize typetable information.
                    713:  */
                    714: 
                    715: public c_modinit (typetable)
                    716: Symbol typetable[];
                    717: {
                    718:     /* nothing right now */
                    719: }
                    720: 
                    721: public boolean c_hasmodules ()
                    722: {
                    723:     return false;
                    724: }
                    725: 
                    726: public boolean c_passaddr (param, exprtype)
                    727: Symbol param, exprtype;
                    728: {
                    729:     boolean b;
                    730:     Symbol t;
                    731: 
                    732:     t = rtype(exprtype);
                    733:     b = (boolean) (t->class == ARRAY);
                    734:     return b;
                    735: }

unix.superglobalmegacorp.com

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