|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)source.c 5.2 (Berkeley) 1/12/88"; ! 9: #endif not lint ! 10: ! 11: static char rcsid[] = "$Header: source.c,v 1.3 87/08/19 15:19:40 mike Exp $"; ! 12: ! 13: /* ! 14: * Source file management. ! 15: */ ! 16: ! 17: #include "defs.h" ! 18: #include "source.h" ! 19: #include "object.h" ! 20: #include "mappings.h" ! 21: #include "machine.h" ! 22: #include "keywords.h" ! 23: #include "tree.h" ! 24: #include "eval.h" ! 25: #ifdef IRIS ! 26: # define R_OK 04 /* read access */ ! 27: # define L_SET 01 /* absolute offset for seek */ ! 28: #else ! 29: # include <sys/file.h> ! 30: #endif ! 31: ! 32: #ifndef public ! 33: typedef int Lineno; ! 34: ! 35: String cursource; ! 36: Lineno curline; ! 37: Lineno cursrcline; ! 38: ! 39: #define LASTLINE 0 /* recognized by printlines */ ! 40: ! 41: #include "lists.h" ! 42: ! 43: List sourcepath; ! 44: #endif ! 45: ! 46: #ifdef IRIS ! 47: # define re_comp regcmp ! 48: # define re_exec(buf) (regex(buf) != NULL) ! 49: #endif ! 50: ! 51: extern char *re_comp(); ! 52: ! 53: private Lineno lastlinenum; ! 54: private String prevsource = nil; ! 55: ! 56: /* ! 57: * Data structure for indexing source seek addresses by line number. ! 58: * ! 59: * The constraints are: ! 60: * ! 61: * we want an array so indexing is fast and easy ! 62: * we don't want to waste space for small files ! 63: * we don't want an upper bound on # of lines in a file ! 64: * we don't know how many lines there are ! 65: * ! 66: * The solution is a "dirty" hash table. We have NSLOTS pointers to ! 67: * arrays of NLINESPERSLOT addresses. To find the source address of ! 68: * a particular line we find the slot, allocate space if necessary, ! 69: * and then find its location within the pointed to array. ! 70: */ ! 71: ! 72: typedef long Seekaddr; ! 73: ! 74: #define NSLOTS 40 ! 75: #define NLINESPERSLOT 500 ! 76: ! 77: #define slotno(line) ((line) div NLINESPERSLOT) ! 78: #define index(line) ((line) mod NLINESPERSLOT) ! 79: #define slot_alloc() newarr(Seekaddr, NLINESPERSLOT) ! 80: #define srcaddr(line) seektab[slotno(line)][index(line)] ! 81: ! 82: private File srcfp; ! 83: private Seekaddr *seektab[NSLOTS]; ! 84: ! 85: /* ! 86: * Determine if the current source file is available. ! 87: */ ! 88: ! 89: public boolean canReadSource () ! 90: { ! 91: boolean b; ! 92: ! 93: if (cursource == nil) { ! 94: b = false; ! 95: } else if (cursource != prevsource) { ! 96: skimsource(); ! 97: b = (boolean) (lastlinenum != 0); ! 98: } else { ! 99: b = true; ! 100: } ! 101: return b; ! 102: } ! 103: ! 104: /* ! 105: * Print out the given lines from the source. ! 106: */ ! 107: ! 108: public printlines(l1, l2) ! 109: Lineno l1, l2; ! 110: { ! 111: register int c; ! 112: register Lineno i, lb, ub; ! 113: register File f; ! 114: ! 115: if (cursource == nil) { ! 116: beginerrmsg(); ! 117: fprintf(stderr, "no source file\n"); ! 118: } else { ! 119: if (cursource != prevsource) { ! 120: skimsource(); ! 121: } ! 122: if (lastlinenum == 0) { ! 123: beginerrmsg(); ! 124: fprintf(stderr, "couldn't read \"%s\"\n", cursource); ! 125: } else { ! 126: lb = (l1 == LASTLINE) ? lastlinenum : l1; ! 127: ub = (l2 == LASTLINE) ? lastlinenum : l2; ! 128: if (lb < 1) { ! 129: beginerrmsg(); ! 130: fprintf(stderr, "line number must be positive\n"); ! 131: } else if (lb > lastlinenum) { ! 132: beginerrmsg(); ! 133: if (lastlinenum == 1) { ! 134: fprintf(stderr, "\"%s\" has only 1 line\n", cursource); ! 135: } else { ! 136: fprintf(stderr, "\"%s\" has only %d lines\n", ! 137: cursource, lastlinenum); ! 138: } ! 139: } else if (ub < lb) { ! 140: beginerrmsg(); ! 141: fprintf(stderr, "second number must be greater than first\n"); ! 142: } else { ! 143: if (ub > lastlinenum) { ! 144: ub = lastlinenum; ! 145: } ! 146: f = srcfp; ! 147: fseek(f, srcaddr(lb), 0); ! 148: for (i = lb; i <= ub; i++) { ! 149: printf("%5d ", i); ! 150: while ((c = getc(f)) != '\n') { ! 151: putchar(c); ! 152: } ! 153: putchar('\n'); ! 154: } ! 155: cursrcline = ub + 1; ! 156: } ! 157: } ! 158: } ! 159: } ! 160: ! 161: /* ! 162: * Search the sourcepath for a file. ! 163: */ ! 164: ! 165: static char fileNameBuf[1024]; ! 166: ! 167: public String findsource(filename) ! 168: String filename; ! 169: { ! 170: register String src, dir; ! 171: ! 172: if (filename[0] == '/') { ! 173: src = filename; ! 174: } else { ! 175: src = nil; ! 176: foreach (String, dir, sourcepath) ! 177: sprintf(fileNameBuf, "%s/%s", dir, filename); ! 178: if (access(fileNameBuf, R_OK) == 0) { ! 179: src = fileNameBuf; ! 180: break; ! 181: } ! 182: endfor ! 183: } ! 184: return src; ! 185: } ! 186: ! 187: /* ! 188: * Open a source file looking in the appropriate places. ! 189: */ ! 190: ! 191: public File opensource(filename) ! 192: String filename; ! 193: { ! 194: String s; ! 195: File f; ! 196: ! 197: s = findsource(filename); ! 198: if (s == nil) { ! 199: f = nil; ! 200: } else { ! 201: f = fopen(s, "r"); ! 202: } ! 203: return f; ! 204: } ! 205: ! 206: /* ! 207: * Set the current source file. ! 208: */ ! 209: ! 210: public setsource(filename) ! 211: String filename; ! 212: { ! 213: if (filename != nil and filename != cursource) { ! 214: prevsource = cursource; ! 215: cursource = filename; ! 216: cursrcline = 1; ! 217: } ! 218: } ! 219: ! 220: /* ! 221: * Read the source file getting seek pointers for each line. ! 222: */ ! 223: ! 224: private skimsource() ! 225: { ! 226: register int c; ! 227: register Seekaddr count; ! 228: register File f; ! 229: register Lineno linenum; ! 230: register Seekaddr lastaddr; ! 231: register int slot; ! 232: ! 233: f = opensource(cursource); ! 234: if (f == nil) { ! 235: lastlinenum = 0; ! 236: } else { ! 237: if (prevsource != nil) { ! 238: free_seektab(); ! 239: if (srcfp != nil) { ! 240: fclose(srcfp); ! 241: } ! 242: } ! 243: prevsource = cursource; ! 244: linenum = 0; ! 245: count = 0; ! 246: lastaddr = 0; ! 247: while ((c = getc(f)) != EOF) { ! 248: ++count; ! 249: if (c == '\n') { ! 250: slot = slotno(++linenum); ! 251: if (slot >= NSLOTS) { ! 252: panic("skimsource: too many lines"); ! 253: } ! 254: if (seektab[slot] == nil) { ! 255: seektab[slot] = slot_alloc(); ! 256: } ! 257: seektab[slot][index(linenum)] = lastaddr; ! 258: lastaddr = count; ! 259: } ! 260: } ! 261: lastlinenum = linenum; ! 262: srcfp = f; ! 263: } ! 264: } ! 265: ! 266: /* ! 267: * Erase information and release space in the current seektab. ! 268: * This is in preparation for reading in seek pointers for a ! 269: * new file. It is possible that seek pointers for all files ! 270: * should be kept around, but the current concern is space. ! 271: */ ! 272: ! 273: private free_seektab() ! 274: { ! 275: register int slot; ! 276: ! 277: for (slot = 0; slot < NSLOTS; slot++) { ! 278: if (seektab[slot] != nil) { ! 279: dispose(seektab[slot]); ! 280: } ! 281: } ! 282: } ! 283: ! 284: /* ! 285: * Figure out current source position. ! 286: */ ! 287: ! 288: public getsrcpos() ! 289: { ! 290: String filename; ! 291: ! 292: curline = srcline(pc); ! 293: filename = srcfilename(pc); ! 294: setsource(filename); ! 295: if (curline != 0) { ! 296: cursrcline = curline; ! 297: } ! 298: } ! 299: ! 300: /* ! 301: * Print out the current source position. ! 302: */ ! 303: ! 304: public printsrcpos() ! 305: { ! 306: printf("at line %d", curline); ! 307: if (nlhdr.nfiles > 1) { ! 308: printf(" in file \"%s\"", cursource); ! 309: } ! 310: } ! 311: ! 312: #define DEF_EDITOR "vi" ! 313: ! 314: /* ! 315: * Invoke an editor on the given file. Which editor to use might change ! 316: * installation to installation. For now, we use "vi". In any event, ! 317: * the environment variable "EDITOR" overrides any default. ! 318: */ ! 319: ! 320: public edit(filename) ! 321: String filename; ! 322: { ! 323: extern String getenv(); ! 324: String ed, src, s; ! 325: Symbol f; ! 326: Address addr; ! 327: char lineno[10]; ! 328: ! 329: ed = getenv("EDITOR"); ! 330: if (ed == nil) { ! 331: ed = DEF_EDITOR; ! 332: } ! 333: src = findsource((filename != nil) ? filename : cursource); ! 334: if (src == nil) { ! 335: f = which(identname(filename, true)); ! 336: if (not isblock(f)) { ! 337: error("can't read \"%s\"", filename); ! 338: } ! 339: addr = firstline(f); ! 340: if (addr == NOADDR) { ! 341: error("no source for \"%s\"", filename); ! 342: } ! 343: src = srcfilename(addr); ! 344: s = findsource(src); ! 345: if (s != nil) { ! 346: src = s; ! 347: } ! 348: sprintf(lineno, "+%d", srcline(addr)); ! 349: } else { ! 350: sprintf(lineno, "+1"); ! 351: } ! 352: if (streq(ed, "vi") or streq(ed, "ex")) { ! 353: call(ed, stdin, stdout, lineno, src, nil); ! 354: } else { ! 355: call(ed, stdin, stdout, src, nil); ! 356: } ! 357: } ! 358: ! 359: /* ! 360: * Strip away portions of a given pattern not part of the regular expression. ! 361: */ ! 362: ! 363: private String getpattern (pattern) ! 364: String pattern; ! 365: { ! 366: register char *p, *r; ! 367: ! 368: p = pattern; ! 369: while (*p == ' ' or *p == '\t') { ! 370: ++p; ! 371: } ! 372: r = p; ! 373: while (*p != '\0') { ! 374: ++p; ! 375: } ! 376: --p; ! 377: if (*p == '\n') { ! 378: *p = '\0'; ! 379: --p; ! 380: } ! 381: if (*p == *r) { ! 382: *p = '\0'; ! 383: --p; ! 384: } ! 385: return r + 1; ! 386: } ! 387: ! 388: /* ! 389: * Search the current file for a regular expression. ! 390: */ ! 391: ! 392: public search (direction, pattern) ! 393: char direction; ! 394: String pattern; ! 395: { ! 396: register String p; ! 397: register File f; ! 398: String re, err; ! 399: Lineno line; ! 400: boolean matched; ! 401: char buf[512]; ! 402: ! 403: if (cursource == nil) { ! 404: beginerrmsg(); ! 405: fprintf(stderr, "no source file\n"); ! 406: } else { ! 407: if (cursource != prevsource) { ! 408: skimsource(); ! 409: } ! 410: if (lastlinenum == 0) { ! 411: beginerrmsg(); ! 412: fprintf(stderr, "couldn't read \"%s\"\n", cursource); ! 413: } else { ! 414: re = getpattern(pattern); ! 415: /* circf = 0; */ ! 416: if (re != nil and *re != '\0') { ! 417: err = re_comp(re); ! 418: if (err != nil) { ! 419: error(err); ! 420: } ! 421: } ! 422: matched = false; ! 423: f = srcfp; ! 424: line = cursrcline; ! 425: do { ! 426: if (direction == '/') { ! 427: ++line; ! 428: if (line > lastlinenum) { ! 429: line = 1; ! 430: } ! 431: } else { ! 432: --line; ! 433: if (line < 1) { ! 434: line = lastlinenum; ! 435: } ! 436: } ! 437: fseek(f, srcaddr(line), L_SET); ! 438: p = buf; ! 439: *p = getc(f); ! 440: while ((*p != '\n') and (*p != EOF)) { ! 441: ++p; ! 442: *p = getc(f); ! 443: } ! 444: *p = '\0'; ! 445: matched = (boolean) re_exec(buf); ! 446: } while (not matched and line != cursrcline); ! 447: if (not matched) { ! 448: beginerrmsg(); ! 449: fprintf(stderr, "no match\n"); ! 450: } else { ! 451: printlines(line, line); ! 452: cursrcline = line; ! 453: } ! 454: } ! 455: } ! 456: } ! 457: ! 458: public integer srcwindowlen () ! 459: { ! 460: Node s; ! 461: ! 462: s = findvar(identname("$listwindow", true)); ! 463: if (s == nil) ! 464: return 10; ! 465: eval(s); ! 466: return pop(integer); ! 467: } ! 468: ! 469: /* ! 470: * Compute a small window around the given line. ! 471: */ ! 472: ! 473: public getsrcwindow (line, l1, l2) ! 474: Lineno line, *l1, *l2; ! 475: { ! 476: integer size; ! 477: ! 478: size = srcwindowlen(); ! 479: *l1 = line - (size div 2); ! 480: if (*l1 < 1) { ! 481: *l1 = 1; ! 482: } ! 483: *l2 = *l1 + size; ! 484: if (lastlinenum != LASTLINE and *l2 > lastlinenum) { ! 485: *l2 = lastlinenum; ! 486: } ! 487: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.