/* Copyright (c) 1982 Regents of the University of California */
static char sccsid
[] = "@(#)source.c 1.2 2/11/82";
* Source file management.
* Seektab is the data structure used for indexing source
* seek addresses by line number.
* we want an array so indexing is fast and easy
* we don't want to waste space for small files
* we don't want an upper bound on # of lines in a file
* we don't know how many lines there are
* The solution is a "dirty" hash table. We have NSLOTS pointers to
* arrays of NLINESPERSLOT addresses. To find the source address of
* a particular line we find the slot, allocate space if necessary,
* and then find its location within the pointed to array.
* As a result, there is a limit of NSLOTS*NLINESPERSLOT lines per file
* but this is plenty high and still fairly inexpensive.
* This implementation maintains only one source file at any given
* so as to avoid consuming too much memory. In an environment where
* memory is less constrained and one expects to be changing between
* files often enough, it would be reasonable to have multiple seek tables.
#define NLINESPERSLOT 500
#define slotno(line) ((line)/NLINESPERSLOT)
#define index(line) ((line)%NLINESPERSLOT)
#define slot_alloc() alloc(NLINESPERSLOT, SEEKADDR)
#define srcaddr(line) seektab[(line)/NLINESPERSLOT][(line)%NLINESPERSLOT]
LOCAL SEEKADDR
*seektab
[NSLOTS
];
* check to make sure a source line number is valid
error("line number must be positive");
if (linenum
> lastlinenum
) {
error("not that many lines");
* print out the given lines from the source
error("second line number less than first");
fseek(fp
, (long) srcaddr(l1
), 0);
for (i
= l1
; i
<= l2
; i
++) {
while ((c
= getc(fp
)) != '\n') {
* read the source file getting seek pointers for each line
register SEEKADDR lastaddr
;
if (file
== NIL
|| file
== cursource
) {
if ((fp
= fopen(file
, "r")) == NULL
) {
panic("can't open \"%s\"", file
);
linenum
= 0, count
= 0, lastaddr
= 0;
while ((c
= getc(fp
)) != EOF
) {
slot
= slotno(++linenum
);
panic("skimsource: too many lines");
if (seektab
[slot
] == NIL
) {
seektab
[slot
] = slot_alloc();
seektab
[slot
][index(linenum
)] = lastaddr
;
* Erase information and release space in the current seektab.
* This is in preparation for reading in seek pointers for a
* new file. It is possible that seek pointers for all files
* should be kept around, but the current concern is space.
for (slot
= 0; slot
< NSLOTS
; slot
++) {
if (seektab
[slot
] != NIL
) {