diff --git a/src/cpp.c b/src/cpp.c
index 8017fce0918be7718cd29eed0b192173bd0113be..d991bc544f01eb579565e06bab9ee4368e31c179 100644
--- a/src/cpp.c
+++ b/src/cpp.c
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: cpp.c,v 1.96 2001/12/16 02:49:38 mast Exp $
+ * $Id: cpp.c,v 1.97 2001/12/19 23:51:19 mast Exp $
  */
 #include "global.h"
 #include "stralloc.h"
@@ -60,7 +60,9 @@ struct pike_predef_s
   char *value;
 };
 
-static struct pike_predef_s *pike_predefs=0;
+static int use_initial_predefs;
+static struct pike_predef_s *first_predef = NULL, *last_predef = NULL;
+
 struct define_part
 {
   int argument;
@@ -211,6 +213,22 @@ void cpp_change_compat(struct cpp *this, int major, int minor)
   this->compat_minor=minor;
 }
 
+static struct mapping *initial_predefs_mapping()
+{
+  struct pike_predef_s *def;
+  struct mapping *map = allocate_mapping (0);
+#ifdef PIKE_DEBUG
+  if (!use_initial_predefs) fatal ("Initial predefs has been taken over.\n");
+#endif
+  for (def = first_predef; def; def = def->next) {
+    push_string (make_shared_string (def->name));
+    push_string (make_shared_string (def->value));
+    mapping_insert (map, sp - 2, sp - 1);
+    pop_n_elems (2);
+  }
+  return map;
+}
+
 /* devours one reference to 'name'! */
 static struct define *alloc_empty_define(struct pike_string *name,
 					 ptrdiff_t parts)
@@ -263,6 +281,17 @@ static void do_magic_define(struct cpp *this,
   this->defines=hash_insert(this->defines, & def->link);
 }
 
+static void add_define(struct cpp *this,
+		       struct pike_string *name,
+		       struct pike_string *what)
+{
+  struct define* def;
+  add_ref (name);
+  def=alloc_empty_define(name,0);
+  add_ref (def->first = what);
+  this->defines=hash_insert(this->defines, & def->link);
+}
+
 static void simple_add_define(struct cpp *this,
 			    char *name,
 			    char *what)
@@ -1464,7 +1493,7 @@ static int do_safe_index_call(struct pike_string *s)
 void f_cpp(INT32 args)
 {
   struct pike_string *data;
-  struct pike_predef_s *tmpf;
+  struct mapping *predefs = NULL;
   struct svalue *save_sp = sp - args;
   struct cpp this;
   int auto_convert = 0;
@@ -1537,6 +1566,67 @@ void f_cpp(INT32 args)
     this.current_file=make_shared_string("-");
   }
 
+  this.compat_major=PIKE_MAJOR_VERSION;
+  this.compat_minor=PIKE_MINOR_VERSION;
+  if(args > 5)
+  {
+    cpp_change_compat(&this, sp[4-args].u.integer, sp[5-args].u.integer);
+  }
+
+  if (use_initial_predefs)
+    /* Typically compiling the master here. */
+    predefs = initial_predefs_mapping();
+  else {
+    low_unsafe_apply_handler ("get_predefines", this.handler, this.compat_handler, 0);
+    if (!UNSAFE_IS_ZERO (sp - 1)) {
+      struct keypair *k;
+      int e, sprintf_args = 0;
+      if (sp[-1].type != 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_svalue (sp - 3);
+	sprintf_args = 2;
+      }
+      else {
+	predefs = copy_mapping (sp[-1].u.mapping);
+	NEW_MAPPING_LOOP (predefs->data) {
+	  if (k->ind.type != 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_svalue (&k->ind);
+	    sprintf_args = 2;
+	    free_mapping (predefs);
+	    predefs = NULL;
+	    goto predef_map_error;
+	  }
+	  if (k->val.type != T_STRING &&
+	      (k->val.type != T_INT || k->val.u.integer)) {
+	    push_constant_text ("Expected zero or string value for predefine\n");
+	    push_constant_text ("Expected zero or string value for predefine %O\n");
+	    push_svalue (&k->ind);
+	    sprintf_args = 2;
+	    free_mapping (predefs);
+	    predefs = NULL;
+	    goto predef_map_error;
+	  }
+	}
+      }
+      if (!predefs) {
+      predef_map_error:
+	free_string (data);
+	free_string (this.current_file);
+	if (this.handler) free_object (this.handler);
+	if (this.compat_handler) free_object (this.compat_handler);
+	f_sprintf (sprintf_args);
+	if (!sp[-1].u.string->size_shift)
+	  Pike_error ("%s", sp[-1].u.string->str);
+	else
+	  Pike_error ("%s", sp[-2].u.string->str);
+      }
+    }
+    pop_stack();
+  }
+
   if (auto_convert && (!data->size_shift) && (data->len > 1)) {
     /* Try to determine if we need to recode the string */
     struct pike_string *new_data = recode_string(data);
@@ -1554,8 +1644,6 @@ void f_cpp(INT32 args)
   this.current_line=1;
   this.compile_errors=0;
   this.defines=0;
-  this.compat_major=PIKE_MAJOR_VERSION;
-  this.compat_minor=PIKE_MINOR_VERSION;
 
   do_magic_define(&this,"__LINE__",insert_current_line);
   do_magic_define(&this,"__FILE__",insert_current_file_as_string);
@@ -1597,8 +1685,17 @@ void f_cpp(INT32 args)
 #endif
   }
 
-  for (tmpf=pike_predefs; tmpf; tmpf=tmpf->next)
-    simple_add_define(&this, tmpf->name, tmpf->value);
+  if (predefs) {
+    struct keypair *k;
+    int e;
+    NEW_MAPPING_LOOP (predefs->data) {
+      if (k->val.type == T_STRING)
+	add_define (&this, k->ind.u.string, k->val.u.string);
+      else
+	add_define (&this, k->ind.u.string, empty_string);
+    }
+    free_mapping (predefs);
+  }
 
   string_builder_binary_strcat(&this.buf, "# 1 ", 4);
   PUSH_STRING_SHIFT(this.current_file->str, this.current_file->len,
@@ -1609,11 +1706,6 @@ void f_cpp(INT32 args)
   SET_ONERROR(tmp, fatal_on_error, "Preprocessor exited with longjump!\n");
 #endif /* PIKE_DEBUG */
 
-  if(args > 5)
-  {
-    cpp_change_compat(&this, sp[4-args].u.integer, sp[5-args].u.integer);
-  }
-
 
   low_cpp(&this, data->str, data->len, data->size_shift,
 	  0, auto_convert, charset);
@@ -1652,8 +1744,30 @@ void f_cpp(INT32 args)
   }
 }
 
+void f__take_over_initial_predefines (INT32 args)
+{
+  pop_n_elems (args);
+  if (use_initial_predefs) {
+    struct pike_predef_s *tmp;
+    push_mapping (initial_predefs_mapping());
+    use_initial_predefs = 0;
+
+    while((tmp=first_predef))
+    {
+      free(tmp->name);
+      free(tmp->value);
+      first_predef=tmp->next;
+      free((char *)tmp);
+    }
+    last_predef = 0;
+  }
+  else Pike_error ("Initial predefines already taken over.\n");
+}
+
 void init_cpp()
 {
+  struct svalue s;
+
   defined_macro=alloc_empty_define(make_shared_string("defined"),0);
   defined_macro->magic=check_defined;
   defined_macro->args=1;
@@ -1662,14 +1776,27 @@ void init_cpp()
   constant_macro->magic=check_constant;
   constant_macro->args=1;
 
-  
+  use_initial_predefs = 1;
+
 /* function(string, string|void, int|string|void, object|void, int|void, int|void:string) */
   ADD_EFUN("cpp", f_cpp, tFunc(tStr tOr(tStr,tVoid)
 			       tOr(tInt,tOr(tStr,tVoid))
 			       tOr(tObj,tVoid)
 			       tOr(tInt,tVoid)
 			       tOr(tInt,tVoid)
-			       , tStr), OPT_EXTERNAL_DEPEND);
+			       , tStr),
+	   /* OPT_SIDE_EFFECT since we might instantiate modules etc. */
+	   OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
+
+  /* Somewhat tricky to add a _constant_ function in _static_modules.Builtin. */
+  s.type = T_FUNCTION;
+  s.subtype = FUNCTION_BUILTIN;
+  s.u.efun = make_callable (f__take_over_initial_predefines,
+			    "_take_over_initial_predefines",
+			    "function(void:mapping(string:string))",
+			    OPT_SIDE_EFFECT, NULL, NULL);
+  simple_add_constant ("_take_over_initial_predefines", &s, 0);
+  free_svalue (&s);
 }
 
 
@@ -1692,19 +1819,23 @@ void add_predefine(char *s)
     tmp->value=(char *)xalloc(4);
     MEMCPY(tmp->value," 1 ",4);
   }
-  tmp->next=pike_predefs;
-  pike_predefs=tmp;
+  tmp->next = NULL;
+  if (first_predef) {
+    last_predef->next = tmp;
+    last_predef = tmp;
+  }
+  else first_predef = last_predef = tmp;
 }
 
 void exit_cpp(void)
 {
 #ifdef DO_PIKE_CLEANUP
   struct pike_predef_s *tmp;
-  while((tmp=pike_predefs))
+  while((tmp=first_predef))
   {
     free(tmp->name);
     free(tmp->value);
-    pike_predefs=tmp->next;
+    first_predef=tmp->next;
     free((char *)tmp);
   }
   free_string(defined_macro->link.s);
diff --git a/src/cpp.h b/src/cpp.h
index d6aea83560ae9ca924839c3dc7b2da70be4ad453..5c10859ae214f843b7da5d95565c01f04c675158 100644
--- a/src/cpp.h
+++ b/src/cpp.h
@@ -1,5 +1,5 @@
 /*
- * $Id: cpp.h,v 1.4 1998/03/28 15:00:07 grubba Exp $
+ * $Id: cpp.h,v 1.5 2001/12/19 23:51:19 mast Exp $
  */
 #ifndef CPP_H
 #define CPP_H
@@ -10,7 +10,6 @@ struct hash_entry;
 #endif
 
 /* Prototypes begin here */
-struct pike_predef_s;
 struct define_part;
 struct define_argument;
 struct define;