diff --git a/src/backend.cmod b/src/backend.cmod
index 1cc2d861f89814eeffb9b92e73d419ebda0992de..3125f7a0c3f558f663bbbf096ebdd11647990b33 100644
--- a/src/backend.cmod
+++ b/src/backend.cmod
@@ -1957,7 +1957,7 @@ PIKECLASS Backend
    PIKEFUN string _sprintf(int type, mapping flags)
    {
      if (type == 'O') {
-       push_constant_text ("Pike.Backend(%d)");
+       push_text ("Pike.Backend(%d)");
        push_int (THIS->id);
        f_sprintf (2);
        stack_pop_n_elems_keep_top (args);
diff --git a/src/builtin.cmod b/src/builtin.cmod
index f4d0af8584530456ac0d2ea9c2718ebad4fb89b5..fee6f7634bad37cb554ca8aaf79d0d49f891d3b8 100644
--- a/src/builtin.cmod
+++ b/src/builtin.cmod
@@ -780,12 +780,12 @@ PIKEFUN string basetype(mixed x)
     case T_ZERO: push_constant_text("zero"); break;
     case T_VOID: push_constant_text("void"); break;
       /* The following are internal and shouldn't be applicable in normal use. */
-    case T_SVALUE_PTR: push_constant_text("svalue_ptr"); break;
-    case T_OBJ_INDEX: push_constant_text("obj_index"); break;
-    case T_MAPPING_DATA: push_constant_text("mapping_data"); break;
-    case T_PIKE_FRAME: push_constant_text("pike_frame"); break;
-    case T_MULTISET_DATA: push_constant_text("multiset_data"); break;
-    default: push_constant_text("unknown"); break;
+    case T_SVALUE_PTR: push_text("svalue_ptr"); break;
+    case T_OBJ_INDEX: push_text("obj_index"); break;
+    case T_MAPPING_DATA: push_text("mapping_data"); break;
+    case T_PIKE_FRAME: push_text("pike_frame"); break;
+    case T_MULTISET_DATA: push_text("multiset_data"); break;
+    default: push_text("unknown"); break;
   }
 }
 
@@ -1741,7 +1741,7 @@ PIKEFUN string program_defined(program p)
     push_string(tmp);
     if(line >= 1)
     {
-      push_constant_text(":");
+      push_text(":");
       push_int(line);
       f_add(3);
     }
@@ -2830,17 +2830,17 @@ PIKEFUN mapping(string:int|string) get_runtime_info()
   optflags OPT_TRY_OPTIMIZE;
 {
   pop_n_elems(args);
-  push_constant_text("bytecode_method");
-  push_constant_text(PIKE_BYTECODE_METHOD_NAME);
-  push_constant_text("abi");
+  push_text("bytecode_method");
+  push_text(PIKE_BYTECODE_METHOD_NAME);
+  push_text("abi");
   push_int(sizeof(void *) * 8);
-  push_constant_text("native_byteorder");
+  push_text("native_byteorder");
   push_int(PIKE_BYTEORDER);
-  push_constant_text("int_size");
+  push_text("int_size");
   push_int(sizeof(INT_TYPE) * 8);
-  push_constant_text("float_size");
+  push_text("float_size");
   push_int(sizeof(FLOAT_TYPE) * 8);
-  push_constant_text("auto_bignum");
+  push_text("auto_bignum");
   push_int(1);
   f_aggregate_mapping(6*2);
 }
@@ -4488,14 +4488,14 @@ PIKECLASS Setter
   {
     struct program *prog;
     if (!THIS->o) {
-      push_constant_text("Setter()");
+      push_text("Setter()");
     } else if ((prog = THIS->o->prog)) {
-      push_constant_text("%O->`%s=");
+      push_text("%O->`%s=");
       ref_push_object(THIS->o);
       ref_push_string(ID_FROM_INT(prog, THIS->f)->name);
       f_sprintf(3);
     } else {
-      push_constant_text("Setter(destructed object)");
+      push_text("Setter(destructed object)");
     }
     stack_pop_n_elems_keep_top(args);
   }
@@ -4591,7 +4591,7 @@ PIKECLASS Null
   {
     pop_n_elems(args);
     if (fmt == 'O') {
-      push_constant_text("Val.null");
+      push_text("Val.null");
     } else {
       push_undefined();
     }
@@ -5361,33 +5361,33 @@ PIKECLASS List
     flags ID_PROTECTED;
   {
     if (!THIS->num_elems) {
-      push_constant_text("ADT.List(/* empty */)");
+      push_text("ADT.List(/* empty */)");
     } else if (c == 'O') {
       struct pike_list_node *node = THIS->head;
       if (THIS->num_elems == 1) {
-	push_constant_text("ADT.List(/* 1 element */\n");
+	push_text("ADT.List(/* 1 element */\n");
       } else {
-	push_constant_text("ADT.List(/* %d elements */\n");
+	push_text("ADT.List(/* %d elements */\n");
 	push_int(THIS->num_elems);
 	f_sprintf(2);
       }
       while (node->next) {
 	if (node->next->next) {
-	  push_constant_text("    %O,\n");
+	  push_text("    %O,\n");
 	} else {
-	  push_constant_text("    %O\n");
+	  push_text("    %O\n");
 	}
 	push_svalue(&node->val);
 	f_sprintf(2);
 	node = node->next;
       }
-      push_constant_text(")");
+      push_text(")");
       f_add(THIS->num_elems + 2);
     } else {
       if (THIS->num_elems == 1) {
-	push_constant_text("ADT.List(/* 1 element */)");
+	push_text("ADT.List(/* 1 element */)");
       } else {
-	push_constant_text("ADT.List(/* %d elements */)");
+	push_text("ADT.List(/* %d elements */)");
 	push_int(THIS->num_elems);
 	f_sprintf(2);
       }
@@ -6092,7 +6092,7 @@ static struct object *val_module;
 static void get_val_module()
 {
   assert (!val_module);
-  push_constant_text ("Val");
+  push_text ("Val");
   APPLY_MASTER ("resolv", 1);
   if (TYPEOF(Pike_sp[-1]) != T_OBJECT)
     Pike_error ("\"Val\" didn't resolve to a module object.\n");
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 73b679bba9af588eda3d311bd54e738ff15a2a38..7e3e01d32908c1dcf3bfc1259b959a790dfc2edb 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -7926,7 +7926,7 @@ PMOD_EXPORT void f_replace_master(INT32 args)
     bad_arg_error("replace_master", Pike_sp-args, args, 1, "object", Pike_sp-args,
 		  "Subtyped master objects are not supported yet.\n");
 
-  push_constant_text ("is_pike_master");
+  push_text ("is_pike_master");
   args++;
   object_set_index (new_master, 0, Pike_sp - 1, (struct svalue *) &svalue_int_one);
 
@@ -9441,7 +9441,7 @@ PMOD_EXPORT void f_program_identifier_defined(INT32 args)
           push_string(tmp);
           if(line >= 1)
           {
-              push_constant_text(":");
+              push_text(":");
               push_int(line);
               f_add(3);
           }
@@ -9470,7 +9470,7 @@ PMOD_EXPORT void f_program_identifier_defined(INT32 args)
       pop_n_elems(args);
       if (line) {
           push_string(file);
-          push_constant_text(":");
+          push_text(":");
           push_int(line);
           f_add(3);
       }
@@ -9618,7 +9618,7 @@ PMOD_EXPORT void f_function_defined(INT32 args)
       pop_n_elems(args);
       if (line) {
 	push_string(file);
-	push_constant_text(":");
+	push_text(":");
 	push_int(line);
 	f_add(3);
       }
diff --git a/src/cpp.c b/src/cpp.c
index d7ecec95ec537976a6a8c53a796ea6648e274c8b..b3bc819b3d80e6927c3444438c6f9306ab08961d 100644
--- a/src/cpp.c
+++ b/src/cpp.c
@@ -916,12 +916,12 @@ static void cpp_constant(struct cpp *this, int value)
 
   /* FIXME: Protection against errors. */
   /* Remove extra whitespace. */
-  push_constant_text(" ");
+  push_text(" ");
   o_subtract();
-  push_constant_text("\t");
+  push_text("\t");
   o_subtract();
   /* Split on . */
-  push_constant_text(".");
+  push_text(".");
   o_divide();
 #ifdef PIKE_DEBUG
   if (TYPEOF(Pike_sp[-1]) != T_ARRAY) {
@@ -988,7 +988,7 @@ static void cpp_constant(struct cpp *this, int value)
     }
   } else {
     /* Handle constant(.foo) */
-    push_constant_text(".");
+    push_text(".");
     ref_push_string(this->current_file);
 
     if (this->handler) {
@@ -1791,7 +1791,7 @@ static struct pike_string *recode_string(struct cpp *this, struct pike_string *d
 
     push_string(end_shared_string(new_str));
 
-    push_constant_text("ebcdic-us");
+    push_text("ebcdic-us");
 
     if (safe_apply_handler ("decode_charset", this->handler, this->compat_handler,
 			    2, BIT_STRING)) {
@@ -3340,8 +3340,8 @@ void f_cpp(INT32 args)
       struct keypair *k;
       int e, sprintf_args = 0;
       if (TYPEOF(sp[-1]) != T_MAPPING) {
-	push_constant_text ("Invalid return value from get_predefines\n");
-	push_constant_text ("Invalid return value from get_predefines, got %O\n");
+	push_text ("Invalid return value from get_predefines\n");
+	push_text ("Invalid return value from get_predefines, got %O\n");
 	push_svalue (sp - 3);
 	sprintf_args = 2;
       }
@@ -3349,8 +3349,8 @@ void f_cpp(INT32 args)
 	predefs = copy_mapping (sp[-1].u.mapping);
 	NEW_MAPPING_LOOP (predefs->data) {
 	  if (TYPEOF(k->ind) != T_STRING || !k->ind.u.string->len) {
-	    push_constant_text ("Expected nonempty string as predefine name\n");
-	    push_constant_text ("Expected nonempty string as predefine name, got %O\n");
+	    push_text ("Expected nonempty string as predefine name\n");
+	    push_text ("Expected nonempty string as predefine name, got %O\n");
 	    push_svalue (&k->ind);
 	    sprintf_args = 2;
 	    free_mapping (predefs);
@@ -3361,9 +3361,9 @@ void f_cpp(INT32 args)
 		   && TYPEOF(k->val) != T_FUNCTION
 		   && TYPEOF(k->val) != T_OBJECT) {
 
-	     push_constant_text ("expected zero, string or function value for"
+	     push_text ("expected zero, string or function value for"
 				 " predefine\n");
-	     push_constant_text ("expected zero, string or function value for"
+	     push_text ("expected zero, string or function value for"
 				 " predefine %O\n");
 	     push_svalue (&k->ind);
 	     sprintf_args = 2;
diff --git a/src/dynamic_load.c b/src/dynamic_load.c
index dbef6e044496b6b03cd7d175fb4ebf274ea78670..79d6dce824b9822684dede2add15a266a928ee12 100644
--- a/src/dynamic_load.c
+++ b/src/dynamic_load.c
@@ -497,7 +497,7 @@ void f_load_module(INT32 args)
 	push_text (err);
     }
     else
-      push_constant_text ("Unknown reason");
+      push_text ("Unknown reason");
 
     add_ref (LOADERR_STRUCT (err_obj)->path = Pike_sp[-args - 1].u.string);
     add_ref (LOADERR_STRUCT (err_obj)->reason = Pike_sp[-1].u.string);
diff --git a/src/encode.c b/src/encode.c
index 03355c4ec479fbc02ef5d2f8963f106f930d0c79..b6ef32a87f536b2de083cadd41063fc3d770141e 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -2217,14 +2217,14 @@ static DECLSPEC(noreturn) void decode_error (
   copy_shared_string (dec->decode_string, data->data_str);
 
   if (decoding) {
-    push_constant_text ("Error while decoding "); n++;
-    push_constant_text ("%O");
+    push_text ("Error while decoding "); n++;
+    push_text ("%O");
     push_svalue (decoding);
     f_sprintf (2); n++;
-    push_constant_text (":\n"); n++;
+    push_text (":\n"); n++;
   }
   else {
-    push_constant_text ("Decode error: "); n++;
+    push_text ("Decode error: "); n++;
   }
 
   init_string_builder (&sb, 0);
diff --git a/src/error.c b/src/error.c
index f617cedf7f5b1cc1014644c811278526f60c62d5..36242bfb44acca0a823bbbad057276bc9917850d 100644
--- a/src/error.c
+++ b/src/error.c
@@ -782,7 +782,7 @@ static void f_error__sprintf(INT32 args)
     }
   }
 
-  push_constant_text("(%O)");
+  push_text("(%O)");
   if(GENERIC_ERROR_THIS->error_message)
     ref_push_string(GENERIC_ERROR_THIS->error_message);
   else
diff --git a/src/gc.c b/src/gc.c
index 13d5cfd2435391ad516952113d6135dd79098a35..e9db3382f2113d27174b04a3aa13b6188eda9af6 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -3409,6 +3409,7 @@ static void warn_bad_cycles(void)
    * (On some architectures longjump() might restore obj_arr's original
    * value (eg if obj_arr is in a register)).
    */
+#if 0
   struct array **obj_arr_ = (struct array **)xalloc(sizeof(struct array *));
   ONERROR tmp;
 
@@ -3416,7 +3417,6 @@ static void warn_bad_cycles(void)
 
   SET_ONERROR(tmp, free_obj_arr, obj_arr_);
 
-#if 0
   {
     struct gc_pop_frame *p;
     unsigned cycle = 0;
@@ -3431,8 +3431,8 @@ static void warn_bad_cycles(void)
       p = p->next;
       if (p ? ((unsigned)(p->cycle != cycle)) : cycle) {
 	if ((*obj_arr_)->size >= 2) {
-	  push_constant_text("gc");
-	  push_constant_text("bad_cycle");
+	  push_text("gc");
+	  push_text("bad_cycle");
 	  push_array(*obj_arr_);
 	  *obj_arr_ = 0;
 	  SAFE_APPLY_MASTER("runtime_warning", 3);
@@ -3444,9 +3444,9 @@ static void warn_bad_cycles(void)
       if (!p) break;
     }
   }
-#endif
 
   CALL_AND_UNSET_ONERROR(tmp);
+#endif
 }
 
 size_t do_gc(void *UNUSED(ignored), int explicit_call)
@@ -4227,51 +4227,51 @@ void f__gc_status(INT32 args)
 
   pop_n_elems(args);
 
-  push_constant_text("num_objects");
+  push_text("num_objects");
   push_int(num_objects);
   size++;
 
-  push_constant_text("num_allocs");
+  push_text("num_allocs");
   push_int64(num_allocs);
   size++;
 
-  push_constant_text("alloc_threshold");
+  push_text("alloc_threshold");
   push_int64(alloc_threshold);
   size++;
 
-  push_constant_text("projected_garbage");
+  push_text("projected_garbage");
   push_float(DO_NOT_WARN((FLOAT_TYPE)(objects_freed * (double) num_allocs /
 				      (double) alloc_threshold)));
   size++;
 
-  push_constant_text("objects_alloced");
+  push_text("objects_alloced");
   push_int64(DO_NOT_WARN((INT64)objects_alloced));
   size++;
 
-  push_constant_text("objects_freed");
+  push_text("objects_freed");
   push_int64(DO_NOT_WARN((INT64)objects_freed));
   size++;
 
-  push_constant_text("last_garbage_ratio");
+  push_text("last_garbage_ratio");
   push_float(DO_NOT_WARN((FLOAT_TYPE) last_garbage_ratio));
   size++;
 
-  push_constant_text("non_gc_time");
+  push_text("non_gc_time");
   push_int64(DO_NOT_WARN((INT64) non_gc_time));
   size++;
 
-  push_constant_text("gc_time");
+  push_text("gc_time");
   push_int64(DO_NOT_WARN((INT64) gc_time));
   size++;
 
-  push_constant_text ("last_garbage_strategy");
+  push_text ("last_garbage_strategy");
   switch (last_garbage_strategy) {
     case GARBAGE_RATIO_LOW:
-      push_constant_text ("garbage_ratio_low"); break;
+      push_text ("garbage_ratio_low"); break;
     case GARBAGE_RATIO_HIGH:
-      push_constant_text ("garbage_ratio_high"); break;
+      push_text ("garbage_ratio_high"); break;
     case GARBAGE_MAX_INTERVAL:
-      push_constant_text ("garbage_max_interval"); break;
+      push_text ("garbage_max_interval"); break;
 #ifdef PIKE_DEBUG
     default:
       Pike_fatal ("Unknown last_garbage_strategy %d\n", last_garbage_strategy);
@@ -4279,11 +4279,11 @@ void f__gc_status(INT32 args)
   }
   size++;
 
-  push_constant_text("last_gc");
+  push_text("last_gc");
   push_int64(last_gc);
   size++;
 
-  push_constant_text ("total_gc_cpu_time");
+  push_text ("total_gc_cpu_time");
   push_int64 (auto_gc_time);
 #ifndef LONG_CPU_TIME
   push_int (1000000000 / CPU_TIME_TICKS);
@@ -4291,7 +4291,7 @@ void f__gc_status(INT32 args)
 #endif
   size++;
 
-  push_constant_text ("total_gc_real_time");
+  push_text ("total_gc_real_time");
   push_int64 (auto_gc_real_time);
 #ifndef LONG_CPU_TIME
   push_int (1000000000 / CPU_TIME_TICKS);
@@ -4300,15 +4300,15 @@ void f__gc_status(INT32 args)
   size++;
 
 #ifdef PIKE_DEBUG
-  push_constant_text ("max_rec_frames");
+  push_text ("max_rec_frames");
   push_int64 (DO_NOT_WARN ((INT64) tot_max_rec_frames));
   size++;
 
-  push_constant_text ("max_link_frames");
+  push_text ("max_link_frames");
   push_int64 (DO_NOT_WARN ((INT64) tot_max_link_frames));
   size++;
 
-  push_constant_text ("max_free_extra_frames");
+  push_text ("max_free_extra_frames");
   push_int64 (DO_NOT_WARN ((INT64) tot_max_free_extra_frames));
   size++;
 #endif
diff --git a/src/modules/Gettext/gettext.c b/src/modules/Gettext/gettext.c
index 8bdf3baa744dcd110670ff525126b5f35a81cf2a..5a18c986c131018332d521a42feb7c13ed78b5c2 100644
--- a/src/modules/Gettext/gettext.c
+++ b/src/modules/Gettext/gettext.c
@@ -383,11 +383,11 @@ void f_localeconv(INT32 args)
   locale = localeconv();
 
 #define MAPSTR(key) do {		\
-    push_constant_text(TOSTR(key));	\
+    push_text(TOSTR(key));	\
     push_text(locale->key);		\
   } while(0)
 #define MAPINT(key) do {		\
-    push_constant_text(TOSTR(key));	\
+    push_text(TOSTR(key));	\
     push_int(locale->key);		\
   } while(0)
 
diff --git a/src/modules/Gmp/mpf.cmod b/src/modules/Gmp/mpf.cmod
index c515834b9092a670d3de56779b85eec9d00fdb48..cc4d682297b0cc9dc4534a518e807d5439c52cd6 100644
--- a/src/modules/Gmp/mpf.cmod
+++ b/src/modules/Gmp/mpf.cmod
@@ -320,9 +320,9 @@ PIKECLASS mpf
 	  return;
 
 	case 'O':
-	  push_constant_text ("Gmp.mpf(");
+	  push_text ("Gmp.mpf(");
 	  f_mpf_get_string(0);
-	  push_constant_text (")");
+	  push_text (")");
 	  f_add (3);
 	  return;
 
@@ -341,11 +341,14 @@ PIKECLASS mpf
    *! @fixme
    *!   Perhaps it should also return true for @expr{"object"@}?
    */
-  PIKEFUN int(0..1) _is_type(string UNUSED)
+  PIKEFUN int(0..1) _is_type(string str)
     flags ID_PROTECTED;
     {
-      push_constant_text("float");
-      f_eq(2);
+      struct pike_string *float_t;
+      MAKE_CONST_STRING(float_t,"float");
+      if( str == float_t )
+          RETURN 1;
+      RETURN 0;
     }
 
   /*! @decl static mixed cast(string to)
diff --git a/src/modules/Gmp/mpq.cmod b/src/modules/Gmp/mpq.cmod
index d64d3a2a6afe047d3b39785f39fb68a222afe159..57e352f88877a8f4b0ede17f4bb86e3c069206ce 100644
--- a/src/modules/Gmp/mpq.cmod
+++ b/src/modules/Gmp/mpq.cmod
@@ -466,7 +466,7 @@ PIKECLASS mpq
       /* If the denominator contains other factors we still need to
        * display it. */
       if (mpz_cmp_ui (den, 1u)) {
-	push_constant_text ("/");
+	push_text ("/");
 	push_string (low_get_mpz_digits (den, 10));
 	strings += 2;
       }
@@ -478,7 +478,7 @@ PIKECLASS mpq
 
     else {
       push_string(low_get_mpz_digits(mpq_numref(mpq),10));
-      push_constant_text("/");
+      push_text("/");
       push_string(low_get_mpz_digits(mpq_denref(mpq),10));
       f_add(3);
     }
@@ -579,9 +579,9 @@ PIKECLASS mpq
 	  return;
 
 	case 'O':
-	  push_constant_text ("Gmp.mpq(");
+	  push_text ("Gmp.mpq(");
 	  format_string (THISMPQ, 1);
-	  push_constant_text (")");
+	  push_text (")");
 	  f_add (3);
 	  return;
 
@@ -612,11 +612,14 @@ PIKECLASS mpq
   
   /*! @decl static int(0..1) _is_type(string arg)
    */
-  PIKEFUN int(0..1) _is_type(string UNUSED)
+  PIKEFUN int(0..1) _is_type(string str)
     flags ID_PROTECTED;
     {
-      push_constant_text("float");
-      f_eq(2);
+      struct pike_string *float_t;
+      MAKE_CONST_STRING(float_t,"float");
+      if( str == float_t )
+          RETURN 1;
+      RETURN 0;
     }
 
   /*! @decl static int|string|float|object cast(string s)
diff --git a/src/modules/Gmp/mpz_glue.c b/src/modules/Gmp/mpz_glue.c
index 99c3a3924d658e479dfbfefa89827b1d4f4783b2..1b10edb2268f7c825f54b13df8fc17c24ff296bd 100644
--- a/src/modules/Gmp/mpz_glue.c
+++ b/src/modules/Gmp/mpz_glue.c
@@ -847,7 +847,7 @@ static void mpzmod__sprintf(INT32 args)
     SIMPLE_ARG_TYPE_ERROR ("Gmp.mpz->_sprintf", 2, "mapping");
 
   push_svalue(&sp[1-args]);
-  push_constant_text("precision");
+  push_text("precision");
   f_index(2);
   if(TYPEOF(sp[-1]) != T_INT)
     SIMPLE_ARG_ERROR ("Gmp.mpz->_sprintf", 2,
@@ -855,7 +855,7 @@ static void mpzmod__sprintf(INT32 args)
   precision = (--sp)->u.integer;
   
   push_svalue(&sp[1-args]);
-  push_constant_text("width");
+  push_text("width");
   f_index(2);
   if(TYPEOF(sp[-1]) != T_INT)
     SIMPLE_ARG_ERROR ("Gmp.mpz->_sprintf", 2,
@@ -864,7 +864,7 @@ static void mpzmod__sprintf(INT32 args)
   width = (--sp)->u.integer;
 
   push_svalue(&sp[1-args]);
-  push_constant_text("flag_left");
+  push_text("flag_left");
   f_index(2);
   if(TYPEOF(sp[-1]) != T_INT)
     SIMPLE_ARG_ERROR ("Gmp.mpz->_sprintf", 2,
@@ -879,16 +879,16 @@ static void mpzmod__sprintf(INT32 args)
     case 't':
       pop_n_elems(args);
       if(THIS_PROGRAM == bignum_program)
-	push_constant_text("int");
+	push_text("int");
       else
-	push_constant_text("object");
+	push_text("object");
       return;
 
   case 'O':
     if (THIS_PROGRAM == mpzmod_program) {
-      push_constant_text ("Gmp.mpz(");
+      push_text ("Gmp.mpz(");
       push_string (low_get_mpz_digits (THIS, 10));
-      push_constant_text (")");
+      push_text (")");
       f_add (3);
       s = (--sp)->u.string;
       break;
@@ -1021,14 +1021,12 @@ static void mpzmod__sprintf(INT32 args)
  */
 static void mpzmod__is_type(INT32 args)
 {
-  if(args < 1)
-    SIMPLE_TOO_FEW_ARGS_ERROR("Gmp.mpz->_is_type", 1);
-  if(TYPEOF(sp[-args]) != T_STRING)
-    SIMPLE_ARG_TYPE_ERROR ("Gmp.mpz->_is_type", 1, "string");
-
-  pop_n_elems(args-1);
-  push_constant_text("int");
-  f_eq(2);
+    struct pike_string *int_t;
+    struct pike_string *str;
+    MAKE_CONST_STRING(int_t,"int");
+    get_all_args( "Gmp.mpz->_is_type", args, "%s", &str );
+    pop_n_elems(args); /* even if str is freed here the comparison is OK. */
+    push_int( str == int_t ? 1 : 0 );
 }
 
 /*! @decl int(0..) size(void|int base)
diff --git a/src/modules/HTTPLoop/accept_and_parse.c b/src/modules/HTTPLoop/accept_and_parse.c
index 2e384e850369787de581cdfdee13e8e5ab772bdd..ba0600870d4b0047adc2cf8744ca75af1c688d48 100644
--- a/src/modules/HTTPLoop/accept_and_parse.c
+++ b/src/modules/HTTPLoop/accept_and_parse.c
@@ -632,25 +632,25 @@ static void f_cache_status(INT32 args)
 {
   struct cache *c = LTHIS->cache;
   pop_n_elems(args);
-  push_constant_text("hits"); 
+  push_text("hits"); 
   push_int64(c->hits);
-  push_constant_text("misses"); 
+  push_text("misses"); 
   push_int64(c->misses);
-  push_constant_text("stale"); 
+  push_text("stale"); 
   push_int64(c->stale);
-  push_constant_text("size"); 
+  push_text("size"); 
   push_int64(c->size);
-  push_constant_text("entries"); 
+  push_text("entries"); 
   push_int64(c->entries);
-  push_constant_text("max_size"); 
+  push_text("max_size"); 
   push_int64(c->max_size);
 
   /* Relative from last call */
-  push_constant_text("sent_bytes"); 
+  push_text("sent_bytes"); 
   push_int(c->sent_data);        c->sent_data=0;
-  push_constant_text("num_request"); 
+  push_text("num_request"); 
   push_int(c->num_requests);    c->num_requests=0;
-  push_constant_text("received_bytes"); 
+  push_text("received_bytes"); 
   push_int(c->received_data);c->received_data=0;
   f_aggregate_mapping( 18 );
 }
diff --git a/src/modules/HTTPLoop/requestobject.c b/src/modules/HTTPLoop/requestobject.c
index de7b92403c213908686ed618c6c0b990fe19783a..eb3dd81bfe20e6418414b14780a05261ba4d4f68 100644
--- a/src/modules/HTTPLoop/requestobject.c
+++ b/src/modules/HTTPLoop/requestobject.c
@@ -569,13 +569,13 @@ void f_aap_index_op(INT32 args)
   {
     struct svalue *tmp;
     pop_stack();
-    push_constant_text("roxen");
+    push_text("roxen");
     if((tmp = low_mapping_lookup(get_builtin_constants(), sp-1)) 
        && TYPEOF(*tmp) == T_OBJECT)
     {
       pop_stack( );
       ref_push_object( tmp->u.object );
-      push_constant_text( "find_supports" );
+      push_text( "find_supports" );
       f_index( 2 );
       ref_push_string(s_client);
       f_aap_index_op( 1 );
diff --git a/src/modules/Image/colors.c b/src/modules/Image/colors.c
index 06866058d9f6002e3c37d39c5bf526dd64654a13..7462ef3e3ac6d88cf677e7b1a982166400fc7371 100644
--- a/src/modules/Image/colors.c
+++ b/src/modules/Image/colors.c
@@ -665,7 +665,7 @@ static void image_color_hex(INT32 args)
    pop_n_elems(args);
    if (i<1)
    {
-      push_constant_text("#");  /* stupid */
+      push_text("#");  /* stupid */
       return;
    }
    else if (i!=sizeof(COLORTYPE)*2)
@@ -810,13 +810,13 @@ static void image_color__sprintf(INT32 args)
 /*       case 'c': */
 /*       case 'd': */
       case 't':
-	 push_constant_text("Image.Color.Color");
+	 push_text("Image.Color.Color");
 	 return;
       case 'O':
 	 if (!THIS->name) try_find_name(THIS);
 	 if (THIS->name==no_name)
 	 {
-	    push_constant_text("Image.Color(\"");
+	    push_text("Image.Color(\"");
 	    if (prec)
 	    {
 	       push_int(prec);
@@ -824,13 +824,13 @@ static void image_color__sprintf(INT32 args)
 	    }
 	    else
 	       image_color_hex(0);
-	    push_constant_text("\")");
+	    push_text("\")");
 	    f_add(3);
 	    return;
 	 }
 	 else
 	 {
-	    push_constant_text("Image.Color.");
+	    push_text("Image.Color.");
 	    ref_push_string(THIS->name);
 	    f_add(2);
 	    return;
@@ -1423,7 +1423,7 @@ static void image_guess_color(INT32 args)
 		"Bad arguments to Image.Color->guess()\n");
    
    f_lower_case(1);
-   push_constant_text(" ");
+   push_text(" ");
    o_subtract();
 
    stack_dup();
@@ -1435,7 +1435,7 @@ static void image_guess_color(INT32 args)
       return;
    }
    pop_stack();
-   push_constant_text("#");
+   push_text("#");
    stack_swap();
    f_add(2);
 
@@ -1693,7 +1693,7 @@ static void image_make_html_color(INT32 args)
       image_get_color(1);
    else
    {
-      push_constant_text("#");
+      push_text("#");
       stack_swap();
       f_add(2);
       image_get_color(1);
diff --git a/src/modules/Image/colortable.c b/src/modules/Image/colortable.c
index f5031020db53faa30cc4962ca126229afb638d41..7a63f9355d5df0c8b6daf10818faa0575a234fc2 100644
--- a/src/modules/Image/colortable.c
+++ b/src/modules/Image/colortable.c
@@ -4457,24 +4457,24 @@ static void image_colortable__sprintf( INT32 args )
   switch( x )
   {
    case 't':
-     push_constant_text("Image.Colortable");
+     push_text("Image.Colortable");
      return;
    case 'O':
-     push_constant_text( "Image.Colortable( %d, m=%s, d=%s )" );
+     push_text( "Image.Colortable( %d, m=%s, d=%s )" );
      push_int64( image_colortable_size( THIS ) );
      switch( THIS->type )
      {
-      case NCT_NONE: push_constant_text( "none" );   break;
-      case NCT_FLAT: push_constant_text( "flat" );   break;
-      case NCT_CUBE: push_constant_text( "cube" );   break;
+      case NCT_NONE: push_text( "none" );   break;
+      case NCT_FLAT: push_text( "flat" );   break;
+      case NCT_CUBE: push_text( "cube" );   break;
      }
      switch( THIS->dither_type )
      {
-      case NCTD_NONE: push_constant_text( "none" );   break;
-      case NCTD_FLOYD_STEINBERG:push_constant_text( "floyd-steinberg" );break;
-      case NCTD_RANDOMCUBE: push_constant_text( "randomcube" );   break;
-      case NCTD_RANDOMGREY: push_constant_text( "randomgrey" );   break;
-      case NCTD_ORDERED: push_constant_text( "ordered" );   break;
+      case NCTD_NONE: push_text( "none" );   break;
+      case NCTD_FLOYD_STEINBERG:push_text( "floyd-steinberg" );break;
+      case NCTD_RANDOMCUBE: push_text( "randomcube" );   break;
+      case NCTD_RANDOMGREY: push_text( "randomgrey" );   break;
+      case NCTD_ORDERED: push_text( "ordered" );   break;
      }
      f_sprintf( 4 );
      return;
diff --git a/src/modules/Image/encodings/avs.c b/src/modules/Image/encodings/avs.c
index 788db13854a31b961d7d5cded42c43ac391bdfc4..20ff3d3785dea77f8629bdd095006d2d1660423f 100644
--- a/src/modules/Image/encodings/avs.c
+++ b/src/modules/Image/encodings/avs.c
@@ -89,9 +89,9 @@ void image_avs_f__decode(INT32 args)
     ((struct image *)ao->storage)->img[c] = apix;
   }
   pop_n_elems(args);
-  push_constant_text("image");
+  push_text("image");
   push_object( io );
-  push_constant_text("alpha");
+  push_text("alpha");
   push_object( ao );
   f_aggregate_mapping( 4 );
 }
@@ -99,7 +99,7 @@ void image_avs_f__decode(INT32 args)
 void image_avs_f_decode(INT32 args)
 {
   image_avs_f__decode(args);
-  push_constant_text("image");
+  push_text("image");
   f_index(2);
 }
 
diff --git a/src/modules/Image/encodings/dsi.c b/src/modules/Image/encodings/dsi.c
index 81eb765d427a812fa90fccd2664ae8ebba2372f4..5877b5fbd103320a8bbdb363c3f00a4e3f1af25d 100644
--- a/src/modules/Image/encodings/dsi.c
+++ b/src/modules/Image/encodings/dsi.c
@@ -84,9 +84,9 @@ static void f__decode( INT32 args )
       }
     }
 
-  push_constant_text( "image" );
+  push_text( "image" );
   push_object( i );
-  push_constant_text( "alpha" );
+  push_text( "alpha" );
   push_object( a );
   f_aggregate_mapping( 4 );
 }
@@ -94,7 +94,7 @@ static void f__decode( INT32 args )
 static void f_decode( INT32 args )
 {
   f__decode( args );
-  push_constant_text( "image" );
+  push_text( "image" );
   f_index( 2 );
 }
 
diff --git a/src/modules/Image/encodings/hrz.c b/src/modules/Image/encodings/hrz.c
index 0d26f477725fbce24ecb58fe82fd70a444a0e6e0..6fbf21bfd12339e3a16ca44d5f37c435dbcfef03 100644
--- a/src/modules/Image/encodings/hrz.c
+++ b/src/modules/Image/encodings/hrz.c
@@ -69,7 +69,7 @@ void image_hrz_f_decode(INT32 args)
 void image_hrz_f__decode(INT32 args)
 {
   image_hrz_f_decode(args);
-  push_constant_text("image");
+  push_text("image");
   stack_swap();
   f_aggregate_mapping(2);
 }
diff --git a/src/modules/Image/encodings/neo.c b/src/modules/Image/encodings/neo.c
index d75e924d65fae33a23fd974e5fbeaa2e1edcc093..3c19201867c2e047f7c0253402557c157a40d622 100644
--- a/src/modules/Image/encodings/neo.c
+++ b/src/modules/Image/encodings/neo.c
@@ -87,7 +87,7 @@ void image_neo_f__decode(INT32 args)
     pal = decode_atari_palette(q+4, 2);
   SET_ONERROR(err, free_atari_palette, pal);
 
-  push_constant_text("palette");
+  push_text("palette");
   for( i=0; i<pal->size; i++ ) {
     push_int(pal->colors[i].r);
     push_int(pal->colors[i].g);
@@ -99,7 +99,7 @@ void image_neo_f__decode(INT32 args)
 
   img = decode_atari_screendump(q+128, res, pal);
 
-  push_constant_text("image");
+  push_text("image");
   push_object(img);
   size += 2;
 
@@ -108,19 +108,19 @@ void image_neo_f__decode(INT32 args)
     rl = q[49]&0xf;
     ll = (q[49]&0xf0)>>4;
 
-    push_constant_text("right_limit");
+    push_text("right_limit");
     push_int( rl );
-    push_constant_text("left_limit");
+    push_text("left_limit");
     push_int( ll );
-    push_constant_text("speed");
+    push_text("speed");
     push_int( q[51] );
-    push_constant_text("direction");
+    push_text("direction");
     if( q[50]&128 )
-      push_constant_text("right");
+      push_text("right");
     else
-      push_constant_text("left");
+      push_text("left");
 
-    push_constant_text("images");
+    push_text("images");
     for(i=0; i<rl-ll+1; i++) {
       if( q[50]&128 )
 	rotate_atari_palette(pal, ll, rl);
@@ -139,7 +139,7 @@ void image_neo_f__decode(INT32 args)
 
   fn = make_shared_binary_string((const char *)q+36, 12);
 
-  push_constant_text("filename");
+  push_text("filename");
   push_string(fn);
   size += 2;
 
@@ -153,7 +153,7 @@ void image_neo_f__decode(INT32 args)
 void image_neo_f_decode(INT32 args)
 {
   image_neo_f__decode(args);
-  push_constant_text("image");
+  push_text("image");
   f_index(2);
 }
 
diff --git a/src/modules/Image/encodings/png.c b/src/modules/Image/encodings/png.c
index a291e56ffbfa92e16d15ab794b97f34e249a9cbc..52d6d0cc7f42edb1ad03cb588257ab2cbf8c96be 100644
--- a/src/modules/Image/encodings/png.c
+++ b/src/modules/Image/encodings/png.c
@@ -1330,7 +1330,7 @@ static void img_png_decode(INT32 args, int mode)
 	    for(i=0; i<len; i++)
 	      push_int(data[i]);
 	    f_aggregate(len);
-	    push_constant_text("sbit");
+	    push_text("sbit");
 	    mapping_insert(m,sp-1,sp-2);
 	    pop_n_elems(2);
 	  }
@@ -1339,7 +1339,7 @@ static void img_png_decode(INT32 args, int mode)
           case 0x67414d41: /* gAMA */
             if(mode==MODE_IMAGE_ONLY) break;
 	    if(len!=4) break;
-	    push_constant_text("gamma");
+	    push_text("gamma");
 	    push_float((float)int_from_32bit(data)/100000.0);
 	    mapping_insert(m,sp-2,sp-1);
 	    pop_n_elems(2);
@@ -1360,7 +1360,7 @@ static void img_png_decode(INT32 args, int mode)
 	    push_int(tmp1);
 	    push_int(tmp2);
 	    f_aggregate(3);
-	    push_constant_text("physical");
+	    push_text("physical");
 	    mapping_insert(m,sp-1,sp-2);
 	    pop_n_elems(2);
 	    break;
@@ -1379,7 +1379,7 @@ static void img_png_decode(INT32 args, int mode)
 	    push_int(tmp1);
 	    push_int(tmp2);
 	    f_aggregate(3);
-	    push_constant_text("offset");
+	    push_text("offset");
 	    mapping_insert(m,sp-1,sp-2);
 	    pop_n_elems(2);
 	    break;
@@ -1394,7 +1394,7 @@ static void img_png_decode(INT32 args, int mode)
 	    push_int(data[5]);
 	    push_int(data[6]);
 	    f_aggregate(6);
-	    push_constant_text("time");
+	    push_text("time");
 	    mapping_insert(m,sp-1,sp-2);
 	    pop_n_elems(2);
 	    break;
@@ -1509,12 +1509,12 @@ static void img_png_decode(INT32 args, int mode)
      mapping_string_insert(m, param_bpp, sp-1);
      pop_stack();
 
-     push_constant_text("xsize");
+     push_text("xsize");
      push_int(ihdr.width);
      mapping_insert(m,sp-2,sp-1);
      pop_n_elems(2);
 
-     push_constant_text("ysize");
+     push_text("ysize");
      push_int(ihdr.height);
      mapping_insert(m,sp-2,sp-1);
      pop_n_elems(2);
@@ -1834,7 +1834,7 @@ static void image_png_decode(INT32 args)
      SIMPLE_TOO_FEW_ARGS_ERROR("Image.PNG.decode", 1);
 
    img_png_decode(args, MODE_IMAGE_ONLY);
-   push_constant_text("image");
+   push_text("image");
    f_index(2);
 }
 
@@ -1855,16 +1855,16 @@ static void image_png_decode_alpha(INT32 args)
 
    image_png__decode(args);
    assign_svalue_no_free(&s,sp-1);
-   push_constant_text("alpha");
+   push_text("alpha");
    f_index(2);
 
    if (TYPEOF(sp[-1]) == T_INT)
    {
       push_svalue(&s);
-      push_constant_text("xsize");
+      push_text("xsize");
       f_index(2);
       push_svalue(&s);
-      push_constant_text("ysize");
+      push_text("ysize");
       f_index(2);
       push_int(255);
       push_int(255);
diff --git a/src/modules/Image/encodings/psd.c b/src/modules/Image/encodings/psd.c
index edcd41c3ecfe8a237df6fdb47c1851acdcea1c15..1822c2075f44e9f703d19e9d70d7fe856ad84ed1 100644
--- a/src/modules/Image/encodings/psd.c
+++ b/src/modules/Image/encodings/psd.c
@@ -613,17 +613,17 @@ static void decode_resources( struct buffer *b )
       case 0x03f0: /* caption */
 	{
 	  struct buffer b = psd_read_pstring( &data );
-	  push_constant_text( "caption" );
+	  push_text( "caption" );
 	  push_buffer( &b );
 	}
 	break;
 
       case 0x0400: /* layer state info */
-	push_constant_text( "active_layer" );
+	push_text( "active_layer" );
 	push_int( psd_read_short( &data ) );
 	break;
       case 0x0408: /* guides */
-	push_constant_text( "guides" );
+	push_text( "guides" );
 	{
 	  int i,num_guides;
 	  short magic1, magic2, magic3, magic4, magic5, magic6; /*from gimp.*/
@@ -645,8 +645,8 @@ static void decode_resources( struct buffer *b )
 	      p = (ptrdiff_t)((((double)p) * (magic4>>8)) / ((double)(magic4&255)));
 	    else
 	      p = (ptrdiff_t)((((double)p) * (magic6>>8)) / ((double)(magic6&255)));
-	    push_constant_text( "pos" );      push_int64( p );
-	    push_constant_text( "vertical" ); push_int( !h );
+	    push_text( "pos" );      push_int64( p );
+	    push_text( "vertical" ); push_int( !h );
 	    f_aggregate_mapping( 4 );
 	  }
 	  f_aggregate( num_guides );
@@ -655,20 +655,20 @@ static void decode_resources( struct buffer *b )
       case 0x040b: /* URL */
 	{
 	  struct buffer b = psd_read_pstring( &data );
-	  push_constant_text( "url" );
+	  push_text( "url" );
 	  push_buffer( &b );
 	}
 	break;
       case 0x03ed: /* res. info. */
-	push_constant_text( "resinfo" );
+	push_text( "resinfo" );
 
-	push_constant_text( "hres" );       push_int(psd_read_int( &data ) );
-	push_constant_text( "hres_unit" );  push_int(psd_read_short( &data ) );
-	push_constant_text( "width_unit" ); push_int(psd_read_short( &data ) );
+	push_text( "hres" );       push_int(psd_read_int( &data ) );
+	push_text( "hres_unit" );  push_int(psd_read_short( &data ) );
+	push_text( "width_unit" ); push_int(psd_read_short( &data ) );
 
-	push_constant_text( "vres" );       push_int(psd_read_int( &data ) );
-	push_constant_text( "vres_unit" );  push_int(psd_read_short( &data ) );
-	push_constant_text( "height_unit" );push_int(psd_read_short( &data ) );
+	push_text( "vres" );       push_int(psd_read_int( &data ) );
+	push_text( "vres_unit" );  push_int(psd_read_short( &data ) );
+	push_text( "height_unit" );push_int(psd_read_short( &data ) );
 
 	f_aggregate_mapping( 12 );
 	break;
diff --git a/src/modules/Image/encodings/ras.c b/src/modules/Image/encodings/ras.c
index 8407af0338c402ff2f6aa68f06706238c673bef3..c4cd35f061668718b991275877c97be2ec88ff9f 100644
--- a/src/modules/Image/encodings/ras.c
+++ b/src/modules/Image/encodings/ras.c
@@ -118,10 +118,10 @@ void img_ras__decode(INT32 args)
   if(TYPEOF(Pike_sp[-1]) != T_STRING)
     SIMPLE_BAD_ARG_ERROR("Image.RAS._decode", 1, "string");
   img_ras_decode(args);
-  push_constant_text("image");
+  push_text("image");
   stack_swap();
-  push_constant_text("format");
-  push_constant_text("image/x-sun-raster");
+  push_text("format");
+  push_text("image/x-sun-raster");
   f_aggregate_mapping(4);
 }
 
diff --git a/src/modules/Image/encodings/tga.c b/src/modules/Image/encodings/tga.c
index b8eb855a3b158faf514d996a77de3674413e9d5e..0d71b3859c34145dc8713f21c7529b1acb606a62 100644
--- a/src/modules/Image/encodings/tga.c
+++ b/src/modules/Image/encodings/tga.c
@@ -831,17 +831,17 @@ void image_tga__decode( INT32 args )
 
   pop_n_elems(args);
 
-  push_constant_text( "alpha" );
+  push_text( "alpha" );
   push_object( i.ao );
-  push_constant_text( "image" );
+  push_text( "image" );
   push_object( i.io );
 
-  push_constant_text( "type" );
-  push_constant_text( "image/x-targa" );
+  push_text( "type" );
+  push_text( "image/x-targa" );
 
-  push_constant_text( "xsize" );
+  push_text( "xsize" );
   push_int( i.img->xsize );
-  push_constant_text( "ysize" );
+  push_text( "ysize" );
   push_int( i.img->ysize );
 
   f_aggregate_mapping( 10 );
diff --git a/src/modules/Image/encodings/wbf.c b/src/modules/Image/encodings/wbf.c
index 05e389ff0268811bdff7e3fa2cb39782f88358d3..53ba8b6c0027948b2f5a7e1b8b102c140b9ce4bb 100644
--- a/src/modules/Image/encodings/wbf.c
+++ b/src/modules/Image/encodings/wbf.c
@@ -100,9 +100,9 @@ static int wbf_read_int( struct buffer *from )
 
 static void push_ext_header( struct ext_header *eh )
 {
-  push_constant_text( "identifier" );
+  push_text( "identifier" );
   push_string( make_shared_binary_string( eh->name, eh->name_len ) );
-  push_constant_text( "value" );
+  push_text( "value" );
   push_string( make_shared_binary_string( eh->value, eh->value_len ) );
   f_aggregate_mapping( 4 );
 }
@@ -234,33 +234,33 @@ static void low_image_f_wbf_decode( int args, int mode )
         return;
 
       case 1: /* Image and header */
-        push_constant_text( "image" );
+        push_text( "image" );
         low_image_f_wbf_decode_type0( &wh, &buff );
         map_num_elems++;
         
       case 0: /* Header only */
-        push_constant_text( "format" );
-        push_constant_text( "image/x-wap.wbmp; type=0" );
+        push_text( "format" );
+        push_text( "image/x-wap.wbmp; type=0" );
         map_num_elems++;
         
-        push_constant_text( "xsize" );
+        push_text( "xsize" );
         push_int( wh.width );
         map_num_elems++;
 
-        push_constant_text( "ysize" );
+        push_text( "ysize" );
         push_int( wh.height );
         map_num_elems++;
 
         if( wh.fix_header_field )
         {
-          push_constant_text( "fix_header_field" );
+          push_text( "fix_header_field" );
           push_int( wh.fix_header_field );
           map_num_elems++;
         }
 
         if( wh.ext_header_field )
         {
-          push_constant_text( "ext_header_field" );
+          push_text( "ext_header_field" );
           push_int( wh.ext_header_field );
           map_num_elems++;
         }
diff --git a/src/modules/Image/encodings/xbm.c b/src/modules/Image/encodings/xbm.c
index 8a8927b595d1fe50d6341384d1ff2f3536c27734..291d0926dce7f71fe02110a9465d290608f559dd 100644
--- a/src/modules/Image/encodings/xbm.c
+++ b/src/modules/Image/encodings/xbm.c
@@ -341,9 +341,9 @@ static void image_xbm__decode( INT32 args )
   }
   
   pop_n_elems(args);
-  push_constant_text( "alpha" );
+  push_text( "alpha" );
   push_object( a );
-    push_constant_text( "image" );
+    push_text( "image" );
   if(i)
     push_object( i );
   else
diff --git a/src/modules/Image/encodings/xcf.c b/src/modules/Image/encodings/xcf.c
index 22d31572c12cb3958fe7a84c2866b8d782659cd9..606815cdb0bc0f5de5b1a0b363ef877004de96c5 100644
--- a/src/modules/Image/encodings/xcf.c
+++ b/src/modules/Image/encodings/xcf.c
@@ -103,10 +103,10 @@ static void f_substring__sprintf( INT32 args )
   switch( x )
   {
    case 't':
-     push_constant_text("SubString");
+     push_text("SubString");
      return;
    case 'O':
-     push_constant_text("SubString( %O /* [+%d .. %d] */ )" );
+     push_text("SubString( %O /* [+%d .. %d] */ )" );
      push_text("string"); f_substring_cast( 1 );
 
      push_int64( s->len );
diff --git a/src/modules/Image/image.c b/src/modules/Image/image.c
index a44f70f7e6acbcabf15c93674fad862a19a3331c..fe70c7a5798cad576288fc022bdb762ca8cd12f2 100644
--- a/src/modules/Image/image.c
+++ b/src/modules/Image/image.c
@@ -4563,10 +4563,10 @@ static void image__sprintf( INT32 args )
   switch( x )
   {
    case 't':
-     push_constant_text("Image.Image");
+     push_text("Image.Image");
      return;
    case 'O':
-     push_constant_text( "Image.Image( %d x %d /* %.1fKb */)" );
+     push_text( "Image.Image( %d x %d /* %.1fKb */)" );
      push_int( THIS->xsize );
      push_int( THIS->ysize );
      push_float( DO_NOT_WARN((FLOAT_TYPE)((THIS->xsize * THIS->ysize) /
diff --git a/src/modules/Image/layers.c b/src/modules/Image/layers.c
index c466a8f0808140c945e8ad1d3b72de2a90e57936..d7f10d2013a88251e4e26f911fd92238ee0be344 100644
--- a/src/modules/Image/layers.c
+++ b/src/modules/Image/layers.c
@@ -1445,17 +1445,17 @@ static void image_layer_cast(INT32 args)
 	 int n=0;
 	 pop_n_elems(args);
 
-	 push_constant_text("xsize");       push_int(THIS->xsize);         n++;
-	 push_constant_text("ysize");       push_int(THIS->ysize);         n++;
-	 push_constant_text("image");       image_layer_image(0);          n++;
-	 push_constant_text("alpha");       image_layer_alpha(0);          n++;
-	 push_constant_text("xoffset");     push_int(THIS->xoffs);         n++;
-	 push_constant_text("yoffset");     push_int(THIS->yoffs);         n++;
-	 push_constant_text("alpha_value"); push_float(THIS->alpha_value); n++;
-	 push_constant_text("fill");        image_layer_fill(0);           n++;
-	 push_constant_text("fill_alpha");  image_layer_fill_alpha(0);     n++;
-	 push_constant_text("tiled");       push_int(THIS->tiled);         n++;
-	 push_constant_text("mode");        image_layer_mode(0);           n++;
+	 push_text("xsize");       push_int(THIS->xsize);         n++;
+	 push_text("ysize");       push_int(THIS->ysize);         n++;
+	 push_text("image");       image_layer_image(0);          n++;
+	 push_text("alpha");       image_layer_alpha(0);          n++;
+	 push_text("xoffset");     push_int(THIS->xoffs);         n++;
+	 push_text("yoffset");     push_int(THIS->yoffs);         n++;
+	 push_text("alpha_value"); push_float(THIS->alpha_value); n++;
+	 push_text("fill");        image_layer_fill(0);           n++;
+	 push_text("fill_alpha");  image_layer_fill_alpha(0);     n++;
+	 push_text("tiled");       push_int(THIS->tiled);         n++;
+	 push_text("mode");        image_layer_mode(0);           n++;
 
 	 f_aggregate_mapping(n*2);
 
@@ -3271,10 +3271,10 @@ static void image_layer__sprintf( INT32 args )
   switch( x )
   {
    case 't':
-     push_constant_text("Image.Layer");
+     push_text("Image.Layer");
      return;
    case 'O':
-     push_constant_text( "Image.Layer(%O i=%O a=%O)" );
+     push_text( "Image.Layer(%O i=%O a=%O)" );
      image_layer_mode(0);
      if( THIS->image ) ref_push_object( THIS->image ); else push_int( 0 );
      if( THIS->alpha ) ref_push_object( THIS->alpha ); else push_int( 0 );
diff --git a/src/modules/MIME/mime.c b/src/modules/MIME/mime.c
index db746e2f675d1f33313c2d62328b00e564bdabfb..56c51b23b627a6a91d16b57ecd5191d99ee96939 100644
--- a/src/modules/MIME/mime.c
+++ b/src/modules/MIME/mime.c
@@ -752,7 +752,7 @@ static void low_tokenize( const char *funname, INT32 args, int mode )
       if (l>0) {
 	/* Yup.  It's an encoded word, so it must be an atom.  */
 	if(mode)
-	  push_constant_text("encoded-word");
+	  push_text("encoded-word");
 	push_string( make_shared_binary_string( (char *)src, l ) );
 	if(mode)
 	  f_aggregate(2);
@@ -766,7 +766,7 @@ static void low_tokenize( const char *funname, INT32 args, int mode )
     case CT_RPAR:
       /* Individual special character, push as a char (= int) */
       if(mode)
-	push_constant_text("special");
+	push_text("special");
       push_int( *src++ );
       if(mode)
 	f_aggregate(2);
@@ -781,7 +781,7 @@ static void low_tokenize( const char *funname, INT32 args, int mode )
 	  break;
 
       if(mode)
-	push_constant_text("word");
+	push_text("word");
       push_string( make_shared_binary_string( (char *)src, l ) );
       if(mode)
 	f_aggregate(2);
@@ -804,7 +804,7 @@ static void low_tokenize( const char *funname, INT32 args, int mode )
 
       /* Push the resulting string */
       if(mode)
-	push_constant_text("word");
+	push_text("word");
 
       if (e) {
 	/* l is the distance to the ending ", and e is the number of	\
@@ -842,7 +842,7 @@ static void low_tokenize( const char *funname, INT32 args, int mode )
       if (l >= cnt) {
 	/* No ]; seems that this was no domain literal after all... */
 	if(mode)
-	  push_constant_text("special");
+	  push_text("special");
 	push_int( *src++ );
 	if(mode)
 	  f_aggregate(2);
@@ -861,7 +861,7 @@ static void low_tokenize( const char *funname, INT32 args, int mode )
 
       /* Push the resulting string */
       if(mode)
-	push_constant_text("domain-literal");
+	push_text("domain-literal");
       push_string( end_shared_string( str ) );
       if(mode)
 	f_aggregate(2);
@@ -889,7 +889,7 @@ static void low_tokenize( const char *funname, INT32 args, int mode )
 	  }
 
       if(mode) {
-	push_constant_text("comment");
+	push_text("comment");
 
 	str = begin_shared_string( l-e-1 );
 
diff --git a/src/modules/Math/matrix_code.h b/src/modules/Math/matrix_code.h
index 2ffa188fec8f988d30a326a909e0d9e9516fd0d2..1815d4947bf30189ec20521b61fa3bdaa88b3ff7 100644
--- a/src/modules/Math/matrix_code.h
+++ b/src/modules/Math/matrix_code.h
@@ -355,7 +355,7 @@ void matrixX(__sprintf)(INT32 args)
 	    return;
 	 }
 
-	 push_constant_text("Math." PNAME "( ({ ({ ");
+	 push_text("Math." PNAME "( ({ ({ ");
 	 n=1;
 	 for (y=0; y<THIS->ysize; y++)
 	 {
@@ -366,10 +366,10 @@ void matrixX(__sprintf)(INT32 args)
 	       push_text(buf); n++;
 	    }
 	    if (y<THIS->ysize-1)
-	       push_constant_text("}),\n                ({ "); 
+	       push_text("}),\n                ({ "); 
 	    n++;
 	 }
-	 push_constant_text("}) }) )"); 
+	 push_text("}) }) )"); 
 	 f_add(n);
 	 stack_pop_n_elems_keep_top(args);
 	 return;
diff --git a/src/modules/Mysql/mysql.c b/src/modules/Mysql/mysql.c
index 318212d16aad1a865bbf226707cc8e439997068b..6344eb2ab2fd275c11d55b7252ea096cd447f1f5 100644
--- a/src/modules/Mysql/mysql.c
+++ b/src/modules/Mysql/mysql.c
@@ -407,9 +407,9 @@ static void connection_set_charset (struct pike_string *charset)
    * charset. We emulate it by setting the charset ourselves. Note
    * that this doesn't work with mysql_real_escape_string, but that
    * function isn't used. */
-  push_constant_text ("SET NAMES '");
+  push_text ("SET NAMES '");
   ref_push_string (charset);	/* FIXME: Quote? */
-  push_constant_text ("'");
+  push_text ("'");
   f_add (3);
   low_query (1, "set_charset", PIKE_MYSQL_FLAG_STORE_RESULT);
   pop_stack();
@@ -793,7 +793,7 @@ static void mysql__sprintf(INT32 args)
 	f_sprintf(3);
       }
       else
-	push_constant_text ("mysql()");
+	push_text ("mysql()");
 
       return;
     }
@@ -1862,7 +1862,7 @@ static void f_get_charset (INT32 args)
   if (PIKE_MYSQL->conn_charset)
     ref_push_string (PIKE_MYSQL->conn_charset);
   else
-    push_constant_text ("latin1");
+    push_text ("latin1");
 }
 
 static void f__can_send_as_latin1 (INT32 args)
diff --git a/src/modules/Odbc/odbc.c b/src/modules/Odbc/odbc.c
index 1e0de077b257ccfbc0d8ca2cb180646181c86ecb..5e7d14206d89a612ce680bffe99b6f6267091222 100644
--- a/src/modules/Odbc/odbc.c
+++ b/src/modules/Odbc/odbc.c
@@ -68,11 +68,9 @@ int odbc_driver_is_old_freetds(HDBC odbc_conn)
     int is_tds = 0;
     push_text(buf);
     f_lower_case(1);
-    push_constant_text("libtdsodbc");
-    f_has_value(2);
-    is_tds = !SAFE_IS_ZERO(&Pike_sp[-1]);
+    is_tds = strstr(Pike_sp[-1].u.string->str, "libtdsodbc") ? 1 : 0;
     pop_stack();
-    
+
     if(is_tds) {
       if(SQLGetInfo(odbc_conn, SQL_DRIVER_VER, buf, sizeof(buf), &len) == SQL_SUCCESS) {
 	double version = atof(buf);
@@ -344,7 +342,7 @@ static void f_create(INT32 args)
 
   if (!database || !database->len) {
     if (!server || !server->len) {
-      push_constant_text("default");
+      push_text("default");
       database = sp[-1].u.string;
       args++;
     } else {
diff --git a/src/modules/Odbc/odbc_result.c b/src/modules/Odbc/odbc_result.c
index 575b164f2202912bd419a880b3b34dc94b59e527..04bb60258c45cfc0d8d29325da24ae463fd8aa34 100644
--- a/src/modules/Odbc/odbc_result.c
+++ b/src/modules/Odbc/odbc_result.c
@@ -491,7 +491,7 @@ static void f_list_tables(INT32 args)
   SQLLEN num_rows;
 
   if (!args) {
-    push_constant_text("%");
+    push_text("%");
     args = 1;
   } else if ((TYPEOF(Pike_sp[-args]) != T_STRING) ||
 	     (Pike_sp[-args].u.string->size_shift)) {
diff --git a/src/modules/Oracle/oracle.c b/src/modules/Oracle/oracle.c
index 6038403d530cb35c74a3e2df63d071d307a1699d..8b97192fbc755ddc45aff24372d007735ec750d7 100644
--- a/src/modules/Oracle/oracle.c
+++ b/src/modules/Oracle/oracle.c
@@ -1489,7 +1489,7 @@ static void push_inout_value(struct inout *inout,
 
       if(ret == OCI_SUCCESS) {
 	if(loblen == 0)
-	  push_constant_text("");
+          push_empty_string();
 	else
 	  push_string(make_shared_binary_string(bufp, loblen));
       }
diff --git a/src/modules/Parser/parser.c b/src/modules/Parser/parser.c
index 0328c0ac1cb61047c994d531078000ef5fbab4fe..f9a2204d98def58cca30b15a946969bc97df4911 100644
--- a/src/modules/Parser/parser.c
+++ b/src/modules/Parser/parser.c
@@ -161,7 +161,7 @@ static void parser_magic_index(INT32 args)
    {
       pop_stack();
       stack_dup();
-      push_constant_text("_Parser_");
+      push_text("_Parser_");
       stack_swap();
       f_add(2);
       SAFE_APPLY_MASTER("resolv",1);
@@ -170,7 +170,7 @@ static void parser_magic_index(INT32 args)
    {
       pop_stack();
       stack_dup();
-      push_constant_text("_Parser");
+      push_text("_Parser");
       SAFE_APPLY_MASTER("resolv",1);
       stack_swap();
       if(TYPEOF(sp[-2]) == T_INT)
diff --git a/src/modules/Parser/xml.cmod b/src/modules/Parser/xml.cmod
index 13471c4c2b45597a94e61919374b00153c5a9385..28b0464655860f4160e3613698630ec4b2f00bc1 100644
--- a/src/modules/Parser/xml.cmod
+++ b/src/modules/Parser/xml.cmod
@@ -972,11 +972,11 @@ PIKECLASS Simple
 
   INIT
   {
-    push_constant_text("lt");    push_constant_text("&#60;");
-    push_constant_text("gt");    push_constant_text(">");
-    push_constant_text("amp");   push_constant_text("&#38;");
-    push_constant_text("apos");  push_constant_text("'");
-    push_constant_text("quot");  push_constant_text("\"");
+    push_text("lt");    push_text("&#60;");
+    push_text("gt");    push_text(">");
+    push_text("amp");   push_text("&#38;");
+    push_text("apos");  push_text("'");
+    push_text("quot");  push_text("\"");
   
     f_aggregate_mapping(10);
     THIS->entities=sp[-1].u.mapping;
@@ -1231,21 +1231,21 @@ static int gobble(char *s)
 
 #define STRIP_SPACES() do {			\
     IF_XMLDEBUG(fprintf(stderr,"STRIPPING SPACES (%s)\n",sp[-1].u.string->str));       \
-    push_constant_text("\n");			\
-    push_constant_text("\r");			\
-    push_constant_text("\t");			\
+    push_text("\n");			\
+    push_text("\r");			\
+    push_text("\t");			\
     f_aggregate(3);				\
-    push_constant_text(" ");			\
-    push_constant_text(" ");			\
-    push_constant_text(" ");			\
+    push_text(" ");			\
+    push_text(" ");			\
+    push_text(" ");			\
     f_aggregate(3);				\
     f_replace(3);				\
-    push_constant_text(" ");			\
+    push_text(" ");			\
     o_divide();					\
     push_empty_string();			\
     f_aggregate(1);                             \
     o_subtract();				\
-    push_constant_text(" ");			\
+    push_text(" ");			\
     o_multiply();				\
     IF_XMLDEBUG(fprintf(stderr,"SPACES STRIPPED (%s)\n",sp[-1].u.string->str));       \
   } while(0)
@@ -1545,7 +1545,7 @@ static void sys(void)
 
 static void xmlerror(char *desc, struct pike_string *tag_name)
 {
-  push_constant_text("error");
+  push_text("error");
   if (tag_name) {
     ref_push_string(tag_name);	/* Name of tag that triggered the error. */
   } else {
@@ -1567,7 +1567,7 @@ static void xmlerror(char *desc, struct pike_string *tag_name)
       READ(1); /* this is '%' */
       IF_XMLDEBUG( fprintf(stderr, "SMEG reference found.\n") );
 
-      push_constant_text("%");
+      push_text("%");
       SIMPLE_READNAME();
 
       add_ref(name=sp[-1].u.string);
diff --git a/src/modules/_Image_FreeType/freetype.c b/src/modules/_Image_FreeType/freetype.c
index fbc6c4dcdd92ad7bfa63450b29f19cbfeda60d1e..8ed0e6600b88ebdd0e4a99f0c16331983d631f7e 100644
--- a/src/modules/_Image_FreeType/freetype.c
+++ b/src/modules/_Image_FreeType/freetype.c
@@ -241,7 +241,7 @@ static void image_ft_face_list_encodings( INT32 args )
     if(e == ft_encoding_none)
       push_int( 0 );
     else {
-      push_constant_text( "%4c" );
+      push_text( "%4c" );
       push_int( e );
       f_sprintf( 2 );
     }
diff --git a/src/modules/_Image_GIF/image_gif.c b/src/modules/_Image_GIF/image_gif.c
index 737c88db6535fbf73d3aa796bdb5d8194eec4a5b..f38a544c67762f252b95845ecc340cae932bbeb7 100644
--- a/src/modules/_Image_GIF/image_gif.c
+++ b/src/modules/_Image_GIF/image_gif.c
@@ -321,7 +321,7 @@ void image_gif_header_block(INT32 args)
 void image_gif_end_block(INT32 args)
 {
    pop_n_elems(args);
-   push_constant_text("\x3b");
+   push_text("\x3b");
 }
 
 /*
@@ -2189,13 +2189,13 @@ void image_gif_decode_layers(INT32 args)
 	     
 	 if (alpha) 
 	 {
-	    push_constant_text("image");
+	    push_text("image");
 	    push_svalue(b->item+3);
-	    push_constant_text("alpha");
+	    push_text("alpha");
 	    push_svalue(b->item+4);
-	    push_constant_text("xoffset");
+	    push_text("xoffset");
 	    push_svalue(b->item+1);
-	    push_constant_text("yoffset");
+	    push_text("yoffset");
 	    push_svalue(b->item+2);
 	    f_aggregate_mapping(8);
 	    push_object(clone_object(image_layer_program,1));
@@ -2203,11 +2203,11 @@ void image_gif_decode_layers(INT32 args)
 	 }
 	 else
 	 {
-	    push_constant_text("image");
+	    push_text("image");
 	    push_svalue(b->item+3);
-	    push_constant_text("xoffset");
+	    push_text("xoffset");
 	    push_svalue(b->item+1);
-	    push_constant_text("yoffset");
+	    push_text("yoffset");
 	    push_svalue(b->item+2);
 	    f_aggregate_mapping(6);
 	    push_object(clone_object(image_layer_program,1));
@@ -2253,10 +2253,10 @@ void image_gif_decode_map(INT32 args)
 {
    image_gif_decode_layer(args);
 
-   push_constant_text("image");
-   push_constant_text("alpha");
-   push_constant_text("xsize");
-   push_constant_text("ysize");
+   push_text("image");
+   push_text("alpha");
+   push_text("xsize");
+   push_text("ysize");
    f_aggregate(4);
 #define stack_swap_behind() do { struct svalue _=sp[-2]; sp[-2]=sp[-3]; sp[-3]=_; } while(0)
    stack_dup();
@@ -2264,8 +2264,8 @@ void image_gif_decode_map(INT32 args)
    f_rows(2);
    f_call_function(1);
    f_mkmapping(2);
-   push_constant_text("type");
-   push_constant_text("image/gif");
+   push_text("type");
+   push_text("image/gif");
    f_aggregate_mapping(2);
    f_add(2);
 }
diff --git a/src/modules/_Image_TIFF/image_tiff.c b/src/modules/_Image_TIFF/image_tiff.c
index 38c66e5065a6b080b9d3779366140648fafd00a1..cc25e0da5c93a52675704a0018bbe7a49cbe1d43 100644
--- a/src/modules/_Image_TIFF/image_tiff.c
+++ b/src/modules/_Image_TIFF/image_tiff.c
@@ -502,34 +502,34 @@ void low_image_tiff_decode( struct buffer *buf,
     TIFFDirectory *td = &tif->tif_dir;
     if (TIFFFieldSet(tif,FIELD_RESOLUTION)) 
     {
-      push_constant_text( "xres" );   push_float( td->td_xresolution );
-      push_constant_text( "yres" );   push_float( td->td_yresolution );
-      push_constant_text( "unit" );  
+      push_text( "xres" );   push_float( td->td_xresolution );
+      push_text( "yres" );   push_float( td->td_yresolution );
+      push_text( "unit" );  
       if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) 
       {
         switch(td->td_resolutionunit)
         {
          case RESUNIT_NONE:
-           push_constant_text("unitless");
+           push_text("unitless");
            break;
          case RESUNIT_INCH:
-           push_constant_text("pixels/inch");
-           push_constant_text( "xdpy" );   push_float( td->td_xresolution );
-           push_constant_text( "ydpy" );   push_float( td->td_yresolution );
+           push_text("pixels/inch");
+           push_text( "xdpy" );   push_float( td->td_xresolution );
+           push_text( "ydpy" );   push_float( td->td_yresolution );
            break;
          case RESUNIT_CENTIMETER:
-           push_constant_text("pixels/cm");
-           push_constant_text( "xdpy" );   push_float( td->td_xresolution/2.5 );
-           push_constant_text( "ydpy" );   push_float( td->td_yresolution/2.5 );
+           push_text("pixels/cm");
+           push_text( "xdpy" );   push_float( td->td_xresolution/2.5 );
+           push_text( "ydpy" );   push_float( td->td_yresolution/2.5 );
            break;
         } 
       } else
-        push_constant_text( "unitless" );  
+        push_text( "unitless" );  
     }
     if (TIFFFieldSet(tif,FIELD_POSITION))
     {
-      push_constant_text("xposition"); push_int(td->td_xposition);
-      push_constant_text("yposition"); push_int(td->td_yposition);
+      push_text("xposition"); push_int(td->td_xposition);
+      push_text("yposition"); push_int(td->td_yposition);
     }
     if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) 
     {
@@ -818,9 +818,9 @@ static void image_tiff__decode( INT32 args )
   buffer.offset = 0;
 
   low_image_tiff_decode( &buffer, &res, 0 );
-  push_constant_text( "image" );
+  push_text( "image" );
   push_object( res.img );
-  push_constant_text( "alpha" );
+  push_text( "alpha" );
   push_object( res.alpha );
   f_aggregate_mapping( sp-osp );
   {
diff --git a/src/modules/_Stdio/#udp.c# b/src/modules/_Stdio/#udp.c#
new file mode 100644
index 0000000000000000000000000000000000000000..2c7c9a18774037a7c3ca4343adb63415f61be814
--- /dev/null
+++ b/src/modules/_Stdio/#udp.c#
@@ -0,0 +1,1543 @@
+/*
+|| This file is part of Pike. For copyright information see COPYRIGHT.
+|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
+|| for more information.
+*/
+
+#define NO_PIKE_SHORTHAND
+#include "global.h"
+
+#include "file_machine.h"
+
+#include "fdlib.h"
+#include "pike_netlib.h"
+#include "interpret.h"
+#include "svalue.h"
+#include "stralloc.h"
+#include "array.h"
+#include "mapping.h"
+#include "object.h"
+#include "backend.h"
+#include "time_stuff.h"
+#include "fd_control.h"
+
+#include "pike_error.h"
+#include "signal_handler.h"
+#include "pike_types.h"
+#include "threads.h"
+#include "bignum.h"
+
+#include "module_support.h"
+#include "builtin_functions.h"
+#include "file.h"
+
+#ifdef HAVE_SYS_TYPE_H
+#include <sys/types.h>
+#endif
+
+#include <sys/stat.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+
+#ifdef HAVE_POLL
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif /* HAVE_POLL_H */
+
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif /* HAVE_SYS_POLL_H */
+
+/* Some constants... */
+
+#ifndef POLLRDNORM
+#define POLLRDNORM	POLLIN
+#endif /* !POLLRDNORM */
+
+#ifndef POLLRDBAND
+#define POLLRDBAND	POLLPRI
+#endif /* !POLLRDBAND */
+
+#else /* !HAVE_POLL */
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#endif /* HAVE_POLL */
+
+#if ! defined(EWOULDBLOCK) && defined(WSAEWOULDBLOCK)
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+#if ! defined(EADDRINUSE) && defined(WSAEADDRINUSE)
+#define EADDRINUSE WSAEADDRINUSE
+#endif
+
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#ifndef ARPA_INET_H
+#include <arpa/inet.h>
+#define ARPA_INET_H
+
+/* Stupid patch to avoid trouble with Linux includes... */
+#ifdef LITTLE_ENDIAN
+#undef LITTLE_ENDIAN
+#endif
+
+#endif
+#endif
+
+#ifdef HAVE_SYS_PROTOSW_H
+#include <sys/protosw.h>
+#endif
+
+#ifdef HAVE_SYS_STREAM_H
+#include <sys/stream.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKETVAR_H
+#include <sys/socketvar.h>
+#endif
+
+/* Fix warning on OSF/1
+ *
+ * NOERROR is defined by both sys/stream.h (-1), and arpa/nameser.h (0),
+ * the latter is included by netdb.h.
+ */
+#ifdef NOERROR
+#undef NOERROR
+#endif /* NOERROR */
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "dmalloc.h"
+
+struct udp_storage {
+  struct fd_callback_box box;	/* Must be first. */
+  int my_errno;
+   
+  int inet_flags;
+
+  int type;
+  int protocol;
+
+  struct svalue read_callback;	/* Mapped. */
+};
+
+void zero_udp(struct object *ignored);
+int low_exit_udp(void);
+void exit_udp(struct object *UNUSED(ignored)) {
+  low_exit_udp();
+}
+
+#undef THIS
+#define THIS ((struct udp_storage *)Pike_fp->current_storage)
+#define THISOBJ (Pike_fp->current_object)
+#define FD (THIS->box.fd)
+
+/*! @module Stdio
+ */
+
+/*! @class UDP
+ */
+
+/*! @decl int(0..1) close()
+ *!
+ *! Closes an open UDP port.
+ *!
+ *! @note
+ *!   This method was introduced in Pike 7.5.
+ */
+static void udp_close(INT32 args)
+{
+  int ret = low_exit_udp();
+  zero_udp(NULL);
+  pop_n_elems(args);
+  push_int( ret==0 );
+}
+
+/*! @decl UDP bind(int|string port, string|void address,@
+ *!string|int(0..1) no_reuseaddr)
+ *!
+ *! Binds a port for receiving or transmitting UDP.
+ *!
+ *! @param no_reuseaddr
+ *! 	If set to @expr{1@}, Pike will not set the @expr{SO_REUSEADDR@} option
+ *! 	on the UDP port.
+ *!
+ *! @note
+ *! 	@expr{SO_REUSEADDR@} is never applied when binding a random port
+ *!	(@expr{bind(0)@}).
+ *!
+ *! 	In general, @expr{SO_REUSEADDR@} is not desirable on UDP ports.
+ *! 	Unless used for receiving multicast, be sure to never bind a
+ *! 	non-random port without setting @expr{no_reuseaddr@} to @expr{1@}.
+ *!
+ *! @throws
+ *!   Throws error when unable to bind port.
+ */
+static void udp_bind(INT32 args)
+{
+  PIKE_SOCKADDR addr;
+  int addr_len;
+  int o;
+  int fd,tmp;
+#if !defined(SOL_IP) && defined(HAVE_GETPROTOBYNAME)
+  static int ip_proto_num = -1;
+#endif /* !SOL_IP && HAVE_GETPROTOBYNAME */
+
+  if(args < 1)
+    SIMPLE_TOO_FEW_ARGS_ERROR("Stdio.UDP->bind", 1);
+
+  if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT &&
+     (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING ||
+      Pike_sp[-args].u.string->size_shift))
+    SIMPLE_BAD_ARG_ERROR("Stdio.UDP->bind", 1, "int|string (8bit)");
+
+  if(args > 2 && TYPEOF(Pike_sp[2-args]) != PIKE_T_INT)
+    SIMPLE_BAD_ARG_ERROR("Stdio.UDP->bind", 3, "int(0..1)");
+
+#if 0
+  f_backtrace(0);
+  APPLY_MASTER("handle_error", 1);
+  pop_stack();
+#endif /* 0 */
+
+  if(FD != -1)
+  {
+    fd = FD;
+    change_fd_for_box (&THIS->box, -1);
+    fd_close(fd);
+  }
+
+  THIS->inet_flags &= ~PIKE_INET_FLAG_IPV6;
+
+  addr_len = get_inet_addr(&addr, (args > 1 && TYPEOF(Pike_sp[1-args])==PIKE_T_STRING?
+				   Pike_sp[1-args].u.string->str : NULL),
+			   (TYPEOF(Pike_sp[-args]) == PIKE_T_STRING?
+			    Pike_sp[-args].u.string->str : NULL),
+			   (TYPEOF(Pike_sp[-args]) == PIKE_T_INT?
+			    Pike_sp[-args].u.integer : -1),
+			   THIS->inet_flags);
+  INVALIDATE_CURRENT_TIME();
+
+#ifdef AF_INET6
+  if (SOCKADDR_FAMILY(addr) == AF_INET6) {
+    THIS->inet_flags |= PIKE_INET_FLAG_IPV6;
+  }
+#endif
+
+  fd = fd_socket(SOCKADDR_FAMILY(addr), THIS->type, THIS->protocol);
+  if(fd < 0)
+  {
+    pop_n_elems(args);
+    THIS->my_errno=errno;
+    Pike_error("Stdio.UDP->bind: failed to create socket (%d, %d, %d)\n",
+	       SOCKADDR_FAMILY(addr), THIS->type, THIS->protocol);
+  }
+
+  /* Make sure this fd gets closed on exec. */
+  set_close_on_exec(fd, 1);
+
+  o=1;
+  /* linux kernel commit f24d43c07e208372aa3d3bff419afbf43ba87698 introduces
+   * a behaviour change where you can get used random ports if bound with
+   * SO_REUSEADDR. */
+  if(addr.ipv4.sin_port && (args > 2 ? !Pike_sp[2-args].u.integer : 1)
+     && fd_setsockopt(fd, SOL_SOCKET,SO_REUSEADDR,
+		      (char *)&o, sizeof(int)) < 0)
+  {
+    fd_close(fd);
+    THIS->my_errno=errno;
+    Pike_error("Stdio.UDP->bind: setsockopt SO_REUSEADDR failed\n");
+  }
+
+#if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
+  if (SOCKADDR_FAMILY(addr) == AF_INET6) {
+    /* Attempt to enable dual-stack (ie mapped IPv4 adresses). Needed on WIN32.
+     * cf http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx
+     */
+    o = 0;
+    fd_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&o, sizeof(int));
+  }
+#endif
+
+#ifndef SOL_IP
+#ifdef HAVE_GETPROTOBYNAME
+  if (ip_proto_num == -1) {
+    /* NOTE: getprotobyname(3N) is not MT-safe. */
+    struct protoent *proto = getprotobyname("ip");
+    if (!proto) {
+      /* No entry for IP, assume zero. */
+      ip_proto_num = 0;
+    } else {
+      ip_proto_num = proto->p_proto;
+    }
+  }
+#define SOL_IP ip_proto_num
+#else /* !HAVE_GETPROTOBYNAME */
+#define SOL_IP 0
+#endif /* HAVE_GETPROTOBYNAME */
+#endif /* SOL_IP */
+
+#ifdef IP_HDRINCL
+  /*  From mtr-0.28:net.c: FreeBSD wants this to avoid sending
+      out packets with protocol type RAW to the network. */
+
+  if (THIS->type==SOCK_RAW && THIS->protocol==255 /* raw */)
+     if(fd_setsockopt(fd, SOL_IP, IP_HDRINCL, (char *)&o, sizeof(int)))
+	Pike_error("Stdio.UDP->bind: setsockopt IP_HDRINCL failed\n");
+#endif /* IP_HDRINCL */
+
+  THREADS_ALLOW_UID();
+
+  tmp=fd_bind(fd, (struct sockaddr *)&addr, addr_len)<0;
+
+  THREADS_DISALLOW_UID();
+
+  if(tmp)
+  {
+    fd_close(fd);
+    THIS->my_errno=errno;
+    Pike_error("Stdio.UDP->bind: failed to bind to port %d\n",
+	       (unsigned INT16)Pike_sp[-args].u.integer);
+    return;
+  }
+
+  if(!Pike_fp->current_object->prog)
+  {
+    if (fd >= 0)
+      while (fd_close(fd) && errno == EINTR) {}
+    Pike_error("Object destructed in Stdio.UDP->bind()\n");
+  }
+
+  change_fd_for_box (&THIS->box, fd);
+  pop_n_elems(args);
+  ref_push_object(THISOBJ);
+}
+
+
+/*! @decl UDP set_fd(int fd)
+ *!
+ *! Use the file descriptor @[fd] for UDP.
+ *! @seealso
+ *!   @[bind]
+ */
+static void udp_set_fd(INT32 args)
+{
+  int fd;
+
+  get_all_args("set_fd", args, "%d", &fd);
+
+  if(FD != -1)
+  {
+    int curfd = FD;
+    change_fd_for_box (&THIS->box, -1);
+    fd_close(curfd);
+  }
+
+  change_fd_for_box (&THIS->box, fd);
+  pop_n_elems(args);
+  ref_push_object(THISOBJ);
+}
+
+/*! @decl int query_fd()
+ *!
+ *! Gets the file descriptor for this UDP port.
+ */
+static void udp_query_fd(INT32 args)
+{
+  pop_n_elems(args);
+  push_int(FD);
+}
+
+
+
+/*! @decl int(0..1) enable_broadcast()
+ *!
+ *! Set the broadcast flag. 
+ *! If enabled then sockets receive packets sent  to  a  broadcast
+ *! address  and  they are allowed to send packets to a
+ *! broadcast address.
+ *!
+ *! @returns
+ *!  Returns @expr{1@} on success, @expr{0@} (zero) otherwise.
+ *!
+ *! @note
+ *!  This is normally only avalable to root users.
+ */
+void udp_enable_broadcast(INT32 args)
+{
+#ifdef SO_BROADCAST
+  int o = 1;
+  pop_n_elems(args);
+  push_int(fd_setsockopt(FD, SOL_SOCKET, SO_BROADCAST, (char *)&o, sizeof(int)));
+  THIS->my_errno=errno;
+#else /* SO_BROADCAST */
+  pop_n_elems(args);
+  push_int(0);
+#endif /* SO_BROADCAST */
+}
+
+/*! @decl int(0..1) enable_multicast(string reply_address)
+ *!   Set the local device for a multicast socket.
+ *!
+ *! @param reply_address
+ *!   Local address that should appear in the multicast packets.
+ *!
+ *! See also the Unix man page for setsocketopt IPPROTO_IP IP_MULTICAST_IF
+ *! and IPPROTO_IPV6 IPV6_MULTICAST_IF.
+ *!
+ *! @note
+ *!   This function did not support IPv6 in Pike 7.8.
+ */
+void udp_enable_multicast(INT32 args)
+{
+  int result;
+  char *ip;
+  PIKE_SOCKADDR reply;
+
+  get_all_args("enable_multicast", args, "%s", &ip);
+
+  get_inet_addr(&reply, ip, NULL, -1, THIS->inet_flags);
+  INVALIDATE_CURRENT_TIME();
+
+#ifdef AF_INET6
+  if (THIS->inet_flags & PIKE_INET_FLAG_IPV6) {
+    if(SOCKADDR_FAMILY(reply) != AF_INET6)
+      Pike_error("Multicast only supported for IPv6.\n");
+
+    result = fd_setsockopt(FD, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+			   (char *)&reply.ipv6.sin6_addr,
+			   sizeof(reply.ipv6.sin6_addr));
+    pop_n_elems(args);
+    push_int(result);
+    return;
+  }
+#endif
+  if(SOCKADDR_FAMILY(reply) != AF_INET)
+    Pike_error("Multicast only supported for IPv4.\n");
+
+  result = fd_setsockopt(FD, IPPROTO_IP, IP_MULTICAST_IF,
+			 (char *)&reply.ipv4.sin_addr,
+			 sizeof(reply.ipv4.sin_addr));
+  pop_n_elems(args);
+  push_int(result);
+}
+
+/*! @decl int set_multicast_ttl(int ttl)
+ *!   Set the time-to-live value of outgoing multicast packets
+ *!   for this socket.
+ *!
+ *! @param ttl
+ *!   The number of router hops sent multicast packets should
+ *!   survive.
+ *!
+ *!   It is very important for multicast packets to set the
+ *!   smallest TTL possible. The default before calling this
+ *!   function is 1 which means that multicast packets don't
+ *!   leak from the local network unless the user program
+ *!   explicitly requests it.
+ *!
+ *! See also the Unix man page for setsocketopt IPPROTO_IP IP_MULTICAST_TTL
+ *! and IPPROTO_IPV6 IPV6_MULTICAST_HOPS.
+ *!
+ *! @note
+ *!   This function did not support IPv6 in Pike 7.8 and earlier.
+ *!
+ *! @seealso
+ *!   @[add_membership()]
+ */
+void udp_set_multicast_ttl(INT32 args)
+{
+  int ttl;
+  get_all_args("set_multicast_ttl", args, "%d", &ttl);
+  pop_n_elems(args);
+#ifdef AF_INET6
+  if (THIS->inet_flags & PIKE_INET_FLAG_IPV6) {
+    push_int( fd_setsockopt(FD, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+			    (char *)&ttl, sizeof(int)) );
+    return;
+  }
+#endif
+  push_int( fd_setsockopt(FD, IPPROTO_IP, IP_MULTICAST_TTL,
+			  (char *)&ttl, sizeof(int)) );
+}
+
+/*! @decl int add_membership(string group, void|string address)
+ *!   Join a multicast group.
+ *!
+ *! @param group
+ *!   @[group] contains the address of the multicast group the
+ *!   application wants to join. It must be a valid multicast address.
+ *!
+ *! @param address
+ *!   @[address] is the address of the local interface with which
+ *!   the system should join to the multicast group. If not provided
+ *!   the system will select an appropriate interface.
+ *!
+ *! See also the Unix man page for setsocketopt IPPROTO_IP IP_ADD_MEMBERSHIP
+ *! and IPPROTO_IPV6 IPV6_JOIN_GROUP.
+ *!
+ *! @note
+ *!   The @[address] parameter is currently not supported for IPv6.
+ *!
+ *! @note
+ *!   This function did not support IPv6 in Pike 7.8 and earlier.
+ *!
+ *! @seealso
+ *!   @[drop_membership()]
+ */
+void udp_add_membership(INT32 args)
+{
+  int face=0;
+  char *group;
+  char *address=0;
+  struct ip_mreq sock;
+  PIKE_SOCKADDR addr;
+
+  get_all_args("add_membership", args, "%s.%s%d", &group, &address, &face);
+
+  get_inet_addr(&addr, group, NULL, -1, THIS->inet_flags);
+  INVALIDATE_CURRENT_TIME();
+
+#ifdef AF_INET6
+  if (THIS->inet_flags & PIKE_INET_FLAG_IPV6) {
+    struct ipv6_mreq sock;
+
+    if (address)
+      Pike_error("Interface address is not supported for IPv6.\n");
+
+    /* NB: This sets imr_interface to IN6ADDR_ANY,
+     *     and clears imr_ifindex if it exists.
+     */
+    MEMSET(&sock, 0, sizeof(sock));
+
+    if(SOCKADDR_FAMILY(addr) != AF_INET6)
+      Pike_error("Mixing IPv6 and other multicast is not supported.\n");
+
+    sock.ipv6mr_multiaddr = addr.ipv6.sin6_addr;
+
+    pop_n_elems(args);
+    push_int( fd_setsockopt(FD, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+			    (char *)&sock, sizeof(sock)) );
+    return;
+  }
+#endif /* AF_INET6 */
+
+  /* NB: This sets imr_interface to INADDR_ANY,
+   *     and clears imr_ifindex if it exists.
+   */
+  MEMSET(&sock, 0, sizeof(sock));
+
+  if(SOCKADDR_FAMILY(addr) != AF_INET)
+    Pike_error("Mixing IPv6 and IPv4 multicast is not supported.\n");
+
+  sock.imr_multiaddr = addr.ipv4.sin_addr;
+
+  if (address) {
+    get_inet_addr(&addr, address, NULL, -1, THIS->inet_flags);
+    INVALIDATE_CURRENT_TIME();
+
+    if(SOCKADDR_FAMILY(addr) != AF_INET)
+      Pike_error("Mixing IPv6 and IPv4 multicast is not supported.\n");
+
+    sock.imr_interface = addr.ipv4.sin_addr;
+  }
+
+  pop_n_elems(args);
+  push_int( fd_setsockopt(FD, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+			  (char *)&sock, sizeof(sock)) );
+}
+
+/*! @decl int drop_membership(string group, void|string address)
+ *!   Leave a multicast group.
+ *!
+ *! @param group
+ *!   @[group] contains the address of the multicast group the
+ *!   application wants to join. It must be a valid multicast address.
+ *!
+ *! @param address
+ *!   @[address] is the address of the local interface with which
+ *!   the system should join to the multicast group. If not provided
+ *!   the system will select an appropriate interface.
+ *!
+ *! See also the Unix man page for setsocketopt IPPROTO_IP IP_DROP_MEMBERSHIP
+ *! and IPPROTO_IPV6 IPV6_LEAVE_GROUP.
+ *!
+ *! @note
+ *!   The @[address] parameter is currently not supported for IPv6.
+ *!
+ *! @note
+ *!   This function did not support IPv6 in Pike 7.8 and earlier.
+ *!
+ *! @seealso
+ *!   @[add_membership()]
+ */
+void udp_drop_membership(INT32 args)
+{
+  int face=0;
+  char *group;
+  char *address=0;
+  struct ip_mreq sock;
+  PIKE_SOCKADDR addr;
+
+  get_all_args("drop_membership", args, "%s.%s%d", &group, &address, &face);
+
+  get_inet_addr(&addr, group, NULL, -1, THIS->inet_flags);
+  INVALIDATE_CURRENT_TIME();
+
+#ifdef AF_INET6
+  if (THIS->inet_flags & PIKE_INET_FLAG_IPV6) {
+    struct ipv6_mreq sock;
+
+    if (address)
+      Pike_error("Interface address is not supported for IPv6.\n");
+
+    /* NB: This sets imr_interface to IN6ADDR_ANY,
+     *     and clears imr_ifindex if it exists.
+     */
+    MEMSET(&sock, 0, sizeof(sock));
+
+    if(SOCKADDR_FAMILY(addr) != AF_INET6)
+      Pike_error("Mixing IPv6 and other multicast is not supported.\n");
+
+    sock.ipv6mr_multiaddr = addr.ipv6.sin6_addr;
+
+    pop_n_elems(args);
+    push_int( fd_setsockopt(FD, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+			    (char *)&sock, sizeof(sock)) );
+    return;
+  }
+#endif /* AF_INET6 */
+
+  /* NB: This sets imr_interface to INADDR_ANY,
+   *     and clears imr_ifindex if it exists.
+   */
+  MEMSET(&sock, 0, sizeof(sock));
+
+  if(SOCKADDR_FAMILY(addr) != AF_INET)
+    Pike_error("Mixing IPv6 and IPv4 multicast is not supported.\n");
+
+  sock.imr_multiaddr = addr.ipv4.sin_addr;
+
+  if (address) {
+    get_inet_addr(&addr, address, NULL, -1, THIS->inet_flags);
+    INVALIDATE_CURRENT_TIME();
+
+    if(SOCKADDR_FAMILY(addr) != AF_INET)
+      Pike_error("Mixing IPv6 and IPv4 multicast is not supported.\n");
+
+    sock.imr_interface = addr.ipv4.sin_addr;
+  }
+
+  pop_n_elems(args);
+  push_int( fd_setsockopt(FD, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+			  (char *)&sock, sizeof(sock)) );
+}
+
+/*! @decl int(0..1) wait(int|float timeout)
+ *!
+ *! Check for data and wait max. @[timeout] seconds.
+ *!
+ *! @returns
+ *!  Returns @expr{1@} if data are ready, @expr{0@} (zero) otherwise.
+ */
+void udp_wait(INT32 args)
+{
+#ifdef HAVE_POLL
+  struct pollfd pollfds[1];
+  int ms;
+#else /* !HAVE_POLL */
+  fd_set rset;
+  struct timeval tv;
+#endif /* HAVE_POLL */
+  FLOAT_TYPE timeout;
+  int fd = FD;
+  int res;
+  int e;
+
+  get_all_args("wait", args, "%F", &timeout);
+
+  if (timeout < 0.0) {
+    timeout = 0.0;
+  }
+
+  if (fd < 0) {
+    Pike_error("udp->wait(): Port not bound!\n");
+  }
+
+#ifdef HAVE_POLL
+  THREADS_ALLOW();
+
+  pollfds->fd = fd;
+  pollfds->events = POLLIN;
+  pollfds->revents = 0;
+  ms = timeout * 1000;
+
+  do {
+    res = poll(pollfds, 1, ms);
+    e = errno;
+  } while (res < 0 && e == EINTR)
+    
+  THREADS_DISALLOW();
+  if (!res) {
+    /* Timeout */
+  } else if (res < 0) {
+    /* Error */
+    Pike_error("udp->wait(): poll() failed with errno %d\n", e);
+  } else {
+    /* Success? */
+    if (pollfds->revents) {
+      res = 1;
+    } else {
+      res = 0;
+    }
+  }
+#else /* !HAVE_POLL */
+  THREADS_ALLOW();
+
+  FD_ZERO(&rset);
+  FD_SET(fd, &rset);
+  tv.tv_sec = DO_NOT_WARN((int)timeout);
+  tv.tv_usec = DO_NOT_WARN((int)((timeout - ((int)timeout)) * 1000000.0));
+  res = fd_select(fd+1, &rset, NULL, NULL, &tv);
+  e = errno;
+
+  THREADS_DISALLOW();
+  if (!res) {
+    /* Timeout */
+  } else if (res < 0) {
+    /* Error */
+    Pike_error("udp->wait(): select() failed with errno %d\n", e);
+  } else {
+    /* Success? */
+    if (FD_ISSET(fd, &rset)) {
+      res = 1;
+    } else {
+      res = 0;
+    }
+  }
+#endif /* HAVE_POLL */
+
+  pop_n_elems(args);
+
+  push_int(res);
+}
+
+/* NOTE: Some versions of AIX seem to have a
+ *         #define events reqevents
+ *       in one of the poll headerfiles. This will break
+ *       the fd_box event handling.
+ */
+#undef events
+
+#define UDP_BUFFSIZE 65536
+
+/*! @decl mapping(string:int|string) read()
+ *! @decl mapping(string:int|string) read(int flag)
+ *!
+ *! Read from the UDP socket.
+ *!
+ *! Flag @[flag] is a bitfield, 1 for out of band data and 2 for peek
+ *!
+ *! @returns
+ *!  mapping(string:int|string) in the form 
+ *!	([
+ *!	   "data" : string received data
+ *!	   "ip" : string   received from this ip
+ *!	   "port" : int    ...and this port
+ *!	])
+ *!
+ *! @seealso
+ *!   @[set_read_callback()], @[MSG_OOB], @[MSG_PEEK]
+ */
+void udp_read(INT32 args)
+{
+  int flags = 0, res=0, fd, e;
+  PIKE_SOCKADDR from;
+  char buffer[UDP_BUFFSIZE];
+  ACCEPT_SIZE_T fromlen = sizeof(from);
+  
+  if(args)
+  {
+    if(Pike_sp[-args].u.integer & 1) {
+      flags |= MSG_OOB;
+    }
+    if(Pike_sp[-args].u.integer & 2) {
+#ifdef MSG_PEEK
+      flags |= MSG_PEEK;
+#else /* !MSG_PEEK */
+      /* FIXME: What should we do here? */
+#endif /* MSG_PEEK */
+    }
+    if(Pike_sp[-args].u.integer & ~3) {
+      Pike_error("Illegal 'flags' value passed to udp->read([int flags])\n");
+    }
+  }
+  pop_n_elems(args);
+  fd = FD;
+  if (FD < 0)
+    Pike_error("Stdio.UDP->read: not open\n");
+  do {
+    THREADS_ALLOW();
+    res = fd_recvfrom(fd, buffer, UDP_BUFFSIZE, flags,
+		      (struct sockaddr *)&from, &fromlen);
+    e = errno;
+    THREADS_DISALLOW();
+
+    check_threads_etc();
+  } while((res==-1) && (e==EINTR));
+
+  THIS->my_errno=errno=e;
+
+  if(res<0)
+  {
+    switch(e)
+    {
+#ifdef WSAEBADF
+       case WSAEBADF:
+#endif
+       case EBADF:
+	  if (THIS->box.backend)
+	    set_fd_callback_events (&THIS->box, 0, 0);
+	  Pike_error("Socket closed\n");
+#ifdef ESTALE
+       case ESTALE:
+#endif
+       case EIO:
+	  if (THIS->box.backend)
+	    set_fd_callback_events (&THIS->box, 0, 0);
+	  Pike_error("I/O error\n");
+       case ENOMEM:
+#ifdef ENOSR
+       case ENOSR:
+#endif /* ENOSR */
+	  Pike_error("Out of memory\n");
+#ifdef ENOTSOCK
+       case ENOTSOCK:
+	  Pike_fatal("reading from non-socket fd!!!\n");
+#endif
+       case EINVAL:
+	 if (!(flags & MSG_OOB)) {
+	   Pike_error("Socket read failed with EINVAL.\n");
+	 }
+	 /* FALL_THROUGH */
+       case EWOULDBLOCK:
+	  push_int( 0 );
+	  return;
+
+       default:
+	  Pike_error("Socket read failed with errno %d.\n", e);
+    }
+  }
+  /* Now comes the interresting part.
+   * make a nice mapping from this stuff..
+   */
+  push_text("data");
+  push_string( make_shared_binary_string(buffer, res) );
+
+  push_text("ip");
+#ifdef fd_inet_ntop
+  if (!fd_inet_ntop( SOCKADDR_FAMILY(from), SOCKADDR_IN_ADDR(from),
+		     buffer, sizeof(buffer) )) {
+    push_text("UNSUPPORTED");
+  } else {
+    /* NOTE: IPv6-mapped IPv4 addresses may only
+     *       connect to other IPv4 addresses.
+     *
+     * Make the Pike-level code believe it has an actual IPv4 address
+     * when getting a mapped address (::FFFF:a.b.c.d).
+     */
+    if ((!strncmp(buffer, "::FFFF:", 7) || !strncmp(buffer, "::ffff:", 7)) &&
+	!strchr(buffer + 7, ':')) {
+      push_text(buffer+7);
+    } else {
+      push_text(buffer);
+    }
+  }
+#else
+  push_text( inet_ntoa( *SOCKADDR_IN_ADDR(from) ) );
+#endif
+
+  push_text("port");
+  push_int(ntohs(from.ipv4.sin_port));
+  f_aggregate_mapping( 6 );
+
+  if (!(THIS->inet_flags & PIKE_INET_FLAG_NB))
+    INVALIDATE_CURRENT_TIME();
+}
+
+/*! @decl int send(string to, int|string port, string message)
+ *! @decl int send(string to, int|string port, string message, int flags)
+ *!
+ *! Send data to a UDP socket. The recipient address will be @[to]
+ *! and port will be @[port].
+ *!
+ *! Flag @[flag] is a bitfield, 1 for out of band data and
+ *! 2 for don't route flag.
+ *!
+ *! @returns
+ *! The number of bytes that were actually written.
+ */
+void udp_sendto(INT32 args)
+{
+  int flags = 0, fd, e;
+  ptrdiff_t res = 0;
+  PIKE_SOCKADDR to;
+  int to_len;
+  char *str;
+  ptrdiff_t len;
+
+  if(FD < 0)
+    Pike_error("UDP: not open\n");
+  
+  check_all_args("send", args,
+		 BIT_STRING, BIT_INT|BIT_STRING, BIT_STRING, BIT_INT|BIT_VOID, 0);
+  
+  if(args>3)
+  {
+    if(Pike_sp[3-args].u.integer & 1) {
+      flags |= MSG_OOB;
+    }
+    if(Pike_sp[3-args].u.integer & 2) {
+#ifdef MSG_DONTROUTE
+      flags |= MSG_DONTROUTE;
+#else /* !MSG_DONTROUTE */
+      /* FIXME: What should we do here? */
+#endif /* MSG_DONTROUTE */
+    }
+    if(Pike_sp[3-args].u.integer & ~3) {
+      Pike_error("Illegal 'flags' value passed to "
+		 "Stdio.UDP->send(string to, int|string port, string message, int flags)\n");
+    }
+  }
+
+  to_len = get_inet_addr(&to, Pike_sp[-args].u.string->str,
+			 (TYPEOF(Pike_sp[1-args]) == PIKE_T_STRING?
+			  Pike_sp[1-args].u.string->str : NULL),
+			 (TYPEOF(Pike_sp[1-args]) == PIKE_T_INT?
+			  Pike_sp[1-args].u.integer : -1),
+			 THIS->inet_flags);
+  INVALIDATE_CURRENT_TIME();
+
+  fd = FD;
+  str = Pike_sp[2-args].u.string->str;
+  len = Pike_sp[2-args].u.string->len;
+
+  do {
+    THREADS_ALLOW();
+    res = fd_sendto( fd, str, len, flags, (struct sockaddr *)&to, to_len);
+    e = errno;
+    THREADS_DISALLOW();
+
+    check_threads_etc();
+  } while((res == -1) && e==EINTR);
+  
+  if(res<0)
+  {
+    switch(e)
+    {
+#ifdef EMSGSIZE
+       case EMSGSIZE:
+#endif
+	  Pike_error("Too big message\n");
+       case EBADF:
+	  if (THIS->box.backend)
+	    set_fd_callback_events (&THIS->box, 0, 0);
+	  Pike_error("Socket closed\n");
+       case ENOMEM:
+#ifdef ENOSR
+       case ENOSR:
+#endif /* ENOSR */
+	  Pike_error("Out of memory\n");
+       case EINVAL:
+#ifdef ENOTSOCK
+       case ENOTSOCK:
+	  if (THIS->box.backend)
+	    set_fd_callback_events (&THIS->box, 0, 0);
+	  Pike_error("Not a socket!!!\n");
+#endif
+       case EWOULDBLOCK:
+	  Pike_error("Message would block.\n");
+    }
+  }
+  pop_n_elems(args);
+  push_int64(res);
+  if (!(THIS->inet_flags & PIKE_INET_FLAG_NB))
+    INVALIDATE_CURRENT_TIME();
+}
+
+
+static int got_udp_event (struct fd_callback_box *box, int DEBUGUSED(event))
+{
+  struct udp_storage *u = (struct udp_storage *) box;
+#ifdef PIKE_DEBUG
+  if (event != PIKE_FD_READ)
+    Pike_fatal ("Got unexpected event %d.\n", event);
+#endif
+
+  u->my_errno = errno;		/* Propagate backend setting. */
+
+  check_destructed (&u->read_callback);
+  if (UNSAFE_IS_ZERO (&u->read_callback))
+    set_fd_callback_events (&u->box, 0, 0);
+  else {
+    apply_svalue (&u->read_callback, 0);
+    if (TYPEOF(Pike_sp[-1]) == PIKE_T_INT && Pike_sp[-1].u.integer == -1) {
+      pop_stack();
+      return -1;
+    }
+    pop_stack();
+  }
+  return 0;
+}
+
+void zero_udp(struct object *o)
+{
+  INIT_FD_CALLBACK_BOX(&THIS->box, NULL, o, -1, 0, got_udp_event, 0);
+  THIS->my_errno = 0;
+  THIS->inet_flags = PIKE_INET_FLAG_UDP;
+  THIS->type=SOCK_DGRAM;
+  THIS->protocol=0;
+  /* map_variable handles read_callback. */
+}
+
+int low_exit_udp()
+{
+  int fd = FD;
+  int ret = 0;
+
+  unhook_fd_callback_box(&THIS->box);
+  FD = -1;
+
+  if(fd != -1)
+  {
+    THREADS_ALLOW();
+    ret = fd_close(fd);
+    THREADS_DISALLOW();
+  }
+
+  /* map_variable handles read_callback. */
+
+  return ret;
+}
+
+static void udp_set_read_callback(INT32 args)
+{
+  struct udp_storage *u = THIS;
+  if(args < 1)
+    SIMPLE_TOO_FEW_ARGS_ERROR("Stdio.UDP->set_read_callback", 1);
+  if(args > 1)
+    pop_n_elems(args-1);
+
+  assign_svalue(& u->read_callback, Pike_sp-1);
+  if (UNSAFE_IS_ZERO (Pike_sp - 1)) {
+    if (u->box.backend)
+      set_fd_callback_events (&u->box, 0, 0);
+  }
+  else {
+    if (!u->box.backend)
+      INIT_FD_CALLBACK_BOX (&u->box, default_backend, u->box.ref_obj,
+			    u->box.fd, PIKE_BIT_FD_READ, got_udp_event, 0);
+    else
+      set_fd_callback_events (&u->box, PIKE_BIT_FD_READ, 0);
+  }
+
+  pop_stack();
+  ref_push_object(THISOBJ);
+}
+
+static void udp_set_nonblocking(INT32 args)
+{
+  if (FD < 0) Pike_error("File not open.\n");
+
+  if (args)
+  {
+     udp_set_read_callback(args);
+     pop_stack();
+  }
+  set_nonblocking(FD,1);
+  THIS->inet_flags |= PIKE_INET_FLAG_NB;
+  ref_push_object(THISOBJ);
+}
+
+/*! @decl object set_blocking()
+ *!
+ *! Sets this object to be blocking.
+ */
+static void udp_set_blocking(INT32 args)
+{
+  if (FD < 0) Pike_error("File not open.\n");
+  set_nonblocking(FD,0);
+  THIS->inet_flags &= ~PIKE_INET_FLAG_NB;
+  pop_n_elems(args);
+  ref_push_object(THISOBJ);
+}
+
+/*! @decl int(0..1) connect(string address, int|string port)
+ *!
+ *!   Establish an UDP connection.
+ *!
+ *!   This function connects an UDP socket previously created with
+ *!   @[Stdio.UDP()] to a remote socket. The @[address] is the IP name or
+ *!   number for the remote machine. 
+ *!
+ *! @returns
+ *!   Returns @expr{1@} on success, @expr{0@} (zero) otherwise.
+ *!
+ *! @note
+ *!   If the socket is in nonblocking mode, you have to wait
+ *!   for a write or close callback before you know if the connection
+ *!   failed or not.
+ *!
+ *! @seealso
+ *!   @[bind()], @[query_address()]
+ */
+static void udp_connect(INT32 args)
+{
+  PIKE_SOCKADDR addr;
+  int addr_len;
+  struct pike_string *dest_addr = NULL;
+  struct svalue *dest_port = NULL;
+
+  int tmp;
+
+  get_all_args("UDP.connect", args, "%S%*", &dest_addr, &dest_port);
+
+  if(TYPEOF(*dest_port) != PIKE_T_INT &&
+     (TYPEOF(*dest_port) != PIKE_T_STRING || dest_port->u.string->size_shift))
+    SIMPLE_BAD_ARG_ERROR("UDP.connect", 2, "int|string (8bit)");
+
+  addr_len =  get_inet_addr(&addr, dest_addr->str,
+			    (TYPEOF(*dest_port) == PIKE_T_STRING?
+			     dest_port->u.string->str : NULL),
+			    (TYPEOF(*dest_port) == PIKE_T_INT?
+			     dest_port->u.integer : -1),
+			    THIS->inet_flags);
+  INVALIDATE_CURRENT_TIME();
+
+  if(FD < 0)
+  {
+     FD = fd_socket(SOCKADDR_FAMILY(addr), SOCK_DGRAM, 0);
+     if(FD < 0)
+     {
+	THIS->my_errno=errno;
+	Pike_error("Stdio.UDP->connect: failed to create socket\n");
+     }
+     set_close_on_exec(FD, 1);
+
+#if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
+     if (SOCKADDR_FAMILY(addr) == AF_INET6) {
+       /* Attempt to enable dual-stack (ie mapped IPv4 adresses).
+	* Needed on WIN32.
+	* cf http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx
+	*/
+       int o = 0;
+       fd_setsockopt(FD, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&o, sizeof(int));
+     }
+#endif
+  }
+
+  tmp=FD;
+  THREADS_ALLOW();
+  tmp=fd_connect(tmp, (struct sockaddr *)&addr, addr_len);
+  THREADS_DISALLOW();
+
+  if (!(THIS->inet_flags & PIKE_INET_FLAG_NB))
+    INVALIDATE_CURRENT_TIME();
+
+  if(tmp < 0)
+  {
+    THIS->my_errno=errno;
+    Pike_error("Stdio.UDP->connect: failed to connect\n");
+  }else{
+    THIS->my_errno=0;
+    pop_n_elems(args);
+    push_int(1);
+  }
+}
+
+/*! @decl string query_address()
+ *! 
+ *! Returns the local address of a socket on the form "x.x.x.x port".
+ *! If this file is not a socket, not connected or some other error occurs,
+ *! zero is returned.
+ */
+static void udp_query_address(INT32 args)
+{
+  PIKE_SOCKADDR addr;
+  int i;
+  int fd = FD;
+  char buffer[496];
+  ACCEPT_SIZE_T len;
+
+  if(fd <0)
+    Pike_error("Stdio.UDP->query_address(): Port not bound yet.\n");
+
+  THREADS_ALLOW();
+
+  len=sizeof(addr);
+  i=fd_getsockname(fd,(struct sockaddr *)&addr,&len);
+
+  THREADS_DISALLOW();
+
+  pop_n_elems(args);
+  if(i < 0 || len < (int)sizeof(addr.ipv4))
+  {
+    push_int(0);
+    return;
+  }
+
+#ifdef fd_inet_ntop
+  fd_inet_ntop(SOCKADDR_FAMILY(addr), SOCKADDR_IN_ADDR(addr),
+	       buffer, sizeof(buffer)-20);
+#else
+  q=inet_ntoa(*SOCKADDR_IN_ADDR(addr));
+  strncpy(buffer,q,sizeof(buffer)-20);
+  buffer[sizeof(buffer)-20]=0;
+#endif
+  sprintf(buffer+strlen(buffer)," %d",(int)(ntohs(addr.ipv4.sin_port)));
+
+  /* NOTE: IPv6-mapped IPv4 addresses may only connect to other IPv4 addresses.
+   *
+   * Make the Pike-level code believe it has an actual IPv4 address
+   * when getting a mapped address (::FFFF:a.b.c.d).
+   */
+  if ((!strncmp(buffer, "::FFFF:", 7) || !strncmp(buffer, "::ffff:", 7)) &&
+      !strchr(buffer + 7, ':')) {
+    push_text(buffer+7);
+  } else {
+    push_text(buffer);
+  }
+}
+
+/*! @decl void set_backend (Pike.Backend backend)
+ *!
+ *! Set the backend used for the read callback.
+ *!
+ *! @note
+ *! The backend keeps a reference to this object as long as there can
+ *! be calls to the read callback, but this object does not keep a
+ *! reference to the backend.
+ *!
+ *! @seealso
+ *!   @[query_backend]
+ */
+static void udp_set_backend (INT32 args)
+{
+  struct udp_storage *u = THIS;
+  struct Backend_struct *backend;
+
+  if (!args)
+    SIMPLE_TOO_FEW_ARGS_ERROR ("Stdio.UDP->set_backend", 1);
+  if (TYPEOF(Pike_sp[-args]) != PIKE_T_OBJECT)
+    SIMPLE_BAD_ARG_ERROR ("Stdio.UDP->set_backend", 1, "object(Pike.Backend)");
+  backend = (struct Backend_struct *)
+    get_storage (Pike_sp[-args].u.object, Backend_program);
+  if (!backend)
+    SIMPLE_BAD_ARG_ERROR ("Stdio.UDP->set_backend", 1, "object(Pike.Backend)");
+
+  if (u->box.backend)
+    change_backend_for_box (&u->box, backend);
+  else
+    INIT_FD_CALLBACK_BOX (&u->box, backend, u->box.ref_obj,
+			  u->box.fd, 0, got_udp_event, 0);
+
+  pop_n_elems (args - 1);
+}
+
+/*! @decl Pike.Backend query_backend()
+ *!
+ *! Return the backend used for the read callback.
+ *!
+ *! @seealso
+ *!   @[set_backend]
+ */
+static void udp_query_backend (INT32 args)
+{
+  pop_n_elems (args);
+  ref_push_object (get_backend_obj (THIS->box.backend ? THIS->box.backend :
+				    default_backend));
+}
+
+/*! @decl int errno()
+ *!
+ *! Returns the error code for the last command on this object.
+ *! Error code is normally cleared when a command is successful.
+ */
+static void udp_errno(INT32 args)
+{
+   pop_n_elems(args);
+   push_int(THIS->my_errno);
+}
+
+/*! @decl UDP set_type(int sock_type)
+ *! @decl UDP set_type(int sock_type, int family)
+ *!
+ *! Sets socket type and protocol family.
+ */
+static void udp_set_type(INT32 args)
+{
+   int type, proto = 0;
+
+   get_all_args("Stdio.UDP->set_type",args,"%d.%d",&type,&proto);
+
+   THIS->type=type;
+   THIS->protocol=proto;
+   
+   pop_n_elems(args);
+   ref_push_object(THISOBJ);
+}
+
+/*! @decl array(int) get_type()
+ *!
+ *! Returns socket type and protocol family.
+ */
+static void udp_get_type(INT32 args)
+{
+   pop_n_elems(args);
+   push_int(THIS->type);
+   push_int(THIS->protocol);
+   f_aggregate(2);
+}
+
+/*! @decl void set_buffer(int bufsize, string mode)
+ *! @decl void set_buffer(int bufsize)
+ *!
+ *! Set internal socket buffer.
+ *!
+ *! This function sets the internal buffer size of a socket or stream.
+ *!
+ *! The second argument allows you to set the read or write buffer by
+ *! specifying @expr{"r"@} or @expr{"w"@}.
+ *!
+ *! @note
+ *!   It is not guaranteed that this function actually does anything,
+ *!   but it certainly helps to increase data transfer speed when it does.
+ *!
+ *! @seealso
+ *!   @[open_socket()], @[accept()]
+ */
+static void udp_set_buffer(INT32 args)
+{
+  INT_TYPE bufsize;
+  int flags = FILE_READ | FILE_WRITE;
+  char *c = NULL;
+
+  if(FD==-1)
+    Pike_error("Stdio.UDP->set_buffer() on closed file.\n");
+
+  get_all_args("Stdio.UDP->set_buffer", args, "%+.%s", &bufsize, &c);
+
+  if(bufsize < 0)
+    Pike_error("Bufsize must be larger than zero.\n");
+
+  if(c)
+  {
+    flags = 0;
+    do
+    {
+      switch( *c )
+      {
+      case 'w': flags |= FILE_WRITE; break;
+      case 'r': flags |= FILE_READ;  break;
+      }
+    } while( *c++ );
+  }
+  pop_n_elems(args);
+
+#ifdef SOCKET_BUFFER_MAX
+#if SOCKET_BUFFER_MAX
+  if(bufsize>SOCKET_BUFFER_MAX) bufsize=SOCKET_BUFFER_MAX;
+#endif
+#ifdef SO_RCVBUF
+  if(flags & FILE_READ)
+  {
+    int tmp=bufsize;
+    fd_setsockopt(FD,SOL_SOCKET, SO_RCVBUF, (char *)&tmp, sizeof(tmp));
+  }
+#endif /* SO_RCVBUF */
+
+#ifdef SO_SNDBUF
+  if(flags & FILE_WRITE)
+  {
+    int tmp=bufsize;
+    fd_setsockopt(FD,SOL_SOCKET, SO_SNDBUF, (char *)&tmp, sizeof(tmp));
+  }
+#endif /* SO_SNDBUF */
+#endif
+}
+
+/*! @decl constant MSG_OOB
+ *! @fixme
+ *! Document this constant.
+ */
+
+/*! @decl constant MSG_PEEK
+ *! @fixme
+ *! Document this constant.
+ */
+
+/*! @endclass
+ */
+
+/*! @endmodule
+ */
+
+void init_stdio_udp(void)
+{
+  START_NEW_PROGRAM_ID (STDIO_UDP);
+
+  ADD_STORAGE(struct udp_storage);
+
+  PIKE_MAP_VARIABLE("_read_callback", OFFSETOF(udp_storage, read_callback),
+		    tFunc(tNone, tInt_10), PIKE_T_MIXED, ID_PROTECTED|ID_PRIVATE);
+
+  ADD_FUNCTION("set_type",udp_set_type,
+	       tFunc(tInt tOr(tVoid,tInt),tObj),0);
+  ADD_FUNCTION("get_type",udp_get_type,
+	       tFunc(tNone,tArr(tInt)),0);
+
+  ADD_FUNCTION("close", udp_close, tFunc(tNone, tInt01), 0);
+
+  ADD_FUNCTION("bind",udp_bind,
+	       tFunc(tOr(tInt,tStr) tOr(tVoid,tStr) tOr(tVoid,tInt),tObj),0);
+
+  ADD_FUNCTION("set_fd",udp_set_fd,
+         tFunc(tInt,tObj),0);
+
+  ADD_FUNCTION("query_fd",udp_query_fd,
+         tFunc(tInt,tObj),0);
+
+  ADD_FUNCTION("enable_broadcast", udp_enable_broadcast,
+	       tFunc(tNone,tInt01), 0);
+
+  ADD_FUNCTION("enable_multicast", udp_enable_multicast,
+	       tFunc(tStr,tInt01), 0);
+
+  ADD_FUNCTION("set_multicast_ttl", udp_set_multicast_ttl,
+	       tFunc(tInt,tInt), 0);
+
+  ADD_FUNCTION("add_membership", udp_add_membership,
+	       tFunc(tStr tOr(tVoid,tStr tOr(tVoid,tInt)),tInt), 0);
+
+  ADD_FUNCTION("drop_membership", udp_drop_membership,
+	       tFunc(tStr tOr(tVoid,tStr tOr(tVoid,tInt)),tInt), 0);
+
+  ADD_FUNCTION("wait", udp_wait, tFunc(tOr(tInt, tFloat), tInt), 0);
+
+  ADD_FUNCTION("read",udp_read,
+	       tFunc(tOr(tInt,tVoid),tMap(tStr,tOr(tInt,tStr))),0);
+
+  add_integer_constant("MSG_OOB", 1, 0);
+#ifdef MSG_PEEK
+  add_integer_constant("MSG_PEEK", 2, 0);
+#endif /* MSG_PEEK */
+
+  ADD_FUNCTION("send",udp_sendto,
+	       tFunc(tStr tOr(tInt,tStr) tStr tOr(tVoid,tInt),tInt),0);
+
+  ADD_FUNCTION("connect",udp_connect,
+	       tFunc(tString tOr(tInt,tStr),tInt),0);
+  
+  ADD_FUNCTION("_set_nonblocking", udp_set_nonblocking,
+	       tFunc(tOr(tFunc(tVoid,tVoid),tVoid),tObj), 0 );
+  ADD_FUNCTION("_set_read_callback", udp_set_read_callback,
+	       tFunc(tFunc(tVoid,tVoid),tObj), 0 );
+
+  ADD_FUNCTION("set_blocking",udp_set_blocking,tFunc(tVoid,tObj), 0 );
+  ADD_FUNCTION("query_address",udp_query_address,tFunc(tNone,tStr),0);
+
+  ADD_FUNCTION ("set_backend", udp_set_backend, tFunc(tObj,tVoid), 0);
+  ADD_FUNCTION ("query_backend", udp_query_backend, tFunc(tVoid,tObj), 0);
+
+  ADD_FUNCTION("errno",udp_errno,tFunc(tNone,tInt),0);
+
+  ADD_FUNCTION("set_buffer", udp_set_buffer, tFunc(tInt tOr(tStr,tVoid),tVoid), 0);
+
+  set_init_callback(zero_udp);
+  set_exit_callback(exit_udp);
+
+  end_class("UDP",0);
+
+  START_NEW_PROGRAM_ID (STDIO_SOCK);
+#ifdef SOCK_STREAM
+  add_integer_constant("STREAM",SOCK_STREAM,0);
+#endif
+#ifdef SOCK_DGRAM
+  add_integer_constant("DGRAM",SOCK_DGRAM,0);
+#endif
+#ifdef SOCK_SEQPACKET
+  add_integer_constant("SEQPACKET",SOCK_SEQPACKET,0);
+#endif
+#ifdef SOCK_RAW
+  add_integer_constant("RAW",SOCK_RAW,0);
+#endif
+#ifdef SOCK_RDM
+  add_integer_constant("RDM",SOCK_RDM,0);
+#endif
+#ifdef SOCK_PACKET
+  add_integer_constant("PACKET",SOCK_PACKET,0);
+#endif
+   push_program(end_program());
+   f_call_function(1);
+   simple_add_constant("SOCK",Pike_sp-1,0);
+   pop_stack();
+
+   START_NEW_PROGRAM_ID (STDIO_IPPROTO);
+   add_integer_constant("IP",0,0);       /* Dummy protocol for TCP.  */
+   add_integer_constant("HOPOPTS",0,0);  /* IPv6 Hop-by-Hop options.  */
+   add_integer_constant("ICMP",1,0);     /* Internet Control Message Protocol.  */
+   add_integer_constant("IGMP",2,0);     /* Internet Group Management Protocol. */
+   add_integer_constant("GGP", 3, 0);	 /* Gateway-Gateway Protocol.  */
+   add_integer_constant("IPIP",4,0);     /* IPIP tunnels (older KA9Q tunnels use 94).  */
+   add_integer_constant("TCP",6,0);      /* Transmission Control Protocol.  */
+   add_integer_constant("EGP",8,0);      /* Exterior Gateway Protocol.  */
+   add_integer_constant("PUP",12,0);     /* PUP protocol.  */
+   add_integer_constant("UDP",17,0);     /* User Datagram Protocol.  */
+   add_integer_constant("IDP",22,0);     /* XNS IDP protocol.  */
+   add_integer_constant("RDP", 27, 0);	 /* "Reliable Datagram" Protocol.  */
+   add_integer_constant("TP",29,0);      /* SO Transport Protocol Class 4.  */
+   add_integer_constant("IPV6",41,0);    /* IPv6 header.  */
+   add_integer_constant("ROUTING",43,0); /* IPv6 routing header.  */
+   add_integer_constant("FRAGMENT",44,0);/* IPv6 fragmentation header.  */
+   add_integer_constant("RSVP",46,0);    /* Reservation Protocol.  */
+   add_integer_constant("GRE",47,0);     /* General Routing Encapsulation.  */
+   add_integer_constant("ESP",50,0);     /* encapsulating security payload.  */
+   add_integer_constant("AH",51,0);      /* authentication header.  */
+   add_integer_constant("ICMPV6",58,0);  /* ICMPv6.  */
+   add_integer_constant("NONE",59,0);    /* IPv6 no next header.  */
+   add_integer_constant("DSTOPTS",60,0); /* IPv6 destination options.  */
+   add_integer_constant("MTP",92,0);     /* Multicast Transport Protocol.  */
+   add_integer_constant("ENCAP",98,0);   /* Encapsulation Header.  */
+   add_integer_constant("PIM",103,0);    /* Protocol Independent Multicast.  */
+   add_integer_constant("COMP",108,0);   /* Compression Header Protocol.  */
+   add_integer_constant("RAW",255,0);    /* Raw IP packets.  */
+   push_program(end_program());
+   f_call_function(1);
+   simple_add_constant("IPPROTO",Pike_sp-1,0);
+   pop_stack();
+}
+
+void exit_stdio_udp(void)
+{
+}
diff --git a/src/modules/_Stdio/efuns.c b/src/modules/_Stdio/efuns.c
index 7a08aa82abe385a9ba73f5f847fad0990b7f2ff6..e324978a880426fc99be7ad5989ee277d433f24c 100644
--- a/src/modules/_Stdio/efuns.c
+++ b/src/modules/_Stdio/efuns.c
@@ -1072,7 +1072,7 @@ void f_get_dir(INT32 args)
   get_all_args("get_dir",args,".%T",&str);
 
   if(!str) {
-    push_constant_text(".");
+    push_text(".");
     str = Pike_sp[-1].u.string;
     args++;
   }
@@ -1361,7 +1361,7 @@ void f_get_dir(INT32 args)
 #if defined(__amigaos4__)
     push_empty_string();
 #else
-    push_constant_text(".");
+    push_text(".");
 #endif
     str = Pike_sp[-1].u.string;
     args++;
@@ -1584,7 +1584,7 @@ void f_exece(INT32 args)
 
     NEW_MAPPING_LOOP(en->data) {
       push_string(k->ind.u.string);
-      push_constant_text("=");
+      push_text("=");
       push_string(k->val.u.string);
       f_add(3);
       env[i++]=sp[-1].u.string->str;
@@ -1879,7 +1879,7 @@ void f_strerror(INT32 args)
   if(s)
     push_text(s);
   else {
-    push_constant_text("Error ");
+    push_text("Error ");
     push_int(err);
     f_add(2);
   }
diff --git a/src/modules/_Stdio/file.c b/src/modules/_Stdio/file.c
index 66ef3e794ce152eef985b9d049a29afcc52ea5bb..40378e8618e39953ad8a92a1836a658ad77f6caa 100644
--- a/src/modules/_Stdio/file.c
+++ b/src/modules/_Stdio/file.c
@@ -2465,28 +2465,28 @@ static void file_grantpt( INT32 args )
 {
   pop_n_elems(args);
 #if defined(USE_PT_CHMOD) || defined(USE_CHGPT)
-  push_constant_text("Process.Process");
+  push_text("Process.Process");
   APPLY_MASTER("resolv", 1);
 
 #ifdef USE_PT_CHMOD
   /* pt_chmod wants to get the fd number as the first argument. */
-  push_constant_text(USE_PT_CHMOD);
-  push_constant_text("4");
+  push_text(USE_PT_CHMOD);
+  push_text("4");
   f_aggregate(2);
 
   /* Send the pty as both fd 3 and fd 4. */
-  push_constant_text("fds");
+  push_text("fds");
   ref_push_object(Pike_fp->current_object);
   ref_push_object(Pike_fp->current_object);
   f_aggregate(2);
   f_aggregate_mapping(2);
 #else /* USE_CHGPT */
   /* chgpt on HPUX doesn't like getting any arguments... */
-  push_constant_text(USE_CHGPT);
+  push_text(USE_CHGPT);
   f_aggregate(1);
 
   /* chgpt wants to get the pty on fd 0. */
-  push_constant_text("stdin");
+  push_text("stdin");
   ref_push_object(Pike_fp->current_object);
   f_aggregate_mapping(2);
 #endif /* USE_PT_CHMOD */
@@ -2979,7 +2979,7 @@ static void file_openpt(INT32 args)
 #else
   if(args > 1)
     pop_n_elems(args - 1);
-  push_constant_text(PTY_MASTER_PATHNAME);
+  push_text(PTY_MASTER_PATHNAME);
   stack_swap();
   file_open(2);
 #endif
@@ -6002,7 +6002,7 @@ static void f_gethostip(INT32 args) {
 
 	push_text( ifr->ifr_name );
 
-	push_constant_text( "ips" );
+	push_text( "ips" );
 	memcpy( &addr, &ifr->ifr_addr, sizeof(ifr->ifr_addr) );
 	push_text( inet_ntoa( addr.sin_addr ) );
 	f_aggregate(1);
diff --git a/src/modules/_Stdio/stat.c b/src/modules/_Stdio/stat.c
index d75aaf5a94d387e5a7d1405e7744c36e27352832..1eec2d937510e0dfbf53aa9e1c8571460ddba582 100644
--- a/src/modules/_Stdio/stat.c
+++ b/src/modules/_Stdio/stat.c
@@ -798,7 +798,7 @@ static void stat_cast(INT32 args)
 
 static void stat__sprintf(INT32 args)
 {
-   int n=0, x;
+   int x;
 
    if (args<1)
       SIMPLE_TOO_FEW_ARGS_ERROR("_sprintf",2);
@@ -811,16 +811,11 @@ static void stat__sprintf(INT32 args)
    switch (x)
    {
       case 'O':
-	 n++; push_constant_text("Stat(");
-
-	 n++; _stat_index(STAT_MODE_STRING);
-
-	 n++; push_constant_text(" ");
-
-	 n++; _stat_index(STAT_SIZE);
-	 n++; push_constant_text("b)");
-	 f_add(n);
-	 return;
+        push_text("Stat(%s %db)");
+        _stat_index(STAT_MODE_STRING);
+        _stat_index(STAT_SIZE);
+        f_sprintf(3);
+        return;
       default:
 	 push_int(0);
 	 return;
diff --git a/src/modules/_Stdio/udp.c b/src/modules/_Stdio/udp.c
index 12e34ea30039e86964b16eb4f8b4781673293ab6..d939fb7e7fe6dea7207717d2c4bbeffb3d0cc481 100644
--- a/src/modules/_Stdio/udp.c
+++ b/src/modules/_Stdio/udp.c
@@ -852,10 +852,10 @@ void udp_read(INT32 args)
   /* Now comes the interresting part.
    * make a nice mapping from this stuff..
    */
-  push_constant_text("data");
+  push_text("data");
   push_string( make_shared_binary_string(buffer, res) );
 
-  push_constant_text("ip");
+  push_text("ip");
 #ifdef fd_inet_ntop
   if (!fd_inet_ntop( SOCKADDR_FAMILY(from), SOCKADDR_IN_ADDR(from),
 		     buffer, sizeof(buffer) )) {
diff --git a/src/modules/spider/spider.c b/src/modules/spider/spider.c
index 4f6444ec135584b2a38fdae32222c84e0a2ca39c..19b719198070d8d5514fe43c2ec4fc761ec3c4a0 100644
--- a/src/modules/spider/spider.c
+++ b/src/modules/spider/spider.c
@@ -132,7 +132,7 @@ void f_parse_accessed_database(INT32 args)
   /* Pop all but the first argument */
   pop_n_elems(args-1);
 
-  push_constant_text("\n");
+  push_text("\n");
   f_divide(2);
 
   if (TYPEOF(sp[-1]) != T_ARRAY) {
diff --git a/src/modules/system/nt.c b/src/modules/system/nt.c
index 25acdbfea9371a43c9d4de10adece458b0dd9f2f..e08726d8e5127425a9275f58cb861658096ae7c7 100644
--- a/src/modules/system/nt.c
+++ b/src/modules/system/nt.c
@@ -3023,7 +3023,7 @@ static struct array *encode_acl(PACL acl)
       switch(((ACE_HEADER *)ace)->AceType)
       {
 	case ACCESS_ALLOWED_ACE_TYPE:
-	  push_constant_text("allow");
+	  push_text("allow");
 	  push_int(((ACE_HEADER *)ace)->AceFlags);
 	  push_int( ((ACCESS_ALLOWED_ACE *)ace)->Mask );
 	  SAFE_PUSH_SID( & ((ACCESS_ALLOWED_ACE *)ace)->SidStart );
@@ -3031,7 +3031,7 @@ static struct array *encode_acl(PACL acl)
 	  break;
 
 	case ACCESS_DENIED_ACE_TYPE:
-	  push_constant_text("deny");
+	  push_text("deny");
 	  push_int(((ACE_HEADER *)ace)->AceFlags);
 	  push_int( ((ACCESS_DENIED_ACE *)ace)->Mask );
 	  SAFE_PUSH_SID( & ((ACCESS_DENIED_ACE *)ace)->SidStart );
@@ -3039,7 +3039,7 @@ static struct array *encode_acl(PACL acl)
 	  break;
 
 	case SYSTEM_AUDIT_ACE_TYPE:
-	  push_constant_text("audit");
+	  push_text("audit");
 	  push_int(((ACE_HEADER *)ace)->AceFlags);
 	  push_int( ((SYSTEM_AUDIT_ACE *)ace)->Mask );
 	  SAFE_PUSH_SID( & ((SYSTEM_AUDIT_ACE *)ace)->SidStart );
@@ -3047,7 +3047,7 @@ static struct array *encode_acl(PACL acl)
 	  break;
 
 	default:
-	  push_constant_text("unknown");
+	  push_text("unknown");
 	  f_aggregate(1);
 	  break;
 
@@ -3268,25 +3268,25 @@ static void f_GetNamedSecurityInfo(INT32 args)
 
     if(owner)
     {
-      push_constant_text("owner");
+      push_text("owner");
       SAFE_PUSH_SID(owner);
       tmp++;
     }
     if(group)
     {
-      push_constant_text("group");
+      push_text("group");
       SAFE_PUSH_SID(group);
       tmp++;
     }
     if(sacl)
     {
-      push_constant_text("sacl");
+      push_text("sacl");
       push_array( encode_acl( sacl ));
       tmp++;
     }
     if(dacl)
     {
-      push_constant_text("dacl");
+      push_text("dacl");
       push_array( encode_acl( dacl ));
       tmp++;
     }
diff --git a/src/pike_embed.c b/src/pike_embed.c
index f6dae9aad558ffeab0c029b94d195f7f8fe4bc6f..f8bf94dd03dcd3cea53041b838f1825bc7a4a2cf 100644
--- a/src/pike_embed.c
+++ b/src/pike_embed.c
@@ -573,7 +573,7 @@ static SAVEDS LONG scan_amigaos_environment_func(struct Hook *REG(a0,hook),
   if(msg->sv_GDir[0] == '\0' ||
      !strcmp(msg->sv_GDir, "ENV:")) {
     push_text(msg->sv_Name);
-    push_constant_text("=");
+    push_text("=");
     push_string(make_shared_binary_string(msg->sv_Var, msg->sv_VarLen));
     f_add(3);
   }
diff --git a/src/pike_security.h b/src/pike_security.h
index 557773d160e9276f1992cf6a1028e1ed77974312..3a9e82f2a275e8e45315702a76034ae39e528a29 100644
--- a/src/pike_security.h
+++ b/src/pike_security.h
@@ -89,8 +89,8 @@ struct pike_creds
     if(!CHECK_SECURITY(SECURITY_BIT_CONDITIONAL_IO))			\
       Pike_error(name ": Permission denied.\n");	       		\
 									\
-    push_constant_text(name);						\
-    push_constant_text(access_type);					\
+    push_text(name);						\
+    push_text(access_type);					\
 									\
     for(e=0;e<args;e++) push_svalue(base_sp+e);				\
 									\
diff --git a/src/post_modules/BSON/bson_config.h.in b/src/post_modules/BSON/bson_config.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..fbafce6db5d48bb0655fa070188205e6f1eb43c3
--- /dev/null
+++ b/src/post_modules/BSON/bson_config.h.in
@@ -0,0 +1,55 @@
+/* bson_config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <WinSock2.h> header file. */
+#undef HAVE_WINSOCK2_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
diff --git a/src/post_modules/COM/com.c b/src/post_modules/COM/com.c
index dcb67e33fe68cc1fff22c596d8ba3277e8f8c001..7419e77d0049f3c1200d52fb1fedbd3f4a773341 100644
--- a/src/post_modules/COM/com.c
+++ b/src/post_modules/COM/com.c
@@ -835,7 +835,7 @@ static void f_cval__sprintf(INT32 args)
     Pike_error("Bad argument 2 for Com.cval->_sprintf().\n");
   
   push_svalue(&Pike_sp[1-args]);
-  push_constant_text("precision");
+  push_text("precision");
   f_index(2);
   if (TYPEOF(Pike_sp[-1]) != PIKE_T_INT)
     Pike_error("\"precision\" argument to Com->_sprintf() is not an integer.\n");
@@ -843,7 +843,7 @@ static void f_cval__sprintf(INT32 args)
   precision = (--Pike_sp)->u.integer;
   
   push_svalue(&Pike_sp[1-args]);
-  push_constant_text("width");
+  push_text("width");
   f_index(2);
   if (TYPEOF(Pike_sp[-1]) != PIKE_T_INT)
     Pike_error("\"width\" argument to Com->_sprintf() is not an integer.\n");
@@ -851,7 +851,7 @@ static void f_cval__sprintf(INT32 args)
   width = (--Pike_sp)->u.integer;
 
   push_svalue(&Pike_sp[1-args]);
-  push_constant_text("flag_left");
+  push_text("flag_left");
   f_index(2);
   if (TYPEOF(Pike_sp[-1]) != PIKE_T_INT)
     Pike_error("\"flag_left\" argument to Com->_sprintf() is not an integer.\n");
@@ -1891,7 +1891,7 @@ static void f_com__sprintf(INT32 args)
   switch (Pike_sp[-args].u.integer)
   {
     case 'O':
-      push_constant_text("Com()");
+      push_text("Com()");
       stack_pop_n_elems_keep_top(args);
       return;
   }
diff --git a/src/post_modules/GSSAPI/gssapi.cmod b/src/post_modules/GSSAPI/gssapi.cmod
index 4d3683d68af6d8942e17f6ba41bae823751a571b..2e419a9385b22301cfdb25c38a9bdfd45444949f 100644
--- a/src/post_modules/GSSAPI/gssapi.cmod
+++ b/src/post_modules/GSSAPI/gssapi.cmod
@@ -842,7 +842,7 @@ static void gssapi_err_create (INT32 args)
       if(TYPEOF(Pike_sp[3-args]) != T_STRING)
 	SIMPLE_ARG_TYPE_ERROR ("create",4,"void|string");
       ref_push_string (Pike_sp[3-args].u.string);
-      push_constant_text (": ");
+      push_text (": ");
       push_string (make_gss_err_message (THIS->major_status, THIS->minor_status,
 					 mech, NULL, NULL));
       f_add (3);
@@ -1063,17 +1063,17 @@ static void missing_err_events (int event)
 static void describe_services_and_push (OM_uint32 services)
 {
   int n = 0;
-  if (services & GSS_C_DELEG_FLAG)	{push_constant_text ("DEL"); n++;}
-  if (services & GSS_C_MUTUAL_FLAG)	{push_constant_text ("MUT"); n++;}
-  if (services & GSS_C_REPLAY_FLAG)	{push_constant_text ("REPL"); n++;}
-  if (services & GSS_C_SEQUENCE_FLAG)	{push_constant_text ("SEQ"); n++;}
-  if (services & GSS_C_CONF_FLAG)	{push_constant_text ("CONF"); n++;}
-  if (services & GSS_C_INTEG_FLAG)	{push_constant_text ("INTEG"); n++;}
-  if (services & GSS_C_ANON_FLAG)	{push_constant_text ("ANON"); n++;}
-  if (services & GSS_C_PROT_READY_FLAG)	{push_constant_text ("READY"); n++;}
-  if (services & GSS_C_TRANS_FLAG)	{push_constant_text ("TRANS"); n++;}
+  if (services & GSS_C_DELEG_FLAG)	{push_text ("DEL"); n++;}
+  if (services & GSS_C_MUTUAL_FLAG)	{push_text ("MUT"); n++;}
+  if (services & GSS_C_REPLAY_FLAG)	{push_text ("REPL"); n++;}
+  if (services & GSS_C_SEQUENCE_FLAG)	{push_text ("SEQ"); n++;}
+  if (services & GSS_C_CONF_FLAG)	{push_text ("CONF"); n++;}
+  if (services & GSS_C_INTEG_FLAG)	{push_text ("INTEG"); n++;}
+  if (services & GSS_C_ANON_FLAG)	{push_text ("ANON"); n++;}
+  if (services & GSS_C_PROT_READY_FLAG)	{push_text ("READY"); n++;}
+  if (services & GSS_C_TRANS_FLAG)	{push_text ("TRANS"); n++;}
   f_aggregate (n);
-  push_constant_text ("|");
+  push_text ("|");
   o_multiply();
 }
 
diff --git a/src/post_modules/GTK1/source/gdkwindow.pre b/src/post_modules/GTK1/source/gdkwindow.pre
index 4429d83fa14ee2d50ec489e22901aa176b3fc0bf..9defa621687ebae7bfbb60d2e4e40f57d02f6ff5 100644
--- a/src/post_modules/GTK1/source/gdkwindow.pre
+++ b/src/post_modules/GTK1/source/gdkwindow.pre
@@ -349,11 +349,11 @@ mapping(string:int) get_geometry()
 {
   gint x, y, w, h, d;
   gdk_window_get_geometry( (GdkWindow *)THIS->obj, &x, &y, &w, &h, &d );
-  push_constant_text( "x" ); push_int(x);
-  push_constant_text( "y" ); push_int(y);
-  push_constant_text( "width" );  push_int(w);
-  push_constant_text( "height" );  push_int(h);
-  push_constant_text( "depth" ); push_int(d);
+  push_text( "x" ); push_int(x);
+  push_text( "y" ); push_int(y);
+  push_text( "width" );  push_int(w);
+  push_text( "height" );  push_int(h);
+  push_text( "depth" ); push_int(d);
   f_aggregate_mapping( 10 );
 }
 
@@ -376,12 +376,12 @@ mapping get_pointer( int deviceid )
 				  (guint32)deviceid, 
 				  &x,&y,&pressure,&xtilt,&ytilt,&modifiers);
     my_pop_n_elems(args);
-    push_constant_text("x"); push_float(x);
-    push_constant_text("y"); push_float(y);
-    push_constant_text("pressure"); push_float(pressure);
-    push_constant_text("xtilt"); push_float(xtilt);
-    push_constant_text("ytilt"); push_float(ytilt);
-    push_constant_text("modifiers"); push_int((int)modifiers);
+    push_text("x"); push_float(x);
+    push_text("y"); push_float(y);
+    push_text("pressure"); push_float(pressure);
+    push_text("xtilt"); push_float(xtilt);
+    push_text("ytilt"); push_float(ytilt);
+    push_text("modifiers"); push_int((int)modifiers);
     f_aggregate_mapping(12);
 }
 
diff --git a/src/post_modules/GTK1/source/gtkbox.pre b/src/post_modules/GTK1/source/gtkbox.pre
index f26993af3ca821be6d063df12bebe3f9c11cbc08..abee5c73fd03cc390a6d80d743cfbc51dfc868ce 100644
--- a/src/post_modules/GTK1/source/gtkbox.pre
+++ b/src/post_modules/GTK1/source/gtkbox.pre
@@ -46,13 +46,13 @@ mapping(string:int) query_child_packing(GTK1.Widget child)
                                GTK_WIDGET( get_gtkobject( o ) ),
                                &ex, &fi, &pa, &ty );
   my_pop_n_elems( args );
-  push_constant_text( "expand" );
+  push_text( "expand" );
   push_int( ex );
-  push_constant_text( "fill" );
+  push_text( "fill" );
   push_int( fi );
-  push_constant_text( "padding" );
+  push_text( "padding" );
   push_int( pa );
-  push_constant_text( "type" );
+  push_text( "type" );
   push_int( ty );
   f_aggregate_mapping( 8 );
 }
diff --git a/src/post_modules/GTK1/source/gtkbuttonbox.pre b/src/post_modules/GTK1/source/gtkbuttonbox.pre
index 062f14bb2644625b19ca3777129907f53a18713d..d6e28808ed86282216ec08f77ba044b8a0d09107 100644
--- a/src/post_modules/GTK1/source/gtkbuttonbox.pre
+++ b/src/post_modules/GTK1/source/gtkbuttonbox.pre
@@ -25,8 +25,8 @@ mapping get_child_size()
   int x, y;
   my_pop_n_elems(args);
   gtk_button_box_get_child_size( GTK_BUTTON_BOX( THIS->obj ), &x, &y );
-  push_constant_text( "x" );  push_int( x );
-  push_constant_text( "y" );  push_int( y );
+  push_text( "x" );  push_int( x );
+  push_text( "y" );  push_int( y );
   f_aggregate_mapping( 4 );
 }
 mapping get_child_ipadding()
@@ -35,8 +35,8 @@ mapping get_child_ipadding()
   int x, y;
   my_pop_n_elems(args);
   gtk_button_box_get_child_ipadding( GTK_BUTTON_BOX( THIS->obj ), &x, &y );
-  push_constant_text( "x" );  push_int( x );
-  push_constant_text( "y" );  push_int( y );
+  push_text( "x" );  push_int( x );
+  push_text( "y" );  push_int( y );
   f_aggregate_mapping( 4 );
 }
 
diff --git a/src/post_modules/GTK2/source/gtkdatabox.pre b/src/post_modules/GTK2/source/gtkdatabox.pre
index b552a5168518ce82514877011d27f60c0e8cf99b..9d05930dd19a224861316ec6a37f04d748cf56fa 100644
--- a/src/post_modules/GTK2/source/gtkdatabox.pre
+++ b/src/post_modules/GTK2/source/gtkdatabox.pre
@@ -164,8 +164,8 @@ static GtkDataboxValue get_value(int offset, int args) {
 }
 
 static void push_value(GtkDataboxValue v) {
-  push_constant_text("x"); push_float(v.x);
-  push_constant_text("y"); push_float(v.y);
+  push_text("x"); push_float(v.x);
+  push_text("y"); push_float(v.y);
   f_aggregate_mapping(4);
 }
 %}
diff --git a/src/post_modules/Nettle/cipher.cmod b/src/post_modules/Nettle/cipher.cmod
index ad111e115c31ae3be5d5f56e55ab9684f0970e78..9e0bd2ce9581ed4516a43da2b23870634c86d6ee 100644
--- a/src/post_modules/Nettle/cipher.cmod
+++ b/src/post_modules/Nettle/cipher.cmod
@@ -1234,9 +1234,9 @@ PIKECLASS BlockCipher
       PIKEFUN string(0..255) name()
 	optflags OPT_TRY_OPTIMIZE;
       {
-	push_constant_text("CBC(");
+	push_text("CBC(");
 	apply(THIS->object, "name", 0);
-	push_constant_text(")");
+	push_text(")");
 	f_add(3);
       }
 
@@ -1458,7 +1458,7 @@ PIKECLASS BlockCipher
       optflags OPT_TRY_OPTIMIZE;
     {
       apply_external(1, f_Nettle_Cipher_name_fun_num, args);
-      push_constant_text(".CTR");
+      push_text(".CTR");
       f_add(2);
     }
 
@@ -1633,9 +1633,9 @@ PIKECLASS BlockCipher
       PIKEFUN string(0..255) name()
 	optflags OPT_TRY_OPTIMIZE;
       {
-	push_constant_text("CTR(");
+	push_text("CTR(");
 	apply(THIS->object, "name", 0);
-	push_constant_text(")");
+	push_text(")");
 	f_add(3);
       }
 
@@ -1918,7 +1918,7 @@ PIKECLASS BlockCipher16
       optflags OPT_TRY_OPTIMIZE;
     {
       apply_external(1, f_Nettle_Cipher_name_fun_num, args);
-      push_constant_text(".CCM");
+      push_text(".CCM");
       f_add(2);
     }
 
@@ -2428,7 +2428,7 @@ PIKECLASS BlockCipher16
     PIKEFUN string(7bit) name()
     {
       apply_external(1, f_Nettle_Cipher_name_fun_num, args);
-      push_constant_text(".CCM8");
+      push_text(".CCM8");
       f_add(2);
     }
 
@@ -2488,7 +2488,7 @@ PIKECLASS BlockCipher16
       optflags OPT_TRY_OPTIMIZE;
     {
       apply_external(1, f_Nettle_Cipher_name_fun_num, args);
-      push_constant_text(".GCM");
+      push_text(".GCM");
       f_add(2);
     }
 
@@ -2665,7 +2665,7 @@ PIKECLASS BlockCipher16
 	optflags OPT_TRY_OPTIMIZE;
       {
 	apply(THIS->object, "name", 0);
-	push_constant_text(".GCM");
+	push_text(".GCM");
 	f_add(2);
       }
 
diff --git a/src/post_modules/SQLite/sqlite.cmod b/src/post_modules/SQLite/sqlite.cmod
index ca249dab8a0d52b848c128f299107d8f933594d0..551dd0574d53e2e78d601d20d34c0f51d04f4fb2 100644
--- a/src/post_modules/SQLite/sqlite.cmod
+++ b/src/post_modules/SQLite/sqlite.cmod
@@ -234,7 +234,7 @@ PIKECLASS ResObj
         push_constant_text("text");
         break;
       default:
-        push_constant_text("unknown");
+        push_text("unknown");
         break;
       }
       f_aggregate_mapping(4);
@@ -522,7 +522,7 @@ PIKECLASS ResObj
   PIKEFUN string server_info()
     optflags OPT_TRY_OPTIMIZE;
   {
-    push_constant_text(sqlite3_libversion());
+    push_text(sqlite3_libversion());
   }
 
   /*! @decl int insert_id()
diff --git a/src/post_modules/ZXID/zxid.cmod b/src/post_modules/ZXID/zxid.cmod
index 4fd1000429dc41fdcb1d0bbf33f34fa3de10da9d..523edaeebbc97adf28c1c7c8ce21b5cc80164a70 100644
--- a/src/post_modules/ZXID/zxid.cmod
+++ b/src/post_modules/ZXID/zxid.cmod
@@ -572,16 +572,16 @@ PIKECLASS Configuration {
       int attrs = 0;
       /* if (!idp->ed->IDPSSODescriptor) continue; */
       push_text(idp->eid);
-      push_constant_text("eid");
+      push_text("eid");
       push_text(idp->eid);
       attrs++;
       if (idp->dpy_name) {
-	push_constant_text("name");
+	push_text("name");
 	push_text(idp->dpy_name);
 	attrs++;
       }
       if (idp->sha1_name) {
-	push_constant_text("sha1_name");
+	push_text("sha1_name");
 	push_text(idp->sha1_name);
 	attrs++;
       }
diff --git a/src/post_modules/_Regexp_PCRE/pcre_glue.cmod b/src/post_modules/_Regexp_PCRE/pcre_glue.cmod
index 33c765f12a9cb16555a499c880a136495ebd0067..f4de8b2849e985c3d01da82cc1d5a8b986cfaff4 100644
--- a/src/post_modules/_Regexp_PCRE/pcre_glue.cmod
+++ b/src/post_modules/_Regexp_PCRE/pcre_glue.cmod
@@ -159,7 +159,7 @@ PIKECLASS _pcre
 	    return;
 
 	 case 'O':
-	    push_constant_text ("%t(%O)");
+	    push_text ("%t(%O)");
 	    ref_push_object(Pike_fp->current_object);
 	    if (THIS->pattern)
 	       ref_push_string(THIS->pattern);
diff --git a/src/signal_handler.c b/src/signal_handler.c
index aa27b3d0b4c82217fba00805852d9422b38956c0..3e1111d3478d1f5b9b86901a98f057f0e41b0f46 100644
--- a/src/signal_handler.c
+++ b/src/signal_handler.c
@@ -2982,7 +2982,7 @@ void f_create_process(INT32 args)
 	      {
 		check_stack(3);
 		ref_push_string(ITEM(i)[e].u.string);
-		push_constant_text("=");
+		push_text("=");
 		ref_push_string(ITEM(v)[e].u.string);
 		f_add(3);
 		ptr++;
@@ -3384,7 +3384,7 @@ void f_create_process(INT32 args)
 	    {
 	      check_stack(3);
 	      ref_push_string(ITEM(i)[e].u.string);
-	      push_constant_text("=");
+	      push_text("=");
 	      ref_push_string(ITEM(v)[e].u.string);
 	      f_add(3);
 	      storage.env[ptr++]=Pike_sp[-1].u.string->str;
diff --git a/src/threads.c b/src/threads.c
index f9f82fd618b47c6573b41ec1b32eafe1fbb78f44..72ccea5662c4960de54af36ac2b920e086da2ec0 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -2685,9 +2685,9 @@ void f_thread_id__sprintf (INT32 args)
     push_undefined();
     return;
   }
-  push_constant_text ("Thread.Thread(");
+  push_text ("Thread.Thread(");
   push_int64(PTR_TO_INT(THREAD_T_TO_PTR(THIS_THREAD->id)));
-  push_constant_text (")");
+  push_text (")");
   f_add (3);
 }
 
diff --git a/src/version.c b/src/version.c
index 90ef959e98f1fea1dd2c12551da3539cf0489ed1..e63d2e712ae24c1c1055e4470b3b066e2471ba61 100644
--- a/src/version.c
+++ b/src/version.c
@@ -25,7 +25,7 @@
 PMOD_EXPORT void f_version(INT32 args)
 {
   pop_n_elems(args);
-  push_constant_text ("Pike v"
+  push_text ("Pike v"
 		      DEFINETOSTR (PIKE_MAJOR_VERSION)
 		      "."
 		      DEFINETOSTR (PIKE_MINOR_VERSION)