1: static  char sccsid[] = "@(#)fio.c 4.2 8/17/82";
   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: }

Defined functions

fback defined in line 246; used 3 times
ffind defined in line 227; used 9 times
fforward defined in line 262; used 3 times
fgetline defined in line 123; used 5 times
finit defined in line 52; used 4 times
fnext defined in line 183; used 3 times
fprev defined in line 198; used 1 times
fprint defined in line 213; used 7 times
fprintn defined in line 279; used 5 times

Defined variables

cfile defined in line 33; used 30 times
fibuf defined in line 35; used 9 times
finfo defined in line 33; used 3 times
sccsid defined in line 1; never used

Defined struct's

finfo defined in line 26; used 6 times
  • in line 32(2), 90(4)
Last modified: 1982-10-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1363
Valid CSS Valid XHTML 1.0 Strict