home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ENTERPRS / CPM / UTILS / S / TUTOR.ARC / CHAPTER6.PAS < prev    next >
Pascal/Delphi Source File  |  1992-11-30  |  17KB  |  838 lines

  1.  
  2. {chapter6.pas}
  3.  
  4. {
  5.         copyright (c) 1981
  6.         by:     bell telephone laboratories, inc. and
  7.                 whitesmith's ltd.,
  8.  
  9.         this software is derived from the book
  10.                 "software tools in pascal", by
  11.                 brian w. kernighan and p. j. plauger
  12.                 addison-wesley, 1981
  13.                 isbn 0-201-10342-7
  14.  
  15.         right is hereby granted to freely distribute or duplicate this
  16.         software, providing distribution or duplication is not for profit
  17.         or other commercial gain and that this copyright notice remains
  18.         intact.
  19. }
  20.  
  21. procedure edit;
  22. const
  23.   maxlines=1000;
  24.   ditto=255;
  25.   curline=period;
  26.   lastline=dollar;
  27.   scan=47;
  28.   backscan=92;
  29.   acmd=97;
  30.   ccmd=99;
  31.   dcmd=100;
  32.   ecmd=101;
  33.   eqcmd=equals;
  34.   fcmd=102;
  35.   gcmd=103;
  36.   icmd=105;
  37.   mcmd=109;
  38.   pcmd=112;
  39.   qcmd=113;
  40.   rcmd=114;
  41.   scmd=115;
  42.   wcmd=119;
  43.   xcmd=120;
  44.  
  45. type
  46.   stcode=(enddata,err,ok);
  47.   buftype=record
  48.     txt:integer;
  49.     mark:boolean;
  50.   end;
  51.  
  52. var
  53.   editfid:file of character;
  54.   buf:array[0..maxlines]of buftype;
  55.   recin:integer;
  56.   recout:integer;
  57.   line1,line2,nlines,curln,lastln:integer;
  58.   pat,lin,savefile:xstring;
  59.   cursave,i:integer;
  60.   status:stcode;
  61.   more:boolean;
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69. procedure gettxt(n:integer;var s:xstring);
  70. var
  71.   ch:char;junk:boolean;i:integer;
  72. begin
  73.   if(n=0) then
  74.     s[1]:=endstr
  75.   else begin
  76.     i:=0;
  77.     seek(editfid,buf[n].txt);
  78.     repeat
  79.       i:=succ(i);
  80.       read(editfid,s[i]);
  81.       recin:=recin+1;
  82.     until s[i]=endstr;
  83.   end
  84. end;
  85.  
  86.  
  87. function getmark(n:integer):boolean;
  88. begin
  89.   getmark:=buf[n].mark
  90. end;
  91.  
  92. procedure putmark(n:integer;m:boolean);
  93. begin
  94.   buf[n].mark:=m
  95. end;
  96.  
  97. function doprint(n1,n2:integer):stcode;
  98. var
  99.   i:integer;
  100.   line:xstring;
  101. begin
  102.   if(n1<=0)then
  103.     doprint:=err
  104.   else begin
  105.     for i:=n1 to n2 do begin
  106.       gettxt(i,line);
  107.       putstr(line,stdout)
  108.     end;
  109.     curln:=n2;
  110.     doprint:=ok
  111.   end
  112. end;
  113.  
  114. function default(def1,def2:integer;
  115.   var status:stcode):stcode;
  116. begin
  117.   if(nlines=0)then begin
  118.     line1:=def1;
  119.     line2:=def2
  120.   end;
  121.   if(line1 > line2)or(line1 <=0)then
  122.     status:=err
  123.   else
  124.     status:=ok;
  125.   default:=status
  126. end;
  127.  
  128. function prevln(n:integer):integer;
  129. begin
  130.   if(n<=0)then
  131.     prevln:=lastln
  132.   else
  133.     prevln:=n-1
  134. end;
  135.  
  136. function nextln(n:integer):integer;
  137. begin
  138.   if(n>=lastln)then
  139.     nextln:=0
  140.   else
  141.     nextln:=n+1
  142. end;
  143.  
  144. function patscan(way:character;var n:integer):stcode;
  145. var
  146.   done:boolean;
  147.   line:xstring;
  148. begin
  149.   n:=curln;
  150.   patscan:=err;
  151.   done:=false;
  152.   repeat
  153.     if(way=scan)then
  154.       n:=nextln(n)
  155.     else
  156.       n:=prevln(n);
  157.     gettxt(n,line);
  158.     if(match(line,pat))then begin
  159.       patscan:=ok;
  160.       done:=true
  161.     end
  162.   until(n=curln)or(done)
  163. end;
  164.  
  165. function esc(var s:xstring; var i:integer):character;
  166. begin
  167.   if(s[i]<>escape) then
  168.     esc:=s[i]
  169.   else if (s[i+1]=endstr) then
  170.     esc:=escape
  171.   else begin
  172.     i:=i+1;
  173.     if (s[i]=ord('n')) then
  174.       esc:=newline
  175.     else if (s[i]=ord('t')) then
  176.       esc:=tab
  177.     else
  178.       esc:=s[i]
  179.     end
  180. end;
  181. function optpat(var lin:xstring;var i:integer):stcode;
  182. begin
  183.   if(lin[i]=endstr)then
  184.     i:=0
  185.   else if(lin[i+1]=endstr)then
  186.     i:=0
  187.   else if(lin[i+1]=lin[i])then
  188.     i:=i+1
  189.   else
  190.     i:=makepat(lin,i+1,lin[i],pat);
  191.   if(pat[1]=endstr)then
  192.     i:=0;
  193.   if(i=0)then begin
  194.     pat[1]:=endstr;
  195.     optpat:=err
  196.   end
  197.   else
  198.     optpat:=ok
  199. end;
  200.  
  201. procedure skipbl(var s:xstring;var i:integer);
  202. begin
  203.   while(s[i]=blank)or(s[i]=tab)do
  204.     i:=i+1
  205. end;
  206.  
  207. function getnum(var lin:xstring;var i,num:integer;
  208.   var status:stcode):stcode;
  209. begin
  210.   status:=ok;
  211.   skipbl(lin,i);
  212.   if(isdigit(lin[i]))then begin
  213.     num:=ctoi(lin,i);
  214.       i:=i-1
  215.   end
  216.   else if(lin[i]=curline)then
  217.     num:=curln
  218.   else if(lin[i]=lastline)then
  219.     num:=lastln
  220.   else if(lin[i]=scan)or(lin[i]=backscan)then begin
  221.     if(optpat(lin,i)=err)then
  222.       status:=err
  223.     else
  224.       status:=patscan(lin[i],num)
  225.   end
  226.   else
  227.     status:=enddata;
  228.   if(status=ok)then
  229.     i:=i+1;
  230.   getnum:=status
  231. end;
  232.  
  233. function getone(var lin:xstring;var i,num:integer;
  234.   var status:stcode):stcode;
  235.   var
  236.     istart,mul,pnum:integer;
  237.   begin
  238.     istart:=i;
  239.     num:=0;
  240.     if(getnum(lin,i,num,status)=ok)then
  241.       repeat
  242.         skipbl(lin,i);
  243.         if(lin[i]<>plus)and(lin[i]<>minus)then
  244.           status:=enddata
  245.         else begin
  246.           if(lin[i]=plus)then
  247.             mul:=+1
  248.           else
  249.             mul:=-1;
  250.           i:=i+1;
  251.           if(getnum(lin,i,pnum,status)=ok)then
  252.             num:=num+mul*pnum;
  253.           if(status=enddata)then
  254.             status:=err
  255.         end
  256.       until(status<>ok);
  257.     if(num<0)or(num > lastln)then
  258.       status:=err;
  259.     if(status<>err)then begin
  260.       if(i<=istart)then
  261.         status:=enddata
  262.       else
  263.         status:=ok
  264.     end;
  265.     getone:=status
  266.   end;
  267.   
  268.         
  269. function getlist(var lin:xstring;var i:integer;
  270.   var status:stcode):stcode;
  271. var
  272.   num:integer;
  273.   done:boolean;
  274. begin
  275.   line2:=0;
  276.   nlines:=0;
  277.   done:=(getone(lin,i,num,status)<>ok);
  278.   while(not done)do begin
  279.     line1:=line2;
  280.     line2:=num;
  281.     nlines:=nlines+1;
  282.     if(lin[i]=semicol)then
  283.       curln:=num;
  284.     if(lin[i]=comma)or(lin[i]=semicol)then begin
  285.       i:=i+1;
  286.       done:=(getone(lin,i,num,status)<>ok)
  287.     end
  288.     else
  289.       done:=true
  290.   end;
  291.   nlines:=min(nlines,2);
  292.   if(nlines=0)then
  293.     line2:=curln;
  294.   if(nlines<=1)then
  295.     line1:=line2;
  296.   if(status<>err)then
  297.     status:=ok;
  298.   getlist:=status
  299. end;
  300.  
  301. procedure reverse(n1,n2:integer);
  302. var
  303.   temp:buftype;
  304. begin
  305.   while(n1<n2)do begin
  306.     temp:=buf[n1];
  307.     buf[n1]:=buf[n2];
  308.     buf[n2]:=temp;
  309.     n1:=n1+1;
  310.     n2:=n2-1
  311.   end
  312. end;
  313. procedure blkmove(n1,n2,n3:integer);
  314. begin
  315.   if(n3<n1-1)then begin
  316.     reverse(n3+1,n1-1);
  317.     reverse(n1,n2);
  318.     reverse(n3+1,n2)
  319.   end
  320.   else if(n3>n2)then begin
  321.     reverse(n1,n2);
  322.     reverse(n2+1,n3);
  323.     reverse(n1,n3)
  324.   end
  325. end;
  326.  
  327. function move(line3:integer):stcode;
  328. begin
  329.   if(line1<=0)or((line3>=line1)and(line3<line2))then
  330.     move:=err
  331.   else begin
  332.     blkmove(line1,line2,line3);
  333.     if(line3>line1)then
  334.       curln:=line3
  335.     else
  336.        curln:=line3+(line2-line1+1);
  337.      move:=ok
  338.    end
  339.  end;
  340.  
  341. function lndelete(n1,n2:integer;var status:stcode):
  342. stcode;
  343. begin
  344.   if(n1<=0)then
  345.     status:=err
  346.   else begin
  347.     blkmove(n1,n2,lastln);
  348.     lastln:=lastln-(n2-n1+1);
  349.     curln:=prevln(n1);
  350.     status:=ok
  351.   end;
  352.   lndelete:=status
  353. end;
  354.  
  355. function ckp(var lin:xstring;i:integer;
  356.   var pflag:boolean;var status:stcode):stcode;
  357. begin
  358.   skipbl(lin,i);
  359.   if(lin[i]=pcmd)then begin
  360.     i:=i+1;
  361.     pflag:=true
  362.   end
  363.   else
  364.     pflag:=false;
  365.   if(lin[i]=newline)then
  366.     status:=ok
  367.   else
  368.     status:=err;
  369.   ckp:=status
  370. end;
  371.  
  372. function puttxt(var lin:xstring):stcode;
  373. var i:integer;
  374. begin
  375.   puttxt:=err;
  376.   if(lastln<maxlines) then begin
  377.     i:=0;
  378.     seek(editfid,recout);
  379.     lastln:=lastln+1;
  380.     buf[lastln].txt:=recout;
  381.     repeat
  382.       i:=succ(i);
  383.       write(editfid,lin[i]);
  384.       recout:=recout+1
  385.     until lin[i]=endstr;
  386.     write(editfid,lin[i]);
  387.     putmark(lastln,false);
  388.     blkmove(lastln,lastln,curln);
  389.     curln:=curln+1;
  390.     puttxt:=ok
  391.   end
  392. end;
  393.  
  394. procedure setbuf;
  395. begin
  396. (*$I-*)
  397.   assign(editfid,'edtemp');
  398.   reset(editfid);
  399.   if (ioresult<>0) then rewrite(editfid);
  400. (*$I+*)
  401.  
  402.   recout:=0;
  403.   recin:=0;
  404.   curln:=0;
  405.   lastln:=0
  406. end;
  407.  
  408.  
  409. procedure clrbuf;
  410. begin
  411.   close(editfid);erase(editfid)
  412. end;
  413.  
  414. function append(line:integer;glob:boolean):stcode;
  415. var
  416.   einline:xstring;
  417.   stat:stcode;
  418.   done:boolean;
  419. begin
  420.   if(glob)then
  421.     stat:=err
  422.   else begin
  423.     curln:=line;
  424.     stat:=ok;
  425.     done:=false;
  426.     while(not done)and(stat=ok)do
  427.       if(not getline(einline,stdin,maxstr))then
  428.         stat:=enddata
  429.       else if(einline[1]=period)
  430.         and(einline[2]=newline)then
  431.           done:=true
  432.       else if(puttxt(einline)=err)then
  433.         stat:=err
  434.   end;
  435.   append:=stat
  436. end;
  437.  
  438. function dowrite(n1,n2:integer;var fil:xstring):stcode;
  439. var
  440.   i:integer;
  441.   fd: filedesc;
  442.   line: xstring;
  443. begin
  444.   fd:=create(fil,iowrite);
  445.   if(fd=ioerror)then
  446.     dowrite:=err
  447.   else begin
  448.     for i:=n1 to n2 do begin
  449.       gettxt(i,line);
  450.       putstr(line,fd)
  451.     end;
  452.     xclose(fd);
  453.     putdec(n2-n1+1,1);
  454.     putc(newline);
  455.     dowrite:=ok
  456.   end
  457. end;
  458.  
  459. function doread(n:integer;var fil:xstring):stcode;
  460. var
  461.   count:integer;
  462.   t:boolean;
  463.   stat:stcode;
  464.   fd:filedesc;
  465.   einline:xstring;
  466. begin
  467.   fd:=open(fil,ioread);
  468.   if(fd=ioerror)then
  469.     stat:=err
  470.   else begin
  471.     curln:=n;
  472.     stat:=ok;
  473.     count:=0;
  474.     repeat
  475.       t:=getline(einline,fd,maxstr);
  476.       if(t)then begin
  477.         stat:=puttxt(einline);
  478.         if(stat<>err)then
  479.           count:=count+1
  480.       end
  481.     until(stat<>ok)or(t=false);
  482.     xclose(fd);
  483.     putdec(count,1);
  484.     putc(newline)
  485.   end;
  486.   doread:=stat
  487. end;
  488.  
  489. function getfn(var lin:xstring;var i:integer;
  490.   var fil:xstring):stcode;
  491. var
  492.   k:integer;
  493.   stat:stcode;
  494.  
  495. function getword(var s:xstring;i:integer;var out:
  496.   xstring):integer;
  497. var
  498.   j:integer;
  499. begin
  500.   while(s[i]in [blank,tab,newline])do
  501.     i:=i+1;
  502.   j:=1;
  503.   while(not(s[i]in [endstr,blank,tab,
  504.     newline]))do begin
  505.     out[j]:=s[i];
  506.     i:=i+1;
  507.     j:=j+1
  508.   end;
  509.   out[j]:=endstr;
  510.   if(s[i]=endstr)then
  511.     getword:=0
  512.   else
  513.     getword:=i
  514. end;
  515.  
  516. begin(*getfn*)
  517.   stat:=err;
  518.   if(lin[i+1]=blank)then begin
  519.     k:=getword(lin,i+2,fil);
  520.     if(k>0)then
  521.       if(lin[k]=newline)then
  522.         stat:=ok
  523.   end
  524.   else if(lin[i+1]=newline)
  525.     and(savefile[1]<>endstr)then begin
  526.       scopy(savefile,1,fil,1);
  527.       stat:=ok;
  528.   end;
  529.   if(stat=ok)and(savefile[1]=endstr)then
  530.     scopy(fil,1,savefile,1);
  531.   getfn:=stat
  532. end;
  533.  
  534. procedure catsub(var lin:xstring;s1,s2: integer;
  535.   var sub: xstring;var new:xstring;
  536.   var k:integer;maxnew:integer);
  537. var
  538.   i,j:integer;
  539.   junk:boolean;
  540. begin
  541.   i:=1;
  542.   while(sub[i]<>endstr)do begin
  543.     if(sub[i]=ditto)then
  544.       for j:=s1 to s2-1 do
  545.         junk:=addstr(lin[j],new,k,maxnew)
  546.       else
  547.         junk:=addstr(sub[i],new,k,maxnew);
  548.       i:=i+1
  549.   end
  550. end;
  551.  
  552. function subst( var sub:xstring;gflag,glob:boolean):stcode;
  553. var
  554.   new,old:xstring;
  555.   j,k,lastm,line,m:integer;
  556.   stat:stcode;
  557.   done,subbed,junk:boolean;
  558. begin
  559.   if(glob)then
  560.     stat:=ok
  561.   else
  562.     stat:=err;
  563.     done:=(line1<=0);
  564.     line:=line1;
  565.     while(not done)and(line<=line2)do begin
  566.       j:=1;
  567.       subbed:=false;
  568.       gettxt(line,old);
  569.       lastm:=0;
  570.       k:=1;
  571.       while(old[k]<>endstr)do begin
  572.         if(gflag)or(not subbed)then
  573.           m:=amatch(old,k,pat,1)
  574.         else
  575.           m:=0;
  576.         if(m>0)and(lastm<>m)then begin
  577.           subbed:=true;
  578.           catsub(old,k,m,sub,new,j,maxstr);
  579.           lastm:=m
  580.         end;
  581.         if(m=0)or(m=k)then begin
  582.           junk:=addstr(old[k],new,j,maxstr);
  583.           k:=k+1
  584.         end
  585.         else
  586.           k:=m
  587.       end;
  588.       if(subbed)then begin
  589.         if(not addstr(endstr,new,j,maxstr))then begin
  590.           stat:=err;
  591.           done:=true
  592.         end
  593.         else begin
  594.           stat:=lndelete(line,line,status);
  595.           stat:=puttxt(new);
  596.           line2:=line2+curln-line;
  597.           line:=curln;
  598.           if(stat=err)then
  599.             done:=true
  600.           else
  601.             stat:=ok
  602.           end
  603.         end;
  604.         line:=line+1
  605.       end;
  606.       subst:=stat
  607.     end;
  608. function makesub(var arg:xstring;from:integer;
  609.   delim:character;var sub:xstring):integer;
  610. var i,j:integer;
  611.    junk:boolean;
  612. begin
  613.   j:=1;
  614.   i:=from;
  615.   while(arg[i]<>delim)and(arg[i]<>endstr)do begin
  616.     if(arg[i]=ord('&'))then
  617.       junk:=addstr(ditto,sub,j,maxpat)
  618.     else
  619.       junk:=addstr(esc(arg,i),sub,j,maxpat);
  620.     i:=i+1
  621.   end;
  622.   if(arg[i]<>delim) then
  623.     makesub:=0
  624.   else if (not addstr(endstr,sub,j,maxpat))then
  625.     makesub:=0
  626.   else
  627.     makesub:=i
  628. end;
  629. function getrhs(var lin:xstring;var i:integer;
  630.   var sub:xstring;var gflag:boolean):stcode;
  631. begin
  632.   getrhs:=ok;
  633.   if(lin[i]=endstr)then
  634.     getrhs:=err
  635.   else if(lin[i+1]=endstr)then
  636.     getrhs:=err
  637.   else begin
  638.     i:=makesub(lin,i+1,lin[i],sub);
  639.     if(i=0)then
  640.       getrhs:=err
  641.     else if(lin[i+1]=ord('g'))then begin
  642.       i:=i+1;
  643.       gflag:=true
  644.     end
  645.     else
  646.       gflag:=false
  647.   end
  648. end;
  649.  
  650. function docmd(var lin:xstring;var i:integer;
  651.   glob:boolean;var status:stcode):stcode;
  652. var
  653.   fil,sub:xstring;
  654.   line3:integer;
  655.   gflag,pflag:boolean;
  656. begin
  657.   pflag:=false;
  658.   status:=err;
  659.   if(lin[i]=pcmd)then begin
  660.     if(lin[i+1]=newline)then 
  661.       if(default(curln,curln,status)=ok)then
  662.         status:=doprint(line1,line2)
  663.   end
  664.   else if(lin[i]=newline)then begin
  665.     if(nlines=0)then
  666.       line2:=nextln(curln);
  667.     status:=doprint(line2,line2)
  668.   end
  669.   else if(lin[i]=qcmd)then begin
  670.     if( lin[i+1]=newline)and(nlines=0)and(not glob)then
  671.   status:=enddata
  672.   end
  673.   else if(lin[i]=acmd)then begin
  674.     if(lin[i+1]=newline)then
  675.       status:=append(line2,glob)
  676.   end
  677.   else if(lin[i]=ccmd)then begin
  678.     if(lin[i+1]=newline)then
  679.       if(default(curln,curln,status)=ok)then
  680.       if(lndelete(line1,line2,status)=ok)then
  681.         status:=append(prevln(line1),glob)
  682.   end
  683.   else if(lin[i]=dcmd)then begin
  684.     if(ckp(lin,i+1,pflag,status)=ok)then
  685.      if(default(curln,curln,status)=ok)then
  686.      if(lndelete(line1,line2,status)=ok)then
  687.      if(nextln(curln)<>0)then
  688.        curln:=nextln(curln)
  689.   end
  690.   else if(lin[i]=icmd)then begin
  691.     if(lin[i+1]=newline)then begin
  692.       if(line2=0)then
  693.         status:=append(0,glob)
  694.       else
  695.         status:=append(prevln(line2),glob)
  696.     end
  697.   end
  698.   else if(lin[i]=eqcmd)then begin
  699.     if(ckp(lin,i+1,pflag,status)=ok)then begin
  700.       putdec(line2,1);
  701.       putc(newline)
  702.     end
  703.   end
  704.   else if(lin[i]=mcmd)then begin
  705.     i:=i+1;
  706.     if(getone(lin,i,line3,status)=enddata)then
  707.       status:=err;
  708.     if(status =ok)then
  709.       if(ckp(lin,i,pflag,status)=ok)then
  710.       if(default(curln,curln,status)=ok)then
  711.         status:=move(line3)
  712.   end
  713.   else if(lin[i]=scmd)then begin
  714.     i:=i+1;
  715.     if(optpat(lin,i)=ok)then 
  716.     if(getrhs(lin,i,sub,gflag)=ok)then
  717.     if(ckp(lin,i+1,pflag,status)=ok)then
  718.     if(default(curln,curln,status)=ok)then
  719.       status:=subst(sub,gflag,glob)
  720.   end
  721.   else if(lin[i]=ecmd)then begin
  722.     if(nlines =0)then
  723.       if(getfn(lin,i,fil)=ok)then begin
  724.         scopy(fil,1,savefile,1);
  725.         clrbuf;
  726.         setbuf;
  727.         status:=doread(0,fil)
  728.       end
  729.   end
  730.   else if(lin[i]=fcmd)then begin
  731.     if(nlines =0)then
  732.       if(getfn(lin,i,fil)=ok)then begin
  733.         scopy(fil,1,savefile,1);
  734.         putstr(savefile,stdout);
  735.         putc(newline);
  736.         status:=ok
  737.     end
  738.   end
  739.   else if(lin[i]=rcmd)then begin
  740.     if(getfn(lin,i,fil)=ok)then
  741.       status:=doread(line2,fil)
  742.   end
  743.   else if(lin[i]=wcmd)then begin
  744.     if(getfn(lin,i,fil)=ok)then
  745.       if(default(1,lastln,status)=ok)then
  746.         status:=dowrite(line1,line2,fil)
  747.   end;
  748.   if(status =ok)and(pflag)then
  749.     status:=doprint(curln,curln);
  750.   docmd:=status
  751. end;(*docmd*)
  752.  
  753. function ckglob(var lin: xstring;var i:integer;
  754.   var status:stcode): stcode;
  755. var
  756.   n:integer;
  757.   gflag:boolean;
  758.   temp: xstring;
  759. begin
  760.   if(lin[i]<>gcmd)and(lin[i]<>xcmd)then
  761.     status:=enddata
  762.   else begin
  763.     gflag:=(lin[i]=gcmd);
  764.     i:=i+1;
  765.     if(optpat(lin,i)=err)then
  766.       status:=err
  767.     else if( default(1,lastln,status)<>err)then begin
  768.       i:=i+1;
  769.       for n:=line1 to line2 do begin
  770.         gettxt(n,temp);
  771.         putmark(n,(match(temp,pat)=gflag))
  772.       end;
  773.  
  774.       for n:=1 to line1-1 do
  775.         putmark(n,false);
  776.       for n:=line2+1 to lastln do
  777.         putmark(n,false);
  778.       status:=ok
  779.     end
  780.   end;
  781.   ckglob:=status
  782. end;
  783.  
  784. function doglob(var lin:xstring;var i,cursave:integer;
  785.   var status: stcode):stcode;
  786. var
  787.   count,istart,n: integer;
  788. begin
  789.   status:=ok;
  790.   count:=0;
  791.   n:=line1;
  792.   istart:=i;
  793.   repeat
  794.     if(getmark(n))then begin
  795.       putmark(n,false);
  796.       curln:=n;
  797.       cursave:=curln;
  798.       i:=istart;
  799.       if(docmd(lin,i,true,status)=ok)then
  800.         count:=0
  801.     end
  802.     else begin
  803.       n:=nextln(n);
  804.       count:=count + 1
  805.     end
  806.   until(count > lastln)or(status <> ok);
  807.   doglob:=status
  808. end;
  809.  
  810. begin
  811.   setbuf;
  812.   pat[1]:=endstr;
  813.   savefile[1]:=endstr;
  814.   if(getarg(2,savefile,maxstr))then
  815.     if(doread(0,savefile)=err)then
  816.       writeln('?');
  817.   more:=getline(lin,stdin,maxstr);
  818.   while(more)do begin
  819.     i:=1;
  820.     cursave:=curln;
  821.     if(getlist(lin,i,status)=ok)then begin
  822.       if(ckglob(lin,i,status)=ok)then
  823.         status:=doglob(lin,i,cursave,status)
  824.       else if(status<>err)then
  825.         status:=docmd(lin,i,false,status)
  826.     end;
  827.     if(status=err)then begin
  828.       writeln('?');
  829.       curln:=min(cursave,lastln)
  830.     end
  831.     else if(status=enddata)then
  832.       more:=false;
  833.     if(more)then
  834.       more:=getline(lin,stdin,maxstr)
  835.   end;
  836.   clrbuf
  837. end;
  838.