Print this page
    
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/common/ficl/tools.c
          +++ new/usr/src/common/ficl/tools.c
   1    1  /*
   2    2   * t o o l s . c
   3    3   * Forth Inspired Command Language - programming tools
   4    4   * Author: John Sadler (john_sadler@alum.mit.edu)
   5    5   * Created: 20 June 2000
   6    6   * $Id: tools.c,v 1.12 2010/08/12 13:57:22 asau Exp $
   7    7   */
   8    8  /*
   9    9   * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
  10   10   * All rights reserved.
  11   11   *
  12   12   * Get the latest Ficl release at http://ficl.sourceforge.net
  13   13   *
  14   14   * I am interested in hearing from anyone who uses Ficl. If you have
  15   15   * a problem, a success story, a defect, an enhancement request, or
  16   16   * if you would like to contribute to the Ficl release, please
  17   17   * contact me by email at the address above.
  18   18   *
  19   19   * L I C E N S E  and  D I S C L A I M E R
  20   20   *
  21   21   * Redistribution and use in source and binary forms, with or without
  22   22   * modification, are permitted provided that the following conditions
  23   23   * are met:
  24   24   * 1. Redistributions of source code must retain the above copyright
  25   25   *    notice, this list of conditions and the following disclaimer.
  26   26   * 2. Redistributions in binary form must reproduce the above copyright
  27   27   *    notice, this list of conditions and the following disclaimer in the
  28   28   *    documentation and/or other materials provided with the distribution.
  29   29   *
  30   30   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  31   31   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32   32   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33   33   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  34   34   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35   35   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36   36   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37   37   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  38   38   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39   39   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  40   40   * SUCH DAMAGE.
  41   41   */
  42   42  
  43   43  /*
  44   44   * NOTES:
  45   45   * SEE needs information about the addresses of functions that
  46   46   * are the CFAs of colon definitions, constants, variables, DOES>
  47   47   * words, and so on. It gets this information from a table and supporting
  48   48   * functions in words.c.
  49   49   * fiColonParen fiDoDoes createParen fiVariableParen fiUserParen fiConstantParen
  50   50   *
  51   51   * Step and break debugger for Ficl
  52   52   * debug  ( xt -- )   Start debugging an xt
  53   53   * Set a breakpoint
  54   54   * Specify breakpoint default action
  55   55   */
  56   56  
  57   57  #include "ficl.h"
  58   58  
  59   59  extern void exit(int);
  60   60  
  61   61  static void ficlPrimitiveStepIn(ficlVm *vm);
  62   62  static void ficlPrimitiveStepOver(ficlVm *vm);
  63   63  static void ficlPrimitiveStepBreak(ficlVm *vm);
  64   64  
  65   65  void
  66   66  ficlCallbackAssert(ficlCallback *callback, int expression,
  67   67      char *expressionString, char *filename, int line)
  68   68  {
  69   69  #if FICL_ROBUST >= 1
  70   70          if (!expression) {
  71   71                  static char buffer[256];
  72   72                  sprintf(buffer, "ASSERTION FAILED at %s:%d: \"%s\"\n",
  73   73                      filename, line, expressionString);
  74   74                  ficlCallbackTextOut(callback, buffer);
  75   75                  exit(-1);
  76   76          }
  77   77  #else /* FICL_ROBUST >= 1 */
  78   78          FICL_IGNORE(callback);
  79   79          FICL_IGNORE(expression);
  80   80          FICL_IGNORE(expressionString);
  81   81          FICL_IGNORE(filename);
  82   82          FICL_IGNORE(line);
  83   83  #endif /* FICL_ROBUST >= 1 */
  84   84  }
  85   85  
  86   86  /*
  87   87   * v m S e t B r e a k
  88   88   * Set a breakpoint at the current value of IP by
  89   89   * storing that address in a BREAKPOINT record
  90   90   */
  91   91  static void
  92   92  ficlVmSetBreak(ficlVm *vm, ficlBreakpoint *pBP)
  93   93  {
  94   94          ficlWord *pStep = ficlSystemLookup(vm->callback.system, "step-break");
  95   95          FICL_VM_ASSERT(vm, pStep);
  96   96  
  97   97          pBP->address = vm->ip;
  98   98          pBP->oldXT = *vm->ip;
  99   99          *vm->ip = pStep;
 100  100  }
 101  101  
 102  102  /*
 103  103   * d e b u g P r o m p t
 104  104   */
 105  105  static void
 106  106  ficlDebugPrompt(ficlVm *vm, int debug)
 107  107  {
 108  108          if (debug)
 109  109                  setenv("prompt", "dbg> ", 1);
 110  110          else
 111  111                  setenv("prompt", "${interpret}", 1);
 112  112  }
 113  113  
 114  114  #if 0
 115  115  static int
 116  116  isPrimitive(ficlWord *word)
 117  117  {
 118  118          ficlWordKind wk = ficlWordClassify(word);
 119  119          return ((wk != COLON) && (wk != DOES));
 120  120  }
 121  121  #endif
 122  122  
 123  123  /*
 124  124   * d i c t H a s h S u m m a r y
 125  125   * Calculate a figure of merit for the dictionary hash table based
 126  126   * on the average search depth for all the words in the dictionary,
 127  127   * assuming uniform distribution of target keys. The figure of merit
 128  128   * is the ratio of the total search depth for all keys in the table
 129  129   * versus a theoretical optimum that would be achieved if the keys
 130  130   * were distributed into the table as evenly as possible.
 131  131   * The figure would be worse if the hash table used an open
 132  132   * addressing scheme (i.e. collisions resolved by searching the
 133  133   * table for an empty slot) for a given size table.
 134  134   */
 135  135  #if FICL_WANT_FLOAT
 136  136  void
 137  137  ficlPrimitiveHashSummary(ficlVm *vm)
 138  138  {
 139  139          ficlDictionary *dictionary = ficlVmGetDictionary(vm);
 140  140          ficlHash *pFHash;
 141  141          ficlWord **hash;
 142  142          unsigned size;
 143  143          ficlWord *word;
 144  144          unsigned i;
 145  145          int nMax = 0;
 146  146          int nWords = 0;
 147  147          int nFilled;
 148  148          double avg = 0.0;
 149  149          double best;
 150  150          int nAvg, nRem, nDepth;
 151  151  
 152  152          FICL_VM_DICTIONARY_CHECK(vm, dictionary, 0);
 153  153  
 154  154          pFHash = dictionary->wordlists[dictionary->wordlistCount - 1];
 155  155          hash = pFHash->table;
 156  156          size = pFHash->size;
 157  157          nFilled = size;
 158  158  
 159  159          for (i = 0; i < size; i++) {
 160  160                  int n = 0;
 161  161                  word = hash[i];
 162  162  
 163  163                  while (word) {
 164  164                          ++n;
 165  165                          ++nWords;
 166  166                          word = word->link;
 167  167                  }
 168  168  
 169  169                  avg += (double)(n * (n+1)) / 2.0;
 170  170  
 171  171                  if (n > nMax)
 172  172                          nMax = n;
 173  173                  if (n == 0)
 174  174                          --nFilled;
 175  175          }
 176  176  
 177  177          /* Calc actual avg search depth for this hash */
 178  178          avg = avg / nWords;
 179  179  
 180  180          /* Calc best possible performance with this size hash */
 181  181          nAvg = nWords / size;
 182  182          nRem = nWords % size;
 183  183          nDepth = size * (nAvg * (nAvg+1))/2 + (nAvg+1)*nRem;
 184  184          best = (double)nDepth/nWords;
 185  185  
 186  186          sprintf(vm->pad, "%d bins, %2.0f%% filled, Depth: "
 187  187              "Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%\n",
 188  188              size, (double)nFilled * 100.0 / size, nMax,
 189  189              avg, best, 100.0 * best / avg);
 190  190  
 191  191          ficlVmTextOut(vm, vm->pad);
 192  192  }
 193  193  #endif
 194  194  
 195  195  /*
 196  196   * Here's the outer part of the decompiler. It's
 197  197   * just a big nested conditional that checks the
 198  198   * CFA of the word to decompile for each kind of
 199  199   * known word-builder code, and tries to do
 200  200   * something appropriate. If the CFA is not recognized,
 201  201   * just indicate that it is a primitive.
 202  202   */
 203  203  static void
 204  204  ficlPrimitiveSeeXT(ficlVm *vm)
 205  205  {
 206  206          ficlWord *word;
 207  207          ficlWordKind kind;
 208  208  
 209  209          word = (ficlWord *)ficlStackPopPointer(vm->dataStack);
 210  210          kind = ficlWordClassify(word);
 211  211  
 212  212          switch (kind) {
 213  213          case FICL_WORDKIND_COLON:
 214  214                  sprintf(vm->pad, ": %.*s\n", word->length, word->name);
 215  215                  ficlVmTextOut(vm, vm->pad);
 216  216                  ficlDictionarySee(ficlVmGetDictionary(vm), word,
 217  217                      &(vm->callback));
 218  218          break;
 219  219          case FICL_WORDKIND_DOES:
 220  220                  ficlVmTextOut(vm, "does>\n");
 221  221                  ficlDictionarySee(ficlVmGetDictionary(vm),
 222  222                      (ficlWord *)word->param->p, &(vm->callback));
 223  223          break;
 224  224          case FICL_WORDKIND_CREATE:
 225  225                  ficlVmTextOut(vm, "create\n");
 226  226          break;
 227  227          case FICL_WORDKIND_VARIABLE:
 228  228                  sprintf(vm->pad, "variable = %ld (%#lx)\n",
 229  229                      (long)word->param->i, (long unsigned)word->param->u);
 230  230                  ficlVmTextOut(vm, vm->pad);
 231  231          break;
 232  232  #if FICL_WANT_USER
 233  233          case FICL_WORDKIND_USER:
 234  234                  sprintf(vm->pad, "user variable %ld (%#lx)\n",
 235  235                      (long)word->param->i, (long unsigned)word->param->u);
 236  236                  ficlVmTextOut(vm, vm->pad);
 237  237          break;
 238  238  #endif
 239  239          case FICL_WORDKIND_CONSTANT:
 240  240                  sprintf(vm->pad, "constant = %ld (%#lx)\n",
 241  241                      (long)word->param->i, (long unsigned)word->param->u);
 242  242                  ficlVmTextOut(vm, vm->pad);
 243  243          break;
 244  244          case FICL_WORDKIND_2CONSTANT:
 245  245                  sprintf(vm->pad, "constant = %ld %ld (%#lx %#lx)\n",
 246  246                      (long)word->param[1].i, (long)word->param->i,
 247  247                      (long unsigned)word->param[1].u,
 248  248                      (long unsigned)word->param->u);
 249  249                  ficlVmTextOut(vm, vm->pad);
 250  250          break;
 251  251  
 252  252          default:
 253  253                  sprintf(vm->pad, "%.*s is a primitive\n", word->length,
 254  254                      word->name);
 255  255                  ficlVmTextOut(vm, vm->pad);
 256  256          break;
 257  257          }
 258  258  
 259  259          if (word->flags & FICL_WORD_IMMEDIATE) {
 260  260                  ficlVmTextOut(vm, "immediate\n");
 261  261          }
 262  262  
 263  263          if (word->flags & FICL_WORD_COMPILE_ONLY) {
 264  264                  ficlVmTextOut(vm, "compile-only\n");
 265  265          }
 266  266  }
 267  267  
 268  268  static void
 269  269  ficlPrimitiveSee(ficlVm *vm)
 270  270  {
 271  271          ficlPrimitiveTick(vm);
 272  272          ficlPrimitiveSeeXT(vm);
 273  273  }
 274  274  
 275  275  /*
 276  276   * f i c l D e b u g X T
 277  277   * debug  ( xt -- )
 278  278   * Given an xt of a colon definition or a word defined by DOES>, set the
 279  279   * VM up to debug the word: push IP, set the xt as the next thing to execute,
 280  280   * set a breakpoint at its first instruction, and run to the breakpoint.
 281  281   * Note: the semantics of this word are equivalent to "step in"
 282  282   */
 283  283  static void
 284  284  ficlPrimitiveDebugXT(ficlVm *vm)
 285  285  {
 286  286          ficlWord *xt = ficlStackPopPointer(vm->dataStack);
 287  287          ficlWordKind wk = ficlWordClassify(xt);
 288  288  
 289  289          ficlStackPushPointer(vm->dataStack, xt);
 290  290          ficlPrimitiveSeeXT(vm);
 291  291  
 292  292          switch (wk) {
 293  293          case FICL_WORDKIND_COLON:
 294  294          case FICL_WORDKIND_DOES:
 295  295                  /*
 296  296                   * Run the colon code and set a breakpoint at the next
 297  297                   * instruction
 298  298                   */
 299  299                  ficlVmExecuteWord(vm, xt);
 300  300                  ficlVmSetBreak(vm, &(vm->callback.system->breakpoint));
 301  301          break;
 302  302          default:
 303  303                  ficlVmExecuteWord(vm, xt);
 304  304          break;
 305  305          }
 306  306  }
 307  307  
 308  308  /*
 309  309   * s t e p I n
 310  310   * Ficl
 311  311   * Execute the next instruction, stepping into it if it's a colon definition
 312  312   * or a does> word. This is the easy kind of step.
 313  313   */
 314  314  static void
 315  315  ficlPrimitiveStepIn(ficlVm *vm)
 316  316  {
 317  317          /*
 318  318           * Do one step of the inner loop
 319  319           */
 320  320          ficlVmExecuteWord(vm, *vm->ip++);
 321  321  
 322  322          /*
 323  323           * Now set a breakpoint at the next instruction
 324  324           */
 325  325          ficlVmSetBreak(vm, &(vm->callback.system->breakpoint));
 326  326  }
 327  327  
 328  328  /*
 329  329   * s t e p O v e r
 330  330   * Ficl
 331  331   * Execute the next instruction atomically. This requires some insight into
 332  332   * the memory layout of compiled code. Set a breakpoint at the next instruction
 333  333   * in this word, and run until we hit it
 334  334   */
 335  335  static void
 336  336  ficlPrimitiveStepOver(ficlVm *vm)
 337  337  {
 338  338          ficlWord *word;
 339  339          ficlWordKind kind;
 340  340          ficlWord *pStep = ficlSystemLookup(vm->callback.system, "step-break");
 341  341          FICL_VM_ASSERT(vm, pStep);
 342  342  
 343  343          word = *vm->ip;
 344  344          kind = ficlWordClassify(word);
 345  345  
 346  346          switch (kind) {
 347  347          case FICL_WORDKIND_COLON:
 348  348          case FICL_WORDKIND_DOES:
 349  349                  /*
 350  350                   * assume that the next ficlCell holds an instruction
 351  351                   * set a breakpoint there and return to the inner interpreter
 352  352                   */
 353  353                  vm->callback.system->breakpoint.address = vm->ip + 1;
 354  354                  vm->callback.system->breakpoint.oldXT =  vm->ip[1];
 355  355                  vm->ip[1] = pStep;
 356  356          break;
 357  357          default:
 358  358                  ficlPrimitiveStepIn(vm);
 359  359          break;
 360  360          }
 361  361  }
 362  362  
 363  363  /*
 364  364   * s t e p - b r e a k
 365  365   * Ficl
 366  366   * Handles breakpoints for stepped execution.
 367  367   * Upon entry, breakpoint contains the address and replaced instruction
 368  368   * of the current breakpoint.
 369  369   * Clear the breakpoint
 370  370   * Get a command from the console.
 371  371   * i (step in) - execute the current instruction and set a new breakpoint
 372  372   *    at the IP
 373  373   * o (step over) - execute the current instruction to completion and set
 374  374   *    a new breakpoint at the IP
 375  375   * g (go) - execute the current instruction and exit
 376  376   * q (quit) - abort current word
 377  377   * b (toggle breakpoint)
 378  378   */
 379  379  
 380  380  extern char *ficlDictionaryInstructionNames[];
 381  381  
 382  382  static void
 383  383  ficlPrimitiveStepBreak(ficlVm *vm)
 384  384  {
 385  385          ficlString command;
 386  386          ficlWord *word;
 387  387          ficlWord *pOnStep;
 388  388          int debug = 1;
 389  389  
 390  390          if (!vm->restart) {
 391  391                  FICL_VM_ASSERT(vm, vm->callback.system->breakpoint.address);
 392  392                  FICL_VM_ASSERT(vm, vm->callback.system->breakpoint.oldXT);
 393  393  
 394  394                  /*
 395  395                   * Clear the breakpoint that caused me to run
 396  396                   * Restore the original instruction at the breakpoint,
 397  397                   * and restore the IP
 398  398                   */
 399  399                  vm->ip = (ficlIp)(vm->callback.system->breakpoint.address);
 400  400                  *vm->ip = vm->callback.system->breakpoint.oldXT;
 401  401  
 402  402                  /*
 403  403                   * If there's an onStep, do it
 404  404                   */
 405  405                  pOnStep = ficlSystemLookup(vm->callback.system, "on-step");
 406  406                  if (pOnStep)
 407  407                          ficlVmExecuteXT(vm, pOnStep);
 408  408  
 409  409                  /*
 410  410                   * Print the name of the next instruction
 411  411                   */
 412  412                  word = vm->callback.system->breakpoint.oldXT;
 413  413  
 414  414                  if ((((ficlInstruction)word) > ficlInstructionInvalid) &&
 415  415                      (((ficlInstruction)word) < ficlInstructionLast))
 416  416                          sprintf(vm->pad, "next: %s (instruction %ld)\n",
 417  417                              ficlDictionaryInstructionNames[(long)word],
 418  418                              (long)word);
 419  419                  else {
 420  420                          sprintf(vm->pad, "next: %s\n", word->name);
 421  421                          if (strcmp(word->name, "interpret") == 0)
 422  422                                  debug = 0;
 423  423                  }
 424  424  
 425  425                  ficlVmTextOut(vm, vm->pad);
 426  426                  ficlDebugPrompt(vm, debug);
 427  427          } else {
 428  428                  vm->restart = 0;
 429  429          }
 430  430  
 431  431          command = ficlVmGetWord(vm);
 432  432  
 433  433          switch (command.text[0]) {
 434  434                  case 'i':
 435  435                          ficlPrimitiveStepIn(vm);
 436  436                  break;
 437  437  
 438  438                  case 'o':
 439  439                          ficlPrimitiveStepOver(vm);
 440  440                  break;
 441  441  
 442  442                  case 'g':
 443  443                  break;
 444  444  
 445  445                  case 'l': {
 446  446                          ficlWord *xt;
 447  447                          xt = ficlDictionaryFindEnclosingWord(
 448  448                              ficlVmGetDictionary(vm), (ficlCell *)(vm->ip));
 449  449                          if (xt) {
 450  450                                  ficlStackPushPointer(vm->dataStack, xt);
 451  451                                  ficlPrimitiveSeeXT(vm);
 452  452                          } else {
 453  453                                  ficlVmTextOut(vm, "sorry - can't do that\n");
 454  454                          }
 455  455                          ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
 456  456                  break;
 457  457                  }
 458  458  
 459  459                  case 'q':
 460  460                          ficlDebugPrompt(vm, 0);
 461  461                          ficlVmThrow(vm, FICL_VM_STATUS_ABORT);
 462  462                          break;
 463  463                  case 'x': {
 464  464                          /*
 465  465                           * Take whatever's left in the TIB and feed it to a
 466  466                           * subordinate ficlVmExecuteString
 467  467                           */
 468  468                          int returnValue;
 469  469                          ficlString s;
 470  470                          ficlWord *oldRunningWord = vm->runningWord;
 471  471  
 472  472                          FICL_STRING_SET_POINTER(s,
 473  473                              vm->tib.text + vm->tib.index);
 474  474                          FICL_STRING_SET_LENGTH(s,
 475  475                              vm->tib.end - FICL_STRING_GET_POINTER(s));
 476  476  
 477  477                          returnValue = ficlVmExecuteString(vm, s);
 478  478  
 479  479                          if (returnValue == FICL_VM_STATUS_OUT_OF_TEXT) {
 480  480                                  returnValue = FICL_VM_STATUS_RESTART;
 481  481                                  vm->runningWord = oldRunningWord;
 482  482                                  ficlVmTextOut(vm, "\n");
 483  483                          }
 484  484                          if (returnValue == FICL_VM_STATUS_ERROR_EXIT)
 485  485                                  ficlDebugPrompt(vm, 0);
 486  486  
 487  487                          ficlVmThrow(vm, returnValue);
 488  488                          break;
 489  489                  }
 490  490  
 491  491                  default:
 492  492                          ficlVmTextOut(vm,
 493  493                              "i -- step In\n"
 494  494                              "o -- step Over\n"
 495  495                              "g -- Go (execute to completion)\n"
 496  496                              "l -- List source code\n"
 497  497                              "q -- Quit (stop debugging and abort)\n"
 498  498                              "x -- eXecute the rest of the line "
 499  499                              "as Ficl words\n");
 500  500                          ficlDebugPrompt(vm, 1);
 501  501                          ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
 502  502                  break;
 503  503          }
 504  504  
 505  505          ficlDebugPrompt(vm, 0);
 506  506  }
 507  507  
 508  508  /*
 509  509   * b y e
 510  510   * TOOLS
 511  511   * Signal the system to shut down - this causes ficlExec to return
 512  512   * VM_USEREXIT. The rest is up to you.
 513  513   */
 514  514  static void
 515  515  ficlPrimitiveBye(ficlVm *vm)
 516  516  {
 517  517          ficlVmThrow(vm, FICL_VM_STATUS_USER_EXIT);
 518  518  }
 519  519  
 520  520  /*
 521  521   * d i s p l a y S t a c k
 522  522   * TOOLS
 523  523   * Display the parameter stack (code for ".s")
 524  524   */
 525  525  
 526  526  struct stackContext
 527  527  {
 528  528          ficlVm *vm;
 529  529          ficlDictionary *dictionary;
 530  530          int count;
 531  531  };
 532  532  
 533  533  static ficlInteger
 534  534  ficlStackDisplayCallback(void *c, ficlCell *cell)
 535  535  {
 536  536          struct stackContext *context = (struct stackContext *)c;
 537  537          char buffer[80];
 538  538  
 539  539  #ifdef _LP64
 540  540          snprintf(buffer, sizeof (buffer), "[0x%016lx %3d]: %20ld (0x%016lx)\n",
 541  541              (unsigned long)cell, context->count++, (long)cell->i,
 542  542              (unsigned long)cell->u);
 543  543  #else
 544  544          snprintf(buffer, sizeof (buffer), "[0x%08x %3d]: %12d (0x%08x)\n",
 545  545              (unsigned)cell, context->count++, cell->i, cell->u);
 546  546  #endif
 547  547  
 548  548          ficlVmTextOut(context->vm, buffer);
 549  549          return (FICL_TRUE);
 550  550  }
 551  551  
 552  552  void
 553  553  ficlStackDisplay(ficlStack *stack, ficlStackWalkFunction callback,
 554  554      void *context)
 555  555  {
 556  556          ficlVm *vm = stack->vm;
 557  557          char buffer[128];
 558  558          struct stackContext myContext;
 559  559  
 560  560          FICL_STACK_CHECK(stack, 0, 0);
 561  561  
 562  562  #ifdef _LP64
 563  563          sprintf(buffer, "[%s stack has %d entries, top at 0x%016lx]\n",
 564  564              stack->name, ficlStackDepth(stack), (unsigned long)stack->top);
 565  565  #else
 566  566          sprintf(buffer, "[%s stack has %d entries, top at 0x%08x]\n",
 567  567              stack->name, ficlStackDepth(stack), (unsigned)stack->top);
 568  568  #endif
 569  569          ficlVmTextOut(vm, buffer);
 570  570  
 571  571          if (callback == NULL) {
 572  572                  myContext.vm = vm;
 573  573                  myContext.count = 0;
 574  574                  context = &myContext;
 575  575                  callback = ficlStackDisplayCallback;
 576  576          }
 577  577          ficlStackWalk(stack, callback, context, FICL_FALSE);
 578  578  
 579  579  #ifdef _LP64
 580  580          sprintf(buffer, "[%s stack base at 0x%016lx]\n", stack->name,
 581  581              (unsigned long)stack->base);
 582  582  #else
 583  583          sprintf(buffer, "[%s stack base at 0x%08x]\n", stack->name,
 584  584              (unsigned)stack->base);
 585  585  #endif
 586  586          ficlVmTextOut(vm, buffer);
 587  587  }
 588  588  
 589  589  void
 590  590  ficlVmDisplayDataStack(ficlVm *vm)
 591  591  {
 592  592          ficlStackDisplay(vm->dataStack, NULL, NULL);
 593  593  }
 594  594  
 595  595  static ficlInteger
 596  596  ficlStackDisplaySimpleCallback(void *c, ficlCell *cell)
 597  597  {
 598  598          struct stackContext *context = (struct stackContext *)c;
 599  599          char buffer[32];
 600  600  
 601  601          sprintf(buffer, "%s%ld", context->count ? " " : "", (long)cell->i);
 602  602          context->count++;
 603  603          ficlVmTextOut(context->vm, buffer);
 604  604          return (FICL_TRUE);
 605  605  }
 606  606  
 607  607  void
 608  608  ficlVmDisplayDataStackSimple(ficlVm *vm)
 609  609  {
 610  610          ficlStack *stack = vm->dataStack;
 611  611          char buffer[32];
 612  612          struct stackContext context;
 613  613  
 614  614          FICL_STACK_CHECK(stack, 0, 0);
 615  615  
 616  616          sprintf(buffer, "[%d] ", ficlStackDepth(stack));
 617  617          ficlVmTextOut(vm, buffer);
 618  618  
 619  619          context.vm = vm;
 620  620          context.count = 0;
 621  621          ficlStackWalk(stack, ficlStackDisplaySimpleCallback, &context,
 622  622              FICL_TRUE);
 623  623  }
 624  624  
 625  625  static ficlInteger
 626  626  ficlReturnStackDisplayCallback(void *c, ficlCell *cell)
 627  627  {
 628  628          struct stackContext *context = (struct stackContext *)c;
 629  629          char buffer[128];
 630  630  
 631  631  #ifdef _LP64
 632  632          sprintf(buffer, "[0x%016lx %3d] %20ld (0x%016lx)", (unsigned long)cell,
 633  633              context->count++, cell->i, cell->u);
 634  634  #else
 635  635          sprintf(buffer, "[0x%08x %3d] %12d (0x%08x)", (unsigned)cell,
 636  636              context->count++, cell->i, cell->u);
 637  637  #endif
 638  638  
 639  639          /*
 640  640           * Attempt to find the word that contains the return
 641  641           * stack address (as if it is part of a colon definition).
 642  642           * If this works, also print the name of the word.
 643  643           */
 644  644          if (ficlDictionaryIncludes(context->dictionary, cell->p)) {
 645  645                  ficlWord *word;
 646  646                  word = ficlDictionaryFindEnclosingWord(context->dictionary,
 647  647                      cell->p);
 648  648                  if (word) {
 649  649                          int offset = (ficlCell *)cell->p - &word->param[0];
 650  650                          sprintf(buffer + strlen(buffer), ", %s + %d ",
 651  651                              word->name, offset);
 652  652                  }
 653  653          }
 654  654          strcat(buffer, "\n");
 655  655          ficlVmTextOut(context->vm, buffer);
 656  656          return (FICL_TRUE);
 657  657  }
 658  658  
 659  659  void
 660  660  ficlVmDisplayReturnStack(ficlVm *vm)
 661  661  {
 662  662          struct stackContext context;
 663  663          context.vm = vm;
 664  664          context.count = 0;
 665  665          context.dictionary = ficlVmGetDictionary(vm);
 666  666          ficlStackDisplay(vm->returnStack, ficlReturnStackDisplayCallback,
 667  667              &context);
 668  668  }
 669  669  
 670  670  /*
 671  671   * f o r g e t - w i d
 672  672   */
 673  673  static void
 674  674  ficlPrimitiveForgetWid(ficlVm *vm)
 675  675  {
 676  676          ficlDictionary *dictionary = ficlVmGetDictionary(vm);
 677  677          ficlHash *hash;
 678  678  
 679  679          hash = (ficlHash *)ficlStackPopPointer(vm->dataStack);
 680  680          ficlHashForget(hash, dictionary->here);
 681  681  }
 682  682  
 683  683  /*
 684  684   * f o r g e t
 685  685   * TOOLS EXT  ( "<spaces>name" -- )
 686  686   * Skip leading space delimiters. Parse name delimited by a space.
 687  687   * Find name, then delete name from the dictionary along with all
 688  688   * words added to the dictionary after name. An ambiguous
 689  689   * condition exists if name cannot be found.
 690  690   *
 691  691   * If the Search-Order word set is present, FORGET searches the
 692  692   * compilation word list. An ambiguous condition exists if the
 693  693   * compilation word list is deleted.
 694  694   */
 695  695  static void
 696  696  ficlPrimitiveForget(ficlVm *vm)
 697  697  {
 698  698          void *where;
 699  699          ficlDictionary *dictionary = ficlVmGetDictionary(vm);
 700  700          ficlHash *hash = dictionary->compilationWordlist;
 701  701  
 702  702          ficlPrimitiveTick(vm);
 703  703          where = ((ficlWord *)ficlStackPopPointer(vm->dataStack))->name;
 704  704          ficlHashForget(hash, where);
 705  705          dictionary->here = FICL_POINTER_TO_CELL(where);
 706  706  }
 707  707  
 708  708  /*
 709  709   * w o r d s
 710  710   */
 711  711  #define nCOLWIDTH       8
 712  712  
 713  713  static void
 714  714  ficlPrimitiveWords(ficlVm *vm)
 715  715  {
 716  716          ficlDictionary *dictionary = ficlVmGetDictionary(vm);
  
    | 
      ↓ open down ↓ | 
    716 lines elided | 
    
      ↑ open up ↑ | 
  
 717  717          ficlHash *hash = dictionary->wordlists[dictionary->wordlistCount - 1];
 718  718          ficlWord *wp;
 719  719          int nChars = 0;
 720  720          int len;
 721  721          unsigned i;
 722  722          int nWords = 0;
 723  723          char *cp;
 724  724          char *pPad;
 725  725          int columns;
 726  726  
 727      -        cp = getenv("COLUMNS");
      727 +        cp = getenv("screen-#cols");
 728  728          /*
 729  729           * using strtol for now. TODO: refactor number conversion from
 730  730           * ficlPrimitiveToNumber() and use it instead.
 731  731           */
 732  732          if (cp == NULL)
 733  733                  columns = 80;
 734  734          else
 735  735                  columns = strtol(cp, NULL, 0);
 736  736  
 737  737          /*
 738  738           * the pad is fixed size area, it's better to allocate
 739  739           * dedicated buffer space to deal with custom terminal sizes.
 740  740           */
 741  741          pPad = malloc(columns + 1);
 742  742          if (pPad == NULL)
 743  743                  ficlVmThrowError(vm, "Error: out of memory");
 744  744  
 745  745          pager_open();
 746  746          for (i = 0; i < hash->size; i++) {
 747  747                  for (wp = hash->table[i]; wp != NULL; wp = wp->link, nWords++) {
 748  748                          if (wp->length == 0) /* ignore :noname defs */
 749  749                                  continue;
 750  750  
 751  751                          /* prevent line wrap due to long words */
 752  752                          if (nChars + wp->length >= columns) {
 753  753                                  pPad[nChars++] = '\n';
 754  754                                  pPad[nChars] = '\0';
 755  755                                  nChars = 0;
 756  756                                  if (pager_output(pPad))
 757  757                                          goto pager_done;
 758  758                          }
 759  759  
 760  760                          cp = wp->name;
 761  761                          nChars += sprintf(pPad + nChars, "%s", cp);
 762  762  
 763  763                          if (nChars > columns - 10) {
 764  764                                  pPad[nChars++] = '\n';
 765  765                                  pPad[nChars] = '\0';
 766  766                                  nChars = 0;
 767  767                                  if (pager_output(pPad))
 768  768                                          goto pager_done;
 769  769                          } else {
 770  770                                  len = nCOLWIDTH - nChars % nCOLWIDTH;
 771  771                                  while (len-- > 0)
 772  772                                          pPad[nChars++] = ' ';
 773  773                          }
 774  774  
 775  775                          if (nChars > columns - 10) {
 776  776                                  pPad[nChars++] = '\n';
 777  777                                  pPad[nChars] = '\0';
 778  778                                  nChars = 0;
 779  779                                  if (pager_output(pPad))
 780  780                                          goto pager_done;
 781  781                          }
 782  782                  }
 783  783          }
 784  784  
 785  785          if (nChars > 0) {
 786  786                  pPad[nChars++] = '\n';
 787  787                  pPad[nChars] = '\0';
 788  788                  nChars = 0;
 789  789                  ficlVmTextOut(vm, pPad);
 790  790          }
 791  791  
 792  792          sprintf(pPad, "Dictionary: %d words, %ld cells used of %u total\n",
 793  793              nWords, (long)(dictionary->here - dictionary->base),
 794  794              dictionary->size);
 795  795          pager_output(pPad);
 796  796  
 797  797  pager_done:
 798  798          free(pPad);
 799  799          pager_close();
 800  800  }
 801  801  
 802  802  /*
 803  803   * l i s t E n v
 804  804   * Print symbols defined in the environment
 805  805   */
 806  806  static void
 807  807  ficlPrimitiveListEnv(ficlVm *vm)
 808  808  {
 809  809          ficlDictionary *dictionary = vm->callback.system->environment;
 810  810          ficlHash *hash = dictionary->forthWordlist;
 811  811          ficlWord *word;
 812  812          unsigned i;
 813  813          int counter = 0;
 814  814  
 815  815          pager_open();
 816  816          for (i = 0; i < hash->size; i++) {
 817  817                  for (word = hash->table[i]; word != NULL;
 818  818                      word = word->link, counter++) {
 819  819                          sprintf(vm->pad, "%s\n", word->name);
 820  820                          if (pager_output(vm->pad))
 821  821                                  goto pager_done;
 822  822                  }
 823  823          }
 824  824  
 825  825          sprintf(vm->pad, "Environment: %d words, %ld cells used of %u total\n",
 826  826              counter, (long)(dictionary->here - dictionary->base),
 827  827              dictionary->size);
 828  828          pager_output(vm->pad);
 829  829  
 830  830  pager_done:
 831  831          pager_close();
 832  832  }
 833  833  
 834  834  /*
 835  835   * This word lists the parse steps in order
 836  836   */
 837  837  void
 838  838  ficlPrimitiveParseStepList(ficlVm *vm)
 839  839  {
 840  840          int i;
 841  841          ficlSystem *system = vm->callback.system;
 842  842          FICL_VM_ASSERT(vm, system);
 843  843  
 844  844          ficlVmTextOut(vm, "Parse steps:\n");
 845  845          ficlVmTextOut(vm, "lookup\n");
 846  846  
 847  847          for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) {
 848  848                  if (system->parseList[i] != NULL) {
 849  849                          ficlVmTextOut(vm, system->parseList[i]->name);
 850  850                          ficlVmTextOut(vm, "\n");
 851  851                  } else
 852  852                          break;
 853  853          }
 854  854  }
 855  855  
 856  856  /*
 857  857   * e n v C o n s t a n t
 858  858   * Ficl interface to ficlSystemSetEnvironment and ficlSetEnvD - allow Ficl
 859  859   * code to set environment constants...
 860  860   */
 861  861  static void
 862  862  ficlPrimitiveEnvConstant(ficlVm *vm)
 863  863  {
 864  864          unsigned value;
 865  865          FICL_STACK_CHECK(vm->dataStack, 1, 0);
 866  866  
 867  867          ficlVmGetWordToPad(vm);
 868  868          value = ficlStackPopUnsigned(vm->dataStack);
 869  869          ficlDictionarySetConstant(ficlSystemGetEnvironment(vm->callback.system),
 870  870              vm->pad, (ficlUnsigned)value);
 871  871  }
 872  872  
 873  873  static void
 874  874  ficlPrimitiveEnv2Constant(ficlVm *vm)
 875  875  {
 876  876          ficl2Integer value;
 877  877  
 878  878          FICL_STACK_CHECK(vm->dataStack, 2, 0);
 879  879  
 880  880          ficlVmGetWordToPad(vm);
 881  881          value = ficlStackPop2Integer(vm->dataStack);
 882  882          ficlDictionarySet2Constant(
 883  883              ficlSystemGetEnvironment(vm->callback.system), vm->pad, value);
 884  884  }
 885  885  
 886  886  
 887  887  /*
 888  888   * f i c l C o m p i l e T o o l s
 889  889   * Builds wordset for debugger and TOOLS optional word set
 890  890   */
 891  891  void
 892  892  ficlSystemCompileTools(ficlSystem *system)
 893  893  {
 894  894          ficlDictionary *dictionary = ficlSystemGetDictionary(system);
 895  895          ficlDictionary *environment = ficlSystemGetEnvironment(system);
 896  896  
 897  897          FICL_SYSTEM_ASSERT(system, dictionary);
 898  898          FICL_SYSTEM_ASSERT(system, environment);
 899  899  
 900  900  
 901  901          /*
 902  902           * TOOLS and TOOLS EXT
 903  903           */
 904  904          ficlDictionarySetPrimitive(dictionary, ".s", ficlVmDisplayDataStack,
 905  905              FICL_WORD_DEFAULT);
 906  906          ficlDictionarySetPrimitive(dictionary, ".s-simple",
 907  907              ficlVmDisplayDataStackSimple,  FICL_WORD_DEFAULT);
 908  908          ficlDictionarySetPrimitive(dictionary, "bye", ficlPrimitiveBye,
 909  909              FICL_WORD_DEFAULT);
 910  910          ficlDictionarySetPrimitive(dictionary, "forget", ficlPrimitiveForget,
 911  911              FICL_WORD_DEFAULT);
 912  912          ficlDictionarySetPrimitive(dictionary, "see", ficlPrimitiveSee,
 913  913              FICL_WORD_DEFAULT);
 914  914          ficlDictionarySetPrimitive(dictionary, "words", ficlPrimitiveWords,
 915  915              FICL_WORD_DEFAULT);
 916  916  
 917  917          /*
 918  918           * Set TOOLS environment query values
 919  919           */
 920  920          ficlDictionarySetConstant(environment, "tools", FICL_TRUE);
 921  921          ficlDictionarySetConstant(environment, "tools-ext", FICL_FALSE);
 922  922  
 923  923          /*
 924  924           * Ficl extras
 925  925           */
 926  926          ficlDictionarySetPrimitive(dictionary, "r.s", ficlVmDisplayReturnStack,
 927  927              FICL_WORD_DEFAULT);
 928  928          ficlDictionarySetPrimitive(dictionary, ".env", ficlPrimitiveListEnv,
 929  929              FICL_WORD_DEFAULT);
 930  930          ficlDictionarySetPrimitive(dictionary, "env-constant",
 931  931              ficlPrimitiveEnvConstant, FICL_WORD_DEFAULT);
 932  932          ficlDictionarySetPrimitive(dictionary, "env-2constant",
 933  933              ficlPrimitiveEnv2Constant, FICL_WORD_DEFAULT);
 934  934          ficlDictionarySetPrimitive(dictionary, "debug-xt", ficlPrimitiveDebugXT,
 935  935              FICL_WORD_DEFAULT);
 936  936          ficlDictionarySetPrimitive(dictionary, "parse-order",
 937  937              ficlPrimitiveParseStepList, FICL_WORD_DEFAULT);
 938  938          ficlDictionarySetPrimitive(dictionary, "step-break",
 939  939              ficlPrimitiveStepBreak, FICL_WORD_DEFAULT);
 940  940          ficlDictionarySetPrimitive(dictionary, "forget-wid",
 941  941              ficlPrimitiveForgetWid, FICL_WORD_DEFAULT);
 942  942          ficlDictionarySetPrimitive(dictionary, "see-xt", ficlPrimitiveSeeXT,
 943  943              FICL_WORD_DEFAULT);
 944  944  
 945  945  #if FICL_WANT_FLOAT
 946  946          ficlDictionarySetPrimitive(dictionary, ".hash",
 947  947              ficlPrimitiveHashSummary, FICL_WORD_DEFAULT);
 948  948  #endif
 949  949  }
  
    | 
      ↓ open down ↓ | 
    212 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX