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