This is the mail archive of the sid@sources.redhat.com mailing list for the SID project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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
2003-10-07  Dave Brolley  <brolley@redhat.com>

	For Stan Cox  <scox@redhat.com>
	* sidmiscutil.h (logger): New class.
	* sidattrutil.h (fixed_attribute_map_with_logging_component): Convert
	to use logger.

2003-10-07  Dave Brolley  <brolley@redhat.com>

	* 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  <brolley@redhat.com>

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

2003-10-07  Dave Brolley  <brolley@redhat.com>

	For Stan Cox  <scox@redhat.com>
	* 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  <brolley@redhat.com>

	* sidattrutil.h (iostream): #include it.
	(log): Use std::cerr and std::endl.
	
2003-10-07  Dave Brolley  <brolley@redhat.com>

	* 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.

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 ());
+     }
+   };
  
  }
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]