home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / PASCAL / KRTOOL.ZIP / CHAPTER6.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-10-19  |  16.9 KB  |  840 lines

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