xec.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. #include "sam.h"
  2. #include "parse.h"
  3. int Glooping;
  4. int nest;
  5. int append(File*, Cmd*, Posn);
  6. int display(File*);
  7. void looper(File*, Cmd*, int);
  8. void filelooper(Cmd*, int);
  9. void linelooper(File*, Cmd*);
  10. void
  11. resetxec(void)
  12. {
  13. Glooping = nest = 0;
  14. }
  15. int
  16. cmdexec(File *f, Cmd *cp)
  17. {
  18. int i;
  19. Addr *ap;
  20. Address a;
  21. if(f && f->unread)
  22. load(f);
  23. if(f==0 && (cp->addr==0 || cp->addr->type!='"') &&
  24. !utfrune("bBnqUXY!", cp->cmdc) &&
  25. cp->cmdc!=('c'|0x100) && !(cp->cmdc=='D' && cp->ctext))
  26. error(Enofile);
  27. i = lookup(cp->cmdc);
  28. if(i >= 0 && cmdtab[i].defaddr != aNo){
  29. if((ap=cp->addr)==0 && cp->cmdc!='\n'){
  30. cp->addr = ap = newaddr();
  31. ap->type = '.';
  32. if(cmdtab[i].defaddr == aAll)
  33. ap->type = '*';
  34. }else if(ap && ap->type=='"' && ap->next==0 && cp->cmdc!='\n'){
  35. ap->next = newaddr();
  36. ap->next->type = '.';
  37. if(cmdtab[i].defaddr == aAll)
  38. ap->next->type = '*';
  39. }
  40. if(cp->addr){ /* may be false for '\n' (only) */
  41. static Address none = {0,0,0};
  42. if(f)
  43. addr = address(ap, f->dot, 0);
  44. else /* a " */
  45. addr = address(ap, none, 0);
  46. f = addr.f;
  47. }
  48. }
  49. current(f);
  50. switch(cp->cmdc){
  51. case '{':
  52. a = cp->addr? address(cp->addr, f->dot, 0): f->dot;
  53. for(cp = cp->ccmd; cp; cp = cp->next){
  54. a.f->dot = a;
  55. cmdexec(a.f, cp);
  56. }
  57. break;
  58. default:
  59. i=(*cmdtab[i].fn)(f, cp);
  60. return i;
  61. }
  62. return 1;
  63. }
  64. int
  65. a_cmd(File *f, Cmd *cp)
  66. {
  67. return append(f, cp, addr.r.p2);
  68. }
  69. int
  70. b_cmd(File *f, Cmd *cp)
  71. {
  72. USED(f);
  73. f = cp->cmdc=='b'? tofile(cp->ctext) : getfile(cp->ctext);
  74. if(f->unread)
  75. load(f);
  76. else if(nest == 0)
  77. filename(f);
  78. return TRUE;
  79. }
  80. int
  81. c_cmd(File *f, Cmd *cp)
  82. {
  83. logdelete(f, addr.r.p1, addr.r.p2);
  84. f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p2;
  85. return append(f, cp, addr.r.p2);
  86. }
  87. int
  88. d_cmd(File *f, Cmd *cp)
  89. {
  90. USED(cp);
  91. logdelete(f, addr.r.p1, addr.r.p2);
  92. f->ndot.r.p1 = f->ndot.r.p2 = addr.r.p1;
  93. return TRUE;
  94. }
  95. int
  96. D_cmd(File *f, Cmd *cp)
  97. {
  98. closefiles(f, cp->ctext);
  99. return TRUE;
  100. }
  101. int
  102. e_cmd(File *f, Cmd *cp)
  103. {
  104. if(getname(f, cp->ctext, cp->cmdc=='e')==0)
  105. error(Enoname);
  106. edit(f, cp->cmdc);
  107. return TRUE;
  108. }
  109. int
  110. f_cmd(File *f, Cmd *cp)
  111. {
  112. getname(f, cp->ctext, TRUE);
  113. filename(f);
  114. return TRUE;
  115. }
  116. int
  117. g_cmd(File *f, Cmd *cp)
  118. {
  119. if(f!=addr.f)panic("g_cmd f!=addr.f");
  120. compile(cp->re);
  121. if(execute(f, addr.r.p1, addr.r.p2) ^ cp->cmdc=='v'){
  122. f->dot = addr;
  123. return cmdexec(f, cp->ccmd);
  124. }
  125. return TRUE;
  126. }
  127. int
  128. i_cmd(File *f, Cmd *cp)
  129. {
  130. return append(f, cp, addr.r.p1);
  131. }
  132. int
  133. k_cmd(File *f, Cmd *cp)
  134. {
  135. USED(cp);
  136. f->mark = addr.r;
  137. return TRUE;
  138. }
  139. int
  140. m_cmd(File *f, Cmd *cp)
  141. {
  142. Address addr2;
  143. addr2 = address(cp->caddr, f->dot, 0);
  144. if(cp->cmdc=='m')
  145. move(f, addr2);
  146. else
  147. copy(f, addr2);
  148. return TRUE;
  149. }
  150. int
  151. n_cmd(File *f, Cmd *cp)
  152. {
  153. int i;
  154. USED(f);
  155. USED(cp);
  156. for(i = 0; i<file.nused; i++){
  157. if(file.filepptr[i] == cmd)
  158. continue;
  159. f = file.filepptr[i];
  160. Strduplstr(&genstr, &f->name);
  161. filename(f);
  162. }
  163. return TRUE;
  164. }
  165. int
  166. p_cmd(File *f, Cmd *cp)
  167. {
  168. USED(cp);
  169. return display(f);
  170. }
  171. int
  172. q_cmd(File *f, Cmd *cp)
  173. {
  174. USED(cp);
  175. USED(f);
  176. trytoquit();
  177. if(downloaded){
  178. outT0(Hexit);
  179. return TRUE;
  180. }
  181. return FALSE;
  182. }
  183. int
  184. s_cmd(File *f, Cmd *cp)
  185. {
  186. int i, j, c, n;
  187. Posn p1, op, didsub = 0, delta = 0;
  188. n = cp->num;
  189. op= -1;
  190. compile(cp->re);
  191. for(p1 = addr.r.p1; p1<=addr.r.p2 && execute(f, p1, addr.r.p2); ){
  192. if(sel.p[0].p1==sel.p[0].p2){ /* empty match? */
  193. if(sel.p[0].p1==op){
  194. p1++;
  195. continue;
  196. }
  197. p1 = sel.p[0].p2+1;
  198. }else
  199. p1 = sel.p[0].p2;
  200. op = sel.p[0].p2;
  201. if(--n>0)
  202. continue;
  203. Strzero(&genstr);
  204. for(i = 0; i<cp->ctext->n; i++)
  205. if((c = cp->ctext->s[i])=='\\' && i<cp->ctext->n-1){
  206. c = cp->ctext->s[++i];
  207. if('1'<=c && c<='9') {
  208. j = c-'0';
  209. if(sel.p[j].p2-sel.p[j].p1>BLOCKSIZE)
  210. error(Elongtag);
  211. bufread(f, sel.p[j].p1, genbuf, sel.p[j].p2-sel.p[j].p1);
  212. Strinsert(&genstr, tmprstr(genbuf, (sel.p[j].p2-sel.p[j].p1)), genstr.n);
  213. }else
  214. Straddc(&genstr, c);
  215. }else if(c!='&')
  216. Straddc(&genstr, c);
  217. else{
  218. if(sel.p[0].p2-sel.p[0].p1>BLOCKSIZE)
  219. error(Elongrhs);
  220. bufread(f, sel.p[0].p1, genbuf, sel.p[0].p2-sel.p[0].p1);
  221. Strinsert(&genstr,
  222. tmprstr(genbuf, (int)(sel.p[0].p2-sel.p[0].p1)),
  223. genstr.n);
  224. }
  225. if(sel.p[0].p1!=sel.p[0].p2){
  226. logdelete(f, sel.p[0].p1, sel.p[0].p2);
  227. delta-=sel.p[0].p2-sel.p[0].p1;
  228. }
  229. if(genstr.n){
  230. loginsert(f, sel.p[0].p2, genstr.s, genstr.n);
  231. delta+=genstr.n;
  232. }
  233. didsub = 1;
  234. if(!cp->flag)
  235. break;
  236. }
  237. if(!didsub && nest==0)
  238. error(Enosub);
  239. f->ndot.r.p1 = addr.r.p1, f->ndot.r.p2 = addr.r.p2+delta;
  240. return TRUE;
  241. }
  242. int
  243. u_cmd(File *f, Cmd *cp)
  244. {
  245. int n;
  246. USED(f);
  247. USED(cp);
  248. n = cp->num;
  249. if(n >= 0)
  250. while(n-- && undo(TRUE))
  251. ;
  252. else
  253. while(n++ && undo(FALSE))
  254. ;
  255. return TRUE;
  256. }
  257. int
  258. w_cmd(File *f, Cmd *cp)
  259. {
  260. int fseq;
  261. fseq = f->seq;
  262. if(getname(f, cp->ctext, FALSE)==0)
  263. error(Enoname);
  264. if(fseq == seq)
  265. error_s(Ewseq, genc);
  266. writef(f);
  267. return TRUE;
  268. }
  269. int
  270. x_cmd(File *f, Cmd *cp)
  271. {
  272. if(cp->re)
  273. looper(f, cp, cp->cmdc=='x');
  274. else
  275. linelooper(f, cp);
  276. return TRUE;
  277. }
  278. int
  279. X_cmd(File *f, Cmd *cp)
  280. {
  281. USED(f);
  282. filelooper(cp, cp->cmdc=='X');
  283. return TRUE;
  284. }
  285. int
  286. plan9_cmd(File *f, Cmd *cp)
  287. {
  288. plan9(f, cp->cmdc, cp->ctext, nest);
  289. return TRUE;
  290. }
  291. int
  292. eq_cmd(File *f, Cmd *cp)
  293. {
  294. int charsonly;
  295. switch(cp->ctext->n){
  296. case 1:
  297. charsonly = FALSE;
  298. break;
  299. case 2:
  300. if(cp->ctext->s[0]=='#'){
  301. charsonly = TRUE;
  302. break;
  303. }
  304. default:
  305. SET(charsonly);
  306. error(Enewline);
  307. }
  308. printposn(f, charsonly);
  309. return TRUE;
  310. }
  311. int
  312. nl_cmd(File *f, Cmd *cp)
  313. {
  314. Address a;
  315. if(cp->addr == 0){
  316. /* First put it on newline boundaries */
  317. addr = lineaddr((Posn)0, f->dot, -1);
  318. a = lineaddr((Posn)0, f->dot, 1);
  319. addr.r.p2 = a.r.p2;
  320. if(addr.r.p1==f->dot.r.p1 && addr.r.p2==f->dot.r.p2)
  321. addr = lineaddr((Posn)1, f->dot, 1);
  322. display(f);
  323. }else if(downloaded)
  324. moveto(f, addr.r);
  325. else
  326. display(f);
  327. return TRUE;
  328. }
  329. int
  330. cd_cmd(File *f, Cmd *cp)
  331. {
  332. USED(f);
  333. cd(cp->ctext);
  334. return TRUE;
  335. }
  336. int
  337. append(File *f, Cmd *cp, Posn p)
  338. {
  339. if(cp->ctext->n>0 && cp->ctext->s[cp->ctext->n-1]==0)
  340. --cp->ctext->n;
  341. if(cp->ctext->n>0)
  342. loginsert(f, p, cp->ctext->s, cp->ctext->n);
  343. f->ndot.r.p1 = p;
  344. f->ndot.r.p2 = p+cp->ctext->n;
  345. return TRUE;
  346. }
  347. int
  348. display(File *f)
  349. {
  350. Posn p1, p2;
  351. int np;
  352. char *c;
  353. p1 = addr.r.p1;
  354. p2 = addr.r.p2;
  355. if(p2 > f->nc){
  356. fprint(2, "bad display addr p1=%ld p2=%ld f->nc=%d\n", p1, p2, f->nc); /*ZZZ should never happen, can remove */
  357. p2 = f->nc;
  358. }
  359. while(p1 < p2){
  360. np = p2-p1;
  361. if(np>BLOCKSIZE-1)
  362. np = BLOCKSIZE-1;
  363. bufread(f, p1, genbuf, np);
  364. genbuf[np] = 0;
  365. c = Strtoc(tmprstr(genbuf, np+1));
  366. if(downloaded)
  367. termwrite(c);
  368. else
  369. Write(1, c, strlen(c));
  370. free(c);
  371. p1 += np;
  372. }
  373. f->dot = addr;
  374. return TRUE;
  375. }
  376. void
  377. looper(File *f, Cmd *cp, int xy)
  378. {
  379. Posn p, op;
  380. Range r;
  381. r = addr.r;
  382. op= xy? -1 : r.p1;
  383. nest++;
  384. compile(cp->re);
  385. for(p = r.p1; p<=r.p2; ){
  386. if(!execute(f, p, r.p2)){ /* no match, but y should still run */
  387. if(xy || op>r.p2)
  388. break;
  389. f->dot.r.p1 = op, f->dot.r.p2 = r.p2;
  390. p = r.p2+1; /* exit next loop */
  391. }else{
  392. if(sel.p[0].p1==sel.p[0].p2){ /* empty match? */
  393. if(sel.p[0].p1==op){
  394. p++;
  395. continue;
  396. }
  397. p = sel.p[0].p2+1;
  398. }else
  399. p = sel.p[0].p2;
  400. if(xy)
  401. f->dot.r = sel.p[0];
  402. else
  403. f->dot.r.p1 = op, f->dot.r.p2 = sel.p[0].p1;
  404. }
  405. op = sel.p[0].p2;
  406. cmdexec(f, cp->ccmd);
  407. compile(cp->re);
  408. }
  409. --nest;
  410. }
  411. void
  412. linelooper(File *f, Cmd *cp)
  413. {
  414. Posn p;
  415. Range r, linesel;
  416. Address a, a3;
  417. nest++;
  418. r = addr.r;
  419. a3.f = f;
  420. a3.r.p1 = a3.r.p2 = r.p1;
  421. for(p = r.p1; p<r.p2; p = a3.r.p2){
  422. a3.r.p1 = a3.r.p2;
  423. /*pjw if(p!=r.p1 || (linesel = lineaddr((Posn)0, a3, 1)).r.p2==p)*/
  424. if(p!=r.p1 || (a = lineaddr((Posn)0, a3, 1), linesel = a.r, linesel.p2==p)){
  425. a = lineaddr((Posn)1, a3, 1);
  426. linesel = a.r;
  427. }
  428. if(linesel.p1 >= r.p2)
  429. break;
  430. if(linesel.p2 >= r.p2)
  431. linesel.p2 = r.p2;
  432. if(linesel.p2 > linesel.p1)
  433. if(linesel.p1>=a3.r.p2 && linesel.p2>a3.r.p2){
  434. f->dot.r = linesel;
  435. cmdexec(f, cp->ccmd);
  436. a3.r = linesel;
  437. continue;
  438. }
  439. break;
  440. }
  441. --nest;
  442. }
  443. void
  444. filelooper(Cmd *cp, int XY)
  445. {
  446. File *f, *cur;
  447. int i;
  448. if(Glooping++)
  449. error(EnestXY);
  450. nest++;
  451. settempfile();
  452. cur = curfile;
  453. for(i = 0; i<tempfile.nused; i++){
  454. f = tempfile.filepptr[i];
  455. if(f==cmd)
  456. continue;
  457. if(cp->re==0 || filematch(f, cp->re)==XY)
  458. cmdexec(f, cp->ccmd);
  459. }
  460. if(cur && whichmenu(cur)>=0) /* check that cur is still a file */
  461. current(cur);
  462. --Glooping;
  463. --nest;
  464. }