Annotation of 43BSDTahoe/lib/old_compiler/dbx/source.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: 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.