home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / cpm86 / trbtol86.lbr / CHAPTER4.PQS / CHAPTER4.PAS
Pascal/Delphi Source File  |  1985-10-23  |  8KB  |  397 lines

  1.  
  2. {
  3.         Copyright (c) 1981
  4.         By:     Bell Telephone Laboratories, Inc. and
  5.                 Whitesmith's Ltd.,
  6.  
  7.         This software is derived from the book
  8.                 "Software Tools in Pascal", by
  9.                 Brian W. Kernighan and P. J. Plauger
  10.                 Addison-Wesley, 1981
  11.                 ISBN 0-201-10342-7
  12.  
  13.         Right is hereby granted to freely distribute or duplicate this
  14.         software, providing distribution or duplication is not for profit
  15.         or other commercial gain and that this copyright notice remains
  16.         intact.
  17. }
  18.  
  19. PROCEDURE SORT;
  20. CONST
  21.   MAXCHARS=10000;
  22.   MAXLINES=300;
  23.   MERGEORDER=5;
  24. TYPE
  25.   CHARPOS=1..MAXCHARS;
  26.   CHARBUF=ARRAY[1..MAXCHARS] OF CHARACTER;
  27.   POSBUF=ARRAY[1..MAXLINES] OF CHARPOS;
  28.   POS=0..MAXLINES;
  29.   FDBUF=ARRAY[1..MERGEORDER]OF FILEDESC;
  30. VAR
  31.   LINEBUF:CHARBUF;
  32.   LINEPOS:POSBUF;
  33.   NLINES:POS;
  34.   INFILE:FDBUF;
  35.   OUTFILE:FILEDESC;
  36.   HIGH,LOW,LIM:INTEGER;
  37.   DONE:BOOLEAN;
  38.   NAME:XSTRING;
  39. FUNCTION GTEXT(VAR LINEPOS:POSBUF;VAR NLINES:POS;
  40.   VAR LINEBUF:CHARBUF;INFILE:FILEDESC):BOOLEAN;
  41. VAR
  42.   I,LEN,NEXTPOS:INTEGER;
  43.   TEMP:XSTRING;
  44.   DONE:BOOLEAN;
  45. BEGIN
  46.   NLINES:=0;
  47.   NEXTPOS:=1;
  48.   REPEAT
  49.     DONE:=(GETLINE(TEMP,INFILE,MAXSTR)=FALSE);
  50.     IF(NOT DONE) THEN BEGIN
  51.       NLINES:=NLINES+1;
  52.       LINEPOS[NLINES]:=NEXTPOS;
  53.       LEN:=XLENGTH(TEMP);
  54.       FOR I:=1 TO LEN DO
  55.         LINEBUF[NEXTPOS+I-1]:=TEMP[I];
  56.       LINEBUF[NEXTPOS+LEN]:=ENDSTR;
  57.       NEXTPOS:=NEXTPOS+LEN+1
  58.     END
  59.   UNTIL (DONE) OR (NEXTPOS>= MAXCHARS-MAXSTR)
  60.     OR (NLINES>=MAXLINES);
  61.   GTEXT:=DONE
  62. END;
  63.  
  64. PROCEDURE PTEXT(VAR LINEPOS:POSBUF;NLINES:INTEGER;
  65.   VAR LINEBUF:CHARBUF;OUTFILE:FILEDESC);
  66. VAR
  67.   I,J:INTEGER;
  68. BEGIN
  69.   FOR I:=1 TO NLINES DO BEGIN
  70.       J:=LINEPOS[I];
  71.       WHILE (LINEBUF[J]<>ENDSTR)DO BEGIN
  72.         PUTCF(LINEBUF[J],OUTFILE);
  73.         J:=J+1
  74.       END
  75.     END
  76. END;
  77.  
  78.       
  79.  
  80. PROCEDURE EXCHANGE(VAR LP1,LP2:CHARPOS);
  81. VAR
  82.   TEMP:CHARPOS;
  83. BEGIN
  84.   TEMP:=LP1;
  85.   LP1:=LP2;
  86.   LP2:=TEMP
  87. END;
  88.  
  89. FUNCTION CMP (I,J:CHARPOS;VAR LINEBUF:CHARBUF)
  90.    :INTEGER;
  91. BEGIN
  92.   WHILE(LINEBUF[I]=LINEBUF[J])
  93.    AND (LINEBUF[I]<>ENDSTR) DO BEGIN
  94.      I:=I+1;
  95.      J:=J+1
  96.    END;
  97.    IF(LINEBUF[I]=LINEBUF[J]) THEN
  98.      CMP:=0
  99.    ELSE IF (LINEBUF[I]=ENDSTR) THEN
  100.      CMP:=-1
  101.    ELSE IF (LINEBUF[J]=ENDSTR) THEN
  102.      CMP:=+1
  103.    ELSE IF (LINEBUF[I]<LINEBUF[J]) THEN
  104.      CMP:=-1
  105.    ELSE
  106.      CMP:=+1
  107. END;(*CMP*)
  108.  
  109.  
  110. PROCEDURE QUICK(VAR LINEPOS:POSBUF; NLINE:POS;
  111.   VAR LINEBUF:CHARBUF);
  112. PROCEDURE RQUICK(LO,HI:INTEGER);
  113. VAR
  114.   I,J:INTEGER;
  115.   PIVLINE:CHARPOS;
  116. BEGIN
  117.   IF (LO<HI) THEN BEGIN
  118.     I:=LO;
  119.     J:=HI;
  120.     PIVLINE:=LINEPOS[J];
  121.     REPEAT
  122.       WHILE (I<J)
  123.         AND (CMP(LINEPOS[I],PIVLINE,LINEBUF)<=0) DO
  124.           I:=I+1;
  125.       WHILE  (J>I)
  126.         AND (CMP(LINEPOS[J],PIVLINE,LINEBUF)>=0) DO
  127.           J:=J-1;
  128.       IF(I<J) THEN
  129.       (*OUT OF ORDER PAIR*)
  130.         EXCHANGE(LINEPOS[I],LINEPOS[J])
  131.     UNTIL (I>=J);
  132.     EXCHANGE(LINEPOS[I],LINEPOS[HI]);
  133.     IF(I-LO<HI-I) THEN BEGIN
  134.       RQUICK(LO,I-1);
  135.       RQUICK(I+1,HI)
  136.     END
  137.     ELSE BEGIN
  138.       RQUICK(I+1,HI);
  139.       RQUICK(LO,I-1)
  140.     END
  141.   END
  142. END;(*RQUICK*)
  143.  
  144. BEGIN(*QUICK*)
  145.   RQUICK(1,NLINES)
  146. END;
  147.  
  148.  
  149. PROCEDURE GNAME(N:INTEGER;VAR NAME:XSTRING);
  150. VAR
  151.   JUNK:INTEGER;
  152.   BEGIN
  153.     NAME[1]:=ORD('S');
  154.     NAME[2]:=ORD('T');
  155.     NAME[3]:=ORD('E');
  156.     NAME[4]:=ORD('M');
  157.     NAME[5]:=ORD('P');
  158.     NAME[6]:=ENDSTR;
  159.   JUNK:=ITOC(N,NAME,XLENGTH(NAME)+1)
  160. END;
  161.  
  162. PROCEDURE GOPEN(VAR INFILE:FDBUF;F1,F2:INTEGER);
  163. VAR
  164.   NAME:XSTRING;
  165.   I:1..MERGEORDER;
  166. BEGIN
  167.   FOR I:=1 TO F2-F1+1 DO BEGIN
  168.     GNAME(F1+I-1,NAME);
  169.     INFILE[I]:=MUSTOPEN(NAME,IOREAD)
  170.   END
  171. END;
  172.  
  173. PROCEDURE GREMOVE(VAR INFILE:FDBUF;F1,F2:INTEGER);
  174. VAR
  175.   NAME:XSTRING;
  176.   I:1..MERGEORDER;
  177. BEGIN
  178.   FOR I:= 1 TO F2-F1+1 DO BEGIN
  179.     XCLOSE(INFILE[I]);
  180.     GNAME(F1+I-1,NAME);
  181.     REMOVE(NAME)
  182.   END
  183. END;
  184.  
  185.  
  186. FUNCTION MAKEFILE(N:INTEGER):FILEDESC;
  187. VAR
  188.   NAME:XSTRING;
  189. BEGIN
  190.   GNAME(N,NAME);
  191.  
  192.   MAKEFILE:=MUSTCREATE(NAME,IOWRITE)
  193. END;
  194.  
  195. PROCEDURE MERGE(VAR INFILE:FDBUF; NF:INTEGER;
  196.   OUTFILE:FILEDESC);
  197.  
  198. VAR
  199.   I,J:INTEGER;
  200.   LBP:CHARPOS;
  201.   TEMP:XSTRING;
  202.  
  203. PROCEDURE REHEAP(VAR LINEPOS:POSBUF;NF:POS;
  204.   VAR LINEBUF:CHARBUF);
  205. VAR
  206.   I,J:INTEGER;
  207. BEGIN
  208.   I:=1;
  209.   J:=2*I;
  210.   WHILE(J<=NF)DO BEGIN
  211.     IF(J<NF) THEN
  212.       IF(CMP(LINEPOS[J],LINEPOS[J+1],LINEBUF)>0)THEN
  213.         J:=J+1;
  214.     IF(CMP(LINEPOS[I],LINEPOS[J],LINEBUF)<=0)THEN
  215.       I:=NF
  216.     ELSE
  217.       EXCHANGE(LINEPOS[I],LINEPOS[J]);(*PERCOLATE*)
  218.     I:=J;
  219.     J:=2*I
  220.   END
  221. END;
  222.  
  223. PROCEDURE SCCOPY(VAR S:XSTRING; VAR CB:CHARBUF;
  224.   I:CHARPOS);
  225. VAR J:INTEGER;
  226. BEGIN
  227.   J:=1;
  228.   WHILE(S[J]<>ENDSTR)DO BEGIN
  229.     CB[I]:=S[J];
  230.     J:=J+1;
  231.     I:=I+1
  232.   END;
  233.   CB[I]:=ENDSTR
  234. END;
  235.  
  236. PROCEDURE CSCOPY(VAR CB:CHARBUF;I:CHARPOS;
  237.   VAR S:XSTRING);
  238. VAR J:INTEGER;
  239. BEGIN
  240.   J:=1;
  241.   WHILE(CB[I]<>ENDSTR)DO BEGIN
  242.     S[J]:=CB[I];
  243.     I:=I+1;
  244.     J:=J+1
  245.   END;
  246.   S[J]:=ENDSTR
  247. END;
  248.  
  249. BEGIN(*MERGE*)
  250.   J:=0;
  251.   FOR I:=1 TO NF DO
  252.     IF(GETLINE(TEMP,INFILE[I],MAXSTR)) THEN BEGIN
  253.       LBP:=(I-1)*MAXSTR+1;
  254.       SCCOPY(TEMP,LINEBUF,LBP);
  255.       LINEPOS[I]:=LBP;
  256.       J:=J+1
  257.     END;
  258.   NF:=J;
  259.   QUICK(LINEPOS,NF,LINEBUF);
  260.   WHILE (NF>0) DO BEGIN
  261.     LBP:=LINEPOS[1];
  262.     CSCOPY(LINEBUF,LBP,TEMP);
  263.     PUTSTR(TEMP,OUTFILE);
  264.     I:=LBP DIV MAXSTR +1;
  265.     IF (GETLINE(TEMP,INFILE[I],MAXSTR))THEN
  266.       SCCOPY(TEMP,LINEBUF,LBP)
  267.     ELSE BEGIN
  268.       LINEPOS[1]:=LINEPOS[NF];
  269.       NF:=NF-1
  270.     END;
  271.     REHEAP(LINEPOS,NF,LINEBUF)
  272.   END
  273. END;
  274.  
  275.  
  276. BEGIN
  277.   HIGH:=0;
  278.   REPEAT (*INITIAL FORMTION OF RUNS*)
  279.     DONE:=GTEXT(LINEPOS,NLINES,LINEBUF,STDIN);
  280.     QUICK(LINEPOS,NLINES,LINEBUF);
  281.     HIGH:=HIGH+1;
  282.     OUTFILE:=MAKEFILE(HIGH);
  283.     PTEXT(LINEPOS,NLINES,LINEBUF,OUTFILE);
  284.     XCLOSE(OUTFILE)
  285.   UNTIL (DONE);
  286.   LOW:=1;
  287.   WHILE (LOW<HIGH) DO BEGIN
  288.     LIM:=MIN(LOW+MERGEORDER-1,HIGH);
  289.     GOPEN(INFILE,LOW,LIM);
  290.     HIGH:=HIGH+1;
  291.     OUTFILE:=MAKEFILE(HIGH);
  292.     MERGE(INFILE,LIM-LOW+1,OUTFILE);
  293.     XCLOSE(OUTFILE);
  294.     GREMOVE(INFILE,LOW,LIM);
  295.     LOW:=LOW+MERGEORDER
  296.   END;
  297.   GNAME(HIGH,NAME);
  298.   OUTFILE:=OPEN(NAME,IOREAD);
  299.   FCOPY(OUTFILE,STDOUT);
  300.   XCLOSE(OUTFILE);
  301.   REMOVE(NAME)
  302. END;
  303.  
  304. PROCEDURE UNIQUE;
  305. VAR
  306.   BUF:ARRAY[0..1] OF XSTRING;
  307.   CUR:0..1;
  308. BEGIN
  309.   CUR:=1;
  310.   BUF[1-CUR][1]:=ENDSTR;
  311.   WHILE (GETLINE(BUF[CUR],STDIN,MAXSTR))DO
  312.     IF (NOT EQUAL (BUF[CUR],BUF[1-CUR])) THEN BEGIN
  313.       PUTSTR(BUF[CUR],STDOUT);
  314.       CUR:=1-CUR
  315.     END
  316. END;
  317.  
  318. PROCEDURE KWIC;
  319. CONST
  320.   FOLD=DOLLAR;
  321. VAR
  322.   BUF:XSTRING;
  323.  
  324. PROCEDURE PUTROT(VAR BUF:XSTRING);
  325. VAR I:INTEGER;
  326.  
  327. PROCEDURE ROTATE(VAR BUF:XSTRING;N:INTEGER);
  328. VAR I:INTEGER;
  329. BEGIN
  330.   I:=N;
  331.   WHILE (BUF[I]<>NEWLINE) AND (BUF[I]<>ENDSTR) DO BEGIN
  332.     PUTC(BUF[I]);
  333.     I:=I+1
  334.   END;
  335.   PUTC(FOLD);
  336.   FOR I:=1 TO N-1 DO
  337.     PUTC(BUF[I]);
  338.   PUTC(NEWLINE)
  339. END;(*ROTATE*)
  340.  
  341. BEGIN(*PUTROT*)
  342.   I:=1;
  343.   WHILE(BUF[I]<>NEWLINE) AND (BUF[I]<>ENDSTR) DO BEGIN
  344.     IF (ISALPHANUM(BUF[I])) THEN BEGIN
  345.       ROTATE(BUF,I);(*TOKEN STATRS AT "I"*)
  346.     REPEAT
  347.       I:=I+1
  348.     UNTIL (NOT ISALPHANUM(BUF[I]))
  349.   END;
  350.   I:=I+1
  351.   END
  352.   
  353. END;(*PUTROT*)
  354.  
  355. BEGIN(*KWIC*)
  356.   WHILE(GETLINE(BUF,STDIN,MAXSTR))DO
  357.     PUTROT(BUF)
  358. END;
  359.  
  360. PROCEDURE UNROTATE;
  361. CONST
  362.   MAXOUT=80;
  363.   MIDDLE=40;
  364.   FOLD=DOLLAR;
  365. VAR
  366.   INBUF,OUTBUF:XSTRING;
  367.   I,J,F:INTEGER;
  368. BEGIN
  369.   WHILE(GETLINE(INBUF,STDIN,MAXSTR))DO BEGIN
  370.     FOR I:=1 TO MAXOUT-1 DO
  371.       OUTBUF[I]:=BLANK;
  372.     F:=INDEX(INBUF,FOLD);
  373.     J:=MIDDLE-1;
  374.     FOR I:=XLENGTH(INBUF)-1 DOWNTO F+1 DO BEGIN
  375.       OUTBUF[J]:=INBUF[I];
  376.       J:=J-1;
  377.       IF(J<=0)THEN
  378.         J:=MAXOUT-1
  379.     END;
  380.     J:=MIDDLE+1;
  381.     FOR I:=1 TO F-1 DO BEGIN
  382.       OUTBUF[J]:=INBUF[I];
  383.       J:=J MOD (MAXOUT-1) +1
  384.     END;
  385.     FOR J:=1 TO MAXOUT-1 DO
  386.       IF(OUTBUF[J]<>BLANK) THEN
  387.         I:=J;
  388.     OUTBUF[I+1]:=ENDSTR;
  389.     PUTSTR(OUTBUF,STDOUT);
  390.     PUTC(NEWLINE)
  391.   END
  392. END;
  393.  
  394.  
  395.  
  396.  
  397.