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://bsd...@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 <msm...@freebsd.org>
+ * Copyright (c) 2011 Wojciech A. Koszek <wkos...@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 <wkos...@freebsd.org>
+ * Copyright (c) 2014 Pedro Souza <pedroso...@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 <msm...@freebsd.org>
+ * Copyright (c) 2011 Wojciech A. Koszek <wkos...@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 <wkos...@freebsd.org>
+ * Copyright (c) 2014 Pedro Souza <pedroso...@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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to