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

unix.superglobalmegacorp.com

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