home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol063 / fcount.pas < prev    next >
Pascal/Delphi Source File  |  1985-02-09  |  10KB  |  450 lines

  1. PROGRAM fcount;
  2.  
  3.  {Program to read a disk file }
  4.  {and count the number of chars and lines. }
  5.  {Program will also allow splitting a long file }
  6.  {into several pieces. }
  7.  
  8.  
  9. CONST
  10.    version = '1.0';
  11.    sector_size = 128;   {#bytes in a sector}
  12.  
  13.    carriage_return = 13; {^M}
  14.    line_feed  = 10;      {^J}
  15.    eof_char  = 26;       {^Z}
  16.  
  17. TYPE
  18.    byte = 0..255;
  19.    sector_array = PACKED ARRAY [1..sector_size] OF byte;
  20.    sector_file  = FILE OF sector_array;
  21.  
  22.    ctr_array  = PACKED ARRAY [1..2] OF INTEGER;  {1=units, 2=thousands}
  23.  
  24.    outch_array = PACKED ARRAY [1..3] OF byte;
  25.    char12 = PACKED ARRAY [1..12] OF CHAR;
  26.  
  27. VAR
  28.    infile   :sector_file;
  29.    infilename   :char12;
  30.  
  31.    outf_flag   :BOOLEAN;  {true if outfile present}
  32.    outfile   :sector_file;
  33.    outfilename   :char12;
  34.  
  35.    list_flag   :BOOLEAN;    {list output}
  36.  
  37.  
  38.    in_buffer   :sector_array;
  39.    in_bufptr   :INTEGER;
  40.  
  41.    out_buffer   :sector_array;
  42.    out_bufptr   :INTEGER;
  43.  
  44.    char_ctr   :ctr_array;
  45.    line_ctr   :ctr_array;
  46.    line_mod_ctr   :ctr_array;
  47.    line_thousands_limit  :INTEGER;
  48.  
  49.  
  50.    status   :INTEGER;
  51.    i        :INTEGER;
  52.  
  53. {----------------------------------------------------------}
  54. {----------------------------------------------------------}
  55. { Increment a symbolic name.  Eg  XXX021 to XXX022. }
  56.  
  57. PROCEDURE incr_name (VAR name :char12);
  58.  
  59. VAR
  60.    i    :INTEGER;
  61.    col   :INTEGER;
  62.    flag   :BOOLEAN;
  63.  
  64. BEGIN{PROCEDURE}
  65.    col := 12;
  66.    WHILE (col>=1) AND (name[col]=' ') DO  col := col - 1;
  67.  
  68.    flag := TRUE;
  69.    WHILE flag AND (col>=1) DO BEGIN
  70.       i := ORD (name[col]) + 1;
  71.       IF i <= ORD('9') THEN BEGIN
  72.          flag := FALSE;
  73.          name[col] := CHR(i);
  74.         END
  75.       ELSE  BEGIN
  76.          name[col] := '0';
  77.          col := col - 1;
  78.       END{IF};
  79.    END{WHILE};
  80. END{PROCEDURE};
  81.  
  82.  
  83. {--------------------------------------------------}
  84. {Reset a big-counter to zero } 
  85.  
  86. PROCEDURE ctr_reset (VAR ctr :ctr_array);
  87.  
  88. BEGIN{PROCEDURE}
  89.    ctr[1] := 0;
  90.    ctr[2] := 0;
  91. END{PROCEDURE};
  92.  
  93. {--------------------------------------------------}
  94. {Increments a big-counter. }
  95.  
  96. PROCEDURE ctr_count  (VAR ctr :ctr_array);
  97.  
  98. BEGIN{PROCEDURE}
  99.    ctr[1] := ctr[1] + 1;
  100.    IF ctr[1] >= 1000 THEN BEGIN
  101.       ctr[2] := ctr[2] + 1;
  102.       ctr[1] := 0;
  103.    END{IF};
  104. END{PROCEDURE};
  105.  
  106.  
  107. {-------------------------------------------------------------}
  108. {Test a counter against another counter}
  109. {Returns TRUE if counter A is bigger than counter B}
  110.  
  111. FUNCTION ctr_gtr (ctra :ctr_array;
  112.                   ctrb :ctr_array )
  113.                  : BOOLEAN;
  114. BEGIN{FUNCTION} 
  115.    ctr_gtr := FALSE;
  116.  
  117.    IF ctra[2] > ctrb[2] THEN ctr_gtr := TRUE;
  118.  
  119.    IF ctra[2] = ctrb[2] THEN ctr_gtr :=  ctra[1] > ctrb[1];
  120. END{FUNCTION};
  121.  
  122.  
  123. {-------------------------------------------------------------}
  124. {Print a big-counter }
  125.  
  126. PROCEDURE ctr_print (ctr :ctr_array);
  127.  
  128. BEGIN{PROCEDURE}
  129.    WRITE (ctr[2], ',' ,  ctr[1]:3 );
  130. END{PROCEDURE};
  131.  
  132.  
  133. {-------------------------------------------------------------}
  134. PROCEDURE get_outfilename;
  135.  
  136. BEGIN{PROCEDURE}
  137.    WRITE('Enter the output filename: ');
  138.    outfilename := '            ';
  139.    READLN (outfilename);
  140.  
  141.    outf_flag := TRUE;
  142.    IF outfilename = '            '  THEN outf_flag := FALSE;
  143.  
  144. END{PROCEDURE};
  145.  
  146. {-------------------------------------------------------------}
  147. PROCEDURE get_infilename;
  148.  
  149. BEGIN{PROCEDURE}
  150.    WRITE('Enter the input filename: ');
  151.    infilename := '            ';
  152.    READLN (infilename);
  153. END{PROCEDURE};
  154.  
  155. {------------------------------------------------------------}
  156. FUNCTION get_limit  :INTEGER; 
  157.  
  158. VAR 
  159.    result   :INTEGER;
  160.  
  161. BEGIN{FUNCTION}
  162.    READLN (result);
  163.    IF result=0 THEN result := MAXINT-1;
  164.    get_limit := result;
  165. END{FUNCTION};
  166.  
  167.  
  168. {------------------------------------------------------------}
  169.  
  170. FUNCTION open_infile  :INTEGER;
  171.  
  172. VAR
  173.    result   :INTEGER; 
  174.  
  175. BEGIN{FUNCTION}
  176.    RESET(infilename,infile);
  177.  
  178.    in_bufptr := sector_size + 1;
  179.  
  180.    result := 0;
  181.    IF EOF(infile) THEN result := -1;
  182.  
  183.    WRITELN('Open input file: ',infilename:12,
  184.            '   result=', result );
  185.  
  186.    open_infile := result;
  187.  
  188. END{FUNCTION};
  189.  
  190. {-------------------------------------------------------------}
  191.  
  192. FUNCTION open_outfile   :INTEGER;
  193.  
  194. VAR
  195.    result   :INTEGER;
  196.  
  197. BEGIN{FUNCTION}
  198.    REWRITE (outfilename, outfile);
  199.  
  200.    out_bufptr := 0;
  201.  
  202.    result := 0;
  203.  
  204.    WRITELN('Open output file: ', outfilename,
  205.            '   result=', result );
  206.  
  207. END{FUNCTION};
  208.  
  209. {--------------------------------------------------------}
  210. {Opens the next output file in sequence.}
  211. {Returns 0 if no error, <0 if error. }
  212.  
  213. FUNCTION open_next_outfile  :INTEGER;
  214.  
  215. VAR
  216.    result   :INTEGER;
  217.  
  218. BEGIN{FUNCTION}
  219.    incr_name (outfilename);
  220.  
  221.    result := open_outfile;
  222.    
  223.    open_next_outfile := result;
  224. END{FUNCTION};
  225.  
  226.  
  227. {--------------------------------------------------------}
  228. {Reads the next sector from the input file. }
  229. {Returns 0 = normal;  -1 = error or EOF. }
  230.  
  231. FUNCTION read_infile  :INTEGER;
  232.  
  233. BEGIN{FUNCTION}
  234.    IF EOF(infile) THEN BEGIN
  235.       read_infile := -1;
  236.       in_bufptr := sector_size + 1;
  237.       END
  238.    ELSE BEGIN
  239.       READ (infile, in_buffer);
  240.       in_bufptr := 0;
  241.       read_infile := 0;
  242.    END{IF};
  243. END{FUNCTION};
  244.  
  245. {--------------------------------------------------------}
  246. {Writes the next sector into the output file. }
  247. {Returns 0 = normal,  <0 if error. }
  248.  
  249. FUNCTION write_outfile    :INTEGER;
  250.  
  251. BEGIN{FUNCTION}
  252.    WRITE(outfile, out_buffer);
  253.    out_bufptr := 0;
  254.    write_outfile := 0;
  255. END{FUNCTION};
  256.   
  257.  
  258. {--------------------------------------------------------}
  259.  
  260. FUNCTION close_infile  :INTEGER;
  261.  
  262. BEGIN{FUNCTION}
  263.    close_infile := 0;
  264. END{FUNCTION};
  265.  
  266.  
  267. {--------------------------------------------------------}
  268.  
  269. FUNCTION close_outfile  :INTEGER;
  270. BEGIN{FUNCTION}
  271.    close_outfile := 0;
  272. END{FUNCTION};
  273.  
  274.  
  275. {--------------------------------------------------------}
  276. {Gets the next char (pseudochar, a byte) from the input buffer.}
  277. {Signals EOF by returning -1.  Returns 0 if get a char. }
  278.  
  279.  
  280. FUNCTION get_char ( VAR in_char :byte )  :INTEGER; 
  281.  
  282. VAR
  283.    status   :INTEGER;
  284.  
  285. BEGIN{FUNCTION}
  286.    status := 0;
  287.    IF in_bufptr >= sector_size THEN BEGIN
  288.       status := read_infile;
  289.    END{IF};
  290.  
  291.    IF status = 0 THEN BEGIN
  292.       in_bufptr := in_bufptr + 1;
  293.       in_char := in_buffer[in_bufptr];
  294.       IF in_char = eof_char THEN status := -1;
  295.    END{IF};
  296.  
  297.    get_char := status;
  298. END{FUNCTION};
  299.  
  300. {--------------------------------------------------------}
  301.  
  302. FUNCTION put_char (out_char :byte)  :INTEGER;
  303.  
  304. VAR
  305.    status   :INTEGER;
  306.  
  307. BEGIN
  308.    status := 0;
  309.  
  310.    out_bufptr := out_bufptr + 1;
  311.    out_buffer[out_bufptr] := out_char;
  312.    
  313.    IF out_bufptr >= sector_size THEN BEGIN
  314.       status := write_outfile;
  315.    END{IF};
  316.  
  317.    put_char := status;
  318. END{FUNCTION};
  319.  
  320.  
  321. {--------------------------------------------------------}
  322. {Purge any chars still remaining in the output buffer}
  323.  
  324. PROCEDURE put_purge;
  325.  
  326. VAR
  327.    i       :INTEGER;
  328.    remaining   :INTEGER;
  329.    status   :INTEGER;
  330.  
  331. BEGIN{PROCEDURE}
  332.    status := put_char (eof_char);  {ensure at least 1 EOL}
  333.    remaining := sector_size - out_bufptr;
  334.    FOR i:= 1 TO remaining DO BEGIN
  335.       status := put_char (eof_char);
  336.    END{FOR};
  337. END{PROCEDURE};
  338.  
  339.  
  340. {--------------------------------------------------------}
  341.  
  342. PROCEDURE putout_char (in_char :byte);
  343.  
  344. VAR
  345.    result   :INTEGER;
  346.  
  347. BEGIN{PROCEDURE}
  348.    IF outf_flag THEN BEGIN
  349.       result := put_char (in_char);
  350.       IF line_mod_ctr[2] > line_thousands_limit THEN BEGIN
  351.          put_purge;
  352.          result := open_next_outfile;
  353.          ctr_reset (line_mod_ctr);
  354.       END{IF};
  355.    END{IF};
  356. END{PROCEDURE};
  357.  
  358. {----------------------------------------------------}
  359.  
  360. PROCEDURE count_char (in_char :byte);
  361.  
  362. BEGIN{PROCEDURE}
  363.    ctr_count (char_ctr);
  364.  
  365.    IF in_char = carriage_return THEN BEGIN
  366.       ctr_count (line_ctr);
  367.       ctr_count (line_mod_ctr);
  368.    END{IF};
  369. END{PROCEDURE};
  370.  
  371.  
  372. {--------------------------------------------------}
  373.  
  374. FUNCTION count_file   :INTEGER;
  375.  
  376. VAR
  377.    i        :INTEGER;
  378.    status   :INTEGER;
  379.    in_char  :byte;
  380.    out_chars :outch_array;
  381.    εchars   :INTEGER;
  382.  
  383. BEGIN{FUNCTION}
  384.    status := 0;
  385.    ctr_reset (line_ctr);
  386.    ctr_reset (line_mod_ctr);
  387.    ctr_reset (char_ctr);
  388.  
  389.    WHILE status = 0  DO BEGIN
  390.       status := get_char (in_char);
  391.       IF (status<>0) AND outf_flag THEN BEGIN
  392.          put_purge;
  393.         END
  394.       ELSE BEGIN
  395.          count_char (in_char);
  396.          IF outf_flag THEN putout_char (in_char);
  397.       END{IF};
  398.    END{WHILE};
  399.    count_file := status;
  400. END{FUNCTION};
  401.  
  402.  
  403. {--------------------------------------------}
  404. {--------------------------------------------}
  405.  
  406. BEGIN{PROGRAM}
  407.    WRITELN ('Fcount  Version ', version);
  408.  
  409.    get_infilename;
  410.    status := open_infile;
  411.    IF status<>0 THEN BEGIN
  412.       WRITELN('*** Could not open input file ', infilename);
  413.    END{IF};
  414.  
  415.    IF status=0  THEN BEGIN
  416.       get_outfilename;
  417.       IF outf_flag THEN BEGIN
  418.          status := open_outfile;
  419.          IF status<>0 THEN BEGIN
  420.             WRITELN('*** Could not open ouput file ', outfilename);
  421.          END{IF}; 
  422.       END{IF};
  423.    END{IF};
  424.      
  425.    IF status=0 THEN BEGIN
  426.       WRITE('Enter max #lines per file (in thousands: ');
  427.       line_thousands_limit := get_limit;
  428.       IF line_thousands_limit > 0 THEN BEGIN
  429.          WRITELN('NOTE that filename should be xxxxx.001');
  430.       END{IF};
  431.    END{IF};
  432.  
  433.    IF status=0 THEN BEGIN
  434.       status := count_file;
  435.    END{IF};
  436.  
  437.    ctr_print (line_ctr);
  438.    WRITE (' lines. ');
  439.    ctr_print (char_ctr);
  440.    WRITE (' characters.');
  441.    WRITELN;
  442.  
  443.    status := close_input;
  444.  
  445.    IF outf_flag THEN BEGIN
  446.       status := close_output;
  447.    END{IF};
  448.  
  449. END{PROGRAM}.
  450.