Retrogamecoding(.org) > Announcements

PulsarBASIC - Teaser thread

<< < (2/7) > >>

Aurel:
well yes
but must be there some C example about that ?

Cybermonkey:
I didn't find one, yet. So if anyone has an example, feel free to post it here.  ;)

Aurel:
I found it long time ago somewhere but i don't know now ...

Ed Davis:

--- Quote from: Cybermonkey 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.  ;)

--- End quote ---

--- Quote from: Cybermonkey 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.  ;)

--- End quote ---
How about this?
First, the binder - to compile:  gcc -s -Os -o binder binder.c

--- Code: ---/*
--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;
}

--- End code ---

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: ---/*------------------------------------------------------------------------
  -- 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;
}

--- End code ---

And a simple script to be bound:

--- Code: ---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.

--- End code ---

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:
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: ---pl0 hanoi.pl0
--- End code ---

Error is

--- Quote ---Eyecatcher not found
--- End quote ---
Would of course be nice that one could use the interpreter in both ways... well, I will have a closer look on the weekend.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version