xref: /csrg-svn/old/dbx/source.c (revision 12608)
19680Slinton /* Copyright (c) 1982 Regents of the University of California */
29680Slinton 
3*12608Slinton static char sccsid[] = "@(#)source.c 1.8 05/20/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 
4810617Slinton 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;
10410617Slinton 		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;
130*12608Slinton     if (filename[0] == '/') {
131*12608Slinton 	f = fopen(filename, "r");
132*12608Slinton     } else {
133*12608Slinton 	foreach (String, dir, sourcepath)
134*12608Slinton 	    sprintf(buf, "%s/%s", dir, filename);
135*12608Slinton 	    f = fopen(buf, "r");
136*12608Slinton 	    if (f != nil) {
137*12608Slinton 		break;
1389680Slinton 	}
139*12608Slinton 	endfor
140*12608Slinton     }
1419680Slinton     return f;
1429680Slinton }
1439680Slinton 
1449680Slinton /*
1459680Slinton  * Set the current source file.
1469680Slinton  */
1479680Slinton 
1489680Slinton public setsource(filename)
1499680Slinton String filename;
1509680Slinton {
1519680Slinton     if (filename != nil and filename != cursource) {
1529680Slinton 	prevsource = cursource;
1539680Slinton 	cursource = filename;
1549680Slinton 	cursrcline = 1;
1559680Slinton     }
1569680Slinton }
1579680Slinton 
1589680Slinton /*
1599680Slinton  * Read the source file getting seek pointers for each line.
1609680Slinton  */
1619680Slinton 
1629680Slinton private skimsource()
1639680Slinton {
1649680Slinton     register int c;
16510617Slinton     register Seekaddr count;
1669680Slinton     register File f;
1679680Slinton     register Lineno linenum;
1689680Slinton     register Seekaddr lastaddr;
1699680Slinton     register int slot;
1709680Slinton 
1719680Slinton     f = opensource(cursource);
1729680Slinton     if (f == nil) {
1739680Slinton 	lastlinenum = 0;
1749680Slinton     } else {
1759680Slinton 	if (prevsource != nil) {
1769680Slinton 	    free_seektab();
1779680Slinton 	    if (srcfp != nil) {
1789680Slinton 		fclose(srcfp);
1799680Slinton 	    }
1809680Slinton 	}
1819680Slinton 	prevsource = cursource;
1829680Slinton 	linenum = 0;
1839680Slinton 	count = 0;
1849680Slinton 	lastaddr = 0;
1859680Slinton 	while ((c = getc(f)) != EOF) {
1869680Slinton 	    ++count;
1879680Slinton 	    if (c == '\n') {
1889680Slinton 		slot = slotno(++linenum);
1899680Slinton 		if (slot >= NSLOTS) {
1909680Slinton 		    panic("skimsource: too many lines");
1919680Slinton 		}
1929680Slinton 		if (seektab[slot] == nil) {
1939680Slinton 		    seektab[slot] = slot_alloc();
1949680Slinton 		}
1959680Slinton 		seektab[slot][index(linenum)] = lastaddr;
1969680Slinton 		lastaddr = count;
1979680Slinton 	    }
1989680Slinton 	}
1999680Slinton 	lastlinenum = linenum;
2009680Slinton 	srcfp = f;
2019680Slinton     }
2029680Slinton }
2039680Slinton 
2049680Slinton /*
2059680Slinton  * Erase information and release space in the current seektab.
2069680Slinton  * This is in preparation for reading in seek pointers for a
2079680Slinton  * new file.  It is possible that seek pointers for all files
2089680Slinton  * should be kept around, but the current concern is space.
2099680Slinton  */
2109680Slinton 
2119680Slinton private free_seektab()
2129680Slinton {
2139680Slinton     register int slot;
2149680Slinton 
2159680Slinton     for (slot = 0; slot < NSLOTS; slot++) {
2169680Slinton 	if (seektab[slot] != nil) {
2179680Slinton 	    dispose(seektab[slot]);
2189680Slinton 	}
2199680Slinton     }
2209680Slinton }
2219680Slinton 
2229680Slinton /*
2239680Slinton  * Figure out current source position.
2249680Slinton  */
2259680Slinton 
2269680Slinton public getsrcpos()
2279680Slinton {
2289680Slinton     String filename;
2299680Slinton 
23011105Slinton     curline = srcline(pc);
23111105Slinton     filename = srcfilename(pc);
2329680Slinton     setsource(filename);
23311837Slinton     if (curline != 0) {
23411837Slinton 	cursrcline = curline;
23511837Slinton     }
2369680Slinton }
2379680Slinton 
2389680Slinton /*
2399680Slinton  * Print out the current source position.
2409680Slinton  */
2419680Slinton 
2429680Slinton public printsrcpos()
2439680Slinton {
2449680Slinton     printf("at line %d", curline);
2459680Slinton     if (nlhdr.nfiles > 1) {
2469680Slinton 	printf(" in file \"%s\"", cursource);
2479680Slinton     }
2489680Slinton }
249