Changeset a35b458 in mainline for boot/generic/src
- Timestamp:
- 2018-03-02T20:10:49Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- Location:
- boot/generic/src
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/generic/src/balloc.c
r3061bc1 ra35b458 49 49 if (alignment == 0) 50 50 return NULL; 51 51 52 52 /* Enforce minimal alignment. */ 53 53 alignment = ALIGN_UP(alignment, 4); 54 54 55 55 uintptr_t addr = phys_base + ALIGN_UP(ballocs->size, alignment); 56 56 57 57 if (ALIGN_UP(ballocs->size, alignment) + size >= max_size) 58 58 return NULL; 59 59 60 60 ballocs->size = ALIGN_UP(ballocs->size, alignment) + size; 61 61 62 62 return (void *) addr; 63 63 } -
boot/generic/src/inflate.c
r3061bc1 ra35b458 103 103 size_t destlen; /**< Output buffer size */ 104 104 size_t destcnt; /**< Position in the output buffer */ 105 105 106 106 uint8_t *src; /**< Input buffer */ 107 107 size_t srclen; /**< Input buffer size */ 108 108 size_t srccnt; /**< Position in the input buffer */ 109 109 110 110 uint16_t bitbuf; /**< Bit buffer */ 111 111 size_t bitlen; /**< Number of bits in the bit buffer */ 112 112 113 113 bool overrun; /**< Overrun condition */ 114 114 } inflate_state_t; … … 240 240 /* Bit accumulator for at least 20 bits */ 241 241 uint32_t val = state->bitbuf; 242 242 243 243 while (state->bitlen < cnt) { 244 244 if (state->srccnt == state->srclen) { … … 246 246 return 0; 247 247 } 248 248 249 249 /* Load 8 more bits */ 250 250 val |= ((uint32_t) state->src[state->srccnt]) << state->bitlen; … … 252 252 state->bitlen += 8; 253 253 } 254 254 255 255 /* Update bits in the buffer */ 256 256 state->bitbuf = (uint16_t) (val >> cnt); 257 257 state->bitlen -= cnt; 258 258 259 259 return ((uint16_t) (val & ((1 << cnt) - 1))); 260 260 } … … 275 275 state->bitbuf = 0; 276 276 state->bitlen = 0; 277 277 278 278 if (state->srccnt + 4 > state->srclen) 279 279 return ELIMIT; 280 280 281 281 uint16_t len = 282 282 state->src[state->srccnt] | (state->src[state->srccnt + 1] << 8); 283 283 uint16_t len_compl = 284 284 state->src[state->srccnt + 2] | (state->src[state->srccnt + 3] << 8); 285 285 286 286 /* Check block length and its complement */ 287 287 if (((int16_t) len) != ~((int16_t) len_compl)) 288 288 return EINVAL; 289 289 290 290 state->srccnt += 4; 291 291 292 292 /* Check input buffer size */ 293 293 if (state->srccnt + len > state->srclen) 294 294 return ELIMIT; 295 295 296 296 /* Check output buffer size */ 297 297 if (state->destcnt + len > state->destlen) 298 298 return ENOMEM; 299 299 300 300 /* Copy data */ 301 301 memcpy(state->dest + state->destcnt, state->src + state->srccnt, len); 302 302 state->srccnt += len; 303 303 state->destcnt += len; 304 304 305 305 return EOK; 306 306 } … … 323 323 size_t index = 0; /* Index of the first code of the given length 324 324 in the symbol table */ 325 325 326 326 size_t len; /* Current number of bits in the code */ 327 327 for (len = 1; len <= MAX_HUFFMAN_BIT; len++) { … … 329 329 code |= get_bits(state, 1); 330 330 CHECK_OVERRUN(*state); 331 331 332 332 uint16_t count = huffman->count[len]; 333 333 if (code < first + count) { … … 336 336 return EOK; 337 337 } 338 338 339 339 /* Update for next length */ 340 340 index += count; … … 343 343 code <<= 1; 344 344 } 345 345 346 346 return EINVAL; 347 347 } … … 364 364 for (len = 0; len <= MAX_HUFFMAN_BIT; len++) 365 365 huffman->count[len] = 0; 366 366 367 367 /* We assume that the lengths are within bounds */ 368 368 size_t symbol; 369 369 for (symbol = 0; symbol < n; symbol++) 370 370 huffman->count[length[symbol]]++; 371 371 372 372 if (huffman->count[0] == n) { 373 373 /* The code is complete, but decoding will fail */ 374 374 return 0; 375 375 } 376 376 377 377 /* Check for an over-subscribed or incomplete set of lengths */ 378 378 int16_t left = 1; … … 385 385 } 386 386 } 387 387 388 388 /* Generate offsets into symbol table */ 389 389 uint16_t offs[MAX_HUFFMAN_BIT + 1]; 390 390 391 391 offs[1] = 0; 392 392 for (len = 1; len < MAX_HUFFMAN_BIT; len++) 393 393 offs[len + 1] = offs[len] + huffman->count[len]; 394 394 395 395 for (symbol = 0; symbol < n; symbol++) { 396 396 if (length[symbol] != 0) { … … 399 399 } 400 400 } 401 401 402 402 return left; 403 403 } … … 422 422 { 423 423 uint16_t symbol; 424 424 425 425 do { 426 426 int err = huffman_decode(state, len_code, &symbol); … … 429 429 return err; 430 430 } 431 431 432 432 if (symbol < 256) { 433 433 /* Write out literal */ 434 434 if (state->destcnt == state->destlen) 435 435 return ENOMEM; 436 436 437 437 state->dest[state->destcnt] = (uint8_t) symbol; 438 438 state->destcnt++; … … 442 442 if (symbol >= 29) 443 443 return EINVAL; 444 444 445 445 size_t len = lens[symbol] + get_bits(state, lens_ext[symbol]); 446 446 CHECK_OVERRUN(*state); 447 447 448 448 /* Get distance */ 449 449 err = huffman_decode(state, dist_code, &symbol); 450 450 if (err != EOK) 451 451 return err; 452 452 453 453 size_t dist = dists[symbol] + get_bits(state, dists_ext[symbol]); 454 454 if (dist > state->destcnt) 455 455 return ENOENT; 456 456 457 457 if (state->destcnt + len > state->destlen) 458 458 return ENOMEM; 459 459 460 460 while (len > 0) { 461 461 /* Copy len bytes from distance bytes back */ … … 467 467 } 468 468 } while (symbol != 256); 469 469 470 470 return EOK; 471 471 } … … 510 510 huffman_t dyn_len_code; 511 511 huffman_t dyn_dist_code; 512 512 513 513 dyn_len_code.count = dyn_len_count; 514 514 dyn_len_code.symbol = dyn_len_symbol; 515 515 516 516 dyn_dist_code.count = dyn_dist_count; 517 517 dyn_dist_code.symbol = dyn_dist_symbol; 518 518 519 519 /* Get number of bits in each table */ 520 520 uint16_t nlen = get_bits(state, 5) + 257; 521 521 CHECK_OVERRUN(*state); 522 522 523 523 uint16_t ndist = get_bits(state, 5) + 1; 524 524 CHECK_OVERRUN(*state); 525 525 526 526 uint16_t ncode = get_bits(state, 4) + 4; 527 527 CHECK_OVERRUN(*state); 528 528 529 529 if ((nlen > MAX_LITLEN) || (ndist > MAX_DIST) 530 530 || (ncode > MAX_ORDER)) 531 531 return EINVAL; 532 532 533 533 /* Read code length code lengths */ 534 534 uint16_t index; … … 537 537 CHECK_OVERRUN(*state); 538 538 } 539 539 540 540 /* Set missing lengths to zero */ 541 541 for (index = ncode; index < MAX_ORDER; index++) 542 542 length[order[index]] = 0; 543 543 544 544 /* Build Huffman code */ 545 545 int16_t rc = huffman_construct(&dyn_len_code, length, MAX_ORDER); 546 546 if (rc != 0) 547 547 return EINVAL; 548 548 549 549 /* Read length/literal and distance code length tables */ 550 550 index = 0; … … 554 554 if (err != EOK) 555 555 return EOK; 556 556 557 557 if (symbol < 16) { 558 558 length[index] = symbol; … … 560 560 } else { 561 561 uint16_t len = 0; 562 562 563 563 if (symbol == 16) { 564 564 if (index == 0) 565 565 return EINVAL; 566 566 567 567 len = length[index - 1]; 568 568 symbol = get_bits(state, 2) + 3; … … 575 575 CHECK_OVERRUN(*state); 576 576 } 577 577 578 578 if (index + symbol > nlen + ndist) 579 579 return EINVAL; 580 580 581 581 while (symbol > 0) { 582 582 length[index] = len; … … 586 586 } 587 587 } 588 588 589 589 /* Check for end-of-block code */ 590 590 if (length[256] == 0) 591 591 return EINVAL; 592 592 593 593 /* Build Huffman tables for literal/length codes */ 594 594 rc = huffman_construct(&dyn_len_code, length, nlen); 595 595 if ((rc < 0) || ((rc > 0) && (dyn_len_code.count[0] + 1 != nlen))) 596 596 return EINVAL; 597 597 598 598 /* Build Huffman tables for distance codes */ 599 599 rc = huffman_construct(&dyn_dist_code, length + nlen, ndist); 600 600 if ((rc < 0) || ((rc > 0) && (dyn_dist_code.count[0] + 1 != ndist))) 601 601 return EINVAL; 602 602 603 603 return inflate_codes(state, &dyn_len_code, &dyn_dist_code); 604 604 } … … 622 622 /* Initialize the state */ 623 623 inflate_state_t state; 624 624 625 625 state.dest = (uint8_t *) dest; 626 626 state.destlen = destlen; 627 627 state.destcnt = 0; 628 628 629 629 state.src = (uint8_t *) src; 630 630 state.srclen = srclen; 631 631 state.srccnt = 0; 632 632 633 633 state.bitbuf = 0; 634 634 state.bitlen = 0; 635 635 636 636 state.overrun = false; 637 637 638 638 uint16_t last; 639 639 int ret = 0; 640 640 641 641 do { 642 642 /* Last block is indicated by a non-zero bit */ 643 643 last = get_bits(&state, 1); 644 644 CHECK_OVERRUN(state); 645 645 646 646 /* Block type */ 647 647 uint16_t type = get_bits(&state, 2); 648 648 CHECK_OVERRUN(state); 649 649 650 650 switch (type) { 651 651 case 0: … … 662 662 } 663 663 } while ((!last) && (ret == 0)); 664 664 665 665 return ret; 666 666 } -
boot/generic/src/memstr.c
r3061bc1 ra35b458 46 46 uint8_t *dp = (uint8_t *) dst; 47 47 const uint8_t *sp = (uint8_t *) src; 48 48 49 49 while (cnt-- != 0) 50 50 *dp++ = *sp++; 51 51 52 52 return dst; 53 53 } … … 67 67 { 68 68 uint8_t *dp = (uint8_t *) dst; 69 69 70 70 while (cnt-- != 0) 71 71 *dp++ = val; 72 72 73 73 return dst; 74 74 } … … 91 91 if (src == dst) 92 92 return dst; 93 93 94 94 /* Non-overlapping? */ 95 95 if ((dst >= src + cnt) || (src >= dst + cnt)) 96 96 return memcpy(dst, src, cnt); 97 97 98 98 uint8_t *dp; 99 99 const uint8_t *sp; 100 100 101 101 /* Which direction? */ 102 102 if (src > dst) { … … 104 104 dp = dst; 105 105 sp = src; 106 106 107 107 while (cnt-- != 0) 108 108 *dp++ = *sp++; … … 111 111 dp = dst + (cnt - 1); 112 112 sp = src + (cnt - 1); 113 113 114 114 while (cnt-- != 0) 115 115 *dp-- = *sp--; 116 116 } 117 117 118 118 return dst; 119 119 } -
boot/generic/src/printf.c
r3061bc1 ra35b458 37 37 int ret; 38 38 va_list args; 39 39 40 40 va_start(args, fmt); 41 41 42 42 ret = vprintf(fmt, args); 43 43 44 44 va_end(args); 45 45 46 46 return ret; 47 47 } -
boot/generic/src/printf_core.c
r3061bc1 ra35b458 138 138 if (str == NULL) 139 139 return printf_putnchars(nullstr, str_size(nullstr), ps); 140 140 141 141 return ps->str_write((void *) str, str_size(str), ps->data); 142 142 } … … 154 154 if (!ascii_check(ch)) 155 155 return ps->str_write((void *) &invalch, 1, ps->data); 156 156 157 157 return ps->str_write(&ch, 1, ps->data); 158 158 } … … 180 180 } 181 181 } 182 182 183 183 if (printf_putchar(ch, ps) > 0) 184 184 counter++; 185 185 186 186 while (--width > 0) { 187 187 /* … … 192 192 counter++; 193 193 } 194 194 195 195 return (int) (counter); 196 196 } … … 210 210 if (str == NULL) 211 211 return printf_putstr(nullstr, ps); 212 212 213 213 /* Print leading spaces. */ 214 214 size_t strw = str_length(str); 215 215 if ((precision == 0) || (precision > strw)) 216 216 precision = strw; 217 217 218 218 /* Left padding */ 219 219 size_t counter = 0; … … 225 225 } 226 226 } 227 227 228 228 /* Part of @a str fitting into the alloted space. */ 229 229 int retval; … … 231 231 if ((retval = printf_putnchars(str, size, ps)) < 0) 232 232 return -counter; 233 233 234 234 counter += retval; 235 235 236 236 /* Right padding */ 237 237 while (width-- > 0) { … … 264 264 else 265 265 digits = digits_small; 266 266 267 267 char data[PRINT_NUMBER_BUFFER_SIZE]; 268 268 char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1]; 269 269 270 270 /* Size of number with all prefixes and signs */ 271 271 int size = 0; 272 272 273 273 /* Put zero at end of string */ 274 274 *ptr-- = 0; 275 275 276 276 if (num == 0) { 277 277 *ptr-- = '0'; … … 283 283 } while (num /= base); 284 284 } 285 285 286 286 /* Size of plain number */ 287 287 int number_size = size; 288 288 289 289 /* 290 290 * Collect the sum of all prefixes/signs/etc. to calculate padding and … … 305 305 } 306 306 } 307 307 308 308 char sgn = 0; 309 309 if (flags & __PRINTF_FLAG_SIGNED) { … … 319 319 } 320 320 } 321 321 322 322 if (flags & __PRINTF_FLAG_LEFTALIGNED) 323 323 flags &= ~__PRINTF_FLAG_ZEROPADDED; 324 324 325 325 /* 326 326 * If the number is left-aligned or precision is specified then … … 331 331 precision = width - size + number_size; 332 332 } 333 333 334 334 /* Print leading spaces */ 335 335 if (number_size > precision) { … … 337 337 precision = number_size; 338 338 } 339 339 340 340 width -= precision + size - number_size; 341 341 size_t counter = 0; 342 342 343 343 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 344 344 while (width-- > 0) { … … 347 347 } 348 348 } 349 349 350 350 /* Print sign */ 351 351 if (sgn) { … … 353 353 counter++; 354 354 } 355 355 356 356 /* Print prefix */ 357 357 if (flags & __PRINTF_FLAG_PREFIX) { … … 386 386 } 387 387 } 388 388 389 389 /* Print leading zeroes */ 390 390 precision -= number_size; … … 393 393 counter++; 394 394 } 395 395 396 396 /* Print the number itself */ 397 397 int retval; 398 398 if ((retval = printf_putstr(++ptr, ps)) > 0) 399 399 counter += retval; 400 400 401 401 /* Print trailing spaces */ 402 402 403 403 while (width-- > 0) { 404 404 if (printf_putchar(' ', ps) == 1) 405 405 counter++; 406 406 } 407 407 408 408 return ((int) counter); 409 409 } … … 497 497 size_t nxt = 0; /* Index of the next character from fmt */ 498 498 size_t j = 0; /* Index to the first not printed nonformating character */ 499 499 500 500 size_t counter = 0; /* Number of characters printed */ 501 501 int retval; /* Return values from nested functions */ 502 502 503 503 while (true) { 504 504 i = nxt; 505 505 wchar_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 506 506 507 507 if (uc == 0) 508 508 break; 509 509 510 510 /* Control character */ 511 511 if (uc == '%') { … … 519 519 counter += retval; 520 520 } 521 521 522 522 j = i; 523 523 524 524 /* Parse modifiers */ 525 525 uint32_t flags = 0; 526 526 bool end = false; 527 527 528 528 do { 529 529 i = nxt; … … 549 549 }; 550 550 } while (!end); 551 551 552 552 /* Width & '*' operator */ 553 553 int width = 0; … … 556 556 width *= 10; 557 557 width += uc - '0'; 558 558 559 559 i = nxt; 560 560 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); … … 575 575 } 576 576 } 577 577 578 578 /* Precision and '*' operator */ 579 579 int precision = 0; … … 585 585 precision *= 10; 586 586 precision += uc - '0'; 587 587 588 588 i = nxt; 589 589 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); … … 604 604 } 605 605 } 606 606 607 607 qualifier_t qualifier; 608 608 609 609 switch (uc) { 610 610 case 't': … … 653 653 qualifier = PrintfQualifierInt; 654 654 } 655 655 656 656 unsigned int base = 10; 657 657 658 658 switch (uc) { 659 659 /* … … 662 662 case 's': 663 663 retval = print_str(va_arg(ap, char *), width, precision, flags, ps); 664 664 665 665 if (retval < 0) { 666 666 counter = -counter; 667 667 goto out; 668 668 } 669 669 670 670 counter += retval; 671 671 j = nxt; … … 673 673 case 'c': 674 674 retval = print_char(va_arg(ap, unsigned int), width, flags, ps); 675 675 676 676 if (retval < 0) { 677 677 counter = -counter; 678 678 goto out; 679 679 }; 680 680 681 681 counter += retval; 682 682 j = nxt; 683 683 goto next_char; 684 684 685 685 /* 686 686 * Integer values … … 714 714 base = 16; 715 715 break; 716 716 717 717 /* Percentile itself */ 718 718 case '%': 719 719 j = i; 720 720 goto next_char; 721 721 722 722 /* 723 723 * Bad formatting. … … 730 730 goto next_char; 731 731 } 732 732 733 733 /* Print integers */ 734 734 size_t size; 735 735 uint64_t number; 736 736 737 737 switch (qualifier) { 738 738 case PrintfQualifierByte: … … 774 774 goto out; 775 775 } 776 776 777 777 if ((retval = print_number(number, width, precision, 778 778 base, flags, ps)) < 0) { … … 780 780 goto out; 781 781 } 782 782 783 783 counter += retval; 784 784 j = nxt; … … 787 787 ; 788 788 } 789 789 790 790 if (i > j) { 791 791 if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) { … … 796 796 counter += retval; 797 797 } 798 798 799 799 out: 800 800 return ((int) counter); -
boot/generic/src/str.c
r3061bc1 ra35b458 141 141 if (*offset + 1 > size) 142 142 return 0; 143 143 144 144 /* First byte read from string */ 145 145 uint8_t b0 = (uint8_t) str[(*offset)++]; 146 146 147 147 /* Determine code length */ 148 148 149 149 unsigned int b0_bits; /* Data bits in first byte */ 150 150 unsigned int cbytes; /* Number of continuation bytes */ 151 151 152 152 if ((b0 & 0x80) == 0) { 153 153 /* 0xxxxxxx (Plain ASCII) */ … … 170 170 return U_SPECIAL; 171 171 } 172 172 173 173 if (*offset + cbytes > size) 174 174 return U_SPECIAL; 175 175 176 176 wchar_t ch = b0 & LO_MASK_8(b0_bits); 177 177 178 178 /* Decode continuation bytes */ 179 179 while (cbytes > 0) { 180 180 uint8_t b = (uint8_t) str[(*offset)++]; 181 181 182 182 /* Must be 10xxxxxx */ 183 183 if ((b & 0xc0) != 0x80) 184 184 return U_SPECIAL; 185 185 186 186 /* Shift data bits to ch */ 187 187 ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS)); 188 188 cbytes--; 189 189 } 190 190 191 191 return ch; 192 192 } … … 211 211 if (*offset >= size) 212 212 return EOVERFLOW; 213 213 214 214 if (!chr_check(ch)) 215 215 return EINVAL; 216 216 217 217 /* Unsigned version of ch (bit operations should only be done 218 218 on unsigned types). */ 219 219 uint32_t cc = (uint32_t) ch; 220 220 221 221 /* Determine how many continuation bytes are needed */ 222 222 223 223 unsigned int b0_bits; /* Data bits in first byte */ 224 224 unsigned int cbytes; /* Number of continuation bytes */ 225 225 226 226 if ((cc & ~LO_MASK_32(7)) == 0) { 227 227 b0_bits = 7; … … 240 240 return EINVAL; 241 241 } 242 242 243 243 /* Check for available space in buffer */ 244 244 if (*offset + cbytes >= size) 245 245 return EOVERFLOW; 246 246 247 247 /* Encode continuation bytes */ 248 248 unsigned int i; … … 251 251 cc = cc >> CONT_BITS; 252 252 } 253 253 254 254 /* Encode first byte */ 255 255 str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1); 256 256 257 257 /* Advance offset */ 258 258 *offset += cbytes + 1; 259 259 260 260 return EOK; 261 261 } … … 274 274 { 275 275 size_t size = 0; 276 276 277 277 while (*str++ != 0) 278 278 size++; 279 279 280 280 return size; 281 281 } … … 298 298 size_t len = 0; 299 299 size_t offset = 0; 300 300 301 301 while (len < max_len) { 302 302 if (str_decode(str, &offset, STR_NO_LIMIT) == 0) 303 303 break; 304 304 305 305 len++; 306 306 } 307 307 308 308 return offset; 309 309 } … … 320 320 size_t len = 0; 321 321 size_t offset = 0; 322 322 323 323 while (str_decode(str, &offset, STR_NO_LIMIT) != 0) 324 324 len++; 325 325 326 326 return len; 327 327 } … … 336 336 if (WCHAR_SIGNED_CHECK(ch >= 0) && (ch <= 127)) 337 337 return true; 338 338 339 339 return false; 340 340 } … … 349 349 if (WCHAR_SIGNED_CHECK(ch >= 0) && (ch <= 1114111)) 350 350 return true; 351 351 352 352 return false; 353 353 } … … 375 375 wchar_t c1 = 0; 376 376 wchar_t c2 = 0; 377 377 378 378 size_t off1 = 0; 379 379 size_t off2 = 0; 380 380 381 381 while (true) { 382 382 c1 = str_decode(s1, &off1, STR_NO_LIMIT); 383 383 c2 = str_decode(s2, &off2, STR_NO_LIMIT); 384 384 385 385 if (c1 < c2) 386 386 return -1; 387 387 388 388 if (c1 > c2) 389 389 return 1; 390 390 391 391 if ((c1 == 0) || (c2 == 0)) 392 392 break; 393 393 } 394 394 395 395 return 0; 396 396 } … … 412 412 size_t src_off = 0; 413 413 size_t dest_off = 0; 414 414 415 415 wchar_t ch; 416 416 while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { … … 418 418 break; 419 419 } 420 420 421 421 dest[dest_off] = '\0'; 422 422 } -
boot/generic/src/vprintf.c
r3061bc1 ra35b458 40 40 size_t offset = 0; 41 41 size_t chars = 0; 42 42 43 43 while (offset < size) { 44 44 putchar(str_decode(str, &offset, size)); 45 45 chars++; 46 46 } 47 47 48 48 return chars; 49 49 } … … 54 54 size_t chars = 0; 55 55 wchar_t uc; 56 56 57 57 while ((uc = str_decode(str, &offset, STR_NO_LIMIT)) != 0) { 58 58 putchar(uc); 59 59 chars++; 60 60 } 61 61 62 62 return chars; 63 63 } … … 69 69 NULL 70 70 }; 71 71 72 72 int ret = printf_core(fmt, &ps, ap); 73 73 74 74 return ret; 75 75 }
Note:
See TracChangeset
for help on using the changeset viewer.