ed.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845
  1. /*
  2. * Editor
  3. */
  4. #include <signal.h>
  5. #include <setjmp.h>
  6. #include <sys/wait.h> /* for wait() */
  7. #include <fcntl.h> /* for open() and symbols for flags */
  8. #include <unistd.h>
  9. #include <stdlib.h>
  10. #include "utfio.h"
  11. #define nelem(X) (sizeof(X) / sizeof(X[0]))
  12. #define MARK 1L
  13. #define UNMARK ~1L
  14. #define mark(n) ((n)|MARK)
  15. #define unmark(n) ((n)&UNMARK)
  16. #define marked(n) ((n)&MARK)
  17. enum {
  18. FNSIZE = 512,
  19. LBSIZE = 4096,
  20. BLKSIZE = 4096,
  21. BLKBSIZE = (BLKSIZE << 2), /* # of bytes in a BLK */
  22. ESIZE = 256,
  23. GBSIZE = 256,
  24. NBRA = 9
  25. };
  26. enum {
  27. CBRA = 1,
  28. CCHR = 2,
  29. CDOT = 4,
  30. CCL = 6,
  31. NCCL = 8,
  32. CDOL = 10,
  33. CEFIL = 11,
  34. CKET = 12,
  35. CBACK = 14,
  36. CCIRC = 15,
  37. STAR = 01
  38. };
  39. int FMODE;
  40. int Q[] = {'\0'};
  41. int T[] = {'T','M','P','\0'};
  42. int M[] = {'M','E','M','?','\0'};
  43. int F[] = {'F','I','L','E','\0'};
  44. int STDOUT[]= {'/','d','e','v','/','s','t','d','o','u','t','\0'};
  45. int NAPPENDED[]= {'?','N',' ','a','p','p','e','n','d','e','d','\0'};
  46. int NL[] = {'\n','\0'};
  47. int A[] = {'a','\0'};
  48. int R[] = {'r','\0'};
  49. int SHRIEK[]= {'!','\0'};
  50. int QUERY[]= {'?','\0'};
  51. enum {
  52. EOF = -1,
  53. READ = 0,
  54. WRITE = 1
  55. };
  56. enum {
  57. LINELEN = 70, /* max number of glyphs in list-mode line */
  58. BELL = 4 /* max number of glyphs needed for \ddd */
  59. };
  60. int line[LINELEN];
  61. int *linp = line;
  62. byte utf8buff[utfbsize];
  63. int ucbuff[ucbsize];
  64. utfio _uio;
  65. utfio *uio=&_uio;
  66. int peekc;
  67. int lastc;
  68. int savedfile[FNSIZE];
  69. int file[FNSIZE];
  70. int linebuf[LBSIZE];
  71. int rhsbuf[LBSIZE/2];
  72. int expbuf[ESIZE+4];
  73. int genbuf[LBSIZE];
  74. long *zero;
  75. long *dot;
  76. long *dol;
  77. int given;
  78. long *addr1;
  79. long *addr2;
  80. long count;
  81. int *linebp;
  82. int io;
  83. int pflag;
  84. void (*oldhup)(int);
  85. void (*oldquit)(int);
  86. int vflag = 1;
  87. int oflag;
  88. int listf;
  89. int listn;
  90. int col;
  91. int *globp;
  92. int tfile = -1;
  93. int tline;
  94. char tftemp[]="/tmp/eXXXXXX";
  95. char tfname[sizeof(tftemp)];
  96. int *loc1;
  97. int *loc2;
  98. int ibuff[BLKSIZE];
  99. int iblock = -1;
  100. int obuff[BLKSIZE];
  101. int oblock = -1;
  102. int ichanged;
  103. int nleft;
  104. long names[26];
  105. int anymarks;
  106. int *braslist[NBRA];
  107. int *braelist[NBRA];
  108. int nbra;
  109. int subnewa;
  110. int subolda;
  111. int fchange;
  112. int wrapp;
  113. int bpagesize = 20;
  114. unsigned int nlall = 128;
  115. jmp_buf savej;
  116. long* address(void);
  117. int getchr(void);
  118. int* getline(long);
  119. int* getblock(long, int);
  120. int* place(int*, int*, int*);
  121. void commands(void);
  122. void quit(void);
  123. void printcom(void);
  124. void bye(int);
  125. void error(int*);
  126. void nonzero(void);
  127. void newline(void);
  128. void rdelete(long*, long*);
  129. void setnoaddr(void);
  130. void init(void);
  131. void putst(int*);
  132. void putst(int*);
  133. void squeeze(int);
  134. void setwide(void);
  135. void putfile(void);
  136. void putd(void);
  137. void callunix(void);
  138. void dosub(void);
  139. void reverse(long*, long*);
  140. void compile(int);
  141. void putchr(int);
  142. long append(int(*)(void), long*);
  143. void add(int);
  144. void browse(void);
  145. void filename(int);
  146. void global(int);
  147. void join(void);
  148. void move(int);
  149. void exfile(void);
  150. void substitute(int);
  151. int getfile(void);
  152. int gettty(void);
  153. int compsub(void);
  154. int getsub(void);
  155. int getcopy(void);
  156. int getnum(void);
  157. int execute(long*);
  158. int putline(void);
  159. int advance(int*, int*);
  160. int cclass(int*, int, int);
  161. int backref(int, int*);
  162. void onintr(int);
  163. void onquit(int);
  164. void onhup(int);
  165. int
  166. main(int argc, char *argv[])
  167. {
  168. int *p1, *p2;
  169. void (*oldintr)(int);
  170. oldquit = signal(SIGQUIT, SIG_IGN);
  171. oldhup = signal(SIGHUP, SIG_IGN);
  172. oldintr = signal(SIGINT, SIG_IGN);
  173. if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
  174. signal(SIGTERM, onquit);
  175. argv++;
  176. while (argc > 1 && **argv=='-') {
  177. switch((*argv)[1]) {
  178. case '\0':
  179. vflag = 0;
  180. break;
  181. case 'q':
  182. signal(SIGQUIT, SIG_DFL);
  183. vflag = 1;
  184. break;
  185. case 'o':
  186. oflag = 1;
  187. break;
  188. }
  189. argv++;
  190. argc--;
  191. }
  192. if (oflag) {
  193. p1 = STDOUT;
  194. p2 = savedfile;
  195. while ((*p2++ = *p1++))
  196. ;
  197. globp = A;
  198. } else if (*argv) {
  199. p1 = ucode((byte *)*argv);
  200. p2 = savedfile;
  201. while ((*p2++ = *p1++))
  202. if (p2 >= &savedfile[nelem(savedfile)])
  203. p2--;
  204. globp = R;
  205. }
  206. if((zero = (long*)malloc(nlall*sizeof(long)))==NULL) {
  207. error(M);
  208. onhup(0);
  209. }
  210. init();
  211. if (oldintr != SIG_IGN)
  212. signal(SIGINT, onintr);
  213. if (oldhup != SIG_IGN)
  214. signal(SIGHUP, onhup);
  215. setjmp(savej);
  216. commands();
  217. quit();
  218. return -1; /* not reached */
  219. }
  220. void
  221. commands(void)
  222. {
  223. long *a1;
  224. int c, temp;
  225. int lastsep;
  226. for (;;) {
  227. if (pflag) {
  228. pflag = 0;
  229. addr1 = addr2 = dot;
  230. printcom();
  231. }
  232. c = '\n';
  233. for (addr1 = 0;;) {
  234. lastsep = c;
  235. a1 = address();
  236. c = getchr();
  237. if (c!=',' && c!=';')
  238. break;
  239. if (lastsep==',')
  240. error(Q);
  241. if (a1==0) {
  242. a1 = zero+1;
  243. if (a1>dol)
  244. a1--;
  245. }
  246. addr1 = a1;
  247. if (c==';')
  248. dot = a1;
  249. }
  250. if (lastsep!='\n' && a1==0)
  251. a1 = dol;
  252. if ((addr2=a1)==0) {
  253. given = 0;
  254. addr2 = dot;
  255. }
  256. else
  257. given = 1;
  258. if (addr1==0)
  259. addr1 = addr2;
  260. switch(c) {
  261. case 'a':
  262. add(0);
  263. continue;
  264. case 'b':
  265. nonzero();
  266. browse();
  267. continue;
  268. case 'c':
  269. nonzero();
  270. newline();
  271. rdelete(addr1, addr2);
  272. append(gettty, addr1-1);
  273. continue;
  274. case 'd':
  275. nonzero();
  276. newline();
  277. rdelete(addr1, addr2);
  278. continue;
  279. case 'E':
  280. fchange = 0;
  281. c = 'e';
  282. case 'e':
  283. setnoaddr();
  284. if (vflag && fchange) {
  285. fchange = 0;
  286. error(Q);
  287. }
  288. filename(c);
  289. init();
  290. addr2 = zero;
  291. goto caseread;
  292. case 'f':
  293. setnoaddr();
  294. filename(c);
  295. putst(savedfile);
  296. continue;
  297. case 'g':
  298. global(1);
  299. continue;
  300. case 'i':
  301. add(-1);
  302. continue;
  303. case 'j':
  304. if (!given)
  305. addr2++;
  306. newline();
  307. join();
  308. continue;
  309. case 'k':
  310. nonzero();
  311. if ((c = getchr()) < 'a' || c > 'z')
  312. error(Q);
  313. newline();
  314. names[c-'a'] = unmark(*addr2);
  315. anymarks = mark(anymarks);
  316. continue;
  317. case 'm':
  318. move(0);
  319. continue;
  320. case 'n':
  321. listn++;
  322. newline();
  323. printcom();
  324. continue;
  325. case '\n':
  326. if (a1==0) {
  327. a1 = dot+1;
  328. addr2 = a1;
  329. addr1 = a1;
  330. }
  331. if (lastsep==';')
  332. addr1 = a1;
  333. printcom();
  334. continue;
  335. case 'l':
  336. listf++;
  337. case 'p':
  338. case 'P':
  339. newline();
  340. printcom();
  341. continue;
  342. case 'Q':
  343. fchange = 0;
  344. case 'q':
  345. setnoaddr();
  346. newline();
  347. quit();
  348. case 'r':
  349. filename(c);
  350. caseread:
  351. if ((io = open((char *)utf8(file), O_RDONLY)) < 0) {
  352. lastc = '\n';
  353. error(file);
  354. }
  355. setwide();
  356. squeeze(0);
  357. uioinitrd(io,uio);
  358. c = zero != dol;
  359. append(getfile, addr2);
  360. exfile();
  361. fchange = c;
  362. continue;
  363. case 's':
  364. nonzero();
  365. substitute(globp!=0);
  366. continue;
  367. case 't':
  368. move(1);
  369. continue;
  370. case 'u':
  371. nonzero();
  372. newline();
  373. if ((*addr2&~01) != subnewa)
  374. error(Q);
  375. *addr2 = subolda;
  376. dot = addr2;
  377. continue;
  378. case 'v':
  379. global(0);
  380. continue;
  381. case 'W':
  382. wrapp++;
  383. case 'w':
  384. setwide();
  385. squeeze(dol>zero);
  386. if ((temp = getchr()) != 'q' && temp != 'Q') {
  387. peekc = temp;
  388. temp = 0;
  389. }
  390. filename(c);
  391. FMODE= O_WRONLY | O_CREAT;
  392. if(wrapp)
  393. FMODE |= O_APPEND;
  394. else
  395. FMODE |= O_TRUNC;
  396. if((io=open((char*)utf8(file), FMODE, 0666)) == -1)
  397. error(file);
  398. uioinit(io,uio);
  399. wrapp = 0;
  400. if (dol > zero)
  401. putfile();
  402. uioflush(uio);
  403. exfile();
  404. if (addr1<=zero+1 && addr2==dol)
  405. fchange = 0;
  406. if (temp == 'Q')
  407. fchange = 0;
  408. if (temp)
  409. quit();
  410. continue;
  411. case '=':
  412. setwide();
  413. squeeze(0);
  414. newline();
  415. count = addr2 - zero;
  416. putd();
  417. putchr('\n');
  418. continue;
  419. case '!':
  420. callunix();
  421. continue;
  422. case EOF:
  423. return;
  424. }
  425. error(Q);
  426. }
  427. }
  428. void
  429. printcom(void)
  430. {
  431. long *a1;
  432. nonzero();
  433. a1 = addr1;
  434. do {
  435. if (listn) {
  436. count = a1-zero;
  437. putd();
  438. putchr('\t');
  439. }
  440. putst(getline(*a1++));
  441. } while (a1 <= addr2);
  442. dot = addr2;
  443. listf = 0;
  444. listn = 0;
  445. pflag = 0;
  446. }
  447. long*
  448. address(void)
  449. {
  450. int sign, opcnt, nextopand, c;
  451. long *a, *b;
  452. nextopand = -1;
  453. sign = 1;
  454. opcnt = 0;
  455. a = dot;
  456. do {
  457. do c = getchr(); while (c==' ' || c=='\t');
  458. if ('0'<=c && c<='9') {
  459. peekc = c;
  460. if (!opcnt)
  461. a = zero;
  462. a += sign*getnum();
  463. } else switch (c) {
  464. case '$':
  465. a = dol;
  466. /* fall through */
  467. case '.':
  468. if (opcnt)
  469. error(Q);
  470. break;
  471. case '\'':
  472. c = getchr();
  473. if (opcnt || c<'a' || 'z'<c)
  474. error(Q);
  475. a = zero;
  476. do a++; while (a<=dol && names[c-'a']!=(*a&~01));
  477. break;
  478. case '?':
  479. sign = -sign;
  480. /* fall through */
  481. case '/':
  482. compile(c);
  483. b = a;
  484. for (;;) {
  485. a += sign;
  486. if (a<=zero)
  487. a = dol;
  488. if (a>dol)
  489. a = zero;
  490. if (execute(a))
  491. break;
  492. if (a==b)
  493. error(Q);
  494. }
  495. break;
  496. default:
  497. if (nextopand == opcnt) {
  498. a += sign;
  499. if (a<zero || dol<a)
  500. continue; /* error(Q); */
  501. }
  502. if (c!='+' && c!='-' && c!='^') {
  503. peekc = c;
  504. if (opcnt==0)
  505. a = 0;
  506. return a;
  507. }
  508. sign = 1;
  509. if (c!='+')
  510. sign = -sign;
  511. nextopand = ++opcnt;
  512. continue;
  513. }
  514. sign = 1;
  515. opcnt++;
  516. } while (zero<=a && a<=dol);
  517. error(Q);
  518. return 0;
  519. }
  520. int
  521. getnum(void)
  522. {
  523. int r, c;
  524. r = 0;
  525. while ((c=getchr())>='0' && c<='9')
  526. r = r*10 + c - '0';
  527. peekc = c;
  528. return r;
  529. }
  530. void
  531. setwide(void)
  532. {
  533. if (!given) {
  534. addr1 = zero + (dol>zero);
  535. addr2 = dol;
  536. }
  537. }
  538. void
  539. setnoaddr(void)
  540. {
  541. if (given)
  542. error(Q);
  543. }
  544. void
  545. nonzero(void)
  546. {
  547. squeeze(1);
  548. }
  549. void
  550. squeeze(int i)
  551. {
  552. if (addr1<zero+i || addr2>dol || addr1>addr2)
  553. error(Q);
  554. }
  555. void
  556. newline(void)
  557. {
  558. int c;
  559. if ((c = getchr()) == '\n' || c == EOF)
  560. return;
  561. if (c=='p' || c=='l' || c=='n') {
  562. pflag++;
  563. if (c=='l')
  564. listf++;
  565. else if (c=='n')
  566. listn++;
  567. if (getchr()=='\n')
  568. return;
  569. }
  570. error(Q);
  571. }
  572. void
  573. filename(int comm)
  574. {
  575. int *p1, *p2;
  576. int c;
  577. count = 0;
  578. c = getchr();
  579. if (c=='\n' || c==EOF) {
  580. p1 = savedfile;
  581. if (*p1==0 && comm!='f')
  582. error(Q);
  583. p2 = file;
  584. while ((*p2++ = *p1++))
  585. ;
  586. return;
  587. }
  588. if (c!=' ')
  589. error(Q);
  590. while ((c = getchr()) == ' ')
  591. ;
  592. if (c=='\n')
  593. error(Q);
  594. p1 = file;
  595. do {
  596. if (p1 >= &file[nelem(file)-1] || c==' ' || c==EOF)
  597. error(Q);
  598. *p1++ = c;
  599. } while ((c = getchr()) != '\n');
  600. *p1++ = 0;
  601. if (savedfile[0]==0 || comm=='e' || comm=='f') {
  602. p1 = savedfile;
  603. p2 = file;
  604. while ((*p1++ = *p2++))
  605. ;
  606. }
  607. }
  608. void
  609. exfile(void)
  610. {
  611. close(io);
  612. io = -1;
  613. if (vflag) {
  614. putd();
  615. putchr('\n');
  616. }
  617. }
  618. void
  619. onintr(int sig)
  620. {
  621. signal(SIGINT, onintr);
  622. putchr('\n');
  623. lastc = '\n';
  624. error(Q);
  625. }
  626. void
  627. onhup(int sig)
  628. {
  629. signal(SIGINT, SIG_IGN);
  630. signal(SIGHUP, SIG_IGN);
  631. if (dol > zero) {
  632. addr1 = zero+1;
  633. addr2 = dol;
  634. io = open("ed.hup", O_WRONLY | O_TRUNC | O_CREAT, 0600);
  635. if (io > 0) {
  636. uioinit(io,uio);
  637. putfile();
  638. uioflush(uio);
  639. exfile();
  640. }
  641. }
  642. fchange = 0;
  643. quit();
  644. }
  645. void
  646. error(int *s)
  647. {
  648. int c;
  649. wrapp = 0;
  650. listf = 0;
  651. listn = 0;
  652. count = 0;
  653. lseek(0, 0, SEEK_END);
  654. pflag = 0;
  655. if (globp)
  656. lastc = '\n';
  657. globp = 0;
  658. peekc = lastc;
  659. if(lastc)
  660. while ((c = getchr()) != '\n' && c != EOF)
  661. ;
  662. if (io > 0) {
  663. close(io);
  664. io = -1;
  665. }
  666. putchr('?');
  667. putst(s);
  668. longjmp(savej, 1);
  669. }
  670. int
  671. getchr(void)
  672. {
  673. byte b[utfbytes];
  674. byte *c;
  675. c=b;
  676. if ((lastc = peekc)) {
  677. peekc = 0;
  678. return lastc;
  679. }
  680. if (globp) {
  681. if ((lastc = *globp++) != 0)
  682. return lastc;
  683. globp = 0;
  684. return EOF;
  685. }
  686. if(read(0,c,1)<= 0)
  687. return lastc = EOF;
  688. if(convnutf(c,&lastc,1))
  689. return lastc; /* unicode ascii */
  690. /*
  691. * lastc should now hold the number of extra bytes needed,
  692. * or 0 if there was a decoding error.
  693. */
  694. if(0==lastc)
  695. return lastc=utfeof; /* decoding error */
  696. if(read(0,++c,lastc)<=0) /* get required extra bytes */
  697. return lastc=utfeof;
  698. if(convutf(--c,&lastc)) /* convert to codepoint */
  699. return lastc;
  700. return lastc = utfeof; /* decoding error */
  701. }
  702. int
  703. gety(void)
  704. {
  705. int c;
  706. int *gf;
  707. int *p;
  708. p = linebuf;
  709. gf = globp;
  710. while ((c = getchr()) != '\n') {
  711. if (c==EOF) {
  712. if (gf)
  713. peekc = c;
  714. return c;
  715. }
  716. if (c == 0)
  717. continue;
  718. *p++ = c;
  719. if (p >= &linebuf[LBSIZE-2])
  720. error(Q);
  721. }
  722. *p = 0;
  723. return 0;
  724. }
  725. int
  726. gettty(void)
  727. {
  728. int rc;
  729. if ((rc = gety()))
  730. return rc;
  731. if (linebuf[0]=='.' && linebuf[1]==0)
  732. return EOF;
  733. return 0;
  734. }
  735. int
  736. getfile(void)
  737. {
  738. int c;
  739. int *lp;
  740. lp = linebuf;
  741. do {
  742. if(uioread(uio,&c,1)<0)
  743. error(Q);
  744. if(c==utfeof) {
  745. if (lp>linebuf) {
  746. putst(NAPPENDED);
  747. c = '\n';
  748. } else
  749. return EOF;
  750. }
  751. if (c == '\0')
  752. continue;
  753. if (lp >= &linebuf[LBSIZE]) {
  754. lastc = '\n';
  755. error(Q);
  756. }
  757. *lp++ = c;
  758. count++;
  759. } while (c != '\n');
  760. *--lp = 0;
  761. return 0;
  762. }
  763. void
  764. putfile(void)
  765. {
  766. long *a1;
  767. int c;
  768. int *lp;
  769. a1 = addr1;
  770. do {
  771. lp = getline(*a1++);
  772. for (;;) {
  773. count++;
  774. if ((c = *lp++) == 0) {
  775. if(uiowrite(uio,NL,1)<0)
  776. error(Q);
  777. break;
  778. }
  779. if(uiowrite(uio,&c,1)<0)
  780. error(Q);
  781. }
  782. } while (a1 <= addr2);
  783. }
  784. long
  785. append(int (*f)(void), long *a)
  786. {
  787. long *a1, *a2, *rdot, *ozero, nline, tl;
  788. nline = 0;
  789. dot = a;
  790. while ((*f)() == 0) {
  791. if ((dol-zero)+1 >= nlall) {
  792. ozero = zero;
  793. nlall += 1024;
  794. if ((zero = (long *)realloc((void *)zero, nlall*sizeof(long)))==NULL) {
  795. error(M);
  796. onhup(0);
  797. }
  798. dot += zero - ozero;
  799. dol += zero - ozero;
  800. }
  801. tl = putline();
  802. nline++;
  803. a1 = ++dol;
  804. a2 = a1+1;
  805. rdot = ++dot;
  806. while (a1 > rdot)
  807. *--a2 = *--a1;
  808. *rdot = tl;
  809. }
  810. return nline;
  811. }
  812. void
  813. add(int i)
  814. {
  815. if (i && (given || dol>zero)) {
  816. addr1--;
  817. addr2--;
  818. }
  819. squeeze(0);
  820. newline();
  821. append(gettty, addr2);
  822. }
  823. void
  824. browse(void)
  825. {
  826. int forward, n;
  827. static int bformat, bnum; /* 0 */
  828. forward = 1;
  829. if((peekc=getchr()) != '\n'){
  830. if (peekc=='-' || peekc=='+') {
  831. if(peekc == '-')
  832. forward=0;
  833. getchr();
  834. }
  835. if((n=getnum()) > 0)
  836. bpagesize = n;
  837. }
  838. newline();
  839. if (pflag) {
  840. bformat = listf;
  841. bnum = listn;
  842. } else {
  843. listf = bformat;
  844. listn = bnum;
  845. }
  846. if (forward) {
  847. addr1 = addr2;
  848. if((addr2+=bpagesize) > dol)
  849. addr2 = dol;
  850. } else {
  851. if((addr1=addr2-bpagesize) <= zero)
  852. addr1 = zero+1;
  853. }
  854. printcom();
  855. }
  856. void
  857. callunix(void)
  858. {
  859. pid_t pid, rpid;
  860. void (*savint)(int);
  861. int retcode;
  862. setnoaddr();
  863. if ((pid = fork()) == 0) {
  864. signal(SIGHUP, oldhup);
  865. signal(SIGQUIT, oldquit);
  866. execl("/bin/sh", "sh", "-t", (char *)NULL);
  867. bye(0100);
  868. }
  869. savint = signal(SIGINT, SIG_IGN);
  870. while ((rpid = wait(&retcode)) != pid && rpid != -1)
  871. ;
  872. signal(SIGINT, savint);
  873. if (vflag) {
  874. putst(SHRIEK);
  875. }
  876. }
  877. void
  878. quit(void)
  879. {
  880. if (vflag && fchange && dol!=zero) {
  881. fchange = 0;
  882. error(Q);
  883. }
  884. bye(0);
  885. }
  886. void
  887. bye(int e)
  888. {
  889. unlink(tfname);
  890. free(zero);
  891. exit(e);
  892. }
  893. void
  894. onquit(int sig)
  895. {
  896. quit();
  897. }
  898. void
  899. rdelete(long *ad1, long *ad2)
  900. {
  901. long *a1, *a2, *a3;
  902. a1 = ad1;
  903. a2 = ad2+1;
  904. a3 = dol;
  905. dol -= a2 - a1;
  906. do {
  907. *a1++ = *a2++;
  908. } while (a2 <= a3);
  909. a1 = ad1;
  910. if (a1 > dol)
  911. a1 = dol;
  912. dot = a1;
  913. fchange = 1;
  914. }
  915. void
  916. gdelete(void)
  917. {
  918. long *a1, *a2, *a3;
  919. a3 = dol;
  920. for (a1=zero; (*a1&01)==0; a1++)
  921. if (a1>=a3)
  922. return;
  923. for (a2=a1+1; a2<=a3;) {
  924. if (*a2&01) {
  925. a2++;
  926. dot = a1;
  927. } else
  928. *a1++ = *a2++;
  929. }
  930. dol = a1-1;
  931. if (dot>dol)
  932. dot = dol;
  933. fchange = 1;
  934. }
  935. int*
  936. getline(long tl)
  937. {
  938. int *bp;
  939. int *lp;
  940. long nl;
  941. lp = linebuf;
  942. bp = getblock(tl, READ);
  943. nl = nleft;
  944. tl &= ~((BLKSIZE/2)-1);
  945. while ((*lp++ = *bp++))
  946. if (--nl == 0) {
  947. bp = getblock(tl+=(BLKSIZE/2), READ);
  948. nl = nleft;
  949. }
  950. return linebuf;
  951. }
  952. int
  953. putline(void)
  954. {
  955. int *bp;
  956. int *lp;
  957. long nl, tl;
  958. fchange = 1;
  959. lp = linebuf;
  960. tl = tline;
  961. bp = getblock(tl, WRITE);
  962. nl = nleft;
  963. tl &= ~((BLKSIZE/2)-1);
  964. while ((*bp = *lp++)) {
  965. if (*bp++ == '\n') {
  966. *--bp = 0;
  967. linebp = lp;
  968. break;
  969. }
  970. if (--nl == 0) {
  971. bp = getblock(tl+=(BLKSIZE/2), WRITE);
  972. nl = nleft;
  973. }
  974. }
  975. nl = tline;
  976. tline += (((lp-linebuf)+03)>>1)&~01;
  977. return nl;
  978. }
  979. void
  980. blkio(int b, int *buf, int rw)
  981. {
  982. if(lseek(tfile, (long)b*(long)BLKBSIZE, SEEK_SET)<0L)
  983. error(T);
  984. if(rw == READ) {
  985. if (read(tfile, buf, BLKBSIZE) != BLKBSIZE)
  986. error(T);
  987. } else if(rw == WRITE) {
  988. if (write(tfile, buf, BLKBSIZE) != BLKBSIZE)
  989. error(T);
  990. } else error(T);
  991. }
  992. int *
  993. getblock(long atl, int iof)
  994. {
  995. int bno, off;
  996. bno = (atl/(BLKSIZE/2));
  997. off = (atl<<1) & (BLKSIZE-1) & ~03;
  998. nleft = BLKSIZE - off;
  999. if (bno==iblock) {
  1000. ichanged |= iof;
  1001. return ibuff+off;
  1002. }
  1003. if (bno==oblock)
  1004. return obuff+off;
  1005. if (iof==READ) {
  1006. if (ichanged)
  1007. blkio(iblock, ibuff, WRITE);
  1008. ichanged = 0;
  1009. iblock = bno;
  1010. blkio(bno, ibuff, READ);
  1011. return ibuff+off;
  1012. }
  1013. if (oblock>=0)
  1014. blkio(oblock, obuff, WRITE);
  1015. oblock = bno;
  1016. return obuff+off;
  1017. }
  1018. void
  1019. init(void)
  1020. {
  1021. long *markp;
  1022. char *a, *b;
  1023. close(tfile);
  1024. unlink(tfname);
  1025. a=tfname;
  1026. b=tftemp;
  1027. while((*a++=*b++))
  1028. ;
  1029. if((tfile = mkstemp(tfname)) == -1)
  1030. error(T);
  1031. tline = 2;
  1032. for (markp = names; markp < &names[26]; )
  1033. *markp++ = 0;
  1034. subnewa = 0;
  1035. anymarks = 0;
  1036. iblock = -1;
  1037. oblock = -1;
  1038. ichanged = 0;
  1039. dot = dol = zero;
  1040. }
  1041. void
  1042. global(int k)
  1043. {
  1044. int *gp, globuf[GBSIZE];
  1045. int c;
  1046. long *a1;
  1047. if (globp)
  1048. error(Q);
  1049. setwide();
  1050. squeeze(dol>zero);
  1051. if ((c=getchr())=='\n')
  1052. error(Q);
  1053. compile(c);
  1054. gp = globuf;
  1055. while ((c = getchr()) != '\n') {
  1056. if (c==EOF)
  1057. error(Q);
  1058. if (c=='\\') {
  1059. c = getchr();
  1060. if (c!='\n')
  1061. *gp++ = '\\';
  1062. }
  1063. *gp++ = c;
  1064. if (gp >= &globuf[GBSIZE-2])
  1065. error(Q);
  1066. }
  1067. if (gp == globuf)
  1068. *gp++ = 'p';
  1069. *gp++ = '\n';
  1070. *gp = 0;
  1071. for (a1=zero; a1<=dol; a1++) {
  1072. *a1 = unmark(*a1);
  1073. if (a1>=addr1 && a1<=addr2 && execute(a1)==k)
  1074. *a1 = mark(*a1);
  1075. }
  1076. /*
  1077. * Special case: g/.../d (avoid n^2 algorithm)
  1078. */
  1079. if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') {
  1080. gdelete();
  1081. return;
  1082. }
  1083. for (a1=zero; a1<=dol; a1++) {
  1084. if (marked(*a1)) {
  1085. *a1 = unmark(*a1);
  1086. dot = a1;
  1087. globp = globuf;
  1088. commands();
  1089. a1 = zero;
  1090. }
  1091. }
  1092. }
  1093. void
  1094. join(void)
  1095. {
  1096. int *gp, *lp;
  1097. long *a1;
  1098. nonzero();
  1099. gp = genbuf;
  1100. for (a1=addr1; a1<=addr2; a1++) {
  1101. lp = getline(*a1);
  1102. while ((*gp = *lp++))
  1103. if (gp++ >= &genbuf[LBSIZE-2])
  1104. error(Q);
  1105. }
  1106. lp = linebuf;
  1107. gp = genbuf;
  1108. while ((*lp++ = *gp++))
  1109. ;
  1110. *addr1 = putline();
  1111. if (addr1 < addr2)
  1112. rdelete(addr1+1, addr2);
  1113. dot = addr1;
  1114. }
  1115. void
  1116. substitute(int inglob)
  1117. {
  1118. long *mp, *a1, nl, *ozero;
  1119. int gsubf, m, n;
  1120. n = getnum(); /* OK even if n==0 */
  1121. gsubf = compsub();
  1122. for (a1 = addr1; a1 <= addr2; a1++) {
  1123. if (execute(a1)){
  1124. m = n;
  1125. do {
  1126. int span = loc2-loc1;
  1127. if (--m <= 0) {
  1128. dosub();
  1129. if (!gsubf)
  1130. break;
  1131. if (span == 0) { /* null RE match */
  1132. if (*loc2=='\0')
  1133. break;
  1134. loc2++;
  1135. }
  1136. }
  1137. } while (execute((long*)0));
  1138. if (m <= 0) {
  1139. inglob = mark(inglob);
  1140. subnewa = putline();
  1141. *a1 = unmark(*a1);
  1142. if (anymarks) {
  1143. for (mp = names; mp < &names[26]; mp++)
  1144. if (*mp == *a1)
  1145. *mp = subnewa;
  1146. }
  1147. subolda = *a1;
  1148. *a1 = subnewa;
  1149. ozero = zero;
  1150. nl = append(getsub, a1);
  1151. nl += zero-ozero;
  1152. a1 += nl;
  1153. addr2 += nl;
  1154. }
  1155. }
  1156. }
  1157. if (inglob==0)
  1158. error(Q);
  1159. }
  1160. int
  1161. compsub(void)
  1162. {
  1163. int seof, c;
  1164. int *p;
  1165. if ((seof = getchr()) == '\n' || seof == ' ')
  1166. error(Q);
  1167. compile(seof);
  1168. p = rhsbuf;
  1169. for (;;) {
  1170. c = getchr();
  1171. if (c=='\\')
  1172. c = escape(getchr());
  1173. if (c=='\n') {
  1174. if (globp && globp[0]) /* last '\n' does not count */
  1175. c = escape(c);
  1176. else {
  1177. peekc = c;
  1178. pflag++;
  1179. break;
  1180. }
  1181. }
  1182. if (c == seof)
  1183. break;
  1184. *p++ = c;
  1185. if (p >= &rhsbuf[LBSIZE/2])
  1186. error(Q);
  1187. }
  1188. *p = 0;
  1189. if ((peekc = getchr()) == 'g') {
  1190. peekc = 0;
  1191. newline();
  1192. return 1;
  1193. }
  1194. newline();
  1195. return 0;
  1196. }
  1197. int
  1198. getsub(void)
  1199. {
  1200. int *p1, *p2;
  1201. p1 = linebuf;
  1202. if ((p2 = linebp) == 0)
  1203. return EOF;
  1204. while ((*p1++ = *p2++))
  1205. ;
  1206. linebp = 0;
  1207. return 0;
  1208. }
  1209. void
  1210. dosub(void)
  1211. {
  1212. int *lp, *sp, *rp;
  1213. int c;
  1214. lp = linebuf;
  1215. sp = genbuf;
  1216. rp = rhsbuf;
  1217. while (lp < loc1)
  1218. *sp++ = *lp++;
  1219. while ((c = *rp++)) {
  1220. if (c=='&') {
  1221. sp = place(sp, loc1, loc2);
  1222. continue;
  1223. } else if (escaped(c) && (c=unescape(c)) >='1' && c < nbra+'1') {
  1224. sp = place(sp, braslist[c-'1'], braelist[c-'1']);
  1225. continue;
  1226. }
  1227. *sp++ = c;
  1228. if (sp >= &genbuf[LBSIZE])
  1229. error(Q);
  1230. }
  1231. lp = loc2;
  1232. loc2 = sp - genbuf + linebuf;
  1233. while ((*sp++ = *lp++))
  1234. if (sp >= &genbuf[LBSIZE])
  1235. error(Q);
  1236. lp = linebuf;
  1237. sp = genbuf;
  1238. while ((*lp++ = *sp++))
  1239. ;
  1240. }
  1241. int*
  1242. place(int *sp, int *l1, int *l2)
  1243. {
  1244. while (l1 < l2) {
  1245. *sp++ = *l1++;
  1246. if (sp >= &genbuf[LBSIZE])
  1247. error(Q);
  1248. }
  1249. return sp;
  1250. }
  1251. void
  1252. move(int cflag)
  1253. {
  1254. long *adt, *ad1, *ad2, *ozero, delta;
  1255. nonzero();
  1256. if ((adt = address())==0) /* address() guarantees addr is in range */
  1257. error(Q);
  1258. newline();
  1259. if (cflag) {
  1260. ad1 = dol;
  1261. ozero = zero;
  1262. append(getcopy, ad1++);
  1263. ad2 = dol;
  1264. delta = zero - ozero;
  1265. ad1 += delta;
  1266. adt += delta;
  1267. } else {
  1268. ad2 = addr2;
  1269. for (ad1 = addr1; ad1 <= ad2;) {
  1270. *ad1=unmark(*ad1);
  1271. ad1++;
  1272. }
  1273. ad1 = addr1;
  1274. }
  1275. ad2++;
  1276. if (adt<ad1) {
  1277. dot = adt + (ad2-ad1);
  1278. if ((++adt)==ad1)
  1279. return;
  1280. reverse(adt, ad1);
  1281. reverse(ad1, ad2);
  1282. reverse(adt, ad2);
  1283. } else if (adt >= ad2) {
  1284. dot = adt++;
  1285. reverse(ad1, ad2);
  1286. reverse(ad2, adt);
  1287. reverse(ad1, adt);
  1288. } else
  1289. error(Q);
  1290. fchange = 1;
  1291. }
  1292. void
  1293. reverse(long *a1, long *a2)
  1294. {
  1295. long t;
  1296. for (;;) {
  1297. t = *--a2;
  1298. if (a2 <= a1)
  1299. return;
  1300. *a2 = *a1;
  1301. *a1++ = t;
  1302. }
  1303. }
  1304. int
  1305. getcopy(void)
  1306. {
  1307. if (addr1 > addr2)
  1308. return EOF;
  1309. getline(*addr1++);
  1310. return 0;
  1311. }
  1312. void
  1313. compile(int eof)
  1314. {
  1315. int c, cclcnt;
  1316. int *ep, *lastep, bracket[NBRA], *bracketp;
  1317. ep = expbuf;
  1318. bracketp = bracket;
  1319. if ((c = getchr()) == '\n') {
  1320. peekc = c;
  1321. c = eof;
  1322. }
  1323. if (c == eof) {
  1324. if (*ep==0)
  1325. error(Q);
  1326. return;
  1327. }
  1328. nbra = 0;
  1329. if (c=='^') {
  1330. c = getchr();
  1331. *ep++ = CCIRC;
  1332. }
  1333. peekc = c;
  1334. lastep = 0;
  1335. for (;;) {
  1336. if (ep >= &expbuf[ESIZE])
  1337. goto cerror;
  1338. c = getchr();
  1339. if (c == '\n') {
  1340. peekc = c;
  1341. c = eof;
  1342. }
  1343. if (c==eof) {
  1344. if (bracketp != bracket)
  1345. goto cerror;
  1346. *ep = CEFIL;
  1347. return;
  1348. }
  1349. if (c!='*')
  1350. lastep = ep;
  1351. switch (c) {
  1352. case '\\':
  1353. if ((c = getchr())=='(') {
  1354. if (nbra >= NBRA)
  1355. goto cerror;
  1356. *bracketp++ = nbra;
  1357. *ep++ = CBRA;
  1358. *ep++ = nbra++;
  1359. continue;
  1360. }
  1361. if (c == ')') {
  1362. if (bracketp <= bracket)
  1363. goto cerror;
  1364. *ep++ = CKET;
  1365. *ep++ = *--bracketp;
  1366. continue;
  1367. }
  1368. if (c>='1' && c<'1'+NBRA) {
  1369. *ep++ = CBACK;
  1370. *ep++ = c-'1';
  1371. continue;
  1372. }
  1373. *ep++ = CCHR;
  1374. if (c=='\n')
  1375. goto cerror;
  1376. *ep++ = c;
  1377. continue;
  1378. case '.':
  1379. *ep++ = CDOT;
  1380. continue;
  1381. case '\n':
  1382. goto cerror;
  1383. case '*':
  1384. if (lastep==0 || *lastep==CBRA || *lastep==CKET)
  1385. goto defchar;
  1386. *lastep |= STAR;
  1387. continue;
  1388. case '$':
  1389. if ((peekc=getchr()) != eof && peekc!='\n')
  1390. goto defchar;
  1391. *ep++ = CDOL;
  1392. continue;
  1393. case '[':
  1394. *ep++ = CCL;
  1395. *ep++ = 0;
  1396. cclcnt = 1;
  1397. if ((c=getchr()) == '^') {
  1398. c = getchr();
  1399. ep[-2] = NCCL;
  1400. }
  1401. do {
  1402. if (c=='\n')
  1403. goto cerror;
  1404. if (c=='-' && ep[-1]!=0) {
  1405. if ((c=getchr())==']') {
  1406. *ep++ = '-';
  1407. cclcnt++;
  1408. if (ep >= &expbuf[ESIZE])
  1409. goto cerror;
  1410. *ep++ = '-';
  1411. cclcnt++;
  1412. if (ep >= &expbuf[ESIZE])
  1413. goto cerror;
  1414. break;
  1415. }
  1416. ep[-1]=c;
  1417. continue;
  1418. }
  1419. *ep++ = c;
  1420. cclcnt++;
  1421. if (ep >= &expbuf[ESIZE])
  1422. goto cerror;
  1423. *ep++ = c;
  1424. cclcnt++;
  1425. if (ep >= &expbuf[ESIZE])
  1426. goto cerror;
  1427. } while ((c = getchr()) != ']');
  1428. lastep[1] = cclcnt;
  1429. continue;
  1430. defchar:
  1431. default:
  1432. *ep++ = CCHR;
  1433. *ep++ = c;
  1434. }
  1435. }
  1436. cerror:
  1437. expbuf[0] = 0;
  1438. nbra = 0;
  1439. error(Q);
  1440. }
  1441. int
  1442. execute(long *addr)
  1443. {
  1444. int *p1, *p2;
  1445. int c;
  1446. for (c=0; c<NBRA; c++) {
  1447. braslist[c] = 0;
  1448. braelist[c] = 0;
  1449. }
  1450. p2 = expbuf;
  1451. if (addr == (long*)0) {
  1452. if (*p2 == CCIRC)
  1453. return 0;
  1454. p1 = loc2;
  1455. } else {
  1456. if (addr == zero)
  1457. return 0;
  1458. p1 = getline(*addr);
  1459. }
  1460. if (*p2 == CCIRC) {
  1461. loc1 = p1;
  1462. return advance(p1, p2+1);
  1463. }
  1464. /* fast check for first character */
  1465. if (*p2 == CCHR) {
  1466. c = p2[1];
  1467. do {
  1468. if (*p1!=c)
  1469. continue;
  1470. if (advance(p1, p2)) {
  1471. loc1 = p1;
  1472. return 1;
  1473. }
  1474. } while (*p1++);
  1475. return 0;
  1476. }
  1477. /* regular algorithm */
  1478. do {
  1479. if (advance(p1, p2)) {
  1480. loc1 = p1;
  1481. return 1;
  1482. }
  1483. } while (*p1++);
  1484. return 0;
  1485. }
  1486. int
  1487. advance(int *lp, int *ep)
  1488. {
  1489. int *curlp;
  1490. int i;
  1491. for (;;)
  1492. switch (*ep++) {
  1493. case CCHR:
  1494. if (*ep++ == *lp++)
  1495. continue;
  1496. return 0;
  1497. case CDOT:
  1498. if (*lp++)
  1499. continue;
  1500. return 0;
  1501. case CDOL:
  1502. if (*lp==0)
  1503. continue;
  1504. return 0;
  1505. case CEFIL:
  1506. loc2 = lp;
  1507. return 1;
  1508. case CCL:
  1509. if (cclass(ep, *lp++, 1)) {
  1510. ep += *ep;
  1511. continue;
  1512. }
  1513. return 0;
  1514. case NCCL:
  1515. if (cclass(ep, *lp++, 0)) {
  1516. ep += *ep;
  1517. continue;
  1518. }
  1519. return 0;
  1520. case CBRA:
  1521. braslist[*ep++] = lp;
  1522. continue;
  1523. case CKET:
  1524. braelist[*ep++] = lp;
  1525. continue;
  1526. case CBACK:
  1527. if (braelist[i = *ep++]==0)
  1528. error(Q);
  1529. if (backref(i, lp)) {
  1530. lp += braelist[i] - braslist[i];
  1531. continue;
  1532. }
  1533. return 0;
  1534. case CBACK|STAR:
  1535. if (braelist[i = *ep++] == 0)
  1536. error(Q);
  1537. curlp = lp;
  1538. while (backref(i, lp))
  1539. lp += braelist[i] - braslist[i];
  1540. while (lp >= curlp) {
  1541. if (advance(lp, ep))
  1542. return 1;
  1543. lp -= braelist[i] - braslist[i];
  1544. }
  1545. continue;
  1546. case CDOT|STAR:
  1547. curlp = lp;
  1548. while (*lp++)
  1549. ;
  1550. goto star;
  1551. case CCHR|STAR:
  1552. curlp = lp;
  1553. while (*lp++ == *ep)
  1554. ;
  1555. ep++;
  1556. goto star;
  1557. case CCL|STAR:
  1558. case NCCL|STAR:
  1559. curlp = lp;
  1560. while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)))
  1561. ;
  1562. ep += *ep;
  1563. goto star;
  1564. star:
  1565. do {
  1566. lp--;
  1567. if (advance(lp, ep))
  1568. return 1;
  1569. } while (lp > curlp);
  1570. return 0;
  1571. default:
  1572. error(Q);
  1573. }
  1574. }
  1575. int
  1576. backref(int i, int *lp)
  1577. {
  1578. int *bp;
  1579. bp = braslist[i];
  1580. while (*bp++ == *lp++)
  1581. if (bp >= braelist[i])
  1582. return 1;
  1583. return 0;
  1584. }
  1585. int
  1586. cclass(int *set, int c, int af)
  1587. {
  1588. int n;
  1589. if (c==0)
  1590. return 0;
  1591. n = *set++;
  1592. while (--n) {
  1593. if (c >= *set++) {
  1594. if(c <= *set++)
  1595. return af;
  1596. } else
  1597. ++set;
  1598. }
  1599. return !af;
  1600. }
  1601. void
  1602. putd(void)
  1603. {
  1604. int r;
  1605. r = count%10;
  1606. count /= 10;
  1607. if (count)
  1608. putd();
  1609. putchr(r + '0');
  1610. }
  1611. void
  1612. putst(int *sp)
  1613. {
  1614. col = 0;
  1615. while (*sp)
  1616. putchr(*sp++);
  1617. putchr('\n');
  1618. }
  1619. void
  1620. putchr(int c)
  1621. {
  1622. int *lp;
  1623. byte utf[utfbytes+1];
  1624. byte a, *b;
  1625. int n;
  1626. lp = linp;
  1627. if (listf) {
  1628. if (c=='\n') {
  1629. if (linp!=line && linp[-1]==' ') {
  1630. *lp++ = '\\';
  1631. *lp++ = 'n';
  1632. }
  1633. *lp++ = c;
  1634. } else {
  1635. if (col >= (LINELEN-BELL)) {
  1636. col = 8;
  1637. *lp++ = '\\';
  1638. *lp++ = '\n';
  1639. *lp++ = '\t';
  1640. }
  1641. col++;
  1642. if (c=='\b' || c=='\t' || c=='\\') {
  1643. *lp++ = '\\';
  1644. if (c=='\b')
  1645. c = 'b';
  1646. else if (c=='\t')
  1647. c = 't';
  1648. *lp++ = c;
  1649. col++;
  1650. } else if (c<' ' || c>='\177') {
  1651. convnucode(c,utf,utfbytes);
  1652. b=utf;
  1653. while((a=*b++)) {
  1654. *lp++ = '\\';
  1655. *lp++ = ((a>>6)&03) + '0';
  1656. *lp++ = ((a>>3)&07) + '0';
  1657. *lp++ = (a & 07) + '0';
  1658. col += 4;
  1659. }
  1660. } else
  1661. *lp++ = c;
  1662. }
  1663. } else
  1664. *lp++ = c;
  1665. if(c == '\n' || lp >= &line[LINELEN-BELL]) {
  1666. linp=line;
  1667. n=utf8nstring(line,utf8buff,lp-line);
  1668. write(oflag?2:1, utf8buff, n);
  1669. return;
  1670. }
  1671. linp = lp;
  1672. }