Annotation of 43BSD/ucb/gprof/gprof.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: char copyright[] =
                      9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)gprof.c    5.1 (Berkeley) 6/4/85";
                     15: #endif not lint
                     16: 
                     17: #include "gprof.h"
                     18: 
                     19: char   *whoami = "gprof";
                     20: 
                     21:     /*
                     22:      * things which get -E excluded by default.
                     23:      */
                     24: char   *defaultEs[] = { "mcount" , "__mcleanup" , 0 };
                     25: 
                     26: main(argc, argv)
                     27:     int argc;
                     28:     char **argv;
                     29: {
                     30:     char       **sp;
                     31:     nltype     **timesortnlp;
                     32: 
                     33:     --argc;
                     34:     argv++;
                     35:     debug = 0;
                     36:     bflag = TRUE;
                     37:     while ( *argv != 0 && **argv == '-' ) {
                     38:        (*argv)++;
                     39:        switch ( **argv ) {
                     40:        case 'a':
                     41:            aflag = TRUE;
                     42:            break;
                     43:        case 'b':
                     44:            bflag = FALSE;
                     45:            break;
                     46:        case 'c':
                     47:            cflag = TRUE;
                     48:            break;
                     49:        case 'd':
                     50:            dflag = TRUE;
                     51:            (*argv)++;
                     52:            debug |= atoi( *argv );
                     53:            debug |= ANYDEBUG;
                     54: #          ifdef DEBUG
                     55:                printf("[main] debug = %d\n", debug);
                     56: #          else not DEBUG
                     57:                printf("%s: -d ignored\n", whoami);
                     58: #          endif DEBUG
                     59:            break;
                     60:        case 'E':
                     61:            ++argv;
                     62:            addlist( Elist , *argv );
                     63:            Eflag = TRUE;
                     64:            addlist( elist , *argv );
                     65:            eflag = TRUE;
                     66:            break;
                     67:        case 'e':
                     68:            addlist( elist , *++argv );
                     69:            eflag = TRUE;
                     70:            break;
                     71:        case 'F':
                     72:            ++argv;
                     73:            addlist( Flist , *argv );
                     74:            Fflag = TRUE;
                     75:            addlist( flist , *argv );
                     76:            fflag = TRUE;
                     77:            break;
                     78:        case 'f':
                     79:            addlist( flist , *++argv );
                     80:            fflag = TRUE;
                     81:            break;
                     82:        case 's':
                     83:            sflag = TRUE;
                     84:            break;
                     85:        case 'z':
                     86:            zflag = TRUE;
                     87:            break;
                     88:        }
                     89:        argv++;
                     90:     }
                     91:     if ( *argv != 0 ) {
                     92:        a_outname  = *argv;
                     93:        argv++;
                     94:     } else {
                     95:        a_outname  = A_OUTNAME;
                     96:     }
                     97:     if ( *argv != 0 ) {
                     98:        gmonname = *argv;
                     99:        argv++;
                    100:     } else {
                    101:        gmonname = GMONNAME;
                    102:     }
                    103:        /*
                    104:         *      turn off default functions
                    105:         */
                    106:     for ( sp = &defaultEs[0] ; *sp ; sp++ ) {
                    107:        Eflag = TRUE;
                    108:        addlist( Elist , *sp );
                    109:        eflag = TRUE;
                    110:        addlist( elist , *sp );
                    111:     }
                    112:        /*
                    113:         *      how many ticks per second?
                    114:         *      if we can't tell, report time in ticks.
                    115:         */
                    116:     hz = hertz();
                    117:     if (hz == 0) {
                    118:        hz = 1;
                    119:        fprintf(stderr, "time is in ticks, not seconds\n");
                    120:     }
                    121:        /*
                    122:         *      get information about a.out file.
                    123:         */
                    124:     getnfile();
                    125:        /*
                    126:         *      get information about mon.out file(s).
                    127:         */
                    128:     do {
                    129:        getpfile( gmonname );
                    130:        if ( *argv != 0 ) {
                    131:            gmonname = *argv;
                    132:        }
                    133:     } while ( *argv++ != 0 );
                    134:        /*
                    135:         *      dump out a gmon.sum file if requested
                    136:         */
                    137:     if ( sflag ) {
                    138:        dumpsum( GMONSUM );
                    139:     }
                    140:        /*
                    141:         *      assign samples to procedures
                    142:         */
                    143:     asgnsamples();
                    144:        /*
                    145:         *      assemble the dynamic profile
                    146:         */
                    147:     timesortnlp = doarcs();
                    148:        /*
                    149:         *      print the dynamic profile
                    150:         */
                    151:     printgprof( timesortnlp ); 
                    152:        /*
                    153:         *      print the flat profile
                    154:         */
                    155:     printprof();       
                    156:        /*
                    157:         *      print the index
                    158:         */
                    159:     printindex();      
                    160:     done();
                    161: }
                    162: 
                    163:     /*
                    164:      * Set up string and symbol tables from a.out.
                    165:      * and optionally the text space.
                    166:      * On return symbol table is sorted by value.
                    167:      */
                    168: getnfile()
                    169: {
                    170:     FILE       *nfile;
                    171: 
                    172:     nfile = fopen( a_outname ,"r");
                    173:     if (nfile == NULL) {
                    174:        perror( a_outname );
                    175:        done();
                    176:     }
                    177:     fread(&xbuf, 1, sizeof(xbuf), nfile);
                    178:     if (N_BADMAG(xbuf)) {
                    179:        fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname );
                    180:        done();
                    181:     }
                    182:     getstrtab(nfile);
                    183:     getsymtab(nfile);
                    184:     gettextspace( nfile );
                    185:     qsort(nl, nname, sizeof(nltype), valcmp);
                    186:     fclose(nfile);
                    187: #   ifdef DEBUG
                    188:        if ( debug & AOUTDEBUG ) {
                    189:            register int j;
                    190: 
                    191:            for (j = 0; j < nname; j++){
                    192:                printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name);
                    193:            }
                    194:        }
                    195: #   endif DEBUG
                    196: }
                    197: 
                    198: getstrtab(nfile)
                    199:     FILE       *nfile;
                    200: {
                    201: 
                    202:     fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0);
                    203:     if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) {
                    204:        fprintf(stderr, "%s: %s: no string table (old format?)\n" ,
                    205:                whoami , a_outname );
                    206:        done();
                    207:     }
                    208:     strtab = (char *)calloc(ssiz, 1);
                    209:     if (strtab == NULL) {
                    210:        fprintf(stderr, "%s: %s: no room for %d bytes of string table",
                    211:                whoami , a_outname , ssiz);
                    212:        done();
                    213:     }
                    214:     if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) {
                    215:        fprintf(stderr, "%s: %s: error reading string table\n",
                    216:                whoami , a_outname );
                    217:        done();
                    218:     }
                    219: }
                    220: 
                    221:     /*
                    222:      * Read in symbol table
                    223:      */
                    224: getsymtab(nfile)
                    225:     FILE       *nfile;
                    226: {
                    227:     register long      i;
                    228:     int                        askfor;
                    229:     struct nlist       nbuf;
                    230: 
                    231:     /* pass1 - count symbols */
                    232:     fseek(nfile, (long)N_SYMOFF(xbuf), 0);
                    233:     nname = 0;
                    234:     for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
                    235:        fread(&nbuf, sizeof(nbuf), 1, nfile);
                    236:        if ( ! funcsymbol( &nbuf ) ) {
                    237:            continue;
                    238:        }
                    239:        nname++;
                    240:     }
                    241:     if (nname == 0) {
                    242:        fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname );
                    243:        done();
                    244:     }
                    245:     askfor = nname + 1;
                    246:     nl = (nltype *) calloc( askfor , sizeof(nltype) );
                    247:     if (nl == 0) {
                    248:        fprintf(stderr, "%s: No room for %d bytes of symbol table\n",
                    249:                whoami, askfor * sizeof(nltype) );
                    250:        done();
                    251:     }
                    252: 
                    253:     /* pass2 - read symbols */
                    254:     fseek(nfile, (long)N_SYMOFF(xbuf), 0);
                    255:     npe = nl;
                    256:     nname = 0;
                    257:     for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
                    258:        fread(&nbuf, sizeof(nbuf), 1, nfile);
                    259:        if ( ! funcsymbol( &nbuf ) ) {
                    260: #          ifdef DEBUG
                    261:                if ( debug & AOUTDEBUG ) {
                    262:                    printf( "[getsymtab] rejecting: 0x%x %s\n" ,
                    263:                            nbuf.n_type , strtab + nbuf.n_un.n_strx );
                    264:                }
                    265: #          endif DEBUG
                    266:            continue;
                    267:        }
                    268:        npe->value = nbuf.n_value;
                    269:        npe->name = strtab+nbuf.n_un.n_strx;
                    270: #      ifdef DEBUG
                    271:            if ( debug & AOUTDEBUG ) {
                    272:                printf( "[getsymtab] %d %s 0x%08x\n" ,
                    273:                        nname , npe -> name , npe -> value );
                    274:            }
                    275: #      endif DEBUG
                    276:        npe++;
                    277:        nname++;
                    278:     }
                    279:     npe->value = -1;
                    280: }
                    281: 
                    282:     /*
                    283:      * read in the text space of an a.out file
                    284:      */
                    285: gettextspace( nfile )
                    286:     FILE       *nfile;
                    287: {
                    288:     unsigned char      *malloc();
                    289:     
                    290:     if ( cflag == 0 ) {
                    291:        return;
                    292:     }
                    293:     textspace = malloc( xbuf.a_text );
                    294:     if ( textspace == 0 ) {
                    295:        fprintf( stderr , "%s: ran out room for %d bytes of text space:  " ,
                    296:                        whoami , xbuf.a_text );
                    297:        fprintf( stderr , "can't do -c\n" );
                    298:        return;
                    299:     }
                    300:     (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 );
                    301:     if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) {
                    302:        fprintf( stderr , "%s: couldn't read text space:  " , whoami );
                    303:        fprintf( stderr , "can't do -c\n" );
                    304:        free( textspace );
                    305:        textspace = 0;
                    306:        return;
                    307:     }
                    308: }
                    309:     /*
                    310:      * information from a gmon.out file is in two parts:
                    311:      * an array of sampling hits within pc ranges,
                    312:      * and the arcs.
                    313:      */
                    314: getpfile(filename)
                    315:     char *filename;
                    316: {
                    317:     FILE               *pfile;
                    318:     FILE               *openpfile();
                    319:     struct rawarc      arc;
                    320: 
                    321:     pfile = openpfile(filename);
                    322:     readsamples(pfile);
                    323:        /*
                    324:         *      the rest of the file consists of
                    325:         *      a bunch of <from,self,count> tuples.
                    326:         */
                    327:     while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) {
                    328: #      ifdef DEBUG
                    329:            if ( debug & SAMPLEDEBUG ) {
                    330:                printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" ,
                    331:                        arc.raw_frompc , arc.raw_selfpc , arc.raw_count );
                    332:            }
                    333: #      endif DEBUG
                    334:            /*
                    335:             *  add this arc
                    336:             */
                    337:        tally( &arc );
                    338:     }
                    339:     fclose(pfile);
                    340: }
                    341: 
                    342: FILE *
                    343: openpfile(filename)
                    344:     char *filename;
                    345: {
                    346:     struct hdr tmp;
                    347:     FILE       *pfile;
                    348: 
                    349:     if((pfile = fopen(filename, "r")) == NULL) {
                    350:        perror(filename);
                    351:        done();
                    352:     }
                    353:     fread(&tmp, sizeof(struct hdr), 1, pfile);
                    354:     if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc ||
                    355:         tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) {
                    356:        fprintf(stderr, "%s: incompatible with first gmon file\n", filename);
                    357:        done();
                    358:     }
                    359:     h = tmp;
                    360:     s_lowpc = (unsigned long) h.lowpc;
                    361:     s_highpc = (unsigned long) h.highpc;
                    362:     lowpc = (unsigned long)h.lowpc / sizeof(UNIT);
                    363:     highpc = (unsigned long)h.highpc / sizeof(UNIT);
                    364:     sampbytes = h.ncnt - sizeof(struct hdr);
                    365:     nsamples = sampbytes / sizeof (unsigned UNIT);
                    366: #   ifdef DEBUG
                    367:        if ( debug & SAMPLEDEBUG ) {
                    368:            printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n",
                    369:                h.lowpc , h.highpc , h.ncnt );
                    370:            printf( "[openpfile]   s_lowpc 0x%x   s_highpc 0x%x\n" ,
                    371:                s_lowpc , s_highpc );
                    372:            printf( "[openpfile]     lowpc 0x%x     highpc 0x%x\n" ,
                    373:                lowpc , highpc );
                    374:            printf( "[openpfile] sampbytes %d nsamples %d\n" ,
                    375:                sampbytes , nsamples );
                    376:        }
                    377: #   endif DEBUG
                    378:     return(pfile);
                    379: }
                    380: 
                    381: tally( rawp )
                    382:     struct rawarc      *rawp;
                    383: {
                    384:     nltype             *parentp;
                    385:     nltype             *childp;
                    386: 
                    387:     parentp = nllookup( rawp -> raw_frompc );
                    388:     childp = nllookup( rawp -> raw_selfpc );
                    389:     childp -> ncall += rawp -> raw_count;
                    390: #   ifdef DEBUG
                    391:        if ( debug & TALLYDEBUG ) {
                    392:            printf( "[tally] arc from %s to %s traversed %d times\n" ,
                    393:                    parentp -> name , childp -> name , rawp -> raw_count );
                    394:        }
                    395: #   endif DEBUG
                    396:     addarc( parentp , childp , rawp -> raw_count );
                    397: }
                    398: 
                    399: /*
                    400:  * dump out the gmon.sum file
                    401:  */
                    402: dumpsum( sumfile )
                    403:     char *sumfile;
                    404: {
                    405:     register nltype *nlp;
                    406:     register arctype *arcp;
                    407:     struct rawarc arc;
                    408:     FILE *sfile;
                    409: 
                    410:     if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) {
                    411:        perror( sumfile );
                    412:        done();
                    413:     }
                    414:     /*
                    415:      * dump the header; use the last header read in
                    416:      */
                    417:     if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) {
                    418:        perror( sumfile );
                    419:        done();
                    420:     }
                    421:     /*
                    422:      * dump the samples
                    423:      */
                    424:     if (fwrite(samples, sizeof(unsigned UNIT), nsamples, sfile) != nsamples) {
                    425:        perror( sumfile );
                    426:        done();
                    427:     }
                    428:     /*
                    429:      * dump the normalized raw arc information
                    430:      */
                    431:     for ( nlp = nl ; nlp < npe ; nlp++ ) {
                    432:        for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
                    433:            arc.raw_frompc = arcp -> arc_parentp -> value;
                    434:            arc.raw_selfpc = arcp -> arc_childp -> value;
                    435:            arc.raw_count = arcp -> arc_count;
                    436:            if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) {
                    437:                perror( sumfile );
                    438:                done();
                    439:            }
                    440: #          ifdef DEBUG
                    441:                if ( debug & SAMPLEDEBUG ) {
                    442:                    printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" ,
                    443:                            arc.raw_frompc , arc.raw_selfpc , arc.raw_count );
                    444:                }
                    445: #          endif DEBUG
                    446:        }
                    447:     }
                    448:     fclose( sfile );
                    449: }
                    450: 
                    451: valcmp(p1, p2)
                    452:     nltype *p1, *p2;
                    453: {
                    454:     if ( p1 -> value < p2 -> value ) {
                    455:        return LESSTHAN;
                    456:     }
                    457:     if ( p1 -> value > p2 -> value ) {
                    458:        return GREATERTHAN;
                    459:     }
                    460:     return EQUALTO;
                    461: }
                    462: 
                    463: readsamples(pfile)
                    464:     FILE       *pfile;
                    465: {
                    466:     register i;
                    467:     unsigned UNIT      sample;
                    468:     
                    469:     if (samples == 0) {
                    470:        samples = (unsigned UNIT *) calloc(sampbytes, sizeof (unsigned UNIT));
                    471:        if (samples == 0) {
                    472:            fprintf( stderr , "%s: No room for %d sample pc's\n", 
                    473:                whoami , sampbytes / sizeof (unsigned UNIT));
                    474:            done();
                    475:        }
                    476:     }
                    477:     for (i = 0; i < nsamples; i++) {
                    478:        fread(&sample, sizeof (unsigned UNIT), 1, pfile);
                    479:        if (feof(pfile))
                    480:                break;
                    481:        samples[i] += sample;
                    482:     }
                    483:     if (i != nsamples) {
                    484:        fprintf(stderr,
                    485:            "%s: unexpected EOF after reading %d/%d samples\n",
                    486:                whoami , --i , nsamples );
                    487:        done();
                    488:     }
                    489: }
                    490: 
                    491: /*
                    492:  *     Assign samples to the procedures to which they belong.
                    493:  *
                    494:  *     There are three cases as to where pcl and pch can be
                    495:  *     with respect to the routine entry addresses svalue0 and svalue1
                    496:  *     as shown in the following diagram.  overlap computes the
                    497:  *     distance between the arrows, the fraction of the sample
                    498:  *     that is to be credited to the routine which starts at svalue0.
                    499:  *
                    500:  *         svalue0                                         svalue1
                    501:  *            |                                               |
                    502:  *            v                                               v
                    503:  *
                    504:  *            +-----------------------------------------------+
                    505:  *            |                                               |
                    506:  *       |  ->|    |<-         ->|         |<-         ->|    |<-  |
                    507:  *       |         |             |         |             |         |
                    508:  *       +---------+             +---------+             +---------+
                    509:  *
                    510:  *       ^         ^             ^         ^             ^         ^
                    511:  *       |         |             |         |             |         |
                    512:  *      pcl       pch           pcl       pch           pcl       pch
                    513:  *
                    514:  *     For the vax we assert that samples will never fall in the first
                    515:  *     two bytes of any routine, since that is the entry mask,
                    516:  *     thus we give call alignentries() to adjust the entry points if
                    517:  *     the entry mask falls in one bucket but the code for the routine
                    518:  *     doesn't start until the next bucket.  In conjunction with the
                    519:  *     alignment of routine addresses, this should allow us to have
                    520:  *     only one sample for every four bytes of text space and never
                    521:  *     have any overlap (the two end cases, above).
                    522:  */
                    523: asgnsamples()
                    524: {
                    525:     register int       j;
                    526:     unsigned UNIT      ccnt;
                    527:     double             time;
                    528:     unsigned long      pcl, pch;
                    529:     register int       i;
                    530:     unsigned long      overlap;
                    531:     unsigned long      svalue0, svalue1;
                    532: 
                    533:     /* read samples and assign to namelist symbols */
                    534:     scale = highpc - lowpc;
                    535:     scale /= nsamples;
                    536:     alignentries();
                    537:     for (i = 0, j = 1; i < nsamples; i++) {
                    538:        ccnt = samples[i];
                    539:        if (ccnt == 0)
                    540:                continue;
                    541:        pcl = lowpc + scale * i;
                    542:        pch = lowpc + scale * (i + 1);
                    543:        time = ccnt;
                    544: #      ifdef DEBUG
                    545:            if ( debug & SAMPLEDEBUG ) {
                    546:                printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" ,
                    547:                        pcl , pch , ccnt );
                    548:            }
                    549: #      endif DEBUG
                    550:        totime += time;
                    551:        for (j = j - 1; j < nname; j++) {
                    552:            svalue0 = nl[j].svalue;
                    553:            svalue1 = nl[j+1].svalue;
                    554:                /*
                    555:                 *      if high end of tick is below entry address, 
                    556:                 *      go for next tick.
                    557:                 */
                    558:            if (pch < svalue0)
                    559:                    break;
                    560:                /*
                    561:                 *      if low end of tick into next routine,
                    562:                 *      go for next routine.
                    563:                 */
                    564:            if (pcl >= svalue1)
                    565:                    continue;
                    566:            overlap = min(pch, svalue1) - max(pcl, svalue0);
                    567:            if (overlap > 0) {
                    568: #              ifdef DEBUG
                    569:                    if (debug & SAMPLEDEBUG) {
                    570:                        printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n",
                    571:                                nl[j].value/sizeof(UNIT), svalue0, svalue1,
                    572:                                nl[j].name, 
                    573:                                overlap * time / scale, overlap);
                    574:                    }
                    575: #              endif DEBUG
                    576:                nl[j].time += overlap * time / scale;
                    577:            }
                    578:        }
                    579:     }
                    580: #   ifdef DEBUG
                    581:        if (debug & SAMPLEDEBUG) {
                    582:            printf("[asgnsamples] totime %f\n", totime);
                    583:        }
                    584: #   endif DEBUG
                    585: }
                    586: 
                    587: 
                    588: unsigned long
                    589: min(a, b)
                    590:     unsigned long a,b;
                    591: {
                    592:     if (a<b)
                    593:        return(a);
                    594:     return(b);
                    595: }
                    596: 
                    597: unsigned long
                    598: max(a, b)
                    599:     unsigned long a,b;
                    600: {
                    601:     if (a>b)
                    602:        return(a);
                    603:     return(b);
                    604: }
                    605: 
                    606:     /*
                    607:      * calculate scaled entry point addresses (to save time in asgnsamples),
                    608:      * and possibly push the scaled entry points over the entry mask,
                    609:      * if it turns out that the entry point is in one bucket and the code
                    610:      * for a routine is in the next bucket.
                    611:      */
                    612: alignentries()
                    613: {
                    614:     register struct nl *nlp;
                    615:     unsigned long      bucket_of_entry;
                    616:     unsigned long      bucket_of_code;
                    617: 
                    618:     for (nlp = nl; nlp < npe; nlp++) {
                    619:        nlp -> svalue = nlp -> value / sizeof(UNIT);
                    620:        bucket_of_entry = (nlp->svalue - lowpc) / scale;
                    621:        bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale;
                    622:        if (bucket_of_entry < bucket_of_code) {
                    623: #          ifdef DEBUG
                    624:                if (debug & SAMPLEDEBUG) {
                    625:                    printf("[alignentries] pushing svalue 0x%x to 0x%x\n",
                    626:                            nlp->svalue, nlp->svalue + UNITS_TO_CODE);
                    627:                }
                    628: #          endif DEBUG
                    629:            nlp->svalue += UNITS_TO_CODE;
                    630:        }
                    631:     }
                    632: }
                    633: 
                    634: bool
                    635: funcsymbol( nlistp )
                    636:     struct nlist       *nlistp;
                    637: {
                    638:     extern char        *strtab;        /* string table from a.out */
                    639:     extern int aflag;          /* if static functions aren't desired */
                    640:     char       *name;
                    641: 
                    642:        /*
                    643:         *      must be a text symbol,
                    644:         *      and static text symbols don't qualify if aflag set.
                    645:         */
                    646:     if ( ! (  ( nlistp -> n_type == ( N_TEXT | N_EXT ) )
                    647:           || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) {
                    648:        return FALSE;
                    649:     }
                    650:        /*
                    651:         *      can't have any `funny' characters in name,
                    652:         *      where `funny' includes  `.', .o file names
                    653:         *                      and     `$', pascal labels.
                    654:         */
                    655:     for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) {
                    656:        if ( *name == '.' || *name == '$' ) {
                    657:            return FALSE;
                    658:        }
                    659:     }
                    660:     return TRUE;
                    661: }
                    662: 
                    663: done()
                    664: {
                    665: 
                    666:     exit(0);
                    667: }

unix.superglobalmegacorp.com

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