Make wgettext_fmt! require an argument *to* format

Like FLOGF!, this now needs at least one argument to format.

This avoids some issues with missing variables and broken format
strings - it is how I found 13ba5bd405c50ffa7b7c7fc4082e8acebb5b68c -
where disown had a format string, with two placeholders, but no
arguments to fill them with.

For use in e.g. macros, where it's otherwise hard to tell if we have
something to format or not, this adds a wgettext_maybe_fmt! version to
"maybe" format, if necessary.
This commit is contained in:
Fabian Boehm 2023-11-29 18:07:53 +01:00
parent f57c5e3a5f
commit 0aa08cf267
10 changed files with 30 additions and 17 deletions

View File

@ -2663,7 +2663,7 @@ macro_rules! parse_error_range {
$(,)?
) => {
let text = if $self.out_errors.is_some() && !$self.unwinding {
Some(wgettext_fmt!($fmt $(, $args)*))
Some(wgettext_maybe_fmt!($fmt $(, $args)*))
} else {
None
};

View File

@ -376,13 +376,13 @@ pub fn functions(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -
props.definition_lineno()
));
}
None => comment.push_utfstr(&wgettext_fmt!("Defined interactively")),
None => comment.push_utfstr(&wgettext!("Defined interactively")),
}
if props.is_copy() {
match props.copy_definition_file() {
Some(path) if path == "-" => {
comment.push_utfstr(&wgettext_fmt!(", copied via `source`"))
comment.push_utfstr(&wgettext!(", copied via `source`"))
}
Some(path) => {
comment.push_utfstr(&wgettext_fmt!(
@ -391,7 +391,7 @@ pub fn functions(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -
props.copy_definition_lineno()
));
}
None => comment.push_utfstr(&wgettext_fmt!(", copied interactively")),
None => comment.push_utfstr(&wgettext!(", copied interactively")),
}
}
}

View File

@ -234,7 +234,7 @@ impl<'a, 'b> builtin_printf_state_t<'a, 'b> {
// Do it if the unconverted digit is a valid hex digit,
// because it could also be an "0x" -> "0" typo.
if s.char_at(0) == '0' && iswxdigit(end.char_at(0)) {
self.nonfatal_error(wgettext_fmt!(
self.nonfatal_error(wgettext!(
"Hint: a leading '0' without an 'x' indicates an octal number"
));
}

View File

@ -88,9 +88,9 @@ pub fn r#type(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> O
let mut comment = WString::new();
if path.is_empty() {
comment.push_utfstr(&wgettext_fmt!("Defined interactively"));
comment.push_utfstr(&wgettext!("Defined interactively"));
} else if path == L!("-") {
comment.push_utfstr(&wgettext_fmt!("Defined via `source`"));
comment.push_utfstr(&wgettext!("Defined via `source`"));
} else {
let lineno: i32 = props.definition_lineno();
comment.push_utfstr(&wgettext_fmt!(
@ -103,9 +103,9 @@ pub fn r#type(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -> O
if props.is_copy() {
let path = props.copy_definition_file().unwrap_or(L!(""));
if path.is_empty() {
comment.push_utfstr(&wgettext_fmt!(", copied interactively"));
comment.push_utfstr(&wgettext!(", copied interactively"));
} else if path == L!("-") {
comment.push_utfstr(&wgettext_fmt!(", copied via `source`"));
comment.push_utfstr(&wgettext!(", copied via `source`"));
} else {
let lineno = props.copy_definition_lineno();
comment.push_utfstr(&wgettext_fmt!(

View File

@ -358,7 +358,7 @@ macro_rules! append_syntax_error {
error.source_start = $source_start;
error.source_length = 0;
error.code = ParseErrorCode::syntax;
error.text = wgettext_fmt!($fmt $(, $arg)*);
error.text = wgettext_maybe_fmt!($fmt $(, $arg)*);
errors.push(error);
}
}
@ -374,7 +374,7 @@ macro_rules! append_cmdsub_error {
) => {
append_cmdsub_error_formatted!(
$errors, $source_start, $source_end,
wgettext_fmt!($fmt $(, $arg)*));
wgettext_maybe_fmt!($fmt $(, $arg)*));
}
}

View File

@ -49,7 +49,7 @@ use crate::trace::{trace_if_enabled, trace_if_enabled_with_args};
use crate::wchar::{wstr, WString, L};
use crate::wchar_ext::WExt;
use crate::wildcard::wildcard_match;
use crate::wutil::{wgettext, wgettext_fmt};
use crate::wutil::{wgettext, wgettext_maybe_fmt};
use libc::{c_int, ENOTDIR, EXIT_SUCCESS, STDERR_FILENO, STDOUT_FILENO};
use std::cell::RefCell;
use std::io::ErrorKind;
@ -115,7 +115,7 @@ impl ParseExecutionContext {
// 'end_execution_reason_t::error'.
macro_rules! report_error {
( $self:ident, $ctx:expr, $status:expr, $node:expr, $fmt:expr $(, $arg:expr )* $(,)? ) => {
report_error_formatted!($self, $ctx, $status, $node, wgettext_fmt!($fmt $(, $arg )*))
report_error_formatted!($self, $ctx, $status, $node, wgettext_maybe_fmt!($fmt $(, $arg )*))
};
}
macro_rules! report_error_formatted {

View File

@ -1166,7 +1166,7 @@ macro_rules! append_syntax_error {
{
append_syntax_error_formatted!(
$errors, $source_location, $source_length,
wgettext_fmt!($fmt $(, $arg)*))
wgettext_maybe_fmt!($fmt $(, $arg)*))
}
}
}

View File

@ -14,7 +14,7 @@ pub(crate) mod prelude {
pub(crate) use crate::{
wchar::{wstr, IntoCharIter, WString, L},
wchar_ext::{ToWString, WExt},
wutil::{sprintf, wgettext, wgettext_fmt, wgettext_str},
wutil::{sprintf, wgettext, wgettext_fmt, wgettext_maybe_fmt, wgettext_str},
};
pub(crate) use widestring_suffix::widestrs;
}

View File

@ -44,6 +44,19 @@ pub(crate) use wgettext_expr;
/// Like wgettext, but applies a sprintf format string.
/// The result is a WString.
macro_rules! wgettext_fmt {
(
$string:expr, // format string
$($args:expr),+ // list of expressions
$(,)? // optional trailing comma
) => {
crate::wutil::sprintf!(&crate::wutil::wgettext!($string), $($args),+)
};
}
pub(crate) use wgettext_fmt;
/// Like wgettext_fmt, but doesn't require an argument to format.
/// For use in macros.
macro_rules! wgettext_maybe_fmt {
(
$string:expr // format string
$(, $args:expr)* // list of expressions
@ -52,7 +65,7 @@ macro_rules! wgettext_fmt {
crate::wutil::sprintf!(&crate::wutil::wgettext!($string), $($args),*)
};
}
pub(crate) use wgettext_fmt;
pub(crate) use wgettext_maybe_fmt;
use crate::ffi_tests::add_test;
add_test!("test_untranslated", || {

View File

@ -19,7 +19,7 @@ use crate::wchar::{wstr, WString, L};
use crate::wchar_ext::WExt;
use crate::wcstringutil::{join_strings, split_string, wcs2string_callback};
use errno::errno;
pub(crate) use gettext::{wgettext, wgettext_fmt, wgettext_str};
pub(crate) use gettext::{wgettext, wgettext_fmt, wgettext_maybe_fmt, wgettext_str};
pub(crate) use printf::sprintf;
use std::ffi::{CStr, OsStr};
use std::fs::{self, canonicalize};