afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome/*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * p r e f i x . c
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Forth Inspired Command Language
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Parser extensions for Ficl
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Created: April 2001
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * $Id: prefix.c,v 1.8 2010/09/13 18:43:04 asau Exp $
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome/*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * All rights reserved.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Get the latest Ficl release at http://ficl.sourceforge.net
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * I am interested in hearing from anyone who uses Ficl. If you have
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * a problem, a success story, a defect, an enhancement request, or
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * if you would like to contribute to the Ficl release, please
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * contact me by email at the address above.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * L I C E N S E and D I S C L A I M E R
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Redistribution and use in source and binary forms, with or without
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * modification, are permitted provided that the following conditions
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * are met:
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 1. Redistributions of source code must retain the above copyright
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * notice, this list of conditions and the following disclaimer.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * notice, this list of conditions and the following disclaimer in the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * documentation and/or other materials provided with the distribution.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * SUCH DAMAGE.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome#include "ficl.h"
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome/*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * (jws) revisions:
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * A prefix is a word in a dedicated wordlist (name stored in list_name below)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * that is searched in a special way by the prefix parse step. When a prefix
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * matches the beginning of an incoming token, push the non-prefix part of the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * token back onto the input stream and execute the prefix code.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * The parse step is called ficlParsePrefix.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Storing prefix entries in the dictionary greatly simplifies
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * the process of matching and dispatching prefixes, avoids the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * need to clean up a dynamically allocated prefix list when the system
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * goes away, but still allows prefixes to be allocated at runtime.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soomestatic char list_name[] = "<prefixes>";
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome/*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * f i c l P a r s e P r e f i x
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * This is the parse step for prefixes - it checks an incoming word
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * to see if it starts with a prefix, and if so runs the corresponding
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * code against the remainder of the word and returns true.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soomeint
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas SoomeficlVmParsePrefix(ficlVm *vm, ficlString s)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome{
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome int i;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlHash *hash;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlWord *word = ficlSystemLookup(vm->callback.system, list_name);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome /*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Make sure we found the prefix dictionary - otherwise silently fail
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * If forth-wordlist is not in the search order, we won't find the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * prefixes.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome if (!word)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome return (0); /* false */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome hash = (ficlHash *)(word->param[0].p);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome /*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Walk the list looking for a match with the beginning of the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * incoming token
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome for (i = 0; i < (int)hash->size; i++) {
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome word = hash->table[i];
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome while (word != NULL) {
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome int n;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome n = word->length;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome /*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * If we find a match, adjust the TIB to give back
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * the non-prefix characters and execute the prefix
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * word.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome if (!ficlStrincmp(FICL_STRING_GET_POINTER(s),
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome word->name, (ficlUnsigned)n)) {
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome /*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * (sadler) fixed off-by-one error when the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * token has no trailing space in the TIB
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlVmSetTibIndex(vm,
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome s.text + n - vm->tib.text);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlVmExecuteWord(vm, word);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome return (1); /* true */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome }
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome word = word->link;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome }
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome }
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome return (0); /* false */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome}
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soomestatic void
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas SoomeficlPrimitiveTempBase(ficlVm *vm)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome{
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome int oldbase = vm->base;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlString number = ficlVmGetWord0(vm);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome int base = ficlStackPopInteger(vm->dataStack);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome vm->base = base;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome if (!ficlVmParseNumber(vm, number))
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlVmThrowError(vm, "%.*s not recognized",
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome FICL_STRING_GET_LENGTH(number),
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome FICL_STRING_GET_POINTER(number));
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome vm->base = oldbase;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome}
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome/*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * f i c l C o m p i l e P r e f i x
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Build prefix support into the dictionary and the parser
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Note: since prefixes always execute, they are effectively IMMEDIATE.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * If they need to generate code in compile state you must add
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * this code explicitly.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soomevoid
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas SoomeficlSystemCompilePrefix(ficlSystem *system)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome{
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlDictionary *dictionary = system->dictionary;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlHash *hash;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome /*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Create a named wordlist for prefixes to reside in...
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Since we're doing a special kind of search, make it
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * a single bucket hashtable - hashing does not help here.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome hash = ficlDictionaryCreateWordlist(dictionary, 1);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome hash->name = list_name;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlDictionaryAppendConstantPointer(dictionary, list_name, hash);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome /*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Put __tempbase in the forth-wordlist
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlDictionarySetPrimitive(dictionary, "__tempbase",
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome ficlPrimitiveTempBase, FICL_WORD_DEFAULT);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome /*
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * If you want to add some prefixes at compilation-time, copy this
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * line to the top of this function:
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * ficlHash *oldCompilationWordlist;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * then copy this code to the bottom, just above the return:
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * oldCompilationWordlist = dictionary->compilationWordlist;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * dictionary->compilationWordlist = hash;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * ficlDictionarySetPrimitive(dictionary, YOUR WORD HERE,
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * FICL_WORD_DEFAULT);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * dictionary->compilationWordlist = oldCompilationWordlist;
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * and substitute in your own actual calls to
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * ficlDictionarySetPrimitive() as needed.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome *
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Or--better yet--do it in your own code, so you don't have
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * to re-modify the Ficl source code every time we cut a new release!
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome */
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome}