From owner-svn-src-projects@FreeBSD.ORG Thu Mar 26 03:43:41 2015 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 622D1CF8; Thu, 26 Mar 2015 03:43:41 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4C316272; Thu, 26 Mar 2015 03:43:41 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t2Q3henV098223; Thu, 26 Mar 2015 03:43:40 GMT (envelope-from rpaulo@FreeBSD.org) Received: (from rpaulo@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t2Q3hd9m098217; Thu, 26 Mar 2015 03:43:39 GMT (envelope-from rpaulo@FreeBSD.org) Message-Id: <201503260343.t2Q3hd9m098217@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: rpaulo set sender to rpaulo@FreeBSD.org using -f From: Rui Paulo Date: Thu, 26 Mar 2015 03:43:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r280656 - projects/lua-bootloader/sys/boot/common X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 26 Mar 2015 03:43:41 -0000 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 __FBSDID("$FreeBSD$"); @@ -36,113 +35,64 @@ __FBSDID("$FreeBSD$"); #include #include #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 + * 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 #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 + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#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 ***