Add support for field width argument to %x (eg, %08x).

Patch from Stefan Reinauer; modified by Kevin O'Connor.
diff --git a/src/boot.c b/src/boot.c
index a7795a1..5dc6761 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -309,7 +309,7 @@
 static void
 call_boot_entry(u16 bootseg, u16 bootip, u8 bootdrv)
 {
-    dprintf(1, "Booting from %x:%x\n", bootseg, bootip);
+    dprintf(1, "Booting from %04x:%04x\n", bootseg, bootip);
 
     struct bregs br;
     memset(&br, 0, sizeof(br));
diff --git a/src/memmap.c b/src/memmap.c
index 49f129b..65c9cd7 100644
--- a/src/memmap.c
+++ b/src/memmap.c
@@ -44,7 +44,7 @@
     for (i=0; i<e820_count; i++) {
         struct e820entry *e = &e820_list[i];
         u64 e_end = e->start + e->size;
-        dprintf(1, "  %d: %x%x - %x%x = %d\n", i
+        dprintf(1, "  %d: %08x%08x - %08x%08x = %d\n", i
                 , (u32)(e->start >> 32), (u32)e->start
                 , (u32)(e_end >> 32), (u32)e_end
                 , e->type);
@@ -56,7 +56,7 @@
 void
 add_e820(u64 start, u64 size, u32 type)
 {
-    dprintf(8, "Add to e820 map: %x %x %d\n", (u32)start, (u32)size, type);
+    dprintf(8, "Add to e820 map: %08x %08x %d\n", (u32)start, (u32)size, type);
 
     if (! size)
         // Huh?  Nothing to do.
diff --git a/src/optionroms.c b/src/optionroms.c
index c42968a..366e107 100644
--- a/src/optionroms.c
+++ b/src/optionroms.c
@@ -84,7 +84,7 @@
 callrom(struct rom_header *rom, u16 offset, u16 bdf)
 {
     u16 seg = FLATPTR_TO_SEG(rom);
-    dprintf(1, "Running option rom at %x:%x\n", seg, offset);
+    dprintf(1, "Running option rom at %04x:%04x\n", seg, offset);
 
     struct bregs br;
     memset(&br, 0, sizeof(br));
@@ -198,7 +198,8 @@
 static struct rom_header *
 map_optionrom(u16 bdf, u32 vendev)
 {
-    dprintf(6, "Attempting to map option rom on dev %x\n", bdf);
+    dprintf(6, "Attempting to map option rom on dev %02x:%02x.%x\n"
+            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf));
 
     u8 htype = pci_config_readb(bdf, PCI_HEADER_TYPE);
     if ((htype & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
@@ -282,7 +283,9 @@
 init_optionrom(u16 bdf)
 {
     u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
-    dprintf(4, "Attempting to init PCI bdf %x (dev/ven %x)\n", bdf, vendev);
+    dprintf(4, "Attempting to init PCI bdf %02x:%02x.%x (dev/ven %x)\n"
+            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)
+            , vendev);
     struct rom_header *rom = lookup_hardcode(vendev);
     if (! rom)
         rom = map_optionrom(bdf, vendev);
diff --git a/src/output.c b/src/output.c
index 5cda9c1..518730a 100644
--- a/src/output.c
+++ b/src/output.c
@@ -134,16 +134,33 @@
 
 // Output an integer in hexadecimal.
 static void
-puthex(u16 action, u32 val)
+puthex(u16 action, u32 val, int width)
 {
-    putsinglehex(action, (val >> 28) & 0xf);
-    putsinglehex(action, (val >> 24) & 0xf);
-    putsinglehex(action, (val >> 20) & 0xf);
-    putsinglehex(action, (val >> 16) & 0xf);
-    putsinglehex(action, (val >> 12) & 0xf);
-    putsinglehex(action, (val >> 8) & 0xf);
-    putsinglehex(action, (val >> 4) & 0xf);
-    putsinglehex(action, (val >> 0) & 0xf);
+    if (!width) {
+        u32 tmp = val;
+        width = 1;
+        if (tmp > 0xffff) {
+            width += 4;
+            tmp >>= 16;
+        }
+        if (tmp > 0xff) {
+            width += 2;
+            tmp >>= 8;
+        }
+        if (tmp > 0xf)
+            width += 1;
+    }
+
+    switch (width) {
+    default: putsinglehex(action, (val >> 28) & 0xf);
+    case 7:  putsinglehex(action, (val >> 24) & 0xf);
+    case 6:  putsinglehex(action, (val >> 20) & 0xf);
+    case 5:  putsinglehex(action, (val >> 16) & 0xf);
+    case 4:  putsinglehex(action, (val >> 12) & 0xf);
+    case 3:  putsinglehex(action, (val >> 8) & 0xf);
+    case 2:  putsinglehex(action, (val >> 4) & 0xf);
+    case 1:  putsinglehex(action, (val >> 0) & 0xf);
+    }
 }
 
 static inline int
@@ -165,10 +182,12 @@
             continue;
         }
         const char *n = s+1;
+        int field_width = 0;
         for (;;) {
             c = GET_GLOBAL(*(u8*)n);
             if (!isdigit(c))
                 break;
+            field_width = field_width * 10 + c - '0';
             n++;
         }
         if (c == 'l') {
@@ -195,9 +214,13 @@
             putuint(action, val);
             break;
         case 'p':
+            /* %p always has 0x prepended */
+            putc(action, '0');
+            putc(action, 'x');
+            field_width = 8;
         case 'x':
             val = va_arg(args, s32);
-            puthex(action, val);
+            puthex(action, val, field_width);
             break;
         case 'c':
             val = va_arg(args, int);
@@ -264,12 +287,12 @@
     while (len) {
         if (count % 8 == 0) {
             putc(0, '\n');
-            puthex(0, count*4);
+            puthex(0, count*4, 8);
             putc(0, ':');
         } else {
             putc(0, ' ');
         }
-        puthex(0, *(u32*)d);
+        puthex(0, *(u32*)d, 8);
         count++;
         len-=4;
         d+=4;
@@ -284,11 +307,11 @@
         dprintf(1, "  NULL\n");
         return;
     }
-    dprintf(1, "  a=%x b=%x c=%x d=%x si=%x di=%x\n"
+    dprintf(1, "   a=%08x  b=%08x  c=%08x  d=%08x si=%08x di=%08x\n"
             , regs->eax, regs->ebx, regs->ecx, regs->edx
             , regs->esi, regs->edi);
-    dprintf(1, "  ds=%x es=%x ip=%x cs=%x f=%x r=%p\n"
-            , regs->ds, regs->es, regs->ip, regs->cs, regs->flags, regs);
+    dprintf(1, "  ds=%08x es=%08x ip=%08x cs=%08x  f=%08x  r=%08x\n"
+            , regs->ds, regs->es, regs->ip, regs->cs, regs->flags, (u32)regs);
 }
 
 // Report entry to an Interrupt Service Routine (ISR).