Annotation of 43BSDReno/pgrm/dbx/source.c, revision 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[] = "@(#)source.c   5.4 (Berkeley) 6/1/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: /*
        !            25:  * Source file management.
        !            26:  */
        !            27: 
        !            28: #include "defs.h"
        !            29: #include "source.h"
        !            30: #include "object.h"
        !            31: #include "mappings.h"
        !            32: #include "machine.h"
        !            33: #include "keywords.h"
        !            34: #include "tree.h"
        !            35: #include "eval.h"
        !            36: #ifdef IRIS
        !            37: #   define R_OK 04     /* read access */
        !            38: #   define L_SET 01    /* absolute offset for seek */
        !            39: #else
        !            40: #   include <sys/file.h>
        !            41: #endif
        !            42: 
        !            43: #ifndef public
        !            44: typedef int Lineno;
        !            45: 
        !            46: String cursource;
        !            47: Lineno curline;
        !            48: Lineno cursrcline;
        !            49: 
        !            50: #define LASTLINE 0             /* recognized by printlines */
        !            51: 
        !            52: #include "lists.h"
        !            53: 
        !            54: List sourcepath;
        !            55: #endif
        !            56: 
        !            57: #ifdef IRIS
        !            58: #   define re_comp regcmp
        !            59: #   define re_exec(buf) (regex(buf) != NULL)
        !            60: #endif
        !            61: 
        !            62: extern char *re_comp();
        !            63: 
        !            64: private Lineno lastlinenum;
        !            65: private String prevsource = nil;
        !            66: 
        !            67: /*
        !            68:  * Data structure for indexing source seek addresses by line number.
        !            69:  *
        !            70:  * The constraints are:
        !            71:  *
        !            72:  *  we want an array so indexing is fast and easy
        !            73:  *  we don't want to waste space for small files
        !            74:  *  we don't want an upper bound on # of lines in a file
        !            75:  *  we don't know how many lines there are
        !            76:  *
        !            77:  * The solution is a "dirty" hash table.  We have NSLOTS pointers to
        !            78:  * arrays of NLINESPERSLOT addresses.  To find the source address of
        !            79:  * a particular line we find the slot, allocate space if necessary,
        !            80:  * and then find its location within the pointed to array.
        !            81:  */
        !            82: 
        !            83: typedef long Seekaddr;
        !            84: 
        !            85: #define NSLOTS 40
        !            86: #define NLINESPERSLOT 500
        !            87: 
        !            88: #define slotno(line)    ((line) div NLINESPERSLOT)
        !            89: #define index(line)    ((line) mod NLINESPERSLOT)
        !            90: #define slot_alloc()    newarr(Seekaddr, NLINESPERSLOT)
        !            91: #define srcaddr(line)  seektab[slotno(line)][index(line)]
        !            92: 
        !            93: private File srcfp;
        !            94: private Seekaddr *seektab[NSLOTS];
        !            95: 
        !            96: /*
        !            97:  * Determine if the current source file is available.
        !            98:  */
        !            99: 
        !           100: public boolean canReadSource ()
        !           101: {
        !           102:     boolean b;
        !           103: 
        !           104:     if (cursource == nil) {
        !           105:        b = false;
        !           106:     } else if (cursource != prevsource) {
        !           107:        skimsource();
        !           108:        b = (boolean) (lastlinenum != 0);
        !           109:     } else {
        !           110:        b = true;
        !           111:     }
        !           112:     return b;
        !           113: }
        !           114: 
        !           115: /*
        !           116:  * Print out the given lines from the source.
        !           117:  */
        !           118: 
        !           119: public printlines(l1, l2)
        !           120: Lineno l1, l2;
        !           121: {
        !           122:     register int c;
        !           123:     register Lineno i, lb, ub;
        !           124:     register File f;
        !           125: 
        !           126:     if (cursource == nil) {
        !           127:        beginerrmsg();
        !           128:        fprintf(stderr, "no source file\n");
        !           129:     } else {
        !           130:        if (cursource != prevsource) {
        !           131:            skimsource();
        !           132:        }
        !           133:        if (lastlinenum == 0) {
        !           134:            beginerrmsg();
        !           135:            fprintf(stderr, "couldn't read \"%s\"\n", cursource);
        !           136:        } else {
        !           137:            lb = (l1 == LASTLINE) ? lastlinenum : l1;
        !           138:            ub = (l2 == LASTLINE) ? lastlinenum : l2;
        !           139:            if (lb < 1) {
        !           140:                beginerrmsg();
        !           141:                fprintf(stderr, "line number must be positive\n");
        !           142:            } else if (lb > lastlinenum) {
        !           143:                beginerrmsg();
        !           144:                if (lastlinenum == 1) {
        !           145:                    fprintf(stderr, "\"%s\" has only 1 line\n", cursource);
        !           146:                } else {
        !           147:                    fprintf(stderr, "\"%s\" has only %d lines\n",
        !           148:                        cursource, lastlinenum);
        !           149:                }
        !           150:            } else if (ub < lb) {
        !           151:                beginerrmsg();
        !           152:                fprintf(stderr, "second number must be greater than first\n");
        !           153:            } else {
        !           154:                if (ub > lastlinenum) {
        !           155:                    ub = lastlinenum;
        !           156:                }
        !           157:                f = srcfp;
        !           158:                fseek(f, srcaddr(lb), 0);
        !           159:                for (i = lb; i <= ub; i++) {
        !           160:                    printf("%5d   ", i);
        !           161:                    while ((c = getc(f)) != '\n') {
        !           162:                        putchar(c);
        !           163:                    }
        !           164:                    putchar('\n');
        !           165:                }
        !           166:                cursrcline = ub + 1;
        !           167:            }
        !           168:        }
        !           169:     }
        !           170: }
        !           171: 
        !           172: /*
        !           173:  * Search the sourcepath for a file.
        !           174:  */
        !           175: 
        !           176: static char fileNameBuf[1024];
        !           177: 
        !           178: public String findsource(filename)
        !           179: String filename;
        !           180: {
        !           181:     register String src, dir;
        !           182: 
        !           183:     if (filename[0] == '/') {
        !           184:        src = filename;
        !           185:     } else {
        !           186:        src = nil;
        !           187:        foreach (String, dir, sourcepath)
        !           188:            sprintf(fileNameBuf, "%s/%s", dir, filename);
        !           189:            if (access(fileNameBuf, R_OK) == 0) {
        !           190:                src = fileNameBuf;
        !           191:                break;
        !           192:            }
        !           193:        endfor
        !           194:     }
        !           195:     return src;
        !           196: }
        !           197: 
        !           198: /*
        !           199:  * Open a source file looking in the appropriate places.
        !           200:  */
        !           201: 
        !           202: public File opensource(filename)
        !           203: String filename;
        !           204: {
        !           205:     String s;
        !           206:     File f;
        !           207: 
        !           208:     s = findsource(filename);
        !           209:     if (s == nil) {
        !           210:        f = nil;
        !           211:     } else {
        !           212:        f = fopen(s, "r");
        !           213:     }
        !           214:     return f;
        !           215: }
        !           216: 
        !           217: /*
        !           218:  * Set the current source file.
        !           219:  */
        !           220: 
        !           221: public setsource(filename)
        !           222: String filename;
        !           223: {
        !           224:     if (filename != nil and filename != cursource) {
        !           225:        prevsource = cursource;
        !           226:        cursource = filename;
        !           227:        cursrcline = 1;
        !           228:     }
        !           229: }
        !           230: 
        !           231: /*
        !           232:  * Read the source file getting seek pointers for each line.
        !           233:  */
        !           234: 
        !           235: private skimsource()
        !           236: {
        !           237:     register int c;
        !           238:     register Seekaddr count;
        !           239:     register File f;
        !           240:     register Lineno linenum;
        !           241:     register Seekaddr lastaddr;
        !           242:     register int slot;
        !           243: 
        !           244:     f = opensource(cursource);
        !           245:     if (f == nil) {
        !           246:        lastlinenum = 0;
        !           247:     } else {
        !           248:        if (prevsource != nil) {
        !           249:            free_seektab();
        !           250:            if (srcfp != nil) {
        !           251:                fclose(srcfp);
        !           252:            }
        !           253:        }
        !           254:        prevsource = cursource;
        !           255:        linenum = 0;
        !           256:        count = 0;
        !           257:        lastaddr = 0;
        !           258:        while ((c = getc(f)) != EOF) {
        !           259:            ++count;
        !           260:            if (c == '\n') {
        !           261:                slot = slotno(++linenum);
        !           262:                if (slot >= NSLOTS) {
        !           263:                    panic("skimsource: too many lines");
        !           264:                }
        !           265:                if (seektab[slot] == nil) {
        !           266:                    seektab[slot] = slot_alloc();
        !           267:                }
        !           268:                seektab[slot][index(linenum)] = lastaddr;
        !           269:                lastaddr = count;
        !           270:            }
        !           271:        }
        !           272:        lastlinenum = linenum;
        !           273:        srcfp = f;
        !           274:     }
        !           275: }
        !           276: 
        !           277: /*
        !           278:  * Erase information and release space in the current seektab.
        !           279:  * This is in preparation for reading in seek pointers for a
        !           280:  * new file.  It is possible that seek pointers for all files
        !           281:  * should be kept around, but the current concern is space.
        !           282:  */
        !           283: 
        !           284: private free_seektab()
        !           285: {
        !           286:     register int slot;
        !           287: 
        !           288:     for (slot = 0; slot < NSLOTS; slot++) {
        !           289:        if (seektab[slot] != nil) {
        !           290:            dispose(seektab[slot]);
        !           291:        }
        !           292:     }
        !           293: }
        !           294: 
        !           295: /*
        !           296:  * Figure out current source position.
        !           297:  */
        !           298: 
        !           299: public getsrcpos()
        !           300: {
        !           301:     String filename;
        !           302: 
        !           303:     curline = srcline(pc);
        !           304:     filename = srcfilename(pc);
        !           305:     setsource(filename);
        !           306:     if (curline != 0) {
        !           307:        cursrcline = curline;
        !           308:     }
        !           309: }
        !           310: 
        !           311: /*
        !           312:  * Print out the current source position.
        !           313:  */
        !           314: 
        !           315: public printsrcpos()
        !           316: {
        !           317:     printf("at line %d", curline);
        !           318:     if (nlhdr.nfiles > 1) {
        !           319:        printf(" in file \"%s\"", cursource);
        !           320:     }
        !           321: }
        !           322: 
        !           323: #define DEF_EDITOR  "vi"
        !           324: 
        !           325: /*
        !           326:  * Invoke an editor on the given file.  Which editor to use might change
        !           327:  * installation to installation.  For now, we use "vi".  In any event,
        !           328:  * the environment variable "EDITOR" overrides any default.
        !           329:  */
        !           330: 
        !           331: public edit(filename)
        !           332: String filename;
        !           333: {
        !           334:     extern String getenv();
        !           335:     String ed, src, s;
        !           336:     Symbol f;
        !           337:     Address addr;
        !           338:     char lineno[10];
        !           339: 
        !           340:     ed = getenv("EDITOR");
        !           341:     if (ed == nil) {
        !           342:        ed = DEF_EDITOR;
        !           343:     }
        !           344:     src = findsource((filename != nil) ? filename : cursource);
        !           345:     if (src == nil) {
        !           346:        f = which(identname(filename, true));
        !           347:        if (not isblock(f)) {
        !           348:            error("can't read \"%s\"", filename);
        !           349:        }
        !           350:        addr = firstline(f);
        !           351:        if (addr == NOADDR) {
        !           352:            error("no source for \"%s\"", filename);
        !           353:        }
        !           354:        src = srcfilename(addr);
        !           355:        s = findsource(src);
        !           356:        if (s != nil) {
        !           357:            src = s;
        !           358:        }
        !           359:        sprintf(lineno, "+%d", srcline(addr));
        !           360:     } else {
        !           361:        sprintf(lineno, "+1");
        !           362:     }
        !           363:     if (streq(ed, "vi") or streq(ed, "ex")) {
        !           364:        call(ed, stdin, stdout, lineno, src, nil);
        !           365:     } else {
        !           366:        call(ed, stdin, stdout, src, nil);
        !           367:     }
        !           368: }
        !           369: 
        !           370: /*
        !           371:  * Strip away portions of a given pattern not part of the regular expression.
        !           372:  */
        !           373: 
        !           374: private String getpattern (pattern)
        !           375: String pattern;
        !           376: {
        !           377:     register char *p, *r;
        !           378: 
        !           379:     p = pattern;
        !           380:     while (*p == ' ' or *p == '\t') {
        !           381:        ++p;
        !           382:     }
        !           383:     r = p;
        !           384:     while (*p != '\0') {
        !           385:        ++p;
        !           386:     }
        !           387:     --p;
        !           388:     if (*p == '\n') {
        !           389:        *p = '\0';
        !           390:        --p;
        !           391:     }
        !           392:     if (*p == *r) {
        !           393:        *p = '\0';
        !           394:        --p;
        !           395:     }
        !           396:     return r + 1;
        !           397: }
        !           398: 
        !           399: /*
        !           400:  * Search the current file for a regular expression.
        !           401:  */
        !           402: 
        !           403: public search (direction, pattern)
        !           404: char direction;
        !           405: String pattern;
        !           406: {
        !           407:     register String p;
        !           408:     register File f;
        !           409:     String re, err;
        !           410:     Lineno line;
        !           411:     boolean matched;
        !           412:     char buf[512];
        !           413:     
        !           414:     if (cursource == nil) {
        !           415:        beginerrmsg();
        !           416:        fprintf(stderr, "no source file\n");
        !           417:     } else {
        !           418:        if (cursource != prevsource) {
        !           419:            skimsource();
        !           420:        }
        !           421:        if (lastlinenum == 0) {
        !           422:            beginerrmsg();
        !           423:            fprintf(stderr, "couldn't read \"%s\"\n", cursource);
        !           424:        } else {
        !           425:            re = getpattern(pattern);
        !           426:            /* circf = 0; */
        !           427:            if (re != nil and *re != '\0') {
        !           428:                err = re_comp(re);
        !           429:                if (err != nil) {
        !           430:                    error(err);
        !           431:                }
        !           432:            }
        !           433:            matched = false;
        !           434:            f = srcfp;
        !           435:            line = cursrcline;
        !           436:            do {
        !           437:                if (direction == '/') {
        !           438:                    ++line;
        !           439:                    if (line > lastlinenum) {
        !           440:                        line = 1;
        !           441:                    }
        !           442:                } else {
        !           443:                    --line;
        !           444:                    if (line < 1) {
        !           445:                        line = lastlinenum;
        !           446:                    }
        !           447:                }
        !           448:                fseek(f, srcaddr(line), L_SET);
        !           449:                p = buf;
        !           450:                *p = getc(f);
        !           451:                while ((*p != '\n') and (*p != EOF)) {
        !           452:                    ++p;
        !           453:                    *p = getc(f);
        !           454:                }
        !           455:                *p = '\0';
        !           456:                matched = (boolean) re_exec(buf);
        !           457:            } while (not matched and line != cursrcline);
        !           458:            if (not matched) {
        !           459:                beginerrmsg();
        !           460:                fprintf(stderr, "no match\n");
        !           461:            } else {
        !           462:                printlines(line, line);
        !           463:                cursrcline = line;
        !           464:            }
        !           465:        }
        !           466:     }
        !           467: }
        !           468: 
        !           469: public integer srcwindowlen ()
        !           470: {
        !           471:     Node s;
        !           472: 
        !           473:     s = findvar(identname("$listwindow", true));
        !           474:     if (s == nil)
        !           475:        return 10;
        !           476:     eval(s);
        !           477:     return pop(integer);
        !           478: }
        !           479: 
        !           480: /*
        !           481:  * Compute a small window around the given line.
        !           482:  */
        !           483: 
        !           484: public getsrcwindow (line, l1, l2)
        !           485: Lineno line, *l1, *l2;
        !           486: {
        !           487:     integer size;
        !           488: 
        !           489:     size = srcwindowlen();
        !           490:     *l1 = line - (size div 2);
        !           491:     if (*l1 < 1) {
        !           492:        *l1 = 1;
        !           493:     }
        !           494:     *l2 = *l1 + size;
        !           495:     if (lastlinenum != LASTLINE and *l2 > lastlinenum) {
        !           496:        *l2 = lastlinenum;
        !           497:     }
        !           498: }

unix.superglobalmegacorp.com

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