#define DATUM "16 February 2004"
#define VERSION "2"
#define BUILD "6"
/*
    Bracmat. Programming language with pattern matching on tree structures.
    Copyright (C) 2002  Bart Jongejan

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/*
NOTES
=====

2002.12.15
----------
This is the open source version of Bracmat.

Originally, Bracmat was written in Basic for the Amstrad computer. Its sole
purpose was to derive a simple expression for the curvature of a model
space-time, starting from the components of the metric. The only operations
the program was capable to perform were multiplications, exponentiations,
logarithms, and partial derivatives. The expressions were a mix of numbers
and symbolic variables, like "a+2*b". Thus, "a+a" was simplified to "2*a".

The second version of Bracmat, about 1988, was developed in Ansi C and run
on an Acorn Archimedes. Great care was taken to make the program portable to
other hardware, such as Atari, VAX and even the PC. The PC architecture, with
its limited memory, its 16 bit architecture and its limitation on the size of
the program stack, posed some severe limitations on the program. Therefore
great care was taken to limit the use of the stack to a minimum. This has
lead to some rather large functions (to save stack-consuming function calls).

The C version became a true programnming language, with program variables,
logical operators and function calls. The syntax, however, was not changed.
For example, instead of using "if...then...else...", I decided to write
something like "...&...|...", using lazy evaluation of the infix binary
logical operators "&" (AND) and "|" (OR) for program control.

The logical operators, of course, should test for operands being "true" or
"false". The main provider of interesting truth values became the pattern
matching operator ":", which tests whether the pattern (the rhs-operand)
matches the subject (the lhs-operand). The single outstanding feature of
Bracmat is, in fact, its pattern recognition, which works on tree structures,
not on strings of characters.

Bracmat was also extended with a few operators that makes this programming
language interesting in the field of computational linguistics, namely the
blank " ", the comma "," and the full stop ".". (The interpunction symbols
"?", "!" and ";" were already 'taken' to serve other purposes.)

You may find the source code difficult to read at some places. You are best
off if you understand English and Dutch (and perhaps Danish). Only if the
program arises enough interest I will invest the effort to streamline the
source text and make it more understandable for the general programmer.

COMPILATION
-----------
To compile an executable you only need this source file, bracmat.c. Unless
you #define MACRO it is assumed that the hardware is litte-endian,
(which has become the most common these days).

With GNU C, this should be enough to compile and link an executable:

gcc bracmat.c

With HP cc:

cc -Ae bracmat.c

If you can compile successfully but cannot run the program succesfully,
try putting -DBIGENDIAN on the command line of the compiler, like this:

cc -DBIGENDIAN  bracmat.c

This works of course only if the machine's hardware is big-endian.
*/

/*
TODO list:
20010103: Make > and < work on non-atomic stuff
20010904: Issue warning if 'arg' is declared as a local variable
*/
/* 20001213, There is a need to improve documentation of fil$ */
/* 20001213, rename a file ren$(oldname.newname) */
/* >Bracmat 16-11-91 */
/* 20010309 evalueer on LUCHT and KOMMA strings is now iterative on the
   right descending (deep) branch, not recursive.
   (It is now possible to read long lists, e.g. dictionairies, without causing
   stack overflow when evaluating the list.)
   20010821 a () () was evaluated to a (). Removed last ().
   20010903 (a.) () was evaluated to a
*/
#define SLOWPLUS 0 /* old code for adding algebraic expressions */
#define COMPILE 0  /* not so successful string table */
#define OBJECTS 0  /* unfinished attempt at implementing objects that can be saved and re-read (serialization)*/
#define DEBUGBRACMAT 0
#define DOCHECKSUM 0
#define WRITETRACE 0


#if COMPILE
#define ALLOCVAR 1
#define MACRO 1
#else
#define ALLOCVAR 0
#define MACRO 0
#endif

#ifndef NDEBUG
#define NDEBUG
#endif

/*#define PVNAME*/
#include <assert.h>
/* COMPILE works not faster, but slower (about 10%) and uses more nodes. */

/* 12.10.1999 */
/* Hier moet nog wat gedaan worden.
Tweede argument van zoeknaam (voorvar) moet verwijderd worden en deallocatie
van eenmaal gealloceerde vars moet niet plaatsvinden.
Wanneer een eindknoop wordt gekopieerd moet een vars->Refcount opgehoogd worden
als de knoop een pointer naar een vars is. Omgekeerd moet vars->Refcount
verlaagd worden als zo'n knoop verwijderd wordt.
RESOLVE is te ruw: de string wordt eenvoudig overschreven met een pointer, wat
tot verlies van geheugen kan leiden.
*/

/*19980208
Bug in match!!
Removed 19971207
*/
/*
sub must also accept . as separator between args
*/
/* wis: 18 Maart 1997, tail recursion optimization; delete deep structures*/
/* bezig met modernisering getallen */
/* 16 mei 1993: constante "-i" ingevoerd om evenwicht te brengen in gedrag
   van complexe getallen en hun complex geconjugeerde. */
/* Nog nodig: -n*i^iets -> n*-i^iets
              n*i*a+m*-i*a  -> (n-m)*i*a
   Goed doortesten !
*/


/* 24 april 1992: UNOPS uitgebreid met MINUS */
/* 26 april 1992: fct aangepast voor (a+b)^-n */
/* 24 maart 1993: function syntax veranderd:
   met FUNC defined oude stijl: foo = fun$(loc'(x,y,z),!arg);
   zonder FUNC define:          foo = x,y,z.!arg */

/* 30 juli 1993: structure:
   het is nu mogelijk om aan een expressie als naam=Bart een andere waarde
   toe te kennen. In feite wordt de rechter operand van de = operator
   stomweg vervangen door de nieuwe waarde, waardoor circulaire data-
   structuren mogelijk worden! BJO 4 Jan 1996

   voorbeeld:

   {?} x==(name=Bart).(age=40)
   {?} !x
   {!} =(name=Bart).(age=40)
   {?} !!x
   {!} Bart.40
   {?} !x:(=?naam.?leeftijd)
   {?} Bart Jongejan:?!naam
   {?} !!x
   {!} Bart Jongejan.40
   {?} x..age=veertig                          BJO 4 Jan 1996
   {?} !!x
   {!} Bart Jongejan.veertig

   x..name.first=Bart vervangt Jan door Bart in

   x==(name=(first=Jan).(family=Abbens)).(age=33)

   Merk op dat de = operator z'n speciale betekenis in patterns kwijt is
   ~=(% %) moet dus voortaan geschreven worden als ((% %) & `~|?)
*/


#define NL 0
#define ENG 1

#define TAAL ENG

#if 0 && defined __GNUC__ && !defined sparc && !defined __hpux && !defined __hpux__
/* TODO test must be changed to a positive list. Bart 20030704 */
#define ARM /*1*//* assume it's an Acorn */
#define os_swix os_swi /* different naming */
typedef struct {
 int r[10];
}os_regset;
#else
/*#define ARM 0*//* assume it isn't an Acorn */
#endif


#if defined __TURBOC__ || (defined ARM && !defined __SYMBIAN32__)
#define O_S 1 /* 1 = with operating system interface, 0 = without (RISC_OS or TURBO-C) */
#else
#define O_S 0
#endif

/* aanwijzingen voor het compileren
   (met een ANSI-C compiler of iets wat daar dichtbij in de buurt komt)

Archimedes ANSI-C release 3:
*up
*del. :0.$.c.clog
*spool :0.$.c.clog
*cc bracmat
*spool

Met RISC_OS functies:

cc bracmat

file cc (in directory c):

| >cc
up
delete $.c.clog
spool $.c.clog
cc -c %0 -IRAM:$.RISC_OSLib
if Sys$ReturnCode = 0 then run c.li %0 else spool

file li (in directory c):

| >li
link -o %0 o.%0 RAM:$.RISC_OSLib.o.RISC_OSLib RAM:$.Clib.o.Stubs
||G
spool
if Sys$ReturnCode = 0 then squeeze %0 else echo |G

ULTRIX v2.2 (of hoger) VAX C compiler
vcc bracmat.c

Microsoft QUICKC (MS-DOS) (compact en large model kunnen allebei)
qcl /Ox /AC /F D000 bracmat.c
Microsoft optimizing compiler V5.1
cl /Ox /AC /F D000 bracmat.c

Borland TURBOC (MS-DOS) V2.0
tcc -w -f- -r- -mc -K- bracmat

Atari : definieer -DATARI i.v.m. BIGENDIAN en extern int _stksize = -1;
               en -DW32   doch alleen als (int)==(long)
*/

/* optionele #defines voor debuggen en aanpassing aan machine */

/*#define TR 1      uitgebreide trace */
#define TELMAX 1 /* maximaal aantal gealloceerde nodes laten zien */
#define TELLING 0   /* idem,uitgebreid met huidige allocatie, per groep van
                       4,8,12 en >12 bytes */
/*#define reslt hreslt  om in resultaat ALLE haakjes te laten zien*/
#define INTSCMP 0   /* linke manier om strings te vergelijken */
#define ICPY 0      /* woord voor woord copieren, i.p.v. byte voor byte */

/* hieronder zijn geen optionele #defines meer */
#if defined __BYTE_ORDER && defined __LITTLE_ENDIAN /* gcc on linux defines these */
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define BIGENDIAN 0
#else
#define BIGENDIAN 1
#endif
#endif

#ifndef BIGENDIAN

#ifdef mc68000
#define BIGENDIAN 1
#endif

#ifdef mc68010
#define BIGENDIAN 1
#endif

#ifdef mc68020
#define BIGENDIAN 1
#endif

#ifdef mc68030
#define BIGENDIAN 1
#endif

#ifdef ATARI
#define BIGENDIAN     1
#endif

#ifdef MC68000
#define BIGENDIAN     1
#endif

#ifdef sparc
#define BIGENDIAN     1
#endif

#ifdef __hpux
#define BIGENDIAN     1
#endif

#ifdef __hpux__
#define BIGENDIAN     1
#endif

#endif

/* this would exclude gcc on Linux
#ifndef BIGENDIAN
#if defined ARM || defined _Windows || defined __MSDOS__ || defined _M_IX86 || defined __WIN32__ || defined _WIN32 || defined _M_I86
#define BIGENDIAN     0
#else
#define BIGENDIAN     1
#endif
#endif
*/

#ifndef BIGENDIAN
#define BIGENDIAN     0
#endif

#if (defined _Windows || defined _MT /*multithreaded, VC6.0*/)&& (!defined __CONSOLE__ || defined NOTCONSOLE || defined BRACMATEMBEDDED)
/* __CONSOLE__ seems always to be defined in C++Builder */
#define MICROSOFT_WINDOWS_API 1
#else
#define MICROSOFT_WINDOWS_API 0
#endif

#if MICROSOFT_WINDOWS_API && defined POLL /*Bart 20030410: Often no need for polling in multithreaded apps.*/
#define JMP 1 /* 1: listen to WM_QUIT message. 0: Do not listen to WM_QUIT message. */
#else
#define JMP 0
#endif

#if MICROSOFT_WINDOWS_API /* def ARM */
#include "bracmat.h"
#else
typedef struct startStruct
    {
    int (*WinIn)(void);
    void (*WinOut)(int c);
    void (*WinFlush)(void);
    } startStruct;
#endif

#if TELLING
#ifndef TELMAX
#define TELMAX 1
#endif
#endif

#ifdef vax /* vax vcc */
#define SIGNED_CHAR 1
#include <unistd.h> /* SEEK_SET, SEEK_CUR */
#define size_t int
#define clock_t long
#define fputc(x,p) putc(x,p)
#define SCHAR_MAX 127
#define W32 1
 typedef int ptrdiff_t;

#else  /* geen vax */
#if defined sun && !defined __GNUC__
#define SIGNED_CHAR 1
#include <unistd.h> /* SEEK_SET, SEEK_CUR */
#define ALERT 7
#define strtoul(a,b,c) strtol(a,b,c)
#else
#include <stddef.h>
#endif
#include <stdlib.h>
#endif

#ifndef ALERT
#define ALERT '\a'
#endif

#include <limits.h> /* o.a. voor INT_MAX en LONG_MAX, hieruit kan W32
                     afgeleid worden, mits deze #define's in ANSI-stijl zijn */

#if !defined W32
#if INT_MAX == LONG_MAX
#define W32 1
#else
#define W32 0
#endif
#endif

#if !W32     /* 20 Dec 1995 */
#if defined __TURBOC__ || defined __MSDOS__
#define MSDOS
#endif
#endif

#include <time.h>
#ifndef CLOCKS_PER_SEC
#ifdef CLK_TCK  /* pre-ANSI-C */
#define CLOCKS_PER_SEC CLK_TCK
#else
#if defined sun
#define CLOCKS_PER_SEC 1000000 /* ??? */
#endif
#endif
#endif

#ifndef SIGNED_CHAR
#define SIGNED_CHAR 0
#endif





#define LOGWORDLENGTH 2
/* vlaggen in knoop */
#define NOT              1      /* ~ */
     /* zo houden ivm vermenging logische en bit operatoren && || | ^ & */
#if OBJECTS
#define OBJECT      (1<< 1)
#endif
#define SUCCES          (1<< 2)
#define KLAAR           (1<< 3)
#define INDIRECT        (1<< 4) /* ! */
#define DUBBEL_INDIRECT (1<< 5) /* !! */
#define FENCE           (1<< 6) /* `   binnen 1 byte met ATOOM en NOT */
#define ATOOM           (1<< 7) /* @ */
#define NONIDENT        (1<< 8) /* % */
#define GROTER_DAN      (1<< 9) /* > */
#define KLEINER_DAN     (1<<10) /* < */
#define NUMBER          (1<<11) /* # */
#define BREUK           (1<<12) /* / */
#define UNIFY           (1<<13) /* ? */
#define IDENT           (1<<14)
#if COMPILE
#define RESOLVED        (1<<15) /* 12.10.1999 */
#endif
#define VISIBLE_FLAGS_NON_COMP   (INDIRECT|DUBBEL_INDIRECT|FENCE|ATOOM|NONIDENT|\
                        NUMBER|BREUK|UNIFY) /* allows < > ~< and ~> as flags on numbers */
#define VISIBLE_FLAGS_WEAK   (INDIRECT|DUBBEL_INDIRECT|FENCE|UNIFY) /* allows < > ~< and ~> as flags on numbers */
#define VISIBLE_FLAGS   (VISIBLE_FLAGS_NON_COMP|NOT|GROTER_DAN|KLEINER_DAN)

#if W32
#define RATIONAAL(psk) (((psk)->ops & (QGETAL|IS_OPERATOR|VISIBLE_FLAGS)) == QGETAL)
#define RATIONAAL_COMP(psk) (((psk)->ops & (QGETAL|IS_OPERATOR|VISIBLE_FLAGS_NON_COMP)) == QGETAL)
#define RATIONAAL_WEAK(psk) (((psk)->ops & (QGETAL|IS_OPERATOR|VISIBLE_FLAGS_WEAK)) == QGETAL)
#define       LESS(psk) (((psk)->flgs & (VISIBLE_FLAGS)) == KLEINER_DAN)
#define LESS_EQUAL(psk) (((psk)->flgs & (VISIBLE_FLAGS)) == (NOT|GROTER_DAN))
#define MORE_EQUAL(psk) (((psk)->flgs & (VISIBLE_FLAGS)) == (NOT|KLEINER_DAN))
#define       MORE(psk) (((psk)->flgs & (VISIBLE_FLAGS)) == GROTER_DAN)

#define GEHEEL(kn) (((kn)->ops & (QGETAL|QBREUK|IS_OPERATOR|VISIBLE_FLAGS)) == QGETAL)
#define GEHEEL_COMP(kn) (((kn)->ops & (QGETAL|QBREUK|IS_OPERATOR|VISIBLE_FLAGS_NON_COMP)) == QGETAL)

#define GEHEEL_NIET_NEG(kn) (((kn)->ops & (QGETAL|MINUS|QBREUK|IS_OPERATOR|VISIBLE_FLAGS))\
                                == QGETAL)
#define GEHEEL_NIET_NEG_COMP(kn) (((kn)->ops & (QGETAL|MINUS|QBREUK|IS_OPERATOR|VISIBLE_FLAGS_NON_COMP))\
                                == QGETAL)

#define GEHEEL_POS(kn) (((kn)->ops & (QGETAL|MINUS|QNUL|QBREUK|IS_OPERATOR|VISIBLE_FLAGS))\
                                == QGETAL)
#define GEHEEL_POS_COMP(kn) (((kn)->ops & (QGETAL|MINUS|QNUL|QBREUK|IS_OPERATOR|VISIBLE_FLAGS_NON_COMP))\
                                == QGETAL)

#define GEHEEL_NIET_NUL(kn) (((kn)->ops & (QGETAL|QNUL|QBREUK|IS_OPERATOR|VISIBLE_FLAGS))\
                                == QGETAL)
#define GEHEEL_NIET_NUL_COMP(kn) (((kn)->ops & (QGETAL|QNUL|QBREUK|IS_OPERATOR|VISIBLE_FLAGS_NON_COMP))\
                                == QGETAL)
#define HAS_MINUS_SIGN(kn) (((kn)->ops & (MINUS|IS_OPERATOR)) == MINUS)

#if OBJECTS
#define RAT_NUL(kn) (((kn)->flgs & (QNUL|IS_OPERATOR|OBJECT|VISIBLE_FLAGS)) == QNUL)
#define RAT_NUL_COMP(kn) (((kn)->flgs & (QNUL|IS_OPERATOR|OBJECT|VISIBLE_FLAGS_NON_COMP)) == QNUL)
#else
#define RAT_NUL(kn) (((kn)->flgs & (QNUL|IS_OPERATOR|VISIBLE_FLAGS)) == QNUL)
#define RAT_NUL_COMP(kn) (((kn)->flgs & (QNUL|IS_OPERATOR|VISIBLE_FLAGS_NON_COMP)) == QNUL)
#endif
#define RAT_NEG(kn) (((kn)->ops & (QGETAL|MINUS|IS_OPERATOR|VISIBLE_FLAGS)) \
                                == (QGETAL|MINUS))
#define RAT_NEG_COMP(kn) (((kn)->ops & (QGETAL|MINUS|IS_OPERATOR|VISIBLE_FLAGS_NON_COMP)) \
                                == (QGETAL|MINUS))

#define RAT_RAT(kn) (((kn)->ops & (QGETAL|QBREUK|IS_OPERATOR|VISIBLE_FLAGS))\
                                == (QGETAL|QBREUK))

#define RAT_RAT_COMP(kn) (((kn)->ops & (QGETAL|QBREUK|IS_OPERATOR|VISIBLE_FLAGS_NON_COMP))\
                                == (QGETAL|QBREUK))
#if COMPILE
#define IS_EEN(kn) (PIOBJ(kn) == EEN && !((kn)->ops & (MINUS | VISIBLE_FLAGS)))
#else
#define IS_EEN(kn) ((kn)->u.iobj == EEN && !((kn)->ops & (MINUS | VISIBLE_FLAGS)))
#endif
#if OBJECTS
#define IS_OBJECT_REF(kn) (((kn)->flgs & \
            (OBJECT|QGETAL|MINUS|QBREUK|IS_OPERATOR)) == (OBJECT|QGETAL))
#endif
#else /* !W32 */
#define RATIONAAL(psk) ((((psk)->ops & (QGETAL|IS_OPERATOR)) == QGETAL) \
                         && (((psk)->flgs & VISIBLE_FLAGS) == 0))
#define RATIONAAL_COMP(psk) ((((psk)->ops & (QGETAL|IS_OPERATOR)) == QGETAL) \
                         && (((psk)->flgs & VISIBLE_FLAGS_NON_COMP) == 0))
#define RATIONAAL_WEAK(psk) ((((psk)->ops & (QGETAL|IS_OPERATOR)) == QGETAL) \
                         && (((psk)->flgs & VISIBLE_FLAGS_WEAK) == 0))
#define       LESS(psk) (((psk)->flgs & (VISIBLE_FLAGS)) == KLEINER_DAN)
#define LESS_EQUAL(psk) (((psk)->flgs & (VISIBLE_FLAGS)) == (NOT|GROTER_DAN))
#define MORE_EQUAL(psk) (((psk)->flgs & (VISIBLE_FLAGS)) == (NOT|KLEINER_DAN))
#define       MORE(psk) (((psk)->flgs & (VISIBLE_FLAGS)) == GROTER_DAN)

#define GEHEEL(kn) ((((kn)->ops & (QGETAL|QBREUK|IS_OPERATOR)) == QGETAL) \
                         && (((kn)->flgs & VISIBLE_FLAGS) == 0))
#define GEHEEL_COMP(kn) ((((kn)->ops & (QGETAL|QBREUK|IS_OPERATOR)) == QGETAL) \
                         && (((kn)->flgs & VISIBLE_FLAGS_NON_COMP) == 0))

#define GEHEEL_NIET_NEG(kn) ((((kn)->ops & (QGETAL|MINUS|QBREUK|IS_OPERATOR))\
                                == QGETAL) \
                         && (((kn)->flgs & VISIBLE_FLAGS) == 0))
#define GEHEEL_NIET_NEG_COMP(kn) ((((kn)->ops & (QGETAL|MINUS|QBREUK|IS_OPERATOR))\
                                == QGETAL) \
                         && (((kn)->flgs & VISIBLE_FLAGS_NON_COMP) == 0))

#define GEHEEL_POS(kn) ((((kn)->ops & (QGETAL|MINUS|QNUL|QBREUK|IS_OPERATOR))\
                                == QGETAL) \
                         && (((kn)->flgs & VISIBLE_FLAGS) == 0))
#define GEHEEL_POS_COMP(kn) ((((kn)->ops & (QGETAL|MINUS|QNUL|QBREUK|IS_OPERATOR))\
                                == QGETAL) \
                         && (((kn)->flgs & VISIBLE_FLAGS_NON_COMP) == 0))

#define GEHEEL_NIET_NUL(kn) ((((kn)->ops & (QGETAL|QNUL|QBREUK|IS_OPERATOR))\
                                == QGETAL) \
                         && (((kn)->flgs & VISIBLE_FLAGS) == 0))
#define GEHEEL_NIET_NUL_COMP(kn) ((((kn)->ops & (QGETAL|QNUL|QBREUK|IS_OPERATOR))\
                                == QGETAL) \
                         && (((kn)->flgs & VISIBLE_FLAGS_NON_COMP) == 0))
#define HAS_MINUS_SIGN(kn) ((((kn)->ops & (MINUS|IS_OPERATOR)) == MINUS))

#if OBJECTS
#define RAT_NUL(kn) ((((kn)->ops & (QNUL|IS_OPERATOR)) == QNUL) \
                             && (((kn)->flgs & (OBJECT|VISIBLE_FLAGS)) == 0))
#define RAT_NUL_COMP(kn) ((((kn)->ops & (QNUL|IS_OPERATOR)) == QNUL) \
                             && (((kn)->flgs & (OBJECT|VISIBLE_FLAGS_NON_COMP)) == 0))
#else
#define RAT_NUL(kn) ((((kn)->ops & (QNUL|IS_OPERATOR)) == QNUL) \
                             && (((kn)->flgs & (VISIBLE_FLAGS)) == 0))
#define RAT_NUL_COMP(kn) ((((kn)->ops & (QNUL|IS_OPERATOR)) == QNUL) \
                             && (((kn)->flgs & (VISIBLE_FLAGS_NON_COMP)) == 0))
#endif
#define RAT_NEG(kn) ((((kn)->ops & (QGETAL|MINUS|IS_OPERATOR)) \
                                == (QGETAL|MINUS))\
                         && (((kn)->flgs & VISIBLE_FLAGS) == 0))
#define RAT_NEG_COMP(kn) ((((kn)->ops & (QGETAL|MINUS|IS_OPERATOR)) \
                                == (QGETAL|MINUS))\
                         && (((kn)->flgs & VISIBLE_FLAGS_NON_COMP) == 0))

#define RAT_RAT(kn) ((((kn)->ops & (QGETAL|QBREUK|IS_OPERATOR))\
                                == (QGETAL|QBREUK))\
                         && (((kn)->flgs & VISIBLE_FLAGS) == 0))
#define RAT_RAT_COMP(kn) ((((kn)->ops & (QGETAL|QBREUK|IS_OPERATOR))\
                                == (QGETAL|QBREUK))\
                         && (((kn)->flgs & VISIBLE_FLAGS_NON_COMP) == 0))

#define IS_EEN(kn) (((kn)->u.iobj == EEN && !((kn)->ops & MINUS))\
                         && (((kn)->flgs & VISIBLE_FLAGS) == 0))
#if OBJECTS
#define IS_OBJECT_REF(kn) (((kn)->flgs & OBJECT) && GEHEEL_NIET_NEG(kn))
#endif
#endif


#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>

#if INTSCMP
#define STRCMP(a,b) intscmp((long*)(a),(long*)(b))
#else
#define STRCMP(a,b) strcmp((char*)(a),(char*)(b))
#endif
#if ICPY
#define MEMCPY(a,b,n) icpy((long*)(a),(long*)(b),n)
#else
#if 1
#define MEMCPY(a,b,n) memcpy((char*)(a),(char*)(b),n)
#else
void * MEMCPY(void * a,void * b,int n)
    {

    int i;
    char * A = (char *)a;
    char * B = (char *)b;
    for(i = 0;i < n;++i)
        {
/*        A[i] = B[i];*/
        /*if(isprint(B[i]))*/
            printf("%c",B[i]);
        /*else
            printf(".");*/
        }
    printf("\n");
    return memcpy(a,b,n);
    /*return a;*/
    }
#endif
#endif

#ifdef ATARI
extern int _stksize = -1;
#endif

#if defined ARM
#if O_S /*20010827, was #ifdef O_S */
#if defined __GNUC__ && !defined sparc
#include "sys/os.h"
#else
#include "os.h"
#endif
#endif
#endif

#if W32
#define SHL 16
#define ops flgs
#else
#define SHL 0
#ifdef MSDOS
#include <dos.h>
#endif
#ifdef __TURBOC__
extern unsigned int _stklen = /*0xA000U;*/0xFF00U;
#endif
#endif
#ifdef __TURBOC__ /* moved out of above #else 20 Dec 1995 */
#if O_S
typedef struct
    {
    int r[10];
    } os_regset;
#endif
#endif

#define RECHTS u.p.rechts
#define LINKS  u.p.links
#define TRUE 1
#define FALSE 0
#define ONCE (1<<4)
/*#define DONOTSHORTEN (1<<5) *//* 32 */
    /*  wordt gezet door match(sub,pat,snijaf).
        Aan : doe geen pogingen om pat met een andere sub te matchen
    */
#if COMPILE
#if MACRO
#define IS_RESOLVED(p) ((p)->flgs & RESOLVED)
#define RESOLVE(p,navar) ((p)->flgs |= RESOLVED, (p)->u.var = navar, navar->Refcount++)
#define RESOLUTION(p) (((p)->u.var))
#define RIS_RESOLVED(p) ((p).flgs & RESOLVED)
        /*#define RRESOLVE(p,navar) ((p).flgs |= RESOLVED, (p).u.var = navar)*/
#define RRESOLUTION(p) (((p).u.var))
#ifdef PVNAME
#define OBJ(p) (RIS_RESOLVED(p) ? (RRESOLUTION(p)->vname) : &((p).u.Obj))
            /*#define ROBJ(p) (RIS_RESOLVED(p) ? *(RRESOLUTION(p)->name) : ((p).u.Obj))*/
#define POBJ(p) (IS_RESOLVED(p) ? (RESOLUTION(p)->vname) : &((p)->u.Obj))
#define RPOBJ(p) (IS_RESOLVED(p) ? *(RESOLUTION(p)->vname) : ((p)->u.Obj))
#define PIOBJ(p) (IS_RESOLVED(p) ? *(int*)(RESOLUTION(p)->vname) : ((p)->u.Iobj))
#define PLOBJ(p) (IS_RESOLVED(p) ? *(long*)(RESOLUTION(p)->vname) : ((p)->u.Lobj))
#else
#define OBJ(p) (RIS_RESOLVED(p) ? &(RRESOLUTION(p)->u.Obj) : &((p).u.Obj))
#define LOBJ(p) (RIS_RESOLVED(p) ? (RRESOLUTION(p)->u.Lobj) : ((p).u.Lobj))
            /*#define ROBJ(p) (RIS_RESOLVED(p) ? *(RRESOLUTION(p)->name) : ((p).u.Obj))*/
#define POBJ(p) (IS_RESOLVED(p) ? &(RESOLUTION(p)->u.Obj) : &((p)->u.Obj))
#define RPOBJ(p) (IS_RESOLVED(p) ? (RESOLUTION(p)->u.Obj) : ((p)->u.Obj))
#define PIOBJ(p) (IS_RESOLVED(p) ? (RESOLUTION(p)->u.Iobj) : ((p)->u.Iobj))
#define PLOBJ(p) (IS_RESOLVED(p) ? (RESOLUTION(p)->u.Lobj) : ((p)->u.Lobj))
#endif
#endif
#else
#define OBJ(p) &((p).u.obj)
#define LOBJ(p) ((p).u.lobj)
#define POBJ(p) &((p)->u.obj)
#define PIOBJ(p) ((p)->u.iobj) /* Added. Bart 20031110 */
#define PLOBJ(p) ((p)->u.lobj)
#endif

#define QOBJ(p) &(p)
#define QPOBJ(p) p

#if BIGENDIAN
#define iobj lobj
#define O(a,b,c) (a*0x1000000L+b*0x10000L+c*0x100)
#else
#define O(a,b,c) (a+b*0x100+c*0x10000L)
#endif

#if TELMAX
#define BEZ O('b','e','z')
#endif

#if O_S && !defined __WIN32__
#define SWI O('s','w','i')
#endif
#define ALC O('a','l','c')
#define APP O('A','P','P')
#define ASC O('a','s','c')
#define CHR O('C','H','R')
#define CLK O('c','l','k')
#define CON O('C','O','N')
#define CUR O('C','U','R')
#define DBG O('d','b','g')
#define DEC O('D','E','C')
#define DEN O('d','e','n')
#define DIV O('d','i','v')
#define DOS O('D','O','S')
#define ECH O('E','C','H')
#define EEN O('1', 0 , 0 )
#define END O('E','N','D')/*SEEK_END hoeft niet te werken voor binary file !!*/
/*#define ERR O('e','r','r')*/
#define EXT O('E','X','T')
#define FIL O('f','i','l')
#define FRE O('f','r','e')
#define FNC O('f','n','c')
#define GET O('g','e','t')
/*#define HUM O('H','U','M')*/
#define IM  O('i', 0 , 0 )
#define KAR O('c','h','r')
#define LIN O('L','I','N')
#define LOW O('l','o','w')
#define LST O('l','s','t')
#define MEM O('M','E','M')
#define MINEEN O('-','1',0)
#define MMF O('m','e','m')
#define MOD O('m','o','d')
#define NEW O('N','E','W')
#define New O('n','e','w')
#define NULLE O('0',0 , 0 )
#define PEE O('p','e','e')
#define PI  O('p','i', 0 )
#define POK O('p','o','k')
#define PUT O('p','u','t')
#define PRV O('?', 0 , 0 )
#define REN O('r','e','n') /* 20001213, rename a file */
#define SET O('S','E','T')
#define STR O('s','t','r')
#define STRt O('S','T','R')
#define SYS O('s','y','s')
#define SIM O('s','i','m')
#define STG O('S','T','R')
#if 0
#define SYM O('s','y','m')
#endif
#define TBL O('t','b','l')
#define TEL O('T','E','L')
#define TWEE O('2', 0 , 0 )
#define TXT O('E','X','P')
#define UPP O('u','p','p')
#define VAP O('V','A','P')
#define XX  O('e', 0 , 0 )

#define REF_COUNT_BITS 6 /* 6 - 15 , 8 - 11 is heel mooi */

#define FILTERS (BREUK | NUMBER | KLEINER_DAN | GROTER_DAN | NONIDENT | ATOOM)
#define ATOMFILTERS (BREUK | NUMBER | KLEINER_DAN | GROTER_DAN | ATOOM | FENCE | IDENT)
#define SATOMFILTERS (/*ATOOM | */FENCE | IDENT)

#define FLGS (FILTERS | FENCE | DUBBEL_INDIRECT | INDIRECT)

#define ONTKENNING(flgs,flag)  ((flgs & NOT ) && \
                                (flgs & FLGS) >= (flag) && \
                                (flgs & FLGS) < ((flag) << 1))
#define FAAL (pat->flgs & NOT)
#define NIKS(p) ((p)->flgs & NOT && !((p)->flgs & FILTERS))

#define ERFENIS (GROTER_DAN|KLEINER_DAN|FENCE/*|OBJECT*/)
#if W32
#define UNOPS (UNIFY | FLGS | NOT | MINUS)
#define HAS_UNOPS(a) ((a)->flgs & UNOPS)
#else
#define UNOPS (UNIFY | FLGS | NOT)
#define HAS_UNOPS(a) ((a)->flgs & UNOPS || (a)->ops & MINUS)
#endif
#define HAS__UNOPS(a) (is_op(a) && (a)->flgs & (UNIFY | FLGS | NOT))
#define IS_VARIABLE(a) (/*is_op(a) && 19970831*/ (a)->flgs & (UNIFY | INDIRECT | DUBBEL_INDIRECT))

typedef int Boolean;
typedef struct Vars vars;

typedef struct sk
    {
#if W32
    unsigned int flgs;
#else
    unsigned int flgs;
    unsigned int ops;
#endif
    union
        {
        struct
            {
            struct sk *links,*rechts;
            } p;
#if COMPILE
        long Lobj;
#if !BIGENDIAN
        int  Iobj;
#endif
        unsigned char Obj;
        vars * var;
#else
        long lobj;
#if !BIGENDIAN
        int  iobj; /* This part of the structure can be used for comparisons
                      with short strings that fit into 2 bytes in one machine
                      operation, like "\0\0" or "1\0" */
#endif
        unsigned char obj;
#endif
        } u;
    } sk;

static sk nilk,nulk,eenk,argk,selfkn,Selfkn,mintweek,mineenk,tweek,vierk;/*diek,*/

typedef sk *psk;

static psk adr[7],m0 = NULL,m1 = NULL,
f0 = NULL,f1 = NULL,f4 = NULL,f5 = NULL
#if SLOWPLUS
,f6 = NULL
#endif
/*,f7 = NULL*/
;

typedef psk *ppsk;
typedef struct ngetal
    {
    int sign;
    ptrdiff_t length;
#if COMPILE
    char *alloc;
#else
    void *alloc;
#endif
    char *number;
    } ngetal;

#define Qgetal psk

typedef struct varia
    {
    struct varia *prev; /* verdi[-1] */
    psk verdi[1];       /* verdi[0], arraysize wordt door psh aangepast */
    } varia;

#if 0
typedef struct /*vars*/ /* sizeof(vars) = n * 4 bytes */
    {
    unsigned char *name;
    struct vars *next;
    int n;
    int selector;
    varia *pvaria; /* kan ook entry[0] bevatten (als n == 0) */
    } vars;
#endif

#if COMPILE
struct Vars /* sizeof(vars) = n * 4 bytes */
    {
    unsigned long Refcount;
    int n;
    int selector;
    vars *Prev;
    vars *next;
    varia *pvaria; /* kan ook entry[0] bevatten (als n == 0) */
#ifdef PVNAME
    unsigned char *vname;
#else
    union
        {
        long Lobj;
#if !BIGENDIAN
        int  Iobj;
#endif
        unsigned char Obj;
        } u;
#endif
    };
#else
struct Vars /* sizeof(vars) = n * 4 bytes */
    {
#ifdef PVNAME
    unsigned char *vname;
#endif
    vars *next;
    int n;
    int selector;
    varia *pvaria; /* kan ook entry[0] bevatten (als n == 0) */
#ifdef PVNAME
/*    unsigned char *vname;*/
#else
    union
        {
        long Lobj;
#if !BIGENDIAN
        int  Iobj;
#endif
        unsigned char Obj;
        } u;
#endif
    };
#endif
/*typedef struct Vars vars;*/

static vars *variabelen[256];

typedef struct kknoop
    {
#if W32
    unsigned long flgs;
#else
    unsigned short flgs;
    unsigned short ops;
#endif
    psk links,rechts;
    } kknoop;

typedef struct objectknoop /* createdWithNew == 0 */
    {
#if W32
    unsigned long flgs;
#else
    unsigned short flgs;
    unsigned short ops;
#endif
    psk links,rechts;
#if W32
    unsigned int refcount : 30;
    unsigned int built_in:1;
    unsigned int createdWithNew:1;
#else
    unsigned long refcount;
#endif
    } objectknoop;

/*typedef typedObjectknoop;*/
typedef enum    {function_fail
                ,built_in_function_ok
                ,user_function_ok
                ,user_object_method_ok
                ,builtin_object_builtin_method_ok
                ,builtin_object_user_method_ok
                } function_return_type;
struct typedObjectknoop;
typedef function_return_type (*method_pnt)(struct typedObjectknoop * This,ppsk pkn);

typedef struct method
    {
    char * name;
    method_pnt func;
    } method;

#ifdef OBJECTDATA
typedef struct objectdata
    {
    void * vdata;
    long refcount; /* a typedObjectknoop is copied shallowly, no copy of the data is made.
                      Therefore, a referencecounter is needed on the data. */
    } objectdata;
#endif
/*
typedef union method_or_data
    {
    method m;
    objectdata d;
    } method_or_data;
*/
typedef struct /**/ typedObjectknoop /**//* createdWithNew == 1 */
    {
#if W32
    unsigned long flgs;
#else
    unsigned short flgs;
    unsigned short ops;
#endif
    psk links,rechts; /* links == nil, rechts == data (if vtab == NULL)
            or name of object type, e.g. [set], [hash], [file], [float] (if vtab != NULL)*/
#if W32
    unsigned int refcount : 30;
    unsigned int built_in:1;
    unsigned int createdWithNew:1;
#else
    unsigned long refcount;
#endif
#ifdef OBJECTDATA
    objectdata * data;
#else
    void * voiddata;
#endif
    method * vtab; /* The last element n of the array must have vtab[n].name == NULL */
    } typedObjectknoop;

#if W32
#define INCREFCOUNT(a) (a)->refcount++
#define DECREFCOUNT(a) (a)->refcount--
#define REFCOUNTNONZERO(a) ((a)->refcount)
#define ISBUILTIN(a) ((a)->built_in)
#define SETBUILTIN(a) (a)->built_in = 1
#define UNSETBUILTIN(a) (a)->built_in = 0
#define ISCREATEDWITHNEW(a) ((a)->createdWithNew)
#define SETCREATEDWITHNEW(a) (a)->createdWithNew = 1
#define UNSETCREATEDWITHNEW(a) (a)->createdWithNew = 0
#else
#define INCREFCOUNT(a) (a)->refcount += 4
#define DECREFCOUNT(a) (a)->refcount -= 4
#define REFCOUNTNONZERO(a) ((a)->refcount & ~3)
#define ISBUILTIN(a) ((a)->refcount & 2)
#define SETBUILTIN(a) (a)->refcount |= 2
#define UNSETBUILTIN(a) (a)->refcount &= ~2
#define ISCREATEDWITHNEW(a) ((a)->refcount & 1)
#define SETCREATEDWITHNEW(a) (a)->refcount |= 1
#define UNSETCREATEDWITHNEW(a) (a)->refcount &= ~1
#endif

#ifndef BRACMATEMBEDDED
static char * errorFileName = NULL;
static FILE * errorStream = NULL;
#endif

typedef struct filehendel
    {
    char *naam;
    FILE *fp;
    long filepos; /* Normally -1. If >= 0, then the file is closed.
                When reopening, filepos is used to find the position
                before the file was closed. */
    long mode;
    long type;
    long size;
    long getal;
    long tijd;
    int written;
    struct filehendel *next;
    char * stop; /* contains characters to stop reading at, default "\n" */
    } filehendel;

static filehendel *fh0 = NULL;

typedef long refCountType;

typedef struct indexType
    {
    long offset;
    refCountType refCnt;
    size_t size;
    } indexType;

typedef struct handleType
    {
    long number;
    char *fileName;
    } handleType;

typedef struct objectType
    {
    handleType handle;
    refCountType refCnt;
    long offset;
    psk obj;
    long size;
    } objectType;

#define NOT_STORED -1L

typedef struct freeStoreType
    {
    long nextFree;
    long size;
    } freeStoreType;

/*       operator                 eindknoop           optab       note
flgs 0                   NOT
     1                  OBJECT                                    if OBJECTS is defined
     2                  SUCCES
     3                  KLAAR
     4                 INDIRECT
     5              DUBBEL_INDIRECT
     6                  FENCE
     7                  ATOOM
     8                 NONIDENT
     9                GROTER_DAN
    10                KLEINER_DAN
    11                  NUMBER
    12                  BREUK
    13                  UNIFY
    14                  IDENT
    15                 RESOLVED                                   if COMPILE is defined
ops 16  0             IS_OPERATOR
    17  1   (operatoren 0-14)     QGETAL
    18  2       "                 MINUS
    19  3       "                 QNUL
    20  4       "                 QBREUK
    21  5             LATEBIND                        NOOP
    22  6          (reference count)
    23  7                 "
    24  8                 "
    25  9                 "
    26 10                 "
    27 11                 "
    28 12                 "
    29 13                 "
    30 14                 "
    31 15                 "
*/

#define OPSH (SHL+1)
#define IS_OPERATOR (1 << SHL)
#define WORDT   ((0<<OPSH) + IS_OPERATOR)
#define DOT     ((1<<OPSH) + IS_OPERATOR)
#define KOMMA   ((2<<OPSH) + IS_OPERATOR)
#define OF      ((3<<OPSH) + IS_OPERATOR)
#define EN      ((4<<OPSH) + IS_OPERATOR)
#define MATCH   ((5<<OPSH) + IS_OPERATOR)
#define LUCHT   ((6<<OPSH) + IS_OPERATOR)
#define PLUS    ((7<<OPSH) + IS_OPERATOR)
#define MAAL    ((8<<OPSH) + IS_OPERATOR)
#define EXP     ((9<<OPSH) + IS_OPERATOR)
#define LOG     ((10<<OPSH) + IS_OPERATOR)
#define DIF     ((11<<OPSH) + IS_OPERATOR)
#define FUU     ((12<<OPSH) + IS_OPERATOR)
#define FUN     ((13<<OPSH) + IS_OPERATOR)
#define STREEP  ((14<<OPSH) + IS_OPERATOR) /* dummy */

static const psk knil[16] =
{NULL,NULL,NULL,NULL,NULL,NULL,&nilk,&nulk,
&eenk,NULL,NULL,NULL,NULL,NULL,NULL,NULL};

static const char opchar[16] =
{'=','.',',','|','&',':',' ','+','*','^','\016','\017','\'','$','_','?'};

#define OPERATOR ((15<<OPSH) + IS_OPERATOR)

#define kop(kn) ((kn)->ops & OPERATOR) /*No test is_op(kn) is needed before using kop(kn)*/
#define is_op(kn) ((kn)->ops & IS_OPERATOR)
#define is_object(kn) (((kn)->ops & (IS_OPERATOR|OPERATOR)) == \
                                    (IS_OPERATOR|WORDT))
#define klopcode(kn) (kop(kn) >> OPSH)

#define nil(p) knil[klopcode(p)]


#define NOOP    (OPERATOR+1)
#define QGETAL  (1 << (SHL+1))
#define MINUS   (1 << (SHL+2))
#define QNUL    (1 << (SHL+3))
#define QBREUK  (1 << (SHL+4))
#define LATEBIND (1 << (SHL+5))
#define EENKEER (1 << (SHL+REF_COUNT_BITS))

#define LAGEROP (1<<OPSH)

#define OPGEBRUIKT \
       ((((unsigned int)(~0)) >> (SHL+REF_COUNT_BITS)) << (SHL+REF_COUNT_BITS))

#ifdef __SYMBIAN32__
#define KILOKNOPEN    10L
#else
#if W32
#if 0 /* def __CONSOLE__*/
#define KILOKNOPEN    6000  /* 10 -> 10000 18 Maart 1997 (Windows 95 CONSOLE)*/
#else
#if defined ARM
#define KILOKNOPEN    10 /* 10 -> 100 21 Aug 1996 (Windows 95)*/
#else
#define KILOKNOPEN    1000 /* 10 -> 100 21 Aug 1996 (Windows 95)*/
#endif
#endif
#else
#define KILOKNOPEN    12L  /*denk om 64K grens per gealloceerd blok in MS-DOS*/
#endif
#endif

#ifdef __CONSOLE__
#define PROMILLAGE4   20L
#define PROMILLAGE8  290L
#define PROMILLAGE12 400L
#define PROMILLAGE16 250L
#define PROMILLAGE20  20L
#define PROMILLAGE24  20L
#else
#if 0
#define PROMILLAGE4   20L  /* 10 *  20 *  4 =   800 */
#define PROMILLAGE8  435L  /* 10 * 420 *  8 = 34800 */
#define PROMILLAGE12 545L  /* 10 * 530 * 12 = 65400  (  < 65536 ) */
                               /*              + 101000 */
#else
#define PROMILLAGE4   40L  /* 12 *  40 *  4 =  1920 */
#define PROMILLAGE8  320L  /* 12 * 320 *  8 = 30720 */
#define B24
#ifdef B24
#define PROMILLAGE12 300L
#define PROMILLAGE16 300L
                                       /*              + 207360 */
#define PROMILLAGE20  10L
#define PROMILLAGE24  30L
#else
#define PROMILLAGE12 320L  /* 12 * 320 * 12 = 46080  (  < 65536 ) */
#define PROMILLAGE16 320L  /* 12 * 320 * 16 = 61440  (  < 65536 ) */
                                       /*              + 207360 */
#define PROMILLAGE20   0L
#define PROMILLAGE24   0L
#endif
#endif
#endif

#define dubbelgebruikt(kn) ((kn)->ops & OPGEBRUIKT)

#if 0
#define opgebruikt(kn) (dubbelgebruikt(kn) == OPGEBRUIKT)
#define incgebruik(kn) ((kn)->ops += EENKEER)
#define decgebruik(kn) ((kn)->ops -= EENKEER)
#else
static int opgebruikt(psk kn)
{
return dubbelgebruikt(kn) == OPGEBRUIKT && !is_object(kn);
}

static void incgebruik(psk kn)
{
if(dubbelgebruikt(kn) == OPGEBRUIKT) /* ensure that this can only be the case
                                        for objectknoop nodes, i.e. test
                                        with opgebruikt before calling
                                        incgebruik. */
    INCREFCOUNT((objectknoop*)kn);
else
    (kn)->ops += EENKEER;
}

static void decgebruik(psk kn)
{
if(is_object(kn)
&& REFCOUNTNONZERO((objectknoop*)kn))
    {
    DECREFCOUNT((objectknoop*)kn);
    }
else
    (kn)->ops -= EENKEER;
}
#endif

/*
#define new_operator_like(kn) (psk)bmalloc(kop(kn) == WORDT ? sizeof(objectknoop) : sizeof(kknoop))
*/

#define STRING    1
#define VAPORIZED 2
#define MEMORY    4
#define ECHO      8

#include <stdarg.h>
static va_list ap;
static unsigned char *startPos;

static const char
hekje1[] = "\1",
hekje5[] = "\5",
hekje6[] = "\6",
onbal[] =
#if TAAL == NL
"ongebalanceerde",
#else
"unbalanced",
#endif
#if 0
 "(m=fun$(loc'(l,r),B$!arg:?arg:%+%:?+?*((~=%+%)^(#<0*?):?l)*?+?&"
 "(m=fun$(loc'(l,r),!arg:%+%:?+?*((~=%+%)^(#<0*?):?l)*?+?&"
  "!l*m$(1+!l^-1*!arg+-1)|w$!arg))&"
#endif
#if 0
 "(B=fun$(loc'(p,q,e,s,r,l),!arg:%?p+%?q&"
  "!p:?*(%+%:?s)^?e*(?&N$!q&!e:#)&!s^(-1*!e):?s&!s^-1*B$(!s*!p+k$!q)|!arg))&"
 "(N=fun$(!arg:(0|?*!s^((#>!e|?&!e:~#):?e|?)*?+?arg&!n)))&"
 "(n=0:?r&"
  "!arg:%+%:?+?*((%+%)^((>!r|?&!r:0):?r):?l&~)*?+?|0:!r&!arg|!l*k$!arg)&"
#endif

fct[] = "(fct=((m,w,b,Z,f,T,v,X,B,N,n,k)."
 "(k=(p.!arg:%?p+?arg&!s*!p+k$!arg|!arg))&"
 "(f=((l,r,S).!arg:(?arg,?S)&Z$(v$(m$!arg:?arg:%+%))|"
  "!arg:%?l*%?r&f$(!l,!S)*f$(!r,!S)|!arg:%?l^%?r&f$(!l,!S)^f$(!r,!S)|!arg))&"
 "(b=(U.!arg:%?U %?arg&!U+b$!arg|!arg))&"
 "(v=(U.!arg:%?U+%?arg&!U v$!arg|!arg))&"
 "(m=((l,r).!arg:%+%:?+?*(?^(#<0*?):?l)*?+?&"
  "!l*m$(1+!l^(-1*+-1)*(1+!l^*!arg+-1)+-1)|w$!arg))&"
 "(w=((l,r).!arg:#%?l*?+%&!l*w$(1+!l^-1*!arg+-1)|!arg))&"
 "(Z=((C,E,G,H,O,P,p,s,q,r,x,t,u,X,Q,R)."
  "!arg:((|1):?E) %?G ?H %?`O (?P&b$!G:?p*(?x^?t|~#%?`x&1:?t)*(?q&"
  "!O:?s*(!x^?u|`!x&1:?u)*(?r&(!E (!P:?Q (?*(!x^?|!x)*?:?X) ?R&"
#if 0
  "!T !X !R !H !Q|!P !H !T):?C:(~=% %)|Z$!C:?C|!S:0&b$!C:?C))))&!C))&"
#else
  "!T !X !R !H !Q|!P !H !T):?C:(% %&`~|?)|Z$!C:?C|!S:0&b$!C:?C))))&!C))&"
#endif
 "(T=!x^!u*f$(!p*!x^(!t+-1*!u)*!q+!s*!r,!S+1))&"
 "f$(!arg,0)))";

typedef struct deelres
    {
    ngetal quot;
    ngetal rest;
    } deelres;







typedef struct byte4
    {
    union
        {
        struct byte4 *p;
        unsigned long f;
        } u;
    } byte4;

static byte4 *p4,*p4start,*p4end;

typedef struct byte8
    {
    union
        {
        struct byte8 *p;
        unsigned long f;
        } u;
    long rest;
    } byte8;

static byte8 *p8,*p8start,*p8end;

typedef struct byte12
    {
    union
        {
        struct byte12 *p;
        unsigned long f;
        } u;
    long rest1;
    long rest2;
    } byte12;

static byte12 *p12,*p12start,*p12end;

typedef struct byte16
    {
    union
        {
        struct byte16 *p;
        unsigned long f;
        } u;
    long rest1;
    long rest2;
    long rest3;
    } byte16;

static byte16 *p16,*p16start,*p16end;

#ifdef _4_5
typedef struct byte20
    {
    union
        {
        struct byte20 *p;
        unsigned long f;
        } u;
    long rest1;
    long rest2;
    long rest3;
    long rest4;
    } byte20;

static byte20 *p20,*p20start,*p20end;

typedef struct byte24
    {
    union
        {
        struct byte24 *p;
        unsigned long f;
        } u;
    long rest1;
    long rest2;
    long rest3;
    long rest4;
    long rest5;
    } byte24;

static byte24 *p24,*p24start,*p24end;
#endif

static size_t telling = 0;

/*ptrdiff_t xlengte,ylengte;*/

static long
#ifdef TELMAX
globalloc = 0,
maxgloballoc = 0;
#endif
#if TELLING
static long
alloc_cnt = 0,
cnts[256],
totcnt = 0;
#endif
static long
al4 = PROMILLAGE4*KILOKNOPEN,
al8 = PROMILLAGE8*KILOKNOPEN,
al12 = PROMILLAGE12*KILOKNOPEN,
al16 = PROMILLAGE16*KILOKNOPEN
#ifdef _4_5
,
al20 = PROMILLAGE20*KILOKNOPEN,
al24 = PROMILLAGE24*KILOKNOPEN
#endif
;

static int
carry,
hum = 1,
mooi = TRUE,
optab[256],
dummy_op = LUCHT,
dummy_flgs = 0, /* Bart 20021215 */
debug = 0;

#ifdef TELMAX
static unsigned int maxbez=0;
#endif

static FILE
*fpi,
*fpo;

static const char quote[256] = {
/*
   1 : quote if first character;
   3 : quote always
   4 : quote if \t and \n must be expanded
*/
0,0,0,0,0,0,0,0,0,4,4,0,0,0,3,3, /* \L \D */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3,1,0,1,3,1,3,3,3,3,3,3,3,1,3,1, /* SP ! # $ % & ' ( ) * + , - . / */
0,0,0,0,0,0,0,0,0,0,3,3,1,3,1,1, /* : < = > ? */
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* @ */
0,0,0,0,0,0,0,0,0,0,0,1,3,1,3,3, /* [ \ ] ^ _ */
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ` */
0,0,0,0,0,0,0,0,0,0,0,3,3,3,1,0};/* { | } ~ */

#define LATIN_1
#ifdef LATIN_1 /* ISO8859 *//* NOT DOS compatible! */
static const unsigned char lowerEquivalent[256] =
{
      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
     16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
    ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
    '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_',
    '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 127,
    128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
    144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
    160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
    176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
    224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
    240, 241, 242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223 /*ringel s*/,
    224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
    240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
};

static const unsigned char upperEquivalent[256] =
{
      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
     16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
    ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
    '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 127,
    128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
    144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
    160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
    176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
    192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
    208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
    192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
    208, 209, 210, 211, 212, 213, 214, 247, 216, 217, 218, 219, 220, 221, 222, 255 /* ij */
};
#endif


static unsigned char ISO8859toCodePage850(unsigned char kar)

{
    static unsigned char translationTable[] =
    {
    0xBA,0xCD,0xC9,0xBB,0xC8,0xBC,0xCC,0xB9,0xCB,0xCA,0xCE,0xDF,0xDC,0xDB,0xFE,0xF2,
    0xB3,0xC4,0xDA,0xBF,0xC0,0xD9,0xC3,0xB4,0xC2,0xC1,0xC5,0xB0,0xB1,0xB2,0xD5,0x9F,
    0xFF,0xAD,0xBD,0x9C,0xCF,0xBE,0xDD,0xF5,0xF9,0xB8,0xA6,0xAE,0xAA,0xF0,0xA9,0xEE,
    0xF8,0xF1,0xFD,0xFC,0xEF,0xE6,0xF4,0xFA,0xF7,0xFB,0xA7,0xAF,0xAC,0xAB,0xF3,0xA8,
    0xB7,0xB5,0xB6,0xC7,0x8E,0x8F,0x92,0x80,0xD4,0x90,0xD2,0xD3,0xDE,0xD6,0xD7,0xD8,
    0xD1,0xA5,0xE3,0xE0,0xE2,0xE5,0x99,0x9E,0x9D,0xEB,0xE9,0xEA,0x9A,0xED,0xE8,0xE1,
    0x85,0xA0,0x83,0xC6,0x84,0x86,0x91,0x87,0x8A,0x82,0x88,0x89,0x8D,0xA1,0x8C,0x8B,
    0xD0,0xA4,0x95,0xA2,0x93,0xE4,0x94,0xF6,0x9B,0x97,0xA3,0x96,0x81,0xEC,0xE7,0x98
    };

    if(kar & 0x80)
        return translationTable[kar & 0x7F];
    else
        return kar;
/*    return kar & 0x80 ? (unsigned char)translationTable[kar & 0x7F] : kar;*/
}

static unsigned char CodePage850toISO8859(unsigned char kar)
{
    static unsigned char translationTable[] =
    {
    0xC7,0xFC,0xE9,0xE2,0xE4,0xE0,0xE5,0xE7,0xEA,0xEB,0xE8,0xEF,0xEE,0xEC,0xC4,0xC5,
    0xC9,0xE6,0xC6,0xF4,0xF6,0xF2,0xFB,0xF9,0xFF,0xD6,0xDC,0xF8,0xA3,0xD8,0xD7,0x9F,
    0xE1,0xED,0xF3,0xFA,0xF1,0xD1,0xAA,0xBA,0xBF,0xAE,0xAC,0xBD,0xBC,0xA1,0xAB,0xBB,
    0x9B,0x9C,0x9D,0x90,0x97,0xC1,0xC2,0xC0,0xA9,0x87,0x80,0x83,0x85,0xA2,0xA5,0x93,
    0x94,0x99,0x98,0x96,0x91,0x9A,0xE3,0xC3,0x84,0x82,0x89,0x88,0x86,0x81,0x8A,0xA4,
    0xF0,0xD0,0xCA,0xCB,0xC8,0x9E,0xCD,0xCE,0xCF,0x95,0x92,0x8D,0x8C,0xA6,0xCC,0x8B,
    0xD3,0xDF,0xD4,0xD2,0xF5,0xD5,0xB5,0xFE,0xDE,0xDA,0xDB,0xD9,0xFD,0xDD,0xAF,0xB4,
    0xAD,0xB1,0x8F,0xBE,0xB6,0xA7,0xF7,0xB8,0xB0,0xA8,0xB7,0xB9,0xB3,0xB2,0x8E,0xA0,
    };

    /* 0x7F = 127, 0xFF = 255 */
    /* delete bit-7 before search in tabel (0-6 is unchanged) */
    /* delete bit 15-8 */

    if(kar & 0x80)
        return translationTable[kar & 0x7F];
    else
        return kar;
/*    return kar & 0x80 ? (unsigned char)translationTable[kar & 0x7F] : kar;*/
}


static unsigned char *start,**pstart,*bron;
#ifdef TR
static int dp = 0;
#endif

static psk anker;

#if 0
static clock_t time0;
#endif

#if defined MSDOS || defined _WIN32
#define DELAY_DUE_TO_INPUT
#endif

#ifdef __GNUC__
#define DELAY_DUE_TO_INPUT
#endif

#ifdef DELAY_DUE_TO_INPUT
static clock_t delayDueToInput = 0;
#endif

#ifdef vax
static struct timeval t0; /* de vax-versie laat twee tijden zien: CPU en echte tijd */
static struct timezone tzp;
#endif

#ifdef __SYMBIAN32__
/* #define LIJSTLEN 0x100*/ /* If too high you get __chkstk error. Stack = 8K only! */
/* #define LIJSTLEN 0x7F00*/
#define LIJSTLEN 0x2000
#else
#ifdef _MSC_VER
#define LIJSTLEN 0x7F00 /* Microsoft C staat 32k automatic data toe */
#else
#ifdef __BORLANDC__
#if __BORLANDC__ >= 0x500
#define LIJSTLEN 0x7000
#else
#define LIJSTLEN 0x7FFC
#endif
#else
#define LIJSTLEN 0x7FFC
#endif
#endif
#endif

static unsigned char *wijzer,*maxwijzer;/* bovengrens (tot, niet t/m)*/
static unsigned char **conc;


/* FUNCTIONS */

static void hreslt(psk wortel,int nivo,int ind,int space);
#if DEBUGBRACMAT
static void hreslts(psk wortel,int nivo,int ind,int space,psk snijaf);
#endif
static int evalueer(ppsk pkn);
static psk subboomcopie(psk src);

#if MICROSOFT_WINDOWS_API
#if WRITETRACE
static void Log(char *fmt,...)
        {
        FILE *fp;
        if(fmt == NULL)
                {
                if((fp = fopen("LOG","w")) != NULL)
                        {
                        fprintf(fp,"LOGFILE %s %s\n",__DATE__,__TIME__);
                        fclose(fp);
                        }
                }
        else
                {
                va_list ap;
                va_start(ap,fmt);
                if((fp = fopen("LOG","a")) != NULL)
                        {
                        fprintf(fp,"%s:",__FILE__);
                        vfprintf(fp,fmt,ap);
                        fputc('\n',fp);
                        fclose(fp);
                        }
                va_end(ap);
                }
        }
#endif

static int (*WinIn)(void) = NULL;
static void (*WinOut)(int c) = NULL;
static void (*WinFlush)(void) = NULL;

static int mygetc(FILE * fpi)
    {
    if(WinIn && fpi == stdin)
        {
        return WinIn();
        }
    else
        return fgetc(fpi);
    }


static void myputc(int c)
    {
    if(WinOut && (fpo == stdout || fpo == stderr))
        {
        WinOut(c);
        }
    else
        fputc(c,fpo);
    }
#else
static void myputc(int c)
    {
    fputc(c,fpo);
    }

static int mygetc(FILE * fpi)
       {
    return fgetc(fpi);
    }
#endif

#if COMPILE
#if !MACRO
        static Boolean IS_RESOLVED(psk p)
          {
          return (p)->flgs & RESOLVED;
          }

        /* te ruw: alleen de eerste vier bytes worden opnieuw gebruikt. */
        static void RESOLVE(psk p,vars * navar)
          {
          assert(navar != NULL);
          assert(p != NULL);
/*          if(!(p->flgs & IDENT))*/
            {
            (p)->flgs |= RESOLVED;
            (p)->u.var = navar;
            navar->Refcount++;
            }
          }

        static vars * RESOLUTION(psk p)
          {
          return (p)->u.var;
          }

        static Boolean RIS_RESOLVED(sk p)
          {
          return (p).flgs & RESOLVED;
          }

        static vars * RRESOLUTION(sk p)
          {
          return (p).u.var;
          }

        static unsigned char * OBJ(sk p)
          {
#ifdef PVNAME
          return RIS_RESOLVED(p) ? (RRESOLUTION(p)->vname) : &((p).u.Obj);
#else
          return RIS_RESOLVED(p) ? &(RRESOLUTION(p)->u.Obj) : &((p).u.Obj);
#endif
          }

        /*
        static unsigned char ROBJ(sk p)
          {
          return RIS_RESOLVED(p) ? *(RRESOLUTION(p)->name) : ((p).u.Obj);
          }
        */

        static unsigned char * POBJ(psk p)
          {
          if(IS_RESOLVED(p))
#ifdef PVNAME
              return RESOLUTION(p)->vname;
#else
              return &RESOLUTION(p)->u.Obj;
#endif
          else
              return &((p)->u.Obj);
/*          return IS_RESOLVED(p) ? (RESOLUTION(p)->name) : &((p)->u.Obj);*/
          }

        static unsigned char RPOBJ(psk p)
          {
#ifdef PVNAME
          return IS_RESOLVED(p) ? *(RESOLUTION(p)->vname) : ((p)->u.Obj);
#else
          return IS_RESOLVED(p) ? (RESOLUTION(p)->u.Obj) : ((p)->u.Obj);
#endif
          }

        static int PIOBJ(psk p)
          {
#ifdef PVNAME
          return IS_RESOLVED(p) ? *(int*)(RESOLUTION(p)->vname) : ((p)->u.Iobj);
#else
          return IS_RESOLVED(p) ? (RESOLUTION(p)->u.Iobj) : ((p)->u.Iobj);
#endif
          }

        static long PLOBJ(psk p)
          {
#ifdef PVNAME
          return IS_RESOLVED(p) ? *(long*)(RESOLUTION(p)->vname) : ((p)->u.Lobj);
#else
          return IS_RESOLVED(p) ? (RESOLUTION(p)->u.Lobj) : ((p)->u.Lobj);
#endif
          }
        static long LOBJ(sk p)
          {
#ifdef PVNAME
          return RIS_RESOLVED(p) ? *(long*)(RRESOLUTION(p)->vname) : ((p).u.Lobj);
#else
          return RIS_RESOLVED(p) ? (RRESOLUTION(p)->u.Lobj) : ((p).u.Lobj);
#endif
          }
#endif
#endif

static void (*verwerk)(int c) = myputc;

static void myprintf(char *string,...)
{
char *i,*j;
va_list ap;
va_start(ap,string);
i = string;
while(i)
    {
    for(j = i;*j;j++)
        (*verwerk)(*j);
    i = va_arg(ap,char *);
    }
va_end(ap);
}


#if MICROSOFT_WINDOWS_API && !defined _MT
static int printf(const char *fmt, ...)
    {
    char buffer[1000];
    int ret;
    va_list ap;
    va_start(ap,fmt);
    ret = vsprintf(buffer,fmt,ap);
    myprintf(buffer,NULL);
    va_end(ap);
    return ret;
    }
#endif

static int errorprintf(const char *fmt, ...)
    {
    char buffer[1000];
    int ret;
    FILE * save = fpo;
    va_list ap;
    va_start(ap,fmt);
    ret = vsprintf(buffer,fmt,ap);
#ifdef BRACMATEMBEDDED
    fpo = stderr;
#else
    fpo = errorStream;
#endif
    if(fpo)
	myprintf(buffer,NULL);
    else
	ret = 0;
    fpo = save;
    va_end(ap);
    return ret;
    }

#if DOCHECKSUM

static int LineNo;
static int N;

static int getchecksum(void)
	{
	byte4 *P4 = p4;
	byte8 *P8 = p8;
	byte12 *P12 = p12;
	byte16 *P16 = p16;
#ifdef _4_5
	byte20 *P20 = p20;
	byte24 *P24 = p24;
#endif
	int sum = 0;
	while(P4)
		{
		sum += (int)P4;
		P4 = P4->u.p;
		}
	while(P8)
		{
		sum += (int)P8;
		P8 = P8->u.p;
		}
	while(P12)
		{
		sum += (int)P12;
		P12 = P12->u.p;
		}
	while(P16)
		{
		sum += (int)P16;
		P16 = P16->u.p;
		}
#ifdef _4_5
	while(P20)
		{
		sum += (int)P20;
		P20 = P20->u.p;
		}
	while(P24)
		{
		sum += (int)P24;
		P24 = P24->u.p;
		}
#endif
	return sum;
	}

static int Checksum = 0;

static void setChecksum(int lineno,int n)
	{
	if(lineno)
		{
		LineNo = lineno;
		N = n;
		}
	Checksum = getchecksum();
	}

static void checksum(int line)
	{
	static int nChecksum = 0;
	nChecksum = getchecksum();
	if(Checksum && Checksum != nChecksum)
		{
		printf("Line %d: Illegal write after bmalloc(%d) on line %d",line,N,LineNo);
		getchar();
		exit(1);
		}
	}

#endif

static void bfree(void *p)
{
#ifdef TELMAX
globalloc--;
#endif
#if W32
#ifdef _4_5
if(p >= (void*)p24start &&
   p <  (void*)p24end)
    {
    al24++;
    ((byte24*)p)->u.p = p24;
    p24 = (byte24*)p;
    }
else
if(p >= (void*)p20start &&
   p <  (void*)p20end)
    {
    al20++;
    ((byte20*)p)->u.p = p20;
    p20 = (byte20*)p;
    }
else
#endif
if(p >= (void*)p16start &&
   p <  (void*)p16end)
    {
    al16++;
    ((byte16*)p)->u.p = p16;
    p16 = (byte16*)p;
    }
else
if(p >= (void*)p12start &&
   p <  (void*)p12end)
    {
    al12++;
    ((byte12*)p)->u.p = p12;
    p12 = (byte12*)p;
    }
else
if(p >= (void*)p8start &&
   p <  (void*)p8end)
    {
    al8++;
    ((byte8*)p)->u.p = p8;
    p8 = (byte8*)p;
    }
else
if(p >= (void*)p4start &&
   p <  (void*)p4end)
    {
    al4++;
    ((byte4*)p)->u.p = p4;
    p4 = (byte4*)p;
    }
#endif
#ifdef MSDOS
if(FP_SEG(p) == FP_SEG(p4start))
    {
    al4++;
    ((byte4*)p)->u.p = p4;
    p4 = (byte4*)p;
    }
else
if(FP_SEG(p) == FP_SEG(p8start))
    {
    al8++;
    ((byte8*)p)->u.p = p8;
    p8 = (byte8*)p;
    }
else
if(FP_SEG(p) == FP_SEG(p12start))
    {
    al12++;
    ((byte12*)p)->u.p = p12;
    p12 = (byte12*)p;
    }
else
if(FP_SEG(p) == FP_SEG(p16start))
    {
    al16++;
    ((byte16*)p)->u.p = p16;
    p16 = (byte16*)p;
    }
#ifdef _4_5
else
if(FP_SEG(p) == FP_SEG(p20start))
    {
    al20++;
    ((byte20*)p)->u.p = p20;
    p20 = (byte20*)p;
    }
else
if(FP_SEG(p) == FP_SEG(p24start))
    {
    al24++;
    ((byte24*)p)->u.p = p24;
    p24 = (byte24*)p;
    }
#endif
#endif
else
    {
    free(p);
    return;
    }
#if DOCHECKSUM
setChecksum(0,0);
#endif
}

#if COMPILE
static void unbind(vars * navar)
    {
    assert(navar->Refcount >= 0);
    if(navar->Refcount == 0)
        {
        if(navar->Prev)
            {
            assert(navar->Prev->next == navar);
            if(navar->next)
                {
                assert(navar->next->Prev == navar);
                navar->next->Prev = navar->Prev;
                navar->Prev->next = navar->next;
                }
            else
                navar->Prev->next = NULL;
            }
        else
            {
#ifdef PVNAME
            assert(variabelen[*(navar->vname)] == navar);
#else
            assert(variabelen[navar->u.Obj] == navar);
#endif
            if(navar->next)
                {
                navar->next->Prev = NULL;
                }
#ifdef PVNAME
            variabelen[*(navar->vname)] = navar->next;
#else
            variabelen[navar->u.Obj] = navar->next;
#endif
            }
#ifdef PVNAME
        if(navar->vname != OBJ(nilk))
            bfree(navar->vname);
#endif
        navar->Prev = NULL;
        navar->next = NULL;
        bfree(navar); /* nieuw */
        }
    else
        navar->pvaria = NULL;
    }
#endif


static void pskfree(psk p)
    {
#if COMPILE
    if(IS_RESOLVED(p))
        {
        assert(p->u.var != NULL);
        p->u.var->Refcount--;
        assert(p->u.var->Refcount >= 0);
        if(!p->u.var->Refcount)
            {
            unbind(p->u.var);
            }
        }
#endif
    bfree(p);
    }

#if TELLING
static void bezetting(void)
{
printf("bezet (promilles) 1 woord : %ld, 2 woorden : %ld, 3 woorden : %ld, 4 woorden : %ld, 5 woorden : %ld, 6 woorden : %ld\n",
1000L-(1000L * al4)/(PROMILLAGE4 *KILOKNOPEN),
1000L-(1000L * al8)/(PROMILLAGE8 *KILOKNOPEN),
1000L-(1000L * al12)/(PROMILLAGE12*KILOKNOPEN),
1000L-(1000L * al16)/(PROMILLAGE16*KILOKNOPEN),
1000L-(1000L * al20)/(PROMILLAGE20*KILOKNOPEN),
1000L-(1000L * al24)/(PROMILLAGE24*KILOKNOPEN));
printf("bezet (absoluut) 1 woord : %ld, 2 woorden : %ld, 3 woorden : %ld, 4 woorden : %ld, 5 woorden : %ld, 6 woorden : %ld\n",
(PROMILLAGE4  * KILOKNOPEN - al4),
(PROMILLAGE8  * KILOKNOPEN - al8),
(PROMILLAGE12 * KILOKNOPEN - al12),
(PROMILLAGE16 * KILOKNOPEN - al16),
(PROMILLAGE20 * KILOKNOPEN - al20),
(PROMILLAGE24 * KILOKNOPEN - al24));
printf("meer dan 6 woorden : %ld\n",
globalloc+al4+al8+al12+al16+al20+al24-1000L*KILOKNOPEN);
}
#endif


#if !DOCHECKSUM
#define bmalloc(LINENO,N) bmalloc(N)
#endif


static void *bmalloc(int lineno,size_t n)
    {
    void *ret;
#if DOCHECKSUM
	int nn = n;
#endif
#if TELLING
    int tel;
    alloc_cnt++;
    if(n<256)
        cnts[n]++;
    totcnt += n;
#endif
#ifdef TELMAX
    globalloc++;
    if(maxgloballoc < globalloc)
        maxgloballoc = globalloc;
#endif
#if DOCHECKSUM
	checksum(__LINE__);
#endif
    n = (n-1) >> 2;
    switch(n)
        {
        case 0 :
            if(p4)
                {
                al4--;
                ret = p4;
                p4 = p4->u.p;
                *(long*)ret = 0;
#if DOCHECKSUM
				setChecksum(lineno,nn);
#endif
                return ret;
                }
        case 1 :
            if(p8)
                {
                al8--;
                p8->rest = 0;
                ret = p8;
                p8 = p8->u.p;
                *(long*)ret = 0;
#if DOCHECKSUM
				setChecksum(lineno,nn);
#endif
                return ret;
                }
        case 2 :
            if(p12)
                {
                al12--;
                ret = p12;
                p12 = p12->u.p;
                *(long*)ret = 0;
                *((long*)ret+n) = 0;
#if DOCHECKSUM
				setChecksum(lineno,nn);
#endif
                return ret;
                }
        case 3 :
            if(p16)
                {
                al16--;
                ret = p16;
                p16 = p16->u.p;
                *(long*)ret = 0;
                *((long*)ret+n) = 0;
#if DOCHECKSUM
				setChecksum(lineno,nn);
#endif
                return ret;
                }
#ifdef _4_5
        case 4 :
            if(p20)
                {
                al20--;
                ret = p20;
                p20 = p20->u.p;
                *(long*)ret = 0;
                *((long*)ret+n) = 0;
#if DOCHECKSUM
				setChecksum(lineno,nn);
#endif
                return ret;
                }
        case 5 :
            if(p24)
                {
                al24--;
                ret = p24;
                p24 = p24->u.p;
                *(long*)ret = 0;
                *((long*)ret+n) = 0;
#if DOCHECKSUM
				setChecksum(lineno,nn);
#endif
                return ret;
                }
#endif
        }
    ret = malloc((n<<2)+4);
    if(!ret)
        {
#if TELLING
        errorprintf(
#if TAAL == NL
        "GEHEUGEN VOL NA %ld ALLOCATIES MET GEMIDDELDE LENGTE %ld\n",
#else
        "MEMORY FULL AFTER %ld ALLOCATIONS WITH MEAN LENGTH %ld\n",
#endif
            globalloc,totcnt/alloc_cnt);
        for(tel = 0;tel<16;tel++)
            {
            int tel1;
            for(tel1 = 0;tel1<256;tel1 += 16)
                errorprintf("%ld ",(cnts[tel+tel1]*1000+500)/alloc_cnt);
            errorprintf("\n");
            }
        bezetting();
#endif
        errorprintf(
#if TAAL == NL
            "geheugen vol (blok van %d bytes kon niet gealloceerd worden)",
#else
            "memory full (requested block of %d bytes could not be allocated)",
#endif
            (n<<2)+4);

        exit(1);
        }

    *((long*)ret+n) = 0;
    *(long*)ret = 0;
#if DOCHECKSUM
	setChecksum(lineno,n);
#endif
    return ret;
    }

static psk new_operator_like(psk kn)
    {
    if(kop(kn) == WORDT)
        {
        if(ISBUILTIN((objectknoop*)kn))
            {
            typedObjectknoop * goal = (typedObjectknoop *)bmalloc(__LINE__,sizeof(typedObjectknoop));
            goal->refcount = 0L;/*OOOOPS*/
            UNSETCREATEDWITHNEW(goal);
            SETBUILTIN(goal);
            goal->vtab = ((typedObjectknoop*)kn)->vtab;
#ifdef OBJECTDATA
            goal->data = ((typedObjectknoop*)kn)->data;
            printf("new_operator_like goal %p goal->vtab %p goal->data %p\n",goal,goal->vtab,goal->data);
            if(goal->data)
                goal->data->refcount++;
#else
            goal->voiddata = NULL;
#endif
            return (psk)goal;
            }
        else
            {
            objectknoop * goal = (objectknoop *)bmalloc(__LINE__,sizeof(objectknoop));
            goal->refcount = 0L;/*OOOOPS*/
            UNSETCREATEDWITHNEW(goal);
            UNSETBUILTIN(goal);
            return (psk)goal;
            }
        }
    else
        return (psk)bmalloc(__LINE__,sizeof(kknoop));
    }

static unsigned char *shift_nw(void)
    {
    if(startPos)
        {
        startPos = va_arg(ap,unsigned char*);
        if(startPos)
                start = startPos;
        }
    return start;
    }

static unsigned char *vshift_w(void)
    {
    if(*pstart && *++pstart)
        {
        bfree(*(pstart-1));
        start = *pstart;
        }
    return start;
    }

static unsigned char *vshift_nw(void)
    {
    if(*pstart && *++pstart)
        start = *pstart;
    return start;
    }

static unsigned char *(*shift)(void) = shift_nw;


static void tel(int c)
{
telling++;
}

static void tstr(int c)
{
static int esc = FALSE,str = FALSE;
if(esc)
    {
    esc = FALSE;
    telling++;
    }
else if(c == '\\')
    esc = TRUE;
else if(str)
    {
    if(c == '"')
        str = FALSE;
    else
        telling++;
    }
else if(c == '"')
    str = TRUE;
else if(c != ' ')
    telling++;
}

static void pstr(int c)
{
static int esc = FALSE,str = FALSE;
if(esc)
    {
    esc = FALSE;
    switch(c)
        {
        case 'n' :
            c = '\n';
            break;
        case 'f' :
            c = '\f';
            break;
        case 'r' :
            c = '\r';
            break;
        case 'b' :
            c = '\b';
            break;
#ifndef vax
        case 'a' :
            c = ALERT;
            break;
#endif
        case 'v' :
            c = '\v';
            break;
        case 't' :
            c = '\t';
            break;
        case 'L' :
            c = 016;
            break;
        case 'D' :
            c = 017;
            break;
        }
    *bron++ = (char)c;
    }
else if(c == '\\')
    esc = TRUE;
else if(str)
    {
    if(c == '"')
        str = FALSE;
    else
        *bron++ = (char)c;
    }
else if(c == '"')
    str = TRUE;
else if(c != ' ')
    *bron++ = (char)c;
}

static void plak(int c)
{
*bron++ = (char)c;
}

#define COMPLEX_MAX 80
#define LINELENGTH 80

static /*int 20031126*/size_t complexiteit(psk wortel,/*int 20031126*/size_t max)
{
/*int left,right;*/
static int ouder,kind;
if(is_op(wortel))
    {
    switch(kop(wortel))
        {
        case OF :
        case EN :
            max += COMPLEX_MAX/5;
            break;
        case WORDT :
        case MATCH :
            max += COMPLEX_MAX/10;
            break;
        case DOT :
        case KOMMA :
        case LUCHT :
            switch(kop(wortel->LINKS))
                {
                case DOT:
                case KOMMA:
                case LUCHT :
                    max += COMPLEX_MAX/10;
                    break;
                default:
                    max += COMPLEX_MAX/LINELENGTH;
                }
            break;
/*
        case PLUS:
            max += COMPLEX_MAX/25;
            break;
        case MAAL:
            max += COMPLEX_MAX/40;
            break;
*/
        default:
            max += COMPLEX_MAX/LINELENGTH;
        }
    ouder = kop(wortel);
    kind = kop(wortel->LINKS);
    if(HAS__UNOPS(wortel->LINKS) || ouder >= kind)
        max += (2 * COMPLEX_MAX)/LINELENGTH; /* 2 parentheses */

    kind = kop(wortel->RECHTS);
    if(HAS__UNOPS(wortel->RECHTS) || ouder > kind || (ouder == kind && ouder > MAAL))
        max += (2 * COMPLEX_MAX)/LINELENGTH; /* 2 parentheses */

    if(max > COMPLEX_MAX)
        return max;
/*
    left = complexiteit(wortel->LINKS,max);
    right = complexiteit(wortel->RECHTS,max);

    if(left > right)
        max = left;
    else
        max = right;
*/
    max = complexiteit(wortel->LINKS,max);
    max = complexiteit(wortel->RECHTS,max);
    }
else
    max += (COMPLEX_MAX*strlen((char*)POBJ(wortel))) / LINELENGTH;
return max;
}

static int indtel = 0,extraspatie = 0,number_of_flags_on_node=0;

static int indent(psk wortel,int nivo,int ind)
{
if(hum)
    {
    if(ind > 0 || (ind == 0 && complexiteit(wortel,2*nivo) > COMPLEX_MAX))
        {  /*    blanks that start a line    */
        int p;
        (*verwerk)('\n');
        for(p = 2*nivo+number_of_flags_on_node;p;p--)
            (*verwerk)(' ');
        ind = TRUE;
        }
    else
        {  /* blanks after an operator or parenthesis */
        for(indtel = extraspatie + 2*indtel;indtel;indtel--)
            (*verwerk)(' ');
        ind = FALSE;
        }
    extraspatie = 0;
    }
return ind;
}

static int moetIndent(psk wortel,int ind,int nivo)
{
return hum && !ind && complexiteit(wortel,2*nivo) > COMPLEX_MAX;
}

static void bewerk(int c)
{
if(c == 016 || c == 017)
    {
    (*verwerk)('\\');
    (*verwerk)(c == 016 ? 'L' : 'D');
    }
else
    (*verwerk)(c);
}

static int lineToLong(unsigned char *string)
    {
    if(  hum
      && strlen((const char *)string) > 10 /*LINELENGTH*/
      /* very short strings are allowed to keep \n and \t */
      )
        return TRUE;
    return FALSE;
    }

static int haalaan(unsigned char *string)
{
unsigned char *wijzer;
if(quote[*string] & 1)
    return TRUE;
for(wijzer = string;*wijzer;wijzer++)
    if(quote[*wijzer] & 2)
        return TRUE;
    else if(  quote[*wijzer] & 4
           && lineToLong(string)
           )
        return TRUE;
return FALSE;
}

static int printflags(psk wortel)
{
int count = 0;
int flgs = wortel->flgs;
if(flgs & NOT)
    {
    (*verwerk)('~');
    ++count;
    }
if(flgs & BREUK)
    {
    (*verwerk)('/');
    ++count;
    }
if(flgs & NUMBER)
    {
    (*verwerk)('#');
    ++count;
    }
if(flgs & KLEINER_DAN)
    {
    (*verwerk)('<');
    ++count;
    }
if(flgs & GROTER_DAN)
    {
    (*verwerk)('>');
    ++count;
    }
if(flgs & NONIDENT)
    {
    (*verwerk)('%');
    ++count;
    }
if(flgs & ATOOM)
    {
    (*verwerk)('@');
    ++count;
    }
if(flgs & UNIFY)
    {
    (*verwerk)('?');
    ++count;
    }
if(flgs & FENCE)
    {
    (*verwerk)('`');
    ++count;
    }
if(flgs & INDIRECT)
    {
    (*verwerk)('!');
    ++count;
    }
if(flgs & DUBBEL_INDIRECT)
    {
    (*verwerk)('!');
    ++count;
    }
#if OBJECTS
if(flgs & OBJECT)
    {
    (*verwerk)('[');
    ++count;
    }
#endif
return count;
}

#define LHS 1
#define RHS 2

static void eindknoop(psk wortel,int space)
{
unsigned char *wijzer;
int q,ikar;
#if COMPILE
if(!RPOBJ(wortel)
#else
if(!wortel->u.obj
#endif
&& !HAS_UNOPS(wortel)
&& space)
    {
    (*verwerk)('(');
    (*verwerk)(')');
    return;
    }
printflags(wortel);
if(wortel->ops & MINUS)
    (*verwerk)('-');
if(mooi)
    {
    for(wijzer = POBJ(wortel);*wijzer;wijzer++)
        bewerk(*wijzer);
    }
else
    {
    Boolean longline = FALSE;
    if((q = haalaan(POBJ(wortel))) == TRUE)
        (*verwerk)('"');
/*
    if(hum) / * 20001129 * /
        for(wijzer = POBJ(wortel);*wijzer;wijzer++)
            bewerk(*wijzer);
    else
    20010103 File saved this way can not be re-read if string contains doublequote \"
*/
    for(wijzer = POBJ(wortel);(ikar = *wijzer) != 0;wijzer++)
        {
        switch(ikar)
            {
            case '\n' :
                if(longline || lineToLong(POBJ(wortel)))
                /* We need to call this, even though haalaan returned TRUE,
                   because haalaan may have returned before reaching this character.
                 */
                  {
                  longline = TRUE;
                  (*verwerk)('\n');
                  continue;
                  }
                ikar = 'n';
                break;
            case '\f' :
                ikar = 'f';
                break;
            case '\r' :
                ikar = 'r';
                break;
            case '\b' :
                ikar = 'b';
                break;
#ifndef vax
            case ALERT :
                ikar = 'a';
                break;
#endif
            case '\v' :
                ikar = 'v';
                break;
            case '\t' :
                if(longline || lineToLong(POBJ(wortel)))
                /* We need to call this, even though haalaan returned TRUE,
                   because haalaan may have returned before reaching this character.
                 */
                  {
                  longline = TRUE;
                  (*verwerk)('\t');
                  continue;
                  }
                ikar = 't';
                break;
            case '"' :
            case '\\' :
                break;
            case 016 :
                ikar = 'L';
                break;
            case 017 :
                ikar = 'D';
                break;
            default :
                (*verwerk)(ikar);
                continue;
            }
        (*verwerk)('\\');
        (*verwerk)(ikar);
        }
    if(q)
        (*verwerk)('"');
    }
}

#define RSP (ouder == LUCHT ? RHS : 0)
#define LSP (ouder == LUCHT ? LHS : 0)

#ifndef reslt
static void reslt(psk wortel,int nivo,int ind,int space)
{
static int ouder,kind,/* 18 Maart 1997:*/newind;
while(is_op(wortel))/* 18 Maart 1997: */
    {
    ouder = kop(wortel);
    kind = kop(wortel->LINKS);
    if(moetIndent(wortel,ind,nivo))
        indtel++;
    if(HAS__UNOPS(wortel->LINKS) || ouder >= kind)
        hreslt(wortel->LINKS,nivo+1,FALSE,(space & LHS) | RSP);
    else
        reslt(wortel->LINKS,nivo+1,FALSE,(space & LHS) | RSP);
    newind = indent(wortel,nivo,ind);
    if(newind)
        extraspatie = 1;
    bewerk(opchar[klopcode(wortel)]);
    ouder = kop(wortel);
    kind = kop(wortel->RECHTS);
    if(HAS__UNOPS(wortel->RECHTS) || ouder > kind || (ouder == kind && ouder > MAAL))
		{
        hreslt(wortel->RECHTS,nivo+1,FALSE,LSP | (space & RHS));
		return;
		}
    else if(ouder < kind)
		{
        reslt(wortel->RECHTS,nivo+1,FALSE,LSP | (space & RHS));
		return;
		}
    else if(newind != ind || ((LSP | (space & RHS)) != space))
        {
        reslt(wortel->RECHTS,nivo,newind,LSP | (space & RHS));
		return;
		}
    wortel = wortel->RECHTS;
	}
indent(wortel,nivo,-1);
eindknoop(wortel,space);
/*
while(1)/ * 18 Maart 1997: * /
    {
    if(is_op(wortel))
        {
        ouder = kop(wortel);
        kind = kop(wortel->LINKS);
        if(moetIndent(wortel,ind,nivo))
            indtel++;
        if(HAS__UNOPS(wortel->LINKS) || ouder >= kind)
            hreslt(wortel->LINKS,nivo+1,FALSE,(space & LHS) | RSP);
        else
            reslt(wortel->LINKS,nivo+1,FALSE,(space & LHS) | RSP);
        newind = indent(wortel,nivo,ind);
        if(newind)
            extraspatie = 1;
        bewerk(opchar[klopcode(wortel)]);
        ouder = kop(wortel);
        kind = kop(wortel->RECHTS);
        if(HAS__UNOPS(wortel->RECHTS) || ouder > kind || (ouder == kind && ouder > MAAL))
            hreslt(wortel->RECHTS,nivo+1,FALSE,LSP | (space & RHS));
        else
            {
            if(ouder < kind)
                reslt(wortel->RECHTS,nivo+1,FALSE,LSP | (space & RHS));
            else if(newind == ind && ((LSP | (space & RHS)) == space))
                {
                wortel = wortel->RECHTS;
                continue;
                }
            else
                reslt(wortel->RECHTS,nivo,newind,LSP | (space & RHS));
            }
        }
    else
        {
        indent(wortel,nivo,-1);
        eindknoop(wortel,space);
        }
    break;
    }
*/
}

#if DEBUGBRACMAT

static void reslts(psk wortel,int nivo,int ind,int space,psk snijaf)
	{
	static int ouder,kind,/* 18 Maart 1997:*/newind;
	while(is_op(wortel))/* 18 Maart 1997: */
        {
		if(snijaf && wortel->RECHTS == snijaf)
			{
			reslt(wortel->LINKS,nivo,ind,space);
			return;
			}
        ouder = kop(wortel);
        kind = kop(wortel->LINKS);
        if(moetIndent(wortel,ind,nivo))
            indtel++;
        if(HAS__UNOPS(wortel->LINKS) || ouder >= kind)
            hreslt(wortel->LINKS,nivo+1,FALSE,(space & LHS) | RSP);
        else
            reslt(wortel->LINKS,nivo+1,FALSE,(space & LHS) | RSP);
        newind = indent(wortel,nivo,ind);
        if(newind)
            extraspatie = 1;
        bewerk(opchar[klopcode(wortel)]);
        ouder = kop(wortel);
        kind = kop(wortel->RECHTS);
        if(HAS__UNOPS(wortel->RECHTS) || ouder > kind || (ouder == kind && ouder > MAAL))
            hreslts(wortel->RECHTS,nivo+1,FALSE,LSP | (space & RHS),snijaf);
        else if(ouder < kind)
			{
            reslts(wortel->RECHTS,nivo+1,FALSE,LSP | (space & RHS),snijaf);
			return;
			}
        else if(newind != ind || ((LSP | (space & RHS)) != space))
			{
            reslts(wortel->RECHTS,nivo,newind,LSP | (space & RHS),snijaf);
			return;
			}
        wortel = wortel->RECHTS;
        }
    indent(wortel,nivo,-1);
    eindknoop(wortel,space);
	}
#endif /* DEBUGBRACMAT */
#endif

static void hreslt(psk wortel,int nivo,int ind,int space)
{
static int ouder,kind;
if(is_op(wortel))
    {
    int number_of_flags;
    indent(wortel,nivo,-1);
    number_of_flags = printflags(wortel);
    number_of_flags_on_node += number_of_flags;
    (*verwerk)('(');
    indtel = 0;
    if(moetIndent(wortel,ind,nivo))
        extraspatie = 1;
    ouder = kop(wortel);
    kind = kop(wortel->LINKS);
    if(HAS__UNOPS(wortel->LINKS) || ouder >= kind)
        hreslt(wortel->LINKS,nivo+1,FALSE,RSP);
    else
        reslt(wortel->LINKS,nivo+1,FALSE,RSP);
    ind = indent(wortel,nivo,ind);
    if(ind)
        extraspatie = 1;
    bewerk(opchar[klopcode(wortel)]);
    ouder = kop(wortel);
    kind = kop(wortel->RECHTS);
    if(HAS__UNOPS(wortel->RECHTS) || ouder > kind || (ouder == kind && ouder > MAAL))
        hreslt(wortel->RECHTS,nivo+1,FALSE,LSP);
    else if(ouder < kind)
        reslt(wortel->RECHTS,nivo+1,FALSE,LSP);
    else
        reslt(wortel->RECHTS,nivo,ind,LSP);
    indent(wortel,nivo,FALSE);
    (*verwerk)(')');
    number_of_flags_on_node -= number_of_flags;
    }
else
    {
    indent(wortel,nivo,-1);
    eindknoop(wortel,space);
    }
}

static void result(psk wortel)
{
if(HAS__UNOPS(wortel))
    {
    hreslt(wortel,0,FALSE,0);
    }
else
    reslt(wortel,0,FALSE,0);
}

#if DEBUGBRACMAT
static void hreslts(psk wortel,int nivo,int ind,int space,psk snijaf)
{
static int ouder,kind;
if(is_op(wortel))
    {
    int number_of_flags;
	if(snijaf && wortel->RECHTS == snijaf)
		{
		hreslt(wortel->LINKS,nivo,ind,space);
		return;
		}
    indent(wortel,nivo,-1);
    number_of_flags = printflags(wortel);
    number_of_flags_on_node += number_of_flags;
    (*verwerk)('(');
    indtel = 0;
    if(moetIndent(wortel,ind,nivo))
        extraspatie = 1;
    ouder = kop(wortel);
    kind = kop(wortel->LINKS);
    if(HAS__UNOPS(wortel->LINKS) || ouder >= kind)
        hreslt(wortel->LINKS,nivo+1,FALSE,RSP);
    else
        reslt(wortel->LINKS,nivo+1,FALSE,RSP);
    ind = indent(wortel,nivo,ind);
    if(ind)
        extraspatie = 1;
    bewerk(opchar[klopcode(wortel)]);
    ouder = kop(wortel);
    kind = kop(wortel->RECHTS);
    if(HAS__UNOPS(wortel->RECHTS) || ouder > kind || (ouder == kind && ouder > MAAL))
        hreslts(wortel->RECHTS,nivo+1,FALSE,LSP,snijaf);
    else if(ouder < kind)
        reslts(wortel->RECHTS,nivo+1,FALSE,LSP,snijaf);
    else
        reslts(wortel->RECHTS,nivo,ind,LSP,snijaf);
    indent(wortel,nivo,FALSE);
    (*verwerk)(')');
    number_of_flags_on_node -= number_of_flags;
    }
else
    {
    indent(wortel,nivo,-1);
    eindknoop(wortel,space);
    }
}

static void results(psk wortel,psk snijaf)
{
if(HAS__UNOPS(wortel))
    {
    hreslts(wortel,0,FALSE,0,snijaf);
    }
else
    reslts(wortel,0,FALSE,0,snijaf);
}
#endif

static long toLong(psk kn)
{
long res;
res = strtoul((char*)POBJ(kn),(char**)NULL,10);
if(kn->ops & MINUS)
    res = -res;
return res;
}


static psk zelfde_als_w(psk kn)
{
#ifdef TELMAX
if(maxbez < kn->ops)
    maxbez = kn->ops;
#endif
if(!opgebruikt(kn))
    {
    incgebruik(kn);
    return kn;
    }
else
    return subboomcopie(kn);
}

#ifdef vax
static int numbercheck(unsigned char *beg)
{
int op_of_0,check;
unsigned char *begin;
begin = beg;
#else
static int numbercheck(unsigned char *begin)
{
int op_of_0,check;
#endif
check = QGETAL;
op_of_0 = *begin;

if(op_of_0 >= '0' && op_of_0 <= '9')
    {
    if(op_of_0 == '0')
        check |= QNUL;
/*    for(;optab[op_of_0 = *++begin] == NOOP;)*/
    for(;optab[op_of_0 = *++begin] != -1;)/*20010126*/
        {
        if(op_of_0 == '/')
            {
            if(check & QBREUK)
                {
                check = 0;
                break;
                }
            else
                check |= QBREUK;
            }
        else if(op_of_0 < '0' || op_of_0 > '9')
            {
            check = 0;
            break;
            }
        }
    }
else
    check = 0;
return check;
}

static int fullnumbercheck(unsigned char *begin)
	{
	if(*begin == '-')
		{
		int ret = numbercheck(begin+1);
		if(ret)
			return ret | MINUS;
		else
			return 0;
		}
	else
		return numbercheck(begin);
	}


static int flags(
#if W32
                void /* 20 Dec 1995 */
#else
                int *opsflgs
#endif
                )
{
int flgs = 0;

#if !W32
*opsflgs = 0;
#endif

for(;;start++)
    {
    switch(*start)
        {
        case '!' :
            if(flgs & INDIRECT)
                flgs |= DUBBEL_INDIRECT;
            else
                flgs |= INDIRECT;
            continue;
        case '?' :
            flgs |= UNIFY;
            continue;
        case '#' :
            flgs |= NUMBER;
            continue;
#if OBJECTS
        case '[' :
            flgs |= OBJECT;
            continue;
#endif
        case '/' :
            flgs |= BREUK;
            continue;
        case '@' :
            flgs |= ATOOM;
            continue;
        case '`' :
            flgs |= FENCE;
            continue;
        case '%' :
            flgs |= NONIDENT;
            continue;
        case '~' :
            flgs ^= NOT;
            continue;
        case '<' :
            flgs |= KLEINER_DAN;
            continue;
        case '>' :
            flgs |= GROTER_DAN;
            continue;
        case '-' :
#if W32
            flgs ^= MINUS;
#else
            *opsflgs ^= MINUS;
#endif
            continue;
        }
    break;
    }

if(flgs & NOT && flgs < ATOOM)
    flgs ^= SUCCES;
return flgs;
}

#if W32
#define flags(OPSFLGS) flags()
#endif


#if ALLOCVAR
static vars * allocVars(size_t len)
    {
    vars * nieuwvar;
    if(len < 4)
        nieuwvar = (vars*)bmalloc(__LINE__,sizeof(vars));
    else
        nieuwvar = (vars*)bmalloc(__LINE__,sizeof(vars) - 3 + len);
    return nieuwvar;
    }
#endif


#if COMPILE
#if ALLOCVAR
static vars * makeNewVar(vars * nieuwvar,int where,vars * navar)
#else
static vars * makeNewVar(unsigned char * string,int where,vars * navar)
#endif
    {
#ifdef PVNAME
    size_t len;
    vars * nieuwvar;
    len = strlen((char*)string);
    nieuwvar = (vars*)bmalloc(__LINE__,sizeof(vars));
#else
#if !ALLOCVAR
    size_t len;
    vars * nieuwvar;
    len = strlen((char*)string);
    if(len < 4)
        nieuwvar = (vars*)bmalloc(__LINE__,sizeof(vars));
    else
        nieuwvar = (vars*)bmalloc(__LINE__,sizeof(vars) - 3 + len);
#endif
#endif
    nieuwvar->Refcount = 1L;
    nieuwvar->n = 0;
    nieuwvar->selector = 0;
    nieuwvar->pvaria = NULL;
#if !ALLOCVAR
    if(*string)
        {
        /*printf("AAAAA\n");*/
#ifdef PVNAME
#if ICPY
        MEMCPY(nieuwvar->vname = (unsigned char*)
             bmalloc(__LINE__,len+1),string,(len >> LOGWORDLENGTH)+1);
#else
        MEMCPY(nieuwvar->vname = (unsigned char*)
             bmalloc(__LINE__,len+1),string,((len >> 2)+1) << 2);
#endif
#else
#if ICPY
        MEMCPY(&nieuwvar->u.Obj ,string,(len >> LOGWORDLENGTH)+1);
#else
        MEMCPY(&nieuwvar->u.Obj ,string,((len >> 2)+1) << 2);
#endif
#endif
        }
    else
        {
#ifdef PVNAME
        nieuwvar->vname = OBJ(nilk);
#else
        nieuwvar->u.Lobj = LOBJ(nilk);
#endif
        }
#endif /* !ALLOCVAR */
    if(navar)
        {
        if(where == 1)
            {
            vars * voorvar = nieuwvar->Prev = navar->Prev;
            navar->Prev = nieuwvar;
            nieuwvar->next = navar;
            if(voorvar == NULL)
#if ALLOCVAR
                variabelen[nieuwvar->u.Obj] = nieuwvar;
#else
                variabelen[*string] = nieuwvar;
#endif
            else
                voorvar->next = nieuwvar;
            }
        else /*where == -1*/
            {
            nieuwvar->Prev = navar;
            navar->next = nieuwvar;
            nieuwvar->next = NULL;
            }
        }
    else
        {
        nieuwvar->Prev = NULL;
        nieuwvar->next = NULL;
#if ALLOCVAR
        variabelen[nieuwvar->u.Obj] = nieuwvar;
#else
        variabelen[*string] = nieuwvar;
#endif
        }
    return nieuwvar;
    }
#endif

#if W32
#define atoom(PKN,FLGS,OPSFLGS) atoom(PKN,FLGS)
#endif

static void atoom(ppsk pkn,int flgs,int opsflgs)
    {
    unsigned char *begin,*eind;
    size_t af = 0;
#if COMPILE
    vars * navar;
    size_t length;
#endif


    begin = start;

    while(optab[*start] == NOOP)
        if(*start++ == 0x7F)
            af++;

    eind = start;
#if COMPILE
    length = (size_t)(eind - begin) - af;
    if(flgs & (INDIRECT|DUBBEL_INDIRECT|UNIFY) || length > 3)
        {
#if ALLOCVAR
        vars * nieuwvar;
#else
        unsigned char * string;
#endif
        flgs |= RESOLVED;
        if(length)
            {
#if ALLOCVAR
            nieuwvar = allocVars(length);
            start = begin;
            begin = &nieuwvar->u.Obj;
#else
            string = (unsigned char *)bmalloc(__LINE__,1 + length);
            start = begin;
            begin = string;
#endif

            while(start < eind)
                {
                if(*start == 0x7F)
                    {
                    ++start;
                    *begin++ = (unsigned char)(*start++ | 0x80);
                    }
                else
                    *begin++ = (unsigned char)(*start++ & 0x7F);
                }
            }
        else
#if ALLOCVAR
            {
            nieuwvar = allocVars(0);
            nieuwvar->u.Lobj = LOBJ(nilk);
            }
#else
            string = OBJ(nilk);
#endif

        *pkn = (psk)bmalloc(__LINE__,sizeof(unsigned long) + sizeof(varia*));
        (*pkn)->flgs = RESOLVED;
#if ALLOCVAR
        navar = variabelen[nieuwvar->u.Obj];
#else
        navar = variabelen[*string];
#endif

        if(navar)
            while(TRUE)
                {
#ifdef PVNAME
                int cmp = STRCMP(navar->vname,string);
#else
#if ALLOCVAR
                int cmp = STRCMP(&navar->u.Obj,&nieuwvar->u.Obj);
#else
                int cmp = STRCMP(&navar->u.Obj,string);
#endif
#endif
                if(cmp == 0)
                    {
                    (*pkn)->u.var = navar;
                    navar->Refcount++;
#if ALLOCVAR
                    bfree(nieuwvar);
#endif
                    break;
                    }
                else if(cmp > 0)
                    {
#if ALLOCVAR
                    (*pkn)->u.var = makeNewVar(nieuwvar,1,navar);
#else
                    (*pkn)->u.var = makeNewVar(string,1,navar);
#endif
                    break;
                    }
                else if(navar->next)
                    {
                    assert(navar == navar->next->Prev);
                    navar = navar->next;
                    }
                else
                    {
#if ALLOCVAR
                    (*pkn)->u.var = makeNewVar(nieuwvar,-1,navar);
#else
                    (*pkn)->u.var = makeNewVar(string,-1,navar);
#endif
                    break;
                    }
                }
        else
            {
#if ALLOCVAR
            (*pkn)->u.var = makeNewVar(nieuwvar,-1,NULL);
#else
            (*pkn)->u.var = makeNewVar(string,-1,NULL);
#endif
            }
#if !ALLOCVAR
        if(string != OBJ(nilk))
            bfree(string);
#endif
        }
    else
        {
        *pkn = (psk)bmalloc(__LINE__,sizeof(unsigned long) + 1 + length);
        start = begin;
        begin = POBJ(*pkn);
        while(start < eind)
            {
            if(*start == 0x7F)
                {
                ++start;
                *begin++ = (unsigned char)(*start++ | 0x80);
                }
            else
                *begin++ = (unsigned char)(*start++ & 0x7F);
            }
        }
#else
	*pkn = (psk)bmalloc(__LINE__,sizeof(unsigned long) + 1 + (size_t)(eind - begin) - af);
start = begin;
begin = POBJ(*pkn);
while(start < eind)
    {
    if(*start == 0x7F)
        {
        ++start;
        *begin++ = (unsigned char)(*start++ | 0x80);
        }
    else
		{
        *begin++ = (unsigned char)(*start++ & 0x7F);
		}
    }
#endif
if(flgs & INDIRECT)
    {
    (*pkn)->flgs = flgs ^ SUCCES;
    }
else
    {
#if W32
    if(ONTKENNING(flgs,NUMBER))
        (*pkn)->flgs = (flgs ^ (KLAAR|SUCCES));
    else
        (*pkn)->flgs = (flgs ^ (KLAAR|SUCCES)) | numbercheck(POBJ(*pkn));
#else
    if(ONTKENNING(flgs,NUMBER))
        (*pkn)->ops = opsflgs;
    else
        (*pkn)->ops = opsflgs | numbercheck(POBJ(*pkn));
    (*pkn)->flgs = (flgs ^ (KLAAR|SUCCES));
#endif
    /* Bart 20010322 : */
    if(  !(flgs & UNIFY)
      && (flgs & (ATOOM|NONIDENT))
#if COMPILE
      && RPOBJ(*pkn)
#else
      && (*pkn)->u.obj
#endif
      )
        (*pkn)->flgs &= ~(ATOOM|NONIDENT); /* Remove superfluous flags @ and % from non-empty atom*/
    }

#if W32
#undef opsflgs
#endif
}

#if W32
#define lex(PKN,GRENS,FLGS,OPSFLGS) lex(PKN,GRENS,FLGS)
#endif

static int lex(ppsk pkn,int grens,int flgs,int opsflgs)
/* tbw zoekt een expressie of subexpressie */
/* returnwaarde is het teken volgend op de expressie */
    {
    int op_of_0;
    if(*start > 0 && *start <= '\6')
        *pkn = zelfde_als_w(adr[*start++]);
    else
        {
#if !W32
        int locopsflgs;
#endif
        int flgs;
        flgs = flags(&locopsflgs);
        if(*start == '(')
            {
            if(*++start == 0)
                (*shift)();
            lex(pkn,0,flgs,locopsflgs);
            }
        else
            atoom(pkn,flgs,locopsflgs);
        }

    if(*start == 0)
        {
        if(!*(*shift)())
            return 0;
        }

    op_of_0 = *start;

    if(*++start == 0)
        (*shift)();

    do
        {
        /* op_of_0 == een operator */
        psk operatorNode;
        int child_op_of_0;
        if(optab[op_of_0] < grens) /* 'op_of_0' heeft te lage prioriteit */
            {
            (*pkn)->flgs ^= flgs; /*19970821*/
            return op_of_0;
            }
        if(optab[op_of_0] == WORDT)
            {
            operatorNode = (psk)bmalloc(__LINE__,sizeof(objectknoop));
    /*        ((objectknoop*)psk)->refcount = 0; done by bmalloc */
            }
        else
            operatorNode = (psk)bmalloc(__LINE__,sizeof(kknoop));
#if W32
        operatorNode->flgs = optab[op_of_0] | SUCCES;
#else
        operatorNode->flgs = SUCCES;
        operatorNode->ops = optab[op_of_0];
        operatorNode->ops ^= opsflgs;
#endif
        /*operatorNode->flgs ^= flgs;*/
        operatorNode->LINKS = *pkn;
        *pkn = operatorNode;/* 'op_of_0' heeft voldoende prioriteit */
        if(optab[op_of_0] == grens) /* 'op_of_0' heeft zelfde prioriteit */
            {
            (*pkn)->flgs ^= flgs; /*19970821*/
            operatorNode->RECHTS = NULL;
            return op_of_0;
            }
        while((child_op_of_0 = lex(&(operatorNode->RECHTS),optab[op_of_0],0,0)) == op_of_0)
            {
            /* zoek rechter-operand bij op_of_0 */
            operatorNode = operatorNode->RECHTS;
            }
        op_of_0 = child_op_of_0;
        }
    while(op_of_0 != 0);
    (*pkn)->flgs ^= flgs; /*19970821*/
    return 0;
    }

static void wis(psk top);

static void bouwboom_w(ppsk pkn,unsigned char **conc)
{
if(*pkn)
    wis(*pkn);
*pkn = NULL;
start = (unsigned char *)conc[0];
pstart = (unsigned char **)conc;
shift = vshift_w;
lex(pkn,0,0,0);
shift = shift_nw;
bfree(conc);
}

static void lput(int c)
{
unsigned char **nconc;
int len;
unsigned char *lijst;
if(wijzer >= maxwijzer)
    {
    for(len=0;conc[++len];);
    lijst = conc[len-1];
    for(;wijzer > lijst && optab[*--wijzer] == NOOP;);
    if(wijzer == lijst)
        {
#if TAAL == NL
        errorprintf("String te lang (> %d bytes)\n",LIJSTLEN-1);
#else
        errorprintf("String too long (> %d bytes)\n",LIJSTLEN-1);
#endif
        return;
        /*exit(1);*/
        }
    ++wijzer;           /* eerste teken na operator */
    /* maxwijzer - wijzer >= 0 */
    nconc = (unsigned char**)bmalloc(__LINE__,(2+len)*sizeof(char*));
    nconc[len] = lijst;
    nconc[--len] = (unsigned char*)bmalloc(__LINE__,(size_t)(wijzer - lijst + 1));
    strncpy((char*)nconc[len],(char*)lijst,(size_t)(wijzer - lijst));
    nconc[len][(unsigned)(wijzer - lijst)] = 0;
    strncpy((char*)lijst,(char*)wijzer,(size_t)(maxwijzer - wijzer));
    wijzer = lijst + (size_t)(maxwijzer - wijzer);
    for(;len--;)
        nconc[len] = conc[len];
    bfree(conc);
    conc = nconc;
    }
*wijzer++ = (unsigned char)c;
}

void writeError(psk pkn)
    {
    FILE *redfpo;
    int redMooi;
    redMooi = mooi;
    mooi = FALSE;
    redfpo = fpo;
#ifdef BRACMATEMBEDDED
    fpo = stderr;
#else
    fpo = errorStream;
#endif
    errorprintf(" in:\n");
    result(pkn);
    myputc('\n');
    fpo = redfpo;
    mooi = redMooi;
    }

#ifndef BRACMATEMBEDDED
static int redirectError(char * name)
    {
    if(errorFileName)
        {
        free(errorFileName);
        errorFileName = NULL;
        }

    if(errorStream && errorStream != stdout && errorStream != stderr)
        fclose(errorStream);

    if(!strcmp(name,"stdout"))
        {
        errorStream = stdout;
        return TRUE;
        }
    else if(!strcmp(name,"stderr"))
        {
        errorStream = stderr;
        return TRUE;
        }
    else
        {
        errorStream = fopen(name,"w");
        if(errorStream)
            {
/*            errorFileName = strdup(name);*/
			errorFileName = (char *)malloc(strlen(name)+1);
			strcpy(errorFileName,name);
            return TRUE;
            }
        errorStream = stderr;
        }
    return FALSE;
    }
#endif

static Boolean input(FILE *fpi,ppsk pkn,int echmemvapstr,Boolean * err)
{
int accolades,ikar,hasop,lucht,escape,noEscape,string,haken,error;
#ifdef __SYMBIAN32__
unsigned char * lijst;
lijst = bmalloc(__LINE__,LIJSTLEN);
#else
unsigned char lijst[LIJSTLEN];
#endif
maxwijzer = lijst + (LIJSTLEN - 1);/* er moet ruimte zijn voor afsluitende 0 */
conc = (unsigned char**)bmalloc(__LINE__,2*sizeof(char*));
error = FALSE;
conc[0] = lijst;
conc[1] = NULL;
accolades = 0;
haken = 0;
hasop = TRUE;
lucht = FALSE;
escape = FALSE;
noEscape = FALSE; /* @"C:\dir1\bracmat" */
string = FALSE;

if(echmemvapstr & 3 /* VAP || STR */)
    {
    for(wijzer = lijst;;)
        {
        if(fpi)
            {
            ikar = mygetc(fpi);
            if(fpi == stdin)
               {
               if(ikar == '\n')
                   break;
               }
            else if(ikar == EOF)
               break;
            }
        else
            if((ikar = *bron++) == 0)
                break;
        if(ikar & 0x80)
             lput(0x7F);
        lput(ikar | 0x80);
        if(echmemvapstr & 2 /* VAP */)
            {
            if(echmemvapstr & 1 /* STR */ )
                lput(' ' | 0x80);
            else
                lput(' ');
            }
        }
    *wijzer = 0;
    bouwboom_w(pkn,conc);
    if(err) *err = error;
#ifdef __SYMBIAN32__
    bfree(lijst);
#endif
    return FALSE;
    }
for(wijzer = lijst;
    (ikar = fpi ? mygetc(fpi) : *bron++) != EOF
    && haken >= 0;)
    {
    if((ikar & 0x80) && !accolades)
        lput(0x7F);
    if(echmemvapstr & 8 /* ECH */)
        {
        if(fpi != stdin && ikar)
            printf("%c",ikar);
        if(ikar == '\n')
            {
            if(accolades)
                printf("{com} ");
            else if(string)
                printf("{str} ");
            else if(haken > 0 || fpi != stdin)
                {
                int tel;
                printf("{%d} ",haken);
                if(fpi == stdin)
                    for(tel = haken;tel;tel--)
                            printf("  ");
                }
            }
        }
    if(escape)
        {
        escape = FALSE;
#if SIGNED_CHAR
        if(ikar >= 0 && ikar < ' ')
#else
        if(ikar < ' ')
#endif
            break;
        switch(ikar)
            {
            case 'n' :
                ikar = '\n' | 0x80;
                break;
            case 'f' :
                ikar = '\f' | 0x80;
                break;
            case 'r' :
                ikar = '\r' | 0x80;
                break;
            case 'b' :
                ikar = '\b' | 0x80;
                break;
#ifndef vax
            case 'a' :
                ikar = ALERT | 0x80;
                break;
#endif
            case 'v' :
                ikar = '\v' | 0x80;
                break;
            case 't' :
                ikar = '\t' | 0x80;
                break;
            case '"' :
                ikar = '"' | 0x80;
                break;
            case 'L' :
                ikar = 016;
                        break;
            case 'D' :
                ikar = 017;
            }
        }
    else if(ikar == '\\' && !accolades && !noEscape)
        {
        escape = TRUE;
        continue;
        }
    if(string)
        {
        if(ikar == '"')
            {
            string = FALSE;
            noEscape = FALSE;
            }
        else
            lput(ikar | 0x80);
        }
    else
        {
        switch(ikar)
            {
            case '{' :
                accolades++;
                break;
            case '}' :
                accolades--;
                if(accolades < 0)
                    {
                    *wijzer = 0;
                    errorprintf(
#if TAAL == NL
                    "\n%s sluitaccolade }",
#else
                    "\n%s brace }",
#endif
                        onbal);
                    error = TRUE;
                    accolades = 0;
                    /*exit(1);*/
                    }
                break;
            default :
                {
                if(!accolades)
                    {
                    if(optab[ikar] == LUCHT
                    && !(ikar == '\n' && fpi == stdin && !haken))
                        {
                        lucht = TRUE;
                        noEscape = FALSE; /* Bart 20030331 */
                        }
                    else
                        {
                        switch(ikar)
                            {
                            case '"':
                                string = TRUE;
                                break;
                            case '@':
                            case '%': /* These flags are removed if the string
                                         is non-empty, so using them to
                                         indicate "do not use escape sequences"
                                         does no harm.
                                         Bart 20010322
                                     */
                                noEscape = TRUE;
                                break;
                            case '(':
                                haken++;
                                break;
                            case ')':
                                noEscape = FALSE;
                                haken--;
                                break;
                            case 0 :
                            case ';' :
                                if(haken)
                                    {
                                    *wijzer = 0;
                                    errorprintf(
                                            "\n%d %s \"(\"",
                                            haken,onbal);
                                    error = TRUE;
                                    /*exit(1);*/
                                    }
                                if(echmemvapstr & 8 /* ECH */)
                                    printf("\n");
                                /* doorvallen */
                            case '\n':
                                /* alleen met fpi==stdin kom je hier direkt */
                                *wijzer = 0;
                                bouwboom_w(pkn,conc);
                                if(error)
                                    writeError(*pkn);
                                if(err) *err = error;
#ifdef __SYMBIAN32__
                                bfree(lijst);
#endif
                                return ikar == ';' && !error;
                            }
                        if(lucht
                        && !hasop
                        && optab[ikar] == NOOP)
                            lput(' ');
                        lucht = FALSE;
                        hasop = ( (ikar == '(')
                             || ((optab[ikar] < NOOP) && ikar != ')'));

                        if(!string)
                            {
                            lput(ikar);
                            if(hasop)
                                noEscape = FALSE;
                            }
                        }
                    }
                }
            }
        }
    if(!(ikar & 0x7F))
        break;
    }
*wijzer = 0;
if(string)
    {
    errorprintf("\n%s \"",onbal);
    error = TRUE;
    /*exit(1);*/
    }
if(accolades)
    {
    errorprintf("\n%d %s \"{\"",accolades,onbal);
    error = TRUE;
    /*exit(1);*/
    }
if(haken > 0)
    {
    errorprintf("\n%d %s \"(\"",haken,onbal);
    error = TRUE;
    /*exit(1);*/
    }
if(haken < 0)
    {
    if(ikar == 'j' || ikar == 'J' || ikar == 'y' || ikar == 'Y')
        {
        exit(0);
        }
    else if(!fpi || fpi == stdin)
        {
        printf(
#if TAAL == NL
        "\nstoppen? (j/n)"
#else
        "\nend session? (y/n)"
#endif
        );
        while((ikar = mygetc(stdin)) != 'n')
            {
            if(ikar == 'j' || ikar == 'J' || ikar == 'y' || ikar == 'Y')
                {
                exit(0);
                }
            }
        while(ikar != '\n')
            {
            ikar = mygetc(stdin);
            }
        }
    else
        {
        errorprintf("\n%d %s \")\"",-haken,onbal);
        error = TRUE;
        /*exit(1);*/
        }
    }
if(echmemvapstr & 8 /* ECH */)
    printf("\n");
if(*conc[0])
    {
    bouwboom_w(pkn,conc);
    if(error)
        {
#ifndef BRACMATEMBEDDED
        if(errorFileName)
            {
            printf("Error! (See file \"%s\")\n",errorFileName);
            }
        else
            {
/*            printf("\n(Use err$<filename> to direct error output to file.)\n");
*/
            printf("\nType name of file to write erroneous code to and then press <return>: ");
            wijzer = lijst;
            while((ikar = mygetc(stdin)) != '\n')
                {
                *wijzer++ = (unsigned char)ikar;
                }
            *wijzer = '\0';
            if(lijst[0])
                redirectError((char*)lijst);
            }
#endif
        writeError(*pkn);
        }
    }
else
    bfree(conc);
if(err) *err = error;
#ifdef __SYMBIAN32__
bfree(lijst);
#endif
return FALSE;
}

#if JMP
#include <setjmp.h>
static jmp_buf jumper;
#endif

int stringEval(const char *s,char **out,int * err)
    {
    Boolean ret;
#if MICROSOFT_WINDOWS_API
    char * buf = malloc(strlen(s) + 11);
    sprintf(buf,"put$(%s,MEM)",s);
#else
    char * buf = malloc(strlen(s) + 7);
    sprintf(buf,"str$(%s)",s);
#endif
    bron = (unsigned char*)buf;
    input(NULL,&anker,4,err);
    if(err && *err) return FALSE;
#if JMP
    if(setjmp(jumper) != 0)
        {
        free(buf);
        return -1;
        }
#endif
    ret = evalueer(&anker);
    if(out != NULL)
        *out = is_op(anker) ? "" : (char*)POBJ(anker);
    free(buf);
    return ret;
    }

#if ICPY
static void icpy(long *d,long *b,int words)
    {
#ifdef vax /* parameters zijn geen locale variabelen in vcc */
    int ww;
    long *dd,*bb;
    ww = words;
    dd = d;
    bb = b;
    while(ww--)
        *dd++ = *bb++;
#else
    while(words--)
        *d++ = *b++;
#endif
    }
#endif

static psk icopievan(psk kn)
    {
    /* EISEN : Na de afsluitende 0 van string moeten eventuele resterende bytes
    van het betreffende computerwoord ook 0 zijn.
    Beide argumenten moeten op een woordgrens beginnen. */
#if COMPILE
    if(IS_RESOLVED(kn))
        {
        psk ret;
        ret = (psk)bmalloc(__LINE__,sizeof(unsigned long)+sizeof(varia*));
        ret->flgs = kn->flgs;
#if !W32
        ret->ops = kn->ops;
#endif
        ret->u.var = kn->u.var;
        ret->u.var->Refcount++;
        ret->ops &= ~OPGEBRUIKT;
        return ret;
        }
    else
        {
        psk ret;
        size_t len;
        len = sizeof(unsigned long)+strlen((char*)POBJ(kn));
        ret = (psk)bmalloc(__LINE__,len+1);
        /*    printf("BBBBB\n");*/
#if ICPY
        MEMCPY(ret,kn,(len >> LOGWORDLENGTH) + 1);
#else
        MEMCPY(ret,kn,((len >> 2) + 1) << 2);
#endif
        ret->ops &= ~OPGEBRUIKT;
        return ret;
        }
#else
    psk ret;
    size_t len;
    len = sizeof(unsigned long)+strlen((char*)POBJ(kn));
    ret = (psk)bmalloc(__LINE__,len+1);
    /*        printf("CCCCC\n");*/
#if ICPY
    MEMCPY(ret,kn,(len >> LOGWORDLENGTH) + 1);
#else
    MEMCPY(ret,kn,((len >> 2) + 1) << 2);
#endif
    ret->ops &= ~OPGEBRUIKT;
    return ret;
#endif
    }

static psk copievan(psk kn)
    {
    psk res;
    res = icopievan(kn);
    res->flgs &= ~IDENT;
    return res;
    }

static psk replace(ppsk goal,psk source)
    {
    wis(*goal);
    return *goal = copievan(source);
    }

static psk subboomcopie(psk src)
    {
    psk goal;
    if(is_op(src))
        {
        goal = new_operator_like(src);
        /*goal = (psk)bmalloc(/ *__LINE__,* /sizeof(kknoop));*/
#if !W32
        goal->flgs = src->flgs;
#endif
        goal->ops = src->ops & ~OPGEBRUIKT;
        goal->LINKS = zelfde_als_w(src->LINKS);
        goal->RECHTS = zelfde_als_w(src->RECHTS);
        return goal;
        }
    else
        return icopievan(src);
    }

static int getal_graad(psk kn)
    {
    if(RATIONAAL_COMP(kn))
        return 4;
    switch(PLOBJ(kn))
        {
        case IM: return 3;
        case PI: return 2;
        case XX: return 1;
        default: return 0;
        }
    }

static int is_constant(psk kn)
	{
	while(is_op(kn))
		{
        /* return is_constant(kn->LINKS) && is_constant(kn->RECHTS);
        18 Maart 1997 */
        if(!is_constant(kn->LINKS))
            return FALSE;
        kn = kn->RECHTS;
		}
	return getal_graad(kn);
	}

static void init_opcode(void)
    {
    int tel;
    for(tel = 0;tel<256;tel++)
        {
#if TELLING
        cnts[tel] = 0;
#endif
        switch (tel)
            {
            case 0   :
            case ')' : optab[tel] = -1   ;break;
            case '=' : optab[tel] = WORDT;break;
            case '.' : optab[tel] = DOT  ;break;
            case ',' : optab[tel] = KOMMA;break;
            case '|' : optab[tel] = OF   ;break;
            case '&' : optab[tel] = EN   ;break;
            case ':' : optab[tel] = MATCH;break;
            case '+' : optab[tel] = PLUS ;break;
            case '*' : optab[tel] = MAAL ;break;
            case '^' : optab[tel] = EXP  ;break;
            case 016 : optab[tel] = LOG  ;break;
            case 017 : optab[tel] = DIF  ;break;
            case '$' : optab[tel] = FUN  ;break;
            case '\'': optab[tel] = FUU  ;break;
            case '_' : optab[tel] = STREEP;break;
            default  : optab[tel] = (tel <= ' ') ? LUCHT : NOOP;
            }
        }
    }

static psk prive(psk pkn)
    {
    if(dubbelgebruikt(pkn))
        {
        decgebruik(pkn);
        return subboomcopie(pkn);
        }
    return pkn;
    }

static void setflgs(ppsk pokn,int flgs)
    {
    if((flgs & ERFENIS) || !(flgs & SUCCES))
        {
        *pokn = prive(*pokn);
        (*pokn)->flgs ^= ((flgs & SUCCES) ^ SUCCES);
        (*pokn)->flgs |= (flgs & ERFENIS);
        if(ONTKENNING(flgs,GROTER_DAN) || ONTKENNING(flgs,KLEINER_DAN))
            (*pokn)->flgs |= NOT;
        }
    }

static void startboom_w(ppsk pkn,...)
    {
    if(*pkn)
        wis(*pkn);
    *pkn = NULL;
    va_start(ap,pkn);
    start = startPos = va_arg(ap,unsigned char *);
    lex(pkn,0,0,0);
    va_end(ap);
    }

static psk vopb(psk pkn,const char *conc[])
    {
    psk okn;
    pstart = (unsigned char **)conc;
    start = (unsigned char *)conc[0];
    shift = vshift_nw;
    lex(&okn,0,0,0);
    shift = shift_nw;
    setflgs(&okn,pkn->flgs);
    wis(pkn);
    return okn;
    }

static psk opb(psk pkn,...)
    {
    psk okn;
    va_start(ap,pkn);
    start = startPos = va_arg(ap,unsigned char*);
    lex(&okn,0,0,0);
    va_end(ap);
    if(pkn)
        {
        setflgs(&okn,pkn->flgs);
        wis(pkn);
        }
    return okn;
    }

static void dopb(ppsk pkn,psk src)
    {
    psk okn;
    okn = zelfde_als_w(src);
    setflgs(&okn,(*pkn)->flgs);
    wis(*pkn);
    *pkn = okn;
    }



static int fireBuiltInFunc(objectknoop * object,char * name)
    {
    /*printf("find member %s\n",name);*/
    if(ISBUILTIN((objectknoop*)object))
        {
        method_pnt theMethod = NULL;
        method * methods = ((typedObjectknoop*)object)->vtab;
        /*
        printf("object==(");result((psk)object);printf(")\n");
        printf("is <%s> built-in?\n",name);
        printf("object %p\n",object);
        result((psk)object);
        printf("methods %p\n",methods);
        getchar();
        */
        if(methods)
            {
            for(;methods->name && strcmp(methods->name,name);++methods)
                ;
            theMethod = methods->func;
            }
        if(theMethod)
            {
            /*printf("theMethod found %p\n",theMethod);*/
            theMethod((struct typedObjectknoop *)object,NULL);
            return TRUE;
            }
        }
    return FALSE;
    }



static void wis(psk top)
    {
    while(!dubbelgebruikt(top)) /* 18 Maart 1997, tail recursion optimisation; delete deep structures*/
        {
        psk kn = NULL; /* 18 Maart 1997 */
#if 1
        if(is_object(top) && ISCREATEDWITHNEW((objectknoop*)top))
            {
    /*        psk kn = NULL;*/
            adr[1] = top->RECHTS;
            kn = opb(kn,"(((=\1).die)')",NULL);
            evalueer(&kn);
            wis(kn);
            if(ISBUILTIN((objectknoop*)top))
                fireBuiltInFunc((objectknoop*)top,"Die");
#ifdef OBJECTDATA
            if(((typedObjectknoop*)top)->data)
                {
                ((typedObjectknoop*)top)->data->refcount--;
                if(((typedObjectknoop*)top)->data->refcount == 0)
                    bfree(((typedObjectknoop*)top)->data->vdata);
                }
#endif
            }
#endif
        if(is_op(top))
            {
            wis(top->LINKS);
            kn = top; /* 18 Maart 1997 */
            top = top->RECHTS; /* 18 Maart 1997 */
            pskfree(kn);
            }
        else
			{
            pskfree(top);
			return;
			}
        }
    decgebruik(top);
    }

static int macht2(int n)
/* retourneert MSB van n */
{
int m;
for(m=1;n;n>>=1,m<<=1);
return m>>1;
}

static ppsk entry(int n,int index,varia **pv)
{
int m;
varia *hv;
if(n == 0)
    return (ppsk)pv;  /* er zijn geen varia records nodig voor 1 entry */
for(m = n,hv = *pv; /* begin bij langste varia record */
    m > 1 && index < macht2(m);
    m >>= 1,hv = hv->prev);
index -= macht2(m);   /* als index == 0, dan wordt index -1 */
return &hv->verdi[index];  /* verdi[-1] == (psk)*prev */
}

static int zoeknaam(psk name,
#if COMPILE
                    int * where,
#else
                    vars **pvoorvar,
#endif
                    vars **pnavar)
{
unsigned char *string;
vars *navar
#if !COMPILE
,*voorvar
#endif
;
#if COMPILE
if(IS_RESOLVED(name))
    {
    *pnavar = RESOLUTION(name);
    if(where)
        *where = 0;
    return (*pnavar)->pvaria != NULL;
    }
else
    {
    string = POBJ(name);
    navar = variabelen[*string];
    if(navar)
        while(TRUE)
            {
#ifdef PVNAME
            int cmp = STRCMP(navar->vname,string);
#else
            int cmp = STRCMP(&navar->u.Obj,string);
#endif
            if(cmp == 0)
                {
                if(where)
                    *where = 0;
                *pnavar = navar;
                RESOLVE(name,navar);
                return (*pnavar)->pvaria != NULL;
                }
            else if(cmp > 0)
                {
                if(where)
                    *where = 1;
                *pnavar = navar;
                return FALSE;
                }
            else if(navar->next)
                {
                assert(navar == navar->next->Prev);
                navar = navar->next;
                }
            else
                {
                *pnavar = navar;
                if(where)
                    *where = -1;
                return FALSE;
                }
            }
    else
        {
        if(where)
            *where = -1;
        *pnavar = NULL;
        return FALSE;
        }
    }
#else
string = POBJ(name);
for(voorvar = NULL,navar = variabelen[*string];
#ifdef PVNAME
    navar && (STRCMP(navar->vname,string) < 0);
#else
    navar && (STRCMP(&navar->u.Obj,string) < 0);
#endif
    voorvar = navar,navar = navar->next);
/* voorvar < string <= navar */
*pvoorvar = voorvar;
*pnavar = navar;
#ifdef PVNAME
return navar && !STRCMP(navar->vname,string);
#else
return navar && !STRCMP(&navar->u.Obj,string);
#endif
#endif
}

#if WRITETRACE
static void writeTrace(psk pkn)
    {
    FILE *redfpo;
    int redMooi;
    int redhum;
    redMooi = mooi;
    redhum = hum;
    mooi = FALSE;
    redfpo = fpo;
    fpo = fopen("log","a");
    hum = FALSE;
    result(pkn);
    myputc('\n');
    fclose(fpo);
    fpo = redfpo;
    mooi = redMooi;
    hum = redhum;
    }

#include "log.h"
LOGCODE

#endif


static Qgetal _qmaalmineen(Qgetal _qx)
{
Qgetal res;
#if COMPILE
res = icopievan(_qx);
res->ops ^= MINUS;
#else
int len;
len = sizeof(long) + 1 + strlen((char*)POBJ(_qx));
res = (Qgetal)bmalloc(__LINE__,len);
memcpy(res,_qx,len);
res->ops ^= MINUS;
res->ops &= ~OPGEBRUIKT;
#endif
#if WRITETRACE
Log("_qmaalmineen(Qgetal _qx)");
writeTrace(_qx);
writeTrace(res);
Log("_qmaalmineen(Qgetal _qx) done");
#endif
return res;
}

static psk numberNode(ngetal g)
{
psk res;
res = (psk)bmalloc(__LINE__,sizeof(long) + 1 + g.length);
if(g.sign & QNUL)
#if COMPILE
    res->u.Obj = '0';
#else
    res->u.obj = '0';
#endif
else
    memcpy((void*)POBJ(res),g.number,g.length);
/*(char*)POBJ(res) + g.length = '\0'; hoeft niet, gebeurt in bmalloc */
#if W32
res->flgs = KLAAR | SUCCES | QGETAL;
#else
res->flgs = KLAAR | SUCCES;
res->ops = QGETAL;
#endif
res->ops |= g.sign;
return res;
}

static psk fnumberNode(ngetal g)
{
psk res;
res = numberNode(g);
bfree(g.alloc);
return res;
}

static Qgetal not_a_number(void)
{
Qgetal res;
res = copievan(&nulk);
res->flgs ^= SUCCES;
return res;
}

#if WRITETRACE
static char *splits(Qgetal _qget,ngetal *ptel,ngetal *pnoem)
{
register char *on;
Log("ptel->sign = _qget->ops & (MINUS|QNUL);");
ptel->sign = _qget->ops & (MINUS|QNUL);
Log("pnoem->sign = 0;");
pnoem->sign = 0;
Log("pnoem->alloc = ptel->alloc = NULL;");
pnoem->alloc = ptel->alloc = NULL;
Log("for(ptel->number = on = (char *)POBJ(_qget); %p",(char *)POBJ(_qget));
Log("for(ptel->number = on = (char *)POBJ(_qget); %s",(char *)POBJ(_qget));
for(ptel->number = on = (char *)POBJ(_qget);
    *on && *on != '/';
    on++
   )
Log("%c",*on);
   ;
Log("ptel->length = on - ptel->number;");
ptel->length = on - ptel->number;
Log("if(*on)");

if(*on)
    {
Log("pnoem->number = on + 1;");
    pnoem->number = on + 1;
Log("pnoem->length = strlen(on + 1);");
    pnoem->length = strlen(on + 1);
Log("return on;");
    return on;
    }
else
    {
Log("pnoem->number = 1;");
    pnoem->number = "1";
Log("pnoem->length = 1;");
    pnoem->length = 1;
Log("return NULL;");
    return NULL;
    }
}
#else
static char *splits(Qgetal _qget,ngetal *ptel,ngetal *pnoem)
{
register char *on;
ptel->sign = _qget->ops & (MINUS|QNUL);
pnoem->sign = 0;
pnoem->alloc = ptel->alloc = NULL;
for(ptel->number = on = (char *)POBJ(_qget);
    *on && *on != '/';
    on++
   );
ptel->length = on - ptel->number;

if(*on)
    {
    pnoem->number = on + 1;
    pnoem->length = strlen(on + 1);
    return on;
    }
else
    {
    pnoem->number = "1";
    pnoem->length = 1;
    return NULL;
    }
}
#endif
static void skipnullen(ngetal *nget,int teken)
{
for(;nget->length > 0 && *(nget->number) == '0';
    nget->number++,nget->length--);
nget->sign = nget->length ? (teken & MINUS) : QNUL;
}

static ngetal nmaal(ngetal x,ngetal y)
{
ngetal res;
char *i1,*i2;
char *wyzer,*tussen;
res.length = x.length+y.length;
res.alloc = res.number = (char*)bmalloc(__LINE__,(size_t)res.length);
for(wyzer = res.number;wyzer - res.number < res.length;*wyzer++ = '0');
for(i1 = x.number + x.length - 1;i1 >= x.number;i1--)
    {
    tussen = --wyzer;
    for(i2 = y.number + y.length - 1;i2 >= y.number;i2--)
        {
        register char prod;
        register char karry;
        register char *tussen2;
        prod = (*i1-'0')*(*i2-'0');
        *tussen += (prod%10);
        karry = prod/10;
        tussen2 = tussen--;
        do
            {
            if(*tussen2 > '9')
                {
                karry++;
                *tussen2 -= 10;
                }
            --tussen2;
            *tussen2 = *tussen2 + karry;
/*            *--tussen2 += karry;*/
            karry = 0;
            }
        while(*tussen2 > '9');
        }
    }
skipnullen(&res,x.sign ^ y.sign);
return res;
}

static void opaf(char **pres,char *bx,char *ex,char *by,char *ey,int act)

{
register char *i1,*i2,*wyzer;
register int lcarry;
lcarry = 0;
i1 = *pres;
i2 = ex;
wyzer = ey;
do
    {
    *i1 = (char)(*i2 + lcarry + act * (*wyzer-'0'));
    if(*i1 > '9')
        {
        lcarry = 1;
        *i1 -= (char)10;
        }
    else
        if(*i1 < '0')
            {
            lcarry = -1;
            *i1 += (char)10;
            }
        else
            lcarry = 0;
    i1--;
    i2--;
    wyzer--;
    }
while(wyzer >= by);
for(;i2 >= bx;)
    {
    *i1 = (char)(*i2 + lcarry);
    if(*i1 > '9')
        {
        lcarry = 1;
        *i1 -= (char)10;
        }
    else
        if(*i1 < '0')
            {
            lcarry = -1;
            *i1 += (char)10;
            }
        else
            lcarry = 0;
    i1--;
    i2--;
    }
*pres = i1+1;
carry = lcarry;
}

static int nndeel(ngetal x,ngetal y,deelres *pres)
{
char *i1,*i2,*i3;
ngetal hquot,hrest;
if(y.sign & QNUL)
    return FALSE;
hrest.length = x.sign & QNUL ? 1 : x.length;
hrest.alloc = hrest.number = (char*)bmalloc(__LINE__,(size_t)(hrest.length));
*(hrest.number) = '0';
memcpy(hrest.number,x.number,x.length);
if(x.length >= y.length)
    hquot.length = 1 + x.length - y.length;
else
    hquot.length = 1;
hquot.alloc = hquot.number = (char*)bmalloc(__LINE__,(size_t)(hquot.length));
*(hquot.number) = '0';
i3 = hquot.number;
for(i1 = hrest.number + (size_t)y.length - 1;
    i1 - hrest.number < x.length;
    i1++,i3++)
    {
    *i3 = '0'-1;
    do
        {
        i2 = i1;
        opaf(&i2,hrest.number,i1,y.number,y.number + y.length - 1,-1);
        (*i3)++;
        }
    while(!carry);
    i2 = i1;
    opaf(&i2,hrest.number,i1,y.number,y.number + y.length - 1,1);
    }
skipnullen(&hrest,x.sign);
skipnullen(&hquot,x.sign ^ y.sign);
pres->rest = hrest;
pres->quot = hquot;
return TRUE;
}

static int numberIs1(ngetal x)
{
return x.number[0] == '1' && x.length == 1;
}

static Qgetal _qndeel(ngetal x,ngetal y)
{
Qgetal res;
deelres resx,resy;
ngetal ggd,hrest;

if(x.sign & QNUL)
    return copievan(&nulk);
else
    if(y.sign & QNUL)
        return not_a_number();
ggd = x;
ggd.alloc = NULL;
hrest = y;
hrest.alloc = NULL;
do
    {
    nndeel(ggd,hrest,&resx);
    if(ggd.alloc)
        bfree(ggd.alloc);
    ggd = hrest;
    hrest = resx.rest;
    bfree(resx.quot.alloc);
    }
while(!(hrest.sign & QNUL));
if(hrest.alloc)
    bfree(hrest.alloc);

nndeel(x,ggd,&resx);
bfree(resx.rest.alloc);

nndeel(y,ggd,&resy);
bfree(resy.rest.alloc);
if(ggd.alloc)
    bfree(ggd.alloc);
resx.quot.sign ^= (resy.quot.sign & MINUS);

if(numberIs1(resy.quot))
    {
    res = numberNode(resx.quot);
    }
else
    {
    res = (psk)bmalloc(__LINE__,sizeof(long) + 2 + resx.quot.length + resy.quot.length);
    sprintf((char*)POBJ(res),"%.*s/%.*s",
     (int /*size_t*/)resx.quot.length,resx.quot.number,
     (int /*size_t*/)resy.quot.length,resy.quot.number);
#if W32
    res->flgs = KLAAR | SUCCES | QGETAL | QBREUK;
#else
    res->flgs = KLAAR | SUCCES;
    res->ops = QGETAL | QBREUK;
#endif
    res->ops |= resx.quot.sign;
    }
bfree(resx.quot.alloc);
bfree(resy.quot.alloc);
return res;
}

static ngetal nplus(ngetal x,ngetal y)
{
ngetal res,hget;
char *hres;
/*int 20031126*/ptrdiff_t xgrotery;
res.length = 1+(x.length>y.length ? x.length : y.length);
res.alloc = res.number = (char*)bmalloc(__LINE__,(size_t)res.length);
*res.number = '0';
hres = res.number+(size_t)res.length - 1;
if(x.length == y.length)
    xgrotery = strncmp(x.number,y.number,(size_t)res.length);
else
    xgrotery = x.length - y.length;
if(xgrotery < 0)
    {
    hget = x;
    x = y;
    y = hget;
    }
if(x.sign == y.sign)
    {
    opaf(&hres,x.number,x.number + x.length - 1,
               y.number,y.number + y.length - 1,1);
    if(carry)
        *--hres = '1';
    }
else
    opaf(&hres,x.number,x.number + x.length - 1,
               y.number,y.number + y.length - 1,-1);
skipnullen(&res,x.sign);
return res;
}

#if WRITETRACE
static Qgetal _qplus(Qgetal _qx,Qgetal _qy)
{
ngetal xt,xn,yt,yn;
char *xb,*yb;
Log("xb = splits(_qx,&xt,&xn);");
xb = splits(_qx,&xt,&xn);
Log("yb = splits(_qy,&yt,&yn);");
yb = splits(_qy,&yt,&yn);
Log("if(!xb && !yb)");
if(!xb && !yb)
    {
    Qgetal ret;
#if OBJECTS
    int objectFlg;
Log("objectFlg = (_qx->flgs & OBJECT) ^ (_qy->flgs & OBJECT);");
    objectFlg = (_qx->flgs & OBJECT) ^ (_qy->flgs & OBJECT);
#endif
Log("ret = fnumberNode(nplus(xt,yt));");
    ret = fnumberNode(nplus(xt,yt));
#if OBJECTS
Log("ret->flgs |= objectFlg;");
    ret->flgs |= objectFlg;
#endif
Log("return ret;");
    return ret;
    }
else
    {
    ngetal pa,pb,som;
    Qgetal res;
Log("pa = nmaal(xt,yn);");
    pa = nmaal(xt,yn);
Log("pb = nmaal(yt,xn);");
    pb = nmaal(yt,xn);
Log("som = nplus(pa,pb);");
    som = nplus(pa,pb);
Log("pskfree(pa.alloc);");
    bfree(pa.alloc);
Log("pskfree(pb.alloc);");
    bfree(pb.alloc);
Log("pa = nmaal(xn,yn);");
    pa = nmaal(xn,yn);
Log("res = _qndeel(som,pa);");
    res = _qndeel(som,pa);
Log("pskfree(som.alloc);");
    bfree(som.alloc);
Log("pskfree(pa.alloc);");
    bfree(pa.alloc);
Log("return res;");
    return res;
    }
}

#else
static Qgetal _qplus(Qgetal _qx,Qgetal _qy)
{
ngetal xt,xn,yt,yn;
char *xb,*yb;
xb = splits(_qx,&xt,&xn);
yb = splits(_qy,&yt,&yn);
if(!xb && !yb)
    {
    Qgetal ret;
#if OBJECTS
    int objectFlg;
    objectFlg = (_qx->flgs & OBJECT) ^ (_qy->flgs & OBJECT);
#endif
    ret = fnumberNode(nplus(xt,yt));
#if OBJECTS
    ret->flgs |= objectFlg;
#endif
    return ret;
    }
else
    {
    ngetal pa,pb,som;
    Qgetal res;
    pa = nmaal(xt,yn);
    pb = nmaal(yt,xn);
    som = nplus(pa,pb);
    bfree(pa.alloc);
    bfree(pb.alloc);
    pa = nmaal(xn,yn);
    res = _qndeel(som,pa);
    bfree(som.alloc);
    bfree(pa.alloc);
    return res;
    }
}

#endif

static Qgetal _qdema(ngetal x1,ngetal x2,ngetal y1,ngetal y2)
{
ngetal pa,pb;
Qgetal res;
pa = nmaal(x1,y1);
pb = nmaal(x2,y2);
res = _qndeel(pa,pb);
bfree(pa.alloc);
bfree(pb.alloc);
return(res);
}

static Qgetal _qmaal(Qgetal _qx,Qgetal _qy)
{
ngetal xt,xn,yt,yn;
char *xb,*yb;
xb = splits(_qx,&xt,&xn);
yb = splits(_qy,&yt,&yn);
if(!xb && !yb)
    return fnumberNode(nmaal(xt,yt));
else
    {
    Qgetal res;
    res = _qdema(xt,xn,yt,yn);
    return res;
    }
}

static Qgetal _q_qdeel(Qgetal _qx,Qgetal _qy)
{
ngetal xt,xn,yt,yn;
char *xb,*yb;
xb = splits(_qx,&xt,&xn);
yb = splits(_qy,&yt,&yn);
if(!xb && !yb)
    return _qndeel(xt,yt);
else
    {
    Qgetal res;
    res = _qdema(xt,xn,yn,yt);
    return res;
    }
}


static Qgetal _qheeldeel(Qgetal _qx,Qgetal _qy)
{
int ok;
deelres deling;
Qgetal res,hulp;
ngetal xt,xn,yt,yn,p1,p2;
splits(_qx,&xt,&xn);
splits(_qy,&yt,&yn);
p1 = nmaal(xt,yn);
p2 = nmaal(xn,yt);
ok = nndeel(p1,p2,&deling);
bfree(p1.alloc);
bfree(p2.alloc);
if(ok)
    {
    res = _qplus((deling.rest.sign & QNUL) || !(_qx->ops & MINUS) ?
                &nulk : (_qy->ops & MINUS) ? &eenk : &mineenk,
                (hulp = numberNode(deling.quot)));
    pskfree(hulp);
    bfree(deling.quot.alloc);
    bfree(deling.rest.alloc);
    }
else
    res = not_a_number();
return res;
}

static Qgetal _qmodulo(Qgetal _qx,Qgetal _qy)
{
Qgetal res,_q1,_q2,_q3;
_q1 = _qmaalmineen(_qy);
_q2 = _qheeldeel(_qx,_qy);
_q3 = _qmaal(_q1,_q2);
pskfree(_q1);
pskfree(_q2);
res = _qplus(_qx,_q3);
pskfree(_q3);
return res;
}

static Qgetal _qdenominator(Qgetal _qx)
{
ngetal xt,xn;
splits(_qx,&xt,&xn);
return numberNode(xn);
}

static int range(psk kn)
{
  if(      LESS(kn)) return -2;
  if(LESS_EQUAL(kn)) return -1;
  if(MORE_EQUAL(kn)) return  1;
  if(      MORE(kn)) return  2;
  return 0;
}
#if 0
static int rangedivide(psk kn1,psk kn2,int sign)
{
/*
     >2 /  3 = >  2/3
     >2 / -3 = < -2/3
     <2 /  3 = <  2/3
     <2 / -3 = > -2/3

      2 / >3   = <  2/3 && > 0  error
      2 / > -3 = < -2/3 || > 0  error
      2 / <3   = >  2/3 || < 0  error
      2 / < -3 = > -2/3 && < 0  error
*/


   int ra1,ra2,ra12;
   ra1 = range(kn1);
   ra2 = range(kn2);
   if(  ((kn1->ops & MINUS && 1) ^ (ra1 < 0))
     || ((kn2->ops & MINUS && 1) ^ (ra2 < 0))
     )
       return 99; /* error */
   ra12 = ra1 * ra2;
   if(ra12 == 0)
       {
       if(ra1 == 0)
           return -ra2;
       return ra1;
       }
   if(ra12 < 0)
       {
       if(ra12 < -1)
           return ra1 < 0 ? -2 : 2;
       return ra1 < 0 ? -1 : 1;
       }
   if(ra12 > 0)
       {
       if(ra12 > 1)
           return ra1 < 0 ? -2 : 2;
       return ra1 < 0 ? -1 : 1;
       }
return 0;
}

static int rangemultiply(psk kn1,psk kn2)
{
   int ra1,ra2,ra12;
   ra1 = range(kn1);
   ra2 = range(kn2);
   ra12 = ra1 * ra2;
   if(ra12 < 0)
       return 99; /* error */
   if(ra12 == 0)
       {
       if(ra1 == 0)
           return -ra2;
       return ra1;
       }
   if(ra12 < -1)
       return ra1 < 0 ? -2 : 2;
   return ra1 < 0 ? -1 : 1;
}
#endif


static int _qvergelijk(Qgetal _qx,Qgetal _qy)
{
Qgetal min_qy,som;
int res;
#if WRITETRACE
Log("min_qy = _qmaalmineen(_qy);");
#endif
min_qy = _qmaalmineen(_qy);
#if WRITETRACE
Log("som = _qplus(_qx,min_qy);");
#endif
som = _qplus(_qx,min_qy);
#if WRITETRACE
Log("pskfree(min_qy);");
#endif
pskfree(min_qy);
#if WRITETRACE
Log("res = som->ops & (MINUS|QNUL);");
#endif
res = som->ops & (MINUS|QNUL);
#if WRITETRACE
Log("pskfree(som);");
#endif
pskfree(som);
#if WRITETRACE
Log("OK");
#endif
return res;
}

static int vgl(psk kn1,psk kn2)
    {
    while(kn1 != kn2)
        {
        register int r;
        if(is_op(kn1))
            if(is_op(kn2))
                {
                r = (int)kop(kn2) - (int)kop(kn1);
                if(r)
                    return r;
                r = vgl(kn1->LINKS,kn2->LINKS);
                if(r)
                    return r;
                    /* return vgl(kn1->RECHTS,kn2->RECHTS);
                18 Maart 1997 */
                kn1 = kn1->RECHTS;
                kn2 = kn2->RECHTS;
                /*19970825  continue;*/
                }
            else
                return 1;
            else if(is_op(kn2))
                return -1;
            else if(RATIONAAL_COMP(kn1) && RATIONAAL_COMP(kn2))
                {
                switch(_qvergelijk(kn1,kn2))
                    {
                    case MINUS: return -1;
                    case QNUL:
                        {
                        int diff;
                        if(RATIONAAL(kn1) || RATIONAAL(kn2))
                            return 0;
                        diff = range(kn1) - range(kn2);
                        if(diff < 0)
                            return -1;
                        if(diff > 0)
                            return 1;
                        return 0;
                        }
                    default: return 1;
                    }
                }
            else
                return (r = HAS_MINUS_SIGN(kn1) - HAS_MINUS_SIGN(kn2)) == 0
                ? strcmp((char*)POBJ(kn1),(char*)POBJ(kn2))
                : r;
            /*19970825 break;*/
        }
    return 0;
    }

/*
name must be atom or <atom>.<atom>.<atom>...
*/
static int setmember(psk name,psk tree,psk nieuw)
    {
    while(is_op(tree))
        {
        if(kop(tree) == WORDT)
            {
            psk nname;
            if(kop(name) == DOT)
                nname = name->LINKS;
            else
                nname = name;
            if(vgl(tree->LINKS,nname))
				{
                return FALSE;
				}
            else if(nname == name)
                {
                wis(tree->RECHTS);
                tree->RECHTS = zelfde_als_w(nieuw);
                return TRUE;
                }
            else /* Found partial match for member name,
                    recurse in both name and member */
                {
                name = name->RECHTS;
                }
            }
        else if(setmember(name,tree->LINKS,nieuw))
			{
            return TRUE;
			}
        tree = tree->RECHTS;
        }
    return FALSE;
    }

static int update(psk name,psk pknoop)
{
vars *navar
#if !COMPILE
,*voorvar
#endif
;
if(is_op(name->LINKS))
    {
    if(kop(name->LINKS) == WORDT)
        return setmember(name->RECHTS,name->LINKS->RECHTS,pknoop);
    else
		{
        return FALSE;
		}
    }
if(zoeknaam(name->LINKS,
#if COMPILE
            NULL,
#else
            &voorvar,
#endif
            &navar))
    {
    psk pkn;
    assert(navar->pvaria);
    pkn = *entry(navar->n,navar->selector,&navar->pvaria);
    return setmember(name->RECHTS,pkn,pknoop);
    }
else
	{
    return FALSE;
	}
}


static int insert(psk name,psk pknoop)
    {
#if COMPILE
    vars *navar,*nieuwvar;
    int where;
#else
    vars *navar,*voorvar,*nieuwvar;
#endif

    if(is_op(name))
        {
        if(kop(name) == WORDT)
            {
            wis(name->RECHTS);
            name->RECHTS = zelfde_als_w(pknoop);
            return TRUE;
            }
        else
            {
            return update(name,pknoop);
    /*        return FALSE;*/
            }
        }
    if(zoeknaam(name,
#if COMPILE
                &where,
#else
                &voorvar,
#endif
                &navar))
        {
        ppsk ppkn;
#if COMPILE
        assert(navar->pvaria);
        ppkn = entry(navar->n,navar->selector,&navar->pvaria);
        if(*ppkn)
            wis(*ppkn);
#else
        wis(*(ppkn = entry(navar->n,navar->selector,&navar->pvaria)));
#endif
        *ppkn = zelfde_als_w(pknoop);
        }
#if COMPILE
    else if(where == 0)
        {
        navar->n = 0;
        navar->selector = 0;
        navar->pvaria = (varia*)zelfde_als_w(pknoop);
        navar->Refcount++; /*!!*/
        }
#endif
    else
        {
#if COMPILE
#if ALLOCVAR
        size_t len;
        unsigned char *string;
        string = POBJ(name);
        len = strlen((char*)string);
        nieuwvar = allocVars(len);
        if(*string)
            {
        /*printf("DDDD\n");*/
#if ICPY
            MEMCPY(&nieuwvar->u.Obj,string,(len >> LOGWORDLENGTH)+1);
#else
            MEMCPY(&nieuwvar->u.Obj,string,((len >> 2)+1) << 2);
#endif
            }
        else
            {
            nieuwvar->u.Lobj = LOBJ(nilk);
            }
        /*nieuwvar =*/ makeNewVar(nieuwvar,where,navar);
#else
        size_t len;
        unsigned char *string,*varname;
        string = POBJ(name);
        len = strlen((char*)string);
        if(*string)
            {
        /*printf("EEEEEE\n");*/
#if ICPY
            MEMCPY(varname = (unsigned char*)
                 bmalloc(__LINE__,len+1),string,(len >> LOGWORDLENGTH)+1);
#else
            MEMCPY(varname = (unsigned char*)
                 bmalloc(__LINE__,len+1),string,((len >> 2)+1) << 2);
#endif
            }
        else
            {
            varname = OBJ(nilk);
            }
        nieuwvar = makeNewVar(varname,where,navar);
        bfree(varname);
#endif
#else
        size_t len;
        unsigned char *string;
        string = POBJ(name);
        len = strlen((char*)string);
#ifdef PVNAME
        nieuwvar = (vars*)bmalloc(__LINE__,sizeof(vars));
        if(*string)
            {
            /*printf("FFFFF\n");*/
#if ICPY
            MEMCPY(nieuwvar->vname = (unsigned char*)
                 bmalloc(__LINE__,len+1),string,(len >> LOGWORDLENGTH)+1);
#else
            MEMCPY(nieuwvar->vname = (unsigned char*)
                 bmalloc(__LINE__,len+1),string,((len >> 2)+1) << 2);
#endif
            }
#else
#if ALLOCVAR
        nieuwvar = allocVars(len);
#else
        if(len < 4)
            nieuwvar = (vars*)bmalloc(__LINE__,sizeof(vars));
        else
            nieuwvar = (vars*)bmalloc(__LINE__,sizeof(vars) - 3 + len);
#endif
        if(*string)
            {
            /*printf("GGGGG %s\n",string);*/
#if ICPY
            MEMCPY(&nieuwvar->u.Obj,string,(len >> LOGWORDLENGTH)+1);
#else
            MEMCPY(&nieuwvar->u.Obj,string,((len >> 2)+1) << 2);
#endif
            }
#endif
        else
            {
#ifdef PVNAME
            nieuwvar->vname = OBJ(nilk);
#else
            nieuwvar->u.Lobj = LOBJ(nilk);
#endif
            }
        nieuwvar->next = navar;
        if(voorvar == NULL)
            variabelen[*string] = nieuwvar;
        else
            voorvar->next = nieuwvar;
        nieuwvar->n = 0;
        nieuwvar->selector = 0;
#endif
        nieuwvar->pvaria = (varia*)zelfde_als_w(pknoop);
        }
    return TRUE;
    }

static int copy_insert(psk name,psk pknoop,psk snijaf)
    {
    psk kn;
    int ret;
    if(pknoop->flgs & IDENT)
        {
        kn = copievan(pknoop);
        }
    else if(snijaf == NULL)
        {
        return insert(name,pknoop);
        }
    else if(pknoop->RECHTS == snijaf)
        {
        kn = zelfde_als_w(pknoop->LINKS);
        }
    else if(!opgebruikt(pknoop) && !opgebruikt(snijaf))
        {
        kn = new_operator_like(pknoop);
        /*kn = (psk)bmalloc(/ *__LINE__,* /sizeof(kknoop));*/
#if !W32
        kn->flgs = pknoop->flgs;
#endif
        kn->ops = (pknoop->ops & ~OPGEBRUIKT) | LATEBIND;
        incgebruik(pknoop);
        incgebruik(snijaf);
        kn->LINKS = pknoop;
        kn->RECHTS = snijaf;
        }
    else
        {
        psk *pp,p;
        for(pp = &kn;;pp = &(p->RECHTS),pknoop = pknoop->RECHTS)
            {
            if(is_op(pknoop))
                {
                if(pknoop->RECHTS == snijaf)
                    {
                    *pp = zelfde_als_w(pknoop->LINKS);
                    break;
                    }
                else
                    {
                    *pp = p = new_operator_like(pknoop);
                    /* *pp = p = (psk)bmalloc(/ *__LINE__,* /sizeof(kknoop)); */
#if !W32
                    p->flgs = pknoop->flgs;
#endif
                    p->ops = pknoop->ops & ~OPGEBRUIKT;
                    p->LINKS = zelfde_als_w(pknoop->LINKS);
                    }
                }
            else
                {
                *pp = icopievan(pknoop);
                break;
                }
            }
        }
    ret = insert(name,kn);
    wis(kn);
    return ret;
    }

static int scopy_insert(psk name,unsigned char * str)
    {
	int ret;
	int nr = fullnumbercheck(str);
	psk kn;
	if(nr & MINUS)
		{
		kn = (psk)bmalloc(__LINE__,sizeof(unsigned long) + strlen((const char *)str));
		strcpy((char *)POBJ(kn),(char *)str + 1);
		}
	else
		{
		kn = (psk)bmalloc(__LINE__,sizeof(unsigned long) + 1 + strlen((const char *)str));
		strcpy((char *)POBJ(kn),(char *)str);
		}
#if W32
    kn->flgs = KLAAR | SUCCES | nr;
#else
    kn->ops = nr;
    kn->flgs = KLAAR | SUCCES;
#endif
	ret = insert(name,kn);
	wis(kn);
	return ret;
    }

static int assign(ppsk pkn)
{
#if 1
register psk lknoop;
if(is_op(lknoop = (*pkn)->LINKS))
    {
    return update(lknoop,(*pkn)->RECHTS);
/*    return FALSE;*/
    }
else
	{
    insert(lknoop,(*pkn)->RECHTS);
	}
return TRUE;
#else
return insert((*pkn)->LINKS,(*pkn)->RECHTS);
#endif
}

#define NIET (p->flgs & NOT && (p->flgs & FLGS) < NUMBER)
#define PGRT (p->flgs & GROTER_DAN)
#define PKLN (p->flgs & KLEINER_DAN)
#define PONG  (PGRT && PKLN)
#define EPGRT (PGRT && !PKLN)
#define EPKLN (PKLN && !PGRT)

static int compare(psk s,psk p)
    {
    int teken;
#if WRITETRACE
    Log("compare");
    writeTrace(s);
    writeTrace(p);
#endif
    /*if(RATIONAAL_COMP(s) && RATIONAAL_COMP(p))*/
    if(RATIONAAL_COMP(s) && RATIONAAL_WEAK(p))
        teken = _qvergelijk /*bereken_verschil*/(s,p);
    else
        {
        if(is_op(s))
            return NIKS(p);
        teken = strcmp((char*)POBJ(s),(char*)POBJ(p));
        if(teken > 0)
            teken = 0;
        else if(teken < 0)
            teken = MINUS;
        else
            teken = QNUL;
        }
    switch(teken)
        {
        case 0 :
			{
            if(s->flgs & KLEINER_DAN)
                return FALSE;
            return NIET ^ (PGRT && 1);
			}
        case QNUL :
			{
            switch(s->flgs & (GROTER_DAN|KLEINER_DAN))
                {
                case GROTER_DAN|KLEINER_DAN :
                    return NIET ^ PONG;
                case GROTER_DAN :
                    return NIET ^ PONG ^ EPGRT;
                case KLEINER_DAN :
                    return NIET ^ PONG ^ EPKLN;
                default :
                    return !NIET ^ (PGRT || PKLN);
                }
			}
        default :
			{
            if(s->flgs & GROTER_DAN)
                return FALSE;
            return NIET ^ (PKLN && 1);
			}
        }
    }

static int scompare(unsigned char * s,psk p)
    {
    int teken;
    int len;
    unsigned char * P;
    int ratnegcomp/*= FALSE*/;
    int flgs = p->flgs;
    if((flgs & (NOT|BREUK)) == (NOT|BREUK))
        {
        flgs &= ~(NOT|BREUK);
        }
    else if((flgs & (NOT|NUMBER)) == (NOT|NUMBER))
        {
        flgs &= ~(NOT|NUMBER);
        }
#if WRITETRACE
    Log("compare");
    writeTrace(s);
    writeTrace(p);
#endif
	if(RATIONAAL_WEAK(p))
		{
		if(fullnumbercheck(s) & QGETAL)
			{
			psk n = NULL;
			n = opb(n,s,NULL);
			ratnegcomp = RAT_NEG_COMP(n);
			teken = _qvergelijk(n,p);
#if DEBUGBRACMAT
            /*if(debug)
                {
    			printf("{");result(n);printf(":");result(p);printf("}");
                }*/
#endif
			wis(n);
			switch(flgs & (NOT|GROTER_DAN|KLEINER_DAN))
				{
				case NOT|GROTER_DAN|KLEINER_DAN:	/* n:~<>p */
				case 0:								/* n:p */
					{
	/*
					n:p		n == p
					n:~<>p  same as n:p
						[n == p]
							TRUE | ONCE
						[n > p]
							if n < 0 && p < 0
								FALSE
							else
								ONCE
						[n < p]
							if n < 0
								ONCE
							else
								FALSE
	*/
					switch(teken)
						{
						case QNUL:	/* n == p */
#if DEBUGBRACMAT
                            /*if(debug)
                                {
	    						printf("[n == p]");
                                }*/
#endif
    						return TRUE|ONCE;
						case 0:		/* n > p */
#if DEBUGBRACMAT
                            /*if(debug)
                                {
    							printf("[n > p]");
                                }*/
#endif
							if(RAT_NEG_COMP(p) || ratnegcomp)
								return FALSE;
							else
								return ONCE;
						default:	/* n < p */
#if DEBUGBRACMAT
                            /*if(debug)
                                {
    							printf("[n < p]");
                                }*/
#endif
							if(ratnegcomp)
								return ONCE;
							else
								return FALSE;
						}
					}
				case KLEINER_DAN:	/* n:<p */
					{
	/*
					n:<p	n < p
						[n == p]
							if n < 0
								FALSE
							else
								ONCE
						[n > p]
							if n < 0
								FALSE
							else
								ONCE
						[n < p]
							TRUE
	*/
					switch(teken)
						{
						case QNUL:	/* n == p */
						case 0:		/* n > p */
							if(ratnegcomp)
								return FALSE;
							else
								return ONCE;
						default:	/* n < p */
							return TRUE;
						}
					}
				case GROTER_DAN:	/* n:>p */
					{
	/*
					n:>p    n > p
						[n == p]
							if n < 0
								ONCE
							else
								FALSE
						[n > p]
							TRUE
						[n < p]
							if n < 0
								ONCE
							else
								FALSE
	*/
					switch(teken)
						{
						case 0:		/* n > p */
							return TRUE;
						default:	/* n == p , n < p */
							if(ratnegcomp)
								return ONCE;
							else
								return FALSE;
						}
					}
				case GROTER_DAN|KLEINER_DAN:	/* n:<>p */
				case NOT:						/* n:~p */
					{
	/*
					n:<>p   n != p
					n:~p    same as n:<>p
						[n == p]
							FALSE
						[n > p]
							TRUE
						[n < p]
							TRUE

	*/
					switch(teken)
						{
						case QNUL:	/* n == p */
							return FALSE;
						default:	/* n < p, n > p */
							return TRUE;
						}
					}
				case NOT|KLEINER_DAN:	/* n:~<p */
					{
	/*
					n:~<p   n >= p
						[n == p]
							if n < 0
								TRUE | ONCE
							else
								TRUE
						[n > p]
							TRUE
						[n < p]
							if n < 0
								ONCE
							else
								FALSE
	*/
					switch(teken)
						{
						case QNUL:	/* n == p */
							if(ratnegcomp)
								return TRUE|ONCE;
							else
								return TRUE;
						case 0:		/* n > p */
							return TRUE;
						default:	/* n < p */
							if(ratnegcomp)
								return ONCE;
							else
								return FALSE;
						}
					}
				case NOT|GROTER_DAN:	/* n:~>p */
					{
	/*
					n:~>p   n <= p
						[n == p]
							if n < 0
								TRUE
							else
								TRUE | ONCE
						[n > p]
							if n < 0
								FALSE
							else
								ONCE
						[n < p]
							TRUE
	*/
					switch(teken)
						{
						case QNUL:	/* n == p */
							if(ratnegcomp)
								return TRUE;
							else
								return TRUE|ONCE;
						case 0:		/* n > p */
							if(ratnegcomp)
								return FALSE;
							else
								return ONCE;
						default:	/* n < p */
							return TRUE;
						}
					}
				default:
                /*    printf("default\n");*/
					return FALSE;
				}
			}
        else
            if(*s == '-' && !s[1])
                return FALSE;
		}

    /*teken = strcmp((char*)s,(char*)POBJ(p));*/
    P = (unsigned char*)POBJ(p);
    teken = *s - *P;
    while(!teken && *s)
        {
        ++s;
        ++P;
        teken = *s - *P;
        }


    if(teken > 0)
        {
        teken = 0;
        len = 0;
        }
    else if(teken < 0)
        {
        teken = MINUS;
        if(*s)
            len = 0;
        else
            len = 1;
        }
    else
        {
        teken = QNUL;
        len = 0;
        }

	switch(flgs & (NOT|GROTER_DAN|KLEINER_DAN))
		{
		case NOT|GROTER_DAN|KLEINER_DAN:	/* n:~<>p */
		case 0:								/* n:p */
			{
/*
			n:p		n == p
			n:~<>p  same as n:p
				[n == p]
					TRUE | ONCE
				[n > p]
					ONCE
				[n < p]
					FALSE
*/
			switch(teken)
				{
				case QNUL:	/* n == p */
#if DEBUGBRACMAT
                    /*if(debug)
                        {
    					printf("[n == p]");
                        }*/
#endif
					return TRUE|ONCE;
				case 0:		/* n > p */
#if DEBUGBRACMAT
                    /*if(debug)
                        {
    					printf("[n > p]");
                        }*/
#endif
					return ONCE;
				default:	/* n < p */
#if DEBUGBRACMAT
                    /*if(debug)
                        {
    					printf("[n < p]");
                        }*/
#endif
                    if(len)
					    return FALSE; /*subject too short*/
                    else
    					return ONCE;
				}
			}
		case KLEINER_DAN:	/* n:<p */
			{
/*
			n:<p	n < p
				[n == p]
					ONCE
				[n > p]
					ONCE
				[n < p]
					TRUE
*/
			switch(teken)
				{
				case QNUL:	/* n == p */
				case 0:		/* n > p */
					return ONCE;
				default:	/* n < p */
					return TRUE;
				}
			}
		case GROTER_DAN:	/* n:>p */
			{
/*
			n:>p    n > p
				[n == p]
					FALSE
				[n > p]
					TRUE
				[n < p]
					FALSE
*/
			switch(teken)
				{
				case 0:		/* n > p */
					return TRUE;
				case QNUL:		/* n == p */
					return FALSE;
				default:	/* n < p */
                    if(len)
					    return FALSE;
                    else
					    return ONCE;
				}
			}
		case GROTER_DAN|KLEINER_DAN:	/* n:<>p */
		case NOT:						/* n:~p */
			{
/*
			n:<>p   n != p
			n:~p    same as n:<>p
				[n == p]
					FALSE
				[n > p]
					TRUE
				[n < p]
					TRUE

*/
			switch(teken)
				{
				case QNUL:	/* n == p */
					return FALSE;
				default:	/* n < p, n > p */
					return TRUE;
				}
			}
		case NOT|KLEINER_DAN:	/* n:~<p */
			{
/*
			n:~<p   n >= p
				[n == p]
					TRUE
				[n > p]
					TRUE
				[n < p]
					FALSE
*/
			switch(teken)
				{
				case QNUL:	/* n == p */
				case 0:		/* n > p */
					return TRUE;
				default:	/* n < p */
                    if(len)
					    return FALSE;
                    else
					    return ONCE;
				}
			}
		case NOT|GROTER_DAN:	/* n:~>p */
			{
/*
			n:~>p   n <= p
				[n == p]
					TRUE | ONCE
				[n > p]
					ONCE
				[n < p]
					TRUE
*/
			switch(teken)
				{
				case QNUL:	/* n == p */
					return TRUE|ONCE;
				case 0:		/* n > p */
					return ONCE;
				default:	/* n < p */
					return TRUE;
				}
			}
		default:
			return ONCE;
		}
    }


static ppsk head(ppsk ppknoop)
{
psk root;
assert(ppknoop != NULL);
if(((root = *ppknoop)->ops & LATEBIND) && is_op(root))
    {
    psk *pp,p,pknoop,snijaf;
    pknoop = root->LINKS;
    snijaf = root->RECHTS;
    for(pp = ppknoop;;pp = &(p->RECHTS),pknoop = pknoop->RECHTS)
        {
        if(is_op(pknoop))
            {
            if(pknoop->RECHTS == snijaf)
                {
                *pp = zelfde_als_w(pknoop->LINKS);
                break;
                }
            else
                {
                *pp = p = new_operator_like(pknoop);
                /* *pp = p = (psk)bmalloc(/ *__LINE__,* /sizeof(kknoop));*/
#if !W32
                p->flgs = pknoop->flgs;
#endif
                p->ops = pknoop->ops & ~OPGEBRUIKT;
                p->LINKS = zelfde_als_w(pknoop->LINKS);
                }
            }
        else
            {
            *pp = icopievan(pknoop);
            break;
            }
        }
    wis(root);
    }
return ppknoop;
}

static psk rechtertak(psk pkn)
{
psk rknoop;
rknoop = pkn->RECHTS;
if(!(pkn->flgs & SUCCES))
    {
    rknoop = prive(rknoop);
    rknoop->flgs ^= SUCCES;
    }
if(pkn->flgs & FENCE && !(rknoop->flgs & FENCE))
    {
    rknoop = prive(rknoop);
    rknoop->flgs |= FENCE;
    }
wis(pkn->LINKS);
pskfree(pkn);
return rknoop;
}

#if 0
static void evalobject(ppsk pkn)
{
while(1)
    {
    if(!((*pkn)->flgs & KLAAR) && is_op(*pkn))
        {
        *pkn = prive(*pkn);
        evalobject(&((*pkn)->LINKS));
        switch(kop(*pkn))
            {
            case WORDT :
                *pkn = rechtertak(*pkn);
                return;
            default:
                /* evalobject(&((*pkn)->RECHTS));
                18 Maart 1997 */
                pkn = &((*pkn)->RECHTS);
                continue;
            }
        }
    break;
    }
}
#endif



static int psh(psk name,psk pknoop,psk dim)
	{
	/* string dient aan de eisen van icpy te voldoen */
	vars *navar
#if !COMPILE
	  ,*voorvar
#endif
	  ;
	varia *nvaria;
	psk cknoop;
	int oldn,n,m2,m22;
	while(is_op(name))
		{
		/* return psh(name->LINKS,pknoop,dim) && psh(name->RECHTS,pknoop,dim);
		18 Maart 1997 */
		if(!psh(name->LINKS,pknoop,dim))
			return FALSE;
		name = name->RECHTS;
		}
    if(dim && !GEHEEL(dim))
        return FALSE;
    if(!zoeknaam(name,
#if COMPILE
                 NULL,
#else
                 &voorvar,
#endif
                 &navar))
        {
        insert(name,pknoop);
        if(dim)
            {
            zoeknaam(name,
#if COMPILE
                     NULL,
#else
                     &voorvar,
#endif
                     &navar);
            }
        else
            return TRUE;
        }
    n = oldn = navar->n;
    if(dim)
        {
        int newn;
#ifdef vax
        newn = atol((char*)POBJ(dim));
#else
        newn = (int)strtoul((char*)POBJ(dim),(char**)NULL,10);
#endif
        if(RAT_NEG(dim))
            newn = oldn - newn + 1;
        if(newn < 0)
            return FALSE;
        navar->n = newn;
        if(oldn >= navar->n)
            {
            assert(navar->pvaria);
            for(;oldn >= navar->n;)
                wis(*entry(n,oldn--,&navar->pvaria));
            }
        navar->n--;
        if(navar->selector > navar->n)
            navar->selector = navar->n;
        }
    else
        {
        navar->n++;
        navar->selector = navar->n;
        }
    m2 = macht2(n);
    if(m2 == 0)
        m22 = 1;
    else
        m22 = m2 << 1;
    if(navar->n >= m22)
        /* alloceren */
        {
        for(;navar->n >= m22;m22 <<= 1)
            {
            nvaria = (varia*)bmalloc(__LINE__,sizeof(varia) + (m22-1)*sizeof(psk));
            nvaria->prev = navar->pvaria;
            navar->pvaria = nvaria;
            }
        }
    else if(navar->n < m2)
        /* dealloceren */
        {
        for(;m2 && navar->n < m2;m2 >>= 1)
            {
            nvaria = navar->pvaria;
            navar->pvaria = nvaria->prev;
            bfree(nvaria);
            }
        if(navar->n < 0)
#if COMPILE
            unbind(navar);
#else
            {
            if(voorvar)
                voorvar->next = navar->next;
            else
                variabelen[*POBJ(name)] = navar->next;
#ifdef PVNAME
            if(navar->vname != OBJ(nilk))
                bfree(navar->vname);
#endif
            bfree(navar);
            return TRUE; /* 20001222 */
            }
#endif
        }
    /*else
       geen allocatie
        {
        }*/
    assert(navar->pvaria);
    for(cknoop = pknoop;
        ++oldn <= navar->n;
        cknoop = *entry(navar->n,oldn,&navar->pvaria) = zelfde_als_w(cknoop));
    return TRUE;
	}

typedef struct classdef
    {
    char * name;
    method * vtab;
    } classdef;

typedef struct pskRecord
    {
    psk entry;
    struct pskRecord * next;
    } pskRecord;

typedef int (*cmpfuncTp)(const char *s, const char *p);
typedef long (*hashfuncTp)(const char *s);

typedef struct Hash
    {
    pskRecord **hash_table;
    unsigned long size;
    unsigned long elements;     /* elements >= record_count */
    unsigned long record_count; /* record_count >= size - unoccupied */
    unsigned long unoccupied;
    cmpfuncTp cmpfunc;
    hashfuncTp hashfunc;
    /*
    unsigned int Dos:1;
    unsigned int casesensitive:1;
    */
    } Hash;

static int strcasecomp(const char *s, const char *p)
    {
    while(*s && *p)
        {
        int diff = (int)lowerEquivalent[(unsigned char)*s] - (int)lowerEquivalent[(unsigned char)*p];
        if(diff)
            return diff;
        ++s;
        ++p;
        }
    return (int)*s - (int)*p;
    }

static int strcasecmpDOS(const char *s, const char *p)
    {
    while(*s && *p)
        {
        int diff = (int)ISO8859toCodePage850(lowerEquivalent[CodePage850toISO8859((unsigned char)*s)]) - (int)ISO8859toCodePage850(lowerEquivalent[CodePage850toISO8859((unsigned char)*p)]);
        if(diff)
            return diff;
        ++s;
        ++p;
        }
    return (int)*s - (int)*p;
    }


static long casesensitivehash(const char * cp)
    {
    long hash_temp = 0;
    while (*cp != '\0')
        {
        if(hash_temp < 0)
            hash_temp = (hash_temp << 1) +1;
        else
            hash_temp = hash_temp << 1;
        hash_temp ^= *cp;
        ++cp;
        }
    return hash_temp;
    }

static long caseinsensitivehash(const char * cp)
    {
    long hash_temp = 0;
    while (*cp != '\0')
        {
        if(hash_temp < 0)
            hash_temp = (hash_temp << 1) +1;
        else
            hash_temp = hash_temp << 1;
        hash_temp ^= lowerEquivalent[(int)*cp];
        ++cp;
        }
    return hash_temp;
    }

static long caseinsensitivehashDOS(const char * cp)
    {
    long hash_temp = 0;
    while (*cp != '\0')
        {
        if(hash_temp < 0)
            hash_temp = (hash_temp << 1) +1;
        else
            hash_temp = hash_temp << 1;
        hash_temp ^= ISO8859toCodePage850(lowerEquivalent[CodePage850toISO8859(*cp)]);
        ++cp;
        }
    return hash_temp;
    }

static psk removeFromHash(Hash * temp,psk Arg)
    {
    const char * key = (const char *)POBJ(Arg);
    long i;
    long hash_temp;
    pskRecord ** pr;
    hash_temp = (*temp->hashfunc)(key);
    i = temp->size ? ((unsigned int)hash_temp) % temp->size : 0;
    pr = temp->hash_table + i;
    if(*pr)
        {
        while(*pr)
            {
            if(kop((*pr)->entry) == LUCHT)
                {
                if(!(*temp->cmpfunc)(key,(const char *)POBJ((*pr)->entry->LINKS->LINKS)))
                    break;
                }
            else if(!(*temp->cmpfunc)(key,(const char *)POBJ((*pr)->entry->LINKS)))
               break;
            pr = &(*pr)->next;
            }
        if(*pr)
            {
            pskRecord * next = (*pr)->next;
            psk ret = (*pr)->entry;
            bfree(*pr);
            *pr = next;
            return ret;
            }
        }
    return NULL;
    }

static psk inserthash(Hash * temp,psk Arg)
    {
    const char * key = (const char *)POBJ(Arg->LINKS);
    long i;
    long hash_temp;
    pskRecord * r;
    hash_temp = (*temp->hashfunc)(key);
    i = temp->size ? ((unsigned int)hash_temp) % temp->size : 0;
    r = temp->hash_table[i];
    if(!r)
        --temp->unoccupied;
    else
        while(r)
            {
            if(kop(r->entry) == LUCHT)
                {
                if(!(*temp->cmpfunc)(key,(const char *)POBJ(r->entry->LINKS->LINKS)))
                    break;
                }
            else if(!(*temp->cmpfunc)(key,(const char *)POBJ(r->entry->LINKS)))
               break;
            r = r->next;
            }
    if(r)
        {
        psk goal = (psk)bmalloc(__LINE__,sizeof(kknoop));
#if W32
        goal->flgs = LUCHT | SUCCES;
#else
        goal->flgs = SUCCES;
        goal->ops = LUCHT;
#endif
        goal->ops &= ~OPGEBRUIKT;
        goal->LINKS = zelfde_als_w(Arg);
        goal->RECHTS = r->entry;
        r->entry = goal;
        }
    else
        {
        r = (pskRecord *)bmalloc(__LINE__,sizeof(pskRecord));
        r->entry = zelfde_als_w(Arg);
        r->next = temp->hash_table[i];
        temp->hash_table[i] = r;
        ++temp->record_count;
        }
    ++temp->elements;
    return r->entry;
    }

static psk findhash(Hash * temp,psk Arg)
    {
    const char * key = (const char *)POBJ(Arg);
    long i;
    long hash_temp;
    pskRecord * r;
    hash_temp = (*temp->hashfunc)(key);
    i = temp->size ? ((unsigned int)hash_temp) % temp->size : 0;
    r = temp->hash_table[i];
    if(r)
        {
        while(r)
            {
            if(kop(r->entry) == LUCHT)
                {
                if(!(*temp->cmpfunc)(key,(const char *)POBJ(r->entry->LINKS->LINKS)))
                    break;
                }
            else if(!(*temp->cmpfunc)(key,(const char *)POBJ(r->entry->LINKS)))
               break;
            r = r->next;
            }
        if(r)
            return r->entry;
        }
    return NULL;
    }

static void freehash(Hash * temp)
    {
    if(temp)
        {
        if(temp->hash_table)
            {
            int i;
            for(i = temp->size;i > 0;)
                {
                pskRecord * r = temp->hash_table[--i];
                pskRecord * next;
                while(r)
                    {
                    wis(r->entry);
                    next = r->next;
                    bfree(r);
                    r = next;
                    }
                }
            bfree(temp->hash_table);
            }
        bfree(temp);
        }
    }

static Hash * newhash(long size)
    {
    int i;
    Hash * temp = bmalloc(__LINE__,sizeof(Hash));
    temp->size = (unsigned int)size;
    temp->record_count = (unsigned int)0;
    temp->hash_table = (pskRecord **)bmalloc(__LINE__,sizeof(pskRecord *) * temp->size);
    temp->cmpfunc = strcmp;
    temp->hashfunc = casesensitivehash;
    /*
    temp->Dos = FALSE;
    temp->casesensitive = TRUE;
    */
    temp->elements = 0L;     /* elements >= record_count */
    temp->record_count = 0L; /* record_count >= size - unoccupied */
    temp->unoccupied = size;
    for(i = temp->size;i > 0;)
        temp->hash_table[--i] = NULL;
    return temp;
    }

static long nextprime(unsigned long g)
    {
    int i;
    unsigned long kleindeler;
    static int bijt[12]=
      {1,  2,  2,  4,    2,    4,    2,    4,    6,    2,  6};
    /*2-3,3-5,5-7,7-11,11-13,13-17,17-19,19-23,23-29,29-1,1-7*/
    unsigned long grootdeler;
    if(g & 1)
        ++g; /* even -> uneven */
    kleindeler = 2;
    i = 0;
    while((grootdeler = g / kleindeler) >= kleindeler)
        {
        if(grootdeler * kleindeler == g)
            {
            ++g;
            kleindeler = 2;
            i = 0;
            }
        else
            {
            kleindeler += bijt[i];
            if(++i > 10)
                i = 3;
            }
        }
    return g;
    }

static void rehash(Hash ** ptemp,int loadFactor/*1-100*/)
    {
    Hash * temp = *ptemp;
    if(temp)
        {
        long newsize;
        Hash * newtable;
/*
        printf("Old: size %ld unoccupied %ld records %ld elements %ld\n",
            temp->size,temp->unoccupied,temp->record_count,temp->elements);
*/
        newsize = nextprime((100 * temp->record_count)/loadFactor);
        newtable = newhash(newsize);
        newtable->cmpfunc = temp->cmpfunc;
        newtable->hashfunc = temp->hashfunc;
        if(temp->hash_table)
            {
            int i;
            for(i = temp->size;i > 0;)
                {
                pskRecord * r = temp->hash_table[--i];
                while(r)
                    {
                    psk pkn = r->entry;
                    while(is_op(pkn) && kop(pkn) == LUCHT)
                        {
                        inserthash(newtable,pkn->LINKS);
                        pkn = pkn->RECHTS;
                        }
                    inserthash(newtable,pkn);
                    r = r->next;
                    }
                }
            }
/*
        printf("New: size %ld unoccupied %ld records %ld elements %ld\n",
            newtable->size,newtable->unoccupied,newtable->record_count,newtable->elements);
*/
        freehash(temp);
        *ptemp = newtable;
        }
    }

static int loadfactor(Hash * temp)
    {
    if(temp->record_count < 10000000L)
        return (100 * temp->record_count) / temp->size;
    else
        return temp->record_count / (temp->size/100);
    }

static function_return_type hashinsert(struct typedObjectknoop * This,ppsk arg)
    {
    psk Arg = (*arg)->RECHTS;
    if(is_op(Arg) && !is_op(Arg->LINKS))
        {
        psk ret;
        int lf = loadfactor((Hash *)This->voiddata);
        if(lf > 100)
            rehash((Hash**)&This->voiddata,60);
        ret = inserthash((Hash *)This->voiddata,Arg);
        wis(*arg);
        *arg = zelfde_als_w(ret);
        return builtin_object_builtin_method_ok;
        }
    return function_fail;
    }

static function_return_type hashfind(struct typedObjectknoop * This,ppsk arg)
    {
    psk Arg = (*arg)->RECHTS;
    if(!is_op(Arg))
        {
        psk ret = findhash((Hash *)This->voiddata,Arg);
        if(ret)
            {
            wis(*arg);
            *arg = zelfde_als_w(ret);
            return builtin_object_builtin_method_ok;
            }
        }
    return function_fail;
    }

static function_return_type  hashremove(struct typedObjectknoop * This,ppsk arg)
    {
    psk Arg = (*arg)->RECHTS;
/*
    printf("hashremove called\n");
*/
    if(!is_op(Arg))
        {
        Hash * temp = (Hash *)This->voiddata;
        psk ret = removeFromHash(temp,Arg);
        if(ret)
            {
            if(loadfactor(temp) < 50)
                rehash((Hash**)&This->voiddata,90);
            wis(*arg);
            *arg = ret;
            return builtin_object_builtin_method_ok;
            }
        }
    return function_fail;
    }

static function_return_type  hashnew(struct typedObjectknoop * This,ppsk arg)
    {
/*
    printf("hashnew called with argument (");
    result((*arg)->RECHTS);
    printf(")\n");
*/
    This->voiddata = (void *)newhash(97);
    return builtin_object_builtin_method_ok;
    }

static function_return_type  hashdie(struct typedObjectknoop * This,ppsk arg)
    {
/*
    printf("hashdie called\n");
*/
    freehash((Hash *)This->voiddata);
/*
    printf("hashdie done\n");
*/
    return builtin_object_builtin_method_ok;
    }

static function_return_type  hashDOS(struct typedObjectknoop * This,ppsk arg)
    {
/*
    printf("hashDOS called\n");
*/
    ((Hash*)This->voiddata)->hashfunc = caseinsensitivehashDOS;
    ((Hash*)This->voiddata)->cmpfunc = strcasecmpDOS;
    rehash((Hash**)&This->voiddata,100);
    return builtin_object_builtin_method_ok;
    }

static function_return_type  hashISO(struct typedObjectknoop * This,ppsk arg)
    {
/*
    printf("hashISO called\n");
*/
    ((Hash*)This->voiddata)->hashfunc = caseinsensitivehash;
    ((Hash*)This->voiddata)->cmpfunc = strcasecomp;
    rehash((Hash**)&This->voiddata,100);
    return builtin_object_builtin_method_ok;
    }

static function_return_type hashcasesensitive(struct typedObjectknoop * This,ppsk arg)
    {
/*
    printf("hashcasesensitive called\n");
*/
    ((Hash*)This->voiddata)->hashfunc = casesensitivehash;
    ((Hash*)This->voiddata)->cmpfunc = strcmp;
    rehash((Hash**)&This->voiddata,100);
    return builtin_object_builtin_method_ok;
    }

static function_return_type hashforall(struct typedObjectknoop * This,ppsk arg)
    {
    Hash * temp = (Hash*)This->voiddata;
/*
    printf("hashforall called\n");
*/
    if(temp)
        {
        if(temp->hash_table)
            {
            int i;
            for(i = temp->size;i > 0;)
                {
                pskRecord * r = temp->hash_table[--i];
                while(r)
                    {
                    psk pkn = NULL;
                    adr[2] = (*arg)->RECHTS; /* each time! adr[n] may be overwritten by evalueer (below)*/
                    adr[3] = r->entry;
                    pkn = opb(pkn,"(\2'\3)",NULL);
                    evalueer(&pkn);
                    wis(pkn);
                    r = r->next;
                    }
                }
            }
        }
    return builtin_object_builtin_method_ok;
    }

method hash[] = {
    {"find",hashfind},
    {"insert",hashinsert},
    {"remove",hashremove},
    {"New",hashnew},
    {"Die",hashdie},
    {"DOS",hashDOS},
    {"ISO",hashISO},
    {"casesensitive",hashcasesensitive},
    {"forall",hashforall},
    {NULL,NULL}};
/*
Standard methods are 'New' and 'Die'.
A user defined 'die' can be added after creation of the object and will be invoked just before 'Die'.

Example:

new$hash:?h;

     (=(Insert=.out$Insert & lst$its & lst$Its & (Its..insert)$!arg)
      (die = .out$"Oh my God")
    ):(=?(h.));

    (h..Insert)$(X.x);

    :?h;



    (=(Insert=.out$Insert & lst$its & lst$Its & (Its..insert)$!arg)
      (die = .out$"The end.")
    ):(=?(new$hash:?k));

    (k..Insert)$(Y.y);

    :?k;

A little problem is that in the last example, the '?' ends up as a flag on the '=' node.

Bart 20010222

*/

classdef classes[] = {{"hash",hash},{NULL,NULL}};


static method_pnt findBuiltInMethod(typedObjectknoop * object,psk methodName)
    {
    if(!is_op(methodName))
        {
        method * methods = object->vtab;
        if(methods)
            {
            for(;methods->name && strcmp(methods->name,(const char *)POBJ(methodName));++methods)
                ;
            return methods->func;
            }
        }
    return NULL;
    }

#if 1
static int getmember(psk name,psk tree,ppsk doel,ppsk self,ppsk object,method_pnt * theMethod)
    {
    while(is_op(tree))
        {
        if(kop(tree) == WORDT)
            {
            psk nname;
            if(  theMethod
              && object
              && ISBUILTIN((objectknoop*)tree)
              && kop(name) == DOT
              )
                {
                *object = tree;  /* object == (=) */
                *theMethod = findBuiltInMethod((typedObjectknoop *)tree,name->RECHTS);
                /* findBuiltInMethod((=),(insert)) */
                if(*theMethod)
                    {
                    *doel = NULL;
                    return TRUE;
                    }
                }

            if(kop(name) == DOT)
                nname = name->LINKS;
            else
                nname = name;
            if(vgl(tree->LINKS,nname))
                return FALSE;
            else if(nname == name)
                {
                *doel = tree->RECHTS;
                return TRUE;
                }
            else
                {
                if(self)
                    *self = tree->RECHTS;
                name = name->RECHTS;
                }
            }
        else
            {
            psk tmp;
            if(getmember(name,tree->LINKS,&tmp,self,object,theMethod))
                {
                *doel = tmp;
                return TRUE;
                }
            }
        tree = tree->RECHTS;
        }
    return FALSE;
    }
#else
static ppsk getmember(psk name,psk tree,ppsk self)
{
while(1)
    {
    if(is_op(tree))
        if(kop(tree) == WORDT)
            {
            psk nname;
            if(/*is_op(name) &&*/ kop(name) == DOT)
                nname = name->LINKS;
            else
                nname = name;
            if(vgl(tree->LINKS,nname))
                return NULL;
            else if(nname == name)
                return &tree->RECHTS;
            else
                {
                if(self)
                    *self = tree->RECHTS;
                /*return getmember(name->RECHTS,tree->RECHTS,self);
                18 Maart 1997 */
                name = name->RECHTS;
                tree = tree->RECHTS;
/*19970825      continue;*/
                }
            }
        else
            {
            ppsk tmp;
            /* return (tmp = getmember(name,tree->LINKS,self)) != NULL
                    ? tmp
                    : getmember(name,tree->RECHTS,self);
            18 Maart 1997 */
            tmp = getmember(name,tree->LINKS,self);
            if(tmp)
                return tmp;
            tree = tree->RECHTS;
/*19970825  continue;*/
            }
    else
        return NULL;
/*19970825 break;*/
    }
}
#endif


static int find(psk naamknoop,ppsk doel,int *newval,ppsk self,ppsk object,method_pnt * theMethod)
/*
'naamknoop' is the expression that has to lead to a binding.
Conceptually, expression (or its complement) and binding are separated by a '=' operator.
E.g.

  say            =         (.out$!arg)
  ---            -         -----------
  expression   '='-operator     binding

    say$HELLO
    and
    (= (.out$!arg))$HELLO

      must be equivalent. Therefore, both of 'say' and its complement '(= .out$!arg)' have the binding '(.out$!arg)'.

        If the binding is found 'find' returns TRUE, otherwise it returns FALSE.
        The binding is either returned in 'doel' or in 'theMethod', not both.
        The parameter 'newval' is set to TRUE if 'doel' has increased a reference counter. (must be ignored if find returns FALSE.)
        The parameter 'self' is the rhs of the root '=' of an object. It is used for non-built-ins
        The parameter 'object' is the root of an object, possibly having built-in methods.


Built in methods:
if
    new$hash:?x
then
    ((=).insert)$   (=) being the hash node with invisible built in method 'insert'
and
    (!x.insert)$
and
    (x..insert)$
must be equivalent
*/
    {
    vars *navar;
    /* 29 juli 1993 */
    if(!doel)
        {
        return FALSE;
        }
    /*printf("naamknoop:(");result(naamknoop);printf(")");getchar();*/
    if(is_op(naamknoop))
        {
        switch(kop(naamknoop))
            {
            case WORDT: /* Lambda function: (=.out$!arg)$HELLO -> naamknoop == (=.out$!arg) */
                {/*
                if(object)
                    {
                    printf("objectA\n");
                    *object = naamknoop;
                    }
                */
                *newval = TRUE;
                *doel = zelfde_als_w(naamknoop->RECHTS);
                /*evalobject(doel);*/ /* This makes that (==.out$!arg)$HELLO also works, but not (===.out$!arg)$HELLO
                                     so what is the meaning of this?
                                    */
                /*printf("doel after evalobject:(");result(*doel);printf(")");getchar();*/
                return TRUE;
                }
            case DOT: /*
                      e.g.

                      (1)
                            x  =  (a=2) (b=3)

                            !(x.a)
                      and
                            !((=  (a=2) (b=3)).a)

                      must give same result.

                      (2)

                      new$hash:?y

                      ((=).insert)$
                      (y..insert)$
                      (!y.insert)$
                      */
                {
                psk tmp;
                psk tmp2 = NULL;
                int nieuw = FALSE;
                if(is_op(naamknoop->LINKS))
                    {
                    if(kop(naamknoop->LINKS) == WORDT) /* naamknoop->LINKS == (=  (a=2) (b=3))   */
                        {
                        if(  theMethod
                          && object
                          && ISBUILTIN((objectknoop*)(naamknoop->LINKS))
                          /*&& !is_op(naamknoop->RECHTS)*/
                          )
                            {
                            *theMethod = findBuiltInMethod((typedObjectknoop *)(naamknoop->LINKS),naamknoop->RECHTS);
                                                /* findBuiltInMethod((=),(insert)) */
                            *object = naamknoop->LINKS;  /* object == (=) */
                            if(*theMethod)
                                {
                                *doel = NULL;
                                return TRUE;
                                }
                            }
                        tmp = naamknoop->LINKS->RECHTS; /* tmp == ((a=2) (b=3))   */
                        }
                    else
                        return FALSE;
                    }
                else                                   /* x */
                    {
                    if(!find(naamknoop->LINKS,&tmp,&nieuw,NULL,NULL/*object*/,NULL/*theMethod*/))
                        return FALSE;
                    /*
                    tmp == ((a=2) (b=3))
                    tmp == (=)
                    */
                    }
                if(self)
                    *self = tmp; /* self == ((a=2) (b=3))   */
                /*
                if(kop(tmp) == WORDT && object && kop(naamknoop->RECHTS) == DOT)
                    {
                    printf("objectC\n");
                    *object = tmp;
                    }
                */
                /*printf("find member (");result(naamknoop->RECHTS);printf(") in (");result(tmp);printf(")\n");*/
                /* The number of '=' to reach the method name in 'tmp' must be one greater
                   than the number of '.' that precedes the method name in 'naamknoop->RECHTS'

                   e.g (= (say=.out$!arg)) and (.say) match

                   For built-in methods (definitions of which are not visible) an invisible '=' has to be assumed.

                   The function getmember resolves this.
                */
                getmember(naamknoop->RECHTS,tmp,&tmp2,self,object,theMethod);

                if(tmp2)
                    {
                    *newval = TRUE;
                    *doel = zelfde_als_w(tmp2);
#ifdef SELF
                    if(*doel && self && *self)
                        {
                        psh(&selfkn,*self,NULL);
                        }
#endif
                    }
                else
                    *doel = NULL;
                if(nieuw)
                    wis(tmp);
                return *doel != NULL || (theMethod && *theMethod != NULL);
                }
            default:
                {
                *newval = FALSE;
                return FALSE;
                }
            }
        }
    else
        {
#if COMPILE
#ifdef PVNAME
        for(navar = variabelen[RPOBJ(naamknoop)];
            navar && (STRCMP(navar->vname,POBJ(naamknoop)) < 0);
            navar = navar->next)
            ;
        if(navar && !STRCMP(navar->vname,POBJ(naamknoop))
           && navar->selector <= navar->n
           && navar->pvaria
          )
#else
        for(navar = variabelen[RPOBJ(naamknoop)];
            navar && (STRCMP(&navar->u.Obj,POBJ(naamknoop)) < 0);
            navar = navar->next)
            ;
        if(navar && !STRCMP(&navar->u.Obj,POBJ(naamknoop))
           && navar->selector <= navar->n
           && navar->pvaria
          )
#endif
#else
#ifdef PVNAME
        for(navar = variabelen[naamknoop->u.obj];
            navar && (STRCMP(navar->vname,POBJ(naamknoop)) < 0);
            navar = navar->next)
            ;
        if(navar && !STRCMP(navar->vname,POBJ(naamknoop))
           && navar->selector <= navar->n
          )
#else
        for(navar = variabelen[naamknoop->u.obj];
            navar && (STRCMP(&navar->u.Obj,POBJ(naamknoop)) < 0);
            navar = navar->next)
            ;
        if(navar && !STRCMP(&navar->u.Obj,POBJ(naamknoop))
           && navar->selector <= navar->n
          )
#endif
#endif
            {
            assert(navar->pvaria);
            *doel = *head(entry(navar->n,navar->selector,&navar->pvaria));
            *newval = FALSE;
            return TRUE;
            }
        else
            {
            return FALSE;
            }
        }
    }

#ifdef SELF
static int naamwoord(psk variabele,ppsk pbinding,unsigned int *pflags,int *newval,ppsk self);

static int sufficiently_resolved(ppsk pbinding,unsigned int *pflags,int *newval,ppsk self)
#else
static int naamwoord(psk variabele,ppsk pbinding,unsigned int *pflags,int *newval);

static int sufficiently_resolved(ppsk pbinding,unsigned int *pflags,int *newval)
#endif
    {
    psk name;
    name = *pbinding; /* e.g. !x or !!x */
    if(!(name->flgs & INDIRECT))
        return TRUE;
    else
        {
        int res;
        int newv;
        res = naamwoord(name,pbinding,pflags,&newv
#ifdef SELF
            ,self
#endif
            );

        if(*newval)
            wis(name);

        *newval = newv;

        return res;
        }
    }

static int deleteNode(psk name)
{
vars *navar
#if !COMPILE
,*voorvar
#endif
;
varia *hv;
if(zoeknaam(name,
#if COMPILE
            NULL,
#else
            &voorvar,
#endif
            &navar))
    {
    assert(navar->pvaria);
    wis(*entry(navar->n,navar->n,&navar->pvaria));
    if(navar->n)
        {
        if((navar->n)-1 < macht2(navar->n))
            {
            hv = navar->pvaria;
            navar->pvaria = hv->prev;
            bfree(hv);
            }
        navar->n--;
        if(navar->n < navar->selector)
            navar->selector = navar->n;
        }
    else
#if COMPILE
        {
        unbind(navar);
        }
#else
        {
        if(voorvar)
            voorvar->next = navar->next;
        else
            variabelen[*POBJ(name)] = navar->next;
#ifdef PVNAME
        if(navar->vname != OBJ(nilk))
            bfree(navar->vname);
#endif
        bfree(navar); /* nieuw */
        }
#endif
    return TRUE;
    }
else
    return FALSE;
}

#ifdef SELF
static int naamwoord(psk variabele,ppsk pbinding,unsigned int *pflags,int *newval,ppsk self)
#else
static int naamwoord(psk variabele,ppsk pbinding,unsigned int *pflags,int *newval)
#endif
/* *pbinding kan een andere waarde krijgen, ook als de boel faalt */
    {
    register int flgs;
#ifdef SELF
    psk self2 = NULL;
#endif
    int ret = TRUE;
    flgs = variabele->flgs;
    *pflags |= (flgs & ERFENIS);
    if(ONTKENNING(flgs,GROTER_DAN) || ONTKENNING(flgs,KLEINER_DAN))
        *pflags |= NOT;
    *pflags ^= ((flgs & SUCCES) ^ SUCCES);
#ifdef SELF
    if(find(variabele,pbinding,newval,self,NULL,NULL))
#else
    if(find(variabele,pbinding,newval,NULL,NULL,NULL))
#endif
        {
        if(sufficiently_resolved(pbinding,pflags,newval
#ifdef SELF
          ,&self2
#endif
          ))
            {
            /*
            a=b=(c=d)
            e:?!(a.b)
            dan krijg ik c en ken daar e aan toe, maar dat is niet de
            bedoeling! Ik moet testen of ik in een object zit (self).
            Als dat zo is, moet ik e toekennen aan its.c (e:?(its.c)),
            zodat ik krijg a=b=c=e
            */
            if(variabele->flgs & DUBBEL_INDIRECT)
                {
#ifdef SELF
                psk self3 = NULL;
#endif
                if(is_op(*pbinding))
                    {
                    psk peval;
                    if(is_object(*pbinding))
                        {
                        peval = zelfde_als_w(*pbinding);
                        }
                    else
                        {
                        peval = subboomcopie(*pbinding);
                        /*
                        a=b=(c.d)
                        c=(d=e)
                        f:?!!(a.b)
                        dan sta ik hier met (c.d)
                        bedoeling is dat ik e vind, zodat
                        ik f kan toekennen aan e.
                        */
                        if(  !(evalueer(&peval) == TRUE)
                          || (  is_op(peval)
                             && kop(peval) != WORDT
                             && kop(peval) != DOT
                             )
                          )
                            {
                            wis(peval);
                            ret = FALSE;
                            }
                        }
                    if(ret)
                        {
                        if(*newval)
                            {
                            *newval = FALSE;
                            wis(*pbinding);
                            }
                        if(naamwoord(peval,pbinding,pflags,newval
#ifdef SELF
                                    ,&self3
#endif
                          ))
                            {
                            wis(peval);
                            /*ret = TRUE;*/
                            }
                        else
                            {
                            wis(peval);
                            ret = FALSE;
                            }
                        }
                    else if(*newval)
                        {
                        *newval = FALSE;
                        wis(*pbinding);
                        }
                    }
                else
                    {
                    int newv = *newval;
                    psk binding;
                    *newval = FALSE;
                    ret = naamwoord(*pbinding,&binding,pflags,newval
#ifdef SELF
                            ,&self3
#endif
                            );
                    if(newv)
                        {
                        wis(*pbinding);
                        }
                    *pbinding = binding;
                    }
#ifdef SELF
                if(self3)
                    {
                    deleteNode(&selfkn);
                    }
#endif
                }
            /*else
                ret = TRUE;*/
            }
        else
            {
            ret = FALSE;
/*            printf("naamwoord NOT sufficiently_resolved\n");*/
            }
        }
    else
        {
        ret = FALSE;
        }
#ifdef SELF
    if(self2)
       {
       deleteNode(&selfkn);
       }
#endif
    return ret;
    }


static int naamwoord_w(psk variabele,ppsk pbinding)
    {
    unsigned int flags,flags2;
    int newval;
    int ret;
#ifdef SELF
    psk self = NULL;
#endif
    flags = SUCCES;
    *pbinding = NULL;
    newval = FALSE;

    if(naamwoord(variabele,pbinding,&flags,&newval
#ifdef SELF
        ,&self
#endif
        ))
        {
        assert(*pbinding != NULL);
        flags2 = (*pbinding)->flgs;
        flags2 |= (flags & (ERFENIS|NOT));
        flags2 ^= ((flags & SUCCES) ^ SUCCES);

        if((*pbinding)->flgs == flags2)
            {
            if(!newval)
                {
                *pbinding = zelfde_als_w(*pbinding);
                }
            }
        else
            {
            if(newval)
                {
                *pbinding = prive(*pbinding);
                }
            else
                {
                *pbinding = subboomcopie(*pbinding);
                }
#if W32
            (*pbinding)->flgs = flags2 & ~OPGEBRUIKT;
#else
            (*pbinding)->flgs = flags2;
#endif
            }
        ret = TRUE;
        }
    else
        ret = FALSE;
#ifdef SELF
    if(self)
        {
        deleteNode(&selfkn);
        }
#endif
#if WRITETRACE
    Log("VARIABLE");
    writeTrace(variabele);
    if(ret)
        writeTrace(*pbinding);
    else
        Log("failed");
    Log("END");
#endif
    return ret;
    }

/*
#define KORT 0
KORT 1 does not work:


{?} dbg'(a b b:? ?%x !x)
match(a b b:? %?x !x)
 match(:?)
 match(a b b:%?x !x)
  match(:%?x)
  match(a b b:%?x)  snijaf:b b
   match(a:%?x)
  match(b b:!x)
   match(b b:a)
  match(a b b:%?x)  snijaf:b
  match(b:!x)
   match(b:a b)
    match(:a)
DONOTSHORTEN
    match(b:a)

    F




{?} dbg'(a b b:? ?%x !x)
match(a b b:? %?x !x)
 match(:?)
 match(a b b:%?x !x)
  match(:%?x)
  match(a b b:%?x)  snijaf:b b
   match(a:%?x)
  match(b b:!x)
   match(b b:a)
  match(a b b:%?x)  snijaf:b
  match(b:!x)
   match(b:a b)
    match(:a)
    match(b:a)

  match(a b b:%?x)
  match(:!x)
   match(:a b b)
    match(:a)
 match(a b b:?)  snijaf:b b
  match(a:?)
 match(b b:%?x !x)
  match(:%?x)
  match(b b:%?x)  snijaf:b
   match(b:%?x)
  match(b:!x)
   match(b:b)
{!} a b b
    S   0,00 sec
*/

#if !DEBUGBRACMAT
#define match(IND,SUB,PAT,SNIJAF) match(SUB,PAT,SNIJAF)
#define stringmatch(IND,SUB,PAT) stringmatch(SUB,PAT)
#endif

static size_t patlen(psk pat)
    {
    if(is_op(pat))
        {
        if(kop(pat) == MATCH)
            {
            size_t len = patlen(pat->LINKS);
            if(!len)
                return patlen(pat->RECHTS);
            else
                return len;
            }
        else
            return 0;
        }
    else
        {
        if(
#if COMPILE
           RPOBJ(pat)
#else
           pat->u.obj
#endif
           )
            {
            int flgs = pat->flgs;
            if(flgs & (UNIFY|INDIRECT|DUBBEL_INDIRECT|KLEINER_DAN|GROTER_DAN))
                return 0;
            else
                {
                if(flgs & NOT)
                    {
                    if(flgs & (BREUK | NUMBER | ATOOM | NONIDENT))
                        flgs &= ~(NOT|BREUK | NUMBER | ATOOM | NONIDENT);
                    }
                if(flgs & NOT)
                    return 0;
                return strlen((char*)POBJ(pat)) + ((pat->flgs & MINUS) ? 1 : 0);
                }
            }
        else
            return 0;
        }
    }

#if 1
#define stringprematch(IND,SUB,PAT) stringprematch(SUB,PAT)
#define falsifiable(IND,PAT) falsifiable(PAT)
static int falsifiable(int ind,psk pat)
    {
    register unsigned int flgs;
#if DEBUGBRACMAT
    if(debug)
        {
        printf("%d%*sfalsifiable(",ind,ind,"");result(pat);printf(")");
        }
#endif
    flgs = pat->flgs;
    if(flgs & NOT/*|INDIRECT|DUBBEL_INDIRECT*/)
        return FALSE;
    if (flgs & (BREUK | NUMBER | /*NONIDENT |*/ ATOOM | IDENT))
		{
#if DEBUGBRACMAT
        if(debug)
            {
		    printf("1\n");
            }
#endif
		return TRUE;
		}
	if(IS_VARIABLE(pat))
		{
#if DEBUGBRACMAT
        if(debug)
            {
    		printf("0\n");
            }
#endif
		return FALSE;
		}
	if(kop(pat) == LUCHT)
		{
        int ret = falsifiable(ind+1,pat->LINKS) || falsifiable(ind+1,pat->RECHTS);
#if DEBUGBRACMAT
        if(debug)
            {
            printf("%c\n",ret ? '1' : '0');
            }
#endif
		return ret;
		}
#if DEBUGBRACMAT
    if(debug)
        {
    	printf("1\n");
        }
#endif
	return TRUE;
    }


static int stringprematch(int ind,unsigned char * sub, psk pat)
    {
    register unsigned int flgs;
#if DEBUGBRACMAT
    if(debug)
        {
        printf("%d%*sprematch(%s",ind,ind,"",sub);printf(":");result(pat);printf(")");
        }
#endif
    flgs = pat->flgs;
    if(flgs & (UNIFY | INDIRECT | DUBBEL_INDIRECT | UNIFY | FENCE | BREUK | NUMBER | NONIDENT | ATOOM | IDENT | KLEINER_DAN | GROTER_DAN | NOT))
        return TRUE;

    if(kop(pat) == LUCHT)
		{
		unsigned char * sloc = sub;
        size_t len = patlen(pat->LINKS);
        if(len > 0)
            {
            while(len && *sloc)
                {
                --len;
                ++sloc;
                }
            if(len)
                {
                return FALSE;
                }
            else if(*sloc)
                {
				unsigned char sav = *sloc;
				*sloc = '\0';
				if(stringprematch(ind+1,sub, pat->LINKS))
                    {
    				*sloc = sav;
	    			return stringprematch(ind+1,sloc, pat->RECHTS);
                    }
                else
                    {
    				*sloc = sav;
                    return FALSE;
                    }
                }
            return TRUE;
            }
		else
			{
			if(falsifiable(ind+1,pat->RECHTS))
				{
				do
					{
					if(stringprematch(ind+1,sloc,pat->RECHTS))
						{
						return TRUE;
						}
					}
				while(*sloc++);
				if(stringprematch(ind+1,sloc,pat->RECHTS))
					{
					return TRUE;
					}
                return FALSE;
				}
#if DEBUGBRACMAT
            if(debug)
                {
    			printf("1\n");
                }
#endif
    		return TRUE;
			}
		}
    if(  is_op(pat)
#if COMPILE
      || !RPOBJ(pat)
#else
      || !pat->u.obj
#endif
	  )
		{
#if DEBUGBRACMAT
        if(debug)
            {
			printf("1\n");
            }
#endif
		return TRUE;
		}
	else
        {
        return scompare((unsigned char*)sub, pat) & TRUE;
        }
    }
#endif


static char stringmatch(int ind,unsigned char * sub, psk pat)
    {
/*
lmr of rmr hebben 3 onafhankelijke vlaggen : TRUE/FALSE, ONCE en FENCE.
TRUE/FALSE Het slagen van de match.
ONCE       Onbereidheid van het patroon om andere subjecten te matchen.
           Van belang voor patroon met spatie, + of * operator.
           Wordt in patronen aangezet door de `@#/ vlaggen en de operatoren
           anders dan spatie + * _ & : | = $ '.
           Wordt uitgezet in patroon met spatie + * of | operator.
FENCE      Onbereidheid van het subject om door alternatieve patronen gematcht
           te worden. Van belang voor de | en : operatoren in een patroon.
           Wordt aangezet door ` vlag (al dan niet in een patroon).
           Wordt uitgezet in patroon met spatie + * | of : operator.
           (Bij | en : operatoren geldt dit alleen voor de linkeroperand,
           bij de andere voor alle behalve de laatste operand in een lijst.)
*/
    char lmr, rmr;
    psk loc;
    unsigned char * sloc;
    register unsigned int flgs;
	char sav;
#if DEBUGBRACMAT
    if(debug)
        {
        printf("%d%*sstringmatch(%s",ind,ind,"",sub);printf(":");result(pat);printf(")");printf("\n");
        }
#endif
    lmr = SCHAR_MAX;
    rmr = FALSE;
    flgs = pat->flgs;
    if ( !(  ((flgs & NONIDENT) && ( (!sub[0] && 1)                   ^ ONTKENNING(flgs, NONIDENT)))
          || ((flgs & ATOOM   ) && ( (sub[0] && sub[1] && 1)          ^ ONTKENNING(flgs, ATOOM   )))
          || ((flgs & BREUK   ) && ( !(fullnumbercheck(sub) | QBREUK) ^ ONTKENNING(flgs, BREUK   )))
          || ((flgs & NUMBER  ) && ( !fullnumbercheck(sub)            ^ ONTKENNING(flgs, NUMBER  )))
          )
       )
        {
        if(IS_VARIABLE(pat))
            {
            psk name = NULL;
            int ok = TRUE;
            if(is_op(pat))
                {
                unsigned int saveflgs = flgs & VISIBLE_FLAGS;
                name = subboomcopie(pat);
                name->flgs &= ~VISIBLE_FLAGS;
                name->flgs |= SUCCES;
                if ((rmr = (char)evalueer(&name)) != TRUE)
                    ok = FALSE;
                name->flgs |= saveflgs;
                pat = name;
                }
            if(ok)
                {
                if (flgs & UNIFY)        /* ?  */
                    {
                    if (!NIKS(pat) || *sub)
                        {
                        if (  is_op(pat)
#if COMPILE
                           || RPOBJ(pat)
#else
                           || pat->u.obj
#endif
                           )
                            if (flgs & INDIRECT)        /* ?! of ?!! */
                                {
                                if (naamwoord_w(pat, &loc))
                                    {
                                    if (is_object(loc))
                                        rmr = (char)scopy_insert(loc, sub);
                                    else
                                        {
                                        rmr = (char)evalueer(&loc);
                                        if(!scopy_insert(loc, sub))
                                            rmr = FALSE;
                                        }
                                    wis(loc);
                                    }
                                }
                            else
                                rmr = (char)scopy_insert(pat, sub);
                        else
                            rmr = TRUE;
                        }
                    }
                else if (flgs & INDIRECT)        /* ! of !! */
                    {
                    if (naamwoord_w(pat, &loc))
                        {
                        rmr = (char)(stringmatch(ind+1,sub, loc) ^ NIKS(pat));
                        wis(loc);
                        }
                    else
                        rmr = (char)NIKS(pat);
                    }
                }
            if(name)
                wis(name);
            }
        else
            switch (kop(pat))
                {
                case PLUS:
                case MAAL:
                    break;
                case LUCHT:
                    if((lmr = (char)(TRUE & stringmatch(ind+1,(unsigned char *)"", pat->LINKS))) != 0)
                        {
                        if (!*sub)
                            {
                            if((rmr = (char)(TRUE & stringmatch(ind+1,(unsigned char *)"", pat->RECHTS))) != 0)
                                {
                                break;
                                }
                            }
                        else
                            {
                            if((rmr = (char)(TRUE & stringmatch(ind+1,sub, pat->RECHTS))) != 0)
                                {
                                break;
                                }
                            }
                        }
                    if(*sub)
                        {
                        sloc = sub+1;
#if 1
					    if(!falsifiable(ind+1,pat->LINKS) && falsifiable(ind+1,pat->RECHTS))
						    {
						    while(*sloc)
							    {
							    if(stringprematch(ind+1,sloc,pat->RECHTS))
								    {
								    sav = *sloc;
								    *sloc = '\0';
    						        lmr = stringmatch(ind+1,sub, pat->LINKS);
								    *sloc = sav;
								    rmr = (lmr & TRUE) ? (char)(~ONCE & stringmatch(ind+1,sloc, pat->RECHTS)) : (char)0;
								    if ((rmr & TRUE) || (lmr & ONCE))
									    {
									    /* klaar! (geslaagd of geONCEd) */
									    rmr |= (char)(pat->flgs & FENCE);
									    if(pat->flgs & SATOMFILTERS || (sloc > sub && pat->flgs & ATOOM))
										    rmr |= ONCE;
									    return (char)(rmr ^ (char)NIKS(pat));
									    }
								    }
							    ++sloc;
							    }
						    }
					    else
#endif
						    {
                            size_t len = patlen(pat->LINKS);
                            if(len > 0)
                                {
                                if(len > 1 && pat->flgs & ATOOM)
                                    {
                                    rmr = ONCE; /* @ab This is quite a useless pattern */
                                    break;
                                    }
                                else
                                    {
                                    --len; /* compensate for initial length 1 (sloc = sub + 1)*/
                                    while(len && *sloc)
                                        {
                                        --len;
                                        ++sloc;
                                        }

                                    if(len)
                                        {
                                        rmr = ONCE;
                                        break;
                                        }
                                    else if(*sloc)
                                        {
							            sav = *sloc;
							            *sloc = '\0';
							            lmr = stringmatch(ind+1,sub, pat->LINKS);
							            *sloc = sav;
							            rmr = (lmr & TRUE) ? (char)(~ONCE & stringmatch(ind+1,sloc, pat->RECHTS)) : (char)0;
                                        break;
                                        }
                                    }
                                }
                            else
                                {
						        while(*sloc)
							        {
							        sav = *sloc;
							        *sloc = '\0';
							        lmr = stringmatch(ind+1,sub, pat->LINKS);
							        *sloc = sav;
							        rmr = (lmr & TRUE) ? (char)(~ONCE & stringmatch(ind+1,sloc, pat->RECHTS)) : (char)0;
							        if ((rmr & TRUE) || (lmr & ONCE))
								        {
								        /* klaar! (geslaagd of geONCEd) */
								        rmr |= (char)(pat->flgs & FENCE);
								        if(pat->flgs & SATOMFILTERS || (sloc > sub && pat->flgs & ATOOM))
									        rmr |= ONCE;
								        return (char)(rmr ^ (char)NIKS(pat));
								        }
							        ++sloc;
							        }
                                }
						    }
                        }

                    rmr = 0;
                    if (  *sub
                       && (lmr = (char)(~(ONCE | FENCE) & stringmatch(ind+1,sub, pat->LINKS))) & TRUE
                       )
                        rmr |= (char)(~ONCE & stringmatch(ind+1,(unsigned char *)"", pat->RECHTS)); /* do not extinguish FENCE flag on rightmost subpattern */
                    break;
                case STREEP:
                    if(sub[0] && sub[1])
                        {
						sav = sub[1];
						lmr = stringmatch(ind+1,sub, pat->LINKS);
						sub[1] = sav;
                        if ((lmr & TRUE)
                             && (rmr = stringmatch(ind+1,sub+1, pat->RECHTS)) & TRUE)
                            {
                            dummy_op = LUCHT;
                            }
                        }
                    break;
                case EN:
                    if ((lmr = stringmatch(ind+1,sub, pat->LINKS)) & TRUE)
                        {
                        loc = zelfde_als_w(pat->RECHTS);
                        /* 13 november 1991 */
                        evalueer(&loc);
                        if (loc->flgs & SUCCES)
                            {
                            rmr = TRUE;
                            if (loc->flgs & FENCE)
                                rmr |= ONCE;
                            }
                        else
                            {
                            rmr = FALSE;
                            if (loc->flgs & FENCE)
                                rmr |= (FENCE | ONCE);        /* 13 november 1991 */
                            }
                        wis(loc);
                        }
                    break;
                case MATCH:
                    if ((lmr = stringmatch(ind+1,sub, pat->LINKS)) & TRUE)
                        rmr = (char)(stringmatch(ind+1,sub, pat->RECHTS) & TRUE);
                    else
                        rmr = FALSE;
                    break;
                case OF:
                    if ((lmr = (char)(stringmatch(ind+1,sub, pat->LINKS) & ~ONCE)) & (TRUE | FENCE))
                        rmr = (char)(lmr & TRUE);
                    else
                        rmr = stringmatch(ind+1,sub, pat->RECHTS);
                    /* & ~ONCE; removed 13 november 1991 */
                    lmr &= ~(FENCE | ONCE);
                    break;
                case FUN:
                case FUU:
                    loc = zelfde_als_w(pat);
                    evalueer(&loc);
                    if (vgl(pat, loc))
                        {
                        rmr = /*~DONOTSHORTEN & */(char)(stringmatch(ind+1,sub, loc) ^ NIKS(loc));
                        wis(loc);
                        break;
                        }
                    wis(loc);
                    /* doorvallen */
                default:
                    if(!is_op(pat))
                        {
#if COMPILE
                        if (RPOBJ(pat)
#else
                        if (pat->u.obj
#endif
                        || !(flgs & (BREUK | NUMBER | NONIDENT | ATOOM | IDENT)))
                            {

                            rmr = (char)(/** / ONCE | / **/ scompare((unsigned char*)sub, pat));
#if DEBUGBRACMAT
                            if(debug)
                                {
							    if(rmr & ONCE)
								    printf("ONCE|");
							    if(rmr & TRUE)
								    printf("TRUE\n");
							    else
								    printf("FALSE\n");
                                }
#endif
#if WRITETRACE
Log("compare done");
#endif
                            }
                        else         /* e.g.    a b c : % */
                            {
                            rmr = TRUE;
                            }
                        }
                }
        }
    if (lmr != SCHAR_MAX)
        rmr |= (char)(lmr & (FENCE | ONCE));
    rmr |= (char)(pat->flgs & FENCE);
    if (pat->flgs & SATOMFILTERS)
        rmr |= ONCE;
    if(is_op(pat))
        rmr ^= (char)NIKS(pat);
    return rmr;
    }


static char
match(int ind,psk sub, psk pat, psk snijaf)
    {
/*
lmr of rmr hebben 3 onafhankelijke vlaggen : TRUE/FALSE, ONCE en FENCE.
TRUE/FALSE Het slagen van de match.
ONCE       Onbereidheid van het patroon om andere subjecten te matchen.
           Van belang voor patroon met spatie, + of * operator.
           Wordt in patronen aangezet door de `@#/ vlaggen en de operatoren
           anders dan spatie + * _ & : | = $ '.
           Wordt uitgezet in patroon met spatie + * of | operator.
FENCE      Onbereidheid van het subject om door alternatieve patronen gematcht
           te worden. Van belang voor de | en : operatoren in een patroon.
           Wordt aangezet door ` vlag (al dan niet in een patroon).
           Wordt uitgezet in patroon met spatie + * | of : operator.
           (Bij | en : operatoren geldt dit alleen voor de linkeroperand,
           bij de andere voor alle behalve de laatste operand in een lijst.)
*/
    char lmr, rmr/*,shifted*/;
    psk loc;
    register unsigned int flgs;
#if DEBUGBRACMAT
    if(debug)
        {
        printf("%d%*smatch(",ind,ind,"");results(sub,snijaf);printf(":");result(pat);printf(")");printf("\n");
        }
#endif
    if (is_op(sub))
        {
        /*
         * if(kop(sub) == WORDT) return match(sub->RECHTS,pat,NULL); else
         */
        if (sub->RECHTS == snijaf)
            return match(ind+1,sub->LINKS, pat, NULL);
        }
    lmr = SCHAR_MAX;
    rmr = FALSE;
    flgs = pat->flgs;
    if ( !(  ((flgs & NONIDENT) && (((sub->flgs & IDENT) && 1) ^ ONTKENNING(flgs, NONIDENT)))
          || ((flgs & ATOOM   ) && ((is_op(sub)          && 1) ^ ONTKENNING(flgs, ATOOM   )))
          || ((flgs & BREUK   ) && ( !RAT_RAT(sub)             ^ ONTKENNING(flgs, BREUK   )))
          || ((flgs & NUMBER  ) && ( !RATIONAAL_COMP(sub)      ^ ONTKENNING(flgs, NUMBER  )))
          )
       )
        {
        if(IS_VARIABLE(pat))
            {
#if 1
            psk name = NULL;
            int ok = TRUE;
            if(is_op(pat))
                {
                unsigned int saveflgs = flgs & VISIBLE_FLAGS;
                name = subboomcopie(pat);
                name->flgs &= ~VISIBLE_FLAGS;
                name->flgs |= SUCCES;
                if ((rmr = (char)evalueer(&name)) != TRUE)
                    ok = FALSE;
                name->flgs |= saveflgs;
                pat = name;
                }
            if(ok)
                {
                if (flgs & UNIFY)        /* ?  */
                    {
#if COMPILE
                    if (!NIKS(pat) || is_op(sub) || RPOBJ(sub))
#else
                    if (!NIKS(pat) || is_op(sub) || (sub->u.obj))
#endif
                        {
                        if (  is_op(pat)
#if COMPILE
                           || RPOBJ(pat)
#else
                           || pat->u.obj
#endif
                           )
                            if (flgs & INDIRECT)        /* ?! of ?!! */
                                {
                                if (naamwoord_w(pat, &loc))
                                    {
                                    if (is_object(loc))
                                        rmr = /*~DONOTSHORTEN & */(char)copy_insert(loc, sub, snijaf);
                                    else
                                        {
                                        rmr = /*~DONOTSHORTEN & */(char) evalueer(&loc);
                                        if(!copy_insert(loc, sub, snijaf))
                                            rmr = FALSE;
                                            /* 19971207. Previously, rmr was not influenced by failure of copy_insert */

                                        }
                                    wis(loc);
                                    }
                                }
                            else
                                rmr = (char)copy_insert(pat, sub, snijaf);
                                /* 19971207. Previously, rmr was unconditionally set to TRUE */

                        else
                            rmr = TRUE;
                        }
                    /*
                     * else NIKS(pat) && !is_op(sub) && !sub->u.obj
                     * dwz   ~?[`][!][!]
                     */
                    }
                else if (flgs & INDIRECT)        /* ! of !! */
                    {
                    if (naamwoord_w(pat, &loc))
                        {
                        rmr = /*~DONOTSHORTEN & */(char)(match(ind+1,sub, loc, snijaf) ^ NIKS(pat));
                        wis(loc);
                        }
                    else
                        rmr = /*~DONOTSHORTEN & */(char)NIKS(pat);
                    }
/*
				if(debug)
					{
					if(rmr & DONOTSHORTEN)
						{
						printf("! DONOTSHORTEN\n");
						}
					}
*/
                }
            if(name)
                wis(name);
#else
            if(is_op(pat))
                {
                if (flgs & (UNIFY | INDIRECT))
                    {
                    psk name;
                    name = subboomcopie(pat);
                    name->flgs &= ~NOT;
                    name->flgs |= SUCCES;
    /*19971203
    Bug in next line:
        x= (p = a | b);
        a:!(x.p) succeeds, but b:!(x.p) fails, because a | b has been evaluated to a
    */
                    if ((rmr = evalueer(&name)) == TRUE)
                        {
                        if (flgs & UNIFY)        /* ?  */
                            rmr = copy_insert(name, sub, snijaf);
                        else
                            rmr = (match(sub, name, snijaf) ^ NIKS(pat));
                        }
                    wis(name);
                    }
                }
            else
                {
                if (flgs & UNIFY)        /* ?  */
                    {
                    if (!NIKS(pat) || is_op(sub) || (sub->u.obj))
                        {
                        if (pat->u.obj)
                            if (flgs & INDIRECT)        /* ?! of ?!! */
                                {
                                if (naamwoord_w(pat, &loc))
                                    {
                                    if (is_object(loc))
                                        rmr = copy_insert(loc, sub, snijaf);
                                    else
                                        {
                                        rmr = (char) evalueer(&loc);
                                        copy_insert(loc, sub, snijaf);
                                        }
                                    wis(loc);
                                    }
                                }
                            else
                                {
                                copy_insert(pat, sub, snijaf);
                                rmr = TRUE;
                                }
                        else
                            rmr = TRUE;
                        }
                    /*
                     * else NIKS(pat) && !is_op(sub) && !sub->u.obj
                     * dwz   ~?[`][!][!]
                     */
                    }
                else if (flgs & INDIRECT)        /* ! of !! */
                    {
                    if (naamwoord_w(pat, &loc))
                        {
                        rmr = (match(sub, loc, snijaf) ^ NIKS(pat));
                        wis(loc);
                        }
                    else
                        rmr = NIKS(pat);
                    }
                }
#endif
            }
        else
            switch (kop(pat))
                {
                case LUCHT:
                case PLUS:
                case MAAL:
                    /*shifted = (char)0;*/
                    if (  !is_op(sub)
                       && !HAS_UNOPS(sub)
/*#if COMPILE*/
                       && (PIOBJ(sub) == PIOBJ(nil(pat)))
/*#else
                       && (sub->u.iobj == nil(pat)->u.iobj)
#endif*/
                       && (lmr = (char)(TRUE & match(ind+1,nil(pat), pat->LINKS, NULL))) != 0
/*
#if KORT
                       && (rmr = (char)((TRUE|DONOTSHORTEN/ *Bart 20010613* /) & match(ind+1,nil(pat), pat->RECHTS, NULL))) != 0
#else
*/

                       && (rmr = (char)( TRUE                                & match(ind+1,nil(pat), pat->RECHTS, NULL))) != 0
/*#endif*/
                       )
                        {
                        break;
                        }
                    if (  (  is_op(sub)        /* fct loopt soms vast zonder dit */
                          || HAS_UNOPS(sub)        /* (UNIFY | FLGS) */
/*#if COMPILE*/
                          || (PIOBJ(sub) != PIOBJ(nil(pat)))
/*#else
                          || (sub->u.iobj != nil(pat)->u.iobj)
#endif*/
                          )
                       && (lmr = (char)(TRUE & match(ind+1,nil(pat), pat->LINKS, NULL))) != 0
/*
#if KORT
                       && (rmr = (char)((TRUE|DONOTSHORTEN/ *Bart 20010613* /) & match(ind+1,sub, pat->RECHTS, snijaf))) != 0
#else
*/
                       && (rmr = (char)( TRUE                                & match(ind+1,sub, pat->RECHTS, snijaf))) != 0
/*#endif*/
                       )
                        {
                        break;
                        }
                    if (  kop(sub) == kop(pat)
                       && (loc = sub->RECHTS) != snijaf
                       )
                        {
                        /*shifted = (char)1;*/
                        do
                            {
                            /*printf("sub:");results(sub,snijaf);printf("  pat->LINKS:");result(pat->LINKS);printf("  loc:");result(loc);
                            printf("  pat->RECHTS:");result(pat->RECHTS);
                            if(snijaf)
                                {printf("  snijaf:");result(snijaf);}
                            printf("\n");*/
                            lmr = match(ind+1,sub, pat->LINKS, loc);
                            /*if(lmr & TRUE)*/
                            rmr = (lmr & TRUE) ? (char)(~ONCE & match(ind+1,loc, pat->RECHTS, snijaf)) : (char)0;
                            if ((rmr & (TRUE/*|DONOTSHORTEN/ *Bart 20010613*/)) || (lmr & ONCE))
                                {
                                /* klaar! (geslaagd of geONCEd) */
                                rmr |= (char)(pat->flgs & FENCE);
                                if(pat->flgs & ATOMFILTERS)
                                    rmr |= ONCE;
                                return (char)(rmr ^ (char)NIKS(pat));
                                }
                            else if (kop(loc) != kop(pat))
                                break;
                            loc = loc->RECHTS;
                            }
                        while(loc != snijaf);
                        rmr = 0;
                        }
/*
#if KORT / *:Bart 20010613* /
                    else
                        {
                        rmr = DONOTSHORTEN;
                        if(debug)
							{
                            printf(" %*s%d %d DONOTSHORTEN\n",ind,"",kop(sub) == kop(pat),(loc = sub->RECHTS) != snijaf);
					        printf(" %*smatch(",ind,"");results(sub,snijaf);printf(":");result(pat);printf(")");if(snijaf){printf("  snijaf:");result(snijaf);}printf("\n");
							}
                        }
#endif
*/
                    if (  (  is_op(sub)
                          || HAS_UNOPS(sub)        /* (UNIFY | FLGS) */
/*#if COMPILE*/
                          || (PIOBJ(sub) != PIOBJ(nil(pat)))
/*#else
                          || (sub->u.iobj != nil(pat)->u.iobj)
#endif*/
                          )
                       && (lmr = (char)(~(ONCE | FENCE) & match(ind+1,sub, pat->LINKS, snijaf))) & TRUE
                       )
                        rmr |= (char)(~ONCE & match(ind+1,nil(pat), pat->RECHTS, NULL));
                    break;
                case STREEP:
                    if (is_op(sub))
                        {
                        if(kop(sub) == WORDT && ISBUILTIN((objectknoop*)sub))
                            {
                            printf("You cannot match an object '=' with '_' if the object is built-in\n");
                            rmr = ONCE;
                            }
                        else if ((lmr = match(ind+1,sub->LINKS, pat->LINKS, NULL)) & TRUE
                             && (rmr = match(ind+1,sub->RECHTS, pat->RECHTS, snijaf)) & TRUE) /* NULL --> snijaf 20031110 */
                            {
                            dummy_op = kop(sub);
                            dummy_flgs = sub->flgs & VISIBLE_FLAGS;
                            }
                        }
                    break;
                case EN:
                    if ((lmr = match(ind+1,sub, pat->LINKS, snijaf)) & TRUE)
                        {
                        loc = zelfde_als_w(pat->RECHTS);
                        /* 13 november 1991 */
                        evalueer(&loc);
                        if (loc->flgs & SUCCES)
                            {
                            rmr = TRUE;
                            if (loc->flgs & FENCE)
                                rmr |= ONCE;
                            }
                        else
                            {
                            rmr = FALSE;
                            if (loc->flgs & FENCE)
                                rmr |= (FENCE | ONCE);        /* 13 november 1991 */
                            }
                        wis(loc);
                        }
                    break;
                case MATCH:
                    if ((lmr = match(ind+1,sub, pat->LINKS, snijaf)) & TRUE)
                        {
						if(pat->flgs & ATOOM)
							rmr = (char)(stringmatch(ind+1,POBJ(sub),pat->RECHTS) & TRUE);
						else
                            rmr = (char)(match(ind+1,sub, pat->RECHTS, snijaf) & TRUE);
/*                        rmr = (char)(match(ind+1,sub, pat->RECHTS, snijaf) & TRUE);*/
                        }
                    else
                        rmr = FALSE;
                    break;
                case OF:
                    if ((lmr = (char)(match(ind+1,sub, pat->LINKS, snijaf) & ~ONCE)) & (TRUE | FENCE))
                        rmr = (char)(lmr & TRUE);
                    else
                        rmr = match(ind+1,sub, pat->RECHTS, snijaf);
                    /* & ~ONCE; removed 13 november 1991 */
                    lmr &= ~(FENCE | ONCE);
                    break;
                case FUN:
                case FUU:
                    loc = zelfde_als_w(pat);
                    evalueer(&loc);
                    if (vgl(pat, loc))
                        {
                        rmr = /*~DONOTSHORTEN & */(char)(match(ind+1,sub, loc, snijaf) ^ NIKS(loc));
                        wis(loc);
                        break;
                        }
                    wis(loc);
                    /* doorvallen */
                default:
                    if(is_op(pat))
                        {
                        if(kop(sub) == kop(pat))
                            {
                            if ((lmr = match(ind+1,sub->LINKS, pat->LINKS, NULL)) & TRUE)
                                rmr = match(ind+1,sub->RECHTS, pat->RECHTS, NULL);
                            }
                        }
                    else
                        {
                        /* 19971207 register long flgs;*/
                        /*flgs = pat->flgs;*/
#if COMPILE
                        if (RPOBJ(pat)
#else
                        if (pat->u.obj
#endif
                        || !(flgs & (BREUK | NUMBER | NONIDENT | ATOOM | IDENT)))
                            {

                            rmr = (char)(/**/ ONCE | /**/ compare(sub, pat));
#if WRITETRACE
Log("compare done");
#endif
                            }
                        else         /* e.g.    a b c : % */
                            {
                            rmr = TRUE;
                            }
                        }
                }
        }
    if (lmr != SCHAR_MAX)
        rmr |= (char)(lmr & (FENCE | ONCE));
    rmr |= (char)(pat->flgs & FENCE);
    if (pat->flgs & ATOMFILTERS)
        rmr |= ONCE;
    if(is_op(pat))
        rmr ^= (char)NIKS(pat);
    return rmr;
    }



static int subroot(ngetal ag,char *conc[],int *pind)
{
int macht,i;
unsigned long g,kleindeler;
unsigned long ores;
static int bijt[12]=
  {1,  2,  2,  4,    2,    4,    2,    4,    6,    2,  6};
/*2-3,3-5,5-7,7-11,11-13,13-17,17-19,19-23,23-29,29-1,1-7*/
unsigned long grootdeler;

#ifdef ERANGE   /* ANSI C : strtoul() out of range */
errno = 0;
g = strtoul(ag.number,NULL,10);
if(errno == ERANGE)
    return FALSE;
#else  /* TURBOC, vcc */
if(ag.length > 10 || ag.length == 10  && strcmp(ag.number,"4294967295") > 0)
    return FALSE;
#ifdef vax
g = atol(ag.number);
#else
g = strtoul(ag.number,NULL,10);
#endif
#endif
ores = 1;
macht = 1;
kleindeler = 2;
i = 0;
while((grootdeler = g / kleindeler) >= kleindeler)
    {
    if(grootdeler * kleindeler == g)
        {
        g = grootdeler;
        if(kleindeler != ores)
            {
            if(ores != 1)
                {
                if(ores < 1000)
                    conc[(*pind)] = (char*)bmalloc(__LINE__,12);
                else
                    conc[*pind] = (char*)bmalloc(__LINE__,20);
                sprintf(conc[(*pind)++],"%ld^(%d*\1)*",ores,macht);
                }
            macht = 1;
            ores = kleindeler;
            }
        else
            macht++;
        }
    else
        {
        kleindeler += bijt[i];
        if(++i > 10)
            i = 3;
        }
    }
if(ores == 1 && macht == 1)
    return FALSE;
conc[*pind] = (char*)bmalloc(__LINE__,24);
if((ores == g && ++macht) || ores == 1)
    sprintf(conc[(*pind)++],"%ld^(%d*\1)",g,macht);
else
    sprintf(conc[(*pind)++],"%ld^(%d*\1)*%ld^\1",ores,macht,g);
return TRUE;
}

static int root(ppsk pkn)
{
char **conc,slash = 0;
int wipe[20],ind;
ngetal teller,noemer;
for(ind = 0; ind < 20; wipe[ind++] = TRUE);
ind = 0;
conc = (char**)bmalloc(__LINE__,20 * sizeof(char **));
   /* 20 is veilige waarde voor ULONGs */
adr[1] = (*pkn)->RECHTS;
if(RAT_RAT_COMP((*pkn)->LINKS))
    {
    splits((*pkn)->LINKS,&teller,&noemer);
    if(!subroot(teller,conc,&ind))
        {
        wipe[ind] = FALSE;
        conc[ind++] = teller.number;
        slash = teller.number[teller.length];
        teller.number[teller.length] = 0;

        wipe[ind] = FALSE;
        conc[ind++] = "^\1";
        }
    wipe[ind] = FALSE;
    conc[ind++] = "*(";
    if(!subroot(noemer,conc,&ind))
        {
        wipe[ind] = FALSE;
        conc[ind++] = noemer.number;
        wipe[ind] = FALSE;
        conc[ind++] = "^\1";
        }
    wipe[ind] = FALSE;
    conc[ind++] = ")^-1";
    }
else
    {
    teller.number = (char*)POBJ((*pkn)->LINKS);
    teller.alloc = NULL;
    teller.length = strlen(teller.number);
    if(!subroot(teller,conc,&ind))
        {
        bfree(conc);
        return TRUE;
        }
    }
conc[ind--] = NULL;
*pkn = vopb(*pkn,(const char**)conc);
if(slash)
    teller.number[teller.length] = slash;
for(;ind >= 0;ind--)
   if(wipe[ind])
       bfree(conc[ind]);
bfree(conc);
return TRUE;
}

static int abseen(psk kn)
{
register unsigned char *wijzer;
wijzer = POBJ(kn);
return(*wijzer == '1' && *++wijzer == 0);
}

static int casemacht(ppsk pkn)
{
static const char *conc[] = {NULL,NULL,NULL,NULL,NULL,NULL},
haakmineen[] = ")^-1",
haakhekje1macht[] = "(\1^",
macht2maaleenmacht[] = ")^2*\1^";
psk lknoop,rknoop;
lknoop = (*pkn)->LINKS;
if(!RATIONAAL_COMP(lknoop))
    {
    return FALSE;
    }
rknoop = (*pkn)->RECHTS;
if(GEHEEL_NIET_NUL_COMP(rknoop) && !abseen(rknoop))
    {
    adr[1] = lknoop;
    if(GEHEEL_POS_COMP(rknoop))
        {
        if(_qvergelijk(&tweek,rknoop) & MINUS)
            {
            /* m^n = (m^(n\2))^2*m^(n mod 2) */
            switch(range(rknoop))
                {/* Ik weet niet meer wat hier de bedoeling van was (09091997)*/
                case  0:  conc[0] = "("  ;  break;
                case -2:  conc[0] = "<(" ;  break;
                case -1:  conc[0] = "~>(";  break;
                case  1:  conc[0] = "~<(";  break;
                case  2:  conc[0] = ">(" ;  break;
                }
            conc[1] = "\1^" /*haakhekje1macht*/;
            conc[2] = hekje5;
            conc[4] = hekje6;
            adr[5] = _qheeldeel(rknoop,&tweek);
            conc[3] = macht2maaleenmacht;
            adr[6] = _qmodulo(rknoop,&tweek);
            *pkn = vopb(*pkn,conc);
            wis(adr[5]);
            wis(adr[6]);
            }
        else
            {
            int ra;
            /* m^2 = m*m */
            ra = range(rknoop);
            if(!ra)
                *pkn = opb(*pkn,"(\1*\1)",NULL);
            else
                *pkn = opb(*pkn,
                          ra == -2 ?  "<(\1*\1)" :
                          ra == -1 ? "~>(\1*\1)" :
                          ra ==  1 ? "~<(\1*\1)" :
                                      ">(\1*\1)"
                          ,NULL);
            }
        }
    else
        {
        /* (a+b)^-n = ((a+b)^n)^-1 */
        conc[0] = haakhekje1macht;
        conc[1] = hekje6;
        adr[6] = _qmaalmineen(rknoop);
        conc[2] = haakmineen;
        conc[3] = 0;
        *pkn = vopb(*pkn,conc);
        wis(adr[6]);
        }
    return TRUE;
    }
else if(RAT_RAT(rknoop))
    {
    return root(pkn);
    }
return FALSE;
}

static psk linkertak(psk pkn)
{
psk lknoop;
lknoop = pkn->LINKS;
if(!(pkn->flgs & SUCCES))
    {
    lknoop = prive(lknoop);
    lknoop->flgs ^= SUCCES;
    }
if(pkn->flgs & FENCE && !(lknoop->flgs & FENCE))
    {
    lknoop = prive(lknoop);
    lknoop->flgs |= FENCE;
    }
wis(pkn->RECHTS);
pskfree(pkn);
return lknoop;
}
#define UNDERSCORE 1


static psk flinkertak(psk pkn)
{
psk lknoop;
lknoop = pkn->LINKS;
if(pkn->flgs & SUCCES)
    {
    lknoop = prive(lknoop);
    lknoop->flgs ^= SUCCES;
    }
if(pkn->flgs & FENCE && !(lknoop->flgs & FENCE))
    {
    lknoop = prive(lknoop);
    lknoop->flgs |= FENCE;
    }
wis(pkn->RECHTS);
pskfree(pkn);
return lknoop;
}

static psk _linkertak(psk pkn)
{
psk lknoop;
lknoop = pkn->LINKS;
if(!(pkn->flgs & SUCCES))
    {
    lknoop = prive(lknoop);
    lknoop->flgs ^= SUCCES;
    }
if(pkn->flgs & FENCE && !(lknoop->flgs & FENCE))
    {
    lknoop = prive(lknoop);
    lknoop->flgs |= FENCE;
    }
wis(pkn->RECHTS);
return lknoop;
}

static psk _fencelinkertak(psk pkn)
{
psk lknoop;
lknoop = pkn->LINKS;
if(!(pkn->flgs & SUCCES))
    {
    lknoop = prive(lknoop);
    lknoop->flgs ^= SUCCES;
    }
if(pkn->flgs & FENCE) /* 19980207 */
    {
    if(!(lknoop->flgs & FENCE))
        {
        lknoop = prive(lknoop);
        lknoop->flgs |= FENCE;
        }
    }
else if(lknoop->flgs & FENCE)
    {
    lknoop = prive(lknoop);
    lknoop->flgs &= ~FENCE;
    }
/*
if(pkn->flgs & FENCE && !(lknoop->flgs & FENCE))
    {
    lknoop = prive(lknoop);
    lknoop->flgs |= FENCE;
    }
else
if(lknoop->flgs & FENCE)
    {
    lknoop = prive(lknoop);
    lknoop->flgs &= ~FENCE;
    }
*/
wis(pkn->RECHTS);
return lknoop;
}

static psk _flinkertak(psk pkn)
{
psk lknoop;
lknoop = pkn->LINKS;
if(pkn->flgs & SUCCES)
    {
    lknoop = prive(lknoop);
    lknoop->flgs ^= SUCCES;
    }
if(pkn->flgs & FENCE && !(lknoop->flgs & FENCE))
    {
    lknoop = prive(lknoop);
    lknoop->flgs |= FENCE;
    }
wis(pkn->RECHTS);
return lknoop;
}

static psk _rechtertak(psk pkn)
{
psk rknoop;
rknoop = pkn->RECHTS;
if(!(pkn->flgs & SUCCES))
    {
    rknoop = prive(rknoop);
    rknoop->flgs ^= SUCCES;
    }
if(pkn->flgs & FENCE && !(rknoop->flgs & FENCE))
    {
    rknoop = prive(rknoop);
    rknoop->flgs |= FENCE;
    }
wis(pkn->LINKS);
return rknoop;
}

static void pop(psk kn)
    {
    while(is_op(kn))
		{
		pop(kn->LINKS);
		/* pop(kn->RECHTS);
		18 Maart 1997 */
		kn = kn->RECHTS;
		}
	deleteNode(kn);
    }

static int tryq(ppsk pkn,psk fun)
{
psk anker;
psh(&argk,*pkn,NULL);
(*pkn)->flgs |= KLAAR;

anker = subboomcopie(fun->RECHTS);

psh(fun->LINKS,&nulk,NULL);
evalueer(&anker);
pop(fun->LINKS);
if(anker->flgs & SUCCES)
    {
    wis(*pkn);
    *pkn = anker;
    deleteNode(&argk);
    return TRUE;
    }
else
    {
    wis(anker);
    deleteNode(&argk);
    return FALSE;
    }
}

static int try_le_elq(psk fun,ppsk pkn)
{
if(!is_op((*pkn)->RECHTS))
    return FALSE;
else
    return tryq(pkn,fun);
}

static psk rechteroperand(psk pkn)
{
psk temp;
unsigned int teken;
temp = (pkn->RECHTS);
return((teken = kop(pkn)) == kop(temp) &&
        (teken == PLUS || teken == MAAL || teken == LUCHT) ?
       temp->LINKS : temp);
}

static int differentieren(ppsk pkn)
{
psk lknoop,rknoop;
rknoop = (*pkn)->RECHTS;
if(RATIONAAL_COMP(lknoop = (*pkn)->LINKS) || is_op(lknoop))
    return FALSE;
if(RATIONAAL_COMP(rknoop))
    replace(pkn,&nulk);
else
    if(kop(rknoop) == PLUS)
        {
        adr[1] = (*pkn)->LINKS;
        adr[2] = rknoop->LINKS;
        adr[3] = rknoop->RECHTS;
        *pkn = opb(*pkn,"((\1\017\2)+(\1\017\3))",NULL);
        }
    else
        {
        if(is_op(rknoop))
            {
            adr[2] = rknoop->LINKS;
            adr[1] = lknoop;
            adr[3] = rknoop->RECHTS;
            switch(kop(rknoop))
                {
                case MAAL :
                    *pkn = opb(*pkn,"(\001\017\2*\3+\2*\001\017\3)",NULL);
                    break;
                case EXP:
                    *pkn = opb(*pkn,
     "(\2^(-1+\3)*\3*\001\017\2+\2^\3*e\016\2*\001\017\3)",NULL);
                    break;
                case LOG :
                    *pkn = opb(*pkn,
     "(\2^-1*e\016\2^-2*e\016\3*\001\017\2+\3^-1*e\016\2^-1*\001\017\3)",NULL);
                    break;
                }
            }
        else
            return FALSE;
        }
return TRUE;
}

static int atomtest(psk kn)
{
#if COMPILE
return (!is_op(kn) && !HAS_UNOPS(kn)) ? (int)RPOBJ(kn) : -1;
#else
return (!is_op(kn) && !HAS_UNOPS(kn)) ? (int)kn->u.obj : -1;
#endif
}

/* 20001222 void -> int */
static int evalmacro(ppsk pkn)
	{/* BJO 24 Jan 1996: dit moet efficienter kunnen! Alleen kopieren waar het nodig is! */
	while(!((*pkn)->flgs & KLAAR) && is_op(*pkn))
		{
		psk h;
		*pkn = prive(*pkn);
		if(!evalmacro(&((*pkn)->LINKS)))
			return FALSE;
		switch(kop(*pkn))
			{
			case STREEP: /* Bart 20021215 */
	/*
	#if W32
				(*pkn)->flgs &= (~OPERATOR & ~KLAAR);
	#else
				(*pkn)->flgs &= ~KLAAR;
				(*pkn)->ops &= ~OPERATOR;
	#endif
	*/

				if(dummy_op == WORDT)
					{
					psk old = *pkn;
					*pkn = (psk)bmalloc(__LINE__,sizeof(objectknoop));
					((typedObjectknoop*)(*pkn))->refcount = 0L;
					UNSETCREATEDWITHNEW((typedObjectknoop*)*pkn);
					UNSETBUILTIN((typedObjectknoop*)*pkn);
					(*pkn)->LINKS = subboomcopie(old->LINKS);
					(*pkn)->RECHTS = subboomcopie(old->RECHTS);
					/*(*pkn)->flgs |= dummy_flgs;*/
					wis(old);
					}
				/*else*/
					{
#if W32
					(*pkn)->flgs &= ~OPERATOR;
#else
					(*pkn)->ops &= ~OPERATOR;
#endif
					(*pkn)->ops |= dummy_op;
					(*pkn)->flgs |= dummy_flgs;
					}
				break;
			case FUN :
				if(atomtest((*pkn)->LINKS) == 0)
					{
					int newval;
					psk tmp = zelfde_als_w((*pkn)->RECHTS);
					evalueer(&tmp);

	/*                    if(  (atomtest((*pkn)->RECHTS) > 0 || kop((*pkn)->RECHTS) == DOT)
					  && find((*pkn)->RECHTS,&h,&newval,NULL,NULL,NULL)*/
					if(  (atomtest(tmp) > 0 || kop(tmp) == DOT)
					  && find(tmp,&h,&newval,NULL,NULL,NULL)
					  )  /* alleen $<atoom> of $(<blah>.<blah>) komt erdoor */
						{
#if W32
						int flgs = (*pkn)->flgs & (UNOPS/*|QGETAL|MINUS|QNUL|QBREUK*/);
#else
						int flgs = (*pkn)->flgs & UNOPS;
						/*int ops = (*pkn)->ops & (MINUS|QGETAL|MINUS|QNUL|QBREUK);*/
#endif
						wis(*pkn);
						if(newval)
							*pkn = h;
						else
							*pkn = zelfde_als_w(h);
						if(  flgs
#if !W32
						  /*|| ops*/
#endif
						  )
							{
							*pkn = prive(*pkn);
							(*pkn)->flgs |= flgs;
#if !W32
							/*(*pkn)->ops |= ops;*/
#endif
							if((*pkn)->flgs & INDIRECT)
								(*pkn)->flgs &= ~KLAAR;
							}
						wis(tmp);
						return TRUE;
						}
					else
						{
						printf("\nevalmacro fails: identifier (");result((*pkn)->RECHTS);printf(") not found.\n");
						wis(tmp);
						return FALSE;
						}
					}
				break;
			case FUU :
				if(atomtest((*pkn)->LINKS) == 0)
					return TRUE; /* afblijven van geneste macro's */
			}
		/* evalmacro(&((*pkn)->RECHTS));
		18 Maart 1997 */
		pkn = &((*pkn)->RECHTS);
		}
	return TRUE;
	}

static void combiflags(psk kn)
{
#if W32
int lflgs;
if((lflgs = kn->LINKS->flgs & UNOPS) != 0)
    {
    kn->RECHTS = prive(kn->RECHTS);
    kn->RECHTS->flgs |= lflgs & ~NOT;
    if(lflgs & NOT)
        kn->RECHTS->flgs ^= NOT|SUCCES;
    }
#else
int lflgs;
int lops = 0;
if((lflgs = kn->LINKS->flgs & UNOPS) != 0
|| (lops = kn->LINKS->ops & MINUS) != 0)
    {
    kn->RECHTS = prive(kn->RECHTS);
    kn->RECHTS->flgs |= lflgs & ~NOT;
    kn->RECHTS->ops |= lops;
    if(lflgs & NOT)
        kn->RECHTS->flgs ^= NOT|SUCCES;
    }
#endif
}


static int is_afhankelyk_van(psk el,psk lijst)
    {
    int ret;
    while(lijst)
        {
        psk hlp,hlp2;
        if(!vgl(el,(hlp = (kop(lijst) == KOMMA) ? lijst->LINKS : lijst)))
            return TRUE;

        if(is_op(hlp))
            {
            if(is_afhankelyk_van(el,hlp->LINKS)
            || is_afhankelyk_van(el,hlp->RECHTS))
                return TRUE;
            }
        else
            {
            int dummy;
            int retobsolete = FALSE;
            psk kn = NULL;
            hlp2 = NULL;
            if(find(hlp,&hlp2,&dummy,NULL,NULL,NULL))
                {
                if(is_afhankelyk_van(el,hlp2))
                    {
                    retobsolete = TRUE;
                    }
                }
             adr[1] = hlp;
             adr[2] = el;
             kn = opb(kn,"(!dep:(? (\1.? \2 ?) ?)",NULL);
             ret = (evalueer(&kn) == TRUE);
             wis(kn);
             if(retobsolete && !ret)
                 errorprintf("Warning:Obsolete dependency is neglected (!%s depends on %s, but is not mentioned in variable dep).\n",
                (char*)POBJ(hlp),(char*)POBJ(el));
             return ret/* || retobsolete*/;
            }
        /* return is_afhankelyk_van(el,(kop(lijst) == KOMMA) ? lijst->RECHTS : NULL);
        18 Maart 1997 */
        lijst = (kop(lijst) == KOMMA) ? lijst->RECHTS : NULL;
        }
    return FALSE;
    }

static int zoekopt(psk kn,long opt)
	{
	while(is_op(kn))
		{
		/*return zoekopt(kn->LINKS,opt) || zoekopt(kn->RECHTS,opt);
		18 Maart 1997 */
		if(zoekopt(kn->LINKS,opt))
			return TRUE;
		kn = kn->RECHTS;
		/*19970825 continue;*/
		}
	return PLOBJ(kn) == opt;
	}

static void mmf(ppsk pk)
{
psk goal;
ppsk pgoal;
vars *navar;
int alfabet,ext;
char dim[22];
ext = zoekopt(*pk,EXT);
wis(*pk);
pgoal = pk;
for(alfabet = 0;alfabet < 0x80;alfabet++)
    {
    for(navar = variabelen[alfabet];
        navar;
        navar = navar->next)
#if COMPILE
      if(navar->pvaria)
#endif
        {
#if COMPILE
        assert(navar->Refcount > 0);
#endif
        goal = *pgoal = (psk)bmalloc(__LINE__,sizeof(kknoop));
#if W32
        goal->flgs = LUCHT | SUCCES;
#else
        goal->flgs = SUCCES;
        goal->ops = LUCHT;
#endif
        if(ext && navar->n > 0) /* was 1 (16 March 1993) */
            {
            goal = goal->LINKS = (psk)bmalloc(__LINE__,sizeof(kknoop));
#if W32
            goal->flgs = DOT | SUCCES;
#else
            goal->flgs = SUCCES;
            goal->ops = DOT;
#endif
            sprintf(dim,"%d.%d",navar->n,navar->selector);
            goal->RECHTS = NULL;
            goal->RECHTS = opb(goal->RECHTS,dim,NULL);
            }
        goal = goal->LINKS =
#ifdef PVNAME
            (psk)bmalloc(__LINE__,sizeof(unsigned long) + 1 + strlen((char*)navar->vname));
        goal->flgs = (KLAAR|SUCCES);
        strcpy((char*)POBJ(goal),(char*)navar->vname);
#else
            (psk)bmalloc(__LINE__,sizeof(unsigned long) + 1 + strlen((char*)&navar->u.Obj));
        goal->flgs = (KLAAR|SUCCES);
        strcpy((char*)POBJ(goal),(char*)&navar->u.Obj);
#endif
        pgoal = &(*pgoal)->RECHTS;
        }
    }
*pgoal = zelfde_als_w(&nilk);
}

static void lstsub(psk kn)
{
vars *navar;
unsigned char *naam;
int alfabet,n;
mooi = FALSE;
naam = POBJ(kn);
for(alfabet = 0;alfabet<256;alfabet++)
    {
    for(navar = variabelen[alfabet];
        navar;
        navar = navar->next)
        {
#if COMPILE
#ifdef PVNAME
        if(navar->vname && navar->pvaria)
          {
          if((RPOBJ(kn) == 0 && alfabet < 0x80) || !STRCMP(navar->vname,naam))
#else
        if(navar->pvaria)
          {
          if((RPOBJ(kn) == 0 && alfabet < 0x80) || !STRCMP(&navar->u.Obj,naam))
#endif
#else
#ifdef PVNAME
        if((kn->u.obj == 0 && alfabet < 0x80) || !STRCMP(navar->vname,naam))
#else
        if((kn->u.obj == 0 && alfabet < 0x80) || !STRCMP(&navar->u.Obj,naam))
#endif
#endif
            {
            for(n = navar->n;n >= 0;n--)
                {
                if(fpo == stdout)
                    {
                    if(navar->n > 0)
                        printf("%c%d (",n == navar->selector ? '>' : ' ',n);
                    else
                        printf("(");
                    }
#ifdef PVNAME
                if(haalaan(navar->vname))
                    myprintf("\"",(char *)navar->vname,"\"=",NULL);
                else
                    myprintf((char *)navar->vname,"=",NULL);
#else
                if(haalaan(&navar->u.Obj))
                    myprintf("\"",(char *)&navar->u.Obj,"\"=",NULL);
                else
                    myprintf((char *)&navar->u.Obj,"=",NULL);
#endif
                if(hum)
                    myprintf("\n",NULL);
                assert(navar->pvaria);
                result(*head(entry(navar->n,n,&navar->pvaria)));
                if(fpo == stdout)
                    printf(")");
                myprintf(";\n",NULL);
                }
            }
#if COMPILE
          }
#endif
        }
    }
mooi = TRUE;
}

static void lst(psk kn)
	{
	while(is_op(kn))
		{
		lst(kn->LINKS);
		/* lst(kn->RECHTS);
		18 Maart 1997 */
		kn = kn->RECHTS;
		}
	lstsub(kn);
	}


static long tijdnr = 0L;
/*
static int openCount = 0;
static int maxOpenCount = 0;
static int allOpenCount = 0;
*/
static void sluitfile(filehendel *fh)
{
fh->filepos = ftell(fh->fp);
fclose(fh->fp);
/* fh->pos != -1 means that the file is closed,
   so it is not necessary to set fh->fp to 0
*/
/*--openCount;
printf("--OPEN %d (%d %d)\n",openCount,maxOpenCount,allOpenCount);
*/
}

static long someopt(psk kn,long opt[])
	{
	int i;
	while(is_op(kn))
		{
        /* return someopt(kn->LINKS,opt) || someopt(kn->RECHTS,opt);
        18 Maart 1997 */
        if(someopt(kn->LINKS,opt))
            return TRUE;
        kn = kn->RECHTS;
        }
    for(i=0;opt[i];i++)
        if(PLOBJ(kn) == opt[i])
            return opt[i];
    return 0L;
	}


static FILE *bfopen(char *naam,char *mode)
{
FILE *fp;
filehendel *fh,*fhmin;
#ifdef vax
char lmode[4];
int i,j;
for(i=j=0;mode[i];i++)
    if(mode[i] != 'b')
        lmode[j++] = mode[i];
lmode[j] = 0;
if((fp=fopen(naam,lmode)) == NULL)
    {
    if(fh0 == NULL)
        return NULL;
    for(fh = fh0,fhmin = NULL;
        fh != NULL;
        fh = fh->next)
        {
        if(fh->pos == -1L /*fh->fp != NULL*/ /* test added 12 Aug 1996 */ && fh->tijd < fhmin->tijd)
            fhmin = fh;
        }
    if(fhmin == NULL)/* test added 12 Aug 1996 */
        return NULL;
    sluitfile(fhmin);
    if((fp=fopen(naam,lmode)) == NULL)
#else
if((fp=fopen(naam,mode)) == NULL)
    {
    if(fh0 == NULL)
        return NULL;
    for(fh = fh0,fhmin = fh0;
        fh != NULL;
        fh = fh->next)
        {
        if(fh->filepos == -1L /* fh->fp != NULL *//* test added 12 Aug 1996 */ && fh->tijd < fhmin->tijd)
            fhmin = fh;
        }
    if(fhmin == NULL)/* test added 12 Aug 1996 */
        return NULL;
    sluitfile(fhmin);
    if((fp=fopen(naam,mode)) == NULL)
#endif
        return NULL;
    }
/*
++openCount;
++allOpenCount;
if(openCount > maxOpenCount)
    maxOpenCount = openCount;
printf("++OPEN %d (%d %d)\n",openCount,maxOpenCount,allOpenCount);
*/
return fp;
}

static filehendel * preparefp(filehendel * fh,char * naam,long mode)
    {
    assert(fh != NULL);
    assert(!strcmp(fh->naam,naam));
    if( mode != 0L /* added 16 July 1996 */
    &&  mode != fh->mode)
        {
        fh->mode = mode;
        if((fh->fp = freopen(fh->naam,(char*)&(fh->mode),fh->fp)) == NULL)
            return NULL;
        fh->written = FALSE;
        }
    else if(fh->filepos > 0L)
        {
        if((fh->fp = bfopen(naam,(char*)&(fh->mode))) == NULL)
            return NULL;
        fh->written = FALSE;
        fseek(fh->fp,fh->filepos,SEEK_SET);
        }
    fh->filepos = -1L;
    fh->tijd = tijdnr++;
    return fh;
    }
/*
Find an existing or create a fresh file handle for a known file name
If the file mode differs from the current file mode,
    reopen the file with the new file mode.
If the file is known but has been closed (e.g. to save file handles),
    open the file with the memorized file mode and go to the memorized position
*/
static filehendel *zoekfp(char *naam,long mode)
    {
    filehendel *fh;
    for(fh = fh0;fh;fh = fh->next)
        if(!strcmp(naam,fh->naam))
            return preparefp(fh,naam,mode);
    return NULL;
    }

static int fil(ppsk pkn)
{
FILE *fp;
psk kns[4];
long ind;
#if W32
int sh;
#else
long fac;
#endif
psk kn;
static filehendel *fh = NULL;
char *naam;

static long types[]={CHR,DEC,STRt,0L};
static long whences[]={SET,CUR,END,0L};
static long modes[]={
O('r', 0 , 0 ),/*open text file for reading                                  */
O('w', 0 , 0 ),/*create text file for writing, or trucate to zero length     */
O('a', 0 , 0 ),/*append; open text file or create for writing at eof         */
O('r','b', 0 ),/*open binary file for reading                                */
O('w','b', 0 ),/*create binary file for writing, or trucate to zero length   */
O('a','b', 0 ),/*append; open binary file or create for writing at eof       */
O('r','+', 0 ),/*open text file for update (reading and writing)             */
O('w','+', 0 ),/*create text file for update, or trucate to zero length      */
O('a','+', 0 ),/*append; open text file or create for update, writing at eof */
O('r','+','b'),
O('r','b','+'),/*open binary file for update (reading and writing)           */
O('w','+','b'),
O('w','b','+'),/*create binary file for update, or trucate to zero length    */
O('a','+','b'),
O('a','b','+'),/*append;open binary file or create for update, writing at eof*/
0L};

long type,numwaarde,whence;
union
    {
    long l;
    char c[4];
    } mode;

union
    {
    short s;
    char c[2];
    } snum;

/*
Fail if there are more than four arguments or if an argument is non-atomic
*/
for(ind = 0,kn = (*pkn)->RECHTS;
    is_op(kn);
    kn = kn->RECHTS)
    {
    if(is_op(kn->LINKS) || ind > 2)
        {
        return FALSE;
        }
    kns[ind++] = kn->LINKS;
    }
kns[ind++] = kn;
for(;ind < 4;)
    kns[ind++] = NULL;

/*
  FIRST ARGUMENT: File name
  if the current file name is different from the argument,
        reset the current file name
  if the first argument is empty, the current file name must not be NULL
  fil$(name)
  fil$(name,...)
  name field is optional in all fil$ operations
*/
#if COMPILE
if(RPOBJ(kns[0]))
#else
if(kns[0]->u.obj)
#endif
    {
    naam = (char*)POBJ(kns[0]);
    if(fh && strcmp(naam,fh->naam))
        fh = NULL;
    }
else
    {
    if(fh)
        naam = fh->naam;
    else
        {
        return FALSE;
        }
    }

/*
  SECOND ARGUMENT: mode, type, whence or TEL
        if the second argument is a mode string,
                the file handel is found and adapted to the  mode
                or a new file handel is made
        else
                file handel is set to current naam
*/
#if COMPILE
if(kns[1] && RPOBJ(kns[1]))
#else
if(kns[1] && kns[1]->u.obj)
#endif
    {
    /*
    SECOND ARGUMENT:FILE MODE
    fil$(,"r")
    fil$(,"b")
    fil$(,"a")
    etc.
    */
    if((mode.l = someopt(kns[1],modes)) != 0L)
        {
        if(fh)
            fh = preparefp(fh,naam,mode.l);
        else
            fh = zoekfp(naam,mode.l);
        if(fh == NULL)
            {
            if((fp=bfopen(naam,(char*)&mode)) == NULL)
                {
                return FALSE;
                }
            fh = (filehendel*)bmalloc(__LINE__,sizeof(filehendel));
            fh->naam = (char*)bmalloc(__LINE__,strlen(naam) + 1);
            strcpy(fh->naam,naam);
            fh->fp = fp;
            fh->filepos = -1L;
            fh->mode = mode.l;
            fh->type = CHR;
            fh->size = 1;
            fh->getal = 1;
            fh->tijd = tijdnr++;
            fh->written = FALSE;
            fh->next = fh0;
            fh->stop = NULL;
            fh0 = fh;
            }
        return TRUE;
        }
    else
        {
    /*
    We do not open a file now, so we should have a file handle in memory.
    */
        if(fh)
            fh = preparefp(fh,naam,0L);
        else
            fh = zoekfp(naam,0L);

        if(!fh)
            {
            return FALSE;
            }

    /*
    SECOND ARGUMENT:TYPE
    fil$(,CHR)
    fil$(,DEC)
    fil$(,CHR,size)
    fil$(,DEC,size)
    fil$(,CHR,size,number)
    fil$(,DEC,size,number)
    */
        if((type = someopt(kns[1],types)) != 0L)
            {
            fh->type = type;
            if(type == STRt)
                {
                /*
                  THIRD ARGUMENT: primary stopping character (e.g. "\n")
                  (only used for reading)
                */
#if COMPILE
                if(kns[2] && RPOBJ(kns[2]))
                    {
                    /*
                    fh->size = RPOBJ(kns[2]);
                    */
                    if(fh->stop)
#define BMALLLOC
#ifdef BMALLLOC
                        bfree(fh->stop);
                    fh->stop = (char*)bmalloc(__LINE__,strlen((char *)POBJ(kns[2])) + 1);
#else
                        free(fh->stop);
                    fh->stop = (char*)malloc(strlen((char *)POBJ(kns[2])) + 1);
#endif
                    strcpy(fh->stop,(char *)POBJ(kns[2]));
                    }
#else /* COMPILE */
                if(kns[2] && kns[2]->u.obj)
                    {
                    /*
                    fh->size = kns[2]->u.obj;
                    */
                    if(fh->stop)
#ifdef BMALLLOC
                        bfree(fh->stop);
                    fh->stop = (char*)bmalloc(__LINE__,strlen((char *)&kns[2]->u.obj) + 1);
#else
                        free(fh->stop);
                    fh->stop = (char*)malloc(strlen((char *)&kns[2]->u.obj) + 1);
#endif
                    strcpy(fh->stop,(char *)&kns[2]->u.obj);
                    }
#endif
                else
                    {
                    /*
                    fh->size = '\n';
                    */
                    if(fh->stop)
#ifdef BMALLLOC
                       bfree(fh->stop);
                    fh->stop = (char*)bmalloc(__LINE__,2);
#else
                        free(fh->stop);
                    fh->stop = (char*)malloc(2);
#endif
                    strcpy(fh->stop,"\n");
                    }
#if 0
                /*
                  FOURTH ARGUMENT: secondary stopping character (e.g. "{")
                  (only used for reading)
                */
#if COMPILE
                if(kns[3] && RPOBJ(kns[3]))
                    fh->getal = RPOBJ(kns[3]));
#else
                if(kns[3] && kns[3]->u.obj)
                    fh->getal = kns[3]->u.obj;
#endif
                else
                    fh->getal = 0;
#endif
                }
            else
                {
                /*
                  THIRD ARGUMENT: a size of elements to read or write
                */
#if COMPILE
                if(kns[2] && RPOBJ(kns[2]))
#else
                if(kns[2] && kns[2]->u.obj)
#endif
                    {
                    if(!GEHEEL(kns[2]))
                        {
                        return FALSE;
                        }
                    fh->size = toLong(kns[2]);
                    }
                else
                    {
                    fh->size = 1;
                    fh->getal = 1;
                    }
                /*
                  FOURTH ARGUMENT: the number of elements to read or write
                */
#if COMPILE
                if(kns[3] && RPOBJ(kns[3]))
#else
                if(kns[3] && kns[3]->u.obj)
#endif
                    {
                    if(!GEHEEL(kns[3]))
                        {
                        return FALSE;
                        }
                    fh->getal = toLong(kns[3]);
                    }
                else
                    fh->getal = 1;
                }
            return TRUE;
            }
    /*
    SECOND ARGUMENT:POSITIONING
    fil$(,SET)
    fil$(,END)
    fil$(,CUR)
    fil$(,SET,offset)
    fil$(,END,offset)
    fil$(,CUR,offset)
    */
        else if((whence = someopt(kns[1],whences)) != 0L)
            {
            long offset;
            fh->tijd = tijdnr++;
            /*
              THIRD ARGUMENT: an offset
            */
#if COMPILE
            if(kns[2] && RPOBJ(kns[2]))
#else
            if(kns[2] && kns[2]->u.obj)
#endif
                {
                if(!GEHEEL(kns[2]))
                    {
                    return FALSE;
                    }
                offset = toLong(kns[2]);
                }
            else
                offset = 0L;

            if((offset < 0L && whence == SEEK_SET)
            || (offset > 0L && whence == SEEK_END)
            || fseek(fh->fp,offset,whence == SET ? SEEK_SET
                            : whence == END ? SEEK_END
                                            : SEEK_CUR))
                {
                filehendel * fhvorig, * fhh;
                sluitfile(fh);
                for(fhvorig = NULL,fhh = fh0
                   ;fhh != fh
                   ;fhvorig = fhh,fhh = fhh->next
                   )
                   ;
                if(fhvorig)
                    fhvorig->next = fh->next;
                else
                    fh0 = fh->next;
                bfree(fh->naam);
                if(fh->stop)
#ifdef BMALLLOC
                    bfree(fh->stop);
#else
                    free(fh->stop);
#endif
                bfree(fh);
                fh = NULL;
                return FALSE;
                }
            fh->written = FALSE;
            return TRUE;
            }
    /*
    SECOND ARGUMENT:TELL POSITION
    fil$(,TEL)
    */
        else if(PLOBJ(kns[1]) == TEL)
            {
            char pos[11];
            sprintf(pos,"%ld",ftell(fh->fp));
            *pkn = opb(*pkn,pos,NULL);
            return TRUE;
            }
        else
            {
            return FALSE;
            }
        }
    /*
    return FALSE if the second argument is not empty but could not be recognised
    */
    }

if(!fh)
    {
    return FALSE;
    }
/*
READ OR WRITE
Now we are either going to read or to write
*/

type = fh->type;
mode.l = fh->mode;
fp = fh->fp;

/*
THIRD ARGUMENT: the number of elements to read or write
*/

#if COMPILE
if(kns[2] && RPOBJ(kns[2]))
#else
if(kns[2] && kns[2]->u.obj)
#endif
    {
    if(!GEHEEL(kns[2]))
        {
        return FALSE;
        }
    fh->getal = toLong(kns[2]);
    }

/*
We allow 1, 2 or 4 bytes to be read/written in one fil$ operation
These can be distributed over decimal numbers.
*/

if(type == DEC)
    switch((int)fh->size)
        {
        case 1 :
            if(fh->getal > 4)
                fh->getal = 4;
            break;
        case 2 :
            if(fh->getal > 2)
                fh->getal = 2;
            break;
        default :
            fh->size = 4; /*Invalid size declaration adjusted*/
            fh->getal = 1;
        }
fh->tijd = tijdnr++;
/*
FOURTH ARGUMENT:VALUE TO WRITE
*/
if(kns[3])
    {
    if(mode.c[0] != 'r' || mode.c[1] == '+' || mode.c[2] == '+')
/*
WRITE
*/
        {
        fh->written = TRUE;
        if(type == DEC)
            {
            numwaarde = toLong(kns[3]);
            for(ind=0;ind < fh->getal;ind++)
                switch((int)fh->size)
                    {
                    case 1 :
                        fputc((int)numwaarde & 0xFF,fh->fp);
                        numwaarde >>= 8;
                        break;
                    case 2 :
                        snum.s = (short)(numwaarde & 0xFFFF);
                        fwrite(snum.c,1,2,fh->fp);
                        numwaarde >>= 16;
                        break;
                    default :
                        fwrite((char*)&numwaarde,1,4,fh->fp);
                        break;
                    }
            }
        else if(type == CHR)
            {
            size_t len,len1,minl;
            len1 = (size_t)(fh->size*fh->getal);
            len = strlen((char*)POBJ(kns[3]));
            minl = len1 < len ? (len1 > 0 ? len1 : len) : len;
            if(fwrite(POBJ(kns[3]),1,minl,fh->fp) == minl)
                for(;len < len1 && putc(' ',fh->fp) != EOF;len++);
            }
        else /*if(type == STRt)*/
            fputs((char *)POBJ(kns[3]),fh->fp);
        }
    else
        {
        /*
        Fail if not in write mode
        */
        return FALSE;
        }
    }
else
    {
    if(mode.c[0] == 'r' || mode.c[1] == '+' || mode.c[2] == '+')
        {
/*
READ
*/
#define INPUTBUFFERSIZE 256
        unsigned char buffer[INPUTBUFFERSIZE];
        unsigned char * bbuffer = buffer;
        if(fh->written)
            {
            fflush(fh->fp);
            fh->written = FALSE;
            }
        if(feof(fp))
            {
            return FALSE;
            }
        if(type == STRt)
            {
            psk lpkn = NULL;
            psk rpkn = NULL;
            char * conc[2];
            int count = 0;
            long pos = ftell(fp);
            int kar;
            while((kar = fgetc(fp)) != EOF && !strchr(fh->stop,kar))
                {
                buffer[count++] = (char)kar;
                if(count == (INPUTBUFFERSIZE - 1))
                    {
                    buffer[(INPUTBUFFERSIZE - 1)] = '\0';
                    while((kar = fgetc(fp)) != EOF && !strchr(fh->stop,kar))
                        count++;
                    if(count >= INPUTBUFFERSIZE)
                        {
                        bbuffer = (unsigned char*)bmalloc(__LINE__,(size_t)count+1);
                        strcpy((char *)bbuffer,(char *)buffer);
                        fseek(fp,pos+(INPUTBUFFERSIZE - 1),SEEK_SET);
                        if(fread((char*)bbuffer+(INPUTBUFFERSIZE - 1),1,count - (INPUTBUFFERSIZE - 1),fh->fp) == 0)
                            {
                            return FALSE;
                            }
                        if(ferror(fh->fp))
                            {
                            perror("fread");
                            return FALSE;
                            }
                        if(kar != EOF)
                            fgetc(fp); /* skip stopping character (which is in 'kar') */
                        }
                    else
                        bbuffer = buffer;
                    break;
                    }
                }
            if(count < (INPUTBUFFERSIZE - 1))
                {
                buffer[count] = '\0';
                bbuffer = buffer;
                }
            bron = bbuffer;
            input(NULL,&lpkn,1,NULL/*int * err*/);
            if(kar == EOF)
                bbuffer[0] = '\0';
            else
                {
                bbuffer[0] = (char)kar;
                bbuffer[1] = '\0';
                }
            bron = bbuffer;
            input(NULL,&rpkn,1,NULL/*int * err*/);
            conc[0] = "(\1.\2)";
            adr[1] = lpkn;
            adr[2] = rpkn;
            conc[1] = NULL;
            *pkn = vopb(*pkn,(const char**)conc);
            wis(adr[1]);
            wis(adr[2]);
            }
        else
            {
            if(fh->size * fh->getal > 255)
                bbuffer = (unsigned char*)bmalloc(__LINE__,(size_t)(fh->size * fh->getal)+1);
                          /* +1 added 18 Maart 1997 */
            else
                bbuffer = buffer;
            if(fread((char*)bbuffer,(size_t)fh->size,(size_t)fh->getal,fh->fp) == 0
            && (size_t)fh->size*(size_t)fh->getal != 0)
                {
                return FALSE;
                }
            if(ferror(fh->fp))
                {
                perror("fread");
                return FALSE;
                }
            *(bbuffer+(int)(fh->size*fh->getal)) = 0;
            if(type == DEC)
                {
                numwaarde = 0L;
#if W32
                sh = 0;
#else
                fac = 1;
#endif
                for(ind = 0;ind<fh->getal;)
                    {
                    switch((int)fh->size)
                        {
#if W32
                        case 1 :
                            numwaarde += (long)bbuffer[ind++] << sh;
                            sh += 8;
                            continue;
                        case 2 :
                            numwaarde += (long)(*(short*)(bbuffer+ind)) << sh;
                            ind += 2;
                            sh += 16;
                            continue;
#else
                        case 1 :
                            numwaarde += bbuffer[ind++] * fac;
                            fac *= 256;
                            continue;
                        case 2 :
                            numwaarde += (long)(*(short*)(bbuffer+ind)) * fac;
                            fac *= 65536L;
                            ind += 2;
                            continue;
#endif
                        default :
                            numwaarde += *(long*)bbuffer;
                            break;
                        }
                    break;
                    }
                sprintf((char*)bbuffer,"%ld",numwaarde);
                }
            bron = bbuffer;
            input(NULL,pkn,1,NULL/*int * err*/);
            }
        if(bbuffer != (unsigned char *)&buffer[0])
        /* buffer ---> (unsigned char *)&buffer[0]
           20 Dec 1995, to make Borland at ease. */
            bfree(bbuffer);
        return TRUE;
        }
    else
        {
        return FALSE;
        }
    }

return TRUE;
}

static int allopts(psk kn,long opt[])
	{
    int i;
	while(is_op(kn))
        {
        /* return allopts(kn->LINKS,opt) && allopts(kn->RECHTS,opt);
        18 Maart 1997 */
        if(!allopts(kn->LINKS,opt))
            return FALSE;
        kn = kn->RECHTS;
        }
    for(i=0;opt[i];i++)
        if(PLOBJ(kn) == opt[i])
            return TRUE;
    return FALSE;
	}

static int flush(void)
    {
#ifdef __GNUC__
    return fflush(fpo);
#else
#if MICROSOFT_WINDOWS_API
    WinFlush();
    return 1;
#else
    return 1;
#endif
#endif
    }


static int output(ppsk pkn,void (*hoe)(
#ifndef vax
    psk k
#endif
    ))
{
FILE *redfpo;
psk rknoop,rlknoop,rrknoop,rrrknoop;
static long opts[] =
{APP,NEW,
 TXT,VAP,
 EXT,MEM,
 CON,LIN,
 0L};
if(kop(rknoop = (*pkn)->RECHTS) == KOMMA)
   {
   redfpo = fpo;
   rlknoop = rknoop->LINKS;
   rrknoop = rknoop->RECHTS;
   hum = !zoekopt(rrknoop,LIN);
   if(allopts(rrknoop,opts))
        {
        if(zoekopt(rrknoop,MEM))
            {
            psk ret;
            telling = 1;
            verwerk = tel;
            fpo = NULL;
            (*hoe)(rlknoop);
            ret = (psk)bmalloc(__LINE__,sizeof(unsigned long)+telling);
            ret->flgs = KLAAR | SUCCES;
#if !W32
            ret->ops = 0;
#endif
            verwerk = plak;
            bron = POBJ(ret);
            (*hoe)(rlknoop);
            hum = 1;
            verwerk = myputc;
            wis(*pkn);
            *pkn = ret;
            fpo = redfpo;
            return TRUE;
            }
        else
            {
            (*hoe)(rlknoop);
            flush();
            adr[2] = rlknoop;
            }
        }
    else if(kop(rrknoop) == KOMMA
         && !is_op(rrknoop->LINKS)
         && allopts((rrrknoop = rrknoop->RECHTS),opts))
        {
        fpo = fopen((char*)POBJ(rrknoop->LINKS),
                    zoekopt(rrrknoop,NEW) ? "w" : "a");
        if(fpo == NULL)
            {
            errorprintf(
#if TAAL == NL
            "%s kan niet geopend worden\n",
#else
            "cannot open %s\n",
#endif
            POBJ(rrknoop->LINKS));
            fpo = redfpo;
            hum = 1;
            return FALSE;
            }
        else
            {
            (*hoe)(rlknoop);
            fclose(fpo);
            fpo = redfpo;
            adr[2] = rlknoop;
            }
        }
    else
        {
        (*hoe)(rknoop);
        flush();
        adr[2] = rknoop;
        }
    dopb(pkn,adr[2]);
    }
else
    {
    (*hoe)(rknoop);
    flush();
    *pkn = rechtertak(*pkn);
    }
hum = 1;
return TRUE;
}

static ptrdiff_t simil(char *s1,char *s2)
{
#define TOLOWER(c) (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c)
char *ls1,*s1l = NULL,*s1r = NULL,*s2l = NULL,*s2r = NULL;
ptrdiff_t max;
/* beschouw elk teken van s1 als mogelijk startpunt voor match */
for(max = 0,ls1 = s1;*ls1;ls1++)
    {
    char *ls2;
    /* vergelijk met s2 */
    for(ls2 = s2;*ls2;ls2++)
        {
        char *lls1,*lls2;
        /* bepaal lengte gelijke stukken */
        for(lls1 = ls1,lls2 = ls2;
            *lls1 && TOLOWER(*lls1) == TOLOWER(*lls2);
            lls1++,lls2++);
        /* pas evt score aan */
        if(lls1 - ls1 > max)
            {
            max = lls1 - ls1;
            /* onthou eindpunten van linkerstrings en
            beginpunten rechterstrings */
            s1l = ls1;
            s1r = lls1;
            s2l = ls2;
            s2r = lls2;
            }
        }
    }
if(max)
    {
    char c1,c2;
    c1 = *s1l;
    c2 = *s2l;
    *s1l = 0;
    *s2l = 0;
    max += simil(s1,s2) + simil(s1r,s2r);
    *s1l = c1;
    *s2l = c2;
    }
return max;
}


static function_return_type find_func(ppsk pkn)
{
psk lknoop = (*pkn)->LINKS;
int nieuw = FALSE;
psk self = NULL;
/*psk dest = NULL;*/
method_pnt theMethod = NULL;
psk object = NULL;
adr[1] = NULL;
if(find(lknoop,&adr[1],&nieuw,&self,&object,&theMethod))
    {
    if(adr[1])
        {
        if(is_op(adr[1])
          && kop(adr[1]) == DOT /*Bart 20010820*/
          )
            {
            psh(&argk,(*pkn)->RECHTS,NULL);
            dopb(pkn,adr[1]);
            if(nieuw)
                wis(adr[1]);
            if(self)
                {
#ifndef SELF
                psh(&selfkn,self,NULL);
#endif
                if(object)
                    {
                    psh(&Selfkn,object,NULL);
                    return builtin_object_user_method_ok;
                    }
                else
                    return user_object_method_ok;
                }
            else
                return user_function_ok;
            }
        else
            {
#if TAAL == NL
            errorprintf("(Syntaxfout) Het volgende is geen functie:\n\n  ");
#else
            errorprintf("(Syntax error) The following is not a function:\n\n  ");
#endif
#ifdef BRACMATEMBEDDED
            fpo = stderr;
#else
            fpo = errorStream;
#endif
            result(lknoop);
            exit(1);
            }
        }
    else if(theMethod)
        {
        return theMethod((struct typedObjectknoop *)object,pkn);
/*
#ifdef SELF
        if(self)
            return builtin_object_user_method_ok;
        else
#endif
            return builtin_object_builtin_method_ok;
*/
        }
    else
        return function_fail; /* should not come here */
    /*return TRUE+TRUE+(self?TRUE:0);*/
    }
else if(debug)
    {
    errorprintf("Function not found");
    writeError(*pkn);
    printf("\n");
    }
return function_fail;
}

static int hasSubObject(psk src)
    {
    while(is_op(src))
        {
        if(kop(src) == WORDT)
            return TRUE;
        else
            {
            /*return hasSubObject(src->LINKS) || hasSubObject(src->RECHTS);
            18 Maart 1997*/
            if(hasSubObject(src->LINKS))
                return TRUE;
            src = src->RECHTS;
            }
        }
    return FALSE;
    }

static psk objectcopiesub(psk src);

static psk objectcopiesub2(psk src) /* src is NOT an object */
    {
    psk goal;
    if(is_op(src) && hasSubObject(src))
        {
        goal = /*new_operator_like(src); */(psk)bmalloc(__LINE__,sizeof(kknoop));
#if !W32
        goal->flgs = src->flgs;
#endif
        goal->ops = src->ops & ~OPGEBRUIKT;
        goal->LINKS = objectcopiesub(src->LINKS);
        goal->RECHTS = objectcopiesub(src->RECHTS);
        return goal;
        }
    else
        return zelfde_als_w(src);
    }

static psk objectcopiesub(psk src)
    {
    psk goal;
    if(is_object(src))
        {
/*        goal = new_operator_like(src);*/
        if(ISBUILTIN((objectknoop*)src))
            {
            goal = (psk)bmalloc(__LINE__,sizeof(typedObjectknoop));
            ((typedObjectknoop*)goal)->refcount = 0L;
            UNSETCREATEDWITHNEW((typedObjectknoop*)goal);/*TODO: This line seems to be superfluous*/
            SETBUILTIN((typedObjectknoop*)goal);
            ((typedObjectknoop*)goal)->vtab = ((typedObjectknoop*)src)->vtab;
#ifdef OBJECTDATA
            ((typedObjectknoop*)goal)->data = ((typedObjectknoop*)src)->data;
            printf("objectcopiesub goal %p goal->vtab %p goal->data %p\n",goal,((typedObjectknoop*)goal)->vtab,((typedObjectknoop*)goal)->data);
            if(((typedObjectknoop*)goal)->data)
                ((typedObjectknoop*)goal)->data->refcount++;
#else
            ((typedObjectknoop*)goal)->voiddata = NULL;
#endif
            }
        else
            {
            goal = (psk)bmalloc(__LINE__,sizeof(objectknoop));
            ((typedObjectknoop*)goal)->refcount = 0L;
            UNSETBUILTIN((typedObjectknoop*)goal);
            }
        UNSETCREATEDWITHNEW((typedObjectknoop*)goal);
#if !W32
        goal->flgs = src->flgs;
#endif
        goal->ops = src->ops & ~OPGEBRUIKT;
        goal->LINKS = zelfde_als_w(src->LINKS);
        goal->RECHTS = zelfde_als_w(src->RECHTS);
        return goal;
        }
    else
        return objectcopiesub2(src);
    }

static psk objectcopie(psk src)
    {
    psk goal;
    if(is_object(src))                              /* Make a copy of this '=' node ... */
        {
        if(ISBUILTIN((objectknoop*)src))
            {
            goal = (psk)bmalloc(__LINE__,sizeof(typedObjectknoop));
            ((typedObjectknoop*)goal)->refcount = 0L;
            UNSETCREATEDWITHNEW((typedObjectknoop*)goal);/*TODO: This line seems to be superfluous*/
            SETBUILTIN((typedObjectknoop*)goal);
            ((typedObjectknoop*)goal)->vtab = ((typedObjectknoop*)src)->vtab;
#ifdef OBJECTDATA
            ((typedObjectknoop*)goal)->data = ((typedObjectknoop*)src)->data;
            printf("objectcopie goal %p goal->vtab %p goal->data %p\n",goal,((typedObjectknoop*)goal)->vtab,((typedObjectknoop*)goal)->data);
            if(((typedObjectknoop*)goal)->data)
                ((typedObjectknoop*)goal)->data->refcount++;
#else
            ((typedObjectknoop*)goal)->voiddata = NULL;
#endif
            }
        else
            {
            goal = (psk)bmalloc(__LINE__,sizeof(objectknoop));
            ((typedObjectknoop*)goal)->refcount = 0L;
            UNSETBUILTIN((typedObjectknoop*)goal);
            }
        UNSETCREATEDWITHNEW((typedObjectknoop*)goal);
#if !W32
        goal->flgs = src->flgs;
#endif
        goal->ops = src->ops & ~OPGEBRUIKT;
        goal->LINKS = zelfde_als_w(src->LINKS);
        /*?? This adds an extra level of copying, but ONLY for objects that have a '=' node as the lhs of the main '=' node*/
        /* What is it good for? Bart 20010220 */
        goal->RECHTS = objectcopiesub(src->RECHTS); /* and of all '=' child nodes (but not of grandchildren!) */
        return goal;
        }
    else
        return objectcopiesub2(src);/*zelfde_als_w(src);*/
    }

static psk getObjectDef(psk source)
    {
    psk def;
    typedObjectknoop * dest;
    if(!is_op(source))
        {
        classdef * df = classes;
        /*printf("built-in?\n");*/
        for(;df->name && strcmp(df->name,(char *)POBJ(source));++df)
            ;
        if(df->vtab)
            {
#if 0
            dest = (typedObjectknoop *)objectcopie(f7);
#else
            dest = (typedObjectknoop *)bmalloc(__LINE__,sizeof(typedObjectknoop));
#if W32
            dest->flgs = WORDT | SUCCES;
#else
            dest->flgs = SUCCES;
            dest->ops = WORDT;
#endif
            dest->links = zelfde_als_w(&nilk);
            dest->rechts = zelfde_als_w(&nilk);
#endif
            /*printf("yes\n");*/
            dest->refcount = 0L;
            SETBUILTIN(dest);
            dest->voiddata = NULL;
            dest->vtab = df->vtab;
            return (psk)dest;
            }
        }
    else if(kop(source) == WORDT)
        return objectcopie(source);

#if 0
    if(naamwoord_w(source,&def))
        {
        printf("def = ("); result(def); printf(")\n");
        adr[4] = objectcopie(def);
        wis(def);
        dest = opb(NULL,"(=\4)",NULL);
        wis(adr[4]);
        printf("dest = ("); result(dest); printf(")\n");
        getchar();
        return dest;
        }
#else


    if(naamwoord_w(source,&def))
        {
/*        printf("def = ("); result(def); printf(")\n");*/
        dest = (typedObjectknoop *)bmalloc(__LINE__,sizeof(typedObjectknoop));
#if W32
        dest->flgs = WORDT | SUCCES;
#else
        dest->flgs = SUCCES;
        dest->ops = WORDT;
#endif
        /*dest->flgs ^= flgs;*/
        dest->links = zelfde_als_w(&nilk);
/*Bart 20010507        dest->rechts = def;*/
        dest->rechts = objectcopie(def);
        wis(def);
        dest->refcount = 0L;
        UNSETBUILTIN(dest);
        dest->voiddata = NULL;
        dest->vtab = NULL;
/*        printf("dest = ("); result((psk)dest); printf(")\n");
        getchar();*/
        return (psk)dest;
        }

#endif
    return NULL;
    }

static psk changeCase(psk pkn,int dos,int low)
    {
    unsigned char * s, *d, * dest;
    int bitset = 0;
    psk ret;
    for(s = POBJ(pkn);*s;++s)
        if(*s & 0x80)
            ++bitset;
    dest = bmalloc(__LINE__,s - POBJ(pkn) + bitset + 1);
    if(low)
        {
        if(dos)
            for(s = POBJ(pkn), d = dest;*s;++s,++d)
                {
                *d = ISO8859toCodePage850(lowerEquivalent[CodePage850toISO8859(*s)]);
                if(*d & 0x80)
                    {
                    *(d+1) = *d ;
                    *d = 0x7F;
                    ++d;
                    }
                else
                    *d |= 0x80;
                }
        else
            for(s = POBJ(pkn), d = dest;*s;++s,++d)
                {
                *d = lowerEquivalent[(int)*s];
                if(*d & 0x80)
                    {
                    *(d+1) = *d ;
                    *d = 0x7F;
                    ++d;
                    }
                else
                    *d |= 0x80;
                }
        }
    else
        {
        if(dos)
            for(s = POBJ(pkn), d = dest;*s;++s,++d)
                {
                *d = ISO8859toCodePage850(upperEquivalent[CodePage850toISO8859(*s)]);
                if(*d & 0x80)
                    {
                    *(d+1) = *d ;
                    *d = 0x7F;
                    ++d;
                    }
                else
                    *d |= 0x80;
                }
        else
            for(s = POBJ(pkn), d = dest;*s;++s,++d)
                {
                *d = upperEquivalent[(int)*s];
                if(*d & 0x80)
                    {
                    *(d+1) = *d ;
                    *d = 0x7F;
                    ++d;
                    }
                else
                    *d |= 0x80;
                }
        }
    *d = '\0';
    ret = NULL;
    ret = opb(ret,dest,NULL);
    setflgs(&ret,pkn->flgs);
    bfree(dest);
    return ret;
    }


static void * strToPointer(const char * str)
    {
    size_t res = 0;
    while(*str)
        res = 10*res+(*str++ - '0');
    return (void *)res;
    }

static void pointerToStr(char * pc,void * p)
    {
    size_t P = (size_t)p;
    char * PC = pc;
    while(P)
        {
        *pc++ = (char)(P % 10) + '0';
        P /= 10;
        }
    *pc-- = '\0';
    while(PC < pc)
        {
        int sav = *PC;
        *PC = *pc;
        *pc = sav;
        ++PC;
        --pc;
        }
    }


#if W32
#define LONGCASE
#else
#ifdef __BORLANDC__
#define LONGCASE
#endif
#endif

#ifdef LONGCASE
#define SWITCH(v) switch(v)
#define FIRSTCASE(a) case a :
#define CASE(a) case a :
#define DEFAULT default :
#else
#define SWITCH(v) long lob;lob = v;
#define FIRSTCASE(a) if(lob == a)
#define CASE(a) else if(lob == a)
#define DEFAULT else
#endif


static function_return_type functies(ppsk pkn)
    {
    psk lknoop;
    psk rknoop,rrknoop,rlknoop,rrlknoop;
    if(is_op(lknoop = (*pkn)->LINKS))
        return find_func(pkn);
        /*return built_in_function_ok;*/
    rknoop = (*pkn)->RECHTS;
    {
    SWITCH(PLOBJ(lknoop))
        {
        FIRSTCASE(STR) /* str$(arg arg arg .. ..) */
            {
            mooi = FALSE;
            hum = 0;/* 15 Dec 1995 */
            telling = 1;
            verwerk = tstr;
            result(rknoop);
            rlknoop = (psk)bmalloc(__LINE__,sizeof(unsigned long)+telling);
    /*
            rlknoop->flgs = KLAAR | SUCCES;
#ifndef LONGCASE
            rlknoop->ops = 0;
#endif
    */
            verwerk = pstr;
            bron = POBJ(rlknoop);
            result(rknoop);
#if W32
            rlknoop->flgs = (KLAAR|SUCCES) | numbercheck(POBJ(rlknoop));
#else
            rlknoop->ops = numbercheck(POBJ(rlknoop));
            rlknoop->flgs = (KLAAR|SUCCES);
#endif
            mooi = TRUE;
            hum = 1;/* 15 Dec 1995 */
            verwerk = myputc;
            wis(*pkn);
            *pkn = rlknoop;
            return built_in_function_ok;
            }
#if O_S
#ifndef __WIN32__
        CASE(SWI) /* swi$(<interrupt number>.(input regs)) */
            {
            int i;
            union
                {
                unsigned int i[sizeof(os_regset) + 1];
                struct
                    {
                    int swicode;
                    os_regset regs;
                    } s;
                } u;
            char pc[121];
            for(i = 0;i < sizeof(os_regset)/sizeof(int);i++)
                u.s.regs.r[i] = 0;
            rrknoop = *pkn;
            i=0;
            do
                {
                rrknoop = rrknoop->RECHTS;
                rlknoop = is_op(rrknoop) ? rrknoop->LINKS : rrknoop;
                if(is_op(rlknoop) || !GEHEEL_NIET_NEG(rlknoop))
                    return function_fail;
                u.i[i++] = (unsigned int)
                    strtoul((char*)POBJ(rlknoop),(char**)NULL,10);
                }
            while(is_op(rrknoop) && i < 10);
#ifdef __TURBOC__
            intr(u.s.swicode,(struct REGPACK *)&u.s.regs);
            sprintf(pc,"0.%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
                        u.i[1],u.i[2],u.i[3],u.i[4],u.i[5],
                        u.i[6],u.i[7],u.i[8],u.i[9],u.i[10]);
#else
#if defined ARM
            i = (int)os_swix(u.s.swicode,&u.s.regs);
            sprintf(pc,"%u.%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
                        i,
                        u.i[1],u.i[2],u.i[3],u.i[4],u.i[5],
                        u.i[6],u.i[7],u.i[8],u.i[9],u.i[10]);
#endif
#endif
            *pkn = opb(*pkn,pc,NULL);
            return built_in_function_ok;
            }
#endif
#endif

#ifdef ERR
        CASE(ERR) /* err $ <file name to direct errorStream to> */
            {
            if(!is_op(rknoop))
                {
                if(redirectError((char*)POBJ(rknoop)))
                    return built_in_function_ok;
                }
            return function_fail;
            }
#endif
        CASE(ALC)  /* alc $ <aantal bytes> */
            {
            void *p;
            char pc[11];
            if(is_op(rknoop)
            || !GEHEEL_POS(rknoop)
            || (p = bmalloc(__LINE__,(int)strtoul((char*)POBJ(rknoop),(char**)NULL,10)))
                  == NULL)
                return function_fail;
/*            sprintf(pc,"%ld",(long)p);*/
            pointerToStr(pc,p);
            /*sprintf(pc,"%Iu",p);*/
            *pkn = opb(*pkn,pc,NULL);
            return built_in_function_ok;
            }
        CASE(FRE) /* fre $ <pointer> */
            {
			void * p;
            if(is_op(rknoop) || !GEHEEL_POS(rknoop))
                return function_fail;
            /*printf("fre$%s\n",(char*)POBJ(rknoop));*/
            p = strToPointer((char*)POBJ(rknoop));
			/*sscanf((char*)POBJ(rknoop),"%Iu",&p);*/
            pskfree(p);
            /*pskfree((void*)strtoul((char*)POBJ(rknoop),(char**)NULL,10));*/
            return built_in_function_ok;
            }
        CASE(PEE) /* pee $ (<pointer>,type) (1,2,4)*/
            {
            void *p;
            int aantal = 1;
            char pc[11];
            if(is_op(rknoop))
                {
                rlknoop = rknoop->LINKS;
                rrknoop = rknoop->RECHTS;
                if(!is_op(rrknoop))
#if COMPILE
                    switch(RPOBJ(rrknoop))
#else
                    switch(rrknoop->u.obj)
#endif
                        {
                        case '2':
                            aantal = 2;
                            break;
                        case '4':
                            aantal = 4;
                            break;
                        }
                }
            else
                rlknoop = rknoop;
            if(is_op(rlknoop) || !GEHEEL_POS(rlknoop))
                return function_fail;
            p = strToPointer((char*)POBJ(rlknoop));
			/*sscanf((char*)POBJ(rlknoop),"%Iu",&p);*/
            p = (void*)((char*)p - (ptrdiff_t)((size_t)p % aantal));
			/*            p = (void*)strtoul((char*)POBJ(rlknoop),(char**)NULL,10);
            p = (void*)((char*)p - (unsigned)((unsigned long)p % aantal));*/
            switch(aantal)
                {
                case 1:
                    sprintf(pc,"%u",(int)*(unsigned char*)p);
                    break;
                case 2:
                    sprintf(pc,"%hu",*(short unsigned int*)p);
                    break;
                default:
                    sprintf(pc,"%lu",*(long unsigned int*)p);
                    break;
                }
            *pkn = opb(*pkn,pc,NULL);
            return built_in_function_ok;
            }
        CASE(POK) /* pok $ (<pointer>,getal,nbytes) */
            {
            int aantal;
            void *p;
            long val;
            aantal = 1;
            if(!is_op(rknoop))
                return function_fail;
            rlknoop = rknoop->LINKS;
            rrknoop = rknoop->RECHTS;
            if(is_op(rrknoop))
                {
                psk rrrknoop;
                rrrknoop = rrknoop->RECHTS;
                rrlknoop = rrknoop->LINKS;
                if(!is_op(rrrknoop))
#if COMPILE
                    switch(RPOBJ(rrrknoop))
#else
                    switch(rrrknoop->u.obj)
#endif
                        {
                        case '2':
                            aantal = 2;
                            break;
                        case '4':
                            aantal = 4;
                        }
                }
            else
                rrlknoop = rrknoop;
            if(is_op(rlknoop) || !GEHEEL_POS(rlknoop)
            || is_op(rrlknoop) || !GEHEEL(rrlknoop))
                return function_fail;
            p = strToPointer((char*)POBJ(rlknoop));
			/*sscanf((char*)POBJ(rlknoop),"%Iu",&p);*/
            p = (void*)((char*)p - (ptrdiff_t)((size_t)p % aantal));
            /*p = (void*)strtoul((char*)POBJ(rlknoop),(char**)NULL,10);
            p = (void*)((char*)p - (unsigned)((unsigned long)p % aantal));*/
    /*        if(GEHEEL_NIET_NEG(rrlknoop))
                val = strtoul((char*)POBJ(rrlknoop),(char**)NULL,10);
            else*/
                val = toLong(rrlknoop);
            switch(aantal)
                {
                case 1:
                    *(unsigned char*)p = (unsigned char)val;
                    break;
                case 2:
                    *(unsigned short int*)p = (unsigned short int)val;
                    break;
                default:
                    *(long*)p = val;
                    break;
                }
            return built_in_function_ok;
            }
        CASE(KAR) /* chr $ getal */
            {
            char pc[3];
            int val;
            if(is_op(rknoop) || !GEHEEL_POS(rknoop))
                return function_fail;
            val = (unsigned char)strtoul((char*)POBJ(rknoop),(char**)NULL,10);
            /*if(val == 0x7F)
                return function_fail; ook dit zal wel niet goed zijn geweest */
            if(val > 0x7F)
                {
                pc[0] = 0x7F;
                pc[1] = (char)(val | 0x80);
                pc[2] = 0;
                }
            else
                {
                pc[0] = (char)(val | 0x80);
                pc[1] = 0;
                }
            *pkn = opb(*pkn,pc,NULL);
            return built_in_function_ok;
            }
        CASE(ASC) /* asc $ character */
            {
            char pc[4];
            if(is_op(rknoop))
                return function_fail;
#if COMPILE
            sprintf(pc,"%d",(int)RPOBJ(rknoop));
#else
            sprintf(pc,"%d",(int)rknoop->u.obj);
#endif
            *pkn = opb(*pkn,pc,NULL);
            return built_in_function_ok;
            }
        CASE(FIL) /* fil $ (<naam>,[<offset>,[set|cur|end]]) */
            {
            return fil(pkn) ? built_in_function_ok : function_fail;
            }
        CASE(FNC) /* fnc $ (<function pointer>.<struct pointer>) */
            {
            typedef Boolean (*fncTp)(void *);
            union
                {
                fncTp pfnc; /* Hoping this works. */
                void * vp;  /* Pointers to data and pointers to functions may
                               have different sizes. */
                } u;
            /*fncTp pfnc;*/
            void * argStruct;
            if(sizeof(int (*)(void *)) != sizeof(void *) || !is_op(rknoop))
                return function_fail;
            u.vp = strToPointer((char*)POBJ(rknoop->LINKS));
            /*20031126 pfnc = (fncTp)strtoul((char*)POBJ(rknoop->LINKS),(char**)NULL,10);*/
            if(!u.pfnc)
                return function_fail;
            argStruct = strToPointer((char*)POBJ(rknoop->RECHTS));
            /*20031126 argStruct = (void *)strtoul((char*)POBJ(rknoop->RECHTS),(char**)NULL,10);*/
            return u.pfnc(argStruct) ? built_in_function_ok : function_fail;
            }
#if TELMAX
        CASE(BEZ) /* bez $  */
            {
            printf("  %ld nodes",globalloc);
            printf("  %ld max nodes",maxgloballoc);
            printf("  maxref = %d\n",maxbez /EENKEER);
#if TELLING
            bezetting();
#endif
            return built_in_function_ok;
            }
#endif
        CASE(MMF) /* mem $ [EXT] */
            {
            mmf(pkn);
            return built_in_function_ok;
            }
        CASE(MOD)
            {
            if(RATIONAAL(rlknoop = rknoop->LINKS) &&
               RATIONAAL(rrknoop = rknoop->RECHTS))
                {
                psk kn;
                kn = _qmodulo(rlknoop,rrknoop);
                wis(*pkn);
                *pkn = kn;
                }
            return built_in_function_ok;
            }
        CASE(LOW)
            {
            psk kn;
            if(!is_op(rknoop))
                kn = changeCase(rknoop,FALSE,TRUE);
            else if(!is_op(rlknoop = rknoop->LINKS))
                kn = changeCase(rlknoop,zoekopt(rknoop->RECHTS,DOS),TRUE);
            else
                return function_fail;
            wis(*pkn);
            *pkn = kn;
            return built_in_function_ok;
            }
        CASE(UPP)
            {
            psk kn;
            if(!is_op(rknoop))
                kn = changeCase(rknoop,FALSE,FALSE);
            else if(!is_op(rlknoop = rknoop->LINKS))
                kn = changeCase(rlknoop,zoekopt(rknoop->RECHTS,DOS),FALSE);
            else
                return function_fail;
            wis(*pkn);
            *pkn = kn;
            return built_in_function_ok;
            }
        CASE(DIV)
            {
            if(  is_op(rknoop)
              && RATIONAAL_COMP(rlknoop = rknoop->LINKS)
              && RATIONAAL_COMP(rrknoop = rknoop->RECHTS)
              )
                {
                psk kn;
                /*int ral,rar;*/
                kn = _qheeldeel(rlknoop,rrknoop);
                /*
                ral = range(rlknoop);
                rar = range(rrknoop);
                */
                wis(*pkn);
                *pkn = kn;
                return built_in_function_ok;
                }
            return function_fail;
            }
        CASE(DEN)
            {
            if(RATIONAAL_COMP(rknoop))
                {
                psk kn;
                kn = _qdenominator(rknoop);
                wis(*pkn);
                *pkn = kn;
                }
            return built_in_function_ok;
            }
        CASE(LST)
            {
            return output(pkn,lst);
            }
        CASE(REN)
            {
            if(  is_op(rknoop)
              && !is_op(rlknoop = rknoop->LINKS)
              && !is_op(rrknoop = rknoop->RECHTS)
              )
                {
                char pc[11];
                int ret = rename((const char*)POBJ(rlknoop),(const char*)POBJ(rrknoop));
                if(ret)
                    {
#ifndef EACCES
                    sprintf(pc,"%d",ret);
#else
                    switch(errno)
                        {
                        case EACCES:
                            /*
                            File or directory specified by newname already exists or
                            could not be created (invalid path); or oldname is a directory
                            and newname specifies a different path.
                            */
                            strcpy(pc,"EACCES");
                            break;
                        case ENOENT:
                            /*
                            File or path specified by oldname not found.
                            */
                            strcpy(pc,"ENOENT");
                            break;
                        case EINVAL:
                            /*
                            Name contains invalid characters.
                            */
                            strcpy(pc,"EINVAL");
                            break;
                        default:
                            sprintf(pc,"%d",errno);
                            break;
                        }
#endif
                    }
                else
                    strcpy(pc,"0");
                *pkn = opb(*pkn,pc,NULL);
                return built_in_function_ok;
                }
            else
                return function_fail;
            }
        CASE(GET) /* get$file */
            {
            int echmemvapstr;
            if(is_op(rknoop))
                {
                if(is_op(rlknoop = rknoop->LINKS))
                    return function_fail;
                rrknoop = rknoop->RECHTS;
                echmemvapstr = (zoekopt(rrknoop,ECH) << 3)
                             + (zoekopt(rrknoop,MEM) << 2)
                             + (zoekopt(rrknoop,VAP) << 1)
                             + (zoekopt(rrknoop,STG));
                }
            else
                {
                echmemvapstr = 0;
                rlknoop = rknoop;
                }
            if(echmemvapstr & 4 /* MEM */)
                {
                int err;
                adr[1] = zelfde_als_w(rlknoop);
                bron = POBJ(adr[1]);
                while(input(NULL,pkn,echmemvapstr,&err) && !err)
                    evalueer(pkn);
                wis(adr[1]);
                }
            else
                {
#if COMPILE
                if(RPOBJ(rlknoop) && strcmp((char*)POBJ(rlknoop),"stdin"))
#else
                if(rlknoop->u.obj && strcmp((char*)POBJ(rlknoop),"stdin"))
#endif
                    {
                    FILE *red;
                    int err;
                    red = fpi;
                    fpi = fopen((char*)POBJ(rlknoop),"r");
                    if(fpi == NULL)
                        {
                        fpi = red;
                        return function_fail;
                        }
                    while(input(fpi,pkn,echmemvapstr,&err) && !err)
                        {
                        evalueer(pkn);
                        }
                    fclose(fpi);
                    fpi = red;
                    }
                else
                    {
                    int err;
                    echmemvapstr |= 8;
#ifdef DELAY_DUE_TO_INPUT
                    while(TRUE)
                        {
                        clock_t time0;
                        Boolean somethingToDo;
                        time0 = clock();
                        somethingToDo = input(stdin,pkn,echmemvapstr,&err) && !err;
                        delayDueToInput += clock() - time0;
                        if(!somethingToDo)
                            break;
                        evalueer(pkn);
                        }
#else
                    while(input(stdin,pkn,echmemvapstr,&err) && !err)
                        evalueer(pkn);
#endif
#if 0
#ifdef CLOCKS_PER_SEC
                    time0 = clock();
#endif
#ifdef vax
                    gettimeofday(&t0,&tzp);
#endif
#endif
                    }
                }
            return built_in_function_ok;
            }
        CASE(PUT) /* put$(file,mode,knoop) of put$knoop */
            {
            return output(pkn,result) ? built_in_function_ok : function_fail;
            }
#if !MICROSOFT_WINDOWS_API || defined __WIN32__ || defined _WIN32
        /* system() not implemented under older Windows */
        CASE(SYS)
            {
            if(is_op(rknoop))
                return function_fail;
            else
                {
                char pc[11];
                int ret = system((const char*)POBJ(rknoop));
                if(ret)
#ifndef E2BIG
                    sprintf(pc,"%d",ret);
#else
                    switch(errno)
                        {
                        case E2BIG:
                            /*
                            Argument list (which is system-dependent) is too big.
                            */
                            strcpy(pc,"E2BIG");
                            break;
                        case ENOENT:
                            /*
                            Command interpreter cannot be found.
                            */
                            strcpy(pc,"ENOENT");
                            break;
                        case ENOEXEC:
                            /*
                            Command-interpreter file has invalid format and is not executable.
                            */
                            strcpy(pc,"ENOEXEC");
                            break;
                        case ENOMEM:
                            /*
                            Not enough memory is available to execute command; or available
                            memory has been corrupted; or invalid block exists, indicating
                            that process making call was not allocated properly.
                            */
                            strcpy(pc,"ENOMEM");
                            break;
                        default:
                            sprintf(pc,"%d",errno);
                            break;
                        }
#endif
                else
                    strcpy(pc,"0");
                *pkn = opb(*pkn,pc,NULL);
                return built_in_function_ok;
                }
            }
#endif
        CASE(TBL) /* tbl$(varnaam,lengte) */
            {
            if(is_op(rknoop))
                return psh(rknoop->LINKS,&nulk,rknoop->RECHTS) ? built_in_function_ok : function_fail;
            else
                return function_fail;
            }
        CASE(PRV) /* "?"$<expr> */
            {
            if((rknoop->flgs & SUCCES)
#if COMPILE
            && (is_op(rknoop) || RPOBJ(rknoop) || HAS_UNOPS(rknoop)))
#else
            && (is_op(rknoop) || rknoop->u.obj || HAS_UNOPS(rknoop)))
#endif
                insert(&nilk,rknoop);
            *pkn = rechtertak(*pkn);
            return built_in_function_ok;
            }
        CASE(CLK) /* clk' */
            {
            static char klok[22];
            long time;
#ifdef DELAY_DUE_TO_INPUT
            time = (long)clock() - delayDueToInput;
#else
            time = (long)clock();
#endif
#ifdef __TURBOC__
            sprintf(klok,"%ld0/%ld",time,(long)(10.0*CLOCKS_PER_SEC));
#else
            sprintf(klok,"%ld/%ld",time,(long)CLOCKS_PER_SEC);
#endif
            *pkn = opb(*pkn,klok,NULL);
            return built_in_function_ok;
            }

        CASE(SIM) /* sim$(<atoom>,<atoom>) , fuzzy compare (percentage) */
            {
            if(kop(rknoop) == KOMMA
            && !is_op(rlknoop = rknoop->LINKS)
            && !is_op(rrknoop = rknoop->RECHTS))
                {
                static char res[22];
                char *str1,*str2;
                str1 = (char*)POBJ(rlknoop);
                str2 = (char*)POBJ(rrknoop);
                sprintf(res,"%ld/%ld",
           (2L*(long)simil(str1,str2)),((long)strlen(str1) + (long)strlen(str2)));
                *pkn = opb(*pkn,res,NULL);
                return built_in_function_ok;
                }
            else
                return function_fail;
            }
#if 0
        CASE(SYM) /* sym$(=~(!a:#&!b)) -> ("~".(=!a):#."&".(=!b)) */
                  /* a+b:?x_?y & sym$(=!a_!b) -> (.(=!a)."_".(=!b)) */
                  /* sym$(=~/%@<>?`!!a) -> ("~" "/" "<" ">" "%" "@" "?" "`" "!!".a) */
            {
            }
#endif
        CASE(DBG) /* dbg$<expr> */
            {
            ++debug;
            if(kop(*pkn) != FUU)
                {
                errorprintf("Use dbg'(expression), not dbg$(expression)!\n");
                writeError(*pkn);
                }
            *pkn = rechtertak(*pkn);
            evalueer(pkn);
            --debug;
            return built_in_function_ok;
            }
        CASE(New) /* new$<object>*/
            {
            if(kop(rknoop) == KOMMA)
                {
                adr[2] = getObjectDef(rknoop->LINKS);
                if(!adr[2])
                    return function_fail;
                adr[3] = rknoop->RECHTS;
                if(ISBUILTIN((objectknoop*)adr[2]))
                    *pkn = opb(*pkn,"(((\2.New)'\3)|)",NULL);
    /*                *pkn = opb(*pkn,"(((\2.New)'\3)&(\2.new)'\3)|)&\2",NULL);*/
    /* We might be able to call 'new' if 'New' had attached the argument
        (containing the definition of a 'new' method) to the rhs of the '='.
       This cannot be done in a general way without introducing new syntax rules for the new$ function.
    */
                else
                    *pkn = opb(*pkn,"(((\2.new)'\3)|)&\2",NULL);
                }
            else
                {
                adr[2] = getObjectDef(rknoop);
                if(!adr[2])
                    return function_fail;
                if(ISBUILTIN((objectknoop*)adr[2]))
                    *pkn = opb(*pkn,"(((\2.New)')|)",NULL);
                /* There cannot be a user-defined 'new' method on a built-in object if there is no way to supply it*/
                /* 'die' CAN be user-supplied. The built-in function is 'Die' */
                else
                    *pkn = opb(*pkn,"(((\2.new)')|)&\2",NULL);
                }
            SETCREATEDWITHNEW((objectknoop*)adr[2]);
            /*printf("New object[%p]",adr[2]);result(adr[2]);printf("\n");*/
            wis(adr[2]);
            return built_in_function_ok;
            }
        CASE(0) /* $<expr>  '<expr> */
            {
            if(kop(*pkn) == FUU && !HAS_UNOPS((*pkn)->LINKS))
                {
                if(!evalmacro(&((*pkn)->RECHTS)))
                    return function_fail;
                adr[1] = (*pkn)->RECHTS;
                *pkn = opb(*pkn,"=\1",NULL);
                }
            else
                {
                combiflags(*pkn);
                *pkn = rechtertak(*pkn);
                }
            return built_in_function_ok;
            }
        DEFAULT
            {
    /*        int dummy;*/
            if(GEHEEL(lknoop))
                {
                vars *navar;
                if(is_op(rknoop))
                    return function_fail;
#if COMPILE
                for(navar = variabelen[RPOBJ(rknoop)];
#else
                for(navar = variabelen[rknoop->u.obj];
#endif
#ifdef PVNAME
                    navar && (STRCMP(navar->vname,POBJ(rknoop)) < 0);
#else
                    navar && (STRCMP(&navar->u.Obj,POBJ(rknoop)) < 0);
#endif
                    navar = navar->next);
                /* eerste naam in een rij gelijke wordt gevonden */
#ifdef PVNAME
                if(navar && !STRCMP(navar->vname,POBJ(rknoop)))
#else
                if(navar && !STRCMP(&navar->u.Obj,POBJ(rknoop)))
#endif
                    {
                    navar->selector =
                       (int)toLong(lknoop)
                     % (navar->n + 1);
                    if(navar->selector < 0)
                        navar->selector += (navar->n + 1);
                    *pkn = rechtertak(*pkn);
                    return built_in_function_ok;
                    }
                }
            if(!(rknoop->flgs & SUCCES))
                return function_fail;
            adr[1] = NULL;
            return find_func(pkn);
            }
        }
        }
    /*return built_in_function_ok; 20 Dec 1995, unreachable code in Borland C */
    }

static int machtbuitenhaakjes(ppsk pkn)
    {
    psk lknoop;
    lknoop = (*pkn)->LINKS;
    if(kop(lknoop) == MAAL)
        {
        adr[1] = lknoop->LINKS;
        adr[2] = lknoop->RECHTS;
        adr[3] = (*pkn)->RECHTS;
        *pkn = opb(*pkn,"\1^\3*\2^\3",NULL);
        return TRUE;
        }
    return FALSE;
    }

#if SLOWPLUS
/*
does not evaluate (1+i*a+i*c)+2+i*b+-i*c+i*d correctly
                  3+i*a+i*b+i*c+i*d+-i*c
or
    b+(i*c+i*d)+-i*c
*/
static ppsk prechteroperand(psk pkn)
{
ppsk temp;
unsigned int teken;
temp = &(pkn->RECHTS);
return((teken = kop(pkn)) == kop(*temp) &&
        (teken == PLUS || teken == MAAL || teken == LUCHT) ?
       &(*temp)->LINKS : temp);
}

static int complic_term(ppsk pkn)
{
ppsk hulp;
hulp = prechteroperand(*pkn);
switch(kop(*hulp))
    {
    case MAAL :
    case EXP  :
        if((match(*hulp,m0,NULL) & TRUE && tryq(hulp,f0))
        || (match(*hulp,m1,NULL) & TRUE && tryq(hulp,f1)))
            {
            (*pkn)->flgs &= ~KLAAR;
            if(is_op((*pkn)->RECHTS))
                (*pkn)->RECHTS->flgs &= ~KLAAR;
            return TRUE;
            }
        /* doorvallen */
    default :
        {
        hulp = &((*pkn)->LINKS);
        switch(kop(*hulp))
            {
            case MAAL :
            case EXP  :
                if((match(*hulp,m0,NULL) & TRUE && tryq(hulp,f0))
                || (match(*hulp,m1,NULL) & TRUE && tryq(hulp,f1)))
                    {
                    (*pkn)->flgs &= ~KLAAR;
                    return TRUE;
                    }
                else
                    return FALSE;
            }
        }
    }
return FALSE;
}

static psk nonnumfactor(psk pknoop,ppsk ppFirstTerm,ppsk staart)
    {
    if(kop(pknoop) == PLUS)
        {
        *staart = pknoop->RECHTS;
        pknoop = pknoop->LINKS;
        }
    else
        *staart = NULL;
    *ppFirstTerm = pknoop;

    if(kop(pknoop) == MAAL && RATIONAAL_COMP(pknoop->LINKS))
        return pknoop->RECHTS;
    else
        return pknoop;
    }

static psk imfactor(psk pknoop,ppsk pprknoop)
    {
    if(kop(pknoop) == MAAL)
        {
        if(is_op(pknoop->LINKS) || PLOBJ(pknoop->LINKS) != IM)
            {
            *pprknoop = pknoop; /*  x^2*y -> x^2*y , x*y -> x*y*/
            return NULL;
            }
        else
            {
            *pprknoop = pknoop->RECHTS;  /* i*y -> y */
            return pknoop->LINKS;        /* i*y -> i */
            }
        }
    else if(is_op(pknoop) || PLOBJ(pknoop) != IM)
        {
        *pprknoop = pknoop;  /* x^2 -> x^2 */
        return NULL;
        }
    else
        {
        *pprknoop = NULL;    /* i -> NULL */
        return pknoop;       /* i -> i */
        }
    }

static int plus_samenvoegen_of_sorteren(ppsk pkn)
    {
    static const char *conc[] = {NULL,NULL,NULL,NULL};
    int knverschil;
    psk iknoop,linksknoop,rechtsknoop,lrknoop,rrknoop,lstaart,rstaart;
    iknoop = *pkn;

    lrknoop = nonnumfactor(iknoop->LINKS,&linksknoop,&lstaart);

    if(!is_op(linksknoop) && RAT_NUL_COMP(lrknoop))
        {
        if(lstaart)
            {
            /* You never get here, the term (0+x)
               in (0+x)+y is already evaluated to x
            */
            /*printf("(0+x)+y -> x+y\n");*/
            /* (0+x)+y -> x+y */
            adr[1] = lstaart;
            adr[2] = iknoop->RECHTS;
            *pkn = opb(*pkn,"\1+\2",NULL);
            }
        else
            {
            /*result(*pkn);
            printf("   0+x -> x\n");*/
            /* 0+x -> x */
            *pkn = rechtertak(*pkn);
            }
        return TRUE;
        }
    else
        {
        rrknoop = nonnumfactor(iknoop->RECHTS,&rechtsknoop,&rstaart);
        if(RATIONAAL_COMP(rechtsknoop) && RATIONAAL_COMP(linksknoop))
            {
            conc[0] = hekje6;
            if(rechtsknoop == linksknoop)
                /* 7+7 -> 2*7 */
                adr[6] = _qmaal(&tweek,linksknoop);
            else
                /* 4+7 -> 11 */
                adr[6] = _qplus(rechtsknoop,linksknoop);
            if(lstaart != NULL)
                {
                adr[5] = lstaart;
                conc[1] = "+\5";
                }
            else
                conc[1] = NULL;
            conc[2] = NULL;
            if(rstaart != NULL)
                {
                adr[4] = rstaart;
                conc[lstaart == NULL ? 1 : 2] = "+\4";
                }
            *pkn = vopb(*pkn,conc);
            wis(adr[6]);
            return TRUE;
            }
        }

    if((knverschil = vgl(lrknoop,rrknoop)) == 0)
        {
        if(rrknoop != rechtsknoop)
            {
            adr[1] = rrknoop;
            adr[2] = rechtsknoop->LINKS;
            if(lrknoop == linksknoop)
                /* a+n*a */
                conc[0] = "(1+\2)*\1";
            /* (1+n)*a */
            else
                {
                /* n*a+m*a */
                adr[3] = linksknoop->LINKS;
                conc[0] = "(\3+\2)*\1";
                /* (n+m)*a */
                }
            }
        else
            {
            adr[1] = lrknoop;
            if(lrknoop != linksknoop)
                {
                /* m*a+a */
                adr[2] = linksknoop->LINKS;
                conc[0] = "(1+\2)*\1";
                /* (1+m)*a */
                }
            else
                /* a+a */
                conc[0] = "2*\1";
            /* 2*a */
            }
        if(lstaart != NULL)
            {
            adr[5] = lstaart;
            conc[1] = "+\5";
            }
        else
            conc[1] = NULL;
        conc[2] = NULL;
        if(rstaart != NULL)
            {
            adr[4] = rstaart;
            conc[lstaart == NULL ? 1 : 2] = "+\4";
            }
        *pkn = vopb(*pkn,conc);
        return TRUE;
        }
    else
        {
        psk lrrknoop,rrrknoop;
        psk leftIM;
        if(  (leftIM = imfactor(lrknoop,&lrrknoop)) != NULL
          && imfactor(rrknoop,&rrrknoop) != NULL
          && (  lrrknoop == rrrknoop
             ||    lrrknoop != NULL
                && rrrknoop != NULL
                && vgl(lrrknoop,rrrknoop) == 0
             )
            /*&& vgl(lrlknoop,rrlknoop) != 0*/
          )
            {
            /*
            (f6=
              a,b,c,i,d
            .     !arg
                :   #?a*((i|-i):?i)*?b
                  + #?c*(-i|i)*!b
                  + ?d
              & (!a+-1*!c)*!i*!b+!d);

               The reason why this works without comparing the signs of 'i'
               is that if the terms both contain 'i' or both contain '-i'
               then the terms are combined already.
            */
            return tryq(pkn,f6);
            }
        else
            {
            int graad;
            if(  getal_graad(rrknoop) > (graad = getal_graad(lrknoop))
              || (!graad && (knverschil > 0))
              )
                {
                /* n*b+m*a */
                /* n*l+m*a */
                /* i*x+y */
                /* e*x+y */
                /* pi*x+y */
                if(rstaart == NULL)
                    {
                    iknoop->RECHTS = iknoop->LINKS;
                    iknoop->LINKS = rechtsknoop;
                    iknoop->flgs &= ~KLAAR;
                    }
                else
                    {
                    adr[1] = iknoop->LINKS;
                    adr[2] = rechtsknoop;
                    adr[3] = rstaart;
                    *pkn = opb(*pkn,"\2+\1+\3",NULL);
                    }
                return TRUE;
                /* m*a+n*b */
                /* m*a+n*l */
                }
            else if(lstaart != NULL) /* dit is in plaats van rechtsbrengen() */
                {
                adr[1] = linksknoop;
                adr[2] = lstaart;
                adr[3] = iknoop->RECHTS;
                *pkn = opb(*pkn,"\1+\2+\3",NULL);
                return TRUE;
                }
            }
        }
    /* lstaart == NULL */
    if(  kop(linksknoop) == LOG
      && kop(rechtsknoop) == LOG
      && !vgl(linksknoop->LINKS,rechtsknoop->LINKS)
      )
        {
        adr[1] = linksknoop->LINKS;
        adr[2] = linksknoop->RECHTS;
        adr[3] = rechtsknoop->RECHTS;
        if(rstaart == NULL)
            *pkn = opb(*pkn,"\1\016(\2*\3)",NULL);
        else
            {
            adr[4] = rstaart;
            *pkn = opb(*pkn,"\1\016(\2*\3)+\4",NULL);
            }
        return TRUE;
        }
    return FALSE;
    }

#else /* SLOWPLUS == 0 */


/*
Bart 20010316
Improvement that DOES evaluate b+(i*c+i*d)+-i*c
It also allows much deeper structures, because the right place for insertion
is found iteratively, not recursively. This also causes some operations to
be tremendously faster. e.g. (1+a+b+c)^30+1&ready evaluates in about
4,5 seconds now, previously in 330 seconds! (AST Bravo MS 5233M 233 MHz MMX Pentium)
*/
static void splitProduct_number_im_rest(psk pknoop,ppsk N,ppsk I, ppsk NNNI)
    {
    psk temp;
    if(kop(pknoop) == MAAL)
        {
        if(RATIONAAL_COMP(pknoop->LINKS))
            {
            *N = pknoop->LINKS;
            temp = pknoop->RECHTS;
            }
        else
            {
            *N = NULL;
            temp = pknoop;
            }
        if(kop(temp) == MAAL)
            {
            if(!is_op(temp->LINKS) && PLOBJ(temp->LINKS) == IM)
                {
                *I = temp->LINKS;
                *NNNI = temp->RECHTS;
                }
            else
                {
                *I = NULL;
                *NNNI = temp;
                }
            }
        else
            {
            if(!is_op(temp) && PLOBJ(temp) == IM)
                {
                *I = temp;
                *NNNI = NULL;
                }
            else
                {
                *I = NULL;
                *NNNI = temp;
                }
            }
        }
    else if(RATIONAAL_COMP(pknoop))
        {
        *N = pknoop;
        *I = NULL;
        *NNNI = NULL;
        }
    else if(!is_op(pknoop) && PLOBJ(pknoop) == IM)
        {
        *N = NULL;
        *I = pknoop;
        *NNNI = NULL;
        }
    else
        {
        *N = NULL;
        *I = NULL;
        *NNNI = pknoop;
        }
    }

static void rechteroperand_and_tail(psk pkn,ppsk head,ppsk tail)
    {
    psk temp = pkn->RECHTS;
    if(kop(pkn) == kop(temp))
        {
        *head = temp->LINKS;
        *tail = temp->RECHTS;
        }
    else
        {
        *head = temp;
        *tail = NULL;
        }
    }

static void linkeroperand_and_tail(psk pkn,ppsk head,ppsk tail)
    {
    psk temp = pkn->LINKS;
    if(kop(pkn) == kop(temp))
        {
        *head = temp->LINKS;
        *tail = temp->RECHTS;
        }
    else
        {
        *head = temp;
        *tail = NULL;
        }
    }

static int expandProduct(ppsk pkn)
    {
    switch(kop(*pkn))
        {
        case MAAL :
        case EXP  :
            /*printf("expandProduct:");result(*pkn);printf(" -> ");*/
            if((match(0,*pkn,m0,NULL) & TRUE && tryq(pkn,f0))
            || (match(0,*pkn,m1,NULL) & TRUE && tryq(pkn,f1)))
                {
                (*pkn)->flgs &= ~KLAAR;
                /*result(*pkn);printf("\n");*/
                return TRUE;
                }
            /*printf("\n");*/
        }
    return FALSE;
    }

static int plus_samenvoegen_of_sorteren(ppsk pkn)
    {
    /*
    Split pkn in left L and right R argument

    If L is zero,
        return R

    If R is zero,
        return L

    If L is a product containing a sum,
        expand it

    If R is a product containing a sum,
        expand it

    Find the proper place split of R into Rhead , RtermS,  RtermGE and Rtail for L to insert into:
        L + R -> Rhead + RtermS + L + RtermGE + Rtail:
    Start with Rhead = NIL, RtermS = NIL  RtermGE is first term of R and Rtail is remainder of R
    Split L into Lterm and Ltail
    If Lterm is a number
        if RtermGE is a number
            return sum(Lterm,RtermGE) + Ltail + Rtail
        else
            return Lterm + Ltail + R
    Else if Rterm is a number
        return Rterm + L + Rtail
    Else
        get the non-numerical factor LtermNN of Lterm
        if LtermNN is imaginary
            get the nonimaginary factors of LtermNN (these may also include 'e' and 'pi') LtermNNNI
            find Rhead,  RtermS, RtermGE and Rtail
                such that Rhead does contain all non-imaginary terms
                and such that RtermGE and Rtail
                    either are NIL
                    or RtermGE is imaginary
                        and (RtermS is NIL or RtermSNNNI <  LtermNNNI) and LtermNNNI <= RtermGENNNI
            if RtermGE is NIL
                return R + L
            else
                if LtermNNNI < RtermGENNNI
                    return Rhead + RtermS + L + RtermGE + Rtail
                else
                    return Rhead + RtermS + sum(L,RtermGE) + Rtail
        else
            find Rhead,  RtermS, RtermGE and Rtail
                such that RtermGE and Rtail
                    either are NIL
                    or (RtermS is NIL or RtermSNN <  LtermNN) and LtermNN <= RtermGENN
            if RtermGE is NIL
                return R + L
            else
                if LtermNN < RtermGENN
                    return Rhead + RtermS + L + RtermGE + Rtail
                else
                    return Rhead + RtermS + sum(L,RtermGE) + Rtail


    */
    static const char *conc[] = {NULL,NULL,NULL,NULL};
    int res = FALSE;
    psk top = *pkn;

    psk L = top->LINKS;
    psk Lterm,Ltail;
    psk LtermN,LtermI,LtermNNNI;

    psk R;
    psk Rterm,Rtail;
    psk RtermN,RtermI,RtermNNNI;

/*    printf("NU:");result(top);printf("\n");*/
    if(!is_op(L) && RAT_NUL_COMP(L))
        {
        /* 0+x -> x */
        *pkn = rechtertak(top);
        return TRUE;
        }

    R = top->RECHTS;
    if(!is_op(R) && RAT_NUL_COMP(R))
        {
        /* x+0 -> x */
        *pkn = linkertak(top);
        return TRUE;
        }

    if(  is_op(L)
      && expandProduct(&top->LINKS)
      )
        {
        res = TRUE;
        }

    if(  is_op(R)
      && expandProduct(&top->RECHTS)
      )
        {
        res = TRUE;
        }

    if(res)
        {
        (*pkn)->flgs &= ~KLAAR;
        return TRUE;
        }

    rechteroperand_and_tail(top,&Rterm,&Rtail);
    linkeroperand_and_tail(top,&Lterm,&Ltail);
    if(RATIONAAL_COMP(Lterm))
        {
        if(RATIONAAL_COMP(Rterm))
            {
            conc[0] = hekje6;
            if(Lterm == Rterm)
                /* 7+7 -> 2*7 */
                adr[6] = _qmaal(&tweek,Rterm);
            else
                /* 4+7 -> 11 */
                adr[6] = _qplus(Lterm,Rterm);
            if(Ltail != NULL)
                {
                adr[5] = Ltail;
                conc[1] = "+\5";
                }
            else
                conc[1] = NULL;
            conc[2] = NULL;
            if(Rtail != NULL)
                {
                adr[4] = Rtail;
                conc[Ltail == NULL ? 1 : 2] = "+\4";
                }
            *pkn = vopb(top,conc);
            wis(adr[6]);
            return TRUE;
            }
        else if(Ltail != NULL)
            {
            adr[1] = Lterm;
            adr[2] = Ltail;
            adr[3] = R;
            *pkn = opb(top,"\1+\2+\3",NULL);
            return TRUE;
            }
        return res;
        }
    else if(RATIONAAL_COMP(Rterm))
        {
        adr[1] = Rterm;
        adr[2] = L;
        if(Rtail)
            {
            adr[3] = Rtail;
            *pkn = opb(top,"\1+\2+\3",NULL);
            }
        else
            {
            *pkn = opb(top,"\1+\2",NULL);
            }
        return TRUE;
        }

    if(  kop(Lterm) == LOG
      && kop(Rterm) == LOG
      && !vgl(Lterm->LINKS,Rterm->LINKS)
      )
        {
        adr[1] = Lterm->LINKS;
        adr[2] = Lterm->RECHTS;
        adr[3] = Rterm->RECHTS;
        if(Rtail == NULL)
            *pkn = opb(top,"\1\016(\2*\3)",NULL);
        else
            {
            adr[4] = Rtail;
            *pkn = opb(top,"\1\016(\2*\3)+\4",NULL);
            }
        return TRUE;
        }

    splitProduct_number_im_rest(Lterm,&LtermN,&LtermI,&LtermNNNI);

    if(LtermI)
        {
        ppsk loper = pkn;
        assert(LtermNNNI != NULL);
        splitProduct_number_im_rest(Rterm,&RtermN,&RtermI,&RtermNNNI);
        while(  /*RtermNNNI != NULL
             &&*/ RtermI == NULL
/*
             && (dif = vgl(LtermNNNI,RtermNNNI)) > 0
*/
             && kop((*loper)->RECHTS) == PLUS
             )
            {
            loper = &(*loper)->RECHTS;
            *loper = prive(*loper);
            rechteroperand_and_tail((*loper),&Rterm,&Rtail);
            splitProduct_number_im_rest(Rterm,&RtermN,&RtermI,&RtermNNNI);
            }
        if(RtermI != NULL)
            {
            int indx;
            int dif;
            if(LtermNNNI == NULL)
                dif = RtermNNNI == NULL ? 0 : -1;
            else if(RtermNNNI == NULL)
                dif = 1;
            else
                while( (dif = vgl(LtermNNNI,RtermNNNI)) > 0
                     && kop((*loper)->RECHTS) == PLUS
                     )
                    {
                    loper = &(*loper)->RECHTS;
                    *loper = prive(*loper);
                    rechteroperand_and_tail((*loper),&Rterm,&Rtail);
                    splitProduct_number_im_rest(Rterm,&RtermN,&RtermI,&RtermNNNI);
                    }
            if(dif == 0)
                {
                if(RtermN)
                    {
                    adr[2] = RtermN;
                    if(LtermN == NULL)
                        {
                        /* a+n*a */
                        if(HAS_MINUS_SIGN(LtermI))
                            if(HAS_MINUS_SIGN(RtermI))
                                {
/*                                printf("A\n");*/
                                conc[0] = "(1+\2)*-i";
                                }
                            else
                                {
/*                                printf("B\n");*/
                                conc[0] = "(-1+\2)*i";
                                }
                        else
                            if(HAS_MINUS_SIGN(RtermI))
                                {
/*                                printf("C\n");*/
                                conc[0] = "(-1+\2)*-i";
                                }
                            else
                                {
/*                                printf("D\n");*/
                                conc[0] = "(1+\2)*i";
                                }
                        }
                    /* (1+n)*a */
                    else
                        {
                        /* n*a+m*a */
                        adr[3] = LtermN;
                        if(HAS_MINUS_SIGN(LtermI))
                            if(HAS_MINUS_SIGN(RtermI))
                                {
/*                                printf("E\n");*/
                                conc[0] = "(\3+\2)*-i";
                                }
                            else
                                {
/*                                printf("F\n");*/
                                conc[0] = "(-1*\3+\2)*i";
                                }
                        else
                            if(HAS_MINUS_SIGN(RtermI))
                                {
/*                                printf("G\n");*/
                                conc[0] = "(\3+-1*\2)*i";
                                }
                            else
                                {
/*                                printf("H\n");*/
                                conc[0] = "(\3+\2)*i";
                                }
                        /* (n+m)*a */
                        }
                    }
                else
                    {
                    adr[1] = LtermNNNI;
                    if(LtermN != NULL)
                        {
                        /* m*a+a */
                        adr[2] = LtermN;
                        if(HAS_MINUS_SIGN(LtermI))
                            if(HAS_MINUS_SIGN(RtermI))
                                {
/*                                printf("I\n");*/
                                conc[0] = "(1+\2)*-i";
                                }
                            else
                                {
/*                                printf("J\n");*/
                                conc[0] = "(-1+\2)*-i";
                                }
                        else
                            if(HAS_MINUS_SIGN(RtermI))
                                {
/*                                printf("K\n");*/
                                conc[0] = "(-1+\2)*i";
                                }
                            else
                                {
/*                                printf("L\n");*/
                                conc[0] = "(1+\2)*i";
                                }
                        /* (1+m)*a */
                        }
                    else
                        {
                        /* a+a */
                        if(HAS_MINUS_SIGN(LtermI))
                            if(HAS_MINUS_SIGN(RtermI))
                                {
/*                                printf("M\n");*/
                                conc[0] = "2*-i";
                                }
                            else
                                {
/*                                printf("N\n");*/
                                conc[0] = "0";
                                }
                        else
                            if(HAS_MINUS_SIGN(RtermI))
                                {
/*                                printf("O\n");*/
                                conc[0] = "0";
                                }
                            else
                                {
/*                                printf("P\n");*/
                                conc[0] = "2*i";
                                }
                        }
                    /* 2*a */
                    }
                if(LtermNNNI != NULL)
                    {
                    adr[1] = RtermNNNI;
                    conc[1] = "*\1";
                    indx = 2;
                    }
                else
                    indx = 1;
                if(Ltail != NULL)
                    {
                    adr[5] = Ltail;
                    conc[indx++] = "+\5";
                    }
                if(Rtail != NULL)
                    {
                    adr[4] = Rtail;
                    conc[indx++] = "+\4";
                    }
                conc[indx] = NULL;
                (*loper)->RECHTS = vopb((*loper)->RECHTS,conc);
                /*evalueer(&loper->RECHTS);*/
                if(loper != pkn)
                    {
                    (*loper)->flgs &= ~KLAAR;
                    evalueer(loper);
                    }
                *pkn = rechtertak(top);
                return TRUE;
                }
            else if(dif > 0) /* b + a */
                {
                adr[1] = Rterm;
                adr[2] = L;
                (*loper)->RECHTS = opb((*loper)->RECHTS,"\1+\2",NULL);
                (*loper)->RECHTS->flgs |= KLAAR;
                /*
                evalueer(&(*loper)->RECHTS);
                */
                *pkn = rechtertak(top);
                return TRUE;
                }
            else if((*loper) != top) /* b + a + c */
                {
                adr[1] = L;
                adr[2] = (*loper)->RECHTS;
                (*loper)->RECHTS = opb((*loper)->RECHTS,"\1+\2",NULL);
                evalueer(&(*loper)->RECHTS);
                *pkn = rechtertak(top);
                return TRUE;
                }
            else if(Ltail != NULL) /* (a+c+f)+b+d+g */
                {
                adr[1] = Lterm;
                adr[2] = Ltail;
                adr[3] = top->RECHTS;
                *pkn = opb(top,"\1+\2+\3",NULL);
                return TRUE;
                }
            }
        else  /* LtermI != NULL && RtermI == NULL */
            {
            adr[1] = Rterm; /* (*loper)->RECHTS; */
            adr[2] = L;
/*            printf("*pkn            1:");result((*pkn));printf("\n");
            printf("(*loper)->RECHTS1:");result((*loper)->RECHTS);printf("\n");*/
            (*loper)->RECHTS = opb((*loper)->RECHTS,"\1+\2",NULL);
/*            printf("*pkn            2:");result((*pkn));printf("\n");
            printf("(*loper)->RECHTS2:");result((*loper)->RECHTS);printf("\n");*/
            (*loper)->RECHTS->flgs |= KLAAR;
            /*
            evalueer(&(*loper)->RECHTS);
            */
            *pkn = rechtertak(top);
            return TRUE;
            }
        }
    else /* LtermI == NULL */
        {
        ppsk loper = pkn;
        int dif = 1;
        assert(LtermNNNI != NULL);
        splitProduct_number_im_rest(Rterm,&RtermN,&RtermI,&RtermNNNI);
        while(  RtermNNNI != NULL
             && RtermI == NULL
             && (dif = vgl(LtermNNNI,RtermNNNI)) > 0
             && kop((*loper)->RECHTS) == PLUS
             )
            {
            loper = &(*loper)->RECHTS;
            *loper = prive(*loper);
            rechteroperand_and_tail((*loper),&Rterm,&Rtail);
            splitProduct_number_im_rest(Rterm,&RtermN,&RtermI,&RtermNNNI);
            }
        if(RtermI != NULL)
            dif = -1;
/*        printf("dif %d\n",dif);*/
        if(dif == 0)
            {
            if(RtermN)
                {
                adr[1] = RtermNNNI;
                adr[2] = RtermN;
                if(LtermN == NULL)
                    /* a+n*a */
                    conc[0] = "(1+\2)*\1";
                /* (1+n)*a */
                else
                    {
                    /* n*a+m*a */
                    adr[3] = LtermN;
                    conc[0] = "(\3+\2)*\1";
                    /* (n+m)*a */
                    }
                }
            else
                {
                adr[1] = LtermNNNI;
                if(LtermN != NULL)
                    {
                    /* m*a+a */
                    adr[2] = LtermN;
                    conc[0] = "(1+\2)*\1";
                    /* (1+m)*a */
                    }
                else
                    /* a+a */
                    conc[0] = "2*\1";
                /* 2*a */
                }
            if(Ltail != NULL)
                {
                adr[5] = Ltail;
                conc[1] = "+\5";
                }
            else
                conc[1] = NULL;
            conc[2] = NULL;
            if(Rtail != NULL)
                {
                adr[4] = Rtail;
                conc[Ltail == NULL ? 1 : 2] = "+\4";
                }
            (*loper)->RECHTS = vopb((*loper)->RECHTS,conc);
            /*evalueer(&loper->RECHTS);*/
            if(loper != pkn)
                {
                (*loper)->flgs &= ~KLAAR;
                evalueer(loper);
                }
            *pkn = rechtertak(top);
            return TRUE;
            }
        else if(dif > 0) /* b + a */
            {
            adr[1] = Rterm;
            adr[2] = L;
            (*loper)->RECHTS = opb((*loper)->RECHTS,"\1+\2",NULL);
            (*loper)->RECHTS->flgs |= KLAAR;
            /*evalueer(&(*loper)->RECHTS);*/
            *pkn = rechtertak(top);
            return TRUE;
            }
        else if((*loper) != top) /* b + a + c */
            {
            adr[1] = L;
            adr[2] = (*loper)->RECHTS;
            (*loper)->RECHTS = opb((*loper)->RECHTS,"\1+\2",NULL);
            evalueer(&(*loper)->RECHTS);
            *pkn = rechtertak(top);
            return TRUE;
            }
        else if(Ltail != NULL) /* (a+c+f)+b+d+g */
            {
            adr[1] = Lterm;
            adr[2] = Ltail;
            adr[3] = top->RECHTS;
            *pkn = opb(top,"\1+\2+\3",NULL);
            return TRUE;
            }
        }
    return res;
    }
#endif

static int maal_samenvoegen_of_sorteren(ppsk pkn)
{
static char *conc[] = {NULL,NULL,NULL,NULL};
psk temp,iknoop,rechtsknoop,linksknoop,llknoop,rlknoop;
int knverschil;
iknoop = *pkn;
rechtsknoop = rechteroperand(*pkn);
linksknoop = iknoop->LINKS;
rlknoop = kop(rechtsknoop) == EXP ? rechtsknoop->LINKS : rechtsknoop;
llknoop = kop(linksknoop) == EXP ? linksknoop->LINKS : linksknoop;
if((knverschil = vgl(llknoop,rlknoop)) == 0)
    {
    /* a^n*a^m */
    if(rlknoop != rechtsknoop)
        {
        adr[1] = rlknoop;
        adr[2] = rechtsknoop->RECHTS;
        if(llknoop == linksknoop)
            /* a*a^n */
            conc[0] = "\1^(1+\2)";
            /* a^(1+n) */
        else
            {
            /* a^n*a^m */
            adr[3] = linksknoop->RECHTS;
            conc[0] = "\1^(\3+\2)";
            /* a^(n+m) */
            }
        }
    else
        {
        if(llknoop != linksknoop)
            {
            /* a^m*a */
            adr[1] = llknoop;
            adr[2] = linksknoop->RECHTS;
            conc[0] = "\1^(1+\2)";
            /* a^(m+1) */
            }
        else
            {
            /* a*a */
            adr[1] = llknoop;
            conc[0] = "\1^2";
            /* a^2 */
            }
        }
    if(rechtsknoop != (temp = iknoop->RECHTS))
        {
        adr[4] = temp->RECHTS;
        conc[1] = "*\4";
        }
    else
        conc[1] = NULL;
    *pkn = vopb(*pkn,(const char**)conc);
    return TRUE;
    }
else
    {
    int graad;
    graad = getal_graad(rlknoop) - getal_graad(llknoop);
    if(graad > 0
    || (graad == 0 && (knverschil > 0)))
        {
        /* b^n*a^m */
        /* l^n*a^m */
        if((temp = iknoop->RECHTS) == rechtsknoop)
            {
            iknoop->RECHTS = linksknoop;
            iknoop->LINKS = rechtsknoop;
            iknoop->flgs &= ~KLAAR;
            }
        else
            {
            adr[1] = linksknoop;
            adr[2] = temp->LINKS;
            adr[3] = temp->RECHTS;
            *pkn = opb(*pkn,"\2*\1*\3",NULL);
            }
        return TRUE;
        /* a^m*b^n */
        /* a^m*l^n */
        }
    else if(PLOBJ(rlknoop) == IM)
        {
        if(PLOBJ(llknoop) == IM)
            {
            /* i^n*-i^m */
            if(rlknoop != rechtsknoop)
                {
                adr[1] = llknoop;
                adr[2] = rechtsknoop->RECHTS;
                if(llknoop == linksknoop)
                    /* i*-i^n */
                    conc[0] = "\1^(1+-1*\2)";
                    /* i^(1-n) */
                else
                    {
                    /* i^n*-i^m */
                    adr[3] = linksknoop->RECHTS;
                    conc[0] = "\1^(\3+-1*\2)";
                    /* i^(n-m) */
                    }
                }
            else
                {
                if(llknoop != linksknoop)
                    {
                    /* i^m*-i */
                    adr[1] = llknoop;
                    adr[2] = linksknoop->RECHTS;
                    conc[0] = "\1^(-1+\2)";
                    /* i^(m-1) */
                    }
                else
                    {
                    /* i*-i */
                    conc[0] = "1";
                    /* 1 */
                    }
                }
            }
        else if(RAT_NEG_COMP(llknoop))
            {
            /* -n*i^m -> n*-i^-m */
            /* -n*-i^m -> n*i^-m */
            if(rlknoop != rechtsknoop)
                {
                adr[1] = llknoop;
                adr[2] = rechtsknoop->LINKS;
                adr[3] = rechtsknoop->RECHTS;
                if(llknoop == linksknoop)
                    /* -n*-i^m */
                    conc[0] = "(-1*\1)*(-1*\2)^\3";
                    /* n*i^-m */
                else
                    return FALSE;
                }
            else
                return FALSE;
            }
        else
            return FALSE;
        if(rechtsknoop != (temp = iknoop->RECHTS))
            {
            adr[4] = temp->RECHTS;
            conc[1] = "*\4";
            }
        else
            conc[1] = NULL;
        *pkn = vopb(*pkn,(const char**)conc);
        return TRUE;
        }
    }
return FALSE;
}

static int rechtsbrengen(psk kn)
    {
    psk lknoop;
    register int gedaan;
    gedaan = FALSE;
    for(;kop(lknoop = kn->LINKS) == kop(kn);)
        {
        lknoop = prive(lknoop);
        lknoop->flgs &= ~KLAAR;
        kn->LINKS = lknoop->LINKS;
        lknoop->LINKS = lknoop->RECHTS;
        lknoop->RECHTS = kn->RECHTS;
        kn->flgs &= ~KLAAR;
        kn->RECHTS = lknoop;
        kn = lknoop;
        gedaan = TRUE;
        }
    return gedaan;
    }

static int stapelmacht(ppsk pkn)
{
psk lknoop;
int gedaan;
gedaan = FALSE;
for(;((lknoop = (*pkn)->LINKS)->flgs & KLAAR) && kop(lknoop) == EXP;)
    {
    gedaan = TRUE;
    (*pkn)->LINKS = lknoop = prive(lknoop);
#if W32
    lknoop->flgs &= ~KLAAR & ~OPERATOR;/* KLAAR vlag uitzetten */
#else
    lknoop->flgs &= ~KLAAR;/* KLAAR vlag uitzetten */
    lknoop->ops &= ~OPERATOR;
#endif
    lknoop->ops |= MAAL;
    adr[1] = lknoop->LINKS;
    adr[2] = lknoop->RECHTS;
    adr[3] = (*pkn)->RECHTS;
    *pkn = opb(*pkn,"(\1^(\2*\3))",NULL);
    }
return gedaan;
}

static int substmaal(ppsk pkn)
{
static const char * conc[] = {NULL,NULL,NULL};
psk rkn,lkn;
psk rvar,lvar;

if(is_op(rkn = rechteroperand(*pkn)))
    rvar = NULL;
else
    {
    if(RAT_NUL(rkn))
        {
        replace(pkn,&nulk);
        return TRUE;
        }
    rvar = rkn;
    }

if(is_op(lkn = (*pkn)->LINKS))
    return FALSE;
else
    {
    if(RAT_NUL(lkn))
        {
        replace(pkn,&nulk);
        return TRUE;
        }
    lvar = lkn;
    }

if(IS_EEN(lkn))
    {
    *pkn = rechtertak(*pkn);
    return TRUE;
    }
else if(RATIONAAL_COMP(lkn) && rvar)
    {
    if(RATIONAAL_COMP(rkn))
        {
        if(rkn == lkn)
            lvar = ((*pkn)->LINKS = prive(lkn));
        conc[0] = hekje6;
        adr[6] = _qmaal(rvar,lvar);
        if(rkn == (*pkn)->RECHTS)
            conc[1] = NULL;
        else
            {
            adr[1] = (*pkn)->RECHTS->RECHTS;
            conc[1] = "*\1";
            }
        *pkn = vopb(*pkn,conc);
        wis(adr[6]);
        return TRUE;
        }
    else
        {
        if(PLOBJ(rkn) == IM && RAT_NEG_COMP(lkn))
            {
            conc[0] = "(\2*\3)";
            adr[2] = _qmaalmineen(lkn);
            adr[3] = _qmaalmineen(rkn);
            if(rkn == (*pkn)->RECHTS)
                conc[1] = NULL;
            else
                {
                adr[1] = (*pkn)->RECHTS->RECHTS;
                conc[1] = "*\1";
                }
            *pkn = vopb(*pkn,conc);
            wis(adr[2]);
            wis(adr[3]);
            return TRUE;
            }
        else
            return FALSE;
        }
    }
else
    return FALSE;
/*
return TRUE;
*/
}

static void numboom(ppsk pkn,psk lknoop,const char *conc[])
{
if(lknoop == (*pkn)->LINKS)
    *pkn = vopb(*pkn,conc+2);
else
    {
    conc[0] = hekje1;
    adr[1] = (*pkn)->LINKS->LINKS;
    *pkn = vopb(*pkn,conc);
    }
}

/*
static int unevenDenominator(psk kn)
    {
    unsigned char *p = POBJ(kn);
    return (p[strlen((char*)p)-1] - '0') & 1;
    }
*/

static int substmacht(ppsk pkn)
{

static const char *conc[] = {NULL,NULL,NULL,NULL};

Qgetal iexponent,
hiexponent;

psk lknoop,rknoop;
if(!is_op(rknoop = (*pkn)->RECHTS))
    {
    if(RAT_NUL(rknoop))
        {
        replace(pkn,&eenk);
        return TRUE;
        }
    if(IS_EEN(rknoop))
        {
        *pkn = linkertak(*pkn);
        return TRUE;
        }
    }

if(is_op(lknoop = (*pkn)->LINKS))
    {
    return FALSE;
    }

if(RAT_NUL(lknoop) || IS_EEN(lknoop))
    {
    *pkn = linkertak(*pkn);
    return TRUE;
    }

if(is_op(rknoop) || !RATIONAAL_COMP(rknoop))
    {
    return FALSE;
    }

if(RATIONAAL_COMP(lknoop))
    {
    if(RAT_NEG_COMP(rknoop) && abseen(rknoop))
        {
        conc[2] = hekje6;
        adr[6] = _q_qdeel(&eenk,lknoop);
        numboom(pkn,lknoop,conc);
        wis(adr[6]);
        return TRUE;
        }
    else
        if(RAT_NEG_COMP(lknoop) && RAT_RAT_COMP(rknoop))
            {
#if 0 /* Bart 19980331 Dit ziet er raar uit! */
            if(unevenDenominator(rknoop))
                /* (-3/4)^5/3  -->  -1*(-3/4*-1)^5/3 */
                conc[2]="-1*(\2*-1)^\3";
            else
                {
                return TRUE;
                }
                /* (-3/4)^5/6  -->  (-3/4*-1)^5/6*i^(2*5/6) */
            /*    conc[2]="(\2*-1)^\3*i^(2*\3)";*/
            /* notice: according to this algorithm,
                 f(x) = {(-7)^x | x in R} is not continuous !
               However, it would be distressing to return
               (-1)^1/3 = i^2/3
               instead of
               (-1)^1/3 = -1
               Even worse, (-1*i)^1/3 would result in i, whereas
                           ( 1*i)^1/3 would result in i^1/3, which
               is not the complex conjugate of i.
               With the chosen algorithm, we have
               (-1*i)^1/3 = i^1/3
               ( 1*i)^1/3 = i^1/3
               and
               (-1*i)^5/6 = i^5/3*i^5/6 = i^15/6
               ( 1*i)^5/6 =               i^ 5/6
               which is still undesirable, as it leaves (-i)^5/6+i^5/6
               with an imaginary part.
            */
            adr[2] = lknoop;
            adr[3] = rknoop;
            numboom(pkn,lknoop,conc);
#endif
            return TRUE;
            }
        else
            {
            /* hier ontbreekt n^m, met m > 2.
               Dit wordt in casemacht behandeld. */
            return FALSE;
            }
    }

if(PLOBJ(lknoop) == IM)
    {
    if(_qvergelijk(rknoop,&nulk) & MINUS)
        { /* i^-n -> -i^n */
          /* -i^-n -> i^n */
        conc[0] = "(\2^\3)";
        adr[2] = _qmaalmineen(lknoop);
        adr[3] = _qmaalmineen(rknoop);
        conc[1] = NULL;
        *pkn = vopb(*pkn,conc);
        wis(adr[2]);
        wis(adr[3]);
        return TRUE;
        }
    else if(_qvergelijk(&tweek,rknoop) & (QNUL|MINUS))
        {
        iexponent = _qmodulo(rknoop,&vierk);
        if(iexponent->ops & QNUL)
            replace(pkn,&eenk);
        else
            {
            int teken;
            teken = _qvergelijk(iexponent,&tweek);
            if(teken & QNUL)
                replace(pkn,&mineenk);
            else
                {
                conc[0] = "(\2^";
                adr[2] = lknoop;
                if(teken & MINUS)
                    conc[2] = ")";
                else
                    {
                    hiexponent = iexponent;
                    iexponent = _qplus(hiexponent,&mintweek);
                    wis(hiexponent);
                    conc[2] = "*-1)";
                    }
                conc[1] = hekje6;
                adr[6] = iexponent;
                *pkn = vopb(*pkn,conc);
                }
            }
        wis(iexponent);
        return TRUE;
        }
    }
return FALSE;
}

static int substlog(ppsk pkn)
{
static const char *conc[] = {NULL,NULL,NULL,NULL};
psk lknoop,rknoop;
if(is_op(rknoop = (*pkn)->RECHTS))
    {
    if(!vgl((*pkn)->LINKS,rknoop))
        {
        replace(pkn,&eenk);
        return TRUE;
        }
    else
        return FALSE;
    }
if(is_op(lknoop = (*pkn)->LINKS))
    return FALSE;

if(RATIONAAL_COMP(lknoop) && RATIONAAL_COMP(rknoop))
	{
	if(_qvergelijk(rknoop,lknoop) & QNUL)
		{
		replace(pkn,&eenk);
		return TRUE;
		}
	}
else if(!vgl((*pkn)->LINKS,rknoop))
    {
    replace(pkn,&eenk);
    return TRUE;
    }

if(IS_EEN(rknoop))
    {
    replace(pkn,&nulk);
    return TRUE;
    }
else
    {
    if(RATIONAAL_COMP(rknoop))
        {
        if(_qvergelijk(rknoop,&nulk) & MINUS)
            {
            /* (nL-m = i*pi/eLn+nLm)  */
            adr[1] = lknoop;
            adr[2] = rknoop;
            *pkn = opb(*pkn,"(i*pi*e\016\1^-1+\1\016(-1*\2))",NULL);
            return TRUE;
            }
        else if(RATIONAAL(lknoop))
            {
            if(_qvergelijk(lknoop,&eenk) & MINUS)
                {
                /* (1/n)Lm = -1*nLm */
                adr[1] = rknoop;
                conc[0] = "(-1*";
                conc[1] = hekje6;
                adr[6] = _q_qdeel(&eenk,lknoop);
                conc[2] = "L\1)";
                *pkn = vopb(*pkn,conc);
                wis(adr[6]);
                return TRUE;
                }
            else if(_qvergelijk(lknoop,rknoop) & MINUS)
                {
                /* nLm = 1+nL(m/n) */
                conc[0] = "(1+\1\016";
                if(lknoop == rknoop)
                    rknoop = (*pkn)->RECHTS = prive(rknoop);
                adr[1] = lknoop;
                conc[1] = hekje6;
                adr[6] = _q_qdeel(rknoop,lknoop);
                conc[2] = ")";
                *pkn = vopb(*pkn,conc);
                wis(adr[6]);
                return TRUE;
                }
            else if(_qvergelijk(rknoop,&eenk) & MINUS)
                {
                /* nLm = -1+nL(m*n) */
                conc[0] = "(-1+\1\016";
                if(lknoop == rknoop)
                    rknoop = (*pkn)->RECHTS = prive(rknoop);
                adr[1] = lknoop;
                conc[1] = hekje6;
                adr[6] = _qmaal(rknoop,lknoop);
                conc[2] = ")";
                *pkn = vopb(*pkn,conc);
                wis(adr[6]);
                return TRUE;
                }
            }
        }
    }
return FALSE;
}

static int substdiff(ppsk pkn)
{
static const char *conc[] = {NULL,NULL,NULL,NULL};
psk lknoop,rknoop;
lknoop = (*pkn)->LINKS;
rknoop = (*pkn)->RECHTS;
if(RATIONAAL_COMP(lknoop) && RATIONAAL_COMP(rknoop))
    {
    conc[2] = hekje5;
    adr[5] = copievan(&nulk);
    numboom(pkn,lknoop,conc);
    wis(adr[5]);
    return TRUE;
    }
else
    {
    if(is_constant(lknoop) || is_constant(rknoop))
        {
        replace(pkn,&nulk);
        return TRUE;
        }
    else
        {
        if(!vgl(lknoop,rknoop))
            {
            replace(pkn,&eenk);
            return TRUE;
            }
        else
            if(  (  kop(rknoop) == FUN
                 || !is_op(rknoop)
                 )
              && is_afhankelyk_van(lknoop,rknoop)
              )
                return TRUE;
            else
                if(!is_op(rknoop))
                    {
                    replace(pkn,&nulk);
                    return TRUE;
                    }
        }
    }
return FALSE;
}


#if JMP /*Bart 20030410: Often no need for polling in multithreaded apps.*/
#include <windows.h>
#include <dde.h>
    static void PeekMsg(void)
    {
    static MSG msg;
#if 0
    PeekMessage(&msg,NULL,0,0,PM_REMOVE/*PM_NOREMOVE*/);
#else
    while(PeekMessage(&msg,NULL,WM_PAINT,/*WM_MOUSELAST*/WM_DDE_LAST,PM_REMOVE))
            {
#if JMP
            if(msg.message == WM_QUIT)
                    {
#if defined __WIN32__ || defined _WIN32
                    PostThreadMessage(GetCurrentThreadId(), WM_QUIT,0,0L);
#else
                    PostAppMessage(GetCurrentTask(),WM_QUIT,0,0L);
#endif
                    longjmp(jumper,1);
                    }
#endif
            TranslateMessage(&msg);        /* Translates virtual key codes */
            DispatchMessage(&msg);        /* Dispatches message to window*/
            }
#endif
    }
#endif

/*
Iterative handling of LUCHT operator in evalueer.
Can now handle very deep structures without stack overflow
*/
static void handleLUCHT(ppsk pkn)
    { /* assumption: (kop(*pkn) == LUCHT) && !((*pkn)->flgs & KLAAR) */
    static psk hulp;
    psk luchtknoop = *pkn;
    psk next;
    ppsk pluchtknoop = pkn;
    while(kop(luchtknoop->RECHTS) == LUCHT && !(luchtknoop->RECHTS->flgs & KLAAR))
        {
        evalueer(&(luchtknoop->LINKS));
        if  (  !is_op(hulp=luchtknoop->LINKS)
#if COMPILE
            && !RPOBJ(hulp)
#else
            && !(hulp->u.obj)
#endif
            && !HAS_UNOPS(hulp)
            )
            {
            luchtknoop = *pluchtknoop = rechtertak(luchtknoop);
            }
        else
            {
            pluchtknoop = &(luchtknoop->RECHTS);
            luchtknoop = luchtknoop->RECHTS;
            }
        if(dubbelgebruikt(luchtknoop))
            {
            decgebruik(luchtknoop);
            hulp = new_operator_like(luchtknoop);
            /*hulp = (psk)bmalloc(/ *__LINE__,* /sizeof(kknoop));*/
#if !W32
            hulp->flgs = luchtknoop->flgs;
#endif
            hulp->ops = luchtknoop->ops & ~OPGEBRUIKT;
            hulp->LINKS = zelfde_als_w(luchtknoop->LINKS);
            hulp->RECHTS = zelfde_als_w(luchtknoop->RECHTS);
            luchtknoop = *pluchtknoop = hulp;
            }
        }
    evalueer(&luchtknoop->LINKS);
    evalueer(&luchtknoop->RECHTS);
    if  (  !is_op(hulp=luchtknoop->LINKS)
#if COMPILE
        && !RPOBJ(hulp)
#else
        && !(hulp->u.obj)
#endif
        && !HAS_UNOPS(hulp)
        )
        {
        *pluchtknoop = rechtertak(luchtknoop);
        }
    else if (  !is_op(luchtknoop->RECHTS)
#if COMPILE
            && !RPOBJ(luchtknoop->RECHTS)
#else
            && !(luchtknoop->RECHTS->u.obj)
#endif
            && !HAS_UNOPS(luchtknoop->RECHTS)
            )
        {
        *pluchtknoop = linkertak(luchtknoop);
        }
    luchtknoop = *pkn;
    if(kop(luchtknoop) == LUCHT)
        {
        if(  !is_op(luchtknoop->RECHTS)
#if COMPILE
          && !RPOBJ(luchtknoop->RECHTS)
#else
          && !(luchtknoop->RECHTS->u.obj)
#endif
          && !HAS_UNOPS(luchtknoop->RECHTS)
          )
            {
            *pkn = linkertak(luchtknoop);
            }
        luchtknoop = *pkn;
        while(kop(luchtknoop) == LUCHT)
            {
            next = luchtknoop->RECHTS;
            rechtsbrengen(luchtknoop);
            if(next->flgs & KLAAR)
                break;
            luchtknoop = next;
            luchtknoop->flgs |= KLAAR;
            }
        }
    }

/*
Iterative handling of KOMMA operator in evalueer.
Can now handle very deep structures without stack overflow
*/
static void handleKOMMA(ppsk pkn)
    { /* assumption: (kop(*pkn) == KOMMA) && !((*pkn)->flgs & KLAAR) */
    static psk hulp;
    psk kommaknoop = *pkn;
    psk next;
    ppsk pkommaknoop;
    while(kop(kommaknoop->RECHTS) == KOMMA && !(kommaknoop->RECHTS->flgs & KLAAR))
        {
        evalueer(&(kommaknoop->LINKS));
        pkommaknoop = &(kommaknoop->RECHTS);
        kommaknoop = kommaknoop->RECHTS;
        if(dubbelgebruikt(kommaknoop))
            {
            decgebruik(kommaknoop);
            hulp = new_operator_like(kommaknoop);
            /*hulp = (psk)bmalloc(/ *__LINE__,* /sizeof(kknoop));*/
#if !W32
            hulp->flgs = kommaknoop->flgs;
#endif
            hulp->ops = kommaknoop->ops & ~OPGEBRUIKT;
            hulp->LINKS = zelfde_als_w(kommaknoop->LINKS);
            hulp->RECHTS = zelfde_als_w(kommaknoop->RECHTS);
            kommaknoop = *pkommaknoop = hulp;
            }
        }
    evalueer(&kommaknoop->LINKS);
    evalueer(&kommaknoop->RECHTS);
    kommaknoop = *pkn;
    while(kop(kommaknoop) == KOMMA)
        {
        next = kommaknoop->RECHTS;
        rechtsbrengen(kommaknoop);
        if(next->flgs & KLAAR)
            break;
        kommaknoop = next;
        kommaknoop->flgs |= KLAAR;
        }
    }

static int evalueer(ppsk pkn)
{
static psk hulp;
sk lkn;
while(!((*pkn)->flgs & KLAAR))
    {
#if WRITETRACE
    writeTrace(*pkn);
#endif
    switch(kop(*pkn))
        {
        case MATCH : case EN : case OF :
            lkn = **pkn;
            if(dubbelgebruikt(&lkn))
                {
                decgebruik(*pkn);
                lkn.LINKS = zelfde_als_w(lkn.LINKS);
                lkn.RECHTS = zelfde_als_w(lkn.RECHTS);
                }
            else
                pskfree(*pkn);
            switch(kop(&lkn))
                {
                case MATCH :
                    if(evalueer(&(lkn.LINKS)) == TRUE)
                        {
						if(lkn.flgs & ATOOM)
							{
							if(!is_op(lkn.LINKS) && stringmatch(0,POBJ(lkn.LINKS),lkn.RECHTS) & TRUE)
								*pkn = _linkertak(&lkn);
							else
                                {
                                if(is_op(lkn.LINKS))
                                    {
                                    printf("!stringmatch:<");result(&lkn);printf(">\n");
                                    getchar();
                                    }
								*pkn = _flinkertak(&lkn);
                                }
							}
						else
							{
							if(match(0,lkn.LINKS,lkn.RECHTS,NULL) & TRUE)
								*pkn = _linkertak(&lkn);
							else
								*pkn = _flinkertak(&lkn);
							}
                        }
                    else
                        {
                        *pkn = _linkertak(&lkn);
                        }
                    continue;
                case EN :
                    if(evalueer(&(lkn.LINKS)))
                        *pkn = _rechtertak(&lkn);/* TRUE of FENCE */
                    else
                        *pkn = _linkertak(&lkn);/* FAAL */
                    continue;
                default :
                    if(!evalueer(&(lkn.LINKS)))
                        *pkn = _rechtertak(&lkn);/* FAAL */
                    else
                        *pkn = _fencelinkertak(&lkn);/* FENCE of TRUE */
                    continue;
                }
        default :
            if(!is_op(*pkn))
    /*        case 0 :        */
                {
                psk adr;
                if(naamwoord_w(*pkn,&adr))
                    {
                    wis(*pkn);
                    *pkn = adr;
                    }
                else
                    {
                    if(dubbelgebruikt(*pkn))
                        {
                        decgebruik(*pkn);
                        *pkn = icopievan(*pkn);
                        }
                    (*pkn)->flgs |= KLAAR;
                    (*pkn)->flgs ^= SUCCES;
                    }
                continue;
                }
            else
                {
                if(dubbelgebruikt(*pkn))
                    {
                    decgebruik(*pkn);
                    hulp = new_operator_like(*pkn);
                    /*hulp = (psk)bmalloc(/ *__LINE__,* /sizeof(kknoop));*/
#if !W32
                    hulp->flgs = (*pkn)->flgs;
#endif
                    hulp->ops = (*pkn)->ops & ~OPGEBRUIKT;
                    hulp->LINKS = zelfde_als_w((*pkn)->LINKS);
                    hulp->RECHTS = zelfde_als_w((*pkn)->RECHTS);
                    *pkn = hulp;
                    }
                }
        }
    (*pkn)->flgs |= KLAAR;
    switch(kop(*pkn))
        {
        case WORDT :
#if COMPILE
            evalueer(&((*pkn)->LINKS));
#if MACRO
            hulp=(*pkn)->LINKS;
            if(is_op(hulp) /* 30 juli 1993 */
            || RPOBJ(hulp))
#else
            if(is_op((*pkn)->LINKS) /* 30 juli 1993 */
            || RPOBJ((*pkn)->LINKS))
#endif
#else
            evalueer(&((*pkn)->LINKS));
            if(is_op((*pkn)->LINKS) /* 30 juli 1993 */
            || (*pkn)->LINKS->u.obj)
#endif
                {
                if(assign(pkn))
                    *pkn = linkertak(*pkn);
                else
                    *pkn = flinkertak(*pkn);
                }
            continue;
        case DOT :
            {
            psk adr;
            evalueer(&((*pkn)->LINKS));
            evalueer(&((*pkn)->RECHTS));
            if((*pkn)->flgs & INDIRECT)
                {
                if(naamwoord_w(*pkn,&adr))
                    {
                    wis(*pkn);
                    *pkn = adr;
                    }
                else
                    {
                    if(dubbelgebruikt(*pkn))
                        {
                        decgebruik(*pkn);
                        *pkn = icopievan(*pkn);
                        }
                    (*pkn)->flgs |= KLAAR;
                    (*pkn)->flgs ^= SUCCES;
                    }
                }
            continue;
            }
        case KOMMA :
            handleKOMMA(pkn);/* do not recurse, iterate! */
            /*
            evalueer(&((*pkn)->LINKS));
            evalueer(&((*pkn)->RECHTS));
            rechtsbrengen(*pkn);
            */
            continue;
        case LUCHT :
            handleLUCHT(pkn);/* do not recurse, iterate! */
            continue;
        case PLUS :
            if(evalueer(&((*pkn)->LINKS)) == TRUE &&
               evalueer(&((*pkn)->RECHTS)) == TRUE)
                {
                if(  plus_samenvoegen_of_sorteren(pkn)
#if SLOWPLUS
                  || complic_term(pkn)
#endif
                  )
                    ;
                }
            else
                (*pkn)->flgs ^= SUCCES;
            continue;
        case MAAL :
            if(evalueer(&((*pkn)->LINKS)) == TRUE &&
               evalueer(&((*pkn)->RECHTS)) == TRUE)
                {
                if(  rechtsbrengen(*pkn)
                  || substmaal(pkn)
                  || maal_samenvoegen_of_sorteren(pkn)
                  )
                    ;
                }
            else
                (*pkn)->flgs ^= SUCCES;
            continue;
        case EXP :
            if(evalueer(&((*pkn)->LINKS)) == TRUE &&
               evalueer(&((*pkn)->RECHTS)) == TRUE)
                {
                if(  stapelmacht(pkn)     /* (a^b)^c->a^(b*c)          */
                  || substmacht(pkn)       /* 0^a 1^a a^0 a^1 n^-1 i^n     */
                  || machtbuitenhaakjes(pkn) /* (a+b)^(c+n)->(a+b)^c*(a+b)^n */
                                             /* (a*b)^c->a^c*b^c       */
                  || casemacht(pkn)
                  || try_le_elq(f4,pkn)
                  )
                    ;
                }
            else
                (*pkn)->flgs ^= SUCCES;
            continue;
        case LOG :
            if(evalueer(&((*pkn)->LINKS)) == TRUE &&
               evalueer(&((*pkn)->RECHTS)) == TRUE)
                {
                if(  substlog(pkn)
                  || try_le_elq(f5,pkn)
                  )
                    ;
                }
            else
                (*pkn)->flgs ^= SUCCES;
            continue;
        case DIF :
            if(evalueer(&((*pkn)->LINKS)) == TRUE &&
               evalueer(&((*pkn)->RECHTS)) == TRUE)
                {
                if(!substdiff(pkn))
                    {
                    if(!differentieren(pkn))
                        (*pkn)->flgs ^= SUCCES;/*???*/
                    }
                }
            else
                (*pkn)->flgs ^= SUCCES;
            continue;
        case FUN :
        case FUU :
            evalueer(&((*pkn)->LINKS));
            if(kop(*pkn) == FUN)
                {
                evalueer(&((*pkn)->RECHTS));
                }
            rechtsbrengen(*pkn);
            switch(functies(pkn))
                {
/*
typedef enum    {function_fail
                ,built_in_function_ok
                ,user_function_ok
                ,user_object_method_ok
                ,builtin_object_builtin_method_ok
                ,builtin_object_user_method_ok
                } function_return_type;
*/
/*                case 0:*/
                case function_fail:
                    (*pkn)->flgs ^= SUCCES;
                    break;
                case built_in_function_ok:
                case builtin_object_builtin_method_ok:
                    break;
/*                case TRUE+TRUE:*/
                case user_function_ok:
                    if(kop(*pkn) == DOT)
                        {
                        psh((*pkn)->LINKS,&nulk,NULL);
                        evalueer(pkn);
                        pop((*pkn)->LINKS);
                        dopb(pkn,(*pkn)->RECHTS);
                        }
                    deleteNode(&argk);
                    break;
/*                case TRUE+TRUE+TRUE:*/
                case user_object_method_ok:
                    if(kop(*pkn) == DOT)
                        {
                        psh((*pkn)->LINKS,&nulk,NULL);
                        evalueer(pkn);
                        pop((*pkn)->LINKS);
                        dopb(pkn,(*pkn)->RECHTS);
                        }
                    deleteNode(&argk);
                    deleteNode(&selfkn);
                    break;
                case builtin_object_user_method_ok:
                    if(kop(*pkn) == DOT)
                        {
                        psh((*pkn)->LINKS,&nulk,NULL);
                        evalueer(pkn);
                        pop((*pkn)->LINKS);
                        dopb(pkn,(*pkn)->RECHTS);
                        }
                    deleteNode(&argk);
                    deleteNode(&selfkn);
                    deleteNode(&Selfkn);
                    break;
                }
            continue;
        case STREEP :
            if(dummy_op == WORDT)
                {
                psk old = *pkn;
                *pkn = (psk)bmalloc(__LINE__,sizeof(objectknoop));
                ((typedObjectknoop*)(*pkn))->refcount = 0L;
                UNSETCREATEDWITHNEW((typedObjectknoop*)*pkn);
                UNSETBUILTIN((typedObjectknoop*)*pkn);
                (*pkn)->LINKS = subboomcopie(old->LINKS);
                (*pkn)->RECHTS = subboomcopie(old->RECHTS);
                /*(*pkn)->flgs |= dummy_flgs;*/
                wis(old);
                }
            /*else*/
                {
#if W32
                (*pkn)->flgs &= (~OPERATOR & ~KLAAR);
#else
                (*pkn)->flgs &= ~KLAAR;
                (*pkn)->ops &= ~OPERATOR;
#endif
                (*pkn)->ops |= dummy_op;
                (*pkn)->flgs |= dummy_flgs;
                }
            continue;
        }
    }
#if JMP
PeekMsg();
#endif
if((*pkn)->flgs & SUCCES)
    {
    return TRUE;
    }
else
    {
    return (*pkn)->flgs & FENCE;
    }
}




#if INTSCMP
static int intscmp(long *s1,long *s2) /* deze routine geeft verschillende resultaten
                                  afhankelijk van BIGENDIAN */
{
#ifdef vax
long *ss1,*ss2;
ss1 = s1;
ss2 = s2;
while(*ss1 > 0x00FFFFFFL)
    {
    if(*ss1 != *ss2)
        {
        if(*ss1 < *ss2)
            return -1;
        else
            return 1;
        }
    ss1++;
    ss2++;
    }
if(*ss1 != *ss2)
    {
    if(*ss1 < *ss2)
        return -1;
    else
        return 1;
    }
else
    return 0;
#else
while(*((char*)s1 + 3))
    {
    if(*s1 != *s2)
        {
        if(*s1 < *s2)
            return -1;
        else
            return 1;
        }
    s1++;
    s2++;
    }
if(*s1 != *s2)
    {
    if(*s1 < *s2)
        return -1;
    else
        return 1;
    }
else
    return 0;
#endif
}
#endif


static void init_ruimte(void)
{
p4start = (byte4*)malloc((size_t)(PROMILLAGE4*sizeof(byte4)*KILOKNOPEN));
if(p4start == NULL)
    {
    exit(-1);
    }
p4end = p4start+(size_t)(PROMILLAGE4*KILOKNOPEN);
for(p4 = p4start;
    p4 < p4end - 1;
    p4++)
    p4->u.p = p4+1;
p4->u.p = NULL;
p4 = p4start;
p8start = (byte8*)malloc((size_t)(PROMILLAGE8*sizeof(byte8)*KILOKNOPEN));
if(p8start == NULL)
    {
    exit(-1);
    }
p8end = p8start+(size_t)(PROMILLAGE8*KILOKNOPEN);
for(p8 = p8start;
    p8 < p8end - 1;
    p8++)
    p8->u.p = p8+1;
p8->u.p = NULL;
p8 = p8start;

p12start = (byte12*)malloc((size_t)(PROMILLAGE12*sizeof(byte12)*KILOKNOPEN));

if(p12start == NULL)
    {
    exit(-1);
    }
p12end = p12start+(size_t)(PROMILLAGE12*KILOKNOPEN);
for(p12 = p12start;
    p12 < p12end - 1;
    p12++)
    p12->u.p = p12+1;
p12->u.p = NULL;
p12 = p12start;

p16start = (byte16*)malloc((size_t)(PROMILLAGE16*sizeof(byte16)*KILOKNOPEN));

if(p16start == NULL)
    {
    exit(-1);
    }
p16end = p16start+(size_t)(PROMILLAGE16*KILOKNOPEN);
for(p16 = p16start;
    p16 < p16end - 1;
    p16++)
    p16->u.p = p16+1;
p16->u.p = NULL;
p16 = p16start;

#ifdef _4_5
p20start = (byte20*)malloc((size_t)(PROMILLAGE20*sizeof(byte20)*KILOKNOPEN));

if(p20start == NULL)
    {
    exit(-1);
    }
p20end = p20start+(size_t)(PROMILLAGE20*KILOKNOPEN);
for(p20 = p20start;
    p20 < p20end - 1;
    p20++)
    p20->u.p = p20+1;
p20->u.p = NULL;
p20 = p20start;

p24start = (byte24*)malloc((size_t)(PROMILLAGE24*sizeof(byte24)*KILOKNOPEN));

if(p24start == NULL)
    {
    exit(-1);
    }
p24end = p24start+(size_t)(PROMILLAGE24*KILOKNOPEN);
for(p24 = p24start;
    p24 < p24end - 1;
    p24++)
    p24->u.p = p24+1;
p24->u.p = NULL;
p24 = p24start;
#endif

#if 0
#ifdef vax
printf("p4 %x - %x p8 %x - %x p12 %x - %x p16 %x - %x p20 %x - %x p24 %x - %x\n",
#else
printf("p4 %p - %p p8 %p - %p p12 %p - %p p16 %p - %p p20 %p - %p p24 %p - %p\n",
#endif
p4start,p4end,
p8start,p8end,
p12start,p12end,
p16start,p16end,
p20start,p20end,
p24start,p24end);
#endif
}

void startProc(startStruct * init)
    {
    int tel;
    if(init)
        {
        if(init->WinIn)
            {
#if MICROSOFT_WINDOWS_API
            WinIn = init->WinIn;
#endif
            }
        if(init->WinOut)
            {
#if MICROSOFT_WINDOWS_API
            WinOut = init->WinOut;
#endif
            }
        if(init->WinFlush)
            {
#if MICROSOFT_WINDOWS_API
            WinFlush = init->WinFlush;
#endif
            }
        }
    for(tel = 0;tel<256;variabelen[tel++] = NULL);
    init_ruimte();
    init_opcode();
    anker = NULL;
    fpi = stdin;
    fpo = stdout;

    argk.flgs = KLAAR | SUCCES;
#if !W32
    argk.ops = 0;
#endif
#if COMPILE
    argk.u.Lobj = O('a','r','g');
#else
    argk.u.lobj = O('a','r','g');
#endif

    selfkn.flgs = KLAAR | SUCCES;
#if !W32
    selfkn.ops = 0;
#endif
#if COMPILE
    selfkn.u.Lobj = O('i','t','s');
#else
    selfkn.u.lobj = O('i','t','s');
#endif

    Selfkn.flgs = KLAAR | SUCCES;
#if !W32
    Selfkn.ops = 0;
#endif
#if COMPILE
    Selfkn.u.Lobj = O('I','t','s');
#else
    Selfkn.u.lobj = O('I','t','s');
#endif

#if 0
    diek.flgs = KLAAR | SUCCES;
#if !W32
    diek.ops = 0;
#endif
#if COMPILE
    diek.u.Lobj = O('d','i','e');
#else
    diek.u.lobj = O('d','i','e');
#endif
#endif

    nilk.flgs = KLAAR | SUCCES | IDENT
#if COMPILE
        | RESOLVED
#endif
        ;
#if !W32
    nilk.ops = 0;
#endif
#if COMPILE
    variabelen[0] = (vars*)bmalloc(__LINE__,sizeof(vars));
    variabelen[0]->Prev = NULL;
    variabelen[0]->next = NULL;
    variabelen[0]->Refcount = 1;
#ifdef PVNAME
    variabelen[0]->vname = (unsigned char*)"\0\0\0\0";
#else
    variabelen[0]->u.Lobj = 0L;
#endif
    variabelen[0]->n = 0;
    variabelen[0]->selector = 0;
    variabelen[0]->pvaria = NULL;
    nilk.u.var = variabelen[0];
#else
    nilk.u.lobj = 0L;
#endif


#if W32
    nulk.flgs = KLAAR | SUCCES | IDENT | QGETAL | QNUL;
#else
    nulk.flgs = KLAAR | SUCCES | IDENT;
    nulk.ops = QGETAL | QNUL;
#endif
#if COMPILE
    nulk.u.Lobj = 0L;
    nulk.u.Obj = '0';
#else
    nulk.u.lobj = 0L;
    nulk.u.obj = '0';
#endif

#if COMPILE
    eenk.u.Lobj = 0L;
    eenk.u.Obj = '1';
#else
    eenk.u.lobj = 0L;
    eenk.u.obj = '1';
#endif
#if W32
    eenk.flgs = KLAAR | SUCCES | IDENT | QGETAL;
#else
    eenk.flgs = KLAAR | SUCCES | IDENT;
    eenk.ops = QGETAL;
#endif
#if COMPILE
#else
    *(&(eenk.u.obj)+1) = 0;
#endif

#if COMPILE
    mintweek.u.Lobj = 0L;
    mintweek.u.Obj = '2';
#else
    mintweek.u.lobj = 0L;
    mintweek.u.obj = '2';
#endif
#if W32
    mintweek.flgs = KLAAR | SUCCES | QGETAL | MINUS;
#else
    mintweek.flgs = KLAAR | SUCCES;
    mintweek.ops = QGETAL | MINUS;
#endif
#if COMPILE
#else
    *(&(mintweek.u.obj)+1) = 0;
#endif

#if COMPILE
    mineenk.u.Lobj = 0L;
    mineenk.u.Obj = '1';
#else
    mineenk.u.lobj = 0L;
    mineenk.u.obj = '1';
#endif
#if W32
    mineenk.flgs = KLAAR | SUCCES | QGETAL | MINUS;
#else
    mineenk.flgs = KLAAR | SUCCES;
    mineenk.ops = QGETAL | MINUS;
#endif
#if COMPILE
#else
    *(&(mineenk.u.obj)+1) = 0;
#endif

#if COMPILE
    tweek.u.Lobj = 0L;
    tweek.u.Obj = '2';
#else
    tweek.u.lobj = 0L;
    tweek.u.obj = '2';
#endif
#if W32
    tweek.flgs = KLAAR | SUCCES | QGETAL;
#else
    tweek.flgs = KLAAR | SUCCES;
    tweek.ops = QGETAL;
#endif
#if COMPILE
#else
    *(&(tweek.u.obj)+1) = 0;
#endif

#if COMPILE
    vierk.u.Lobj = 0L;
    vierk.u.Obj = '4';
#else
    vierk.u.lobj = 0L;
    vierk.u.obj = '4';
#endif
#if W32
    vierk.flgs = KLAAR | SUCCES | QGETAL;
#else
    vierk.flgs = KLAAR | SUCCES;
    vierk.ops = QGETAL;
#endif
#if COMPILE
#else
    *(&(vierk.u.obj)+1) = 0;
#endif


#if 1
    m0 = opb(m0,"?*(%+%)^~/#>1*?" , NULL);
    m1 = opb(m1,"?*(%+%)*?" , NULL);
    f0 = opb(f0,
        "((\177g,\177k).!arg:?\177g*((%+%)^~/#>1:?arg)*?\177k&!\177g*",
        "\177pow$!arg*!\177k)",NULL);
    f1 = opb(f1,
        "((\177g,\177h,\177i).!arg:?\177g*(%?\177h+%?\177i)*",
        "?arg&!\177g*!\177h*!arg+!\177g*!\177i*!arg)",NULL);
    f4 = opb(f4,
        "(\177l.!arg:?\177l^(?+?*!\177l\016?*?+?)&\177a$!arg|!arg:e^",
        "((?+?#\177l*i*pi+?&`!\177b|?*(pi|i)*?*(?+?*(pi|i)*?+?:%+%)*?&\177c:?\177l):",
        "?arg)&e^!\177l$!arg*!\177l)",NULL);
    f5 = opb(f5,
        "(\177l.!arg:?\177l\016(?*!\177l^?*?)&\177d$!arg)" , NULL);

#if SLOWPLUS
    f6 = opb(f6,
        "(\177a,\177b,\177c,\177i,\177d.!arg:#?\177a*((i|-i):?\177i)*?\177b+",
        "#?\177c*(-i|i)*!\177b+?\177d&",
        "(!\177a+-1*!\177c)*!\177i*!\177b+!\177d)" , NULL);
/*
    f6 = opb(f6,
                                  "(a,b,c,i,d,f",
                                ".     !arg",
                                    ":   #?a*((i|-i):?i)*?b",
                                      "+ #?c*(-i|i)*!b",
                                      "+ ?d",
                                  "& (!a+-1*!c)*!i*!b+!d)",
                                "|     !arg",
                                    ":   (#?a*((i|-i):?i)*?b + ?f)",
                                      "+ #?c*(-i|i)*!b",
                                      "+ ?d",
                                  "& (!a+-1*!c)*!i*!b+!f+!d)",
                                   NULL);
*/
/*
    f6 = opb(f6,
        "(a,b,c,i,d.!arg:#?a*((i|-i):?i)*?b+",
        "#?c*(-i|i)*!b+?d&",
        "(!a+-1*!c)*!i*!b+!d)" , NULL);
*/
#endif
    startboom_w(&anker ,
        "(cat=((\177w,\177n,\177o,\177l,\177c,\177d,\177p).!arg:((?\177w,",
        "(?\177n,?\177o)|?\177n&():?\177o)|?\177w&():?\177n:?\177o)&(\177l=(.",
        "!arg:%?\177c ?arg&!\177c:((?\177d.?)|?\177d)&()'(? (`=()$\177d|(()$\177d.?",
        ")) ?):?\177p&(!\177w:!\177p&~$(!\177n:!\177p)&!\177c|()) \177l$!arg|()))&(",
        "():!\177w:!\177n|(():!\177w&mem$():?\177w|())&\177l)$(mem$!\177o))),",

        "(out=(.put$!arg:?arg&put$\212&!arg)),",

        "(flt=((e,d,m,s,f).!arg:(~0:?arg,~<0:?d)&(-1*!arg:>0:?arg&-1|1):?s&",
        "10\016!arg:?e+(10\016?m|#&1:?m)&get$(div$(!m+1/2*(1/10^!d:?d),!d),MEM,VAP):",
        "`%?f ?m&str$(!s*!f (!d:~1&\254|) !m \252\261\260\305 !e))),",

        "(\177a=((\177j,\177g,\177h,\177i).!arg:?\177l^(?\177j+?\177g*",
        "!\177l\016?\177h*?\177i+?arg)&!\177l^(!\177j+!arg)*!\177h^(!\177g*!\177i))),"
        ,

        /* \177e \177c of \177f kan aan \177l toegekend worden. */
        "(\177e=((\177j,\177g).!arg:?\177j+?#\177g*i*pi+?arg&1:?\177l",
        "&!\177j+(mod$(1+!\177g,2)+-1)*i*pi+!arg)),",

        "(\177c=(.1+!arg:?arg&1:?\177l&-1+!arg)),",

        "(\177f=(\177j.!arg:?\177j+?#\177l*i*pi+?arg&i^(2*!\177l):",
        "?\177l&!\177j+!arg)),",

        /* als b faalt, dan heeft \177l geen functienaam. f4 faalt dan */
        "(\177b=(!\177l:(<-1|~<1)&\177e|(-1|1/2|-1/2)&\177f):?\177l),",


        "(\177d=((\177j,\177g,\177h).!arg:?\177l\016(?\177j*!\177l^?\177g*",
        "?\177h)&!\177l\016(!\177j*!\177h)+!\177g)),",
#if 0
        "(\177pow=((\177a,\177b,\177c,\177d,\177l,\177s,\177f).!arg:(%?\177a",
        "+%?\177b)^?\177c&0:?\177d&1:?\177f&(\177l=!\177c:>0&!\177s+!\177f*!\177a^",
        "(-1+!\177c:?\177c)*\177pow$(!\177b^!\177d):?\177s&!\177f*!\177c*(1+!\177d:",
        "?\177d)^-1:?\177f&!\177l)&1+!\177c:?\177c&~!\177l&!\177s|!arg)),",
#endif
        "(\177pow=((\177b,\177c,\177d,\177l,\177s,\177f).!arg:(%?\177b+",
        "%?\177c)^?\177d&1:?\177f&(\177s=!\177d:1&0|(!\177f*!\177d*(1+!\177l:?\177l)^",
        "-1:?\177f)*!\177b^!\177l*\177pow$(!\177c^(-1+!\177d:?\177d))+!\177s)&!\177b",
        "^!\177d+!\177c^!\177d+!\177s|!arg)),",
        /*
            (pow=
              b,c,d,l,s,f
            .     !arg:(%?b+%?c)^?d
                & 1:?f
                & ( s
                  =   !d:1&0
                    |     (!f*!d*(1+!l:?l)^-1:?f)
                        * !b^!l
                        * pow$(!c^(-1+!d:?d))
                      + !s
                  )
                & !b^!d+!c^!d+!s
              | !arg
            );
        */
        "(tay=((f,tot,x,fac,cnt,res,R).",
        "(R=!cnt:!tot&!res|!res+(sub$(!x\017!f:?f.!x.0))*((!fac*(!cnt+1:?cnt))",
        ":?fac)^-1*!x^!cnt:?res&!R)&",
        "!arg:(?f,?x,?tot)&(fac=1)&(cnt=0)&((sub$(!f.!x.0)):?res)&!R)),",

        "(ego=(r.sub$(sub$(!arg.(sin.?r).'sin$!r).(cos.?r).'cos$!r))),",

        "(goe=((h,s).sub$(!arg.'(e^?h).",
        "'(-1*(sgn$(-1+i*!h+1:?h):?s)*i*(sin.-1+!s*!h+1:?s)+(cos.!s))))),",

        "(sin=(.i*(-1/2*e^(i*!arg)+1/2*e^(-i*!arg)))),",

        "(cos=(.1/2*(e^(i*!arg)+e^(-i*!arg)))),",

        "(sgn=(.!arg:?#%arg*%+?&sgn$!arg|!arg:<0&-1|1)),",
        "(abs=(.sgn$!arg*!arg)),",

        "(sub=((\177e,\177x,\177v,\177F).(\177F=((\177l,\177r).",
        "(!arg:!\177x&!\177v:?arg|)&!arg:%?\177l_%?\177r&(\177F$!\177l)_",
        "(\177F$!\177r)|!arg))&!arg:(",
        "(?\177e.?\177x.?\177v)|out$str$(UseDotInSub !arg)&get'&`~)&\177F$!\177e)),",
        fct,
        NULL);

#else
    m0 = opb(m0,"?*(%+%)^~/#>1*?" , NULL);
    m1 = opb(m1,"?*(%+%)*?" , NULL);
    f0 = opb(f0,
        "((g,k).!arg:?g*((%+%)^~/#>1:?arg)*?k&!g*",
        "pow$!arg*!k)",NULL);
    f1 = opb(f1,
        "((g,h,i).!arg:?g*(%?h+%?i)*",
        "?arg&!g*!h*!arg+!g*!i*!arg)",NULL);
    f4 = opb(f4,
        "(l.!arg:?l^(?+?*!l\016?*?+?)&a$!arg|!arg:e^",
        "((?+?#l*i*pi+?&`!b|?*(pi|i)*?*(?+?*(pi|i)*?+?:%+%)*?&c:?l):",
        "?arg)&e^!l$!arg*!l)",NULL);
    f5 = opb(f5,
        "(l.!arg:?l\016(?*!l^?*?)&d$!arg)" , NULL);
    startboom_w(&anker ,
        "(cat=((w,n,o,l,c,d,p).!arg:((?w,",
        "(?n,?o)|?n&():?o)|?w&():?n:?o)&(l=(.",
        "!arg:%?c ?arg&!c:((?d.?)|?d)&()'(? (`=()$d|(()$d.?",
        ")) ?):?p&(!w:!p&~$(!n:!p)&!c|()) l$!arg|()))&(",
        "():!w:!n|(():!w&mem$():?w|())&l)$(mem$!o))),",

        "(out=(.put$!arg:?arg&put$\212&!arg)),",

        "(flt=((e,d,m,s,f).!arg:(~0:?arg,~<0:?d)&(-1*!arg:>0:?arg&-1|1):?s&",
        "10\016!arg:?e+(10\016?m|#&1:?m)&get$(div$(!m+1/2*(1/10^!d:?d),!d),MEM,VAP):",
        "`%?f ?m&str$(!s*!f (!d:~1&\254|) !m \252\261\260\305 !e))),",

        "(a=((j,g,h,i).!arg:?l^(?j+?g*",
        "!l\016?h*?i+?arg)&!l^(!j+!arg)*!h^(!g*!i))),"
        ,

        /* e c of f kan aan l toegekend worden. */
        "(e=((j,g).!arg:?j+?#g*i*pi+?arg&1:?l",
        "&!j+(mod$(1+!g,2)+-1)*i*pi+!arg)),",

        "(c=(.1+!arg:?arg&1:?l&-1+!arg)),",

        "(f=(j.!arg:?j+?#l*i*pi+?arg&i^(2*!l):",
        "?l&!j+!arg)),",

        /* als b faalt, dan heeft l geen functienaam. f4 faalt dan */
        "(b=(!l:(<-1|~<1)&e|(-1|1/2|-1/2)&f):?l),",


        "(d=((j,g,h).!arg:?l\016(?j*!l^?g*",
        "?h)&!l\016(!j*!h)+!g)),",
#if 0
        "(pow=((a,b,c,d,l,s,f).!arg:(%?a",
        "+%?b)^?c&0:?d&1:?f&(l=!c:>0&!s+!f*!a^",
        "(-1+!c:?c)*pow$(!b^!d):?s&!f*!c*(1+!d:",
        "?d)^-1:?f&!l)&1+!c:?c&~!l&!s|!arg)),",
#endif
        "(pow=((b,c,d,l,s,f).!arg:(%?b+",
        "%?c)^?d&1:?f&(s=!d:1&0|(!f*!d*(1+!l:?l)^",
        "-1:?f)*!b^!l*pow$(!c^(-1+!d:?d))+!s)&!b",
        "^!d+!c^!d+!s|!arg)),",

        "(tay=((f,tot,x,fac,cnt,res,R).",
        "(R=!cnt:!tot&!res|!res+(sub$(!x\017!f:?f.!x.0))*((!fac*(!cnt+1:?cnt))",
        ":?fac)^-1*!x^!cnt:?res&!R)&",
        "!arg:(?f,?x,?tot)&(fac=1)&(cnt=0)&((sub$(!f.!x.0)):?res)&!R)),",

        "(ego=(r.sub$(sub$(!arg.(sin.?r).'sin$!r).(cos.?r).'cos$!r))),",

        "(goe=((h,s).sub$(!arg.'(e^?h).",
        "'(-1*(sgn$(-1+i*!h+1:?h):?s)*i*(sin.-1+!s*!h+1:?s)+(cos.!s))))),",

        "(sin=(.i*(-1/2*e^(i*!arg)+1/2*e^(-i*!arg)))),",

        "(cos=(.1/2*(e^(i*!arg)+e^(-i*!arg)))),",

        "(sgn=(.!arg:?#%arg*%+?&sgn$!arg|!arg:<0&-1|1)),",
        "(abs=(.sgn$!arg*!arg)),",

        "(sub=((e,x,v,F).(F=((l,r).",
        "(!arg:!x&!v:?arg|)&!arg:%?l_%?r&(F$!l)_",
        "(F$!r)|!arg))&!arg:(?e,?x,?v)&F$!e)),",
        fct,
        NULL);



#endif

#if JMP
    if(setjmp(jumper) != 0)
        return;
#endif
    evalueer(&anker);
}

void endProc(void)
    {
    int err;
/*  stringEval("cat$:? CloseDown ? & CloseDown$ | out$\"No CloseDown function provided, exiting all the same.\"",NULL,&err);*/
    stringEval("cat$:? CloseDown ? & CloseDown$ | ",NULL,&err);
    if(err)
        printf("Error executing CloseDown\n");
    }

/* bracmatmain.c - the text-mode front end for bracmat */
#ifndef BRACMATEMBEDDED

#include <stddef.h>

#if defined ARM
#define COPYRIGHT "\xA9"
#else
#define COPYRIGHT "(c)"
#endif


void mainlus(int argc,char *argv[])
    {
    int err;
    char *mainloop;

#ifdef vax

    struct timeval t1;
    long int spanne;
    tzp.tz_minuteswest = 0;
    tzp.tz_dsttime = 0;

#endif

    mainloop = argc > 1 ? argv[1] :
    "(w=\"11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\\n"
    "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\\n"
    "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\\n"
    "PROVIDE THE PROGRAM \\\"AS IS\\\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\\n"
    "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\\n"
    "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\\n"
    "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\\n"
    "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\\n"
    "REPAIR OR CORRECTION.\\n\")&"
    "(c=\"12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\\n"
    "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\\n"
    "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\\n"
    "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\\n"
    "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\\n"
    "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\\n"
    "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\\n"
    "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\\n"
    "POSSIBILITY OF SUCH DAMAGES.\\n\")&"
    "out$\"\\nBracmat version " VERSION ", build " BUILD " (" DATUM ")\\n"
    "Copyright (C) 2002 Bart Jongejan\\n"
    "Bracmat comes with ABSOLUTELY NO WARRANTY; for details type `!w'.\\n"
    "This is free software, and you are welcome to redistribute it\\n"
    "under certain conditions; type `!c' for details.\\n\\n"
        "\\n\\n{?} get$help { tutorial }\\n{?} )        { stop }\"&"

#if 1 /* May make an error in the timimg due to the time needed for input. */

        "(main=put$\"{?} \"&clk$():?\201&((\"?\"$(get'):(|?&clk$+-1*!\201:?\201&"

#else /* Does not handle multi-line input correctly, */

        "(main=put$\"{?} \"&get'(,STR):?\202&clk$():?\201&((\"?\"$(get$(!\202,MEM)):"
        "(|?&clk$+-1*!\201:?\201&"

#endif

        "put$\"{!} \"&put$!&out$(\"\\n    S  \" str$(div$(!\201,1) \",\" (div$(mod$("
        "!\201*100,100),1):?\201&!\201:<10&0|) !\201) sec))|out$\"\\n    F\")|"
        "out$\"\\n    I\")&"

#if TELMAX

        "bez'&"

#endif

        "!main)&!main";


#if 0
        "(exp=I:?expr&put$\"{?} \"&clk$:?t&(get':?expr|F:?expr)&'$expr:exit|\
        ('$expr:help&get$help|'$expr:|put$\"{!} \"&('$expr:(F&out$\"\\n    F\"|\
        I&out$\"\\n    I\")|put$('$expr:fun_?&_:($|')&'$expr|!expr)&put$\
        \"\\n    S  \"&\"?\"$('$expr)&clk$+-1*!t:?t&out$(str$(div$(!t,1) \",\" \
        (div$(mod$(!t*100,100),1):?t&!t:<10&0|) !t sec))))&!exp)&!exp";
#endif

        stringEval(mainloop,NULL,&err);

#if 0

        for(;;)
            {
            stringInput(mainloop,&anker,4);
            switch(evalueer(&anker))
                {
                case TRUE :
                    if(is_op(anker) || anker->u.obj || HAS_UNOPS(anker))
                        {
                        printf("{!} ");
                        result(anker);
                        insert(&nilk,anker);
                        printf("\n    S");
                        break;
                        }
                    continue;
                case FENCE :
                    printf("\n    I");
                    break;
                default :
                    printf("\n    F");
                    break;
                }
#ifdef vax

            gettimeofday(&t1,&tzp);
            spanne = (t1.tv_sec * 100 + t1.tv_usec / 10000)
                - (t0.tv_sec * 100 + t0.tv_usec / 10000);
            printf("  %ld,%02ld sec",spanne /100, spanne % 100);
            spanne = (clock()-time0)/10000;
            printf(" (%ld,%02ld sec CPU)",spanne /100, spanne % 100);
#else
#ifdef CLOCKS_PER_SEC
            time0 = clock()-time0;
            printf("  %ld,%02d sec",(long)
#ifdef __TURBOC__ /* CLOCKS_PER_SEC == 18.2, Microsoft klaagt over 18.2 */
                ((time0 * (clock_t)10) / (clock_t)182),
#else
                ((long)time0 / (long)CLOCKS_PER_SEC),
#endif
                (int)(
#if CLOCKS_PER_SEC == 100
                (time0 % CLOCKS_PER_SEC)
#else
#ifdef __TURBOC__ /* CLOCKS_PER_SEC == 18.2 */
                ((clock_t)100 * ((time0 * (clock_t)10) % (clock_t)182)) / (clock_t)182
#else
                ((unsigned long)100 * (unsigned long)(time0 % CLOCKS_PER_SEC)) / CLOCKS_PER_SEC
#endif
#endif
                ));
#endif
#endif

#if TELLING
            bezetting();
#endif
#ifdef TELMAX
            printf("  %ld nodes",globalloc);
            printf("  %ld max nodes",maxgloballoc);
            printf("  maxref = %d\n",maxbez /EENKEER);
#else
            printf("\n");
#endif
            }
#endif
}

int main(int argc,char *argv[])
    {
    /*
    int i;
    for(i = 0;i < argc;++i)
        printf("argv[%d](%d)=%s\n",i,strlen(argv[i]),argv[i]);
    */
/*#ifdef __SYMBIAN32__*/
    errorStream = stderr;
/*#endif*/
#if WRITETRACE
    remove("log");
#endif
    startProc(NULL);
    mainlus(argc,argv);
    endProc();
    return 0;
    }

#endif /*#ifndef BRACMATEMBEDDED*/
