C68Port - A (LONG!) proposal

Anything QL Software or Programming Related.
User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

C68Port - A (LONG!) proposal

Post by NormanDunbar »

Ok, this is a thought experiment at the moment, but you never know what might appear at some point in the future. As we know, Time, jobs, family and illnesses (mine and other peoples') all conspire to get in the way of our valuable QLing time.

The Problem(s)

There's no source code (available) for CPort, so if we need to make changes, we have to look into the grammar file, or the libCPORT library, etc. Not ideal. Well, not for me that is.

So, given this, plus the seemingly large number of foibles that CPort has, I thought that I might as well attempt to write a new version, with some changes that I want to see, and maybe, improve (!) things.

The plan is to continue to use libCPORT, after all, why bother reinventing the wheel? It may need some additional code added, but time will tell. There may be toolkits out there that are very popular - DJToolkit anyone? - and which might be useful if included in the library, or even, a separate toolkit based library. (LibTurboTK, libDJTK?)

I've been thinking about any CPort problems that I'm aware of - but it's been a long while since I used CPort, so I'm probably a bit rusty.

Did I mention I'm planning to write it all in assembler? No? That's because I'm not! :-)


SuperBASIC Source Files

I intend for the source code to be a _SAV file, created by QSAVE (or SMSQ). Hopefully, BBQL users will still be able to compile/convert a file. We shall see.

I never liked the SuperCharge, Turbo, CPort manner of compiling the resident SuperBASIC program. So, a _SAV file it will be. It's the same thing after all, and should work in an identical manner, but those of us on BBQL with limited RAM might find that a quick QSAVE: NEW: EX C68Port ... a valid working solution. Maybe! Probably followed by a QLOAD: ED: etc!


Ok, here are my initial list of foibles and potential solutions.


FOR loops

When a FOR loop in SuperBASIC ends, the loop variable, always floating point, unless Minerva is used, holds the final value in the list of values. In C, the value is one (step) more than the final value.

I propose "fixing" this by the simply addition of an extra line of code, from this:

Code: Select all

IMPLICIT% x
...
FOR x = 1 to 10 step whatever
   ...
END FOR x
To this:

Code: Select all

short x;    // This might be a candidate for globals.h of course!
...
for (x = 1; x <= 10; x++) {
   ...
}
x = 10;
Obviously, the type of 'x' depends on IMPLICIT% and such like, and we would want to try and avoid 'x' having been declared previously to this call. Problems problems eh?

See also Ranges below for other problems.


Variables - Global

In SuperBASIC, any variable declared in the main part of the program, or in any called PROCedure or FuNction, becomes globally visible. In C this is totally different where any variable declared within a function is restricted in scope to that particular function and unless passed as a parameter, to no other called functions.

To this end, to replicate the behaviour of SuperBASIC, my thoughts are to scan the program (pass 1) and write out a globals.h file containing every variable declared in the entire program, that is not declared LOCal. This globals.h file will be #included by the converted C code.


Variables - Local

In SuperBASIC, any variable declared in any called PROCedure or FuNction, as a LOCal variable, is 'globally' visible to all called PROCedures or FuNctions until the defining PROCedure or FuNction ends. In C this is totally different where any variable declared within a function is restricted in scope to that particular function and unless passed as a parameter, to no other called functions. Houston, we have a problem!

At the moment, I'm thinking of setting up some support code to enable this to be the same in any compiled/converted programs, as follows, and it gets messy here! (Final details are yet to be thought out - so thoughts may change)

I think we need a setLOcal() and a getLocal() function to set or get the value of a local parameter, or the C68 version of one anyway. Due to this being C and not C++, overloading would require different names, so:

Code: Select all

float getLocal(char *VariableName);
short getLocal_i(char *VariableName);
char *getLocal_s(char *VariableName);

short setLocal(char *VariableName, float newValue);
short setLocal_i(char *VariableName, short newValue);
short *setLocal_s(char *VariableName, char *newValue);
Don't ask me about arrays, multi-dimensional or whatever, just yet! ;-)

The LOCal variables "stack" will be an array (how big?) of pointers to a linked list of variables, possibly of the following node type, which has no idea of what to do with arrays, for now:

Code: Select all

typedef struct SB_LOCAL {
    short type;
    char[howBig?] varName;  // Maybe a char* or whatever.
    union {
        short value_i;
        float value;
        char *value_s;
    }
} SB_LOCAL;

I'm not showing next/prev pointers etc here.

The thought is to build a linked list of the above nodes, one for each LOCal variable in a PROCedure or FuNction, then push() the root pointer to the list, onto the stack of list pointers mentioned above. As we exit from a PROCedure or FuNction, pop() the pointer off and delete the list entries and the list.

When we need a LOCal, use getLocal() to fetch the value.
When we need to change a LOCal, use setLocal() to fetch the value.

We would scan the entire stack of locals, in their linked lists, from TOS to BOS until we come across the first one that matches the supplied name, and use that. Maybe, just keep a pointer to it handy somewhere, it depends, in case we need to read it or write it again?

Sounds complicated, I admit, but it's the only way I can think of to replicate the SuperBASIC behaviour in a C program. I'm trying here to get a working program "first time" without needing any manipulations to get the generated C code working/compiling - that way, frustration leads. Why? Years ago, I wrote a program in SuperBASIC and it worked well, but I wanted it in C. I used CPort on it and it converted happily, but it took me as long to tidy it all up so that it would compile and execute than if I had simply written it again from scratch in C.


Ranges

FOR loops, SELECT ON clauses and similar, take ranges of values. For example:

Code: Select all

FOR x = 1 to 5, 7 to 9 step 0.01, 123.5, 616 to 666 step 0.5
   ...
END FOR x
So what the hell would that look like in C? One idea (if it can be called such) that sort of ambles to mind would be to:

Create a temporary function with the code in it that corresponds to the body of the above loop, perhaps in a separate file, then in the main body of the program where the above loop is executed, call the function with each value in turn:

Code: Select all

for (short x = 1; x <= 5; x++) {tempForXFunction(x);}
for (float x = 7.0; x <= 9.0; x += 0.01) {tempForXFunction(x);}
tempForXFunction(123.5);
for (float x = 616; x <= 666; x += 0.5) {tempForXFunction(x);}
float x = 666.0;    // Another candidate for globals.h perhaps?
Looks pretty cr4p to me though! How do we handle EXIT X or NEXT X in this case? It's not quite as atomic as SuperBASIC would be.

Hmm, perhaps NEXT X would simply be a return, which would kick off the next iteration.


LibCPORT

Dave Walker's version of libCPORT is different from the one on Dilwyn's 'Sinclair QL Homepage' web site - I'm assuming Dave's is the de-facto one, but, is there another version out there in userland that I'm not aware of yet? (I'm not at my QL because I'm working, so I can't check versions yet!)


Right then, anyone interested? Any further comments? Is it worth pursuing? I'm intending for this to be free by the way. And open source. And on Github, so anyone can join in with the hard work!


Minerva Integer Tokenisation

Apparently, this has to always be turned off when using CPort. Does anyone know why? What effect did it have? If I remember correctly, and I don't have Minerva to check, it does something similar to IMPLICIT% for REPEat, FOR loops etc?

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
stevepoole
Super Gold Card
Posts: 712
Joined: Mon Nov 24, 2014 2:03 pm

Re: C68Port - A (LONG!) proposal

Post by stevepoole »

Hi Norm,
For well over a year, two Quanta members and I have been converting a SuperBasic program, (well over 80 pages long) into C.
We used turbo, CPort and CFix to get Cee code. But then there was the problem that CPort Cee uses many constructs which are internal to the QL, so the Cee wouldn't run under windows... So we had to rewrite all the QL specifics in standard Cee ourselves. There was a write-up in Quanta...
Then there was the problem of graphics output : We used the QUINCY compiler to tweak code, with a Borland Graphics file included to get output. This worked.
Now you are talking of putting code on GitHub as OpenSource. So the Cee code needs to be VisualStudio compliant, meaning using Microsoft graphics instead...
But Cee code is not too convenient to convert SuperBasic from...better to use C++ for PRINT and INPUT...
FOR loops are indeed awkward to deal with, as many QL programs use the '0' index in a special way. Just adding 1 to indexes may sometimes work, but you have to subtract it again at some point for the code to make sense.
This is not a criticism of your project, just a statement briefly defining a few of the problems encountered. But there have been posts on the QLForum which stated that other programs than C68 transcode SB into CEE directly, with no need to tweak.
But your project is a fascinating one, and I am sure there is a real need to swap programs to and from C++.
Best Wishes,
Steve.


User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: C68Port - A (LONG!) proposal

Post by NormanDunbar »

Hi Steve,
stevepoole wrote:Hi Norm,
For well over a year, two Quanta members and I have been converting a SuperBasic program, (well over 80 pages long) into C.
We used turbo, CPort and CFix to get Cee code. But then there was the problem that CPort Cee uses many constructs which are internal to the QL, so the Cee wouldn't run under windows... So we had to rewrite all the QL specifics in standard Cee ourselves. There was a write-up in Quanta...
I think there's two separate "problems" being described here. The SB->C conversion and the QL->whatever port. CPort does the first, and I know of no tools that do the latter, other than the programmer him/herself. CPort, after all, was designed to be run on a QL and nothing else. Porting even standard C code requires a lot of compromise - look at cross platform code and see how many #ifdefs you see!
stevepoole wrote:Then there was the problem of graphics output : We used the QUINCY compiler to tweak code, with a Borland Graphics file included to get output. This worked.
If you are talking about the Quincy compiler system, then it's not really a compiler. It's an IDE, written by Al Stevens (or Stephens) many years ago, to provide a free set of C programming tools - including the MinGW C++ compiler. I used it many years ago. I don't think it's been updated recently though, but I might be wrong. Ironically, if I remember, the code is written in Visual C/C++ rather than using its 'own' MingW compiler. I also think it pre-dates 64 bit computing, so unless there's an easy way to upgrade the compiler to use the 64 bit MinGW one, it won't do 64 bit.

Quincy is Windows only though, so even what you got to work on Windows might not work on Mac or Unix systems - probably including the graphics.

Somewhere, in my collection, I might have the original articles from Dr Dobb's Journal, where the project was documented. I may have a look later. I think he wrote it for a book/tutorial series on C++programming.
stevepoole wrote:Now you are talking of putting code on GitHub as OpenSource. So the Cee code needs to be VisualStudio compliant, meaning using Microsoft graphics instead...
Nope! The code will be open source for anyone [here] to use and abuse. Converted programs need not use Microsoft (Windows) graphics at all. The intention of C68Port, if it sees the light of day, is to convert SB->C but definitely not to port QL->whatever. So any graphics in the SB program should be converted to similar C calls to do exactly the same thing.

It most certainly will not be Visual C++ compliant for a number of reasons, mainly that Visual C++ these days is .net, so bears more resemblance to Java (hack, spit!) than to C++ and, even before it was .net and was still proper C++, it was so uncompliant with the standards that most standards compliant code would simply not compile on Visual C++. This applies to Visual C too, the plain vanilla C code, not C++. I had major problems converting a C program to compile under Windows Visual C.

I've put a small eRant about Visual C on https://github.com/NormanDunbar/TraceMiner - scroll down to the "compiling with Visual C" for details. Simple stuff that simply will not compile. Visual C is not even ANSI compatible.

My cross platform C and C++ variant of choice is QT - all the graphics (unless you go DirectX, and even then, at least Linux can do DirectX) are cross platform. The same code compiles on Linux, Unix, BSD, MACos, and Windows, amongst others. It even does Android and possibly iOS as well - but I don't develop for phones or tablets so I've not tried.

So, if you want graphics to be easily cross platform, QT is the way to go. There may be other systems but I don;t know of, or use them.
stevepoole wrote:But Cee code is not too convenient to convert SuperBasic from...better to use C++ for PRINT and INPUT...
Indeed. C's input and output routines are a tad fragile and prone to (programmer) error allowing buffer overruns and all sorts of nasties.
stevepoole wrote:FOR loops are indeed awkward to deal with, as many QL programs use the '0' index in a special way. Just adding 1 to indexes may sometimes work, but you have to subtract it again at some point for the code to make sense.
I'm not sure what you refrer to here Steve, sorry. Unless you mean Array indexing?
stevepoole wrote:This is not a criticism of your project, just a statement briefly defining a few of the problems encountered. But there have been posts on the QLForum which stated that other programs than C68 transcode SB into CEE directly, with no need to tweak.
No problem. As I say, it's a thought experiment at the moment. I was "thinking aloud" here to see if there was any interest. And maybe, if I care to admit it, flush out someone who has the source code for the existing CPort!



Cheers
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
XorA
Site Admin
Posts: 1358
Joined: Thu Jun 02, 2011 11:31 am
Location: Shotts, North Lanarkshire, Scotland, UK

Re: C68Port - A (LONG!) proposal

Post by XorA »

Looks pretty cr4p to me though! How do we handle EXIT X or NEXT X in this case? It's not quite as atomic as SuperBASIC would be.
Your probably in the realms of long jump there, but you could probably do it with a goto too.


Derek_Stewart
Font of All Knowledge
Posts: 3929
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: C68Port - A (LONG!) proposal

Post by Derek_Stewart »

Hi,

I am not interested in programming on Windows and probably the programming effort involved would not justify the end result. It would be better to implemement C++ on the QL, which I am always told is not possible.

With regards to CPORT, or more specfically C68 libCPORT, I am sure that the source code could be made available as a starting point to enhance the C Porting process.

The Digitial Precision programme CPORT will probably still be copyright and is a Turbo compiled programme, so unless we can decompile it then the task is hard.

Could the Cport_Grammer file help with the development of something better.


Regards,

Derek
User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: C68Port - A (LONG!) proposal

Post by NormanDunbar »

XorA wrote:Your probably in the realms of long jump there, but you could probably do it with a goto too.
Yes, I thought about that, then immediately discounted it. I hate setjmp and longjmp calls - too hard for my tiny brain to figure out where the hell I came from to get here! :(

The other way is to set flags all over the place.

Or, dare I say it, use a goto! :o :shock: :twisted:

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: C68Port - A (LONG!) proposal

Post by NormanDunbar »

Hi Derek,
Derek_Stewart wrote:I am not interested in programming on Windows and probably the programming effort involved would not justify the end result. It would be better to implemement C++ on the QL, which I am always told is not possible.
It might be possible, maybe porting G++ but I have to admit, trying to follow even the "how to compile" instructions for that is a nightmare!
Derek_Stewart wrote:With regards to CPORT, or more specfically C68 libCPORT, I am sure that the source code could be made available as a starting point to enhance the C Porting process.
There are sources for libCPORT on Dave Walker's and Dilwyn's web sites, that's not a problem, CPort, on the other hand has no (known) sources available that I know of.

Chas Dillon's program sources have been made available, but sadly not CPort.
Derek_Stewart wrote:The Digitial Precision programme CPORT will probably still be copyright and is a Turbo compiled programme, so unless we can decompile it then the task is hard./quote]
I'm thinking "nightmare" to be honest.
Derek_Stewart wrote:Could the Cport_Grammer file help with the development of something better.
Not really. I'm hoping to do it without a grammar file. The format of the current grammar file, according to the docs I've found, is somewhat unknown.


Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: C68Port - A (LONG!) proposal

Post by tofro »

Norman,

you could simply push all the functions that belong to a call chain using LOCal variables into a separate compilation unit and make these locals static globals there.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: C68Port - A (LONG!) proposal

Post by NormanDunbar »

Hi Tobias,

I never thought of that! I'll definitely look into that.

Thanks.

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: C68Port - A (LONG!) proposal

Post by NormanDunbar »

Morning Tobias,

I looked into statics as you suggested and it works fine, until I hit recursion. Then, unfortunately, it doesn't work as the local variables get overwritten by each recursive call. Damn!

Back to the drawing board!

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
Post Reply