|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <plumb.h> | 
|  | #include "errors.h" | 
|  |  | 
|  | #undef waitfor | 
|  | #define waitfor samwaitfor | 
|  |  | 
|  | #undef warn | 
|  | #define warn samwarn | 
|  |  | 
|  | /* | 
|  | * BLOCKSIZE is relatively small to keep memory consumption down. | 
|  | */ | 
|  |  | 
|  | #define	BLOCKSIZE	2048 | 
|  | #define	RUNESIZE	sizeof(Rune) | 
|  | #define	NDISC		5 | 
|  | #define	NBUFFILES	3+2*NDISC	/* plan 9+undo+snarf+NDISC*(transcript+buf) */ | 
|  | #define NSUBEXP	10 | 
|  |  | 
|  | #define	TRUE		1 | 
|  | #define	FALSE		0 | 
|  |  | 
|  | #undef INFINITY	/* Darwin declares this as HUGE_VAL */ | 
|  | #define	INFINITY	0x7FFFFFFFL | 
|  | #define	INCR		25 | 
|  | #define	STRSIZE		(2*BLOCKSIZE) | 
|  |  | 
|  | typedef long		Posn;		/* file position or address */ | 
|  | typedef	ushort		Mod;		/* modification number */ | 
|  |  | 
|  | typedef struct Address	Address; | 
|  | typedef struct Block	Block; | 
|  | typedef struct Buffer	Buffer; | 
|  | typedef struct Disk	Disk; | 
|  | typedef struct Discdesc	Discdesc; | 
|  | typedef struct File	File; | 
|  | typedef struct List	List; | 
|  | typedef struct Range	Range; | 
|  | typedef struct Rangeset	Rangeset; | 
|  | typedef struct String	String; | 
|  |  | 
|  | enum State | 
|  | { | 
|  | Clean =		' ', | 
|  | Dirty =		'\'', | 
|  | Unread =	'-' | 
|  | }; | 
|  |  | 
|  | struct Range | 
|  | { | 
|  | Posn	p1, p2; | 
|  | }; | 
|  |  | 
|  | struct Rangeset | 
|  | { | 
|  | Range	p[NSUBEXP]; | 
|  | }; | 
|  |  | 
|  | struct Address | 
|  | { | 
|  | Range	r; | 
|  | File	*f; | 
|  | }; | 
|  |  | 
|  | struct String | 
|  | { | 
|  | short	n; | 
|  | short	size; | 
|  | Rune	*s; | 
|  | }; | 
|  |  | 
|  | struct List	/* code depends on a long being able to hold a pointer */ | 
|  | { | 
|  | int	type;	/* 'p' for pointer, 'P' for Posn */ | 
|  | int	nalloc; | 
|  | int	nused; | 
|  | union{ | 
|  | void*	listp; | 
|  | void**	voidp; | 
|  | Posn*	posnp; | 
|  | String**stringp; | 
|  | File**	filep; | 
|  | }g; | 
|  | }; | 
|  |  | 
|  | #define	listptr		g.listp | 
|  | #define	voidpptr	g.voidp | 
|  | #define	posnptr		g.posnp | 
|  | #define	stringpptr	g.stringp | 
|  | #define	filepptr	g.filep | 
|  |  | 
|  | enum | 
|  | { | 
|  | Blockincr =	256, | 
|  | Maxblock = 	8*1024, | 
|  |  | 
|  | BUFSIZE = Maxblock,	/* size from fbufalloc() */ | 
|  | RBUFSIZE = BUFSIZE/sizeof(Rune) | 
|  | }; | 
|  |  | 
|  |  | 
|  | enum | 
|  | { | 
|  | Null		= '-', | 
|  | Delete		= 'd', | 
|  | Insert		= 'i', | 
|  | Filename	= 'f', | 
|  | Dot		= 'D', | 
|  | Mark		= 'm' | 
|  | }; | 
|  |  | 
|  | struct Block | 
|  | { | 
|  | uint		addr;	/* disk address in bytes */ | 
|  | union { | 
|  | uint	n;	/* number of used runes in block */ | 
|  | Block	*next;	/* pointer to next in free list */ | 
|  | } u; | 
|  | }; | 
|  |  | 
|  | struct Disk | 
|  | { | 
|  | int		fd; | 
|  | uint		addr;	/* length of temp file */ | 
|  | Block		*free[Maxblock/Blockincr+1]; | 
|  | }; | 
|  |  | 
|  | Disk*		diskinit(void); | 
|  | Block*		disknewblock(Disk*, uint); | 
|  | void		diskrelease(Disk*, Block*); | 
|  | void		diskread(Disk*, Block*, Rune*, uint); | 
|  | void		diskwrite(Disk*, Block**, Rune*, uint); | 
|  |  | 
|  | struct Buffer | 
|  | { | 
|  | uint		nc; | 
|  | Rune		*c;	/* cache */ | 
|  | uint		cnc;	/* bytes in cache */ | 
|  | uint		cmax;	/* size of allocated cache */ | 
|  | uint		cq;	/* position of cache */ | 
|  | int		cdirty;	/* cache needs to be written */ | 
|  | uint		cbi;	/* index of cache Block */ | 
|  | Block		**bl;	/* array of blocks */ | 
|  | uint		nbl;	/* number of blocks */ | 
|  | }; | 
|  | void		bufinsert(Buffer*, uint, Rune*, uint); | 
|  | void		bufdelete(Buffer*, uint, uint); | 
|  | uint		bufload(Buffer*, uint, int, int*); | 
|  | void		bufread(Buffer*, uint, Rune*, uint); | 
|  | void		bufclose(Buffer*); | 
|  | void		bufreset(Buffer*); | 
|  |  | 
|  | struct File | 
|  | { | 
|  | Buffer 	b;				/* the data */ | 
|  | Buffer		delta;		/* transcript of changes */ | 
|  | Buffer		epsilon;	/* inversion of delta for redo */ | 
|  | String		name;		/* name of associated file */ | 
|  | uvlong		qidpath;	/* of file when read */ | 
|  | uint		mtime;		/* of file when read */ | 
|  | ulong	dev;		/* of file when read */ | 
|  | int		unread;		/* file has not been read from disk */ | 
|  |  | 
|  | long		seq;		/* if seq==0, File acts like Buffer */ | 
|  | long		cleanseq;	/* f->seq at last read/write of file */ | 
|  | int		mod;		/* file appears modified in menu */ | 
|  | char		rescuing;	/* sam exiting; this file unusable */ | 
|  |  | 
|  | #if 0 | 
|  | //	Text		*curtext;	/* most recently used associated text */ | 
|  | //	Text		**text;		/* list of associated texts */ | 
|  | //	int		ntext; | 
|  | //	int		dumpid;		/* used in dumping zeroxed windows */ | 
|  | #endif | 
|  |  | 
|  | Posn		hiposn;		/* highest address touched this Mod */ | 
|  | Address		dot;		/* current position */ | 
|  | Address		ndot;		/* new current position after update */ | 
|  | Range		tdot;		/* what terminal thinks is current range */ | 
|  | Range		mark;		/* tagged spot in text (don't confuse with Mark) */ | 
|  | List		*rasp;		/* map of what terminal's got */ | 
|  | short		tag;		/* for communicating with terminal */ | 
|  | char		closeok;	/* ok to close file? */ | 
|  | char		deleted;	/* delete at completion of command */ | 
|  | Range		prevdot;	/* state before start of change */ | 
|  | Range		prevmark; | 
|  | long		prevseq; | 
|  | int		prevmod; | 
|  | }; | 
|  | /*File*		fileaddtext(File*, Text*); */ | 
|  | void		fileclose(File*); | 
|  | void		filedelete(File*, uint, uint); | 
|  | /*void		filedeltext(File*, Text*); */ | 
|  | void		fileinsert(File*, uint, Rune*, uint); | 
|  | uint		fileload(File*, uint, int, int*); | 
|  | void		filemark(File*); | 
|  | void		filereset(File*); | 
|  | void		filesetname(File*, String*); | 
|  | void		fileundelete(File*, Buffer*, uint, uint); | 
|  | void		fileuninsert(File*, Buffer*, uint, uint); | 
|  | void		fileunsetname(File*, Buffer*); | 
|  | void		fileundo(File*, int, int, uint*, uint*, int); | 
|  | int		fileupdate(File*, int, int); | 
|  |  | 
|  | int		filereadc(File*, uint); | 
|  | File		*fileopen(void); | 
|  | void		loginsert(File*, uint, Rune*, uint); | 
|  | void		logdelete(File*, uint, uint); | 
|  | void		logsetname(File*, String*); | 
|  | int		fileisdirty(File*); | 
|  | long		undoseq(File*, int); | 
|  | long		prevseq(Buffer*); | 
|  |  | 
|  | void		raspload(File*); | 
|  | void		raspstart(File*); | 
|  | void		raspdelete(File*, uint, uint, int); | 
|  | void		raspinsert(File*, uint, Rune*, uint, int); | 
|  | void		raspdone(File*, int); | 
|  | void		raspflush(File*); | 
|  |  | 
|  | /* | 
|  | * acme fns | 
|  | */ | 
|  | void*	fbufalloc(void); | 
|  | void	fbuffree(void*); | 
|  | uint	min(uint, uint); | 
|  | void	cvttorunes(char*, int, Rune*, int*, int*, int*); | 
|  |  | 
|  | #define	runemalloc(a)		(Rune*)emalloc((a)*sizeof(Rune)) | 
|  | #define	runerealloc(a, b)	(Rune*)realloc((a), (b)*sizeof(Rune)) | 
|  | #define	runemove(a, b, c)	memmove((a), (b), (c)*sizeof(Rune)) | 
|  |  | 
|  | int	alnum(int); | 
|  | int	Read(int, void*, int); | 
|  | void	Seek(int, long, int); | 
|  | int	plan9(File*, int, String*, int); | 
|  | int	Write(int, void*, int); | 
|  | int	bexecute(File*, Posn); | 
|  | void	cd(String*); | 
|  | void	closefiles(File*, String*); | 
|  | void	closeio(Posn); | 
|  | void	cmdloop(void); | 
|  | void	cmdupdate(void); | 
|  | void	compile(String*); | 
|  | void	copy(File*, Address); | 
|  | File	*current(File*); | 
|  | void	delete(File*); | 
|  | void	delfile(File*); | 
|  | void	dellist(List*, int); | 
|  | void	doubleclick(File*, Posn); | 
|  | void	dprint(char*, ...); | 
|  | void	edit(File*, int); | 
|  | void	*emalloc(ulong); | 
|  | void	*erealloc(void*, ulong); | 
|  | void	error(Err); | 
|  | void	error_c(Err, int); | 
|  | void	error_r(Err, char*); | 
|  | void	error_s(Err, char*); | 
|  | int	execute(File*, Posn, Posn); | 
|  | int	filematch(File*, String*); | 
|  | void	filename(File*); | 
|  | void	fixname(String*); | 
|  | void	fullname(String*); | 
|  | void	getcurwd(void); | 
|  | File	*getfile(String*); | 
|  | int	getname(File*, String*, int); | 
|  | long	getnum(int); | 
|  | void	hiccough(char*); | 
|  | void	inslist(List*, int, ...); | 
|  | Address	lineaddr(Posn, Address, int); | 
|  | List	*listalloc(int); | 
|  | void	listfree(List*); | 
|  | void	load(File*); | 
|  | File	*lookfile(String*); | 
|  | void	lookorigin(File*, Posn, Posn); | 
|  | int	lookup(int); | 
|  | void	move(File*, Address); | 
|  | void	moveto(File*, Range); | 
|  | File	*newfile(void); | 
|  | void	nextmatch(File*, String*, Posn, int); | 
|  | int	newtmp(int); | 
|  | void	notifyf(void*, char*); | 
|  | void	panic(char*); | 
|  | void	printposn(File*, int); | 
|  | void	print_ss(char*, String*, String*); | 
|  | void	print_s(char*, String*); | 
|  | int	rcv(void); | 
|  | Range	rdata(List*, Posn, Posn); | 
|  | Posn	readio(File*, int*, int, int); | 
|  | void	rescue(void); | 
|  | void	resetcmd(void); | 
|  | void	resetsys(void); | 
|  | void	resetxec(void); | 
|  | void	rgrow(List*, Posn, Posn); | 
|  | void	samerr(char*); | 
|  | void	settempfile(void); | 
|  | int	skipbl(void); | 
|  | void	snarf(File*, Posn, Posn, Buffer*, int); | 
|  | void	sortname(File*); | 
|  | void	startup(char*, int, char**, char**); | 
|  | void	state(File*, int); | 
|  | int	statfd(int, ulong*, uvlong*, long*, long*, long*); | 
|  | int	statfile(char*, ulong*, uvlong*, long*, long*, long*); | 
|  | void	Straddc(String*, int); | 
|  | void	Strclose(String*); | 
|  | int	Strcmp(String*, String*); | 
|  | void	Strdelete(String*, Posn, Posn); | 
|  | void	Strdupl(String*, Rune*); | 
|  | void	Strduplstr(String*, String*); | 
|  | void	Strinit(String*); | 
|  | void	Strinit0(String*); | 
|  | void	Strinsert(String*, String*, Posn); | 
|  | void	Strinsure(String*, ulong); | 
|  | int	Strispre(String*, String*); | 
|  | void	Strzero(String*); | 
|  | int	Strlen(Rune*); | 
|  | char	*Strtoc(String*); | 
|  | void	syserror(char*); | 
|  | void	telldot(File*); | 
|  | void	tellpat(void); | 
|  | String	*tmpcstr(char*); | 
|  | String	*tmprstr(Rune*, int); | 
|  | void	freetmpstr(String*); | 
|  | void	termcommand(void); | 
|  | void	termwrite(char*); | 
|  | File	*tofile(String*); | 
|  | void	trytoclose(File*); | 
|  | void	trytoquit(void); | 
|  | int	undo(int); | 
|  | void	update(void); | 
|  | int	waitfor(int); | 
|  | void	warn(Warn); | 
|  | void	warn_s(Warn, char*); | 
|  | void	warn_SS(Warn, String*, String*); | 
|  | void	warn_S(Warn, String*); | 
|  | int	whichmenu(File*); | 
|  | void	writef(File*); | 
|  | Posn	writeio(File*); | 
|  | Discdesc *Dstart(void); | 
|  |  | 
|  | extern Rune	samname[];	/* compiler dependent */ | 
|  | extern Rune	*left[]; | 
|  | extern Rune	*right[]; | 
|  |  | 
|  | extern char	RSAM[];		/* system dependent */ | 
|  | extern char	SAMTERM[]; | 
|  | extern char	HOME[]; | 
|  | extern char	TMPDIR[]; | 
|  | extern char	SH[]; | 
|  | extern char	SHPATH[]; | 
|  | extern char	RX[]; | 
|  | extern char	RXPATH[]; | 
|  |  | 
|  | /* | 
|  | * acme globals | 
|  | */ | 
|  | extern long		seq; | 
|  | extern Disk		*disk; | 
|  |  | 
|  | extern char	*rsamname;	/* globals */ | 
|  | extern char	*samterm; | 
|  | extern Rune	genbuf[]; | 
|  | extern char	*genc; | 
|  | extern int	io; | 
|  | extern int	patset; | 
|  | extern int	quitok; | 
|  | extern Address	addr; | 
|  | extern Buffer	snarfbuf; | 
|  | extern Buffer	plan9buf; | 
|  | extern List	file; | 
|  | extern List	tempfile; | 
|  | extern File	*cmd; | 
|  | extern File	*curfile; | 
|  | extern File	*lastfile; | 
|  | extern Mod	modnum; | 
|  | extern Posn	cmdpt; | 
|  | extern Posn	cmdptadv; | 
|  | extern Rangeset	sel; | 
|  | extern String	curwd; | 
|  | extern String	cmdstr; | 
|  | extern String	genstr; | 
|  | extern String	lastpat; | 
|  | extern String	lastregexp; | 
|  | extern String	plan9cmd; | 
|  | extern int	downloaded; | 
|  | extern int	eof; | 
|  | extern int	bpipeok; | 
|  | extern int	panicking; | 
|  | extern Rune	empty[]; | 
|  | extern int	termlocked; | 
|  | extern int	outbuffered; | 
|  |  | 
|  | #include "mesg.h" | 
|  |  | 
|  | void	outTs(Hmesg, int); | 
|  | void	outT0(Hmesg); | 
|  | void	outTl(Hmesg, long); | 
|  | void	outTslS(Hmesg, int, long, String*); | 
|  | void	outTS(Hmesg, String*); | 
|  | void	outTsS(Hmesg, int, String*); | 
|  | void	outTsllS(Hmesg, int, long, long, String*); | 
|  | void	outTsll(Hmesg, int, long, long); | 
|  | void	outTsl(Hmesg, int, long); | 
|  | void	outTsv(Hmesg, int, vlong); | 
|  | void	outflush(void); | 
|  | int needoutflush(void); |