home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / FILER.ZIP / SORTER.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-11-18  |  15.6 KB  |  458 lines

  1. (***************************************************************)
  2. (*                                                             *)
  3. (*        FILER A LA PASCAL DATA BASE SOURCE CODE FILE         *)
  4. (*                                                             *)
  5. (*        (C) 1985 by  John M. Harlan                          *)
  6. (*                     24000 Telegraph                         *)
  7. (*                     Southfield, MI. 48034                   *)
  8. (*                                                             *)
  9. (*     The FILER GROUP of programs is released on a "FREE      *)
  10. (*     SOFTWARE" basis.  The recipient is free to examine      *)
  11. (*     and use the software with the understanding that if     *)
  12. (*     the FILER GROUP of programs prove to be of use and      *)
  13. (*     value,  a contribution to the author is encouraged.     *)
  14. (*                                                             *)
  15. (*     While reasonable effort has been made to ensure the     *)
  16. (*     reliability of the FILER GROUP of programs, no war-     *)
  17. (*     ranty is given. The recipient uses the programs at      *)
  18. (*     his own risk  and in no event shall the author be       *)
  19. (*     liable for damages arising from their use.              *)
  20. (*                                                             *)
  21. (*                                                             *)
  22. (***************************************************************)
  23.  
  24.  
  25. PROGRAM SORTER; { ONE OF THE FILER GROUP OF PROGRAMS }
  26. {  PROGRAM TO SORT FILES CREATED BY THE FILER GROUP OF PROGRMS  }
  27. {  SORTER.PAS  VERSION 2.0 }
  28. {  INCLUDE FILES : SORTER1.PAS, SORT.BOX (PART OF TURBO TOOLBOX) }
  29. {  APR 29, 1985 }
  30.  
  31. TYPE
  32.   RANGE          = ARRAY[1..256] OF CHAR;
  33.   STRING60         =  STRING[60];
  34.   STRING20         =  STRING[20];
  35.   NAMESTR          =  STRING[12];
  36.  
  37. VAR
  38.   FILERECCHGD      : BOOLEAN;    { FOR SOURCE FILE }
  39.   RECADDEDTOFILE   : BOOLEAN;    { FOR SOURCE FILE }
  40.   FILERECCHGD2     : BOOLEAN;    { FOR DESTINATION FILE }
  41.   RECADDEDTOFILE2  : BOOLEAN;    { FOR DESTINATION FILE }
  42.   FILEEXISTS       : BOOLEAN;
  43.   NULLRECORD       : BOOLEAN;
  44.  
  45.   CH               : CHAR;
  46.  
  47.   FILENAME         : STRING[6];
  48.   FILEDATE,
  49.   CURRDATE         : STRING[8];
  50.   SOURCENAME       : STRING[14];
  51.   SOURCENAMEDAT    : STRING[14];
  52.   SOURCENAMEBAK    : STRING[14];
  53.   ANS              : STRING60;
  54.   MESSAGE          : STRING60;
  55.   THISKEY          : STRING60;
  56.  
  57.   W, X, Y, Z, CODE, FIRST, LEN,
  58.   MAXNBRREC, RCDLEN,
  59.   BLOCKINGFACTOR, FIELDPERRECORD,
  60.   ASCII, KEYLENGTH                      : INTEGER;
  61.  
  62.   DATARECORD, DISKRECORD, PRECBYTE,
  63.   DISKRECNOWINMEM, NBRDISKRECUSED,
  64.   NBRRECUSED,LASTRECUSED                : INTEGER;  { FOR SOURCE FILE }
  65.  
  66.   DATARECORD2, DISKRECORD2, PRECBYTE2,
  67.   DISKRECNOWINMEM2, NBRDISKRECUSED2,
  68.   NBRRECUSED2,LASTRECUSED2              : INTEGER;  { FOR DESTINATION FILE }
  69.  
  70.   NUMVALUE                              :    REAL;
  71.  
  72.   LABELLENGTH, DATALEN, DATAFORM,
  73.   LABELPOSN, DATAPOSN, ROW,
  74.   COLUMN                            :    ARRAY[1..32] OF INTEGER;
  75.   KEYFIELD                          :    ARRAY[0..10] OF INTEGER;
  76.   LBL                               :    ARRAY[1..384] OF CHAR;
  77.   GETDATA                           :    RANGE;  { FOR SOURCE FILE }
  78.   OUTDATA                           :    RANGE;  { FOR DESTINATION FILE }
  79.  
  80.   SOURCE                            :    FILE;
  81.   DESTINATION                       :    FILE;
  82.  
  83. {$ISORT.BOX}           { INCLUDE SORT ROUTINE FROM TURBO TOOLBOX }
  84.  
  85. {================================================================}
  86. {        BINARY CODED DECIMAL TO INTEGER FUNCTION                }
  87. {================================================================}
  88. FUNCTION BCDTOIN (CHA : CHAR) : INTEGER;
  89. BEGIN
  90.   BCDTOIN := ORD(CHA) - TRUNC(ORD(CHA)/16)*6;
  91. END;
  92. {================================================================}
  93. {             CHARACTER TO INTEGER FUNCTION                      }
  94. {================================================================}
  95. FUNCTION CHTOIN(VAR CHARRAY : RANGE; START, LEN : INTEGER)  : INTEGER;
  96. VAR
  97.   CODE, RESULT : INTEGER;
  98.   WORKSTRING   : STRING[10];
  99. BEGIN
  100.   WORKSTRING := '';
  101.   FOR RESULT := 0 TO LEN-1  DO
  102.     BEGIN
  103.       IF CHARRAY[START + RESULT ] = ' ' THEN
  104.         WORKSTRING := WORKSTRING + '0'
  105.       ELSE WORKSTRING := WORKSTRING + CHARRAY[START+RESULT];
  106.     END;
  107.   VAL(WORKSTRING,RESULT,CODE);
  108.   CHTOIN := RESULT;
  109. END;
  110. {================================================================}
  111. {               TIDE (EDIT BACKWARDS) PROCEDURE                  }
  112. {================================================================}
  113. PROCEDURE TIDE( VAR MESSAGE : STRING60);
  114. VAR W  :  INTEGER;
  115. BEGIN
  116.   FOR W := LENGTH(MESSAGE) DOWNTO 1 DO
  117.     BEGIN
  118.       IF MESSAGE[W] IN [',', '$', '+'] THEN
  119.         BEGIN
  120.           DELETE(MESSAGE,W,1);
  121.           MESSAGE := ' ' + MESSAGE;
  122.         END;
  123.     END;
  124. END;
  125. {===============================================================}
  126. {                      FUNCTION EDITNBR                         }
  127. {===============================================================}
  128. FUNCTION EDITNBR(X: REAL; Y,Z: INTEGER; DOLLAR: CHAR ) : STRING20;
  129. VAR
  130.   NUMSTRING : STRING[24];
  131. BEGIN    { CONVERT THE REAL NUMBER TO A STRING VALUE }
  132.   STR(X:18:Z,NUMSTRING);
  133.   IF Z = 0 THEN Z := 16  { FIRST POSSIBLE COMMA LOCATION  }
  134.   ELSE Z := POS('.',NUMSTRING)-3;  {    DITTO             }
  135.  
  136.   WHILE Z > 1 DO  {  INSERT COMMAS/SPACES IN THE NUMBER  }
  137.     BEGIN
  138.       IF NUMSTRING[Z-1] IN [' ','-'] THEN
  139.         INSERT(' ',NUMSTRING,Z)
  140.       ELSE INSERT(',',NUMSTRING,Z);
  141.       Z := Z -3 ;  {  COMMAS OCCUR EVERY THIRD CHARACTER  }
  142.     END;
  143.  
  144.   {  FIND THE FIRST NON SPACE CHARACTER IN THE NUMBER }
  145.   Z := 0;
  146.   REPEAT
  147.     Z := Z + 1;
  148.  UNTIL NUMSTRING[Z] <> ' ';
  149.  
  150.   { DELETE ANY SPACE FOLLOWING A MINUS SIGN }
  151.   IF NUMSTRING[Z] = '-' THEN
  152.     BEGIN
  153.       IF NUMSTRING[Z+1] = ' ' THEN DELETE(NUMSTRING,Z+1,1);
  154.       IF DOLLAR = '$' THEN INSERT('$',NUMSTRING,Z+1);
  155.     END
  156.  
  157.   { ADD THE $/SPACE CHARACTER TO THE BEGINNING OF THE NUMBER }
  158.   ELSE NUMSTRING[Z-1] := DOLLAR;
  159.  
  160.   { REPLACE THE NUMBER WITH A FIELD OF '<' IF IT IS TOO BIG  }
  161.   Z := LENGTH(NUMSTRING)-Y;
  162.   IF NUMSTRING[Z-1] = '-' THEN
  163.       FOR Z := Y DOWNTO 0 DO NUMSTRING[Z] := '<'
  164.   ELSE
  165.     BEGIN
  166.       IF NUMSTRING[Z] IN ['0'..'9',',','-','.'] THEN
  167.           FOR Z := Y DOWNTO 0 DO NUMSTRING[Z] := '<';
  168.     END;
  169.   EDITNBR := COPY(NUMSTRING,Z+1,Y);
  170.  
  171. END;
  172. {================================================================}
  173. {               STRING TO REAL NUMBER PROCEDURE                  }
  174. {================================================================}
  175. PROCEDURE STRINGTOREAL(VAR SOURCE:STRING60;VAR NUMB:REAL;VAR CODE:INTEGER);
  176. VAR
  177.   W  :  INTEGER;
  178.   CONDITION  :  BOOLEAN;
  179. BEGIN
  180.   W := 1;
  181.   NUMB := 0;
  182.   CONDITION := TRUE;
  183.   TIDE(SOURCE); { ELIMINATE PUNCTUATION }
  184.   REPEAT  { UNTIL CONDITION = FALSE }
  185.     IF SOURCE[W] = ' ' THEN DELETE(SOURCE,1,1)
  186.     ELSE CONDITION := FALSE;
  187.     IF LENGTH(SOURCE) = 0 THEN
  188.       BEGIN
  189.         SOURCE := '0';
  190.         CONDITION := FALSE;
  191.       END;
  192.   UNTIL CONDITION = FALSE;
  193.   IF LENGTH(SOURCE) = 1 THEN CONDITION := TRUE;
  194.   WHILE CONDITION = FALSE DO
  195.     BEGIN
  196.       IF SOURCE[W] = ' ' THEN
  197.         BEGIN
  198.           CONDITION := TRUE;
  199.           W := W-2;
  200.         END;
  201.       IF LENGTH(SOURCE) = W THEN
  202.         BEGIN
  203.           CONDITION := TRUE;
  204.           W := W-1;
  205.         END;
  206.       W := W + 1;
  207.     END;
  208.   SOURCE := COPY(SOURCE,1,W);
  209.   VAL( SOURCE,NUMB,CODE );
  210. END;
  211. {================================================================}
  212. {           CALCULATE DISKRECORD & PRECBYTE PROCEDURE            }
  213. {================================================================}
  214. PROCEDURE CALCULATE;
  215.   BEGIN
  216.     DISKRECORD := TRUNC((DATARECORD-1)/BLOCKINGFACTOR)*2+7;
  217.     PRECBYTE := ((DATARECORD-1) MOD BLOCKINGFACTOR)*RCDLEN;
  218.   END;
  219. {================================================================}
  220. {                   GET DATA RECORD PROCEDURE                    }
  221. {================================================================}
  222. PROCEDURE GETDATAREC;
  223.   BEGIN
  224.     CALCULATE;
  225.     IF DISKRECORD <> DISKRECNOWINMEM THEN
  226.       BEGIN
  227.         IF FILERECCHGD = TRUE THEN
  228.           BEGIN
  229.             IF DISKRECNOWINMEM > NBRDISKRECUSED THEN
  230.               BEGIN                 { GET NEXT AVAILABLE RECORD }
  231.                 SEEK(SOURCE,NBRDISKRECUSED+2);
  232.                 NBRDISKRECUSED := DISKRECNOWINMEM;
  233.               END
  234.             ELSE
  235.               BEGIN
  236.                 SEEK(SOURCE,DISKRECNOWINMEM);
  237.               END;
  238.             BLOCKWRITE(SOURCE,GETDATA,2);  {SAVE CHANGED DATA}
  239.             FILERECCHGD := FALSE;
  240.           END;
  241.         IF DISKRECORD <= NBRDISKRECUSED THEN
  242.           BEGIN
  243.             SEEK(SOURCE,DISKRECORD);
  244.             BLOCKREAD(SOURCE,GETDATA,2);         {  RECORD DATA  }
  245.           END
  246.         ELSE FILLCHAR(GETDATA[1],256,' '); {SPACES FOR EMPTY REC }
  247.         DISKRECNOWINMEM := DISKRECORD;
  248.       END;
  249.   END;
  250. {================================================================}
  251. {     CALCULATE DESTINATION DISKRECORD & PRECBYTE PROCEDURE      }
  252. {================================================================}
  253. PROCEDURE CALCULATE2;
  254.   BEGIN
  255.     DISKRECORD2 := TRUNC((DATARECORD2-1)/BLOCKINGFACTOR)*2+7;
  256.     PRECBYTE2 := ((DATARECORD2-1) MOD BLOCKINGFACTOR)*RCDLEN;
  257.   END;
  258. {================================================================}
  259. {            GET DESTINATION DATA RECORD PROCEDURE               }
  260. {================================================================}
  261. PROCEDURE GETDATAREC2;
  262.   BEGIN
  263.     CALCULATE2;
  264.     IF DISKRECORD2 <> DISKRECNOWINMEM2 THEN
  265.       BEGIN
  266.         IF FILERECCHGD2 = TRUE THEN
  267.           BEGIN
  268.             IF DISKRECNOWINMEM2 > NBRDISKRECUSED2 THEN
  269.               BEGIN                 { GET NEXT AVAILABLE RECORD }
  270.                 SEEK(DESTINATION,NBRDISKRECUSED2+2);
  271.                 NBRDISKRECUSED2 := DISKRECNOWINMEM2;
  272.               END
  273.             ELSE
  274.               BEGIN
  275.                 SEEK(DESTINATION,DISKRECNOWINMEM2);
  276.               END;
  277.             BLOCKWRITE(DESTINATION,OUTDATA,2);  {SAVE CHANGED DATA}
  278.             FILERECCHGD2 := FALSE;
  279.           END;
  280.         IF DISKRECORD2 <= NBRDISKRECUSED2 THEN
  281.           BEGIN
  282.             SEEK(DESTINATION,DISKRECORD2);
  283.             BLOCKREAD(DESTINATION,OUTDATA,2);         {  RECORD DATA  }
  284.           END
  285.         ELSE FILLCHAR(OUTDATA[1],256,' '); {SPACES FOR EMPTY REC }
  286.         DISKRECNOWINMEM2 := DISKRECORD2;
  287.       END;
  288.   END;
  289. {================================================================}
  290. {               GET DATA FROM ARRAY PROCEDURE                    }
  291. {================================================================}
  292. PROCEDURE GETDATAFROMARRAY(VAR MESSAGE : STRING60; Z : INTEGER);
  293. VAR W :  INTEGER;
  294. BEGIN
  295.   MESSAGE := '';
  296.   FOR W := PRECBYTE+DATAPOSN[Z] TO PRECBYTE+DATAPOSN[Z+1]-1 DO
  297.     MESSAGE := MESSAGE + GETDATA[W];
  298. END;
  299. {================================================================}
  300. {                      PROCEDURE INP                             }
  301. {================================================================}
  302. PROCEDURE INP;
  303. BEGIN
  304.   WRITELN('BUILD KEY FIELDS FOR SORT');
  305.   WRITELN;
  306.   FOR DATARECORD := 1 TO NBRRECUSED DO
  307.     BEGIN
  308.       CALCULATE;
  309.       GETDATAREC;
  310.       NULLRECORD := TRUE;
  311.       Y := 1;
  312.       WHILE ( Y <= RCDLEN) AND ( NULLRECORD = TRUE) DO
  313.         BEGIN
  314.           IF GETDATA[PRECBYTE+Y] <> ' ' THEN NULLRECORD := FALSE;
  315.           Y := Y+1;
  316.         END;
  317.       IF NULLRECORD = TRUE THEN NBRRECUSED := NBRRECUSED -1
  318.       ELSE
  319.         BEGIN                {  BUILD KEY FIELD FOR SORT  }
  320.           THISKEY := '';
  321.           FOR Z := 1 TO KEYFIELD[0] DO
  322.             BEGIN
  323.               GETDATAFROMARRAY(ANS,KEYFIELD[Z]);
  324.               THISKEY := THISKEY + ANS;
  325.             END;
  326.           STR(DATARECORD:5,ANS);
  327.           IF LENGTH(THISKEY)>55 THEN
  328.             THISKEY := COPY(THISKEY,1,55);
  329.           THISKEY := THISKEY + ANS ;
  330.           WRITELN(THISKEY,'  ');
  331.          SORTRELEASE(THISKEY);
  332.        END;
  333.     END;
  334.   WRITELN;
  335.   WRITELN;
  336.   WRITELN('DATA INPUT COMPLETED');
  337.   WRITELN;
  338.   WRITELN;
  339.   WRITELN('..oO[  SORTING  ]Oo..');
  340.   WRITELN;
  341. END;
  342. {================================================================}
  343. {                       FUNCTION LESS                            }
  344. {================================================================}
  345. FUNCTION LESS;
  346. VAR
  347.   FIRSTSTRING  :  STRING60 ABSOLUTE X;
  348.   SECONDSTRING :  STRING60 ABSOLUTE Y;
  349. BEGIN
  350.   LESS := FIRSTSTRING < SECONDSTRING;
  351. END;
  352. {================================================================}
  353. {                       PROCEDURE OUTP                           }
  354. {================================================================}
  355. PROCEDURE OUTP;
  356. BEGIN
  357. WRITELN;
  358. WRITELN('..oO[  KEY SORT DONE  ]Oo..');
  359. WRITELN;
  360. WRITELN;
  361. WRITELN('..oO[  MOVING RECORDS  ]Oo..');
  362. WRITELN;
  363. WRITELN;
  364.   FOR DATARECORD2 := 1 TO NBRRECUSED DO
  365.     BEGIN
  366.       SORTRETURN(THISKEY);
  367.       ANS := COPY(THISKEY,KEYLENGTH-4,5);
  368.       FOR W := 1 TO 5  DO
  369.         IF ANS[W] =' ' THEN ANS[W] := '0';
  370.       VAL(ANS,DATARECORD,CODE);
  371.       GETDATAREC;  { GET SOURCE RECORD }
  372.       GETDATAREC2; { GET DESTINATION RECORD }
  373.       FOR W := 1 TO RCDLEN DO
  374.         OUTDATA[PRECBYTE2+W] := GETDATA[PRECBYTE+W];
  375.       FILERECCHGD2 := TRUE;
  376.       GOTOXY(1,23);
  377.       WRITE('   RECORD ',DATARECORD2,' OF ',NBRRECUSED,' MOVED.');
  378.     END;
  379.     GOTOXY(1,23);
  380.     CLREOL;
  381.     WRITELN;
  382.   IF FILERECCHGD2 = TRUE THEN
  383.     BEGIN                            { WRITE LAST CHANGED RECORD }
  384.       SEEK(DESTINATION,DISKRECNOWINMEM2);
  385.       BLOCKWRITE(DESTINATION,OUTDATA,2)
  386.     END;
  387.   WRITELN;
  388.   WRITELN('..oO[  RECORDS MOVED  ]Oo..');
  389.   WRITELN;
  390.   WRITELN;
  391. END;
  392. {================================================================}
  393. {                 PRINT LABEL AND FIELD NUMBER                   }
  394. {================================================================}
  395. PROCEDURE PRINTLABFLDNBR( Z: INTEGER);
  396. VAR
  397.   W      :  INTEGER;
  398. BEGIN
  399.   IF ROW[Z] <22 THEN
  400.     BEGIN
  401.       GOTOXY(COLUMN[Z],ROW[Z]);
  402.       FOR W := LABELPOSN[Z] TO LABELPOSN[Z+1]-1 DO
  403.       WRITE (LBL[W]);
  404.       WRITE('= ',Z);
  405.     END;
  406. END;
  407. {================================================================}
  408. {                      PRINT LABEL                               }
  409. {================================================================}
  410. PROCEDURE PRINTLABEL( Z: INTEGER);
  411. VAR
  412.   W      :  INTEGER;
  413. BEGIN
  414.   WRITE(Z,' : ');
  415.   FOR W := LABELPOSN[Z] TO LABELPOSN[Z+1]-1 DO
  416.   WRITE (LBL[W]);
  417.   WRITELN;
  418. END;
  419. {================================================================}
  420. {                 DISPLAY ONE RECORD PROCEDURE                   }
  421. {================================================================}
  422. PROCEDURE DISPLAYREC;
  423. BEGIN
  424.   CLRSCR;
  425.   FOR Z := 1 TO FIELDPERRECORD DO
  426.   PRINTLABFLDNBR(Z);
  427.   GOTOXY(70,23);
  428.   WRITE('RECORD ',DATARECORD);
  429.   LASTRECUSED := DATARECORD;
  430. END;
  431. {===============================================================}
  432. {                       FUNCTION EXIST                          }
  433. {===============================================================}
  434. FUNCTION EXIST(FILENAME : NAMESTR) : BOOLEAN;
  435. VAR
  436.   FIL :  FILE;
  437. BEGIN
  438.   ASSIGN(FIL,FILENAME);
  439.   {$I-}
  440.   RESET(FIL);
  441.   {$I+}
  442.   EXIST := (IORESULT = 0)
  443. END;
  444. {================================================================}
  445. {           FUNCTION GET NUMBER IN GETDATA FIELD ( Z )           }
  446. {================================================================}
  447. FUNCTION FNBRINFLD(Z : INTEGER) : REAL;
  448. VAR
  449.   REALVAL : REAL;
  450.   BEGIN
  451.     GETDATAFROMARRAY(ANS,Z);
  452.     IF DATAFORM[Z] <> ASCII THEN
  453.       STRINGTOREAL(ANS,REALVAL,CODE)
  454.     ELSE REALVAL := 0;
  455.     FNBRINFLD := REALVAL;
  456.   END;
  457. {$ISORTER1.PAS}
  458.