|
|
1.1 ! root 1: /* Copyright (c) 1982 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)source.c 1.9 8/5/83"; ! 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 ! 16: typedef int Lineno; ! 17: ! 18: String cursource; ! 19: Lineno curline; ! 20: Lineno cursrcline; ! 21: ! 22: #define LASTLINE 0 /* recognized by printlines */ ! 23: ! 24: #include "lists.h" ! 25: ! 26: List sourcepath; ! 27: #endif ! 28: ! 29: private Lineno lastlinenum; ! 30: private 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: ! 48: typedef long Seekaddr; ! 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: ! 58: private File srcfp; ! 59: private Seekaddr *seektab[NSLOTS]; ! 60: ! 61: /* ! 62: * Print out the given lines from the source. ! 63: */ ! 64: ! 65: public printlines(l1, l2) ! 66: Lineno 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; ! 104: fseek(f, srcaddr(lb), 0); ! 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: * Search the sourcepath for a file. ! 120: */ ! 121: ! 122: static char fileNameBuf[1024]; ! 123: ! 124: public String findsource(filename) ! 125: String filename; ! 126: { ! 127: register File f; ! 128: register String src, dir; ! 129: ! 130: if (filename[0] == '/') { ! 131: src = filename; ! 132: } else { ! 133: src = nil; ! 134: foreach (String, dir, sourcepath) ! 135: sprintf(fileNameBuf, "%s/%s", dir, filename); ! 136: f = fopen(fileNameBuf, "r"); ! 137: if (f != nil) { ! 138: fclose(f); ! 139: src = fileNameBuf; ! 140: break; ! 141: } ! 142: endfor ! 143: } ! 144: return src; ! 145: } ! 146: ! 147: /* ! 148: * Open a source file looking in the appropriate places. ! 149: */ ! 150: ! 151: public File opensource(filename) ! 152: String filename; ! 153: { ! 154: String s; ! 155: File f; ! 156: ! 157: s = findsource(filename); ! 158: if (s == nil) { ! 159: f = nil; ! 160: } else { ! 161: f = fopen(s, "r"); ! 162: } ! 163: return f; ! 164: } ! 165: ! 166: /* ! 167: * Set the current source file. ! 168: */ ! 169: ! 170: public setsource(filename) ! 171: String filename; ! 172: { ! 173: if (filename != nil and filename != cursource) { ! 174: prevsource = cursource; ! 175: cursource = filename; ! 176: cursrcline = 1; ! 177: } ! 178: } ! 179: ! 180: /* ! 181: * Read the source file getting seek pointers for each line. ! 182: */ ! 183: ! 184: private skimsource() ! 185: { ! 186: register int c; ! 187: register Seekaddr count; ! 188: register File f; ! 189: register Lineno linenum; ! 190: register Seekaddr lastaddr; ! 191: register int slot; ! 192: ! 193: f = opensource(cursource); ! 194: if (f == nil) { ! 195: lastlinenum = 0; ! 196: } else { ! 197: if (prevsource != nil) { ! 198: free_seektab(); ! 199: if (srcfp != nil) { ! 200: fclose(srcfp); ! 201: } ! 202: } ! 203: prevsource = cursource; ! 204: linenum = 0; ! 205: count = 0; ! 206: lastaddr = 0; ! 207: while ((c = getc(f)) != EOF) { ! 208: ++count; ! 209: if (c == '\n') { ! 210: slot = slotno(++linenum); ! 211: if (slot >= NSLOTS) { ! 212: panic("skimsource: too many lines"); ! 213: } ! 214: if (seektab[slot] == nil) { ! 215: seektab[slot] = slot_alloc(); ! 216: } ! 217: seektab[slot][index(linenum)] = lastaddr; ! 218: lastaddr = count; ! 219: } ! 220: } ! 221: lastlinenum = linenum; ! 222: srcfp = f; ! 223: } ! 224: } ! 225: ! 226: /* ! 227: * Erase information and release space in the current seektab. ! 228: * This is in preparation for reading in seek pointers for a ! 229: * new file. It is possible that seek pointers for all files ! 230: * should be kept around, but the current concern is space. ! 231: */ ! 232: ! 233: private free_seektab() ! 234: { ! 235: register int slot; ! 236: ! 237: for (slot = 0; slot < NSLOTS; slot++) { ! 238: if (seektab[slot] != nil) { ! 239: dispose(seektab[slot]); ! 240: } ! 241: } ! 242: } ! 243: ! 244: /* ! 245: * Figure out current source position. ! 246: */ ! 247: ! 248: public getsrcpos() ! 249: { ! 250: String filename; ! 251: ! 252: curline = srcline(pc); ! 253: filename = srcfilename(pc); ! 254: setsource(filename); ! 255: if (curline != 0) { ! 256: cursrcline = curline; ! 257: } ! 258: } ! 259: ! 260: /* ! 261: * Print out the current source position. ! 262: */ ! 263: ! 264: public printsrcpos() ! 265: { ! 266: printf("at line %d", curline); ! 267: if (nlhdr.nfiles > 1) { ! 268: printf(" in file \"%s\"", cursource); ! 269: } ! 270: } ! 271: ! 272: #define DEF_EDITOR "vi" ! 273: ! 274: /* ! 275: * Invoke an editor on the given file. Which editor to use might change ! 276: * installation to installation. For now, we use "vi". In any event, ! 277: * the environment variable "EDITOR" overrides any default. ! 278: */ ! 279: ! 280: public edit(filename) ! 281: String filename; ! 282: { ! 283: extern String getenv(); ! 284: String ed, src, s; ! 285: Symbol f; ! 286: Address addr; ! 287: char lineno[10]; ! 288: ! 289: ed = getenv("EDITOR"); ! 290: if (ed == nil) { ! 291: ed = DEF_EDITOR; ! 292: } ! 293: src = findsource((filename != nil) ? filename : cursource); ! 294: if (src == nil) { ! 295: f = which(identname(filename, true)); ! 296: if (not isblock(f)) { ! 297: error("can't read \"%s\"", filename); ! 298: } ! 299: addr = firstline(f); ! 300: if (addr == NOADDR) { ! 301: error("no source for \"%s\"", filename); ! 302: } ! 303: src = srcfilename(addr); ! 304: s = findsource(src); ! 305: if (s != nil) { ! 306: src = s; ! 307: } ! 308: sprintf(lineno, "+%d", srcline(addr)); ! 309: } else { ! 310: sprintf(lineno, "+1"); ! 311: } ! 312: call(ed, stdin, stdout, lineno, src, nil); ! 313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.