From 19aaeb4399f6f4ee6e1599e98ed98d2e8dfb02b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Mon, 25 May 1998 03:38:47 -0700
Subject: [PATCH] made it possible to set index in strings

Rev: lib/modules/Yabu.pmod/test.pike:1.3
Rev: src/builtin_functions.c:1.111
Rev: src/docode.c:1.38
Rev: src/docode.h:1.7
Rev: src/interpret.c:1.85
Rev: src/main.c:1.53
Rev: src/module_support.c:1.12
Rev: src/object.c:1.52
Rev: src/operators.c:1.33
Rev: src/operators.h:1.5
Rev: src/stralloc.c:1.36
Rev: src/stralloc.h:1.16
Rev: src/testsuite.in:1.114
---
 lib/modules/Yabu.pmod/test.pike |  3 +-
 src/builtin_functions.c         |  4 +-
 src/docode.c                    | 45 +++++++++++++-----
 src/docode.h                    |  7 ++-
 src/interpret.c                 | 33 ++++++++++++-
 src/main.c                      |  5 +-
 src/module_support.c            |  5 +-
 src/object.c                    | 11 ++++-
 src/operators.c                 | 83 ++++++++++++++++++++++++++++++++-
 src/operators.h                 | 22 ++++++---
 src/stralloc.c                  |  8 ++--
 src/stralloc.h                  |  4 +-
 src/testsuite.in                | 17 ++++++-
 13 files changed, 206 insertions(+), 41 deletions(-)

diff --git a/lib/modules/Yabu.pmod/test.pike b/lib/modules/Yabu.pmod/test.pike
index a30780a77b..6f9fb39b83 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 316dd9b72c..b0c85a48c6 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 765c6392cb..3866fb9e1a 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 69e3a03377..f249782b39 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 8151f6bfb7..1228002c26 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 aadbf7b078..db2699e769 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 186ab37af9..18a85a08e4 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 afe58ce507..f0c32330fa 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 b553b4dbf5..5198f538b8 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 f85f1a081d..d148275a7e 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 b64ae337f1..64ff0a111d 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 23d76dc1cb..243a8606f0 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 b3eb6ba505..51b16eafdc 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())
-- 
GitLab