[patch][rfa] ulog enhancements. C++ issues

Dave Brolley <[email protected]>
Newsgroups gmane.comp.emulators.sid.devel
Organization Red Hat Canada, Ltd
Message-ID <[email protected]>
Hi,

This patch fixes some problems with the ulog support and also abstracts 
it into a separate utility class "logger" so that a component can have 
specialized loggers in addition to the generic ulog support logger.

This patch also addresses some C++ language issues needed for 
compilation with recent releases of gcc.

Dave
include.ChangeLog (text/plain, 1.8 KB)
2003-10-07  Dave Brolley  <[email protected]>

	For Stan Cox  <[email protected]>
	* sidmiscutil.h (logger): New class.
	* sidattrutil.h (fixed_attribute_map_with_logging_component): Convert
	to use logger.

2003-10-07  Dave Brolley  <[email protected]>

	* sidattrutil.h (SID_LOG_PERSISTENT_BUFFER): New macro.
	(SID_LOG_TRANSIENT_MALLOC_BUFFER): New macro.
	(buffer_output): New member of
	fixed_attribute_map_with_logging_component.
	(fixed_attribute_with_logging_component): Add buffer-output attribute.
	Use SID_LOG_PERSISTENT_BUFFER.
	(~fixed_attribute_with_logging_component): Use
	SID_LOG_PERSISTENT_BUFFER.
	(log): Buffer output based on buffer_output. Use
	SID_LOG_TRANSIENT_MALLOC_BUFFER.
	* sidcpuutil.h (get_total_latency): New method of basic_cpu.

2003-10-07  Dave Brolley  <[email protected]>

	* sidattrutil.h (log): Don't use STDCTYPE for vsnprint or vasprintf.

2003-10-07  Dave Brolley  <[email protected]>

	For Stan Cox  <[email protected]>
	* sidmiscutil.h (bijection::find): Add typename.
	* sidbusutil.h (ro_value_control_register): New ValueType typedef.
	(control_register_bus::word_write, control_register_bus::word_read):
	Add typename

2003-10-07  Dave Brolley  <[email protected]>

	* sidattrutil.h (iostream): #include it.
	(log): Use std::cerr and std::endl.
	
2003-10-07  Dave Brolley  <[email protected]>

	* sidattrutil.h (fixed_attribute_map_with_logging_component):
	Initialize saved_messages and saved_levels.
	(~fixed_attribute_map_with_logging_component): Output saved messages.
	Delete buffer if necessary.
	(log): Save message for later if output pin not connected. Otherwise
	output saved messages before the new message. Use vsnprintf or
	vasprintf if possible.
	(check_level): New member of fixed_attribute_map_with_logging_component.
	(output_saved_messages): Ditto.
include.patch.txt (text/plain, 10.6 KB)
Index: sid/include/sidattrutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidattrutil.h,v
retrieving revision 1.5
diff -c -p -r1.5 sidattrutil.h
*** sid/include/sidattrutil.h	20 Jun 2003 21:29:13 -0000	1.5
--- sid/include/sidattrutil.h	21 Oct 2003 20:21:46 -0000
***************
*** 2,8 ****
  // mappings between application objects and their string
  // representations.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2002, 2003 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
--- 2,8 ----
  // mappings between application objects and their string
  // representations.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2003 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
***************
*** 43,48 ****
--- 43,49 ----
  #endif
  
  #include <cassert>
+ #include <sidmiscutil.h>
  
  
  namespace sidutil
*************** make_attribute (const sid::any_int<IntTy
*** 687,693 ****
      operator () (const std::string& s) const
        {
  	// XXX: improve? 
! 	return hash<const char*> () (s.c_str ()); 
        }
    };
  #endif
--- 688,694 ----
      operator () (const std::string& s) const
        {
  	// XXX: improve? 
! 	return std::hash<const char*> () (s.c_str ()); 
        }
    };
  #endif
*************** make_attribute (const sid::any_int<IntTy
*** 699,705 ****
    private:
      // use hash table for this, if available
  #ifdef HAVE_HASHING
!     typedef hash_map<std::string,attribute_coder_base*,hash_string> attribute_map_t;
  #else
      typedef std::map<std::string,attribute_coder_base*> attribute_map_t;
  #endif
--- 700,706 ----
    private:
      // use hash table for this, if available
  #ifdef HAVE_HASHING
!     typedef std::hash_map<std::string,attribute_coder_base*,hash_string> attribute_map_t;
  #else
      typedef std::map<std::string,attribute_coder_base*> attribute_map_t;
  #endif
*************** make_attribute (const sid::any_int<IntTy
*** 1037,1042 ****
--- 1038,1044 ----
  	add_attribute ("ulog-level", &ulog_level, "setting");
  	add_attribute ("ulog-mode",  &ulog_mode,  "setting");
  	add_pin ("ulog-out", & ulog_out_pin);
+ 	ulog_logger =  new logger (& ulog_out_pin, buffer_output, ulog_level, ulog_mode);
  #if SID_LOG_PERSISTENT_BUFFER
  	buffer = new char[buffer_size];
  #endif
*************** make_attribute (const sid::any_int<IntTy
*** 1044,1125 ****
      ~fixed_attribute_map_with_logging_component () throw()
        {
  	// Output any saved messages.
! 	output_saved_messages ();
  #if SID_LOG_PERSISTENT_BUFFER
  	delete [] buffer;
  #endif
        }
  
!     virtual void log (sid::host_int_4 level, const char *fmt, ...)
        {
! 	if (! buffer_output)
! 	  {
! 	    // Output any saved messages first
! 	    output_saved_messages ();
! 
! 	    // Check the logging level and mode.
! 	    if (! check_level (level))
! 	      return;
! 	  }
! 
! 	// Write the message into a buffer.
! 	int length;
! 	for (;;)
! 	  {
! 	    va_list ap;
! 	    va_start (ap, fmt);
! #if HAVE_VSNPRINTF
! 	    length = vsnprintf (buffer, buffer_size, fmt, ap);
! 	    va_end (ap);
! 	    if (length < buffer_size)
! 	      break;
! 	    delete [] buffer;
! 	    buffer_size = length + 256;
! 	    buffer = new char[buffer_size];
! #elif HAVE_VASPRINTF
! 	    length = vasprintf (&buffer, fmt, ap);
! 	    va_end (ap);
! 	    break;
! #else
! 	    length = STDCTYPE(vsprintf) (buffer, fmt, ap);
! 	    va_end (ap);
! 	    if (length >= buffer_size)
! 	      std::cerr << "Error: ulog buffer overflow!!!" << std::endl;
! 	    break;
! #endif
! 	  }
! 
! 	// If the output pin is not connected yet, Save the message for
! 	// later. This happens when the log message is issued from the
! 	// component's constructor.
! 	if (buffer_output)
! 	  {
! 	    saved_messages.push_back (std::string (buffer));
! 	    saved_levels.push_back (level);
! 	  }
! 	else
! 	  {
! 	    // Otherwise, output the new message.
! 	    for (int i = 0; i < length; ++i)
! 	      ulog_out_pin.drive (buffer[i]);
! 	  }
! 
! #if SID_LOG_TRANSIENT_MALLOC_BUFFER
! 	free (buffer);
! #endif
        }
  
  private:
      bool check_level (sid::host_int_4 level)
        {
! 	if (level > ulog_level)
! 	  return false;
! 
! 	if (level != ulog_level
! 	    && (ulog_mode == "match" || ulog_mode == "equal"))
! 	  return false;
! 
! 	return true;
        }
  
      void output_saved_messages ()
--- 1046,1072 ----
      ~fixed_attribute_map_with_logging_component () throw()
        {
  	// Output any saved messages.
! 	// output_saved_messages ();
! 	ulog_logger->output_saved_messages ();
  #if SID_LOG_PERSISTENT_BUFFER
  	delete [] buffer;
  #endif
        }
  
!     void log (sid::host_int_4 level, const char *fmt, ...)
        {
! 	va_list ap;
! 	va_start (ap, fmt);
! 	// In case values changed
! 	ulog_logger->set_attributes (buffer_output, ulog_level, ulog_mode);
! 	ulog_logger->log (level, fmt, ap);
! 	va_end (ap);
        }
  
  private:
      bool check_level (sid::host_int_4 level)
        {
! 	ulog_logger->check_level (level);
        }
  
      void output_saved_messages ()
*************** private:
*** 1141,1146 ****
--- 1088,1094 ----
      std::string ulog_mode;
      sidutil::output_pin ulog_out_pin;
      bool buffer_output;
+     sidutil::logger *ulog_logger;
      char *buffer;
      long buffer_size;
      std::vector<std::string> saved_messages;
Index: sid/include/sidcpuutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidcpuutil.h,v
retrieving revision 1.26
diff -c -p -r1.26 sidcpuutil.h
*** sid/include/sidcpuutil.h	29 Aug 2003 19:27:05 -0000	1.26
--- sid/include/sidcpuutil.h	21 Oct 2003 20:21:46 -0000
*************** namespace sidutil
*** 234,240 ****
--- 234,244 ----
  	else
  	  *this << std::endl;
        }
+     private:
        bool cout_p;
+ 
+       template <typename T> friend
+       basic_cpu::cpu_trace_stream& operator<< (basic_cpu::cpu_trace_stream& s, T t);
      };
  
      template <typename T> friend
Index: sid/include/sidmiscutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidmiscutil.h,v
retrieving revision 1.6
diff -c -p -r1.6 sidmiscutil.h
*** sid/include/sidmiscutil.h	22 Nov 2002 20:35:00 -0000	1.6
--- sid/include/sidmiscutil.h	21 Oct 2003 20:21:46 -0000
***************
*** 8,15 ****
--- 8,17 ----
  #define SIDMISCUTIL_H
  
  #include <sidconfig.h>
+ #include <sidpinutil.h>
  
  #include <string>
+ #include <iostream>
  #include <fstream>
  #include <vector>
  #include <map>
***************
*** 20,26 ****
--- 22,40 ----
  #ifdef __CYGWIN__
  #include <sys/cygwin.h>
  #endif
+ // XXX: kludge for compatibility both with old & new libstdc++
+ #if STD_CCTYPE
+ #define STDCTYPE(func) std::func
+ #else
+ #define STDCTYPE(func) func
+ #endif
+ 
+ #include <limits.h>
+ #include <stdio.h>
+ #include <stdarg.h>
  
+ using std::string;
+ using std::vector;
  
  namespace sidutil
  {
*************** namespace sidutil
*** 376,381 ****
--- 390,534 ----
      return file;
    }
  
+   class logger
+   {
+ #define SID_LOG_PERSISTENT_BUFFER (HAVE_VSNPRINTF || ! HAVE_VASPRINTF)
+ #define SID_LOG_TRANSIENT_MALLOC_BUFFER (! SID_LOG_PERSISTENT_BUFFER)
+   public:
+     logger (sidutil::output_pin *p_ulog_out_pin,
+ 	    bool p_buffer_output,
+ 	    sid::host_int_4 p_ulog_level,
+ 	    std::string p_ulog_mode) :
+       ulog_level (p_ulog_level),
+       ulog_mode (p_ulog_mode),
+       buffer_output (p_buffer_output),
+       buffer_size (4096), // big enough for now
+       saved_messages (),
+       saved_levels ()
+       {
+ 	ulog_out_pin = p_ulog_out_pin;
+ #if SID_LOG_PERSISTENT_BUFFER
+ 	buffer = new char[buffer_size];
+ #endif
+       }
+     ~logger () throw()
+       {
+ 	// Output any saved messages.
+ 	output_saved_messages ();
+ #if SID_LOG_PERSISTENT_BUFFER
+ 	delete [] buffer;
+ #endif
+       }
+ 
+     void set_attributes (bool p_buffer_output,
+  			 sid::host_int_4 p_ulog_level,
+  			 std::string p_ulog_mode)
+     {
+       buffer_output = p_buffer_output;
+       ulog_level  = p_ulog_level;
+       ulog_mode = p_ulog_mode;
+     }
+ 
+     virtual void log (sid::host_int_4 level, const char *fmt, va_list ap)
+       {
+ 	if (! buffer_output)
+ 	  {
+ 	    // Output any saved messages first
+ 	    output_saved_messages ();
+ 
+ 	    // Check the logging level and mode.
+ 	    if (! check_level (level))
+ 	      return;
+ 	  }
+ 
+ 	// Write the message into a buffer.
+ 	int length;
+ 	for (;;)
+ 	  {
+ #if HAVE_VSNPRINTF
+ 	    length = vsnprintf (buffer, buffer_size, fmt, ap);
+ 	    if (length < buffer_size)
+ 	      break;
+ 	    delete [] buffer;
+ 	    buffer_size = length + 256;
+ 	    buffer = new char[buffer_size];
+ #elif HAVE_VASPRINTF
+ 	    length = vasprintf (&buffer, fmt, ap);
+ 	    break;
+ #else
+ 	    length = STDCTYPE(vsprintf) (buffer, fmt, ap);
+ 	    if (length >= buffer_size)
+ 	      std::cerr << "Error: ulog buffer overflow!!!" << std::endl;
+ 	    break;
+ #endif
+ 	  }
+ 
+ 	// If the output pin is not connected yet, Save the message for
+ 	// later. This happens when the log message is issued from the
+ 	// component's constructor.
+ 	if (buffer_output)
+ 	  {
+ 	    saved_messages.push_back (std::string (buffer));
+ 	    saved_levels.push_back (level);
+ 	  }
+ 	else
+ 	  {
+ 	    // Otherwise, output the new message.
+ 	    for (int i = 0; i < length; ++i)
+ 	      ulog_out_pin->drive (buffer[i]);
+ 	  }
+ 
+ #if SID_LOG_TRANSIENT_MALLOC_BUFFER
+ 	free (buffer);
+ #endif
+       }
+ 
+   public:
+     bool check_level (sid::host_int_4 level)
+       {
+ 	if (level > ulog_level)
+ 	  return false;
+ 
+ 	if (level != ulog_level
+ 	    && (ulog_mode == "match" || ulog_mode == "equal"))
+ 	  return false;
+ 
+ 	return true;
+       }
+ 
+   public:
+     void output_saved_messages ()
+       {
+ 	while (saved_messages.size () > 0)
+ 	  {
+ 	    if (check_level (saved_levels[0]))
+ 	      {
+ 		std::string s = saved_messages[0];
+ 		for (int i = 0; i < s.size (); ++i)
+ 		  ulog_out_pin->drive (s[i]);
+ 	      }
+ 	    saved_messages.erase (saved_messages.begin ());
+ 	    saved_levels.erase (saved_levels.begin ());
+ 	  }
+       }
+ 
+   private:
+     sid::host_int_4 ulog_level;
+     std::string ulog_mode;
+     sidutil::output_pin *ulog_out_pin;
+     bool buffer_output;
+     char *buffer;
+     long buffer_size;
+     std::vector<std::string> saved_messages;
+     std::vector<sid::host_int_4> saved_levels;
+ #undef SID_LOG_PERSISTENT_BUFFER
+ #undef SID_LOG_TRANSIENT_MALLOC_BUFFER
+   public:
+     void delete_saved_messages ()
+     {
+       saved_messages.erase (saved_messages.end ());
+     }
+   };
  
  }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.