home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol085 / removecc.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1984-04-29  |  10.0 KB  |  414 lines

  1. PROGRAM removecc;
  2.  
  3. { Program to read a disk file   }
  4. { and remove any control characters or change them to }
  5. { a sequence of printable characters.   }
  6. { Also finds any high-bit-set characters,  }
  7. { strips the high bit and optionally prefixes the char }
  8. { with an escape character. }
  9.  
  10. {Assume the escape char for control chars is chosen to  }
  11. {be "%".  Then this table shows how control codes are   }
  12. {represented in the output file.  }
  13.  
  14. {  binary char value (ORD)    representation
  15.   -------------------------   --------------
  16.     0  NUL  %@
  17.     1  SOH  %A
  18.     2  STX  %B
  19.     .        .
  20.     .        .
  21.     .        .
  22.    25  EM   %Y
  23.    26  SUB  %Z
  24.    27  ESC  %[
  25.    28  FS   %\
  26.    29  GS   %]
  27.    30  RS   %^
  28.    31  US   %_
  29.    92  %    %%       ***** note this special representation!
  30.   127  DEL  %?       ***** note this special representation!
  31.  }
  32.  
  33.  
  34.  
  35. CONST
  36.    version = '1.1';
  37.    sector_size = 128;   {#bytes in a sector}
  38.  
  39.    carriage_return = 13; {^M}
  40.    line_feed  = 10;      {^J}
  41.    eof_char  = 26;       {^Z}
  42.  
  43. TYPE
  44.    byte = 0..255;
  45.    sector_array = PACKED ARRAY [1..sector_size] OF byte;
  46.    sector_file  = FILE OF sector_array;
  47.  
  48.    outch_array = PACKED ARRAY [1..3] OF byte;
  49.    char12 = PACKED ARRAY [1..12] OF CHAR;
  50. VAR
  51.    infile   :sector_file;
  52.    infilename   :char12;
  53.  
  54.    outfile   :sector_file;
  55.    outfilename   :char12;
  56.  
  57.    list_flag   :BOOLEAN;    {list output}
  58.  
  59.  
  60.    s_recno     :INTEGER;
  61.    in_buffer   :sector_array;
  62.    in_bufptr   :INTEGER;
  63.  
  64.    out_buffer   :sector_array;
  65.    out_bufptr   :INTEGER;
  66.  
  67.    ctr_highbit   :INTEGER;
  68.    ctr_cc        :INTEGER;
  69.  
  70.    esc_highbit_char   :byte;  {escape char for highbit chars}
  71.    esc_control_char   :byte;  {escape char for control chars}
  72.  
  73.    status   :INTEGER;
  74.  
  75. {----------------------------------------------------------}
  76. {----------------------------------------------------------}
  77.  
  78. PROCEDURE ask_escape_chars;
  79.  
  80. VAR
  81.    flag   :BOOLEAN;
  82.    response   :CHAR;
  83.  
  84. BEGIN
  85.    flag := TRUE;
  86.    WHILE flag DO BEGIN
  87.       WRITE ('Enter the control-chars escape character: ');
  88.       READLN (response);
  89.       IF response=' ' THEN BEGIN
  90.          WRITELN ('No escape char; control codes remain as is.');
  91.          esc_control_char := 0;
  92.          flag := FALSE;
  93.          END
  94.       ELSE IF response IN ['!', '#', '$', '%', '&', '*',
  95.                            '|', '~', '`', '''', '{', '}',
  96.                            '=', '"', '<', '>', '/']
  97.          THEN BEGIN
  98.              flag := FALSE;
  99.              esc_control_char := ORD (response);
  100.          END
  101.       ELSE BEGIN
  102.             WRITELN('*** Not an acceptable character. Try again.');
  103.       END{IF};
  104.    END{WHILE};
  105.  
  106.    flag := TRUE;
  107.    WHILE flag DO BEGIN
  108.       WRITE ('Enter the highbit-chars escape character: ');
  109.       READLN (response);
  110.       IF response=' ' THEN BEGIN
  111.          WRITELN ('No escape char; high bits will be stripped.');
  112.          esc_highbit_char := 0;
  113.          flag := FALSE;
  114.          END
  115.       ELSE IF response IN ['!', '#', '$', '%', '&', '*',
  116.                            '|', '~', '`', '''', '{', '}',
  117.                            '=', '"', '<', '>', '/']  THEN BEGIN
  118.           flag := FALSE;
  119.           esc_highbit_char := ORD (response);
  120.           END
  121.       ELSE BEGIN
  122.             WRITELN('*** Not an acceptable character. Try again.');
  123.       END{IF};
  124.       IF (esc_highbit_char>0) AND
  125.             (esc_control_char = esc_highbit_char) THEN BEGIN
  126.          WRITELN ('*** Cannot be the same as the control escape char.');
  127.          WRITELN ('    Try again. ');
  128.          flag := TRUE;
  129.       END{IF};
  130.    END{WHILE};
  131. END{PROCEDURE};
  132.  
  133.  
  134. {--------------------------------------------------}
  135.  
  136. { Translates the char in in_char into a 1 to 3 byte}
  137. { sequence stored in out_chars.  Sets nchars to the}
  138. { # of chars. }
  139.  
  140. PROCEDURE xlate_char ( in_char :byte;
  141.                    VAR out_chars :outch_array;
  142.                    VAR nchars :INTEGER );
  143.  
  144. BEGIN{PROCEDURE}
  145.    nchars := 0;
  146.    IF in_char > 127 THEN BEGIN
  147.       {Handle high-bit chars}
  148.       in_char := in_char - 128;
  149.       ctr_highbit := ctr_highbit + 1;
  150.       IF esc_highbit_char > 0  THEN BEGIN
  151.          nchars := nchars + 1;
  152.          out_chars[nchars] := esc_highbit_char;
  153.       END{IF};
  154.    END{IF};
  155.  
  156.    IF (in_char>31) AND (in_char<127) THEN BEGIN
  157.       {Handle "ordinary" characters. }
  158.       nchars := nchars + 1;
  159.       out_chars[nchars] := in_char;
  160.       IF (in_char=esc_control_char) OR 
  161.          (in_char=esc_highbit_char)
  162.       THEN BEGIN
  163.          nchars := nchars + 1;
  164.          out_chars[nchars] := in_char;
  165.       END{IF};
  166.      END
  167.    ELSE IF (in_char=carriage_return) OR
  168.            (in_char=line_feed) THEN BEGIN
  169.          nchars := nchars + 1;
  170.          out_chars[nchars] := in_char; 
  171.       END
  172.    ELSE IF (in_char<=31) OR (in_char=127) THEN BEGIN
  173.       { Handle control chars. }
  174.       { We have already excluded CR and LF}
  175.       ctr_cc := ctr_cc + 1;
  176.       IF esc_control_char=0 THEN BEGIN
  177.          nchars := nchars + 1;
  178.          out_chars[nchars] := in_char;
  179.          END
  180.       ELSE BEGIN
  181.          nchars := nchars + 1;
  182.          out_chars[nchars] := esc_control_char;
  183.          nchars := nchars + 1;
  184.          out_chars[nchars] := in_char + ORD('@');
  185.          IF in_char=127  THEN out_chars[nchars] := ORD('?');
  186.       END{IF};
  187.    END{IF};
  188. END{PROCEDURE};
  189.  
  190.  
  191. {-------------------------------------------------------------}
  192.  
  193. FUNCTION open_infile  :INTEGER;
  194.  
  195. BEGIN{FUNCTION}
  196.    WRITE('Enter the input filename: ');
  197.    infilename := '            ';
  198.    READLN(infilename);
  199.  
  200.    RESET(infilename,infile);
  201.  
  202.    in_bufptr := sector_size + 1;
  203.  
  204.    open_infile := 0;
  205.    IF EOF(infile) THEN open_infile := -1;
  206.  
  207. END{FUNCTION};
  208.  
  209. {-------------------------------------------------------------}
  210.  
  211. FUNCTION open_outfile   :INTEGER;
  212.  
  213. BEGIN{FUNCTION}
  214.    WRITE('Enter the output filename: ');
  215.    outfilename := '            ';
  216.    READLN (outfilename);
  217.  
  218.    REWRITE (outfilename,outfile);
  219.  
  220.    out_bufptr := 0;
  221.  
  222.    open_outfile := 0;
  223. END{FUNCTION};
  224.  
  225. {--------------------------------------------------------}
  226. {Reads the next sector from the input file. }
  227. {Returns 0 = normal;  -1 = error or EOF. }
  228.  
  229. FUNCTION read_infile  :INTEGER;
  230.  
  231. BEGIN{FUNCTION}
  232.    IF EOF(infile) THEN BEGIN
  233.       read_infile := -1;
  234.       in_bufptr := sector_size + 1;
  235.       END
  236.    ELSE BEGIN
  237.       READ (infile, in_buffer);
  238.       in_bufptr := 0;
  239.       read_infile := 0;
  240.    END{IF};
  241. END{FUNCTION};
  242.  
  243. {--------------------------------------------------------}
  244. {Writes the next sector into the output file. }
  245. {Returns 0 = normal,  <0 if error. }
  246.  
  247. FUNCTION write_outfile    :INTEGER;
  248.  
  249. BEGIN{FUNCTION}
  250.    WRITE(outfile, out_buffer);
  251.    out_bufptr := 0;
  252.    write_outfile := 0;
  253. END{FUNCTION};
  254.   
  255.  
  256. {--------------------------------------------------------}
  257.  
  258. FUNCTION close_infile  :INTEGER;
  259.  
  260. BEGIN{FUNCTION}
  261.    close_infile := 0;
  262. END{FUNCTION};
  263.  
  264.  
  265. {--------------------------------------------------------}
  266.  
  267. FUNCTION close_outfile  :INTEGER;
  268. BEGIN{FUNCTION}
  269.    close_outfile := 0;
  270. END{FUNCTION};
  271.  
  272.  
  273. {--------------------------------------------------------}
  274. {Gets the next char (pseudochar, a byte) from the input buffer.}
  275. {Signals EOF by returning -1.  Returns 0 if get a char. }
  276.  
  277.  
  278. FUNCTION get_char ( VAR in_char :byte )  :INTEGER; 
  279.  
  280. VAR
  281.    status   :INTEGER;
  282.  
  283. BEGIN{FUNCTION}
  284.    status := 0;
  285.    IF in_bufptr >= sector_size THEN BEGIN
  286.       status := read_infile;
  287.    END{IF};
  288.  
  289.    IF status = 0 THEN BEGIN
  290.       in_bufptr := in_bufptr + 1;
  291.       in_char := in_buffer[in_bufptr];
  292.       IF in_char = eof_char THEN status := -1;
  293.    END{IF};
  294.  
  295.    get_char := status;
  296. END{FUNCTION};
  297.  
  298. {--------------------------------------------------------}
  299.  
  300. FUNCTION put_char (out_char :byte)  :INTEGER;
  301.  
  302. VAR
  303.    status   :INTEGER;
  304.  
  305. BEGIN
  306.    status := 0;
  307.  
  308.    out_bufptr := out_bufptr + 1;
  309.    out_buffer[out_bufptr] := out_char;
  310.    
  311.    IF out_bufptr >= sector_size THEN BEGIN
  312.       status := write_outfile;
  313.    END{IF};
  314.  
  315.    put_char := status;
  316. END{FUNCTION};
  317.  
  318.  
  319. {--------------------------------------------------------}
  320. {Purge the last buffer load to the output file.}
  321.  
  322. PROCEDURE put_purge;
  323.  
  324. VAR
  325.    i       :INTEGER;
  326.    remaining   :INTEGER;
  327.    status   :INTEGER;
  328.  
  329. BEGIN{PROCEDURE}
  330.    remaining := sector_size - out_bufptr;
  331.    FOR i:= 1 TO remaining DO BEGIN
  332.       status := put_char (eof_char);
  333.    END{FOR};
  334. END{PROCEDURE};
  335.  
  336.  
  337. {--------------------------------------------------------}
  338.  
  339. PROCEDURE pause;
  340.  
  341. VAR
  342.    response   :CHAR; 
  343.  
  344. BEGIN{PROCEDURE}
  345.    WRITELN('enter CR to continue');
  346.    READLN(response);
  347. END{PROCEDURE};
  348.  
  349. {--------------------------------------------------}
  350. FUNCTION copy_file  :INTEGER;
  351.  
  352. VAR
  353.    status   :INTEGER;
  354.    i        :INTEGER;
  355.    in_char  :byte;
  356.    out_chars   :outch_array;
  357.    nchars   :INTEGER;
  358.  
  359. BEGIN{FUNCTION}
  360.    status := 0;
  361.    WHILE status = 0  DO BEGIN
  362.       status := get_char (in_char);
  363.       IF status <> 0 THEN BEGIN
  364.          put_purge;
  365.         END
  366.       ELSE BEGIN
  367.          xlate_char (in_char, out_chars, nchars);
  368.          FOR i := 1 TO nchars DO BEGIN
  369.             IF status = 0 THEN status := put_char (out_chars[i]);
  370.          END{FOR};
  371.       END{IF};
  372.    END{WHILE};
  373.    copy_file := status;
  374. END{FUNCTION};
  375.  
  376.  
  377. {--------------------------------------------------}
  378. {--------------------------------------------------}
  379.  
  380. BEGIN{PROGRAM}
  381.    WRITELN ('RemoveCC  Version ',version);
  382.  
  383.    ctr_cc := 0;
  384.    ctr_highbit := 0;
  385.  
  386.    status := open_infile; 
  387.    IF status <> 0 THEN BEGIN
  388.       WRITELN('Could not open file ', infilename);
  389.    END{IF};
  390.  
  391.    IF status = 0 THEN BEGIN
  392.       status := open_outfile;
  393.       IF status <> 0 THEN BEGIN
  394.          WRITELN('Could not open output file ',outfilename);
  395.       END{IF};
  396.    END{IF};
  397.  
  398.    IF status=0 THEN BEGIN
  399.       ask_escape_chars;
  400.    END{IF};
  401.  
  402.  
  403.    IF status = 0 THEN BEGIN
  404.       status := copy_file;
  405.    END{IF};
  406.  
  407.    WRITELN(ctr_cc, ' control chars.  ',
  408.            ctr_highbit, ' high-bit chars.');
  409.  
  410.    status := close_input;
  411.    status := close_output;
  412.  
  413. END{PROGRAM}.
  414.