SourceForge has been redesigned. Learn more.
Close

Diff of /src/dmh.cpp [2facf8] .. [b70b9b]  Maximize  Restore

Switch to side-by-side view

--- a/src/dmh.cpp
+++ b/src/dmh.cpp
@@ -4,10 +4,11 @@
  * $Id$
  *
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2009, 2010, 2011, MinGW Project
- *
- *
- * Implementation of the diagnostic message handling subsystem.
+ * Copyright (C) 2009, 2010, 2011, 2012, MinGW.org Project
+ *
+ *
+ * Implementation of the core components of, and the CLI specific
+ * API for, the diagnostic message handling subsystem.
  *
  *
  * This is free software.  Permission is granted to copy, modify and
@@ -28,23 +29,39 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
-#include "dmh.h"
-
-class dmhTypeGeneric
-{
-  /* Abstract base class, from which message handlers are derived.
-   */
-  public:
-    dmhTypeGeneric( const char* );
-    virtual uint16_t control( const uint16_t, const uint16_t ) = 0;
-    virtual int notify( const dmh_severity, const char*, va_list ) = 0;
-    virtual int printf( const char*, va_list ) = 0;
-
-  protected:
-    const char *progname;
-};
-
-class dmhTypeTTY : public dmhTypeGeneric
+#include "dmhcore.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/* Prototype this at point of use, rather than in dmhcore.h,
+ * so that we don't need to arbitrarily include windows.h in
+ * any DMH client.
+ */
+EXTERN_C void dmh_setpty( HWND );
+
+/* Implementation of the dmh_exception class.
+ */
+static const char *unspecified_error = "Unspecified error";
+
+dmh_exception::dmh_exception() throw():
+  message( unspecified_error ){}
+
+dmh_exception::dmh_exception( const char *msg ) throw():
+  message( unspecified_error )
+  {
+    if( msg && *msg )
+      message = msg;
+  }
+
+dmh_exception::~dmh_exception() throw(){}
+
+const char* dmh_exception::what() const throw()
+{
+  return message;
+}
+
+class dmhTypeTTY: public dmhTypeGeneric
 {
   /* Diagnostic message handler for use in console applications.
    */
@@ -58,48 +75,28 @@
     inline int emit_and_flush( int );
 };
 
-class dmhTypeGUI : public dmhTypeGeneric
-{
-  /* Diagnostic message handler for use in window applications.
-   */
-  public:
-    dmhTypeGUI( const char* );
-    virtual uint16_t control( const uint16_t, const uint16_t );
-    virtual int notify( const dmh_severity, const char*, va_list );
-    virtual int printf( const char*, va_list );
-};
-
-dmh_exception::dmh_exception() throw()
-: message( "Unspecified error" )
-{}
-
-dmh_exception::dmh_exception::dmh_exception(const char * msg) throw()
-: message( "Unspecified error" )
-{
-  if( msg && *msg )
-    message = msg;
-}
-
-dmh_exception::~dmh_exception() throw()
-{}
-
-const char* dmh_exception::what() const throw()
-{
-  return message;
-}
-
 /* Constructors serve to initialise the message handler,
  * simply creating the class instance, and storing the specified
  * program name within it.
  */
 dmhTypeGeneric::dmhTypeGeneric( const char* name ):progname( name ){}
 dmhTypeTTY::dmhTypeTTY( const char* name ):dmhTypeGeneric( name ){}
-dmhTypeGUI::dmhTypeGUI( const char* name ):dmhTypeGeneric( name ){}
 
 /* This pointer stores the address of the message handler
  * class instance, after initialisation.
  */
 static dmhTypeGeneric *dmh = NULL;
+
+#define client GetModuleHandle( NULL )
+static inline dmhTypeGeneric *dmh_init_gui( const char *progname )
+{
+  /* Stub function to support run-time binding of a client-provided
+   * implementation for the DMH_SUBSYSTEM_GUI class methods.
+   */
+  typedef dmhTypeGeneric *(*init_hook)( const char * );
+  init_hook do_init = (init_hook)(GetProcAddress( client, "dmh_init_gui" ));
+  return do_init ? do_init( progname ) : NULL;
+}
 
 EXTERN_C void dmh_init( const dmh_class subsystem, const char *progname )
 {
@@ -114,11 +111,16 @@
      * passing the specified program name, select...
      */
     if( subsystem == DMH_SUBSYSTEM_GUI )
+    {
       /*
        * ...a GUI class handler on demand...
        */
-      dmh = new dmhTypeGUI( progname );
-
+      if( (dmh = dmh_init_gui( strdup( progname ))) == NULL )
+	/*
+	 * ...but bail out, if this cannot be initialised...
+	 */
+	throw dmh_exception( "DMH subsystem initialisation failed" );
+    }
     else
       /* ...otherwise, a console class handler by default.
        */
@@ -139,34 +141,6 @@
    * return the specified status code.
    */
   return status;
-}
-
-uint16_t dmhTypeGUI::control( const uint16_t request, const uint16_t mask )
-{
-  /* Select optional features of the GUI class message handler.
-   *
-   * FIXME: this is a stub; implementation to be provided.
-   */
-  return 0;
-}
-
-int dmhTypeGUI::notify( const dmh_severity code, const char *fmt, va_list argv )
-{
-  /* Message dispatcher for GUI applications.
-   *
-   * FIXME: this is a stub; implementation to be provided.
-   */
-  return
-  fprintf( stderr, "%s: *** ERROR *** DMH_SUBSYSTEM_GUI not yet implemented\n", progname );
-}
-
-int dmhTypeGUI::printf( const char *fmt, va_list argv )
-{
-  /* Display arbitrary text messages via the diagnostic message handler.
-   *
-   * FIXME: this is a stub; implementation to be provided.
-   */
-  return notify( DMH_ERROR, fmt, argv );
 }
 
 uint16_t dmhTypeTTY::control( const uint16_t request, const uint16_t mask )
@@ -193,9 +167,9 @@
   return status;
 }
 
-int dmhTypeTTY::notify( const dmh_severity code, const char *fmt, va_list argv )
-{
-  /* Message dispatcher for console class applications.
+const char *dmhTypeGeneric::severity_tag( dmh_severity code )
+{
+  /* Helper function to assign labels to the known severity codes.
    */
   static const char *severity[] =
   {
@@ -206,13 +180,24 @@
     "ERROR",		/* DMH_ERROR */
     "FATAL"		/* DMH_FATAL */
   };
-
+  return severity[code];
+}
+
+/* Establish the format to be used for the prefix string, which is
+ * attached to TTY and PTY notifications.
+ */
+const char *dmhTypeGeneric::notification_format = "%s: *** %s *** ";
+
+int dmhTypeTTY::notify( const dmh_severity code, const char *fmt, va_list argv )
+{
+  /* Message dispatcher for console class applications.
+   */
   /* Dispatch the message to standard error, terminate application
    * if DMH_FATAL, else continue, returning the message length.
    */
   return abort_if_fatal( code,
       emit_and_flush(
-	fprintf( stderr, "%s: *** %s *** ", progname, severity[code] )
+	fprintf( stderr, notification_format, progname, severity_tag( code ) )
 	+ vfprintf( stderr, fmt, argv )
 	)
       );
@@ -228,7 +213,19 @@
 
 EXTERN_C uint16_t dmh_control( const uint16_t request, const uint16_t mask )
 {
+  /* Public helper to access and manipulate the control channel for
+   * the diagnostic message handler.
+   */
   return dmh->control( request, mask );
+}
+
+EXTERN_C void dmh_setpty( HWND console )
+{
+  /* Public API for assignment of a GUI window as a pseudo-console
+   * for streaming of diagnostic message handler output; ("console"
+   * is assumed to refer to a Windows EDITTEXT control).
+   */
+  dmh->set_console_hook( (void *)(console) );
 }
 
 EXTERN_C int dmh_notify( const dmh_severity code, const char *fmt, ... )