summaryrefslogtreecommitdiff
path: root/usr/src/common/ficl/prefix.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/common/ficl/prefix.c')
-rw-r--r--usr/src/common/ficl/prefix.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/usr/src/common/ficl/prefix.c b/usr/src/common/ficl/prefix.c
new file mode 100644
index 0000000000..8e396d92cb
--- /dev/null
+++ b/usr/src/common/ficl/prefix.c
@@ -0,0 +1,182 @@
+/*
+ * p r e f i x . c
+ * Forth Inspired Command Language
+ * Parser extensions for Ficl
+ * Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu)
+ * Created: April 2001
+ * $Id: prefix.c,v 1.8 2010/09/13 18:43:04 asau Exp $
+ */
+/*
+ * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
+ * All rights reserved.
+ *
+ * Get the latest Ficl release at http://ficl.sourceforge.net
+ *
+ * I am interested in hearing from anyone who uses Ficl. If you have
+ * a problem, a success story, a defect, an enhancement request, or
+ * if you would like to contribute to the Ficl release, please
+ * contact me by email at the address above.
+ *
+ * L I C E N S E and D I S C L A I M E R
+ *
+ * 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 "ficl.h"
+
+/*
+ * (jws) revisions:
+ * A prefix is a word in a dedicated wordlist (name stored in list_name below)
+ * that is searched in a special way by the prefix parse step. When a prefix
+ * matches the beginning of an incoming token, push the non-prefix part of the
+ * token back onto the input stream and execute the prefix code.
+ *
+ * The parse step is called ficlParsePrefix.
+ * Storing prefix entries in the dictionary greatly simplifies
+ * the process of matching and dispatching prefixes, avoids the
+ * need to clean up a dynamically allocated prefix list when the system
+ * goes away, but still allows prefixes to be allocated at runtime.
+ */
+
+static char list_name[] = "<prefixes>";
+
+/*
+ * f i c l P a r s e P r e f i x
+ * This is the parse step for prefixes - it checks an incoming word
+ * to see if it starts with a prefix, and if so runs the corresponding
+ * code against the remainder of the word and returns true.
+ */
+int
+ficlVmParsePrefix(ficlVm *vm, ficlString s)
+{
+ int i;
+ ficlHash *hash;
+ ficlWord *word = ficlSystemLookup(vm->callback.system, list_name);
+
+ /*
+ * Make sure we found the prefix dictionary - otherwise silently fail
+ * If forth-wordlist is not in the search order, we won't find the
+ * prefixes.
+ */
+ if (!word)
+ return (0); /* false */
+
+ hash = (ficlHash *)(word->param[0].p);
+ /*
+ * Walk the list looking for a match with the beginning of the
+ * incoming token
+ */
+ for (i = 0; i < (int)hash->size; i++) {
+ word = hash->table[i];
+ while (word != NULL) {
+ int n;
+ n = word->length;
+ /*
+ * If we find a match, adjust the TIB to give back
+ * the non-prefix characters and execute the prefix
+ * word.
+ */
+ if (!ficlStrincmp(FICL_STRING_GET_POINTER(s),
+ word->name, (ficlUnsigned)n)) {
+ /*
+ * (sadler) fixed off-by-one error when the
+ * token has no trailing space in the TIB
+ */
+ ficlVmSetTibIndex(vm,
+ s.text + n - vm->tib.text);
+ ficlVmExecuteWord(vm, word);
+
+ return (1); /* true */
+ }
+ word = word->link;
+ }
+ }
+
+ return (0); /* false */
+}
+
+static void
+ficlPrimitiveTempBase(ficlVm *vm)
+{
+ int oldbase = vm->base;
+ ficlString number = ficlVmGetWord0(vm);
+ int base = ficlStackPopInteger(vm->dataStack);
+
+ vm->base = base;
+ if (!ficlVmParseNumber(vm, number))
+ ficlVmThrowError(vm, "%.*s not recognized",
+ FICL_STRING_GET_LENGTH(number),
+ FICL_STRING_GET_POINTER(number));
+
+ vm->base = oldbase;
+}
+
+/*
+ * f i c l C o m p i l e P r e f i x
+ * Build prefix support into the dictionary and the parser
+ * Note: since prefixes always execute, they are effectively IMMEDIATE.
+ * If they need to generate code in compile state you must add
+ * this code explicitly.
+ */
+void
+ficlSystemCompilePrefix(ficlSystem *system)
+{
+ ficlDictionary *dictionary = system->dictionary;
+ ficlHash *hash;
+
+ /*
+ * Create a named wordlist for prefixes to reside in...
+ * Since we're doing a special kind of search, make it
+ * a single bucket hashtable - hashing does not help here.
+ */
+ hash = ficlDictionaryCreateWordlist(dictionary, 1);
+ hash->name = list_name;
+ ficlDictionaryAppendConstantPointer(dictionary, list_name, hash);
+
+ /*
+ * Put __tempbase in the forth-wordlist
+ */
+ ficlDictionarySetPrimitive(dictionary, "__tempbase",
+ ficlPrimitiveTempBase, FICL_WORD_DEFAULT);
+
+ /*
+ * If you want to add some prefixes at compilation-time, copy this
+ * line to the top of this function:
+ *
+ * ficlHash *oldCompilationWordlist;
+ *
+ * then copy this code to the bottom, just above the return:
+ *
+ *
+ * oldCompilationWordlist = dictionary->compilationWordlist;
+ * dictionary->compilationWordlist = hash;
+ * ficlDictionarySetPrimitive(dictionary, YOUR WORD HERE,
+ * FICL_WORD_DEFAULT);
+ * dictionary->compilationWordlist = oldCompilationWordlist;
+ *
+ * and substitute in your own actual calls to
+ * ficlDictionarySetPrimitive() as needed.
+ *
+ * Or--better yet--do it in your own code, so you don't have
+ * to re-modify the Ficl source code every time we cut a new release!
+ */
+}