|
|
1.1 ! root 1: /* Copyright (c) 1982 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)source.c 1.4 3/24/83"; ! 4: ! 5: /* ! 6: * Source file management. ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: #include "source.h" ! 11: ! 12: /* ! 13: * Seektab is the data structure used for indexing source ! 14: * seek addresses by line number. ! 15: * ! 16: * The constraints are: ! 17: * ! 18: * we want an array so indexing is fast and easy ! 19: * we don't want to waste space for small files ! 20: * we don't want an upper bound on # of lines in a file ! 21: * we don't know how many lines there are ! 22: * ! 23: * The solution is a sparse array. We have NSLOTS pointers to ! 24: * arrays of NLINESPERSLOT addresses. To find the source address of ! 25: * a particular line we find the slot, allocate space if necessary, ! 26: * and then find its location within the pointed to array. ! 27: * ! 28: * As a result, there is a limit of NSLOTS*NLINESPERSLOT lines per file ! 29: * but this is plenty high and still fairly inexpensive. ! 30: * ! 31: * This implementation maintains only one source file at any given ! 32: * so as to avoid consuming too much memory. In an environment where ! 33: * memory is less constrained and one expects to be changing between ! 34: * files often enough, it would be reasonable to have multiple seek tables. ! 35: */ ! 36: ! 37: typedef int SEEKADDR; ! 38: ! 39: #define NSLOTS 40 ! 40: #define NLINESPERSLOT 500 ! 41: ! 42: #define slotno(line) ((line)/NLINESPERSLOT) ! 43: #define index(line) ((line)%NLINESPERSLOT) ! 44: #define slot_alloc() alloc(NLINESPERSLOT, SEEKADDR) ! 45: #define srcaddr(line) seektab[(line)/NLINESPERSLOT][(line)%NLINESPERSLOT] ! 46: ! 47: LOCAL SEEKADDR *seektab[NSLOTS]; ! 48: ! 49: LOCAL FILE *srcfp; ! 50: ! 51: /* ! 52: * check to make sure a source line number is valid ! 53: */ ! 54: ! 55: chkline(linenum) ! 56: register LINENO linenum; ! 57: { ! 58: if (linenum < 1) { ! 59: error("line number must be positive"); ! 60: } ! 61: if (linenum > lastlinenum) { ! 62: error("not that many lines"); ! 63: } ! 64: } ! 65: ! 66: /* ! 67: * print out the given lines from the source ! 68: */ ! 69: ! 70: printlines(l1, l2) ! 71: LINENO l1, l2; ! 72: { ! 73: register int c; ! 74: register LINENO i; ! 75: register FILE *fp; ! 76: ! 77: chkline(l1); ! 78: chkline(l2); ! 79: if (l2 < l1) { ! 80: error("second line number less than first"); ! 81: } ! 82: fp = srcfp; ! 83: fseek(fp, (long) srcaddr(l1), 0); ! 84: for (i = l1; i <= l2; i++) { ! 85: printf("%5d ", i); ! 86: while ((c = getc(fp)) != '\n') { ! 87: putchar(c); ! 88: } ! 89: putchar('\n'); ! 90: } ! 91: } ! 92: ! 93: /* ! 94: * read the source file getting seek pointers for each line ! 95: */ ! 96: ! 97: skimsource(file) ! 98: char *file; ! 99: { ! 100: register int c; ! 101: register SEEKADDR count; ! 102: register FILE *fp; ! 103: register LINENO linenum; ! 104: register SEEKADDR lastaddr; ! 105: register int slot; ! 106: ! 107: if (file == NIL || file == cursource) { ! 108: return; ! 109: } ! 110: if ((fp = fopen(file, "r")) == NULL) { ! 111: panic("can't open \"%s\"", file); ! 112: } ! 113: if (cursource != NIL) { ! 114: free_seektab(); ! 115: } ! 116: cursource = file; ! 117: linenum = 0, count = 0, lastaddr = 0; ! 118: while ((c = getc(fp)) != EOF) { ! 119: count++; ! 120: if (c == '\n') { ! 121: slot = slotno(++linenum); ! 122: if (slot >= NSLOTS) { ! 123: panic("skimsource: too many lines"); ! 124: } ! 125: if (seektab[slot] == NIL) { ! 126: seektab[slot] = slot_alloc(); ! 127: } ! 128: seektab[slot][index(linenum)] = lastaddr; ! 129: lastaddr = count; ! 130: } ! 131: } ! 132: lastlinenum = linenum; ! 133: srcfp = fp; ! 134: } ! 135: ! 136: /* ! 137: * Erase information and release space in the current seektab. ! 138: * This is in preparation for reading in seek pointers for a ! 139: * new file. It is possible that seek pointers for all files ! 140: * should be kept around, but the current concern is space. ! 141: */ ! 142: ! 143: LOCAL free_seektab() ! 144: { ! 145: register int slot; ! 146: ! 147: for (slot = 0; slot < NSLOTS; slot++) { ! 148: if (seektab[slot] != NIL) { ! 149: free(seektab[slot]); ! 150: seektab[slot] = NIL; ! 151: } ! 152: } ! 153: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.