12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586 |
- /*
- * Editor
- */
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <regexp.h>
- enum
- {
- FNSIZE = 128, /* file name */
- LBSIZE = 4096, /* max line size */
- BLKSIZE = 4096, /* block size in temp file */
- NBLK = 8191, /* max size of temp file */
- ESIZE = 256, /* max size of reg exp */
- GBSIZE = 256, /* max size of global command */
- MAXSUB = 9, /* max number of sub reg exp */
- ESCFLG = 0xFFFF, /* escape Rune - user defined code */
- EOF = -1,
- };
- void (*oldhup)(int);
- void (*oldquit)(int);
- int* addr1;
- int* addr2;
- int anymarks;
- Biobuf bcons;
- int col;
- long count;
- int* dol;
- int* dot;
- int fchange;
- char file[FNSIZE];
- Rune genbuf[LBSIZE];
- int given;
- Rune* globp;
- int iblock;
- int ichanged;
- int io;
- Biobuf iobuf;
- int lastc;
- char line[70];
- Rune* linebp;
- Rune linebuf[LBSIZE];
- int listf;
- int listn;
- Rune* loc1;
- Rune* loc2;
- int names[26];
- int nleft;
- int oblock;
- int oflag;
- Reprog *pattern;
- int peekc;
- int pflag;
- int rescuing;
- Rune rhsbuf[LBSIZE/2];
- char savedfile[FNSIZE];
- jmp_buf savej;
- int subnewa;
- int subolda;
- Resub subexp[MAXSUB];
- char* tfname;
- int tline;
- int waiting;
- int wrapp;
- int* zero;
- char Q[] = "";
- char T[] = "TMP";
- char WRERR[] = "WRITE ERROR";
- int bpagesize = 20;
- char hex[] = "0123456789abcdef";
- char* linp = line;
- ulong nlall = 128;
- int tfile = -1;
- int vflag = 1;
- void add(int);
- int* address(void);
- int append(int(*)(void), int*);
- void browse(void);
- void callunix(void);
- void commands(void);
- void compile(int);
- int compsub(void);
- void dosub(void);
- void error(char*);
- int match(int*);
- void exfile(int);
- void filename(int);
- Rune* getblock(int, int);
- int getchr(void);
- int getcopy(void);
- int getfile(void);
- Rune* getline(int);
- int getnum(void);
- int getsub(void);
- int gettty(void);
- void global(int);
- void init(void);
- void join(void);
- void move(int);
- void newline(void);
- void nonzero(void);
- void notifyf(void*, char*);
- Rune* place(Rune*, Rune*, Rune*);
- void printcom(void);
- void putchr(int);
- void putd(void);
- void putfile(void);
- int putline(void);
- void putshst(Rune*);
- void putst(char*);
- void quit(void);
- void rdelete(int*, int*);
- void regerror(char *);
- void reverse(int*, int*);
- void setnoaddr(void);
- void setwide(void);
- void squeeze(int);
- void substitute(int);
- void
- main(int argc, char *argv[])
- {
- char *p1, *p2;
- Binit(&bcons, 0, OREAD);
- notify(notifyf);
- ARGBEGIN {
- case 'o':
- oflag = 1;
- vflag = 0;
- break;
- } ARGEND
- USED(argc);
- if(*argv && (strcmp(*argv, "-") == 0)) {
- argv++;
- vflag = 0;
- }
- if(oflag) {
- p1 = "/fd/1";
- p2 = savedfile;
- while(*p2++ = *p1++)
- ;
- globp = L"a";
- } else
- if(*argv) {
- p1 = *argv;
- p2 = savedfile;
- while(*p2++ = *p1++)
- if(p2 >= &savedfile[sizeof(savedfile)])
- p2--;
- globp = L"r";
- }
- zero = malloc((nlall+5)*sizeof(int*));
- tfname = mktemp("/tmp/eXXXXX");
- init();
- setjmp(savej);
- commands();
- quit();
- }
- void
- commands(void)
- {
- int *a1, c, temp;
- char lastsep;
- Dir *d;
- for(;;) {
- if(pflag) {
- pflag = 0;
- addr1 = addr2 = dot;
- printcom();
- }
- c = '\n';
- for(addr1 = 0;;) {
- lastsep = c;
- a1 = address();
- c = getchr();
- if(c != ',' && c != ';')
- break;
- if(lastsep == ',')
- error(Q);
- if(a1 == 0) {
- a1 = zero+1;
- if(a1 > dol)
- a1--;
- }
- addr1 = a1;
- if(c == ';')
- dot = a1;
- }
- if(lastsep != '\n' && a1 == 0)
- a1 = dol;
- if((addr2=a1) == 0) {
- given = 0;
- addr2 = dot;
- } else
- given = 1;
- if(addr1 == 0)
- addr1 = addr2;
- switch(c) {
- case 'a':
- add(0);
- continue;
- case 'b':
- nonzero();
- browse();
- continue;
- case 'c':
- nonzero();
- newline();
- rdelete(addr1, addr2);
- append(gettty, addr1-1);
- continue;
- case 'd':
- nonzero();
- newline();
- rdelete(addr1, addr2);
- continue;
- case 'E':
- fchange = 0;
- c = 'e';
- case 'e':
- setnoaddr();
- if(vflag && fchange) {
- fchange = 0;
- error(Q);
- }
- filename(c);
- init();
- addr2 = zero;
- goto caseread;
- case 'f':
- setnoaddr();
- filename(c);
- putst(savedfile);
- continue;
- case 'g':
- global(1);
- continue;
- case 'i':
- add(-1);
- continue;
- case 'j':
- if(!given)
- addr2++;
- newline();
- join();
- continue;
- case 'k':
- nonzero();
- c = getchr();
- if(c < 'a' || c > 'z')
- error(Q);
- newline();
- names[c-'a'] = *addr2 & ~01;
- anymarks |= 01;
- continue;
- case 'm':
- move(0);
- continue;
- case 'n':
- listn++;
- newline();
- printcom();
- continue;
- case '\n':
- if(a1==0) {
- a1 = dot+1;
- addr2 = a1;
- addr1 = a1;
- }
- if(lastsep==';')
- addr1 = a1;
- printcom();
- continue;
- case 'l':
- listf++;
- case 'p':
- case 'P':
- newline();
- printcom();
- continue;
- case 'Q':
- fchange = 0;
- case 'q':
- setnoaddr();
- newline();
- quit();
- case 'r':
- filename(c);
- caseread:
- if((io=open(file, OREAD)) < 0) {
- lastc = '\n';
- error(file);
- }
- if((d = dirfstat(io)) != nil){
- if(d->mode & DMAPPEND)
- print("warning: %s is append only\n", file);
- free(d);
- }
- Binit(&iobuf, io, OREAD);
- setwide();
- squeeze(0);
- c = zero != dol;
- append(getfile, addr2);
- exfile(OREAD);
- fchange = c;
- continue;
- case 's':
- nonzero();
- substitute(globp != 0);
- continue;
- case 't':
- move(1);
- continue;
- case 'u':
- nonzero();
- newline();
- if((*addr2&~01) != subnewa)
- error(Q);
- *addr2 = subolda;
- dot = addr2;
- continue;
- case 'v':
- global(0);
- continue;
- case 'W':
- wrapp++;
- case 'w':
- setwide();
- squeeze(dol>zero);
- temp = getchr();
- if(temp != 'q' && temp != 'Q') {
- peekc = temp;
- temp = 0;
- }
- filename(c);
- if(!wrapp ||
- ((io = open(file, OWRITE)) == -1) ||
- ((seek(io, 0L, 2)) == -1))
- if((io = create(file, OWRITE, 0666)) < 0)
- error(file);
- Binit(&iobuf, io, OWRITE);
- wrapp = 0;
- if(dol > zero)
- putfile();
- exfile(OWRITE);
- if(addr1<=zero+1 && addr2==dol)
- fchange = 0;
- if(temp == 'Q')
- fchange = 0;
- if(temp)
- quit();
- continue;
- case '=':
- setwide();
- squeeze(0);
- newline();
- count = addr2 - zero;
- putd();
- putchr(L'\n');
- continue;
- case '!':
- callunix();
- continue;
- case EOF:
- return;
- }
- error(Q);
- }
- }
- void
- printcom(void)
- {
- int *a1;
- nonzero();
- a1 = addr1;
- do {
- if(listn) {
- count = a1-zero;
- putd();
- putchr(L'\t');
- }
- putshst(getline(*a1++));
- } while(a1 <= addr2);
- dot = addr2;
- listf = 0;
- listn = 0;
- pflag = 0;
- }
- int*
- address(void)
- {
- int sign, *a, opcnt, nextopand, *b, c;
- nextopand = -1;
- sign = 1;
- opcnt = 0;
- a = dot;
- do {
- do {
- c = getchr();
- } while(c == ' ' || c == '\t');
- if(c >= '0' && c <= '9') {
- peekc = c;
- if(!opcnt)
- a = zero;
- a += sign*getnum();
- } else
- switch(c) {
- case '$':
- a = dol;
- case '.':
- if(opcnt)
- error(Q);
- break;
- case '\'':
- c = getchr();
- if(opcnt || c < 'a' || c > 'z')
- error(Q);
- a = zero;
- do {
- a++;
- } while(a <= dol && names[c-'a'] != (*a & ~01));
- break;
- case '?':
- sign = -sign;
- case '/':
- compile(c);
- b = a;
- for(;;) {
- a += sign;
- if(a <= zero)
- a = dol;
- if(a > dol)
- a = zero;
- if(match(a))
- break;
- if(a == b)
- error(Q);
- }
- break;
- default:
- if(nextopand == opcnt) {
- a += sign;
- if(a < zero || dol < a)
- continue; /* error(Q); */
- }
- if(c != '+' && c != '-' && c != '^') {
- peekc = c;
- if(opcnt == 0)
- a = 0;
- return a;
- }
- sign = 1;
- if(c != '+')
- sign = -sign;
- nextopand = ++opcnt;
- continue;
- }
- sign = 1;
- opcnt++;
- } while(zero <= a && a <= dol);
- error(Q);
- return 0;
- }
- int
- getnum(void)
- {
- int r, c;
- r = 0;
- for(;;) {
- c = getchr();
- if(c < '0' || c > '9')
- break;
- r = r*10 + (c-'0');
- }
- peekc = c;
- return r;
- }
- void
- setwide(void)
- {
- if(!given) {
- addr1 = zero + (dol>zero);
- addr2 = dol;
- }
- }
- void
- setnoaddr(void)
- {
- if(given)
- error(Q);
- }
- void
- nonzero(void)
- {
- squeeze(1);
- }
- void
- squeeze(int i)
- {
- if(addr1 < zero+i || addr2 > dol || addr1 > addr2)
- error(Q);
- }
- void
- newline(void)
- {
- int c;
- c = getchr();
- if(c == '\n' || c == EOF)
- return;
- if(c == 'p' || c == 'l' || c == 'n') {
- pflag++;
- if(c == 'l')
- listf++;
- else
- if(c == 'n')
- listn++;
- c = getchr();
- if(c == '\n')
- return;
- }
- error(Q);
- }
- void
- filename(int comm)
- {
- char *p1, *p2;
- Rune rune;
- int c;
- count = 0;
- c = getchr();
- if(c == '\n' || c == EOF) {
- p1 = savedfile;
- if(*p1 == 0 && comm != 'f')
- error(Q);
- p2 = file;
- while(*p2++ = *p1++)
- ;
- return;
- }
- if(c != ' ')
- error(Q);
- while((c=getchr()) == ' ')
- ;
- if(c == '\n')
- error(Q);
- p1 = file;
- do {
- if(p1 >= &file[sizeof(file)-6] || c == ' ' || c == EOF)
- error(Q);
- rune = c;
- p1 += runetochar(p1, &rune);
- } while((c=getchr()) != '\n');
- *p1 = 0;
- if(savedfile[0] == 0 || comm == 'e' || comm == 'f') {
- p1 = savedfile;
- p2 = file;
- while(*p1++ = *p2++)
- ;
- }
- }
- void
- exfile(int om)
- {
- if(om == OWRITE)
- if(Bflush(&iobuf) < 0)
- error(Q);
- close(io);
- io = -1;
- if(vflag) {
- putd();
- putchr(L'\n');
- }
- }
- void
- error1(char *s)
- {
- int c;
- wrapp = 0;
- listf = 0;
- listn = 0;
- count = 0;
- seek(0, 0, 2);
- pflag = 0;
- if(globp)
- lastc = '\n';
- globp = 0;
- peekc = lastc;
- if(lastc)
- for(;;) {
- c = getchr();
- if(c == '\n' || c == EOF)
- break;
- }
- if(io > 0) {
- close(io);
- io = -1;
- }
- putchr(L'?');
- putst(s);
- }
- void
- error(char *s)
- {
- error1(s);
- longjmp(savej, 1);
- }
- void
- rescue(void)
- {
- rescuing = 1;
- if(dol > zero) {
- addr1 = zero+1;
- addr2 = dol;
- io = create("ed.hup", OWRITE, 0666);
- if(io > 0){
- Binit(&iobuf, io, OWRITE);
- putfile();
- }
- }
- fchange = 0;
- quit();
- }
- void
- notifyf(void *a, char *s)
- {
- if(strcmp(s, "interrupt") == 0){
- if(rescuing || waiting)
- noted(NCONT);
- putchr(L'\n');
- lastc = '\n';
- error1(Q);
- notejmp(a, savej, 0);
- }
- if(strcmp(s, "hangup") == 0){
- if(rescuing)
- noted(NDFLT);
- rescue();
- }
- fprint(2, "ed: note: %s\n", s);
- abort();
- }
- int
- getchr(void)
- {
- if(lastc = peekc) {
- peekc = 0;
- return lastc;
- }
- if(globp) {
- if((lastc=*globp++) != 0)
- return lastc;
- globp = 0;
- return EOF;
- }
- lastc = Bgetrune(&bcons);
- return lastc;
- }
- int
- gety(void)
- {
- int c;
- Rune *gf, *p;
- p = linebuf;
- gf = globp;
- for(;;) {
- c = getchr();
- if(c == '\n') {
- *p = 0;
- return 0;
- }
- if(c == EOF) {
- if(gf)
- peekc = c;
- return c;
- }
- if(c == 0)
- continue;
- *p++ = c;
- if(p >= &linebuf[LBSIZE-2])
- error(Q);
- }
- }
- int
- gettty(void)
- {
- int rc;
- rc = gety();
- if(rc)
- return rc;
- if(linebuf[0] == '.' && linebuf[1] == 0)
- return EOF;
- return 0;
- }
- int
- getfile(void)
- {
- int c;
- Rune *lp;
- lp = linebuf;
- do {
- c = Bgetrune(&iobuf);
- if(c < 0) {
- if(lp > linebuf) {
- putst("'\\n' appended");
- c = '\n';
- } else
- return EOF;
- }
- if(lp >= &linebuf[LBSIZE]) {
- lastc = '\n';
- error(Q);
- }
- *lp++ = c;
- count++;
- } while(c != '\n');
- lp[-1] = 0;
- return 0;
- }
- void
- putfile(void)
- {
- int *a1;
- Rune *lp;
- long c;
- a1 = addr1;
- do {
- lp = getline(*a1++);
- for(;;) {
- count++;
- c = *lp++;
- if(c == 0) {
- if(Bputrune(&iobuf, '\n') < 0)
- error(Q);
- break;
- }
- if(Bputrune(&iobuf, c) < 0)
- error(Q);
- }
- } while(a1 <= addr2);
- if(Bflush(&iobuf) < 0)
- error(Q);
- }
- int
- append(int (*f)(void), int *a)
- {
- int *a1, *a2, *rdot, nline, tl;
- nline = 0;
- dot = a;
- while((*f)() == 0) {
- if((dol-zero) >= nlall) {
- nlall += 512;
- a1 = realloc(zero, (nlall+5)*sizeof(int*));
- if(a1 == 0) {
- error("MEM?");
- rescue();
- }
- tl = a1 - zero; /* relocate pointers */
- zero += tl;
- addr1 += tl;
- addr2 += tl;
- dol += tl;
- dot += tl;
- }
- tl = putline();
- nline++;
- a1 = ++dol;
- a2 = a1+1;
- rdot = ++dot;
- while(a1 > rdot)
- *--a2 = *--a1;
- *rdot = tl;
- }
- return nline;
- }
- void
- add(int i)
- {
- if(i && (given || dol > zero)) {
- addr1--;
- addr2--;
- }
- squeeze(0);
- newline();
- append(gettty, addr2);
- }
- void
- browse(void)
- {
- int forward, n;
- static int bformat, bnum; /* 0 */
- forward = 1;
- peekc = getchr();
- if(peekc != '\n'){
- if(peekc == '-' || peekc == '+') {
- if(peekc == '-')
- forward = 0;
- getchr();
- }
- n = getnum();
- if(n > 0)
- bpagesize = n;
- }
- newline();
- if(pflag) {
- bformat = listf;
- bnum = listn;
- } else {
- listf = bformat;
- listn = bnum;
- }
- if(forward) {
- addr1 = addr2;
- addr2 += bpagesize;
- if(addr2 > dol)
- addr2 = dol;
- } else {
- addr1 = addr2-bpagesize;
- if(addr1 <= zero)
- addr1 = zero+1;
- }
- printcom();
- }
- void
- callunix(void)
- {
- int c, pid;
- Rune rune;
- char buf[512];
- char *p;
- setnoaddr();
- p = buf;
- while((c=getchr()) != EOF && c != '\n')
- if(p < &buf[sizeof(buf) - 6]) {
- rune = c;
- p += runetochar(p, &rune);
- }
- *p = 0;
- pid = fork();
- if(pid == 0) {
- execl("/bin/rc", "rc", "-c", buf, nil);
- exits("execl failed");
- }
- waiting = 1;
- while(waitpid() != pid)
- ;
- waiting = 0;
- if(vflag)
- putst("!");
- }
- void
- quit(void)
- {
- if(vflag && fchange && dol!=zero) {
- fchange = 0;
- error(Q);
- }
- remove(tfname);
- exits(0);
- }
- void
- onquit(int sig)
- {
- USED(sig);
- quit();
- }
- void
- rdelete(int *ad1, int *ad2)
- {
- int *a1, *a2, *a3;
- a1 = ad1;
- a2 = ad2+1;
- a3 = dol;
- dol -= a2 - a1;
- do {
- *a1++ = *a2++;
- } while(a2 <= a3);
- a1 = ad1;
- if(a1 > dol)
- a1 = dol;
- dot = a1;
- fchange = 1;
- }
- void
- gdelete(void)
- {
- int *a1, *a2, *a3;
- a3 = dol;
- for(a1=zero; (*a1&01)==0; a1++)
- if(a1>=a3)
- return;
- for(a2=a1+1; a2<=a3;) {
- if(*a2 & 01) {
- a2++;
- dot = a1;
- } else
- *a1++ = *a2++;
- }
- dol = a1-1;
- if(dot > dol)
- dot = dol;
- fchange = 1;
- }
- Rune*
- getline(int tl)
- {
- Rune *lp, *bp;
- int nl;
- lp = linebuf;
- bp = getblock(tl, OREAD);
- nl = nleft;
- tl &= ~((BLKSIZE/2) - 1);
- while(*lp++ = *bp++) {
- nl -= sizeof(Rune);
- if(nl == 0) {
- bp = getblock(tl += BLKSIZE/2, OREAD);
- nl = nleft;
- }
- }
- return linebuf;
- }
- int
- putline(void)
- {
- Rune *lp, *bp;
- int nl, tl;
- fchange = 1;
- lp = linebuf;
- tl = tline;
- bp = getblock(tl, OWRITE);
- nl = nleft;
- tl &= ~((BLKSIZE/2)-1);
- while(*bp = *lp++) {
- if(*bp++ == '\n') {
- bp[-1] = 0;
- linebp = lp;
- break;
- }
- nl -= sizeof(Rune);
- if(nl == 0) {
- tl += BLKSIZE/2;
- bp = getblock(tl, OWRITE);
- nl = nleft;
- }
- }
- nl = tline;
- tline += ((lp-linebuf) + 03) & 077776;
- return nl;
- }
- void
- blkio(int b, uchar *buf, long (*iofcn)(int, void *, long))
- {
- seek(tfile, b*BLKSIZE, 0);
- if((*iofcn)(tfile, buf, BLKSIZE) != BLKSIZE) {
- error(T);
- }
- }
- Rune*
- getblock(int atl, int iof)
- {
- int bno, off;
-
- static uchar ibuff[BLKSIZE];
- static uchar obuff[BLKSIZE];
- bno = atl / (BLKSIZE/2);
- off = (atl<<1) & (BLKSIZE-1) & ~03;
- if(bno >= NBLK) {
- lastc = '\n';
- error(T);
- }
- nleft = BLKSIZE - off;
- if(bno == iblock) {
- ichanged |= iof;
- return (Rune*)(ibuff+off);
- }
- if(bno == oblock)
- return (Rune*)(obuff+off);
- if(iof == OREAD) {
- if(ichanged)
- blkio(iblock, ibuff, write);
- ichanged = 0;
- iblock = bno;
- blkio(bno, ibuff, read);
- return (Rune*)(ibuff+off);
- }
- if(oblock >= 0)
- blkio(oblock, obuff, write);
- oblock = bno;
- return (Rune*)(obuff+off);
- }
- void
- init(void)
- {
- int *markp;
- close(tfile);
- tline = 2;
- for(markp = names; markp < &names[26]; )
- *markp++ = 0;
- subnewa = 0;
- anymarks = 0;
- iblock = -1;
- oblock = -1;
- ichanged = 0;
- if((tfile = create(tfname, ORDWR, 0600)) < 0){
- error1(T);
- exits(0);
- }
- dot = dol = zero;
- }
- void
- global(int k)
- {
- Rune *gp, globuf[GBSIZE];
- int c, *a1;
- if(globp)
- error(Q);
- setwide();
- squeeze(dol > zero);
- c = getchr();
- if(c == '\n')
- error(Q);
- compile(c);
- gp = globuf;
- while((c=getchr()) != '\n') {
- if(c == EOF)
- error(Q);
- if(c == '\\') {
- c = getchr();
- if(c != '\n')
- *gp++ = '\\';
- }
- *gp++ = c;
- if(gp >= &globuf[GBSIZE-2])
- error(Q);
- }
- if(gp == globuf)
- *gp++ = 'p';
- *gp++ = '\n';
- *gp = 0;
- for(a1=zero; a1<=dol; a1++) {
- *a1 &= ~01;
- if(a1 >= addr1 && a1 <= addr2 && match(a1) == k)
- *a1 |= 01;
- }
- /*
- * Special case: g/.../d (avoid n^2 algorithm)
- */
- if(globuf[0] == 'd' && globuf[1] == '\n' && globuf[2] == 0) {
- gdelete();
- return;
- }
- for(a1=zero; a1<=dol; a1++) {
- if(*a1 & 01) {
- *a1 &= ~01;
- dot = a1;
- globp = globuf;
- commands();
- a1 = zero;
- }
- }
- }
- void
- join(void)
- {
- Rune *gp, *lp;
- int *a1;
- nonzero();
- gp = genbuf;
- for(a1=addr1; a1<=addr2; a1++) {
- lp = getline(*a1);
- while(*gp = *lp++)
- if(gp++ >= &genbuf[LBSIZE-2])
- error(Q);
- }
- lp = linebuf;
- gp = genbuf;
- while(*lp++ = *gp++)
- ;
- *addr1 = putline();
- if(addr1 < addr2)
- rdelete(addr1+1, addr2);
- dot = addr1;
- }
- void
- substitute(int inglob)
- {
- int *mp, *a1, nl, gsubf, n;
- n = getnum(); /* OK even if n==0 */
- gsubf = compsub();
- for(a1 = addr1; a1 <= addr2; a1++) {
- if(match(a1)){
- int *ozero;
- int m = n;
- do {
- int span = loc2-loc1;
- if(--m <= 0) {
- dosub();
- if(!gsubf)
- break;
- if(span == 0) { /* null RE match */
- if(*loc2 == 0)
- break;
- loc2++;
- }
- }
- } while(match(0));
- if(m <= 0) {
- inglob |= 01;
- subnewa = putline();
- *a1 &= ~01;
- if(anymarks) {
- for(mp=names; mp<&names[26]; mp++)
- if(*mp == *a1)
- *mp = subnewa;
- }
- subolda = *a1;
- *a1 = subnewa;
- ozero = zero;
- nl = append(getsub, a1);
- addr2 += nl;
- nl += zero-ozero;
- a1 += nl;
- }
- }
- }
- if(inglob == 0)
- error(Q);
- }
- int
- compsub(void)
- {
- int seof, c;
- Rune *p;
- seof = getchr();
- if(seof == '\n' || seof == ' ')
- error(Q);
- compile(seof);
- p = rhsbuf;
- for(;;) {
- c = getchr();
- if(c == '\\') {
- c = getchr();
- *p++ = ESCFLG;
- if(p >= &rhsbuf[LBSIZE/2])
- error(Q);
- } else
- if(c == '\n' && (!globp || !globp[0])) {
- peekc = c;
- pflag++;
- break;
- } else
- if(c == seof)
- break;
- *p++ = c;
- if(p >= &rhsbuf[LBSIZE/2])
- error(Q);
- }
- *p = 0;
- peekc = getchr();
- if(peekc == 'g') {
- peekc = 0;
- newline();
- return 1;
- }
- newline();
- return 0;
- }
- int
- getsub(void)
- {
- Rune *p1, *p2;
- p1 = linebuf;
- if((p2 = linebp) == 0)
- return EOF;
- while(*p1++ = *p2++)
- ;
- linebp = 0;
- return 0;
- }
- void
- dosub(void)
- {
- Rune *lp, *sp, *rp;
- int c, n;
- lp = linebuf;
- sp = genbuf;
- rp = rhsbuf;
- while(lp < loc1)
- *sp++ = *lp++;
- while(c = *rp++) {
- if(c == '&'){
- sp = place(sp, loc1, loc2);
- continue;
- }
- if(c == ESCFLG && (c = *rp++) >= '1' && c < MAXSUB+'0') {
- n = c-'0';
- if(subexp[n].rsp && subexp[n].rep) {
- sp = place(sp, subexp[n].rsp, subexp[n].rep);
- continue;
- }
- error(Q);
- }
- *sp++ = c;
- if(sp >= &genbuf[LBSIZE])
- error(Q);
- }
- lp = loc2;
- loc2 = sp - genbuf + linebuf;
- while(*sp++ = *lp++)
- if(sp >= &genbuf[LBSIZE])
- error(Q);
- lp = linebuf;
- sp = genbuf;
- while(*lp++ = *sp++)
- ;
- }
- Rune*
- place(Rune *sp, Rune *l1, Rune *l2)
- {
- while(l1 < l2) {
- *sp++ = *l1++;
- if(sp >= &genbuf[LBSIZE])
- error(Q);
- }
- return sp;
- }
- void
- move(int cflag)
- {
- int *adt, *ad1, *ad2;
- nonzero();
- if((adt = address())==0) /* address() guarantees addr is in range */
- error(Q);
- newline();
- if(cflag) {
- int *ozero, delta;
- ad1 = dol;
- ozero = zero;
- append(getcopy, ad1++);
- ad2 = dol;
- delta = zero - ozero;
- ad1 += delta;
- adt += delta;
- } else {
- ad2 = addr2;
- for(ad1 = addr1; ad1 <= ad2;)
- *ad1++ &= ~01;
- ad1 = addr1;
- }
- ad2++;
- if(adt<ad1) {
- dot = adt + (ad2-ad1);
- if((++adt)==ad1)
- return;
- reverse(adt, ad1);
- reverse(ad1, ad2);
- reverse(adt, ad2);
- } else
- if(adt >= ad2) {
- dot = adt++;
- reverse(ad1, ad2);
- reverse(ad2, adt);
- reverse(ad1, adt);
- } else
- error(Q);
- fchange = 1;
- }
- void
- reverse(int *a1, int *a2)
- {
- int t;
- for(;;) {
- t = *--a2;
- if(a2 <= a1)
- return;
- *a2 = *a1;
- *a1++ = t;
- }
- }
- int
- getcopy(void)
- {
- if(addr1 > addr2)
- return EOF;
- getline(*addr1++);
- return 0;
- }
- void
- compile(int eof)
- {
- Rune c;
- char *ep;
- char expbuf[ESIZE];
- if((c = getchr()) == '\n') {
- peekc = c;
- c = eof;
- }
- if(c == eof) {
- if(!pattern)
- error(Q);
- return;
- }
- if(pattern) {
- free(pattern);
- pattern = 0;
- }
- ep = expbuf;
- do {
- if(c == '\\') {
- if(ep >= expbuf+sizeof(expbuf)) {
- error(Q);
- return;
- }
- ep += runetochar(ep, &c);
- if((c = getchr()) == '\n') {
- error(Q);
- return;
- }
- }
- if(ep >= expbuf+sizeof(expbuf)) {
- error(Q);
- return;
- }
- ep += runetochar(ep, &c);
- } while((c = getchr()) != eof && c != '\n');
- if(c == '\n')
- peekc = c;
- *ep = 0;
- pattern = regcomp(expbuf);
- }
- int
- match(int *addr)
- {
- if(!pattern)
- return 0;
- if(addr){
- if(addr == zero)
- return 0;
- subexp[0].rsp = getline(*addr);
- } else
- subexp[0].rsp = loc2;
- subexp[0].rep = 0;
- if(rregexec(pattern, linebuf, subexp, MAXSUB)) {
- loc1 = subexp[0].rsp;
- loc2 = subexp[0].rep;
- return 1;
- }
- loc1 = loc2 = 0;
- return 0;
-
- }
- void
- putd(void)
- {
- int r;
- r = count%10;
- count /= 10;
- if(count)
- putd();
- putchr(r + L'0');
- }
- void
- putst(char *sp)
- {
- Rune r;
- col = 0;
- for(;;) {
- sp += chartorune(&r, sp);
- if(r == 0)
- break;
- putchr(r);
- }
- putchr(L'\n');
- }
- void
- putshst(Rune *sp)
- {
- col = 0;
- while(*sp)
- putchr(*sp++);
- putchr(L'\n');
- }
- void
- putchr(int ac)
- {
- char *lp;
- int c;
- Rune rune;
- lp = linp;
- c = ac;
- if(listf) {
- if(c == '\n') {
- if(linp != line && linp[-1] == ' ') {
- *lp++ = '\\';
- *lp++ = 'n';
- }
- } else {
- if(col > (72-6-2)) {
- col = 8;
- *lp++ = '\\';
- *lp++ = '\n';
- *lp++ = '\t';
- }
- col++;
- if(c=='\b' || c=='\t' || c=='\\') {
- *lp++ = '\\';
- if(c == '\b')
- c = 'b';
- else
- if(c == '\t')
- c = 't';
- col++;
- } else
- if(c<' ' || c>='\177') {
- *lp++ = '\\';
- *lp++ = 'x';
- *lp++ = hex[c>>12];
- *lp++ = hex[c>>8&0xF];
- *lp++ = hex[c>>4&0xF];
- c = hex[c&0xF];
- col += 5;
- }
- }
- }
- rune = c;
- lp += runetochar(lp, &rune);
- if(c == '\n' || lp >= &line[sizeof(line)-5]) {
- linp = line;
- write(oflag? 2: 1, line, lp-line);
- return;
- }
- linp = lp;
- }
- char*
- mktemp(char *as)
- {
- char *s;
- unsigned pid;
- int i;
- pid = getpid();
- s = as;
- while(*s++)
- ;
- s--;
- while(*--s == 'X') {
- *s = pid % 10 + '0';
- pid /= 10;
- }
- s++;
- i = 'a';
- while(access(as, 0) != -1) {
- if(i == 'z')
- return "/";
- *s = i++;
- }
- return as;
- }
- void
- regerror(char *s)
- {
- USED(s);
- error(Q);
- }
|