1 use crate::io::{self, Write}; 2 use alloc::{ 3 collections::BTreeMap, 4 string::{String, ToString}, 5 vec::Vec, 6 }; 7 use core::{char, cmp, f64, ffi::VaList, fmt, num::FpCategory, ops::Range, slice}; 8 9 use crate::{ 10 header::errno::EILSEQ, 11 platform::{self, types::*}, 12 }; 13 14 // ____ _ _ _ _ 15 // | __ ) ___ (_) | ___ _ __ _ __ | | __ _| |_ ___ _ 16 // | _ \ / _ \| | |/ _ \ '__| '_ \| |/ _` | __/ _ (_) 17 // | |_) | (_) | | | __/ | | |_) | | (_| | || __/_ 18 // |____/ \___/|_|_|\___|_| | .__/|_|\__,_|\__\___(_) 19 // |_| 20 21 #[derive(Clone, Copy, PartialEq, Eq, Debug)] 22 enum IntKind { 23 Byte, 24 Short, 25 Int, 26 Long, 27 LongLong, 28 IntMax, 29 PtrDiff, 30 Size, 31 } 32 #[derive(Clone, Copy, PartialEq, Eq, Debug)] 33 enum FmtKind { 34 Percent, 35 36 Signed, 37 Unsigned, 38 39 Scientific, 40 Decimal, 41 AnyNotation, 42 43 String, 44 Char, 45 Pointer, 46 GetWritten, 47 } 48 #[derive(Clone, Copy, Debug)] 49 enum Number { 50 Static(usize), 51 Index(usize), 52 Next, 53 } 54 impl Number { 55 unsafe fn resolve(self, varargs: &mut VaListCache, ap: &mut VaList) -> usize { 56 let arg = match self { 57 Number::Static(num) => return num, 58 Number::Index(i) => varargs.get(i - 1, ap, None), 59 Number::Next => { 60 let i = varargs.i; 61 varargs.i += 1; 62 varargs.get(i, ap, None) 63 } 64 }; 65 match arg { 66 VaArg::c_char(i) => i as usize, 67 VaArg::c_double(i) => i as usize, 68 VaArg::c_int(i) => i as usize, 69 VaArg::c_long(i) => i as usize, 70 VaArg::c_longlong(i) => i as usize, 71 VaArg::c_short(i) => i as usize, 72 VaArg::intmax_t(i) => i as usize, 73 VaArg::pointer(i) => i as usize, 74 VaArg::ptrdiff_t(i) => i as usize, 75 VaArg::ssize_t(i) => i as usize, 76 VaArg::wint_t(i) => i as usize, 77 } 78 } 79 } 80 #[derive(Clone, Copy, Debug)] 81 enum VaArg { 82 c_char(c_char), 83 c_double(c_double), 84 c_int(c_int), 85 c_long(c_long), 86 c_longlong(c_longlong), 87 c_short(c_short), 88 intmax_t(intmax_t), 89 pointer(*const c_void), 90 ptrdiff_t(ptrdiff_t), 91 ssize_t(ssize_t), 92 wint_t(wint_t), 93 } 94 impl VaArg { 95 unsafe fn arg_from(fmtkind: FmtKind, intkind: IntKind, ap: &mut VaList) -> VaArg { 96 // Per the C standard using va_arg with a type with a size 97 // less than that of an int for integers and double for floats 98 // is invalid. As a result any arguments smaller than an int or 99 // double passed to a function will be promoted to the smallest 100 // possible size. The VaList::arg function will handle this 101 // automagically. 102 103 match (fmtkind, intkind) { 104 (FmtKind::Percent, _) => panic!("Can't call arg_from on %"), 105 106 (FmtKind::Char, IntKind::Long) | (FmtKind::Char, IntKind::LongLong) => { 107 VaArg::wint_t(ap.arg::<wint_t>()) 108 } 109 110 (FmtKind::Char, _) 111 | (FmtKind::Unsigned, IntKind::Byte) 112 | (FmtKind::Signed, IntKind::Byte) => VaArg::c_char(ap.arg::<c_char>()), 113 (FmtKind::Unsigned, IntKind::Short) | (FmtKind::Signed, IntKind::Short) => { 114 VaArg::c_short(ap.arg::<c_short>()) 115 } 116 (FmtKind::Unsigned, IntKind::Int) | (FmtKind::Signed, IntKind::Int) => { 117 VaArg::c_int(ap.arg::<c_int>()) 118 } 119 (FmtKind::Unsigned, IntKind::Long) | (FmtKind::Signed, IntKind::Long) => { 120 VaArg::c_long(ap.arg::<c_long>()) 121 } 122 (FmtKind::Unsigned, IntKind::LongLong) | (FmtKind::Signed, IntKind::LongLong) => { 123 VaArg::c_longlong(ap.arg::<c_longlong>()) 124 } 125 (FmtKind::Unsigned, IntKind::IntMax) | (FmtKind::Signed, IntKind::IntMax) => { 126 VaArg::intmax_t(ap.arg::<intmax_t>()) 127 } 128 (FmtKind::Unsigned, IntKind::PtrDiff) | (FmtKind::Signed, IntKind::PtrDiff) => { 129 VaArg::ptrdiff_t(ap.arg::<ptrdiff_t>()) 130 } 131 (FmtKind::Unsigned, IntKind::Size) | (FmtKind::Signed, IntKind::Size) => { 132 VaArg::ssize_t(ap.arg::<ssize_t>()) 133 } 134 135 (FmtKind::AnyNotation, _) | (FmtKind::Decimal, _) | (FmtKind::Scientific, _) => { 136 VaArg::c_double(ap.arg::<c_double>()) 137 } 138 139 (FmtKind::GetWritten, _) | (FmtKind::Pointer, _) | (FmtKind::String, _) => { 140 VaArg::pointer(ap.arg::<*const c_void>()) 141 } 142 } 143 } 144 unsafe fn transmute(&self, fmtkind: FmtKind, intkind: IntKind) -> VaArg { 145 // At this point, there are conflicting printf arguments. An 146 // example of this is: 147 // ```c 148 // printf("%1$d %1$lf\n", 5, 0.1); 149 // ``` 150 // We handle it just like glibc: We read it from the VaList 151 // using the *last* argument type, but we transmute it when we 152 // try to access the other ones. 153 union Untyped { 154 c_char: c_char, 155 c_double: c_double, 156 c_int: c_int, 157 c_long: c_long, 158 c_longlong: c_longlong, 159 c_short: c_short, 160 intmax_t: intmax_t, 161 pointer: *const c_void, 162 ptrdiff_t: ptrdiff_t, 163 ssize_t: ssize_t, 164 wint_t: wint_t, 165 } 166 let untyped = match *self { 167 VaArg::c_char(i) => Untyped { c_char: i }, 168 VaArg::c_double(i) => Untyped { c_double: i }, 169 VaArg::c_int(i) => Untyped { c_int: i }, 170 VaArg::c_long(i) => Untyped { c_long: i }, 171 VaArg::c_longlong(i) => Untyped { c_longlong: i }, 172 VaArg::c_short(i) => Untyped { c_short: i }, 173 VaArg::intmax_t(i) => Untyped { intmax_t: i }, 174 VaArg::pointer(i) => Untyped { pointer: i }, 175 VaArg::ptrdiff_t(i) => Untyped { ptrdiff_t: i }, 176 VaArg::ssize_t(i) => Untyped { ssize_t: i }, 177 VaArg::wint_t(i) => Untyped { wint_t: i }, 178 }; 179 match (fmtkind, intkind) { 180 (FmtKind::Percent, _) => panic!("Can't call transmute on %"), 181 182 (FmtKind::Char, IntKind::Long) | (FmtKind::Char, IntKind::LongLong) => { 183 VaArg::wint_t(untyped.wint_t) 184 } 185 186 (FmtKind::Char, _) 187 | (FmtKind::Unsigned, IntKind::Byte) 188 | (FmtKind::Signed, IntKind::Byte) => VaArg::c_char(untyped.c_char), 189 (FmtKind::Unsigned, IntKind::Short) | (FmtKind::Signed, IntKind::Short) => { 190 VaArg::c_short(untyped.c_short) 191 } 192 (FmtKind::Unsigned, IntKind::Int) | (FmtKind::Signed, IntKind::Int) => { 193 VaArg::c_int(untyped.c_int) 194 } 195 (FmtKind::Unsigned, IntKind::Long) | (FmtKind::Signed, IntKind::Long) => { 196 VaArg::c_long(untyped.c_long) 197 } 198 (FmtKind::Unsigned, IntKind::LongLong) | (FmtKind::Signed, IntKind::LongLong) => { 199 VaArg::c_longlong(untyped.c_longlong) 200 } 201 (FmtKind::Unsigned, IntKind::IntMax) | (FmtKind::Signed, IntKind::IntMax) => { 202 VaArg::intmax_t(untyped.intmax_t) 203 } 204 (FmtKind::Unsigned, IntKind::PtrDiff) | (FmtKind::Signed, IntKind::PtrDiff) => { 205 VaArg::ptrdiff_t(untyped.ptrdiff_t) 206 } 207 (FmtKind::Unsigned, IntKind::Size) | (FmtKind::Signed, IntKind::Size) => { 208 VaArg::ssize_t(untyped.ssize_t) 209 } 210 211 (FmtKind::AnyNotation, _) | (FmtKind::Decimal, _) | (FmtKind::Scientific, _) => { 212 VaArg::c_double(untyped.c_double) 213 } 214 215 (FmtKind::GetWritten, _) | (FmtKind::Pointer, _) | (FmtKind::String, _) => { 216 VaArg::pointer(untyped.pointer) 217 } 218 } 219 } 220 } 221 #[derive(Default)] 222 struct VaListCache { 223 args: Vec<VaArg>, 224 i: usize, 225 } 226 impl VaListCache { 227 unsafe fn get( 228 &mut self, 229 i: usize, 230 ap: &mut VaList, 231 default: Option<(FmtKind, IntKind)>, 232 ) -> VaArg { 233 if let Some(&arg) = self.args.get(i) { 234 // This value is already cached 235 let mut arg = arg; 236 if let Some((fmtkind, intkind)) = default { 237 // ...but as a different type 238 arg = arg.transmute(fmtkind, intkind); 239 } 240 return arg; 241 } 242 243 // Get all values before this value 244 while self.args.len() < i { 245 // We can't POSSIBLY know the type if we reach this 246 // point. Reaching here means there are unused gaps in the 247 // arguments. Ultimately we'll have to settle down with 248 // defaulting to c_int. 249 self.args.push(VaArg::c_int(ap.arg::<c_int>())) 250 } 251 252 // Add the value to the cache 253 self.args.push(match default { 254 Some((fmtkind, intkind)) => VaArg::arg_from(fmtkind, intkind, ap), 255 None => VaArg::c_int(ap.arg::<c_int>()), 256 }); 257 258 // Return the value 259 self.args[i] 260 } 261 } 262 263 // ___ _ _ _ _ 264 // |_ _|_ __ ___ _ __ | | ___ _ __ ___ ___ _ __ | |_ __ _| |_(_) ___ _ __ _ 265 // | || '_ ` _ \| '_ \| |/ _ \ '_ ` _ \ / _ \ '_ \| __/ _` | __| |/ _ \| '_ \(_) 266 // | || | | | | | |_) | | __/ | | | | | __/ | | | || (_| | |_| | (_) | | | |_ 267 // |___|_| |_| |_| .__/|_|\___|_| |_| |_|\___|_| |_|\__\__,_|\__|_|\___/|_| |_(_) 268 // |_| 269 270 enum FmtCase { 271 Lower, 272 Upper, 273 } 274 275 // The spelled-out "infinity"/"INFINITY" is also permitted by the standard 276 static INF_STR_LOWER: &str = "inf"; 277 static INF_STR_UPPER: &str = "INF"; 278 279 static NAN_STR_LOWER: &str = "nan"; 280 static NAN_STR_UPPER: &str = "NAN"; 281 282 unsafe fn pop_int_raw(format: &mut *const u8) -> Option<usize> { 283 let mut int = None; 284 while let Some(digit) = (**format as char).to_digit(10) { 285 *format = format.add(1); 286 if int.is_none() { 287 int = Some(0); 288 } 289 *int.as_mut().unwrap() *= 10; 290 *int.as_mut().unwrap() += digit as usize; 291 } 292 int 293 } 294 unsafe fn pop_index(format: &mut *const u8) -> Option<usize> { 295 // Peek ahead for a positional argument: 296 let mut format2 = *format; 297 if let Some(i) = pop_int_raw(&mut format2) { 298 if *format2 == b'$' { 299 *format = format2.add(1); 300 return Some(i); 301 } 302 } 303 None 304 } 305 unsafe fn pop_int(format: &mut *const u8) -> Option<Number> { 306 if **format == b'*' { 307 *format = format.add(1); 308 Some(pop_index(format).map(Number::Index).unwrap_or(Number::Next)) 309 } else { 310 pop_int_raw(format).map(Number::Static) 311 } 312 } 313 314 unsafe fn fmt_int<I>(fmt: u8, i: I) -> String 315 where 316 I: fmt::Display + fmt::Octal + fmt::LowerHex + fmt::UpperHex, 317 { 318 match fmt { 319 b'o' => format!("{:o}", i), 320 b'u' => i.to_string(), 321 b'x' => format!("{:x}", i), 322 b'X' => format!("{:X}", i), 323 _ => panic!( 324 "fmt_int should never be called with the fmt {:?}", 325 fmt as char 326 ), 327 } 328 } 329 330 fn pad<W: Write>( 331 w: &mut W, 332 current_side: bool, 333 pad_char: u8, 334 range: Range<usize>, 335 ) -> io::Result<()> { 336 if current_side { 337 for _ in range { 338 w.write_all(&[pad_char])?; 339 } 340 } 341 Ok(()) 342 } 343 344 fn abs(float: c_double) -> c_double { 345 // Don't ask me whe float.abs() seems absent... 346 if float.is_sign_negative() { 347 -float 348 } else { 349 float 350 } 351 } 352 353 fn float_string(float: c_double, precision: usize, trim: bool) -> String { 354 let mut string = format!("{:.p$}", float, p = precision); 355 if trim && string.contains('.') { 356 let truncate = { 357 let slice = string.trim_end_matches('0'); 358 let mut truncate = slice.len(); 359 if slice.ends_with('.') { 360 truncate -= 1; 361 } 362 truncate 363 }; 364 string.truncate(truncate); 365 } 366 string 367 } 368 369 fn float_exp(mut float: c_double) -> (c_double, isize) { 370 let mut exp: isize = 0; 371 while abs(float) >= 10.0 { 372 float /= 10.0; 373 exp += 1; 374 } 375 while f64::EPSILON < abs(float) && abs(float) < 1.0 { 376 float *= 10.0; 377 exp -= 1; 378 } 379 (float, exp) 380 } 381 382 fn fmt_float_exp<W: Write>( 383 w: &mut W, 384 exp_fmt: u8, 385 trim: bool, 386 precision: usize, 387 float: c_double, 388 exp: isize, 389 left: bool, 390 pad_space: usize, 391 pad_zero: usize, 392 ) -> io::Result<()> { 393 let mut exp2 = exp; 394 let mut exp_len = 1; 395 while exp2 >= 10 { 396 exp2 /= 10; 397 exp_len += 1; 398 } 399 400 let string = float_string(float, precision, trim); 401 let len = string.len() + 2 + 2.max(exp_len); 402 403 pad(w, !left, b' ', len..pad_space)?; 404 let bytes = if string.starts_with('-') { 405 w.write_all(&[b'-'])?; 406 &string.as_bytes()[1..] 407 } else { 408 string.as_bytes() 409 }; 410 pad(w, !left, b'0', len..pad_zero)?; 411 w.write_all(bytes)?; 412 write!(w, "{}{:+03}", exp_fmt as char, exp)?; 413 pad(w, left, b' ', len..pad_space)?; 414 415 Ok(()) 416 } 417 418 fn fmt_float_normal<W: Write>( 419 w: &mut W, 420 trim: bool, 421 precision: usize, 422 float: c_double, 423 left: bool, 424 pad_space: usize, 425 pad_zero: usize, 426 ) -> io::Result<usize> { 427 let string = float_string(float, precision, trim); 428 429 pad(w, !left, b' ', string.len()..pad_space)?; 430 let bytes = if string.starts_with('-') { 431 w.write_all(&[b'-'])?; 432 &string.as_bytes()[1..] 433 } else { 434 string.as_bytes() 435 }; 436 pad(w, true, b'0', string.len()..pad_zero)?; 437 w.write_all(bytes)?; 438 pad(w, left, b' ', string.len()..pad_space)?; 439 440 Ok(string.len()) 441 } 442 443 /// Write ±infinity or ±NaN representation for any floating-point style 444 fn fmt_float_nonfinite<W: Write>(w: &mut W, float: c_double, case: FmtCase) -> io::Result<()> { 445 if float.is_sign_negative() { 446 w.write_all(&[b'-'])?; 447 } 448 449 let nonfinite_str = match float.classify() { 450 FpCategory::Infinite => match case { 451 FmtCase::Lower => INF_STR_LOWER, 452 FmtCase::Upper => INF_STR_UPPER, 453 }, 454 FpCategory::Nan => match case { 455 FmtCase::Lower => NAN_STR_LOWER, 456 FmtCase::Upper => NAN_STR_UPPER, 457 }, 458 _ => { 459 // This function should only be called with infinite or NaN value. 460 panic!("this should not be possible") 461 } 462 }; 463 464 w.write_all(nonfinite_str.as_bytes())?; 465 466 Ok(()) 467 } 468 469 #[derive(Clone, Copy)] 470 struct PrintfIter { 471 format: *const u8, 472 } 473 #[derive(Clone, Copy, Debug)] 474 struct PrintfArg { 475 index: Option<usize>, 476 alternate: bool, 477 zero: bool, 478 left: bool, 479 sign_reserve: bool, 480 sign_always: bool, 481 min_width: Number, 482 precision: Option<Number>, 483 intkind: IntKind, 484 fmt: u8, 485 fmtkind: FmtKind, 486 } 487 #[derive(Debug)] 488 enum PrintfFmt { 489 Plain(&'static [u8]), 490 Arg(PrintfArg), 491 } 492 impl Iterator for PrintfIter { 493 type Item = Result<PrintfFmt, ()>; 494 fn next(&mut self) -> Option<Self::Item> { 495 unsafe { 496 // Send PrintfFmt::Plain until the next % 497 let mut len = 0; 498 while *self.format.add(len) != 0 && *self.format.add(len) != b'%' { 499 len += 1; 500 } 501 if len > 0 { 502 let slice = slice::from_raw_parts(self.format as *const u8, len); 503 self.format = self.format.add(len); 504 return Some(Ok(PrintfFmt::Plain(slice))); 505 } 506 self.format = self.format.add(len); 507 if *self.format == 0 { 508 return None; 509 } 510 511 // *self.format is guaranteed to be '%' at this point 512 self.format = self.format.add(1); 513 514 let mut peekahead = self.format; 515 let index = pop_index(&mut peekahead).map(|i| { 516 self.format = peekahead; 517 i 518 }); 519 520 // Flags: 521 let mut alternate = false; 522 let mut zero = false; 523 let mut left = false; 524 let mut sign_reserve = false; 525 let mut sign_always = false; 526 527 loop { 528 match *self.format { 529 b'#' => alternate = true, 530 b'0' => zero = true, 531 b'-' => left = true, 532 b' ' => sign_reserve = true, 533 b'+' => sign_always = true, 534 _ => break, 535 } 536 self.format = self.format.add(1); 537 } 538 539 // Width and precision: 540 let min_width = pop_int(&mut self.format).unwrap_or(Number::Static(0)); 541 let precision = if *self.format == b'.' { 542 self.format = self.format.add(1); 543 match pop_int(&mut self.format) { 544 int @ Some(_) => int, 545 None => return Some(Err(())), 546 } 547 } else { 548 None 549 }; 550 551 // Integer size: 552 let mut intkind = IntKind::Int; 553 loop { 554 intkind = match *self.format { 555 b'h' => { 556 if intkind == IntKind::Short || intkind == IntKind::Byte { 557 IntKind::Byte 558 } else { 559 IntKind::Short 560 } 561 } 562 b'j' => IntKind::IntMax, 563 b'l' => { 564 if intkind == IntKind::Long || intkind == IntKind::LongLong { 565 IntKind::LongLong 566 } else { 567 IntKind::Long 568 } 569 } 570 b'q' | b'L' => IntKind::LongLong, 571 b't' => IntKind::PtrDiff, 572 b'z' => IntKind::Size, 573 _ => break, 574 }; 575 576 self.format = self.format.add(1); 577 } 578 let fmt = *self.format; 579 let fmtkind = match fmt { 580 b'%' => FmtKind::Percent, 581 b'd' | b'i' => FmtKind::Signed, 582 b'o' | b'u' | b'x' | b'X' => FmtKind::Unsigned, 583 b'e' | b'E' => FmtKind::Scientific, 584 b'f' | b'F' => FmtKind::Decimal, 585 b'g' | b'G' => FmtKind::AnyNotation, 586 b's' => FmtKind::String, 587 b'c' => FmtKind::Char, 588 b'p' => FmtKind::Pointer, 589 b'n' => FmtKind::GetWritten, 590 _ => return Some(Err(())), 591 }; 592 self.format = self.format.add(1); 593 594 Some(Ok(PrintfFmt::Arg(PrintfArg { 595 index, 596 alternate, 597 zero, 598 left, 599 sign_reserve, 600 sign_always, 601 min_width, 602 precision, 603 intkind, 604 fmt, 605 fmtkind, 606 }))) 607 } 608 } 609 } 610 611 unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, mut ap: VaList) -> io::Result<c_int> { 612 let w = &mut platform::CountingWriter::new(w); 613 614 let iterator = PrintfIter { 615 format: format as *const u8, 616 }; 617 618 // Pre-fetch vararg types 619 let mut varargs = VaListCache::default(); 620 let mut positional = BTreeMap::new(); 621 // ^ NOTE: This depends on the sorted order, do not change to HashMap or whatever 622 623 for section in iterator { 624 let arg = match section { 625 Ok(PrintfFmt::Plain(text)) => continue, 626 Ok(PrintfFmt::Arg(arg)) => arg, 627 Err(()) => return Ok(-1), 628 }; 629 if arg.fmtkind == FmtKind::Percent { 630 continue; 631 } 632 for num in &[arg.min_width, arg.precision.unwrap_or(Number::Static(0))] { 633 match num { 634 Number::Next => varargs.args.push(VaArg::c_int(ap.arg::<c_int>())), 635 Number::Index(i) => { 636 positional.insert(i - 1, (FmtKind::Signed, IntKind::Int)); 637 } 638 Number::Static(_) => (), 639 } 640 } 641 match arg.index { 642 Some(i) => { 643 positional.insert(i - 1, (arg.fmtkind, arg.intkind)); 644 } 645 None => varargs 646 .args 647 .push(VaArg::arg_from(arg.fmtkind, arg.intkind, &mut ap)), 648 } 649 } 650 651 // Make sure, in order, the positional arguments exist with the specified type 652 for (i, arg) in positional { 653 varargs.get(i, &mut ap, Some(arg)); 654 } 655 656 // Main loop 657 for section in iterator { 658 let arg = match section { 659 Ok(PrintfFmt::Plain(text)) => { 660 w.write_all(text)?; 661 continue; 662 } 663 Ok(PrintfFmt::Arg(arg)) => arg, 664 Err(()) => return Ok(-1), 665 }; 666 let alternate = arg.alternate; 667 let zero = arg.zero; 668 let mut left = arg.left; 669 let sign_reserve = arg.sign_reserve; 670 let sign_always = arg.sign_always; 671 let min_width = arg.min_width.resolve(&mut varargs, &mut ap); 672 let precision = arg.precision.map(|n| n.resolve(&mut varargs, &mut ap)); 673 let pad_zero = if zero { min_width } else { 0 }; 674 let signed_space = match pad_zero { 675 0 => min_width as isize, 676 _ => 0, 677 }; 678 let pad_space = if signed_space < 0 { 679 left = true; 680 -signed_space as usize 681 } else { 682 signed_space as usize 683 }; 684 let intkind = arg.intkind; 685 let fmt = arg.fmt; 686 let fmtkind = arg.fmtkind; 687 let fmtcase = match fmt { 688 b'x' | b'f' | b'e' | b'g' => Some(FmtCase::Lower), 689 b'X' | b'F' | b'E' | b'G' => Some(FmtCase::Upper), 690 _ => None, 691 }; 692 693 694 let index = arg.index.map(|i| i - 1).unwrap_or_else(|| { 695 if fmtkind == FmtKind::Percent { 696 0 697 } else { 698 let i = varargs.i; 699 varargs.i += 1; 700 i 701 } 702 }); 703 704 match fmtkind { 705 FmtKind::Percent => w.write_all(&[b'%'])?, 706 FmtKind::Signed => { 707 let string = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 708 VaArg::c_char(i) => i.to_string(), 709 VaArg::c_double(i) => panic!("this should not be possible"), 710 VaArg::c_int(i) => i.to_string(), 711 VaArg::c_long(i) => i.to_string(), 712 VaArg::c_longlong(i) => i.to_string(), 713 VaArg::c_short(i) => i.to_string(), 714 VaArg::intmax_t(i) => i.to_string(), 715 VaArg::pointer(i) => (i as usize).to_string(), 716 VaArg::ptrdiff_t(i) => i.to_string(), 717 VaArg::ssize_t(i) => i.to_string(), 718 VaArg::wint_t(_) => unreachable!("this should not be possible"), 719 }; 720 let positive = !string.starts_with('-'); 721 let zero = precision == Some(0) && string == "0"; 722 723 let mut len = string.len(); 724 let mut final_len = string.len().max(precision.unwrap_or(0)); 725 if positive && (sign_reserve || sign_always) { 726 final_len += 1; 727 } 728 if zero { 729 len = 0; 730 final_len = 0; 731 } 732 733 pad(w, !left, b' ', final_len..pad_space)?; 734 735 let bytes = if positive { 736 if sign_reserve { 737 w.write_all(&[b' '])?; 738 } else if sign_always { 739 w.write_all(&[b'+'])?; 740 } 741 string.as_bytes() 742 } else { 743 w.write_all(&[b'-'])?; 744 &string.as_bytes()[1..] 745 }; 746 pad(w, true, b'0', len..precision.unwrap_or(pad_zero))?; 747 748 if !zero { 749 w.write_all(bytes)?; 750 } 751 752 pad(w, left, b' ', final_len..pad_space)?; 753 } 754 FmtKind::Unsigned => { 755 let string = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 756 VaArg::c_char(i) => fmt_int(fmt, i as c_uchar), 757 VaArg::c_double(i) => panic!("this should not be possible"), 758 VaArg::c_int(i) => fmt_int(fmt, i as c_uint), 759 VaArg::c_long(i) => fmt_int(fmt, i as c_ulong), 760 VaArg::c_longlong(i) => fmt_int(fmt, i as c_ulonglong), 761 VaArg::c_short(i) => fmt_int(fmt, i as c_ushort), 762 VaArg::intmax_t(i) => fmt_int(fmt, i as uintmax_t), 763 VaArg::pointer(i) => fmt_int(fmt, i as usize), 764 VaArg::ptrdiff_t(i) => fmt_int(fmt, i as size_t), 765 VaArg::ssize_t(i) => fmt_int(fmt, i as size_t), 766 VaArg::wint_t(_) => unreachable!("this should not be possible"), 767 }; 768 let zero = precision == Some(0) && string == "0"; 769 770 // If this int is padded out to be larger than it is, don't 771 // add an extra zero if octal. 772 let no_precision = precision.map(|pad| pad < string.len()).unwrap_or(true); 773 774 let len; 775 let final_len = if zero { 776 len = 0; 777 0 778 } else { 779 len = string.len(); 780 len.max(precision.unwrap_or(0)) 781 + if alternate && string != "0" { 782 match fmt { 783 b'o' if no_precision => 1, 784 b'x' | b'X' => 2, 785 _ => 0, 786 } 787 } else { 788 0 789 } 790 }; 791 792 pad(w, !left, b' ', final_len..pad_space)?; 793 794 if alternate && string != "0" { 795 match fmt { 796 b'o' if no_precision => w.write_all(&[b'0'])?, 797 b'x' => w.write_all(&[b'0', b'x'])?, 798 b'X' => w.write_all(&[b'0', b'X'])?, 799 _ => (), 800 } 801 } 802 pad(w, true, b'0', len..precision.unwrap_or(pad_zero))?; 803 804 if !zero { 805 w.write_all(string.as_bytes())?; 806 } 807 808 pad(w, left, b' ', final_len..pad_space)?; 809 } 810 FmtKind::Scientific => { 811 let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 812 VaArg::c_double(i) => i, 813 _ => panic!("this should not be possible"), 814 }; 815 if float.is_finite() { 816 let (float, exp) = float_exp(float); 817 let precision = precision.unwrap_or(6); 818 819 fmt_float_exp( 820 w, fmt, false, precision, float, exp, left, pad_space, pad_zero, 821 )?; 822 } else { 823 fmt_float_nonfinite(w, float, fmtcase.unwrap())?; 824 } 825 } 826 FmtKind::Decimal => { 827 let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 828 VaArg::c_double(i) => i, 829 _ => panic!("this should not be possible"), 830 }; 831 if float.is_finite() { 832 let precision = precision.unwrap_or(6); 833 834 fmt_float_normal(w, false, precision, float, left, pad_space, pad_zero)?; 835 } else { 836 fmt_float_nonfinite(w, float, fmtcase.unwrap())?; 837 } 838 } 839 FmtKind::AnyNotation => { 840 let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 841 VaArg::c_double(i) => i, 842 _ => panic!("this should not be possible"), 843 }; 844 if float.is_finite() { 845 let (log, exp) = float_exp(float); 846 let exp_fmt = b'E' | (fmt & 32); 847 let precision = precision.unwrap_or(6); 848 let use_exp_format = exp < -4 || exp >= precision as isize; 849 850 if use_exp_format { 851 // Length of integral part will always be 1 here, 852 // because that's how x/floor(log10(x)) works 853 let precision = precision.saturating_sub(1); 854 fmt_float_exp( 855 w, exp_fmt, true, precision, log, exp, left, pad_space, pad_zero, 856 )?; 857 } else { 858 // Length of integral part will be the exponent of 859 // the unused logarithm, unless the exponent is 860 // negative which in case the integral part must 861 // of course be 0, 1 in length 862 let len = 1 + cmp::max(0, exp) as usize; 863 let precision = precision.saturating_sub(len); 864 fmt_float_normal(w, true, precision, float, left, pad_space, pad_zero)?; 865 } 866 } else { 867 fmt_float_nonfinite(w, float, fmtcase.unwrap())?; 868 } 869 } 870 FmtKind::String => { 871 let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 872 VaArg::pointer(p) => p, 873 _ => panic!("this should not be possible"), 874 } as *const c_char; 875 876 if ptr.is_null() { 877 w.write_all(b"(null)")?; 878 } else { 879 let max = precision.unwrap_or(::core::usize::MAX); 880 881 if intkind == IntKind::Long || intkind == IntKind::LongLong { 882 // Handle wchar_t 883 let mut ptr = ptr as *const wchar_t; 884 let mut string = String::new(); 885 886 while *ptr != 0 { 887 let c = match char::from_u32(*ptr as _) { 888 Some(c) => c, 889 None => { 890 platform::errno = EILSEQ; 891 return Err(io::last_os_error()); 892 } 893 }; 894 if string.len() + c.len_utf8() >= max { 895 break; 896 } 897 string.push(c); 898 ptr = ptr.add(1); 899 } 900 901 pad(w, !left, b' ', string.len()..pad_space)?; 902 w.write_all(string.as_bytes())?; 903 pad(w, left, b' ', string.len()..pad_space)?; 904 } else { 905 let mut len = 0; 906 while *ptr.add(len) != 0 && len < max { 907 len += 1; 908 } 909 910 pad(w, !left, b' ', len..pad_space)?; 911 w.write_all(slice::from_raw_parts(ptr as *const u8, len))?; 912 pad(w, left, b' ', len..pad_space)?; 913 } 914 } 915 } 916 FmtKind::Char => match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 917 VaArg::c_char(c) => { 918 pad(w, !left, b' ', 1..pad_space)?; 919 w.write_all(&[c as u8])?; 920 pad(w, left, b' ', 1..pad_space)?; 921 } 922 VaArg::wint_t(c) => { 923 let c = match char::from_u32(c as _) { 924 Some(c) => c, 925 None => { 926 platform::errno = EILSEQ; 927 return Err(io::last_os_error()); 928 } 929 }; 930 let mut buf = [0; 4]; 931 932 pad(w, !left, b' ', 1..pad_space)?; 933 w.write_all(c.encode_utf8(&mut buf).as_bytes())?; 934 pad(w, left, b' ', 1..pad_space)?; 935 } 936 _ => unreachable!("this should not be possible"), 937 }, 938 FmtKind::Pointer => { 939 let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 940 VaArg::pointer(p) => p, 941 _ => panic!("this should not be possible"), 942 }; 943 944 let mut len = 1; 945 if ptr.is_null() { 946 len = "(nil)".len(); 947 } else { 948 let mut ptr = ptr as usize; 949 while ptr >= 10 { 950 ptr /= 10; 951 len += 1; 952 } 953 } 954 955 pad(w, !left, b' ', len..pad_space)?; 956 if ptr.is_null() { 957 write!(w, "(nil)")?; 958 } else { 959 write!(w, "0x{:x}", ptr as usize)?; 960 } 961 pad(w, left, b' ', len..pad_space)?; 962 } 963 FmtKind::GetWritten => { 964 let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) { 965 VaArg::pointer(p) => p, 966 _ => panic!("this should not be possible"), 967 }; 968 969 match intkind { 970 IntKind::Byte => *(ptr as *mut c_char) = w.written as c_char, 971 IntKind::Short => *(ptr as *mut c_short) = w.written as c_short, 972 IntKind::Int => *(ptr as *mut c_int) = w.written as c_int, 973 IntKind::Long => *(ptr as *mut c_long) = w.written as c_long, 974 IntKind::LongLong => *(ptr as *mut c_longlong) = w.written as c_longlong, 975 IntKind::IntMax => *(ptr as *mut intmax_t) = w.written as intmax_t, 976 IntKind::PtrDiff => *(ptr as *mut ptrdiff_t) = w.written as ptrdiff_t, 977 IntKind::Size => *(ptr as *mut size_t) = w.written as size_t, 978 } 979 } 980 } 981 } 982 Ok(w.written as c_int) 983 } 984 985 pub unsafe fn printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> c_int { 986 inner_printf(w, format, ap).unwrap_or(-1) 987 } 988