1 #include <u.h>
2 #include <libc.h>
3 #include <plumb.h>
4 #include "errors.h"
5 
6 #undef waitfor
7 #define waitfor samwaitfor
8 
9 #undef warn
10 #define warn samwarn
11 
12 /*
13  * BLOCKSIZE is relatively small to keep memory consumption down.
14  */
15 
16 #define	BLOCKSIZE	2048
17 #define	RUNESIZE	sizeof(Rune)
18 #define	NDISC		5
19 #define	NBUFFILES	3+2*NDISC	/* plan 9+undo+snarf+NDISC*(transcript+buf) */
20 #define NSUBEXP	10
21 
22 #define	TRUE		1
23 #define	FALSE		0
24 
25 #undef INFINITY	/* Darwin declares this as HUGE_VAL */
26 #define	INFINITY	0x7FFFFFFFL
27 #define	INCR		25
28 #define	STRSIZE		(2*BLOCKSIZE)
29 
30 typedef long		Posn;		/* file position or address */
31 typedef	ushort		Mod;		/* modification number */
32 
33 typedef struct Address	Address;
34 typedef struct Block	Block;
35 typedef struct Buffer	Buffer;
36 typedef struct Disk	Disk;
37 typedef struct Discdesc	Discdesc;
38 typedef struct File	File;
39 typedef struct List	List;
40 typedef struct Range	Range;
41 typedef struct Rangeset	Rangeset;
42 typedef struct String	String;
43 
44 enum State
45 {
46 	Clean =		' ',
47 	Dirty =		'\'',
48 	Unread =	'-'
49 };
50 
51 struct Range
52 {
53 	Posn	p1, p2;
54 };
55 
56 struct Rangeset
57 {
58 	Range	p[NSUBEXP];
59 };
60 
61 struct Address
62 {
63 	Range	r;
64 	File	*f;
65 };
66 
67 struct String
68 {
69 	short	n;
70 	short	size;
71 	Rune	*s;
72 };
73 
74 struct List	/* code depends on a long being able to hold a pointer */
75 {
76 	int	type;	/* 'p' for pointer, 'P' for Posn */
77 	int	nalloc;
78 	int	nused;
79 	union{
80 		void*	listp;
81 		void**	voidp;
82 		Posn*	posnp;
83 		String**stringp;
84 		File**	filep;
85 	}g;
86 };
87 
88 #define	listptr		g.listp
89 #define	voidpptr	g.voidp
90 #define	posnptr		g.posnp
91 #define	stringpptr	g.stringp
92 #define	filepptr	g.filep
93 
94 enum
95 {
96 	Blockincr =	256,
97 	Maxblock = 	8*1024,
98 
99 	BUFSIZE = Maxblock,	/* size from fbufalloc() */
100 	RBUFSIZE = BUFSIZE/sizeof(Rune)
101 };
102 
103 
104 enum
105 {
106 	Null		= '-',
107 	Delete		= 'd',
108 	Insert		= 'i',
109 	Filename	= 'f',
110 	Dot		= 'D',
111 	Mark		= 'm'
112 };
113 
114 struct Block
115 {
116 	uint		addr;	/* disk address in bytes */
117 	union {
118 		uint	n;	/* number of used runes in block */
119 		Block	*next;	/* pointer to next in free list */
120 	} u;
121 };
122 
123 struct Disk
124 {
125 	int		fd;
126 	uint		addr;	/* length of temp file */
127 	Block		*free[Maxblock/Blockincr+1];
128 };
129 
130 Disk*		diskinit(void);
131 Block*		disknewblock(Disk*, uint);
132 void		diskrelease(Disk*, Block*);
133 void		diskread(Disk*, Block*, Rune*, uint);
134 void		diskwrite(Disk*, Block**, Rune*, uint);
135 
136 struct Buffer
137 {
138 	uint		nc;
139 	Rune		*c;	/* cache */
140 	uint		cnc;	/* bytes in cache */
141 	uint		cmax;	/* size of allocated cache */
142 	uint		cq;	/* position of cache */
143 	int		cdirty;	/* cache needs to be written */
144 	uint		cbi;	/* index of cache Block */
145 	Block		**bl;	/* array of blocks */
146 	uint		nbl;	/* number of blocks */
147 };
148 void		bufinsert(Buffer*, uint, Rune*, uint);
149 void		bufdelete(Buffer*, uint, uint);
150 uint		bufload(Buffer*, uint, int, int*);
151 void		bufread(Buffer*, uint, Rune*, uint);
152 void		bufclose(Buffer*);
153 void		bufreset(Buffer*);
154 
155 struct File
156 {
157 	Buffer 	b;				/* the data */
158 	Buffer		delta;		/* transcript of changes */
159 	Buffer		epsilon;	/* inversion of delta for redo */
160 	String		name;		/* name of associated file */
161 	uvlong		qidpath;	/* of file when read */
162 	uint		mtime;		/* of file when read */
163 	int		dev;		/* of file when read */
164 	int		unread;		/* file has not been read from disk */
165 
166 	long		seq;		/* if seq==0, File acts like Buffer */
167 	long		cleanseq;	/* f->seq at last read/write of file */
168 	int		mod;		/* file appears modified in menu */
169 	char		rescuing;	/* sam exiting; this file unusable */
170 
171 #if 0
172 //	Text		*curtext;	/* most recently used associated text */
173 //	Text		**text;		/* list of associated texts */
174 //	int		ntext;
175 //	int		dumpid;		/* used in dumping zeroxed windows */
176 #endif
177 
178 	Posn		hiposn;		/* highest address touched this Mod */
179 	Address		dot;		/* current position */
180 	Address		ndot;		/* new current position after update */
181 	Range		tdot;		/* what terminal thinks is current range */
182 	Range		mark;		/* tagged spot in text (don't confuse with Mark) */
183 	List		*rasp;		/* map of what terminal's got */
184 	short		tag;		/* for communicating with terminal */
185 	char		closeok;	/* ok to close file? */
186 	char		deleted;	/* delete at completion of command */
187 	Range		prevdot;	/* state before start of change */
188 	Range		prevmark;
189 	long		prevseq;
190 	int		prevmod;
191 };
192 /*File*		fileaddtext(File*, Text*); */
193 void		fileclose(File*);
194 void		filedelete(File*, uint, uint);
195 /*void		filedeltext(File*, Text*); */
196 void		fileinsert(File*, uint, Rune*, uint);
197 uint		fileload(File*, uint, int, int*);
198 void		filemark(File*);
199 void		filereset(File*);
200 void		filesetname(File*, String*);
201 void		fileundelete(File*, Buffer*, uint, uint);
202 void		fileuninsert(File*, Buffer*, uint, uint);
203 void		fileunsetname(File*, Buffer*);
204 void		fileundo(File*, int, int, uint*, uint*, int);
205 int		fileupdate(File*, int, int);
206 
207 int		filereadc(File*, uint);
208 File		*fileopen(void);
209 void		loginsert(File*, uint, Rune*, uint);
210 void		logdelete(File*, uint, uint);
211 void		logsetname(File*, String*);
212 int		fileisdirty(File*);
213 long		undoseq(File*, int);
214 long		prevseq(Buffer*);
215 
216 void		raspload(File*);
217 void		raspstart(File*);
218 void		raspdelete(File*, uint, uint, int);
219 void		raspinsert(File*, uint, Rune*, uint, int);
220 void		raspdone(File*, int);
221 void		raspflush(File*);
222 
223 /*
224  * acme fns
225  */
226 void*	fbufalloc(void);
227 void	fbuffree(void*);
228 uint	min(uint, uint);
229 void	cvttorunes(char*, int, Rune*, int*, int*, int*);
230 
231 #define	runemalloc(a)		(Rune*)emalloc((a)*sizeof(Rune))
232 #define	runerealloc(a, b)	(Rune*)realloc((a), (b)*sizeof(Rune))
233 #define	runemove(a, b, c)	memmove((a), (b), (c)*sizeof(Rune))
234 
235 int	alnum(int);
236 int	Read(int, void*, int);
237 void	Seek(int, long, int);
238 int	plan9(File*, int, String*, int);
239 int	Write(int, void*, int);
240 int	bexecute(File*, Posn);
241 void	cd(String*);
242 void	closefiles(File*, String*);
243 void	closeio(Posn);
244 void	cmdloop(void);
245 void	cmdupdate(void);
246 void	compile(String*);
247 void	copy(File*, Address);
248 File	*current(File*);
249 void	delete(File*);
250 void	delfile(File*);
251 void	dellist(List*, int);
252 void	doubleclick(File*, Posn);
253 void	dprint(char*, ...);
254 void	edit(File*, int);
255 void	*emalloc(ulong);
256 void	*erealloc(void*, ulong);
257 void	error(Err);
258 void	error_c(Err, int);
259 void	error_r(Err, char*);
260 void	error_s(Err, char*);
261 int	execute(File*, Posn, Posn);
262 int	filematch(File*, String*);
263 void	filename(File*);
264 void	fixname(String*);
265 void	fullname(String*);
266 void	getcurwd(void);
267 File	*getfile(String*);
268 int	getname(File*, String*, int);
269 long	getnum(int);
270 void	hiccough(char*);
271 void	inslist(List*, int, ...);
272 Address	lineaddr(Posn, Address, int);
273 List	*listalloc(int);
274 void	listfree(List*);
275 void	load(File*);
276 File	*lookfile(String*);
277 void	lookorigin(File*, Posn, Posn);
278 int	lookup(int);
279 void	move(File*, Address);
280 void	moveto(File*, Range);
281 File	*newfile(void);
282 void	nextmatch(File*, String*, Posn, int);
283 int	newtmp(int);
284 void	notifyf(void*, char*);
285 void	panic(char*);
286 void	printposn(File*, int);
287 void	print_ss(char*, String*, String*);
288 void	print_s(char*, String*);
289 int	rcv(void);
290 Range	rdata(List*, Posn, Posn);
291 Posn	readio(File*, int*, int, int);
292 void	rescue(void);
293 void	resetcmd(void);
294 void	resetsys(void);
295 void	resetxec(void);
296 void	rgrow(List*, Posn, Posn);
297 void	samerr(char*);
298 void	settempfile(void);
299 int	skipbl(void);
300 void	snarf(File*, Posn, Posn, Buffer*, int);
301 void	sortname(File*);
302 void	startup(char*, int, char**, char**);
303 void	state(File*, int);
304 int	statfd(int, ulong*, uvlong*, long*, long*, long*);
305 int	statfile(char*, ulong*, uvlong*, long*, long*, long*);
306 void	Straddc(String*, int);
307 void	Strclose(String*);
308 int	Strcmp(String*, String*);
309 void	Strdelete(String*, Posn, Posn);
310 void	Strdupl(String*, Rune*);
311 void	Strduplstr(String*, String*);
312 void	Strinit(String*);
313 void	Strinit0(String*);
314 void	Strinsert(String*, String*, Posn);
315 void	Strinsure(String*, ulong);
316 int	Strispre(String*, String*);
317 void	Strzero(String*);
318 int	Strlen(Rune*);
319 char	*Strtoc(String*);
320 void	syserror(char*);
321 void	telldot(File*);
322 void	tellpat(void);
323 String	*tmpcstr(char*);
324 String	*tmprstr(Rune*, int);
325 void	freetmpstr(String*);
326 void	termcommand(void);
327 void	termwrite(char*);
328 File	*tofile(String*);
329 void	trytoclose(File*);
330 void	trytoquit(void);
331 int	undo(int);
332 void	update(void);
333 int	waitfor(int);
334 void	warn(Warn);
335 void	warn_s(Warn, char*);
336 void	warn_SS(Warn, String*, String*);
337 void	warn_S(Warn, String*);
338 int	whichmenu(File*);
339 void	writef(File*);
340 Posn	writeio(File*);
341 Discdesc *Dstart(void);
342 
343 extern Rune	samname[];	/* compiler dependent */
344 extern Rune	*left[];
345 extern Rune	*right[];
346 
347 extern char	RSAM[];		/* system dependent */
348 extern char	SAMTERM[];
349 extern char	HOME[];
350 extern char	TMPDIR[];
351 extern char	SH[];
352 extern char	SHPATH[];
353 extern char	RX[];
354 extern char	RXPATH[];
355 
356 /*
357  * acme globals
358  */
359 extern long		seq;
360 extern Disk		*disk;
361 
362 extern char	*rsamname;	/* globals */
363 extern char	*samterm;
364 extern Rune	genbuf[];
365 extern char	*genc;
366 extern int	io;
367 extern int	patset;
368 extern int	quitok;
369 extern Address	addr;
370 extern Buffer	snarfbuf;
371 extern Buffer	plan9buf;
372 extern List	file;
373 extern List	tempfile;
374 extern File	*cmd;
375 extern File	*curfile;
376 extern File	*lastfile;
377 extern Mod	modnum;
378 extern Posn	cmdpt;
379 extern Posn	cmdptadv;
380 extern Rangeset	sel;
381 extern String	curwd;
382 extern String	cmdstr;
383 extern String	genstr;
384 extern String	lastpat;
385 extern String	lastregexp;
386 extern String	plan9cmd;
387 extern int	downloaded;
388 extern int	eof;
389 extern int	bpipeok;
390 extern int	panicking;
391 extern Rune	empty[];
392 extern int	termlocked;
393 extern int	outbuffered;
394 
395 #include "mesg.h"
396 
397 void	outTs(Hmesg, int);
398 void	outT0(Hmesg);
399 void	outTl(Hmesg, long);
400 void	outTslS(Hmesg, int, long, String*);
401 void	outTS(Hmesg, String*);
402 void	outTsS(Hmesg, int, String*);
403 void	outTsllS(Hmesg, int, long, long, String*);
404 void	outTsll(Hmesg, int, long, long);
405 void	outTsl(Hmesg, int, long);
406 void	outTsv(Hmesg, int, vlong);
407 void	outflush(void);
408 int needoutflush(void);
409