Humble Framework for SkyOS


Main Page | Modules | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

HDebug.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 **  $Header: /SkyOS.root/HFramework/HDebug.h 8     4/17/05 12:29p Lee Neuse $
00004 **
00005 ****************************************************************************/
00023 #ifndef HDEBUG_H
00024 #   define  HDEBUG_H
00025 
00026 #ifndef __DEBUG__
00027 #   define  __DEBUG__   0
00028 #endif
00029 
00030 #if __DEBUG__
00031 
00032 #define SEND_TO_STDERR  1
00033 #define SEND_TO_PRINTD  0
00034 
00044 class HDebug : public HObjNoCopy
00045     {
00046     typedef HObjNoCopy  base_class;
00047     static StringPtr    ClassName(void) { return "HDebug"; }
00048 /*  ----------------------------------------------------------------------
00049     VARIABLES
00050     ----------------------------------------------------------------------  */
00051 protected:
00052     FILE *              m_pfLog;        
00053 /*  ----------------------------------------------------------------------
00054     CTOR / DTOR
00055     ----------------------------------------------------------------------  */
00056 public:
00057     HDebug(void) : m_pfLog(NULL)
00058         { /* EMPTY CTOR */ }
00059 
00060     virtual 
00061     ~HDebug(void)
00062         { Close(); }
00063 /*  ----------------------------------------------------------------------
00064     METHODS
00065     ----------------------------------------------------------------------  */
00066 public:
00075     static void
00076     Check(bool bPassed, StringPtr pstrTest, StringPtr pstrFile, uint32 uLine)
00077         {
00078         if (!bPassed)   // only do this if check fails
00079             {
00080             const uint32    kMaxMsgLen = MAX_PATH * 2;
00081             Text            szMsg[kMaxMsgLen+1] = { '\0' };
00082 
00083             (void) STR_SPRINTF( szMsg, kMaxMsgLen,
00084                                 "Sanity check at %s(%lu): \"%s\"", 
00085                                 pstrFile, uLine, pstrTest);
00086                                 
00087             if (GI_messagebox(  NULL, WGF_MB_ICON_STOP|WGF_MB_CANCEL, 
00088                                 const_cast<TextPtr>("Sanity Check?"), 
00089                                 szMsg) == ID_OK)
00090                 {
00091                 GetLog().LogV("%s approved.\n", szMsg);
00092                 }
00093             else
00094                 throw std::runtime_error(szMsg);
00095             }
00096         }
00100     void
00101     Close(void)
00102         {
00103         if (IsOpen() && fclose(m_pfLog) == 0) 
00104             m_pfLog = NULL;
00105         }
00109     void
00110     Flush(void) const
00111         {
00112         if (IsOpen())
00113             (void) fflush(m_pfLog);
00114         }
00124     void
00125     Log(StringPtr pstr) const
00126         {
00127         int32   nLen = STR_NLEN(pstr, KB(8));   // don't log more than 8Kb
00128         
00129         if (nLen <= 0)
00130             return; // never mind...user passed us crap
00131 
00132 #if SEND_TO_STDERR
00133         (void) fwrite(pstr, sizeof(Text), nLen, stderr);
00134 #endif
00135 #if SEND_TO_PRINTD
00136         (void) printd( (char *)(pstr) );
00137 #endif
00138         if (IsOpen())
00139             {
00140             (void) fwrite(pstr, sizeof(Text), nLen, m_pfLog);
00141             Flush();
00142             }
00143         }
00154     void 
00155     LogHex(uint8 const * pData, uint32 uBytes) const
00156         {
00157         if (GOOD_PTR(pData))
00158             {
00159             uint32  uOffset = 0;
00160             
00161             uBytes = min(uBytes, KB(1));    // limit output to 1KB
00162             
00163             while (uOffset < uBytes)
00164                 {
00165                 LogV("0x%04lX :", uOffset);
00166                 for (uint32 udx = 0; udx < 16 && uOffset < uBytes; ++udx)
00167                     LogV(" %02X", pData[uOffset++]);
00168                 Log(kStrEOL);
00169                 }
00170                 
00171             Flush();
00172             }
00173         }
00185     void                
00186     LogMsg(StringPtr pstrClass, HANDLE hWnd, const s_gi_msg * pMsg) const
00187         {
00188         StringPtr   pstr = NULL;
00189 
00190         if (NULL_PTR(pMsg)) 
00191             return; // bail out if the message isn't valid or the log is closed
00192         
00193         switch (pMsg->type)
00194             {
00195             case MSG_APPLICATIONS_CHANGED:
00196             case MSG_APPLICATIONS_SWITCHED:
00197             case MSG_GUI_DRAW_CHILD:
00198             case MSG_GUI_WINDOW_FOCUS_GET:
00199             case MSG_GUI_WINDOW_FOCUS_LOST:
00200             case MSG_GUI_REDRAW:
00201             case MSG_MOUSE_MOVE:
00202                 // Don't log these messages...
00203                 return;
00204 
00205             case MSG_COMMAND:
00206                 LogV(   "%s[0x%08lX] => MSG_COMMAND (%u)\n", 
00207                         pstrClass, int32(hWnd), pMsg->para1);
00208                 return;
00209 
00210             case MSG_MOUSE_BUT1_PRESSED:
00211                 LogV(   "%s[0x%08lX] => MSG_MOUSE_BUT1_PRESSED at (%u, %u)\n", 
00212                         pstrClass, int32(hWnd), pMsg->para1, pMsg->para2);
00213                 return;
00214 
00215             case MSG_MOUSE_BUT2_PRESSED:
00216                 LogV(   "%s[0x%08lX] => MSG_MOUSE_BUT2_PRESSED at (%u, %u)\n", 
00217                         pstrClass, int32(hWnd), pMsg->para1, pMsg->para2);
00218                 return;
00219 
00220             case MSG_WINDOW_SIZED:
00221                 LogV(   "%s[0x%08lX] => MSG_WINDOW_SIZED (%d, %d, %d, %d)\n",
00222                         pstrClass, int32(hWnd), pMsg->rect.x1, pMsg->rect.y1, pMsg->rect.x2, pMsg->rect.y2);
00223                 return;
00224                 
00225             case MSG_DESTROY:               pstr = "MSG_DESTROY";               break;
00226             case MSG_GUI_CLOSE_WIN:         pstr = "MSG_GUI_CLOSE_WIN";         break;
00227             case MSG_GUI_CREATE_WINDOW:     pstr = "MSG_GUI_CREATE_WINDOW";     break;
00228             case MSG_GUI_WINDOW_CLOSE:      pstr = "MSG_GUI_WINDOW_CLOSE";      break;
00229             case MSG_GUI_WINDOW_CREATED:    pstr = "MSG_GUI_WINDOW_CREATED";    break;
00230             case MSG_GUI_WINDOW_SIZED:      pstr = "MSG_GUI_WINDOW_SIZED";      break;
00231             case MSG_KEY_DOWN:              pstr = "MSG_KEY_DOWN";              break;
00232             case MSG_KEY_UP:                pstr = "MSG_KEY_UP";                break;
00233             case MSG_MOUSE_BUT1_RELEASED:   pstr = "MSG_MOUSE_BUT1_RELEASED";   break;
00234             case MSG_MOUSE_BUT2_RELEASED:   pstr = "MSG_MOUSE_BUT2_RELEASED";   break;
00235             case MSG_MOUSE_ENTER:           pstr = "MSG_MOUSE_ENTER";           break;
00236             case MSG_MOUSE_LEAVE:           pstr = "MSG_MOUSE_LEAVE";           break;
00237 //          case MSG_MOUSE_MOVE:            pstr = "MSG_MOUSE_MOVE";            break;
00238             case MSG_PRE_DESTROY:           pstr = "MSG_PRE_DESTROY";           break;
00239             case MSG_THEME_CHANGED:         pstr = "MSG_THEME_CHANGED";         break;
00240             case MSG_TIMER:                 pstr = "MSG_TIMER";                 break;
00241             case MSG_TIMER_REACHED:         pstr = "MSG_TIMER_REACHED";         break;
00242             case MSG_WINDOW_DESTROY:        pstr = "MSG_WINDOW_DESTROY";        break;
00243             case MSG_WINDOW_SHOW:           pstr = "MSG_WINDOW_SHOW";           break;
00244 
00245 
00246             case WM_WG_CHECKBOX_CHANGED:    pstr = "WM_WG_CHECKBOX_CHANGED";    break;
00247 
00248             default:
00249 /*
00250 **  Note: Widget messages are defined in msg_widget.h
00251 **  00000 - 10099           SkyGI WM / Kernel message
00252 **  10100 - 10199           wgCombo
00253 **  10200 - 10299           wgText  
00254 **  10300 - 10399           wgListbox  
00255 **  10400 - 10499           wgClient 
00256 **  10500 - 10599           wgTitle  
00257 **  10800 - 11999           Common widget messages
00258 **  12000 - 12099           wgTree
00259 **  13000 - 13099           wgPopup
00260 **  14000 - 14099           wgCheck
00261 */
00262                 if (pMsg->type >= 10100 && pMsg->type <= 10199)
00263                     {
00264                     LogV(   "%s[0x%08lX] => COMBO WIDGET MSG#%04u\n", 
00265                             pstrClass, int32(hWnd), (pMsg->type - 10100));
00266                     }
00267                 else if (pMsg->type >= 10200 && pMsg->type <= 10299)
00268                     {
00269                     LogV(   "%s[0x%08lX] => TEXT WIDGET MSG#%04u\n", 
00270                             pstrClass, int32(hWnd), (pMsg->type - 10200));
00271                     }
00272                 else if (pMsg->type >= 10300 && pMsg->type <= 10399)
00273                     {
00274                     LogV(   "%s[0x%08lX] => LISTBOX WIDGET MSG#%04u\n", 
00275                             pstrClass, int32(hWnd), (pMsg->type - 10300));
00276                     }
00277                 else if (pMsg->type >= 10400 && pMsg->type <= 10499)
00278                     {
00279                     LogV(   "%s[0x%08lX] => CLIENT WIDGET MSG#%04u\n", 
00280                             pstrClass, int32(hWnd), (pMsg->type - 10400));
00281                     }
00282                 else if (pMsg->type >= 10500 && pMsg->type <= 10599)
00283                     {
00284                     LogV(   "%s[0x%08lX] => TITLE WIDGET MSG#%04u\n", 
00285                             pstrClass, int32(hWnd), (pMsg->type - 10500));
00286                     }
00287                 else if (pMsg->type >= 10800 && pMsg->type <= 11999)
00288                     {
00289                     LogV(   "%s[0x%08lX] => GENERIC WIDGET MSG#%04u\n", 
00290                             pstrClass, int32(hWnd), (pMsg->type - 10800));
00291                     }
00292                 else if (pMsg->type >= 12000 && pMsg->type <= 12099)
00293                     {
00294                     LogV(   "%s[0x%08lX] => TREE WIDGET MSG#%04u\n", 
00295                             pstrClass, int32(hWnd), (pMsg->type - 12000));
00296                     }
00297                 else if (pMsg->type >= 13000 && pMsg->type <= 13099)
00298                     {
00299                     LogV(   "%s[0x%08lX] => POPUP WIDGET MSG#%04u\n", 
00300                             pstrClass, int32(hWnd), (pMsg->type - 13000));
00301                     }
00302                 else if (pMsg->type >= 14000 && pMsg->type <= 14099)
00303                     {
00304                     LogV(   "%s[0x%08lX] => CHECBOX WIDGET MSG#%04u\n", 
00305                             pstrClass, int32(hWnd), (pMsg->type - 14000));
00306                     }
00307                 else
00308                     {
00309                     LogV(   "%s[0x%08lX] => Unrecognized message %u\n", 
00310                             pstrClass, int32(hWnd), pMsg->type);
00311                     }
00312                 return;
00313 
00314             }
00315 
00316         LogV(   "%s[0x%08lX] => %s\n", 
00317                 pstrClass, int32(hWnd), pstr);
00318             
00319         Flush();
00320         }
00330 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00331     GCC_ONLY( __attribute__ ((format (printf,2,3))) )
00332 #endif
00333     void
00334     LogV(StringPtr pstr, ...) const
00335         {
00336         if (GOOD_PTR(pstr))
00337             {
00338             const uint32    kMaxOut = 2047;
00339             va_list         vaList;
00340             Text            szOut[kMaxOut+1];
00341             
00342             va_start(vaList, pstr);
00343             Humble::safe_vsprintf(szOut, kMaxOut, pstr, vaList);
00344             va_end(vaList);
00345 
00346             Log(szOut);
00347             }
00348         }
00358     bool
00359     Open(StringPtr pstrLogFile)
00360         { 
00361         if (GOOD_PTR(pstrLogFile))
00362             {
00363             Close();    // close the existing log (if any)
00364             m_pfLog = fopen(pstrLogFile, "w+t");
00365             }
00366             
00367         return IsOpen();
00368         }
00369 /*  ----------------------------------------------------------------------
00370     GETTERS & SETTERS
00371     ----------------------------------------------------------------------  */
00372 public:
00375     static HDebug &     GetLog(void)
00376                             {
00377                             static HDebug   me;
00378                             return me;
00379                             }
00380 /*  ----------------------------------------------------------------------
00381     INLINES
00382     ----------------------------------------------------------------------  */
00385     inline bool         IsOpen(void) const
00386                             { return GOOD_PTR(m_pfLog); }
00387     };
00388 /*  ----------------------------------------------------------------------
00389     DEBUG Macros
00390     ----------------------------------------------------------------------  */
00394 
00396 #   define ASSERT(x)        if (x) ; else throw HAssertion(#x,__FILE__,__LINE__)
00397 
00398 #   define ASSERT_HND(h)    if (GOOD_HND(h)) ; else throw HAssertion(#h " is NULL",__FILE__,__LINE__)
00399 
00400 #   define ASSERT_PTR(p)    if (GOOD_PTR(p)) ; else throw HAssertion(#p " is NULL",__FILE__,__LINE__)
00401 
00402 #   define ASSERT_STR(s)    if (STR_VALID(s)) ; else throw HAssertion(#s " is invalid",__FILE__,__LINE__)
00403 
00404 #   define DEBUG_CHECK(x)   HDebug::Check((x),#x,__FILE__,__LINE__)
00405 
00406 #   define DEBUG_LOG        HDebug::GetLog().LogV
00407 
00408 #   define DEBUG_HEX(p,u)   HDebug::GetLog().LogHex((p),(u))
00409 
00410 #   define DEBUG_MSG(x,w,p) HDebug::GetLog().LogMsg((x),(w),(p))
00411 
00412 #   define DEBUG_ONLY(x)    x
00413 
00414 #else   // !__DEBUG__
00415     inline void             ignore(...) { /* EMPTY FUNCTION */ }
00416 
00417 #   define ASSERT(x)        NOTHING
00418 #   define ASSERT_HND(x)    NOTHING
00419 #   define ASSERT_PTR(x)    NOTHING
00420 #   define ASSERT_STR(x)    NOTHING
00421 #   define DEBUG_CHECK(x)   NOTHING
00422 #   define DEBUG_LOG        ignore
00423 #   define DEBUG_HEX(p,u)   NOTHING
00424 #   define DEBUG_MSG(t,w,p) NOTHING
00425 #   define DEBUG_ONLY(x)    NOTHING
00426 #endif  // __DEBUG__
00427 
00428 #endif  // HDEBUG_H
00429 /****************************************************************************
00430 **
00431 **  $History: HDebug.h $
00432  * 
00433  * *****************  Version 8  *****************
00434  * User: Lee Neuse    Date: 4/17/05    Time: 12:29p
00435  * Updated in $/SkyOS.root/HFramework
00436  * Development snapshot 050417
00437  * 
00438  * *****************  Version 7  *****************
00439  * User: Neusel       Date: 2/04/05    Time: 10:45a
00440  * Updated in $/SkyOS.root/pig/Humble
00441  * 
00442  * *****************  Version 6  *****************
00443  * User: Neusel       Date: 12/24/04   Time: 3:59p
00444  * Updated in $/SkyOS.root/pig/Humble
00445  * 
00446  * *****************  Version 5  *****************
00447  * User: Neusel       Date: 12/23/04   Time: 1:34p
00448  * Updated in $/SkyOS.root/pig/Humble
00449  * Posted as HFramework-debug 20041223
00450  * 
00451  * *****************  Version 4  *****************
00452  * User: Neusel       Date: 12/10/04   Time: 3:57p
00453  * Updated in $/SkyOS.root/pig/Humble
00454  * 20041210
00455  * 
00456  * *****************  Version 3  *****************
00457  * User: Neusel       Date: 12/08/04   Time: 5:06p
00458  * Updated in $/SkyOS.root/pig/Humble
00459  * 20041208
00460  * 
00461  * *****************  Version 2  *****************
00462  * User: Neusel       Date: 11/30/04   Time: 1:01p
00463  * Updated in $/SkyOS.root/pig/Humble
00464  * Released as HUMBLE_VER 20041130.
00465  * 
00466  * *****************  Version 1  *****************
00467  * User: Neusel       Date: 11/23/04   Time: 8:24a
00468  * Created in $/SkyOS.root/pig/Humble
00469 **
00470 **  -------------------------------------------------------------------------
00471 **
00472 **  End of HDebug.h
00473 **
00474 ****************************************************************************/