svn commit: r326712 - in head/stand: . common
Warner Losh
imp at FreeBSD.org
Fri Dec 8 19:57:20 UTC 2017
Author: imp
Date: Fri Dec 8 19:57:16 2017
New Revision: 326712
URL: https://svnweb.freebsd.org/changeset/base/326712
Log:
Create interp class.
Create an interp class. Use it to separate out the different types of
interpreters: forth and simple with function pointers rather than
via #ifdefs.
Obtained from: lua boot loader project
(via https://bsdimp@github.com/bsdimp/freebsd.git lua-bootloader)
Sponsored by: Netflix
Added:
head/stand/common/interp.h (contents, props changed)
head/stand/common/interp_simple.c (contents, props changed)
Modified:
head/stand/common/interp.c
head/stand/common/interp_forth.c
head/stand/loader.mk
Modified: head/stand/common/interp.c
==============================================================================
--- head/stand/common/interp.c Fri Dec 8 19:57:11 2017 (r326711)
+++ head/stand/common/interp.c Fri Dec 8 19:57:16 2017 (r326712)
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith at freebsd.org>
+ * Copyright (c) 2011 Wojciech A. Koszek <wkoszek at FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,7 +24,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -36,112 +36,60 @@ __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;
+#define MAXARGS 20 /* maximum number of arguments allowed */
+
+struct interp *interp =
+#if defined(BOOT_FORTH)
+ &boot_interp_forth;
#else
-#define RETURN(x) return(x)
+ &boot_interp_simple;
#endif
-#define MAXARGS 20 /* maximum number of arguments allowed */
-
-static void prompt(void);
-
-#ifndef BOOT_FORTH
-static int perform(int argc, char *argv[]);
-
-/*
- * 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);
+ return INTERP_INCL(interp, "/boot/loader.rc");
}
-#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. */
- include("/boot/loader.rc");
- } else if (*rc != '\0')
- include(rc);
+ /*
+ * Read our default configuration
+ */
+ INTERP_LOAD_DEF_CONFIG(interp);
+ printf("\n");
+ /*
+ * Before interacting, we might want to autoboot.
+ */
+ autoboot_maybe();
- printf("\n");
+ /*
+ * 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);
- /*
- * 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");
+ for (;;) {
+ input[0] = '\0';
+ prompt();
+ ngets(input, sizeof(input));
+ INTERP_RUN(interp, input);
}
-#endif
- }
}
/*
@@ -158,214 +106,87 @@ COMMAND_SET(include, "include", "read commands from a
static int
command_include(int argc, char *argv[])
{
- int i;
- int res;
- char **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]);
+ /*
+ * 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]);
+ 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);
+ 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
+ int result;
+ struct bootblk_command **cmdp;
+ bootblk_cmd_t *cmd;
- if (((fd = open(filename, O_RDONLY)) == -1)) {
- snprintf(command_errbuf, sizeof(command_errbuf),
- "can't open '%s': %s", filename, strerror(errno));
- return(CMD_ERROR);
- }
+ if (argc < 1)
+ return(CMD_OK);
- /*
- * 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;
+ /* 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;
}
- /* 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);
- }
- snprintf(command_errbuf, sizeof(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;
+ if (cmd != NULL) {
+ result = (cmd)(argc, argv);
} else {
- se->next = sp;
+ command_errmsg = "unknown command";
}
- 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) {
- snprintf(command_errbuf, sizeof(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);
- }
-
- /* 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;
- } else {
- printf("%s line %d: parse error\n", filename, sp->line);
- res=CMD_ERROR;
- break;
- }
-#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);
+ char *pr, *p, *cp, *ev;
- 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;
+ 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: head/stand/common/interp.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/stand/common/interp.h Fri Dec 8 19:57:16 2017 (r326712)
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 2011 Wojciech A. Koszek <wkoszek at FreeBSD.org>
+ * 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];
+};
Modified: head/stand/common/interp_forth.c
==============================================================================
--- head/stand/common/interp_forth.c Fri Dec 8 19:57:11 2017 (r326711)
+++ head/stand/common/interp_forth.c Fri Dec 8 19:57:16 2017 (r326712)
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith at freebsd.org>
+ * Copyright (c) 2011 Wojciech A. Koszek <wkoszek at FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include "bootstrap.h"
#include "ficl.h"
+#include "interp.h"
extern unsigned bootprog_rev;
@@ -60,9 +62,14 @@ extern unsigned 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;
+#define RETURN(x) stackPushINT(bf_vm->pStack,!x); return(x)
/*
* Shim for taking commands from BF and passing them out to 'standard'
@@ -71,91 +78,93 @@ FICL_VM *bf_vm;
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;
+ 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);
+ /* Get the name of the current word */
+ name = vm->runningWord->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);
+ /* 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;
}
- }
- 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;
- }
+ if (cmd == NULL)
+ panic("callout for unknown command '%s'", name);
- switch (result) {
- case CMD_CRIT:
- printf("%s\n", command_errmsg);
- break;
- case CMD_FATAL:
- panic("%s\n", command_errmsg);
- }
+ /* 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);
- 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 != CMD_OK)
- vmThrow(vm, result);
+ 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++)
+ ;
- /* This is going to be thrown!!! */
- stackPushINT(vm->pStack,result);
+ 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;
+ }
+
+ /* XXX Not sure about the rest of this -- imp */
+
+ switch (result) {
+ case CMD_CRIT:
+ printf("%s\n", command_errmsg);
+ break;
+ case CMD_FATAL:
+ panic("%s\n", command_errmsg);
+ }
+
+ 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 != CMD_OK)
+ vmThrow(vm, result);
+
+ /* This is going to be thrown!!! */
+ stackPushINT(vm->pStack,result);
}
/*
@@ -249,16 +258,23 @@ bf_command(FICL_VM *vm)
/*
* Initialise the Forth interpreter, create all our commands as words.
*/
-void
-bf_init(const char *rc)
+static void
+interp_forth_init(void *ctx)
{
+ struct interp_forth_softc *softc;
struct bootblk_command **cmdp;
char create_buf[41]; /* 31 characters-long builtins */
- int fd;
+ FICL_SYSTEM *bf_sys;
+ FICL_VM *bf_vm;
- bf_sys = ficlInitSystem(BF_DICTSIZE);
- bf_vm = ficlNewVM(bf_sys);
+ softc = ctx;
+ assert((softc->bf_sys == NULL) && (softc->bf_vm == NULL) &&
+ (softc->pInterp == NULL)); /* No Forth context at this stage */
+
+ bf_sys = softc->bf_sys = ficlInitSystem(BF_DICTSIZE);
+ bf_vm = softc->bf_vm = ficlNewVM(bf_sys);
+
/* Put all private definitions in a "builtins" vocabulary */
ficlExec(bf_vm, "vocabulary builtins also builtins definitions");
@@ -279,28 +295,35 @@ bf_init(const char *rc)
ficlSetEnv(bf_sys, "FreeBSD_version", __FreeBSD_version);
ficlSetEnv(bf_sys, "loader_version", bootprog_rev);
+#if 0 /* XXX lost functionality -- imp */
/* try to load and run init file if present */
if (rc == NULL)
rc = "/boot/boot.4th";
if (*rc != '\0') {
+ int fd;
+
fd = open(rc, O_RDONLY);
if (fd != -1) {
(void)ficlExecFD(bf_vm, fd);
close(fd);
}
}
+#endif
}
/*
* Feed a line of user input to the Forth interpreter
*/
-int
-bf_run(char *line)
+static int
+interp_forth_run(void *ctx, const char *line)
{
+ struct interp_forth_softc *softc;
int result;
- result = ficlExec(bf_vm, line);
+ softc = ctx;
+ result = ficlExec(softc->bf_vm, (char *)line);
+
DEBUG("ficlExec '%s' = %d", line, result);
switch (result) {
case VM_OUTOFTEXT:
@@ -326,7 +349,32 @@ bf_run(char *line)
if (result == VM_USEREXIT)
panic("interpreter exit");
- setenv("interpret", bf_vm->state ? "" : "OK", 1);
+ setenv("interpret", softc->bf_vm->state ? "" : "OK", 1);
return (result);
}
+
+static int
+interp_forth_incl(void *ctx, const char *filename)
+{
+ struct interp_forth_softc *softc;
+ int fd;
+
+ softc = ctx;
+
+ 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: head/stand/common/interp_simple.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/stand/common/interp_simple.c Fri Dec 8 19:57:16 2017 (r326712)
@@ -0,0 +1,183 @@
+/*-
+ * Copyright (c) 2011 Wojciech A. Koszek <wkoszek at FreeBSD.org>
+ * 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;
+};
+
+static void
+interp_simple_init(void *ctx)
+{
+
+ (void)ctx; /* Silent the compiler */
+}
+
+static 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;
+}
+
+static 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] == '@') {
+ cp++;
+ flags |= SL_QUIET;
+ }
+ /* Error OK? */
+ if (input[0] == '-') {
+ cp++;
+ flags |= SL_IGNOREERR;
+ }
+ /* 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\n", filename, line);
+ return (CMD_ERROR);
+ }
+ strcpy(sp->text, cp);
+ sp->flags = flags;
+ sp->line = line;
+ sp->next = NULL;
+
+ if (script == NULL) {
+ script = sp;
+ } else {
+ se->next = sp;
+ }
+ se = sp;
+ }
+ close(fd);
+
+ /*
+ * Execute the script
+ */
+ argv = NULL;
+ res = CMD_OK;
+ for (sp = script; sp != NULL; sp = sp->next) {
+
+ /* print if not being quiet */
+ if (!(sp->flags & SL_QUIET)) {
+ prompt();
+ printf("%s\n", sp->text);
+ }
+
+ /* 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;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list