fixed problem with opening absolute pathnames
[unix-history] / usr / src / old / dbx / source.c
CommitLineData
79155b94
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
e3e28726 3static char sccsid[] = "@(#)source.c 1.8 %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;
e3e28726
ML
130 if (filename[0] == '/') {
131 f = fopen(filename, "r");
132 } else {
133 foreach (String, dir, sourcepath)
134 sprintf(buf, "%s/%s", dir, filename);
135 f = fopen(buf, "r");
136 if (f != nil) {
137 break;
79155b94 138 }
e3e28726
ML
139 endfor
140 }
79155b94
ML
141 return f;
142}
143
144/*
145 * Set the current source file.
146 */
147
148public setsource(filename)
149String filename;
150{
151 if (filename != nil and filename != cursource) {
152 prevsource = cursource;
153 cursource = filename;
154 cursrcline = 1;
155 }
156}
157
158/*
159 * Read the source file getting seek pointers for each line.
160 */
161
162private skimsource()
163{
164 register int c;
bb516de5 165 register Seekaddr count;
79155b94
ML
166 register File f;
167 register Lineno linenum;
168 register Seekaddr lastaddr;
169 register int slot;
170
171 f = opensource(cursource);
172 if (f == nil) {
173 lastlinenum = 0;
174 } else {
175 if (prevsource != nil) {
176 free_seektab();
177 if (srcfp != nil) {
178 fclose(srcfp);
179 }
180 }
181 prevsource = cursource;
182 linenum = 0;
183 count = 0;
184 lastaddr = 0;
185 while ((c = getc(f)) != EOF) {
186 ++count;
187 if (c == '\n') {
188 slot = slotno(++linenum);
189 if (slot >= NSLOTS) {
190 panic("skimsource: too many lines");
191 }
192 if (seektab[slot] == nil) {
193 seektab[slot] = slot_alloc();
194 }
195 seektab[slot][index(linenum)] = lastaddr;
196 lastaddr = count;
197 }
198 }
199 lastlinenum = linenum;
200 srcfp = f;
201 }
202}
203
204/*
205 * Erase information and release space in the current seektab.
206 * This is in preparation for reading in seek pointers for a
207 * new file. It is possible that seek pointers for all files
208 * should be kept around, but the current concern is space.
209 */
210
211private free_seektab()
212{
213 register int slot;
214
215 for (slot = 0; slot < NSLOTS; slot++) {
216 if (seektab[slot] != nil) {
217 dispose(seektab[slot]);
218 }
219 }
220}
221
222/*
223 * Figure out current source position.
224 */
225
226public getsrcpos()
227{
228 String filename;
229
ef552238
ML
230 curline = srcline(pc);
231 filename = srcfilename(pc);
79155b94 232 setsource(filename);
370fc044
ML
233 if (curline != 0) {
234 cursrcline = curline;
235 }
79155b94
ML
236}
237
238/*
239 * Print out the current source position.
240 */
241
242public printsrcpos()
243{
244 printf("at line %d", curline);
245 if (nlhdr.nfiles > 1) {
246 printf(" in file \"%s\"", cursource);
247 }
248}