diff --git a/src/language.yacc b/src/language.yacc
index 342ec8220e6c26ee298eda93af77913880f9e022..0ccc0def67991c1d3649d06bc82f3b94078d40eb 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -156,7 +156,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.24 1997/02/14 04:45:57 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.25 1997/02/18 05:13:34 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -181,8 +181,6 @@ RCSID("$Id: language.yacc,v 1.24 1997/02/14 04:45:57 hubbe Exp $");
 #define YYDEBUG 1
 #endif
 
-static void push_locals();
-static void pop_locals();
 void free_all_local_names();
 void add_local_name(struct pike_string *,struct pike_string *);
 
@@ -524,8 +522,6 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')'
     int e;
     if($9)
     {
-      union idptr tmp;
-      int args, vargs;
       for(e=0; e<$6; e++)
       {
 	if(!local_variables->variable[e].name ||
@@ -534,25 +530,8 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')'
 	  my_yyerror("Missing name for argument %d",e);
 	}
       }
-      
-      tmp.offset=PC;
-      args=count_arguments($<string>8);
-      if(args < 0) 
-      {
-	args=~args;
-	vargs=IDENTIFIER_VARARGS;
-      }else{
-	vargs=0;
-      }
-      ins_byte(local_variables->max_number_of_locals, A_PROGRAM);
-      ins_byte(args, A_PROGRAM);
-      dooptcode($4, $9, $6);
-      
-      define_function($4,
-		      $<string>8,
-		      $1,
-		      IDENTIFIER_PIKE_FUNCTION | vargs,
-		      &tmp);
+
+      dooptcode($4, $9, $<string>8, $1);
     }
     if(local_variables->current_return_type)
     {
@@ -858,8 +837,7 @@ lambda: F_LAMBDA
   {
     struct pike_string *type;
     char buf[40];
-    int f,e,args,vargs;
-    union idptr func;
+    int f,e;
     struct pike_string *name;
     
     setup_fake_program();
@@ -884,28 +862,15 @@ lambda: F_LAMBDA
     push_type(T_FUNCTION);
     
     type=pop_type();
-    func.offset=PC;
-    
-    args=count_arguments(type);
-    if(args < 0) 
-    {
-      args=~args;
-      vargs=IDENTIFIER_VARARGS;
-    }else{
-      vargs=0;
-    }
-    ins_byte(local_variables->max_number_of_locals, A_PROGRAM);
-    ins_byte(args, A_PROGRAM);
     
     sprintf(buf,"__lambda_%ld",
 	    (long)fake_program.num_identifier_references);
     name=make_shared_string(buf);
-    dooptcode(name,mknode(F_ARG_LIST,$6,mknode(F_RETURN,mkintnode(0),0)),$4);
-    f=define_function(name,
-		      type,
-		      0,
-		      IDENTIFIER_PIKE_FUNCTION | vargs,
-		      &func);
+
+    f=dooptcode(name,
+	      mknode(F_ARG_LIST,$6,mknode(F_RETURN,mkintnode(0),0)),
+	      type,
+	      0);
     free_string(name);
     free_string(type);
     pop_locals();
@@ -1413,29 +1378,3 @@ void free_all_local_names()
   local_variables->max_number_of_locals = 0;
 }
 
-static void push_locals()
-{
-  struct locals *l;
-  l=ALLOC_STRUCT(locals);
-  l->current_type=0;
-  l->current_return_type=0;
-  l->next=local_variables;
-  l->current_number_of_locals=0;
-  l->max_number_of_locals=0;
-  local_variables=l;
-}
-
-static void pop_locals()
-{
-  struct locals *l;
-  free_all_local_names();
-  l=local_variables->next;
-  if(local_variables->current_type)
-    free_string(local_variables->current_type);
-  if(local_variables->current_return_type)
-    free_string(local_variables->current_return_type);
-  free((char *)local_variables);
-
-  local_variables=l;
-  /* insert check if ( local->next == parent locals ) here */
-}
diff --git a/src/las.c b/src/las.c
index 6ac6d40c9ff086aa32256d31036d437d8bbc9c1a..5e66d7fd3d5d7755416b6aaef7bdd71539ef590e 100644
--- a/src/las.c
+++ b/src/las.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: las.c,v 1.20 1997/02/11 07:10:54 hubbe Exp $");
+RCSID("$Id: las.c,v 1.21 1997/02/18 05:13:35 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -1882,14 +1882,123 @@ static node *eval(node *n)
 
 INT32 last_function_opt_info;
 
-void dooptcode(struct pike_string *name,node *n, int args)
+static int stupid_args(node *n, int expected,int vargs)
 {
+  if(!n) return expected;
+  switch(n->token)
+  {
+  case F_PUSH_ARRAY:
+    if(!vargs) return -1;
+
+    if(stupid_args(CAR(n), expected,vargs) == expected+1)
+      return 65535;
+    return -1;
+
+  case F_ARG_LIST:
+    expected=stupid_args(CAR(n), expected,vargs);
+    if(expected==-1) return -1;
+    return stupid_args(CDR(n), expected,vargs);
+  case F_LOCAL:
+    return n->u.number==expected ? expected + 1 : -1;
+  default:
+    return -1;
+  }
+}
+
+static is_null_branch(node *n)
+{
+  if(!n) return 1;
+  if(n->token==F_CAST && n->type==void_type_string)
+    return is_null_branch(CAR(n));
+  if(n->token==F_ARG_LIST)
+    return is_null_branch(CAR(n)) && is_null_branch(CDR(n));
+  return 0;
+}
+
+static struct svalue *is_stupid_func(node *n,
+				     int args,
+				     int vargs)
+{
+  node *a,*b;
+  int tmp;
+  while(1)
+  {
+    if(!n) return 0;
+
+    if(n->token == F_ARG_LIST)
+    {
+      if(is_null_branch(CAR(n)))
+	n=CDR(n);
+      else
+	n=CAR(n);
+      continue;
+    }
+
+    if(n->token == F_CAST && n->type==void_type_string)
+    {
+      n=CAR(n);
+      continue;
+    }
+    break;
+  }
+
+  if(n->token != F_RETURN) return 0;
+  n=CAR(n);
+
+  if(n->token != F_APPLY) return 0;
+
+  tmp=stupid_args(CDR(n),0,vargs);
+  if(!(vargs?tmp==65535:tmp==args)) return 0;
+
+  n=CAR(n);
+  if(n->token != F_CONSTANT) return 0;
+  return &n->u.sval;
+}
+
+int dooptcode(struct pike_string *name,
+	      node *n,
+	      struct pike_string *type,
+	      int modifiers)
+{
+  union idptr tmp;
+  int args, vargs, ret;
+  struct svalue *foo;
+
 #ifdef DEBUG
   if(a_flag > 1)
     fprintf(stderr,"Doing function '%s' at %x\n",name->str,PC);
 #endif
   last_function_opt_info=OPT_SIDE_EFFECT;
+
+  args=count_arguments(type);
+  if(args < 0) 
+  {
+    args=~args;
+    vargs=IDENTIFIER_VARARGS;
+  }else{
+    vargs=0;
+  }
   n=mknode(F_ARG_LIST,n,0);
+
+  if(foo=is_stupid_func(n, args, vargs))
+  {
+    if(foo->type == T_FUNCTION && foo->subtype==FUNCTION_BUILTIN)
+    {
+      tmp.c_fun=foo->u.efun->function;
+      ret=define_function(name,
+			  type,
+			  modifiers,
+			  IDENTIFIER_C_FUNCTION | vargs,
+			  &tmp);
+      free_node(n);
+      return ret;
+    }
+  }
+  
+  tmp.offset=PC;
+  ins_byte(local_variables->max_number_of_locals, A_PROGRAM);
+  ins_byte(args, A_PROGRAM);
+  
 #ifdef DEBUG
   if(a_flag > 2)
   {
@@ -1900,9 +2009,16 @@ void dooptcode(struct pike_string *name,node *n, int args)
   if(!num_parse_error)
   {
     do_code_block(n);
-    last_function_opt_info = n->tree_info;
   }
+  
+  ret=define_function(name,
+		      type,
+		      modifiers,
+		      IDENTIFIER_PIKE_FUNCTION | vargs,
+		      &tmp);
+
   free_node(n);
+  return ret;
 }
 
 INT32 get_opt_info() { return last_function_opt_info; }
diff --git a/src/las.h b/src/las.h
index c3924ec0dcde302ba9bae975522099738d3f1be9..078670474766d8fde6c66d094b511c50d5441205 100644
--- a/src/las.h
+++ b/src/las.h
@@ -110,7 +110,10 @@ struct used_vars;
 void fix_type_field(node *n);
 struct timer_oflo;
 int eval_low(node *n);
-void dooptcode(struct pike_string *name,node *n, int args);
+int dooptcode(struct pike_string *name,
+	      node *n,
+	      struct pike_string *type,
+	      int modifiers);
 INT32 get_opt_info();
 /* Prototypes end here */
 
diff --git a/src/program.c b/src/program.c
index a65b25795c67416067b01b0e720c6d511f8bba2c..aa7972a8f89979ad28fb75f2e9f1a718a2a57bf2 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: program.c,v 1.20 1997/02/11 07:20:15 hubbe Exp $");
+RCSID("$Id: program.c,v 1.21 1997/02/18 05:13:35 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -547,16 +547,14 @@ struct program *end_program()
   {
     union idptr tmp;
     struct pike_string *s;
+    push_locals();
     s=make_shared_string("__INIT");
-    tmp.offset=PC;
-    ins_byte(0, A_PROGRAM); /* num locals */
-    ins_byte(0, A_PROGRAM); /* num args */
-    dooptcode(s,mknode(F_ARG_LIST,init_node,mknode(F_RETURN,mkintnode(0),0)),0);
-    define_function(s,
-		    function_type_string,
-		    0,  /* ID_STATIC, */
-		    IDENTIFIER_PIKE_FUNCTION,
-		    & tmp);
+    dooptcode(s,
+	      mknode(F_ARG_LIST,
+		     init_node,mknode(F_RETURN,mkintnode(0),0)),
+	      function_type_string,
+	      0);
+    pop_locals();
     free_string(s);
     init_node=0;
   }
@@ -1664,3 +1662,29 @@ void count_memory_in_programs(INT32 *num_, INT32 *size_)
   *num_=num;
   *size_=size;
 }
+void push_locals()
+{
+  struct locals *l;
+  l=ALLOC_STRUCT(locals);
+  l->current_type=0;
+  l->current_return_type=0;
+  l->next=local_variables;
+  l->current_number_of_locals=0;
+  l->max_number_of_locals=0;
+  local_variables=l;
+}
+
+void pop_locals()
+{
+  struct locals *l;
+  free_all_local_names();
+  l=local_variables->next;
+  if(local_variables->current_type)
+    free_string(local_variables->current_type);
+  if(local_variables->current_return_type)
+    free_string(local_variables->current_return_type);
+  free((char *)local_variables);
+
+  local_variables=l;
+  /* insert check if ( local->next == parent locals ) here */
+}
diff --git a/src/program.h b/src/program.h
index 0a3ad12dc1f476ecc01c3d655605597efce5a668..326913e0413961ee39096aeac6a49af650f7ba43 100644
--- a/src/program.h
+++ b/src/program.h
@@ -249,6 +249,8 @@ void gc_check_all_programs();
 void gc_mark_all_programs();
 void gc_free_all_unreferenced_programs();
 void count_memory_in_programs(INT32 *num_, INT32 *size_);
+void push_locals();
+void pop_locals();
 /* Prototypes end here */