Re: [fpc-pascal] Read Field names from VMT

2023-12-27 Thread Amir via fpc-pascal
Thank you!On Dec 27, 2023 7:46 AM, Sven Barth via fpc-pascal  wrote:

Am 26.12.2023 um 21:29 schrieb Amir---
  via fpc-pascal:


  
  
  On 12/26/23 01:14, Sven Barth via
fpc-pascal wrote:
  
  


  

  Amir--- via fpc-pascal

schrieb am Di., 26. Dez. 2023, 07:03:
  
  Hi,

   I want to retrieve the name of the fields in a
record/class, at run 
time. It looks like "TVmt.vFieldTable" is what I need.
But I cannot find 
any documentation about how to explore the content of
this table. I 
appreciate any pointer.
  

  
  
  
  This only works for published fields and only
fields of type class or interface can be published. 
  

  
  That would work for me. How can I enumerate over those fields?

You can use the PVmtFieldTable and PVmtFieldEntry types from the
TypInfo unit:

=== code begin ===

program tfield;

{$mode objfpc}{$H+}

uses
  TypInfo;

type
  {$M+}
  TSub = class

  end;

  TTest = class
  published
    fTest: TSub;
  end;

var
  vft: PVmtFieldTable;
  vfe: PVmtFieldEntry;
  i: SizeInt;
begin
  vft := PVmtFieldTable(PVMT(TTest)^.vFieldTable);
  Writeln(vft^.Count, ' field(s) with ', vft^.ClassTab^.Count, '
type(s)');
  for i := 0 to vft^.Count - 1 do begin
    vfe := vft^.Field[i];
    Writeln(i, ' -> ', vfe^.Name, ' @ ', vfe^.FieldOffset, ' of
type ', vft^.ClassTab^.ClassRef[vfe^.TypeIndex - 1]^.ClassName);
  end;
end.

=== code end ===

=== output begin ===

PS C:\fpc\git> .\testoutput\tfield.exe
1 field(s) with 1 type(s)
0 -> fTest @ 8 of type TSub

=== output end ===

Side note: contrary to what I had originally written only classes,
but not interfaces are allowed for published fields and they need to
have $M enabled.

Regards,
Sven
  
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread Wayne Sherman via fpc-pascal
On Wed, Dec 27, 2023 at 3:42 PM Wayne Sherman wrote:
> Example using a TFileStream descendant and StreamIO AssignStream:
> ...(line 42 follows)
>   FileWrite(TextRec(Output).Handle, Buffer, Count);

Although that worked (I don't know why) I intended line 42 to be:
FileWrite(TextRec(FOriginalStdOut).Handle, Buffer, Count);
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread Wayne Sherman via fpc-pascal
Example using a TFileStream descendant and StreamIO AssignStream:

program TeeStdOut;
{$mode objfpc}

uses
  Classes, SysUtils, StreamIO;

type
  TTeeStream = class(TFileStream)
  Private
FOriginalStdOut: Text;
FNewStdOut: Text;
  public
constructor Create(const AFileName: string; Mode: Word);
destructor Destroy; override;
function Write(const Buffer; Count : Longint) : Longint; override;
  end;

constructor TTeeStream.Create(const AFileName: string; Mode: Word);
begin
  inherited Create(AFileName, Mode);

  FOriginalStdOut := Output; // save original stdout
  AssignStream(FNewStdOut, Self);
  Rewrite(FNewStdOut);

  // The following code causes stdout to be redirected
  //   to FNewStdOut (and our TTeeStream)
  Output := FNewStdOut;
end;

destructor TTeeStream.Destroy;
begin
  Output := FOriginalStdOut;
  Close(FNewStdOut);
  inherited Destroy;
end;

function TTeeStream.Write(const Buffer; Count: Longint): Longint;
begin
  Result := inherited Write(Buffer, Count);
//  FileWrite(System.StdOutPutHandle, Buffer, Count); //this also works
  FileWrite(TextRec(Output).Handle, Buffer, Count);
end;

var
  TeeStream: TTeeStream;
begin
  WriteLn('WriteLn to stdout before TTeeStream redirect');

  TeeStream := TTeeStream.Create('test.txt', fmCreate);
  try
WriteLn('Hello, World! after creating TTeeStream');
WriteLn('(WriteLn to stdout redirected to console and to file)');
  finally
TeeStream.Free;
  end;

  WriteLn('WriteLn to stdout after destroying TTeeStream');
end.

On Wed, Dec 27, 2023 at 3:25 AM James Richters via fpc-pascal
 wrote:
>
> I wanted to write what I thought should be a simple procedure, just instead 
> of calling WRITELN() with some arguments,
>
> call WRITELOG() with the same arguments that you would use to write to a 
> file, but my WRITELOG() procedure would
>
> write to the screen and the file.. but I can’t figure out how to pass all the 
> arguments to the two WRTIELNs.
>
>
>
> So….
>
>
>
> Procedure WriteLog(Filename:String, AllOtherAurguments:);
>
> Begin
>
> Writeln(Filename,AllOtherAurguments);
>
> Writeln(AllOtherAurguments);
>
> End;
>
>
>
> How can I make this work?  Since WRITELN can take any number of many kinds of 
> arguments,
>
> how can I get them all and pass them along without knowing how many or what 
> types they are?
>
> How does WRITELN even work when you don’t know this information?
>
>
>
> I’m guessing there should be some way to do this, because WRITELN itself 
> works, but how it could
>
> possibly work is not within my experience.
>
>
>
> The only way I could think of would be if there were versions of WRITELN with 
> every combination
>
> of possible arguments, but that seems completely unmanageable and ridiculous,
>
> so there must be something more advanced going on, but maybe WRTELN is 
> special and not something I can duplicate?
>
>
>
>
>
> Any Ideas?
>
>
>
> James
>
> ___
> fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread Sven Barth via fpc-pascal

Am 27.12.2023 um 12:25 schrieb James Richters via fpc-pascal:


I wanted to write what I thought should be a simple procedure, just 
instead of calling WRITELN() with some arguments,


call WRITELOG() with the same arguments that you would use to write to 
a file, but my WRITELOG() procedure would


write to the screen and the file.. but I can’t figure out how to pass 
all the arguments to the two WRTIELNs.


So….

Procedure WriteLog(Filename:String, AllOtherAurguments:);

Begin

Writeln(Filename,AllOtherAurguments);

Writeln(AllOtherAurguments);

End;

How can I make this work?Since WRITELN can take any number of many 
kinds of arguments,


how can I get them all and pass them along without knowing how many or 
what types they are?


How does WRITELN even work when you don’t know this information?

I’m guessing there should be some way to do this, because WRITELN 
itself works, but how it could


possibly work is not within my experience.

The only way I could think of would be if there were versions of 
WRITELN with every combination


of possible arguments, but that seems completely unmanageable and 
ridiculous,


so there must be something more advanced going on, but maybe WRTELN is 
special and not something I can duplicate?




Write(Ln) is a compiler intrinsic and thus can behave in ways that are 
not possible for ordinary functions.


Your only ways are either to use "array of const" like "Format" does or 
write a text file driver as is done in the StreamIO unit which allows to 
assign a Stream to a TextFile that can in turn be used as the file 
parameter of Write(Ln). You can implement any other output through this.


Regards,
Sven___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Read Field names from VMT

2023-12-27 Thread Sven Barth via fpc-pascal

Am 26.12.2023 um 21:29 schrieb Amir--- via fpc-pascal:


On 12/26/23 01:14, Sven Barth via fpc-pascal wrote:
Amir--- via fpc-pascal  schrieb am 
Di., 26. Dez. 2023, 07:03:


Hi,

   I want to retrieve the name of the fields in a record/class,
at run
time. It looks like "TVmt.vFieldTable" is what I need. But I
cannot find
any documentation about how to explore the content of this table. I
appreciate any pointer.


This only works for published fields and only fields of type class or 
interface can be published.

That would work for me. How can I enumerate over those fields?


You can use the PVmtFieldTable and PVmtFieldEntry types from the TypInfo 
unit:


=== code begin ===

program tfield;

{$mode objfpc}{$H+}

uses
  TypInfo;

type
  {$M+}
  TSub = class

  end;

  TTest = class
  published
    fTest: TSub;
  end;

var
  vft: PVmtFieldTable;
  vfe: PVmtFieldEntry;
  i: SizeInt;
begin
  vft := PVmtFieldTable(PVMT(TTest)^.vFieldTable);
  Writeln(vft^.Count, ' field(s) with ', vft^.ClassTab^.Count, ' type(s)');
  for i := 0 to vft^.Count - 1 do begin
    vfe := vft^.Field[i];
    Writeln(i, ' -> ', vfe^.Name, ' @ ', vfe^.FieldOffset, ' of type ', 
vft^.ClassTab^.ClassRef[vfe^.TypeIndex - 1]^.ClassName);

  end;
end.

=== code end ===

=== output begin ===

PS C:\fpc\git> .\testoutput\tfield.exe
1 field(s) with 1 type(s)
0 -> fTest @ 8 of type TSub

=== output end ===

Side note: contrary to what I had originally written only classes, but 
not interfaces are allowed for published fields and they need to have $M 
enabled.


Regards,
Sven___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread Wayne Sherman via fpc-pascal
On Wed, Dec 27, 2023 at 3:25 AM James Richters wrote:
> I wanted to write what I thought should be a simple procedure, just instead
> of calling WRITELN() with some arguments, call WRITELOG() with the same
> arguments that you would use to write to a file, but my WRITELOG() procedure
> would write to the screen and the file.. but I can’t figure out how to pass 
> all
> the arguments to the two WRTIELNs.

Essentially you want to emulate what the "tee" command does but
internal to your program.  You can intercept data written to STDOUT
and copy the data to your desired destination(s) (i.e. to console and
file).

See message thread "redirecting stdout" here:
https://lists.freepascal.org/pipermail/fpc-pascal/2010-July/thread.html#26149

Also redirecting stdout to a Stream / TMemo:
https://forum.lazarus.freepascal.org/index.php/topic,34621.0.html
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread DougC via fpc-pascal
It would be very useful if WriteStr() was a function that returned the 
resulting string instead of returning it via an output parameter. Then you 
could just wrap the Writeln parameters in WriteStr() and pass it to the new 
logging procedure. Unfortunately, the ISO extension did not end up doing that!



Doug C.___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread James Richters via fpc-pascal
>Writeln() is special. You cannot duplicate it.
That's good to know, I can stop trying.

>What you can do is use WriteStr(), it has the same action as Writeln() but
writes to a string instead of a file.

I was hoping to just replace all existing Writeln()s with my procedure with
a global search and replace.
I think it's probably easiest to make my procedure:

Procedure WriteLog(Filename:String, WriteString:String);
Begin
Writeln(Filename,WriteString);
Writeln(WriteString);
End;

Then just fix the call to concatenate everything into a single string:

So if I end up with this:
WriteLog(Myfile,'some text ',MyInteger);

I'll have to change it to this:
WriteLog(Myfile,'some text '+InttoStr(MyInteger));

And if the arguments are really complicated I can just use WriteStr() to
store it into a string and call my procedure with the resulting string.

It will be a little more effort than doing a global search and replace but
at least I know that it's the only way.

Thanks for the help

James



___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread Thomas Kurz via fpc-pascal
I think he wants to define his own procedure.

The nearest thing that comes into my mind is using ARRAY OF CONST, but the call 
requires square brackets, then:

procedure myproc (x: string; y: array of const);
begin ... end;

myproc ('Hello world', ['Number 1', 'Number 2', 3, 4.0]);


- Original Message - 
From: Michael Van Canneyt via fpc-pascal 
To: ja...@productionautomation.net 
Sent: Wednesday, December 27, 2023, 12:40:24
Subject: [fpc-pascal] Procedures that work like WRITELN()



On Wed, 27 Dec 2023, James Richters via fpc-pascal wrote:

> I wanted to write what I thought should be a simple procedure, just instead
> of calling WRITELN() with some arguments,
> call WRITELOG() with the same arguments that you would use to write to a
> file, but my WRITELOG() procedure would
> write to the screen and the file.. but I can't figure out how to pass all
> the arguments to the two WRTIELNs.

> So..

> Procedure WriteLog(Filename:String, AllOtherAurguments:);
> Begin
>Writeln(Filename,AllOtherAurguments);
>Writeln(AllOtherAurguments);
> End;

> How can I make this work?  Since WRITELN can take any number of many kinds
> of arguments,
> how can I get them all and pass them along without knowing how many or what
> types they are?
> How does WRITELN even work when you don't know this information?

> I'm guessing there should be some way to do this, because WRITELN itself
> works, but how it could
> possibly work is not within my experience.

> The only way I could think of would be if there were versions of WRITELN
> with every combination
> of possible arguments, but that seems completely unmanageable and
> ridiculous,
> so there must be something more advanced going on, but maybe WRTELN is
> special and not something I can duplicate?

Writeln() is special. You cannot duplicate it.

What you can do is use WriteStr(), it has the same action as Writeln() but
writes to a string instead of a file.

https://www.freepascal.org/docs-html/current/rtl/system/writestr.html

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Daily snapshots?

2023-12-27 Thread Thomas Kurz via fpc-pascal
Hello,

as it seems to take longer for the next major release, I'd appreciate if 
automated snapshots could be provided either daily or weekly.

In the documentation, I found a link to 
ftp://ftp.freepascal.org/pub/fpc/snapshot/trunk/ but I cannot login. I tried 
with user=anynous and password=my-email-address.

I don't mind the long time for the next release, but it'd help enormously to 
have the option to download an up-to-date nightly build :)

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread Michael Van Canneyt via fpc-pascal




On Wed, 27 Dec 2023, James Richters via fpc-pascal wrote:


I wanted to write what I thought should be a simple procedure, just instead
of calling WRITELN() with some arguments,
call WRITELOG() with the same arguments that you would use to write to a
file, but my WRITELOG() procedure would
write to the screen and the file.. but I can't figure out how to pass all
the arguments to the two WRTIELNs.

So..

Procedure WriteLog(Filename:String, AllOtherAurguments:);
Begin
   Writeln(Filename,AllOtherAurguments);
   Writeln(AllOtherAurguments);
End;

How can I make this work?  Since WRITELN can take any number of many kinds
of arguments,
how can I get them all and pass them along without knowing how many or what
types they are?
How does WRITELN even work when you don't know this information?

I'm guessing there should be some way to do this, because WRITELN itself
works, but how it could
possibly work is not within my experience.

The only way I could think of would be if there were versions of WRITELN
with every combination
of possible arguments, but that seems completely unmanageable and
ridiculous,
so there must be something more advanced going on, but maybe WRTELN is
special and not something I can duplicate?


Writeln() is special. You cannot duplicate it.

What you can do is use WriteStr(), it has the same action as Writeln() but
writes to a string instead of a file.

https://www.freepascal.org/docs-html/current/rtl/system/writestr.html

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread James Richters via fpc-pascal
I wanted to write what I thought should be a simple procedure, just instead
of calling WRITELN() with some arguments,
call WRITELOG() with the same arguments that you would use to write to a
file, but my WRITELOG() procedure would 
write to the screen and the file.. but I can't figure out how to pass all
the arguments to the two WRTIELNs.
 
So..
 
Procedure WriteLog(Filename:String, AllOtherAurguments:);
Begin
Writeln(Filename,AllOtherAurguments);
Writeln(AllOtherAurguments);
End;
 
How can I make this work?  Since WRITELN can take any number of many kinds
of arguments,
how can I get them all and pass them along without knowing how many or what
types they are?
How does WRITELN even work when you don't know this information?  
 
I'm guessing there should be some way to do this, because WRITELN itself
works, but how it could 
possibly work is not within my experience. 
 
The only way I could think of would be if there were versions of WRITELN
with every combination
of possible arguments, but that seems completely unmanageable and
ridiculous,
so there must be something more advanced going on, but maybe WRTELN is
special and not something I can duplicate?
 
 
Any Ideas?
 
James
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal