home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume3 / turbo_tools / part2 / chapter6.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1986-11-30  |  16.1 KB  |  841 lines

  1. {chapter6.pas}
  2.  
  3. {
  4.         Copyright (c) 1981
  5.         By:     Bell Telephone Laboratories, Inc. and
  6.                 Whitesmith's Ltd.,
  7.  
  8.         This software is derived from the book
  9.                 "Software Tools in Pascal", by
  10.                 Brian W. Kernighan and P. J. Plauger
  11.                 Addison-Wesley, 1981
  12.                 ISBN 0-201-10342-7
  13.  
  14.         Right is hereby granted to freely distribute or duplicate this
  15.         software, providing distribution or duplication is not for profit
  16.         or other commercial gain and that this copyright notice remains
  17.         intact.
  18. }
  19.  
  20. PROCEDURE EDIT;
  21. CONST
  22.   MAXLINES=1000;
  23.   DITTO=255;
  24.   CURLINE=PERIOD;
  25.   LASTLINE=DOLLAR;
  26.   SCAN=47;
  27.   BACKSCAN=92;
  28.   ACMD=97;
  29.   CCMD=99;
  30.   DCMD=100;
  31.   ECMD=101;
  32.   EQCMD=EQUALS;
  33.   FCMD=102;
  34.   GCMD=103;
  35.   ICMD=105;
  36.   MCMD=109;
  37.   PCMD=112;
  38.   QCMD=113;
  39.   RCMD=114;
  40.   SCMD=115;
  41.   WCMD=119;
  42.   XCMD=120;
  43.  
  44. TYPE
  45.   STCODE=(ENDDATA,ERR,OK);
  46.   BUFTYPE=RECORD
  47.     TXT:INTEGER;
  48.     MARK:BOOLEAN;
  49.   END;
  50.  
  51. VAR
  52.   EDITFID:FILE OF CHARACTER;
  53.   BUF:ARRAY[0..MAXLINES]OF BUFTYPE;
  54.   RECIN:INTEGER;
  55.   RECOUT:INTEGER;
  56.   LINE1,LINE2,NLINES,CURLN,LASTLN:INTEGER;
  57.   PAT,LIN,SAVEFILE:XSTRING;
  58.   CURSAVE,I:INTEGER;
  59.   STATUS:STCODE;
  60.   MORE:BOOLEAN;
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68. PROCEDURE GETTXT(N:INTEGER;VAR S:XSTRING);
  69. VAR
  70.   ch:char;JUNK:BOOLEAN;I:INTEGER;
  71. BEGIN
  72.   IF(N=0) THEN
  73.     S[1]:=ENDSTR
  74.   ELSE BEGIN
  75.     i:=0;
  76.     SEEK(EDITFID,BUF[N].TXT);
  77.     repeat
  78.       i:=succ(i);
  79.       READ(EDITFID,s[i]);
  80.       RECIN:=RECIN+1;
  81.     until S[I]=ENDSTR;
  82.   END
  83. END;
  84.  
  85.  
  86. FUNCTION GETMARK(N:INTEGER):BOOLEAN;
  87. BEGIN
  88.   GETMARK:=BUF[N].MARK
  89. END;
  90.  
  91. PROCEDURE PUTMARK(N:INTEGER;M:BOOLEAN);
  92. BEGIN
  93.   BUF[N].MARK:=M
  94. END;
  95.  
  96. FUNCTION DOPRINT(N1,N2:INTEGER):STCODE;
  97. VAR
  98.   I:INTEGER;
  99.   LINE:XSTRING;
  100. BEGIN
  101.   IF(N1<=0)THEN
  102.     DOPRINT:=ERR
  103.   ELSE BEGIN
  104.     FOR I:=N1 TO N2 DO BEGIN
  105.       GETTXT(I,LINE);
  106.       PUTSTR(LINE,STDOUT)
  107.     END;
  108.     CURLN:=N2;
  109.     DOPRINT:=OK
  110.   END
  111. END;
  112.  
  113. FUNCTION DEFAULT(DEF1,DEF2:INTEGER;
  114.   VAR STATUS:STCODE):STCODE;
  115. BEGIN
  116.   IF(NLINES=0)THEN BEGIN
  117.     LINE1:=DEF1;
  118.     LINE2:=DEF2
  119.   END;
  120.   IF(LINE1 > LINE2)OR(LINE1 <=0)THEN
  121.     STATUS:=ERR
  122.   ELSE
  123.     STATUS:=OK;
  124.   DEFAULT:=STATUS
  125. END;
  126.  
  127. FUNCTION PREVLN(N:INTEGER):INTEGER;
  128. BEGIN
  129.   IF(N<=0)THEN
  130.     PREVLN:=LASTLN
  131.   ELSE
  132.     PREVLN:=N-1
  133. END;
  134.  
  135. FUNCTION NEXTLN(N:INTEGER):INTEGER;
  136. BEGIN
  137.   IF(N>=LASTLN)THEN
  138.     NEXTLN:=0
  139.   ELSE
  140.     NEXTLN:=N+1
  141. END;
  142.  
  143. FUNCTION PATSCAN(WAY:CHARACTER;VAR N:INTEGER):STCODE;
  144. VAR
  145.   DONE:BOOLEAN;
  146.   LINE:XSTRING;
  147. BEGIN
  148.   N:=CURLN;
  149.   PATSCAN:=ERR;
  150.   DONE:=FALSE;
  151.   REPEAT
  152.     IF(WAY=SCAN)THEN
  153.       N:=NEXTLN(N)
  154.     ELSE
  155.       N:=PREVLN(N);
  156.     GETTXT(N,LINE);
  157.     IF(MATCH(LINE,PAT))THEN BEGIN
  158.       PATSCAN:=OK;
  159.       DONE:=TRUE
  160.     END
  161.   UNTIL(N=CURLN)OR(DONE)
  162. END;
  163.  
  164. FUNCTION ESC(VAR S:XSTRING; VAR I:INTEGER):CHARACTER;
  165. BEGIN
  166.   IF(S[I]<>ESCAPE) THEN
  167.     ESC:=S[I]
  168.   ELSE IF (S[I+1]=ENDSTR) THEN
  169.     ESC:=ESCAPE
  170.   ELSE BEGIN
  171.     I:=I+1;
  172.     IF (S[I]=ORD('N')) THEN
  173.       ESC:=NEWLINE
  174.     ELSE IF (S[I]=ORD('T')) THEN
  175.       ESC:=TAB
  176.     ELSE
  177.       ESC:=S[I]
  178.     END
  179. END;
  180. FUNCTION OPTPAT(VAR LIN:XSTRING;VAR I:INTEGER):STCODE;
  181. BEGIN
  182.   IF(LIN[I]=ENDSTR)THEN
  183.     I:=0
  184.   ELSE IF(LIN[I+1]=ENDSTR)THEN
  185.     I:=0
  186.   ELSE IF(LIN[I+1]=LIN[I])THEN
  187.     I:=I+1
  188.   ELSE
  189.     I:=MAKEPAT(LIN,I+1,LIN[I],PAT);
  190.   IF(PAT[1]=ENDSTR)THEN
  191.     I:=0;
  192.   IF(I=0)THEN BEGIN
  193.     PAT[1]:=ENDSTR;
  194.     OPTPAT:=ERR
  195.   END
  196.   ELSE
  197.     OPTPAT:=OK
  198. END;
  199.  
  200. PROCEDURE SKIPBL(VAR S:XSTRING;VAR I:INTEGER);
  201. BEGIN
  202.   WHILE(S[I]=BLANK)OR(S[I]=TAB)DO
  203.     I:=I+1
  204. END;
  205.  
  206. FUNCTION GETNUM(VAR LIN:XSTRING;VAR I,NUM:INTEGER;
  207.   VAR STATUS:STCODE):STCODE;
  208. BEGIN
  209.   STATUS:=OK;
  210.   SKIPBL(LIN,I);
  211.   IF(ISDIGIT(LIN[I]))THEN BEGIN
  212.     NUM:=CTOI(LIN,I);
  213.       I:=I-1
  214.   END
  215.   ELSE IF(LIN[I]=CURLINE)THEN
  216.     NUM:=CURLN
  217.   ELSE IF(LIN[I]=LASTLINE)THEN
  218.     NUM:=LASTLN
  219.   ELSE IF(LIN[I]=SCAN)OR(LIN[I]=BACKSCAN)THEN BEGIN
  220.     IF(OPTPAT(LIN,I)=ERR)THEN
  221.       STATUS:=ERR
  222.     ELSE
  223.       STATUS:=PATSCAN(LIN[I],NUM)
  224.   END
  225.   ELSE
  226.     STATUS:=ENDDATA;
  227.   IF(STATUS=OK)THEN
  228.     I:=I+1;
  229.   GETNUM:=STATUS
  230. END;
  231.  
  232. FUNCTION GETONE(VAR LIN:XSTRING;VAR I,NUM:INTEGER;
  233.   VAR STATUS:STCODE):STCODE;
  234.   VAR
  235.     ISTART,MUL,PNUM:INTEGER;
  236.   BEGIN
  237.     ISTART:=I;
  238.     NUM:=0;
  239.     IF(GETNUM(LIN,I,NUM,STATUS)=OK)THEN
  240.       REPEAT
  241.         SKIPBL(LIN,I);
  242.         IF(LIN[I]<>PLUS)AND(LIN[I]<>MINUS)THEN
  243.           STATUS:=ENDDATA
  244.         ELSE BEGIN
  245.           IF(LIN[I]=PLUS)THEN
  246.             MUL:=+1
  247.           ELSE
  248.             MUL:=-1;
  249.           I:=I+1;
  250.           IF(GETNUM(LIN,I,PNUM,STATUS)=OK)THEN
  251.             NUM:=NUM+MUL*PNUM;
  252.           IF(STATUS=ENDDATA)THEN
  253.             STATUS:=ERR
  254.         END
  255.       UNTIL(STATUS<>OK);
  256.     IF(NUM<0)OR(NUM > LASTLN)THEN
  257.       STATUS:=ERR;
  258.     IF(STATUS<>ERR)THEN BEGIN
  259.       IF(I<=ISTART)THEN
  260.         STATUS:=ENDDATA
  261.       ELSE
  262.         STATUS:=OK
  263.     END;
  264.     GETONE:=STATUS
  265.   END;
  266.   
  267.         
  268. FUNCTION GETLIST(VAR LIN:XSTRING;VAR I:INTEGER;
  269.   VAR STATUS:STCODE):STCODE;
  270. VAR
  271.   NUM:INTEGER;
  272.   DONE:BOOLEAN;
  273. BEGIN
  274.   LINE2:=0;
  275.   NLINES:=0;
  276.   DONE:=(GETONE(LIN,I,NUM,STATUS)<>OK);
  277.   WHILE(NOT DONE)DO BEGIN
  278.     LINE1:=LINE2;
  279.     LINE2:=NUM;
  280.     NLINES:=NLINES+1;
  281.     IF(LIN[I]=SEMICOL)THEN
  282.       CURLN:=NUM;
  283.     IF(LIN[I]=COMMA)OR(LIN[I]=SEMICOL)THEN BEGIN
  284.       I:=I+1;
  285.       DONE:=(GETONE(LIN,I,NUM,STATUS)<>OK)
  286.     END
  287.     ELSE
  288.       DONE:=TRUE
  289.   END;
  290.   NLINES:=MIN(NLINES,2);
  291.   IF(NLINES=0)THEN
  292.     LINE2:=CURLN;
  293.   IF(NLINES<=1)THEN
  294.     LINE1:=LINE2;
  295.   IF(STATUS<>ERR)THEN
  296.     STATUS:=OK;
  297.   GETLIST:=STATUS
  298. END;
  299.  
  300. PROCEDURE REVERSE(N1,N2:INTEGER);
  301. VAR
  302.   TEMP:BUFTYPE;
  303. BEGIN
  304.   WHILE(N1<N2)DO BEGIN
  305.     TEMP:=BUF[N1];
  306.     BUF[N1]:=BUF[N2];
  307.     BUF[N2]:=TEMP;
  308.     N1:=N1+1;
  309.     N2:=N2-1
  310.   END
  311. END;
  312. PROCEDURE BLKMOVE(N1,N2,N3:INTEGER);
  313. BEGIN
  314.   IF(N3<N1-1)THEN BEGIN
  315.     REVERSE(N3+1,N1-1);
  316.     REVERSE(N1,N2);
  317.     REVERSE(N3+1,N2)
  318.   END
  319.   ELSE IF(N3>N2)THEN BEGIN
  320.     REVERSE(N1,N2);
  321.     REVERSE(N2+1,N3);
  322.     REVERSE(N1,N3)
  323.   END
  324. END;
  325.  
  326. FUNCTION MOVE(LINE3:INTEGER):STCODE;
  327. BEGIN
  328.   IF(LINE1<=0)OR((LINE3>=LINE1)AND(LINE3<LINE2))THEN
  329.     MOVE:=ERR
  330.   ELSE BEGIN
  331.     BLKMOVE(LINE1,LINE2,LINE3);
  332.     IF(LINE3>LINE1)THEN
  333.       CURLN:=LINE3
  334.     ELSE
  335.        CURLN:=LINE3+(LINE2-LINE1+1);
  336.      MOVE:=OK
  337.    END
  338.  END;
  339.  
  340. FUNCTION LNDELETE(N1,N2:INTEGER;VAR STATUS:STCODE):
  341. STCODE;
  342. BEGIN
  343.   IF(N1<=0)THEN
  344.     STATUS:=ERR
  345.   ELSE BEGIN
  346.     BLKMOVE(N1,N2,LASTLN);
  347.     LASTLN:=LASTLN-(N2-N1+1);
  348.     CURLN:=PREVLN(N1);
  349.     STATUS:=OK
  350.   END;
  351.   LNDELETE:=STATUS
  352. END;
  353.  
  354. FUNCTION CKP(VAR LIN:XSTRING;I:INTEGER;
  355.   VAR PFLAG:BOOLEAN;VAR STATUS:STCODE):STCODE;
  356. BEGIN
  357.   SKIPBL(LIN,I);
  358.   IF(LIN[I]=PCMD)THEN BEGIN
  359.     I:=I+1;
  360.     PFLAG:=TRUE
  361.   END
  362.   ELSE
  363.     PFLAG:=FALSE;
  364.   IF(LIN[I]=NEWLINE)THEN
  365.     STATUS:=OK
  366.   ELSE
  367.     STATUS:=ERR;
  368.   CKP:=STATUS
  369. END;
  370.  
  371. FUNCTION PUTTXT(VAR LIN:XSTRING):STCODE;
  372. VAR I:INTEGER;
  373. BEGIN
  374.   PUTTXT:=ERR;
  375.   IF(LASTLN<MAXLINES) THEN BEGIN
  376.     i:=0;
  377.     seek(editfid,recout);
  378.     lastln:=lastln+1;
  379.     buf[lastln].txt:=recout;
  380.     repeat
  381.       i:=succ(i);
  382.       WRITE(EDITFID,lin[i]);
  383.       recout:=recout+1
  384.     until lin[i]=ENDSTR;
  385.     write(editfid,lin[i]);
  386.     PUTMARK(LASTLN,FALSE);
  387.     BLKMOVE(LASTLN,LASTLN,CURLN);
  388.     CURLN:=CURLN+1;
  389.     PUTTXT:=OK
  390.   END
  391. END;
  392.  
  393. PROCEDURE SETBUF;
  394. BEGIN
  395. (*$I-*)
  396.   ASSIGN(EDITFID,'EDTEMP');
  397.   RESET(EDITFID);
  398.   IF (IORESULT<>0) THEN REWRITE(EDITFID);
  399. (*$I+*)
  400.  
  401.   RECOUT:=0;
  402.   RECIN:=0;
  403.   CURLN:=0;
  404.   LASTLN:=0
  405. END;
  406.  
  407.  
  408. PROCEDURE CLRBUF;
  409. BEGIN
  410.   CLOSE(EDITFID);ERASE(EDITFID)
  411. END;
  412.  
  413. FUNCTION APPEND(LINE:INTEGER;GLOB:BOOLEAN):STCODE;
  414. VAR
  415.   EINLINE:XSTRING;
  416.   STAT:STCODE;
  417.   DONE:BOOLEAN;
  418. BEGIN
  419.   IF(GLOB)THEN
  420.     STAT:=ERR
  421.   ELSE BEGIN
  422.     CURLN:=LINE;
  423.     STAT:=OK;
  424.     DONE:=FALSE;
  425.     WHILE(NOT DONE)AND(STAT=OK)DO
  426.       IF(NOT GETLINE(EINLINE,STDIN,MAXSTR))THEN
  427.         STAT:=ENDDATA
  428.       ELSE IF(EINLINE[1]=PERIOD)
  429.         AND(EINLINE[2]=NEWLINE)THEN
  430.           DONE:=TRUE
  431.       ELSE IF(PUTTXT(EINLINE)=ERR)THEN
  432.         STAT:=ERR
  433.   END;
  434.   APPEND:=STAT
  435. END;
  436.  
  437. FUNCTION DOWRITE(N1,N2:INTEGER;VAR FIL:XSTRING):STCODE;
  438. VAR
  439.   I:INTEGER;
  440.   FD: FILEDESC;
  441.   LINE: XSTRING;
  442. BEGIN
  443.   FD:=CREATE(FIL,IOWRITE);
  444.   IF(FD=IOERROR)THEN
  445.     DOWRITE:=ERR
  446.   ELSE BEGIN
  447.     FOR I:=N1 TO N2 DO BEGIN
  448.       GETTXT(I,LINE);
  449.       PUTSTR(LINE,FD)
  450.     END;
  451.     XCLOSE(FD);
  452.     PUTDEC(N2-N1+1,1);
  453.     PUTC(NEWLINE);
  454.     DOWRITE:=OK
  455.   END
  456. END;
  457.  
  458. FUNCTION DOREAD(N:INTEGER;VAR FIL:XSTRING):STCODE;
  459. VAR
  460.   COUNT:INTEGER;
  461.   T:BOOLEAN;
  462.   STAT:STCODE;
  463.   FD:FILEDESC;
  464.   EINLINE:XSTRING;
  465. BEGIN
  466.   FD:=OPEN(FIL,IOREAD);
  467.   IF(FD=IOERROR)THEN
  468.     STAT:=ERR
  469.   ELSE BEGIN
  470.     CURLN:=N;
  471.     STAT:=OK;
  472.     COUNT:=0;
  473.     REPEAT
  474.       T:=GETLINE(EINLINE,FD,MAXSTR);
  475.       IF(T)THEN BEGIN
  476.         STAT:=PUTTXT(EINLINE);
  477.         IF(STAT<>ERR)THEN
  478.           COUNT:=COUNT+1
  479.       END
  480.     UNTIL(STAT<>OK)OR(T=FALSE);
  481.     XCLOSE(FD);
  482.     PUTDEC(COUNT,1);
  483.     PUTC(NEWLINE)
  484.   END;
  485.   DOREAD:=STAT
  486. END;
  487.  
  488. FUNCTION GETFN(VAR LIN:XSTRING;VAR I:INTEGER;
  489.   VAR FIL:XSTRING):STCODE;
  490. VAR
  491.   K:INTEGER;
  492.   STAT:STCODE;
  493.  
  494. FUNCTION GETWORD(VAR S:XSTRING;I:INTEGER;VAR OUT:
  495.   XSTRING):INTEGER;
  496. VAR
  497.   J:INTEGER;
  498. BEGIN
  499.   WHILE(S[I]IN [BLANK,TAB,NEWLINE])DO
  500.     I:=I+1;
  501.   J:=1;
  502.   WHILE(NOT(S[I]IN [ENDSTR,BLANK,TAB,
  503.     NEWLINE]))DO BEGIN
  504.     OUT[J]:=S[I];
  505.     I:=I+1;
  506.     J:=J+1
  507.   END;
  508.   OUT[J]:=ENDSTR;
  509.   IF(S[I]=ENDSTR)THEN
  510.     GETWORD:=0
  511.   ELSE
  512.     GETWORD:=I
  513. END;
  514.  
  515. BEGIN(*GETFN*)
  516.   STAT:=ERR;
  517.   IF(LIN[I+1]=BLANK)THEN BEGIN
  518.     K:=GETWORD(LIN,I+2,FIL);
  519.     IF(K>0)THEN
  520.       IF(LIN[K]=NEWLINE)THEN
  521.         STAT:=OK
  522.   END
  523.   ELSE IF(LIN[I+1]=NEWLINE)
  524.     AND(SAVEFILE[1]<>ENDSTR)THEN BEGIN
  525.       SCOPY(SAVEFILE,1,FIL,1);
  526.       STAT:=OK;
  527.   END;
  528.   IF(STAT=OK)AND(SAVEFILE[1]=ENDSTR)THEN
  529.     SCOPY(FIL,1,SAVEFILE,1);
  530.   GETFN:=STAT
  531. END;
  532.  
  533. PROCEDURE CATSUB(VAR LIN:XSTRING;S1,S2: INTEGER;
  534.   VAR SUB: XSTRING;VAR NEW:XSTRING;
  535.   VAR K:INTEGER;MAXNEW:INTEGER);
  536. VAR
  537.   I,J:INTEGER;
  538.   JUNK:BOOLEAN;
  539. BEGIN
  540.   I:=1;
  541.   WHILE(SUB[I]<>ENDSTR)DO BEGIN
  542.     IF(SUB[I]=DITTO)THEN
  543.       FOR J:=S1 TO S2-1 DO
  544.         JUNK:=ADDSTR(LIN[J],NEW,K,MAXNEW)
  545.       ELSE
  546.         JUNK:=ADDSTR(SUB[I],NEW,K,MAXNEW);
  547.       I:=I+1
  548.   END
  549. END;
  550.  
  551. FUNCTION SUBST( VAR SUB:XSTRING;GFLAG,GLOB:BOOLEAN):STCODE;
  552. VAR
  553.   NEW,OLD:XSTRING;
  554.   J,K,LASTM,LINE,M:INTEGER;
  555.   STAT:STCODE;
  556.   DONE,SUBBED,JUNK:BOOLEAN;
  557. BEGIN
  558.   IF(GLOB)THEN
  559.     STAT:=OK
  560.   ELSE
  561.     STAT:=ERR;
  562.     DONE:=(LINE1<=0);
  563.     LINE:=LINE1;
  564.     WHILE(NOT DONE)AND(LINE<=LINE2)DO BEGIN
  565.       J:=1;
  566.       SUBBED:=FALSE;
  567.       GETTXT(LINE,OLD);
  568.       LASTM:=0;
  569.       K:=1;
  570.       WHILE(OLD[K]<>ENDSTR)DO BEGIN
  571.         IF(GFLAG)OR(NOT SUBBED)THEN
  572.           M:=AMATCH(OLD,K,PAT,1)
  573.         ELSE
  574.           M:=0;
  575.         IF(M>0)AND(LASTM<>M)THEN BEGIN
  576.           SUBBED:=TRUE;
  577.           CATSUB(OLD,K,M,SUB,NEW,J,MAXSTR);
  578.           LASTM:=M
  579.         END;
  580.         IF(M=0)OR(M=K)THEN BEGIN
  581.           JUNK:=ADDSTR(OLD[K],NEW,J,MAXSTR);
  582.           K:=K+1
  583.         END
  584.         ELSE
  585.           K:=M
  586.       END;
  587.       IF(SUBBED)THEN BEGIN
  588.         IF(NOT ADDSTR(ENDSTR,NEW,J,MAXSTR))THEN BEGIN
  589.           STAT:=ERR;
  590.           DONE:=TRUE
  591.         END
  592.         ELSE BEGIN
  593.           STAT:=LNDELETE(LINE,LINE,STATUS);
  594.           STAT:=PUTTXT(NEW);
  595.           LINE2:=LINE2+CURLN-LINE;
  596.           LINE:=CURLN;
  597.           IF(STAT=ERR)THEN
  598.             DONE:=TRUE
  599.           ELSE
  600.             STAT:=OK
  601.           END
  602.         END;
  603.         LINE:=LINE+1
  604.       END;
  605.       SUBST:=STAT
  606.     END;
  607. FUNCTION MAKESUB(VAR ARG:XSTRING;FROM:INTEGER;
  608.   DELIM:CHARACTER;VAR SUB:XSTRING):INTEGER;
  609. VAR I,J:INTEGER;
  610.    JUNK:BOOLEAN;
  611. BEGIN
  612.   J:=1;
  613.   I:=FROM;
  614.   WHILE(ARG[I]<>DELIM)AND(ARG[I]<>ENDSTR)DO BEGIN
  615.     IF(ARG[I]=ORD('&'))THEN
  616.       JUNK:=ADDSTR(DITTO,SUB,J,MAXPAT)
  617.     ELSE
  618.       JUNK:=ADDSTR(ESC(ARG,I),SUB,J,MAXPAT);
  619.     I:=I+1
  620.   END;
  621.   IF(ARG[I]<>DELIM) THEN
  622.     MAKESUB:=0
  623.   ELSE IF (NOT ADDSTR(ENDSTR,SUB,J,MAXPAT))THEN
  624.     MAKESUB:=0
  625.   ELSE
  626.     MAKESUB:=I
  627. END;
  628. FUNCTION GETRHS(VAR LIN:XSTRING;VAR I:INTEGER;
  629.   VAR SUB:XSTRING;VAR GFLAG:BOOLEAN):STCODE;
  630. BEGIN
  631.   GETRHS:=OK;
  632.   IF(LIN[I]=ENDSTR)THEN
  633.     GETRHS:=ERR
  634.   ELSE IF(LIN[I+1]=ENDSTR)THEN
  635.     GETRHS:=ERR
  636.   ELSE BEGIN
  637.     I:=MAKESUB(LIN,I+1,LIN[I],SUB);
  638.     IF(I=0)THEN
  639.       GETRHS:=ERR
  640.     ELSE IF(LIN[I+1]=ORD('G'))THEN BEGIN
  641.       I:=I+1;
  642.       GFLAG:=TRUE
  643.     END
  644.     ELSE
  645.       GFLAG:=FALSE
  646.   END
  647. END;
  648.  
  649. FUNCTION DOCMD(VAR LIN:XSTRING;VAR I:INTEGER;
  650.   GLOB:BOOLEAN;VAR STATUS:STCODE):STCODE;
  651. VAR
  652.   FIL,SUB:XSTRING;
  653.   LINE3:INTEGER;
  654.   GFLAG,PFLAG:BOOLEAN;
  655. BEGIN
  656.   PFLAG:=FALSE;
  657.   STATUS:=ERR;
  658.   IF(LIN[I]=PCMD)THEN BEGIN
  659.     IF(LIN[I+1]=NEWLINE)THEN 
  660.       IF(DEFAULT(CURLN,CURLN,STATUS)=OK)THEN
  661.         STATUS:=DOPRINT(LINE1,LINE2)
  662.   END
  663.   ELSE IF(LIN[I]=NEWLINE)THEN BEGIN
  664.     IF(NLINES=0)THEN
  665.       LINE2:=NEXTLN(CURLN);
  666.     STATUS:=DOPRINT(LINE2,LINE2)
  667.   END
  668.   ELSE IF(LIN[I]=QCMD)THEN BEGIN
  669.     IF( LIN[I+1]=NEWLINE)AND(NLINES=0)AND(NOT GLOB)THEN
  670.   STATUS:=ENDDATA
  671.   END
  672.   ELSE IF(LIN[I]=ACMD)THEN BEGIN
  673.     IF(LIN[I+1]=NEWLINE)THEN
  674.       STATUS:=APPEND(LINE2,GLOB)
  675.   END
  676.   ELSE IF(LIN[I]=CCMD)THEN BEGIN
  677.     IF(LIN[I+1]=NEWLINE)THEN
  678.       IF(DEFAULT(CURLN,CURLN,STATUS)=OK)THEN
  679.       IF(LNDELETE(LINE1,LINE2,STATUS)=OK)THEN
  680.         STATUS:=APPEND(PREVLN(LINE1),GLOB)
  681.   END
  682.   ELSE IF(LIN[I]=DCMD)THEN BEGIN
  683.     IF(CKP(LIN,I+1,PFLAG,STATUS)=OK)THEN
  684.      IF(DEFAULT(CURLN,CURLN,STATUS)=OK)THEN
  685.      IF(LNDELETE(LINE1,LINE2,STATUS)=OK)THEN
  686.      IF(NEXTLN(CURLN)<>0)THEN
  687.        CURLN:=NEXTLN(CURLN)
  688.   END
  689.   ELSE IF(LIN[I]=ICMD)THEN BEGIN
  690.     IF(LIN[I+1]=NEWLINE)THEN BEGIN
  691.       IF(LINE2=0)THEN
  692.         STATUS:=APPEND(0,GLOB)
  693.       ELSE
  694.         STATUS:=APPEND(PREVLN(LINE2),GLOB)
  695.     END
  696.   END
  697.   ELSE IF(LIN[I]=EQCMD)THEN BEGIN
  698.     IF(CKP(LIN,I+1,PFLAG,STATUS)=OK)THEN BEGIN
  699.       PUTDEC(LINE2,1);
  700.       PUTC(NEWLINE)
  701.     END
  702.   END
  703.   ELSE IF(LIN[I]=MCMD)THEN BEGIN
  704.     I:=I+1;
  705.     IF(GETONE(LIN,I,LINE3,STATUS)=ENDDATA)THEN
  706.       STATUS:=ERR;
  707.     IF(STATUS =OK)THEN
  708.       IF(CKP(LIN,I,PFLAG,STATUS)=OK)THEN
  709.       IF(DEFAULT(CURLN,CURLN,STATUS)=OK)THEN
  710.         STATUS:=MOVE(LINE3)
  711.   END
  712.   ELSE IF(LIN[I]=SCMD)THEN BEGIN
  713.     I:=I+1;
  714.     IF(OPTPAT(LIN,I)=OK)THEN 
  715.     IF(GETRHS(LIN,I,SUB,GFLAG)=OK)THEN
  716.     IF(CKP(LIN,I+1,PFLAG,STATUS)=OK)THEN
  717.     IF(DEFAULT(CURLN,CURLN,STATUS)=OK)THEN
  718.       STATUS:=SUBST(SUB,GFLAG,GLOB)
  719.   END
  720.   ELSE IF(LIN[I]=ECMD)THEN BEGIN
  721.     IF(NLINES =0)THEN
  722.       IF(GETFN(LIN,I,FIL)=OK)THEN BEGIN
  723.         SCOPY(FIL,1,SAVEFILE,1);
  724.         CLRBUF;
  725.         SETBUF;
  726.         STATUS:=DOREAD(0,FIL)
  727.       END
  728.   END
  729.   ELSE IF(LIN[I]=FCMD)THEN BEGIN
  730.     IF(NLINES =0)THEN
  731.       IF(GETFN(LIN,I,FIL)=OK)THEN BEGIN
  732.         SCOPY(FIL,1,SAVEFILE,1);
  733.         PUTSTR(SAVEFILE,STDOUT);
  734.         PUTC(NEWLINE);
  735.         STATUS:=OK
  736.     END
  737.   END
  738.   ELSE IF(LIN[I]=RCMD)THEN BEGIN
  739.     IF(GETFN(LIN,I,FIL)=OK)THEN
  740.       STATUS:=DOREAD(LINE2,FIL)
  741.   END
  742.   ELSE IF(LIN[I]=WCMD)THEN BEGIN
  743.     IF(GETFN(LIN,I,FIL)=OK)THEN
  744.       IF(DEFAULT(1,LASTLN,STATUS)=OK)THEN
  745.         STATUS:=DOWRITE(LINE1,LINE2,FIL)
  746.   END;
  747.   IF(STATUS =OK)AND(PFLAG)THEN
  748.     STATUS:=DOPRINT(CURLN,CURLN);
  749.   DOCMD:=STATUS
  750. END;(*DOCMD*)
  751.  
  752. FUNCTION CKGLOB(VAR LIN: XSTRING;VAR I:INTEGER;
  753.   VAR STATUS:STCODE): STCODE;
  754. VAR
  755.   N:INTEGER;
  756.   GFLAG:BOOLEAN;
  757.   TEMP: XSTRING;
  758. BEGIN
  759.   IF(LIN[I]<>GCMD)AND(LIN[I]<>XCMD)THEN
  760.     STATUS:=ENDDATA
  761.   ELSE BEGIN
  762.     GFLAG:=(LIN[I]=GCMD);
  763.     I:=I+1;
  764.     IF(OPTPAT(LIN,I)=ERR)THEN
  765.       STATUS:=ERR
  766.     ELSE IF( DEFAULT(1,LASTLN,STATUS)<>ERR)THEN BEGIN
  767.       I:=I+1;
  768.       FOR N:=LINE1 TO LINE2 DO BEGIN
  769.         GETTXT(N,TEMP);
  770.         PUTMARK(N,(MATCH(TEMP,PAT)=GFLAG))
  771.       END;
  772.  
  773.       FOR N:=1 TO LINE1-1 DO
  774.         PUTMARK(N,FALSE);
  775.       FOR N:=LINE2+1 TO LASTLN DO
  776.         PUTMARK(N,FALSE);
  777.       STATUS:=OK
  778.     END
  779.   END;
  780.   CKGLOB:=STATUS
  781. END;
  782.  
  783. FUNCTION DOGLOB(VAR LIN:XSTRING;VAR I,CURSAVE:INTEGER;
  784.   VAR STATUS: STCODE):STCODE;
  785. VAR
  786.   COUNT,ISTART,N: INTEGER;
  787. BEGIN
  788.   STATUS:=OK;
  789.   COUNT:=0;
  790.   N:=LINE1;
  791.   ISTART:=I;
  792.   REPEAT
  793.     IF(GETMARK(N))THEN BEGIN
  794.       PUTMARK(N,FALSE);
  795.       CURLN:=N;
  796.       CURSAVE:=CURLN;
  797.       I:=ISTART;
  798.       IF(DOCMD(LIN,I,TRUE,STATUS)=OK)THEN
  799.         COUNT:=0
  800.     END
  801.     ELSE BEGIN
  802.       N:=NEXTLN(N);
  803.       COUNT:=COUNT + 1
  804.     END
  805.   UNTIL(COUNT > LASTLN)OR(STATUS <> OK);
  806.   DOGLOB:=STATUS
  807. END;
  808.  
  809. BEGIN
  810.   SETBUF;
  811.   PAT[1]:=ENDSTR;
  812.   SAVEFILE[1]:=ENDSTR;
  813.   IF(GETARG(2,SAVEFILE,MAXSTR))THEN
  814.     IF(DOREAD(0,SAVEFILE)=ERR)THEN
  815.       WRITELN('?');
  816.   MORE:=GETLINE(LIN,STDIN,MAXSTR);
  817.   WHILE(MORE)DO BEGIN
  818.     I:=1;
  819.     CURSAVE:=CURLN;
  820.     IF(GETLIST(LIN,I,STATUS)=OK)THEN BEGIN
  821.       IF(CKGLOB(LIN,I,STATUS)=OK)THEN
  822.         STATUS:=DOGLOB(LIN,I,CURSAVE,STATUS)
  823.       ELSE IF(STATUS<>ERR)THEN
  824.         STATUS:=DOCMD(LIN,I,FALSE,STATUS)
  825.     END;
  826.     IF(STATUS=ERR)THEN BEGIN
  827.       WRITELN('?');
  828.       CURLN:=MIN(CURSAVE,LASTLN)
  829.     END
  830.     ELSE IF(STATUS=ENDDATA)THEN
  831.       MORE:=FALSE;
  832.     IF(MORE)THEN
  833.       MORE:=GETLINE(LIN,STDIN,MAXSTR)
  834.   END;
  835.   CLRBUF
  836. END;
  837.  
  838.  
  839.  
  840.  
  841.