Added auto-colourising DBGC() macro
authorMichael Brown <mcb30@etherboot.org>
Fri, 29 Dec 2006 03:05:21 +0000 (03:05 +0000)
committerMichael Brown <mcb30@etherboot.org>
Fri, 29 Dec 2006 03:05:21 +0000 (03:05 +0000)
src/core/debug.c
src/include/compiler.h

index 3facad2..9ef25b8 100644 (file)
@@ -1,4 +1,5 @@
 #include <stdint.h>
+#include <stdarg.h>
 #include <io.h>
 #include <console.h>
 
@@ -85,3 +86,58 @@ int check_region ( void *region, size_t len ) {
        }
        return corrupted;
 }
+
+#define NUM_AUTO_COLOURS 6
+
+struct autocolour {
+       void * id;
+       unsigned long last_used;
+};
+
+static int autocolourise ( void *id ) {
+       static struct autocolour acs[NUM_AUTO_COLOURS];
+       static unsigned long use;
+       unsigned int i;
+       unsigned int oldest;
+       unsigned int oldest_last_used;
+
+       /* Increment usage iteration counter */
+       use++;
+
+       /* Scan through list for a currently assigned colour */
+       for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
+               if ( acs[i].id == id ) {
+                       acs[i].last_used = use;
+                       return i;
+               }
+       }
+
+       /* No colour found; evict the oldest from the list */
+       oldest = 0;
+       oldest_last_used = use;
+       for ( i = 0 ; i < ( sizeof ( acs ) / sizeof ( acs[0] ) ) ; i++ ) {
+               if ( acs[i].last_used < oldest_last_used ) {
+                       oldest_last_used = acs[i].last_used;
+                       oldest = i;
+               }
+       }
+       acs[oldest].id = id;
+       acs[oldest].last_used = use;
+       return oldest;
+}
+
+/** printf() for debugging with automatic colourisation
+ *
+ * @v id               Message stream ID
+ * @v fmt              printf() format
+ * @v ...              printf() argument list
+ */
+void dbg_printf_autocolour ( void *id, const char *fmt, ... ) {
+       va_list args;
+
+       printf ( "\033[%dm", ( id ? ( 31 + autocolourise ( id ) ) : 0 ) );
+       va_start ( args, fmt );
+       vprintf ( fmt, args );
+       va_end ( args );
+       printf ( "\033[0m" );
+}
index f4ea32e..49aaec6 100644 (file)
@@ -100,15 +100,6 @@ __asm__ ( ".equ\t" OBJECT_SYMBOL_STR ", 0" );
  *
  */
 
-/** @def DBG2
- *
- * Print a level 2 debugging message.
- *
- * As for DBG().  DBG2() takes effect only when the debugging level is
- * 2 or greater.
- *
- */
-
 /*
  * If debug_OBJECT is set to a true value, the macro DBG(...) will
  * expand to printf(...) when compiling OBJECT, and the symbol
@@ -120,36 +111,57 @@ __asm__ ( ".equ\t" OBJECT_SYMBOL_STR ", 0" );
 #if DEBUG_SYMBOL
 #include "console.h"
 #define DEBUG_SYMBOL_STR _XSTR ( DEBUG_SYMBOL )
-__asm__ ( ".equ\tDEBUG_LEVEL, " DEBUG_SYMBOL_STR );
+__asm__ ( ".equ\tDBGLVL, " DEBUG_SYMBOL_STR );
 #endif
 
-/** Do not print
+/** printf() for debugging
+ *
+ * This function exists so that the DBG() macros can expand to
+ * printf() calls without dragging the printf() prototype into scope.
  *
- * This function is used only for printf()-style format string
- * checking.  The function body does not exist, and no reference to it
- * should ever appear in any compiled object.
+ * As far as the compiler is concerned, dbg_printf() and printf() are
+ * completely unrelated calls; it's only at the assembly stage that
+ * references to the dbg_printf symbol are collapsed into references
+ * to the printf symbol.
  */
-extern int __attribute__ (( format ( printf, 1, 2 ) ))
-__do_not_printf ( const char *fmt, ... );
+extern int __attribute__ (( format ( printf, 1, 2 ) )) 
+dbg_printf ( const char *fmt, ... ) asm ( "printf" );
 
-#define DBG_PRINT(...) printf ( __VA_ARGS__ )
-#define DBG_DISCARD(...) do {                                  \
-               if ( 0 ) __do_not_printf ( __VA_ARGS__ );       \
-       } while ( 0 )
-
-#define DBG  DBG_DISCARD
-#define DBG2 DBG_DISCARD
+extern void __attribute__ (( format ( printf, 2, 3 ) )) 
+dbg_printf_autocolour ( void *id, const char *fmt, ... );
 
+/* Compatibility with existing Makefile */
 #if DEBUG_SYMBOL >= 1
-#undef DBG
-#define DBG DBG_PRINT
-#endif
-
 #if DEBUG_SYMBOL >= 2
-#undef DBG2
-#define DBG2 DBG_PRINT
+#define DBGLVL 3
+#else
+#define DBGLVL 1
+#endif
+#else
+#define DBGLVL 0
 #endif
 
+#define DBGLVL_LOG     1
+#define DBG_LOG                ( DBGLVL & DBGLVL_LOG )
+#define DBGLVL_EXTRA   2
+#define DBG_EXTRA      ( DBGLVL & DBGLVL_EXTRA )
+
+#define DBG_IF( level, ... ) do {                              \
+               if ( DBG_ ## level ) {                          \
+                       dbg_printf ( __VA_ARGS__ );             \
+               }                                               \
+       } while ( 0 )
+
+#define DBGC_IF( level, ... ) do {                             \
+               if ( DBG_ ## level ) {                          \
+                       dbg_printf_autocolour ( __VA_ARGS__ );  \
+               }                                               \
+       } while ( 0 )
+
+#define DBG( ... )     DBG_IF ( LOG, __VA_ARGS__ )
+#define DBG2( ... )    DBG_IF ( EXTRA, __VA_ARGS__ )
+#define DBGC( ... )    DBGC_IF ( LOG, __VA_ARGS__ )
+
 #if DEBUG_SYMBOL == 0
 #define NDEBUG
 #endif
@@ -157,23 +169,13 @@ __do_not_printf ( const char *fmt, ... );
 /** Declare a data structure as packed. */
 #define PACKED __attribute__ (( packed ))
 
-/** 
- * Declare a variable or data structure as unused.
- *
- * Note that using #__unused on a static global variable (such as a
- * table structure as mentioned in tables.h) is necessary in order to
- * inhibit compiler warnings.
- *
- */
+/** Declare a variable or data structure as unused. */
 #define __unused __attribute__ (( unused ))
 
 /**
  * Declare a function as used.
  *
  * Necessary only if the function is called only from assembler code.
- * You cannot use this attribute for static global variables; use
- * #__unused instead.
- *
  */
 #define __used __attribute__ (( used ))