xref: /csrg-svn/old/dbx/source.c (revision 9680)
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