EJC (C-Compiler) experiments

Anything QL Software or Programming Related.
User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: EJC (C-Compiler) experiments

Post by tofro »

bwinkel67 wrote:...perspective is important, and from a machine code perspective you aren't forced into boundaries that higher level languages put in purposefully.
Ah, well you are basically facing the very same limits in machine code, just later, because machine code programs are generally smaller than high-level language ones. Most machine code programs are written in position-independent (PC-relative) code. This has, however, limits in that it can't address further away than +-32k. Once you reach that limit (which is admittedly pretty high considering the average size of a machine code program), you are faced with the same problem, because now you either need to insert jump islands, some sort of runtime relocation, or register-based addressing (which is also some sort of runtime relocation).

Especially PE programs and programs for high-color machines can easily exceed these limits, even in machine code because the high amount of space occupied by bitmap graphics.

I have reached this limit already several times and what I typically do is reverting to machine code macros along the lines of

Code: Select all

* This macro jumps (in a "PC-relative" way) to a 
* subroutine which would normally be not reachable 
* by a bsr. Use in large programs you dont want to 
* make 'impure'. 
FARJSR          MACRO   target,register   
                EXPAND        
                lea     .lab[.L],[register]           
                add.l   ([register]),[register]           
                jsr     ([register])           
                bra.s   .across[.L]  
.lab[.L]        dc.l    [target]-* 
.across[.L]               
		ENDM  
I use similar macros to address data further away than 32k.


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: EJC (C-Compiler) experiments

Post by bwinkel67 »

Ah yes, I was thinking more of being forced into structures but limitations makes us all get creative :-/


User avatar
Peter
QL Wafer Drive
Posts: 1953
Joined: Sat Jan 22, 2011 8:47 am

Re: EJC (C-Compiler) experiments

Post by Peter »

ql_freak wrote:I have a copy of PDQC also, but afaik it doesn't create reentrant, ROMable code like EJC.
PDQC can create ROMable code, thats the only reason I use it. I compiled the very first working QL-SD driver (long before Adrian's Qubide derivative and Wolfgang's QLWA version) with PDQC.


User avatar
ql_freak
Gold Card
Posts: 354
Joined: Sun Jan 18, 2015 1:29 am

Re: EJC (C-Compiler) experiments

Post by ql_freak »

Sorry for quoting myself.
ql_freak wrote:Albeit there seems to be a bug. If I use:

ex 'cc' , #1 , 'ram1_err_txt' ; 'cc -?'

the help file is written to 'RAM1_err_txt'

But if I use:

ex 'cc' , #1 , 'ram1_err_txt' ; 'cc hello': REMark You MUST NOT write the "_c" suffix (EJC cc is friendly and also allows ".c" :-)

(hello_c contains an error), the error message is NOT written to "RAM1_err_txt" :-(
Now where I have stable version of my ecc compiler driver, I have found out, how to get the error messages from the original EJC cc compiler driver. "cc" prints the error messages only, if it is called with the -v option (switch) for "verbose". This is unusual, verbose option normally prints more informations, but error messages should normally always be printed when there were errors.

In my ecc I have added this, it prints error messages if -v was specified OR if there were errors in pass 1.

Now understanding how to use the compiler, I have written my first real program. Try to write it in another language, it's not so easy I think:

Code: Select all

/* Simple QL/QDOS calculator with expression parser */

#include <stdio.h>
#include <math.h>
#include <val.h>

#define CONBUFLEN 260

int main() {
    char *userin, userinbuf[CONBUFLEN];
    int *rorre=0.;
    double result, x;

    x = 4*atan(1.e0); /* use x for the value of pi (3.14...) */
    printf("Simple QL calculator for evaluating expressions\n");
    printf("Use 'x' for value of pi, e.g. 2*sin(x/6)\n");
    printf("Simplecalc understands all the usual operators and functions such as\n");
    printf("+ - * /  ^ sin cos tan asn acs atn exp log\n");

    for (;;) {
        printf(">");
        userin = gets(userinbuf);
        if (userin[0] == '\0' || !userin) {
            printf("By...\n");
            exit(0);
        }
        result = val(userin,rorre,x,0.);
        if (*rorre)
            printf("Error in expression\n");
        else
            printf("%.14g\n",result);
    }
}
NOT BAD FOR A PROGRAM WITH JUST 33 LINES OF CODE

I have attached the program (with source) in the zipfile and a screenshot which shows how it is compiled and some example calculations (to quit just press enter at the > prompt) AND the wonderfully MicroEMACS with syntax hilighting - a dream :-)
simplecalcWithEJC.png
Attachments
simplecalc.zip
(11.16 KiB) Downloaded 98 times


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
User avatar
pjw
QL Wafer Drive
Posts: 1286
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: EJC (C-Compiler) experiments

Post by pjw »

Nice one, ql-freak :) Of course theres a whole lot more going on in the 20k code than your 33 lines.. but let me not rain on your picnic. A val function has often been missed in SuperBASIC. One can achieve something similar now by using a slave SBASIC. But not with 16 digit precision!

I know its only a simple POC, but you may want to add a check for divide by zero: 1/0 returns 0.


Per
dont be happy. worry
- ?
User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: EJC (C-Compiler) experiments

Post by bwinkel67 »

Congrats on getting the compile to work. It can be a pain to figure these things out but once you do you are on your way :)

Wow, 21K for a 1K source, that's a bit bloated...the val call is adding a bunch of library code with it. My original interpreter (cl.zip), with no graphics but full expression tree that I implemetned was a little over 30k with Digital 'C' SE...but that accounts for a full BASIC parse tree as well and some command line stuff.

Curious what a 50K source file would give but I don't expect it to grow linear as once all the libraries code is added then what's left is the code written. I currently have a 65K source file compile down to 45K but still find that a bit too big for my taste.
Last edited by bwinkel67 on Mon Jul 06, 2020 12:44 am, edited 1 time in total.


User avatar
ql_freak
Gold Card
Posts: 354
Joined: Sun Jan 18, 2015 1:29 am

Re: EJC (C-Compiler) experiments

Post by ql_freak »

@pjw:
Now as I know how to work with EJC I perhaps try to port my Coca (there I have written the expression parser myself) for EJC (at least a command line version). My parser detects divisions by 0 and has support for variables and allows spaces between the tokens, e.g.:

tax = 1 + 19/100
brutto = 9,34 * tax

This was just a test (especially for me), that I can now work with the compiler.


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
User avatar
ql_freak
Gold Card
Posts: 354
Joined: Sun Jan 18, 2015 1:29 am

Re: EJC (C-Compiler) experiments

Post by ql_freak »

bwinkel67 wrote:Wow, 21K for a 1K source, that's a bit bloated...the val call is adding a bunch of library code with it.
The BIG thing is <stdio.h>. Especially for K&R compilers a lot of functions are inside of stdio.h, which are in other header files in ANSI C. Unfortunately you need the scanf() function, cause it eases the writing of an expression parser a lot.


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
User avatar
ql_freak
Gold Card
Posts: 354
Joined: Sun Jan 18, 2015 1:29 am

Re: EJC (C-Compiler) experiments

Post by ql_freak »

Peter wrote:PDQC can create ROMable code, thats the only reason I use it. I compiled the very first working QL-SD driver (long before Adrian's Qubide derivative and Wolfgang's QLWA version) with PDQC.
Hi Peter,

thank you! I will have a look at it.

Ciao Peter


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: EJC (C-Compiler) experiments

Post by NormanDunbar »

Morning ql_freak.

A nice little calculator there, and well done on figuring it all out in the end.

Code: Select all

userin = gets(userinbuf);
Most people I know strongly advise against using gets() for the simple reason that it leaves one susceptable to a buffer overflow. Gcc advise the use of getline() instead, as we probably don't have that, a better alternative might be fgets():

Code: Select all

char *fgets(char *str, int n, FILE *stream)
you can limit the number of characters read in and help prevent a crash.


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