diff --git a/src/docode.c b/src/docode.c
index 5e1444c88b36cf2be4434047d3533252cd44d6b8..0fecbb09ee1039a020e6a9e6db462f238b899c0d 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.43 1999/01/31 09:01:44 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.44 1999/02/10 01:29:05 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -331,7 +331,8 @@ static int do_docode2(node *n,int flags)
 #endif
 
     if(match_types(CAR(n)->type,array_type_string) ||
-       match_types(CAR(n)->type,string_type_string))
+       match_types(CAR(n)->type,string_type_string) ||
+       match_types(CAR(n)->type,object_type_string))
     {
       code_expression(CDR(n), 0, "assignment");
       emit2(F_LTOSVAL2);
diff --git a/src/lex.c b/src/lex.c
index 12ab77fe67ccb48b875f81b8d12db837221cab13..26a4fcee1f420960c3f9b3016d7ae85408a5d7cc 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.61 1999/01/31 09:01:53 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.62 1999/02/10 01:29:06 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -722,7 +722,6 @@ static int yylex2(YYSTYPE *yylval)
       
       switch(GETC())
       {
-      case '+': tmp="```+"; break;
       case '/': tmp="```/"; break;
       case '%': tmp="```%"; break;
       case '*': tmp="```*"; break;
@@ -730,6 +729,10 @@ static int yylex2(YYSTYPE *yylval)
       case '|': tmp="```|"; break;
       case '^': tmp="```^"; break;
       case '~': tmp="```~"; break;
+      case '+':
+	if(GOBBLE('=')) { tmp="```+="; break; }
+	tmp="```+";
+	break;
       case '<':
 	if(GOBBLE('<')) { tmp="```<<"; break; }
 	if(GOBBLE('=')) { tmp="```<="; break; }
diff --git a/src/modules/Gmp/mpz_glue.c b/src/modules/Gmp/mpz_glue.c
index a5b05b1248660d8712d1d641324809ffdead198c..45d37de6e24972ef0fdaa984177f4ae05a41e7b8 100644
--- a/src/modules/Gmp/mpz_glue.c
+++ b/src/modules/Gmp/mpz_glue.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: mpz_glue.c,v 1.37 1999/02/01 02:42:21 hubbe Exp $");
+RCSID("$Id: mpz_glue.c,v 1.38 1999/02/10 01:29:43 hubbe Exp $");
 #include "gmp_machine.h"
 
 #if defined(HAVE_GMP2_GMP_H) && defined(HAVE_LIBGMP2)
@@ -438,6 +438,19 @@ BINFUN(mpzmod_add,mpz_add)
 BINFUN(mpzmod_mul,mpz_mul)
 BINFUN(mpzmod_gcd,mpz_gcd)
 
+
+static void mpzmod_add_eq(INT32 args)
+{
+  INT32 e;
+  struct object *res;
+  for(e=0; e<args; e++)
+    get_mpz(sp+e-args, 1);
+  for(e=0;e<args;e++)
+    mpz_add(THIS, THIS, OBTOMPZ(sp[e-args].u.object));
+  pop_n_elems(args);
+  ref_push_object(fp->current_object);
+}
+
 static void mpzmod_sub(INT32 args)
 {
   INT32 e;
@@ -930,6 +943,7 @@ void pike_module_init(void)
 #define MPZ_BINOP_TYPE ("function(" MPZ_ARG_TYPE "...:object)")
 
   add_function("`+",mpzmod_add,MPZ_BINOP_TYPE,0);
+  add_function("`+=",mpzmod_add_eq,MPZ_BINOP_TYPE,0);
   add_function("``+",mpzmod_add,MPZ_BINOP_TYPE,0);
   add_function("`-",mpzmod_sub,MPZ_BINOP_TYPE,0);
   add_function("``-",mpzmod_rsub,MPZ_BINOP_TYPE,0);
diff --git a/src/operators.c b/src/operators.c
index b102c8729ea62e93becb66d31d99d2b97f2d58a9..90b76c1bb6b29a333808ff0e2c9f766dacf4215f 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -5,7 +5,7 @@
 \*/
 #include "global.h"
 #include <math.h>
-RCSID("$Id: operators.c,v 1.45 1999/02/01 02:41:41 hubbe Exp $");
+RCSID("$Id: operators.c,v 1.46 1999/02/10 01:29:07 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -90,15 +90,23 @@ void f_add(INT32 args)
     }else{
       if(types & BIT_OBJECT)
       {
-	if(sp[-args].type == T_OBJECT &&
-	  sp[-args].u.object->prog &&
-	   FIND_LFUN(sp[-args].u.object->prog,LFUN_ADD) != -1)
+	if(sp[-args].type == T_OBJECT && sp[-args].u.object->prog)
 	{
-	  apply_lfun(sp[-args].u.object, LFUN_ADD, args-1);
-	  free_svalue(sp-2);
-	  sp[-2]=sp[-1];
-	  sp--;
-	  return;
+	  if(sp[-args].u.object->refs==1 &&
+	     FIND_LFUN(sp[-args].u.object->prog,LFUN_ADD_EQ) != -1)
+	  {
+	    apply_lfun(sp[-args].u.object, LFUN_ADD_EQ, args-1);
+	    pop_stack();
+	    return;
+	  }
+	  if(FIND_LFUN(sp[-args].u.object->prog,LFUN_ADD) != -1)
+	  {
+	    apply_lfun(sp[-args].u.object, LFUN_ADD, args-1);
+	    free_svalue(sp-2);
+	    sp[-2]=sp[-1];
+	    sp--;
+	    return;
+	  }
 	}
 	for(e=1;e<args;e++)
 	{
@@ -282,6 +290,25 @@ void f_add(INT32 args)
     break;
   }
 
+  case BIT_ARRAY|BIT_INT:
+  {
+    if(IS_UNDEFINED(sp-args))
+    {
+      int e;
+      struct array *a;
+
+      for(e=1;e<args;e++)
+	if(sp[e-args].type != T_ARRAY)
+	  error("`+: trying to add integers and arrays.\n");
+
+      a=add_arrays(sp-args+1,args-1);
+      pop_n_elems(args);
+      push_array(a);
+      return;
+    }
+    error("`+: trying to add integers and arrays.\n");
+  }
+      
   case BIT_ARRAY:
   {
     struct array *a;
diff --git a/src/program.c b/src/program.c
index 432c000183c5fc1a05da587b2a823b48d1a9d92e..1579fd92eb0bbd65719354724863df48f7687f54 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: program.c,v 1.108 1999/02/01 02:41:43 hubbe Exp $");
+RCSID("$Id: program.c,v 1.109 1999/02/10 01:29:08 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -90,6 +90,7 @@ char *lfun_names[] = {
   "``*",
   "``/",
   "``%",
+  "`+=",
 };
 
 struct program *first_program = 0;
diff --git a/src/program.h b/src/program.h
index 50ba895c6fa3f994efae201c4af8b2876c43b38c..dbaead1c24cdb08e4e691d8b1fd2592800cfe78c 100644
--- a/src/program.h
+++ b/src/program.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: program.h,v 1.49 1999/02/01 02:41:45 hubbe Exp $
+ * $Id: program.h,v 1.50 1999/02/10 01:29:10 hubbe Exp $
  */
 #ifndef PROGRAM_H
 #define PROGRAM_H
@@ -55,8 +55,9 @@
 #define LFUN_RMULTIPLY 35
 #define LFUN_RDIVIDE 36
 #define LFUN_RMOD 37
+#define LFUN_ADD_EQ 38
 
-#define NUM_LFUNS 38
+#define NUM_LFUNS 39
 
 extern char *lfun_names[];
 
diff --git a/src/security.c b/src/security.c
index 8055f73765bf60040869ce5bf55400af48fafdde..0b3e95589828529dbf2b4e33a864655deca98c6b 100644
--- a/src/security.c
+++ b/src/security.c
@@ -1,7 +1,8 @@
 #include "global.h"
 
 /* To do:
- * controls for file->connect() & file->open_socket()
+ * controls for file->pipe()
+ * controls for kill/create_process/signal
  * controls for all/most functions in the system module
  * controls for all/most functions in files/efun.c
  * controls for all/most functions in spider
diff --git a/src/testsuite.in b/src/testsuite.in
index 444c138f69025c5fe16ef45a810b280636486797..5e537def4dec81d3004dde3c5df6bc7113ea3182 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,4 @@
-stest_true([["$Id: testsuite.in,v 1.145 1999/02/06 03:03:07 mast Exp $"]])
+stest_true([["$Id: testsuite.in,v 1.146 1999/02/10 01:29:12 hubbe Exp $"]])
 cond([[all_constants()->_verify_internals]],
 [[
   test_do(_verify_internals())
@@ -843,6 +843,8 @@ test_equal([[ `+( ([1:2]), ([1:2]), ([2:3,4:5]), ([6:7,1:2]),([8:9])  )]],[[ ([1
 
 test_any([[mapping m=([1:2,3:2]); return search(m,2,search(m,2))!=-1;]],1)
 
+test_any([[mapping m=([]); for(int e=0;e<1000;e++) m[e&3]+=({e}); return sizeof(m)==4 && sizeof(m[0])==250;]],1)
+
 // rows
 test_equal([[rows(({1,2,3,4,5,6,7,8,9}),({6,7,2}))]],[[({7,8,3})]])
 test_equal([[rows(({1,2,3,4,5,6,7,8,9}),({0,4,1}))]],[[({1,5,2})]])