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

📄 ed.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright 1987 Brian Beattie Rights Reserved. * * Permission to copy and/or distribute granted under the * following conditions: * * 1). No charge may be made other than resonable charges *	for reproduction. * * 2). This notice must remain intact. * * 3). No further restrictions may be added. * *//*	This program used to be in many little pieces, with this makefile:.SUFFIXES:	.c .sCFLAGS = -FOBJS =	append.s catsub.s ckglob.s deflt.s del.s docmd.s doglob.s\  doprnt.s doread.s dowrite.s ed.s egets.s find.s getfn.s getlst.s\  getnum.s getone.s getptr.s getrhs.s gettxt.s ins.s join.s maksub.s\  move.s optpat.s set.s setbuf.s subst.s getpat.s matchs.s amatch.s\  unmkpat.s omatch.s makepat.s bitmap.s dodash.s esc.s System.sed:	$(OBJS)  cc -T. -i -o ed $(OBJS)*/#include <sys/types.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/wait.h>#include <stdio.h>/****************************//*	tools.h	*//* *	#defines for non-printing ASCII characters */#define NUL	0x00		/* ^@ */#define EOS	0x00		/* end of string */#define SOH	0x01		/* ^A */#define STX	0x02		/* ^B */#define ETX	0x03		/* ^C */#define EOT	0x04		/* ^D */#define ENQ	0x05		/* ^E */#define ACK	0x06		/* ^F */#define BEL	0x07		/* ^G */#define BS	0x08		/* ^H */#define HT	0x09		/* ^I */#define LF	0x0a		/* ^J */#define NL	'\n'#define VT	0x0b		/* ^K */#define FF	0x0c		/* ^L */#define CR	0x0d		/* ^M */#define SO	0x0e		/* ^N */#define SI	0x0f		/* ^O */#define DLE	0x10		/* ^P */#define DC1	0x11		/* ^Q */#define DC2	0x12		/* ^R */#define DC3	0x13		/* ^S */#define DC4	0x14		/* ^T */#define NAK	0x15		/* ^U */#define SYN	0x16		/* ^V */#define ETB	0x17		/* ^W */#define CAN	0x18		/* ^X */#define EM	0x19		/* ^Y */#define SUB	0x1a		/* ^Z */#define ESC	0x1b		/* ^[ */#define FS	0x1c		/* ^\ */#define GS	0x1d		/* ^] */#define RS	0x1e		/* ^^ */#define US	0x1f		/* ^_ */#define SP	0x20		/* space */#define DEL	0x7f		/* DEL */#define TRUE	1#define FALSE	0#define ERR	-2/*	Definitions of meta-characters used in pattern matching *	routines.  LITCHAR & NCCL are only used as token identifiers; *	all the others are also both token identifier and actual symbol *	used in the regular expression. */#define BOL	'^'#define EOL	'$'#define ANY	'.'#define LITCHAR	'L'#define	ESCAPE	'\\'#define CCL	'['		/* Character class: [...] */#define CCLEND	']'#define NEGATE	'~'#define NCCL	'!'		/* Negative character class [^...] */#define CLOSURE	'*'#define OR_SYM	'|'#define DITTO	'&'#define OPEN	'('#define CLOSE	')'/* Largest permitted size for an expanded character class.  (i.e. the class * [a-z] will expand into 26 symbols; [a-z0-9] will expand into 36.) */#define CLS_SIZE	128/* *	Tokens are used to hold pattern templates. (see makepat()) */typedef char BITMAP;typedef struct token {  char tok;  char lchar;  BITMAP *bitmap;  struct token *next;} TOKEN;#define TOKSIZE sizeof (TOKEN)/* *	An absolute maximun for strings. */#define MAXSTR	132		/* Maximum numbers of characters in a line *//* Macros */#define max(a,b)	((a>b)?a:b)#define min(a,b)	((a<b)?a:b)#define toupper(c)	(c>='a'&&c<='z'?c-32:c)/*	ed.h	*/#define FATAL	(ERR-1)struct line {  int l_stat;			/* empty, mark */  struct line *l_prev;  struct line *l_next;  char l_buff[1];};typedef struct line LINE;#define LINFREE	1		/* entry not in use */#define LGLOB	2		/* line marked global */				/* max number of chars per line */#define MAXLINE	(sizeof(int) == 2 ? 256 : 8192)#define MAXPAT	256		/* max number of chars per replacement				 * pattern */				/* max file name size */#define MAXFNAME (sizeof(int) == 2 ? 256 : 1024)extern LINE line0;extern int curln, lastln, line1, line2, nlines;extern int nflg;		/* print line number flag */extern int lflg;		/* print line in verbose mode */extern char *inptr;		/* tty input buffer */extern char linbuf[], *linptr;	/* current line */extern int truncflg;		/* truncate long line flag */extern int eightbit;		/* save eighth bit */extern int nonascii;		/* count of non-ascii chars read */extern int nullchar;		/* count of null chars read */extern int truncated;		/* count of lines truncated */extern int fchanged;		/* file changed */#define nextln(l)	((l)+1 > lastln ? 0 : (l)+1)#define prevln(l)	((l)-1 < 0 ? lastln : (l)-1)/*	amatch.c	*//* #include <stdio.h> *//* #include "tools.h" */_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(static char *match, (char *lin, TOKEN *pat, char *boln));_PROTOTYPE(char *amatch, (char *lin, TOKEN *pat, char *boln));_PROTOTYPE(int append, (int line, int glob));_PROTOTYPE(BITMAP *makebitmap, (unsigned size));_PROTOTYPE(int setbit, (unsigned c, char *map, unsigned val));_PROTOTYPE(int testbit, (unsigned c, char *map));_PROTOTYPE(char *catsub, (char *from, char *to, char *sub, char *new, char *newend));_PROTOTYPE(int ckglob, (void));_PROTOTYPE(int deflt, (int def1, int def2));_PROTOTYPE(int del, (int from, int to));_PROTOTYPE(int docmd, (int glob));_PROTOTYPE(int dolst, (int line1, int line2));_PROTOTYPE(char *dodash, (int delim, char *src, char *map));_PROTOTYPE(int doglob, (void));_PROTOTYPE(int doprnt, (int from, int to));_PROTOTYPE(void prntln, (char *str, int vflg, int lin));_PROTOTYPE(void putcntl, (int c, FILE *stream));_PROTOTYPE(int doread, (int lin, char *fname));_PROTOTYPE(int dowrite, (int from, int to, char *fname, int apflg));_PROTOTYPE(void intr, (int sig));_PROTOTYPE(int egets, (char *str, int size, FILE *stream));_PROTOTYPE(int esc, (char **s));_PROTOTYPE(int find, (TOKEN *pat, int dir));_PROTOTYPE(char *getfn, (void));_PROTOTYPE(int getlst, (void));_PROTOTYPE(int getnum, (int first));_PROTOTYPE(int getone, (void));_PROTOTYPE(TOKEN *getpat, (char *arg));_PROTOTYPE(LINE *getptr, (int num));_PROTOTYPE(int getrhs, (char *sub));_PROTOTYPE(char *gettxt, (int num));_PROTOTYPE(int ins, (char *str));_PROTOTYPE(int System, (char *c));_PROTOTYPE(int join, (int first, int last));_PROTOTYPE(TOKEN *makepat, (char *arg, int delim));_PROTOTYPE(char *maksub, (char *sub, int subsz));_PROTOTYPE(char *matchs, (char *line, TOKEN *pat, int ret_endp));_PROTOTYPE(int move, (int num));_PROTOTYPE(int transfer, (int num));_PROTOTYPE(int omatch, (char **linp, TOKEN *pat, char *boln));_PROTOTYPE(TOKEN *optpat, (void));_PROTOTYPE(int set, (void));_PROTOTYPE(int show, (void));_PROTOTYPE(void relink, (LINE *a, LINE *x, LINE *y, LINE *b));_PROTOTYPE(void clrbuf, (void));_PROTOTYPE(void set_buf, (void));_PROTOTYPE(int subst, (TOKEN *pat, char *sub, int gflg, int pflag));_PROTOTYPE(void unmakepat, (TOKEN *head));/*     Scans throught the pattern template looking for a match * with lin.  Each element of lin is compared with the template * until either a mis-match is found or the end of the template * is reached.  In the former case a 0 is returned; in the latter, * a pointer into lin (pointing to the character following the * matched pattern) is returned. * *	"lin"	is a pointer to the line being searched. *	"pat"	is a pointer to a template made by makepat(). *	"boln"	is a pointer into "lin" which points at the *			character at the beginning of the line. */char *paropen[9], *parclose[9];int between, parnum;char *amatch(lin, pat, boln)char *lin;TOKEN *pat;char *boln;{  between = 0;  parnum = 0;  lin = match(lin, pat, boln);  if (between) return 0;  while (parnum < 9) {	paropen[parnum] = parclose[parnum] = "";	parnum++;  }  return lin;}static char *match(lin, pat, boln)char *lin;TOKEN *pat;char *boln;{  register char *bocl, *rval, *strstart;  if (pat == 0) return 0;  strstart = lin;  while (pat) {	if (pat->tok == CLOSURE && pat->next) {		/* Process a closure: first skip over the closure		 * token to the object to be repeated.  This object		 * can be a character class. */		pat = pat->next;		/* Now match as many occurrences of the closure		 * pattern as possible. */		bocl = lin;		while (*lin && omatch(&lin, pat, boln));		/* 'Lin' now points to the character that made made		 * us fail.  Now go on to process the rest of the		 * string.  A problem here is a character following		 * the closure which could have been in the closure.		 * For example, in the pattern "[a-z]*t" (which		 * matches any lower-case word ending in a t), the		 * final 't' will be sucked up in the while loop.		 * So, if the match fails, we back up a notch and try		 * to match the rest of the string again, repeating		 * this process recursively until we get back to the		 * beginning of the closure.  The recursion goes, at		 * most two levels deep. */		if (pat = pat->next) {			int savbtwn = between;			int savprnm = parnum;			while (bocl <= lin) {				if (rval = match(lin, pat, boln)) {					/* Success */					return(rval);				} else {					--lin;					between = savbtwn;					parnum = savprnm;				}			}			return(0);	/* match failed */		}	} else if (pat->tok == OPEN) {		if (between || parnum >= 9) return 0;		paropen[parnum] = lin;		between = 1;		pat = pat->next;	} else if (pat->tok == CLOSE) {		if (!between) return 0;		parclose[parnum++] = lin;		between = 0;		pat = pat->next;	} else if (omatch(&lin, pat, boln)) {		pat = pat->next;	} else {		return(0);	}  }  /* Note that omatch() advances lin to point at the next character to   * be matched.  Consequently, when we reach the end of the template,   * lin will be pointing at the character following the last character   * matched.  The exceptions are templates containing only a BOLN or   * EOLN token.  In these cases omatch doesn't advance.   *    * A philosophical point should be mentioned here.  Is $ a position or a   * character? (i.e. does $ mean the EOL character itself or does it   * mean the character at the end of the line.)  I decided here to   * make it mean the former, in order to make the behavior of match()   * consistent.  If you give match the pattern ^$ (match all lines   * consisting only of an end of line) then, since something has to be   * returned, a pointer to the end of line character itself is   * returned. */  return((char *) max(strstart, lin));}/*	append.c	*//* #include <stdio.h> *//* #include "tools.h" *//* #include "ed.h" */int append(line, glob)int line, glob;{  int stat;  char lin[MAXLINE];  if (glob) return(ERR);  curln = line;  while (1) {	if (nflg) printf("%6d. ", curln + 1);	if (fgets(lin, MAXLINE, stdin) == NULL) return(EOF);	if (lin[0] == '.' && lin[1] == '\n') return (0);	stat = ins(lin);	if (stat < 0) return(ERR);  }}/*	bitmap.c	*//* *	BITMAP.C -	makebitmap, setbit, testbit *			bit-map manipulation routines. * *	Copyright (c) Allen I. Holub, all rights reserved.  This program may *		for copied for personal, non-profit use only. * */#ifdef DEBUG/* #include <stdio.h> */#endif/* #include "tools.h" */BITMAP *makebitmap(size)unsigned size;{  /* Make a bit map with "size" bits.  The first entry in the map is an   * "unsigned int" representing the maximum bit.  The map itself is   * concatenated to this integer. Return a pointer to a map on   * success, 0 if there's not enough memory. */  unsigned *map, numbytes;  numbytes = (size >> 3) + ((size & 0x07) ? 1 : 0);#ifdef DEBUG  printf("Making a %d bit map (%d bytes required)\n", size, numbytes);#endif  if (map = (unsigned *) malloc(numbytes + sizeof(unsigned))) *map = size;  return((BITMAP *) map);}int setbit(c, map, val)unsigned c, val;char *map;{  /* Set bit c in the map to val. If c > map-size, 0 is returned, else   * 1 is returned. */  if (c >= *(unsigned *) map)	/* if c >= map size */	return 0;  map += sizeof(unsigned);	/* skip past size */  if (val)	map[c >> 3] |= 1 << (c & 0x07);  else	map[c >> 3] &= ~(1 << (c & 0x07));  return 1;}int testbit(c, map)unsigned c;char *map;{  /* Return 1 if the bit corresponding to c in map is set. 0 if it is not. */  if (c >= *(unsigned *) map) return 0;  map += sizeof(unsigned);  return(map[c >> 3] & (1 << (c & 0x07)));}/*	catsub.c	*//* #include <stdio.h> *//* #include "tools.h" *//* #include "ed.h" */extern char *paropen[9], *parclose[9];char *catsub(from, to, sub, new, newend)char *from, *to, *sub, *new, *newend;{  char *cp, *cp2;  for (cp = new; *sub != EOS && cp < newend;) {	if (*sub == DITTO) for (cp2 = from; cp2 < to;) {			*cp++ = *cp2++;			if (cp >= newend) break;		}	else if (*sub == ESCAPE) {		sub++;		if ('1' <= *sub && *sub <= '9') {			char *parcl = parclose[*sub - '1'];			for (cp2 = paropen[*sub - '1']; cp2 < parcl;) {				*cp++ = *cp2++;				if (cp >= newend) break;			}		} else			*cp++ = *sub;	} else		*cp++ = *sub;	sub++;  }  return(cp);}/*	ckglob.c	*//* #include <stdio.h> *//* #include "tools.h" *//* #include "ed.h" */int ckglob(){  TOKEN *glbpat;  char c, delim;  char lin[MAXLINE];  int num;  LINE *ptr;  c = *inptr;  if (c != 'g' && c != 'v') return(0);  if (deflt(1, lastln) < 0) return(ERR);  delim = *++inptr;  if (delim <= ' ') return(ERR);  glbpat = optpat();  if (*inptr == delim) inptr++;  ptr = getptr(1);  for (num = 1; num <= lastln; num++) {	ptr->l_stat &= ~LGLOB;	if (line1 <= num && num <= line2) {		strcpy(lin, ptr->l_buff);		strcat(lin, "\n");		if (matchs(lin, glbpat, 0)) {			if (c == 'g') ptr->l_stat |= LGLOB;		} else {			if (c == 'v') ptr->l_stat |= LGLOB;		}	}	ptr = ptr->l_next;  }  return(1);}/*	deflt.c	*//* #include <stdio.h> *//* #include "tools.h" *//* #include "ed.h" */int deflt(def1, def2)int def1, def2;{  if (nlines == 0) {	line1 = def1;	line2 = def2;  }  if (line1 > line2 || line1 <= 0) return(ERR);  return(0);}/*	del.c	*//* #include <stdio.h> *//* #include "tools.h" *//* #include "ed.h" */int del(from, to)int from, to;{  LINE *first, *last, *next, *tmp;  if (from < 1) from = 1;  first = getptr(prevln(from));  last = getptr(nextln(to));  next = first->l_next;  while (next != last && next != &line0) {	tmp = next->l_next;	free((char *) next);	next = tmp;  }  relink(first, last, first, last);  lastln -= (to - from) + 1;  curln = prevln(from);  return(0);}/*	docmd.c	*//* #include <stdio.h> *//* #include "tools.h" *//* #include "ed.h" */char fname[MAXFNAME];int fchanged;extern int nofname;extern int mark[];int docmd(glob)int glob;{  static char rhs[MAXPAT];  TOKEN *subpat;  int c, err, line3;  int apflg, pflag, gflag;  int nchng;  char *fptr;  pflag = FALSE;  while (*inptr == SP && *inptr == HT) inptr++;  c = *inptr++;  switch (c) {      case NL:	if (nlines == 0) {		if ((line2 = nextln(curln)) == 0) return(ERR);	}	curln = line2;	return(1);	break;      case '=':	printf("%d\n", line2);	break;      case 'a':	if (*inptr != NL || nlines > 1) return(ERR);	if (append(line1, glob) < 0) return(ERR);;	fchanged = TRUE;	break;      case 'c':	if (*inptr != NL) return(ERR);	if (deflt(curln, curln) < 0) return(ERR);	if (del(line1, line2) < 0) return(ERR);	if (append(curln, glob) < 0) return (ERR);	fchanged = TRUE;	break;      case 'd':	if (*inptr != NL) return(ERR);	if (deflt(curln, curln) < 0) return(ERR);	if (del(line1, line2) < 0) return(ERR);	if (nextln(curln) != 0) curln = nextln(curln);	fchanged = TRUE;	break;      case 'e':	if (nlines > 0) return(ERR);	if (fchanged) {		fchanged = FALSE;		return(ERR);	}	/* FALL THROUGH */      case 'E':	if (nlines > 0) return(ERR);	if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);	if ((fptr = getfn()) == NULL) return(ERR);	clrbuf();	if ((err = doread(0, fptr)) < 0) return(err);	strcpy(fname, fptr);	fchanged = FALSE;	break;      case 'f':	if (nlines > 0) return(ERR);	if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);	if ((fptr = getfn()) == NULL) return(ERR);	if (nofname)		printf("%s\n", fname);	else		strcpy(fname, fptr);	break;      case 'i':	if (*inptr != NL || nlines > 1) return(ERR);	if (append(prevln(line1), glob) < 0) return(ERR);	fchanged = TRUE;	break;      case 'j':	if (*inptr != NL || deflt(curln, curln + 1) < 0) return(ERR);	if (join(line1, line2) < 0) return(ERR);	break;      case 'k':	while (*inptr == ' ' || *inptr == HT) inptr++;	if (*inptr < 'a' || *inptr > 'z') return ERR;	c = *inptr++;	if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);	mark[c - 'a'] = line1;	break;      case 'l':	if (*inptr != NL) return(ERR);	if (deflt(curln, curln) < 0) return (ERR);	if (dolst(line1, line2) < 0) return (ERR);	break;      case 'm':	if ((line3 = getone()) < 0) return(ERR);	if (deflt(curln, curln) < 0) return (ERR);	if (move(line3) < 0) return (ERR);	fchanged = TRUE;	break;      case 'P':      case 'p':	if (*inptr != NL) return(ERR);	if (deflt(curln, curln) < 0) return (ERR);	if (doprnt(line1, line2) < 0) return (ERR);	break;      case 'q':	if (fchanged) {		fchanged = FALSE;		return(ERR);	}	/* FALL THROUGH */      case 'Q':	if (*inptr == NL && nlines == 0 && !glob)		return(EOF);	else		return(ERR);      case 'r':	if (nlines > 1) return(ERR);

⌨️ 快捷键说明

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