Annotation of 41BSD/cmd/sdb/fio.c, revision 1.1.1.1

1.1       root        1: static char sccsid[] = "@(#)fio.c 4.1 10/9/80";
                      2: /*
                      3:  * sdb - a symbolic debugger for unix - source file access routines.
                      4:  */
                      5: #include "head.h"
                      6: #include <stdio.h>
                      7: 
                      8: /*
                      9:  * These procedures manage the source files examined by sdb,
                     10:  * providing access to lines by number and utilities for printing
                     11:  * and scrolling.  One file is kept open by these routines, and
                     12:  * line index tables are maintained for all files which have been
                     13:  * ``current'' at any time so far.  This makes line access trivial,
                     14:  * since the location of each line in the files is known,
                     15:  * although we get ``burned'' if the file is changed.
                     16:  * SHOULD WATCH THE MODTIME OF FILES AND REINDEX IF IT CHANGES.
                     17:  */
                     18: 
                     19: /*
                     20:  * Structure for files which have been ``indexed''.
                     21:  * Contains a pointer to the file name, a pointer to an
                     22:  * array of seek pointers for the lines in the file,
                     23:  * and a next link in a chain of these for all files we have indexed,
                     24:  * The currently open file is cinfo->; the chain of active files is finfo.
                     25:  */
                     26: struct finfo {
                     27:        char    *name;                  /* name of this file w/o common pfx */
                     28:        off_t   *lines;                 /* array of seek pointers */
                     29: /* line i stretches from lines[i-1] to lines[i] - 1, if first line is 1 */
                     30:        int     nlines;                 /* number of lines in file */
                     31: /* lines array actually has nlines+1 elements, so last line is bracketed */
                     32:        struct  finfo *next;            /* link in chain of known files */
                     33: } *finfo, *cfile;
                     34: FILE   *FIO;                           /* current open file (only 1 now) */
                     35: char   fibuf[BUFSIZ];
                     36: /*
                     37:  * We use stdio when first reading the file, but thereafter
                     38:  * use our own routines, because we want to be able
                     39:  * to read backwards efficiently and avoid a tell() system
                     40:  * call on each line.  Fseekpt remebers where we are in the current
                     41:  * file.
                     42:  */
                     43: off_t  fseekpt;
                     44: 
                     45: /*
                     46:  * Make ``name'' the current source file, if it isn't already.
                     47:  * If we have never seen this file before, then we create a finfo
                     48:  * structure for it indexing the lines (this requires reading the
                     49:  * entire file and building an index, but is well worth it since
                     50:  * we otherwise have to brute force search the files all the time.)
                     51:  */
                     52: finit(name)
                     53:        char *name;
                     54: {
                     55:        char buf[BUFSIZ];
                     56:        register off_t *lp;
                     57:        
                     58:        if (cfile && !strcmp(cfile->name, name))
                     59:                return;                 /* its already current, do nothing */
                     60:        /* IT WOULD BE BETTER TO HAVE A COUPLE OF FILE DESCRIPTORS, LRU */
                     61:        if (FIO) {
                     62:                fclose(FIO);
                     63:                FIO = NULL;
                     64:        }
                     65:        /*
                     66:         * Paste the given name onto the common prefix (directory path)
                     67:         * to form the full name of the file to be opened.
                     68:         */
                     69:        strcpy(fp, name);
                     70:        if ((FIO = fopen(filework, "r")) == NULL) {
                     71:                nolines = 1;
                     72:                perror(filework);
                     73:                return;
                     74:        }
                     75:        setbuf(FIO, fibuf);
                     76:        fseekpt = -BUFSIZ;              /* putatively illegal */
                     77:        strcpy(curfile, name);
                     78:        /*
                     79:         * See if we have alread indexed this file.
                     80:         * If so, nothing much to do.
                     81:         */
                     82:        for (cfile = finfo; cfile; cfile = cfile->next)
                     83:                if (!strcmp(cfile->name, name))
                     84:                        return;
                     85:        /*
                     86:         * Create a structure for this (new) file.
                     87:         * Lines array grows 100 lines at a time.
                     88:         * 1 extra so last line is bracketed.
                     89:         */
                     90:        cfile = (struct finfo *)sbrk(sizeof (struct finfo));
                     91:        lp = cfile->lines = (off_t *)sbrk(101 * sizeof (off_t));
                     92:        *lp++ = 0;              /* line 1 starts at 0 ... */
                     93:        cfile->nlines = 0;
                     94:        /* IT WOULD PROBABLY BE FASTER TO JUST USE GETC AND LOOK FOR \n */
                     95:        while (fgets(buf, sizeof buf, FIO)) {
                     96:                if ((++cfile->nlines % 100) == 0)
                     97:                        sbrk(100 * sizeof (off_t));
                     98:                /*
                     99:                 * Mark end of the cfile->nlines'th line
                    100:                 */
                    101:                lp[0] = lp[-1] + strlen(buf);
                    102:                lp++;
                    103:        }
                    104:        if (cfile->nlines == 0) {
                    105:                printf("%s: no lines in file\n", filework);
                    106:                cfile = 0;
                    107:                return;
                    108:        }
                    109:        /*
                    110:         * Allocate space for the name, making sure to leave the
                    111:         * break on a word boundary.
                    112:         * IT WOULD BE MUCH BETTER TO USE MALLOC AND REALLOC IN SDB.
                    113:         */
                    114:        sbrk(lp + ((strlen(name)+sizeof(off_t)-1)&~(sizeof(off_t)-1)));
                    115:        strcpy(cfile->name = (char *)lp, name);
                    116:        cfile->next = finfo;
                    117:        finfo = cfile;
                    118: }
                    119: 
                    120: /*
                    121:  * Get the current line (fline) into fbuf
                    122:  */
                    123: fgetline()
                    124: {
                    125:        register off_t *op = &cfile->lines[fline-1];
                    126:        int o, n;
                    127: 
                    128:        n = op[1] - op[0];
                    129:        fbuf[n] = 0;
                    130:        /*
                    131:         * Case 1.  Line begins in current buffer.
                    132:         *
                    133:         * Compute the number of characters into the buffer where
                    134:         * the line starts.  If this offset plus its length is greater
                    135:         * than BUFSIZ, then this line splits across a buffer boundary
                    136:         * so take the rest of this buffer and the first part of the next.
                    137:         * Otherwise just take a chunk of this buffer.
                    138:         */
                    139:        if (*op >= fseekpt && *op < fseekpt + BUFSIZ) {
                    140: case1:
                    141:                o = op[0] - fseekpt;
                    142:                if (o + n > BUFSIZ) {
                    143:                        strncpy(fbuf, fibuf+o, BUFSIZ-o);
                    144:                        fseekpt += BUFSIZ;
                    145:                        read(fileno(FIO), fibuf, BUFSIZ);
                    146:                        strncpy(fbuf+BUFSIZ-o, fibuf, n-(BUFSIZ-o));
                    147:                } else
                    148:                        strncpy(fbuf, fibuf+o, n);
                    149:                return;
                    150:        }
                    151:        /*
                    152:         * Case 2.  Line ends in current buffer.
                    153:         *
                    154:         * If the line ends in this buffer (but doesn't begin in
                    155:         * it or else we would have had case 1) take the beginning
                    156:         * part of the buffer (end of the line) and then back up and
                    157:         * get the rest of the line from the end of the previous block.
                    158:         */
                    159:        if (op[1]-1 >= fseekpt && op[1] <= fseekpt+BUFSIZ) {
                    160:                o = op[1] - fseekpt;
                    161:                strncpy(fbuf+n-o, fibuf, o);
                    162:                fseekpt -= BUFSIZ;
                    163:                lseek(fileno(FIO), fseekpt, 0);
                    164:                read(fileno(FIO), fibuf, BUFSIZ);
                    165:                strncpy(fbuf, fibuf+op[0]-fseekpt, n-o);
                    166:                return;
                    167:        }
                    168:        /*
                    169:         * Case 3.  Line not in current buffer at all.
                    170:         *
                    171:         * Read in the buffer where the line starts and then go
                    172:         * back and handle as case 1.
                    173:         */
                    174:        fseekpt = (op[0] / BUFSIZ) * BUFSIZ;
                    175:        lseek(fileno(FIO), fseekpt, 0);
                    176:        read(fileno(FIO), fibuf, BUFSIZ);
                    177:        goto case1;
                    178: }
                    179: 
                    180: /*
                    181:  * Advance current line, end-around (like for / search).
                    182:  */
                    183: fnext()
                    184: {
                    185:        
                    186:        if (cfile == 0)
                    187:                return;
                    188:        if (fline == cfile->nlines) {
                    189:                fline = 1;
                    190:        } else
                    191:                fline++;
                    192:        fgetline();
                    193: }
                    194: 
                    195: /*
                    196:  * Retreat the current line, end around.
                    197:  */
                    198: fprev()
                    199: {
                    200: 
                    201:        if (cfile == 0)
                    202:                return;
                    203:        if (fline == 1)
                    204:                fline = cfile->nlines;
                    205:        else
                    206:                fline--;
                    207:        fgetline();
                    208: }
                    209: 
                    210: /*
                    211:  * Print the current line.
                    212:  */
                    213: fprint()
                    214: {
                    215:        register char *p;
                    216:        
                    217:        if (cfile == 0) {
                    218:                error("No lines in file");
                    219:                return;
                    220:        }
                    221:        printf("%d: %s", fline, fbuf);
                    222: }
                    223: 
                    224: /*
                    225:  * Make line `num' current.
                    226:  */
                    227: ffind(num)
                    228:        register int num;
                    229: {
                    230:        
                    231:        if (cfile == 0)
                    232:                return;
                    233:        if (num > cfile->nlines)
                    234:                error("Not that many lines in file");
                    235:        else if (num <= 0)
                    236:                error("Zero or negative line?");
                    237:        else {
                    238:                fline = num;
                    239:                fgetline();
                    240:        }
                    241: }
                    242: 
                    243: /*
                    244:  * Go back n lines.
                    245:  */
                    246: fback(n)
                    247: {
                    248:        int i;
                    249:        
                    250:        if (cfile == 0)
                    251:                return (0);
                    252:        if (n > fline - 1)
                    253:                n = fline - 1;
                    254:        fline -= n;
                    255:        fgetline();
                    256:        return (n);
                    257: }
                    258: 
                    259: /*
                    260:  * Go forwards n lines.
                    261:  */
                    262: fforward(n)
                    263:        int n;
                    264: {
                    265:        register int fnext;
                    266:        
                    267:        if (cfile == 0)
                    268:                return(0);
                    269:        if (fline + n > cfile->nlines)
                    270:                n = cfile->nlines - fline;
                    271:        fline += n;
                    272:        fgetline();
                    273:        return (n);
                    274: }
                    275: 
                    276: /*
                    277:  * Print (upto) n lines, returning number printed.
                    278:  */
                    279: fprintn(n)
                    280:        int n;
                    281: {
                    282:        register int i;
                    283:        
                    284:        if (cfile == 0) {
                    285:                error("No lines in file");
                    286:                return (0);
                    287:        }
                    288:        for (i = 1; i <= n; i++) {
                    289:                fprint();
                    290:                if (fline == cfile->nlines || i == n)
                    291:                        return(i);
                    292:                fnext();
                    293:        }
                    294:        return (n);
                    295: }

unix.superglobalmegacorp.com

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