-/* Copyright (c) 1982 Regents of the University of California */
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
-static char sccsid[] = "@(#)source.c 1.4 %G%";
+#ifndef lint
+static char sccsid[] = "@(#)source.c 5.2 (Berkeley) %G%";
+#endif not lint
+
+static char rcsid[] = "$Header: source.c,v 1.3 87/08/19 15:19:40 mike Exp $";
/*
* Source file management.
#include "object.h"
#include "mappings.h"
#include "machine.h"
+#include "keywords.h"
+#include "tree.h"
+#include "eval.h"
+#ifdef IRIS
+# define R_OK 04 /* read access */
+# define L_SET 01 /* absolute offset for seek */
+#else
+# include <sys/file.h>
+#endif
#ifndef public
typedef int Lineno;
List sourcepath;
#endif
+#ifdef IRIS
+# define re_comp regcmp
+# define re_exec(buf) (regex(buf) != NULL)
+#endif
+
+extern char *re_comp();
+
private Lineno lastlinenum;
private String prevsource = nil;
typedef long Seekaddr;
-#define NSLOTS 20
+#define NSLOTS 40
#define NLINESPERSLOT 500
#define slotno(line) ((line) div NLINESPERSLOT)
private File srcfp;
private Seekaddr *seektab[NSLOTS];
+/*
+ * Determine if the current source file is available.
+ */
+
+public boolean canReadSource ()
+{
+ boolean b;
+
+ if (cursource == nil) {
+ b = false;
+ } else if (cursource != prevsource) {
+ skimsource();
+ b = (boolean) (lastlinenum != 0);
+ } else {
+ b = true;
+ }
+ return b;
+}
+
/*
* Print out the given lines from the source.
*/
beginerrmsg();
fprintf(stderr, "couldn't read \"%s\"\n", cursource);
} else {
- lb = (l1 == 0) ? lastlinenum : l1;
- ub = (l2 == 0) ? lastlinenum : l2;
+ lb = (l1 == LASTLINE) ? lastlinenum : l1;
+ ub = (l2 == LASTLINE) ? lastlinenum : l2;
if (lb < 1) {
beginerrmsg();
fprintf(stderr, "line number must be positive\n");
}
}
+/*
+ * Search the sourcepath for a file.
+ */
+
+static char fileNameBuf[1024];
+
+public String findsource(filename)
+String filename;
+{
+ register String src, dir;
+
+ if (filename[0] == '/') {
+ src = filename;
+ } else {
+ src = nil;
+ foreach (String, dir, sourcepath)
+ sprintf(fileNameBuf, "%s/%s", dir, filename);
+ if (access(fileNameBuf, R_OK) == 0) {
+ src = fileNameBuf;
+ break;
+ }
+ endfor
+ }
+ return src;
+}
+
/*
* Open a source file looking in the appropriate places.
*/
public File opensource(filename)
String filename;
{
- register String dir;
- char buf[256];
+ String s;
File f;
- f = nil;
- foreach (String, dir, sourcepath)
- sprintf(buf, "%s/%s", dir, filename);
- f = fopen(buf, "r");
- if (f != nil) {
- break;
- }
- endfor
+ s = findsource(filename);
+ if (s == nil) {
+ f = nil;
+ } else {
+ f = fopen(s, "r");
+ }
return f;
}
/*
* Figure out current source position.
- * Have to use "pc - 1" because pc is the address of the next instruction
- * rather than the current one.
*/
public getsrcpos()
{
String filename;
- curline = srcline(pc - 1);
- filename = srcfilename(pc - 1);
+ curline = srcline(pc);
+ filename = srcfilename(pc);
setsource(filename);
- cursrcline = curline;
+ if (curline != 0) {
+ cursrcline = curline;
+ }
}
/*
printf(" in file \"%s\"", cursource);
}
}
+
+#define DEF_EDITOR "vi"
+
+/*
+ * Invoke an editor on the given file. Which editor to use might change
+ * installation to installation. For now, we use "vi". In any event,
+ * the environment variable "EDITOR" overrides any default.
+ */
+
+public edit(filename)
+String filename;
+{
+ extern String getenv();
+ String ed, src, s;
+ Symbol f;
+ Address addr;
+ char lineno[10];
+
+ ed = getenv("EDITOR");
+ if (ed == nil) {
+ ed = DEF_EDITOR;
+ }
+ src = findsource((filename != nil) ? filename : cursource);
+ if (src == nil) {
+ f = which(identname(filename, true));
+ if (not isblock(f)) {
+ error("can't read \"%s\"", filename);
+ }
+ addr = firstline(f);
+ if (addr == NOADDR) {
+ error("no source for \"%s\"", filename);
+ }
+ src = srcfilename(addr);
+ s = findsource(src);
+ if (s != nil) {
+ src = s;
+ }
+ sprintf(lineno, "+%d", srcline(addr));
+ } else {
+ sprintf(lineno, "+1");
+ }
+ if (streq(ed, "vi") or streq(ed, "ex")) {
+ call(ed, stdin, stdout, lineno, src, nil);
+ } else {
+ call(ed, stdin, stdout, src, nil);
+ }
+}
+
+/*
+ * Strip away portions of a given pattern not part of the regular expression.
+ */
+
+private String getpattern (pattern)
+String pattern;
+{
+ register char *p, *r;
+
+ p = pattern;
+ while (*p == ' ' or *p == '\t') {
+ ++p;
+ }
+ r = p;
+ while (*p != '\0') {
+ ++p;
+ }
+ --p;
+ if (*p == '\n') {
+ *p = '\0';
+ --p;
+ }
+ if (*p == *r) {
+ *p = '\0';
+ --p;
+ }
+ return r + 1;
+}
+
+/*
+ * Search the current file for a regular expression.
+ */
+
+public search (direction, pattern)
+char direction;
+String pattern;
+{
+ register String p;
+ register File f;
+ String re, err;
+ Lineno line;
+ boolean matched;
+ char buf[512];
+
+ if (cursource == nil) {
+ beginerrmsg();
+ fprintf(stderr, "no source file\n");
+ } else {
+ if (cursource != prevsource) {
+ skimsource();
+ }
+ if (lastlinenum == 0) {
+ beginerrmsg();
+ fprintf(stderr, "couldn't read \"%s\"\n", cursource);
+ } else {
+ re = getpattern(pattern);
+ /* circf = 0; */
+ if (re != nil and *re != '\0') {
+ err = re_comp(re);
+ if (err != nil) {
+ error(err);
+ }
+ }
+ matched = false;
+ f = srcfp;
+ line = cursrcline;
+ do {
+ if (direction == '/') {
+ ++line;
+ if (line > lastlinenum) {
+ line = 1;
+ }
+ } else {
+ --line;
+ if (line < 1) {
+ line = lastlinenum;
+ }
+ }
+ fseek(f, srcaddr(line), L_SET);
+ p = buf;
+ *p = getc(f);
+ while ((*p != '\n') and (*p != EOF)) {
+ ++p;
+ *p = getc(f);
+ }
+ *p = '\0';
+ matched = (boolean) re_exec(buf);
+ } while (not matched and line != cursrcline);
+ if (not matched) {
+ beginerrmsg();
+ fprintf(stderr, "no match\n");
+ } else {
+ printlines(line, line);
+ cursrcline = line;
+ }
+ }
+ }
+}
+
+public integer srcwindowlen ()
+{
+ Node s;
+
+ s = findvar(identname("$listwindow", true));
+ if (s == nil)
+ return 10;
+ eval(s);
+ return pop(integer);
+}
+
+/*
+ * Compute a small window around the given line.
+ */
+
+public getsrcwindow (line, l1, l2)
+Lineno line, *l1, *l2;
+{
+ integer size;
+
+ size = srcwindowlen();
+ *l1 = line - (size div 2);
+ if (*l1 < 1) {
+ *l1 = 1;
+ }
+ *l2 = *l1 + size;
+ if (lastlinenum != LASTLINE and *l2 > lastlinenum) {
+ *l2 = lastlinenum;
+ }
+}