svn commit: r280656 - projects/lua-bootloader/sys/boot/common
Rui Paulo
rpaulo at FreeBSD.org
Thu Mar 26 03:43:41 UTC 2015
Author: rpaulo
Date: Thu Mar 26 03:43:38 2015
New Revision: 280656
URL: https://svnweb.freebsd.org/changeset/base/280656
Log:
Split the interpreter code to make it easy to support Forth, Lua and
the barebones interpreter.
Submitted by: Pedro Souza
Added:
projects/lua-bootloader/sys/boot/common/interp.h (contents, props changed)
projects/lua-bootloader/sys/boot/common/interp_simple.c (contents, props changed)
Modified:
projects/lua-bootloader/sys/boot/common/interp.c
projects/lua-bootloader/sys/boot/common/interp_forth.c
Modified: projects/lua-bootloader/sys/boot/common/interp.c
==============================================================================
--- projects/lua-bootloader/sys/boot/common/interp.c Thu Mar 26 03:05:07 2015 (r280655)
+++ projects/lua-bootloader/sys/boot/common/interp.c Thu Mar 26 03:43:38 2015 (r280656)
@@ -23,7 +23,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -36,113 +35,64 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include <string.h>
#include "bootstrap.h"
+#include "interp.h"
-#ifdef BOOT_FORTH
-#include "ficl.h"
-#define RETURN(x) stackPushINT(bf_vm->pStack,!x); return(x)
-
-extern FICL_VM *bf_vm;
-#else
-#define RETURN(x) return(x)
-#endif
#define MAXARGS 20 /* maximum number of arguments allowed */
-static void prompt(void);
-
-#ifndef BOOT_FORTH
-static int perform(int argc, char *argv[]);
+struct interp *interp =
+#if defined(BOOT_LUA)
+ &boot_interp_lua;
+#elif defined(BOOT_FORTH)
+ &boot_interp_forth;
+#else
+ &boot_interp_simple;
+#endif
-/*
- * Perform the command
- */
int
-perform(int argc, char *argv[])
+default_load_config(void *ctx)
{
- int result;
- struct bootblk_command **cmdp;
- bootblk_cmd_t *cmd;
-
- if (argc < 1)
- return(CMD_OK);
-
- /* set return defaults; a successful command will override these */
- command_errmsg = command_errbuf;
- strcpy(command_errbuf, "no error message");
- cmd = NULL;
- result = CMD_ERROR;
-
- /* search the command set for the command */
- SET_FOREACH(cmdp, Xcommand_set) {
- if (((*cmdp)->c_name != NULL) && !strcmp(argv[0], (*cmdp)->c_name))
- cmd = (*cmdp)->c_fn;
- }
- if (cmd != NULL) {
- result = (cmd)(argc, argv);
- } else {
- command_errmsg = "unknown command";
- }
- RETURN(result);
+ if (INTERP_INCL(interp, "/boot/loader.rc") != CMD_OK)
+ return INTERP_INCL(interp, "/boot/boot.conf");
+ return CMD_OK;
}
-#endif /* ! BOOT_FORTH */
/*
* Interactive mode
*/
void
-interact(const char *rc)
+interact(const char * rc)
{
- static char input[256]; /* big enough? */
-#ifndef BOOT_FORTH
- int argc;
- char **argv;
-#endif
+ static char input[256]; /* big enough? */
-#ifdef BOOT_FORTH
- bf_init((rc) ? "" : NULL);
-#endif
+ INTERP_INIT(interp);
- if (rc == NULL) {
- /* Read our default configuration. */
- if (include("/boot/loader.rc") != CMD_OK)
- include("/boot/boot.conf");
- } else if (*rc != '\0')
- include(rc);
-
- printf("\n");
-
- /*
- * Before interacting, we might want to autoboot.
- */
- autoboot_maybe();
-
- /*
- * Not autobooting, go manual
- */
- printf("\nType '?' for a list of commands, 'help' for more detailed help.\n");
- if (getenv("prompt") == NULL)
- setenv("prompt", "${interpret}", 1);
- if (getenv("interpret") == NULL)
- setenv("interpret", "OK", 1);
-
-
- for (;;) {
- input[0] = '\0';
- prompt();
- ngets(input, sizeof(input));
-#ifdef BOOT_FORTH
- bf_vm->sourceID.i = 0;
- bf_run(input);
-#else
- if (!parse(&argc, &argv, input)) {
- if (perform(argc, argv))
- printf("%s: %s\n", argv[0], command_errmsg);
- free(argv);
- } else {
- printf("parse error\n");
+ /*
+ * Read our default configuration
+ */
+ INTERP_LOAD_DEF_CONFIG(interp);
+ printf("\n");
+ /*
+ * Before interacting, we might want to autoboot.
+ */
+ autoboot_maybe();
+
+ /*
+ * Not autobooting, go manual
+ */
+ printf("\nType '?' for a list of commands, 'help' for more detailed help.\n");
+ if (getenv("prompt") == NULL)
+ setenv("prompt", "${interpret}", 1);
+ if (getenv("interpret") == NULL)
+ setenv("interpret", "OK", 1);
+
+
+ for (;;) {
+ input[0] = '\0';
+ prompt();
+ ngets(input, sizeof(input));
+ INTERP_RUN(interp, input);
}
-#endif
- }
}
/*
@@ -159,210 +109,87 @@ COMMAND_SET(include, "include", "read co
static int
command_include(int argc, char *argv[])
{
- int i;
- int res;
- char **argvbuf;
-
- /*
- * Since argv is static, we need to save it here.
- */
- argvbuf = (char**) calloc((u_int)argc, sizeof(char*));
- for (i = 0; i < argc; i++)
- argvbuf[i] = strdup(argv[i]);
-
- res=CMD_OK;
- for (i = 1; (i < argc) && (res == CMD_OK); i++)
- res = include(argvbuf[i]);
-
- for (i = 0; i < argc; i++)
- free(argvbuf[i]);
- free(argvbuf);
+ int i;
+ int res;
+ char **argvbuf;
+
+ /*
+ * Since argv is static, we need to save it here.
+ */
+ argvbuf = (char**) calloc((u_int)argc, sizeof(char*));
+ for (i = 0; i < argc; i++)
+ argvbuf[i] = strdup(argv[i]);
+
+ res=CMD_OK;
+ for (i = 1; (i < argc) && (res == CMD_OK); i++)
+ res = INTERP_INCL(interp, argvbuf[i]);
+
+ for (i = 0; i < argc; i++)
+ free(argvbuf[i]);
+ free(argvbuf);
- return(res);
+ return(res);
}
/*
- * Header prepended to each line. The text immediately follows the header.
- * We try to make this short in order to save memory -- the loader has
- * limited memory available, and some of the forth files are very long.
+ * Perform the command
*/
-struct includeline
-{
- struct includeline *next;
-#ifndef BOOT_FORTH
- int flags;
- int line;
-#define SL_QUIET (1<<0)
-#define SL_IGNOREERR (1<<1)
-#endif
- char text[0];
-};
-
int
-include(const char *filename)
+perform(int argc, char *argv[])
{
- struct includeline *script, *se, *sp;
- char input[256]; /* big enough? */
-#ifdef BOOT_FORTH
- int res;
- char *cp;
- int prevsrcid, fd, line;
-#else
- int argc,res;
- char **argv, *cp;
- int fd, flags, line;
-#endif
-
- if (((fd = open(filename, O_RDONLY)) == -1)) {
- sprintf(command_errbuf,"can't open '%s': %s", filename, strerror(errno));
- return(CMD_ERROR);
- }
-
- /*
- * Read the script into memory.
- */
- script = se = NULL;
- line = 0;
-
- while (fgetstr(input, sizeof(input), fd) >= 0) {
- line++;
-#ifdef BOOT_FORTH
- cp = input;
-#else
- flags = 0;
- /* Discard comments */
- if (strncmp(input+strspn(input, " "), "\\ ", 2) == 0)
- continue;
- cp = input;
- /* Echo? */
- if (input[0] == '@') {
- cp++;
- flags |= SL_QUIET;
- }
- /* Error OK? */
- if (input[0] == '-') {
- cp++;
- flags |= SL_IGNOREERR;
- }
-#endif
- /* Allocate script line structure and copy line, flags */
- if (*cp == '\0')
- continue; /* ignore empty line, save memory */
- sp = malloc(sizeof(struct includeline) + strlen(cp) + 1);
- /* On malloc failure (it happens!), free as much as possible and exit */
- if (sp == NULL) {
- while (script != NULL) {
- se = script;
- script = script->next;
- free(se);
- }
- sprintf(command_errbuf, "file '%s' line %d: memory allocation "
- "failure - aborting", filename, line);
- return (CMD_ERROR);
- }
- strcpy(sp->text, cp);
-#ifndef BOOT_FORTH
- sp->flags = flags;
- sp->line = line;
-#endif
- sp->next = NULL;
-
- if (script == NULL) {
- script = sp;
- } else {
- se->next = sp;
- }
- se = sp;
- }
- close(fd);
-
- /*
- * Execute the script
- */
-#ifndef BOOT_FORTH
- argv = NULL;
-#else
- prevsrcid = bf_vm->sourceID.i;
- bf_vm->sourceID.i = fd;
-#endif
- res = CMD_OK;
- for (sp = script; sp != NULL; sp = sp->next) {
-
-#ifdef BOOT_FORTH
- res = bf_run(sp->text);
- if (res != VM_OUTOFTEXT) {
- sprintf(command_errbuf, "Error while including %s, in the line:\n%s", filename, sp->text);
- res = CMD_ERROR;
- break;
- } else
- res = CMD_OK;
-#else
- /* print if not being quiet */
- if (!(sp->flags & SL_QUIET)) {
- prompt();
- printf("%s\n", sp->text);
+ int result;
+ struct bootblk_command **cmdp;
+ bootblk_cmd_t *cmd;
+
+ if (argc < 1)
+ return(CMD_OK);
+
+ /* set return defaults; a successful command will override these */
+ command_errmsg = command_errbuf;
+ strcpy(command_errbuf, "no error message");
+ cmd = NULL;
+ result = CMD_ERROR;
+
+ /* search the command set for the command */
+ SET_FOREACH(cmdp, Xcommand_set) {
+ if (((*cmdp)->c_name != NULL) && !strcmp(argv[0], (*cmdp)->c_name))
+ cmd = (*cmdp)->c_fn;
}
-
- /* Parse the command */
- if (!parse(&argc, &argv, sp->text)) {
- if ((argc > 0) && (perform(argc, argv) != 0)) {
- /* normal command */
- printf("%s: %s\n", argv[0], command_errmsg);
- if (!(sp->flags & SL_IGNOREERR)) {
- res=CMD_ERROR;
- break;
- }
- }
- free(argv);
- argv = NULL;
+ if (cmd != NULL) {
+ result = (cmd)(argc, argv);
} else {
- printf("%s line %d: parse error\n", filename, sp->line);
- res=CMD_ERROR;
- break;
+ command_errmsg = "unknown command";
}
-#endif
- }
-#ifndef BOOT_FORTH
- if (argv != NULL)
- free(argv);
-#else
- bf_vm->sourceID.i = prevsrcid;
-#endif
- while(script != NULL) {
- se = script;
- script = script->next;
- free(se);
- }
- return(res);
+ return result;
}
/*
* Emit the current prompt; use the same syntax as the parser
* for embedding environment variables.
*/
-static void
-prompt(void)
+void
+prompt(void)
{
- char *pr, *p, *cp, *ev;
-
- if ((cp = getenv("prompt")) == NULL)
- cp = ">";
- pr = p = strdup(cp);
-
- while (*p != 0) {
- if ((*p == '$') && (*(p+1) == '{')) {
- for (cp = p + 2; (*cp != 0) && (*cp != '}'); cp++)
- ;
- *cp = 0;
- ev = getenv(p + 2);
-
- if (ev != NULL)
- printf("%s", ev);
- p = cp + 1;
- continue;
+ char *pr, *p, *cp, *ev;
+
+ if ((cp = getenv("prompt")) == NULL)
+ cp = ">";
+ pr = p = strdup(cp);
+
+ while (*p != 0) {
+ if ((*p == '$') && (*(p+1) == '{')) {
+ for (cp = p + 2; (*cp != 0) && (*cp != '}'); cp++)
+ ;
+ *cp = 0;
+ ev = getenv(p + 2);
+
+ if (ev != NULL)
+ printf("%s", ev);
+ p = cp + 1;
+ continue;
+ }
+ putchar(*p++);
}
- putchar(*p++);
- }
- putchar(' ');
- free(pr);
+ putchar(' ');
+ free(pr);
}
Added: projects/lua-bootloader/sys/boot/common/interp.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/lua-bootloader/sys/boot/common/interp.h Thu Mar 26 03:43:38 2015 (r280656)
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2014 Pedro Souza <pedrosouza at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+typedef void interp_init_t(void *ctx);
+typedef int interp_run_t(void *ctx, const char *input);
+typedef int interp_incl_t(void *ctx, const char *filename);
+typedef int interp_load_def_t(void *ctx); // load default configuration files
+
+struct interp {
+ interp_init_t *init;
+ interp_run_t *run;
+ interp_incl_t *incl;
+ interp_load_def_t *load_configs;
+ void *context;
+};
+
+#define INTERP_INIT(i) do { \
+ if (((i) != NULL) && ((i)->init != NULL)) { \
+ ((i)->init((i)->context)); \
+ } \
+} while (0)
+
+#define INTERP_RUN(i, input) \
+ ((i)->run(((i)->context), input))
+
+#define INTERP_INCL(i, filename) \
+ ((i)->incl(((i)->context), filename))
+
+#define INTERP_LOAD_DEF_CONFIG(i) \
+ ((i)->load_configs(((i)->context)))
+
+
+
+extern struct interp boot_interp_simple;
+extern struct interp boot_interp_forth;
+extern struct interp boot_interp_lua;
+
+
+extern struct interp *interp;
+
+int perform(int argc, char *argv[]);
+void prompt(void);
+
+/*
+ * Default config loader for interp_simple & intep_forth
+ * Use it if your interpreter does not use a custom config
+ * file.
+ *
+ * Calls interp->include with 'loader.rc' or 'boot.conf'
+ */
+int default_load_config(void *ctx);
+
+struct includeline
+{
+ struct includeline *next;
+ int flags;
+ int line;
+#define SL_QUIET (1<<0)
+#define SL_IGNOREERR (1<<1)
+ char text[0];
+};
\ No newline at end of file
Modified: projects/lua-bootloader/sys/boot/common/interp_forth.c
==============================================================================
--- projects/lua-bootloader/sys/boot/common/interp_forth.c Thu Mar 26 03:05:07 2015 (r280655)
+++ projects/lua-bootloader/sys/boot/common/interp_forth.c Thu Mar 26 03:43:38 2015 (r280656)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include "bootstrap.h"
#include "ficl.h"
+#include "interp.h"
extern char bootprog_rev[];
@@ -60,10 +61,14 @@ extern char bootprog_rev[];
/*
* BootForth Interface to Ficl Forth interpreter.
*/
+struct interp_forth_softc {
+ FICL_SYSTEM *bf_sys;
+ FICL_VM *bf_vm;
+ FICL_WORD *pInterp;
+};
+struct interp_forth_softc forth_softc = { NULL, NULL, NULL };
-FICL_SYSTEM *bf_sys;
-FICL_VM *bf_vm;
-FICL_WORD *pInterp;
+#define RETURN(x) stackPushINT(bf_vm->pStack,!x); return(x)
/*
* Shim for taking commands from BF and passing them out to 'standard'
@@ -72,81 +77,81 @@ FICL_WORD *pInterp;
static void
bf_command(FICL_VM *vm)
{
- char *name, *line, *tail, *cp;
- size_t len;
- struct bootblk_command **cmdp;
- bootblk_cmd_t *cmd;
- int nstrings, i;
- int argc, result;
- char **argv;
-
- /* Get the name of the current word */
- name = vm->runningWord->name;
-
- /* Find our command structure */
- cmd = NULL;
- SET_FOREACH(cmdp, Xcommand_set) {
- if (((*cmdp)->c_name != NULL) && !strcmp(name, (*cmdp)->c_name))
- cmd = (*cmdp)->c_fn;
- }
- if (cmd == NULL)
- panic("callout for unknown command '%s'", name);
-
- /* Check whether we have been compiled or are being interpreted */
- if (stackPopINT(vm->pStack)) {
- /*
- * Get parameters from stack, in the format:
- * an un ... a2 u2 a1 u1 n --
- * Where n is the number of strings, a/u are pairs of
- * address/size for strings, and they will be concatenated
- * in LIFO order.
- */
- nstrings = stackPopINT(vm->pStack);
- for (i = 0, len = 0; i < nstrings; i++)
- len += stackFetch(vm->pStack, i * 2).i + 1;
- line = malloc(strlen(name) + len + 1);
- strcpy(line, name);
-
- if (nstrings)
- for (i = 0; i < nstrings; i++) {
- len = stackPopINT(vm->pStack);
- cp = stackPopPtr(vm->pStack);
- strcat(line, " ");
- strncat(line, cp, len);
- }
- } else {
- /* Get remainder of invocation */
- tail = vmGetInBuf(vm);
- for (cp = tail, len = 0; cp != vm->tib.end && *cp != 0 && *cp != '\n'; cp++, len++)
- ;
-
- line = malloc(strlen(name) + len + 2);
- strcpy(line, name);
- if (len > 0) {
- strcat(line, " ");
- strncat(line, tail, len);
- vmUpdateTib(vm, tail + len);
+ char *name, *line, *tail, *cp;
+ size_t len;
+ struct bootblk_command **cmdp;
+ bootblk_cmd_t *cmd;
+ int nstrings, i;
+ int argc, result;
+ char **argv;
+
+ /* Get the name of the current word */
+ name = vm->runningWord->name;
+
+ /* Find our command structure */
+ cmd = NULL;
+ SET_FOREACH(cmdp, Xcommand_set) {
+ if (((*cmdp)->c_name != NULL) && !strcmp(name, (*cmdp)->c_name))
+ cmd = (*cmdp)->c_fn;
+ }
+ if (cmd == NULL)
+ panic("callout for unknown command '%s'", name);
+
+ /* Check whether we have been compiled or are being interpreted */
+ if (stackPopINT(vm->pStack)) {
+ /*
+ * Get parameters from stack, in the format:
+ * an un ... a2 u2 a1 u1 n --
+ * Where n is the number of strings, a/u are pairs of
+ * address/size for strings, and they will be concatenated
+ * in LIFO order.
+ */
+ nstrings = stackPopINT(vm->pStack);
+ for (i = 0, len = 0; i < nstrings; i++)
+ len += stackFetch(vm->pStack, i * 2).i + 1;
+ line = malloc(strlen(name) + len + 1);
+ strcpy(line, name);
+
+ if (nstrings)
+ for (i = 0; i < nstrings; i++) {
+ len = stackPopINT(vm->pStack);
+ cp = stackPopPtr(vm->pStack);
+ strcat(line, " ");
+ strncat(line, cp, len);
+ }
+ } else {
+ /* Get remainder of invocation */
+ tail = vmGetInBuf(vm);
+ for (cp = tail, len = 0; cp != vm->tib.end && *cp != 0 && *cp != '\n'; cp++, len++)
+ ;
+
+ line = malloc(strlen(name) + len + 2);
+ strcpy(line, name);
+ if (len > 0) {
+ strcat(line, " ");
+ strncat(line, tail, len);
+ vmUpdateTib(vm, tail + len);
+ }
+ }
+ DEBUG("cmd '%s'", line);
+
+ command_errmsg = command_errbuf;
+ command_errbuf[0] = 0;
+ if (!parse(&argc, &argv, line)) {
+ result = (cmd)(argc, argv);
+ free(argv);
+ } else {
+ result=BF_PARSE;
}
- }
- DEBUG("cmd '%s'", line);
-
- command_errmsg = command_errbuf;
- command_errbuf[0] = 0;
- if (!parse(&argc, &argv, line)) {
- result = (cmd)(argc, argv);
- free(argv);
- } else {
- result=BF_PARSE;
- }
- free(line);
- /*
- * If there was error during nested ficlExec(), we may no longer have
- * valid environment to return. Throw all exceptions from here.
- */
- if (result != 0)
- vmThrow(vm, result);
- /* This is going to be thrown!!! */
- stackPushINT(vm->pStack,result);
+ free(line);
+ /*
+ * If there was error during nested ficlExec(), we may no longer have
+ * valid environment to return. Throw all exceptions from here.
+ */
+ if (result != 0)
+ vmThrow(vm, result);
+ /* This is going to be thrown!!! */
+ stackPushINT(vm->pStack,result);
}
/*
@@ -241,87 +246,114 @@ bf_command(FICL_VM *vm)
* Initialise the Forth interpreter, create all our commands as words.
*/
void
-bf_init(const char *rc)
+interp_forth_init(void *ctx)
{
- struct bootblk_command **cmdp;
- char create_buf[41]; /* 31 characters-long builtins */
- int fd;
-
- bf_sys = ficlInitSystem(BF_DICTSIZE);
- bf_vm = ficlNewVM(bf_sys);
-
- /* Put all private definitions in a "builtins" vocabulary */
- ficlExec(bf_vm, "vocabulary builtins also builtins definitions");
-
- /* Builtin constructor word */
- ficlExec(bf_vm, BUILTIN_CONSTRUCTOR);
-
- /* make all commands appear as Forth words */
- SET_FOREACH(cmdp, Xcommand_set) {
- ficlBuild(bf_sys, (char *)(*cmdp)->c_name, bf_command, FW_DEFAULT);
- ficlExec(bf_vm, "forth definitions builtins");
- sprintf(create_buf, "builtin: %s", (*cmdp)->c_name);
- ficlExec(bf_vm, create_buf);
- ficlExec(bf_vm, "builtins definitions");
- }
- ficlExec(bf_vm, "only forth definitions");
-
- /* Export some version numbers so that code can detect the loader/host version */
- ficlSetEnv(bf_sys, "FreeBSD_version", __FreeBSD_version);
- ficlSetEnv(bf_sys, "loader_version",
- (bootprog_rev[0] - '0') * 10 + (bootprog_rev[2] - '0'));
-
- pInterp = ficlLookup(bf_sys, "interpret");
-
- /* try to load and run init file if present */
- if (rc == NULL)
- rc = "/boot/boot.4th";
- if (*rc != '\0') {
- fd = open(rc, O_RDONLY);
- if (fd != -1) {
- (void)ficlExecFD(bf_vm, fd);
- close(fd);
+ struct interp_forth_softc *softc;
+ struct bootblk_command **cmdp;
+ char create_buf[41]; /* 31 characters-long builtins */
+ int fd;
+
+ softc = ctx;
+
+ assert((softc->bf_sys == NULL) && (softc->bf_vm == NULL) &&
+ (softc->pInterp == NULL)); /* No Forth context at this stage */
+
+ softc->bf_sys = ficlInitSystem(BF_DICTSIZE);
+ softc->bf_vm = ficlNewVM(softc->bf_sys);
+
+ /* Put all private definitions in a "builtins" vocabulary */
+ ficlExec(softc->bf_vm, "vocabulary builtins also builtins definitions");
+
+ /* Builtin constructor word */
+ ficlExec(softc->bf_vm, BUILTIN_CONSTRUCTOR);
+
+ /* make all commands appear as Forth words */
+ SET_FOREACH(cmdp, Xcommand_set) {
+ ficlBuild(softc->bf_sys, (char *)(*cmdp)->c_name, bf_command, FW_DEFAULT);
+ ficlExec(softc->bf_vm, "forth definitions builtins");
+ sprintf(create_buf, "builtin: %s", (*cmdp)->c_name);
+ ficlExec(softc->bf_vm, create_buf);
+ ficlExec(softc->bf_vm, "builtins definitions");
+ }
+ ficlExec(softc->bf_vm, "only forth definitions");
+
+ /* Export some version numbers so that code can detect the loader/host version */
+ ficlSetEnv(softc->bf_sys, "FreeBSD_version", __FreeBSD_version);
+ ficlSetEnv(softc->bf_sys, "loader_version",
+ (bootprog_rev[0] - '0') * 10 + (bootprog_rev[2] - '0'));
+
+ /* try to load and run init file if present */
+ if ((fd = open("/boot/boot.4th", O_RDONLY)) != -1) {
+ (void)ficlExecFD(softc->bf_vm, fd);
+ close(fd);
}
- }
- /* Do this again, so that interpret can be redefined. */
- pInterp = ficlLookup(bf_sys, "interpret");
+ /* Do this last, so /boot/boot.4th can change it */
+ softc->pInterp = ficlLookup(softc->bf_sys, "interpret");
}
/*
* Feed a line of user input to the Forth interpreter
*/
int
-bf_run(char *line)
+interp_forth_run(void *ctx, const char *line)
{
- int result;
+ struct interp_forth_softc *softc;
+ int result;
+
+ softc = ctx;
+
+ result = ficlExec(softc->bf_vm, (char*)line);
- result = ficlExec(bf_vm, line);
+ DEBUG("ficlExec '%s' = %d", line, result);
+ switch (result) {
+ case VM_OUTOFTEXT:
+ case VM_ABORTQ:
+ case VM_QUIT:
+ case VM_ERREXIT:
+ break;
+ case VM_USEREXIT:
+ printf("No where to leave to!\n");
+ break;
+ case VM_ABORT:
+ printf("Aborted!\n");
+ break;
+ case BF_PARSE:
+ printf("Parse error!\n");
+ break;
+ default:
+ /* Hopefully, all other codes filled this buffer */
+ printf("%s\n", command_errmsg);
+ }
+
+ if (result == VM_USEREXIT)
+ panic("interpreter exit");
+ setenv("interpret", softc->bf_vm->state ? "" : "OK", 1);
+
+ return result;
+}
+
+int
+interp_forth_incl(void *ctx, const char *filename)
+{
+ struct interp_forth_softc *softc;
+ int fd;
- DEBUG("ficlExec '%s' = %d", line, result);
- switch (result) {
- case VM_OUTOFTEXT:
- case VM_ABORTQ:
- case VM_QUIT:
- case VM_ERREXIT:
- break;
- case VM_USEREXIT:
- printf("No where to leave to!\n");
- break;
- case VM_ABORT:
- printf("Aborted!\n");
- break;
- case BF_PARSE:
- printf("Parse error!\n");
- break;
- default:
- /* Hopefully, all other codes filled this buffer */
- printf("%s\n", command_errmsg);
- }
-
- if (result == VM_USEREXIT)
- panic("interpreter exit");
- setenv("interpret", bf_vm->state ? "" : "OK", 1);
+ softc = ctx;
- return result;
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ printf("can't open %s\n", filename);
+ return (CMD_ERROR);
+ }
+ return (ficlExecFD(softc->bf_vm, fd));
}
+
+
+struct interp boot_interp_forth = {
+ .init = interp_forth_init,
+ .run = interp_forth_run,
+ .incl = interp_forth_incl,
+ .load_configs = default_load_config,
+ .context = &forth_softc
+};
Added: projects/lua-bootloader/sys/boot/common/interp_simple.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/lua-bootloader/sys/boot/common/interp_simple.c Thu Mar 26 03:43:38 2015 (r280656)
@@ -0,0 +1,182 @@
+/*-
+ * Copyright (c) 2014 Pedro Souza <pedrosouza at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <string.h>
+#include "bootstrap.h"
+#include "interp.h"
+
+struct interp_simple_softc {
+ int dummy;
+};
+
+void
+interp_simple_init(void *ctx)
+{
+
+ (void)ctx; /* Silent the compiler */
+}
+
+int
+interp_simple_run(void *ctx, const char *input)
+{
+ struct interp_simple_softc *softc;
+ int argc;
+ char **argv;
+
+ softc = ctx;
+ (void)softc; /* Currently unused */
+
+ if (!parse(&argc, &argv, input)) {
+ if (perform(argc, argv))
+ printf("%s: %s\n", argv[0], command_errmsg);
+ free(argv);
+ } else {
+ printf("parse error\n");
+ }
+ return 0;
+}
+
+int
+interp_simple_incl(void *ctx, const char *filename)
+{
+ struct includeline *script, *se, *sp;
+ char input[256]; /* big enough? */
+ int argc,res;
+ char **argv, *cp;
+ int fd, flags, line;
+
+ (void)ctx; /* Silent the compiler */
+
+ if (((fd = open(filename, O_RDONLY)) == -1)) {
+ sprintf(command_errbuf,"can't open '%s': %s\n", filename, strerror(errno));
+ return(CMD_ERROR);
+ }
+
+ /*
+ * Read the script into memory.
+ */
+ script = se = NULL;
+ line = 0;
+
+ while (fgetstr(input, sizeof(input), fd) >= 0) {
+ line++;
+ flags = 0;
+ /* Discard comments */
+ if (strncmp(input+strspn(input, " "), "\\ ", 2) == 0)
+ continue;
+ cp = input;
+ /* Echo? */
+ if (input[0] == '@') {
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list