3 Rune genbuf[BLOCKSIZE];
17 List tempfile = { 'p' };
26 char *samterm = SAMTERM;
27 char *rsamname = RSAM;
32 Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'};
36 void main(int argc, char *argv[])
40 char *termargs[10], **ap;
49 machine = EARGF(usage());
55 samterm = EARGF(usage());
58 rsamname = EARGF(usage());
61 dprint("sam: unknown flag %c\n", ARGC());
63 /* options for samterm */
66 if(ap >= termargs+nelem(termargs))
71 if(ap >= termargs+nelem(termargs))
79 Strinit0(&lastregexp);
89 startup(machine, Rflag, termargs, argv);
93 for(i=0; i<argc; i++){
94 if(!setjmp(mainloop)){
97 Strduplstr(&genstr, t);
100 logsetname(newfile(), &genstr);
103 }else if(!downloaded)
107 current(file.filepptr[0]);
110 trytoquit(); /* if we already q'ed, quitok will be TRUE */
117 dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n");
132 for(i=0; i<file.nused; i++){
133 f = file.filepptr[i];
134 if(f==cmd || f->nc==0 || !fileisdirty(f))
137 sprint(buf, "%s/sam.save", home);
138 io = create(buf, 1, 0777);
143 c = Strtoc(&f->name);
144 strncpy(buf, c, sizeof buf-1);
145 buf[sizeof buf-1] = 0;
148 sprint(buf, "nameless.%d", nblank++);
149 fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf);
150 addr.r.p1 = 0, addr.r.p2 = f->nc;
152 fprint(io, "\n---%s\n", (char *)buf);
161 if(!panicking++ && !setjmp(mainloop)){
164 dprint("sam: panic: %s: %r\n", s);
166 fprint(2, "sam: panic: %s: %r\n", s);
189 * back out any logged changes & restore old sequences
191 for(i=0; i<file.nused; i++){
192 f = file.filepptr[i];
196 bufdelete(&f->epsilon, 0, f->epsilon.nc);
198 f->dot.r = f->prevdot;
199 f->mark = f->prevmark;
200 state(f, f->prevmod ? Dirty: Clean);
207 curfile->unread = FALSE;
209 outTs(Hcurrent, curfile->tag);
211 longjmp(mainloop, 1);
226 if(f == cmd) /* possible? */
230 if(fileisdirty(f) && !f->closeok){
233 t = Strtoc(&f->name);
234 strncpy(buf, t, sizeof buf-1);
237 strcpy(buf, "nameless file");
238 error_s(Emodified, buf);
250 for(c = 0; c<file.nused; c++){
251 f = file.filepptr[c];
252 if(f!=cmd && fileisdirty(f)){
266 Strduplstr(&genstr, &f->name);
274 f->cleanseq = f->seq;
277 fileupdate(f, TRUE, TRUE);
283 if(cmd && cmd->seq!=0){
284 fileupdate(cmd, FALSE, downloaded);
285 cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc;
293 if(downloaded && f->rasp)
294 outTs(Hclose, f->tag);
307 for(anymod = i=0; i<tempfile.nused; i++){
308 f = tempfile.filepptr[i];
309 if(f==cmd) /* cmd gets done in main() */
315 if(f->seq==seq && fileupdate(f, FALSE, downloaded))
331 edit(File *f, int cmd)
338 logdelete(f, addr.r.p1, addr.r.p2);
339 if(cmd=='e' || cmd=='I'){
340 logdelete(f, (Posn)0, f->nc);
342 }else if(f->nc!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0))
344 if((io = open(genc, OREAD))<0) {
345 if (curfile && curfile->unread)
346 curfile->unread = FALSE;
347 error_r(Eopen, genc);
349 p = readio(f, &nulls, empty, TRUE);
350 closeio((cmd=='e' || cmd=='I')? -1 : p);
352 f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p;
354 f->ndot.r.p1 = f->ndot.r.p2 = 0;
360 state(f, empty && !nulls? Clean : Dirty);
362 f->cleanseq = f->seq;
368 getname(File *f, String *s, int save)
377 if(s==0 || (c = s->s[0])==0){ /* no name provided */
379 Strduplstr(&genstr, &f->name);
382 if(c!=' ' && c!='\t')
384 for(i=0; (c=s->s[i])==' ' || c=='\t'; i++)
387 Straddc(&genstr, s->s[i++]);
391 if(f && (save || f->name.s[0]==0)){
392 logsetname(f, &genstr);
393 if(Strcmp(&f->name, &genstr)){
394 quitok = f->closeok = FALSE;
397 state(f, Dirty); /* if it's 'e', fix later */
401 genc = Strtoc(&genstr);
403 if(i && genstr.s[i-1]==0)
405 return i; /* strlen(name) */
413 genc = Strtoc(&genstr);
414 dprint("%c%c%c %s\n", " '"[f->mod],
415 "-+"[f->rasp!=0], " ."[f==curfile], genc);
419 undostep(File *f, int isundo)
425 fileundo(f, isundo, 1, &p1, &p2, TRUE);
450 max = undoseq(curfile, isundo);
454 for(i = 0; i<tempfile.nused; i++){
455 f = tempfile.filepptr[i];
456 if(f!=cmd && undoseq(f, isundo)==max)
471 addr.r.p1 = 0, addr.r.p2 = flist->nc;
472 retcode = plan9(flist, '<', s, FALSE);
473 fileupdate(flist, FALSE, FALSE);
475 if (flist->nc > BLOCKSIZE)
478 Strinsure(&genstr, flist->nc);
479 bufread(flist, (Posn)0, genbuf, flist->nc);
480 memmove(genstr.s, genbuf, flist->nc*RUNESIZE);
481 genstr.n = flist->nc;
482 Straddc(&genstr, '\0');
493 getwd(buf, sizeof(buf));
495 Strduplstr(&curwd, t);
499 else if(curwd.s[curwd.n-1] != '/')
500 Straddc(&curwd, '/');
512 if(getname((File *)0, str, FALSE))
518 fd = open("/dev/wdir", OWRITE);
520 write(fd, s, strlen(s));
523 Strduplstr(&owd, &curwd);
526 for(i=0; i<tempfile.nused; i++){
527 f = tempfile.filepptr[i];
528 if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){
529 Strinsert(&f->name, &owd, (Posn)0);
532 }else if(f != cmd && Strispre(&curwd, &f->name)){
546 for(i = 0; s->s[i]==' ' || s->s[i]=='\t'; i++)
548 if((c==' ' || c=='\t') && s->s[i]!='\n'){
550 Strdelete(s, 0L, (long)i+1);
554 while((c = s->s[i++]) && c!='\n')
556 Straddc(&genstr, '\0');
561 Strdupl(&genstr, empty);
565 genc = Strtoc(&genstr);
570 readflist(int readall, int delete)
578 for(i=0,f=0; f==0 || readall || delete; i++){ /* ++ skips blank */
579 Strdelete(&genstr, (Posn)0, i);
580 for(i=0; (c = genstr.s[i])==' ' || c=='\t' || c=='\n'; i++)
584 Strdelete(&genstr, (Posn)0, i);
585 for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++)
591 Strduplstr(&t, tmprstr(genstr.s, i+1));
599 }else if(f==0 && readall)
600 logsetname(f = newfile(), &t);
613 if(loadflist(s) == 0){
614 f = lookfile(&genstr); /* empty string ==> nameless file */
616 error_s(Emenu, genc);
617 }else if((f=readflist(FALSE, FALSE)) == 0)
618 error_s(Emenu, genc);
627 if(loadflist(s) == 0)
628 logsetname(f = newfile(), &genstr);
629 else if((f=readflist(TRUE, FALSE)) == 0)
635 closefiles(File *f, String *s)
645 if(loadflist(s) == 0)
647 readflist(FALSE, TRUE);
651 copy(File *f, Address addr2)
655 for(p=addr.r.p1; p<addr.r.p2; p+=ni){
659 bufread(f, p, genbuf, ni);
660 loginsert(addr2.f, addr2.r.p2, tmprstr(genbuf, ni)->s, ni);
662 addr2.f->ndot.r.p2 = addr2.r.p2+(f->dot.r.p2-f->dot.r.p1);
663 addr2.f->ndot.r.p1 = addr2.r.p2;
667 move(File *f, Address addr2)
669 if(addr.r.p2 <= addr2.r.p2){
670 logdelete(f, addr.r.p1, addr.r.p2);
672 }else if(addr.r.p1 >= addr2.r.p2){
674 logdelete(f, addr.r.p1, addr.r.p2);
680 nlcount(File *f, Posn p0, Posn p1)
685 if(filereadc(f, p0++)=='\n')
691 printposn(File *f, int charsonly)
696 l1 = 1+nlcount(f, (Posn)0, addr.r.p1);
697 l2 = l1+nlcount(f, addr.r.p1, addr.r.p2);
698 /* check if addr ends with '\n' */
699 if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && filereadc(f, addr.r.p2-1)=='\n')
706 dprint("#%lud", addr.r.p1);
707 if(addr.r.p2 != addr.r.p1)
708 dprint(",#%lud", addr.r.p2);
715 if(tempfile.nalloc < file.nused){
716 if(tempfile.filepptr)
717 free(tempfile.filepptr);
718 tempfile.filepptr = emalloc(sizeof(File*)*file.nused);
719 tempfile.nalloc = file.nused;
721 memmove(tempfile.filepptr, file.filepptr, sizeof(File*)*file.nused);
722 tempfile.nused = file.nused;