123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587 |
- /*
- * 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);
- }
- return 0;
- }
- 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 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);
- }
|