00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <sys/types.h>
00031 #include <signal.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <unistd.h>
00035 #include <sys/wait.h>
00036 #include <stdio.h>
00037
00038
00039
00040
00041
00042
00043
00044
00045 #define NUL 0x00
00046 #define EOS 0x00
00047 #define SOH 0x01
00048 #define STX 0x02
00049 #define ETX 0x03
00050 #define EOT 0x04
00051 #define ENQ 0x05
00052 #define ACK 0x06
00053 #define BEL 0x07
00054 #define BS 0x08
00055 #define HT 0x09
00056 #define LF 0x0a
00057 #define NL '\n'
00058 #define VT 0x0b
00059 #define FF 0x0c
00060 #define CR 0x0d
00061 #define SO 0x0e
00062 #define SI 0x0f
00063 #define DLE 0x10
00064 #define DC1 0x11
00065 #define DC2 0x12
00066 #define DC3 0x13
00067 #define DC4 0x14
00068 #define NAK 0x15
00069 #define SYN 0x16
00070 #define ETB 0x17
00071 #define CAN 0x18
00072 #define EM 0x19
00073 #define SUB 0x1a
00074 #define ESC 0x1b
00075 #define FS 0x1c
00076 #define GS 0x1d
00077 #define RS 0x1e
00078 #define US 0x1f
00079 #define SP 0x20
00080 #define DEL 0x7f
00081
00082
00083 #define TRUE 1
00084 #define FALSE 0
00085 #define ERR -2
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 #define BOL '^'
00096 #define EOL '$'
00097 #define ANY '.'
00098 #define LITCHAR 'L'
00099 #define ESCAPE '\\'
00100 #define CCL '['
00101 #define CCLEND ']'
00102 #define NEGATE '^'
00103 #define NCCL '!'
00104 #define CLOSURE '*'
00105 #define OR_SYM '|'
00106 #define DITTO '&'
00107 #define OPEN '('
00108 #define CLOSE ')'
00109
00110
00111
00112
00113 #define CLS_SIZE 128
00114
00115
00116
00117
00118 typedef char BITMAP;
00119
00120 typedef struct token {
00121 char tok;
00122 char lchar;
00123 BITMAP *bitmap;
00124 struct token *next;
00125 } TOKEN;
00126
00127 #define TOKSIZE sizeof (TOKEN)
00128
00129
00130
00131
00132
00133 #define MAXSTR 132
00134
00135
00136
00137 #define max(a,b) ((a>b)?a:b)
00138 #define min(a,b) ((a<b)?a:b)
00139 #define toupper(c) (c>='a'&&c<='z'?c-32:c)
00140
00141
00142 #define FATAL (ERR-1)
00143 struct line {
00144 int l_stat;
00145 struct line *l_prev;
00146 struct line *l_next;
00147 char l_buff[1];
00148 };
00149
00150 typedef struct line LINE;
00151
00152 #define LINFREE 1
00153 #define LGLOB 2
00154
00155
00156 #define MAXLINE (sizeof(int) == 2 ? 256 : 8192)
00157 #define MAXPAT 256
00158
00159
00160 #define MAXFNAME (sizeof(int) == 2 ? 256 : 1024)
00161
00162 extern LINE line0;
00163 extern int curln, lastln, line1, line2, nlines;
00164 extern int nflg;
00165 extern int lflg;
00166 extern char *inptr;
00167 extern char linbuf[], *linptr;
00168 extern int truncflg;
00169 extern int eightbit;
00170 extern int nonascii;
00171 extern int nullchar;
00172 extern int truncated;
00173 extern int fchanged;
00174
00175 #define nextln(l) ((l)+1 > lastln ? 0 : (l)+1)
00176 #define prevln(l) ((l)-1 < 0 ? lastln : (l)-1)
00177
00178
00179
00180
00181
00182 _PROTOTYPE(int main, (int argc, char **argv));
00183 _PROTOTYPE(static char *match, (char *lin, TOKEN *pat, char *boln));
00184 _PROTOTYPE(char *amatch, (char *lin, TOKEN *pat, char *boln));
00185 _PROTOTYPE(int append, (int line, int glob));
00186 _PROTOTYPE(BITMAP *makebitmap, (unsigned size));
00187 _PROTOTYPE(int setbit, (unsigned c, char *map, unsigned val));
00188 _PROTOTYPE(int testbit, (unsigned c, char *map));
00189 _PROTOTYPE(char *catsub, (char *from, char *to, char *sub, char *new, char *newend));
00190 _PROTOTYPE(int ckglob, (void));
00191 _PROTOTYPE(int deflt, (int def1, int def2));
00192 _PROTOTYPE(int del, (int from, int to));
00193 _PROTOTYPE(int docmd, (int glob));
00194 _PROTOTYPE(int dolst, (int line1, int line2));
00195 _PROTOTYPE(char *dodash, (int delim, char *src, char *map));
00196 _PROTOTYPE(int doglob, (void));
00197 _PROTOTYPE(int doprnt, (int from, int to));
00198 _PROTOTYPE(void prntln, (char *str, int vflg, int lin));
00199 _PROTOTYPE(void putcntl, (int c, FILE *stream));
00200 _PROTOTYPE(int doread, (int lin, char *fname));
00201 _PROTOTYPE(int dowrite, (int from, int to, char *fname, int apflg));
00202 _PROTOTYPE(void intr, (int sig));
00203 _PROTOTYPE(int egets, (char *str, int size, FILE *stream));
00204 _PROTOTYPE(int esc, (char **s));
00205 _PROTOTYPE(int find, (TOKEN *pat, int dir));
00206 _PROTOTYPE(char *getfn, (void));
00207 _PROTOTYPE(int getlst, (void));
00208 _PROTOTYPE(int getnum, (int first));
00209 _PROTOTYPE(int getone, (void));
00210 _PROTOTYPE(TOKEN *getpat, (char *arg));
00211 _PROTOTYPE(LINE *getptr, (int num));
00212 _PROTOTYPE(int getrhs, (char *sub));
00213 _PROTOTYPE(char *gettxt, (int num));
00214 _PROTOTYPE(int ins, (char *str));
00215 _PROTOTYPE(int System, (char *c));
00216 _PROTOTYPE(int join, (int first, int last));
00217 _PROTOTYPE(TOKEN *makepat, (char *arg, int delim));
00218 _PROTOTYPE(char *maksub, (char *sub, int subsz));
00219 _PROTOTYPE(char *matchs, (char *line, TOKEN *pat, int ret_endp));
00220 _PROTOTYPE(int move, (int num));
00221 _PROTOTYPE(int transfer, (int num));
00222 _PROTOTYPE(int omatch, (char **linp, TOKEN *pat, char *boln));
00223 _PROTOTYPE(TOKEN *optpat, (void));
00224 _PROTOTYPE(int set, (void));
00225 _PROTOTYPE(int show, (void));
00226 _PROTOTYPE(void relink, (LINE *a, LINE *x, LINE *y, LINE *b));
00227 _PROTOTYPE(void clrbuf, (void));
00228 _PROTOTYPE(void set_buf, (void));
00229 _PROTOTYPE(int subst, (TOKEN *pat, char *sub, int gflg, int pflag));
00230 _PROTOTYPE(void unmakepat, (TOKEN *head));
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 char *paropen[9], *parclose[9];
00246 int between, parnum;
00247
00248 char *amatch(lin, pat, boln)
00249 char *lin;
00250 TOKEN *pat;
00251 char *boln;
00252 {
00253 between = 0;
00254 parnum = 0;
00255
00256 lin = match(lin, pat, boln);
00257
00258 if (between) return 0;
00259
00260 while (parnum < 9) {
00261 paropen[parnum] = parclose[parnum] = "";
00262 parnum++;
00263 }
00264 return lin;
00265 }
00266
00267 static char *match(lin, pat, boln)
00268 char *lin;
00269 TOKEN *pat;
00270 char *boln;
00271 {
00272 register char *bocl, *rval, *strstart;
00273
00274 if (pat == 0) return 0;
00275
00276 strstart = lin;
00277
00278 while (pat) {
00279 if (pat->tok == CLOSURE && pat->next) {
00280
00281
00282
00283
00284 pat = pat->next;
00285
00286
00287
00288 bocl = lin;
00289
00290 while (*lin && omatch(&lin, pat, boln));
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 if (pat = pat->next) {
00306 int savbtwn = between;
00307 int savprnm = parnum;
00308
00309 while (bocl <= lin) {
00310 if (rval = match(lin, pat, boln)) {
00311
00312 return(rval);
00313 } else {
00314 --lin;
00315 between = savbtwn;
00316 parnum = savprnm;
00317 }
00318 }
00319 return(0);
00320 }
00321 } else if (pat->tok == OPEN) {
00322 if (between || parnum >= 9) return 0;
00323 paropen[parnum] = lin;
00324 between = 1;
00325 pat = pat->next;
00326 } else if (pat->tok == CLOSE) {
00327 if (!between) return 0;
00328 parclose[parnum++] = lin;
00329 between = 0;
00330 pat = pat->next;
00331 } else if (omatch(&lin, pat, boln)) {
00332 pat = pat->next;
00333 } else {
00334 return(0);
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 return((char *) max(strstart, lin));
00354 }
00355
00356
00357
00358
00359
00360
00361 int append(line, glob)
00362 int line, glob;
00363 {
00364 int stat;
00365 char lin[MAXLINE];
00366
00367 if (glob) return(ERR);
00368 curln = line;
00369 while (1) {
00370 if (nflg) printf("%6d. ", curln + 1);
00371
00372 if (fgets(lin, MAXLINE, stdin) == NULL) return(EOF);
00373 if (lin[0] == '.' && lin[1] == '\n') return (0);
00374 stat = ins(lin);
00375 if (stat < 0) return(ERR);
00376
00377 }
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 #ifdef DEBUG
00391
00392 #endif
00393
00394
00395
00396
00397 BITMAP *makebitmap(size)
00398 unsigned size;
00399 {
00400
00401
00402
00403
00404
00405 unsigned *map, numbytes;
00406
00407 numbytes = (size >> 3) + ((size & 0x07) ? 1 : 0);
00408
00409 #ifdef DEBUG
00410 printf("Making a %d bit map (%d bytes required)\n", size, numbytes);
00411 #endif
00412
00413 if (map = (unsigned *) malloc(numbytes + sizeof(unsigned))) {
00414 *map = size;
00415 memset(map + 1, 0, numbytes);
00416 }
00417
00418 return((BITMAP *) map);
00419 }
00420
00421 int setbit(c, map, val)
00422 unsigned c, val;
00423 char *map;
00424 {
00425
00426
00427
00428 if (c >= *(unsigned *) map)
00429 return 0;
00430
00431 map += sizeof(unsigned);
00432
00433 if (val)
00434 map[c >> 3] |= 1 << (c & 0x07);
00435 else
00436 map[c >> 3] &= ~(1 << (c & 0x07));
00437
00438 return 1;
00439 }
00440
00441 int testbit(c, map)
00442 unsigned c;
00443 char *map;
00444 {
00445
00446
00447 if (c >= *(unsigned *) map) return 0;
00448
00449 map += sizeof(unsigned);
00450
00451 return(map[c >> 3] & (1 << (c & 0x07)));
00452 }
00453
00454
00455
00456
00457
00458
00459 extern char *paropen[9], *parclose[9];
00460
00461 char *catsub(from, to, sub, new, newend)
00462 char *from, *to, *sub, *new, *newend;
00463 {
00464 char *cp, *cp2;
00465
00466 for (cp = new; *sub != EOS && cp < newend;) {
00467 if (*sub == DITTO) for (cp2 = from; cp2 < to;) {
00468 *cp++ = *cp2++;
00469 if (cp >= newend) break;
00470 }
00471 else if (*sub == ESCAPE) {
00472 sub++;
00473 if ('1' <= *sub && *sub <= '9') {
00474 char *parcl = parclose[*sub - '1'];
00475
00476 for (cp2 = paropen[*sub - '1']; cp2 < parcl;) {
00477 *cp++ = *cp2++;
00478 if (cp >= newend) break;
00479 }
00480 } else
00481 *cp++ = *sub;
00482 } else
00483 *cp++ = *sub;
00484
00485 sub++;
00486 }
00487
00488 return(cp);
00489 }
00490
00491
00492
00493
00494
00495
00496 int ckglob()
00497 {
00498 TOKEN *glbpat;
00499 char c, delim;
00500 char lin[MAXLINE];
00501 int num;
00502 LINE *ptr;
00503
00504 c = *inptr;
00505
00506 if (c != 'g' && c != 'v') return(0);
00507
00508 if (deflt(1, lastln) < 0) return(ERR);
00509
00510 delim = *++inptr;
00511 if (delim <= ' ') return(ERR);
00512
00513 glbpat = optpat();
00514
00515 if (*inptr == delim) inptr++;
00516
00517 ptr = getptr(1);
00518 for (num = 1; num <= lastln; num++) {
00519 ptr->l_stat &= ~LGLOB;
00520 if (line1 <= num && num <= line2) {
00521 strcpy(lin, ptr->l_buff);
00522 strcat(lin, "\n");
00523 if (matchs(lin, glbpat, 0)) {
00524 if (c == 'g') ptr->l_stat |= LGLOB;
00525 } else {
00526 if (c == 'v') ptr->l_stat |= LGLOB;
00527 }
00528 }
00529 ptr = ptr->l_next;
00530 }
00531 return(1);
00532 }
00533
00534
00535
00536
00537
00538
00539 int deflt(def1, def2)
00540 int def1, def2;
00541 {
00542 if (nlines == 0) {
00543 line1 = def1;
00544 line2 = def2;
00545 }
00546 if (line1 > line2 || line1 <= 0) return(ERR);
00547 return(0);
00548 }
00549
00550
00551
00552
00553
00554
00555 int del(from, to)
00556 int from, to;
00557 {
00558 LINE *first, *last, *next, *tmp;
00559
00560 if (from < 1) from = 1;
00561 first = getptr(prevln(from));
00562 last = getptr(nextln(to));
00563 next = first->l_next;
00564 while (next != last && next != &line0) {
00565 tmp = next->l_next;
00566 free((char *) next);
00567 next = tmp;
00568 }
00569 relink(first, last, first, last);
00570 lastln -= (to - from) + 1;
00571 curln = prevln(from);
00572 return(0);
00573 }
00574
00575
00576
00577
00578
00579
00580 char fname[MAXFNAME];
00581 int fchanged;
00582 extern int nofname;
00583
00584 extern int mark[];
00585
00586 int docmd(glob)
00587 int glob;
00588 {
00589 static char rhs[MAXPAT];
00590 TOKEN *subpat;
00591 int c, err, line3;
00592 int apflg, pflag, gflag;
00593 int nchng;
00594 char *fptr;
00595
00596 pflag = FALSE;
00597 while (*inptr == SP && *inptr == HT) inptr++;
00598
00599 c = *inptr++;
00600
00601 switch (c) {
00602 case NL:
00603 if (nlines == 0) {
00604 if ((line2 = nextln(curln)) == 0) return(ERR);
00605 }
00606 curln = line2;
00607 return(1);
00608 break;
00609
00610 case '=': printf("%d\n", line2); break;
00611
00612 case 'a':
00613 if (*inptr != NL || nlines > 1) return(ERR);
00614
00615 if (append(line1, glob) < 0) return(ERR);;
00616 fchanged = TRUE;
00617 break;
00618
00619 case 'c':
00620 if (*inptr != NL) return(ERR);
00621
00622 if (deflt(curln, curln) < 0) return(ERR);
00623
00624 if (del(line1, line2) < 0) return(ERR);
00625 if (append(curln, glob) < 0) return (ERR);
00626 fchanged = TRUE;
00627 break;
00628
00629 case 'd':
00630 if (*inptr != NL) return(ERR);
00631
00632 if (deflt(curln, curln) < 0) return(ERR);
00633
00634 if (del(line1, line2) < 0) return(ERR);
00635 if (nextln(curln) != 0) curln = nextln(curln);
00636 fchanged = TRUE;
00637 break;
00638
00639 case 'e':
00640 if (nlines > 0) return(ERR);
00641 if (fchanged) {
00642 fchanged = FALSE;
00643 return(ERR);
00644 }
00645
00646
00647 case 'E':
00648 if (nlines > 0) return(ERR);
00649
00650 if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
00651
00652 if ((fptr = getfn()) == NULL) return(ERR);
00653
00654 clrbuf();
00655 if ((err = doread(0, fptr)) < 0) return(err);
00656
00657 strcpy(fname, fptr);
00658 fchanged = FALSE;
00659 break;
00660
00661 case 'f':
00662 if (nlines > 0) return(ERR);
00663
00664 if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
00665
00666 if ((fptr = getfn()) == NULL) return(ERR);
00667
00668 if (nofname)
00669 printf("%s\n", fname);
00670 else
00671 strcpy(fname, fptr);
00672 break;
00673
00674 case 'i':
00675 if (*inptr != NL || nlines > 1) return(ERR);
00676
00677 if (append(prevln(line1), glob) < 0) return(ERR);
00678 fchanged = TRUE;
00679 break;
00680
00681 case 'j':
00682 if (*inptr != NL || deflt(curln, curln + 1) < 0) return(ERR);
00683
00684 if (join(line1, line2) < 0) return(ERR);
00685 break;
00686
00687 case 'k':
00688 while (*inptr == ' ' || *inptr == HT) inptr++;
00689
00690 if (*inptr < 'a' || *inptr > 'z') return ERR;
00691 c = *inptr++;
00692
00693 if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
00694
00695 mark[c - 'a'] = line1;
00696 break;
00697
00698 case 'l':
00699 if (*inptr != NL) return(ERR);
00700 if (deflt(curln, curln) < 0) return (ERR);
00701 if (dolst(line1, line2) < 0) return (ERR);
00702 break;
00703
00704 case 'm':
00705 if ((line3 = getone()) < 0) return(ERR);
00706 if (deflt(curln, curln) < 0) return (ERR);
00707 if (move(line3) < 0) return (ERR);
00708 fchanged = TRUE;
00709 break;
00710
00711 case 'P':
00712 case 'p':
00713 if (*inptr != NL) return(ERR);
00714 if (deflt(curln, curln) < 0) return (ERR);
00715 if (doprnt(line1, line2) < 0) return (ERR);
00716 break;
00717
00718 case 'q':
00719 if (fchanged) {
00720 fchanged = FALSE;
00721 return(ERR);
00722 }
00723
00724
00725 case 'Q':
00726 if (*inptr == NL && nlines == 0 && !glob)
00727 return(EOF);
00728 else
00729 return(ERR);
00730
00731 case 'r':
00732 if (nlines > 1) return(ERR);
00733
00734 if (nlines == 0) line2 = lastln;
00735
00736 if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
00737
00738 if ((fptr = getfn()) == NULL) return(ERR);
00739
00740 if ((err = doread(line2, fptr)) < 0) return(err);
00741 fchanged = TRUE;
00742 break;
00743
00744 case 's':
00745 if (*inptr == 'e') return(set());
00746 while (*inptr == SP || *inptr == HT) inptr++;
00747 if ((subpat = optpat()) == NULL) return (ERR);
00748 if ((gflag = getrhs(rhs)) < 0) return (ERR);
00749 if (*inptr == 'p') pflag++;
00750 if (deflt(curln, curln) < 0) return (ERR);
00751 if ((nchng = subst(subpat, rhs, gflag, pflag)) < 0) return (ERR);
00752 if (nchng) fchanged = TRUE;
00753 break;
00754
00755 case 't':
00756 if ((line3 = getone()) < 0) return(ERR);
00757 if (deflt(curln, curln) < 0) return (ERR);
00758 if (transfer(line3) < 0) return (ERR);
00759 fchanged = TRUE;
00760 break;
00761
00762 case 'W':
00763 case 'w':
00764 apflg = (c == 'W');
00765
00766 if (*inptr != ' ' && *inptr != HT && *inptr != NL) return(ERR);
00767
00768 if ((fptr = getfn()) == NULL) return(ERR);
00769
00770 if (deflt(1, lastln) < 0) return(ERR);
00771 if (dowrite(line1, line2, fptr, apflg) < 0) return (ERR);
00772 fchanged = FALSE;
00773 break;
00774
00775 case 'x':
00776 if (*inptr == NL && nlines == 0 && !glob) {
00777 if ((fptr = getfn()) == NULL) return(ERR);
00778 if (dowrite(1, lastln, fptr, 0) >= 0) return (EOF);
00779 }
00780 return(ERR);
00781
00782 case 'z':
00783 if (deflt(curln, curln) < 0) return(ERR);
00784
00785 switch (*inptr) {
00786 case '-':
00787 if (doprnt(line1 - 21, line1) < 0) return(ERR);
00788 break;
00789
00790 case '.':
00791 if (doprnt(line1 - 11, line1 + 10) < 0) return(ERR);
00792 break;
00793
00794 case '+':
00795 case '\n':
00796 if (doprnt(line1, line1 + 21) < 0) return(ERR);
00797 break;
00798 }
00799 break;
00800
00801 default: return(ERR);
00802 }
00803 return(0);
00804 }
00805
00806 int dolst(line1, line2)
00807 int line1, line2;
00808 {
00809 int oldlflg = lflg, p;
00810
00811 lflg = 1;
00812 p = doprnt(line1, line2);
00813 lflg = oldlflg;
00814
00815 return p;
00816 }
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 char *dodash(delim, src, map)
00835 int delim;
00836 char *src, *map;
00837 {
00838
00839 register int first, last;
00840 char *start;
00841
00842 start = src;
00843
00844 while (*src && *src != delim) {
00845 if (*src != '-') setbit(esc(&src), map, 1);
00846
00847 else if (src == start || *(src + 1) == delim)
00848 setbit('-', map, 1);
00849 else {
00850 src++;
00851
00852 if (*src < *(src - 2)) {
00853 first = *src;
00854 last = *(src - 2);
00855 } else {
00856 first = *(src - 2);
00857 last = *src;
00858 }
00859
00860 while (++first <= last) setbit(first, map, 1);
00861
00862 }
00863 src++;
00864 }
00865 return(src);
00866 }
00867
00868
00869
00870
00871
00872
00873 int doglob()
00874 {
00875 int lin, stat;
00876 char *cmd;
00877 LINE *ptr;
00878
00879 cmd = inptr;
00880
00881 while (1) {
00882 ptr = getptr(1);
00883 for (lin = 1; lin <= lastln; lin++) {
00884 if (ptr->l_stat & LGLOB) break;
00885 ptr = ptr->l_next;
00886 }
00887 if (lin > lastln) break;
00888
00889 ptr->l_stat &= ~LGLOB;
00890 curln = lin;
00891 inptr = cmd;
00892 if ((stat = getlst()) < 0) return(stat);
00893 if ((stat = docmd(1)) < 0) return (stat);
00894 }
00895 return(curln);
00896 }
00897
00898
00899
00900
00901
00902
00903 int doprnt(from, to)
00904 int from, to;
00905 {
00906 int i;
00907 LINE *lptr;
00908
00909 from = from < 1 ? 1 : from;
00910 to = to > lastln ? lastln : to;
00911
00912 if (to != 0) {
00913 lptr = getptr(from);
00914 for (i = from; i <= to; i++) {
00915 prntln(lptr->l_buff, lflg, (nflg ? i : 0));
00916 lptr = lptr->l_next;
00917 }
00918 curln = to;
00919 }
00920 return(0);
00921 }
00922
00923 void prntln(str, vflg, lin)
00924 char *str;
00925 int vflg, lin;
00926 {
00927 if (lin) printf("%7d ", lin);
00928 while (*str && *str != NL) {
00929 if (*str < ' ' || *str >= 0x7f) {
00930 switch (*str) {
00931 case '\t':
00932 if (vflg)
00933 putcntl(*str, stdout);
00934 else
00935 putc(*str, stdout);
00936 break;
00937
00938 case DEL:
00939 putc('^', stdout);
00940 putc('?', stdout);
00941 break;
00942
00943 default:
00944 putcntl(*str, stdout);
00945 break;
00946 }
00947 } else
00948 putc(*str, stdout);
00949 str++;
00950 }
00951 if (vflg) putc('$', stdout);
00952 putc('\n', stdout);
00953 }
00954
00955 void putcntl(c, stream)
00956 char c;
00957 FILE *stream;
00958 {
00959 putc('^', stream);
00960 putc((c & 31) | '@', stream);
00961 }
00962
00963
00964
00965
00966
00967
00968 extern int diag;
00969
00970 int doread(lin, fname)
00971 int lin;
00972 char *fname;
00973 {
00974 FILE *fp;
00975 int err;
00976 long bytes;
00977 int lines;
00978 static char str[MAXLINE];
00979
00980 err = 0;
00981 nonascii = nullchar = truncated = 0;
00982
00983 if (diag) printf("\"%s\" ", fname);
00984 if ((fp = fopen(fname, "r")) == NULL) {
00985 printf("file open err\n");
00986 return(ERR);
00987 }
00988 curln = lin;
00989 for (lines = 0, bytes = 0; (err = egets(str, MAXLINE, fp)) > 0;) {
00990 bytes += strlen(str);
00991 if (ins(str) < 0) {
00992 printf("file insert error\n");
00993 err++;
00994 break;
00995 }
00996 lines++;
00997 }
00998 fclose(fp);
00999 if (err < 0) return(err);
01000 if (diag) {
01001 printf("%d lines %ld bytes", lines, bytes);
01002 if (nonascii) printf(" [%d non-ascii]", nonascii);
01003 if (nullchar) printf(" [%d nul]", nullchar);
01004 if (truncated) printf(" [%d lines truncated]", truncated);
01005 printf("\n");
01006 }
01007 return(err);
01008 }
01009
01010
01011
01012
01013
01014
01015 int dowrite(from, to, fname, apflg)
01016 int from, to;
01017 char *fname;
01018 int apflg;
01019 {
01020 FILE *fp;
01021 int lin, err;
01022 int lines;
01023 long bytes;
01024 char *str;
01025 LINE *lptr;
01026
01027 err = 0;
01028
01029 lines = bytes = 0;
01030 if (diag) printf("\"%s\" ", fname);
01031 if ((fp = fopen(fname, (apflg ? "a" : "w"))) == NULL) {
01032 printf("file open error\n");
01033 return(ERR);
01034 }
01035 lptr = getptr(from);
01036 for (lin = from; lin <= to; lin++) {
01037 str = lptr->l_buff;
01038 lines++;
01039 bytes += strlen(str) + 1;
01040 if (fputs(str, fp) == EOF) {
01041 printf("file write error\n");
01042 err++;
01043 break;
01044 }
01045 fputc('\n', fp);
01046 lptr = lptr->l_next;
01047 }
01048 if (diag) printf("%d lines %ld bytes\n", lines, bytes);
01049 fclose(fp);
01050 return(err);
01051 }
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 #include <setjmp.h>
01072 jmp_buf env;
01073
01074 LINE line0;
01075 int curln = 0;
01076 int lastln = 0;
01077 char *inptr;
01078 static char inlin[MAXLINE];
01079 int nflg, lflg;
01080 int line1, line2, nlines;
01081 extern char fname[];
01082 int version = 1;
01083 int diag = 1;
01084
01085 void intr(sig)
01086 int sig;
01087 {
01088 printf("?\n");
01089 longjmp(env, 1);
01090 }
01091
01092 int main(argc, argv)
01093 int argc;
01094 char **argv;
01095 {
01096 int stat, i, doflush;
01097
01098 set_buf();
01099 doflush = isatty(1);
01100
01101 if (argc > 1 && (strcmp(argv[1], "-") == 0 || strcmp(argv[1], "-s") == 0)) {
01102 diag = 0;
01103 argc--;
01104 argv++;
01105 }
01106 if (argc > 1) {
01107 for (i = 1; i < argc; i++) {
01108 if (doread(0, argv[i]) == 0) {
01109 curln = 1;
01110 strcpy(fname, argv[i]);
01111 break;
01112 }
01113 }
01114 }
01115 while (1) {
01116 setjmp(env);
01117 if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, intr);
01118
01119 if (doflush) fflush(stdout);
01120
01121 if (fgets(inlin, sizeof(inlin), stdin) == NULL) {
01122 break;
01123 }
01124 for (;;) {
01125 inptr = strchr(inlin, EOS);
01126 if (inptr >= inlin+2 && inptr[-2] == '\\' && inptr[-1] == NL) {
01127 inptr[-1] = 'n';
01128 if (fgets(inptr, sizeof(inlin) - (inptr - inlin),
01129 stdin) == NULL) break;
01130 } else {
01131 break;
01132 }
01133 }
01134 if (*inlin == '!') {
01135 if ((inptr = strchr(inlin, NL)) != NULL) *inptr = EOS;
01136 System(inlin + 1);
01137 continue;
01138 }
01139 inptr = inlin;
01140 if (getlst() >= 0)
01141 if ((stat = ckglob()) != 0) {
01142 if (stat >= 0 && (stat = doglob()) >= 0) {
01143 curln = stat;
01144 continue;
01145 }
01146 } else {
01147 if ((stat = docmd(0)) >= 0) {
01148 if (stat == 1) doprnt(curln, curln);
01149 continue;
01150 }
01151 }
01152 if (stat == EOF) {
01153 exit(0);
01154 }
01155 if (stat == FATAL) {
01156 fputs("FATAL ERROR\n", stderr);
01157 exit(1);
01158 }
01159 printf("?\n");
01160 }
01161 return(0);
01162 }
01163
01164
01165
01166
01167
01168
01169 int eightbit = 1;
01170 int nonascii, nullchar, truncated;
01171 int egets(str, size, stream)
01172 char *str;
01173 int size;
01174 FILE *stream;
01175 {
01176 int c, count;
01177 char *cp;
01178
01179 for (count = 0, cp = str; size > count;) {
01180 c = getc(stream);
01181 if (c == EOF) {
01182 *cp++ = '\n';
01183 *cp = EOS;
01184 if (count) {
01185 printf("[Incomplete last line]\n");
01186 }
01187 return(count);
01188 }
01189 if (c == NL) {
01190 *cp++ = c;
01191 *cp = EOS;
01192 return(++count);
01193 }
01194 if (c > 127) {
01195 if (!eightbit)
01196 c = c & 127;
01197 nonascii++;
01198 }
01199 if (c) {
01200 *cp++ = c;
01201 count++;
01202 } else
01203 nullchar++;
01204 }
01205 str[count - 1] = EOS;
01206 if (c != NL) {
01207 printf("truncating line\n");
01208 truncated++;
01209 while ((c = getc(stream)) != EOF)
01210 if (c == NL) break;
01211 }
01212 return(count);
01213 }
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224 int esc(s)
01225 char **s;
01226 {
01227 register int rval;
01228
01229
01230 if (**s != ESCAPE) {
01231 rval = **s;
01232 } else {
01233 (*s)++;
01234
01235 switch (toupper(**s)) {
01236 case '\000': rval = ESCAPE; break;
01237 case 'S': rval = ' '; break;
01238 case 'N': rval = '\n'; break;
01239 case 'T': rval = '\t'; break;
01240 case 'B': rval = '\b'; break;
01241 case 'R': rval = '\r'; break;
01242 default: rval = **s; break;
01243 }
01244 }
01245
01246 return(rval);
01247 }
01248
01249
01250
01251
01252
01253
01254 int find(pat, dir)
01255 TOKEN *pat;
01256 int dir;
01257 {
01258 int i, num;
01259 char lin[MAXLINE];
01260 LINE *ptr;
01261
01262 num = curln;
01263 ptr = getptr(curln);
01264 num = (dir ? nextln(num) : prevln(num));
01265 ptr = (dir ? ptr->l_next : ptr->l_prev);
01266 for (i = 0; i < lastln; i++) {
01267 if (num == 0) {
01268 num = (dir ? nextln(num) : prevln(num));
01269 ptr = (dir ? ptr->l_next : ptr->l_prev);
01270 }
01271 strcpy(lin, ptr->l_buff);
01272 strcat(lin, "\n");
01273 if (matchs(lin, pat, 0)) {
01274 return(num);
01275 }
01276 num = (dir ? nextln(num) : prevln(num));
01277 ptr = (dir ? ptr->l_next : ptr->l_prev);
01278 }
01279 return(ERR);
01280 }
01281
01282
01283
01284
01285
01286
01287 extern char fname[MAXFNAME];
01288 int nofname;
01289
01290 char *getfn()
01291 {
01292 static char file[256];
01293 char *cp;
01294
01295 if (*inptr == NL) {
01296 nofname = TRUE;
01297 strcpy(file, fname);
01298 } else {
01299 nofname = FALSE;
01300 while (*inptr == SP || *inptr == HT) inptr++;
01301
01302 cp = file;
01303 while (*inptr && *inptr != NL && *inptr != SP && *inptr != HT) {
01304 *cp++ = *inptr++;
01305 }
01306 *cp = '\0';
01307
01308 if (strlen(file) == 0) {
01309 printf("bad file name\n");
01310 return(NULL);
01311 }
01312 }
01313
01314 if (strlen(file) == 0) {
01315 printf("no file name\n");
01316 return(NULL);
01317 }
01318 return(file);
01319 }
01320
01321
01322
01323
01324
01325
01326 int getlst()
01327 {
01328 int num;
01329
01330 line2 = 0;
01331 for (nlines = 0; (num = getone()) >= 0;) {
01332 line1 = line2;
01333 line2 = num;
01334 nlines++;
01335 if (*inptr != ',' && *inptr != ';') break;
01336 if (*inptr == ';') curln = num;
01337 inptr++;
01338 }
01339 nlines = min(nlines, 2);
01340 if (nlines == 0) line2 = curln;
01341 if (nlines <= 1) line1 = line2;
01342
01343 if (num == ERR)
01344 return(num);
01345 else
01346 return(nlines);
01347 }
01348
01349
01350
01351
01352
01353
01354 int mark['z' - 'a' + 1];
01355
01356 int getnum(first)
01357 int first;
01358 {
01359 TOKEN *srchpat;
01360 int num;
01361 char c;
01362
01363 while (*inptr == SP || *inptr == HT) inptr++;
01364
01365 if (*inptr >= '0' && *inptr <= '9') {
01366 for (num = 0; *inptr >= '0' && *inptr <= '9';) {
01367 num = (num * 10) + *inptr - '0';
01368 inptr++;
01369 }
01370 return num;
01371 }
01372 switch (c = *inptr) {
01373 case '.':
01374 inptr++;
01375 return(curln);
01376
01377 case '$':
01378 inptr++;
01379 return(lastln);
01380
01381 case '/':
01382 case '?':
01383 srchpat = optpat();
01384 if (*inptr == c) inptr++;
01385 return(find(srchpat, c == '/' ? 1 : 0));
01386
01387 case '-':
01388 case '+':
01389 return(first ? curln : 1);
01390
01391 case '\'':
01392 inptr++;
01393 if (*inptr < 'a' || *inptr > 'z') return(EOF);
01394
01395 return mark[*inptr++ - 'a'];
01396
01397 default:
01398 return(first ? EOF : 1);
01399 }
01400 }
01401
01402
01403
01404
01405
01406
01407 #define FIRST 1
01408 #define NOTFIRST 0
01409
01410 int getone()
01411 {
01412 int c, i, num;
01413
01414 if ((num = getnum(FIRST)) >= 0) {
01415 while (1) {
01416 while (*inptr == SP || *inptr == HT) inptr++;
01417
01418 if (*inptr != '+' && *inptr != '-') break;
01419 c = *inptr++;
01420
01421 if ((i = getnum(NOTFIRST)) < 0) return(i);
01422
01423 if (c == '+') {
01424 num += i;
01425 } else {
01426 num -= i;
01427 }
01428 }
01429 }
01430 return(num > lastln ? ERR : num);
01431 }
01432
01433
01434
01435
01436
01437
01438 TOKEN *
01439 getpat(arg)
01440 char *arg;
01441 {
01442
01443 return(makepat(arg, '\000'));
01444 }
01445
01446
01447
01448
01449
01450
01451 LINE *
01452 getptr(num)
01453 int num;
01454 {
01455 LINE *ptr;
01456 int j;
01457
01458 if (2 * num > lastln && num <= lastln) {
01459 ptr = line0.l_prev;
01460 for (j = lastln; j > num; j--) ptr = ptr->l_prev;
01461 } else {
01462 ptr = &line0;
01463 for (j = 0; j < num; j++) ptr = ptr->l_next;
01464 }
01465 return(ptr);
01466 }
01467
01468
01469
01470
01471
01472
01473 int getrhs(sub)
01474 char *sub;
01475 {
01476 if (inptr[0] == NL || inptr[1] == NL)
01477 return(ERR);
01478
01479 if (maksub(sub, MAXPAT) == NULL) return(ERR);
01480
01481 inptr++;
01482 while (*inptr == SP || *inptr == HT) inptr++;
01483 if (*inptr == 'g') {
01484 inptr++;
01485 return(1);
01486 }
01487 return(0);
01488 }
01489
01490
01491
01492
01493
01494
01495 char *
01496 gettxt(num)
01497 int num;
01498 {
01499 LINE *lin;
01500 static char txtbuf[MAXLINE];
01501
01502 lin = getptr(num);
01503 strcpy(txtbuf, lin->l_buff);
01504 strcat(txtbuf, "\n");
01505 return(txtbuf);
01506 }
01507
01508
01509
01510
01511
01512
01513 int ins(str)
01514 char *str;
01515 {
01516 char buf[MAXLINE], *cp;
01517 LINE *new, *cur, *nxt;
01518
01519 cp = buf;
01520 while (1) {
01521 if ((*cp = *str++) == NL) *cp = EOS;
01522 if (*cp) {
01523 cp++;
01524 continue;
01525 }
01526 if ((new = (LINE *) malloc(sizeof(LINE) + strlen(buf))) == NULL)
01527 return(ERR);
01528
01529 new->l_stat = 0;
01530 strcpy(new->l_buff, buf);
01531 cur = getptr(curln);
01532 nxt = cur->l_next;
01533 relink(cur, new, new, nxt);
01534 relink(new, nxt, cur, new);
01535 lastln++;
01536 curln++;
01537
01538 if (*str == EOS)
01539 return(1);
01540
01541 cp = buf;
01542 }
01543 }
01544
01545
01546
01547
01548
01549
01550 extern int fchanged;
01551
01552 int join(first, last)
01553 int first, last;
01554 {
01555 char buf[MAXLINE];
01556 char *cp = buf, *str;
01557 int num;
01558
01559 if (first <= 0 || first > last || last > lastln) return(ERR);
01560 if (first == last) {
01561 curln = first;
01562 return 0;
01563 }
01564 for (num = first; num <= last; num++) {
01565 str = gettxt(num);
01566
01567 while (*str != NL && cp < buf + MAXLINE - 1) *cp++ = *str++;
01568
01569 if (cp == buf + MAXLINE - 1) {
01570 printf("line too long\n");
01571 return(ERR);
01572 }
01573 }
01574 *cp++ = NL;
01575 *cp = EOS;
01576 del(first, last);
01577 curln = first - 1;
01578 ins(buf);
01579 fchanged = TRUE;
01580 return 0;
01581 }
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 TOKEN *
01604 makepat(arg, delim)
01605 char *arg;
01606 int delim;
01607 {
01608 TOKEN *head, *tail, *ntok;
01609 int error;
01610
01611
01612
01613 if (*arg == '\0' || *arg == delim || *arg == '\n' || *arg == CLOSURE)
01614 return(0);
01615
01616 error = 0;
01617 tail = head = NULL;
01618
01619 while (*arg && *arg != delim && *arg != '\n' && !error) {
01620 ntok = (TOKEN *) malloc(TOKSIZE);
01621 ntok->lchar = '\000';
01622 ntok->next = 0;
01623
01624 switch (*arg) {
01625 case ANY: ntok->tok = ANY; break;
01626
01627 case BOL:
01628 if (head == 0)
01629 ntok->tok = BOL;
01630 else
01631 ntok->tok = LITCHAR;
01632 ntok->lchar = BOL;
01633 break;
01634
01635 case EOL:
01636 if (*(arg + 1) == delim || *(arg + 1) == '\000' ||
01637 *(arg + 1) == '\n') {
01638 ntok->tok = EOL;
01639 } else {
01640 ntok->tok = LITCHAR;
01641 ntok->lchar = EOL;
01642 }
01643 break;
01644
01645 case CLOSURE:
01646 if (head != 0) {
01647 switch (tail->tok) {
01648 case BOL:
01649 case EOL:
01650 case CLOSURE:
01651 return(0);
01652
01653 default:
01654 ntok->tok = CLOSURE;
01655 }
01656 }
01657 break;
01658
01659 case CCL:
01660
01661 if (*(arg + 1) == NEGATE) {
01662 ntok->tok = NCCL;
01663 arg += 2;
01664 } else {
01665 ntok->tok = CCL;
01666 arg++;
01667 }
01668
01669 if (ntok->bitmap = makebitmap(CLS_SIZE))
01670 arg = dodash(CCLEND, arg, ntok->bitmap);
01671 else {
01672 fprintf(stderr, "Not enough memory for pat\n");
01673 error = 1;
01674 }
01675 break;
01676
01677 default:
01678 if (*arg == ESCAPE && *(arg + 1) == OPEN) {
01679 ntok->tok = OPEN;
01680 arg++;
01681 } else if (*arg == ESCAPE && *(arg + 1) == CLOSE) {
01682 ntok->tok = CLOSE;
01683 arg++;
01684 } else {
01685 ntok->tok = LITCHAR;
01686 ntok->lchar = esc(&arg);
01687 }
01688 }
01689
01690 if (error || ntok == 0) {
01691 unmakepat(head);
01692 return(0);
01693 } else if (head == 0) {
01694
01695
01696 ntok->next = 0;
01697 head = tail = ntok;
01698 } else if (ntok->tok != CLOSURE) {
01699
01700
01701 tail->next = ntok;
01702 ntok->next = tail;
01703 tail = ntok;
01704 } else if (head != tail) {
01705
01706
01707
01708 (tail->next)->next = ntok;
01709 ntok->next = tail;
01710 } else {
01711
01712
01713
01714 ntok->next = head;
01715 tail->next = ntok;
01716 head = ntok;
01717 }
01718 arg++;
01719 }
01720
01721 tail->next = 0;
01722 return(head);
01723 }
01724
01725
01726
01727
01728
01729
01730 char *
01731 maksub(sub, subsz)
01732 char *sub;
01733 int subsz;
01734 {
01735 int size;
01736 char delim, *cp;
01737
01738 size = 0;
01739 cp = sub;
01740
01741 delim = *inptr++;
01742 for (size = 0; *inptr != delim && *inptr != NL && size < subsz; size++) {
01743 if (*inptr == '&') {
01744 *cp++ = DITTO;
01745 inptr++;
01746 } else if ((*cp++ = *inptr++) == ESCAPE) {
01747 if (size >= subsz) return(NULL);
01748
01749 switch (toupper(*inptr)) {
01750 case NL: *cp++ = ESCAPE; break;
01751 break;
01752 case 'S':
01753 *cp++ = SP;
01754 inptr++;
01755 break;
01756 case 'N':
01757 *cp++ = NL;
01758 inptr++;
01759 break;
01760 case 'T':
01761 *cp++ = HT;
01762 inptr++;
01763 break;
01764 case 'B':
01765 *cp++ = BS;
01766 inptr++;
01767 break;
01768 case 'R':
01769 *cp++ = CR;
01770 inptr++;
01771 break;
01772 case '0':{
01773 int i = 3;
01774 *cp = 0;
01775 do {
01776 if (*++inptr < '0' || *inptr > '7')
01777 break;
01778
01779 *cp = (*cp << 3) | (*inptr - '0');
01780 } while (--i != 0);
01781 cp++;
01782 } break;
01783 default: *cp++ = *inptr++; break;
01784 }
01785 }
01786 }
01787 if (size >= subsz) return(NULL);
01788
01789 *cp = EOS;
01790 return(sub);
01791 }
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816 char *
01817 matchs(line, pat, ret_endp)
01818 char *line;
01819 TOKEN *pat;
01820 int ret_endp;
01821 {
01822
01823 char *rval, *bptr;
01824 char *line2;
01825 TOKEN *pat2;
01826 char c;
01827 short ok;
01828
01829 bptr = line;
01830
01831 while (*line) {
01832
01833 if (pat && pat->tok == LITCHAR) {
01834 while (*line) {
01835 pat2 = pat;
01836 line2 = line;
01837 if (*line2 != pat2->lchar) {
01838 c = pat2->lchar;
01839 while (*line2 && *line2 != c) ++line2;
01840 line = line2;
01841 if (*line2 == '\0') break;
01842 }
01843 ok = 1;
01844 ++line2;
01845 pat2 = pat2->next;
01846 while (pat2 && pat2->tok == LITCHAR) {
01847 if (*line2 != pat2->lchar) {
01848 ok = 0;
01849 break;
01850 }
01851 ++line2;
01852 pat2 = pat2->next;
01853 }
01854 if (!pat2) {
01855 if (ret_endp)
01856 return(--line2);
01857 else
01858 return(line);
01859 } else if (ok)
01860 break;
01861 ++line;
01862 }
01863 if (*line == '\0') return(0);
01864 } else {
01865 line2 = line;
01866 pat2 = pat;
01867 }
01868 if ((rval = amatch(line2, pat2, bptr)) == 0) {
01869 if (pat && pat->tok == BOL) break;
01870 line++;
01871 } else {
01872 if (rval > bptr && rval > line)
01873 rval--;
01874 rval = ret_endp ? rval : line;
01875 break;
01876 }
01877 }
01878 return(rval);
01879 }
01880
01881
01882
01883
01884
01885
01886 int move(num)
01887 int num;
01888 {
01889 LINE *k0, *k1, *k2, *k3;
01890
01891 if (line1 <= 0 || line2 < line1 || (line1 <= num && num <= line2))
01892 return(ERR);
01893 k0 = getptr(prevln(line1));
01894 k1 = getptr(line1);
01895 k2 = getptr(line2);
01896 k3 = getptr(nextln(line2));
01897
01898 relink(k0, k3, k0, k3);
01899 lastln -= line2 - line1 + 1;
01900
01901 if (num > line1) num -= line2 - line1 + 1;
01902
01903 curln = num + (line2 - line1 + 1);
01904
01905 k0 = getptr(num);
01906 k3 = getptr(nextln(num));
01907
01908 relink(k0, k1, k2, k3);
01909 relink(k2, k3, k0, k1);
01910 lastln += line2 - line1 + 1;
01911
01912 return(1);
01913 }
01914
01915 int transfer(num)
01916 int num;
01917 {
01918 int mid, lin, ntrans;
01919
01920 if (line1 <= 0 || line1 > line2) return(ERR);
01921
01922 mid = num < line2 ? num : line2;
01923
01924 curln = num;
01925 ntrans = 0;
01926
01927 for (lin = line1; lin <= mid; lin++) {
01928 ins(gettxt(lin));
01929 ntrans++;
01930 }
01931 lin += ntrans;
01932 line2 += ntrans;
01933
01934 for (; lin <= line2; lin += 2) {
01935 ins(gettxt(lin));
01936 line2++;
01937 }
01938 return(1);
01939 }
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952 int omatch(linp, pat, boln)
01953 char **linp;
01954 TOKEN *pat;
01955 char *boln;
01956 {
01957
01958 register int advance;
01959
01960 advance = -1;
01961
01962 if (**linp) {
01963 switch (pat->tok) {
01964 case LITCHAR:
01965 if (**linp == pat->lchar) advance = 1;
01966 break;
01967
01968 case BOL:
01969 if (*linp == boln) advance = 0;
01970 break;
01971
01972 case ANY:
01973 if (**linp != '\n') advance = 1;
01974 break;
01975
01976 case EOL:
01977 if (**linp == '\n') advance = 0;
01978 break;
01979
01980 case CCL:
01981 if (testbit(**linp, pat->bitmap)) advance = 1;
01982 break;
01983
01984 case NCCL:
01985 if (!testbit(**linp, pat->bitmap)) advance = 1;
01986 break;
01987 }
01988 }
01989 if (advance >= 0) *linp += advance;
01990
01991 return(++advance);
01992 }
01993
01994
01995
01996
01997
01998
01999 TOKEN *oldpat;
02000
02001 TOKEN *
02002 optpat()
02003 {
02004 char delim, str[MAXPAT], *cp;
02005
02006 delim = *inptr++;
02007 cp = str;
02008 while (*inptr != delim && *inptr != NL) {
02009 if (*inptr == ESCAPE && inptr[1] != NL) *cp++ = *inptr++;
02010 *cp++ = *inptr++;
02011 }
02012
02013 *cp = EOS;
02014 if (*str == EOS) return(oldpat);
02015 if (oldpat) unmakepat(oldpat);
02016 oldpat = getpat(str);
02017 return(oldpat);
02018 }
02019
02020
02021
02022
02023
02024
02025 struct tbl {
02026 char *t_str;
02027 int *t_ptr;
02028 int t_val;
02029 } *t, tbl[] = {
02030
02031 "number", &nflg, TRUE,
02032 "nonumber", &nflg, FALSE,
02033 "list", &lflg, TRUE,
02034 "nolist", &lflg, FALSE,
02035 "eightbit", &eightbit, TRUE,
02036 "noeightbit", &eightbit, FALSE,
02037 0
02038 };
02039
02040 int set()
02041 {
02042 char word[16];
02043 int i;
02044
02045 inptr++;
02046 if (*inptr != 't') {
02047 if (*inptr != SP && *inptr != HT && *inptr != NL) return(ERR);
02048 } else
02049 inptr++;
02050
02051 if (*inptr == NL) return(show());
02052
02053 while (*inptr == SP || *inptr == HT) inptr++;
02054
02055 for (i = 0; *inptr != SP && *inptr != HT && *inptr != NL;)
02056 word[i++] = *inptr++;
02057 word[i] = EOS;
02058 for (t = tbl; t->t_str; t++) {
02059 if (strcmp(word, t->t_str) == 0) {
02060 *t->t_ptr = t->t_val;
02061 return(0);
02062 }
02063 }
02064 return(0);
02065 }
02066
02067 int show()
02068 {
02069 extern int version;
02070
02071 printf("ed version %d.%d\n", version / 100, version % 100);
02072 printf("number %s, list %s\n", nflg ? "ON" : "OFF", lflg ? "ON" : "OFF");
02073 return(0);
02074 }
02075
02076
02077
02078
02079
02080
02081 void relink(a, x, y, b)
02082 LINE *a, *x, *y, *b;
02083 {
02084 x->l_prev = a;
02085 y->l_next = b;
02086 }
02087
02088 void clrbuf()
02089 {
02090 del(1, lastln);
02091 }
02092
02093 void set_buf()
02094 {
02095 relink(&line0, &line0, &line0, &line0);
02096 curln = lastln = 0;
02097 }
02098
02099
02100
02101
02102
02103
02104 int subst(pat, sub, gflg, pflag)
02105 TOKEN *pat;
02106 char *sub;
02107 int gflg, pflag;
02108 {
02109 int lin, chngd, nchngd;
02110 char *txtptr, *txt;
02111 char *lastm, *m, *new, buf[MAXLINE];
02112
02113 if (line1 <= 0) return(ERR);
02114 nchngd = 0;
02115 for (lin = line1; lin <= line2; lin++) {
02116 txt = txtptr = gettxt(lin);
02117 new = buf;
02118 chngd = 0;
02119 lastm = NULL;
02120 while (*txtptr) {
02121 if (gflg || !chngd)
02122 m = amatch(txtptr, pat, txt);
02123 else
02124 m = NULL;
02125 if (m != NULL && lastm != m) {
02126 chngd++;
02127 new = catsub(txtptr, m, sub, new,
02128 buf + MAXLINE);
02129 lastm = m;
02130 }
02131 if (m == NULL || m == txtptr) {
02132 *new++ = *txtptr++;
02133 } else {
02134 txtptr = m;
02135 }
02136 }
02137 if (chngd) {
02138 if (new >= buf + MAXLINE) return(ERR);
02139 *new++ = EOS;
02140 del(lin, lin);
02141 ins(buf);
02142 nchngd++;
02143 if (pflag) doprnt(curln, curln);
02144 }
02145 }
02146 if (nchngd == 0 && !gflg) {
02147 return(ERR);
02148 }
02149 return(nchngd);
02150 }
02151
02152
02153 #define SHELL "/bin/sh"
02154 #define SHELL2 "/usr/bin/sh"
02155
02156 int System(c)
02157 char *c;
02158 {
02159 int pid, status;
02160
02161 switch (pid = fork()) {
02162 case -1:
02163 return -1;
02164 case 0:
02165 execl(SHELL, "sh", "-c", c, (char *) 0);
02166 execl(SHELL2, "sh", "-c", c, (char *) 0);
02167 exit(-1);
02168 default: while (wait(&status) != pid);
02169 }
02170 return status;
02171 }
02172
02173
02174
02175
02176
02177
02178 void unmakepat(head)
02179 TOKEN *head;
02180 {
02181
02182 register TOKEN *old_head;
02183
02184 while (head) {
02185 switch (head->tok) {
02186 case CCL:
02187 case NCCL:
02188 free(head->bitmap);
02189
02190
02191 default:
02192 old_head = head;
02193 head = head->next;
02194 free((char *) old_head);
02195 break;
02196 }
02197 }
02198 }