/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <cursor.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include <fcall.h>#include <plumb.h>#include "dat.h"#include "edit.h"#include "fns.h" static char linex[]="\n";static char wordx[]=" \t\n";struct cmdtab cmdtab[]={/* cmdc text regexp addr defcmd defaddr count token fn */ '\n', 0, 0, 0, 0, aDot, 0, 0, nl_cmd, 'a', 1, 0, 0, 0, aDot, 0, 0, a_cmd, 'b', 0, 0, 0, 0, aNo, 0, linex, b_cmd, 'c', 1, 0, 0, 0, aDot, 0, 0, c_cmd, 'd', 0, 0, 0, 0, aDot, 0, 0, d_cmd, 'e', 0, 0, 0, 0, aNo, 0, wordx, e_cmd, 'f', 0, 0, 0, 0, aNo, 0, wordx, f_cmd, 'g', 0, 1, 0, 'p', aDot, 0, 0, g_cmd, 'i', 1, 0, 0, 0, aDot, 0, 0, i_cmd, 'm', 0, 0, 1, 0, aDot, 0, 0, m_cmd, 'p', 0, 0, 0, 0, aDot, 0, 0, p_cmd, 'r', 0, 0, 0, 0, aDot, 0, wordx, e_cmd, 's', 0, 1, 0, 0, aDot, 1, 0, s_cmd, 't', 0, 0, 1, 0, aDot, 0, 0, m_cmd, 'u', 0, 0, 0, 0, aNo, 2, 0, u_cmd, 'v', 0, 1, 0, 'p', aDot, 0, 0, g_cmd, 'w', 0, 0, 0, 0, aAll, 0, wordx, w_cmd, 'x', 0, 1, 0, 'p', aDot, 0, 0, x_cmd, 'y', 0, 1, 0, 'p', aDot, 0, 0, x_cmd, '=', 0, 0, 0, 0, aDot, 0, linex, eq_cmd, 'B', 0, 0, 0, 0, aNo, 0, linex, B_cmd, 'D', 0, 0, 0, 0, aNo, 0, linex, D_cmd, 'X', 0, 1, 0, 'f', aNo, 0, 0, X_cmd, 'Y', 0, 1, 0, 'f', aNo, 0, 0, X_cmd, '<', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd, '|', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd, '>', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd,/* deliberately unimplemented: 'k', 0, 0, 0, 0, aDot, 0, 0, k_cmd, 'n', 0, 0, 0, 0, aNo, 0, 0, n_cmd, 'q', 0, 0, 0, 0, aNo, 0, 0, q_cmd, '!', 0, 0, 0, 0, aNo, 0, linex, plan9_cmd, */ 0, 0, 0, 0, 0, 0, 0, 0,}; Cmd *parsecmd(int);Addr *compoundaddr(void);Addr *simpleaddr(void);void freecmd(void);void okdelim(int); Rune *cmdstartp;Rune *cmdendp;Rune *cmdp;Channel *editerrc; String *lastpat;int patset; List cmdlist;List addrlist;List stringlist;Text *curtext;int editing = Inactive; String* newstring(int); voideditthread(void*){ Cmd *cmdp; threadsetname("editthread"); while((cmdp=parsecmd(0)) != 0){// ocurfile = curfile;// loaded = curfile && !curfile->unread; if(cmdexec(curtext, cmdp) == 0) break; freecmd(); } sendp(editerrc, nil);} voidallelogterm(Window *w, void*){ elogterm(w->body.file);} voidalleditinit(Window *w, void*){ textcommit(&w->tag, TRUE); textcommit(&w->body, TRUE); w->body.file->editclean = FALSE;} voidallupdate(Window *w, void*){ Text *t; int i; File *f; t = &w->body; f = t->file; if(f->curtext != t) /* do curtext only */ return; if(f->elog.type == Null) elogterm(f); else if(f->elog.type != Empty){ elogapply(f); if(f->editclean){ f->mod = FALSE; for(i=0; i<f->ntext; i++) f->text[i]->w->dirty = FALSE; } } textsetselect(t, t->q0, t->q1); textscrdraw(t); winsettag(w);} voidediterror(char *fmt, ...){ va_list arg; char *s; va_start(arg, fmt); s = vsmprint(fmt, arg); va_end(arg); freecmd(); allwindows(allelogterm, nil); /* truncate the edit logs */ sendp(editerrc, s); threadexits(nil);} voideditcmd(Text *ct, Rune *r, uint n){ char *err; if(n == 0) return; if(2*n > RBUFSIZE){ warning(nil, "string too long\n"); return; } allwindows(alleditinit, nil); if(cmdstartp) free(cmdstartp); cmdstartp = runemalloc(n+2); runemove(cmdstartp, r, n); if(r[n] != '\n') cmdstartp[n++] = '\n'; cmdstartp[n] = '\0'; cmdendp = cmdstartp+n; cmdp = cmdstartp; if(ct->w == nil) curtext = nil; else curtext = &ct->w->body; resetxec(); if(editerrc == nil){ editerrc = chancreate(sizeof(char*), 0); lastpat = allocstring(0); } threadcreate(editthread, nil, STACK); err = recvp(editerrc); editing = Inactive; if(err != nil){ if(err[0] != '\0') warning(nil, "Edit: %s\n", err); free(err); } /* update everyone whose edit log has data */ allwindows(allupdate, nil);} intgetch(void){ if(*cmdp == *cmdendp) return -1; return *cmdp++;} intnextc(void){ if(*cmdp == *cmdendp) return -1; return *cmdp;} voidungetch(void){ if(--cmdp < cmdstartp) error("ungetch");} longgetnum(int signok){ long n; int c, sign; n = 0; sign = 1; if(signok>1 && nextc()=='-'){ sign = -1; getch(); } if((c=nextc())<'0' || '9'<c) /* no number defaults to 1 */ return sign; while('0'<=(c=getch()) && c<='9') n = n*10 + (c-'0'); ungetch(); return sign*n;} intcmdskipbl(void){ int c; do c = getch(); while(c==' ' || c=='\t'); if(c >= 0) ungetch(); return c;} /* * Check that list has room for one more element. */voidgrowlist(List *l){ if(l->listptr==0 || l->nalloc==0){ l->nalloc = INCR; l->listptr = emalloc(INCR*sizeof(void*)); l->nused = 0; }else if(l->nused == l->nalloc){ l->listptr = erealloc(l->listptr, (l->nalloc+INCR)*sizeof(void*)); memset(l->ptr+l->nalloc, 0, INCR*sizeof(void*)); l->nalloc += INCR; }} /* * Remove the ith element from the list */voiddellist(List *l, int i){ memmove(&l->ptr[i], &l->ptr[i+1], (l->nused-(i+1))*sizeof(void*)); l->nused--;} /* * Add a new element, whose position is i, to the list */voidinslist(List *l, int i, void *v){ growlist(l); memmove(&l->ptr[i+1], &l->ptr[i], (l->nused-i)*sizeof(void*)); l->ptr[i] = v; l->nused++;} voidlistfree(List *l){ free(l->listptr); free(l);} String*allocstring(int n){ String *s; s = emalloc(sizeof(String)); s->n = n; s->nalloc = n+10; s->r = emalloc(s->nalloc*sizeof(Rune)); s->r[n] = '\0'; return s;} voidfreestring(String *s){ free(s->r); free(s);} Cmd*newcmd(void){ Cmd *p; p = emalloc(sizeof(Cmd)); inslist(&cmdlist, cmdlist.nused, p); return p;} String*newstring(int n){ String *p; p = allocstring(n); inslist(&stringlist, stringlist.nused, p); return p;} Addr*newaddr(void){ Addr *p; p = emalloc(sizeof(Addr)); inslist(&addrlist, addrlist.nused, p); return p;} voidfreecmd(void){ int i; while(cmdlist.nused > 0) free(cmdlist.ucharptr[--cmdlist.nused]); while(addrlist.nused > 0) free(addrlist.ucharptr[--addrlist.nused]); while(stringlist.nused>0){ i = --stringlist.nused; freestring(stringlist.stringptr[i]); }} voidokdelim(int c){ if(c=='\\' || ('a'<=c && c<='z') || ('A'<=c && c<='Z') || ('0'<=c && c<='9')) editerror("bad delimiter %c\n", c);} voidatnl(void){ int c; cmdskipbl(); c = getch(); if(c != '\n') editerror("newline expected (saw %C)", c);} voidStraddc(String *s, int c){ if(s->n+1 >= s->nalloc){ s->nalloc += 10; s->r = erealloc(s->r, s->nalloc*sizeof(Rune)); } s->r[s->n++] = c; s->r[s->n] = '\0';} voidgetrhs(String *s, int delim, int cmd){ int c; while((c = getch())>0 && c!=delim && c!='\n'){ if(c == '\\'){ if((c=getch()) <= 0) error("bad right hand side"); if(c == '\n'){ ungetch(); c='\\'; }else if(c == 'n') c='\n'; else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */ Straddc(s, '\\'); } Straddc(s, c); } ungetch(); /* let client read whether delimiter, '\n' or whatever */} String *collecttoken(char *end){ String *s = newstring(0); int c; while((c=nextc())==' ' || c=='\t') Straddc(s, getch()); /* blanks significant for getname() */ while((c=getch())>0 && utfrune(end, c)==0) Straddc(s, c); if(c != '\n') atnl(); return s;} String *collecttext(void){ String *s; int begline, i, c, delim; s = newstring(0); if(cmdskipbl()=='\n'){ getch(); i = 0; do{ begline = i; while((c = getch())>0 && c!='\n') i++, Straddc(s, c); i++, Straddc(s, '\n'); if(c < 0) goto Return; }while(s->r[begline]!='.' || s->r[begline+1]!='\n'); s->r[s->n-2] = '\0'; s->n -= 2; }else{ okdelim(delim = getch()); getrhs(s, delim, 'a'); if(nextc()==delim) getch(); atnl(); } Return: return s;} intcmdlookup(int c){ int i; for(i=0; cmdtab[i].cmdc; i++) if(cmdtab[i].cmdc == c) return i; return -1;} Cmd*parsecmd(int nest){ int i, c; struct cmdtab *ct; Cmd *cp, *ncp; Cmd cmd; cmd.next = cmd.cmd = 0; cmd.re = 0; cmd.flag = cmd.num = 0; cmd.addr = compoundaddr(); if(cmdskipbl() == -1) return 0; if((c=getch())==-1) return 0; cmd.cmdc = c; if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */ getch(); /* the 'd' */ cmd.cmdc='c'|0x100; } i = cmdlookup(cmd.cmdc); if(i >= 0){ if(cmd.cmdc == '\n') goto Return; /* let nl_cmd work it all out */ ct = &cmdtab[i];Lines 1–500 of 688. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h> #include <libc.h> #include <draw.h> #include <thread.h> #include <cursor.h> #include <mouse.h> #include <keyboard.h> #include <frame.h> #include <fcall.h> #include <plumb.h> #include "dat.h" #include "edit.h" #include "fns.h" static char linex[]="\n"; static char wordx[]=" \t\n"; struct cmdtab cmdtab[]={ /* cmdc text regexp addr defcmd defaddr count token fn */ '\n', 0, 0, 0, 0, aDot, 0, 0, nl_cmd, 'a', 1, 0, 0, 0, aDot, 0, 0, a_cmd, 'b', 0, 0, 0, 0, aNo, 0, linex, b_cmd, 'c', 1, 0, 0, 0, aDot, 0, 0, c_cmd, 'd', 0, 0, 0, 0, aDot, 0, 0, d_cmd, 'e', 0, 0, 0, 0, aNo, 0, wordx, e_cmd, 'f', 0, 0, 0, 0, aNo, 0, wordx, f_cmd, 'g', 0, 1, 0, 'p', aDot, 0, 0, g_cmd, 'i', 1, 0, 0, 0, aDot, 0, 0, i_cmd, 'm', 0, 0, 1, 0, aDot, 0, 0, m_cmd, 'p', 0, 0, 0, 0, aDot, 0, 0, p_cmd, 'r', 0, 0, 0, 0, aDot, 0, wordx, e_cmd, 's', 0, 1, 0, 0, aDot, 1, 0, s_cmd, 't', 0, 0, 1, 0, aDot, 0, 0, m_cmd, 'u', 0, 0, 0, 0, aNo, 2, 0, u_cmd, 'v', 0, 1, 0, 'p', aDot, 0, 0, g_cmd, 'w', 0, 0, 0, 0, aAll, 0, wordx, w_cmd, 'x', 0, 1, 0, 'p', aDot, 0, 0, x_cmd, 'y', 0, 1, 0, 'p', aDot, 0, 0, x_cmd, '=', 0, 0, 0, 0, aDot, 0, linex, eq_cmd, 'B', 0, 0, 0, 0, aNo, 0, linex, B_cmd, 'D', 0, 0, 0, 0, aNo, 0, linex, D_cmd, 'X', 0, 1, 0, 'f', aNo, 0, 0, X_cmd, 'Y', 0, 1, 0, 'f', aNo, 0, 0, X_cmd, '<', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd, '|', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd, '>', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd, /* deliberately unimplemented: 'k', 0, 0, 0, 0, aDot, 0, 0, k_cmd, 'n', 0, 0, 0, 0, aNo, 0, 0, n_cmd, 'q', 0, 0, 0, 0, aNo, 0, 0, q_cmd, '!', 0, 0, 0, 0, aNo, 0, linex, plan9_cmd, */ 0, 0, 0, 0, 0, 0, 0, 0, }; Cmd *parsecmd(int); Addr *compoundaddr(void); Addr *simpleaddr(void); void freecmd(void); void okdelim(int); Rune *cmdstartp; Rune *cmdendp; Rune *cmdp; Channel *editerrc; String *lastpat; int patset; List cmdlist; List addrlist; List stringlist; Text *curtext; int editing = Inactive; String* newstring(int); void editthread(void*) { Cmd *cmdp; threadsetname("editthread"); while((cmdp=parsecmd(0)) != 0){ // ocurfile = curfile; // loaded = curfile && !curfile->unread; if(cmdexec(curtext, cmdp) == 0) break; freecmd(); } sendp(editerrc, nil); } void allelogterm(Window *w, void*) { elogterm(w->body.file); } void alleditinit(Window *w, void*) { textcommit(&w->tag, TRUE); textcommit(&w->body, TRUE); w->body.file->editclean = FALSE; } void allupdate(Window *w, void*) { Text *t; int i; File *f; t = &w->body; f = t->file; if(f->curtext != t) /* do curtext only */ return; if(f->elog.type == Null) elogterm(f); else if(f->elog.type != Empty){ elogapply(f); if(f->editclean){ f->mod = FALSE; for(i=0; i<f->ntext; i++) f->text[i]->w->dirty = FALSE; } } textsetselect(t, t->q0, t->q1); textscrdraw(t); winsettag(w); } void editerror(char *fmt, ...) { va_list arg; char *s; va_start(arg, fmt); s = vsmprint(fmt, arg); va_end(arg); freecmd(); allwindows(allelogterm, nil); /* truncate the edit logs */ sendp(editerrc, s); threadexits(nil); } void editcmd(Text *ct, Rune *r, uint n) { char *err; if(n == 0) return; if(2*n > RBUFSIZE){ warning(nil, "string too long\n"); return; } allwindows(alleditinit, nil); if(cmdstartp) free(cmdstartp); cmdstartp = runemalloc(n+2); runemove(cmdstartp, r, n); if(r[n] != '\n') cmdstartp[n++] = '\n'; cmdstartp[n] = '\0'; cmdendp = cmdstartp+n; cmdp = cmdstartp; if(ct->w == nil) curtext = nil; else curtext = &ct->w->body; resetxec(); if(editerrc == nil){ editerrc = chancreate(sizeof(char*), 0); lastpat = allocstring(0); } threadcreate(editthread, nil, STACK); err = recvp(editerrc); editing = Inactive; if(err != nil){ if(err[0] != '\0') warning(nil, "Edit: %s\n", err); free(err); } /* update everyone whose edit log has data */ allwindows(allupdate, nil); } int getch(void) { if(*cmdp == *cmdendp) return -1; return *cmdp++; } int nextc(void) { if(*cmdp == *cmdendp) return -1; return *cmdp; } void ungetch(void) { if(--cmdp < cmdstartp) error("ungetch"); } long getnum(int signok) { long n; int c, sign; n = 0; sign = 1; if(signok>1 && nextc()=='-'){ sign = -1; getch(); } if((c=nextc())<'0' || '9'<c) /* no number defaults to 1 */ return sign; while('0'<=(c=getch()) && c<='9') n = n*10 + (c-'0'); ungetch(); return sign*n; } int cmdskipbl(void) { int c; do c = getch(); while(c==' ' || c=='\t'); if(c >= 0) ungetch(); return c; } /* * Check that list has room for one more element. */ void growlist(List *l) { if(l->listptr==0 || l->nalloc==0){ l->nalloc = INCR; l->listptr = emalloc(INCR*sizeof(void*)); l->nused = 0; }else if(l->nused == l->nalloc){ l->listptr = erealloc(l->listptr, (l->nalloc+INCR)*sizeof(void*)); memset(l->ptr+l->nalloc, 0, INCR*sizeof(void*)); l->nalloc += INCR; } } /* * Remove the ith element from the list */ void dellist(List *l, int i) { memmove(&l->ptr[i], &l->ptr[i+1], (l->nused-(i+1))*sizeof(void*)); l->nused--; } /* * Add a new element, whose position is i, to the list */ void inslist(List *l, int i, void *v) { growlist(l); memmove(&l->ptr[i+1], &l->ptr[i], (l->nused-i)*sizeof(void*)); l->ptr[i] = v; l->nused++; } void listfree(List *l) { free(l->listptr); free(l); } String* allocstring(int n) { String *s; s = emalloc(sizeof(String)); s->n = n; s->nalloc = n+10; s->r = emalloc(s->nalloc*sizeof(Rune)); s->r[n] = '\0'; return s; } void freestring(String *s) { free(s->r); free(s); } Cmd* newcmd(void){ Cmd *p; p = emalloc(sizeof(Cmd)); inslist(&cmdlist, cmdlist.nused, p); return p; } String* newstring(int n) { String *p; p = allocstring(n); inslist(&stringlist, stringlist.nused, p); return p; } Addr* newaddr(void) { Addr *p; p = emalloc(sizeof(Addr)); inslist(&addrlist, addrlist.nused, p); return p; } void freecmd(void) { int i; while(cmdlist.nused > 0) free(cmdlist.ucharptr[--cmdlist.nused]); while(addrlist.nused > 0) free(addrlist.ucharptr[--addrlist.nused]); while(stringlist.nused>0){ i = --stringlist.nused; freestring(stringlist.stringptr[i]); } } void okdelim(int c) { if(c=='\\' || ('a'<=c && c<='z') || ('A'<=c && c<='Z') || ('0'<=c && c<='9')) editerror("bad delimiter %c\n", c); } void atnl(void) { int c; cmdskipbl(); c = getch(); if(c != '\n') editerror("newline expected (saw %C)", c); } void Straddc(String *s, int c) { if(s->n+1 >= s->nalloc){ s->nalloc += 10; s->r = erealloc(s->r, s->nalloc*sizeof(Rune)); } s->r[s->n++] = c; s->r[s->n] = '\0'; } void getrhs(String *s, int delim, int cmd) { int c; while((c = getch())>0 && c!=delim && c!='\n'){ if(c == '\\'){ if((c=getch()) <= 0) error("bad right hand side"); if(c == '\n'){ ungetch(); c='\\'; }else if(c == 'n') c='\n'; else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */ Straddc(s, '\\'); } Straddc(s, c); } ungetch(); /* let client read whether delimiter, '\n' or whatever */ } String * collecttoken(char *end) { String *s = newstring(0); int c; while((c=nextc())==' ' || c=='\t') Straddc(s, getch()); /* blanks significant for getname() */ while((c=getch())>0 && utfrune(end, c)==0) Straddc(s, c); if(c != '\n') atnl(); return s; } String * collecttext(void) { String *s; int begline, i, c, delim; s = newstring(0); if(cmdskipbl()=='\n'){ getch(); i = 0; do{ begline = i; while((c = getch())>0 && c!='\n') i++, Straddc(s, c); i++, Straddc(s, '\n'); if(c < 0) goto Return; }while(s->r[begline]!='.' || s->r[begline+1]!='\n'); s->r[s->n-2] = '\0'; s->n -= 2; }else{ okdelim(delim = getch()); getrhs(s, delim, 'a'); if(nextc()==delim) getch(); atnl(); } Return: return s; } int cmdlookup(int c) { int i; for(i=0; cmdtab[i].cmdc; i++) if(cmdtab[i].cmdc == c) return i; return -1; } Cmd* parsecmd(int nest) { int i, c; struct cmdtab *ct; Cmd *cp, *ncp; Cmd cmd; cmd.next = cmd.cmd = 0; cmd.re = 0; cmd.flag = cmd.num = 0; cmd.addr = compoundaddr(); if(cmdskipbl() == -1) return 0; if((c=getch())==-1) return 0; cmd.cmdc = c; if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */ getch(); /* the 'd' */ cmd.cmdc='c'|0x100; } i = cmdlookup(cmd.cmdc); if(i >= 0){ if(cmd.cmdc == '\n') goto Return; /* let nl_cmd work it all out */ ct = &cmdtab[i];