home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file is part of the portable Forth environment written in ANSI C.
- * Copyright (C) 1995 Dirk Uwe Zoller
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * This file is version 0.9.13 of 17-July-95
- * Check for the latest version of this package via anonymous ftp at
- * roxi.rz.fht-mannheim.de:/pub/languages/forth/pfe-VERSION.tar.gz
- * or sunsite.unc.edu:/pub/languages/forth/pfe-VERSION.tar.gz
- * or ftp.cygnus.com:/pub/forth/pfe-VERSION.tar.gz
- *
- * Please direct any comments via internet to
- * duz@roxi.rz.fht-mannheim.de.
- * Thank You.
- */
- /*
- * support.c --- Subroutines for the Forth-System
- * (duz 09Jul93)
- */
-
- #include "forth.h"
- #include "support.h"
- #include "compiler.h"
- #include "dblsub.h"
- #include "term.h"
- #include "lined.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <math.h>
- #include <limits.h>
- #include <errno.h>
- #include <string.h>
- #include <ctype.h>
- #include <setjmp.h>
-
- #ifdef HAVE_UNISTD_H
- #include <unistd.h> /* access() if available */
- #endif
-
- #include "missing.h"
-
- Cell
- aligned (Cell n) /* return Cell-aligned address */
- {
- while (!ALIGNED (n))
- n++;
- return n;
- }
-
- Cell
- dfaligned (Cell n) /* return double float-aligned address */
- {
- while (!DFALIGNED (n))
- n++;
- return n;
- }
-
- void *
- getmem (size_t size) /* allocate memory, die when failed */
- {
- void *p = malloc (size);
-
- if (p == NULL)
- fatal ("out of memory");
- return p;
- }
-
- void *
- xalloc (size_t size) /* allocate memory, throw when failed */
- {
- void *p = malloc (size);
-
- if (p == NULL)
- tHrow (THROW_OUT_OF_MEMORY);
- return p;
- }
-
- /************************************************************************/
- /* miscellaneous execution semantics and runtimes */
- /************************************************************************/
-
- void
- sysvar_runtime (void)
- {
- *--sp = PFA[0];
- }
-
- void
- sysconst_runtime (void)
- {
- *--sp = *(Cell *) PFA[0];
- }
-
- void
- dictvar_runtime (void)
- {
- *--sp = (Cell) ((char *) sys.dict + PFA[0]);
- }
-
- void
- dictconst_runtime (void)
- {
- *--sp = *(Cell *) ((char *) sys.dict + PFA[0]);
- }
-
- void /* compiles the execution semantics */
- compile1 (void) /* of a state smart word */
- {
- question_comp_ ();
- COMMA (&((Semant **) W)[-1]->exec[0]);
- }
-
- void /* compiles the alternative exec.sem. */
- compile2 (void) /* of an even smarter word (e.g. TO) */
- {
- question_comp_ ();
- COMMA (&((Seman2 **) W)[-1]->exec[1]);
- }
-
- /************************************************************************/
- /* strings */
- /************************************************************************/
-
- void
- strpush (const char *s)
- {
- if (s)
- *--sp = (Cell)s, *--sp = strlen (s);
- else
- *--sp = 0, *--sp = 0;
- }
-
- char *
- pocket (void)
- {
- char *p = membot.pocket[sys.pocket];
-
- sys.pocket = (sys.pocket + 1) % option.pockets;
- return p;
- }
-
- int
- dash_trailing (char *s, int n)
- {
- while (n > 0 && isspace (s[n - 1]))
- n--;
- return n;
- }
-
- #if 0
- char *
- strlwr (char *str)
- {
- char *p;
- for (p = str; *p; p++)
- *p = tolower (*p);
- return str;
- }
-
- char *
- strupr (char *str)
- {
- char *p;
- for (p = str; *p; p++)
- *p = tolower (*p);
- return str;
- }
- #endif
-
- void
- lower (char *p, int n) /* tolower() applied to counted string */
- {
- while (--n >= 0)
- *p = tolower (*p), p++;
- }
-
- void
- upper (char *p, int n) /* toupper() applied to counted string */
- {
- while (--n >= 0)
- *p = toupper (*p), p++;
- }
-
- char *
- store_c_string (const char *src, int n, char *dst, int max)
- {
- if (n >= max)
- n = max - 1;
- memcpy (dst, src, n);
- dst[n] = '\0';
- return dst;
- }
-
- char *
- store_filename (const char *src, int n, char *dst, int max)
- {
- if (n >= max)
- n = max - 1;
- memcpy (dst, src, n);
- dst[n] = '\0';
- if (LOWER_CASE_FN)
- lower (dst, n);
- return dst;
- }
-
- /************************************************************************/
- /* string comparision and pattern matching */
- /************************************************************************/
-
- char *
- search (const char *p1, int u1, const char *p2, int u2)
- /* search for substring p2/u2 in string p1/u1 */
- {
- if (u2 == 0)
- return (char *) p1;
- if (u2 > u1)
- return NULL;
- u1 -= u2;
- for (;;)
- {
- char *p = (char *) memchr (p1, *p2, u1 + 1);
-
- if (p == NULL)
- return NULL;
- if (memcmp (p, p2, u2) == 0)
- return (char *) p;
- u1 -= p - p1;
- if (u1 == 0)
- return NULL;
- p1 = p + 1;
- u1--;
- }
- }
-
- static int
- do_match (const short *pattern, const char *string)
- /* match with a processed pattern, i.e. one without `\' escapes */
- {
- int c;
-
- for (;;)
- switch (c = *pattern++)
- {
- case '\0':
- return *string == '\0';
- case -'*':
- while (*string && !do_match (pattern, string))
- string++;
- continue;
- case -'?':
- if (*string++)
- continue;
- return 0;
- default:
- if (*string++ == c)
- continue;
- return 0;
- }
- }
-
- int
- match (const char *pattern, const char *string)
- /*
- * Match string against pattern.
- * Pattern knows wildcards `*' and `?' and `\' to escape a wildcard.
- */
- {
- short buf[0x100], *p = buf;
-
- /* preprocess pattern, remove `\' */
- for (;;)
- {
- int c = *(unsigned char *) pattern;
-
- pattern++;
- switch (c)
- {
- default:
- *p++ = c;
- continue;
- case '\0':
- *p = 0;
- break;
- case '?':
- *p++ = -'?';
- continue;
- case '*':
- *p++ = -'*';
- continue;
- case '\\':
- if (*pattern)
- *p++ = *pattern++;
- else
- *p++ = c;
- continue;
- }
- break;
- }
- /* match with preprocessed pattern */
- return do_match (buf, string);
- }
-
- /************************************************************************/
- /* expanding file names with paths and extensions */
- /************************************************************************/
-
- static const char *
- get_token (const char *toks, char del, char *s)
- /*
- * Sort of strtok() which is useless here since it isn't reentrant and
- * can't handle empty tokens.
- * Isolates a string delimited by del from toks, copies it to s.
- * Returns a pointer to just after the delimiter inside toks
- * or to the delimiting '\0' of toks if the token was the last one.
- */
- {
- while (*toks != del)
- {
- if (*toks == '\0')
- {
- *s = '\0';
- return toks;
- }
- *s++ = *toks++;
- }
- toks++;
- *s = '\0';
- return toks;
- }
-
- static int
- try_extensions (char *nm, const char *ext)
- /*
- * Append all extensions from ext to nm.
- * Check if file exists, if so return true, else false.
- */
- {
- char *z = nm + strlen (nm);
-
- while (*ext)
- {
- ext = get_token (ext, PATH_DELIMITER, z);
- if (access (nm, F_OK) == 0)
- return 1;
- }
- return 0;
- }
-
- #define stpcpy(D,S) (strcpy (D, S) + strlen (S))
-
- char *
- expand_filename (const char *nm, const char *paths,
- const char *exts, char *fn)
- /*
- * nm file name input, short
- * path search path for files
- * ext default file extensions
- * fn full file name, output
- */
- {
- char buf[PATH_LENGTH], *p;
- char *home = getenv ("HOME");
-
- if (*nm == '~' && home)
- {
- p = buf;
- p = stpcpy (p, home);
- p = stpcpy (p, ++nm);
- if (try_extensions (buf, exts))
- return strcpy (fn, buf);
- }
- else
- {
- while (*paths)
- {
- p = buf;
- if (*paths == '~' && home)
- {
- paths++;
- p = stpcpy (p, home);
- }
- paths = get_token (paths, PATH_DELIMITER, p);
- strcat (buf, nm);
- if (try_extensions (buf, exts))
- return strcpy (fn, buf);
- }
- }
- return strcpy (fn, nm);
- }
-
- /************************************************************************/
- /* unsigned and floored divide and number i/o conversion */
- /************************************************************************/
-
- udiv_t
- udiv (uCell num, uCell denom) /* unsigned divide procedure, single prec */
- {
- udiv_t res;
-
- res.quot = num / denom;
- res.rem = num % denom;
- return res;
- }
-
- fdiv_t
- fdiv (Cell num, Cell denom) /* floored divide procedure, single prec */
- {
- fdiv_t res;
-
- res.quot = num / denom;
- res.rem = num % denom;
- if (res.rem && (num ^ denom) < 0)
- {
- res.quot--;
- res.rem += denom;
- }
- return res;
- }
-
- uCell
- u_d_div (udCell *ud, uCell denom)
- /*
- * Divides *ud by denom, leaves result in *ud, returns remainder.
- * For number output conversion: dividing by BASE.
- */
- {
- udCell nom = *ud;
- udiv_t h;
-
- h = udiv (D0 (nom), denom);
- D0 (*ud) = h.quot;
- D0 (nom) = h.rem;
- h = udiv (nom.hi, denom);
- D1 (*ud) = h.quot;
- D1 (nom) = h.rem;
- h = udiv (CELL (D1 (nom), D2 (nom)), denom);
- D2 (*ud) = h.quot;
- D2 (nom) = h.rem;
- h = udiv (nom.lo, denom);
- D3 (*ud) = h.quot;
- return h.rem;
- }
-
- void
- u_d_mul (udCell *ud, uCell w, uCell c)
- /*
- * Computes *ud * w + c, where w is actually only half of a Cell in size.
- * Leaves result in *ud.
- * For number input conversion: multiply by BASE and add digit.
- */
- {
- c += D3 (*ud) * w, D3 (*ud) = W1 (c), c >>= HALFCELL;
- c += D2 (*ud) * w, D2 (*ud) = W1 (c), c >>= HALFCELL;
- c += D1 (*ud) * w, D1 (*ud) = W1 (c), c >>= HALFCELL;
- D0 (*ud) = D0 (*ud) * w + c;
- }
-
- int
- dig2num (Byte c, uCell *n, uCell base)
- /*
- * Get value of digit c into *n, return flag: valid digit.
- */
- {
- if (c < '0')
- return FALSE;
- if (c <= '9')
- c -= '0';
- else
- {
- if (LOWER_CASE)
- c = toupper (c);
- if (c < 'A')
- return FALSE;
- if (c <= 'Z')
- c -= 'A' - ('9' - '0' + 1);
- else
- {
- if (LOWER_CASE || c < 'a')
- return FALSE;
- c -= 'a' - ('9' - '0' + 1) - ('Z' - 'A' + 1);
- }
- }
- if (c >= base)
- return FALSE;
- *n = c;
- return TRUE;
- }
-
- char
- num2dig (uCell n) /* make digit */
- {
- if (n < 10)
- return n + '0';
- if (n < 10 + 'Z' - 'A' + 1)
- return n - 10 + 'A';
- else
- return n - (10 + 'Z' - 'A' + 1) + 'a';
- }
-
- void
- hold (char c) /* insert into pictured numeric */
- { /* output string */
- if (HLD <= (char *) DP)
- tHrow (THROW_PICNUM_OVER);
- *--HLD = c;
- }
-
- const char *
- to_number (const char *p, uCell *n, udCell *d, uCell base)
- {
- for (; *n > 0; p++, --*n)
- {
- uCell c;
-
- if (!dig2num (*p, &c, base))
- break;
- u_d_mul (d, base, c);
- if (DPL >= 0)
- DPL++;
- }
- return p;
- }
-
- int
- number_question (const char *p, uCell n, dCell *d)
- {
- uCell base = 0;
- int sign = 0;
-
- for (; n; p++, n--)
- {
- switch (*p)
- {
- default:
- break;
- case '-':
- if (sign)
- return 0;
- sign = 1;
- continue;
- #if PREFIX_HEX
- case PREFIX_HEX:
- if (base)
- return 0;
- base = 16;
- continue;
- #endif
- #if PREFIX_BINARY
- case PREFIX_BINARY:
- if (base)
- return 0;
- base = 2;
- continue;
- #endif
- }
- break;
- }
- if (base == 0)
- base = BASE;
- d->lo = d->hi = 0;
- DPL = -1;
- p = to_number (p, &n, (udCell *) d, base);
- if (n == 0)
- goto happy;
- if (*p != '.')
- return 0;
- DPL = 0;
- p++;
- n--;
- p = to_number (p, &n, (udCell *) d, base);
- if (n != 0)
- return 0;
- happy:
- if (sign)
- dnegate (d);
- return 1;
- }
-
- #if defined USE_STRTOD /* most systems have good strtod */
-
- static int
- to_float (char *p, Cell n, double *r)
- {
- char buf[80], *q;
-
- store_c_string (p, n, buf, sizeof buf);
- if (tolower (buf[n - 1]) == 'e')
- {
- buf[n++] = '0';
- buf[n] = '\0';
- }
- *r = strtod (buf, &q);
- if (q == NULL)
- return 1;
- while (isspace (*q))
- q++;
- return *q == '\0';
- }
-
- #else /* but some haven't */
-
- static int
- to_float (char *p, Cell n, double *r)
- {
- enum state /* states of the state machine */
- {
- bpn, /* before point, maybe sign */
- bp, /* before point, no more sign (had one) */
- ap, /* after point */
- exn, /* exponent, maybe sign */
- ex /* exponent, no more sign */
- };
- enum state state = bpn;
- int sign = 1; /* sign of mantissa */
- long double mant = 0; /* the mantissa */
- int esign = 1; /* sign of exponent */
- int exp = 0; /* the exponent */
- int scale = 0; /* number of digits after point */
-
- while (--n >= 0)
- {
- char c = *p++;
-
- switch (state)
- {
- case bpn:
- switch (c)
- {
- case '-':
- sign = -1;
- case '+':
- state = bp;
- continue;
- case '.':
- state = ap;
- continue;
- default:
- if (isspace (c))
- continue;
- if (isdigit (c))
- {
- mant = c - '0';
- state = bp;
- continue;
- }
- }
- return 0;
- case bp:
- switch (c)
- {
- case '.':
- state = ap;
- continue;
- case '-':
- esign = -1;
- case '+':
- state = ex;
- continue;
- case 'e':
- if (!LOWER_CASE)
- return 0;
- case 'E':
- state = exn;
- continue;
- default:
- if (isdigit (c))
- {
- mant *= 10;
- mant += c - '0';
- continue;
- }
- }
- return 0;
- case ap:
- switch (c)
- {
- case '-':
- esign = -1;
- case '+':
- state = ex;
- continue;
- case 'e':
- if (!LOWER_CASE)
- return 0;
- case 'E':
- state = exn;
- continue;
- default:
- if (isdigit (c))
- {
- mant *= 10;
- mant += c - '0';
- scale--;
- continue;
- }
- }
- return 0;
- case exn:
- switch (c)
- {
- case '-':
- esign = -1;
- case '+':
- state = ex;
- continue;
- default:
- if (isdigit (c))
- {
- exp = c - '0';
- state = ex;
- continue;
- }
- }
- return 0;
- case ex:
- if (isdigit (c))
- {
- exp *= 10;
- exp += c - '0';
- continue;
- }
- return 0;
- }
- }
- *r = sign * mant * pow10 (scale + esign * exp);
- return 1;
- }
-
- #endif
-
- /*
- * These are for internal use only (SEE and debugger),
- * The real `UD.R' etc. words use HOLD and the memory area below PAD
- */
-
- char *
- str_ud_dot_r (udCell ud, char *p, int w, int base)
- {
- *--p = '\0';
- do
- {
- *--p = num2dig (u_d_div (&ud, base));
- w--;
- }
- while (ud.lo || ud.hi);
- while (w > 0)
- *--p = ' ', w--;
- return p;
- }
-
- char *
- str_d_dot_r (dCell d, char *p, int w, int base)
- {
- int sign = 0;
-
- if (d.hi < 0)
- dnegate (&d), sign = 1;
- *--p = '\0';
- do
- {
- *--p = num2dig (u_d_div ((udCell *) &d, base));
- w--;
- }
- while (d.lo || d.hi);
- if (sign)
- *--p = '-', w--;
- while (w > 0)
- *--p = ' ', w--;
- return p;
- }
-
- char *
- str_dot (Cell n, char *p, int base)
- {
- dCell d;
- char *bl;
-
- *--p = '\0';
- bl = p - 1;
- d.lo = n;
- d.hi = n < 0 ? -1 : 0;
- p = str_d_dot_r (d, p, 0, base);
- *bl = ' ';
- return p;
- }
-
- /************************************************************************/
- /* console i/o */
- /************************************************************************/
-
- /* output adjusting the OUT variable */
-
- void
- outc (char c) /* emit single character */
- {
- int x, y;
-
- c_putc (c);
- c_wherexy (&x, &y);
- OUT = x;
- }
-
- void
- outs (const char *s) /* type a string */
- {
- int x, y;
-
- c_puts (s);
- c_wherexy (&x, &y);
- OUT = x;
- }
-
- int
- outf (const char *s,...) /* type a string with formatting */
- {
- char buf[0x200];
- va_list p;
- int r;
-
- va_start (p, s);
- r = vsprintf (buf, s, p);
- outs (buf);
- va_end (p);
- return r;
- }
-
- void
- type (const char *s, Cell n) /* TYPE counted string to terminal */
- {
- int x, y;
-
- while (--n >= 0)
- c_putc_noflush (*s++);
- c_wherexy (&x, &y);
- OUT = x;
- c_flush ();
- }
-
- void
- type_on_line (const char *s, Cell n)
- {
- if (OUT + n >= cols)
- cr_ ();
- type (s, n);
- }
-
- void
- spaces (int n)
- {
- int x, y;
-
- while (--n >= 0)
- c_putc_noflush (' ');
- fflush (stdout);
- c_wherexy (&x, &y);
- OUT = x;
- }
-
- void
- tab (int n)
- {
- spaces (n - OUT % n);
- }
-
- void
- dot_line (File *fid, Cell n, Cell l)
- {
- char *p = block (fid, n) + l * 64;
- type (p, dash_trailing (p, 64));
- }
-
- /* input */
-
- static int
- get_line (char *p, Cell n)
- {
- char *q, buf[0x100];
- extern code (bye);
-
- q = fgets (buf, n, stdin);
- if (q == NULL)
- bye_ ();
- q = strrchr (q, '\n');
- if (q)
- *q = '\0';
- strcpy (p, buf);
- return strlen (p);
- }
-
- int
- expect (char *p, Cell n) /* EXPECT counted string from terminal, */
- { /* simple editing facility with Backspace, */
- int i; /* very traditional, use lined() instead! */
- char c;
-
- if (option.canonical)
- return get_line (p, n);
- for (i = 0; i < n;)
- {
- switch (c = c_getkey ())
- {
- default:
- p[i++] = c;
- outc (c);
- continue;
- case 27:
- for (; i > 0; i--)
- backspace_ ();
- continue;
- case '\t':
- while (i < n)
- {
- p[i++] = ' ';
- space_ ();
- if (OUT % 8 == 0)
- break;
- }
- continue;
- case '\r':
- case '\n':
- space_ ();
- goto fin;
- case 127:
- case '\b':
- if (i <= 0)
- {
- c_bell ();
- continue;
- }
- i--;
- backspace_ ();
- continue;
- }
- }
- fin:p[i] = 0;
- SPAN = i;
- return i;
- }
-
- int
- aCcept (char *p, int n) /* better input facility using lined() */
- {
- extern struct lined accept_lined;
-
- if (option.canonical)
- return get_line (p, n);
- accept_lined.string = p;
- accept_lined.max_length = n;
- lined (&accept_lined, NULL);
- space_ ();
- return accept_lined.length;
- }
-
- int
- question_stop (void) /* check for 'q' pressed */
- {
- if (ekeypressed ())
- {
- if (tolower (c_getkey ()) == 'q')
- return 1;
- if (tolower (c_getkey ()) == 'q')
- return 1;
- }
- return 0;
- }
-
- int
- question_cr (void)
- /*
- * Like CR but stop after one screenful and return flag if 'q' pressed.
- * Improved by aph@oclc.org (Andrew Houghton)
- */
- {
- static char more[] = "more? ";
- static char help[] = "\r[next line=<return>, next page=<space>, quit=q] ";
-
- cr_ ();
- if (option.canonical)
- return 0;
- if (sys.lines < sys.more)
- return 0;
- sys.lines = 0;
- for (;;)
- {
- outs (more);
- switch (tolower (c_getkey ()))
- {
- case 'n': /* no more */
- case 'q': /* quit */
- return 1;
- case 'y': /* more */
- case ' ': /* page */
- while (OUT)
- backspace_ ();
- sys.more = rows - 1;
- return 0;
- case '\r': /* line */
- case '\n': /* line */
- while (OUT)
- backspace_ ();
- sys.more = 1;
- return 0;
- default: /* unknown */
- c_bell ();
- /* ... */
- case '?': /* help */
- case 'h': /* help */
- outs (help);
- break;
- }
- }
- }
-
- /************************************************************************/
- /* files */
- /************************************************************************/
-
- void
- file_errorz (const char *fn)
- {
- tHrow (-256 - errno, fn);
- }
-
- void
- file_error (const char *fn, int len)
- {
- char buf[PATH_LENGTH];
-
- store_filename (fn, len, buf, sizeof buf);
- file_errorz (buf);
- }
-
- static File *
- free_file_slot (void)
- {
- File *f;
-
- for (f = membot.files; f < memtop.files; f++)
- if (f->f == NULL)
- {
- memset (f, 0, sizeof *f);
- return f;
- }
- return NULL;
- }
-
- int
- file_access (const char *fn, int len)
- /*
- * Return best possible access method,
- * 0 if no access but file exists, -1 if file doesn't exist.
- */
- {
- char buf[PATH_LENGTH];
-
- store_filename (fn, len, buf, sizeof buf);
- if (access (buf, F_OK) != 0)
- return -1;
- if (access (buf, R_OK | W_OK) == 0)
- return FMODE_RW;
- if (access (buf, R_OK) == 0)
- return FMODE_RO;
- if (access (buf, W_OK) == 0)
- return FMODE_WO;
- return 0;
- }
-
- static char open_mode[][4] = /* mode strings for fopen() */
- {
- "r", "r+", "r+", /* R/O W/O R/W */
- "rb", "r+b", "r+b", /* after application of BIN */
- };
-
- File *
- open_file (const char *name, int len, int mode)
- {
- File *fid;
-
- fid = free_file_slot ();
- if (fid == NULL)
- return NULL;
- store_filename (name, len, fid->name, sizeof fid->name);
- fid->mode = mode;
- fid->last_op = 0;
- strcpy (fid->mdstr, open_mode[mode - FMODE_RO]);
- if ((fid->f = fopen (fid->name, fid->mdstr)) == NULL)
- return NULL;
- fid->size = (uCell) (fsize (fid->f) / BPBUF);
- fid->n = (unsigned) -1;
- return fid;
- }
-
- File *
- create_file (const char *name, int len, int mode)
- {
- char fn[PATH_LENGTH];
- File *fid;
-
- store_filename (name, len, fn, sizeof fn);
- fclose (fopen (fn, "wb"));
- fid = open_file (name, len, mode);
- if (fid)
- {
- return fid;
- }
- else
- {
- remove (fn);
- return NULL;
- }
- }
-
- int
- close_file (File *fid)
- {
- int res = 0;
-
- if (fid->f)
- {
- res = fclose (fid->f);
- memset (fid, 0, sizeof *fid);
- }
- return res;
- }
-
- int
- reposition_file (File *fid, long pos)
- {
- fid->last_op = 0;
- return fseek (fid->f, pos, SEEK_SET) ? errno : 0;
- }
-
- static int
- can_read (File *fid)
- /*
- * Called before trying to read from a file.
- * Checks if you may, maybe fseeks() so you can.
- */
- {
- switch (fid->mode) /* check permission */
- {
- case FMODE_WO:
- case FMODE_WOB:
- return 0;
- }
- if (fid->last_op < 0) /* last operation was write? */
- fseek (fid->f, 0, SEEK_CUR); /* then seek to this position */
- fid->last_op = 1;
- return 1;
- }
-
- static int
- can_write (File *fid)
- /*
- * Called before trying to write to a file.
- * Checks if you may, maybe fseeks() so you can.
- */
- {
- switch (fid->mode) /* check permission */
- {
- case FMODE_RO:
- case FMODE_ROB:
- return 0;
- }
- if (fid->last_op > 0) /* last operation was read? */
- fseek (fid->f, 0, SEEK_CUR); /* then seek to this position */
- fid->last_op = -1;
- return 1;
- }
-
- int
- read_file (void *p, uCell *n, File *fid)
- {
- int m;
-
- if (!can_read (fid))
- return EPERM;
- errno = 0;
- m = fread (p, 1, *n, fid->f);
- if (m != *n)
- {
- *n = m;
- return errno;
- }
- else
- return 0;
- }
-
- int
- write_file (void *p, uCell n, File *fid)
- {
- if (!can_write (fid))
- return EPERM;
- errno = 0;
- return fwrite (p, 1, n, fid->f) != n ? errno : 0;
- }
-
- int
- resize_file (File *fid, long size)
- {
- long pos;
- int r;
-
- if (fid == NULL || fid->f == NULL)
- tHrow (THROW_FILE_NEX);
-
- pos = ftell (fid->f);
- if (pos == -1)
- return -1;
-
- fclose (fid->f);
- r = resize (fid->name, size);
- fid->f = fopen (fid->name, fid->mdstr);
-
- if (pos < size)
- fseek (fid->f, pos, SEEK_SET);
- else
- fseek (fid->f, 0, SEEK_END);
- return r;
- }
-
- int
- read_line (char *p, uCell *u, File *fid, Cell *ior)
- {
- int c, n;
-
- if (!can_read (fid))
- return EPERM;
- if (feof (fid->f))
- {
- *u = 0;
- *ior = 0;
- return FALSE;
- }
- fid->pos = ftell (fid->f);
- for (n = 0; n < *u; n++)
- switch (c = getc (fid->f))
- {
- case EOF:
- if (!ferror (fid->f))
- goto happy;
- *u = n;
- *ior = errno;
- return FALSE;
- case '\r':
- c = getc (fid->f);
- if (c != '\n')
- ungetc (c, fid->f);
- case '\n':
- goto happy;
- default:
- *p++ = c;
- }
- happy:
- *u = n;
- *ior = 0;
- fid->n++;
- return TRUE;
- }
-
- int
- systemf (const char *s,...) /* issue a system() call after formatting */
- {
- char buf[0x100];
- va_list p;
- int r;
-
- va_start (p, s);
- vsprintf (buf, s, p);
- va_end (p);
- system_terminal ();
- swap_signals ();
- r = system (buf);
- swap_signals ();
- interactive_terminal ();
- c_normal ();
- return r;
- }
-
- /************************************************************************/
- /* source input */
- /************************************************************************/
-
- /* 1. read from terminal */
-
- code (query)
- {
- SOURCE_ID = 0;
- BLK = 0;
- TO_IN = 0;
- TIB = membot.tib;
- NUMBER_TIB = aCcept (TIB, TIB_SIZE);
- SPAN = NUMBER_TIB;
- }
-
- /* 2. read from text-file */
-
- int
- next_line (void)
- {
- Cell ior;
- uCell len;
-
- len = sizeof SOURCE_FILE->buffer;
- if (!read_line (SOURCE_FILE->buffer, &len, SOURCE_FILE, &ior))
- {
- SOURCE_FILE->len = len;
- return 0;
- }
- TIB = SOURCE_FILE->buffer;
- NUMBER_TIB = SOURCE_FILE->len = len;
- BLK = 0;
- TO_IN = 0;
- return 1;
- }
-
- /* 3. read from block-file */
-
- File *
- open_block_file (const char *name, int len)
- {
- char nm[PATH_LENGTH], fn[PATH_LENGTH];
- int mode;
-
- store_filename (name, len, nm, sizeof nm);
- expand_filename (nm, option.blkpaths, option.blkext, fn);
- mode = file_access (fn, strlen (fn));
- if (mode <= 0)
- return NULL;
- return open_file (fn, strlen (fn), mode + FMODE_BIN);
- }
-
- int
- use_block_file (const char *name, int len)
- {
- File *fid;
-
- fid = open_block_file (name, len);
- if (fid == NULL)
- return FALSE;
- if (BLOCK_FILE)
- {
- save_buffers_ ();
- close_file (BLOCK_FILE);
- }
- BLOCK_FILE = fid;
- return TRUE;
- }
-
- void
- read_write (File *fid, char *p, uCell n, int readflag)
- /* very traditional block read/write primitive */
- {
- size_t len;
-
- question_file_open (fid);
- clearerr (fid->f);
- if (n > fid->size)
- tHrow (THROW_INVALID_BLOCK);
- if (readflag && n == fid->size)
- {
- memset (p, ' ', BPBUF);
- return;
- }
- if (fseek (fid->f, n * BPBUF, SEEK_SET) != 0)
- file_errorz (fid->name);
- if (readflag)
- {
- if (!can_read (fid))
- tHrow (THROW_BLOCK_READ);
- len = fread (p, 1, BPBUF, fid->f);
- if (ferror (fid->f))
- file_errorz (fid->name);
- memset (p + len, ' ', BPBUF - len);
- }
- else
- {
- if (!can_write (fid))
- tHrow (THROW_BLOCK_WRITE);
- len = fwrite (p, 1, BPBUF, fid->f);
- if (len < BPBUF || ferror (fid->f))
- file_errorz (fid->name);
- if (n == fid->size)
- fid->size++;
- }
- return;
- }
-
- char *
- buffer (File *fid, uCell n, int *reload)
- {
- question_file_open (fid);
- if (fid->n != n)
- {
- if (fid->updated)
- read_write (fid, fid->buffer, fid->n, FALSE);
- fid->n = n;
- *reload = 1;
- }
- else
- *reload = 0;
- return fid->buffer;
- }
-
- char *
- block (File *fid, uCell n)
- {
- char *p;
- int reload;
-
- p = buffer (fid, n, &reload);
- if (reload)
- read_write (fid, p, n, TRUE);
- return p;
- }
-
- void
- empty_buffers (File *fid)
- {
- question_file_open (fid);
- ZERO (fid->buffer);
- fid->n = UINT_MAX;
- fid->updated = 0;
- }
-
- void
- save_buffers (File *fid)
- {
- if (fid && fid->updated)
- {
- read_write (fid, fid->buffer, fid->n, FALSE);
- fflush (fid->f);
- fid->updated = 0;
- }
- }
-
- void
- update (File *fid)
- {
- question_file_open (fid);
- if ((int) fid->n < 0)
- tHrow (THROW_INVALID_BLOCK);
- fid->updated = 1;
- }
-
- void
- list (File *fid, int n)
- {
- int i;
-
- for (i = 0; i < 16; i++)
- {
- cr_ ();
- outf ("%2d: ", i);
- dot_line (fid, n, i);
- }
- space_ ();
- SCR = n;
- }
-
- /* dispatch input source */
-
- void
- source (char **p, int *n)
- {
- switch (SOURCE_ID)
- {
- case -1: /* string from EVALUATE */
- *p = TIB;
- *n = NUMBER_TIB;
- break;
- case 0: /* string from QUERY or BLOCK */
- if (BLK)
- {
- *p = block (BLOCK_FILE, BLK);
- *n = BPBUF;
- }
- else
- {
- *p = TIB;
- *n = NUMBER_TIB;
- }
- break;
- default: /* source line from text file */
- *p = SOURCE_FILE->buffer;
- *n = SOURCE_FILE->len;
- }
- }
-
- void *
- save_input (void *p)
- {
- Iframe *iframe = (Iframe *) p;
-
- --iframe;
- iframe->magic = INPUT_MAGIC;
- iframe->input = sys.input;
- iframe->prev = sys.saved_input;
- sys.saved_input = iframe;
-
- p = (void *) iframe;
- return p;
- }
-
- void *
- restore_input (void *p)
- {
- Iframe *iframe = (Iframe *) p;
-
- if (iframe->magic != INPUT_MAGIC)
- tHrow (THROW_ARG_TYPE);
- sys.input = iframe->input;
- sys.saved_input = iframe->prev;
- ++iframe;
-
- p = (void *) iframe;
- return p;
- }
-
- int
- refill (void)
- {
- switch (SOURCE_ID)
- {
- case -1:
- return 0;
- case 0:
- if (BLK)
- {
- BLK++;
- TO_IN = 0;
- }
- else
- query_ ();
- return 1;
- default:
- return next_line ();
- }
- }
-
- void
- skip_delimiter (char del)
- {
- char *q;
- int i, n;
-
- source (&q, &n);
- if (del == ' ')
- for (i = TO_IN; i < n && isascii (q[i]) && isspace (q[i]); i++);
- else
- for (i = TO_IN; i < n && q[i] == del; i++);
- TO_IN = i;
- }
-
- int
- parse (char del, char **p, uCell *l)
- {
- char *q;
- int i, n;
-
- source (&q, &n);
- *p = q + TO_IN;
- if (del == ' ')
- for (i = TO_IN; i < n && !(isascii (q[i]) && isspace (q[i])); i++);
- else
- for (i = TO_IN; i < n && q[i] != del; i++);
- *l = i - TO_IN;
- if (i == n)
- {
- TO_IN = i;
- return 0;
- }
- else
- {
- TO_IN = i + 1;
- return 1;
- }
- }
-
- char *
- word (char del) /* action of WORD callable from C functions */
- {
- char *p, *q;
- int n, i;
-
- skip_delimiter (del);
- source (&q, &n);
- q += TO_IN;
- n -= TO_IN;
- p = (char *) DP + 1;
- if (del == ' ')
- for (i = 0; i < n && !(isascii (*q) && isspace (*q)); i++)
- *p++ = *q++;
- else
- for (i = 0; i < n && *q != del; i++)
- *p++ = *q++;
- TO_IN += i + (i < n);
- *p = '\0';
- if (i > 255)
- tHrow (THROW_PARSE_OVER);
- *DP = i;
- return (char *) DP;
- }
-
- /************************************************************************/
- /* inner and outer interpreter */
- /************************************************************************/
-
- typedef struct /* jumpbuf is a jmp_buf enhanced by */
- { /* space to preserve global variables */
- jmp_buf jmp; /* stored in registers. */
- #ifdef REGRP
- Xt **rp;
- #endif
- #ifdef REGSP
- Cell *sp;
- #endif
- #ifdef REGLP
- Cell *lp;
- #endif
- #ifdef REGFP
- double *fp;
- #endif
- }
- jumpbuf;
-
- Code (jump) /* longjmp via (jumpbuf*) following inline */
- { /* purpose: stop the inner interpreter */
- jumpbuf *buf = (jumpbuf *) *ip;
-
- #ifdef REGRP /* save global register variables */
- buf->rp = rp;
- #endif
- #ifdef REGSP
- buf->sp = sp;
- #endif
- #ifdef REGLP
- buf->lp = lp;
- #endif
- #ifdef REGFP
- buf->fp = fp;
- #endif
- longjmp (buf->jmp, 1);
- }
-
- void
- run_forth (Xt xt) /* Run a forth word from within C-code. */
- { /* This is the inner interpreter. */
- static pCode jump_p = jump_;
- jumpbuf stop;
- Xt list[3];
-
- list[0] = xt;
- list[1] = &jump_p;
- list[2] = (Xt) &stop;
- ip = list;
- if (setjmp (stop.jmp))
- {
- #ifdef REGRP /* restore global register variables */
- rp = stop.rp; /* clobbered by longjmp() */
- #endif
- #ifdef REGSP
- sp = stop.sp;
- #endif
- #ifdef REGLP
- lp = stop.lp;
- #endif
- #ifdef REGFP
- fp = stop.fp;
- #endif
- return;
- }
- for (;;)
- {
- #ifdef W
- Xt w;
- #define NEXT w = *ip++, (*w) () /* ip is register but W isn't */
- #else
- #define NEXT W = *ip++, (*W) () /* ip and W are same: register or not */
- #endif
- #ifdef UNROLL_NEXT /* if it helps */
- NEXT; NEXT; NEXT; NEXT; /* do a little loop unrolling for speed */
- NEXT; NEXT; NEXT; NEXT;
- #else
- NEXT; /* on some machines it doesn't do any good */
- #endif
- }
- }
-
- void
- call_forth (Xt xt)
- {
- #if 0 && defined SunOS
- void *saved_ip;
-
- saved_ip = ip;
- printf ("%X/%X\n", ip, saved_ip);
- run_forth (xt);
- printf ("%X/%X\n", ip, saved_ip);
- ip = saved_ip;
- printf ("%X/%X\n\n", ip, saved_ip);
- #else
- Xt *saved_ip = ip;
-
- run_forth (xt);
- ip = saved_ip;
- #endif
- }
-
- void
- normal_execute (Xt xt) /* i.e. w/o debugging */
- {
- #ifdef W
- call_forth (xt);
- #else
- W = xt;
- (*W) ();
- #endif
- }
-
- void (*execute) (Xt xt) = normal_execute;
-
- code (interpret)
- {
- char *s, *p;
- int len;
- dCell d;
- double f;
-
- for (;;)
- {
- for (;;)
- {
- p = word (' ');
- if ((len = *(Byte *) p++) != 0)
- break;
- switch (SOURCE_ID)
- {
- default:
- if (next_line ())
- continue;
- case 0:
- case -1:
- return;
- }
- }
- if (STATE)
- {
- if (sys.locals && compile_local (p, len))
- continue;
- s = find (p, len);
- if (s != NULL)
- {
- Xt xt = name_from (s);
-
- if (*s & IMMEDIATE)
- {
- call_forth (xt);
- question_stack_ ();
- }
- else
- COMMA (xt);
- continue;
- }
- if (number_question (p, len, &d))
- {
- if (DPL >= 0)
- {
- COMPILE1 (two_literal);
- COMMA (d.hi);
- }
- else
- COMPILE1 (literal);
- COMMA (d.lo);
- continue;
- }
- if (BASE == 10 && FLOAT_INPUT && to_float (p, len, &f))
- {
- #if DFLOAT_ALIGN > CELL_ALIGN
- if (DFALIGNED (DP))
- COMPILE2 (f_literal);
- #endif
- COMPILE1 (f_literal);
- FCOMMA (f);
- continue;
- }
- }
- else
- {
- s = find (p, len);
- if (s != NULL)
- {
- call_forth (name_from (s));
- question_stack_ ();
- continue;
- }
- if (number_question (p, len, &d))
- {
- *--sp = d.lo;
- if (DPL >= 0)
- *--sp = d.hi;
- continue;
- }
- if (BASE == 10 && FLOAT_INPUT && to_float (p, len, &f))
- {
- *--fp = f;
- continue;
- }
- }
- tHrow (THROW_UNDEFINED);
- }
- }
-
- void
- evaluate (char *p, int n)
- {
- rp = (Xt **) save_input (rp);
- SOURCE_ID = -1;
- BLK = 0;
- TIB = p;
- NUMBER_TIB = n;
- TO_IN = 0;
- interpret_ ();
- rp = (Xt **) restore_input (rp);
- }
-
- void
- load (File *fid, uCell blk)
- {
- if (blk == 0)
- tHrow (THROW_INVALID_BLOCK);
- rp = (Xt **) save_input (rp);
- BLOCK_FILE = fid;
- SOURCE_ID = 0;
- BLK = blk;
- TO_IN = 0;
- interpret_ ();
- rp = (Xt **) restore_input (rp);
- }
-
- void
- load_file (char *fn, int cnt, int blk)
- {
- File *fid = open_block_file (fn, cnt);
-
- if (fid == NULL)
- file_error (fn, cnt);
- load (fid, blk);
- }
-
- void
- thru (File *fid, int lo, int hi)
- {
- int i;
-
- for (i = lo; i <= hi; i++)
- load (fid, i);
- }
-
- void
- include_file (File *fid)
- {
- if (fid == NULL || fid->f == NULL)
- tHrow (THROW_FILE_NEX);
- rp = (Xt **) save_input (rp);
- SOURCE_ID = (Cell) fid;
- BLK = 0;
- TO_IN = 0;
- interpret_ ();
- rp = (Xt **) restore_input (rp);
- }
-
- void
- included (const char *name, int len)
- {
- char nm[0x80], fn[0x100];
- File *f;
-
- store_filename (name, len, nm, sizeof nm);
- expand_filename (nm, option.incpaths, option.incext, fn);
- f = open_file (fn, strlen (fn), FMODE_RO);
- if (!f)
- tHrow (THROW_FILE_NEX);
- include_file (f);
- close_file (f);
- }
-
- static void
- unnest_input (Iframe *p)
- {
- while (sys.saved_input && sys.saved_input != p)
- {
- switch (SOURCE_ID)
- {
- case -1:
- case 0:
- break;
- default:
- close_file (SOURCE_FILE);
- }
- rp = (Xt **) restore_input (sys.saved_input);
- }
- }
-
- /************************************************************************/
- /* QUIT, ABORT and exception handling */
- /************************************************************************/
-
- jmp_buf quit_dest; /* QUIT and ABORT do a THROW which longjmp() */
- jmp_buf abort_dest; /* here thus C-stack gets cleaned up too */
-
- static void
- quit_initializations (void) /* Things quit has to initialize: */
- {
- rp = sys.r0; /* return stack */
- lp = NULL; /* including all local variables */
- STATE = FALSE; /* interpreting now */
- sys.cAtch = NULL; /* and no exceptions caught */
- debug_off (); /* turn off debugger */
- }
-
- static void /* normal interactive QUIT */
- do_quit (void) /* doing the QUERY-INTERPRET loop */
- {
- setjmp (quit_dest);
- quit_initializations ();
- unnest_input (NULL);
- for (;;)
- {
- cr_ ();
- query_ ();
- interpret_ ();
- question_stack_ ();
- if (!STATE)
- outs ("ok");
- }
- }
-
- static void
- abort_initializations (void) /* Things ABORT has to initialize: */
- {
- sp = sys.s0; /* stacks */
- fp = sys.f0;
- reset_order_ (); /* reset search order */
- definitions_ (); /* and vocabulary in extension */
- decimal_ (); /* number i/o base */
- standard_io_ (); /* disable i/o redirection */
- }
-
- void
- do_abort (void)
- {
- setjmp (abort_dest);
- abort_initializations ();
- do_quit ();
- }
-
- static void
- show_error (char *fmt,...)
- {
- char buf[128];
- va_list p;
- int n;
-
- sys.input_err = sys.input; /* save input specification of error */
- va_start (p, fmt);
- vsprintf (buf, fmt, p);
- va_end (p);
- outf ("\nError: \"%.*s\" %s\n", *DP, DP + 1, buf);
- switch (SOURCE_ID)
- {
- case 0:
- if (BLK && BLOCK_FILE && !ferror (BLOCK_FILE->f))
- {
- outf ("Block %lu line %d:\n",
- (unsigned long) BLK, (int) TO_IN / 64);
- dot_line (BLOCK_FILE, BLK, TO_IN / 64);
- n = TO_IN % 64;
- break;
- }
- case -1:
- type (TIB, NUMBER_TIB);
- n = TO_IN;
- break;
- default:
- outf ("File %s line %lu:\n",
- SOURCE_FILE->name, (unsigned long) SOURCE_FILE->n);
- type (TIB, NUMBER_TIB);
- n = TO_IN;
- }
- outf ("\n%*s", n, "^");
- longjmp (abort_dest, 2);
- }
-
- static void
- throw_msg (int id, char *msg)
- {
- /* *INDENT-OFF* */
- static char *throw_explanation[] =
- {
- /* -1 */ NULL, /* ABORT */
- /* -2 */ NULL, /* ABORT" */
- /* -3 */ "stack overflow",
- /* -4 */ "stack underflow",
- /* -5 */ "return stack overflow",
- /* -6 */ "return stack underflow",
- /* -7 */ "do-loops nested too deeply during execution",
- /* -8 */ "dictionary overflow",
- /* -9 */ "invalid memory address",
- /* -10 */ "division by zero",
- /* -11 */ "result out of range",
- /* -12 */ "argument type mismatch",
- /* -13 */ "undefined word",
- /* -14 */ "interpreting a compile-only word",
- /* -15 */ "invalid FORGET",
- /* -16 */ "attempt to use a zero-length string as a name",
- /* -17 */ "pictured numeric output string overflow",
- /* -18 */ "parsed string overflow",
- /* -19 */ "definition name too long",
- /* -20 */ "write to a read-only location",
- /* -21 */ "unsupported operation",
- /* -22 */ "control structure mismatch",
- /* -23 */ "address alignment exception",
- /* -24 */ "invalid numeric argument",
- /* -25 */ "return stack imbalance",
- /* -26 */ "loop parameters unavailable",
- /* -27 */ "invalid recursion",
- /* -28 */ "user interrupt",
- /* -29 */ "compiler nesting",
- /* -30 */ "obsolescent feature",
- /* -31 */ ">BODY used on non-CREATEDd definition",
- /* -32 */ "invalid name argument",
- /* -33 */ "block read exception",
- /* -34 */ "block write exception",
- /* -35 */ "invalid block number",
- /* -36 */ "invalid file position",
- /* -37 */ "file I/O exception",
- /* -38 */ "non-existent file",
- /* -39 */ "unexpected end of file",
- /* -40 */ "invalid BASE for floating-point conversion",
- /* -41 */ "loss of precision",
- /* -42 */ "floating-point divide by zero",
- /* -43 */ "floating-point result out of range",
- /* -44 */ "floating-point stack overflow",
- /* -45 */ "floating-point stack underflow",
- /* -46 */ "floating-point invalid argument",
- /* -47 */ "compilation word list deleted",
- /* -48 */ "invalid POSTPONE",
- /* -49 */ "search-order overflow",
- /* -50 */ "search-order underflow",
- /* -51 */ "compilation word list changed",
- /* -52 */ "control flow stack overflow",
- /* -53 */ "exception stack overflow",
- /* -54 */ "floating-point underflow",
- /* -55 */ "floating-point unidentified fault",
- /* -56 */ NULL, /* QUIT */
- /* -57 */ "error in sending or receiving a character",
- /* -58 */ "[IF], [ELSE] or [THEN] error"
- }, *pfe_throw_explanation[] =
- {
- /* -2048 */ "no or not matching binary image",
- /* -2049 */ "binary image too big",
- /* -2050 */ "out of memory",
- /* -2051 */ "index out of range",
- };
- /* *INDENT-ON* */
-
- if (-1 - DIM (throw_explanation) < id && id <= -1)
- strcpy (msg, throw_explanation[-1 - id]);
- else if (-2048 < id && id <= -256)
- {
- char fn[PATH_LENGTH];
-
- strcpy (fn, msg);
- sprintf (msg, ": File %s: %s", fn, strerror (-256 - id));
- }
- else if (-2048 - DIM (pfe_throw_explanation) < id && id <= -2048)
- strcpy (msg, pfe_throw_explanation[-2048 - id]);
- else
- sprintf (msg, "%d THROW unassigned", id);
- }
-
- int
- cAtch (Xt xt)
- {
- Except *x = DEC (rp, Except);
- int id;
-
- x->magic = EXCEPTION_MAGIC;
- x->ip = ip;
- x->sp = sp;
- x->lp = lp;
- x->fp = fp;
- x->iframe = sys.saved_input;
- x->prev = sys.cAtch;
- sys.cAtch = x;
- id = setjmp (x->jmp);
- if (!id)
- call_forth (xt);
- sys.cAtch = x->prev;
- rp = (Xt **) &x[1];
- return id;
- }
-
- void
- tHrow (int id,...)
- {
- Except *x = sys.cAtch;
- va_list p;
- char msg[80];
-
- if (x && x->magic == EXCEPTION_MAGIC)
- {
- ip = x->ip;
- sp = x->sp;
- lp = x->lp;
- fp = x->fp;
- unnest_input (x->iframe);
- longjmp (x->jmp, id);
- }
- switch (id)
- {
- case THROW_ABORT_QUOTE:
- {
- char *addr;
- int len;
-
- va_start (p, id);
- addr = va_arg (p, char *);
- len = va_arg (p, int);
- va_end (p);
- show_error ("%.*s", len, addr);
- }
- case THROW_ABORT:
- longjmp (abort_dest, 1);
- case THROW_QUIT:
- longjmp (quit_dest, 1);
- default:
- if (-2048 < id && id <= -256)
- {
- va_start (p, id);
- strcpy (msg, va_arg (p, char *));
- va_end (p);
- }
- throw_msg (id, msg);
- show_error (msg);
- }
- }
-
- void
- abortq (const char *fmt,...)
- {
- char buf[128];
- int n;
- va_list p;
-
- va_start (p, fmt);
- n = vsprintf (buf, fmt, p);
- va_end (p);
- tHrow (THROW_ABORT_QUOTE, buf, n);
- }
-
- void
- question_pairs (Cell n)
- {
- if (n != *sp++)
- tHrow (THROW_CONTROL_MISMATCH);
- }
-
- void
- question_file_open (File *fid)
- {
- if (fid == NULL || fid->f == NULL)
- tHrow (THROW_FILE_NEX);
- }
-
- /************************************************************************/
- /* Initialize dictionary, and system variables, include files */
- /************************************************************************/
-
- static void
- init_dictionary (Dict *dict, uCell size)
- {
- Dict *saved_sysdict;
-
- /* Temporarily activate this dictionary: */
- saved_sysdict = sys.dict;
- sys.dict = dict;
-
- if (option.load_dict)
- {
- if (!reload_dictionary (option.load_dict, sys.dict))
- fatal ("Couldn't reload dictionary file %s", option.load_dict);
- }
- else
- {
- /* Wipe the dictionary: */
- memset (dict, 0, size);
- preload_dictionary ();
-
- /* Define the following default search order:
- * ONLY EXTENSIONS ALSO FORTH ALSO */
- only_runtime ();
- CONTEXT[0] = FORTH;
- CONTEXT[1] = extensions_list.wid;
- also_ ();
- default_order_ ();
- }
- /* Action of ABORT and QUIT, but don't enter the interactive QUIT */
- abort_initializations ();
- quit_initializations ();
-
- /* Include .pferc if it exists: */
- if (option.pferc_file && access (option.pferc_file, R_OK) == 0)
- included (option.pferc_file, strlen (option.pferc_file));
-
- /* Include file from command line: */
- if (option.include_file)
- included (option.include_file, strlen (option.include_file));
-
- /* Switch back to the former dictionary: */
- sys.dict = saved_sysdict;
- }
-
- void /* set up all system variables */
- initialize_system (void) /* and initialize the dictionary */
- {
- memset (&sys, 0, sizeof sys);
- sys.dict = (Dict *) membot.dict;
- sys.s0 = memtop.stack;
- sys.f0 = memtop.fstack;
- sys.r0 = memtop.rstack;
- TIB = membot.tib;
- BASE = 10;
- DPL = -1;
- PRECISION = 6;
- LOWER_CASE = option.lower_case_on;
- LOWER_CASE_FN = option.lower_case_fn;
- FLOAT_INPUT = option.float_input;
- sys.local = (char (*)[32]) membot.stack;
-
- memset (memtop.files - 3, 0, sizeof (File) * 3);
-
- sys.stdIn = memtop.files - 3;
- sys.stdIn->f = stdin;
- strcpy (sys.stdIn->name, "<STDIN>");
- strcpy (sys.stdIn->mdstr, "r");
- sys.stdIn->mode = FMODE_RO;
-
- sys.stdOut = memtop.files - 2;
- sys.stdOut->f = stdout;
- strcpy (sys.stdOut->name, "<STDOUT>");
- strcpy (sys.stdOut->mdstr, "a");
- sys.stdOut->mode = FMODE_WO;
-
- sys.stdErr = memtop.files - 1;
- sys.stdErr->f = stderr;
- strcpy (sys.stdErr->name, "<STDERR>");
- strcpy (sys.stdErr->mdstr, "a");
- sys.stdErr->mode = FMODE_WO;
-
- if (option.block_file)
- {
- if (!use_block_file (option.block_file, strlen (option.block_file))
- && strcmp (option.block_file, DEFAULT_BLKFILE) != 0)
- fatal ("Can't find block file %s", option.block_file);
- }
-
- read_help_index (HELPDIR, "index");
-
- REDEFINED_MSG = FALSE;
- init_dictionary (sys.dict, memsiz.dict);
- REDEFINED_MSG = TRUE;
-
- if (option.save_dict)
- {
- extern void *getmem (size_t n);
- Dict *dict2 = (Dict *) getmem ((size_t) memsiz.dict);
- long size;
-
- init_dictionary (dict2, memsiz.dict);
- size = save_dictionary (sys.dict, dict2, option.save_dict);
- if (size)
- outf ("\nSaved dictionary to %s, wrote %ld bytes.\n",
- option.save_dict, size);
- else
- outs ("\nCouldn't create relocatable dictionary image.\n");
- free (dict2);
- }
- }
-