1*9680Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*9680Slinton 3*9680Slinton static char sccsid[] = "@(#)@(#)source.c 1.1 12/15/82"; 4*9680Slinton 5*9680Slinton /* 6*9680Slinton * Source file management. 7*9680Slinton */ 8*9680Slinton 9*9680Slinton #include "defs.h" 10*9680Slinton #include "source.h" 11*9680Slinton #include "object.h" 12*9680Slinton #include "mappings.h" 13*9680Slinton #include "machine.h" 14*9680Slinton 15*9680Slinton #ifndef public 16*9680Slinton typedef int Lineno; 17*9680Slinton 18*9680Slinton String cursource; 19*9680Slinton Lineno curline; 20*9680Slinton Lineno cursrcline; 21*9680Slinton 22*9680Slinton #define LASTLINE 0 /* recognized by printlines */ 23*9680Slinton 24*9680Slinton #include "lists.h" 25*9680Slinton 26*9680Slinton List sourcepath; 27*9680Slinton #endif 28*9680Slinton 29*9680Slinton private Lineno lastlinenum; 30*9680Slinton private String prevsource = nil; 31*9680Slinton 32*9680Slinton /* 33*9680Slinton * Data structure for indexing source seek addresses by line number. 34*9680Slinton * 35*9680Slinton * The constraints are: 36*9680Slinton * 37*9680Slinton * we want an array so indexing is fast and easy 38*9680Slinton * we don't want to waste space for small files 39*9680Slinton * we don't want an upper bound on # of lines in a file 40*9680Slinton * we don't know how many lines there are 41*9680Slinton * 42*9680Slinton * The solution is a "dirty" hash table. We have NSLOTS pointers to 43*9680Slinton * arrays of NLINESPERSLOT addresses. To find the source address of 44*9680Slinton * a particular line we find the slot, allocate space if necessary, 45*9680Slinton * and then find its location within the pointed to array. 46*9680Slinton */ 47*9680Slinton 48*9680Slinton typedef int Seekaddr; 49*9680Slinton 50*9680Slinton #define NSLOTS 20 51*9680Slinton #define NLINESPERSLOT 500 52*9680Slinton 53*9680Slinton #define slotno(line) ((line) div NLINESPERSLOT) 54*9680Slinton #define index(line) ((line) mod NLINESPERSLOT) 55*9680Slinton #define slot_alloc() newarr(Seekaddr, NLINESPERSLOT) 56*9680Slinton #define srcaddr(line) seektab[slotno(line)][index(line)] 57*9680Slinton 58*9680Slinton private File srcfp; 59*9680Slinton private Seekaddr *seektab[NSLOTS]; 60*9680Slinton 61*9680Slinton /* 62*9680Slinton * Print out the given lines from the source. 63*9680Slinton */ 64*9680Slinton 65*9680Slinton public printlines(l1, l2) 66*9680Slinton Lineno l1, l2; 67*9680Slinton { 68*9680Slinton register int c; 69*9680Slinton register Lineno i, lb, ub; 70*9680Slinton register File f; 71*9680Slinton 72*9680Slinton if (cursource == nil) { 73*9680Slinton beginerrmsg(); 74*9680Slinton fprintf(stderr, "no source file\n"); 75*9680Slinton } else { 76*9680Slinton if (cursource != prevsource) { 77*9680Slinton skimsource(); 78*9680Slinton } 79*9680Slinton if (lastlinenum == 0) { 80*9680Slinton beginerrmsg(); 81*9680Slinton fprintf(stderr, "couldn't read \"%s\"\n", cursource); 82*9680Slinton } else { 83*9680Slinton lb = (l1 == 0) ? lastlinenum : l1; 84*9680Slinton ub = (l2 == 0) ? lastlinenum : l2; 85*9680Slinton if (lb < 1) { 86*9680Slinton beginerrmsg(); 87*9680Slinton fprintf(stderr, "line number must be positive\n"); 88*9680Slinton } else if (lb > lastlinenum) { 89*9680Slinton beginerrmsg(); 90*9680Slinton if (lastlinenum == 1) { 91*9680Slinton fprintf(stderr, "\"%s\" has only 1 line\n", cursource); 92*9680Slinton } else { 93*9680Slinton fprintf(stderr, "\"%s\" has only %d lines\n", 94*9680Slinton cursource, lastlinenum); 95*9680Slinton } 96*9680Slinton } else if (ub < lb) { 97*9680Slinton beginerrmsg(); 98*9680Slinton fprintf(stderr, "second number must be greater than first\n"); 99*9680Slinton } else { 100*9680Slinton if (ub > lastlinenum) { 101*9680Slinton ub = lastlinenum; 102*9680Slinton } 103*9680Slinton f = srcfp; 104*9680Slinton fseek(f, (long) srcaddr(lb), 0); 105*9680Slinton for (i = lb; i <= ub; i++) { 106*9680Slinton printf("%5d ", i); 107*9680Slinton while ((c = getc(f)) != '\n') { 108*9680Slinton putchar(c); 109*9680Slinton } 110*9680Slinton putchar('\n'); 111*9680Slinton } 112*9680Slinton cursrcline = ub + 1; 113*9680Slinton } 114*9680Slinton } 115*9680Slinton } 116*9680Slinton } 117*9680Slinton 118*9680Slinton /* 119*9680Slinton * Open a source file looking in the appropriate places. 120*9680Slinton */ 121*9680Slinton 122*9680Slinton public File opensource(filename) 123*9680Slinton String filename; 124*9680Slinton { 125*9680Slinton register String dir; 126*9680Slinton char buf[256]; 127*9680Slinton File f; 128*9680Slinton 129*9680Slinton f = nil; 130*9680Slinton foreach (String, dir, sourcepath) 131*9680Slinton sprintf(buf, "%s/%s", dir, filename); 132*9680Slinton f = fopen(buf, "r"); 133*9680Slinton if (f != nil) { 134*9680Slinton break; 135*9680Slinton } 136*9680Slinton endfor 137*9680Slinton return f; 138*9680Slinton } 139*9680Slinton 140*9680Slinton /* 141*9680Slinton * Set the current source file. 142*9680Slinton */ 143*9680Slinton 144*9680Slinton public setsource(filename) 145*9680Slinton String filename; 146*9680Slinton { 147*9680Slinton if (filename != nil and filename != cursource) { 148*9680Slinton prevsource = cursource; 149*9680Slinton cursource = filename; 150*9680Slinton cursrcline = 1; 151*9680Slinton } 152*9680Slinton } 153*9680Slinton 154*9680Slinton /* 155*9680Slinton * Read the source file getting seek pointers for each line. 156*9680Slinton */ 157*9680Slinton 158*9680Slinton private skimsource() 159*9680Slinton { 160*9680Slinton register int c; 161*9680Slinton register Lineno count; 162*9680Slinton register File f; 163*9680Slinton register Lineno linenum; 164*9680Slinton register Seekaddr lastaddr; 165*9680Slinton register int slot; 166*9680Slinton 167*9680Slinton f = opensource(cursource); 168*9680Slinton if (f == nil) { 169*9680Slinton lastlinenum = 0; 170*9680Slinton } else { 171*9680Slinton if (prevsource != nil) { 172*9680Slinton free_seektab(); 173*9680Slinton if (srcfp != nil) { 174*9680Slinton fclose(srcfp); 175*9680Slinton } 176*9680Slinton } 177*9680Slinton prevsource = cursource; 178*9680Slinton linenum = 0; 179*9680Slinton count = 0; 180*9680Slinton lastaddr = 0; 181*9680Slinton while ((c = getc(f)) != EOF) { 182*9680Slinton ++count; 183*9680Slinton if (c == '\n') { 184*9680Slinton slot = slotno(++linenum); 185*9680Slinton if (slot >= NSLOTS) { 186*9680Slinton panic("skimsource: too many lines"); 187*9680Slinton } 188*9680Slinton if (seektab[slot] == nil) { 189*9680Slinton seektab[slot] = slot_alloc(); 190*9680Slinton } 191*9680Slinton seektab[slot][index(linenum)] = lastaddr; 192*9680Slinton lastaddr = count; 193*9680Slinton } 194*9680Slinton } 195*9680Slinton lastlinenum = linenum; 196*9680Slinton srcfp = f; 197*9680Slinton } 198*9680Slinton } 199*9680Slinton 200*9680Slinton /* 201*9680Slinton * Erase information and release space in the current seektab. 202*9680Slinton * This is in preparation for reading in seek pointers for a 203*9680Slinton * new file. It is possible that seek pointers for all files 204*9680Slinton * should be kept around, but the current concern is space. 205*9680Slinton */ 206*9680Slinton 207*9680Slinton private free_seektab() 208*9680Slinton { 209*9680Slinton register int slot; 210*9680Slinton 211*9680Slinton for (slot = 0; slot < NSLOTS; slot++) { 212*9680Slinton if (seektab[slot] != nil) { 213*9680Slinton dispose(seektab[slot]); 214*9680Slinton } 215*9680Slinton } 216*9680Slinton } 217*9680Slinton 218*9680Slinton /* 219*9680Slinton * Figure out current source position. 220*9680Slinton */ 221*9680Slinton 222*9680Slinton public getsrcpos() 223*9680Slinton { 224*9680Slinton String filename; 225*9680Slinton 226*9680Slinton curline = srcline(pc); 227*9680Slinton filename = srcfilename(pc); 228*9680Slinton setsource(filename); 229*9680Slinton cursrcline = curline; 230*9680Slinton } 231*9680Slinton 232*9680Slinton /* 233*9680Slinton * Print out the current source position. 234*9680Slinton */ 235*9680Slinton 236*9680Slinton public printsrcpos() 237*9680Slinton { 238*9680Slinton printf("at line %d", curline); 239*9680Slinton if (nlhdr.nfiles > 1) { 240*9680Slinton printf(" in file \"%s\"", cursource); 241*9680Slinton } 242*9680Slinton } 243