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