The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/boot/ficl/dict.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*******************************************************************
    2 ** d i c t . c
    3 ** Forth Inspired Command Language - dictionary methods
    4 ** Author: John Sadler (john_sadler@alum.mit.edu)
    5 ** Created: 19 July 1997
    6 ** $Id: dict.c,v 1.14 2001/12/05 07:21:34 jsadler Exp $
    7 *******************************************************************/
    8 /*
    9 ** This file implements the dictionary -- FICL's model of 
   10 ** memory management. All FICL words are stored in the
   11 ** dictionary. A word is a named chunk of data with its
   12 ** associated code. FICL treats all words the same, even
   13 ** precompiled ones, so your words become first-class
   14 ** extensions of the language. You can even define new 
   15 ** control structures.
   16 **
   17 ** 29 jun 1998 (sadler) added variable sized hash table support
   18 */
   19 /*
   20 ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
   21 ** All rights reserved.
   22 **
   23 ** Get the latest Ficl release at http://ficl.sourceforge.net
   24 **
   25 ** I am interested in hearing from anyone who uses ficl. If you have
   26 ** a problem, a success story, a defect, an enhancement request, or
   27 ** if you would like to contribute to the ficl release, please
   28 ** contact me by email at the address above.
   29 **
   30 ** L I C E N S E  and  D I S C L A I M E R
   31 ** 
   32 ** Redistribution and use in source and binary forms, with or without
   33 ** modification, are permitted provided that the following conditions
   34 ** are met:
   35 ** 1. Redistributions of source code must retain the above copyright
   36 **    notice, this list of conditions and the following disclaimer.
   37 ** 2. Redistributions in binary form must reproduce the above copyright
   38 **    notice, this list of conditions and the following disclaimer in the
   39 **    documentation and/or other materials provided with the distribution.
   40 **
   41 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   42 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   43 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   44 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   45 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   46 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   47 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   48 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   49 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   50 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   51 ** SUCH DAMAGE.
   52 */
   53 
   54 /* $FreeBSD$ */
   55 
   56 #ifdef TESTMAIN
   57 #include <stdio.h>
   58 #include <ctype.h>
   59 #else
   60 #include <stand.h>
   61 #endif
   62 #include <string.h>
   63 #include "ficl.h"
   64 
   65 /* Dictionary on-demand resizing control variables */
   66 CELL dictThreshold;
   67 CELL dictIncrease;
   68 
   69 
   70 static char *dictCopyName(FICL_DICT *pDict, STRINGINFO si);
   71 
   72 /**************************************************************************
   73                         d i c t A b o r t D e f i n i t i o n
   74 ** Abort a definition in process: reclaim its memory and unlink it
   75 ** from the dictionary list. Assumes that there is a smudged 
   76 ** definition in process...otherwise does nothing.
   77 ** NOTE: this function is not smart enough to unlink a word that
   78 ** has been successfully defined (ie linked into a hash). It
   79 ** only works for defs in process. If the def has been unsmudged,
   80 ** nothing happens.
   81 **************************************************************************/
   82 void dictAbortDefinition(FICL_DICT *pDict)
   83 {
   84     FICL_WORD *pFW;
   85     ficlLockDictionary(TRUE);
   86     pFW = pDict->smudge;
   87 
   88     if (pFW->flags & FW_SMUDGE)
   89         pDict->here = (CELL *)pFW->name;
   90 
   91     ficlLockDictionary(FALSE);
   92     return;
   93 }
   94 
   95 
   96 /**************************************************************************
   97                         a l i g n P t r
   98 ** Aligns the given pointer to FICL_ALIGN address units.
   99 ** Returns the aligned pointer value.
  100 **************************************************************************/
  101 void *alignPtr(void *ptr)
  102 {
  103 #if FICL_ALIGN > 0
  104     char *cp;
  105     CELL c;
  106     cp = (char *)ptr + FICL_ALIGN_ADD;
  107     c.p = (void *)cp;
  108     c.u = c.u & (~FICL_ALIGN_ADD);
  109     ptr = (CELL *)c.p;
  110 #endif
  111     return ptr;
  112 }
  113 
  114 
  115 /**************************************************************************
  116                         d i c t A l i g n
  117 ** Align the dictionary's free space pointer
  118 **************************************************************************/
  119 void dictAlign(FICL_DICT *pDict)
  120 {
  121     pDict->here = alignPtr(pDict->here);
  122 }
  123 
  124 
  125 /**************************************************************************
  126                         d i c t A l l o t
  127 ** Allocate or remove n chars of dictionary space, with
  128 ** checks for underrun and overrun
  129 **************************************************************************/
  130 int dictAllot(FICL_DICT *pDict, int n)
  131 {
  132     char *cp = (char *)pDict->here;
  133 #if FICL_ROBUST
  134     if (n > 0)
  135     {
  136         if ((unsigned)n <= dictCellsAvail(pDict) * sizeof (CELL))
  137             cp += n;
  138         else
  139             return 1;       /* dict is full */
  140     }
  141     else
  142     {
  143         n = -n;
  144         if ((unsigned)n <= dictCellsUsed(pDict) * sizeof (CELL))
  145             cp -= n;
  146         else                /* prevent underflow */
  147             cp -= dictCellsUsed(pDict) * sizeof (CELL);
  148     }
  149 #else
  150     cp += n;
  151 #endif
  152     pDict->here = PTRtoCELL cp;
  153     return 0;
  154 }
  155 
  156 
  157 /**************************************************************************
  158                         d i c t A l l o t C e l l s
  159 ** Reserve space for the requested number of cells in the
  160 ** dictionary. If nCells < 0 , removes space from the dictionary.
  161 **************************************************************************/
  162 int dictAllotCells(FICL_DICT *pDict, int nCells)
  163 {
  164 #if FICL_ROBUST
  165     if (nCells > 0)
  166     {
  167         if (nCells <= dictCellsAvail(pDict))
  168             pDict->here += nCells;
  169         else
  170             return 1;       /* dict is full */
  171     }
  172     else
  173     {
  174         nCells = -nCells;
  175         if (nCells <= dictCellsUsed(pDict))
  176             pDict->here -= nCells;
  177         else                /* prevent underflow */
  178             pDict->here -= dictCellsUsed(pDict);
  179     }
  180 #else
  181     pDict->here += nCells;
  182 #endif
  183     return 0;
  184 }
  185 
  186 
  187 /**************************************************************************
  188                         d i c t A p p e n d C e l l
  189 ** Append the specified cell to the dictionary
  190 **************************************************************************/
  191 void dictAppendCell(FICL_DICT *pDict, CELL c)
  192 {
  193     *pDict->here++ = c;
  194     return;
  195 }
  196 
  197 
  198 /**************************************************************************
  199                         d i c t A p p e n d C h a r
  200 ** Append the specified char to the dictionary
  201 **************************************************************************/
  202 void dictAppendChar(FICL_DICT *pDict, char c)
  203 {
  204     char *cp = (char *)pDict->here;
  205     *cp++ = c;
  206     pDict->here = PTRtoCELL cp;
  207     return;
  208 }
  209 
  210 
  211 /**************************************************************************
  212                         d i c t A p p e n d W o r d
  213 ** Create a new word in the dictionary with the specified
  214 ** name, code, and flags. Name must be NULL-terminated.
  215 **************************************************************************/
  216 FICL_WORD *dictAppendWord(FICL_DICT *pDict, 
  217                           char *name, 
  218                           FICL_CODE pCode, 
  219                           UNS8 flags)
  220 {
  221     STRINGINFO si;
  222     SI_SETLEN(si, strlen(name));
  223     SI_SETPTR(si, name);
  224     return dictAppendWord2(pDict, si, pCode, flags);
  225 }
  226 
  227 
  228 /**************************************************************************
  229                         d i c t A p p e n d W o r d 2
  230 ** Create a new word in the dictionary with the specified
  231 ** STRINGINFO, code, and flags. Does not require a NULL-terminated
  232 ** name.
  233 **************************************************************************/
  234 FICL_WORD *dictAppendWord2(FICL_DICT *pDict, 
  235                            STRINGINFO si, 
  236                            FICL_CODE pCode, 
  237                            UNS8 flags)
  238 {
  239     FICL_COUNT len  = (FICL_COUNT)SI_COUNT(si);
  240     char *pName;
  241     FICL_WORD *pFW;
  242 
  243     ficlLockDictionary(TRUE);
  244 
  245     /*
  246     ** NOTE: dictCopyName advances "here" as a side-effect.
  247     ** It must execute before pFW is initialized.
  248     */
  249     pName         = dictCopyName(pDict, si);
  250     pFW           = (FICL_WORD *)pDict->here;
  251     pDict->smudge = pFW;
  252     pFW->hash     = hashHashCode(si);
  253     pFW->code     = pCode;
  254     pFW->flags    = (UNS8)(flags | FW_SMUDGE);
  255     pFW->nName    = (char)len;
  256     pFW->name     = pName;
  257     /*
  258     ** Point "here" to first cell of new word's param area...
  259     */
  260     pDict->here   = pFW->param;
  261 
  262     if (!(flags & FW_SMUDGE))
  263         dictUnsmudge(pDict);
  264 
  265     ficlLockDictionary(FALSE);
  266     return pFW;
  267 }
  268 
  269 
  270 /**************************************************************************
  271                         d i c t A p p e n d U N S
  272 ** Append the specified FICL_UNS to the dictionary
  273 **************************************************************************/
  274 void dictAppendUNS(FICL_DICT *pDict, FICL_UNS u)
  275 {
  276     *pDict->here++ = LVALUEtoCELL(u);
  277     return;
  278 }
  279 
  280 
  281 /**************************************************************************
  282                         d i c t C e l l s A v a i l
  283 ** Returns the number of empty cells left in the dictionary
  284 **************************************************************************/
  285 int dictCellsAvail(FICL_DICT *pDict)
  286 {
  287     return pDict->size - dictCellsUsed(pDict);
  288 }
  289 
  290 
  291 /**************************************************************************
  292                         d i c t C e l l s U s e d
  293 ** Returns the number of cells consumed in the dicionary
  294 **************************************************************************/
  295 int dictCellsUsed(FICL_DICT *pDict)
  296 {
  297     return pDict->here - pDict->dict;
  298 }
  299 
  300 
  301 /**************************************************************************
  302                         d i c t C h e c k
  303 ** Checks the dictionary for corruption and throws appropriate
  304 ** errors.
  305 ** Input: +n number of ADDRESS UNITS (not Cells) proposed to allot
  306 **        -n number of ADDRESS UNITS proposed to de-allot
  307 **         0 just do a consistency check
  308 **************************************************************************/
  309 void dictCheck(FICL_DICT *pDict, FICL_VM *pVM, int n)
  310 {
  311     if ((n >= 0) && (dictCellsAvail(pDict) * (int)sizeof(CELL) < n))
  312     {
  313         vmThrowErr(pVM, "Error: dictionary full");
  314     }
  315 
  316     if ((n <= 0) && (dictCellsUsed(pDict) * (int)sizeof(CELL) < -n))
  317     {
  318         vmThrowErr(pVM, "Error: dictionary underflow");
  319     }
  320 
  321     if (pDict->nLists > FICL_DEFAULT_VOCS)
  322     {
  323         dictResetSearchOrder(pDict);
  324         vmThrowErr(pVM, "Error: search order overflow");
  325     }
  326     else if (pDict->nLists < 0)
  327     {
  328         dictResetSearchOrder(pDict);
  329         vmThrowErr(pVM, "Error: search order underflow");
  330     }
  331 
  332     return;
  333 }
  334 
  335 
  336 /**************************************************************************
  337                         d i c t C o p y N a m e
  338 ** Copy up to nFICLNAME characters of the name specified by si into
  339 ** the dictionary starting at "here", then NULL-terminate the name,
  340 ** point "here" to the next available byte, and return the address of
  341 ** the beginning of the name. Used by dictAppendWord.
  342 ** N O T E S :
  343 ** 1. "here" is guaranteed to be aligned after this operation.
  344 ** 2. If the string has zero length, align and return "here"
  345 **************************************************************************/
  346 static char *dictCopyName(FICL_DICT *pDict, STRINGINFO si)
  347 {
  348     char *oldCP    = (char *)pDict->here;
  349     char *cp       = oldCP;
  350     char *name     = SI_PTR(si);
  351     int   i        = SI_COUNT(si);
  352 
  353     if (i == 0)
  354     {
  355         dictAlign(pDict);
  356         return (char *)pDict->here;
  357     }
  358 
  359     if (i > nFICLNAME)
  360         i = nFICLNAME;
  361     
  362     for (; i > 0; --i)
  363     {
  364         *cp++ = *name++;
  365     }
  366 
  367     *cp++ = '\0';
  368 
  369     pDict->here = PTRtoCELL cp;
  370     dictAlign(pDict);
  371     return oldCP;
  372 }
  373 
  374 
  375 /**************************************************************************
  376                         d i c t C r e a t e
  377 ** Create and initialize a dictionary with the specified number
  378 ** of cells capacity, and no hashing (hash size == 1).
  379 **************************************************************************/
  380 FICL_DICT  *dictCreate(unsigned nCells)
  381 {
  382     return dictCreateHashed(nCells, 1);
  383 }
  384 
  385 
  386 FICL_DICT  *dictCreateHashed(unsigned nCells, unsigned nHash)
  387 {
  388     FICL_DICT *pDict;
  389     size_t nAlloc;
  390 
  391     nAlloc =  sizeof (FICL_HASH) + nCells      * sizeof (CELL)
  392                                  + (nHash - 1) * sizeof (FICL_WORD *);
  393 
  394     pDict = ficlMalloc(sizeof (FICL_DICT));
  395     assert(pDict);
  396     memset(pDict, 0, sizeof (FICL_DICT));
  397     pDict->dict = ficlMalloc(nAlloc);
  398     assert(pDict->dict);
  399 
  400     pDict->size = nCells;
  401     dictEmpty(pDict, nHash);
  402     return pDict;
  403 }
  404 
  405 
  406 /**************************************************************************
  407                         d i c t C r e a t e W o r d l i s t
  408 ** Create and initialize an anonymous wordlist
  409 **************************************************************************/
  410 FICL_HASH *dictCreateWordlist(FICL_DICT *dp, int nBuckets)
  411 {
  412     FICL_HASH *pHash;
  413     
  414     dictAlign(dp);
  415     pHash    = (FICL_HASH *)dp->here;
  416     dictAllot(dp, sizeof (FICL_HASH) 
  417         + (nBuckets-1) * sizeof (FICL_WORD *));
  418 
  419     pHash->size = nBuckets;
  420     hashReset(pHash);
  421     return pHash;
  422 }
  423 
  424 
  425 /**************************************************************************
  426                         d i c t D e l e t e 
  427 ** Free all memory allocated for the given dictionary 
  428 **************************************************************************/
  429 void dictDelete(FICL_DICT *pDict)
  430 {
  431     assert(pDict);
  432     ficlFree(pDict);
  433     return;
  434 }
  435 
  436 
  437 /**************************************************************************
  438                         d i c t E m p t y
  439 ** Empty the dictionary, reset its hash table, and reset its search order.
  440 ** Clears and (re-)creates the hash table with the size specified by nHash.
  441 **************************************************************************/
  442 void dictEmpty(FICL_DICT *pDict, unsigned nHash)
  443 {
  444     FICL_HASH *pHash;
  445 
  446     pDict->here = pDict->dict;
  447 
  448     dictAlign(pDict);
  449     pHash = (FICL_HASH *)pDict->here;
  450     dictAllot(pDict, 
  451               sizeof (FICL_HASH) + (nHash - 1) * sizeof (FICL_WORD *));
  452 
  453     pHash->size = nHash;
  454     hashReset(pHash);
  455 
  456     pDict->pForthWords = pHash;
  457     pDict->smudge = NULL;
  458     dictResetSearchOrder(pDict);
  459     return;
  460 }
  461 
  462 
  463 /**************************************************************************
  464                         d i c t H a s h S u m m a r y
  465 ** Calculate a figure of merit for the dictionary hash table based
  466 ** on the average search depth for all the words in the dictionary,
  467 ** assuming uniform distribution of target keys. The figure of merit
  468 ** is the ratio of the total search depth for all keys in the table
  469 ** versus a theoretical optimum that would be achieved if the keys
  470 ** were distributed into the table as evenly as possible. 
  471 ** The figure would be worse if the hash table used an open
  472 ** addressing scheme (i.e. collisions resolved by searching the
  473 ** table for an empty slot) for a given size table.
  474 **************************************************************************/
  475 #if FICL_WANT_FLOAT
  476 void dictHashSummary(FICL_VM *pVM)
  477 {
  478     FICL_DICT *dp = vmGetDict(pVM);
  479     FICL_HASH *pFHash;
  480     FICL_WORD **pHash;
  481     unsigned size;
  482     FICL_WORD *pFW;
  483     unsigned i;
  484     int nMax = 0;
  485     int nWords = 0;
  486     int nFilled;
  487     double avg = 0.0;
  488     double best;
  489     int nAvg, nRem, nDepth;
  490 
  491     dictCheck(dp, pVM, 0);
  492 
  493     pFHash = dp->pSearch[dp->nLists - 1];
  494     pHash  = pFHash->table;
  495     size   = pFHash->size;
  496     nFilled = size;
  497 
  498     for (i = 0; i < size; i++)
  499     {
  500         int n = 0;
  501         pFW = pHash[i];
  502 
  503         while (pFW)
  504         {
  505             ++n;
  506             ++nWords;
  507             pFW = pFW->link;
  508         }
  509 
  510         avg += (double)(n * (n+1)) / 2.0;
  511 
  512         if (n > nMax)
  513             nMax = n;
  514         if (n == 0)
  515             --nFilled;
  516     }
  517 
  518     /* Calc actual avg search depth for this hash */
  519     avg = avg / nWords;
  520 
  521     /* Calc best possible performance with this size hash */
  522     nAvg = nWords / size;
  523     nRem = nWords % size;
  524     nDepth = size * (nAvg * (nAvg+1))/2 + (nAvg+1)*nRem;
  525     best = (double)nDepth/nWords;
  526 
  527     sprintf(pVM->pad, 
  528         "%d bins, %2.0f%% filled, Depth: Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%", 
  529         size,
  530         (double)nFilled * 100.0 / size, nMax,
  531         avg, 
  532         best,
  533         100.0 * best / avg);
  534 
  535     ficlTextOut(pVM, pVM->pad, 1);
  536 
  537     return;
  538 }
  539 #endif
  540 
  541 /**************************************************************************
  542                         d i c t I n c l u d e s
  543 ** Returns TRUE iff the given pointer is within the address range of 
  544 ** the dictionary.
  545 **************************************************************************/
  546 int dictIncludes(FICL_DICT *pDict, void *p)
  547 {
  548     return ((p >= (void *) &pDict->dict)
  549         &&  (p <  (void *)(&pDict->dict + pDict->size)) 
  550            );
  551 }
  552 
  553 /**************************************************************************
  554                         d i c t L o o k u p
  555 ** Find the FICL_WORD that matches the given name and length.
  556 ** If found, returns the word's address. Otherwise returns NULL.
  557 ** Uses the search order list to search multiple wordlists.
  558 **************************************************************************/
  559 FICL_WORD *dictLookup(FICL_DICT *pDict, STRINGINFO si)
  560 {
  561     FICL_WORD *pFW = NULL;
  562     FICL_HASH *pHash;
  563     int i;
  564     UNS16 hashCode   = hashHashCode(si);
  565 
  566     assert(pDict);
  567 
  568     ficlLockDictionary(1);
  569 
  570     for (i = (int)pDict->nLists - 1; (i >= 0) && (!pFW); --i)
  571     {
  572         pHash = pDict->pSearch[i];
  573         pFW = hashLookup(pHash, si, hashCode);
  574     }
  575 
  576     ficlLockDictionary(0);
  577     return pFW;
  578 }
  579 
  580 
  581 /**************************************************************************
  582                         f i c l L o o k u p L o c
  583 ** Same as dictLookup, but looks in system locals dictionary first...
  584 ** Assumes locals dictionary has only one wordlist...
  585 **************************************************************************/
  586 #if FICL_WANT_LOCALS
  587 FICL_WORD *ficlLookupLoc(FICL_SYSTEM *pSys, STRINGINFO si)
  588 {
  589     FICL_WORD *pFW = NULL;
  590         FICL_DICT *pDict = pSys->dp;
  591     FICL_HASH *pHash = ficlGetLoc(pSys)->pForthWords;
  592     int i;
  593     UNS16 hashCode   = hashHashCode(si);
  594 
  595     assert(pHash);
  596     assert(pDict);
  597 
  598     ficlLockDictionary(1);
  599     /* 
  600     ** check the locals dict first... 
  601     */
  602     pFW = hashLookup(pHash, si, hashCode);
  603 
  604     /* 
  605     ** If no joy, (!pFW) --------------------------v
  606     ** iterate over the search list in the main dict 
  607     */
  608     for (i = (int)pDict->nLists - 1; (i >= 0) && (!pFW); --i)
  609     {
  610         pHash = pDict->pSearch[i];
  611         pFW = hashLookup(pHash, si, hashCode);
  612     }
  613 
  614     ficlLockDictionary(0);
  615     return pFW;
  616 }
  617 #endif
  618 
  619 
  620 /**************************************************************************
  621                     d i c t R e s e t S e a r c h O r d e r
  622 ** Initialize the dictionary search order list to sane state
  623 **************************************************************************/
  624 void dictResetSearchOrder(FICL_DICT *pDict)
  625 {
  626     assert(pDict);
  627     pDict->pCompile = pDict->pForthWords;
  628     pDict->nLists = 1;
  629     pDict->pSearch[0] = pDict->pForthWords;
  630     return;
  631 }
  632 
  633 
  634 /**************************************************************************
  635                         d i c t S e t F l a g s
  636 ** Changes the flags field of the most recently defined word:
  637 ** Set all bits that are ones in the set parameter, clear all bits
  638 ** that are ones in the clr parameter. Clear wins in case the same bit
  639 ** is set in both parameters.
  640 **************************************************************************/
  641 void dictSetFlags(FICL_DICT *pDict, UNS8 set, UNS8 clr)
  642 {
  643     assert(pDict->smudge);
  644     pDict->smudge->flags |= set;
  645     pDict->smudge->flags &= ~clr;
  646     return;
  647 }
  648 
  649 
  650 /**************************************************************************
  651                         d i c t S e t I m m e d i a t e 
  652 ** Set the most recently defined word as IMMEDIATE
  653 **************************************************************************/
  654 void dictSetImmediate(FICL_DICT *pDict)
  655 {
  656     assert(pDict->smudge);
  657     pDict->smudge->flags |= FW_IMMEDIATE;
  658     return;
  659 }
  660 
  661 
  662 /**************************************************************************
  663                         d i c t U n s m u d g e 
  664 ** Completes the definition of a word by linking it
  665 ** into the main list
  666 **************************************************************************/
  667 void dictUnsmudge(FICL_DICT *pDict)
  668 {
  669     FICL_WORD *pFW = pDict->smudge;
  670     FICL_HASH *pHash = pDict->pCompile;
  671 
  672     assert(pHash);
  673     assert(pFW);
  674     /*
  675     ** :noname words never get linked into the list...
  676     */
  677     if (pFW->nName > 0)
  678         hashInsertWord(pHash, pFW);
  679     pFW->flags &= ~(FW_SMUDGE);
  680     return;
  681 }
  682 
  683 
  684 /**************************************************************************
  685                         d i c t W h e r e
  686 ** Returns the value of the HERE pointer -- the address
  687 ** of the next free cell in the dictionary
  688 **************************************************************************/
  689 CELL *dictWhere(FICL_DICT *pDict)
  690 {
  691     return pDict->here;
  692 }
  693 
  694 
  695 /**************************************************************************
  696                         h a s h F o r g e t
  697 ** Unlink all words in the hash that have addresses greater than or
  698 ** equal to the address supplied. Implementation factor for FORGET
  699 ** and MARKER.
  700 **************************************************************************/
  701 void hashForget(FICL_HASH *pHash, void *where)
  702 {
  703     FICL_WORD *pWord;
  704     unsigned i;
  705 
  706     assert(pHash);
  707     assert(where);
  708 
  709     for (i = 0; i < pHash->size; i++)
  710     {
  711         pWord = pHash->table[i];
  712 
  713         while ((void *)pWord >= where)
  714         {
  715             pWord = pWord->link;
  716         }
  717 
  718         pHash->table[i] = pWord;
  719     }
  720 
  721     return;
  722 }
  723 
  724 
  725 /**************************************************************************
  726                         h a s h H a s h C o d e
  727 ** 
  728 ** Generate a 16 bit hashcode from a character string using a rolling
  729 ** shift and add stolen from PJ Weinberger of Bell Labs fame. Case folds
  730 ** the name before hashing it...
  731 ** N O T E : If string has zero length, returns zero.
  732 **************************************************************************/
  733 UNS16 hashHashCode(STRINGINFO si)
  734 {   
  735     /* hashPJW */
  736     UNS8 *cp;
  737     UNS16 code = (UNS16)si.count;
  738     UNS16 shift = 0;
  739 
  740     if (si.count == 0)
  741         return 0;
  742 
  743     /* changed to run without errors under Purify -- lch */
  744     for (cp = (UNS8 *)si.cp; si.count && *cp; cp++, si.count--)
  745     {
  746         code = (UNS16)((code << 4) + tolower(*cp));
  747         shift = (UNS16)(code & 0xf000);
  748         if (shift)
  749         {
  750             code ^= (UNS16)(shift >> 8);
  751             code ^= (UNS16)shift;
  752         }
  753     }
  754 
  755     return (UNS16)code;
  756 }
  757 
  758 
  759 
  760 
  761 /**************************************************************************
  762                         h a s h I n s e r t W o r d
  763 ** Put a word into the hash table using the word's hashcode as
  764 ** an index (modulo the table size).
  765 **************************************************************************/
  766 void hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW)
  767 {
  768     FICL_WORD **pList;
  769 
  770     assert(pHash);
  771     assert(pFW);
  772 
  773     if (pHash->size == 1)
  774     {
  775         pList = pHash->table;
  776     }
  777     else
  778     {
  779         pList = pHash->table + (pFW->hash % pHash->size);
  780     }
  781 
  782     pFW->link = *pList;
  783     *pList = pFW;
  784     return;
  785 }
  786 
  787 
  788 /**************************************************************************
  789                         h a s h L o o k u p
  790 ** Find a name in the hash table given the hashcode and text of the name.
  791 ** Returns the address of the corresponding FICL_WORD if found, 
  792 ** otherwise NULL.
  793 ** Note: outer loop on link field supports inheritance in wordlists.
  794 ** It's not part of ANS Forth - ficl only. hashReset creates wordlists
  795 ** with NULL link fields.
  796 **************************************************************************/
  797 FICL_WORD *hashLookup(FICL_HASH *pHash, STRINGINFO si, UNS16 hashCode)
  798 {
  799     FICL_UNS nCmp = si.count;
  800     FICL_WORD *pFW;
  801     UNS16 hashIdx;
  802 
  803     if (nCmp > nFICLNAME)
  804         nCmp = nFICLNAME;
  805 
  806     for (; pHash != NULL; pHash = pHash->link)
  807     {
  808         if (pHash->size > 1)
  809             hashIdx = (UNS16)(hashCode % pHash->size);
  810         else            /* avoid the modulo op for single threaded lists */
  811             hashIdx = 0;
  812 
  813         for (pFW = pHash->table[hashIdx]; pFW; pFW = pFW->link)
  814         {
  815             if ( (pFW->nName == si.count) 
  816                 && (!strincmp(si.cp, pFW->name, nCmp)) )
  817                 return pFW;
  818 #if FICL_ROBUST
  819             assert(pFW != pFW->link);
  820 #endif
  821         }
  822     }
  823 
  824     return NULL;
  825 }
  826 
  827 
  828 /**************************************************************************
  829                              h a s h R e s e t
  830 ** Initialize a FICL_HASH to empty state.
  831 **************************************************************************/
  832 void hashReset(FICL_HASH *pHash)
  833 {
  834     unsigned i;
  835 
  836     assert(pHash);
  837 
  838     for (i = 0; i < pHash->size; i++)
  839     {
  840         pHash->table[i] = NULL;
  841     }
  842 
  843     pHash->link = NULL;
  844     pHash->name = NULL;
  845     return;
  846 }
  847 
  848 /**************************************************************************
  849                     d i c t C h e c k T h r e s h o l d
  850 ** Verify if an increase in the dictionary size is warranted, and do it if
  851 ** so.
  852 **************************************************************************/
  853 
  854 void dictCheckThreshold(FICL_DICT* dp)
  855 {
  856     if( dictCellsAvail(dp) < dictThreshold.u ) {
  857         dp->dict = ficlMalloc( dictIncrease.u * sizeof (CELL) );
  858         assert(dp->dict);
  859         dp->here = dp->dict;
  860         dp->size = dictIncrease.u;
  861         dictAlign(dp);
  862     }
  863 }
  864 

Cache object: 310165be57f7add2e965079b74f65757


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.