home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / swag / textfile.swg / 0002_HEXDUMP.PAS.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-05-28  |  11.4 KB  |  332 lines

  1. {   In the following message is a Complete Program I just wrote
  2. (including 3 routines from TeeCee's hints) which solves a particular
  3. problem I was having, but also demonstrates some things I see queried
  4. here.  So, there are a number of useful routines in it, as well as a
  5. whole Program which may help.
  6.    This Program dumps a Dos File to Hex and (modified) BCD.  It is
  7. patterned after Vernon Buerg's LIST display (using Alt-H), which I find
  8. useful to look at binary Files.  The problem is (was) I couldn't PrtSc
  9. the screens, due to numerous special Characters which often hung my
  10. Printer.  So, I wrote this Program to "dump" such Files to either the
  11. Printer or a Printer File.  It substitutes an underscore For most
  12. special Characters (you can change this, of course).
  13.    note, too, that it demonstates the use of a C-like Character stream
  14. i/o, which is a Variation of the "stream i/o" which is discussed here.
  15. This allows fast i/o of any Type of File, and could be modified to
  16. provide perFormant i/o For Text Files.
  17.    A number of the internal routines are a bit clumsy, since I had to
  18. (107 min left), (H)elp, More? make them "generic" For this post, rather than make use of after-market
  19. libraries that I use (TTT, in my Case).
  20.    Enjoy!...
  21. }
  22.  
  23. Program Hex_Dump;        { Dump a File in Hex and BCD   930107 }
  24. Uses Crt, Dos, Printer;
  25. {$M 8192,0,8192}
  26.    {  Public Domain, by Mike Copeland and Trevor Carlsen  1993 }
  27. Const VERSION = '1.1';
  28.       BSize   = 32768;                           { Buffer Size }
  29.       ifLinE  = 4;                          { InFormation Line }
  30.       PRLinE  = 24;                              { Prompt Line }
  31.       ERLinE  = 25;                               { Error Line }
  32.       DSLinE  = 22;                             { Display Line }
  33.       PL      = 1;                          { partial line o/p }
  34.       WL      = 2;                            { whole line o/p }
  35.       B40     = '                                        ';
  36. Var   CP      : Word;                      { Character Pointer }
  37.       BLKNO   : Word;                                { Block # }
  38.       L,N     : Word;
  39.       RES     : Word;
  40.       LONG    : LongInt;
  41.       NCP     : LongInt;              { # Characters Processed }
  42.       FSize   : LongInt;                  { Computed File Size }
  43.       BV      : Byte;                  { generic Byte Variable }
  44.       PRtoK   : Boolean;
  45.       PFP     : Boolean;
  46.       REGS    : Registers;
  47.       PRTFile : String;
  48.       F1      : String;
  49.       MSTR,S1 : String;
  50.       PFV1    : Text;
  51.       F       : File;
  52.       B       : Array[0..BSize-1] of Byte;
  53.       CH      : Char;
  54.  
  55. Procedure WPROM (S : String);             { generalized Prompt }
  56. begin
  57.   GotoXY (1,PRLinE); Write (S); ClrEol; GotoXY (Length(S)+1,PRLinE);
  58. end;  { WPROM }
  59.  
  60. Procedure CLEARBOT;                   { clear bottom of screen }
  61. begin
  62.   GotoXY (1,PRLinE); ClrEol; GotoXY (1,ERLinE); ClrEol
  63. end;  { CLEARBOT }
  64.  
  65. Function GETYN : Char;               { get Single-key response }
  66. Var CH : Char;
  67. begin
  68.   CH := UpCase(ReadKey); if CH = #0 then CH := ReadKey;
  69.   CLEARBOT; GETYN := CH;
  70. end;  { GETYN }
  71.  
  72. Procedure PAUSE;              { Generalized Pause processing }
  73. Var CH : Char;
  74. begin
  75.   WPROM ('Press any key to continue...'); CH := GETYN
  76. end;  { PAUSE }
  77.  
  78. Procedure ERRor1 (S : String);       { General Error process }
  79. Var CH : Char;
  80. begin
  81.   GotoXY (1,ERLinE); Write (^G,S); ClrEol; PAUSE
  82. end;  { ERRor1 }
  83.  
  84. Procedure FATAL (S : String);      { Fatal error - Terminate }
  85. begin
  86.   ERRor1 (S); Halt
  87. end;  { FATAL }
  88.  
  89. Function TEStoNLinE : Byte;      { Tests For Printer On Line }
  90. Var  REGS : Registers;
  91. begin
  92.   With REGS do
  93.     begin
  94.       AH := 2; DX := 0;
  95.       Intr($17, Dos.Registers(REGS));
  96.       TEStoNLinE := AH;
  97.     end
  98. end;  { TEStoNLinE }
  99.  
  100. Function SYS_DATE : String;   { Format System Date as YY/MM/DD }
  101. Var S1, S2, S3 : String[2];
  102. begin
  103.   REGS.AX := $2A00;                                 { Function }
  104.   MsDos (Dos.Registers(REGS));             { fetch System Date }
  105.   With REGS do
  106.     begin
  107.       Str((CX mod 100):2,S1); Str(Hi(DX):2,S2); Str(Lo(DX):2,S3);
  108.     end;
  109.   if S2[1] = ' ' then S2[1] := '0';           { fill in blanks }
  110.   if S3[1] = ' ' then S3[1] := '0';
  111.   SYS_DATE := S1+'/'+S2+'/'+S3
  112. end;  { SYS_DATE }
  113.  
  114. Function SYS_TIME : String;               { Format System Time }
  115. Var S1, S2, S3 : String[2];
  116. begin
  117.   REGS.AX := $2C00;                                 { Function }
  118.   MsDos (Dos.Registers(REGS));             { fetch System Time }
  119.   With REGS do
  120.     begin
  121.       Str(Hi(CX):2,S1); Str(Lo(CX):2,S2); Str(Hi(DX):2,S3);
  122.     end;
  123.   if S2[1] = ' ' then S2[1] := '0';           { fill in blanks }
  124.   if S3[1] = ' ' then S3[1] := '0';
  125.   if S1[1] = ' ' then S1[1] := '0';
  126.   SYS_TIME := S1+':'+S2+':'+S3
  127. end;  { SYS_TIME }
  128.  
  129. Function EXISTS ( FN : String): Boolean;  { test File existance }
  130. Var F : SearchRec;
  131. begin
  132.   FindFirst (FN,AnyFile,F); EXISTS := DosError = 0
  133. end;  { EXISTS }
  134.  
  135. Function UPPER (S : String) : String;
  136. Var I : Integer;
  137. begin
  138.   For I := 1 to Length(S) do
  139.     S[I] := UpCase(S[I]);
  140.   UPPER := S;
  141. end;  { UPPER }
  142.  
  143. Procedure SET_File (FN : String);      { File Output For PRinT }
  144. begin
  145.   PRTFile := FN; PFP := False; PRtoK := False;
  146. end;  { SET_File }
  147.  
  148. Procedure PRinT_inIT (S : String);  { Initialize Printer/File Output }
  149. Var X,Y : Word;
  150. begin
  151.   PRtoK := TestOnLine = 144; PFP := False; X := WhereX; Y := WhereY;
  152.   if PRtoK then
  153.     begin
  154.       WPROM ('Printer is Online - do you wish Printer or File? (P/f) ');
  155.  
  156.       if GETYN = 'F' then SET_File (S)
  157.       else
  158.         begin
  159.           WPROM ('Please align Printer'); PAUSE
  160.         end
  161.     end
  162.   else SET_File (S);
  163.   GotoXY (X,Y)                            { restore cursor }
  164. end;  { PRinT_inIT }
  165.  
  166. Function OPENF (Var FV : Text; FN : String; MODE : Char) : Boolean;
  167. Var FLAG  : Boolean;
  168. begin
  169.   FLAG := True;                             { set default }
  170.   Assign (FV, FN);                        { allocate File }
  171.   Case UpCase(MODE) of                        { open mode }
  172.     'W' : begin                                  { output }
  173.             {$I-} ReWrite (FV); {$I+}
  174.           end;
  175.     'R' : begin                                   { input }
  176.             {$I-} Reset (FV); {$I+}
  177.           end;
  178.     'A' : begin                            { input/extend }
  179.             {$I-} Append (FV); {$I+}
  180.           end;
  181.     else
  182.   end; { of Case }
  183.   if Ioresult <> 0 then          { test For error on OPEN }
  184.     begin
  185.       FLAG := False;           { set Function result flag }
  186.       ERRor1 ('*** Unable to OPEN '+FN);
  187.     end;
  188.   OPENF := FLAG                        { set return value }
  189. end;  { OPENF }
  190.  
  191. Procedure PRinT (inD : Integer; X : String); { Print Report Line }
  192. Var AF : Char;                              { Append Flag }
  193.     XX,Y : Word;
  194. begin
  195.   if PRtoK then                         { Printer online? }
  196.     begin
  197.       Case inD of              { what Type of print line? }
  198.         PL  : Write (LST, X);              { partial line }
  199.         WL  : Writeln (LST, X);              { whole line }
  200.       end
  201.     end  { Printer o/p }
  202.   else                                     { use o/p File }
  203.     begin
  204.       XX := WhereX; Y := WhereY;
  205.       if not PFP then                   { File not opened }
  206.         begin
  207.           AF := 'W';                            { default }
  208.           if EXISTS (PRTFile) then
  209.             begin
  210.               WPROM ('** Print File '+PRTFile+' exists - Append to it? (Y/n) ');
  211.               if GETYN <> 'N' then AF := 'A';
  212.             end;
  213.           if OPENF (PFV1, PRTFile, AF) then PFP := True { set flag }
  214.           else FATAL ('*** Cannot Open Printer O/P File - Terminating');
  215.  
  216.         end;  { of if }
  217.       GotoXY (XX,Y);                      { restore cursor }
  218.       Case inD of
  219.         PL  : Write (PFV1, X);                   { partial }
  220.         WL  : Writeln (PFV1, X);                   { whole }
  221.       end;
  222.     end;  { else }
  223. end;  { PRinT }
  224.  
  225. Function FSI (N : LongInt; W : Byte) : String; { LongInt->String }
  226. Var S : String;
  227. begin
  228.   if W > 0 then Str (N:W,S)
  229.   else          Str (N,S);
  230.   FSI := S;
  231. end;  { FSI }
  232.  
  233. Procedure CLOSEF (Var FYL : Text);  { Close a File - open or not }
  234. begin
  235. {$I-} Close (FYL); {$I+} if Ioresult <> 0 then;
  236. end;  { CLOSEF }
  237.  
  238. Function CENTER (S : String; N : Byte): String;  { center N Char line }
  239. begin
  240.   CENTER := Copy(B40+B40,1,(N-Length(S)) Shr 1)+S
  241. end;  { CENTER }
  242.  
  243. Procedure SSL;                              { System Status Line }
  244. {  This routine is just For "flash"; it can be omitted... }
  245. Const DLM = #32#179#32;
  246. begin
  247.   GotoXY (1,1); Write (F1+DLM+'Fsz: '+FSI(FSize,1)+DLM+
  248.                              'Blk: '+FSI(BLKNO,1)+DLM+
  249.                              'C# '+FSI(CP,1));
  250. end;  { SSL }
  251.  
  252.            {  The following 3 routines are by Trevor Carlsen }
  253. Function Byte2Hex(numb : Byte): String; { Byte to hex String }
  254. Const HexChars : Array[0..15] of Char = '0123456789ABCDEF';
  255. begin
  256.   Byte2Hex[0] := #2; Byte2Hex[1] := HexChars[numb shr 4];
  257.   Byte2Hex[2] := HexChars[numb and 15];
  258. end; { Byte2Hex }
  259.  
  260. Function Numb2Hex(numb: Word): String;  { Word to hex String.}
  261. begin
  262.   Numb2Hex := Byte2Hex(hi(numb))+Byte2Hex(lo(numb));
  263. end; { Numb2Hex }
  264.  
  265. Function Long2Hex(L: LongInt): String; { LongInt to hex String }
  266. begin
  267.   Long2Hex := Numb2Hex(L shr 16) + Numb2Hex(L);
  268. end; { Long2Hex }
  269.  
  270. Function GET_Byte: Byte;         { fetch Byte from buffer data }
  271. begin
  272.   GET_Byte := Byte(B[CP]); Inc (CP); Inc (NCP)
  273. end;  { GET_Byte }
  274.  
  275. Function EOS (Var FV : File): Boolean; { Eof on String File Function }
  276. begin
  277.   if CP >= RES then                    { data still in buffer? }
  278.     if NCP < FSize then
  279.       begin                               { no - get new block }
  280.         BLKNO := (NCP div BSize);
  281.         FillChar(B,BSize,#0);                  { block to read }
  282.         Seek (F,BLKNO*BSize); BlockRead (F,B,BSize,RES); CP := 0;
  283.       end
  284.     else RES := 0;
  285.   EOS := RES = 0;
  286. end;  { EOS }
  287.  
  288. begin
  289.   ClrScr; GotoXY (1,2);
  290.   Write (CENTER('--- Hex Dump - Version '+VERSION+' ---',80));
  291.   if ParamCount > 0 then F1 := ParamStr(1)
  292.   else
  293.     begin
  294.       WPROM ('Filename to be dumped: '); readln (F1); CLEARBOT
  295.     end;
  296.   if not EXISTS (F1) then FATAL ('*** '+F1+' File not present - Terminating! ***');
  297.   PRinT_inIT ('HEXDUMP.TXT'); F1 := UPPER(F1);
  298.   PRinT (WL,CENTER('Hex Dump of '+F1+'  '+SYS_DATE+' '+SYS_TIME,80));
  299.   Assign (F,F1); GotoXY (1,ifLinE); Write ('Processing ',F1);
  300.   Reset (F,1); FSize := FileSize(F); CP := BSize; NCP := 0; RES :=
  301. BSize;
  302.   PRinT (WL,'offset  Addr  1  2  3  4  5  6  7  8  9 10  A  B  C  D  E  F  1234567890abcdef');
  303.   While not EOS (F) do
  304.     begin
  305.       if (NCP mod 16) = 0 then
  306.         begin
  307.           if NCP > 0 then
  308.             begin
  309.               PRinT (WL,MSTR+S1); SSL
  310.             end;
  311.           MSTR := FSI(NCP,6)+'  '+Numb2Hex(NCP); { offset & Address }
  312.           S1 := '  ';
  313.         end;
  314.       BV := GET_Byte;                 { fetch next Byte from buffer }
  315.       MSTR := MSTR+' '+Byte2Hex(BV);                     { Hex info }
  316.       if BV in [32..126] then S1 := S1+Chr(BV)           { BCD info }
  317.       else                    S1 := S1+'_';
  318.     end;
  319.   Close (F);
  320.   While (NCP mod 16) > 0 do
  321.     begin
  322.       MSTR := MSTR+'   '; Inc (NCP);           { fill out last line }
  323.     end;
  324.   PRinT (WL,MSTR+S1); SSL; MSTR := 'Printer';
  325.   if PFP then
  326.     begin
  327.       CLOSEF (PFV1); MSTR := PRTFile
  328.     end;
  329.   GotoXY (1,ifLinE+1); Write ('Formatted output is on ',MSTR);
  330.   GotoXY (1,ERLinE); Write (CENTER('Finis...',80))
  331. end.
  332.