xref: /drstd/src/std/macros.rs (revision 0fe3ff0054d3aec7fbf9bddecfecb10bc7d23a51)
1 //! Standard library macros
2 //!
3 //! This module contains a set of macros which are exported from the standard
4 //! library. Each macro is available for use when linking against the standard
5 //! library.
6 // ignore-tidy-dbg
7 
8 //#[doc = include_str!("../../core/src/macros/panic.md")]
9 #[macro_export]
10 #[rustc_builtin_macro(std_panic)]
11 #[allow_internal_unstable(edition_panic)]
12 #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")]
13 macro_rules! panic {
14     // Expands to either `$crate::std::panic::panic_2015` or `$crate::std::panic::panic_2021`
15     // depending on the edition of the caller.
16     ($($arg:tt)*) => {
17         /* compiler built-in */
18     };
19 }
20 
21 /// Prints to the standard output.
22 ///
23 /// Equivalent to the [`println!`] macro except that a newline is not printed at
24 /// the end of the message.
25 ///
26 /// Note that stdout is frequently line-buffered by default so it may be
27 /// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted
28 /// immediately.
29 ///
30 /// The `print!` macro will lock the standard output on each call. If you call
31 /// `print!` within a hot loop, this behavior may be the bottleneck of the loop.
32 /// To avoid this, lock stdout with [`io::stdout().lock()`][lock]:
33 /// ```
34 /// use std::io::{stdout, Write};
35 ///
36 /// let mut lock = stdout().lock();
37 /// write!(lock, "hello world").unwrap();
38 /// ```
39 ///
40 /// Use `print!` only for the primary output of your program. Use
41 /// [`eprint!`] instead to print error and progress messages.
42 ///
43 /// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
44 /// for details of the macro argument syntax.
45 ///
46 /// [flush]: crate::std::io::Write::flush
47 /// [`println!`]: crate::std::println
48 /// [`eprint!`]: crate::std::eprint
49 /// [lock]: crate::std::io::Stdout
50 ///
51 /// # Panics
52 ///
53 /// Panics if writing to `io::stdout()` fails.
54 ///
55 /// Writing to non-blocking stdout can cause an error, which will lead
56 /// this macro to panic.
57 ///
58 /// # Examples
59 ///
60 /// ```
61 /// use std::io::{self, Write};
62 ///
63 /// print!("this ");
64 /// print!("will ");
65 /// print!("be ");
66 /// print!("on ");
67 /// print!("the ");
68 /// print!("same ");
69 /// print!("line ");
70 ///
71 /// io::stdout().flush().unwrap();
72 ///
73 /// print!("this string has a newline, why not choose println! instead?\n");
74 ///
75 /// io::stdout().flush().unwrap();
76 /// ```
77 #[macro_export]
78 #[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")]
79 #[allow_internal_unstable(print_internals)]
80 macro_rules! print {
81     ($($arg:tt)*) => {{
82         $crate::std::io::_print($crate::std::format_args!($($arg)*));
83     }};
84 }
85 
86 /// Prints to the standard output, with a newline.
87 ///
88 /// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
89 /// (no additional CARRIAGE RETURN (`\r`/`U+000D`)).
90 ///
91 /// This macro uses the same syntax as [`format!`], but writes to the standard output instead.
92 /// See [`std::fmt`] for more information.
93 ///
94 /// The `println!` macro will lock the standard output on each call. If you call
95 /// `println!` within a hot loop, this behavior may be the bottleneck of the loop.
96 /// To avoid this, lock stdout with [`io::stdout().lock()`][lock]:
97 /// ```
98 /// use std::io::{stdout, Write};
99 ///
100 /// let mut lock = stdout().lock();
101 /// writeln!(lock, "hello world").unwrap();
102 /// ```
103 ///
104 /// Use `println!` only for the primary output of your program. Use
105 /// [`eprintln!`] instead to print error and progress messages.
106 ///
107 /// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
108 /// for details of the macro argument syntax.
109 ///
110 /// [`std::fmt`]: crate::std::fmt
111 /// [`eprintln!`]: crate::std::eprintln
112 /// [lock]: crate::std::io::Stdout
113 ///
114 /// # Panics
115 ///
116 /// Panics if writing to [`io::stdout`] fails.
117 ///
118 /// Writing to non-blocking stdout can cause an error, which will lead
119 /// this macro to panic.
120 ///
121 /// [`io::stdout`]: crate::std::io::stdout
122 ///
123 /// # Examples
124 ///
125 /// ```
126 /// println!(); // prints just a newline
127 /// println!("hello there!");
128 /// println!("format {} arguments", "some");
129 /// let local_variable = "some";
130 /// println!("format {local_variable} arguments");
131 /// ```
132 #[macro_export]
133 #[cfg_attr(not(test), rustc_diagnostic_item = "println_macro")]
134 #[allow_internal_unstable(print_internals, format_args_nl)]
135 macro_rules! println {
136     () => {
137         $crate::std::print!("\n")
138     };
139     ($($arg:tt)*) => {{
140         $crate::std::io::_print($crate::std::format_args_nl!($($arg)*));
141     }};
142 }
143 
144 /// Prints to the standard error.
145 ///
146 /// Equivalent to the [`print!`] macro, except that output goes to
147 /// [`io::stderr`] instead of [`io::stdout`]. See [`print!`] for
148 /// example usage.
149 ///
150 /// Use `eprint!` only for error and progress messages. Use `print!`
151 /// instead for the primary output of your program.
152 ///
153 /// [`io::stderr`]: crate::std::io::stderr
154 /// [`io::stdout`]: crate::std::io::stdout
155 ///
156 /// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
157 /// for details of the macro argument syntax.
158 ///
159 /// # Panics
160 ///
161 /// Panics if writing to `io::stderr` fails.
162 ///
163 /// Writing to non-blocking stderr can cause an error, which will lead
164 /// this macro to panic.
165 ///
166 /// # Examples
167 ///
168 /// ```
169 /// eprint!("Error: Could not complete task");
170 /// ```
171 #[macro_export]
172 #[cfg_attr(not(test), rustc_diagnostic_item = "eprint_macro")]
173 #[allow_internal_unstable(print_internals)]
174 macro_rules! eprint {
175     ($($arg:tt)*) => {{
176         $crate::std::io::_eprint($crate::std::format_args!($($arg)*));
177     }};
178 }
179 
180 /// Prints to the standard error, with a newline.
181 ///
182 /// Equivalent to the [`println!`] macro, except that output goes to
183 /// [`io::stderr`] instead of [`io::stdout`]. See [`println!`] for
184 /// example usage.
185 ///
186 /// Use `eprintln!` only for error and progress messages. Use `println!`
187 /// instead for the primary output of your program.
188 ///
189 /// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
190 /// for details of the macro argument syntax.
191 ///
192 /// [`io::stderr`]: crate::std::io::stderr
193 /// [`io::stdout`]: crate::std::io::stdout
194 /// [`println!`]: crate::std::println
195 ///
196 /// # Panics
197 ///
198 /// Panics if writing to `io::stderr` fails.
199 ///
200 /// Writing to non-blocking stderr can cause an error, which will lead
201 /// this macro to panic.
202 ///
203 /// # Examples
204 ///
205 /// ```
206 /// eprintln!("Error: Could not complete task");
207 /// ```
208 #[macro_export]
209 #[cfg_attr(not(test), rustc_diagnostic_item = "eprintln_macro")]
210 #[allow_internal_unstable(print_internals, format_args_nl)]
211 macro_rules! eprintln {
212     () => {
213         $crate::std::eprint!("\n")
214     };
215     ($($arg:tt)*) => {{
216         $crate::std::io::_eprint($crate::std::format_args_nl!($($arg)*));
217     }};
218 }
219 
220 /// Prints and returns the value of a given expression for quick and dirty
221 /// debugging.
222 ///
223 /// An example:
224 ///
225 /// ```rust
226 /// let a = 2;
227 /// let b = dbg!(a * 2) + 1;
228 /// //      ^-- prints: [src/main.rs:2] a * 2 = 4
229 /// assert_eq!(b, 5);
230 /// ```
231 ///
232 /// The macro works by using the `Debug` implementation of the type of
233 /// the given expression to print the value to [stderr] along with the
234 /// source location of the macro invocation as well as the source code
235 /// of the expression.
236 ///
237 /// Invoking the macro on an expression moves and takes ownership of it
238 /// before returning the evaluated expression unchanged. If the type
239 /// of the expression does not implement `Copy` and you don't want
240 /// to give up ownership, you can instead borrow with `dbg!(&expr)`
241 /// for some expression `expr`.
242 ///
243 /// The `dbg!` macro works exactly the same in release builds.
244 /// This is useful when debugging issues that only occur in release
245 /// builds or when debugging in release mode is significantly faster.
246 ///
247 /// Note that the macro is intended as a debugging tool and therefore you
248 /// should avoid having uses of it in version control for long periods
249 /// (other than in tests and similar).
250 /// Debug output from production code is better done with other facilities
251 /// such as the [`debug!`] macro from the [`log`] crate.
252 ///
253 /// # Stability
254 ///
255 /// The exact output printed by this macro should not be relied upon
256 /// and is subject to future changes.
257 ///
258 /// # Panics
259 ///
260 /// Panics if writing to `io::stderr` fails.
261 ///
262 /// # Further examples
263 ///
264 /// With a method call:
265 ///
266 /// ```rust
267 /// fn foo(n: usize) {
268 ///     if let Some(_) = dbg!(n.checked_sub(4)) {
269 ///         // ...
270 ///     }
271 /// }
272 ///
273 /// foo(3)
274 /// ```
275 ///
276 /// This prints to [stderr]:
277 ///
278 /// ```text,ignore
279 /// [src/main.rs:4] n.checked_sub(4) = None
280 /// ```
281 ///
282 /// Naive factorial implementation:
283 ///
284 /// ```rust
285 /// fn factorial(n: u32) -> u32 {
286 ///     if dbg!(n <= 1) {
287 ///         dbg!(1)
288 ///     } else {
289 ///         dbg!(n * factorial(n - 1))
290 ///     }
291 /// }
292 ///
293 /// dbg!(factorial(4));
294 /// ```
295 ///
296 /// This prints to [stderr]:
297 ///
298 /// ```text,ignore
299 /// [src/main.rs:3] n <= 1 = false
300 /// [src/main.rs:3] n <= 1 = false
301 /// [src/main.rs:3] n <= 1 = false
302 /// [src/main.rs:3] n <= 1 = true
303 /// [src/main.rs:4] 1 = 1
304 /// [src/main.rs:5] n * factorial(n - 1) = 2
305 /// [src/main.rs:5] n * factorial(n - 1) = 6
306 /// [src/main.rs:5] n * factorial(n - 1) = 24
307 /// [src/main.rs:11] factorial(4) = 24
308 /// ```
309 ///
310 /// The `dbg!(..)` macro moves the input:
311 ///
312 /// ```compile_fail
313 /// /// A wrapper around `usize` which importantly is not Copyable.
314 /// #[derive(Debug)]
315 /// struct NoCopy(usize);
316 ///
317 /// let a = NoCopy(42);
318 /// let _ = dbg!(a); // <-- `a` is moved here.
319 /// let _ = dbg!(a); // <-- `a` is moved again; error!
320 /// ```
321 ///
322 /// You can also use `dbg!()` without a value to just print the
323 /// file and line whenever it's reached.
324 ///
325 /// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
326 /// a tuple (and return it, too):
327 ///
328 /// ```
329 /// assert_eq!(dbg!(1usize, 2u32), (1, 2));
330 /// ```
331 ///
332 /// However, a single argument with a trailing comma will still not be treated
333 /// as a tuple, following the convention of ignoring trailing commas in macro
334 /// invocations. You can use a 1-tuple directly if you need one:
335 ///
336 /// ```
337 /// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
338 /// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
339 /// ```
340 ///
341 /// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
342 /// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
343 /// [`log`]: https://crates.io/crates/log
344 #[macro_export]
345 #[cfg_attr(not(test), rustc_diagnostic_item = "dbg_macro")]
346 macro_rules! dbg {
347     // NOTE: We cannot use `concat!` to make a static string as a format argument
348     // of `eprintln!` because `file!` could contain a `{` or
349     // `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
350     // will be malformed.
351     () => {
352         $crate::std::eprintln!("[{}:{}]", $crate::std::file!(), $crate::std::line!())
353     };
354     ($val:expr $(,)?) => {
355         // Use of `match` here is intentional because it affects the lifetimes
356         // of temporaries - https://stackoverflow.com/a/48732525/1063961
357         match $val {
358             tmp => {
359                 $crate::std::eprintln!("[{}:{}] {} = {:#?}",
360                     $crate::std::file!(), $crate::std::line!(), $crate::std::stringify!($val), &tmp);
361                 tmp
362             }
363         }
364     };
365     ($($val:expr),+ $(,)?) => {
366         ($($crate::std::dbg!($val)),+,)
367     };
368 }
369 
370 #[cfg(test)]
371 macro_rules! assert_approx_eq {
372     ($a:expr, $b:expr) => {{
373         let (a, b) = (&$a, &$b);
374         assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
375     }};
376 }
377 
378 #[macro_export]
379 #[cfg(not(feature = "trace"))]
380 macro_rules! trace {
381     ($($arg:tt)*) => {};
382 }
383 
384 #[macro_export]
385 #[cfg(feature = "trace")]
386 macro_rules! trace {
387     ($($arg:tt)*) => ({
388         use $crate::{Pal, Sys};
389         eprintln!($($arg)*);
390     });
391 }
392 
393 #[macro_export]
394 #[cfg(not(feature = "trace"))]
395 macro_rules! trace_expr {
396     ($expr:expr, $($arg:tt)*) => {
397         $expr
398     };
399 }
400 
401 #[macro_export]
402 #[cfg(feature = "trace")]
403 macro_rules! trace_expr {
404     ($expr:expr, $($arg:tt)*) => ({
405         use $crate::header::errno::STR_ERROR;
406         use $crate::platform;
407 
408         trace!("{}", format_args!($($arg)*));
409 
410         #[allow(unused_unsafe)]
411         let trace_old_errno = unsafe { dlibc::errno };
412         #[allow(unused_unsafe)]
413         unsafe { dlibc::errno = 0; }
414 
415         let ret = $expr;
416 
417         #[allow(unused_unsafe)]
418         let trace_errno = unsafe { dlibc::errno } as isize;
419         if trace_errno == 0 {
420             #[allow(unused_unsafe)]
421             unsafe { dlibc::errno = trace_old_errno; }
422         }
423 
424         let trace_strerror = if trace_errno >= 0 && trace_errno < STR_ERROR.len() as isize {
425             STR_ERROR[trace_errno as usize]
426         } else {
427             "Unknown error"
428         };
429 
430         trace!("{} = {} ({}, {})", format_args!($($arg)*), ret, trace_errno, trace_strerror);
431 
432         ret
433     });
434 }
435 
436 #[macro_export]
437 macro_rules! strto_impl {
438     (
439         $rettype:ty, $signed:expr, $maxval:expr, $minval:expr, $s:ident, $endptr:ident, $base:ident
440     ) => {{
441         // ensure these are constants
442         const CHECK_SIGN: bool = $signed;
443         const MAX_VAL: $rettype = $maxval;
444         const MIN_VAL: $rettype = $minval;
445 
446         let set_endptr = |idx: isize| {
447             if !$endptr.is_null() {
448                 // This is stupid, but apparently strto* functions want
449                 // const input but mut output, yet the man page says
450                 // "stores the address of the first invalid character in *endptr"
451                 // so obviously it doesn't want us to clone it.
452                 *$endptr = $s.offset(idx) as *mut _;
453             }
454         };
455 
456         let invalid_input = || {
457             dlibc::errno = EINVAL;
458             set_endptr(0);
459         };
460 
461         // only valid bases are 2 through 36
462         if $base != 0 && ($base < 2 || $base > 36) {
463             invalid_input();
464             return 0;
465         }
466 
467         let mut idx = 0;
468 
469         // skip any whitespace at the beginning of the string
470         while ctype::isspace(*$s.offset(idx) as c_int) != 0 {
471             idx += 1;
472         }
473 
474         // check for +/-
475         let positive = match is_positive(*$s.offset(idx)) {
476             Some((pos, i)) => {
477                 idx += i;
478                 pos
479             }
480             None => {
481                 invalid_input();
482                 return 0;
483             }
484         };
485 
486         // convert the string to a number
487         let num_str = $s.offset(idx);
488         let res = match $base {
489             0 => detect_base(num_str)
490                 .and_then(|($base, i)| convert_integer(num_str.offset(i), $base)),
491             8 => convert_octal(num_str),
492             16 => convert_hex(num_str),
493             _ => convert_integer(num_str, $base),
494         };
495 
496         // check for error parsing octal/hex prefix
497         // also check to ensure a number was indeed parsed
498         let (num, i, overflow) = match res {
499             Some(res) => res,
500             None => {
501                 invalid_input();
502                 return 0;
503             }
504         };
505         idx += i;
506 
507         let overflow = if CHECK_SIGN {
508             overflow || (num as c_long).is_negative()
509         } else {
510             overflow
511         };
512         // account for the sign
513         let num = num as $rettype;
514         let num = if overflow {
515             dlibc::errno = ERANGE;
516             if CHECK_SIGN {
517                 if positive {
518                     MAX_VAL
519                 } else {
520                     MIN_VAL
521                 }
522             } else {
523                 MAX_VAL
524             }
525         } else {
526             if positive {
527                 num
528             } else {
529                 // not using -num to keep the compiler happy
530                 num.overflowing_neg().0
531             }
532         };
533 
534         set_endptr(idx);
535 
536         num
537     }};
538 }
539 #[macro_export]
540 macro_rules! strto_float_impl {
541     ($type:ident, $s:expr, $endptr:expr) => {{
542         let mut s = $s;
543         let endptr = $endptr;
544 
545         // TODO: Handle named floats: NaN, Inf...
546 
547         while ctype::isspace(*s as c_int) != 0 {
548             s = s.offset(1);
549         }
550 
551         let mut result: $type = 0.0;
552         let mut radix = 10;
553 
554         let result_sign = match *s as u8 {
555             b'-' => {
556                 s = s.offset(1);
557                 -1.0
558             }
559             b'+' => {
560                 s = s.offset(1);
561                 1.0
562             }
563             _ => 1.0,
564         };
565 
566         if *s as u8 == b'0' && *s.offset(1) as u8 == b'x' {
567             s = s.offset(2);
568             radix = 16;
569         }
570 
571         while let Some(digit) = (*s as u8 as char).to_digit(radix) {
572             result *= radix as $type;
573             result += digit as $type;
574             s = s.offset(1);
575         }
576 
577         if *s as u8 == b'.' {
578             s = s.offset(1);
579 
580             let mut i = 1.0;
581             while let Some(digit) = (*s as u8 as char).to_digit(radix) {
582                 i *= radix as $type;
583                 result += digit as $type / i;
584                 s = s.offset(1);
585             }
586         }
587 
588         let s_before_exponent = s;
589 
590         let exponent = match (*s as u8, radix) {
591             (b'e' | b'E', 10) | (b'p' | b'P', 16) => {
592                 s = s.offset(1);
593 
594                 let is_exponent_positive = match *s as u8 {
595                     b'-' => {
596                         s = s.offset(1);
597                         false
598                     }
599                     b'+' => {
600                         s = s.offset(1);
601                         true
602                     }
603                     _ => true,
604                 };
605 
606                 // Exponent digits are always in base 10.
607                 if (*s as u8 as char).is_digit(10) {
608                     let mut exponent_value = 0;
609 
610                     while let Some(digit) = (*s as u8 as char).to_digit(10) {
611                         exponent_value *= 10;
612                         exponent_value += digit;
613                         s = s.offset(1);
614                     }
615 
616                     let exponent_base = match radix {
617                         10 => 10u128,
618                         16 => 2u128,
619                         _ => unreachable!(),
620                     };
621 
622                     if is_exponent_positive {
623                         Some(exponent_base.pow(exponent_value) as $type)
624                     } else {
625                         Some(1.0 / (exponent_base.pow(exponent_value) as $type))
626                     }
627                 } else {
628                     // Exponent had no valid digits after 'e'/'p' and '+'/'-', rollback
629                     s = s_before_exponent;
630                     None
631                 }
632             }
633             _ => None,
634         };
635 
636         if !endptr.is_null() {
637             // This is stupid, but apparently strto* functions want
638             // const input but mut output, yet the man page says
639             // "stores the address of the first invalid character in *endptr"
640             // so obviously it doesn't want us to clone it.
641             *endptr = s as *mut _;
642         }
643 
644         if let Some(exponent) = exponent {
645             result_sign * result * exponent
646         } else {
647             result_sign * result
648         }
649     }};
650 }
651 #[macro_export]
652 macro_rules! c_str {
653     ($lit:expr) => {
654         #[allow(unused_unsafe)]
655         unsafe {
656             $crate::c_str::CStr::from_bytes_with_nul_unchecked(concat!($lit, "\0").as_bytes())
657         }
658     };
659 }
660