Logo Search packages:      
Sourcecode: yforth version File versions  Download package

core.c

/* yForth? - Written by Luca Padovani (C) 1996/97
 * ------------------------------------------------------------------------
 * This software is FreeWare as long as it comes with this header in each
 * source file, anyway you can use it or any part of it whatever
 * you want. It comes without any warranty, so use it at your own risk.
 * ------------------------------------------------------------------------
 * Module name:     core.c
 * Abstract:        Core word set
 */

#include <string.h>
#include <setjmp.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "yforth.h"
#include "udio.h"
#include "core.h"
#include "coree.h"
#include "float.h"
#include "double.h"
#include "toolse.h"
#include "locals.h"
#include "block.h"
#include "exceptio.h"

/**************************************************************************/
/* VARIABLES **************************************************************/
/**************************************************************************/

Char s_tmp_buffer[TMP_BUFFER_SIZE];     /* used by s" */

Cell _to_in;                            /* ptr to parse area */
Cell _source_id;                        /* input source device */
Char * _tib;                            /* ptr to terminal input buffer */
Char * _input_buffer;                   /* current input buffer */
Cell _in_input_buffer;                  /* # of chars in input buffer */
Cell _base;                             /* base is base */
Char * _dp;                             /* dictionary pointer */
Cell _error;                            /* error code */
struct word_def * _last;                /* ptr to last defined word */
Cell _state;                            /* state of the interpreter */
Cell _check_system = 1;                 /* 1 => check stacks overflow & underflow */
                                        /* Some variables used by environment? follows... */
Cell _env_slash_counted_string;         
Cell _env_slash_hold;
Cell _env_slash_pad;
Cell _env_address_unit_bits;
Cell _env_core;
Cell _env_core_ext;
Cell _env_floored;
Cell _env_max_char;
Cell _env_max_d;
Cell _env_max_n;
Cell _env_max_u;
Cell _env_max_ud;
Cell _env_return_stack_cells;
Cell _env_stack_cells;
Cell _env_double;
Cell _env_double_ext;
Cell _env_floating;
Cell _env_floating_stack;
Cell _env_max_float;
Cell _env_floating_ext;
Cell _env_memory_alloc;
Cell _env_memory_alloc_ext;
Cell _env_search_order;
Cell _env_search_order_ext;
Cell _env_wordlists;
Cell _env_tools;
Cell _env_tools_ext;
Cell _env_number_locals;
Cell _env_locals;
Cell _env_locals_ext;
Cell _env_facility;
Cell _env_facility_ext;
Cell _env_block;
Cell _env_block_ext;
Cell _env_exception;
Cell _env_exception_ext;
Cell _env_file;
Cell _env_file_ext;
Cell _env_string;
Cell _env_string_ext;

/**************************************************************************/
/* WORDS ******************************************************************/
/**************************************************************************/

void _dot_quote() {
      compile_cell((Cell) _paren_dot_quote_paren);
      *--sp = '"';
      _word();
      _dp = (Char *) WORD_PTR(_dp);
    sp++;
}

void _paren_dot_quote_paren() {
    register Char *addr = (Char *) ip;
    *--sp = (Cell) (addr + 1);
    *--sp = (Cell) *addr;
      _type();
      ip = (pfp *) WORD_PTR((Char *) ip);
}

void _type() {
    register Cell u = *sp++;
    register Char *addr = (Char *) *sp++;
    while (u--) putchar(*addr++);
}

void _u_dot() {
      *--sp = 0;
    _less_number_sign();
    _number_sign_s();
    _number_sign_greater();
      _type();
    putchar(' ');
}

void _c_r() {
      putchar('\n');
}

void _emit() {
      putchar(*sp++);
}

#ifdef DOUBLE_DEF
void _dot() {
      _s_to_d();
      _d_dot();
}
#else
void _dot() {
      register DCell u = *sp;
      register int usign = u < 0;
      if (usign) u = -u;
      sp--;
      PUT_DCELL(sp, u);
      _less_number_sign();
      _number_sign_s();
      if (usign) {
            *--sp = '-';
            _hold();
      }
      _number_sign_greater();
      _type();
      putchar(' ');
}
#endif

void _space() {
    putchar(' ');
}

void _spaces() {
    register UCell u = *sp++;
    while (u--) putchar(' ');
}

void _less_number_sign() {
      in_pnos = 0;
      p_pnos = pnos + pnos_size;
}

void _number_sign() {
      register UDCell ud1 = GET_DCELL(sp);
      register int rem = ud1 % _base;
      ud1 /= _base;
      PUT_DCELL(sp, ud1);
      if (rem < 10) *--p_pnos = rem + '0';
      else *--p_pnos = rem - 10 + 'a';
      in_pnos++;
}

void _hold() {
      register Char ch = (Char) *sp++;
      *--p_pnos = ch;
      in_pnos++;
}

void _number_sign_s() {
      do _number_sign();
      while (sp[0] || sp[1]);
}

void _number_sign_greater() {
      sp[1] = (Cell) p_pnos;
      sp[0] = in_pnos;
}

void _store() {
      register Cell *addr = (Cell *) *sp++;
      *addr = *sp++;
}

void _star() {
    sp[1] *= *sp;
    sp++;
}

void _star_slash() {
    register DCell d = (DCell) sp[1] * (DCell) sp[2];
    sp[2] = d / (DCell) sp[0];
    sp += 2;
}

void _star_slash_mod() {
      register DCell d = (DCell) sp[1] * (DCell) sp[2];
    sp[2] = d % (DCell) sp[0];
      sp[1] = d / (DCell) sp[0];
      sp++;
}

void _plus() {
      sp[1] += sp[0];
      sp++;
}

void _plus_store() {
    register Cell *addr = (Cell *) *sp++;
    *addr += *sp++;
}

void _minus() {
    sp[1] -= sp[0];
    sp++;
}

void _slash() {
      sp[1] /= sp[0];
      sp++;
}

void _slash_mod() {
      register Cell n1 = sp[1];
      register Cell n2 = sp[0];
    sp[1] = n1 % n2;
    sp[0] = n1 / n2;
}

void _zero_less() {
    sp[0] = FFLAG(sp[0] < 0);
}

void _zero_equals() {
    sp[0] = FFLAG(sp[0] == 0);
}

void _one_plus() {
      sp[0]++;
}

void _one_minus() {
    sp[0]--;
}

void _two_store() {
    register Cell *addr = (Cell *) *sp++;
    *addr++ = *sp++;
    *addr = *sp++;
}

void _two_star() {
    sp[0] <<= 1;
}

void _two_slash() {
      sp[0] >>= 1;
}

void _two_fetch() {
    register Cell *addr = (Cell *) *sp;
    *sp-- = *(addr + 1);
    *sp = *addr;
}

void _two_drop() {
    sp += 2;
}

void _two_dupe() {
    sp -= 2;
    sp[0] = sp[2];
    sp[1] = sp[3];
}

void _two_over() {
      sp -= 2;
    sp[0] = sp[4];
    sp[1] = sp[5];
}

void _two_swap() {
    register Cell x4 = sp[0];
      register Cell x3 = sp[1];
      sp[0] = sp[2];
    sp[1] = sp[3];
    sp[2] = x4;
    sp[3] = x3;
}

void _less_than() {
    sp[1] = FFLAG(sp[1] < sp[0]);
    sp++;
}

void _equals() {
      sp[1] = FFLAG(sp[1] == sp[0]);
    sp++;
}

void _greater_than() {
    sp[1] = FFLAG(sp[1] > sp[0]);
    sp++;
}

void _to_r() {
    *--rp = *sp++;
}

void _question_dupe() {
    if (sp[0]) sp--, sp[0] = sp[1];
}

void _fetch() {
    sp[0] = *((Cell *) sp[0]);
}

void _abs() {
    register Cell n = sp[0];
    sp[0] = n >= 0 ? n : -n;
}

void _align() {
      _dp = (Char *) ALIGN_PTR(_dp);
}

void _aligned() {
    sp[0] = ALIGN_PTR((Cell *) sp[0]);
}

void _and() {
      sp[1] &= sp[0];
    sp++;
}

void _b_l() {
      *--sp = ' ';
}

void _c_store() {
    register Char *addr = (Char *) *sp++;
    *addr = (Char) *sp++;
}

void _c_fetch() {
    register Char *addr = (Char *) *sp;
    *sp = (Cell) *addr;
}

void _cell_plus() {
      sp[0] += sizeof(Cell);
}

void _cells() {
    sp[0] *= sizeof(Cell);
}

void _char_plus() {
    sp[0] += sizeof(Char);
}

void _chars() {
    sp[0] *= sizeof(Char);
}

void _depth() {
      register Cell dep = sp_top - sp;
      *--sp = dep;
}

void _drop() {
      sp++;
}

void _dupe() {
    sp--;
    sp[0] = sp[1];
}

void _f_m_slash_mod() {
    register Cell n1 = *sp++;
      register DCell d1 = GET_DCELL(sp);
    sp[0] = d1 / n1;
    sp[1] = d1 % n1;
#if !FLOORED_DIVISION
      if (*sp < 0) {
            sp[0]--;
            if (sp[1] > 0) sp[1]++;
            else sp[1]--;
            sp[1] = -sp[1];
      }     
#endif
}

void _invert() {
    sp[0] = ~sp[0];
}

void _l_shift() {
      register UCell u = (UCell) *sp++;
    sp[0] <<= u;
}

void _m_star() {
    register DCell d = (DCell) sp[1] * (DCell) sp[0];
      PUT_DCELL(sp, d);
}

void _max() {
    register Cell n2 = *sp++;
    sp[0] = sp[0] > n2 ? sp[0] : n2;
}

void _min() {
    register Cell n2 = *sp++;
    sp[0] = sp[0] < n2 ? sp[0] : n2;
}

void _mod() {
    sp[1] %= sp[0];
    sp++;
}

void _negate() {
    sp[0] = -sp[0];
}

void _or() {
      sp[1] |= sp[0];
    sp++;
}

void _over() {
    sp--;
    sp[0] = sp[2];
}

void _r_from() {
      *--sp = *rp++;
}

void _r_fetch() {
    *--sp = *rp;
}

void _rote() {
    register Cell x3 = sp[0];
    register Cell x2 = sp[1];
    register Cell x1 = sp[2];
    sp[0] = x1;
    sp[1] = x3;
    sp[2] = x2;
}

void _r_shift() {
    register UCell u = (UCell) *sp++;
      ((UCell *) sp)[0] >>= u;
}

void _s_to_d() {
    register DCell d = (DCell) (*sp--);
      PUT_DCELL(sp, d);
}

void _s_m_slash_rem() {
    register Cell n1 = *sp++;
      register DCell d1 = GET_DCELL(sp);
    sp[0] = d1 / n1;
    sp[1] = d1 % n1;
#if FLOORED_DIVISION
      if (*sp < 0) {
            sp[0]++;
            if (sp[1] > 0) sp[1]--;
            else sp[1]++;
            sp[1] = -sp[1];
      }     
#endif
}

void _swap() {
    register Cell temp = sp[0];
    sp[0] = sp[1];
    sp[1] = temp;
}

void _u_less_than() {
    sp[1] = FFLAG((UCell) sp[1] < (UCell) sp[0]);
      sp++;
}

void _u_m_star() {
      register UDCell ud = (UDCell) sp[1] * (UDCell) sp[0];
      PUT_DCELL(sp, ud);
}

void _u_m_slash_mod() {
      register UCell u1 = *sp++;
      register UDCell ud = GET_DCELL(sp);
      sp[1] = ud % u1;
      sp[0] = ud / u1;
}

void _xor() {
      sp[1] ^= sp[0];
      sp++;
}

void _do_literal() {
    *--sp = (Cell) *ip++;
}

void _do_fliteral() {
      *--fp = (Real) *((Real *) ip);
      ip += sizeof(Real) / sizeof(Cell);
}

void _word() {
      register Char *addr;
      register Char delim = (Char) *sp;
      register int i, j;
      while (_to_in < _in_input_buffer && _input_buffer[_to_in] == delim) _to_in++;
      _parse();
      i = *_dp = *sp++;
      addr = (Char *) *sp;
      for (j = 0; j < i; j++) *(_dp + j + 1) = *addr++;
      *(_dp + i + 1) = ' ';
      *sp = (Cell) _dp;
}

void _to_number() {
      register UCell u1 = (UCell) *sp;
    register Char *addr = (Char *) *(sp + 1);
      register UDCell ud1 = GET_DCELL(sp + 2);
      while (is_base_digit(*addr) && u1) {
            ud1 *= _base;
            if (*addr <= '9') ud1 += *addr - '0';
            else ud1 += toupper(*addr) - 'A' + 10;
            addr++;
            u1--;
      }
      PUT_DCELL(sp + 2, ud1);
      *(sp + 1) = (Cell) addr;
      *sp = u1;
}

void _read_const() {
      register Cell n;
      register Cell usign = 1;
      register UDCell num;
      register const_type = 1;
      register Char *orig = (Char *) sp[1];
      register Cell orig_len = sp[0];
      if (sp[0] && *((Char *) sp[1]) == '-') {
            usign = -1;
            sp[1] += sizeof(Char);
            sp[0]--;
      }
      while (sp[0]) {
            _to_number();
            if (sp[0] && *((Char *) sp[1]) == '.') {
                  const_type = 2;
                  sp[0]--;
                  sp[1] += sizeof(Char);
            } else break;
      }
      n = *sp++;
      num = GET_DCELL(sp + 1);
      if (usign < 0) {
            num = -num;
            PUT_DCELL(sp + 1, num);
      }
      if (!n) *sp = const_type;
#ifdef FLOAT_DEF
      else {
            if (_base == 10) {
                  sp++;
                  sp[1] = (Cell) orig;
                  sp[0] = orig_len;
                  _to_float();
                  if (*sp) sp[0] = 3;
            } else *sp = 0;
      }
#else
      else *sp = 0;
#endif
}

void _interpret() {
      register struct word_def *xt;
      while (!_error && _to_in < _in_input_buffer) {
            *--sp = ' ';
            _word();
            sp++;
            if (!(*_dp)) continue;                    /* Please forget this! */
            xt = search_word(_dp + 1, *_dp);
            if (xt) {
                  if (_state == INTERPRET) {
                        if (xt->class & COMP_ONLY) _error = E_NOCOMP;
                        else exec_word(xt);
                  } else /* _state == COMPILE */ {
                        if (xt->class & IMMEDIATE) exec_word(xt);
                        else compile_word(xt);
                  }
            } else /* xt == 0 */ {
                  register UDCell num;
                  *--sp = 0;
                  *--sp = 0;
                  *--sp = (Cell) (_dp + sizeof(Char));
                  *--sp = (Cell) *_dp;
                  _read_const();
                  if (!(*sp)) {
                        sp++;
                        _error = E_NOWORD;
                  } else {
                        switch (*sp++) {
                              case 1:
                                    num = GET_DCELL(sp);
                                    if (_state == INTERPRET) sp++;
                                    else {
                                          sp += 2;
                                          compile_cell((Cell) _do_literal);
                                          compile_cell((Cell) num);
                                    }
                                    break;
                              case 2:
                                    num = GET_DCELL(sp);
                                    if (_state == COMPILE) {
                                          sp += 2;
                                          compile_cell((Cell) _do_literal);
                                          compile_cell((Cell) num);
                                          compile_cell((Cell) _do_literal);
                                          compile_cell((Cell) (num >> CellBits));
                                    }
                                    break;
                              case 3:
                                    if (_state == COMPILE) {
                                          compile_cell((Cell) _do_fliteral);
                                          compile_real(*fp);
                                          fp++;
                                    }
                                    break;
                        }
                  }
            }
      }
}

void _accept() {
    register Cell n1 = *sp++;
    register Char *addr = (Char *) *sp;
      register int i = 0;
    register char ch;
    do {
            ch = getchar();
        i = process_char(addr, n1, i, ch);
    } while (ch != '\n');
    *sp = i;
}

void _source() {
    *--sp = (Cell) _input_buffer;
    *--sp = _in_input_buffer;
}

void _paren() {
      register Cell eof = 1;
      do {
            while (_to_in < _in_input_buffer && _input_buffer[_to_in] != ')') _to_in++;
            if (_source_id != 0 && _source_id != -1 && _to_in == _in_input_buffer) {
                  _refill();
                  eof = !(*sp++);
            }
      } while (_to_in == _in_input_buffer && !eof);
      if (_to_in < _in_input_buffer) _to_in++;
}

void _evaluate() {
    register Cell u = *sp++;
      register Char *addr = (Char *) *sp++;
      save_input_specification();
      _source_id = -1;
      _in_input_buffer = u;
      _input_buffer = addr;
      _to_in = 0;
      _b_l_k = 0;
      _interpret();
      restore_input_specification();
}

void _view_error_msg() {
      static struct an_error {
            char *msg;
            char please_abort;
            char print_word;
      } err_msg[] = {
            { "everything allright",                        0, 0 },
            { "no input avaliable",                         0, 0 },
            { "unknown word",                               0, 1 },
            { "word must be compiled",                      0, 1 },
            { "corrupted dictionary",                       1, 0 },
            { "not enough memory",                          0, 0 },
            { "data-stack underflow",                       1, 0 },
            { "data-stack overflow",                        1, 0 },
            { "return-stack underflow",                     1, 0 },
            { "return-stack overflow",                      1, 0 },
            { "floating-stack underflow",             1, 0 },
            { "floating-stack overflow",              1, 0 },
            { "data-space corrupted",                       1, 0 },
            { "data-space exhausted",                       1, 0 },
            { "unable to access image file",          0, 0 },
            { "primitive not implemented",          0, 1 },
            { "floating-point/math exception",        0, 0 },
            { "segmentation fault",                         0, 0 },
            { "file not found",                                   0, 0 },
      };
      if (err_msg[-_error].print_word) {
            putchar('[');
            *--sp = (Cell) _dp;
            _count();
            _type();
            printf("] ");
      }
      printf("error(%d): %s.\n", -_error, err_msg[-_error].msg);
      if (err_msg[-_error].please_abort) {
            printf("Aborting...\n");
            _abort();
      }
}

void _quit() {
      while (1) {
            rp = rp_top;
            _source_id = 0;
            _input_buffer = _tib;
            _state = INTERPRET;
            _error = E_OK;
            while (_error == E_OK) {
                  _refill();
                  if (*sp++) {
                        _to_in = 0;
                        _interpret();
                        if (_state == INTERPRET && !_error) printf("ok\n");
                        else if (_state == COMPILE) printf("ko ");
                  } else _error = E_NOINPUT;
                  if (_error == E_OK && _check_system) check_system();
            }
            _view_error_msg();
      }
}

void _comma() {
      *((Cell *) _dp) = *sp++;
      _dp += sizeof(Cell);
}

void _allot() {
      _dp += *sp++;
}

void _c_comma() {
      *_dp++ = (Char) *sp++;
}

void _here() {
    *--sp = (Cell) _dp;
}

void _do_exit() {
      ip = 0;
}

void _exit_imm() {
      clear_locals();
      compile_cell((Cell) _do_exit);
}

void _paren_do_colon_paren() {
      *--rp = (Cell) (ip + 1);
      ip = (pfp *) *ip;
      while (ip) (*ip++)();
      ip = (pfp *) *rp++;
}

void _colon() {
      create_definition(A_COLON);
      _state = COMPILE;
      init_locals();
}

void _variable() {
      create_definition(A_VARIABLE);
      compile_cell(0);
      mark_word(_last);
}

void _constant() {
      register Cell x = *sp++;
      create_definition(A_CONSTANT);
      compile_cell(x);
      mark_word(_last);
}

void _create() {
      create_definition(A_CREATE);
      compile_cell(0);
      mark_word(_last);
}

void _does() {
      compile_cell((Cell) _paren_does_paren);
      _exit_imm();
      mark_word(_last);
      init_locals();
}

void _paren_does_paren() {
      _last->func[0] = (pfp) (ip + 1);
}

void _semi_colon() {
      _exit_imm();
      _state = INTERPRET;
      mark_word(_last);
}

void _zero_branch() {
      if (*sp++) ip++;
      else ip += 1 + (Cell) *ip;
}

void _branch() {
      ip += 1 + (Cell) *ip;
}

void _if() {
      compile_cell((Cell) _zero_branch);
      *--sp = (Cell) _dp;
      compile_cell(0);
}

void _then() {
    register Cell *patch = (Cell *) *sp++;
    *patch = ((Cell *) _dp) - patch - 1;
}

void _else() {
      _ahead();
      *--sp = 1;
      _roll();
      _then();
}

void _begin() {
    *--sp = (Cell) _dp;
}

void _do() {
    compile_cell((Cell) _paren_do_paren);
    *--sp = (Cell) _dp;
    *--sp = 0;  /* Non e' un ?do */
}

void _paren_do_paren() {
    *--rp = *sp++;
    *--rp = *sp++;
    /* R: index limit --- */
}

void _loop() {
    register Cell q_do = *sp++;
    register Cell *dest = (Cell *) *sp++;
    compile_cell((Cell) _paren_loop_paren);
    compile_cell(dest - ((Cell *) _dp) - 1);
    if (q_do) {
        register Cell *patch = (Cell *) *sp++;
        *patch = ((Cell *) _dp) - patch - 1;
    }
}

void _paren_loop_paren() {
    if (rp[0] == ++rp[1]) {
        ip++;
        rp += 2;
    } else ip += 1 + (Cell) *ip;
}

void _i() {
    *--sp = rp[1];
}

void _j() {
    *--sp = rp[3];
}

void _plus_loop() {
    register Cell q_do = *sp++;
    register Cell *dest = (Cell *) *sp++;
    compile_cell((Cell) _paren_plus_loop_paren);
    compile_cell(dest - ((Cell *) _dp) - 1);
    if (q_do) {
        register Cell *patch = (Cell *) *sp++;
        *patch = ((Cell *) _dp) - patch - 1;
    }
}

void _paren_plus_loop_paren() {
    register Cell old_index = *rp;
    rp[1] += *sp++;
    if (old_index < rp[1] && rp[0] >= rp[1]) {
        ip++;
        rp += 2;
    } else ip += 1 + (Cell) *ip;
}

void _find() {
      register Char *addr = (Char *) *sp;
      register Cell len = (Cell) *addr++;
      register struct word_def *xt = search_word(addr, len);
      set_find_stack(addr, xt);
}

void _recurse() {
    compile_cell((Cell) _paren_do_colon_paren);
    compile_cell((Cell) &_last->func[0]);
}

void _tick() {
    register Char *addr;
    *--sp = ' ';
      _word();
      addr = (Char *) *sp;
      if (!(*sp = (Cell) search_word(addr + 1, *addr))) _error = E_NOWORD;
}

void _to_body() {
      *sp = (Cell) &((struct word_def *) *sp)->func[0];
}

void _abort() {
      *--sp = -1;
      _throw();
}

void _abort_quote() {
      _if();
      _s_quote();
      compile_cell((Cell) _do_literal);
      compile_cell(-2);
      compile_cell((Cell) _throw);
      _then();
}

void _count() {
      register Char *addr = (Char *) *sp;
    sp--;
    sp[0] = (Cell) *addr;
    sp[1]++;
}

void _decimal() {
    _base = 10;
}

void _environment_query() {
      register Cell len = *sp++;
      register Char *addr = (Char *) *sp++;
      static struct {
            Char *name;
            Cell *var;
      } kw[] = {
            { "/COUNTED-STRING",          &_env_slash_counted_string },
            { "/HOLD",                          &_env_slash_hold },
            { "/PAD",                           &_env_slash_pad },
            { "ADDRESS-UNIT-BITS",        &_env_address_unit_bits },
            { "CORE",                           &_env_core },
            { "CORE-EXT",                       &_env_core_ext },
            { "FLOORED",                        &_env_floored },
            { "MAX-CHAR",                       &_env_max_char },
            { "MAX-D",                          &_env_max_d },
            { "MAX-N",                          &_env_max_n },
            { "MAX-U",                          &_env_max_u },
            { "MAX-UD",                         &_env_max_ud },
            { "RETURN-STACK-CELLS",       &_env_return_stack_cells },
            { "STACK-CELLS",              &_env_stack_cells },
            { "DOUBLE",                         &_env_double },
            { "DOUBLE-EXT",                     &_env_double_ext },
            { "FLOATING",                       &_env_floating },
            { "FLOATING-STACK",                 &_env_floating_stack },
            { "MAX-FLOAT",                      &_env_max_float },
            { "FLOATING-EXT",             &_env_floating_ext },
            { "MEMORY-ALLOC",             &_env_memory_alloc },
            { "MEMORY-ALLOC-EXT",         &_env_memory_alloc_ext },
            { "SEARCH-ORDER",             &_env_search_order },
            { "WORDLISTS",                      &_env_wordlists },
            { "SEARCH-ORDER-EXT",         &_env_search_order_ext },
            { "TOOLS",                          &_env_tools },
            { "TOOLS-EXT",                      &_env_tools_ext },
            { "#LOCALS",                        &_env_number_locals },
            { "LOCALS",                         &_env_locals },
            { "LOCALS-EXT",                     &_env_locals_ext },
            { "FACILITY",                       &_env_facility },
            { "FACILITY-EXT",             &_env_facility_ext },
            { "BLOCK",                          &_env_block },
            { "BLOCK-EXT",                      &_env_block_ext },
            { "EXCEPTION",                      &_env_exception },
            { "EXCEPTION-EXT",                  &_env_exception_ext },
            { "FILE",                           &_env_file },
            { "FILE-EXT",                       &_env_file_ext },
            { "STRING",                         &_env_string },
            { "STRING-EXT",                     &_env_string_ext },
            { NULL,                             NULL },
      };
      register int i = 0;
      for (i = 0; i < len; i++) addr[i] = toupper(addr[i]);
      i = 0;
      while (kw[i].name && memcmp(addr, kw[i].name, len)) i++;
      if (kw[i].name) {
            if (!strcmp(kw[i].name + 1, "MAX-UD")) {
                  sp -= 2;
                  PUT_DCELL(sp, MAX_UD);
            } else if (!strcmp(kw[i].name + 1, "MAX-FLOAT"))
                  *--fp = MAX_F;
            else *--sp = *kw[i].var;
            *--sp = FFLAG(1);
      } else *--sp = FFLAG(0);
}

void _execute() {
      exec_word((struct word_def *) *sp++);
}

void _fill() {
      register int c = (int) *sp++;
      register UCell u = (UCell) *sp++;
      register Char *addr = (Char *) *sp++;
      if (u) memset(addr, c, u);
}

void _immediate() {
    _last->class |= IMMEDIATE;
}

void _key() {
      *--sp = d_getch();
}

void _leave() {
    rp += 2;
      while (*ip != _paren_loop_paren && *ip != _paren_plus_loop_paren) ip++;
    ip += 2;
}

void _literal() {
    compile_cell((Cell) _do_literal);
    compile_cell(sp[0]);
    sp++;
}

void _move() {
    register UCell u = (UCell) *sp++;
    register Char *dest = (Char *) *sp++;
    register Char *source = (Char *) *sp++;
    if (u) memmove(dest, source, u);
}

void _postpone() {
    *--sp = ' ';
    _word();
    _find();
    if (*sp++ > 0)  /* IMMEDIATE word */
        compile_word((struct word_def *) *sp++);
    else {
        compile_cell((Cell) _paren_compile_paren);
        compile_cell(sp[0]);
        sp++;
    }
}

void _paren_compile_paren() {
    compile_word((struct word_def *) *sp++);
}

void _s_quote() {
      if (_state == INTERPRET) {
            *--sp = '"';
            _word();
            memcpy(s_tmp_buffer, _dp, *_dp + 1);
            sp[0] = (Cell) s_tmp_buffer;
            _count();
      } else {
            _c_quote();
            compile_cell((Cell) _count);
      }
}

void _sign() {
    if (*sp++ < 0) {
            *p_pnos-- = '-';
            in_pnos++;
    }
}

void _unloop() {
    rp += 2;
}

void _left_bracket() {
    _state = INTERPRET;
}

void _bracket_tick() {
    _tick();
    _literal();
}

void _char() {
      *--sp = ' ';
      _word();
      sp[0] = _dp[1];
}

void _bracket_char() {
      _char();
      _literal();
}

void _right_bracket() {
    _state = COMPILE;
}

void _while() {
      _if();
      *--sp = 1;
      _roll();
}

void _repeat() {
      _again();
      _then();
}

void _do_value() {
      *--sp = (Cell) *((Cell *) *ip++);
}

/**************************************************************************/
/* AUXILIARY FUNCTIONS ****************************************************/
/**************************************************************************/

/* strmatch: compare two strings, the first is expressed as (s1, len), while
 * the second is a counted string pointed by "s2". If the two strings are
 * identical return 0, 1 otherwise. The comparison is case INsensitive
 */
int strmatch(const Char *s1, const Char *s2, int len1) {
      if (len1 != *s2++) return (1);
      else {
            while (len1--) if (toupper(*s1++) != toupper(*s2++)) return (1);
            return (0);
      }
}

/* search_wordlist: search a word (name, len) within the selected vocabulary.
 * Called by "search_word"
 */
struct word_def *search_wordlist(Char *name, Cell len, struct vocabulary *wid) {
      register struct word_def *p = wid->voc[hash_func(name, len)];
      while (p && strmatch(name, p->name, len)) p = p->link;
      return (p);
}

/* search_word: search the word (name, len) into the vocabularies, starting
 * with the vocabulary on the top of the vocabularies stack. If found,
 * return the word's execution token, which is a pointer to the structure
 * "word_def" of the word. If not found, return NULL.
 */
struct word_def *search_word(Char *name, Cell len) {
      register struct word_def *p;
      register Cell ttop = top;
      if (locals_defined()) {
            p = get_first_local();
            while (p && strmatch(name, p->name, len)) p = p->link;
            if (p) return (p);
      }
      while (ttop >= 0) {
            p = search_wordlist(name, len, ttop >= 0 ? list[ttop] : forth_wid);
            if (p) return (p);
            ttop--;
      }
      return (0);
}

/* ins_word: add the word with execution token "p" in the current
 * compilation vocabulary
 */
void ins_word(struct word_def *p) {
      register int hash = hash_func(p->name + 1, *p->name);
      p->link = voc->voc[hash];
}

/* mark_word: make the word with execution token "p" visible, by updating
 * the compilation vocabulary head pointer
 */
void mark_word(struct word_def *p) {
      register int hash = hash_func(p->name + 1, *p->name);
      voc->voc[hash] = p;
}

/* set_find_stack: setup the data stack after a search in the vocabularies
 * as reuired by the word "find"
 */
void set_find_stack(Char *addr, struct word_def *xt) {
      if (xt) {
            *sp = (Cell) xt;
            if (xt->class & IMMEDIATE) *--sp = 1;
            else *--sp = (Cell) -1;
      } else {
            *sp = (Cell) addr;
            *--sp = 0;
      }
}

/* is_base_digit: return true if the digit "ch" is valid in the current base
 * stored in the variable "base".
 */
int is_base_digit(Char ch) {
      ch = toupper(ch);
      if (ch >= '0' && ch <= '9') {
            if (ch - '0' < _base) return (1);
            else return (0);
      }
      if (ch >= 'A' && ch <= 'Z') {
            if (ch - 'A' + 10 < _base) return (1);
            else return (0);
      }
      return (0);
}

/* process_char: do the work when a key is stroken on the keyboard.
 * "addr" is a base pointer to the buffer where the characters are to be
 * stored, "max_len" is the size of the buffer, "cur_pos" the current
 * position within the buffer, and "ch" the character to be processed.
 */
int process_char(Char *addr, int max_len, int cur_pos, char ch) {
      switch (ch) {
            case '\b':
                  if (cur_pos) cur_pos--;
                  else putchar('\a');
                  break;
            case 0:
        case EOF:
        default:
            if (ch >= 32) {
                        if (cur_pos < max_len) addr[cur_pos++] = ch;
                        else putchar('\a');
            }
                  break;
      }
      return cur_pos;
}

/* create_definition: create a new word in the dictionary allocating the
 * space for the name, which is stored yet by the call to "word", then
 * allocating a structure "word_def" and setting the "class" field to the
 * value passed to the function.
 */
void create_definition(Cell class) {
      register struct word_def *def;
      register Char *name;
      *--sp = (Cell) ' ';
      name = _dp;
      _word();
      sp++;
      _dp = (Char *) WORD_PTR(_dp);
      _align();
      def = (struct word_def *) _dp;
      _last = def;
      def->name = name;
      def->class = class;
      ins_word(def);
      _dp += sizeof(struct word_def) - sizeof(Cell);
}

/* exec_colon: execute a colon definition, with the first instruction pointed
 * by "ip0"
 */
void exec_colon(pfp *ip0) {
      register pfp *old_ip = ip;
      ip = ip0;
      while (ip) (*ip++)();
      ip = old_ip;
}

/* exec_word: execute the word with execution token "xt" when interpreting
 */
void exec_word(struct word_def *xt) {
      switch (xt->class & A_WORD) {
            case A_PRIMITIVE: xt->func[0](); break;
            case A_FVARIABLE:
            case A_2VARIABLE:
            case A_VARIABLE: *--sp = (Cell) &xt->func[0]; break;
            case A_COLON: exec_colon(&xt->func[0]); break;
            case A_VALUE:
            case A_USER:
            case A_CONSTANT: *--sp = (Cell) xt->func[0]; break;
            case A_2CONSTANT:
                  *--sp = (Cell) xt->func[0];
                  *--sp = (Cell) xt->func[1];
                  break;
            case A_FCONSTANT: *--fp = *((Real *) &xt->func[0]); break;
            case A_CREATE:
                  *--sp = (Cell) &xt->func[1];
                  if (xt->func[0]) exec_colon((pfp *) xt->func[0]);
                  break;
            case A_MARKER:
                  exec_marker((struct voc_marker *) &xt->func[0]);
                  break;
            case A_LOCAL:
            default: _error = E_NOVOC; break;
      }
}

/* compile_word: compile word with execution token "xt" within the dictionary
 */
void compile_word(struct word_def *xt) {
      switch (xt->class & A_WORD) {
            case A_PRIMITIVE:
                  compile_cell((Cell) xt->func[0]);
                  break;
            case A_VARIABLE:
            case A_2VARIABLE:
            case A_FVARIABLE:
                  compile_cell((Cell) _do_literal);
                  compile_cell((Cell) &xt->func[0]);
                  break;
            case A_VALUE:
                  compile_cell((Cell) _do_value);
                  compile_cell((Cell) &xt->func[0]);
                  break;
            case A_USER:
            case A_CONSTANT:
                  compile_cell((Cell) _do_literal);
                  compile_cell((Cell) xt->func[0]);
                  break;
            case A_2CONSTANT:
                  compile_cell((Cell) _do_literal);
                  compile_cell((Cell) xt->func[0]);
                  compile_cell((Cell) _do_literal);
                  compile_cell((Cell) xt->func[1]);
                  break;
            case A_FCONSTANT:
                  compile_cell((Cell) _do_fliteral);
                  compile_real(*((Real *) &xt->func[0]));
                  break;
            case A_COLON:
                  compile_cell((Cell) _paren_do_colon_paren);
                  compile_cell((Cell) &xt->func[0]);
                  break;
            case A_CREATE:
                  compile_cell((Cell) _do_literal);
                  compile_cell((Cell) &xt->func[1]);
                  if (xt->func[0]) {
                        compile_cell((Cell) _paren_do_colon_paren);
                        compile_cell((Cell) xt->func[0]);
                  }
                  break;
            case A_LOCAL:
                  compile_cell((Cell) _paren_read_local_paren);
                  compile_cell((Cell) xt->func[0]);
                  break;
            case A_MARKER:
                  compile_cell((Cell) _paren_marker_paren);
                  compile_cell((Cell) &xt->func[0]);
                  break;
            default: _error = E_NOVOC; break;
      }
}

/* save_input_specification: save all the information needed to restore the
 * state of current input later. First the word "save-input" is called, and
 * then each Cell on the stack is copied in the return stack
 */
void save_input_specification() {
      register int dim, dim1;
      _save_input();
      dim1 = dim = *sp++;
      while (dim--) _to_r();
      *--sp = (Cell) dim1;
      _to_r();
}

/* restore_input_specification: restore the input source by calling
 * "restore-input" after that the Cells on the return stack has been moved
 * on the data stack
 */
void restore_input_specification() {
      register int dim = *rp++, dim1 = dim;
      while (dim--) _r_from();
      *--sp = (Cell) dim1;
      _restore_input();
      sp++;
}

/* check_system: perform some tests to verify that's everything ok */
void check_system() {
      if (sp > sp_top) _error = E_DSTK_UNDER;
      else if (sp < sp_base) _error = E_DSTK_OVER;
      else if (rp > rp_top) _error = E_RSTK_UNDER;
      else if (rp < rp_base) _error = E_RSTK_OVER;
      else if (fstack_size && fp > fp_top) _error = E_FSTK_UNDER;
      else if (fstack_size && fp < fp_base) _error = E_FSTK_OVER;
      else if (_dp < dp0) _error = E_DSPACE_UNDER;
      else if (_dp > dp0 + dspace_size) _error = E_DSPACE_OVER;
}

Generated by  Doxygen 1.6.0   Back to index