早期freebsd实现

源代码在线查看: source.c

软件大小: 40554 K
上传用户: luyibo54618
关键词: freebsd
下载地址: 免注册下载 普通下载 VIP

相关代码

				/*				 * 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 lint				static 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 				#endif								#ifndef public				typedef 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)				#endif								extern 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 						    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;				    }				}							

相关资源