Recent

Author Topic: [SOLVED]A case of blindness, probably. Old hands, plz help.  (Read 2728 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 19235
  • Glad to be alive.
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #15 on: September 04, 2024, 01:49:42 pm »
That part is fixed, but I noticed another buggy so I removed the last post by me, but you already saw it.
Will post the fixed version later.
objects are fine constructs. You can even initialize them with constructors.

Zvoni

  • Hero Member
  • *****
  • Posts: 3396
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #16 on: September 04, 2024, 01:52:27 pm »
NotaBene: The phenomenon is on Windows for me (No Linux available for me at work)

That said: BlockRead the whole file (0 To FileSize-1), and then Dump the Bytes 16-wise?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

BrunoK

  • Hero Member
  • *****
  • Posts: 766
  • Retired programmer
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #17 on: September 04, 2024, 01:53:21 pm »
Never liked the file of stuff thing, not enough control.
Code: Pascal  [Select][+][-]
  1. program hexdump;
  2. { Simple Hexdump, unix like clone.
  3.   Has error! Where?
  4.   (c)1991-2024, Thaddy de Koning.
  5.   Use as you like, no license }
  6. {$mode objfpc}{$I-}{$H-}
  7.  
  8. uses
  9.   SysUtils;
  10.  
  11. const
  12.   maxchar = 15;
  13. type
  14.   TByteOrChar  = packed record
  15.   case boolean of
  16.     false:(asByte : packed array[0..maxchar] of byte);
  17.     true :(asChar : packed array[0..maxchar] of AnsiChar);
  18.   end;
  19.  
  20.   function ByteToHex(const value:byte):string;inline;
  21.   const
  22.     HexDigits = '0123456789ABCDEF';
  23.   begin
  24.     ByteToHex := HexDigits[hi(value)+1]+HexDigits[lo(value)+1];
  25.   end;
  26.  
  27. var
  28.   f: file of TByteOrChar;
  29.   bor: TByteOrChar;
  30.   i,r: integer;
  31.   fHandle: THandle;
  32.   BytesRead: integer;
  33. begin
  34.  
  35.   if ParamCount > 0 then
  36.   begin
  37.     Assign(f,paramstr(1));
  38.     filemode := 0;
  39.     reset(f);
  40.     fHandle:=FileRec(f).Handle;
  41.     bytesRead := maxchar;
  42.     r:= IOResult;
  43.     if r = 0 then
  44.     begin
  45.       while (bytesRead>=maxchar) do
  46.       begin
  47.         write(HexStr(FilePos(f) * 16,8):10);
  48.         bytesRead := FileRead(fHandle, bor, bytesRead);
  49.         for i := 0 to bytesRead-1 do
  50.         begin
  51.           write(ByteToHex(bor.asbyte[i]):3);
  52.           if (bor.asbyte[i] < 32 ) or  (bor.asbyte[i] > 127 ) then bor.aschar[i]:='.';
  53.         end;
  54.         write(StringOfChar(' ', (maxchar - BytesRead)*3));
  55.         writeln('|':2,LeftStr(bor.asChar, bytesread),'|');
  56.       end;
  57.       close(f);
  58.     end
  59.     else
  60.       case r of
  61.       2:writeln('File not found');
  62.       5:writeln('Access denied');
  63.       else
  64.         writeln('A less  common error occurred:',r:4);
  65.     end;
  66.  end
  67.  else
  68.    writeln('Use: hexdump <filename>');
  69. end.

Zvoni

  • Hero Member
  • *****
  • Posts: 3396
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #18 on: September 04, 2024, 01:56:18 pm »
Never liked the file of stuff thing, not enough control.
Code: Pascal  [Select][+][-]
  1. program hexdump;
  2. { Simple Hexdump, unix like clone.
  3.   Has error! Where?
  4.   (c)1991-2024, Thaddy de Koning.
  5.   Use as you like, no license }
  6. {$mode objfpc}{$I-}{$H-}
  7.  
  8. uses
  9.   SysUtils;
  10.  
  11. const
  12.   maxchar = 15;
  13. type
  14.   TByteOrChar  = packed record
  15.   case boolean of
  16.     false:(asByte : packed array[0..maxchar] of byte);
  17.     true :(asChar : packed array[0..maxchar] of AnsiChar);
  18.   end;
  19.  
  20.   function ByteToHex(const value:byte):string;inline;
  21.   const
  22.     HexDigits = '0123456789ABCDEF';
  23.   begin
  24.     ByteToHex := HexDigits[hi(value)+1]+HexDigits[lo(value)+1];
  25.   end;
  26.  
  27. var
  28.   f: file of TByteOrChar;
  29.   bor: TByteOrChar;
  30.   i,r: integer;
  31.   fHandle: THandle;
  32.   BytesRead: integer;
  33. begin
  34.  
  35.   if ParamCount > 0 then
  36.   begin
  37.     Assign(f,paramstr(1));
  38.     filemode := 0;
  39.     reset(f);
  40.     fHandle:=FileRec(f).Handle;
  41.     bytesRead := maxchar;
  42.     r:= IOResult;
  43.     if r = 0 then
  44.     begin
  45.       while (bytesRead>=maxchar) do
  46.       begin
  47.         write(HexStr(FilePos(f) * 16,8):10);
  48.         bytesRead := FileRead(fHandle, bor, bytesRead);
  49.         for i := 0 to bytesRead-1 do
  50.         begin
  51.           write(ByteToHex(bor.asbyte[i]):3);
  52.           if (bor.asbyte[i] < 32 ) or  (bor.asbyte[i] > 127 ) then bor.aschar[i]:='.';
  53.         end;
  54.         write(StringOfChar(' ', (maxchar - BytesRead)*3));
  55.         writeln('|':2,LeftStr(bor.asChar, bytesread),'|');
  56.       end;
  57.       close(f);
  58.     end
  59.     else
  60.       case r of
  61.       2:writeln('File not found');
  62.       5:writeln('Access denied');
  63.       else
  64.         writeln('A less  common error occurred:',r:4);
  65.     end;
  66.  end
  67.  else
  68.    writeln('Use: hexdump <filename>');
  69. end.
Bug in Line 48? You're reading 15 Bytes (Bytesread)

Line 41 should be BytesRead:=maxchar+1; ?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 19235
  • Glad to be alive.
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #19 on: September 04, 2024, 01:58:22 pm »
NotaBene: The phenomenon is on Windows for me (No Linux available for me at work)

That said: BlockRead the whole file (0 To FileSize-1), and then Dump the Bytes 16-wise?
It behaves the same on linux, it is probably the keyboard buffer or something.
Strange thing is it worked 33 years ago, although I made changes today..
Will investigate further, just for fun. :o ;D MUST be equal or better than hexdump!
objects are fine constructs. You can even initialize them with constructors.

BrunoK

  • Hero Member
  • *****
  • Posts: 766
  • Retired programmer
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #20 on: September 04, 2024, 02:01:48 pm »
Line 41 should be BytesRead:=maxchar+1; ?
Ok, ok.
Code: Pascal  [Select][+][-]
  1. program hexdump;
  2. { Simple Hexdump, unix like clone.
  3.   Has error! Where?
  4.   (c)1991-2024, Thaddy de Koning.
  5.   Use as you like, no license }
  6. {$mode objfpc}{$I-}{$H-}
  7.  
  8. uses
  9.   SysUtils;
  10.  
  11. const
  12.   maxchar = 16;
  13. type
  14.   TByteOrChar  = packed record
  15.   case boolean of
  16.     false:(asByte : packed array[0..maxchar-1] of byte);
  17.     true :(asChar : packed array[0..maxchar-1] of AnsiChar);
  18.   end;
  19.  
  20.   function ByteToHex(const value:byte):string;inline;
  21.   const
  22.     HexDigits = '0123456789ABCDEF';
  23.   begin
  24.     ByteToHex := HexDigits[hi(value)+1]+HexDigits[lo(value)+1];
  25.   end;
  26.  
  27. var
  28.   f: file of TByteOrChar;
  29.   bor: TByteOrChar;
  30.   i,r: integer;
  31.   fHandle: THandle;
  32.   BytesRead: integer;
  33. begin
  34.  
  35.   if ParamCount > 0 then
  36.   begin
  37.     Assign(f,paramstr(1));
  38.     filemode := 0;
  39.     reset(f);
  40.     fHandle:=FileRec(f).Handle;
  41.     bytesRead := maxchar;
  42.     r:= IOResult;
  43.     if r = 0 then
  44.     begin
  45.       while (bytesRead>=maxchar) do
  46.       begin
  47.         write(HexStr(FilePos(f) * 16,8):10);
  48.         bytesRead := FileRead(fHandle, bor, bytesRead);
  49.         for i := 0 to bytesRead-1 do
  50.         begin
  51.           write(ByteToHex(bor.asbyte[i]):3);
  52.           if (bor.asbyte[i] < 32 ) or  (bor.asbyte[i] > 127 ) then bor.aschar[i]:='.';
  53.         end;
  54.         write(StringOfChar(' ', (maxchar - BytesRead)*3));
  55.         writeln('|':2,LeftStr(bor.asChar, bytesread),'|');
  56.       end;
  57.       close(f);
  58.     end
  59.     else
  60.       case r of
  61.       2:writeln('File not found');
  62.       5:writeln('Access denied');
  63.       else
  64.         writeln('A less  common error occurred:',r:4);
  65.     end;
  66.  end
  67.  else
  68.    writeln('Use: hexdump <filename>');
  69. end.

Thaddy

  • Hero Member
  • *****
  • Posts: 19235
  • Glad to be alive.
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #21 on: September 04, 2024, 02:38:49 pm »
Claim it, Bruno, claim it... It looks fixed... Many thanks. >:( ;D :D O:-) 8-)
(Anger is assigned to me, not you)
Only problem I have is that it relies on sysutils, which is an absolute no go for me.
I think I can fix that too.
« Last Edit: September 04, 2024, 02:41:39 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Zvoni

  • Hero Member
  • *****
  • Posts: 3396
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #22 on: September 04, 2024, 02:51:04 pm »
No Sysutils
Code: Pascal  [Select][+][-]
  1. program hexdump;
  2. { Simple Hexdump, unix like clone.
  3.   Has error! Where?
  4.   (c)1991-2024, Thaddy de Koning.
  5.   Use as you like, no license }
  6. {$mode objfpc}{$I-}{$H-}
  7.  
  8. const
  9.   maxchar = 16;
  10. type
  11.   TByteOrChar  = packed record
  12.   case boolean of
  13.     false:(asByte : packed array[0..maxchar-1] of byte);
  14.     true :(asChar : packed array[0..maxchar-1] of AnsiChar);
  15.   end;
  16.  
  17.   function ByteToHex(const value:byte):string;inline;
  18.   const
  19.     HexDigits = '0123456789ABCDEF';
  20.   begin
  21.     ByteToHex := HexDigits[hi(value)+1]+HexDigits[lo(value)+1];
  22.   end;
  23.  
  24. var
  25.   f:File;
  26.   bor: TByteOrChar;
  27.   i,r,fs,rem,row: integer;
  28. begin
  29.   if ParamCount > 0 then
  30.   begin
  31.     Assign(f,paramstr(1));
  32.     filemode := 0;
  33.     reset(f,1);
  34.     r:= IOResult;
  35.     if r = 0 then
  36.     begin
  37.       fs:=FileSize(f);
  38.       row:=0;
  39.       rem:=fs;
  40.       While rem div maxchar>0 Do
  41.       Begin
  42.         Blockread(f,bor,maxchar);
  43.         write(HexStr(row * 16,8):10);
  44.         for i := 0 to maxchar-1 do
  45.         begin
  46.           write(ByteToHex(bor.asbyte[i]):3);
  47.           if (bor.asbyte[i] < 32 ) or  (bor.asbyte[i] > 127 ) then bor.aschar[i]:='.';
  48.         end;
  49.         writeln('|':2,bor.asChar,'|');
  50.         rem:=rem-maxchar;
  51.         Inc(row);
  52.       End;
  53.       If rem mod maxchar>0 Then
  54.       Begin
  55.         FillChar(bor,maxchar,' ');
  56.         Blockread(f,bor,rem mod maxchar);
  57.         write(HexStr(row * 16,8):10);
  58.         for i := 0 to (rem mod maxchar)-1 do
  59.         begin
  60.           write(ByteToHex(bor.asbyte[i]):3);
  61.           if (bor.asbyte[i] < 32 ) or  (bor.asbyte[i] > 127 ) then bor.aschar[i]:='.';
  62.         end;
  63.         For i:=(rem mod maxchar) To maxchar-1 Do write(' ':3);
  64.         writeln('|':2,bor.asChar,'|');
  65.         Inc(row);
  66.       End;
  67.       write(HexStr(row * 16,8):10);
  68.       close(f);
  69.     end
  70.     else
  71.       case r of
  72.       2:writeln('File not found');
  73.       5:writeln('Access denied');
  74.       else
  75.         writeln('A less  common error occurred:',r:4);
  76.     end;
  77.  end
  78.  else
  79.    writeln('Use: hexdump <filename>');
  80. end.

Yeah, yeah,... duplicate code and all that.
Clobbered together in some 10 minutes
« Last Edit: September 04, 2024, 03:21:11 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

BrunoK

  • Hero Member
  • *****
  • Posts: 766
  • Retired programmer
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #23 on: September 04, 2024, 03:32:06 pm »
No Sysutils

Yeah, yeah,... duplicate code and all that.
Clobbered together in some 10 minutes
Still doesn't end cleanly :
00000800 69 6C 65 6E 61 6D 65 3E 27 29 3B 0D 0A 65 6E 64 |ilename>');..end|
 00000810 2E 0D 0A                                        |...             |
 00000820

00000820 is past end of file.
A bit too much code.
Without sysutils, clean end of file :
Code: Pascal  [Select][+][-]
  1. program hexdump3;
  2. { Simple Hexdump, unix like clone.
  3.   Has error! Where?
  4.   (c)1991-2024, Thaddy de Koning.
  5.   Use as you like, no license }
  6. {$mode objfpc}{$I-}{$H-}
  7.  
  8. const
  9.   maxchar = 16;
  10. type
  11.   TByteOrChar  = packed record
  12.   case boolean of
  13.     false:(asByte : packed array[0..maxchar-1] of byte);
  14.     true :(asChar : packed array[0..maxchar-1] of AnsiChar);
  15.   end;
  16.  
  17.   function ByteToHex(const value:byte):string;inline;
  18.   const
  19.     HexDigits = '0123456789ABCDEF';
  20.   begin
  21.     ByteToHex := HexDigits[hi(value)+1]+HexDigits[lo(value)+1];
  22.   end;
  23.  
  24. var
  25.   f:File;
  26.   bor: TByteOrChar;
  27.   i,r,rem: integer;
  28.   fs, ofs: Int64;
  29. begin
  30.   if ParamCount > 0 then
  31.   begin
  32.     Assign(f,paramstr(1));
  33.     filemode := 0;
  34.     reset(f,1);
  35.     r:= IOResult;
  36.     if r = 0 then
  37.     begin
  38.       fs:=FileSize(f);
  39.       ofs:=0;
  40.       rem:=maxchar;
  41.       While ofs<fs do
  42.       Begin
  43.         if ofs+rem>fs then
  44.           rem := fs-ofs;
  45.         Blockread(f,bor,rem);
  46.         write(HexStr(ofs, 8):10);
  47.         for i := 0 to rem - 1 do
  48.         begin
  49.           write(ByteToHex(bor.asbyte[i]):3);
  50.           if (bor.asbyte[i] < 32 ) or  (bor.asbyte[i] > 127 ) then bor.aschar[i]:='.';
  51.         end;
  52.         writeln(StringOfChar(' ', (maxchar-rem)*3), '|':2,Copy(bor.asChar, 1, rem),'|');
  53.         Inc(ofs, maxchar);
  54.       End;
  55.       close(f);
  56.     end
  57.     else
  58.       case r of
  59.       2:writeln('File not found');
  60.       5:writeln('Access denied');
  61.       else
  62.         writeln('A  less  common  error occurred:',r:4);
  63.     end;
  64.  end
  65.  else
  66.    writeln('Use: hexdump <filename>');
  67. end.
@Grumpy, No need for claim, could be useful.


Zvoni

  • Hero Member
  • *****
  • Posts: 3396
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #24 on: September 04, 2024, 03:38:50 pm »
Still doesn't end cleanly :
00000800 69 6C 65 6E 61 6D 65 3E 27 29 3B 0D 0A 65 6E 64 |ilename>');..end|
 00000810 2E 0D 0A                                        |...             |
 00000820

00000820 is past end of file.
A bit too much code.
Err.... Thaddy specifically said, that the last (empty line) has to be "there". See post 1 with the screenshot

EDIT: After fooling around with that, i've come to the conclusion, that "read" cannot read "partial records", so in case of Thaddy's original code, which is a "File of 16 bytes",
"read" cannot read the last segment, if it'S not the FULL 16 Bytes.
Probably the reason, why EOF(f) returns true
« Last Edit: September 04, 2024, 03:42:38 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

BrunoK

  • Hero Member
  • *****
  • Posts: 766
  • Retired programmer
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #25 on: September 04, 2024, 03:54:50 pm »
Err.... Thaddy specifically said, that the last (empty line) has to be "there". See post 1 with the screenshot
He stated he had a problem. A dump is useful if it dumps exactly what is in a file. Or maybe, if one knows the logical sector size, rounding up to sector size.
Dumping memory blocks is another subject but that little program might can handy when wanting to see around memory. (Such as dumping surround of an ansi string).
Quote
EDIT: After fooling around with that, i've come to the conclusion, that "read" cannot read "partial records", so in case of Thaddy's original code, which is a "File of 16 bytes",
"read" cannot read the last segment, if it'S not the FULL 16 Bytes.
Probably the reason, why EOF(f) returns true
Thats why I wrote I didn' like file of stuff, but file on its own is ok, I learned something today.

Zvoni

  • Hero Member
  • *****
  • Posts: 3396
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #26 on: September 04, 2024, 04:08:51 pm »
Err.... Thaddy specifically said, that the last (empty line) has to be "there". See post 1 with the screenshot
He stated he had a problem. A dump is useful if it dumps exactly what is in a file. Or maybe, if one knows the logical sector size, rounding up to sector size.
Dumping memory blocks is another subject but that little program might can handy when wanting to see around memory. (Such as dumping surround of an ansi string).
From Post 1
Quote
The error is the last line of the output missing.
The screenshot shows "his" hexdump (upper half), and the "original" (Linux/Unix)-Hexdump (lower half).

That said: I agree, that that last empty line is kinda "weird"
« Last Edit: September 05, 2024, 09:39:38 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

MarkMLl

  • Hero Member
  • *****
  • Posts: 8572
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #27 on: September 04, 2024, 04:09:14 pm »
EDIT: After fooling around with that, i've come to the conclusion, that "read" cannot read "partial records", so in case of Thaddy's original code, which is a "File of 16 bytes",
"read" cannot read the last segment, if it'S not the FULL 16 Bytes.
Probably the reason, why EOF(f) returns true
Thats why I wrote I didn' like file of stuff, but file on its own is ok, I learned something today.

Ouch. I'm not sure I've ever seen it explicitly stated, so this would probably have to be considered to be implementation-defined.

However, In Wirth's day a record would either have been an 80-column punched card, or a fixed-length block on magnetic tape, or a fixed-length record in a fixed-length disk block which was always read in its entirely.

So I've got some sympathy with not expecting to see a fractional record:

Do Not Fold, Staple, Spindle or Mutilate

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 19235
  • Glad to be alive.
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #28 on: September 04, 2024, 04:57:55 pm »
An untyped file,
Size of the buffer
Modulo file size to determine any remnants, because that would be zero except for the last read.
Should be OK.

Thanks to you all. When fully tested I intend to document it and replublish, because otherwise pure Pascal will be lost in heaven. O:-)
BrunoK: programmers count from zero, so I corrected that.. ;D
« Last Edit: September 04, 2024, 06:01:07 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

BrunoK

  • Hero Member
  • *****
  • Posts: 766
  • Retired programmer
Re: [SOLVED]A case of blindness, probably. Old hands, plz help.
« Reply #29 on: September 04, 2024, 06:40:36 pm »
BrunoK: programmers count from zero, so I corrected that..
I dont know if you mean to be ironic.

Any way in my first years of programming, (late 70's) and of course if my memory does not fail, both BASIC and Cobol where indexed with first element at (1) and surprisingly, except in geometry, during my brief studies, tables where based at 1.

Then later I tried a bit of C that was Offset 0 based, I noticed that the disgustingly slow Basic used on mini had an Option base 0 possibility, and articles in Byte, Dr Dobb's etc where very base 0 oriented.

Switching to delphi (3 I think) throw-ed me full in 0 based offset calculations.

Windows is fully base 0 offset, a scrollbar with a min of 0 and a range of 100, f. ex., has a max of 100 which is an outer bound. It is very practical for size calculation and lots of other things.

Regrettably many non windows widget sets do not see things this way and it makes life difficult when trying to normalize behavior of controls like the TScrollBar and probably also for some control sizes/position calculations.

AND most important, if you pass an array to a procedure or function it is always 0 based in FPC, Delphi etc...

 

TinyPortal © 2005-2018