Skip to content

libterm: parse extended terminfo format #68036

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libterm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub fn stderr() -> Option<Box<StderrTerminal>> {
#[allow(missing_docs)]
pub mod color {
/// Number for a terminal color
pub type Color = u16;
pub type Color = u32;

pub const BLACK: Color = 0;
pub const RED: Color = 1;
Expand Down
4 changes: 2 additions & 2 deletions src/libterm/terminfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct TermInfo {
/// Map of capability name to boolean value
pub bools: HashMap<String, bool>,
/// Map of capability name to numeric value
pub numbers: HashMap<String, u16>,
pub numbers: HashMap<String, u32>,
/// Map of capability name to raw (unexpanded) string
pub strings: HashMap<String, Vec<u8>>,
}
Expand Down Expand Up @@ -129,7 +129,7 @@ fn cap_for_attr(attr: Attr) -> &'static str {
/// A Terminal that knows how many colors it supports, with a reference to its
/// parsed Terminfo database record.
pub struct TerminfoTerminal<T> {
num_colors: u16,
num_colors: u32,
out: T,
ti: TermInfo,
}
Expand Down
39 changes: 23 additions & 16 deletions src/libterm/terminfo/parser/compiled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,16 @@ pub static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear",

fn read_le_u16(r: &mut dyn io::Read) -> io::Result<u16> {
let mut b = [0; 2];
let mut amt = 0;
while amt < b.len() {
match r.read(&mut b[amt..])? {
0 => return Err(io::Error::new(io::ErrorKind::Other, "end of file")),
n => amt += n,
}
}
r.read_exact(&mut b)?;
Ok((b[0] as u16) | ((b[1] as u16) << 8))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Ok((b[0] as u16) | ((b[1] as u16) << 8))
Ok(u16::from_le_bytes(b))

}

fn read_le_u32(r: &mut dyn io::Read) -> io::Result<u32> {
let mut b = [0; 4];
r.read_exact(&mut b)?;
Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Ok((b[0] as u32) | ((b[1] as u32) << 8) | ((b[2] as u32) << 16) | ((b[3] as u32) << 24))
Ok(u32::from_le_bytes(b))

}

fn read_byte(r: &mut dyn io::Read) -> io::Result<u8> {
match r.bytes().next() {
Some(s) => s,
Expand All @@ -194,9 +194,12 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin

// Check magic number
let magic = t!(read_le_u16(file));
if magic != 0x011A {
return Err(format!("invalid magic number: expected {:x}, found {:x}", 0x011A, magic));
}

let extended = match magic {
0o0432 => false,
0o01036 => true,
_ => return Err(format!("invalid magic number, found {:o}", magic)),
};

// According to the spec, these fields must be >= -1 where -1 means that the feature is not
// supported. Using 0 instead of -1 works because we skip sections with length 0.
Expand Down Expand Up @@ -258,11 +261,15 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, Strin
t!(read_byte(file)); // compensate for padding
}

let numbers_map: HashMap<String, u16> = t! {
(0..numbers_count).filter_map(|i| match read_le_u16(file) {
Ok(0xFFFF) => None,
Ok(n) => Some(Ok((nnames[i].to_string(), n))),
Err(e) => Some(Err(e))
let numbers_map: HashMap<String, u32> = t! {
(0..numbers_count).filter_map(|i| {
let number = if extended { read_le_u32(file) } else { read_le_u16(file).map(Into::into) };

match number {
Ok(0xFFFF) => None,
Ok(n) => Some(Ok((nnames[i].to_string(), n))),
Err(e) => Some(Err(e))
}
}).collect()
};

Expand Down Expand Up @@ -318,7 +325,7 @@ pub fn msys_terminfo() -> TermInfo {
strings.insert("setab".to_string(), b"\x1B[4%p1%dm".to_vec());

let mut numbers = HashMap::new();
numbers.insert("colors".to_string(), 8u16);
numbers.insert("colors".to_string(), 8);

TermInfo {
names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version
Expand Down
2 changes: 1 addition & 1 deletion src/libterm/win.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn bits_to_color(bits: u16) -> color::Color {
_ => unreachable!(),
};

color | (bits & 0x8) // copy the hi-intensity bit
color | (u32::from(bits) & 0x8) // copy the hi-intensity bit
}

impl<T: Write + Send + 'static> WinConsole<T> {
Expand Down