diff --git a/src/global.h b/src/global.h
index 3c1fee03a4f32d66c7e5e3f29dccefa81f8ad6c4..b00023842f2c6f5af8b0fe8bae2a9d3fd71397f4 100644
--- a/src/global.h
+++ b/src/global.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: global.h,v 1.21 1998/05/12 07:33:11 hubbe Exp $
+ * $Id: global.h,v 1.22 1998/05/12 23:51:23 hubbe Exp $
  */
 #ifndef GLOBAL_H
 #define GLOBAL_H
@@ -42,11 +42,6 @@ struct svalue;
 
 #include "machine.h"
 
-/*
- * Ugga, bugga, hope the gods of select() listen to us!
- */
-#define FD_SETSIZE MAX_OPEN_FILEDESCRIPTORS
-
 /*
  * Max number of local variables in a function.
  * Currently there is no support for more than 256
diff --git a/src/interpret.c b/src/interpret.c
index 543943aaf8ed6a96fcb68b9b5e5e5f91e6d7a6b8..76c3c8538d8bbb06868a470545a83cef2fd3178d 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.80 1998/04/20 18:43:08 grubba Exp $");
+RCSID("$Id: interpret.c,v 1.81 1998/05/12 23:51:23 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -388,9 +388,15 @@ static char trace_buffer[100];
   instr+=EXTRACT_UCHAR(pc++),\
   (t_flag>3 ? sprintf(trace_buffer,"-    Arg = %ld\n",(long)instr),write_to_stderr(trace_buffer,strlen(trace_buffer)) : 0),\
   instr))
+#define GET_ARG2() (\
+  instr=EXTRACT_UCHAR(pc++),\
+  (t_flag>3 ? sprintf(trace_buffer,"-    Arg2= %ld\n",(long)instr),write_to_stderr(trace_buffer,strlen(trace_buffer)) : 0),\
+  instr)
+
 
 #else
 #define GET_ARG() (instr=prefix,prefix=0,instr+EXTRACT_UCHAR(pc++))
+#define GET_ARG2() EXTRACT_UCHAR(pc++)
 #endif
 
 #define CASE(X) case (X)-F_OFFSET:
@@ -741,10 +747,49 @@ static int eval_instruction(unsigned char *pc)
       CASE(F_2_LOCALS);
       assign_svalue_no_free(sp++,fp->locals+GET_ARG());
       print_return_value();
-      assign_svalue_no_free(sp++,fp->locals+GET_ARG());
+      assign_svalue_no_free(sp++,fp->locals+GET_ARG2());
       print_return_value();
       break;
-      
+
+      CASE(F_LOCAL_2_LOCAL);
+      {
+	int tmp=GET_ARG();
+	assign_svalue(fp->locals+tmp, fp->locals+GET_ARG2());
+	break;
+      }
+
+      CASE(F_LOCAL_2_GLOBAL);
+      {
+	INT32 tmp=GET_ARG() + fp->context.identifier_level;
+	struct identifier *i;
+
+	if(!fp->current_object->prog)
+	  error("Cannot access global variables in destructed object.\n");
+
+	i=ID_FROM_INT(fp->current_object->prog, tmp);
+	if(!IDENTIFIER_IS_VARIABLE(i->identifier_flags))
+	  error("Cannot assign functions or constants.\n");
+	if(i->run_time_type == T_MIXED)
+	{
+	  assign_svalue((struct svalue *)GLOBAL_FROM_INT(tmp), fp->locals + GET_ARG2());
+	}else{
+	  assign_to_short_svalue((union anything *)GLOBAL_FROM_INT(tmp),
+				 i->run_time_type,
+				 fp->locals + GET_ARG2());
+	}
+	break;
+      }
+
+      CASE(F_GLOBAL_2_LOCAL);
+      {
+	INT32 tmp=GET_ARG() + fp->context.identifier_level;
+	INT32 tmp2=GET_ARG2();
+	free_svalue(fp->locals + tmp2);
+	low_object_index_no_free(fp->locals + tmp2,
+				 fp->current_object,
+				 tmp);
+	break;
+      }
 
       CASE(F_LOCAL_LVALUE);
       sp[0].type=T_LVALUE;
@@ -1149,6 +1194,20 @@ static int eval_instruction(unsigned char *pc)
       DOJUMP();
       break;
 
+      CASE(F_BRANCH_IF_NOT_LOCAL_ARROW);
+      {
+	struct svalue tmp;
+	tmp.type=T_STRING;
+	tmp.u.string=fp->context.prog->strings[GET_ARG()];
+	tmp.subtype=1;
+	sp->type=T_INT;	
+	sp++;
+	index_no_free(sp-1,fp->locals+GET_ARG2() , &tmp);
+	print_return_value();
+      }
+
+      /* Fall through */
+
       CASE(F_BRANCH_WHEN_ZERO);
       if(!IS_ZERO(sp-1))
       {
@@ -1179,6 +1238,16 @@ static int eval_instruction(unsigned char *pc)
       }
       break;
 
+      CASE(F_BRANCH_IF_NOT_LOCAL);
+      instr=GET_ARG();
+      if(!IS_ZERO(fp->locals + instr))
+      {
+	pc+=sizeof(INT32);
+      }else{
+	DOJUMP();
+      }
+      break;
+
       CJUMP(F_BRANCH_WHEN_EQ, is_eq);
       CJUMP(F_BRANCH_WHEN_NE,!is_eq);
       CJUMP(F_BRANCH_WHEN_LT, is_lt);
@@ -1434,7 +1503,7 @@ static int eval_instruction(unsigned char *pc)
 	struct svalue *s=fp->locals+GET_ARG();
 	if(s->type == T_STRING) s->subtype=0;
 	sp++->type=T_INT;
-	index_no_free(sp-1,fp->locals+GET_ARG(),s);
+	index_no_free(sp-1,fp->locals+GET_ARG2(),s);
 	break;
       }
 
@@ -1448,6 +1517,60 @@ static int eval_instruction(unsigned char *pc)
 	break;
       }
 
+      CASE(F_GLOBAL_LOCAL_INDEX);
+      {
+	struct svalue tmp,*s;
+	low_object_index_no_free(sp,
+				 fp->current_object,
+				 GET_ARG() + fp->context.identifier_level);
+	sp++;
+	s=fp->locals+GET_ARG2();
+	if(s->type == T_STRING) s->subtype=0;
+	index_no_free(&tmp,sp-1,s);
+	free_svalue(sp-1);
+	sp[-1]=tmp;
+	break;
+      }
+
+      CASE(F_LOCAL_ARROW);
+      {
+	struct svalue tmp;
+	tmp.type=T_STRING;
+	tmp.u.string=fp->context.prog->strings[GET_ARG()];
+	tmp.subtype=1;
+	sp->type=T_INT;	
+	sp++;
+	index_no_free(sp-1,fp->locals+GET_ARG2() , &tmp);
+	print_return_value();
+	break;
+      }
+
+      CASE(F_ARROW);
+      {
+	struct svalue tmp,tmp2;
+	tmp.type=T_STRING;
+	tmp.u.string=fp->context.prog->strings[GET_ARG()];
+	tmp.subtype=1;
+	index_no_free(&tmp2, sp-1, &tmp);
+	free_svalue(sp-1);
+	sp[-1]=tmp2;
+	print_return_value();
+	break;
+      }
+
+      CASE(F_STRING_INDEX);
+      {
+	struct svalue tmp,tmp2;
+	tmp.type=T_STRING;
+	tmp.u.string=fp->context.prog->strings[GET_ARG()];
+	tmp.subtype=0;
+	index_no_free(&tmp2, sp-1, &tmp);
+	free_svalue(sp-1);
+	sp[-1]=tmp2;
+	print_return_value();
+	break;
+      }
+
       CASE(F_POS_INT_INDEX);
       push_int(GET_ARG());
       print_return_value();
@@ -1456,23 +1579,6 @@ static int eval_instruction(unsigned char *pc)
       CASE(F_NEG_INT_INDEX);
       push_int(-GET_ARG());
       print_return_value();
-      goto do_index;
-
-      CASE(F_ARROW);
-      copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]);
-      sp->type=T_STRING;
-      sp->subtype=1;
-      sp++;
-      print_return_value();
-      goto do_index;
-
-      CASE(F_STRING_INDEX);
-      copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]);
-      sp->type=T_STRING;
-      sp->subtype=0;
-      sp++;
-      print_return_value();
-      /* Fall through */
 
       CASE(F_INDEX);
     do_index:
diff --git a/src/language.yacc b/src/language.yacc
index b350ce86795ddea058c6d132e8afa98424d367b0..97544dfc4340512c3b0d5d2b60a03ff949d840d3 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -22,12 +22,13 @@
 %token F_BRANCH_WHEN_LT F_BRANCH_WHEN_GT
 %token F_BRANCH_WHEN_LE F_BRANCH_WHEN_GE
 %token F_BRANCH_WHEN_EQ F_BRANCH_WHEN_NE
-%token F_BRANCH_IF_LOCAL
+%token F_BRANCH_IF_LOCAL F_BRANCH_IF_NOT_LOCAL
+%token F_BRANCH_IF_NOT_LOCAL_ARROW
 %token F_INC_LOOP F_DEC_LOOP
 %token F_INC_NEQ_LOOP F_DEC_NEQ_LOOP
 
 %token F_INDEX F_ARROW F_INDIRECT F_STRING_INDEX F_LOCAL_INDEX
-%token F_LOCAL_LOCAL_INDEX
+%token F_LOCAL_LOCAL_INDEX F_LOCAL_ARROW F_GLOBAL_LOCAL_INDEX
 %token F_POS_INT_INDEX F_NEG_INT_INDEX
 %token F_LTOSVAL F_LTOSVAL2
 %token F_PUSH_ARRAY 
@@ -57,6 +58,7 @@
 %token F_ASSIGN F_ASSIGN_AND_POP
 %token F_ASSIGN_LOCAL F_ASSIGN_LOCAL_AND_POP
 %token F_ASSIGN_GLOBAL F_ASSIGN_GLOBAL_AND_POP
+%token F_LOCAL_2_LOCAL F_LOCAL_2_GLOBAL F_GLOBAL_2_LOCAL
 %token F_ADD F_SUBTRACT F_ADD_INT F_ADD_NEG_INT
 %token F_ADD_TO_AND_POP
 %token F_MULTIPLY F_DIVIDE F_MOD
@@ -79,13 +81,13 @@
  * These are token values that needn't have an associated code for the
  * compiled file
  */
+%token F_MAX_OPCODE
 
 /* This is the end of file marker used by the lexer
  * to enable nicer EOF in error handling.
  */
 %token F_LEX_EOF
 
-%token F_MAX_OPCODE
 %token F_ADD_EQ
 %token F_AND_EQ
 %token F_ARG_LIST
@@ -177,7 +179,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.95 1998/04/30 16:30:37 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.96 1998/05/12 23:51:25 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
diff --git a/src/las.c b/src/las.c
index 695e6c2507c717481c132708edb357e92a3a0cf9..8d422391028b897010bf39c95453f395753db70b 100644
--- a/src/las.c
+++ b/src/las.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: las.c,v 1.61 1998/05/01 15:48:12 grubba Exp $");
+RCSID("$Id: las.c,v 1.62 1998/05/12 23:51:26 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -2360,7 +2360,11 @@ int dooptcode(struct pike_string *name,
 #endif
     if(!num_parse_error)
     {
+      extern int remove_clear_locals;
+      remove_clear_locals=args;
+      if(vargs) remove_clear_locals++;
       do_code_block(n);
+      remove_clear_locals=0x7fffffff;
     }
   }
   
diff --git a/src/lex.c b/src/lex.c
index bdbab93d94e3fa0125a94fa2754800f5e97182e3..b3b0c0dd0f98090e8f587d71d9efc69d305873d1 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: lex.c,v 1.52 1998/04/27 19:17:16 grubba Exp $");
+RCSID("$Id: lex.c,v 1.53 1998/05/12 23:51:26 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -137,6 +137,8 @@ struct keyword instr_names[]=
 { "branch",             F_BRANCH, I_ISJUMP },
 { "branch non zero",	F_BRANCH_WHEN_NON_ZERO, I_ISJUMP },	
 { "branch if local",	F_BRANCH_IF_LOCAL, I_HASARG },	
+{ "branch if !local",	F_BRANCH_IF_NOT_LOCAL, I_HASARG },	
+{ "branch if ! local->x",	F_BRANCH_IF_NOT_LOCAL_ARROW, I_HASARG },	
 { "branch when zero",	F_BRANCH_WHEN_ZERO, I_ISJUMP },	
 { "branch if <",	F_BRANCH_WHEN_LT, I_ISJUMP },
 { "branch if >",	F_BRANCH_WHEN_GT, I_ISJUMP },
@@ -234,6 +236,11 @@ struct keyword instr_names[]=
 { "call function",      F_CALL_FUNCTION, 0 },
 { "call function & return", F_CALL_FUNCTION_AND_RETURN, 0 },
 { "+= and pop",         F_ADD_TO_AND_POP, 0 },
+{ "local=local;",       F_LOCAL_2_LOCAL, I_HASARG },
+{ "local=global;",      F_GLOBAL_2_LOCAL, I_HASARG },
+{ "global=local;",      F_LOCAL_2_GLOBAL, I_HASARG },
+{ "local->x",           F_LOCAL_ARROW, I_HASARG },
+{ "global[local]",      F_GLOBAL_LOCAL_INDEX, I_HASARG },
 };
 
 struct instr instrs[F_MAX_INSTR - F_OFFSET];
diff --git a/src/peep.c b/src/peep.c
index 81dc5a60b262b5ad694611b29f1272005f42c945..73a7ee2438ad70836306143896ad6b9e938ab8f5 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -13,7 +13,7 @@
 #include "dmalloc.h"
 #include "stuff.h"
 
-RCSID("$Id: peep.c,v 1.23 1998/05/01 15:45:55 grubba Exp $");
+RCSID("$Id: peep.c,v 1.24 1998/05/12 23:51:26 hubbe Exp $");
 
 struct p_instr_s
 {
@@ -332,6 +332,7 @@ void assemble(void)
 
 /**** Peephole optimizer ****/
 
+int remove_clear_locals=0x7fffffff;
 static int fifo_len, eye,len;
 static p_instr *instructions;
 
diff --git a/src/peep.in b/src/peep.in
index 306f7b871330b137697e19b2cc9f266be8260016..8d9ef2a71ab4c81dc8b8acdc0d9a4f5394d414e9 100644
--- a/src/peep.in
+++ b/src/peep.in
@@ -1,5 +1,5 @@
 //
-// $Id: peep.in,v 1.14 1998/04/01 00:47:49 hubbe Exp $
+// $Id: peep.in,v 1.15 1998/05/12 23:51:26 hubbe Exp $
 //
 
 NOP :
@@ -33,6 +33,12 @@ COMPL COMPL :
 NEGATE CONST_1 ADD : COMPL
 NEGATE CONST1 SUBTRACT : COMPL
 CONST0 ASSIGN_LOCAL_AND_POP : CLEAR_LOCAL($2a)
+
+// Remove clearing of locals from the beginning of functions
+CLEAR_LOCAL [(fifo_len == (long)instrbuf.s.len / (long)sizeof(p_instr)) && $1a>=remove_clear_locals] : 
+CLEAR_2_LOCAL [(fifo_len == (long)instrbuf.s.len / (long)sizeof(p_instr)) && $1a>=remove_clear_locals] : 
+CLEAR_4_LOCAL [(fifo_len == (long)instrbuf.s.len / (long)sizeof(p_instr)) && $1a>=remove_clear_locals] : 
+
 CLEAR_LOCAL NUMBER(0) ASSIGN_LOCAL_AND_POP ($1a) : CLEAR_LOCAL($1a)
 CLEAR_LOCAL NUMBER(0) ASSIGN_LOCAL_AND_POP ($1a+1) : CLEAR_2_LOCAL($1a)
 CLEAR_2_LOCAL CLEAR_2_LOCAL($1a+2) : CLEAR_4_LOCAL($1a)
@@ -170,6 +176,7 @@ NEG_NUMBER ADD_INT: NUMBER($-1a+$2a)
 NEG_NUMBER ADD_NEG_INT: NUMBER(-$1a-$2a)
 
 LOCAL BRANCH_WHEN_NON_ZERO : BRANCH_IF_LOCAL($1a) POINTER($2a)
+LOCAL BRANCH_WHEN_ZERO : BRANCH_IF_NOT_LOCAL($1a) POINTER($2a)
 
 DEC_LOCAL_AND_POP LOCAL ($1a) : DEC_LOCAL ($1a)
 INC_LOCAL_AND_POP LOCAL ($1a) : INC_LOCAL ($1a)
@@ -217,3 +224,17 @@ LOCAL_LVALUE MARK_X [$2a>1] : MARK_X($2a-2) LOCAL_LVALUE($1a)
 
 BasicBranch0(BRANCH_WHEN_NON_ZERO, BRANCH_AND_POP_WHEN_NON_ZERO)
 BasicBranch0(BRANCH_WHEN_ZERO, BRANCH_AND_POP_WHEN_ZERO)
+
+LOCAL ASSIGN_LOCAL_AND_POP : LOCAL_2_LOCAL($2a) BYTE($1a)
+GLOBAL ASSIGN_LOCAL_AND_POP : GLOBAL_2_LOCAL($1a) BYTE($2a)
+LOCAL ASSIGN_GLOBAL_AND_POP : LOCAL_2_GLOBAL($2a) BYTE($1a)
+
+LOCAL ARROW : LOCAL_ARROW($2a) BYTE($1a)
+LOCAL_ARROW BYTE BRANCH_WHEN_ZERO: BRANCH_IF_NOT_LOCAL_ARROW($1a) BYTE($2a) POINTER($3a)
+
+GLOBAL LOCAL_INDEX : GLOBAL_LOCAL_INDEX($1a) BYTE($2a)
+
+SIZEOF CONST1 BRANCH_WHEN_LT : SIZEOF BRANCH_WHEN_ZERO ($3a)
+SIZEOF_LOCAL CONST1 BRANCH_WHEN_LT : SIZEOF BRANCH_WHEN_ZERO ($3a)
+SIZEOF CONST0 BRANCH_WHEN_LE : SIZEOF BRANCH_WHEN_ZERO ($3a)
+SIZEOF_LOCAL CONST0 BRANCH_WHEN_LE : SIZEOF BRANCH_WHEN_ZERO ($3a)
diff --git a/src/testsuite.in b/src/testsuite.in
index 5f01c13e305192c5f1d2e75e01c9d407caadc8b9..d1813fda6de1b2ac9ad78d72ec15fb3c33db18b5 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,4 @@
-stest_true([["$Id: testsuite.in,v 1.104 1998/05/07 23:49:36 hubbe Exp $"]])
+stest_true([["$Id: testsuite.in,v 1.105 1998/05/12 23:51:27 hubbe Exp $"]])
 cond([[all_constants()->_verify_internals]],
 [[
   test_do(_verify_internals())
@@ -2050,7 +2050,7 @@ test_equal(Array.diff("123.org"/"","http://123.org/"/""),
 // - explode
 test_equal(({"a","b","c",}), "anna bnna c"/"nna ")
 test_equal(({"","",}),"hej"/"hej")
-test_equal(({}),""/"hej")
+test_equal(({""}),""/"hej")
 
 // - fork()
 // FIXME: add tests for fork