Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2007-06

Metaware

16 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Tom Walsh

Heh, if you are reading this then you may know what Metaware is?

I've a large(!) body of code written over the years under the Metaware Professional Pascal compiler. This code is to be translated to run on the fpc compiler.

I wonder if anyone out there has attempted such an endeavor and might give me some suggestions, or even some warnings about what I should watch out for? I have found that there are some functional differences that Metaware has over fpc, one example is the yield() function which returns the intermediate result of a function call. There are a few other functional differences, these should be able to be (re)written out.

Another "interesting feature" is a #define statement which is very much like a C macro:
#define ChMap(A,C) Vt220Map[A] := chr(c)
There are quite a bit of these '#defines' throughout this source. I'm thinking that the fpc alias is not going to work very well here and that I would have to recode these defines as functions / procedures?

I had considered building a pre-processor to reformat the input to ppcx64 into a delphi style construction, but there are enough significant differences in source file structure and declarations that would make this a whole lot of work. Probably would also be a headache to maintain such an animal as well (yacc?).

Here is a snippet of the first few lines of a pascal source:

========== begin ================
export (libdos4);
{ Include MetaWare libraries }
    pragma c_include('implement.pf');
    pragma c_include('language.pf');
...
...
    pragma c_include('dospriv.inc');
{ C routine package }
package FromC;
  pragma calling_convention(language.C);
  pragma routine_aliasing_convention(implement.global_aliasing_convention);
  type
    int = LongInt;
program libdos4_unit;

with
defstd4,

  dospriv;
var
  KeySaveChar: char;
function DosKeyCharHave:
  boolean;
  begin
    return(FromC.rdchk(0) = 1);
  end;
========== snip =================

Anyhow, any thoughts that someone may have would be greatly appreciated!

TIA,

Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net http://cyberiansoftware.com http://openzipit.org "Windows? No thanks, I have work to do..." ----------------------------------------------------

Reply by email

Daniël Mantione
to Tom Walsh

Op Mon, 18 Jun 2007, schreef Tom Walsh:

Show quoted text 8 lines
Heh, if you are reading this then you may know what Metaware is? I've a large(!) body of code written over the years under the Metaware Professional Pascal compiler. This code is to be translated to run on the fpc compiler. I wonder if anyone out there has attempted such an endeavor and might give me some suggestions, or even some warnings about what I should watch out for?

From time to time we meet people who are trying to bring new life into old Pascal code bases. Generally the experience is that is a lot of work since even the lack of small feature might involve rewriting a lot of code. The biggest risk with these projects is that the original developer(s) are gone and the people doing the port lack the knowledge about the code to do it properly. Success means a lot of benefits, like supporting many platforms to many new possibilites due to interoperation with other code in the Free Pascal world.

I'm not aware of anyone who has ported code from Metaware Pascal.

I have found that there are some functional differences that Metaware has over fpc, one example is the yield() function which returns the intermediate result of a function call.

?

Show quoted text 9 lines
There are a few other functional differences, these should be able to be (re)written out. Another "interesting feature" is a #define statement which is very much like a C macro: #define ChMap(A,C) Vt220Map[A] := chr(c) There are quite a bit of these '#defines' throughout this source. I'm thinking that the fpc alias is not going to work very well here and that I would have to recode these defines as functions / procedures?

Yes, while Free Pascal can do macros, we do not support macro's with parameters, please convert them to inline procedures.

Show quoted text 7 lines
I had considered building a pre-processor to reformat the input to ppcx64 into a delphi style construction, but there are enough significant differences in source file structure and declarations that would make this a whole lot of work. Probably would also be a headache to maintain such an animal as well (yacc?). Here is a snippet of the first few lines of a pascal source:

Wow... I doubt I would recognize that code as Pascal if I wasn't told it was. Free Pascal implements the UCSD-Pascal derived dialects of the language (Turbo Pascal, Delphi, Metrowerks Pascal).

Daniël

Show quoted text 50 lines
========== begin ================ export (libdos4); { Include MetaWare libraries } pragma c_include('implement.pf'); pragma c_include('language.pf'); ... ... pragma c_include('dospriv.inc'); { C routine package } package FromC; pragma calling_convention(language.C); pragma routine_aliasing_convention(implement.global_aliasing_convention); type int = LongInt; program libdos4_unit; with defstd4, dospriv; var KeySaveChar: char; function DosKeyCharHave: boolean; begin return(FromC.rdchk(0) = 1); end; ========== snip ================= Anyhow, any thoughts that someone may have would be greatly appreciated! TIA, -- Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net http://cyberiansoftware.com http://openzipit.org "Windows? No thanks, I have work to do..." ---------------------------------------------------- _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Tom Verhoeff
to Tom Walsh: Heh, if you are reading this then you may know what Metaware is? I've a large(!) body of…
Tom Walsh wrote
Heh, if you are reading this then you may know what Metaware is?

Unfortunately for you, I have no such experience; never heard of it.

Another "interesting feature" is a #define statement which is very much like a C macro: #define ChMap(A,C) Vt220Map[A] := chr(c)

Would it be an option see if you can pull it through a C preprocessor to eliminate the #define constructs?

Tom

E-MAIL: T.Verhoeff @ TUE.NL | Dept. of Math. & Comp. Science PHONE: +31 40 247 41 25 | Technische Universiteit Eindhoven FAX: +31 40 247 54 04 | PO Box 513, NL-5600 MB Eindhoven http://www.win.tue.nl/~wstomv/ | The Netherlands

Reply by email

Tom Walsh
to Daniël Mantione: Op Mon, 18 Jun 2007, schreef Tom Walsh: From time to time we meet people who are trying…
Daniël Mantione wrote 18 lines
Wow... I doubt I would recognize that code as Pascal if I wasn't told it was. Free Pascal implements the UCSD-Pascal derived dialects of the language (Turbo Pascal, Delphi, Metrowerks Pascal). Daniël > ========== begin ================ > export (libdos4); > > { Include MetaWare libraries } > pragma c_include('implement.pf'); > pragma c_include('language.pf'); > ... > ... > pragma c_include('dospriv.inc'); > >

Yes, I know. I learned the UCSD Pascal dialect while programming old Apple ][ pascal. Heh, that was a while ago. This Metaware looks pretty much like UCSD code in a lot of respects, but then they go into these weird C-like extensions.

Fortunately, the developers are still very much active writing new code against the Metaware compiler. You know how it is, just like Cobol, once you get them hooked (swindled?), management will keep shoveling money into it...

TomW

Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net http://cyberiansoftware.com http://openzipit.org "Windows? No thanks, I have work to do..." ----------------------------------------------------

Reply by email

Darius Blaszijk
to Tom Walsh
Tom Walsh wrote 32 lines
Daniël Mantione wrote: > Wow... I doubt I would recognize that code as Pascal if I wasn't told > it was. Free Pascal implements the UCSD-Pascal derived dialects of > the language (Turbo Pascal, Delphi, Metrowerks Pascal). > > Daniël > > >> ========== begin ================ >> export (libdos4); >> >> { Include MetaWare libraries } >> pragma c_include('implement.pf'); >> pragma c_include('language.pf'); >> ... >> ... >> pragma c_include('dospriv.inc'); >> >> Yes, I know. I learned the UCSD Pascal dialect while programming old Apple ][ pascal. Heh, that was a while ago. This Metaware looks pretty much like UCSD code in a lot of respects, but then they go into these weird C-like extensions. Fortunately, the developers are still very much active writing new code against the Metaware compiler. You know how it is, just like Cobol, once you get them hooked (swindled?), management will keep shoveling money into it...
{$mode metaware}

:)

Show quoted text 5 lines
TomW

Reply by email

Mark Wood
to Daniël Mantione: Op Mon, 18 Jun 2007, schreef Tom Walsh: From time to time we meet people who are trying…
Show quoted text 7 lines
> I have found that there are some functional differences that Metaware has over > fpc, one example is the yield() function which returns the intermediate result > of a function call. > ?

'?' indeed! I am fascinated! What does yield do exactly... presumably it returns a result from the function without closing down that instance of the function? Amazing concept. I am still trying to work out how that could be useful or even how it could be used (without breaking stuff upstream).

There are several preprocessory type contraptions that suit Pascal directly or could handle it at the least. Why not use one of those to try adjusting code. We do that sort of stuff a fair bit (although mainly with code from other -non-pascalian languages). Or how about even beating the code into a more pascally form using Perl, or even something as basic as the Boxer text editor? (laborious job though, of course)

Interesting stuff.

By the way, I agree about the merits of converting code from old or foreign repositories. There is some great code out there and it is useful to reclaim it by porting it across. We often get unexpected spinoff stuff out of that process. At the moment we are working on setting up a website offering most of this stuff back to the community.

Hmmm... if there is anything useful in your work (not the proprietary code from the developer, I mean in the conversion work) perhaps if you share that as a project on sourceforge or similar, others will help you develop the conversion. You would have to work out the benefit though (be it producing a conversion tool, or a library, or whatever).

Cheers,
Mark.

Reply by email

Luca Olivetti
to Mark Wood

En/na Mark Wood ha escrit:

Show quoted text 13 lines
>> I have found that there are some functional differences that Metaware has over >> fpc, one example is the yield() function which returns the intermediate result >> of a function call. >> > > ? > '?' indeed! I am fascinated! What does yield do exactly... presumably it returns a result from the function without closing down that instance of the function? Amazing concept. I am still trying to work out how that could be useful or even how it could be used (without breaking stuff upstream).

Maybe it's something similar to this?

http://www.ibm.com/developerworks/library/l-pycon.html

Bye

Luca

Reply by email

Vinzent Hoefler
to memsom: I suspect - given the word "DOS" in some of the code, it allows a DOS event loop to…
memsom wrote 7 lines
> '?' indeed! I am fascinated! What does yield do exactly... > presumably it returns a result from the function without closing > down that instance of the function? Amazing concept. I suspect - given the word "DOS" in some of the code, it allows a DOS event loop to continue in a single threaded co-operative multitasking environment.

Nope. It's that what Mark thinks, and more like (Python's) generator thingie (link posted by Luca):

-- 8< --
Some high level languages support iterators in exactly this fashion. For example Metaware's Professional Pascal Compiler for the PC supports iterators[14]. Were you to create a code sequence as follows:

        iterator OneToFour:integer;
begin
yield 1;
yield 2;
yield 3;
yield 4;
end;

and call it in the main program as follows:

	for i in OneToFour do writeln(i);

-- 8< --
-- Found in: http://www.oopweb.com/Assembly/Documents/ArtOfAssembly/ Volume/Chapter_12/CH12-6.html

Regards,

Vinzent.

Reply by email

memsom
to Mark Wood: '?' indeed! I am fascinated! What does yield do exactly... presumably it returns a result…
'?' indeed! I am fascinated! What does yield do exactly... presumably it returns a result from the function without closing down that instance of the function? Amazing concept.

I suspect - given the word "DOS" in some of the code, it allows a DOS event loop to continue in a single threaded co-operative multitasking environment. A bit like Application.ProcessMessages in Delphi or Application.DoEvents() in DotNet. You can probably do other things at the same time, but Yield says this to me (maybe my old Mac programming hat as the Toolbox has a similar API.) If so, it's probably a little redundant now and use of threads could get around the problem (or even using the Application object from Lazarus API to implement the "processmessages"/yield part?)

Reply by email

memsom
to Vinzent Hoefler: Nope. It's that what Mark thinks, and more like (Python's) generator thingie (link posted…
Nope. It's that what Mark thinks, and more like (Python's) generator thingie (link posted by Luca):

Riiiight.. like:

insert into blah (test) values(1);
insert into blah (test) values(2);
insert into blah (test) values(3);
insert into blah (test) values(4);
create procedure test()
returns(res integer)
begin
  for select test from blah
  into :res do
  begin
    suspend;
  end
end

Reply by email

Tom Walsh
to Mark Wood: '?' indeed! I am fascinated! What does yield do exactly... presumably it returns a result…
Mark Wood wrote 13 lines
>> I have found that there are some functional differences that Metaware has over >> fpc, one example is the yield() function which returns the intermediate result >> of a function call. >> > ? > '?' indeed! I am fascinated! What does yield do exactly... presumably it returns a result from the function without closing down that instance of the function? Amazing concept. I am still trying to work out how that could be useful or even how it could be used (without breaking stuff upstream).

This would be one example, a function which returns a value each time it is called. There are some scoping rules which dictate whether the yield'ed function will init or continue from the last yield point:

============== begin ====================
iterator LoopStep(Start, Stop, StepSize   : StdInt) : StdInt;
  var
    i, Answer, NumLoops : StdInt;
  begin
    if StepSize = 0 then return;
    Answer := Start;
    NumLoops := ((Stop - Start) DIV StepSize) + 1;
    for i := 1 to NumLoops do begin
      Yield(Answer);
      Answer := Answer + StepSize;
    end;
  end;
============== snip =====================

Not sure why they found this terribly useful, but I don't write financial code...

TomW

Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net http://cyberiansoftware.com http://openzipit.org "Windows? No thanks, I have work to do..." ----------------------------------------------------

Reply by email

Tom Walsh
to memsom: I suspect - given the word "DOS" in some of the code, it allows a DOS event loop to…
memsom wrote 16 lines
> '?' indeed! I am fascinated! What does yield do exactly... presumably it > returns a result from the function without closing down that instance of > the function? Amazing concept. > I suspect - given the word "DOS" in some of the code, it allows a DOS event loop to continue in a single threaded co-operative multitasking environment. A bit like Application.ProcessMessages in Delphi or Application.DoEvents() in DotNet. You can probably do other things at the same time, but Yield says this to me (maybe my old Mac programming hat as the Toolbox has a similar API.) If so, it's probably a little redundant now and use of threads could get around the problem (or even using the Application object from Lazarus API to implement the "processmessages"/yield part?)

Well, the programmers are referring to 'Dos' in the generic sense, this is definately on a unix box.

TomW

Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net http://cyberiansoftware.com http://openzipit.org "Windows? No thanks, I have work to do..." ----------------------------------------------------

Reply by email

Tom Walsh
to Tom Walsh: This would be one example, a function which returns a value each time it is called. …
Tom Walsh wrote 21 lines
Mark Wood wrote: > >>> I have found that there are some functional differences that >>> Metaware has over >>> fpc, one example is the yield() function which returns the >>> intermediate result >>> of a function call. >>> >> ? >> > '?' indeed! I am fascinated! What does yield do exactly... presumably > it returns a result from the function without closing down that > instance of the function? Amazing concept. I am still trying to work > out how that could be useful or even how it could be used (without > breaking stuff upstream). > This would be one example, a function which returns a value each time it is called. There are some scoping rules which dictate whether the yield'ed function will init or continue from the last yield point:

About three years ago, when this project was first proposed, I did find a white-paper written by someone at Metaware which outlined the internals of the yield(). Apparently, they construct a seperate stack frame for a function containing a yield(). When it is first called via the main entry point, it constructs the frame and fills the local vars. Subsequent calls cause the function to be continued, rather than run from the initial entry point. This is an example from the manual:

============ begin ==============
Package Telephone_directories;
..
...
...
iterator AllEntriesInOrder (const aDirectory: Directory) :
       (const NextName: string(10); const NextNumber: string(8));
var
    I: 1..MaxSize;
begin
    for I := 1 to aDirectory.Size do
       with aDirectory.Entry[i] do
          Yield(Name, Number);
    end;
end;

{ this is a new program that uses the iterator }
...
...
...
with Telephone_Directories; { with seems to be something like the 'uses' clause }

    var MyDirectory: Directory;

...
...

    for aName, aNumber in AllEntriesInOrder(MyDirectory) do
       writeln (aName, ' : ', aNumber);

...
...

================ snip ===================

Oh, then there is the "cycle" statement which reads very much like the continue statement we all know about....

Odd shi^H^Htuff.

TomW

Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net http://cyberiansoftware.com http://openzipit.org "Windows? No thanks, I have work to do..." ----------------------------------------------------

Reply by email

Mark Wood
to Tom Walsh: This would be one example, a function which returns a value each time it is called. …

It strikes me that whilst it may not be the best programming form, the same thing could be done readily with a global variable?

M.

Tom Walsh wrote 43 lines
Mark Wood wrote: > >>> I have found that there are some functional differences that >>> Metaware has over >>> fpc, one example is the yield() function which returns the >>> intermediate result >>> of a function call. >>> >> ? >> > '?' indeed! I am fascinated! What does yield do exactly... presumably > it returns a result from the function without closing down that > instance of the function? Amazing concept. I am still trying to work > out how that could be useful or even how it could be used (without > breaking stuff upstream). > This would be one example, a function which returns a value each time it is called. There are some scoping rules which dictate whether the yield'ed function will init or continue from the last yield point: ============== begin ==================== iterator LoopStep(Start, Stop, StepSize : StdInt) : StdInt; var i, Answer, NumLoops : StdInt; begin if StepSize = 0 then return; Answer := Start; NumLoops := ((Stop - Start) DIV StepSize) + 1; for i := 1 to NumLoops do begin Yield(Answer); Answer := Answer + StepSize; end; end; ============== snip ===================== Not sure why they found this terribly useful, but I don't write financial code... TomW

Reply by email

Vinzent Hoefler
to Mark Wood

On Wednesday 20 June 2007 06:55, Mark Wood wrote:

[iterator functions with yield()]

It strikes me that whilst it may not be the best programming form, the same thing could be done readily with a global variable?

Not if you call such an iterator several times at once (in nested loops for example):

|for i in LoopStep (1, 10, 1) ...
| for j in LoopStep (2, 20, 3) ...

Correct me, if I'm wrong, but AFAICS each function retains its own set of local variables and thus return "sets". This would be very hard to accomplish with global variables.

Regards,

Vinzent.

Reply by email

memsom
to Tom Walsh: About three years ago, when this project was first proposed, I did find a white-paper…
About three years ago, when this project was first proposed, I did find a white-paper written by someone at Metaware which outlined the internals of the yield().

And the code runs in a single thread or concurrently?

Looks like it would be nigh on impossible to translate the code as it stands: for a start, the returning multiple resultants is not possible (without using a type and therefore not likely to be generic)...

You might be able to break the code down as follows: create a stateful class that represents the "iterator". Use the iteration pattern - the class would have a "next" method that returns "true" when there is snother iteration possible. The "next" takes a method/function pointer, that calculates the next item and stores the result. Sort of like how Borland implemented the sort method in the TList class. Your "iterator" class would need a stack and some kind of statefulness. You'd need some data storage for the iteration result.

You could create a generic iterator in this way by doing something like:

type
  TIterationProc = function(target, stack: TObject): boolean of object;
  TIterator = class
  public
    stack: TObject; //holds data and state
    target: TObject; //is where the data goes
    operation: IterationProc; //moves to next iteration
    function Next(): boolean; //indirectly calls "operation"
  end;

A call to next then calls the TIterationProc (though this could be a method of target I guess, if you want more concrete types to be used.) Operation performs whatever the coder requires to generate the next step and returns true when it is successful. Stack holds the, well, stack. You could implement it however you saw fit really, I made it a TObject to demonstrate it could be any type. Operation is coded to use Target to store the iteration result. You'd assign the instance of whatever data structire you want to use to it, and after calling "Next" the data is updated.

You could then pretty it up by wrapping that mechanism into a class that gives an interface that makes more sense. Wrapper would have the same methods exposed as the iterator, but would encapsulate the fixing up the internal data and typecasting it etc. The data could be exposed as properties for example.

To be honest this is pretty noddy stuff, so I don't want to teach you to suck eggs or anything, but it should be possible to do it.

Reply by email