Changeset 280a27e in mainline for generic/src/debug/print.c
- Timestamp:
- 2006-04-16T13:16:44Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 50de918
- Parents:
- c624b96
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/debug/print.c
rc624b96 r280a27e 1 1 /* 2 2 * Copyright (C) 2001-2004 Jakub Jermar 3 * Copyright (C) 2006 Josef Cejka 3 4 * All rights reserved. 4 5 * … … 35 36 #include <arch.h> 36 37 37 static char digits[] = "0123456789abcdef"; /**< Hexadecimal characters */38 38 SPINLOCK_INITIALIZE(printflock); /**< printf spinlock */ 39 39 40 41 /** Print NULL terminated string 42 * 43 * Print characters from str using putchar() until 44 * \\0 character is reached. 45 * 46 * @param str Characters to print. 40 #define __PRINTF_FLAG_PREFIX 0x00000001 /* show prefixes 0x or 0*/ 41 #define __PRINTF_FLAG_SIGNED 0x00000002 /* signed / unsigned number */ 42 #define __PRINTF_FLAG_ZEROPADDED 0x00000004 /* print leading zeroes */ 43 #define __PRINTF_FLAG_LEFTALIGNED 0x00000010 /* align to left */ 44 #define __PRINTF_FLAG_SHOWPLUS 0x00000020 /* always show + sign */ 45 #define __PRINTF_FLAG_SPACESIGN 0x00000040 /* print space instead of plus */ 46 #define __PRINTF_FLAG_BIGCHARS 0x00000080 /* show big characters */ 47 #define __PRINTF_FLAG_NEGATIVE 0x00000100 /* number has - sign */ 48 49 #define PRINT_NUMBER_BUFFER_SIZE (64+5) /* Buffer big enought for 64 bit number 50 * printed in base 2, sign, prefix and 51 * 0 to terminate string.. (last one is only for better testing 52 * end of buffer by zero-filling subroutine) 53 */ 54 typedef enum { 55 PrintfQualifierByte = 0, 56 PrintfQualifierShort, 57 PrintfQualifierInt, 58 PrintfQualifierLong, 59 PrintfQualifierLongLong, 60 PrintfQualifierNative, 61 PrintfQualifierPointer 62 } qualifier_t; 63 64 static char digits_small[] = "0123456789abcdef"; /* Small hexadecimal characters */ 65 static char digits_big[] = "0123456789ABCDEF"; /* Big hexadecimal characters */ 66 67 static inline int isdigit(int c) 68 { 69 return ((c >= '0' )&&( c <= '9')); 70 } 71 72 static __native strlen(const char *str) 73 { 74 __native counter = 0; 75 76 while (str[counter] != 0) { 77 counter++; 78 } 79 80 return counter; 81 } 82 83 /** Print one string without adding \n at end 84 * Dont use this function directly - printflock is not locked here 85 * */ 86 static int putstr(const char *str) 87 { 88 int count; 89 if (str == NULL) { 90 str = "(NULL)"; 91 } 92 93 for (count = 0; str[count] != 0; count++) { 94 putchar(str[count]); 95 } 96 return count; 97 } 98 99 /** Print count characters from buffer to output 47 100 * 48 101 */ 49 static void print_str(const char *str) 50 { 51 int i = 0; 52 char c; 53 char errstr[] = "(NULL)"; 54 55 if (str == NULL) { 56 while ((c = errstr[i++])) 57 putchar(c); 58 return; 59 } 60 61 while ((c = str[i++])) 62 putchar(c); 63 } 64 65 66 /** Print hexadecimal digits 67 * 68 * Print fixed count of hexadecimal digits from 69 * the number num. The digits are printed in 70 * natural left-to-right order starting with 71 * the width-th digit. 72 * 73 * @param num Number containing digits. 74 * @param width Count of digits to print. 75 * 102 static int putnchars(const char *buffer, __native count) 103 { 104 int i; 105 if (buffer == NULL) { 106 buffer = "(NULL)"; 107 count = 6; 108 } 109 110 for (i = 0; i < count; i++) { 111 putchar(buffer[i]); 112 } 113 114 return count; 115 } 116 117 /** Print one formatted character 118 * @param c character to print 119 * @param width 120 * @param flags 121 * @return number of printed characters or EOF 76 122 */ 77 static void print_fixed_hex(const __u64 num, const int width) 78 { 79 int i; 80 81 for (i = width*8 - 4; i >= 0; i -= 4) 82 putchar(digits[(num>>i) & 0xf]); 123 static int print_char(char c, int width, __u64 flags) 124 { 125 int counter = 0; 126 127 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 128 while (--width > 0) { /* one space is consumed by character itself hence predecrement */ 129 /* FIXME: painful slow */ 130 putchar(' '); 131 ++counter; 132 } 133 } 134 135 putchar(c); 136 ++counter; 137 138 while (--width > 0) { /* one space is consumed by character itself hence predecrement */ 139 putchar(' '); 140 ++counter; 141 } 142 143 return counter; 144 } 145 146 /** Print one string 147 * @param s string 148 * @param width 149 * @param precision 150 * @param flags 151 * @return number of printed characters or EOF 152 */ 153 154 static int print_string(char *s, int width, int precision, __u64 flags) 155 { 156 int counter = 0; 157 __native size; 158 159 if (s == NULL) { 160 return putstr("(NULL)"); 161 } 162 163 size = strlen(s); 164 165 /* print leading spaces */ 166 167 if (precision == 0) 168 precision = size; 169 170 width -= precision; 171 172 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 173 while (width-- > 0) { 174 putchar(' '); 175 counter++; 176 } 177 } 178 179 while (precision > size) { 180 precision--; 181 putchar(' '); 182 ++counter; 183 } 184 185 if (putnchars(s, precision) == EOF) { 186 return EOF; 187 } 188 189 counter += precision; 190 191 while (width-- > 0) { 192 putchar(' '); 193 ++counter; 194 } 195 196 return ++counter; 83 197 } 84 198 … … 90 204 * 91 205 * @param num Number to print. 206 * @param width 207 * @param precision 92 208 * @param base Base to print the number in (should 93 209 * be in range 2 .. 16). 210 * @param flags output modifiers 211 * @return number of written characters or EOF 94 212 * 95 213 */ 96 static void print_number(const __native num, const unsigned int base) 97 { 98 int val = num; 99 char d[sizeof(__native)*8+1]; /* this is good enough even for base == 2 */ 100 int i = sizeof(__native)*8-1; 101 102 do { 103 d[i--] = digits[val % base]; 104 } while (val /= base); 105 106 d[sizeof(__native)*8] = 0; 107 print_str(&d[i + 1]); 214 static int print_number(__u64 num, int width, int precision, int base , __u64 flags) 215 { 216 char *digits = digits_small; 217 char d[PRINT_NUMBER_BUFFER_SIZE]; /* this is good enough even for base == 2, prefix and sign */ 218 char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1]; 219 int size = 0; 220 int written = 0; 221 char sgn; 222 223 if (flags & __PRINTF_FLAG_BIGCHARS) 224 digits = digits_big; 225 226 *ptr-- = 0; /* Put zero at end of string */ 227 228 if (num == 0) { 229 *ptr-- = '0'; 230 size++; 231 } else { 232 do { 233 *ptr-- = digits[num % base]; 234 size++; 235 } while (num /= base); 236 } 237 238 /* Collect sum of all prefixes/signs/... to calculate padding and leading zeroes */ 239 if (flags & __PRINTF_FLAG_PREFIX) { 240 switch(base) { 241 case 2: /* Binary formating is not standard, but usefull */ 242 size += 2; 243 break; 244 case 8: 245 size++; 246 break; 247 case 16: 248 size += 2; 249 break; 250 } 251 } 252 253 sgn = 0; 254 if (flags & __PRINTF_FLAG_SIGNED) { 255 if (flags & __PRINTF_FLAG_NEGATIVE) { 256 sgn = '-'; 257 size++; 258 } else if (flags & __PRINTF_FLAG_SHOWPLUS) { 259 sgn = '+'; 260 size++; 261 } else if (flags & __PRINTF_FLAG_SPACESIGN) { 262 sgn = ' '; 263 size++; 264 } 265 } 266 267 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 268 flags &= ~__PRINTF_FLAG_ZEROPADDED; 269 } 270 271 /* if number is leftaligned or precision is specified then zeropadding is ignored */ 272 if (flags & __PRINTF_FLAG_ZEROPADDED) { 273 if ((precision == 0) && (width > size)) { 274 precision = width - size; 275 } 276 } 277 278 /* print leading spaces */ 279 if (size > precision) /* We must print whole number not only a part */ 280 precision = size; 281 282 width -= precision; 283 284 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 285 while (width-- > 0) { 286 putchar(' '); 287 written++; 288 } 289 } 290 291 /* print sign */ 292 if (sgn) { 293 putchar(sgn); 294 written++; 295 } 296 297 /* print prefix */ 298 299 if (flags & __PRINTF_FLAG_PREFIX) { 300 switch(base) { 301 case 2: /* Binary formating is not standard, but usefull */ 302 putchar('0'); 303 if (flags & __PRINTF_FLAG_BIGCHARS) { 304 putchar('B'); 305 } else { 306 putchar('b'); 307 } 308 written += 2; 309 break; 310 case 8: 311 putchar('o'); 312 written++; 313 break; 314 case 16: 315 putchar('0'); 316 if (flags & __PRINTF_FLAG_BIGCHARS) { 317 putchar('X'); 318 } else { 319 putchar('x'); 320 } 321 written += 2; 322 break; 323 } 324 } 325 326 /* print leading zeroes */ 327 precision -= size; 328 while (precision-- > 0) { 329 putchar('0'); 330 written++; 331 } 332 333 334 /* print number itself */ 335 336 written += putstr(++ptr); 337 338 /* print ending spaces */ 339 340 while (width-- > 0) { 341 putchar(' '); 342 written++; 343 } 344 345 return written; 108 346 } 109 347 … … 165 403 * @param fmt Formatting NULL terminated string. 166 404 */ 167 void printf(const char *fmt, ...) 168 { 169 int irqpri, i = 0; 405 int printf(const char *fmt, ...) 406 { 407 int irqpri; 408 int i = 0, j = 0; /* i is index of currently processed char from fmt, j is index to the first not printed nonformating character */ 409 int end; 410 int counter; /* counter of printed characters */ 411 int retval; /* used to store return values from called functions */ 170 412 va_list ap; 171 char c; 413 char c; 414 qualifier_t qualifier; /* type of argument */ 415 int base; /* base in which will be parameter (numbers only) printed */ 416 __u64 number; /* argument value */ 417 __native size; /* byte size of integer parameter */ 418 int width, precision; 419 __u64 flags; 420 421 counter = 0; 172 422 173 423 va_start(ap, fmt); 174 424 175 425 irqpri = interrupts_disable(); 176 426 spinlock_lock(&printflock); 177 427 178 while ((c = fmt[i++])) { 179 switch (c) { 180 181 /* control character */ 182 case '%': 183 184 switch (c = fmt[i++]) { 185 186 /* percentile itself */ 187 case '%': 188 break; 189 190 /* 191 * String and character conversions. 192 */ 193 case 's': 194 print_str(va_arg(ap, char_ptr)); 195 goto loop; 196 197 case 'c': 198 c = (char) va_arg(ap, int); 199 break; 200 201 /* 202 * Hexadecimal conversions with fixed width. 203 */ 204 case 'P': 205 print_str("0x"); 206 case 'p': 207 print_fixed_hex(va_arg(ap, __native), sizeof(__native)); 208 goto loop; 209 210 case 'Q': 211 print_str("0x"); 212 case 'q': 213 print_fixed_hex(va_arg(ap, __u64), INT64); 214 goto loop; 215 216 case 'L': 217 print_str("0x"); 218 case 'l': 219 print_fixed_hex(va_arg(ap, __native), INT32); 220 goto loop; 221 222 case 'W': 223 print_str("0x"); 224 case 'w': 225 print_fixed_hex(va_arg(ap, __native), INT16); 226 goto loop; 227 228 case 'B': 229 print_str("0x"); 230 case 'b': 231 print_fixed_hex(va_arg(ap, __native), INT8); 232 goto loop; 233 234 /* 235 * Decimal and hexadecimal conversions. 236 */ 237 case 'd': 238 print_number(va_arg(ap, __native), 10); 239 goto loop; 240 241 case 'X': 242 print_str("0x"); 243 case 'x': 244 print_number(va_arg(ap, __native), 16); 245 goto loop; 246 247 /* 248 * Bad formatting. 249 */ 250 default: 428 429 while ((c = fmt[i])) { 430 /* control character */ 431 if (c == '%' ) { 432 /* print common characters if any processed */ 433 if (i > j) { 434 if ((retval = putnchars(&fmt[j], (__native)(i - j))) == EOF) { /* error */ 435 counter = -counter; 436 goto out; 437 } 438 counter += retval; 439 } 440 441 j = i; 442 /* parse modifiers */ 443 flags = 0; 444 end = 0; 445 446 do { 447 ++i; 448 switch (c = fmt[i]) { 449 case '#': flags |= __PRINTF_FLAG_PREFIX; break; 450 case '-': flags |= __PRINTF_FLAG_LEFTALIGNED; break; 451 case '+': flags |= __PRINTF_FLAG_SHOWPLUS; break; 452 case ' ': flags |= __PRINTF_FLAG_SPACESIGN; break; 453 case '0': flags |= __PRINTF_FLAG_ZEROPADDED; break; 454 default: end = 1; 455 }; 456 457 } while (end == 0); 458 459 /* width & '*' operator */ 460 width = 0; 461 if (isdigit(fmt[i])) { 462 while (isdigit(fmt[i])) { 463 width *= 10; 464 width += fmt[i++] - '0'; 465 } 466 } else if (fmt[i] == '*') { 467 /* get width value from argument list*/ 468 i++; 469 width = (int)va_arg(ap, int); 470 if (width < 0) { 471 /* negative width means to set '-' flag */ 472 width *= -1; 473 flags |= __PRINTF_FLAG_LEFTALIGNED; 474 } 475 } 476 477 /* precision and '*' operator */ 478 precision = 0; 479 if (fmt[i] == '.') { 480 ++i; 481 if (isdigit(fmt[i])) { 482 while (isdigit(fmt[i])) { 483 precision *= 10; 484 precision += fmt[i++] - '0'; 485 } 486 } else if (fmt[i] == '*') { 487 /* get precision value from argument list*/ 488 i++; 489 precision = (int)va_arg(ap, int); 490 if (precision < 0) { 491 /* negative precision means to ignore it */ 492 precision = 0; 493 } 494 } 495 } 496 497 switch (fmt[i++]) { 498 /** TODO: unimplemented qualifiers: 499 * t ptrdiff_t - ISO C 99 500 */ 501 case 'h': /* char or short */ 502 qualifier = PrintfQualifierShort; 503 if (fmt[i] == 'h') { 504 i++; 505 qualifier = PrintfQualifierByte; 506 } 507 break; 508 case 'l': /* long or long long*/ 509 qualifier = PrintfQualifierLong; 510 if (fmt[i] == 'l') { 511 i++; 512 qualifier = PrintfQualifierLongLong; 513 } 514 break; 515 case 'z': /* __native */ 516 qualifier = PrintfQualifierNative; 517 break; 518 default: 519 qualifier = PrintfQualifierInt; /* default type */ 520 --i; 521 } 522 523 base = 10; 524 525 switch (c = fmt[i]) { 526 527 /* 528 * String and character conversions. 529 */ 530 case 's': 531 if ((retval = print_string(va_arg(ap, char*), width, precision, flags)) == EOF) { 532 counter = -counter; 533 goto out; 534 }; 535 536 counter += retval; 537 j = i + 1; 538 goto next_char; 539 case 'c': 540 c = va_arg(ap, unsigned int); 541 if ((retval = print_char(c, width, flags )) == EOF) { 542 counter = -counter; 543 goto out; 544 }; 545 546 counter += retval; 547 j = i + 1; 548 goto next_char; 549 550 /* 551 * Integer values 552 */ 553 case 'P': /* pointer */ 554 flags |= __PRINTF_FLAG_BIGCHARS; 555 case 'p': 556 flags |= __PRINTF_FLAG_PREFIX; 557 base = 16; 558 qualifier = PrintfQualifierPointer; 559 break; 560 case 'b': 561 base = 2; 562 break; 563 case 'o': 564 base = 8; 565 break; 566 case 'd': 567 case 'i': 568 flags |= __PRINTF_FLAG_SIGNED; 569 case 'u': 570 break; 571 case 'X': 572 flags |= __PRINTF_FLAG_BIGCHARS; 573 case 'x': 574 base = 16; 575 break; 576 /* percentile itself */ 577 case '%': 578 j = i; 579 goto next_char; 580 /* 581 * Bad formatting. 582 */ 583 default: 584 /* Unknown format 585 * now, the j is index of '%' so we will 586 * print whole bad format sequence 587 */ 588 goto next_char; 589 } 590 591 592 /* Print integers */ 593 /* print number */ 594 switch (qualifier) { 595 case PrintfQualifierByte: 596 size = sizeof(unsigned char); 597 number = (__u64)va_arg(ap, unsigned int); 598 break; 599 case PrintfQualifierShort: 600 size = sizeof(unsigned short); 601 number = (__u64)va_arg(ap, unsigned int); 602 break; 603 case PrintfQualifierInt: 604 size = sizeof(unsigned int); 605 number = (__u64)va_arg(ap, unsigned int); 606 break; 607 case PrintfQualifierLong: 608 size = sizeof(unsigned long); 609 number = (__u64)va_arg(ap, unsigned long); 610 break; 611 case PrintfQualifierLongLong: 612 size = sizeof(unsigned long long); 613 number = (__u64)va_arg(ap, unsigned long long); 614 break; 615 case PrintfQualifierPointer: 616 size = sizeof(void *); 617 number = (__u64)(unsigned long)va_arg(ap, void *); 618 break; 619 case PrintfQualifierNative: 620 size = sizeof(__native); 621 number = (__u64)va_arg(ap, __native); 622 break; 623 default: /* Unknown qualifier */ 624 counter = -counter; 625 goto out; 626 627 } 628 629 if (flags & __PRINTF_FLAG_SIGNED) { 630 if (number & (0x1 << (size*8 - 1))) { 631 flags |= __PRINTF_FLAG_NEGATIVE; 632 633 if (size == sizeof(__u64)) { 634 number = -((__s64)number); 635 } else { 636 number = ~number; 637 number &= (~((0xFFFFFFFFFFFFFFFFll) << (size * 8))); 638 number++; 639 } 640 } 641 } 642 643 if ((retval = print_number(number, width, precision, base, flags)) == EOF ) { 644 counter = -counter; 251 645 goto out; 252 } 253 254 default: putchar(c); 646 }; 647 648 counter += retval; 649 j = i + 1; 650 } 651 next_char: 652 653 ++i; 654 } 655 656 if (i > j) { 657 if ((retval = putnchars(&fmt[j], (__native)(i - j))) == EOF) { /* error */ 658 counter = -counter; 659 goto out; 255 660 } 256 257 loop: 258 ; 259 } 260 661 counter += retval; 662 } 261 663 out: 262 664 spinlock_unlock(&printflock); … … 264 666 265 667 va_end(ap); 266 } 668 return counter; 669 } 670
Note:
See TracChangeset
for help on using the changeset viewer.