Annotation of 43BSDReno/pgrm/dbx/source.c, revision 1.1.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.