⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 source.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)source.c	5.4 (Berkeley) 6/1/90";#endif /* not lint *//* * Source file management. */#include "defs.h"#include "source.h"#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 publictypedef int Lineno;String cursource;Lineno curline;Lineno cursrcline;#define LASTLINE 0		/* recognized by printlines */#include "lists.h"List sourcepath;#endif#ifdef IRIS#   define re_comp regcmp#   define re_exec(buf) (regex(buf) != NULL)#endifextern char *re_comp();private Lineno lastlinenum;private String prevsource = nil;/* * Data structure for indexing source seek addresses by line number. * * The constraints are: * *  we want an array so indexing is fast and easy *  we don't want to waste space for small files *  we don't want an upper bound on # of lines in a file *  we don't know how many lines there are * * The solution is a "dirty" hash table.  We have NSLOTS pointers to * arrays of NLINESPERSLOT addresses.  To find the source address of * a particular line we find the slot, allocate space if necessary, * and then find its location within the pointed to array. */typedef long Seekaddr;#define NSLOTS 40#define NLINESPERSLOT 500#define slotno(line)    ((line) div NLINESPERSLOT)#define index(line)	((line) mod NLINESPERSLOT)#define slot_alloc()    newarr(Seekaddr, NLINESPERSLOT)#define srcaddr(line)	seektab[slotno(line)][index(line)]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. */public printlines(l1, l2)Lineno l1, l2;{    register int c;    register Lineno i, lb, ub;    register File f;    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 {	    lb = (l1 == LASTLINE) ? lastlinenum : l1;	    ub = (l2 == LASTLINE) ? lastlinenum : l2;	    if (lb < 1) {		beginerrmsg();		fprintf(stderr, "line number must be positive\n");	    } else if (lb > lastlinenum) {		beginerrmsg();		if (lastlinenum == 1) {		    fprintf(stderr, "\"%s\" has only 1 line\n", cursource);		} else {		    fprintf(stderr, "\"%s\" has only %d lines\n",			cursource, lastlinenum);		}	    } else if (ub < lb) {		beginerrmsg();		fprintf(stderr, "second number must be greater than first\n");	    } else {		if (ub > lastlinenum) {		    ub = lastlinenum;		}		f = srcfp;		fseek(f, srcaddr(lb), 0);		for (i = lb; i <= ub; i++) {		    printf("%5d   ", i);		    while ((c = getc(f)) != '\n') {			putchar(c);		    }		    putchar('\n');		}		cursrcline = ub + 1;	    }	}    }}/* * 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;{    String s;    File f;    s = findsource(filename);    if (s == nil) {	f = nil;    } else {	f = fopen(s, "r");    }    return f;}/* * Set the current source file. */public setsource(filename)String filename;{    if (filename != nil and filename != cursource) {	prevsource = cursource;	cursource = filename;	cursrcline = 1;    }}/* * Read the source file getting seek pointers for each line. */private skimsource(){    register int c;    register Seekaddr count;    register File f;    register Lineno linenum;    register Seekaddr lastaddr;    register int slot;    f = opensource(cursource);    if (f == nil) {	lastlinenum = 0;    } else {	if (prevsource != nil) {	    free_seektab();	    if (srcfp != nil) {		fclose(srcfp);	    }	}	prevsource = cursource;	linenum = 0;	count = 0;	lastaddr = 0;	while ((c = getc(f)) != EOF) {	    ++count;	    if (c == '\n') {		slot = slotno(++linenum);		if (slot >= NSLOTS) {		    panic("skimsource: too many lines");		}		if (seektab[slot] == nil) {		    seektab[slot] = slot_alloc();		}		seektab[slot][index(linenum)] = lastaddr;		lastaddr = count;	    }	}	lastlinenum = linenum;	srcfp = f;    }}/* * Erase information and release space in the current seektab. * This is in preparation for reading in seek pointers for a * new file.  It is possible that seek pointers for all files * should be kept around, but the current concern is space. */private free_seektab(){    register int slot;    for (slot = 0; slot < NSLOTS; slot++) {	if (seektab[slot] != nil) {	    dispose(seektab[slot]);	}    }}/* * Figure out current source position. */public getsrcpos(){    String filename;    curline = srcline(pc);    filename = srcfilename(pc);    setsource(filename);    if (curline != 0) {	cursrcline = curline;    }}/* * Print out the current source position. */public printsrcpos(){    printf("at line %d", curline);    if (nlhdr.nfiles > 1) {	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;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -