Author Topic: PulsarBASIC - Teaser thread  (Read 9690 times)

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
PulsarBASIC - Teaser thread
« on: June 10, 2019, 10:45:11 AM »
So it's a while since I started combining the Pulsar2D framework with the My_Basic interpreter. Until today I had problems with DATA & READ but the issue could be solved today. There is no download, yet. It's a rather complicated compilation on Windows because I did not port the Library to C. Yeah, I am not so fluent in C, so I felt this wouldn't work. Anyway, I figured out that it is possible to compile a library with FreeBASIC so it can be used from C. The "only" thing is providing a *h.-file. And still the pulsarbasic.c file has about 2700 lines.
Anyway, this might be interesting for drfloyd since I am providing a tiny editor. So one can start the editor, load a file, press run and that's it. (The editor is based on my old project TinyIDE from 2010 and compiled with Lazarus.)
So the funny thing for me as a developer is that I am actually using 3 programming languages and compilers: ANSI C (gcc), BASIC (FreeBASIC) and Object Pascal (FreePascal). Can it be more versatile?
I hope I can provide a download soon.


Aurel

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #1 on: June 10, 2019, 01:05:51 PM »
It looks interesting even i am not very much in game programming.  ;)
..for drFloyd ...hmm he just jumping from place to place ,
looking for "perfect" replacement for Blitz Basic.

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
Re: PulsarBASIC - Teaser thread
« Reply #2 on: June 10, 2019, 03:53:08 PM »
Yes, that's right. Anyway, I think this is a project I will push further. There are a few things I want to implement, most important of all the creation of executables.
Oh, btw, I am using now the old editor of EGSL which is now the PulsarBASIC-Editor as seen in the screenshot.

Aurel

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #3 on: June 10, 2019, 06:34:13 PM »
Quote
There are a few things I want to implement, most important of all the creation of executables.

That should be no problem on Windows.
Using BIND topology : runtime.exe + sourcefile(in binary form- not ascii file).
That technic i was used in Aurel Basic long time ago.

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
Re: PulsarBASIC - Teaser thread
« Reply #4 on: June 10, 2019, 07:18:01 PM »
Yes, that's the technique I am using with PulsarLua. But it's a bit harder to implement it in C ...

Aurel

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #5 on: June 10, 2019, 09:25:48 PM »
well yes
but must be there some C example about that ?

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
Re: PulsarBASIC - Teaser thread
« Reply #6 on: June 11, 2019, 07:15:59 AM »
I didn't find one, yet. So if anyone has an example, feel free to post it here.  ;)

Aurel

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #7 on: June 11, 2019, 07:26:58 PM »
I found it long time ago somewhere but i don't know now ...

Ed Davis

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #8 on: June 12, 2019, 02:05:22 AM »
I didn't find one, yet. So if anyone has an example, feel free to post it here.  ;)
I didn't find one, yet. So if anyone has an example, feel free to post it here.  ;)
How about this?
First, the binder - to compile:  gcc -s -Os -o binder binder.c
Code: [Select]
/*
--binder=> bind runtime script output-filename -----------

To build: gcc -s -Os -o binder.exe binder.c

ed_davis2@yahoo.com

arg[1] = runtime
arg[2] = script
arg[3] = output-filename

copy_file(arg[1], arg[3]) -- copy runtime to output
copy_file(arg[2], arg[3], APPEND) -- append script to output

--append runtime length
write(arg[3], format(filesize(arg[1]):8:'0'), APPEND)
-- append script length
write(arg[3], format(filesize(arg[2]):8:'0'), APPEND)
-- append a pity eyecatcher
write(arg[3], format("Southern":8:'0'), APPEND)
halt

--interpreter---------------------------------------------------

-- find the size of the runtime
f = open(arg[0], "r")
seek(f, -24, SEEK_END)
new string buf(8)
read(f, buf, buf.size)
runtime_size = val(buf)

read(f, buf, buf.size)
script_size = val(buf)

read(f, buf, buf.size)
if buf <> "Southern" error("Eyecatcher not found!!!")

-- read in the script
seek(f, runtime_size, SEEK_SET)

new string buf(script_size)
read(f, buf, script_size)
close(f)

run(buf)
halt
*/

#include <stdio.h>
#include <string.h>
#include <errno.h>

#if defined(__linux__)
#include <unistd.h>
#include <sys/stat.h>
#define stricmp strcasecmp
#endif

enum {n_interp = 1, n_script = 2, n_final = 3, REPLY_SIZE = 4};

int main(int argc, char *argv[]) {
    FILE *interp, *script, *final;
    int c, rt_size, script_size;

    if (argc < 4) {
        printf("format: binder interp script output-file\n");
        return 2;
    }

    interp = fopen(argv[n_interp], "rb");
    if (!interp) {
        perror(argv[n_interp]);
        return 2;
    }

    script = fopen(argv[n_script], "rb");
    if (!script) {
        perror(argv[n_script]);
        return 2;
    }

    /* don't overwrite output without confirmation */
    final = fopen(argv[n_final], "rb");
    if (final) {
        char buf[REPLY_SIZE];

        fclose(final);
        printf("File %s exists - delete it? (y/n)\n", argv[n_final]);
        if (!fgets(buf, REPLY_SIZE, stdin)) {
            printf("Nothing ventured, nothing gained\n");
            return 2;
        }
        if (buf[0] != 'y') {
            printf("Please try again later\n");
            return 2;
        }
    }

    final = fopen(argv[n_final], "wb");
    if (!final) {
        perror(argv[n_final]);
        return 2;
    }

    rt_size = 0;
    while ((c = fgetc(interp)) != EOF) {
        fputc(c, final);
        ++rt_size;
    }
    fclose(interp);
    printf("Interp size is %d\n", rt_size);

    script_size = 0;
    while ((c = fgetc(script)) != EOF) {
        fputc(c, final);
        ++script_size;
    }
    fclose(script);
    printf("Script size is %d\n", script_size);

    fprintf(final, "%08d", rt_size);
    fprintf(final, "%08d", script_size);
    fprintf(final, "31415926");
    fclose(final);
    printf("%s size is %d + %d + %d = %d\n", argv[n_final],
        rt_size, script_size, 24, rt_size+script_size+24);
#if defined(__linux__)
    chmod(argv[n_final], 0755);
#endif

    printf("%s bound to %s in %s\n", argv[n_script], argv[n_interp], argv[n_final]);
    return 0;
}

Then the interpreter - to compile: gcc -s -Os -o pl0 pl0.c
Just showing the "load the code routine here".  Complete interpreter is attached as pl0.c.
Code: [Select]
/*------------------------------------------------------------------------
  -- find the size of the runtime
  f = open(arg[0], "r")
  seek(f, -24, SEEK_END)
  new string buf(8)
  read(f, buf, buf.size)
  runtime_size = val(buf)

  read(f, buf, buf.size)
  script_size = val(buf)

  read(f, buf, buf.size)
  if buf <> "Southern" error("Eyecatcher not found!!!")

  -- read in the script
  seek(f, runtime_size, SEEK_SET)

  new string buf(script_size)
  read(f, buf, script_size)
  close(f)

  data is stored in 3 8 char fields:

  0..7:   size of the exe
  8..15:  size of the appended script
  16..23: eyecatcher
 ------------------------------------------------------------------------*/
int load_script(void) {
    FILE *fp;
    char buf[24], buf2[9];
    int size_read, rt_size;
    char exe_name[PATH_MAX];

/* get the exec name */
#if defined(__WIN32)
    GetModuleFileName(NULL, exe_name, MAX_PATH);
#elif defined(__linux__)
    char linkname[PATH_MAX];
    struct stat finfo;
    int len;

    sprintf(linkname, "/proc/%d/exe", getpid());
    if ((len = readlink(linkname, exe_name, PATH_MAX - 1)) > 0) {
        exe_name[len] = '\0';
    } else {
        perror("Error: ");
        return false;
    }
#endif

    fp = fopen(exe_name, "rb");
    if (!fp) {
        perror(exe_name);
        return false;
    }
    /* 24 bytes from end, to read 3 fields noted above */
    if (fseek(fp, -24, SEEK_END) != 0) {
        perror("fseek: ");
        return false;
    }

    /* read all 3 fields */
    size_read = fread(buf, 1, sizeof(buf), fp);
    /* eyecather matches? (3rd field) */
    if (memcmp(&buf[16], "31415926", 8) != 0) {
        printf("Eyecatcher not found\n");
        return false;
    }

    /* first field, the exe length */
    memcpy(buf2, buf, 8);
    buf2[8] = '\0';
    rt_size = strtol(buf2, NULL, 10);

    /* second field, the script length */
    memcpy(buf2, &buf[8], 8);
    buf2[8] = '\0';
    script_size = strtol(buf2, NULL, 10);

    script = malloc(script_size);

    /* seek to the start of the script */
    if (fseek(fp, rt_size, SEEK_SET) != 0) {
        perror("fseek: ");
        return false;
    }

    size_read = fread(script, 1, script_size, fp);
    fclose(fp);
    if (size_read != script_size) {
        printf("Could not read entire script: asked %d got %d\n", script_size, size_read);
        return false;
    }
    return true;
}

And a simple script to be bound:
Code: [Select]
const left = 0, middle = 1, right = 2;

procedure move(n, source, aux, dest);

    procedure printmove();

        procedure printpole(p);
        begin
            if p = 0 then
                write('left  ');
            elseif p = 1 then
                write('middle');
            elseif p = 2 then
                write('right ');
            end;
        end;

    begin {printmove}
        write('Move a disk from ');  printpole(source);
        write(' to ');               printpole(dest);
        writeln();
    end;

begin {move}
    if n = 1 then
        printmove();
    else
        move(n-1, source, dest, aux);
        printmove();
        move(n-1, aux, source, dest);
    end;
end;

var disks;

begin
    repeat
        writeln();
        write('Number of disks (2-10, 1 to stop)? ');
        read(disks);
        if (disks > 1) and (disks <= 10) then
            writeln();
            writeln('For ', disks, ' disks, the required moves are:');
            writeln();
            move(disks, left, middle, right);
        end;
    until disks = 1;
end.

To bind:

binder pl0 hanoi.pl0 hhh
(binder pl0.exe hanoi.pl0 hhh.exe on Windows)

Tested under Windows and Linux.
Let me know if you have questions/problems.

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
Re: PulsarBASIC - Teaser thread
« Reply #9 on: June 12, 2019, 03:52:12 PM »
Ok, thanks that's what I was looking for. So far as I can see, one can't start a script simply by writing
Code: [Select]
pl0 hanoi.pl0
Error is
Quote
Eyecatcher not found
Would of course be nice that one could use the interpreter in both ways... well, I will have a closer look on the weekend.

Ed Davis

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #10 on: June 12, 2019, 03:57:22 PM »
Ok, thanks that's what I was looking for. So far as I can see, one can't start a script simply by writing
Code: [Select]
pl0 hanoi.pl0
Error is
Quote
Eyecatcher not found
Would of course be nice that one could use the interpreter in both ways... well, I will have a closer look on the weekend.

Whoops!  In my original version, you could do that, but I remove the code :-)

Also, I was brain-dead when I wrote this.  Really only need the script size, not the runtime size.

If you are interested, I can post a new version with both features mentioned above.

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
Re: PulsarBASIC - Teaser thread
« Reply #11 on: June 12, 2019, 05:32:13 PM »
Whoops!  In my original version, you could do that, but I remove the code :-)

Also, I was brain-dead when I wrote this.  Really only need the script size, not the runtime size.

If you are interested, I can post a new version with both features mentioned above.
That would be highly appreciated.  :D
I think I will this first implement in AllegroBASIC since it is easier to compile (C only).
« Last Edit: June 12, 2019, 06:16:02 PM by Cybermonkey »

Aurel

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #12 on: June 12, 2019, 06:30:42 PM »
Yes Ed post it..

My own version is written long time ago in Emergence basic

runtime.exe  put it into memory - size let say 100

source.bas - put in another memory block in binary form - size let say 50

concat two memory blocks into  one


my_runtime = mem1 + mem2


save runtime on disk  as exe file

when you run your program runtime jump to location of 101 to read source
and start processing it until the end of file is reached.

Is that ok?

Ed Davis

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #13 on: June 12, 2019, 07:58:46 PM »
If you are interested, I can post a new version with both features mentioned above.
That would be highly appreciated.  :D

New version is attached.

Ed Davis

  • Guest
Re: PulsarBASIC - Teaser thread
« Reply #14 on: June 13, 2019, 07:52:44 AM »
My own version is written long time ago in Emergence basic

runtime.exe  put it into memory - size let say 100

source.bas - put in another memory block in binary form - size let say 50

concat two memory blocks into  one


my_runtime = mem1 + mem2


save runtime on disk  as exe file

when you run your program runtime jump to location of 101 to read source
and start processing it until the end of file is reached.

Is that ok?

If it works, then it is ok!
:-)