summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/slang/slang.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/slang/slang.c')
-rw-r--r--mdk-stage1/slang/slang.c5547
1 files changed, 0 insertions, 5547 deletions
diff --git a/mdk-stage1/slang/slang.c b/mdk-stage1/slang/slang.c
deleted file mode 100644
index 6edc7df37..000000000
--- a/mdk-stage1/slang/slang.c
+++ /dev/null
@@ -1,5547 +0,0 @@
-/* -*- mode: C; mode: fold; -*- */
-/* slang.c --- guts of S-Lang interpreter */
-/* Copyright (c) 1992, 1999, 2001 John E. Davis
- * This file is part of the S-Lang library.
- *
- * You may distribute under the terms of either the GNU General Public
- * License or the Perl Artistic License.
- */
-
-#include "slinclud.h"
-
-#if SLANG_HAS_FLOAT
-# include <math.h>
-#endif
-
-#include "slang.h"
-#include "_slang.h"
-
-#define USE_COMBINED_BYTECODES 0
-
-struct _SLBlock_Type;
-
-typedef struct
-{
- struct _SLBlock_Type *body;
- unsigned int num_refs;
-}
-_SLBlock_Header_Type;
-
-typedef struct
-{
- char *name;
- SLang_Name_Type *next;
- char name_type;
-
- union
- {
- _SLBlock_Header_Type *header; /* body of function */
- char *autoload_filename;
- }
- v;
-#if _SLANG_HAS_DEBUG_CODE
- char *file;
-#endif
-#define SLANG_MAX_LOCAL_VARIABLES 254
-#define AUTOLOAD_NUM_LOCALS (SLANG_MAX_LOCAL_VARIABLES + 1)
- unsigned char nlocals; /* number of local variables */
- unsigned char nargs; /* number of arguments */
-}
-_SLang_Function_Type;
-
-typedef struct
-{
- char *name;
- SLang_Name_Type *next;
- char name_type;
-
- SLang_Object_Type obj;
-}
-SLang_Global_Var_Type;
-
-typedef struct
-{
- char *name;
- SLang_Name_Type *next;
- char name_type;
-
- int local_var_number;
-}
-SLang_Local_Var_Type;
-
-typedef struct _SLBlock_Type
-{
- unsigned char bc_main_type;
- unsigned char bc_sub_type;
- union
- {
- struct _SLBlock_Type *blk;
- int i_blk;
-
- SLang_Name_Type *nt_blk;
- SLang_App_Unary_Type *nt_unary_blk;
- SLang_Intrin_Var_Type *nt_ivar_blk;
- SLang_Intrin_Fun_Type *nt_ifun_blk;
- SLang_Global_Var_Type *nt_gvar_blk;
- SLang_IConstant_Type *iconst_blk;
- SLang_DConstant_Type *dconst_blk;
- _SLang_Function_Type *nt_fun_blk;
-
- VOID_STAR ptr_blk;
- char *s_blk;
- SLang_BString_Type *bs_blk;
-
-#if SLANG_HAS_FLOAT
- double *double_blk; /*literal double is a pointer */
-#endif
- float float_blk;
- long l_blk;
- struct _SLang_Struct_Type *struct_blk;
- int (*call_function)(void);
- }
- b;
-}
-SLBlock_Type;
-
-/* Debugging and tracing variables */
-
-void (*SLang_Enter_Function)(char *) = NULL;
-void (*SLang_Exit_Function)(char *) = NULL;
-/* If non null, these call C functions before and after a slang function. */
-
-int _SLang_Trace = 0;
-/* If _SLang_Trace = -1, do not trace intrinsics */
-static int Trace_Mode = 0;
-
-static char *Trace_Function; /* function to be traced */
-int SLang_Traceback = 0;
-/* non zero means do traceback. If less than 0, do not show local variables */
-
-/* These variables handle _NARGS processing by the parser */
-int SLang_Num_Function_Args;
-static int *Num_Args_Stack;
-static unsigned int Recursion_Depth;
-static SLang_Object_Type *Frame_Pointer;
-static int Next_Function_Num_Args;
-static unsigned int Frame_Pointer_Depth;
-static unsigned int *Frame_Pointer_Stack;
-
-static int Lang_Break_Condition = 0;
-/* true if any one below is true. This keeps us from testing 3 variables.
- * I know this can be perfomed with a bitmapped variable, but...
- */
-static int Lang_Break = 0;
-static int Lang_Return = 0;
-/* static int Lang_Continue = 0; */
-
-SLang_Object_Type *_SLRun_Stack;
-SLang_Object_Type *_SLStack_Pointer;
-static SLang_Object_Type *_SLStack_Pointer_Max;
-
-/* Might want to increase this. */
-static SLang_Object_Type Local_Variable_Stack[SLANG_MAX_LOCAL_STACK];
-static SLang_Object_Type *Local_Variable_Frame = Local_Variable_Stack;
-
-static void free_function_header (_SLBlock_Header_Type *);
-
-void (*SLang_Dump_Routine)(char *);
-
-static void call_dump_routine (char *fmt, ...)
-{
- char buf[1024];
- va_list ap;
-
- va_start (ap, fmt);
- if (SLang_Dump_Routine != NULL)
- {
- (void) _SLvsnprintf (buf, sizeof (buf), fmt, ap);
- (*SLang_Dump_Routine) (buf);
- }
- else
- {
- vfprintf (stderr, fmt, ap);
- fflush (stderr);
- }
- va_end (ap);
-}
-
-static void do_traceback (char *, unsigned int, char *);
-static int init_interpreter (void);
-
-/*{{{ push/pop/etc stack manipulation functions */
-
-/* This routine is assumed to work even in the presence of a SLang_Error. */
-_INLINE_
-int SLang_pop (SLang_Object_Type *x)
-{
- register SLang_Object_Type *y;
-
- y = _SLStack_Pointer;
- if (y == _SLRun_Stack)
- {
- if (SLang_Error == 0) SLang_Error = SL_STACK_UNDERFLOW;
- x->data_type = 0;
- return -1;
- }
- y--;
- *x = *y;
-
- _SLStack_Pointer = y;
- return 0;
-}
-
-static int pop_ctrl_integer (int *i)
-{
- int type;
- SLang_Class_Type *cl;
-#if _SLANG_OPTIMIZE_FOR_SPEED
- register SLang_Object_Type *y;
-
- /* Most of the time, either an integer or a char will be on the stack.
- * Optimize these cases.
- */
- y = _SLStack_Pointer;
- if (y == _SLRun_Stack)
- {
- if (SLang_Error == 0) SLang_Error = SL_STACK_UNDERFLOW;
- return -1;
- }
- y--;
-
- type = y->data_type;
- if (type == SLANG_INT_TYPE)
- {
- _SLStack_Pointer = y;
- *i = y->v.int_val;
- return 0;
- }
- if (type == SLANG_CHAR_TYPE)
- {
- _SLStack_Pointer = y;
- *i = y->v.char_val;
- return 0;
- }
-#else
- if (-1 == (type = SLang_peek_at_stack ()))
- return -1;
-#endif
-
- cl = _SLclass_get_class ((unsigned char) type);
- if (cl->cl_to_bool == NULL)
- {
- SLang_verror (SL_TYPE_MISMATCH,
- "%s cannot be used in a boolean context",
- cl->cl_name);
- return -1;
- }
- return cl->cl_to_bool ((unsigned char) type, i);
-}
-
-_INLINE_
-int SLang_peek_at_stack (void)
-{
- if (_SLStack_Pointer == _SLRun_Stack)
- {
- if (SLang_Error == 0)
- SLang_Error = SL_STACK_UNDERFLOW;
- return -1;
- }
-
- return (_SLStack_Pointer - 1)->data_type;
-}
-
-int SLang_peek_at_stack1 (void)
-{
- int type;
-
- type = SLang_peek_at_stack ();
- if (type == SLANG_ARRAY_TYPE)
- type = (_SLStack_Pointer - 1)->v.array_val->data_type;
-
- return type;
-}
-
-_INLINE_
-void SLang_free_object (SLang_Object_Type *obj)
-{
- unsigned char data_type;
- SLang_Class_Type *cl;
-
- if (obj == NULL) return;
- data_type = obj->data_type;
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [data_type])
- return;
- if (data_type == SLANG_STRING_TYPE)
- {
- SLang_free_slstring (obj->v.s_val);
- return;
- }
-#endif
- cl = _SLclass_get_class (data_type);
-#if !_SLANG_OPTIMIZE_FOR_SPEED
- if (cl->cl_class_type != SLANG_CLASS_TYPE_SCALAR)
-#endif
- (*cl->cl_destroy) (data_type, (VOID_STAR) &obj->v);
-}
-
-_INLINE_
-int SLang_push (SLang_Object_Type *x)
-{
- register SLang_Object_Type *y;
- y = _SLStack_Pointer;
-
- /* if there is a SLang_Error, probably not much harm will be done
- if it is ignored here */
- /* if (SLang_Error) return; */
-
- /* flag it now */
- if (y >= _SLStack_Pointer_Max)
- {
- if (!SLang_Error) SLang_Error = SL_STACK_OVERFLOW;
- return -1;
- }
-
- *y = *x;
- _SLStack_Pointer = y + 1;
- return 0;
-}
-
-/* _INLINE_ */
-int SLclass_push_ptr_obj (unsigned char type, VOID_STAR pval)
-{
- register SLang_Object_Type *y;
- y = _SLStack_Pointer;
-
- if (y >= _SLStack_Pointer_Max)
- {
- if (!SLang_Error) SLang_Error = SL_STACK_OVERFLOW;
- return -1;
- }
-
- y->data_type = type;
- y->v.ptr_val = pval;
-
- _SLStack_Pointer = y + 1;
- return 0;
-}
-
-_INLINE_
-int SLclass_push_int_obj (unsigned char type, int x)
-{
- register SLang_Object_Type *y;
- y = _SLStack_Pointer;
-
- if (y >= _SLStack_Pointer_Max)
- {
- if (!SLang_Error) SLang_Error = SL_STACK_OVERFLOW;
- return -1;
- }
-
- y->data_type = type;
- y->v.int_val = x;
-
- _SLStack_Pointer = y + 1;
- return 0;
-}
-
-_INLINE_
-int _SLang_pop_object_of_type (unsigned char type, SLang_Object_Type *obj,
- int allow_arrays)
-{
- register SLang_Object_Type *y;
-
- y = _SLStack_Pointer;
- if (y == _SLRun_Stack)
- return SLang_pop (obj);
- y--;
- if (y->data_type != type)
- {
-#if _SLANG_OPTIMIZE_FOR_SPEED
- /* This is an implicit typecast. We do not want to typecast
- * floats to ints implicitly.
- */
- if (_SLarith_Is_Arith_Type [type]
- && _SLarith_Is_Arith_Type [y->data_type]
- && (_SLarith_Is_Arith_Type [type] >= _SLarith_Is_Arith_Type[y->data_type]))
- {
- /* This should not fail */
- (void) _SLarith_typecast (y->data_type, (VOID_STAR)&y->v, 1,
- type, (VOID_STAR)&obj->v);
- obj->data_type = type;
- _SLStack_Pointer = y;
- return 0;
- }
-#endif
-
- if ((allow_arrays == 0)
- || (y->data_type != SLANG_ARRAY_TYPE)
- || (y->v.array_val->data_type != type))
- if (-1 == SLclass_typecast (type, 1, 0))
- return -1;
- }
- *obj = *y;
- _SLStack_Pointer = y;
- return 0;
-}
-
-/* This function reverses the top n items on the stack and returns a
- * an offset from the start of the stack to the last item.
- */
-int SLreverse_stack (int n)
-{
- SLang_Object_Type *otop, *obot, tmp;
-
- otop = _SLStack_Pointer;
- if ((n > otop - _SLRun_Stack) || (n < 0))
- {
- SLang_Error = SL_STACK_UNDERFLOW;
- return -1;
- }
- obot = otop - n;
- otop--;
- while (otop > obot)
- {
- tmp = *obot;
- *obot = *otop;
- *otop = tmp;
- otop--;
- obot++;
- }
- return (int) ((_SLStack_Pointer - n) - _SLRun_Stack);
-}
-
-_INLINE_
-int SLroll_stack (int np)
-{
- int n, i;
- SLang_Object_Type *otop, *obot, tmp;
-
- if ((n = abs(np)) <= 1) return 0; /* identity */
-
- obot = otop = _SLStack_Pointer;
- i = n;
- while (i != 0)
- {
- if (obot <= _SLRun_Stack)
- {
- SLang_Error = SL_STACK_UNDERFLOW;
- return -1;
- }
- obot--;
- i--;
- }
- otop--;
-
- if (np > 0)
- {
- /* Put top on bottom and roll rest up. */
- tmp = *otop;
- while (otop > obot)
- {
- *otop = *(otop - 1);
- otop--;
- }
- *otop = tmp;
- }
- else
- {
- /* Put bottom on top and roll rest down. */
- tmp = *obot;
- while (obot < otop)
- {
- *obot = *(obot + 1);
- obot++;
- }
- *obot = tmp;
- }
- return 0;
-}
-
-int _SLstack_depth (void)
-{
- return (int) (_SLStack_Pointer - _SLRun_Stack);
-}
-
-int SLdup_n (int n)
-{
- SLang_Object_Type *bot, *top;
-
- if (n <= 0)
- return 0;
-
- top = _SLStack_Pointer;
- if (top < _SLRun_Stack + n)
- {
- if (SLang_Error == 0)
- SLang_Error = SL_STACK_UNDERFLOW;
- return -1;
- }
- if (top + n > _SLStack_Pointer_Max)
- {
- if (SLang_Error == 0)
- SLang_Error = SL_STACK_OVERFLOW;
- return -1;
- }
- bot = top - n;
-
- while (bot < top)
- {
- SLang_Class_Type *cl;
- unsigned char data_type = bot->data_type;
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [data_type])
- {
- *_SLStack_Pointer++ = *bot++;
- continue;
- }
-#endif
- cl = _SLclass_get_class (data_type);
- if (-1 == (*cl->cl_push) (data_type, (VOID_STAR) &bot->v))
- return -1;
- bot++;
- }
- return 0;
-}
-
-/*}}}*/
-
-/*{{{ inner interpreter and support functions */
-
-_INLINE_
-int _SL_increment_frame_pointer (void)
-{
- if (Recursion_Depth >= SLANG_MAX_RECURSIVE_DEPTH)
- {
- SLang_verror (SL_STACK_OVERFLOW, "Num Args Stack Overflow");
- return -1;
- }
- Num_Args_Stack [Recursion_Depth] = SLang_Num_Function_Args;
-
- SLang_Num_Function_Args = Next_Function_Num_Args;
- Next_Function_Num_Args = 0;
- Recursion_Depth++;
- return 0;
-}
-
-_INLINE_
-int _SL_decrement_frame_pointer (void)
-{
- if (Recursion_Depth == 0)
- {
- SLang_verror (SL_STACK_UNDERFLOW, "Num Args Stack Underflow");
- return -1;
- }
-
- Recursion_Depth--;
- if (Recursion_Depth < SLANG_MAX_RECURSIVE_DEPTH)
- SLang_Num_Function_Args = Num_Args_Stack [Recursion_Depth];
-
- return 0;
-}
-
-_INLINE_
-int SLang_start_arg_list (void)
-{
- if (Frame_Pointer_Depth < SLANG_MAX_RECURSIVE_DEPTH)
- {
- Frame_Pointer_Stack [Frame_Pointer_Depth] = (unsigned int) (Frame_Pointer - _SLRun_Stack);
- Frame_Pointer = _SLStack_Pointer;
- Frame_Pointer_Depth++;
- Next_Function_Num_Args = 0;
- return 0;
- }
-
- SLang_verror (SL_STACK_OVERFLOW, "Frame Stack Overflow");
- return -1;
-}
-
-_INLINE_
-int SLang_end_arg_list (void)
-{
- if (Frame_Pointer_Depth == 0)
- {
- SLang_verror (SL_STACK_UNDERFLOW, "Frame Stack Underflow");
- return -1;
- }
- Frame_Pointer_Depth--;
- if (Frame_Pointer_Depth < SLANG_MAX_RECURSIVE_DEPTH)
- {
- Next_Function_Num_Args = (int) (_SLStack_Pointer - Frame_Pointer);
- Frame_Pointer = _SLRun_Stack + Frame_Pointer_Stack [Frame_Pointer_Depth];
- }
- return 0;
-}
-
-_INLINE_
-static int do_bc_call_direct_frame (int (*f)(void))
-{
- if ((0 == SLang_end_arg_list ())
- && (0 == _SL_increment_frame_pointer ()))
- {
- (void) (*f) ();
- _SL_decrement_frame_pointer ();
- }
- if (SLang_Error)
- return -1;
- return 0;
-}
-
-static int do_name_type_error (SLang_Name_Type *nt)
-{
- char buf[256];
- if (nt != NULL)
- {
- (void) _SLsnprintf (buf, sizeof (buf), "(Error occurred processing %s)", nt->name);
- do_traceback (buf, 0, NULL);
- }
- return -1;
-}
-
-/* local and global variable assignments */
-
-static int do_binary_ab (int op, SLang_Object_Type *obja, SLang_Object_Type *objb)
-{
- SLang_Class_Type *a_cl, *b_cl, *c_cl;
- unsigned char b_data_type, a_data_type, c_data_type;
- int (*binary_fun) (int,
- unsigned char, VOID_STAR, unsigned int,
- unsigned char, VOID_STAR, unsigned int,
- VOID_STAR);
- VOID_STAR pa;
- VOID_STAR pb;
- VOID_STAR pc;
- int ret;
-
- b_data_type = objb->data_type;
- a_data_type = obja->data_type;
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (_SLarith_Is_Arith_Type[a_data_type]
- && _SLarith_Is_Arith_Type[b_data_type])
- {
- int status;
- status = _SLarith_bin_op (obja, objb, op);
- if (status != 1)
- return status;
- /* drop and try it the hard way */
- }
-#endif
-
- a_cl = _SLclass_get_class (a_data_type);
- if (a_data_type == b_data_type)
- b_cl = a_cl;
- else
- b_cl = _SLclass_get_class (b_data_type);
-
- if (NULL == (binary_fun = _SLclass_get_binary_fun (op, a_cl, b_cl, &c_cl, 1)))
- return -1;
-
- c_data_type = c_cl->cl_data_type;
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [a_data_type])
- pa = (VOID_STAR) &obja->v;
- else
-#endif
- pa = _SLclass_get_ptr_to_value (a_cl, obja);
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [b_data_type])
- pb = (VOID_STAR) &objb->v;
- else
-#endif
- pb = _SLclass_get_ptr_to_value (b_cl, objb);
-
- pc = c_cl->cl_transfer_buf;
-
- if (1 != (*binary_fun) (op,
- a_data_type, pa, 1,
- b_data_type, pb, 1,
- pc))
- {
- SLang_verror (SL_NOT_IMPLEMENTED,
- "Binary operation between %s and %s failed",
- a_cl->cl_name, b_cl->cl_name);
-
- return -1;
- }
-
- /* apush will create a copy, so make sure we free after the push */
- ret = (*c_cl->cl_apush)(c_data_type, pc);
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [c_data_type])
-#endif
- (*c_cl->cl_adestroy)(c_data_type, pc);
-
- return ret;
-}
-
-_INLINE_
-static void do_binary (int op)
-{
- SLang_Object_Type obja, objb;
-
- if (SLang_pop (&objb)) return;
- if (0 == SLang_pop (&obja))
- {
- (void) do_binary_ab (op, &obja, &objb);
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [obja.data_type])
-#endif
- SLang_free_object (&obja);
- }
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [objb.data_type])
-#endif
- SLang_free_object (&objb);
-}
-
-static int do_unary_op (int op, SLang_Object_Type *obj, int unary_type)
-{
- int (*f) (int, unsigned char, VOID_STAR, unsigned int, VOID_STAR);
- VOID_STAR pa;
- VOID_STAR pb;
- SLang_Class_Type *a_cl, *b_cl;
- unsigned char a_type, b_type;
- int ret;
-
- a_type = obj->data_type;
- a_cl = _SLclass_get_class (a_type);
-
- if (NULL == (f = _SLclass_get_unary_fun (op, a_cl, &b_cl, unary_type)))
- return -1;
-
- b_type = b_cl->cl_data_type;
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [a_type])
- pa = (VOID_STAR) &obj->v;
- else
-#endif
- pa = _SLclass_get_ptr_to_value (a_cl, obj);
-
- pb = b_cl->cl_transfer_buf;
-
- if (1 != (*f) (op, a_type, pa, 1, pb))
- {
- SLang_verror (SL_NOT_IMPLEMENTED,
- "Unary operation for %s failed", a_cl->cl_name);
- return -1;
- }
-
- ret = (*b_cl->cl_apush)(b_type, pb);
- /* cl_apush creates a copy, so make sure we call cl_adestroy */
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [b_type])
-#endif
- (*b_cl->cl_adestroy)(b_type, pb);
-
- return ret;
-}
-
-_INLINE_
-static int do_unary (int op, int unary_type)
-{
- SLang_Object_Type obj;
- int ret;
-
- if (-1 == SLang_pop (&obj)) return -1;
- ret = do_unary_op (op, &obj, unary_type);
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [obj.data_type])
-#endif
- SLang_free_object (&obj);
- return ret;
-}
-
-static int do_assignment_binary (int op, SLang_Object_Type *obja_ptr)
-{
- SLang_Object_Type objb;
- int ret;
-
- if (SLang_pop (&objb))
- return -1;
-
- ret = do_binary_ab (op, obja_ptr, &objb);
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [objb.data_type])
-#endif
- SLang_free_object (&objb);
- return ret;
-}
-
-/* The order of these is assumed to match the binary operators
- * defined in slang.h
- */
-static int
-map_assignment_op_to_binary (unsigned char op_type, int *op, int *is_unary)
-{
- *is_unary = 0;
- switch (op_type)
- {
- case _SLANG_BCST_PLUSEQS:
- case _SLANG_BCST_MINUSEQS:
- case _SLANG_BCST_TIMESEQS:
- case _SLANG_BCST_DIVEQS:
- *op = SLANG_PLUS + (op_type - _SLANG_BCST_PLUSEQS);
- break;
-
- case _SLANG_BCST_BOREQS:
- *op = SLANG_BOR;
- break;
-
- case _SLANG_BCST_BANDEQS:
- *op = SLANG_BAND;
- break;
-
- case _SLANG_BCST_POST_MINUSMINUS:
- case _SLANG_BCST_MINUSMINUS:
- *op = SLANG_MINUS;
- *is_unary = 1;
- break;
-
- case _SLANG_BCST_PLUSPLUS:
- case _SLANG_BCST_POST_PLUSPLUS:
- *op = SLANG_PLUS;
- *is_unary = 1;
- break;
-
- default:
- SLang_verror (SL_NOT_IMPLEMENTED, "Assignment operator not implemented");
- return -1;
- }
- return 0;
-}
-
-static int
-perform_lvalue_operation (unsigned char op_type, SLang_Object_Type *obja_ptr)
-{
- switch (op_type)
- {
- case _SLANG_BCST_ASSIGN:
- break;
-
- /* The order of these is assumed to match the binary operators
- * defined in slang.h
- */
- case _SLANG_BCST_PLUSEQS:
- case _SLANG_BCST_MINUSEQS:
- case _SLANG_BCST_TIMESEQS:
- case _SLANG_BCST_DIVEQS:
- if (-1 == do_assignment_binary (SLANG_PLUS + (op_type - _SLANG_BCST_PLUSEQS), obja_ptr))
- return -1;
- break;
-
- case _SLANG_BCST_BOREQS:
- if (-1 == do_assignment_binary (SLANG_BOR, obja_ptr))
- return -1;
- break;
-
- case _SLANG_BCST_BANDEQS:
- if (-1 == do_assignment_binary (SLANG_BAND, obja_ptr))
- return -1;
- break;
-
- case _SLANG_BCST_PLUSPLUS:
- case _SLANG_BCST_POST_PLUSPLUS:
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (obja_ptr->data_type == SLANG_INT_TYPE)
- return SLclass_push_int_obj (SLANG_INT_TYPE, obja_ptr->v.int_val + 1);
-#endif
- if (-1 == do_unary_op (SLANG_PLUSPLUS, obja_ptr, _SLANG_BC_UNARY))
- return -1;
- break;
-
- case _SLANG_BCST_MINUSMINUS:
- case _SLANG_BCST_POST_MINUSMINUS:
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (obja_ptr->data_type == SLANG_INT_TYPE)
- return SLclass_push_int_obj (SLANG_INT_TYPE, obja_ptr->v.int_val - 1);
-#endif
- if (-1 == do_unary_op (SLANG_MINUSMINUS, obja_ptr, _SLANG_BC_UNARY))
- return -1;
- break;
-
- default:
- SLang_Error = SL_INTERNAL_ERROR;
- return -1;
- }
- return 0;
-}
-
-_INLINE_
-static int
-set_lvalue_obj (unsigned char op_type, SLang_Object_Type *obja_ptr)
-{
- if (op_type != _SLANG_BCST_ASSIGN)
- {
- if (-1 == perform_lvalue_operation (op_type, obja_ptr))
- return -1;
- }
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [obja_ptr->data_type])
-#endif
- SLang_free_object (obja_ptr);
-
- return SLang_pop(obja_ptr);
-}
-
-static int
-set_struct_lvalue (SLBlock_Type *bc_blk)
-{
- int type;
- SLang_Class_Type *cl;
- char *name;
- int op;
-
- if (-1 == (type = SLang_peek_at_stack ()))
- return -1;
-
- cl = _SLclass_get_class (type);
- if ((cl->cl_sput == NULL)
- || (cl->cl_sget == NULL))
- {
- SLang_verror (SL_NOT_IMPLEMENTED,
- "%s does not support structure access",
- cl->cl_name);
- SLdo_pop_n (2); /* object plus what was to be assigned */
- return -1;
- }
- name = bc_blk->b.s_blk;
- op = bc_blk->bc_sub_type;
-
- if (op != _SLANG_BCST_ASSIGN)
- {
- /* We have something like (A.x += b) or (A.x++). In either case,
- * we need A.x.
- */
- SLang_Object_Type obj_A;
- SLang_Object_Type obj;
-
- if (-1 == SLang_pop (&obj_A))
- return -1;
-
- if ((-1 == _SLpush_slang_obj (&obj_A))
- || (-1 == cl->cl_sget ((unsigned char) type, name))
- || (-1 == SLang_pop (&obj)))
- {
- SLang_free_object (&obj_A);
- return -1;
- }
- /* Now the value of A.x is in obj. */
- if (-1 == perform_lvalue_operation (op, &obj))
- {
- SLang_free_object (&obj);
- SLang_free_object (&obj_A);
- return -1;
- }
- SLang_free_object (&obj);
- /* The result of the operation is now on the stack.
- * Perform assignment */
- if (-1 == SLang_push (&obj_A))
- {
- SLang_free_object (&obj_A);
- return -1;
- }
- }
-
- return (*cl->cl_sput) ((unsigned char) type, name);
-}
-
-static int make_unit_object (SLang_Object_Type *a, SLang_Object_Type *u)
-{
- unsigned char type;
-
- type = a->data_type;
- if (type == SLANG_ARRAY_TYPE)
- type = a->v.array_val->data_type;
-
- u->data_type = type;
- switch (type)
- {
- case SLANG_UCHAR_TYPE:
- case SLANG_CHAR_TYPE:
- u->v.char_val = 1;
- break;
-
- case SLANG_SHORT_TYPE:
- case SLANG_USHORT_TYPE:
- u->v.short_val = 1;
- break;
-
- case SLANG_LONG_TYPE:
- case SLANG_ULONG_TYPE:
- u->v.long_val = 1;
- break;
-
-#if SLANG_HAS_FLOAT
- case SLANG_FLOAT_TYPE:
- u->v.float_val = 1;
- break;
-
- case SLANG_COMPLEX_TYPE:
- u->data_type = SLANG_DOUBLE_TYPE;
- case SLANG_DOUBLE_TYPE:
- u->v.double_val = 1;
- break;
-#endif
- default:
- u->data_type = SLANG_INT_TYPE;
- u->v.int_val = 1;
- }
- return 0;
-}
-
-
-/* We want to convert 'A[i] op X' to 'A[i] = A[i] op X'. The code that
- * has been generated is: X __args i A __aput-op
- * where __aput-op represents this function. We need to generate:
- * __args i A __eargs __aget X op __args i A __eargs __aput
- * Here, __eargs implies a call to do_bc_call_direct_frame with either
- * the aput or aget function. In addition, __args represents a call to
- * SLang_start_arg_list. Of course, i represents a set of indices.
- *
- * Note: If op is an unary operation (e.g., ++ or --), then X will not
- * b present an will have to be taken to be 1.
- *
- * Implementation note: For efficiency, calls to setup the frame, start
- * arg list will be omitted and SLang_Num_Function_Args will be set.
- * This is ugly but the alternative is much less efficient rendering these
- * assignment operators useless. So, the plan is to roll the stack to get X,
- * then duplicate the next N values, call __aget followed by op X, finally
- * calling __aput. Hence, the sequence is:
- *
- * start: X i .. j A
- * dupN: X i .. j A i .. j A
- * __aget: X i .. j A Y
- * roll: i .. j A Y X
- * op: i .. j A Z
- * roll: Z i .. j A
- * __aput:
- */
-static int
-set_array_lvalue (int op)
-{
- SLang_Object_Type x, y;
- int num_args, is_unary;
-
- if (-1 == map_assignment_op_to_binary (op, &op, &is_unary))
- return -1;
-
- /* Grab the indices and the array. Do not start a new frame. */
- if (-1 == SLang_end_arg_list ())
- return -1;
- num_args = Next_Function_Num_Args;
- Next_Function_Num_Args = 0;
-
- if (-1 == SLdup_n (num_args))
- return -1;
-
- SLang_Num_Function_Args = num_args;
- if (-1 == _SLarray_aget ())
- return -1;
-
- if (-1 == SLang_pop (&y))
- return -1;
-
- if (is_unary == 0)
- {
- if ((-1 == SLroll_stack (-(num_args + 1)))
- || (-1 == SLang_pop (&x)))
- {
- SLang_free_object (&y);
- return -1;
- }
- }
- else if (-1 == make_unit_object (&y, &x))
- {
- SLang_free_object (&y);
- return -1;
- }
-
- if (-1 == do_binary_ab (op, &y, &x))
- {
- SLang_free_object (&y);
- SLang_free_object (&x);
- return -1;
- }
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [y.data_type])
-#endif
- SLang_free_object (&y);
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [x.data_type])
-#endif
- SLang_free_object (&x);
-
- if (-1 == SLroll_stack (num_args + 1))
- return -1;
-
- SLang_Num_Function_Args = num_args;
- return _SLarray_aput ();
-}
-
-
-static int
-set_intrin_lvalue (SLBlock_Type *bc_blk)
-{
- unsigned char op_type;
- SLang_Object_Type obja;
- SLang_Class_Type *cl;
- SLang_Intrin_Var_Type *ivar;
- VOID_STAR intrinsic_addr;
- unsigned char intrinsic_type;
-
- ivar = bc_blk->b.nt_ivar_blk;
-
- intrinsic_type = ivar->type;
- intrinsic_addr = ivar->addr;
-
- op_type = bc_blk->bc_sub_type;
-
- cl = _SLclass_get_class (intrinsic_type);
-
- if (op_type != _SLANG_BCST_ASSIGN)
- {
- /* We want to get the current value into obja. This is the
- * easiest way.
- */
- if ((-1 == (*cl->cl_push) (intrinsic_type, intrinsic_addr))
- || (-1 == SLang_pop (&obja)))
- return -1;
-
- (void) perform_lvalue_operation (op_type, &obja);
- SLang_free_object (&obja);
-
- if (SLang_Error)
- return -1;
- }
-
- return (*cl->cl_pop) (intrinsic_type, intrinsic_addr);
-}
-
-int _SLang_deref_assign (SLang_Ref_Type *ref)
-{
- SLang_Object_Type *objp;
- SLang_Name_Type *nt;
- SLBlock_Type blk;
-
- if (ref->is_global == 0)
- {
- objp = ref->v.local_obj;
- if (objp > Local_Variable_Frame)
- {
- SLang_verror (SL_UNDEFINED_NAME, "Local variable reference is out of scope");
- return -1;
- }
- return set_lvalue_obj (_SLANG_BCST_ASSIGN, objp);
- }
-
- nt = ref->v.nt;
- switch (nt->name_type)
- {
- case SLANG_GVARIABLE:
- case SLANG_PVARIABLE:
- if (-1 == set_lvalue_obj (_SLANG_BCST_ASSIGN,
- &((SLang_Global_Var_Type *)nt)->obj))
- {
- do_name_type_error (nt);
- return -1;
- }
- break;
-
- case SLANG_IVARIABLE:
- blk.b.nt_blk = nt;
- blk.bc_sub_type = _SLANG_BCST_ASSIGN;
- if (-1 == set_intrin_lvalue (&blk))
- {
- do_name_type_error (nt);
- return -1;
- }
- break;
-
- case SLANG_LVARIABLE:
- SLang_Error = SL_INTERNAL_ERROR;
- /* set_intrin_lvalue (&blk); */
- return -1;
-
- case SLANG_RVARIABLE:
- default:
- SLang_verror (SL_READONLY_ERROR, "deref assignment to %s not allowed", nt->name);
- return -1;
- }
-
- return 0;
-}
-
-static void set_deref_lvalue (SLBlock_Type *bc_blk)
-{
- SLang_Object_Type *objp;
- SLang_Ref_Type *ref;
-
- switch (bc_blk->bc_sub_type)
- {
- case SLANG_LVARIABLE:
- objp = (Local_Variable_Frame - bc_blk->b.i_blk);
- break;
- case SLANG_GVARIABLE:
- case SLANG_PVARIABLE:
- objp = &bc_blk->b.nt_gvar_blk->obj;
- break;
- default:
- SLang_Error = SL_INTERNAL_ERROR;
- return;
- }
-
- if (-1 == _SLpush_slang_obj (objp))
- return;
-
- if (-1 == SLang_pop_ref (&ref))
- return;
- (void) _SLang_deref_assign (ref);
- SLang_free_ref (ref);
-}
-
-static int push_struct_field (char *name)
-{
- int type;
- SLang_Class_Type *cl;
-
- if (-1 == (type = SLang_peek_at_stack ()))
- return -1;
-
- cl = _SLclass_get_class ((unsigned char) type);
- if (cl->cl_sget == NULL)
- {
- SLang_verror (SL_NOT_IMPLEMENTED,
- "%s does not permit structure access",
- cl->cl_name);
- SLdo_pop_n (2);
- return -1;
- }
-
- return (*cl->cl_sget) ((unsigned char) type, name);
-}
-
-static void trace_dump (char *format, char *name, SLang_Object_Type *objs, int n, int dir)
-{
- unsigned int len;
- char prefix [52];
-
- len = Trace_Mode - 1;
- if (len + 2 >= sizeof (prefix))
- len = sizeof (prefix) - 2;
-
- SLMEMSET (prefix, ' ', len);
- prefix[len] = 0;
-
- call_dump_routine (prefix);
- call_dump_routine (format, name, n);
-
- if (n > 0)
- {
- prefix[len] = ' ';
- len++;
- prefix[len] = 0;
-
- _SLdump_objects (prefix, objs, n, dir);
- }
-}
-
-/* Pop a data item from the stack and return a pointer to it.
- * Strings are not freed from stack so use another routine to do it.
- */
-static VOID_STAR pop_pointer (SLang_Object_Type *obj, unsigned char type)
-{
-#ifndef _SLANG_OPTIMIZE_FOR_SPEED
- SLang_Class_Type *cl;
-#endif
-
- SLang_Array_Type *at;
-
- /* Arrays are special. Allow scalars to automatically convert to arrays.
- */
- if (type == SLANG_ARRAY_TYPE)
- {
- if (-1 == SLang_pop_array (&at, 1))
- return NULL;
- obj->data_type = SLANG_ARRAY_TYPE;
- return obj->v.ptr_val = (VOID_STAR) at;
- }
-
- if (type == 0)
- {
- /* This happens when an intrinsic is declared without any information
- * regarding parameter types.
- */
- if (-1 == SLang_pop (obj))
- return NULL;
- type = obj->data_type;
- }
- else if (-1 == _SLang_pop_object_of_type (type, obj, 0))
- return NULL;
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- type = _SLclass_Class_Type [type];
-#else
- type = _SLclass_get_class (type)->cl_class_type;
-#endif
-
- if (type == SLANG_CLASS_TYPE_SCALAR)
- return (VOID_STAR) &obj->v;
- else if (type == SLANG_CLASS_TYPE_MMT)
- return SLang_object_from_mmt (obj->v.ref);
- else
- return obj->v.ptr_val;
-}
-
-/* This is ugly. Does anyone have a advice for a cleaner way of doing
- * this??
- */
-typedef void (*VF0_Type)(void);
-typedef void (*VF1_Type)(VOID_STAR);
-typedef void (*VF2_Type)(VOID_STAR, VOID_STAR);
-typedef void (*VF3_Type)(VOID_STAR, VOID_STAR, VOID_STAR);
-typedef void (*VF4_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef void (*VF5_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef void (*VF6_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef void (*VF7_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef long (*LF0_Type)(void);
-typedef long (*LF1_Type)(VOID_STAR);
-typedef long (*LF2_Type)(VOID_STAR, VOID_STAR);
-typedef long (*LF3_Type)(VOID_STAR, VOID_STAR, VOID_STAR);
-typedef long (*LF4_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef long (*LF5_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef long (*LF6_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef long (*LF7_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-#if SLANG_HAS_FLOAT
-typedef double (*FF0_Type)(void);
-typedef double (*FF1_Type)(VOID_STAR);
-typedef double (*FF2_Type)(VOID_STAR, VOID_STAR);
-typedef double (*FF3_Type)(VOID_STAR, VOID_STAR, VOID_STAR);
-typedef double (*FF4_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef double (*FF5_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef double (*FF6_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-typedef double (*FF7_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
-#endif
-
-static int execute_intrinsic_fun (SLang_Intrin_Fun_Type *objf)
-{
-#if SLANG_HAS_FLOAT
- double xf;
-#endif
- VOID_STAR p[SLANG_MAX_INTRIN_ARGS];
- SLang_Object_Type objs[SLANG_MAX_INTRIN_ARGS];
- long ret;
- unsigned char type;
- unsigned int argc;
- unsigned int i;
- FVOID_STAR fptr;
- unsigned char *arg_types;
- int stk_depth;
-
- fptr = objf->i_fun;
- argc = objf->num_args;
- type = objf->return_type;
- arg_types = objf->arg_types;
-
- if (argc > SLANG_MAX_INTRIN_ARGS)
- {
- SLang_verror(SL_APPLICATION_ERROR,
- "Intrinsic function %s requires too many parameters", objf->name);
- return -1;
- }
-
- if (-1 == _SL_increment_frame_pointer ())
- return -1;
-
- stk_depth = -1;
- if (Trace_Mode && (_SLang_Trace > 0))
- {
- int nargs;
-
- stk_depth = _SLstack_depth ();
-
- nargs = SLang_Num_Function_Args;
- if (nargs == 0)
- nargs = (int)argc;
-
- stk_depth -= nargs;
-
- if (stk_depth >= 0)
- trace_dump (">>%s (%d args)\n",
- objf->name,
- _SLStack_Pointer - nargs,
- nargs,
- 1);
- }
-
- i = argc;
- while (i != 0)
- {
- i--;
- if (NULL == (p[i] = pop_pointer (objs + i, arg_types[i])))
- {
- i++;
- goto free_and_return;
- }
- }
-
- ret = 0;
-#if SLANG_HAS_FLOAT
- xf = 0.0;
-#endif
-
- switch (argc)
- {
- case 0:
- if (type == SLANG_VOID_TYPE) ((VF0_Type) fptr) ();
-#if SLANG_HAS_FLOAT
- else if (type == SLANG_DOUBLE_TYPE) xf = ((FF0_Type) fptr)();
-#endif
- else ret = ((LF0_Type) fptr)();
- break;
-
- case 1:
- if (type == SLANG_VOID_TYPE) ((VF1_Type) fptr)(p[0]);
-#if SLANG_HAS_FLOAT
- else if (type == SLANG_DOUBLE_TYPE) xf = ((FF1_Type) fptr)(p[0]);
-#endif
- else ret = ((LF1_Type) fptr)(p[0]);
- break;
-
- case 2:
- if (type == SLANG_VOID_TYPE) ((VF2_Type) fptr)(p[0], p[1]);
-#if SLANG_HAS_FLOAT
- else if (type == SLANG_DOUBLE_TYPE) xf = ((FF2_Type) fptr)(p[0], p[1]);
-#endif
- else ret = ((LF2_Type) fptr)(p[0], p[1]);
- break;
-
- case 3:
- if (type == SLANG_VOID_TYPE) ((VF3_Type) fptr)(p[0], p[1], p[2]);
-#if SLANG_HAS_FLOAT
- else if (type == SLANG_DOUBLE_TYPE) xf = ((FF3_Type) fptr)(p[0], p[1], p[2]);
-#endif
- else ret = ((LF3_Type) fptr)(p[0], p[1], p[2]);
- break;
-
- case 4:
- if (type == SLANG_VOID_TYPE) ((VF4_Type) fptr)(p[0], p[1], p[2], p[3]);
-#if SLANG_HAS_FLOAT
- else if (type == SLANG_DOUBLE_TYPE) xf = ((FF4_Type) fptr)(p[0], p[1], p[2], p[3]);
-#endif
- else ret = ((LF4_Type) fptr)(p[0], p[1], p[2], p[3]);
- break;
-
- case 5:
- if (type == SLANG_VOID_TYPE) ((VF5_Type) fptr)(p[0], p[1], p[2], p[3], p[4]);
-#if SLANG_HAS_FLOAT
- else if (type == SLANG_DOUBLE_TYPE) xf = ((FF5_Type) fptr)(p[0], p[1], p[2], p[3], p[4]);
-#endif
- else ret = ((LF5_Type) fptr)(p[0], p[1], p[2], p[3], p[4]);
- break;
-
- case 6:
- if (type == SLANG_VOID_TYPE) ((VF6_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5]);
-#if SLANG_HAS_FLOAT
- else if (type == SLANG_DOUBLE_TYPE) xf = ((FF6_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5]);
-#endif
- else ret = ((LF6_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5]);
- break;
-
- case 7:
- if (type == SLANG_VOID_TYPE) ((VF7_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
-#if SLANG_HAS_FLOAT
- else if (type == SLANG_DOUBLE_TYPE) xf = ((FF7_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
-#endif
- else ret = ((LF7_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
- break;
- }
-
- switch (type)
- {
- case SLANG_VOID_TYPE:
- break;
-
-#if SLANG_HAS_FLOAT
- case SLANG_DOUBLE_TYPE:
- (void) SLang_push_double (xf);
- break;
-#endif
- case SLANG_UINT_TYPE:
- case SLANG_INT_TYPE: (void) SLclass_push_int_obj (type, (int) ret);
- break;
-
- case SLANG_CHAR_TYPE:
- case SLANG_UCHAR_TYPE: (void) SLclass_push_char_obj (type, (char) ret);
- break;
-
- case SLANG_SHORT_TYPE:
- case SLANG_USHORT_TYPE: (void) SLclass_push_short_obj (type, (short) ret);
- break;
-
- case SLANG_LONG_TYPE:
- case SLANG_ULONG_TYPE: (void) SLclass_push_long_obj (type, ret);
- break;
-
- case SLANG_STRING_TYPE:
- if (NULL == (char *)ret)
- {
- if (SLang_Error == 0) SLang_Error = SL_INTRINSIC_ERROR;
- }
- else (void) SLang_push_string ((char *)ret);
- break;
-
- default:
- SLang_verror (SL_NOT_IMPLEMENTED,
- "Support for intrinsic functions returning %s is not provided",
- SLclass_get_datatype_name (type));
- }
-
- if (stk_depth >= 0)
- {
- stk_depth = _SLstack_depth () - stk_depth;
-
- trace_dump ("<<%s (returning %d values)\n",
- objf->name,
- _SLStack_Pointer - stk_depth,
- stk_depth,
- 1);
- }
-
- free_and_return:
- while (i < argc)
- {
- SLang_free_object (objs + i);
- i++;
- }
-
- return _SL_decrement_frame_pointer ();
-}
-
-static int inner_interp(register SLBlock_Type *);
-
-/* Switch_Obj_Ptr points to the NEXT available free switch object */
-static SLang_Object_Type Switch_Objects[SLANG_MAX_NESTED_SWITCH];
-static SLang_Object_Type *Switch_Obj_Ptr = Switch_Objects;
-static SLang_Object_Type *Switch_Obj_Max = Switch_Objects + SLANG_MAX_NESTED_SWITCH;
-
-static void
-lang_do_loops (unsigned char stype, SLBlock_Type *block, unsigned int num_blocks)
-{
- int i, ctrl;
- int first, last;
- SLBlock_Type *blks[4];
- char *loop_name;
- SLang_Foreach_Context_Type *foreach_context;
- SLang_Class_Type *cl;
- int type;
- unsigned int j;
-
- j = 0;
- for (i = 0; i < (int) num_blocks; i++)
- {
- if (block[i].bc_main_type != _SLANG_BC_BLOCK)
- {
- if (block[i].bc_main_type == _SLANG_BC_LINE_NUM)
- continue;
-
- SLang_verror (SL_SYNTAX_ERROR, "Bytecode is not a looping block");
- return;
- }
- blks[j] = block[i].b.blk;
- j++;
- }
-
- num_blocks = j;
- block = blks[0];
-
- switch (stype)
- {
- case _SLANG_BCST_FOREACH:
- loop_name = "foreach";
- if (num_blocks != 1)
- goto wrong_num_blocks_error;
-
- /* We should find Next_Function_Num_Args + 1 items on the stack.
- * The first Next_Function_Num_Args items represent the arguments to
- * to USING. The last item (deepest in stack) is the object to loop
- * over. So, roll the stack up and grab it.
- */
- if ((-1 == SLroll_stack (-(Next_Function_Num_Args + 1)))
- || (-1 == (type = SLang_peek_at_stack ())))
- goto return_error;
-
- cl = _SLclass_get_class ((unsigned char) type);
- if ((cl->cl_foreach == NULL)
- || (cl->cl_foreach_open == NULL)
- || (cl->cl_foreach_close == NULL))
- {
- SLang_verror (SL_NOT_IMPLEMENTED, "%s does not permit foreach", cl->cl_name);
- SLdo_pop_n (Next_Function_Num_Args + 1);
- goto return_error;
- }
-
- if (NULL == (foreach_context = (*cl->cl_foreach_open) ((unsigned char)type, Next_Function_Num_Args)))
- goto return_error;
-
- while (1)
- {
- int status;
-
- if (SLang_Error)
- {
- (*cl->cl_foreach_close) ((unsigned char) type, foreach_context);
- goto return_error;
- }
-
- status = (*cl->cl_foreach) ((unsigned char) type, foreach_context);
- if (status <= 0)
- {
- if (status == 0)
- break;
-
- (*cl->cl_foreach_close) ((unsigned char) type, foreach_context);
- goto return_error;
- }
-
- inner_interp (block);
- if (Lang_Break) break;
- Lang_Break_Condition = /* Lang_Continue = */ 0;
- }
- (*cl->cl_foreach_close) ((unsigned char) type, foreach_context);
- break;
-
- case _SLANG_BCST_WHILE:
- loop_name = "while";
-
- if (num_blocks != 2)
- goto wrong_num_blocks_error;
-
- type = blks[1]->bc_main_type;
- while (1)
- {
- if (SLang_Error)
- goto return_error;
-
- inner_interp (block);
- if (Lang_Break) break;
-
- if (-1 == pop_ctrl_integer (&ctrl))
- goto return_error;
-
- if (ctrl == 0) break;
-
- if (type)
- {
- inner_interp (blks[1]);
- if (Lang_Break) break;
- Lang_Break_Condition = /* Lang_Continue = */ 0;
- }
- }
- break;
-
- case _SLANG_BCST_DOWHILE:
- loop_name = "do...while";
-
- if (num_blocks != 2)
- goto wrong_num_blocks_error;
-
- while (1)
- {
- if (SLang_Error)
- goto return_error;
-
- Lang_Break_Condition = /* Lang_Continue = */ 0;
- inner_interp (block);
- if (Lang_Break) break;
- Lang_Break_Condition = /* Lang_Continue = */ 0;
- inner_interp (blks[1]);
- if (-1 == pop_ctrl_integer (&ctrl))
- goto return_error;
-
- if (ctrl == 0) break;
- }
- break;
-
- case _SLANG_BCST_CFOR:
- loop_name = "for";
-
- /* we need 4 blocks: first 3 control, the last is code */
- if (num_blocks != 4) goto wrong_num_blocks_error;
-
- inner_interp (block);
- while (1)
- {
- if (SLang_Error)
- goto return_error;
-
- inner_interp(blks[1]); /* test */
- if (-1 == pop_ctrl_integer (&ctrl))
- goto return_error;
-
- if (ctrl == 0) break;
- inner_interp(blks[3]); /* code */
- if (Lang_Break) break;
- inner_interp(blks[2]); /* bump */
- Lang_Break_Condition = /* Lang_Continue = */ 0;
- }
- break;
-
- case _SLANG_BCST_FOR:
- loop_name = "_for";
-
- if (num_blocks != 1)
- goto wrong_num_blocks_error;
-
- /* 3 elements: first, last, step */
- if ((-1 == SLang_pop_integer (&ctrl))
- || (-1 == SLang_pop_integer (&last))
- || (-1 == SLang_pop_integer (&first)))
- goto return_error;
-
- i = first;
- while (1)
- {
- /* It is ugly to have this test here but I do not know of a
- * simple way to do this without using two while loops.
- */
- if (ctrl >= 0)
- {
- if (i > last) break;
- }
- else if (i < last) break;
-
- if (SLang_Error) goto return_error;
-
- SLclass_push_int_obj (SLANG_INT_TYPE, i);
- inner_interp (block);
- if (Lang_Break) break;
- Lang_Break_Condition = /* Lang_Continue = */ 0;
-
- i += ctrl;
- }
- break;
-
- case _SLANG_BCST_LOOP:
- loop_name = "loop";
- if (num_blocks != 1)
- goto wrong_num_blocks_error;
-
- if (-1 == SLang_pop_integer (&ctrl))
- goto return_error;
- while (ctrl > 0)
- {
- ctrl--;
-
- if (SLang_Error)
- goto return_error;
-
- inner_interp (block);
- if (Lang_Break) break;
- Lang_Break_Condition = /* Lang_Continue = */ 0;
- }
- break;
-
- case _SLANG_BCST_FOREVER:
- loop_name = "forever";
-
- if (num_blocks != 1)
- goto wrong_num_blocks_error;
-
- while (1)
- {
- if (SLang_Error)
- goto return_error;
-
- inner_interp (block);
- if (Lang_Break) break;
- Lang_Break_Condition = /* Lang_Continue = */ 0;
- }
- break;
-
- default: SLang_verror(SL_INTERNAL_ERROR, "Unknown loop type");
- return;
- }
- Lang_Break = /* Lang_Continue = */ 0;
- Lang_Break_Condition = Lang_Return;
- return;
-
- wrong_num_blocks_error:
- SLang_verror (SL_SYNTAX_ERROR, "Wrong number of blocks for '%s' construct", loop_name);
-
- /* drop */
- return_error:
- do_traceback (loop_name, 0, NULL);
-}
-
-static void lang_do_and_orelse (unsigned char stype, SLBlock_Type *addr, SLBlock_Type *addr_max)
-{
- int test = 0;
- int is_or;
-
- is_or = (stype == _SLANG_BCST_ORELSE);
-
- while (addr <= addr_max)
- {
- if (addr->bc_main_type == _SLANG_BC_LINE_NUM)
- {
- addr++;
- continue;
- }
-
- inner_interp (addr->b.blk);
- if (SLang_Error
- || Lang_Break_Condition
- || (-1 == pop_ctrl_integer (&test)))
- return;
-
- if (is_or == (test != 0))
- break;
-
- /* if (((stype == _SLANG_BCST_ANDELSE) && (test == 0))
- * || ((stype == _SLANG_BCST_ORELSE) && test))
- * break;
- */
-
- addr++;
- }
- SLclass_push_int_obj (SLANG_INT_TYPE, test);
-}
-
-static void do_else_if (SLBlock_Type *zero_block, SLBlock_Type *non_zero_block)
-{
- int test;
-
- if (-1 == pop_ctrl_integer (&test))
- return;
-
- if (test == 0)
- non_zero_block = zero_block;
-
- if (non_zero_block != NULL)
- inner_interp (non_zero_block->b.blk);
-}
-
-int _SLang_trace_fun (char *f)
-{
- if (NULL == (f = SLang_create_slstring (f)))
- return -1;
-
- SLang_free_slstring (Trace_Function);
- Trace_Function = f;
- _SLang_Trace = 1;
- return 0;
-}
-
-int _SLdump_objects (char *prefix, SLang_Object_Type *x, unsigned int n, int dir)
-{
- char *s;
- SLang_Class_Type *cl;
-
- while (n)
- {
- cl = _SLclass_get_class (x->data_type);
-
- if (NULL == (s = _SLstringize_object (x)))
- s = "??";
-
- call_dump_routine ("%s[%s]:%s\n", prefix, cl->cl_name, s);
-
- SLang_free_slstring (s);
-
- x += dir;
- n--;
- }
- return 0;
-}
-
-static SLBlock_Type *Exit_Block_Ptr;
-static SLBlock_Type *Global_User_Block[5];
-static SLBlock_Type **User_Block_Ptr = Global_User_Block;
-char *_SLang_Current_Function_Name = NULL;
-
-static int execute_slang_fun (_SLang_Function_Type *fun)
-{
- register unsigned int i;
- register SLang_Object_Type *frame, *lvf;
- register unsigned int n_locals;
- _SLBlock_Header_Type *header;
- /* SLBlock_Type *val; */
- SLBlock_Type *exit_block_save;
- SLBlock_Type **user_block_save;
- SLBlock_Type *user_blocks[5];
- char *save_fname;
-
- exit_block_save = Exit_Block_Ptr;
- user_block_save = User_Block_Ptr;
- User_Block_Ptr = user_blocks;
- *(user_blocks) = NULL;
- *(user_blocks + 1) = NULL;
- *(user_blocks + 2) = NULL;
- *(user_blocks + 3) = NULL;
- *(user_blocks + 4) = NULL;
-
- Exit_Block_Ptr = NULL;
-
- save_fname = _SLang_Current_Function_Name;
- _SLang_Current_Function_Name = fun->name;
-
- _SL_increment_frame_pointer ();
-
- /* need loaded? */
- if (fun->nlocals == AUTOLOAD_NUM_LOCALS)
- {
- header = NULL;
- if (-1 == SLang_load_file(fun->v.autoload_filename))
- goto the_return;
-
- if (fun->nlocals == AUTOLOAD_NUM_LOCALS)
- {
- SLang_verror (SL_UNDEFINED_NAME, "%s: Function did not autoload",
- _SLang_Current_Function_Name);
- goto the_return;
- }
- }
-
- n_locals = fun->nlocals;
-
- /* let the error propagate through since it will do no harm
- and allow us to restore stack. */
-
- /* set new stack frame */
- lvf = frame = Local_Variable_Frame;
- i = n_locals;
- if ((lvf + i) > Local_Variable_Stack + SLANG_MAX_LOCAL_STACK)
- {
- SLang_verror(SL_STACK_OVERFLOW, "%s: Local Variable Stack Overflow",
- _SLang_Current_Function_Name);
- goto the_return;
- }
-
- /* Make sure we do not allow this header to get destroyed by something
- * like: define crash () { eval ("define crash ();") }
- */
- header = fun->v.header;
- header->num_refs++;
-
- while (i--)
- {
- lvf++;
- lvf->data_type = SLANG_UNDEFINED_TYPE;
- }
- Local_Variable_Frame = lvf;
-
- /* read values of function arguments */
- i = fun->nargs;
- while (i > 0)
- {
- i--;
- (void) SLang_pop (Local_Variable_Frame - i);
- }
-
- if (SLang_Enter_Function != NULL) (*SLang_Enter_Function)(_SLang_Current_Function_Name);
-
- if (_SLang_Trace)
- {
- int stack_depth;
-
- stack_depth = _SLstack_depth ();
-
- if ((Trace_Function != NULL)
- && (0 == strcmp (Trace_Function, _SLang_Current_Function_Name))
- && (Trace_Mode == 0))
- Trace_Mode = 1;
-
- if (Trace_Mode)
- {
- /* The local variable frame grows backwards */
- trace_dump (">>%s (%d args)\n",
- _SLang_Current_Function_Name,
- Local_Variable_Frame,
- (int) fun->nargs,
- -1);
- Trace_Mode++;
- }
-
- inner_interp (header->body);
- Lang_Break_Condition = Lang_Return = Lang_Break = 0;
- if (Exit_Block_Ptr != NULL) inner_interp(Exit_Block_Ptr);
-
- if (Trace_Mode)
- {
- Trace_Mode--;
- stack_depth = _SLstack_depth () - stack_depth;
-
- trace_dump ("<<%s (returning %d values)\n",
- _SLang_Current_Function_Name,
- _SLStack_Pointer - stack_depth,
- stack_depth,
- 1);
-
- if (Trace_Mode == 1)
- Trace_Mode = 0;
- }
- }
- else
- {
- inner_interp (header->body);
- Lang_Break_Condition = Lang_Return = Lang_Break = 0;
- if (Exit_Block_Ptr != NULL) inner_interp(Exit_Block_Ptr);
- }
-
- if (SLang_Exit_Function != NULL) (*SLang_Exit_Function)(_SLang_Current_Function_Name);
-
- if (SLang_Error)
- do_traceback(fun->name, n_locals,
-#if _SLANG_HAS_DEBUG_CODE
- fun->file
-#else
- NULL
-#endif
- );
-
- /* free local variables.... */
- lvf = Local_Variable_Frame;
- while (lvf > frame)
- {
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [lvf->data_type])
-#endif
- SLang_free_object (lvf);
- lvf--;
- }
- Local_Variable_Frame = lvf;
-
- if (header->num_refs == 1)
- free_function_header (header);
- else
- header->num_refs--;
-
- the_return:
-
- Lang_Break_Condition = Lang_Return = Lang_Break = 0;
- Exit_Block_Ptr = exit_block_save;
- User_Block_Ptr = user_block_save;
- _SLang_Current_Function_Name = save_fname;
- _SL_decrement_frame_pointer ();
-
- if (SLang_Error)
- return -1;
-
- return 0;
-}
-
-static void do_traceback (char *name, unsigned int locals, char *file)
-{
- char *s;
- unsigned int i;
- SLang_Object_Type *objp;
- unsigned short stype;
-
- /* FIXME: Priority=low
- * I need to make this configurable!!! That is, let the
- * application decide whether or not a usage error should result in a
- * traceback.
- */
- if (SLang_Error == SL_USAGE_ERROR)
- return;
-
- if (SLang_Traceback == 0)
- return;
-
- call_dump_routine ("S-Lang Traceback: %s\n", name);
- if (SLang_Traceback < 0)
- return;
-
- if (file != NULL)
- call_dump_routine ("File: %s\n", file);
-
- if (locals == 0)
- return;
-
- call_dump_routine (" Local Variables:\n");
-
- for (i = 0; i < locals; i++)
- {
- SLang_Class_Type *cl;
- char *class_name;
-
- objp = Local_Variable_Frame - i;
- stype = objp->data_type;
-
- s = _SLstringize_object (objp);
- cl = _SLclass_get_class (stype);
- class_name = cl->cl_name;
-
- call_dump_routine ("\t$%d: Type: %s,\tValue:\t", i, class_name);
-
- if (s == NULL) call_dump_routine("??\n");
- else
- {
- char *q = "";
-#ifndef HAVE_VSNPRINTF
- char buf[256];
- if (strlen (s) >= sizeof (buf))
- {
- strncpy (buf, s, sizeof(buf));
- s = buf;
- s[sizeof(buf) - 1] = 0;
- }
-#endif
- if (SLANG_STRING_TYPE == stype) q = "\"";
- call_dump_routine ("%s%s%s\n", q, s, q);
- }
- }
-}
-
-static void do_app_unary (SLang_App_Unary_Type *nt)
-{
- if (-1 == do_unary (nt->unary_op, nt->name_type))
- do_traceback (nt->name, 0, NULL);
-}
-
-static int inner_interp_nametype (SLang_Name_Type *nt)
-{
- SLBlock_Type bc_blks[2];
-
- bc_blks[0].b.nt_blk = nt;
- bc_blks[0].bc_main_type = nt->name_type;
- bc_blks[1].bc_main_type = 0;
- return inner_interp(bc_blks);
-}
-
-int _SLang_dereference_ref (SLang_Ref_Type *ref)
-{
- if (ref == NULL)
- {
- SLang_Error = SL_INTERNAL_ERROR;
- return -1;
- }
-
- if (ref->is_global == 0)
- {
- SLang_Object_Type *obj = ref->v.local_obj;
- if (obj > Local_Variable_Frame)
- {
- SLang_verror (SL_UNDEFINED_NAME, "Local variable deref is out of scope");
- return -1;
- }
- return _SLpush_slang_obj (ref->v.local_obj);
- }
-
- (void) inner_interp_nametype (ref->v.nt);
- return 0;
-}
-
-int _SLang_is_ref_initialized (SLang_Ref_Type *ref)
-{
- unsigned char type;
-
- if (ref == NULL)
- {
- SLang_Error = SL_INTERNAL_ERROR;
- return -1;
- }
-
- if (ref->is_global == 0)
- {
- SLang_Object_Type *obj = ref->v.local_obj;
- if (obj > Local_Variable_Frame)
- {
- SLang_verror (SL_UNDEFINED_NAME, "Local variable deref is out of scope");
- return -1;
- }
- type = ref->v.local_obj->data_type;
- }
- else
- {
- SLang_Name_Type *nt = ref->v.nt;
- if ((nt->name_type != SLANG_GVARIABLE)
- && (nt->name_type != SLANG_PVARIABLE))
- return 1;
- type = ((SLang_Global_Var_Type *)nt)->obj.data_type;
- }
- return type != SLANG_UNDEFINED_TYPE;
-}
-
-int _SLang_uninitialize_ref (SLang_Ref_Type *ref)
-{
- SLang_Object_Type *obj;
-
- if (ref == NULL)
- {
- SLang_Error = SL_INTERNAL_ERROR;
- return -1;
- }
-
- if (ref->is_global == 0)
- {
- obj = ref->v.local_obj;
- if (obj > Local_Variable_Frame)
- {
- SLang_verror (SL_UNDEFINED_NAME, "Local variable deref is out of scope");
- return -1;
- }
- obj = ref->v.local_obj;
- }
- else
- {
- SLang_Name_Type *nt = ref->v.nt;
- if ((nt->name_type != SLANG_GVARIABLE)
- && (nt->name_type != SLANG_PVARIABLE))
- return -1;
- obj = &((SLang_Global_Var_Type *)nt)->obj;
- }
- SLang_free_object (obj);
- obj->data_type = SLANG_UNDEFINED_TYPE;
- obj->v.ptr_val = NULL;
- return 0;
-}
-
-void (*SLang_Interrupt)(void);
-static int Last_Error;
-void (*SLang_User_Clear_Error)(void);
-void _SLang_clear_error (void)
-{
- if (Last_Error <= 0)
- {
- Last_Error = 0;
- return;
- }
- Last_Error--;
- if (SLang_User_Clear_Error != NULL) (*SLang_User_Clear_Error)();
-}
-
-int _SLpush_slang_obj (SLang_Object_Type *obj)
-{
- unsigned char subtype;
- SLang_Class_Type *cl;
-
- if (obj == NULL) return SLang_push_null ();
-
- subtype = obj->data_type;
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type[subtype])
- return SLang_push (obj);
-#endif
-
- cl = _SLclass_get_class (subtype);
- return (*cl->cl_push) (subtype, (VOID_STAR) &obj->v);
-}
-
-_INLINE_
-static int push_local_variable (int i)
-{
- SLang_Class_Type *cl;
- SLang_Object_Type *obj;
- unsigned char subtype;
-
- obj = Local_Variable_Frame - i;
- subtype = obj->data_type;
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type[subtype])
- return SLang_push (obj);
- if (subtype == SLANG_STRING_TYPE)
- return _SLang_dup_and_push_slstring (obj->v.s_val);
-#endif
-
- cl = _SLclass_get_class (subtype);
- return (*cl->cl_push) (subtype, (VOID_STAR) &obj->v);
-}
-
-static int push_intrinsic_variable (SLang_Intrin_Var_Type *ivar)
-{
- SLang_Class_Type *cl;
- unsigned char stype;
-
- stype = ivar->type;
- cl = _SLclass_get_class (stype);
-
- if (-1 == (*cl->cl_push_intrinsic) (stype, ivar->addr))
- {
- do_name_type_error ((SLang_Name_Type *) ivar);
- return -1;
- }
- return 0;
-}
-
-static int dereference_object (void)
-{
- SLang_Object_Type obj;
- SLang_Class_Type *cl;
- unsigned char type;
- int ret;
-
- if (-1 == SLang_pop (&obj))
- return -1;
-
- type = obj.data_type;
-
- cl = _SLclass_get_class (type);
- ret = (*cl->cl_dereference)(type, (VOID_STAR) &obj.v);
-
- SLang_free_object (&obj);
- return ret;
-}
-
-static int case_function (void)
-{
- unsigned char type;
- SLang_Object_Type obj;
- SLang_Object_Type *swobjptr;
-
- swobjptr = Switch_Obj_Ptr - 1;
-
- if ((swobjptr < Switch_Objects)
- || (0 == (type = swobjptr->data_type)))
- {
- SLang_verror (SL_SYNTAX_ERROR, "Misplaced 'case' keyword");
- return -1;
- }
-
- if (-1 == SLang_pop (&obj))
- return -1;
-
- if (obj.data_type != type)
- {
- SLang_Class_Type *a_cl, *b_cl;
-
- a_cl = _SLclass_get_class (obj.data_type);
- b_cl = _SLclass_get_class (type);
-
- if (NULL == _SLclass_get_binary_fun (SLANG_EQ, a_cl, b_cl, &a_cl, 0))
- {
- (void) SLclass_push_int_obj (SLANG_INT_TYPE, 0);
- SLang_free_object (&obj);
- return 0;
- }
- }
-
- (void) do_binary_ab (SLANG_EQ, swobjptr, &obj);
- SLang_free_object (&obj);
- return 0;
-}
-
-static void tmp_variable_function (SLBlock_Type *addr)
-{
- SLang_Object_Type *obj;
-
- switch (addr->bc_sub_type)
- {
- case SLANG_GVARIABLE:
- case SLANG_PVARIABLE:
- obj = &addr->b.nt_gvar_blk->obj;
- break;
-
- case SLANG_LVARIABLE:
- obj = Local_Variable_Frame - addr->b.i_blk;
- break;
-
- default:
- SLang_Error = SL_INTERNAL_ERROR;
- return;
- }
-
- /* There is no need to go through higher level routines since we are
- * not creating or destroying extra copies.
- */
- if (-1 == SLang_push (obj))
- return;
-
- obj->data_type = SLANG_UNDEFINED_TYPE;
- obj->v.ptr_val = NULL;
-}
-
-
-static int
-do_inner_interp_error (SLBlock_Type *err_block,
- SLBlock_Type *addr_start,
- SLBlock_Type *addr)
-{
- int save_err, slerr;
-
- /* Someday I can use the these variable to provide extra information
- * about what went wrong.
- */
- (void) addr_start;
- (void) addr;
-
- if (err_block == NULL)
- goto return_error;
-
- if (SLang_Error < 0) /* errors less than 0 are severe */
- goto return_error;
-
- save_err = Last_Error++;
- slerr = SLang_Error;
- SLang_Error = 0;
- inner_interp (err_block->b.blk);
-
- if (Last_Error <= save_err)
- {
- /* Caught error and cleared it */
- Last_Error = save_err;
- if ((Lang_Break_Condition == 0)
- /* An error may have cleared the error and then caused the
- * function to return. We will allow that but let's not allow
- * 'break' nor 'continue' statements until later.
- */
- || Lang_Return)
- return 0;
-
- /* drop--- either a break or continue was called */
- }
-
- Last_Error = save_err;
- SLang_Error = slerr;
-
- return_error:
-#if _SLANG_HAS_DEBUG_CODE
- while (addr >= addr_start)
- {
- if (addr->bc_main_type == _SLANG_BC_LINE_NUM)
- {
- char buf[256];
- sprintf (buf, "(Error occurred on line %lu)", addr->b.l_blk);
- do_traceback (buf, 0, NULL);
- break;
- }
- /* Special hack for 16 bit systems to prevent pointer wrapping. */
-#if defined(__16_BIT_SYSTEM__)
- if (addr == addr_start)
- break;
-#endif
- addr--;
- }
-#endif
- return -1;
-}
-
-
-#define GATHER_STATISTICS 0
-#if GATHER_STATISTICS
-static unsigned int Bytecodes[0xFFFF];
-
-static void print_stats (void)
-{
- unsigned int i;
- unsigned long total;
- FILE *fp = fopen ("stats.txt", "w");
- if (fp == NULL)
- return;
-
- total = 0;
- for (i = 0; i < 0xFFFF; i++)
- total += Bytecodes[i];
-
- if (total == 0)
- total = 1;
-
- for (i = 0; i < 0xFFFF; i++)
- {
- if (Bytecodes[i])
- fprintf (fp, "0x%04X %9u %e\n", i, Bytecodes[i], Bytecodes[i]/(double) total);
- }
- fclose (fp);
-}
-
-static void add_to_statistics (SLBlock_Type *b)
-{
- unsigned short x, y;
-
- x = b->bc_main_type;
- if (x == 0)
- {
- Bytecodes[0] += 1;
- return;
- }
- b++;
- y = b->bc_main_type;
-
- Bytecodes[(x << 8) | y] += 1;
-}
-
-#endif
-
-/* inner interpreter */
-/* The return value from this function is only meaningful when it is used
- * to process blocks for the switch statement. If it returns 0, the calling
- * routine should pass the next block to it. Otherwise it will
- * return non-zero, with or without error.
- */
-static int inner_interp (SLBlock_Type *addr_start)
-{
- SLBlock_Type *block, *err_block, *addr;
-#if GATHER_STATISTICS
- static int inited = 0;
-
- if (inited == 0)
- {
- (void) SLang_add_cleanup_function (print_stats);
- inited = 1;
- }
-#endif
-
- /* for systems that have no real interrupt facility (e.g. go32 on dos) */
- if (SLang_Interrupt != NULL) (*SLang_Interrupt)();
-
- block = err_block = NULL;
- addr = addr_start;
-
-#if GATHER_STATISTICS
- add_to_statistics (addr);
-#endif
- while (1)
- {
- switch (addr->bc_main_type)
- {
- case 0:
- return 1;
- case _SLANG_BC_LVARIABLE:
- push_local_variable (addr->b.i_blk);
- break;
- case _SLANG_BC_GVARIABLE:
- if (-1 == _SLpush_slang_obj (&addr->b.nt_gvar_blk->obj))
- do_name_type_error (addr->b.nt_blk);
- break;
-
- case _SLANG_BC_IVARIABLE:
- case _SLANG_BC_RVARIABLE:
- push_intrinsic_variable (addr->b.nt_ivar_blk);
- break;
-
- case _SLANG_BC_INTRINSIC:
- execute_intrinsic_fun (addr->b.nt_ifun_blk);
- if (SLang_Error)
- do_traceback(addr->b.nt_ifun_blk->name, 0, NULL);
- break;
-
- case _SLANG_BC_FUNCTION:
- execute_slang_fun (addr->b.nt_fun_blk);
- if (Lang_Break_Condition) goto handle_break_condition;
- break;
-
- case _SLANG_BC_MATH_UNARY:
- case _SLANG_BC_APP_UNARY:
- /* Make sure we treat these like function calls since the
- * parser took sin(x) to be a function call.
- */
- if (0 == _SL_increment_frame_pointer ())
- {
- do_app_unary (addr->b.nt_unary_blk);
- (void) _SL_decrement_frame_pointer ();
- }
- break;
-
- case _SLANG_BC_ICONST:
- SLclass_push_int_obj (SLANG_INT_TYPE, addr->b.iconst_blk->i);
- break;
-
-#if SLANG_HAS_FLOAT
- case _SLANG_BC_DCONST:
- SLang_push_double (addr->b.dconst_blk->d);
- break;
-#endif
-
- case _SLANG_BC_PVARIABLE:
- if (-1 == _SLpush_slang_obj (&addr->b.nt_gvar_blk->obj))
- do_name_type_error (addr->b.nt_blk);
- break;
-
- case _SLANG_BC_PFUNCTION:
- execute_slang_fun (addr->b.nt_fun_blk);
- if (Lang_Break_Condition) goto handle_break_condition;
- break;
-
- case _SLANG_BC_BINARY:
- do_binary (addr->b.i_blk);
- break;
-
- case _SLANG_BC_LITERAL:
-#if !_SLANG_OPTIMIZE_FOR_SPEED
- case _SLANG_BC_LITERAL_INT:
- case _SLANG_BC_LITERAL_STR:
-#endif
- {
- SLang_Class_Type *cl = _SLclass_get_class (addr->bc_sub_type);
- (*cl->cl_push_literal) (addr->bc_sub_type, (VOID_STAR) &addr->b.ptr_blk);
- }
- break;
-#if _SLANG_OPTIMIZE_FOR_SPEED
- case _SLANG_BC_LITERAL_INT:
- SLclass_push_int_obj (addr->bc_sub_type, (int) addr->b.l_blk);
- break;
-
- case _SLANG_BC_LITERAL_STR:
- _SLang_dup_and_push_slstring (addr->b.s_blk);
- break;
-#endif
- case _SLANG_BC_BLOCK:
- switch (addr->bc_sub_type)
- {
- case _SLANG_BCST_ERROR_BLOCK:
- err_block = addr;
- break;
-
- case _SLANG_BCST_EXIT_BLOCK:
- Exit_Block_Ptr = addr->b.blk;
- break;
-
- case _SLANG_BCST_USER_BLOCK0:
- case _SLANG_BCST_USER_BLOCK1:
- case _SLANG_BCST_USER_BLOCK2:
- case _SLANG_BCST_USER_BLOCK3:
- case _SLANG_BCST_USER_BLOCK4:
- User_Block_Ptr[addr->bc_sub_type - _SLANG_BCST_USER_BLOCK0] = addr->b.blk;
- break;
-
- case _SLANG_BCST_LOOP:
- case _SLANG_BCST_WHILE:
- case _SLANG_BCST_FOR:
- case _SLANG_BCST_FOREVER:
- case _SLANG_BCST_CFOR:
- case _SLANG_BCST_DOWHILE:
- case _SLANG_BCST_FOREACH:
- if (block == NULL) block = addr;
- lang_do_loops(addr->bc_sub_type, block, 1 + (unsigned int) (addr - block));
- block = NULL;
- break;
-
- case _SLANG_BCST_IFNOT:
-#if _SLANG_OPTIMIZE_FOR_SPEED
- {
- int i;
-
- if ((0 == pop_ctrl_integer (&i)) && (i == 0))
- inner_interp (addr->b.blk);
- }
-#else
- do_else_if (addr, NULL);
-#endif
- break;
-
- case _SLANG_BCST_IF:
-#if _SLANG_OPTIMIZE_FOR_SPEED
- {
- int i;
-
- if ((0 == pop_ctrl_integer (&i)) && i)
- inner_interp (addr->b.blk);
- }
-#else
- do_else_if (NULL, addr);
-#endif
- break;
-
- case _SLANG_BCST_NOTELSE:
- do_else_if (block, addr);
- block = NULL;
- break;
-
- case _SLANG_BCST_ELSE:
- do_else_if (addr, block);
- block = NULL;
- break;
-
- case _SLANG_BCST_SWITCH:
- if (Switch_Obj_Ptr == Switch_Obj_Max)
- {
- SLang_doerror("switch nesting too deep");
- break;
- }
- (void) SLang_pop (Switch_Obj_Ptr);
- Switch_Obj_Ptr++;
-
- if (block == NULL) block = addr;
- while ((SLang_Error == 0)
- && (block <= addr)
- && (Lang_Break_Condition == 0)
- && (0 == inner_interp (block->b.blk)))
- block++;
- Switch_Obj_Ptr--;
- SLang_free_object (Switch_Obj_Ptr);
- Switch_Obj_Ptr->data_type = 0;
- block = NULL;
- break;
-
- case _SLANG_BCST_ANDELSE:
- case _SLANG_BCST_ORELSE:
- if (block == NULL) block = addr;
- lang_do_and_orelse (addr->bc_sub_type, block, addr);
- block = NULL;
- break;
-
- default:
- if (block == NULL) block = addr;
- break;
- }
- if (Lang_Break_Condition) goto handle_break_condition;
- break;
-
- case _SLANG_BC_RETURN:
- Lang_Break_Condition = Lang_Return = Lang_Break = 1; return 1;
- case _SLANG_BC_BREAK:
- Lang_Break_Condition = Lang_Break = 1; return 1;
- case _SLANG_BC_CONTINUE:
- Lang_Break_Condition = /* Lang_Continue = */ 1; return 1;
-
- case _SLANG_BC_EXCH:
- (void) SLreverse_stack (2);
- break;
-
- case _SLANG_BC_LABEL:
- {
- int test;
- if ((0 == SLang_pop_integer (&test))
- && (test == 0))
- return 0;
- }
- break;
-
- case _SLANG_BC_LOBJPTR:
- (void)_SLang_push_ref (0, (VOID_STAR)(Local_Variable_Frame - addr->b.i_blk));
- break;
-
- case _SLANG_BC_GOBJPTR:
- (void)_SLang_push_ref (1, (VOID_STAR)addr->b.nt_blk);
- break;
-
- case _SLANG_BC_X_ERROR:
- if (err_block != NULL)
- {
- inner_interp(err_block->b.blk);
- if (SLang_Error) err_block = NULL;
- }
- else SLang_verror(SL_SYNTAX_ERROR, "No ERROR_BLOCK");
- if (Lang_Break_Condition) goto handle_break_condition;
- break;
-
- case _SLANG_BC_X_USER0:
- case _SLANG_BC_X_USER1:
- case _SLANG_BC_X_USER2:
- case _SLANG_BC_X_USER3:
- case _SLANG_BC_X_USER4:
- if (User_Block_Ptr[addr->bc_main_type - _SLANG_BC_X_USER0] != NULL)
- {
- inner_interp(User_Block_Ptr[addr->bc_main_type - _SLANG_BC_X_USER0]);
- }
- else SLang_verror(SL_SYNTAX_ERROR, "No block for X_USERBLOCK");
- if (Lang_Break_Condition) goto handle_break_condition;
- break;
-
- case _SLANG_BC_CALL_DIRECT:
- (*addr->b.call_function) ();
- break;
-
- case _SLANG_BC_CALL_DIRECT_FRAME:
- do_bc_call_direct_frame (addr->b.call_function);
- break;
-
- case _SLANG_BC_UNARY:
- do_unary (addr->b.i_blk, _SLANG_BC_UNARY);
- break;
-
- case _SLANG_BC_UNARY_FUNC:
- /* Make sure we treat these like function calls since the
- * parser took abs(x) to be a function call.
- */
- if (0 == _SL_increment_frame_pointer ())
- {
- do_unary (addr->b.i_blk, _SLANG_BC_UNARY);
- (void) _SL_decrement_frame_pointer ();
- }
- break;
-
- case _SLANG_BC_DEREF_ASSIGN:
- set_deref_lvalue (addr);
- break;
- case _SLANG_BC_SET_LOCAL_LVALUE:
- set_lvalue_obj (addr->bc_sub_type, Local_Variable_Frame - addr->b.i_blk);
- break;
- case _SLANG_BC_SET_GLOBAL_LVALUE:
- if (-1 == set_lvalue_obj (addr->bc_sub_type, &addr->b.nt_gvar_blk->obj))
- do_name_type_error (addr->b.nt_blk);
- break;
- case _SLANG_BC_SET_INTRIN_LVALUE:
- set_intrin_lvalue (addr);
- break;
- case _SLANG_BC_SET_STRUCT_LVALUE:
- set_struct_lvalue (addr);
- break;
-
- case _SLANG_BC_FIELD:
- (void) push_struct_field (addr->b.s_blk);
- break;
-
- case _SLANG_BC_SET_ARRAY_LVALUE:
- set_array_lvalue (addr->bc_sub_type);
- break;
-
-#if _SLANG_HAS_DEBUG_CODE
- case _SLANG_BC_LINE_NUM:
- break;
-#endif
-
- case _SLANG_BC_TMP:
- tmp_variable_function (addr);
- break;
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
- case _SLANG_BC_LVARIABLE_AGET:
- if (0 == push_local_variable (addr->b.i_blk))
- do_bc_call_direct_frame (_SLarray_aget);
- break;
-
- case _SLANG_BC_LVARIABLE_APUT:
- if (0 == push_local_variable (addr->b.i_blk))
- do_bc_call_direct_frame (_SLarray_aput);
- break;
- case _SLANG_BC_INTEGER_PLUS:
- if (0 == SLclass_push_int_obj (addr->bc_sub_type, (int) addr->b.l_blk))
- do_binary (SLANG_PLUS);
- break;
-
- case _SLANG_BC_INTEGER_MINUS:
- if (0 == SLclass_push_int_obj (addr->bc_sub_type, (int) addr->b.l_blk))
- do_binary (SLANG_MINUS);
- break;
-#endif
-#if 0
- case _SLANG_BC_ARG_LVARIABLE:
- (void) SLang_start_arg_list ();
- push_local_variable (addr->b.i_blk);
- break;
-#endif
- case _SLANG_BC_EARG_LVARIABLE:
- push_local_variable (addr->b.i_blk);
- (void) SLang_end_arg_list ();
- break;
-
-#if USE_COMBINED_BYTECODES
- case _SLANG_BC_CALL_DIRECT_INTRINSIC:
- (*addr->b.call_function) ();
- addr++;
- execute_intrinsic_fun (addr->b.nt_ifun_blk);
- if (SLang_Error)
- do_traceback(addr->b.nt_ifun_blk->name, 0, NULL);
- break;
-
- case _SLANG_BC_INTRINSIC_CALL_DIRECT:
- execute_intrinsic_fun (addr->b.nt_ifun_blk);
- if (SLang_Error)
- {
- do_traceback(addr->b.nt_ifun_blk->name, 0, NULL);
- break;
- }
- addr++;
- (*addr->b.call_function) ();
- break;
-
- case _SLANG_BC_CALL_DIRECT_LSTR:
- (*addr->b.call_function) ();
- addr++;
- _SLang_dup_and_push_slstring (addr->b.s_blk);
- break;
-
- case _SLANG_BC_CALL_DIRECT_SLFUN:
- (*addr->b.call_function) ();
- addr++;
- execute_slang_fun (addr->b.nt_fun_blk);
- if (Lang_Break_Condition) goto handle_break_condition;
- break;
-
- case _SLANG_BC_CALL_DIRECT_INTRSTOP:
- (*addr->b.call_function) ();
- addr++;
- /* drop */
- case _SLANG_BC_INTRINSIC_STOP:
- execute_intrinsic_fun (addr->b.nt_ifun_blk);
- if (SLang_Error == 0)
- return 1;
- do_traceback(addr->b.nt_ifun_blk->name, 0, NULL);
- break;
-
- case _SLANG_BC_CALL_DIRECT_EARG_LVAR:
- (*addr->b.call_function) ();
- addr++;
- push_local_variable (addr->b.i_blk);
- (void) SLang_end_arg_list ();
- break;
-
- case _SLANG_BC_CALL_DIRECT_LINT:
- (*addr->b.call_function) ();
- addr++;
- SLclass_push_int_obj (addr->bc_sub_type, (int) addr->b.l_blk);
- break;
-
- case _SLANG_BC_CALL_DIRECT_LVAR:
- (*addr->b.call_function) ();
- addr++;
- push_local_variable (addr->b.i_blk);
- break;
-#endif /* USE_COMBINED_BYTECODES */
-
- default:
- SLang_verror (SL_INTERNAL_ERROR, "Byte-Code 0x%X is not valid", addr->bc_main_type);
- }
-
- /* Someday I plan to add a 'signal' intrinsic function. Then when a
- * signal is caught, a variable will be set to one and that value of
- * that variable will need to be monitored here, e.g.,
- * if (Handle_Signal) handle_signal ();
- * It would be nice to check only one variable instead of Handle_Signal
- * and SLang_Error. Perhaps I should phase out SLang_Error = xxx
- * and used something like: SLang_set_error (code); Then, I could
- * use:
- * if (Handle_Condition)
- * {
- * Handle_Condition = 0;
- * if (SLang_Error) ....
- * else if (Handle_Signal) handle_signal ();
- * else....
- * }
- */
- if (SLang_Error)
- {
- if (-1 == do_inner_interp_error (err_block, addr_start, addr))
- return 1;
- if (SLang_Error)
- return 1;
-
- /* Otherwise, error cleared. Continue onto next bytecode.
- * Someday I need to add something to indicate where the
- * next statement begins since continuing on the next
- * bytecode is not really what is desired.
- */
- if (Lang_Break_Condition) goto handle_break_condition;
- }
- addr++;
- }
-
- handle_break_condition:
- /* Get here if Lang_Break_Condition != 0, which implies that either
- * Lang_Return, Lang_Break, or Lang_Continue is non zero
- */
- if (Lang_Return)
- Lang_Break = 1;
-
- return 1;
-}
-
-/*}}}*/
-
-/* The functions below this point are used to implement the parsed token
- * to byte-compiled code.
- */
-/* static SLang_Name_Type **Static_Hash_Table; */
-
-static SLang_Name_Type **Locals_Hash_Table;
-static int Local_Variable_Number;
-static unsigned int Function_Args_Number;
-int _SLang_Auto_Declare_Globals = 0;
-int (*SLang_Auto_Declare_Var_Hook) (char *);
-
-static SLang_NameSpace_Type *This_Static_NameSpace;
-static SLang_NameSpace_Type *Global_NameSpace;
-
-#if _SLANG_HAS_DEBUG_CODE
-static char *This_Compile_Filename;
-#endif
-static SLBlock_Type SLShort_Blocks[6];
-/* These are initialized in add_table below. I cannot init a Union!! */
-
-static int Lang_Defining_Function;
-static void (*Default_Variable_Mode) (_SLang_Token_Type *);
-static void (*Default_Define_Function) (char *, unsigned long);
-
-static int push_compile_context (char *);
-static int pop_compile_context (void);
-
-typedef struct
-{
- int block_type;
- SLBlock_Type *block; /* beginning of block definition */
- SLBlock_Type *block_ptr; /* current location */
- SLBlock_Type *block_max; /* end of definition */
- SLang_NameSpace_Type *static_namespace;
-}
-Block_Context_Type;
-
-static Block_Context_Type Block_Context_Stack [SLANG_MAX_BLOCK_STACK_LEN];
-static unsigned int Block_Context_Stack_Len;
-
-static SLBlock_Type *Compile_ByteCode_Ptr;
-static SLBlock_Type *This_Compile_Block;
-static SLBlock_Type *This_Compile_Block_Max;
-static int This_Compile_Block_Type;
-#define COMPILE_BLOCK_TYPE_FUNCTION 1
-#define COMPILE_BLOCK_TYPE_BLOCK 2
-#define COMPILE_BLOCK_TYPE_TOP_LEVEL 3
-
-/* If it returns 0, DO NOT FREE p */
-static int lang_free_branch (SLBlock_Type *p)
-{
- /* Note: we look at 0,2,4, since these blocks are 0 terminated */
- if ((p == SLShort_Blocks)
- || (p == SLShort_Blocks + 2)
- || (p == SLShort_Blocks + 4)
- )
- return 0;
-
- while (1)
- {
- SLang_Class_Type *cl;
-
- switch (p->bc_main_type)
- {
- case _SLANG_BC_BLOCK:
- if (lang_free_branch(p->b.blk))
- SLfree((char *)p->b.blk);
- break;
-
- case _SLANG_BC_LITERAL:
- case _SLANG_BC_LITERAL_STR:
- /* No user types should be here. */
- cl = _SLclass_get_class (p->bc_sub_type);
- (*cl->cl_byte_code_destroy) (p->bc_sub_type, (VOID_STAR) &p->b.ptr_blk);
- break;
-
- case _SLANG_BC_FIELD:
- case _SLANG_BC_SET_STRUCT_LVALUE:
- SLang_free_slstring (p->b.s_blk);
- break;
-
- default:
- break;
-
- case 0:
- return 1;
- }
- p++;
- }
-}
-
-static void free_function_header (_SLBlock_Header_Type *h)
-{
- if (h->num_refs > 1)
- {
- h->num_refs--;
- return;
- }
-
- if (h->body != NULL)
- {
- if (lang_free_branch (h->body))
- SLfree ((char *) h->body);
- }
-
- SLfree ((char *) h);
-}
-
-static int push_block_context (int type)
-{
- Block_Context_Type *c;
- unsigned int num;
- SLBlock_Type *b;
-
- if (Block_Context_Stack_Len == SLANG_MAX_BLOCK_STACK_LEN)
- {
- SLang_verror (SL_STACK_OVERFLOW, "Block stack overflow");
- return -1;
- }
-
- num = 5; /* 40 bytes */
- if (NULL == (b = (SLBlock_Type *) SLcalloc (num, sizeof (SLBlock_Type))))
- return -1;
-
- c = Block_Context_Stack + Block_Context_Stack_Len;
- c->block = This_Compile_Block;
- c->block_ptr = Compile_ByteCode_Ptr;
- c->block_max = This_Compile_Block_Max;
- c->block_type = This_Compile_Block_Type;
- c->static_namespace = This_Static_NameSpace;
-
- Compile_ByteCode_Ptr = This_Compile_Block = b;
- This_Compile_Block_Max = b + num;
- This_Compile_Block_Type = type;
-
- Block_Context_Stack_Len += 1;
- return 0;
-}
-
-static int pop_block_context (void)
-{
- Block_Context_Type *c;
-
- if (Block_Context_Stack_Len == 0)
- return -1;
-
- Block_Context_Stack_Len -= 1;
- c = Block_Context_Stack + Block_Context_Stack_Len;
-
- This_Compile_Block = c->block;
- This_Compile_Block_Max = c->block_max;
- This_Compile_Block_Type = c->block_type;
- Compile_ByteCode_Ptr = c->block_ptr;
- This_Static_NameSpace = c->static_namespace;
-
- return 0;
-}
-
-int _SLcompile_push_context (SLang_Load_Type *load_object)
-{
- if (-1 == push_compile_context (load_object->name))
- return -1;
-
- if (NULL == (This_Static_NameSpace = _SLns_allocate_namespace (load_object->name, SLSTATIC_HASH_TABLE_SIZE)))
- {
- pop_compile_context ();
- return -1;
- }
-
- if (-1 == push_block_context (COMPILE_BLOCK_TYPE_TOP_LEVEL))
- {
- pop_compile_context ();
- return -1;
- }
-
- return 0;
-}
-
-int _SLcompile_pop_context (void)
-{
- if (This_Compile_Block_Type == COMPILE_BLOCK_TYPE_TOP_LEVEL)
- {
- Compile_ByteCode_Ptr->bc_main_type = 0;
- if (lang_free_branch (This_Compile_Block))
- SLfree ((char *) This_Compile_Block);
- }
-
- (void) pop_block_context ();
- (void) pop_compile_context ();
-
- if (This_Compile_Block == NULL)
- return 0;
-
-#if 0
- if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_TOP_LEVEL)
- {
- SLang_verror (SL_INTERNAL_ERROR, "Not at top-level");
- return -1;
- }
-#endif
-
- return 0;
-}
-
-/*{{{ Hash and Name Table Functions */
-
-static SLang_Name_Type *locate_name_in_table (char *name, unsigned long hash,
- SLang_Name_Type **table, unsigned int table_size)
-{
- SLang_Name_Type *t;
- char ch;
-
- t = table [(unsigned int) (hash % table_size)];
- ch = *name++;
-
- while (t != NULL)
- {
- if ((ch == t->name[0])
- && (0 == strcmp (t->name + 1, name)))
- break;
-
- t = t->next;
- }
-
- return t;
-}
-
-static SLang_Name_Type *locate_namespace_encoded_name (char *name, int err_on_bad_ns)
-{
- char *ns, *ns1;
- SLang_NameSpace_Type *table;
- SLang_Name_Type *nt;
-
- ns = name;
- name = strchr (name, '-');
- if ((name == NULL) || (name [1] != '>'))
- name = ns;
-
- ns1 = SLang_create_nslstring (ns, (unsigned int) (name - ns));
- if (ns1 == NULL)
- return NULL;
- if (ns != name)
- name += 2;
- ns = ns1;
-
- if (*ns == 0)
- {
- /* Use Global Namespace */
- SLang_free_slstring (ns);
- return locate_name_in_table (name, _SLcompute_string_hash (name),
- Global_NameSpace->table, Global_NameSpace->table_size);
- }
-
- if (NULL == (table = _SLns_find_namespace (ns)))
- {
- if (err_on_bad_ns)
- SLang_verror (SL_SYNTAX_ERROR, "Unable to find namespace called %s", ns);
- SLang_free_slstring (ns);
- return NULL;
- }
- SLang_free_slstring (ns);
-
- /* FIXME: the hash table size should be stored in the hash table itself */
- nt = locate_name_in_table (name, _SLcompute_string_hash (name),
- table->table, table->table_size);
- if (nt == NULL)
- return NULL;
-
- switch (nt->name_type)
- {
- /* These are private and cannot be accessed through the namespace. */
- case SLANG_PVARIABLE:
- case SLANG_PFUNCTION:
- return NULL;
- }
- return nt;
-}
-
-static SLang_Name_Type *locate_hashed_name (char *name, unsigned long hash)
-{
- SLang_Name_Type *t;
-
- if (Lang_Defining_Function)
- {
- t = locate_name_in_table (name, hash, Locals_Hash_Table, SLLOCALS_HASH_TABLE_SIZE);
- if (t != NULL)
- return t;
- }
-
- if ((This_Static_NameSpace != NULL)
- && (NULL != (t = locate_name_in_table (name, hash, This_Static_NameSpace->table, This_Static_NameSpace->table_size))))
- return t;
-
- t = locate_name_in_table (name, hash, Global_NameSpace->table, Global_NameSpace->table_size);
- if (NULL != t)
- return t;
-
- return locate_namespace_encoded_name (name, 1);
-}
-
-SLang_Name_Type *_SLlocate_name (char *name)
-{
- return locate_hashed_name (name, _SLcompute_string_hash (name));
-}
-
-static SLang_Name_Type *
-add_name_to_hash_table (char *name, unsigned long hash,
- unsigned int sizeof_obj, unsigned char name_type,
- SLang_Name_Type **table, unsigned int table_size,
- int check_existing)
-{
- SLang_Name_Type *t;
-
- if (check_existing)
- {
- t = locate_name_in_table (name, hash, table, table_size);
- if (t != NULL)
- return t;
- }
-
- if (-1 == _SLcheck_identifier_syntax (name))
- return NULL;
-
- t = (SLang_Name_Type *) SLmalloc (sizeof_obj);
- if (t == NULL)
- return t;
-
- memset ((char *) t, 0, sizeof_obj);
- if (NULL == (t->name = _SLstring_dup_hashed_string (name, hash)))
- {
- SLfree ((char *) t);
- return NULL;
- }
- t->name_type = name_type;
-
- hash = hash % table_size;
- t->next = table [(unsigned int)hash];
- table [(unsigned int) hash] = t;
-
- return t;
-}
-
-static SLang_Name_Type *
-add_global_name (char *name, unsigned long hash,
- unsigned char name_type, unsigned int sizeof_obj,
- SLang_NameSpace_Type *ns)
-{
- SLang_Name_Type *nt;
- SLang_Name_Type **table;
- unsigned int table_size;
-
- table = ns->table;
- table_size = ns->table_size;
-
- nt = locate_name_in_table (name, hash, table, table_size);
- if (nt != NULL)
- {
- if (nt->name_type == name_type)
- return nt;
-
- SLang_verror (SL_DUPLICATE_DEFINITION, "%s cannot be re-defined", name);
- return NULL;
- }
-
- return add_name_to_hash_table (name, hash, sizeof_obj, name_type,
- table, table_size, 0);
-}
-
-static int add_intrinsic_function (SLang_NameSpace_Type *ns,
- char *name, FVOID_STAR addr, unsigned char ret_type,
- unsigned int nargs, va_list ap)
-{
- SLang_Intrin_Fun_Type *f;
- unsigned int i;
-
- if (-1 == init_interpreter ())
- return -1;
-
- if (ns == NULL) ns = Global_NameSpace;
-
- if (nargs > SLANG_MAX_INTRIN_ARGS)
- {
- SLang_verror (SL_APPLICATION_ERROR, "Function %s requires too many arguments", name);
- return -1;
- }
-
- if (ret_type == SLANG_FLOAT_TYPE)
- {
- SLang_verror (SL_NOT_IMPLEMENTED, "Function %s is not permitted to return float", name);
- return -1;
- }
-
- f = (SLang_Intrin_Fun_Type *) add_global_name (name, _SLcompute_string_hash (name),
- SLANG_INTRINSIC, sizeof (SLang_Intrin_Fun_Type),
- ns);
-
- if (f == NULL)
- return -1;
-
- f->i_fun = addr;
- f->num_args = nargs;
- f->return_type = ret_type;
-
- for (i = 0; i < nargs; i++)
- f->arg_types [i] = va_arg (ap, unsigned int);
-
- return 0;
-}
-
-int SLadd_intrinsic_function (char *name, FVOID_STAR addr, unsigned char ret_type,
- unsigned int nargs, ...)
-{
- va_list ap;
- int status;
-
- va_start (ap, nargs);
- status = add_intrinsic_function (NULL, name, addr, ret_type, nargs, ap);
- va_end (ap);
-
- return status;
-}
-
-int SLns_add_intrinsic_function (SLang_NameSpace_Type *ns,
- char *name, FVOID_STAR addr, unsigned char ret_type,
- unsigned int nargs, ...)
-{
- va_list ap;
- int status;
-
- va_start (ap, nargs);
- status = add_intrinsic_function (ns, name, addr, ret_type, nargs, ap);
- va_end (ap);
-
- return status;
-}
-
-int SLns_add_intrinsic_variable (SLang_NameSpace_Type *ns,
- char *name, VOID_STAR addr, unsigned char data_type, int ro)
-{
- SLang_Intrin_Var_Type *v;
-
- if (-1 == init_interpreter ())
- return -1;
-
- if (ns == NULL) ns = Global_NameSpace;
-
- v = (SLang_Intrin_Var_Type *)add_global_name (name,
- _SLcompute_string_hash (name),
- (ro ? SLANG_RVARIABLE : SLANG_IVARIABLE),
- sizeof (SLang_Intrin_Var_Type),
- ns);
- if (v == NULL)
- return -1;
-
- v->addr = addr;
- v->type = data_type;
- return 0;
-}
-
-int SLadd_intrinsic_variable (char *name, VOID_STAR addr, unsigned char data_type, int ro)
-{
- return SLns_add_intrinsic_variable (NULL, name, addr, data_type, ro);
-}
-
-static int
-add_slang_function (char *name, unsigned char type, unsigned long hash,
- unsigned int num_args, unsigned int num_locals,
-#if _SLANG_HAS_DEBUG_CODE
- char *file,
-#endif
- _SLBlock_Header_Type *h,
- SLang_NameSpace_Type *ns)
-{
- _SLang_Function_Type *f;
-
-#if _SLANG_HAS_DEBUG_CODE
- if ((file != NULL)
- && (NULL == (file = SLang_create_slstring (file))))
- return -1;
-#endif
-
- f = (_SLang_Function_Type *)add_global_name (name, hash,
- type,
- sizeof (_SLang_Function_Type),
- ns);
- if (f == NULL)
- {
-#if _SLANG_HAS_DEBUG_CODE
- SLang_free_slstring (file); /* NULL ok */
-#endif
- return -1;
- }
-
- if (f->v.header != NULL)
- {
- if (f->nlocals == AUTOLOAD_NUM_LOCALS)
- SLang_free_slstring ((char *)f->v.autoload_filename); /* autoloaded filename */
- else
- free_function_header (f->v.header);
- }
-
-#if _SLANG_HAS_DEBUG_CODE
- if (f->file != NULL) SLang_free_slstring (f->file);
- f->file = file;
-#endif
- f->v.header = h;
- f->nlocals = num_locals;
- f->nargs = num_args;
-
- return 0;
-}
-
-int SLang_autoload (char *name, char *file)
-{
- _SLang_Function_Type *f;
- unsigned long hash;
-
- hash = _SLcompute_string_hash (name);
- f = (_SLang_Function_Type *)locate_name_in_table (name, hash, Global_NameSpace->table, Global_NameSpace->table_size);
-
- if ((f != NULL)
- && (f->name_type == SLANG_FUNCTION)
- && (f->v.header != NULL)
- && (f->nlocals != AUTOLOAD_NUM_LOCALS))
- {
- /* already loaded */
- return 0;
- }
-
- file = SLang_create_slstring (file);
- if (-1 == add_slang_function (name, SLANG_FUNCTION, hash, 0, AUTOLOAD_NUM_LOCALS,
-#if _SLANG_HAS_DEBUG_CODE
- file,
-#endif
- (_SLBlock_Header_Type *) file,
- Global_NameSpace))
- {
- SLang_free_slstring (file);
- return -1;
- }
-
- return 0;
-}
-
-SLang_Name_Type *_SLlocate_global_name (char *name)
-{
- unsigned long hash;
-
- hash = _SLcompute_string_hash (name);
- return locate_name_in_table (name, hash, Global_NameSpace->table,
- Global_NameSpace->table_size);
-}
-
-/*}}}*/
-
-static void free_local_variable_table (void)
-{
- unsigned int i;
- SLang_Name_Type *t, *t1;
-
- for (i = 0; i < SLLOCALS_HASH_TABLE_SIZE; i++)
- {
- t = Locals_Hash_Table [i];
- while (t != NULL)
- {
- SLang_free_slstring (t->name);
- t1 = t->next;
- SLfree ((char *) t);
- t = t1;
- }
- Locals_Hash_Table [i] = NULL;
- }
- Local_Variable_Number = 0;
-}
-
-/* call inner interpreter or return for more */
-static void lang_try_now(void)
-{
- Compile_ByteCode_Ptr++;
- if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_TOP_LEVEL)
- return;
-
- Compile_ByteCode_Ptr->bc_main_type = 0; /* so next command stops after this */
-
- /* now do it */
- inner_interp (This_Compile_Block);
- (void) lang_free_branch (This_Compile_Block);
- Compile_ByteCode_Ptr = This_Compile_Block;
-}
-
-SLang_Name_Type *SLang_get_fun_from_ref (SLang_Ref_Type *ref)
-{
- if (ref->is_global)
- {
- SLang_Name_Type *nt = ref->v.nt;
-
- switch (nt->name_type)
- {
- case SLANG_PFUNCTION:
- case SLANG_FUNCTION:
- case SLANG_INTRINSIC:
- case SLANG_MATH_UNARY:
- case SLANG_APP_UNARY:
- return nt;
- }
- SLang_verror (SL_TYPE_MISMATCH,
- "Reference to a function expected. Found &%s",
- nt->name);
- }
-
- SLang_verror (SL_TYPE_MISMATCH,
- "Reference to a function expected");
- return NULL;
-}
-
-int SLexecute_function (SLang_Name_Type *nt)
-{
- unsigned char type;
- char *name;
-
- if (SLang_Error)
- return -1;
-
- type = nt->name_type;
- name = nt->name;
-
- switch (type)
- {
- case SLANG_PFUNCTION:
- case SLANG_FUNCTION:
- execute_slang_fun ((_SLang_Function_Type *) nt);
- break;
-
- case SLANG_INTRINSIC:
- execute_intrinsic_fun ((SLang_Intrin_Fun_Type *) nt);
- break;
-
- case SLANG_MATH_UNARY:
- case SLANG_APP_UNARY:
- inner_interp_nametype (nt);
- break;
-
- default:
- SLang_verror (SL_TYPE_MISMATCH, "%s is not a function", name);
- return -1;
- }
-
- if (SLang_Error)
- {
- SLang_verror (SLang_Error, "Error while executing %s", name);
- return -1;
- }
-
- return 1;
-}
-
-int SLang_execute_function (char *name)
-{
- SLang_Name_Type *entry;
-
- if (NULL == (entry = SLang_get_function (name)))
- return 0;
-
- return SLexecute_function (entry);
-}
-
-/* return S-Lang function or NULL */
-SLang_Name_Type *SLang_get_function (char *name)
-{
- SLang_Name_Type *entry;
-
- if (NULL == (entry = locate_namespace_encoded_name (name, 0)))
- return NULL;
-
- if ((entry->name_type == SLANG_FUNCTION)
- || (entry->name_type == SLANG_INTRINSIC))
- return entry;
-
- return NULL;
-}
-
-static void lang_begin_function (void)
-{
- if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_TOP_LEVEL)
- {
- SLang_verror (SL_SYNTAX_ERROR, "Function nesting is illegal");
- return;
- }
- Lang_Defining_Function = 1;
- (void) push_block_context (COMPILE_BLOCK_TYPE_FUNCTION);
-}
-
-#if USE_COMBINED_BYTECODES
-static void optimize_block (SLBlock_Type *b)
-{
- while (1)
- {
- switch (b->bc_main_type)
- {
- case 0:
- return;
-
- default:
- b++;
- break;
-
- case _SLANG_BC_CALL_DIRECT:
- b++;
- switch (b->bc_main_type)
- {
- case 0:
- return;
- case _SLANG_BC_INTRINSIC:
- if ((b+1)->bc_main_type == 0)
- {
- (b-1)->bc_main_type = _SLANG_BC_CALL_DIRECT_INTRSTOP;
- return;
- }
- (b-1)->bc_main_type = _SLANG_BC_CALL_DIRECT_INTRINSIC;
- b++;
- break;
- case _SLANG_BC_LITERAL_STR:
- (b-1)->bc_main_type = _SLANG_BC_CALL_DIRECT_LSTR;
- b++;
- break;
- case _SLANG_BC_FUNCTION:
- case _SLANG_BC_PFUNCTION:
- (b-1)->bc_main_type = _SLANG_BC_CALL_DIRECT_SLFUN;
- b++;
- break;
- case _SLANG_BC_EARG_LVARIABLE:
- (b-1)->bc_main_type = _SLANG_BC_CALL_DIRECT_EARG_LVAR;
- b++;
- break;
- case _SLANG_BC_LITERAL_INT:
- (b-1)->bc_main_type = _SLANG_BC_CALL_DIRECT_LINT;
- b++;
- break;
- case _SLANG_BC_LVARIABLE:
- (b-1)->bc_main_type = _SLANG_BC_CALL_DIRECT_LVAR;
- b++;
- break;
- }
- break;
-
- case _SLANG_BC_INTRINSIC:
- b++;
- switch (b->bc_main_type)
- {
- case _SLANG_BC_CALL_DIRECT:
- (b-1)->bc_main_type = _SLANG_BC_INTRINSIC_CALL_DIRECT;
- b++;
- break;
-#if 0
- case _SLANG_BC_BLOCK:
- (b-1)->bc_main_type = _SLANG_BC_INTRINSIC_BLOCK;
- b++;
- break;
-#endif
-
- case 0:
- (b-1)->bc_main_type = _SLANG_BC_INTRINSIC_STOP;
- return;
- }
- break;
- }
- }
-}
-
-#endif
-
-
-/* name will be NULL if the object is to simply terminate the function
- * definition. See SLang_restart.
- */
-static int lang_define_function (char *name, unsigned char type, unsigned long hash,
- SLang_NameSpace_Type *ns)
-{
- if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_FUNCTION)
- {
- SLang_verror (SL_SYNTAX_ERROR, "Premature end of function");
- return -1;
- }
-
- /* terminate function */
- Compile_ByteCode_Ptr->bc_main_type = 0;
-
- if (name != NULL)
- {
- _SLBlock_Header_Type *h;
-
- h = (_SLBlock_Header_Type *)SLmalloc (sizeof (_SLBlock_Header_Type));
- if (h != NULL)
- {
- h->num_refs = 1;
- h->body = This_Compile_Block;
-
-#if USE_COMBINED_BYTECODES
- optimize_block (h->body);
-#endif
-
- if (-1 == add_slang_function (name, type, hash,
- Function_Args_Number,
- Local_Variable_Number,
-#if _SLANG_HAS_DEBUG_CODE
- This_Compile_Filename,
-#endif
- h, ns))
- SLfree ((char *) h);
- }
- /* Drop through for clean-up */
- }
-
- free_local_variable_table ();
-
- Function_Args_Number = 0;
- Lang_Defining_Function = 0;
-
- if (SLang_Error) return -1;
- /* SLang_restart will finish this if there is a slang error. */
-
- pop_block_context ();
-
- /* A function is only defined at top-level */
- if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_TOP_LEVEL)
- {
- SLang_verror (SL_INTERNAL_ERROR, "Not at top-level");
- return -1;
- }
- Compile_ByteCode_Ptr = This_Compile_Block;
- return 0;
-}
-
-static void define_static_function (char *name, unsigned long hash)
-{
- (void) lang_define_function (name, SLANG_FUNCTION, hash, This_Static_NameSpace);
-}
-
-static void define_private_function (char *name, unsigned long hash)
-{
- (void) lang_define_function (name, SLANG_PFUNCTION, hash, This_Static_NameSpace);
-}
-
-static void define_public_function (char *name, unsigned long hash)
-{
- (void) lang_define_function (name, SLANG_FUNCTION, hash, Global_NameSpace);
-}
-
-static void lang_end_block (void)
-{
- SLBlock_Type *node, *branch;
- unsigned char mtype;
-
- if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_BLOCK)
- {
- SLang_verror (SL_SYNTAX_ERROR, "Not defining a block");
- return;
- }
-
- /* terminate the block */
- Compile_ByteCode_Ptr->bc_main_type = 0;
- branch = This_Compile_Block;
-
- /* Try to save some space by using the cached blocks. */
- if (Compile_ByteCode_Ptr == branch + 1)
- {
- mtype = branch->bc_main_type;
- if (((mtype == _SLANG_BC_BREAK)
- || (mtype == _SLANG_BC_CONTINUE)
- || (mtype == _SLANG_BC_RETURN))
- && (SLang_Error == 0))
- {
- SLfree ((char *)branch);
- branch = SLShort_Blocks + 2 * (int) (mtype - _SLANG_BC_RETURN);
- }
- }
-
-#if USE_COMBINED_BYTECODES
- optimize_block (branch);
-#endif
-
- pop_block_context ();
- node = Compile_ByteCode_Ptr++;
-
- node->bc_main_type = _SLANG_BC_BLOCK;
- node->bc_sub_type = 0;
- node->b.blk = branch;
-}
-
-static int lang_begin_block (void)
-{
- return push_block_context (COMPILE_BLOCK_TYPE_BLOCK);
-}
-
-static int lang_check_space (void)
-{
- unsigned int n;
- SLBlock_Type *p;
-
- if (NULL == (p = This_Compile_Block))
- {
- SLang_verror (SL_INTERNAL_ERROR, "Top-level block not present");
- return -1;
- }
-
- /* Allow 1 extra for terminator */
- if (Compile_ByteCode_Ptr + 1 < This_Compile_Block_Max)
- return 0;
-
- n = (unsigned int) (This_Compile_Block_Max - p);
-
- /* enlarge the space by 2 objects */
- n += 2;
-
- if (NULL == (p = (SLBlock_Type *) SLrealloc((char *)p, n * sizeof(SLBlock_Type))))
- return -1;
-
- This_Compile_Block_Max = p + n;
- n = (unsigned int) (Compile_ByteCode_Ptr - This_Compile_Block);
- This_Compile_Block = p;
- Compile_ByteCode_Ptr = p + n;
-
- return 0;
-}
-
-/* returns positive number if name is a function or negative number if it
- is a variable. If it is intrinsic, it returns magnitude of 1, else 2 */
-int SLang_is_defined(char *name)
-{
- SLang_Name_Type *t;
-
- if (-1 == init_interpreter ())
- return -1;
-
- t = locate_namespace_encoded_name (name, 0);
- if (t == NULL)
- return 0;
-
- switch (t->name_type)
- {
- case SLANG_FUNCTION:
- /* case SLANG_PFUNCTION: */
- return 2;
- case SLANG_GVARIABLE:
- /* case SLANG_PVARIABLE: */
- return -2;
-
- case SLANG_ICONSTANT:
- case SLANG_DCONSTANT:
- case SLANG_RVARIABLE:
- case SLANG_IVARIABLE:
- return -1;
-
- case SLANG_INTRINSIC:
- default:
- return 1;
- }
-}
-
-static int add_global_variable (char *name, char name_type, unsigned long hash,
- SLang_NameSpace_Type *ns)
-{
- SLang_Name_Type *g;
-
- /* Note the importance of checking if it is already defined or not. For example,
- * suppose X is defined as an intrinsic variable. Then S-Lang code like:
- * !if (is_defined("X")) { variable X; }
- * will not result in a global variable X. On the other hand, this would
- * not be an issue if 'variable' statements always were not processed
- * immediately. That is, as it is now, 'if (0) {variable ZZZZ;}' will result
- * in the variable ZZZZ being defined because of the immediate processing.
- * The current solution is to do: if (0) { eval("variable ZZZZ;"); }
- */
- /* hash = _SLcompute_string_hash (name); */
- g = locate_name_in_table (name, hash, ns->table, ns->table_size);
-
- if (g != NULL)
- {
- if (g->name_type == name_type)
- return 0;
- }
-
- if (NULL == add_global_name (name, hash, name_type,
- sizeof (SLang_Global_Var_Type), ns))
- return -1;
-
- return 0;
-}
-
-int SLadd_global_variable (char *name)
-{
- if (-1 == init_interpreter ())
- return -1;
-
- return add_global_variable (name, SLANG_GVARIABLE,
- _SLcompute_string_hash (name),
- Global_NameSpace);
-}
-
-static int add_local_variable (char *name, unsigned long hash)
-{
- SLang_Local_Var_Type *t;
-
- /* local variable */
- if (Local_Variable_Number >= SLANG_MAX_LOCAL_VARIABLES)
- {
- SLang_verror (SL_SYNTAX_ERROR, "Too many local variables");
- return -1;
- }
-
- if (NULL != locate_name_in_table (name, hash, Locals_Hash_Table, SLLOCALS_HASH_TABLE_SIZE))
- {
- SLang_verror (SL_SYNTAX_ERROR, "Local variable %s has already been defined", name);
- return -1;
- }
-
- t = (SLang_Local_Var_Type *)
- add_name_to_hash_table (name, hash,
- sizeof (SLang_Local_Var_Type), SLANG_LVARIABLE,
- Locals_Hash_Table, SLLOCALS_HASH_TABLE_SIZE, 0);
- if (t == NULL)
- return -1;
-
- t->local_var_number = Local_Variable_Number;
- Local_Variable_Number++;
- return 0;
-}
-
-static void (*Compile_Mode_Function) (_SLang_Token_Type *);
-static void compile_basic_token_mode (_SLang_Token_Type *);
-
-/* if an error occurs, discard current object, block, function, etc... */
-void SLang_restart (int localv)
-{
- int save = SLang_Error;
-
- SLang_Error = SL_UNKNOWN_ERROR;
-
- _SLcompile_ptr = _SLcompile;
- Compile_Mode_Function = compile_basic_token_mode;
-
- Lang_Break = /* Lang_Continue = */ Lang_Return = 0;
- Trace_Mode = 0;
-
- while (This_Compile_Block_Type == COMPILE_BLOCK_TYPE_BLOCK)
- lang_end_block();
-
- if (This_Compile_Block_Type == COMPILE_BLOCK_TYPE_FUNCTION)
- {
- /* Terminate function definition and free variables */
- lang_define_function (NULL, SLANG_FUNCTION, 0, Global_NameSpace);
- if (lang_free_branch (This_Compile_Block))
- SLfree((char *)This_Compile_Block);
- }
- Lang_Defining_Function = 0;
-
- SLang_Error = save;
-
- if (SLang_Error == SL_STACK_OVERFLOW)
- {
- /* This loop guarantees that the stack is properly cleaned. */
- while (_SLStack_Pointer != _SLRun_Stack)
- {
- SLdo_pop ();
- }
- }
-
- while ((This_Compile_Block_Type != COMPILE_BLOCK_TYPE_TOP_LEVEL)
- && (0 == pop_block_context ()))
- ;
-
- if (localv)
- {
- Next_Function_Num_Args = SLang_Num_Function_Args = 0;
- Local_Variable_Frame = Local_Variable_Stack;
- Recursion_Depth = 0;
- Frame_Pointer = _SLStack_Pointer;
- Frame_Pointer_Depth = 0;
- Switch_Obj_Ptr = Switch_Objects;
- while (Switch_Obj_Ptr < Switch_Obj_Max)
- {
- SLang_free_object (Switch_Obj_Ptr);
- Switch_Obj_Ptr++;
- }
- Switch_Obj_Ptr = Switch_Objects;
- }
-}
-
-static void compile_directive (unsigned char sub_type)
-{
- /* This function is called only from compile_directive_mode which is
- * only possible when a block is available.
- */
-
- /* use BLOCK */
- Compile_ByteCode_Ptr--;
- Compile_ByteCode_Ptr->bc_sub_type = sub_type;
-
- lang_try_now ();
-}
-
-static void compile_unary (int op, unsigned char mt)
-{
- Compile_ByteCode_Ptr->bc_main_type = mt;
- Compile_ByteCode_Ptr->b.i_blk = op;
- Compile_ByteCode_Ptr->bc_sub_type = 0;
-
- lang_try_now ();
-}
-
-
-static void compile_binary (int op)
-{
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_BINARY;
- Compile_ByteCode_Ptr->b.i_blk = op;
- Compile_ByteCode_Ptr->bc_sub_type = 0;
-
- lang_try_now ();
-}
-
-#if _SLANG_OPTIMIZE_FOR_SPEED
-static int try_compressed_bytecode (unsigned char last_bc, unsigned char bc)
-{
- if (Compile_ByteCode_Ptr != This_Compile_Block)
- {
- SLBlock_Type *b;
- b = Compile_ByteCode_Ptr - 1;
- if (b->bc_main_type == last_bc)
- {
- Compile_ByteCode_Ptr = b;
- b->bc_main_type = bc;
- lang_try_now ();
- return 0;
- }
- }
- return -1;
-}
-#endif
-
-static void compile_fast_binary (int op, unsigned char bc)
-{
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (0 == try_compressed_bytecode (_SLANG_BC_LITERAL_INT, bc))
- return;
-#else
- (void) bc;
-#endif
- compile_binary (op);
-}
-
-/* This is a hack */
-typedef struct _Special_NameTable_Type
-{
- char *name;
- int (*fun) (struct _Special_NameTable_Type *, _SLang_Token_Type *);
- VOID_STAR blk_data;
- unsigned char main_type;
-}
-Special_NameTable_Type;
-
-static int handle_special (Special_NameTable_Type *nt, _SLang_Token_Type *tok)
-{
- (void) tok;
- Compile_ByteCode_Ptr->bc_main_type = nt->main_type;
- Compile_ByteCode_Ptr->b.ptr_blk = nt->blk_data;
- return 0;
-}
-
-static int handle_special_file (Special_NameTable_Type *nt, _SLang_Token_Type *tok)
-{
- char *name;
-
- (void) nt; (void) tok;
-
- if (This_Static_NameSpace == NULL) name = "***Unknown***";
- else
- name = This_Static_NameSpace->name;
-
- name = SLang_create_slstring (name);
- if (name == NULL)
- return -1;
-
- Compile_ByteCode_Ptr->b.s_blk = name;
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_LITERAL_STR;
- Compile_ByteCode_Ptr->bc_sub_type = SLANG_STRING_TYPE;
- return 0;
-}
-
-static int handle_special_line (Special_NameTable_Type *nt, _SLang_Token_Type *tok)
-{
- (void) nt;
-
-#if _SLANG_HAS_DEBUG_CODE
- Compile_ByteCode_Ptr->b.l_blk = (long) tok->line_number;
-#endif
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_LITERAL;
- Compile_ByteCode_Ptr->bc_sub_type = SLANG_UINT_TYPE;
-
- return 0;
-}
-
-static Special_NameTable_Type Special_Name_Table [] =
-{
- {"EXECUTE_ERROR_BLOCK", handle_special, NULL, _SLANG_BC_X_ERROR},
- {"X_USER_BLOCK0", handle_special, NULL, _SLANG_BC_X_USER0},
- {"X_USER_BLOCK1", handle_special, NULL, _SLANG_BC_X_USER1},
- {"X_USER_BLOCK2", handle_special, NULL, _SLANG_BC_X_USER2},
- {"X_USER_BLOCK3", handle_special, NULL, _SLANG_BC_X_USER3},
- {"X_USER_BLOCK4", handle_special, NULL, _SLANG_BC_X_USER4},
- {"__FILE__", handle_special_file, NULL, 0},
- {"__LINE__", handle_special_line, NULL, 0},
-#if 0
- {"__NAMESPACE__", handle_special_namespace, NULL, 0},
-#endif
- {NULL, NULL, NULL, 0}
-};
-
-static void compile_hashed_identifier (char *name, unsigned long hash, _SLang_Token_Type *tok)
-{
- SLang_Name_Type *entry;
- unsigned char name_type;
-
- entry = locate_hashed_name (name, hash);
-
- if (entry == NULL)
- {
- Special_NameTable_Type *nt = Special_Name_Table;
-
- while (nt->name != NULL)
- {
- if (strcmp (name, nt->name))
- {
- nt++;
- continue;
- }
-
- if (0 == (*nt->fun)(nt, tok))
- lang_try_now ();
- return;
- }
-
- SLang_verror (SL_UNDEFINED_NAME, "%s is undefined", name);
- return;
- }
-
- name_type = entry->name_type;
- Compile_ByteCode_Ptr->bc_main_type = name_type;
-
- if (name_type == SLANG_LVARIABLE)
- Compile_ByteCode_Ptr->b.i_blk = ((SLang_Local_Var_Type *) entry)->local_var_number;
- else
- Compile_ByteCode_Ptr->b.nt_blk = entry;
-
- lang_try_now ();
-}
-
-static void compile_tmp_variable (char *name, unsigned long hash)
-{
- SLang_Name_Type *entry;
- unsigned char name_type;
-
- if (NULL == (entry = locate_hashed_name (name, hash)))
- {
- SLang_verror (SL_UNDEFINED_NAME, "%s is undefined", name);
- return;
- }
-
- name_type = entry->name_type;
- switch (name_type)
- {
- case SLANG_LVARIABLE:
- Compile_ByteCode_Ptr->b.i_blk = ((SLang_Local_Var_Type *) entry)->local_var_number;
- break;
-
- case SLANG_GVARIABLE:
- case SLANG_PVARIABLE:
- Compile_ByteCode_Ptr->b.nt_blk = entry;
- break;
-
- default:
- SLang_verror (SL_SYNTAX_ERROR, "__tmp(%s) does not specifiy a variable", name);
- return;
- }
-
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_TMP;
- Compile_ByteCode_Ptr->bc_sub_type = name_type;
-
- lang_try_now ();
-}
-
-static void compile_simple (unsigned char main_type)
-{
- Compile_ByteCode_Ptr->bc_main_type = main_type;
- Compile_ByteCode_Ptr->bc_sub_type = 0;
- Compile_ByteCode_Ptr->b.blk = NULL;
- lang_try_now ();
-}
-
-static void compile_identifier (char *name, _SLang_Token_Type *tok)
-{
- compile_hashed_identifier (name, _SLcompute_string_hash (name), tok);
-}
-
-static void compile_call_direct (int (*f) (void), unsigned char byte_code)
-{
- Compile_ByteCode_Ptr->b.call_function = f;
- Compile_ByteCode_Ptr->bc_main_type = byte_code;
- Compile_ByteCode_Ptr->bc_sub_type = 0;
- lang_try_now ();
-}
-
-static void compile_lvar_call_direct (int (*f)(void), unsigned char bc,
- unsigned char frame_op)
-{
-#if _SLANG_OPTIMIZE_FOR_SPEED
- if (0 == try_compressed_bytecode (_SLANG_BC_LVARIABLE, bc))
- return;
-#else
- (void) bc;
-#endif
-
- compile_call_direct (f, frame_op);
-}
-
-static void compile_integer (long i, unsigned char bc_main_type, unsigned char bc_sub_type)
-{
- Compile_ByteCode_Ptr->b.l_blk = i;
- Compile_ByteCode_Ptr->bc_main_type = bc_main_type;
- Compile_ByteCode_Ptr->bc_sub_type = bc_sub_type;
-
- lang_try_now ();
-}
-
-#if SLANG_HAS_FLOAT
-static void compile_double (char *str, unsigned char type)
-{
- double d;
- unsigned int factor = 1;
- double *ptr;
-
-#if 1
- d = _SLang_atof (str);
-#else
- if (1 != sscanf (str, "%lf", &d))
- {
- SLang_verror (SL_SYNTAX_ERROR, "Unable to convert %s to double", str);
- return;
- }
-#endif
-
-#if SLANG_HAS_COMPLEX
- if (type == SLANG_COMPLEX_TYPE) factor = 2;
-#endif
- if (NULL == (ptr = (double *) SLmalloc(factor * sizeof(double))))
- return;
-
- Compile_ByteCode_Ptr->b.double_blk = ptr;
-#if SLANG_HAS_COMPLEX
- if (type == SLANG_COMPLEX_TYPE)
- *ptr++ = 0;
-#endif
- *ptr = d;
-
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_LITERAL;
- Compile_ByteCode_Ptr->bc_sub_type = type;
- lang_try_now ();
-}
-
-static void compile_float (char *s)
-{
- float x;
-
-#if 1
- x = (float) _SLang_atof (s);
-#else
- if (1 != sscanf (s, "%f", &x))
- {
- SLang_verror (SL_SYNTAX_ERROR, "Unable to convert %s to float", s);
- return;
- }
-#endif
- Compile_ByteCode_Ptr->b.float_blk = x;
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_LITERAL;
- Compile_ByteCode_Ptr->bc_sub_type = SLANG_FLOAT_TYPE;
- lang_try_now ();
-}
-
-#endif
-
-static void compile_string (char *s, unsigned long hash)
-{
- if (NULL == (Compile_ByteCode_Ptr->b.s_blk = _SLstring_dup_hashed_string (s, hash)))
- return;
-
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_LITERAL_STR;
- Compile_ByteCode_Ptr->bc_sub_type = SLANG_STRING_TYPE;
-
- lang_try_now ();
-}
-
-static void compile_bstring (SLang_BString_Type *s)
-{
- if (NULL == (Compile_ByteCode_Ptr->b.bs_blk = SLbstring_dup (s)))
- return;
-
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_LITERAL;
- Compile_ByteCode_Ptr->bc_sub_type = SLANG_BSTRING_TYPE;
-
- lang_try_now ();
-}
-
-/* assign_type is one of _SLANG_BCST_ASSIGN, ... values */
-static void compile_assign (unsigned char assign_type,
- char *name, unsigned long hash)
-{
- SLang_Name_Type *v;
- unsigned char main_type;
- SLang_Class_Type *cl;
-
- v = locate_hashed_name (name, hash);
- if (v == NULL)
- {
- if ((_SLang_Auto_Declare_Globals == 0)
- || (NULL != strchr (name, '-')) /* namespace->name form */
- || Lang_Defining_Function
- || (assign_type != _SLANG_BCST_ASSIGN)
- || (This_Static_NameSpace == NULL))
- {
- SLang_verror (SL_UNDEFINED_NAME, "%s is undefined", name);
- return;
- }
- /* Note that function local variables are not at top level */
-
- /* Variables that are automatically declared are given static
- * scope.
- */
- if ((NULL != SLang_Auto_Declare_Var_Hook)
- && (-1 == (*SLang_Auto_Declare_Var_Hook) (name)))
- return;
-
- if ((-1 == add_global_variable (name, SLANG_GVARIABLE, hash, This_Static_NameSpace))
- || (NULL == (v = locate_hashed_name (name, hash))))
- return;
- }
-
- switch (v->name_type)
- {
- case SLANG_LVARIABLE:
- main_type = _SLANG_BC_SET_LOCAL_LVALUE;
- Compile_ByteCode_Ptr->b.i_blk = ((SLang_Local_Var_Type *) v)->local_var_number;
- break;
-
- case SLANG_GVARIABLE:
- case SLANG_PVARIABLE:
- main_type = _SLANG_BC_SET_GLOBAL_LVALUE;
- Compile_ByteCode_Ptr->b.nt_blk = v;
- break;
-
- case SLANG_IVARIABLE:
- cl = _SLclass_get_class (((SLang_Intrin_Var_Type *)v)->type);
- if (cl->cl_class_type != SLANG_CLASS_TYPE_SCALAR)
- {
- SLang_verror (SL_SYNTAX_ERROR, "Assignment to %s is not allowed", name);
- return;
- }
- main_type = _SLANG_BC_SET_INTRIN_LVALUE;
- Compile_ByteCode_Ptr->b.nt_blk = v;
- break;
-
- case SLANG_RVARIABLE:
- SLang_verror (SL_READONLY_ERROR, "%s is read-only", name);
- return;
-
- default:
- SLang_verror (SL_DUPLICATE_DEFINITION, "%s may not be used as an lvalue", name);
- return;
- }
-
- Compile_ByteCode_Ptr->bc_sub_type = assign_type;
- Compile_ByteCode_Ptr->bc_main_type = main_type;
-
- lang_try_now ();
-}
-
-static void compile_deref_assign (char *name, unsigned long hash)
-{
- SLang_Name_Type *v;
-
- v = locate_hashed_name (name, hash);
-
- if (v == NULL)
- {
- SLang_verror (SL_UNDEFINED_NAME, "%s is undefined", name);
- return;
- }
-
- switch (v->name_type)
- {
- case SLANG_LVARIABLE:
- Compile_ByteCode_Ptr->b.i_blk = ((SLang_Local_Var_Type *) v)->local_var_number;
- break;
-
- case SLANG_GVARIABLE:
- case SLANG_PVARIABLE:
- Compile_ByteCode_Ptr->b.nt_blk = v;
- break;
-
- default:
- /* FIXME: Priority=low
- * This could be made to work. It is not a priority because
- * I cannot imagine application intrinsics which are references.
- */
- SLang_verror (SL_NOT_IMPLEMENTED, "Deref assignment to %s is not allowed", name);
- return;
- }
-
- Compile_ByteCode_Ptr->bc_sub_type = v->name_type;
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_DEREF_ASSIGN;
-
- lang_try_now ();
-}
-
-static void
-compile_struct_assign (_SLang_Token_Type *t)
-{
- Compile_ByteCode_Ptr->bc_sub_type = _SLANG_BCST_ASSIGN + (t->type - _STRUCT_ASSIGN_TOKEN);
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_SET_STRUCT_LVALUE;
- Compile_ByteCode_Ptr->b.s_blk = _SLstring_dup_hashed_string (t->v.s_val, t->hash);
- lang_try_now ();
-}
-
-static void
-compile_array_assign (_SLang_Token_Type *t)
-{
- Compile_ByteCode_Ptr->bc_sub_type = _SLANG_BCST_ASSIGN + (t->type - _ARRAY_ASSIGN_TOKEN);
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_SET_ARRAY_LVALUE;
- Compile_ByteCode_Ptr->b.s_blk = NULL;
- lang_try_now ();
-}
-
-static void compile_dot(_SLang_Token_Type *t)
-{
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_FIELD;
- Compile_ByteCode_Ptr->b.s_blk = _SLstring_dup_hashed_string(t->v.s_val, t->hash);
- lang_try_now ();
-}
-
-static void compile_ref (char *name, unsigned long hash)
-{
- SLang_Name_Type *entry;
- unsigned char main_type;
-
- if (NULL == (entry = locate_hashed_name (name, hash)))
- {
- SLang_verror (SL_UNDEFINED_NAME, "%s is undefined", name);
- return;
- }
-
- main_type = entry->name_type;
-
- if (main_type == SLANG_LVARIABLE)
- {
- main_type = _SLANG_BC_LOBJPTR;
- Compile_ByteCode_Ptr->b.i_blk = ((SLang_Local_Var_Type *)entry)->local_var_number;
- }
- else
- {
- main_type = _SLANG_BC_GOBJPTR;
- Compile_ByteCode_Ptr->b.nt_blk = entry;
- }
-
- Compile_ByteCode_Ptr->bc_main_type = main_type;
- lang_try_now ();
-}
-
-static void compile_break (unsigned char break_type,
- int requires_block, int requires_fun,
- char *str)
-{
- if ((requires_fun
- && (Lang_Defining_Function == 0))
- || (requires_block
- && (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_BLOCK)))
- {
- SLang_verror (SL_SYNTAX_ERROR, "misplaced %s", str);
- return;
- }
-
- Compile_ByteCode_Ptr->bc_main_type = break_type;
- Compile_ByteCode_Ptr->bc_sub_type = 0;
-
- lang_try_now ();
-}
-
-static void compile_public_variable_mode (_SLang_Token_Type *t)
-{
- if (t->type == IDENT_TOKEN)
- {
- /* If the variable is already defined in the static hash table,
- * generate an error.
- */
- if ((This_Static_NameSpace != NULL)
- && (NULL != locate_name_in_table (t->v.s_val, t->hash, This_Static_NameSpace->table, This_Static_NameSpace->table_size)))
- {
- SLang_verror (SL_DUPLICATE_DEFINITION,
- "%s already has static or private linkage in this unit",
- t->v.s_val);
- return;
- }
- add_global_variable (t->v.s_val, SLANG_GVARIABLE, t->hash, Global_NameSpace);
- }
- else if (t->type == CBRACKET_TOKEN)
- Compile_Mode_Function = compile_basic_token_mode;
- else
- SLang_verror (SL_SYNTAX_ERROR, "Misplaced token in variable list");
-}
-
-static void compile_local_variable_mode (_SLang_Token_Type *t)
-{
- if (t->type == IDENT_TOKEN)
- add_local_variable (t->v.s_val, t->hash);
- else if (t->type == CBRACKET_TOKEN)
- Compile_Mode_Function = compile_basic_token_mode;
- else
- SLang_verror (SL_SYNTAX_ERROR, "Misplaced token in variable list");
-}
-
-static void compile_static_variable_mode (_SLang_Token_Type *t)
-{
- if (t->type == IDENT_TOKEN)
- add_global_variable (t->v.s_val, SLANG_GVARIABLE, t->hash, This_Static_NameSpace);
- else if (t->type == CBRACKET_TOKEN)
- Compile_Mode_Function = compile_basic_token_mode;
- else
- SLang_verror (SL_SYNTAX_ERROR, "Misplaced token in variable list");
-}
-
-static void compile_private_variable_mode (_SLang_Token_Type *t)
-{
- if (t->type == IDENT_TOKEN)
- add_global_variable (t->v.s_val, SLANG_PVARIABLE, t->hash, This_Static_NameSpace);
- else if (t->type == CBRACKET_TOKEN)
- Compile_Mode_Function = compile_basic_token_mode;
- else
- SLang_verror (SL_SYNTAX_ERROR, "Misplaced token in variable list");
-}
-
-static void compile_function_mode (_SLang_Token_Type *t)
-{
- if (-1 == lang_check_space ())
- return;
-
- if (t->type != IDENT_TOKEN)
- SLang_verror (SL_SYNTAX_ERROR, "Expecting function name");
- else
- lang_define_function (t->v.s_val, SLANG_FUNCTION, t->hash, Global_NameSpace);
-
- Compile_Mode_Function = compile_basic_token_mode;
-}
-
-/* An error block is not permitted to contain continue or break statements.
- * This restriction may be removed later but for now reject them.
- */
-static int check_error_block (void)
-{
- SLBlock_Type *p;
- unsigned char t;
-
- /* Back up to the block and then scan it. */
- p = (Compile_ByteCode_Ptr - 1)->b.blk;
-
- while (0 != (t = p->bc_main_type))
- {
- if ((t == _SLANG_BC_BREAK)
- || (t == _SLANG_BC_CONTINUE))
- {
- SLang_verror (SL_SYNTAX_ERROR,
- "An ERROR_BLOCK is not permitted to contain continue or break statements");
- return -1;
- }
- p++;
- }
- return 0;
-}
-
-/* The only allowed tokens are the directives and another block start.
- * The mode is only active if a block is available. The inner_interp routine
- * expects such safety checks.
- */
-static void compile_directive_mode (_SLang_Token_Type *t)
-{
- int bc_sub_type;
-
- if (-1 == lang_check_space ())
- return;
-
- bc_sub_type = -1;
-
- switch (t->type)
- {
- case FOREVER_TOKEN:
- bc_sub_type = _SLANG_BCST_FOREVER;
- break;
-
- case IFNOT_TOKEN:
- bc_sub_type = _SLANG_BCST_IFNOT;
- break;
-
- case IF_TOKEN:
- bc_sub_type = _SLANG_BCST_IF;
- break;
-
- case ANDELSE_TOKEN:
- bc_sub_type = _SLANG_BCST_ANDELSE;
- break;
-
- case SWITCH_TOKEN:
- bc_sub_type = _SLANG_BCST_SWITCH;
- break;
-
- case EXITBLK_TOKEN:
- if (Lang_Defining_Function == 0)
- {
- SLang_verror (SL_SYNTAX_ERROR, "misplaced EXIT_BLOCK");
- break;
- }
- bc_sub_type = _SLANG_BCST_EXIT_BLOCK;
- break;
-
- case ERRBLK_TOKEN:
- if (This_Compile_Block_Type == COMPILE_BLOCK_TYPE_TOP_LEVEL)
- {
- SLang_verror (SL_SYNTAX_ERROR, "misplaced ERROR_BLOCK");
- break;
- }
- if (0 == check_error_block ())
- bc_sub_type = _SLANG_BCST_ERROR_BLOCK;
- break;
-
- case USRBLK0_TOKEN:
- case USRBLK1_TOKEN:
- case USRBLK2_TOKEN:
- case USRBLK3_TOKEN:
- case USRBLK4_TOKEN:
- if (This_Compile_Block_Type == COMPILE_BLOCK_TYPE_TOP_LEVEL)
- {
- SLang_verror (SL_SYNTAX_ERROR, "misplaced USER_BLOCK");
- break;
- }
- bc_sub_type = _SLANG_BCST_USER_BLOCK0 + (t->type - USRBLK0_TOKEN);
- break;
-
- case NOTELSE_TOKEN:
- bc_sub_type = _SLANG_BCST_NOTELSE;
- break;
-
- case ELSE_TOKEN:
- bc_sub_type = _SLANG_BCST_ELSE;
- break;
-
- case LOOP_TOKEN:
- bc_sub_type = _SLANG_BCST_LOOP;
- break;
-
- case DOWHILE_TOKEN:
- bc_sub_type = _SLANG_BCST_DOWHILE;
- break;
-
- case WHILE_TOKEN:
- bc_sub_type = _SLANG_BCST_WHILE;
- break;
-
- case ORELSE_TOKEN:
- bc_sub_type = _SLANG_BCST_ORELSE;
- break;
-
- case _FOR_TOKEN:
- bc_sub_type = _SLANG_BCST_FOR;
- break;
-
- case FOR_TOKEN:
- bc_sub_type = _SLANG_BCST_CFOR;
- break;
-
- case FOREACH_TOKEN:
- bc_sub_type = _SLANG_BCST_FOREACH;
- break;
-
- case OBRACE_TOKEN:
- lang_begin_block ();
- break;
-
- default:
- SLang_verror (SL_SYNTAX_ERROR, "Expecting directive token. Found 0x%X", t->type);
- break;
- }
-
- /* Reset this pointer first because compile_directive may cause a
- * file to be loaded.
- */
- Compile_Mode_Function = compile_basic_token_mode;
-
- if (bc_sub_type != -1)
- compile_directive (bc_sub_type);
-}
-
-static unsigned int Assign_Mode_Type;
-static void compile_assign_mode (_SLang_Token_Type *t)
-{
- if (t->type != IDENT_TOKEN)
- {
- SLang_verror (SL_SYNTAX_ERROR, "Expecting identifier for assignment");
- return;
- }
-
- compile_assign (Assign_Mode_Type, t->v.s_val, t->hash);
- Compile_Mode_Function = compile_basic_token_mode;
-}
-
-static void compile_basic_token_mode (_SLang_Token_Type *t)
-{
- if (-1 == lang_check_space ())
- return;
-
- switch (t->type)
- {
- case PUSH_TOKEN:
- case NOP_TOKEN:
- case EOF_TOKEN:
- case READONLY_TOKEN:
- case DO_TOKEN:
- case VARIABLE_TOKEN:
- case SEMICOLON_TOKEN:
- default:
- SLang_verror (SL_SYNTAX_ERROR, "Unknown or unsupported token type 0x%X", t->type);
- break;
-
- case DEREF_TOKEN:
- compile_call_direct (dereference_object, _SLANG_BC_CALL_DIRECT);
- break;
-
- case STRUCT_TOKEN:
- compile_call_direct (_SLstruct_define_struct, _SLANG_BC_CALL_DIRECT);
- break;
-
- case TYPEDEF_TOKEN:
- compile_call_direct (_SLstruct_define_typedef, _SLANG_BC_CALL_DIRECT);
- break;
-
- case TMP_TOKEN:
- compile_tmp_variable (t->v.s_val, t->hash);
- break;
-
- case DOT_TOKEN: /* X . field */
- compile_dot (t);
- break;
-
- case COMMA_TOKEN:
- break; /* do nothing */
-
- case IDENT_TOKEN:
- compile_hashed_identifier (t->v.s_val, t->hash, t);
- break;
-
- case _REF_TOKEN:
- compile_ref (t->v.s_val, t->hash);
- break;
-
- case ARG_TOKEN:
- compile_call_direct (SLang_start_arg_list, _SLANG_BC_CALL_DIRECT);
- break;
-
- case EARG_TOKEN:
- compile_lvar_call_direct (SLang_end_arg_list, _SLANG_BC_EARG_LVARIABLE, _SLANG_BC_CALL_DIRECT);
- break;
-
- case COLON_TOKEN:
- if (This_Compile_Block_Type == COMPILE_BLOCK_TYPE_BLOCK)
- compile_simple (_SLANG_BC_LABEL);
- else SLang_Error = SL_SYNTAX_ERROR;
- break;
-
- case POP_TOKEN:
- compile_call_direct (SLdo_pop, _SLANG_BC_CALL_DIRECT);
- break;
-
- case CASE_TOKEN:
- if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_BLOCK)
- SLang_verror (SL_SYNTAX_ERROR, "Misplaced 'case'");
- else
- compile_call_direct (case_function, _SLANG_BC_CALL_DIRECT);
- break;
-
- case CHAR_TOKEN:
- compile_integer (t->v.long_val, _SLANG_BC_LITERAL, SLANG_CHAR_TYPE);
- break;
- case SHORT_TOKEN:
- compile_integer (t->v.long_val, _SLANG_BC_LITERAL, SLANG_SHORT_TYPE);
- break;
- case INT_TOKEN:
- compile_integer (t->v.long_val, _SLANG_BC_LITERAL_INT, SLANG_INT_TYPE);
- break;
- case UCHAR_TOKEN:
- compile_integer (t->v.long_val, _SLANG_BC_LITERAL, SLANG_UCHAR_TYPE);
- break;
- case USHORT_TOKEN:
- compile_integer (t->v.long_val, _SLANG_BC_LITERAL, SLANG_USHORT_TYPE);
- break;
- case UINT_TOKEN:
- compile_integer (t->v.long_val, _SLANG_BC_LITERAL_INT, SLANG_UINT_TYPE);
- break;
- case LONG_TOKEN:
- compile_integer (t->v.long_val, _SLANG_BC_LITERAL, SLANG_LONG_TYPE);
- break;
- case ULONG_TOKEN:
- compile_integer (t->v.long_val, _SLANG_BC_LITERAL, SLANG_ULONG_TYPE);
- break;
-
-#if SLANG_HAS_FLOAT
- case FLOAT_TOKEN:
- compile_float (t->v.s_val);
- break;
-
- case DOUBLE_TOKEN:
- compile_double (t->v.s_val, SLANG_DOUBLE_TYPE);
- break;
-#endif
-#if SLANG_HAS_COMPLEX
- case COMPLEX_TOKEN:
- compile_double (t->v.s_val, SLANG_COMPLEX_TYPE);
- break;
-#endif
-
- case STRING_TOKEN:
- compile_string (t->v.s_val, t->hash);
- break;
-
- case _BSTRING_TOKEN:
- compile_bstring (SLbstring_create ((unsigned char *)t->v.s_val, (unsigned int) t->hash));
- break;
-
- case BSTRING_TOKEN:
- compile_bstring (t->v.b_val);
- break;
-
- case _NULL_TOKEN:
- compile_identifier ("NULL", t);
- break;
-
- case _INLINE_WILDCARD_ARRAY_TOKEN:
- compile_call_direct (_SLarray_wildcard_array, _SLANG_BC_CALL_DIRECT);
- break;
-
- case _INLINE_ARRAY_TOKEN:
- compile_call_direct (_SLarray_inline_array, _SLANG_BC_CALL_DIRECT_FRAME);
- break;
-
- case _INLINE_IMPLICIT_ARRAY_TOKEN:
- compile_call_direct (_SLarray_inline_implicit_array, _SLANG_BC_CALL_DIRECT_FRAME);
- break;
-
- case ARRAY_TOKEN:
- compile_lvar_call_direct (_SLarray_aget, _SLANG_BC_LVARIABLE_AGET, _SLANG_BC_CALL_DIRECT_FRAME);
- break;
-
- /* Note: I need to add the other _ARRAY assign tokens. */
- case _ARRAY_PLUSEQS_TOKEN:
- case _ARRAY_MINUSEQS_TOKEN:
- case _ARRAY_TIMESEQS_TOKEN:
- case _ARRAY_DIVEQS_TOKEN:
- case _ARRAY_BOREQS_TOKEN:
- case _ARRAY_BANDEQS_TOKEN:
- case _ARRAY_POST_MINUSMINUS_TOKEN:
- case _ARRAY_MINUSMINUS_TOKEN:
- case _ARRAY_POST_PLUSPLUS_TOKEN:
- case _ARRAY_PLUSPLUS_TOKEN:
- compile_array_assign (t);
- break;
-
- case _ARRAY_ASSIGN_TOKEN:
- compile_lvar_call_direct (_SLarray_aput, _SLANG_BC_LVARIABLE_APUT, _SLANG_BC_CALL_DIRECT_FRAME);
- break;
-
- case _STRUCT_ASSIGN_TOKEN:
- case _STRUCT_PLUSEQS_TOKEN:
- case _STRUCT_MINUSEQS_TOKEN:
- case _STRUCT_TIMESEQS_TOKEN:
- case _STRUCT_DIVEQS_TOKEN:
- case _STRUCT_BOREQS_TOKEN:
- case _STRUCT_BANDEQS_TOKEN:
- case _STRUCT_POST_MINUSMINUS_TOKEN:
- case _STRUCT_MINUSMINUS_TOKEN:
- case _STRUCT_POST_PLUSPLUS_TOKEN:
- case _STRUCT_PLUSPLUS_TOKEN:
- compile_struct_assign (t);
- break;
-
- case _SCALAR_ASSIGN_TOKEN:
- case _SCALAR_PLUSEQS_TOKEN:
- case _SCALAR_MINUSEQS_TOKEN:
- case _SCALAR_TIMESEQS_TOKEN:
- case _SCALAR_DIVEQS_TOKEN:
- case _SCALAR_BOREQS_TOKEN:
- case _SCALAR_BANDEQS_TOKEN:
- case _SCALAR_POST_MINUSMINUS_TOKEN:
- case _SCALAR_MINUSMINUS_TOKEN:
- case _SCALAR_POST_PLUSPLUS_TOKEN:
- case _SCALAR_PLUSPLUS_TOKEN:
- compile_assign (_SLANG_BCST_ASSIGN + (t->type - _SCALAR_ASSIGN_TOKEN),
- t->v.s_val, t->hash);
- break;
-
- case _DEREF_ASSIGN_TOKEN:
- compile_deref_assign (t->v.s_val, t->hash);
- break;
-
- /* For processing RPN tokens */
- case ASSIGN_TOKEN:
- case PLUSEQS_TOKEN:
- case MINUSEQS_TOKEN:
- case TIMESEQS_TOKEN:
- case DIVEQS_TOKEN:
- case BOREQS_TOKEN:
- case BANDEQS_TOKEN:
- case POST_MINUSMINUS_TOKEN:
- case MINUSMINUS_TOKEN:
- case POST_PLUSPLUS_TOKEN:
- case PLUSPLUS_TOKEN:
- Compile_Mode_Function = compile_assign_mode;
- Assign_Mode_Type = _SLANG_BCST_ASSIGN + (t->type - ASSIGN_TOKEN);
- break;
-
- case LT_TOKEN:
- compile_binary (SLANG_LT);
- break;
-
- case LE_TOKEN:
- compile_binary (SLANG_LE);
- break;
-
- case GT_TOKEN:
- compile_binary (SLANG_GT);
- break;
-
- case GE_TOKEN:
- compile_binary (SLANG_GE);
- break;
-
- case EQ_TOKEN:
- compile_binary (SLANG_EQ);
- break;
-
- case NE_TOKEN:
- compile_binary (SLANG_NE);
- break;
-
- case AND_TOKEN:
- compile_binary (SLANG_AND);
- break;
-
- case ADD_TOKEN:
- compile_fast_binary (SLANG_PLUS, _SLANG_BC_INTEGER_PLUS);
- break;
-
- case SUB_TOKEN:
- compile_fast_binary (SLANG_MINUS, _SLANG_BC_INTEGER_MINUS);
- break;
-
- case TIMES_TOKEN:
- compile_binary (SLANG_TIMES);
- break;
-
- case DIV_TOKEN:
- compile_binary (SLANG_DIVIDE);
- break;
-
- case POW_TOKEN:
- compile_binary (SLANG_POW);
- break;
-
- case BXOR_TOKEN:
- compile_binary (SLANG_BXOR);
- break;
-
- case BAND_TOKEN:
- compile_binary (SLANG_BAND);
- break;
-
- case BOR_TOKEN:
- compile_binary (SLANG_BOR);
- break;
-
- case SHR_TOKEN:
- compile_binary (SLANG_SHR);
- break;
-
- case SHL_TOKEN:
- compile_binary (SLANG_SHL);
- break;
-
- case MOD_TOKEN:
- compile_binary (SLANG_MOD);
- break;
-
- case OR_TOKEN:
- compile_binary (SLANG_OR);
- break;
-
- case NOT_TOKEN:
- compile_unary (SLANG_NOT, _SLANG_BC_UNARY);
- break;
-
- case BNOT_TOKEN:
- compile_unary (SLANG_BNOT, _SLANG_BC_UNARY);
- break;
-
- case MUL2_TOKEN:
- compile_unary (SLANG_MUL2, _SLANG_BC_UNARY_FUNC);
- break;
-
- case CHS_TOKEN:
- compile_unary (SLANG_CHS, _SLANG_BC_UNARY_FUNC);
- break;
-
- case ABS_TOKEN:
- compile_unary (SLANG_ABS, _SLANG_BC_UNARY_FUNC);
- break;
-
- case SQR_TOKEN:
- compile_unary (SLANG_SQR, _SLANG_BC_UNARY_FUNC);
- break;
-
- case SIGN_TOKEN:
- compile_unary (SLANG_SIGN, _SLANG_BC_UNARY_FUNC);
- break;
-
- case BREAK_TOKEN:
- compile_break (_SLANG_BC_BREAK, 1, 0, "break");
- break;
-
- case RETURN_TOKEN:
- compile_break (_SLANG_BC_RETURN, 0, 1, "return");
- break;
-
- case CONT_TOKEN:
- compile_break (_SLANG_BC_CONTINUE, 1, 0, "continue");
- break;
-
- case EXCH_TOKEN:
- compile_break (_SLANG_BC_EXCH, 0, 0, ""); /* FIXME: Priority=low */
- break;
-
- case STATIC_TOKEN:
- if (Lang_Defining_Function == 0)
- Compile_Mode_Function = compile_static_variable_mode;
- else
- SLang_verror (SL_NOT_IMPLEMENTED, "static variables not permitted in functions");
- break;
-
- case PRIVATE_TOKEN:
- if (Lang_Defining_Function == 0)
- Compile_Mode_Function = compile_private_variable_mode;
- else
- SLang_verror (SL_NOT_IMPLEMENTED, "private variables not permitted in functions");
- break;
-
- case PUBLIC_TOKEN:
- if (Lang_Defining_Function == 0)
- Compile_Mode_Function = compile_public_variable_mode;
- else
- SLang_verror (SL_NOT_IMPLEMENTED, "public variables not permitted in functions");
- break;
-
- case OBRACKET_TOKEN:
- if (Lang_Defining_Function == 0)
- Compile_Mode_Function = Default_Variable_Mode;
- else
- Compile_Mode_Function = compile_local_variable_mode;
- break;
-
- case OPAREN_TOKEN:
- lang_begin_function ();
- break;
-
- case DEFINE_STATIC_TOKEN:
- if (Lang_Defining_Function)
- define_static_function (t->v.s_val, t->hash);
- else SLang_Error = SL_SYNTAX_ERROR;
- break;
-
- case DEFINE_PRIVATE_TOKEN:
- if (Lang_Defining_Function)
- define_private_function (t->v.s_val, t->hash);
- else SLang_Error = SL_SYNTAX_ERROR;
- break;
-
- case DEFINE_PUBLIC_TOKEN:
- if (Lang_Defining_Function)
- define_public_function (t->v.s_val, t->hash);
- else SLang_Error = SL_SYNTAX_ERROR;
- break;
-
- case DEFINE_TOKEN:
- if (Lang_Defining_Function)
- (*Default_Define_Function) (t->v.s_val, t->hash);
- else
- SLang_Error = SL_SYNTAX_ERROR;
- break;
-
- case CPAREN_TOKEN:
- if (Lang_Defining_Function)
- Compile_Mode_Function = compile_function_mode;
- else SLang_Error = SL_SYNTAX_ERROR;
- break;
-
- case CBRACE_TOKEN:
- lang_end_block ();
- Compile_Mode_Function = compile_directive_mode;
- break;
-
- case OBRACE_TOKEN:
- lang_begin_block ();
- break;
-
- case FARG_TOKEN:
- Function_Args_Number = Local_Variable_Number;
- break;
-
-#if _SLANG_HAS_DEBUG_CODE
- case LINE_NUM_TOKEN:
- Compile_ByteCode_Ptr->bc_main_type = _SLANG_BC_LINE_NUM;
- Compile_ByteCode_Ptr->b.l_blk = t->v.long_val;
- lang_try_now ();
- break;
-#endif
- case POUND_TOKEN:
- compile_call_direct (_SLarray_matrix_multiply, _SLANG_BC_CALL_DIRECT);
- break;
- }
-}
-
-void _SLcompile (_SLang_Token_Type *t)
-{
- if (SLang_Error == 0)
- {
- if (Compile_Mode_Function != compile_basic_token_mode)
- {
- if (Compile_Mode_Function == NULL)
- Compile_Mode_Function = compile_basic_token_mode;
-#if _SLANG_HAS_DEBUG_CODE
- if (t->type == LINE_NUM_TOKEN)
- {
- compile_basic_token_mode (t);
- return;
- }
-#endif
- }
-
- (*Compile_Mode_Function) (t);
- }
-
- if (SLang_Error)
- {
- Compile_Mode_Function = compile_basic_token_mode;
- SLang_restart (0);
- }
-}
-
-void (*_SLcompile_ptr)(_SLang_Token_Type *) = _SLcompile;
-
-typedef struct _Compile_Context_Type
-{
- struct _Compile_Context_Type *next;
- SLang_NameSpace_Type *static_namespace;
- void (*compile_variable_mode) (_SLang_Token_Type *);
- void (*define_function) (char *, unsigned long);
- int lang_defining_function;
- int local_variable_number;
- unsigned int function_args_number;
- SLang_Name_Type **locals_hash_table;
- void (*compile_mode_function)(_SLang_Token_Type *);
-#if _SLANG_HAS_DEBUG_CODE
- char *compile_filename;
-#endif
-}
-Compile_Context_Type;
-
-static Compile_Context_Type *Compile_Context_Stack;
-
-/* The only way the push/pop_context functions can get called is via
- * an eval type function. That can only happen when executed from a
- * top level block. This means that Compile_ByteCode_Ptr can always be
- * rest back to the beginning of a block.
- */
-
-static int pop_compile_context (void)
-{
- Compile_Context_Type *cc;
-
- if (NULL == (cc = Compile_Context_Stack))
- return -1;
-
- This_Static_NameSpace = cc->static_namespace;
- Compile_Context_Stack = cc->next;
- Default_Variable_Mode = cc->compile_variable_mode;
- Default_Define_Function = cc->define_function;
- Compile_Mode_Function = cc->compile_mode_function;
-
- Lang_Defining_Function = cc->lang_defining_function;
- Local_Variable_Number = cc->local_variable_number;
- Function_Args_Number = cc->function_args_number;
-
-#if _SLANG_HAS_DEBUG_CODE
- SLang_free_slstring (This_Compile_Filename);
- This_Compile_Filename = cc->compile_filename;
-#endif
-
- SLfree ((char *) Locals_Hash_Table);
- Locals_Hash_Table = cc->locals_hash_table;
-
- SLfree ((char *) cc);
-
- return 0;
-}
-
-static int push_compile_context (char *name)
-{
- Compile_Context_Type *cc;
- SLang_Name_Type **lns;
-
- cc = (Compile_Context_Type *)SLmalloc (sizeof (Compile_Context_Type));
- if (cc == NULL)
- return -1;
- memset ((char *) cc, 0, sizeof (Compile_Context_Type));
-
- lns = (SLang_Name_Type **) SLcalloc (sizeof (SLang_Name_Type *), SLLOCALS_HASH_TABLE_SIZE);
- if (lns == NULL)
- {
- SLfree ((char *) cc);
- return -1;
- }
-
-#if _SLANG_HAS_DEBUG_CODE
- if ((name != NULL)
- && (NULL == (name = SLang_create_slstring (name))))
- {
- SLfree ((char *) cc);
- SLfree ((char *) lns);
- return -1;
- }
-
- cc->compile_filename = This_Compile_Filename;
- This_Compile_Filename = name;
-#endif
-
- cc->static_namespace = This_Static_NameSpace;
- cc->compile_variable_mode = Default_Variable_Mode;
- cc->define_function = Default_Define_Function;
- cc->locals_hash_table = Locals_Hash_Table;
-
- cc->lang_defining_function = Lang_Defining_Function;
- cc->local_variable_number = Local_Variable_Number;
- cc->function_args_number = Function_Args_Number;
- cc->locals_hash_table = Locals_Hash_Table;
- cc->compile_mode_function = Compile_Mode_Function;
-
- cc->next = Compile_Context_Stack;
- Compile_Context_Stack = cc;
-
- Compile_Mode_Function = compile_basic_token_mode;
- Default_Variable_Mode = compile_public_variable_mode;
- Default_Define_Function = define_public_function;
- Lang_Defining_Function = 0;
- Local_Variable_Number = 0;
- Function_Args_Number = 0;
- Locals_Hash_Table = lns;
- return 0;
-}
-
-static int init_interpreter (void)
-{
- SLang_NameSpace_Type *ns;
-
- if (Global_NameSpace != NULL)
- return 0;
-
- if (NULL == (ns = _SLns_allocate_namespace ("***GLOBAL***", SLGLOBALS_HASH_TABLE_SIZE)))
- return -1;
- if (-1 == _SLns_set_namespace_name (ns, "Global"))
- return -1;
- Global_NameSpace = ns;
-
- _SLRun_Stack = (SLang_Object_Type *) SLcalloc (SLANG_MAX_STACK_LEN,
- sizeof (SLang_Object_Type));
- if (_SLRun_Stack == NULL)
- return -1;
-
- _SLStack_Pointer = _SLRun_Stack;
- _SLStack_Pointer_Max = _SLRun_Stack + SLANG_MAX_STACK_LEN;
-
- SLShort_Blocks[0].bc_main_type = _SLANG_BC_RETURN;
- SLShort_Blocks[2].bc_main_type = _SLANG_BC_BREAK;
- SLShort_Blocks[4].bc_main_type = _SLANG_BC_CONTINUE;
-
- Num_Args_Stack = (int *) SLmalloc (sizeof (int) * SLANG_MAX_RECURSIVE_DEPTH);
- if (Num_Args_Stack == NULL)
- {
- SLfree ((char *) _SLRun_Stack);
- return -1;
- }
- Recursion_Depth = 0;
- Frame_Pointer_Stack = (unsigned int *) SLmalloc (sizeof (unsigned int) * SLANG_MAX_RECURSIVE_DEPTH);
- if (Frame_Pointer_Stack == NULL)
- {
- SLfree ((char *) _SLRun_Stack);
- SLfree ((char *)Num_Args_Stack);
- return -1;
- }
- Frame_Pointer_Depth = 0;
- Frame_Pointer = _SLRun_Stack;
-
- Default_Variable_Mode = compile_public_variable_mode;
- Default_Define_Function = define_public_function;
- return 0;
-}
-
-static int add_generic_table (SLang_NameSpace_Type *ns,
- SLang_Name_Type *table, char *pp_name,
- unsigned int entry_len)
-{
- SLang_Name_Type *t, **ns_table;
- char *name;
- unsigned int table_size;
-
- if (-1 == init_interpreter ())
- return -1;
-
- if (ns == NULL)
- ns = Global_NameSpace;
-
- ns_table = ns->table;
- table_size = ns->table_size;
-
- if ((pp_name != NULL)
- && (-1 == SLdefine_for_ifdef (pp_name)))
- return -1;
-
- t = table;
- while (NULL != (name = t->name))
- {
- unsigned long hash;
-
- /* Backward compatibility: '.' WAS used as hash marker */
- if (*name == '.')
- {
- name++;
- t->name = name;
- }
-
- if (NULL == (name = SLang_create_slstring (name)))
- return -1;
-
- t->name = name;
-
- hash = _SLcompute_string_hash (name);
- hash = hash % table_size;
-
- t->next = ns_table [(unsigned int) hash];
- ns_table [(unsigned int) hash] = t;
-
- t = (SLang_Name_Type *) ((char *)t + entry_len);
- }
-
- return 0;
-}
-
-int SLadd_intrin_fun_table (SLang_Intrin_Fun_Type *tbl, char *pp)
-{
- return add_generic_table (NULL, (SLang_Name_Type *) tbl, pp, sizeof (SLang_Intrin_Fun_Type));
-}
-
-int SLadd_intrin_var_table (SLang_Intrin_Var_Type *tbl, char *pp)
-{
- return add_generic_table (NULL, (SLang_Name_Type *) tbl, pp, sizeof (SLang_Intrin_Var_Type));
-}
-
-int SLadd_app_unary_table (SLang_App_Unary_Type *tbl, char *pp)
-{
- return add_generic_table (NULL, (SLang_Name_Type *) tbl, pp, sizeof (SLang_App_Unary_Type));
-}
-
-int SLadd_math_unary_table (SLang_Math_Unary_Type *tbl, char *pp)
-{
- return add_generic_table (NULL, (SLang_Name_Type *) tbl, pp, sizeof (SLang_Math_Unary_Type));
-}
-
-int SLadd_iconstant_table (SLang_IConstant_Type *tbl, char *pp)
-{
- return add_generic_table (NULL, (SLang_Name_Type *) tbl, pp, sizeof (SLang_IConstant_Type));
-}
-
-#if SLANG_HAS_FLOAT
-int SLadd_dconstant_table (SLang_DConstant_Type *tbl, char *pp)
-{
- return add_generic_table (NULL, (SLang_Name_Type *) tbl, pp, sizeof (SLang_DConstant_Type));
-}
-#endif
-
-/* ----------- */
-int SLns_add_intrin_fun_table (SLang_NameSpace_Type *ns, SLang_Intrin_Fun_Type *tbl, char *pp)
-{
- return add_generic_table (ns, (SLang_Name_Type *) tbl, pp, sizeof (SLang_Intrin_Fun_Type));
-}
-
-int SLns_add_intrin_var_table (SLang_NameSpace_Type *ns, SLang_Intrin_Var_Type *tbl, char *pp)
-{
- return add_generic_table (ns, (SLang_Name_Type *) tbl, pp, sizeof (SLang_Intrin_Var_Type));
-}
-
-int SLns_add_app_unary_table (SLang_NameSpace_Type *ns, SLang_App_Unary_Type *tbl, char *pp)
-{
- return add_generic_table (ns, (SLang_Name_Type *) tbl, pp, sizeof (SLang_App_Unary_Type));
-}
-
-int SLns_add_math_unary_table (SLang_NameSpace_Type *ns, SLang_Math_Unary_Type *tbl, char *pp)
-{
- return add_generic_table (ns, (SLang_Name_Type *) tbl, pp, sizeof (SLang_Math_Unary_Type));
-}
-
-int SLns_add_iconstant_table (SLang_NameSpace_Type *ns, SLang_IConstant_Type *tbl, char *pp)
-{
- return add_generic_table (ns, (SLang_Name_Type *) tbl, pp, sizeof (SLang_IConstant_Type));
-}
-
-#if SLANG_HAS_FLOAT
-int SLns_add_dconstant_table (SLang_NameSpace_Type *ns, SLang_DConstant_Type *tbl, char *pp)
-{
- return add_generic_table (ns, (SLang_Name_Type *) tbl, pp, sizeof (SLang_DConstant_Type));
-}
-#endif
-
-/* what is a bitmapped value:
- * 1 intrin fun
- * 2 user fun
- * 4 intrin var
- * 8 user defined var
- */
-SLang_Array_Type *_SLang_apropos (char *namespace_name, char *pat, unsigned int what)
-{
- SLang_NameSpace_Type *ns;
-
- if (namespace_name == NULL)
- namespace_name = "Global";
-
- if (*namespace_name == 0)
- ns = This_Static_NameSpace;
- else ns = _SLns_find_namespace (namespace_name);
-
- return _SLnspace_apropos (ns, pat, what);
-}
-
-void _SLang_implements_intrinsic (char *name)
-{
- if (This_Static_NameSpace == NULL)
- {
- SLang_verror (SL_INTRINSIC_ERROR, "No namespace available");
- return;
- }
-
- (void) _SLns_set_namespace_name (This_Static_NameSpace, name);
-
- Default_Define_Function = define_static_function;
- Default_Variable_Mode = compile_static_variable_mode;
-}
-
-void _SLang_use_namespace_intrinsic (char *name)
-{
- SLang_NameSpace_Type *ns;
-
- if (NULL == (ns = _SLns_find_namespace (name)))
- {
- SLang_verror (SL_INTRINSIC_ERROR, "Namespace %s does not exist", name);
- return;
- }
- This_Static_NameSpace = ns;
- if (Global_NameSpace == ns)
- {
- Default_Define_Function = define_public_function;
- Default_Variable_Mode = compile_public_variable_mode;
- }
- else
- {
- Default_Define_Function = define_static_function;
- Default_Variable_Mode = compile_static_variable_mode;
- }
-}
-
-
-char *_SLang_cur_namespace_intrinsic (void)
-{
- if (This_Static_NameSpace == NULL)
- return "Global";
-
- if (This_Static_NameSpace->namespace_name == NULL)
- return "";
-
- return This_Static_NameSpace->namespace_name;
-}