6 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
7 * Copyright (C) 2009, 2010, 2011, MinGW Project
10 * Implementation of the diagnostic message handling subsystem.
13 * This is free software. Permission is granted to copy, modify and
14 * redistribute this software, under the provisions of the GNU General
15 * Public License, Version 3, (or, at your option, any later version),
16 * as published by the Free Software Foundation; see the file COPYING
17 * for licensing details.
19 * Note, in particular, that this software is provided "as is", in the
20 * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
21 * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
22 * PARTICULAR PURPOSE. Under no circumstances will the author, or the
23 * MinGW Project, accept liability for any damages, however caused,
24 * arising from the use of this software.
35 /* Abstract base class, from which message handlers are derived.
38 dmhTypeGeneric( const char* );
39 virtual uint16_t control( const uint16_t, const uint16_t ) = 0;
40 virtual int notify( const dmh_severity, const char*, va_list ) = 0;
41 virtual int printf( const char*, va_list ) = 0;
47 class dmhTypeTTY : public dmhTypeGeneric
49 /* Diagnostic message handler for use in console applications.
52 dmhTypeTTY( const char* );
53 virtual uint16_t control( const uint16_t, const uint16_t );
54 virtual int notify( const dmh_severity, const char*, va_list );
55 virtual int printf( const char*, va_list );
58 inline int emit_and_flush( int );
61 class dmhTypeGUI : public dmhTypeGeneric
63 /* Diagnostic message handler for use in window applications.
66 dmhTypeGUI( const char* );
67 virtual uint16_t control( const uint16_t, const uint16_t );
68 virtual int notify( const dmh_severity, const char*, va_list );
69 virtual int printf( const char*, va_list );
72 dmh_exception::dmh_exception() throw()
73 : message( "Unspecified error" )
76 dmh_exception::dmh_exception::dmh_exception(const char * msg) throw()
77 : message( "Unspecified error" )
83 dmh_exception::~dmh_exception() throw()
86 const char* dmh_exception::what() const throw()
91 /* Constructors serve to initialise the message handler,
92 * simply creating the class instance, and storing the specified
93 * program name within it.
95 dmhTypeGeneric::dmhTypeGeneric( const char* name ):progname( name ){}
96 dmhTypeTTY::dmhTypeTTY( const char* name ):dmhTypeGeneric( name ){}
97 dmhTypeGUI::dmhTypeGUI( const char* name ):dmhTypeGeneric( name ){}
99 /* This pointer stores the address of the message handler
100 * class instance, after initialisation.
102 static dmhTypeGeneric *dmh = NULL;
104 EXTERN_C void dmh_init( const dmh_class subsystem, const char *progname )
106 /* Public entry point for message handler initialisation...
108 * We only do it once, silently ignoring any attempt to
109 * establish a second handler.
113 /* No message handler has yet been initialised;
114 * passing the specified program name, select...
116 if( subsystem == DMH_SUBSYSTEM_GUI )
118 * ...a GUI class handler on demand...
120 dmh = new dmhTypeGUI( progname );
123 /* ...otherwise, a console class handler by default.
125 dmh = new dmhTypeTTY( progname );
130 int abort_if_fatal( const dmh_severity code, int status )
132 /* Helper function to abort an application, on notification
133 * of a DMH_FATAL exception.
135 if( code == DMH_FATAL )
136 throw dmh_exception( "Fatal error occured" );
138 /* If the exception wasn't DMH_FATAL, then fall through to
139 * return the specified status code.
144 uint16_t dmhTypeGUI::control( const uint16_t request, const uint16_t mask )
146 /* Select optional features of the GUI class message handler.
148 * FIXME: this is a stub; implementation to be provided.
153 int dmhTypeGUI::notify( const dmh_severity code, const char *fmt, va_list argv )
155 /* Message dispatcher for GUI applications.
157 * FIXME: this is a stub; implementation to be provided.
160 fprintf( stderr, "%s: *** ERROR *** DMH_SUBSYSTEM_GUI not yet implemented\n", progname );
163 int dmhTypeGUI::printf( const char *fmt, va_list argv )
165 /* Display arbitrary text messages via the diagnostic message handler.
167 * FIXME: this is a stub; implementation to be provided.
169 return notify( DMH_ERROR, fmt, argv );
172 uint16_t dmhTypeTTY::control( const uint16_t request, const uint16_t mask )
174 /* Select optional features of the console class message handler.
175 * This message handler provides no optional features; we make this
181 inline int dmhTypeTTY::emit_and_flush( int status )
183 /* Users of MSYS terminal emulators, in place of the standard
184 * MS-Windows console, may experience an I/O buffering issue on
185 * stderr (?!!) which may result in apparently erratic delivery
186 * of progress reporting diagnostics; this may lead to a false
187 * impression that mingw-get has stalled. This inline wrapper
188 * ensures that any buffer which is improperly associated with
189 * stderr is flushed after each message is posted; this may
190 * mitigate the improper buffering issue.
196 int dmhTypeTTY::notify( const dmh_severity code, const char *fmt, va_list argv )
198 /* Message dispatcher for console class applications.
200 static const char *severity[] =
202 /* Labels to identify message severity...
204 "INFO", /* DMH_INFO */
205 "WARNING", /* DMH_WARNING */
206 "ERROR", /* DMH_ERROR */
207 "FATAL" /* DMH_FATAL */
210 /* Dispatch the message to standard error, terminate application
211 * if DMH_FATAL, else continue, returning the message length.
213 return abort_if_fatal( code,
215 fprintf( stderr, "%s: *** %s *** ", progname, severity[code] )
216 + vfprintf( stderr, fmt, argv )
221 int dmhTypeTTY::printf( const char *fmt, va_list argv )
223 /* Display arbitrary text messages via the diagnostic message handler;
224 * for the TTY subsystem, this is equivalent to printf() on stderr.
226 return emit_and_flush( vfprintf( stderr, fmt, argv ) );
229 EXTERN_C uint16_t dmh_control( const uint16_t request, const uint16_t mask )
231 return dmh->control( request, mask );
234 EXTERN_C int dmh_notify( const dmh_severity code, const char *fmt, ... )
236 /* Public entry point for diagnostic message dispatcher.
240 /* The message handler has been called before initialising it;
241 * this is an internal program error -- treat it as fatal!
243 dmh_init( DMH_SUBSYSTEM_TTY, "dmh" );
244 dmh_notify( DMH_FATAL, "message handler was not initialised\n" );
247 /* Normal operation; pass the message on to the active handler.
250 va_start( argv, fmt );
251 int retcode = dmh->notify( code, fmt, argv );
256 EXTERN_C int dmh_printf( const char *fmt, ... )
258 /* Simulate standard printf() function calls, redirecting the display
259 * of formatted output through the diagnostic message handler.
262 va_start( argv, fmt );
263 int retcode = dmh->printf( fmt, argv );
268 /* $RCSfile$: end of file */