1 #include <u.h> 2 #include <libc.h> 3 #include "errors.h" 4 5 /* 6 * BLOCKSIZE is relatively small to keep memory consumption down. 7 */ 8 9 #define BLOCKSIZE 2048 10 #define RUNESIZE sizeof(Rune) 11 #define NDISC 5 12 #define NBUFFILES 3+2*NDISC /* plan 9+undo+snarf+NDISC*(transcript+buf) */ 13 #define NSUBEXP 10 14 15 #define TRUE 1 16 #define FALSE 0 17 18 #define INFINITY 0x7FFFFFFFL 19 #define INCR 25 20 #define STRSIZE (2*BLOCKSIZE) 21 22 typedef long Posn; /* file position or address */ 23 typedef ushort Mod; /* modification number */ 24 25 typedef struct Address Address; 26 typedef struct Block Block; 27 typedef struct Buffer Buffer; 28 typedef struct Disc Disc; 29 typedef struct Discdesc Discdesc; 30 typedef struct File File; 31 typedef struct List List; 32 typedef struct Mark Mark; 33 typedef struct Range Range; 34 typedef struct Rangeset Rangeset; 35 typedef struct String String; 36 37 enum State 38 { 39 Clean = ' ', 40 Dirty = '\'', 41 Unread = '-', 42 Readerr = '~', 43 }; 44 45 struct Range 46 { 47 Posn p1, p2; 48 }; 49 50 struct Rangeset 51 { 52 Range p[NSUBEXP]; 53 }; 54 55 struct Address 56 { 57 Range r; 58 File *f; 59 }; 60 61 struct List /* code depends on a long being able to hold a pointer */ 62 { 63 int nalloc; 64 int nused; 65 union{ 66 void *listp; 67 Block *blkp; 68 long *longp; 69 uchar* *ucharp; 70 String* *stringp; 71 File* *filep; 72 long listv; 73 }g; 74 }; 75 76 #define listptr g.listp 77 #define blkptr g.blkp 78 #define longptr g.longp 79 #define ucharpptr g.ucharp 80 #define stringpptr g.stringp 81 #define filepptr g.filep 82 #define listval g.listv 83 84 /* 85 * Block must fit in a long because the list routines manage arrays of 86 * blocks. Two problems: some machines (e.g. Cray) can't pull this off 87 * -- on them, use bitfields -- and the ushort bnum limits temp file sizes 88 * to about 200 megabytes. Advantages: small, simple code and small 89 * memory overhead. If you really want to edit huge files, making BLOCKSIZE 90 * bigger is the easiest way. 91 */ 92 struct Block 93 { 94 ushort bnum; /* absolute number on disk */ 95 short nrunes; /* runes stored in this block */ 96 }; 97 98 struct Discdesc 99 { 100 int fd; /* plan 9 file descriptor of temp file */ 101 ulong nbk; /* high water mark */ 102 List free; /* array of free block indices */ 103 }; 104 105 struct Disc 106 { 107 Discdesc *desc; /* descriptor of temp file */ 108 Posn nrunes; /* runes on disc file */ 109 List block; /* list of used block indices */ 110 }; 111 112 struct String 113 { 114 short n; 115 short size; 116 Rune *s; 117 }; 118 119 struct Buffer 120 { 121 Disc *disc; /* disc storage */ 122 Posn nrunes; /* total length of buffer */ 123 String cache; /* in-core storage for efficiency */ 124 Posn c1, c2; /* cache start and end positions in disc */ 125 /* note: if dirty, cache is really c1, c1+cache.n */ 126 int dirty; /* cache dirty */ 127 }; 128 129 #define NGETC 128 130 131 struct File 132 { 133 Buffer *buf; /* cached disc storage */ 134 Buffer *transcript; /* what's been done */ 135 Posn markp; /* file pointer to start of latest change */ 136 Mod mod; /* modification stamp */ 137 Posn nrunes; /* total length of file */ 138 Posn hiposn; /* highest address touched this Mod */ 139 Address dot; /* current position */ 140 Address ndot; /* new current position after update */ 141 Range tdot; /* what terminal thinks is current range */ 142 Range mark; /* tagged spot in text (don't confuse with Mark) */ 143 List *rasp; /* map of what terminal's got */ 144 String name; /* file name */ 145 short tag; /* for communicating with terminal */ 146 char state; /* Clean, Dirty, Unread, or Readerr*/ 147 char closeok; /* ok to close file? */ 148 char deleted; /* delete at completion of command */ 149 char marked; /* file has been Fmarked at least once; once 150 * set, this will never go off as undo doesn't 151 * revert to the dawn of time */ 152 long dev; /* file system from which it was read */ 153 long qid; /* file from which it was read */ 154 long date; /* time stamp of plan9 file */ 155 Posn cp1, cp2; /* Write-behind cache positions and */ 156 String cache; /* string */ 157 Rune getcbuf[NGETC]; 158 int ngetc; 159 int getci; 160 Posn getcp; 161 }; 162 163 struct Mark 164 { 165 Posn p; 166 Range dot; 167 Range mark; 168 Mod m; 169 short s1; 170 }; 171 172 /* 173 * The precedent to any message in the transcript. 174 * The component structures must be an integral number of Runes long. 175 */ 176 union Hdr 177 { 178 struct _csl 179 { 180 short c; 181 short s; 182 long l; 183 }csl; 184 struct _cs 185 { 186 short c; 187 short s; 188 }cs; 189 struct _cll 190 { 191 short c; 192 long l; 193 long l1; 194 }cll; 195 Mark mark; 196 }; 197 198 #define Fgetc(f) ((--(f)->ngetc<0)? Fgetcload(f, (f)->getcp) : (f)->getcbuf[(f)->getcp++, (f)->getci++]) 199 #define Fbgetc(f) (((f)->getci<=0)? Fbgetcload(f, (f)->getcp) : (f)->getcbuf[--(f)->getcp, --(f)->getci]) 200 201 int alnum(int); 202 void Bclean(Buffer*); 203 void Bterm(Buffer*); 204 void Bdelete(Buffer*, Posn, Posn); 205 void Bflush(Buffer*); 206 void Binsert(Buffer*, String*, Posn); 207 Buffer *Bopen(Discdesc*); 208 int Bread(Buffer*, Rune*, int, Posn); 209 void Dclose(Disc*); 210 void Ddelete(Disc*, Posn, Posn); 211 void Dinsert(Disc*, Rune*, int, Posn); 212 Disc *Dopen(Discdesc*); 213 int Dread(Disc*, Rune*, int, Posn); 214 void Dreplace(Disc*, Posn, Posn, Rune*, int); 215 int Fbgetcload(File*, Posn); 216 int Fbgetcset(File*, Posn); 217 long Fchars(File*, Rune*, Posn, Posn); 218 void Fclose(File*); 219 void Fdelete(File*, Posn, Posn); 220 int Fgetcload(File*, Posn); 221 int Fgetcset(File*, Posn); 222 void Finsert(File*, String*, Posn); 223 File *Fopen(void); 224 void Fsetname(File*, String*); 225 void Fstart(void); 226 int Fupdate(File*, int, int); 227 int Read(int, void*, int); 228 void Seek(int, long, int); 229 int plan9(File*, int, String*, int); 230 int Write(int, void*, int); 231 int bexecute(File*, Posn); 232 void cd(String*); 233 void closefiles(File*, String*); 234 void closeio(Posn); 235 void cmdloop(void); 236 void cmdupdate(void); 237 void compile(String*); 238 void copy(File*, Address); 239 File *current(File*); 240 void delete(File*); 241 void delfile(File*); 242 void dellist(List*, int); 243 void doubleclick(File*, Posn); 244 void dprint(char*, ...); 245 void edit(File*, int); 246 void *emalloc(ulong); 247 void *erealloc(void*, ulong); 248 void error(Err); 249 void error_c(Err, int); 250 void error_s(Err, char*); 251 int execute(File*, Posn, Posn); 252 int filematch(File*, String*); 253 void filename(File*); 254 File *getfile(String*); 255 int getname(File*, String*, int); 256 long getnum(void); 257 void hiccough(char*); 258 void inslist(List*, int, long); 259 Address lineaddr(Posn, Address, int); 260 void listfree(List*); 261 void load(File*); 262 File *lookfile(String*); 263 void lookorigin(File*, Posn, Posn); 264 int lookup(int); 265 void move(File*, Address); 266 void moveto(File*, Range); 267 File *newfile(void); 268 void nextmatch(File*, String*, Posn, int); 269 int newtmp(int); 270 void notifyf(void*, char*); 271 void panic(char*); 272 void printposn(File*, int); 273 void print_ss(char*, String*, String*); 274 void print_s(char*, String*); 275 int rcv(void); 276 Range rdata(List*, Posn, Posn); 277 Posn readio(File*, int*, int); 278 void rescue(void); 279 void resetcmd(void); 280 void resetsys(void); 281 void resetxec(void); 282 void rgrow(List*, Posn, Posn); 283 void samerr(char*); 284 void settempfile(void); 285 int skipbl(void); 286 void snarf(File*, Posn, Posn, Buffer*, int); 287 void sortname(File*); 288 void startup(char*, int, char**, char**); 289 void state(File*, int); 290 int statfd(int, ulong*, ulong*, long*, long*, long*); 291 int statfile(char*, ulong*, ulong*, long*, long*, long*); 292 void Straddc(String*, int); 293 void Strclose(String*); 294 int Strcmp(String*, String*); 295 void Strdelete(String*, Posn, Posn); 296 void Strdupl(String*, Rune*); 297 void Strduplstr(String*, String*); 298 void Strinit(String*); 299 void Strinit0(String*); 300 void Strinsert(String*, String*, Posn); 301 void Strinsure(String*, ulong); 302 void Strzero(String*); 303 int Strlen(Rune*); 304 char *Strtoc(String*); 305 void syserror(char*); 306 void telldot(File*); 307 void tellpat(void); 308 String *tmpcstr(char*); 309 String *tmprstr(Rune*, int); 310 void freetmpstr(String*); 311 void termcommand(void); 312 void termwrite(char*); 313 File *tofile(String*); 314 void toterminal(File*, int); 315 void trytoclose(File*); 316 void trytoquit(void); 317 int undo(void); 318 void update(void); 319 int waitfor(int); 320 void warn(Warn); 321 void warn_s(Warn, char*); 322 void warn_SS(Warn, String*, String*); 323 void warn_S(Warn, String*); 324 int whichmenu(File*); 325 void writef(File*); 326 Posn writeio(File*); 327 Discdesc *Dstart(void); 328 329 extern Rune samname[]; /* compiler dependent */ 330 extern Rune *left[]; 331 extern Rune *right[]; 332 333 extern char RSAM[]; /* system dependent */ 334 extern char SAMTERM[]; 335 extern char HOME[]; 336 extern char TMPDIR[]; 337 extern char SH[]; 338 extern char SHPATH[]; 339 extern char RX[]; 340 extern char RXPATH[]; 341 extern char SAMSAVECMD[]; 342 343 extern char *rsamname; /* globals */ 344 extern char *samterm; 345 extern Rune genbuf[]; 346 extern char *genc; 347 extern int io; 348 extern int patset; 349 extern int quitok; 350 extern Address addr; 351 extern Buffer *undobuf; 352 extern Buffer *snarfbuf; 353 extern Buffer *plan9buf; 354 extern List file; 355 extern List tempfile; 356 extern File *cmd; 357 extern File *curfile; 358 extern File *lastfile; 359 extern Mod modnum; 360 extern Posn cmdpt; 361 extern Posn cmdptadv; 362 extern Rangeset sel; 363 extern String cmdstr; 364 extern String genstr; 365 extern String lastpat; 366 extern String lastregexp; 367 extern String plan9cmd; 368 extern int downloaded; 369 extern int eof; 370 extern int bpipeok; 371 extern int panicking; 372 extern Rune empty[]; 373 extern int termlocked; 374 extern int noflush; 375 376 #include "mesg.h" 377 378 void outTs(Hmesg, int); 379 void outT0(Hmesg); 380 void outTl(Hmesg, long); 381 void outTslS(Hmesg, int, long, String*); 382 void outTS(Hmesg, String*); 383 void outTsS(Hmesg, int, String*); 384 void outTsllS(Hmesg, int, long, long, String*); 385 void outTsll(Hmesg, int, long, long); 386 void outTsl(Hmesg, int, long); 387 void outTsv(Hmesg, int, long); 388 void outstart(Hmesg); 389 void outcopy(int, void*); 390 void outshort(int); 391 void outlong(long); 392 void outvlong(void*); 393 void outsend(void); 394 void outflush(void); 395