📄 logging.c
字号:
} while ((fch >= '0') && (fch <= '9')) { *width = (((*width) * 10) + (fch - '0')); fch = *(++(*format)); } } if (fch == 'l') { /* skip 'l' in "%lx", etc. */ *longval = TRUE; fch = *(++(*format)); } return fch;}/* * Convert the long value ival to text, writing the result character * by character using the 'CHAROUT' macro in hexadecimal. * * fch is used to specify one of the three variants used: 'p' for * the pointer type (0x00224AFDB etc) 'X' for hex numbers with leading * 0x and capital letter A-F, 'x' for hex numbers with no leading 0x * and lower-case a-f. * * width is the field width, which may be exceeded if representation * of the value demands, pad is TRUE if the value should be padded to * to the left up to the width * */static int log_itoh(char fch, unsigned long uval, int width, int padzero){ int count, loop; int len = 0, mark = FALSE; const char *hextab; char buffer[12]; /* stack space used to hold number */ if (fch == 'X' || fch == 'p') { hextab = hextab1; if (fch == 'p') mark = TRUE; } else { hextab = hextab2; } /* * Read each nibble from high to low; unless it's zero copy the * hex character equivalent into the buffer. Note we start from * bit (n-4) where (n) is the number of bits in the word, as * loop is the base bit number (i.e. the nibble is from the bit * at 'loop' to the bit at 'loop+3'. */ count = 0; for (loop = (sizeof(long) * 8) - 4; loop >= 0; loop -= 4) { int nibble = (uval >> loop) & 0xF; if (nibble != 0 || count != 0) { buffer[count++] = hextab[nibble]; } } if (count == 0) buffer[count++] = '0'; if (width != 0) { width -= count + (mark? 2: 0); if (padzero) { if (mark) { CHAROUT('0'); CHAROUT('x'); len += 2; } for (; (width > 0); width--) { CHAROUT('0'); len++; } } else { for (; (width > 0); width--) { CHAROUT(' '); len++; } if (mark) { CHAROUT('0'); CHAROUT('x'); len += 2; } } } else if (mark) { CHAROUT('0'); CHAROUT('x'); len += 2; } for (loop = 0; loop < count; loop++) { CHAROUT(buffer[loop]); len++; } return len;}/* * Convert the long value ival to text, writing the result character * by character using the 'CHAROUT' macro in hexadecimal. * * fch is used to specify one of the three variants used: 'p' for * the pointer type (0x00224AFDB etc) 'X' for hex numbers with leading * 0x and capital letter A-F, 'x' for hex numbers with no leading 0x * and lower-case a-f. * * width is the field width, which may be exceeded if representation * of the value demands, pad is TRUE if the value should be padded to * to the left up to the width * */static int buf_itoh(char *buf, unsigned long uval, int width, int padzero){ int count, loop; int len = 0; char buffer[12]; /* stack space used to hold number */ count = 0; for (loop = (sizeof(long) * 8) - 4; loop >= 0; loop -= 4) { int nibble = (uval >> loop) & 0xF; if (nibble != 0 || count != 0) { buffer[count++] = hextab2[nibble]; } } if (count == 0) buffer[count++] = '0'; if (width != 0) { width -= count; for (; (width > 0); width--) { *buf++ = (padzero)?'0':' '; len++; } } for (loop = 0; loop < count; loop++) { *buf++ = (buffer[loop]); len++; } return len;}/* * Convert the long value ival to text, writing the result character * by character using the 'CHAROUT' macro in decimal. * * width is the field width, which may be exceeded if representation * of the value demands, padzero is TRUE if the value should be padded to * to the left up to the width, sign is TRUE if the value should be * considered to be a signed number. * * note: the sign char is not counted in the field width [BUG] */static int log_itod(long ival, int width, int padzero, int sign){ int count; int len = 0; int writeminus = FALSE; char buffer[12]; /* stack space used to hold number */ if (sign && (ival < 0)) { ival = -ival; writeminus = TRUE; } /* * The simplest method of displaying numbers is to * provide a small recursive routine. However, to reduce * stack usage the following non-recursive solution is * used. */ /* * Place the conversion into the buffer in * reverse order: */ count = 0; while (ival != 0) { buffer[count++] = (char)('0' + ((unsigned long)ival % 10)); ival = ((unsigned long)ival / 10); } if (count == 0) buffer[count++] = '0'; /* * Check if we are placing the data in a fixed * width field, and write the minus in the right * place relative to the padding. */ if (width != 0) { width -= count + (writeminus ? 1 : 0); if (padzero) { if (writeminus) { CHAROUT('-'); len++; } for (; (width > 0); width--) { CHAROUT('0'); len++; } } else { for (; (width > 0); width--) { CHAROUT(' '); len++; } if (writeminus) { CHAROUT('-'); len++; } } } else if (writeminus) { CHAROUT('-'); len++; } /* then display the buffer in reverse order */ for (; (count != 0); count--) { CHAROUT(buffer[count - 1]); len++; } return len;}/* * Convert the zero-terminated string stored in memory at address 'string' * to characters passed to CHAROUT. If width is non-zero, and is larger * than the string length, then pad characters will be used to make up the * string to this length, padding on the right. If the pointer value is NULL * the characters "(nil)" will be written instead. */static int log_ptos(char *string, int width){ int len = 0; if (string != NULL) { while (*string) { /* * NOTE: We do not use "*string++" as the macro * parameter, since we do not know how many times * the parameter may be expanded within the macro. */ CHAROUT(*string); len++; string++; } if (width != 0) { width -= len; for (; (width > 0); width--) { CHAROUT(' '); len++; } } } else { CHAROUT('('); CHAROUT('n'); CHAROUT('i'); CHAROUT('l'); CHAROUT(')'); len += 5; } return len;}/* * Simulate 'printf' using the CHAROUT macro. Read a format string to interpret * the n args following (n >= 0) as pointers, integers or characters (as ints). * NOTE: Double, float values, precision values (%.8) and variable width fields * are not supported. * * The number of characters printed is returned. */int log_printf(char *format, ...){ va_list args; int l; va_start(args, format); l = log_vprintf(format, args); va_end(args); return l;}static int log_vprintf(char *format, va_list args){ int len = 0; while ((format != NULL) && (*format != '\0')) { if (*format == '%') { char fch; /* get format character (skipping '%') */ int width = 0; /* No field width by default */ int padzero = FALSE; /* By default we pad with spaces */ int longval = FALSE; /* seen 'ld' etc? */ fch = log_readformat(&format, &width, &padzero, &longval); switch (fch) { case 'c': /* char => ignore longval */ { int ival = va_arg(args, int); CHAROUT((char)ival); len++; break; } case 'p': /* hexadecimal pointer => ignore longval */ { void *vp = va_arg(args, void *); if (width == 0) { /* default format: 8 digits wide, leading "0x", zero padded */ width = 8; padzero = TRUE; } len += log_itoh(fch, (unsigned long)vp, width, padzero); break; } case 'X': case 'x': /* hexadecimal */ /* default format: min width */ if (longval) { unsigned long luval = va_arg(args, unsigned long); len += log_itoh(fch, luval, width, padzero); } else { unsigned int uval = va_arg(args, unsigned int); len += log_itoh(fch, (unsigned long)uval, width, padzero); } break; case 'i': case 'd': /* decimal */ /* default format: min width */ if (longval) { long lival = va_arg(args, long); len += log_itod(lival, width, padzero, TRUE); } else { int ival = va_arg(args, int); len += log_itod((long)ival, width, padzero, TRUE); } break; case 'u': /* unsigned decimal */ /* default format: min width */ if (longval) { unsigned long lival = va_arg(args, unsigned long); len += log_itod((long)lival, width, padzero, FALSE); } else { unsigned int ival = va_arg(args, unsigned int); len += log_itod((long)ival, width, padzero, FALSE); } break; case 's': /* string => ignore longval */ { char *string = va_arg(args, char *); len += log_ptos(string, width); } break; case '\0': /* * string terminated by '%' character, bodge things * to prepare for default "format++" below */ format--; break; default: /* just display the character */ CHAROUT(*format); len++; break; } } else { CHAROUT(*format); len++; } format++; } return len;}/* * Routine to return the bit number of the single bit set in 'x'. * * Multiply the value 'x' by the 'magic number' 0x450FBAF * extracting the most significant 6 bits of the 32 bit * answer. The result is a unique value. * take this unique value and return it's bit postition via a[]. * * Algorithm courtesy D. Seal. */int __rt_bitnumber(unsigned long x){ static unsigned char a[64] = { 0, 0, 1, 12, 2, 6, 0, 13, 3, 0, 7, 0, 0, 0, 0, 14, 10, 4, 0, 0, 8, 0, 0, 25, 0, 0, 0, 0, 0, 21, 27, 15, 31, 11, 5, 0, 0, 0, 0, 0, 9, 0, 0, 24, 0, 0, 20, 26, 30, 0, 0, 0, 0, 23, 0, 19, 29, 0, 22, 18, 28, 17, 16, 0 }; if (x == 0) return 0xff; x *= 0x11; /* multiply by 17 -> total factor 0x11 */ x *= 0x41; /* multiply by 65 -> total factor 0x451 */ x *= 0xffff; /* multiply by 65535 -> total factor 0x450FBAF */ return (int)(a[x >> 26]);}/* * Save the current format and args in the message save buffer. * The format must be parsed to determine the number and approximate * types of the args, then these args must be saved in the buffer. * The data: * * ulong format, (line, file), flags, <args>, ulong count * * where (line,file) are compile-time optional. * * should be appended to the message buffer, starting at savebufinsert, * when this routine exits. Args are all converted to unsigned long * type, as this is the type of the buffer. Note that the count * value includes itself and the format, so it's minimum value is 2. * A count of zero is used in the buffer to indicate start-of-data. */static void log_logsave(struct LogSaveBuffer *sb, WarnLevel level, char *format, va_list args){ int argcount = 0; char *file; int line; log_id id; /* * This code assumes pointers will fit in an unsigned long value. If * this is not true it WILL BREAK!! */ /* ASSERT(sizeof(unsigned long) >= sizeof(void *), "pointer size problem"); */ sb->message++; log_saveitem(sb, (unsigned long)format); log_getmsginfo(&file, &line, &id); log_saveitem(sb, (unsigned long)line); log_saveitem(sb, (unsigned long)file); log_saveitem(sb, level | (id & 0xff) << 8); while ((format != NULL) && (*format != '\0')) { if (*format == '%') { char fch; /* get format character (skipping '%') */ int ival; /* holder for integer arguments */ char *string; /* holder for string arguments */ void *vp; int longval = FALSE; /* seen 'ld' etc? */ /* these aren't needed, except by log_readformat() ... sigh */ int width = 0; int padzero = FALSE;/* seen '04' etc? */ fch = log_readformat(&format, &width, &padzero, &longval); switch (fch) { case 'c': /* char */ ival = va_arg(args, int); log_saveitem(sb, (unsigned long)ival); argcount++; break; case 'p': /* hexadecimal pointer */ vp = va_arg(args, void *); log_saveitem(sb, (unsigned long)vp); argcount++; break; case 'd': case 'u': case 'i': case 'x':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -