From e34dcf4a28218b19e17aa2d7a7b59251370c8803 Mon Sep 17 00:00:00 2001
From: Martin Nilsson <mani@lysator.liu.se>
Date: Sat, 22 May 2004 14:14:48 +0200
Subject: [PATCH] Improved f_cpp, I think

Rev: src/cpp.c:1.136
---
 src/cpp.c | 179 ++++++++++++++++++++++++++----------------------------
 1 file changed, 86 insertions(+), 93 deletions(-)

diff --git a/src/cpp.c b/src/cpp.c
index 3bc023ed87..7396ebddaf 100644
--- a/src/cpp.c
+++ b/src/cpp.c
@@ -2,7 +2,7 @@
 || 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.
-|| $Id: cpp.c,v 1.135 2004/04/15 22:07:48 mast Exp $
+|| $Id: cpp.c,v 1.136 2004/05/22 12:14:48 nilsson Exp $
 */
 
 #include "global.h"
@@ -110,6 +110,7 @@ struct cpp
   struct object *compat_handler;
   int compat_major;
   int compat_minor;
+  struct pike_string *data;
 };
 
 struct define *defined_macro =0;
@@ -1699,96 +1700,111 @@ static int do_safe_index_call(struct cpp *this, struct pike_string *s)
  *! @seealso
  *!   @[compile()]
  */
+
+/* Doesn't free string_builder buf! */
+static void free_cpp(struct cpp *this)
+{
+  if(this->defines)
+    free_hashtable(this->defines, free_one_define);
+
+  if(this->current_file)
+    free_string(this->current_file);
+
+  if(this->handler) {
+    free_object(this->handler);
+    this->handler = 0;
+  }
+
+  if(this->compat_handler) {
+    free_object(this->compat_handler);
+    this->compat_handler=0;
+  }
+
+  if(this->data)
+    free_string(this->data);
+}
+
 void f_cpp(INT32 args)
 {
-  struct pike_string *data;
-  struct mapping *predefs = NULL;
-  struct svalue *save_sp = sp - args;
   struct cpp this;
+  struct svalue *save_sp = sp - args;
+  struct mapping *predefs = NULL;
+
+  struct pike_string *data;
+
+  struct pike_string *current_file = 0;
+
+  struct svalue *charset_sv = 0;
   int auto_convert = 0;
   struct pike_string *charset = NULL;
 
+  struct object *handler = 0;
+
+  int compat_major, compat_minor;
+
+  ONERROR err;
 #ifdef PIKE_DEBUG
   ONERROR tmp;
 #endif /* PIKE_DEBUG */
 
-  if(args<1)
-    SIMPLE_TOO_FEW_ARGS_ERROR("cpp", 1);
+  get_all_args("cpp", args, "%t.%T%*%O%i%i", &data, &current_file,
+	       &charset_sv, &handler, &compat_major, &compat_minor);
 
-  if(sp[-args].type != T_STRING)
-    SIMPLE_BAD_ARG_ERROR("cpp", 1, "string");
-
-  data = sp[-args].u.string;
+  this.current_line=1;
+  this.compile_errors=0;
+  this.defines=0;
 
+  this.data = data;
   add_ref(data);
 
-  this.handler = NULL;
-  this.compat_handler = NULL;
+  if(current_file)
+    add_ref(current_file);
+  else
+    current_file = make_shared_string("-");
+  this.current_file = current_file;
 
-  if(args>1)
-  {
-    if(args > 5)
-    {
-      if(sp[4-args].type != T_INT)
-	SIMPLE_BAD_ARG_ERROR("cpp", 5, "int");
-      if(sp[5-args].type != T_INT)
-	SIMPLE_BAD_ARG_ERROR("cpp", 6, "int");
-    }
-    if(sp[1-args].type != T_STRING) {
-      free_string(data);
-      SIMPLE_BAD_ARG_ERROR("cpp", 2, "string");
-    }
-    copy_shared_string(this.current_file, sp[1-args].u.string);
-
-    if (args > 2) {
-      if (sp[2-args].type == T_STRING) {
-	charset = sp[2 - args].u.string;
-	push_string(data);
-	ref_push_string(charset);
-	if (!safe_apply_handler ("decode_charset", this.handler, this.compat_handler,
-				 2, BIT_STRING)) {
-	  free_string(this.current_file);
-	  cpp_handle_exception (&this, "Error decoding with charset '%s'",
-				charset->str);
-	  Pike_error("Unknown charset.\n");
-	}
-	data = sp[-1].u.string;
-	sp--;
-	dmalloc_touch_svalue(sp);
-      } else if (sp[2-args].type == T_INT) {
-	auto_convert = sp[2-args].u.integer;
-      } else {
-	free_string(data);
-	SIMPLE_BAD_ARG_ERROR("cpp", 3, "string|int");
-      }
-      if (args > 3) {
-	if (sp[3-args].type == T_OBJECT) {
-	  if ((this.handler = sp[3-args].u.object)) {
-	    add_ref(this.handler);
-	  }
-	} else if (sp[3-args].type != T_INT) {
-	  free_string(data);
-	  free_string(this.current_file);
-	  SIMPLE_BAD_ARG_ERROR("cpp", 4, "object");
-	}
+  this.compat_major=PIKE_MAJOR_VERSION;
+  this.compat_minor=PIKE_MINOR_VERSION;
+  this.compat_handler = 0;
+  this.handler = handler;
+  if(handler)
+    add_ref(handler);
+
+  /* Don't call free_cpp before all variables are cleared or set. */
+  SET_ONERROR(err, free_cpp, &this);
+
+  if(charset_sv) {
+    if(charset_sv->type == T_STRING) {
+      charset = charset_sv->u.string;
+      push_string(data);
+      ref_push_string(charset);
+      if (!safe_apply_handler ("decode_charset", this.handler,
+			       this.compat_handler, 2, BIT_STRING)) {
+	cpp_handle_exception (&this, "Error decoding with charset '%s'",
+			      charset->str);
+	Pike_error("Unknown charset.\n");
       }
+      free(data);
+      this.data = data = sp[-1].u.string;
+      sp--;
+      dmalloc_touch_svalue(sp);
+    }
+    else if(charset_sv->type == T_INT)
+      auto_convert = charset_sv->u.integer;
+    else {
+      SIMPLE_BAD_ARG_ERROR("cpp", 3, "string|int");
     }
-  }else{
-    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);
-  }
+    cpp_change_compat(&this, compat_major, compat_minor);
 
   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);
+    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;
@@ -1824,10 +1840,6 @@ void f_cpp(INT32 args)
       }
       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);
@@ -1842,19 +1854,16 @@ void f_cpp(INT32 args)
     /* Try to determine if we need to recode the string */
     struct pike_string *new_data = recode_string(&this, data);
     free_string(data);
-    data = new_data;
+    this.data = data = new_data;
   }
   if (data->size_shift) {
     /* Get rid of any byte order marks (0xfeff) */
     struct pike_string *new_data = filter_bom(data);
     free_string(data);
-    data = new_data;
+    this.data = data = new_data;
   }
 
   init_string_builder(&this.buf, 0);
-  this.current_line=1;
-  this.compile_errors=0;
-  this.defines=0;
 
   do_magic_define(&this,"__LINE__",insert_current_line);
   do_magic_define(&this,"__FILE__",insert_current_file_as_string);
@@ -1922,24 +1931,8 @@ void f_cpp(INT32 args)
   UNSET_ONERROR(tmp);
 #endif /* PIKE_DEBUG */
 
-  if(this.defines)
-    free_hashtable(this.defines, free_one_define);
-
-  if(this.compat_handler)
-  {
-    free_object(this.compat_handler);
-    this.compat_handler=0;
-  }
-
-  if (this.handler)
-  {
-    free_object(this.handler);
-    this.handler = 0;
-  }
-
-  free_string(this.current_file);
-
-  free_string(data);
+  UNSET_ONERROR(err);
+  free_cpp(&this);
 
   if(this.compile_errors)
   {
-- 
GitLab