xref: /csrg-svn/old/dbx/source.c (revision 10617)
19680Slinton /* Copyright (c) 1982 Regents of the University of California */
29680Slinton 
3*10617Slinton static char sccsid[] = "@(#)source.c 1.4 01/24/83";
49680Slinton 
59680Slinton /*
69680Slinton  * Source file management.
79680Slinton  */
89680Slinton 
99680Slinton #include "defs.h"
109680Slinton #include "source.h"
119680Slinton #include "object.h"
129680Slinton #include "mappings.h"
139680Slinton #include "machine.h"
149680Slinton 
159680Slinton #ifndef public
169680Slinton typedef int Lineno;
179680Slinton 
189680Slinton String cursource;
199680Slinton Lineno curline;
209680Slinton Lineno cursrcline;
219680Slinton 
229680Slinton #define LASTLINE 0		/* recognized by printlines */
239680Slinton 
249680Slinton #include "lists.h"
259680Slinton 
269680Slinton List sourcepath;
279680Slinton #endif
289680Slinton 
299680Slinton private Lineno lastlinenum;
309680Slinton private String prevsource = nil;
319680Slinton 
329680Slinton /*
339680Slinton  * Data structure for indexing source seek addresses by line number.
349680Slinton  *
359680Slinton  * The constraints are:
369680Slinton  *
379680Slinton  *  we want an array so indexing is fast and easy
389680Slinton  *  we don't want to waste space for small files
399680Slinton  *  we don't want an upper bound on # of lines in a file
409680Slinton  *  we don't know how many lines there are
419680Slinton  *
429680Slinton  * The solution is a "dirty" hash table.  We have NSLOTS pointers to
439680Slinton  * arrays of NLINESPERSLOT addresses.  To find the source address of
449680Slinton  * a particular line we find the slot, allocate space if necessary,
459680Slinton  * and then find its location within the pointed to array.
469680Slinton  */
479680Slinton 
48*10617Slinton typedef long Seekaddr;
499680Slinton 
509680Slinton #define NSLOTS 20
519680Slinton #define NLINESPERSLOT 500
529680Slinton 
539680Slinton #define slotno(line)    ((line) div NLINESPERSLOT)
549680Slinton #define index(line)	((line) mod NLINESPERSLOT)
559680Slinton #define slot_alloc()    newarr(Seekaddr, NLINESPERSLOT)
569680Slinton #define srcaddr(line)	seektab[slotno(line)][index(line)]
579680Slinton 
589680Slinton private File srcfp;
599680Slinton private Seekaddr *seektab[NSLOTS];
609680Slinton 
619680Slinton /*
629680Slinton  * Print out the given lines from the source.
639680Slinton  */
649680Slinton 
659680Slinton public printlines(l1, l2)
669680Slinton Lineno l1, l2;
679680Slinton {
689680Slinton     register int c;
699680Slinton     register Lineno i, lb, ub;
709680Slinton     register File f;
719680Slinton 
729680Slinton     if (cursource == nil) {
739680Slinton 	beginerrmsg();
749680Slinton 	fprintf(stderr, "no source file\n");
759680Slinton     } else {
769680Slinton 	if (cursource != prevsource) {
779680Slinton 	    skimsource();
789680Slinton 	}
799680Slinton 	if (lastlinenum == 0) {
809680Slinton 	    beginerrmsg();
819680Slinton 	    fprintf(stderr, "couldn't read \"%s\"\n", cursource);
829680Slinton 	} else {
839680Slinton 	    lb = (l1 == 0) ? lastlinenum : l1;
849680Slinton 	    ub = (l2 == 0) ? lastlinenum : l2;
859680Slinton 	    if (lb < 1) {
869680Slinton 		beginerrmsg();
879680Slinton 		fprintf(stderr, "line number must be positive\n");
889680Slinton 	    } else if (lb > lastlinenum) {
899680Slinton 		beginerrmsg();
909680Slinton 		if (lastlinenum == 1) {
919680Slinton 		    fprintf(stderr, "\"%s\" has only 1 line\n", cursource);
929680Slinton 		} else {
939680Slinton 		    fprintf(stderr, "\"%s\" has only %d lines\n",
949680Slinton 			cursource, lastlinenum);
959680Slinton 		}
969680Slinton 	    } else if (ub < lb) {
979680Slinton 		beginerrmsg();
989680Slinton 		fprintf(stderr, "second number must be greater than first\n");
999680Slinton 	    } else {
1009680Slinton 		if (ub > lastlinenum) {
1019680Slinton 		    ub = lastlinenum;
1029680Slinton 		}
1039680Slinton 		f = srcfp;
104*10617Slinton 		fseek(f, srcaddr(lb), 0);
1059680Slinton 		for (i = lb; i <= ub; i++) {
1069680Slinton 		    printf("%5d   ", i);
1079680Slinton 		    while ((c = getc(f)) != '\n') {
1089680Slinton 			putchar(c);
1099680Slinton 		    }
1109680Slinton 		    putchar('\n');
1119680Slinton 		}
1129680Slinton 		cursrcline = ub + 1;
1139680Slinton 	    }
1149680Slinton 	}
1159680Slinton     }
1169680Slinton }
1179680Slinton 
1189680Slinton /*
1199680Slinton  * Open a source file looking in the appropriate places.
1209680Slinton  */
1219680Slinton 
1229680Slinton public File opensource(filename)
1239680Slinton String filename;
1249680Slinton {
1259680Slinton     register String dir;
1269680Slinton     char buf[256];
1279680Slinton     File f;
1289680Slinton 
1299680Slinton     f = nil;
1309680Slinton     foreach (String, dir, sourcepath)
1319680Slinton 	sprintf(buf, "%s/%s", dir, filename);
1329680Slinton 	f = fopen(buf, "r");
1339680Slinton 	if (f != nil) {
1349680Slinton 	    break;
1359680Slinton 	}
1369680Slinton     endfor
1379680Slinton     return f;
1389680Slinton }
1399680Slinton 
1409680Slinton /*
1419680Slinton  * Set the current source file.
1429680Slinton  */
1439680Slinton 
1449680Slinton public setsource(filename)
1459680Slinton String filename;
1469680Slinton {
1479680Slinton     if (filename != nil and filename != cursource) {
1489680Slinton 	prevsource = cursource;
1499680Slinton 	cursource = filename;
1509680Slinton 	cursrcline = 1;
1519680Slinton     }
1529680Slinton }
1539680Slinton 
1549680Slinton /*
1559680Slinton  * Read the source file getting seek pointers for each line.
1569680Slinton  */
1579680Slinton 
1589680Slinton private skimsource()
1599680Slinton {
1609680Slinton     register int c;
161*10617Slinton     register Seekaddr count;
1629680Slinton     register File f;
1639680Slinton     register Lineno linenum;
1649680Slinton     register Seekaddr lastaddr;
1659680Slinton     register int slot;
1669680Slinton 
1679680Slinton     f = opensource(cursource);
1689680Slinton     if (f == nil) {
1699680Slinton 	lastlinenum = 0;
1709680Slinton     } else {
1719680Slinton 	if (prevsource != nil) {
1729680Slinton 	    free_seektab();
1739680Slinton 	    if (srcfp != nil) {
1749680Slinton 		fclose(srcfp);
1759680Slinton 	    }
1769680Slinton 	}
1779680Slinton 	prevsource = cursource;
1789680Slinton 	linenum = 0;
1799680Slinton 	count = 0;
1809680Slinton 	lastaddr = 0;
1819680Slinton 	while ((c = getc(f)) != EOF) {
1829680Slinton 	    ++count;
1839680Slinton 	    if (c == '\n') {
1849680Slinton 		slot = slotno(++linenum);
1859680Slinton 		if (slot >= NSLOTS) {
1869680Slinton 		    panic("skimsource: too many lines");
1879680Slinton 		}
1889680Slinton 		if (seektab[slot] == nil) {
1899680Slinton 		    seektab[slot] = slot_alloc();
1909680Slinton 		}
1919680Slinton 		seektab[slot][index(linenum)] = lastaddr;
1929680Slinton 		lastaddr = count;
1939680Slinton 	    }
1949680Slinton 	}
1959680Slinton 	lastlinenum = linenum;
1969680Slinton 	srcfp = f;
1979680Slinton     }
1989680Slinton }
1999680Slinton 
2009680Slinton /*
2019680Slinton  * Erase information and release space in the current seektab.
2029680Slinton  * This is in preparation for reading in seek pointers for a
2039680Slinton  * new file.  It is possible that seek pointers for all files
2049680Slinton  * should be kept around, but the current concern is space.
2059680Slinton  */
2069680Slinton 
2079680Slinton private free_seektab()
2089680Slinton {
2099680Slinton     register int slot;
2109680Slinton 
2119680Slinton     for (slot = 0; slot < NSLOTS; slot++) {
2129680Slinton 	if (seektab[slot] != nil) {
2139680Slinton 	    dispose(seektab[slot]);
2149680Slinton 	}
2159680Slinton     }
2169680Slinton }
2179680Slinton 
2189680Slinton /*
2199680Slinton  * Figure out current source position.
2209841Slinton  * Have to use "pc - 1" because pc is the address of the next instruction
2219841Slinton  * rather than the current one.
2229680Slinton  */
2239680Slinton 
2249680Slinton public getsrcpos()
2259680Slinton {
2269680Slinton     String filename;
2279680Slinton 
2289841Slinton     curline = srcline(pc - 1);
2299841Slinton     filename = srcfilename(pc - 1);
2309680Slinton     setsource(filename);
2319680Slinton     cursrcline = curline;
2329680Slinton }
2339680Slinton 
2349680Slinton /*
2359680Slinton  * Print out the current source position.
2369680Slinton  */
2379680Slinton 
2389680Slinton public printsrcpos()
2399680Slinton {
2409680Slinton     printf("at line %d", curline);
2419680Slinton     if (nlhdr.nfiles > 1) {
2429680Slinton 	printf(" in file \"%s\"", cursource);
2439680Slinton     }
2449680Slinton }
245