diff --git a/lib/modules/Yabu.pmod/test.pike b/lib/modules/Yabu.pmod/test.pike
index a30780a77b8166dfe6d7ff86510f8f3cb1b4b983..6f9fb39b83bcc3b6141fd0fb8b47601016773876 100644
--- a/lib/modules/Yabu.pmod/test.pike
+++ b/lib/modules/Yabu.pmod/test.pike
@@ -64,6 +64,5 @@ int main(int argc, array argv)
   // Remove test database.
   db->purge();
 
-  write("Yabu test program says everything is A OK.\n");
-  return 1;
+  return 0;
 }
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 316dd9b72c0f116526a3aff67639ca6eb31715dd..b0c85a48c68563ffd4ef584fd727ec789be096d7 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.110 1998/05/19 18:47:41 grubba Exp $");
+RCSID("$Id: builtin_functions.c,v 1.111 1998/05/25 10:38:44 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -2919,8 +2919,6 @@ void f__locate_references(INT32 args)
 
 void init_builtin_efuns(void)
 {
-  init_operators();
-
   add_efun("gethrtime", f_gethrtime,"function(int|void:int)", OPT_EXTERNAL_DEPEND);
 
 #ifdef HAVE_GETHRVTIME
diff --git a/src/docode.c b/src/docode.c
index 765c6392cb7f38b2527da9783d2886e9312b7d9d..3866fb9e1a1af303b7beeeee806607fa33d85d05 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.37 1998/05/17 20:06:43 grubba Exp $");
+RCSID("$Id: docode.c,v 1.38 1998/05/25 10:38:44 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -206,7 +206,7 @@ static int do_docode2(node *n,int flags)
 	emit(F_NUMBER,0);
 	emit(F_NUMBER,0);
 	return 2;
-
+	
       case F_ARRAY_LVALUE:
       case F_LVALUE_LIST:
       case F_LOCAL:
@@ -216,15 +216,23 @@ static int do_docode2(node *n,int flags)
       case F_ARROW:
       case F_ARG_LIST:
       case F_EXTERNAL:
-	break;
-    }
+	  break;
+      }
+  }
+
+  if(flags & DO_LVALUE_IF_POSSIBLE)
+  {
+    flags|=DO_INDIRECT;
+    flags &=~DO_LVALUE_IF_POSSIBLE;
+  }else{
+    flags &=~DO_INDIRECT;
   }
 
   switch(n->token)
   {
   case F_EXTERNAL:
     emit(F_LDA, n->u.integer.a);
-    if(flags & DO_LVALUE)
+    if(flags & WANT_LVALUE)
     {
       emit(F_EXTERNAL_LVALUE, n->u.integer.b);
       return 2;
@@ -686,7 +694,7 @@ static int do_docode2(node *n,int flags)
     }
 
   case F_ARG_LIST:
-    tmp1=do_docode(CAR(n),flags & ~DO_LVALUE);
+    tmp1=do_docode(CAR(n),flags & ~WANT_LVALUE);
     tmp1+=do_docode(CDR(n),flags);
     return tmp1;
 
@@ -944,7 +952,7 @@ static int do_docode2(node *n,int flags)
   case F_ARROW:
     if(CDR(n)->token != F_CONSTANT || CDR(n)->u.sval.type!=T_STRING)
       fatal("Bugg in F_ARROW, index not string.");
-    if(flags & DO_LVALUE)
+    if(flags & WANT_LVALUE)
     {
       /* FIXME!!!! ??? I wonder what needs fixing... /Hubbe */
       tmp1=do_docode(CAR(n), 0);
@@ -963,9 +971,20 @@ static int do_docode2(node *n,int flags)
     return tmp1;
 
   case F_INDEX:
-    if(flags & DO_LVALUE)
+    if(flags & WANT_LVALUE)
     {
-      tmp1=do_docode(CAR(n), 0);
+      int mklval=CAR(n) && match_types(CAR(n)->type, string_type_string);
+      tmp1=do_docode(CAR(n),
+		     mklval ? DO_LVALUE_IF_POSSIBLE : 0);
+      if(tmp1==2)
+      {
+#ifdef DEBUG
+	if(!mklval)
+	  fatal("Unwanted lvalue!\n");
+#endif
+	emit2(F_INDIRECT);
+      }
+      
       if(do_docode(CDR(n),0) != 1)
 	fatal("Internal compiler error, please report this (1).");
       if(CDR(n)->token != F_CONSTANT &&
@@ -975,7 +994,9 @@ static int do_docode2(node *n,int flags)
     }else{
       tmp1=do_docode(CAR(n), DO_NOT_COPY);
       code_expression(CDR(n), DO_NOT_COPY, "index");
+
       emit2(F_INDEX);
+
       if(!(flags & DO_NOT_COPY))
       {
 	while(n && (n->token==F_INDEX || n->token==F_ARROW)) n=CAR(n);
@@ -1046,7 +1067,7 @@ static int do_docode2(node *n,int flags)
   case F_LOCAL:
     if(n->u.number >= compiler_frame->max_number_of_locals)
       yyerror("Illegal to use local variable here.");
-    if(flags & DO_LVALUE)
+    if(flags & WANT_LVALUE)
     {
       emit(F_LOCAL_LVALUE,n->u.number);
       return 2;
@@ -1058,14 +1079,14 @@ static int do_docode2(node *n,int flags)
   case F_IDENTIFIER:
     if(IDENTIFIER_IS_FUNCTION(ID_FROM_INT(new_program, n->u.number)->identifier_flags))
     {
-      if(flags & DO_LVALUE)
+      if(flags & WANT_LVALUE)
       {
 	yyerror("Cannot assign functions.\n");
       }else{
 	emit(F_LFUN,n->u.number);
       }
     }else{
-      if(flags & DO_LVALUE)
+      if(flags & WANT_LVALUE)
       {
 	emit(F_GLOBAL_LVALUE,n->u.number);
 	return 2;
diff --git a/src/docode.h b/src/docode.h
index 69e3a03377907813ebfdddb11d786f753e56fcd2..f249782b39e9f2303fdfc1547663be14690b4be6 100644
--- a/src/docode.h
+++ b/src/docode.h
@@ -5,15 +5,18 @@
 \*/
 
 /*
- * $Id: docode.h,v 1.6 1998/04/27 10:00:27 hubbe Exp $
+ * $Id: docode.h,v 1.7 1998/05/25 10:38:45 hubbe Exp $
  */
 #ifndef DOCODE_H
 #define DOCODE_H
 
-
 #define DO_LVALUE 1
 #define DO_NOT_COPY 2
 #define DO_POP 4
+#define DO_INDIRECT 8
+#define DO_LVALUE_IF_POSSIBLE 16
+
+#define WANT_LVALUE (DO_LVALUE | DO_INDIRECT)
 
 extern int store_linenumbers;
 
diff --git a/src/interpret.c b/src/interpret.c
index 8151f6bfb78825f616fcdaebb1a7f87ae6883a4c..1228002c26c7b02a007c1302e922e8227f22a7cd 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.84 1998/05/24 08:44:30 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.85 1998/05/25 10:38:45 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -1584,7 +1584,13 @@ static int eval_instruction(unsigned char *pc)
 
       CASE(F_INDEX);
     do_index:
-      o_index();
+      {
+	struct svalue s;
+	index_no_free(&s,sp-2,sp-1);
+	pop_n_elems(2);
+	*sp=s;
+	sp++;
+      }
       print_return_value();
       break;
 
@@ -1600,6 +1606,29 @@ static int eval_instruction(unsigned char *pc)
       }
       break;
 
+      CASE(F_INDIRECT);
+      {
+	struct svalue s;
+	lvalue_to_svalue_no_free(&s,sp-2);
+	if(s.type != T_STRING)
+	{
+	  pop_n_elems(2);
+	  *sp=s;
+	  sp++;
+	}else{
+	  struct object *o;
+	  o=low_clone(string_assignment_program);
+	  ((struct string_assignment_storage *)o->storage)->lval[0]=sp[-2];
+	  ((struct string_assignment_storage *)o->storage)->lval[1]=sp[-1];
+	  ((struct string_assignment_storage *)o->storage)->s=s.u.string;
+	  sp-=2;
+	  push_object(o);
+	}
+      }
+      print_return_value();
+      break;
+      
+
       CASE(F_SIZEOF);
       instr=pike_sizeof(sp-1);
       pop_stack();
diff --git a/src/main.c b/src/main.c
index aadbf7b0788f5020d9dfb39fed228b85e4cdc072..db2699e7690534b09b3e399ea3cd3deed24899de 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: main.c,v 1.52 1998/05/12 16:53:17 grubba Exp $");
+RCSID("$Id: main.c,v 1.53 1998/05/25 10:38:45 hubbe Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -26,6 +26,7 @@ RCSID("$Id: main.c,v 1.52 1998/05/12 16:53:17 grubba Exp $");
 #include "mapping.h"
 #include "cpp.h"
 #include "main.h"
+#include "operators.h"
 
 #include <errno.h>
 
@@ -395,6 +396,7 @@ void do_exit(int num) ATTRIBUTE((noreturn))
 void low_init_main(void)
 {
   th_init();
+  init_operators();
   init_builtin_efuns();
   init_signals();
   init_dynamic_load();
@@ -424,6 +426,7 @@ void low_exit_main(void)
   exit_cpp();
   cleanup_interpret();
   cleanup_added_efuns();
+  exit_operators();
   cleanup_pike_types();
   cleanup_program();
   cleanup_compiler();
diff --git a/src/module_support.c b/src/module_support.c
index 186ab37af9e13adcf67404d2fbe96bb2f6850d5b..18a85a08e40c7cd88997971f6414ae1ba341cc2d 100644
--- a/src/module_support.c
+++ b/src/module_support.c
@@ -6,7 +6,7 @@
 #include "pike_types.h"
 #include "error.h"
 
-RCSID("$Id: module_support.c,v 1.11 1998/04/12 12:20:12 grubba Exp $");
+RCSID("$Id: module_support.c,v 1.12 1998/05/25 10:38:45 hubbe Exp $");
 
 /* Checks that args_to_check arguments are OK.
  * Returns 1 if everything worked ok, zero otherwise.
@@ -155,7 +155,8 @@ int va_get_args(struct svalue *s,
       break;
     case 'i':
       if(s->type != T_INT) return ret;
-      *va_arg(ap, INT32 *)=s->u.integer; break;
+      *va_arg(ap, INT32 *)=s->u.integer;
+      break;
     case 's':
       if(s->type != T_STRING) return ret;
       *va_arg(ap, char **)=s->u.string->str;
diff --git a/src/object.c b/src/object.c
index afe58ce5076d3e3df454b8858407b5c71fffde07..f0c32330fa4ec582edaa1be29be3f26589a0c243 100644
--- a/src/object.c
+++ b/src/object.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: object.c,v 1.51 1998/05/17 20:43:01 grubba Exp $");
+RCSID("$Id: object.c,v 1.52 1998/05/25 10:38:46 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -748,8 +748,15 @@ union anything *object_get_item_ptr(struct object *o,
   }
 
   f=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX;
+
   if(FIND_LFUN(p,f) != -1)
-    error("Cannot do incremental operations on overloaded index (yet).\n");
+  {
+    return 0;
+
+    /* error("Cannot do incremental operations on overloaded index (yet).\n");
+     */
+  }
+    
 
   switch(index->type)
   {
diff --git a/src/operators.c b/src/operators.c
index b553b4dbf53d6c756467dc7eb5a7464502e0f638..5198f538b8e1c6de987170fea7fce38d201b67ef 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -5,7 +5,7 @@
 \*/
 #include <math.h>
 #include "global.h"
-RCSID("$Id: operators.c,v 1.32 1998/04/17 05:08:02 hubbe Exp $");
+RCSID("$Id: operators.c,v 1.33 1998/05/25 10:38:46 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -24,6 +24,7 @@ RCSID("$Id: operators.c,v 1.32 1998/04/17 05:08:02 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "pike_types.h"
+#include "module_support.h"
 
 #define COMPARISON(ID,NAME,FUN)			\
 void ID(INT32 args)				\
@@ -1729,6 +1730,67 @@ static int generate_call_function(node *n)
   return 1;
 }
 
+struct program *string_assignment_program;
+
+#undef THIS
+#define THIS ((struct string_assignment_storage *)(fp->current_storage))
+static void f_string_assignment_index(INT32 args)
+{
+  INT32 i;
+  get_all_args("string[]",args,"%i",&i);
+  if(i<0) i+=THIS->s->len;
+  if(i<0)
+    i+=THIS->s->len;
+  if(i<0 || i>=THIS->s->len)
+    error("Index %d is out of range 0 - %d.\n", i, THIS->s->len-1);
+  else
+    i=EXTRACT_UCHAR(THIS->s->str + i);
+  pop_n_elems(args);
+  push_int(i);
+}
+
+static void f_string_assignment_assign_index(INT32 args)
+{
+  INT32 i,j;
+  union anything *u;
+  get_all_args("string[]=",args,"%i%i",&i,&j);
+  if((u=get_pointer_if_this_type(THIS->lval, T_STRING)))
+  {
+    free_string(THIS->s);
+    if(i<0) i+=u->string->len;
+    if(i<0 || i>=u->string->len)
+      error("String index out of range %ld\n",(long)i);
+    u->string=modify_shared_string(u->string,i,j);
+    copy_shared_string(THIS->s, u->string);
+  }else{
+    lvalue_to_svalue_no_free(sp,THIS->lval);
+    sp++;
+    if(sp[-1].type != T_STRING) error("string[]= failed.\n");
+    if(i<0) i+=sp[-1].u.string->len;
+    if(i<0 || i>=sp[-1].u.string->len)
+      error("String index out of range %ld\n",(long)i);
+    sp[-1].u.string=modify_shared_string(sp[-1].u.string,i,j);
+    assign_lvalue(THIS->lval, sp-1);
+    pop_stack();
+  }
+  pop_n_elems(args);
+  push_int(j);
+}
+
+
+static void init_string_assignment_storage(struct object *o)
+{
+  THIS->lval[0].type=T_INT;
+  THIS->lval[1].type=T_INT;
+  THIS->s=0;
+}
+
+static void exit_string_assignment_storage(struct object *o)
+{
+  free_svalues(THIS->lval, 2, BIT_MIXED);
+  if(THIS->s)
+    free_string(THIS->s);
+}
 
 void init_operators(void)
 {
@@ -1819,4 +1881,23 @@ void init_operators(void)
 
   /* This one should be removed */
   add_efun2("call_function",f_call_function,"function(mixed,mixed ...:mixed)",OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function);
+
+
+  start_new_program();
+  add_storage(sizeof(struct string_assignment_storage));
+  add_function("`[]",f_string_assignment_index,"function(int:int)",0);
+  add_function("`[]=",f_string_assignment_assign_index,"function(int,int:int)",0);
+  set_init_callback(init_string_assignment_storage);
+  set_exit_callback(exit_string_assignment_storage);
+  string_assignment_program=end_program();
+}
+
+
+void exit_operators()
+{
+  if(string_assignment_program)
+  {
+    free_program(string_assignment_program);
+    string_assignment_program=0;
+  }
 }
diff --git a/src/operators.h b/src/operators.h
index f85f1a081d489f98d4c98662bd9eff5ffd80ec8f..d148275a7e9dbfd008084cde47f148ffdfde06bb 100644
--- a/src/operators.h
+++ b/src/operators.h
@@ -5,20 +5,27 @@
 \*/
 
 /*
- * $Id: operators.h,v 1.4 1998/03/28 15:07:37 grubba Exp $
+ * $Id: operators.h,v 1.5 1998/05/25 10:38:46 hubbe Exp $
  */
 #ifndef OPERATORS_H
 #define OPERATORS_H
 
 #define COMPARISON(ID,NAME,X) void ID(INT32 num_arg);
 
+extern struct program *string_assignment_program;
+struct string_assignment_storage
+{
+  struct svalue lval[2];
+  struct pike_string *s;
+};
+
 /* Prototypes begin here */
-COMPARISON(f_eq,"`==", is_eq(sp-2,sp-1))
-COMPARISON(f_ne,"`!=",!is_eq(sp-2,sp-1))
-COMPARISON(f_lt,"`<" , is_lt(sp-2,sp-1))
-COMPARISON(f_le,"`<=",!is_gt(sp-2,sp-1))
-COMPARISON(f_gt,"`>" , is_gt(sp-2,sp-1))
-COMPARISON(f_ge,"`>=",!is_lt(sp-2,sp-1))
+void f_ne(INT32 args);
+COMPARISON(f_eq,"`==", is_eq)
+COMPARISON(f_lt,"`<" , is_lt)
+COMPARISON(f_le,"`<=",!is_gt)
+COMPARISON(f_gt,"`>" , is_gt)
+COMPARISON(f_ge,"`>=",!is_lt)
 
 void f_add(INT32 args);
 void o_subtract(void);
@@ -49,6 +56,7 @@ void f_index(INT32 args);
 void f_arrow(INT32 args);
 void f_sizeof(INT32 args);
 void init_operators(void);
+void exit_operators();
 /* Prototypes end here */
 
 #undef COMPARISON
diff --git a/src/stralloc.c b/src/stralloc.c
index b64ae337f18b4b8e46b28f7893b21c55ff3ab63a..64ff0a111dd0170c18d90ec08b2eb5eb8f1a35f5 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -15,7 +15,7 @@
 
 #include <ctype.h>
 
-RCSID("$Id: stralloc.c,v 1.35 1998/04/24 00:09:35 hubbe Exp $");
+RCSID("$Id: stralloc.c,v 1.36 1998/05/25 10:38:46 hubbe Exp $");
 
 #define BEGIN_HASH_SIZE 997
 #define MAX_AVG_LINK_LENGTH 3
@@ -639,14 +639,14 @@ struct pike_string *realloc_shared_string(struct pike_string *a, INT32 size)
  */
 struct pike_string *modify_shared_string(struct pike_string *a,
 					 INT32 index,
-					 char c)
+					 int c)
 {
 #ifdef DEBUG
   if(index<0 || index>=a->len)
     fatal("Index out of range in modify_shared_string()\n");
 #endif
 
-  if(a->str[index]==c) return a;
+  if(EXTRACT_UCHAR(a->str+index)==c) return a;
 
   if(a->refs==1)
   {
@@ -663,7 +663,7 @@ struct pike_string *modify_shared_string(struct pike_string *a,
     struct pike_string *r;
     r=begin_shared_string(a->len);
     MEMCPY(r->str, a->str, a->len);
-    a->str[index]=c;
+    r->str[index]=c;
     free_string(a);
     return end_shared_string(r);
   }
diff --git a/src/stralloc.h b/src/stralloc.h
index 23d76dc1cbd78628c895617a2bfdeb6b0ddf17c3..243a8606f0ec77a7e5bca3c9401af7b3b16d6571 100644
--- a/src/stralloc.h
+++ b/src/stralloc.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: stralloc.h,v 1.15 1998/03/28 15:09:14 grubba Exp $
+ * $Id: stralloc.h,v 1.16 1998/05/25 10:38:46 hubbe Exp $
  */
 #ifndef STRALLOC_H
 #define STRALLOC_H
@@ -99,7 +99,7 @@ struct pike_string *realloc_unlinked_string(struct pike_string *a, INT32 size);
 struct pike_string *realloc_shared_string(struct pike_string *a, INT32 size);
 struct pike_string *modify_shared_string(struct pike_string *a,
 					 INT32 index,
-					 char c);
+					 int c);
 struct pike_string *add_shared_strings(struct pike_string *a,
 					 struct pike_string *b);
 struct pike_string *add_and_free_shared_strings(struct pike_string *a,
diff --git a/src/testsuite.in b/src/testsuite.in
index b3eb6ba505255781b17d7dc70ee1be965478fa17..51b16eafdc8d4981826016be98aa687b1f064e30 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,4 @@
-stest_true([["$Id: testsuite.in,v 1.113 1998/05/24 23:21:00 marcus Exp $"]])
+stest_true([["$Id: testsuite.in,v 1.114 1998/05/25 10:38:47 hubbe Exp $"]])
 cond([[all_constants()->_verify_internals]],
 [[
   test_do(_verify_internals())
@@ -2375,6 +2375,21 @@ test_equal(Array.everynth("0123456789"/"",3,4),
 
 test_equal(Array.transpose( ({ ({ 1,2,3}), ({4,5,6}) }) ),
 	({ ({1,4}), ({2,5}), ({3,6}) }))
+
+test_true(!Yabu.test()->main(1,({"test"})))
+test_do([[
+  string s;
+  for(s="foobar";strlen(s)<78;s+=s)
+  {
+    for(int e=0;e<strlen(s);e++)
+    {
+      s[e]++;
+    }
+  }
+]])
+
+test_any([[string s="foo"; s[2]='t'; s[0]--; return s;]],"eot")
+
 cond([[all_constants()->_verify_internals]],
 [[
   test_do(_verify_internals())