Annotation of 41BSD/cmd/sdb/fio.c, revision 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.