From: Greg King Date: Sun, 25 Aug 2013 04:31:36 +0000 (-0400) Subject: Made an exec() program-chaining function for the Commodore libraries. X-Git-Tag: V2.15~236^2~4 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=172ce143498cd810816e12d19f835ecf2d309ec5;p=cc65 Made an exec() program-chaining function for the Commodore libraries. --- diff --git a/libsrc/cbm/exec.c b/libsrc/cbm/exec.c new file mode 100644 index 000000000..302115c17 --- /dev/null +++ b/libsrc/cbm/exec.c @@ -0,0 +1,99 @@ +/* +** Program-chaining function for Commodore platforms. +** +** 2013-08-24, Greg King +** +** This function exploits the program-chaining feature in CBM BASIC's ROM. +** It puts the desired program's name and unit number into a LOAD statement. +** Then, it points BASIC to that statement, so that the ROM will run that +** statement after this program quits. The ROM will load the next program, +** and execute it. +*/ + +#include +#include +#include +#include +#include +#include +#if defined(__CBM610__) +# include +#elif defined(__CBM510__) +# include +#endif + + +#pragma data-name(push, "LOWCODE") +static struct line { + const char end_of_line; + const struct line *const next; + const unsigned line_num; + const char load_token, quotes[2], add_token, quote; + char name[21]; + const char comma; + char unit[3]; +} basic = { + '\0', &basic + 1, /* high byte must be non-zero */ + 0, 0x93, + + /* This string operation copies the name to high BASIC RAM. + ** So, it won't be overwritten when the next program is loaded. + */ + "\"\"", 0xaa, '\"', + "\" ", /* format: "123:1234567890123456\"" */ + ',', "01" +}; +#pragma data-name(pop) + +/* These values are platform-specific. */ +extern const struct line *txtptr; +#pragma zpsym("txtptr") +extern char basbuf[]; /* BASIC's input buffer */ +extern void basbuf_len[]; +#pragma zpsym("basbuf_len") + + +int __fastcall__ exec (const char* progname, const char* cmdline) +{ + static int fd; + static unsigned char dv, n = 0; + + /* Exclude devices that can't load files. */ + dv = getcurrentdevice (); + if (dv < 8 && dv != 1 || dv > 30) { + return _mappederrno (9); /* illegal device number */ + } + utoa (dv, basic.unit, 10); + + /* Don't try to run a program that can't be found. */ + fd = open (progname, O_RDONLY); + if (fd < 0) { + return fd; + } + close (fd); + + do { + if ((basic.name[n] = progname[n]) == '\0') { + break; + } + } while (++n < 20); /* truncate long names */ + basic.name[n] = '\"'; + + /* Build the next program's argument list. */ + basbuf[0] = 0x8f; /* REM token */ + basbuf[1] = '\0'; + if (cmdline != NULL) { + strncat (basbuf, cmdline, (size_t)basbuf_len - 2); + } + +#if defined(__CBM510__) || defined(__CBM610__) + pokewsys ((unsigned)&txtptr, (unsigned)&basic); +#else + txtptr = &basic; +#endif + + /* (The return code, in ST, will be destroyed by LOAD. + ** So, don't bother to set it here.) + */ + exit (__AX__); +}