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

unix.superglobalmegacorp.com

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