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