Skip to content

Commit a653a21

Browse files
stty: refactor arg processing loop
1 parent 4bbbb97 commit a653a21

File tree

1 file changed

+124
-146
lines changed

1 file changed

+124
-146
lines changed

src/uu/stty/src/stty.rs

Lines changed: 124 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use std::num::IntErrorKind;
3030
use std::os::fd::{AsFd, BorrowedFd};
3131
use std::os::unix::fs::OpenOptionsExt;
3232
use std::os::unix::io::{AsRawFd, RawFd};
33-
use uucore::error::{UResult, USimpleError};
33+
use uucore::error::{UError, UResult, USimpleError};
3434
use uucore::format_usage;
3535
use uucore::locale::{get_message, get_message_with_args};
3636

@@ -270,37 +270,9 @@ fn stty(opts: &Options) -> UResult<()> {
270270

271271
if let Some(args) = &opts.settings {
272272
let mut args_iter = args.iter();
273-
// iterate over args: skip to next arg if current one is a control char
274273
while let Some(&arg) = args_iter.next() {
275-
// control char
276-
if let Some(char_index) = cc_to_index(arg) {
277-
if let Some(mapping) = args_iter.next() {
278-
let cc_mapping = string_to_control_char(mapping).map_err(|e| {
279-
let message = match e {
280-
ControlCharMappingError::IntOutOfRange(val) => get_message_with_args(
281-
"stty-error-invalid-integer-argument-value-too-large",
282-
HashMap::from([("value".to_string(), format!("'{val}'"))]),
283-
),
284-
ControlCharMappingError::MultipleChars(val) => get_message_with_args(
285-
"stty-error-invalid-integer-argument",
286-
HashMap::from([("value".to_string(), format!("'{val}'"))]),
287-
),
288-
};
289-
USimpleError::new(1, message)
290-
})?;
291-
valid_args.push(ArgOptions::Mapping((char_index, cc_mapping)));
292-
} else {
293-
return Err(USimpleError::new(
294-
1,
295-
get_message_with_args(
296-
"stty-error-missing-argument",
297-
HashMap::from([("arg".to_string(), (*arg).to_string())]),
298-
),
299-
));
300-
}
301-
// ispeed/ospeed baud rate setting
302-
} else if arg == "ispeed" || arg == "ospeed" {
303-
match args_iter.next() {
274+
match arg {
275+
"ispeed" | "ospeed" => match args_iter.next() {
304276
Some(speed) => {
305277
if let Some(baud_flag) = string_to_baud(speed) {
306278
valid_args.push(ArgOptions::Flags(baud_flag));
@@ -318,149 +290,125 @@ fn stty(opts: &Options) -> UResult<()> {
318290
}
319291
}
320292
None => {
321-
return Err(USimpleError::new(
322-
1,
323-
get_message_with_args(
324-
"stty-error-missing-argument",
325-
HashMap::from([("arg".to_string(), (*arg).to_string())]),
326-
),
327-
));
293+
return missing_arg(arg);
328294
}
329-
}
330-
} else if arg == "line" {
331-
match args_iter.next() {
295+
},
296+
"line" => match args_iter.next() {
332297
Some(line) => match parse_u8_or_err(line) {
333298
Ok(n) => valid_args.push(ArgOptions::Special(SpecialSetting::Line(n))),
334299
Err(e) => return Err(USimpleError::new(1, e)),
335300
},
336301
None => {
337-
return Err(USimpleError::new(
338-
1,
339-
get_message_with_args(
340-
"stty-error-missing-argument",
341-
HashMap::from([("arg".to_string(), arg.to_string())]),
342-
),
343-
));
302+
return missing_arg(arg);
344303
}
345-
}
346-
} else if arg == "min" {
347-
match args_iter.next() {
304+
},
305+
"min" => match args_iter.next() {
348306
Some(min) => match parse_u8_or_err(min) {
349307
Ok(n) => {
350308
valid_args.push(ArgOptions::Mapping((S::VMIN, n)));
351309
}
352310
Err(e) => return Err(USimpleError::new(1, e)),
353311
},
354312
None => {
355-
return Err(USimpleError::new(
356-
1,
357-
get_message_with_args(
358-
"stty-error-missing-argument",
359-
HashMap::from([("arg".to_string(), arg.to_string())]),
360-
),
361-
));
313+
return missing_arg(arg);
362314
}
363-
}
364-
} else if arg == "time" {
365-
match args_iter.next() {
315+
},
316+
"time" => match args_iter.next() {
366317
Some(time) => match parse_u8_or_err(time) {
367318
Ok(n) => valid_args.push(ArgOptions::Mapping((S::VTIME, n))),
368319
Err(e) => return Err(USimpleError::new(1, e)),
369320
},
370321
None => {
371-
return Err(USimpleError::new(
372-
1,
373-
get_message_with_args(
374-
"stty-error-missing-argument",
375-
HashMap::from([("arg".to_string(), arg.to_string())]),
376-
),
377-
));
322+
return missing_arg(arg);
323+
}
324+
},
325+
"rows" => {
326+
if let Some(rows) = args_iter.next() {
327+
if let Some(n) = parse_rows_cols(rows) {
328+
valid_args.push(ArgOptions::Special(SpecialSetting::Rows(n)));
329+
} else {
330+
return invalid_integer_arg(rows);
331+
}
332+
} else {
333+
return missing_arg(arg);
378334
}
379335
}
380-
// baud rate setting
381-
} else if let Some(baud_flag) = string_to_baud(arg) {
382-
valid_args.push(ArgOptions::Flags(baud_flag));
383-
// non control char flag
384-
} else if let Some(flag) = string_to_flag(arg) {
385-
let remove_group = match flag {
386-
AllFlags::Baud(_) => false,
387-
AllFlags::ControlFlags((flag, remove)) => check_flag_group(flag, remove),
388-
AllFlags::InputFlags((flag, remove)) => check_flag_group(flag, remove),
389-
AllFlags::LocalFlags((flag, remove)) => check_flag_group(flag, remove),
390-
AllFlags::OutputFlags((flag, remove)) => check_flag_group(flag, remove),
391-
};
392-
if remove_group {
393-
return Err(USimpleError::new(
394-
1,
395-
get_message_with_args(
396-
"stty-error-invalid-argument",
397-
HashMap::from([("arg".to_string(), (*arg).to_string())]),
398-
),
399-
));
400-
}
401-
valid_args.push(flag.into());
402-
// combination setting
403-
} else if let Some(combo) = string_to_combo(arg) {
404-
valid_args.append(&mut combo_to_flags(combo));
405-
} else if arg == "rows" {
406-
if let Some(rows) = args_iter.next() {
407-
if let Some(n) = parse_rows_cols(rows) {
408-
valid_args.push(ArgOptions::Special(SpecialSetting::Rows(n)));
336+
"columns" | "cols" => {
337+
if let Some(cols) = args_iter.next() {
338+
if let Some(n) = parse_rows_cols(cols) {
339+
valid_args.push(ArgOptions::Special(SpecialSetting::Cols(n)));
340+
} else {
341+
return invalid_integer_arg(cols);
342+
}
409343
} else {
410-
return Err(USimpleError::new(
411-
1,
412-
get_message_with_args(
413-
"stty-error-invalid-integer-argument",
414-
HashMap::from([("value".to_string(), format!("'{rows}'"))]),
415-
),
416-
));
344+
return missing_arg(arg);
417345
}
418-
} else {
419-
return Err(USimpleError::new(
420-
1,
421-
get_message_with_args(
422-
"stty-error-missing-argument",
423-
HashMap::from([("arg".to_string(), (*arg).to_string())]),
424-
),
425-
));
426346
}
427-
} else if arg == "columns" || arg == "cols" {
428-
if let Some(cols) = args_iter.next() {
429-
if let Some(n) = parse_rows_cols(cols) {
430-
valid_args.push(ArgOptions::Special(SpecialSetting::Cols(n)));
347+
"drain" => {
348+
set_arg = SetArg::TCSADRAIN;
349+
}
350+
"-drain" => {
351+
set_arg = SetArg::TCSANOW;
352+
}
353+
"size" => {
354+
valid_args.push(ArgOptions::Print(PrintSetting::Size));
355+
}
356+
&_ => {
357+
// control char
358+
if let Some(char_index) = cc_to_index(arg) {
359+
if let Some(mapping) = args_iter.next() {
360+
let cc_mapping = string_to_control_char(mapping).map_err(|e| {
361+
let message = match e {
362+
ControlCharMappingError::IntOutOfRange(val) => {
363+
get_message_with_args(
364+
"stty-error-invalid-integer-argument-value-too-large",
365+
HashMap::from([(
366+
"value".to_string(),
367+
format!("'{val}'"),
368+
)]),
369+
)
370+
}
371+
ControlCharMappingError::MultipleChars(val) => {
372+
get_message_with_args(
373+
"stty-error-invalid-integer-argument",
374+
HashMap::from([(
375+
"value".to_string(),
376+
format!("'{val}'"),
377+
)]),
378+
)
379+
}
380+
};
381+
USimpleError::new(1, message)
382+
})?;
383+
valid_args.push(ArgOptions::Mapping((char_index, cc_mapping)));
384+
} else {
385+
return missing_arg(arg);
386+
}
387+
// baud rate
388+
} else if let Some(baud_flag) = string_to_baud(arg) {
389+
valid_args.push(ArgOptions::Flags(baud_flag));
390+
// non control char flag
391+
} else if let Some(flag) = string_to_flag(arg) {
392+
let remove_group = match flag {
393+
AllFlags::Baud(_) => false,
394+
AllFlags::ControlFlags((flag, remove)) => {
395+
check_flag_group(flag, remove)
396+
}
397+
AllFlags::InputFlags((flag, remove)) => check_flag_group(flag, remove),
398+
AllFlags::LocalFlags((flag, remove)) => check_flag_group(flag, remove),
399+
AllFlags::OutputFlags((flag, remove)) => check_flag_group(flag, remove),
400+
};
401+
if remove_group {
402+
return invalid_arg(arg);
403+
}
404+
valid_args.push(flag.into());
405+
// combination setting
406+
} else if let Some(combo) = string_to_combo(arg) {
407+
valid_args.append(&mut combo_to_flags(combo));
431408
} else {
432-
return Err(USimpleError::new(
433-
1,
434-
get_message_with_args(
435-
"stty-error-invalid-integer-argument",
436-
HashMap::from([("value".to_string(), format!("'{cols}'"))]),
437-
),
438-
));
409+
return invalid_arg(arg);
439410
}
440-
} else {
441-
return Err(USimpleError::new(
442-
1,
443-
get_message_with_args(
444-
"stty-error-missing-argument",
445-
HashMap::from([("arg".to_string(), (*arg).to_string())]),
446-
),
447-
));
448411
}
449-
} else if arg == "drain" {
450-
set_arg = SetArg::TCSADRAIN;
451-
} else if arg == "-drain" {
452-
set_arg = SetArg::TCSANOW;
453-
} else if arg == "size" {
454-
valid_args.push(ArgOptions::Print(PrintSetting::Size));
455-
// not a valid option
456-
} else {
457-
return Err(USimpleError::new(
458-
1,
459-
get_message_with_args(
460-
"stty-error-invalid-argument",
461-
HashMap::from([("arg".to_string(), (*arg).to_string())]),
462-
),
463-
));
464412
}
465413
}
466414

@@ -490,6 +438,36 @@ fn stty(opts: &Options) -> UResult<()> {
490438
Ok(())
491439
}
492440

441+
fn missing_arg<T>(arg: &str) -> Result<T, Box<dyn UError>> {
442+
Err::<T, Box<dyn UError>>(USimpleError::new(
443+
1,
444+
get_message_with_args(
445+
"stty-error-missing-argument",
446+
HashMap::from([("arg".to_string(), (*arg).to_string())]),
447+
),
448+
))
449+
}
450+
451+
fn invalid_arg<T>(arg: &str) -> Result<T, Box<dyn UError>> {
452+
Err::<T, Box<dyn UError>>(USimpleError::new(
453+
1,
454+
get_message_with_args(
455+
"stty-error-invalid-argument",
456+
HashMap::from([("arg".to_string(), (*arg).to_string())]),
457+
),
458+
))
459+
}
460+
461+
fn invalid_integer_arg<T>(arg: &str) -> Result<T, Box<dyn UError>> {
462+
Err::<T, Box<dyn UError>>(USimpleError::new(
463+
1,
464+
get_message_with_args(
465+
"stty-error-invalid-integer-argument",
466+
HashMap::from([("value".to_string(), format!("'{arg}'"))]),
467+
),
468+
))
469+
}
470+
493471
/// GNU uses different error messages if values overflow or underflow a u8,
494472
/// this function returns the appropriate error message in the case of overflow or underflow, or u8 on success
495473
fn parse_u8_or_err(arg: &str) -> Result<u8, String> {

0 commit comments

Comments
 (0)