mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-25 10:39:01 -06:00
hayro-cmap reads CMap streams with hayro-postscript's token scanner, whose object::read skipped each `<<` and `>>` by calling itself again. A CMap holding a long run of `<` or `>` used one stack frame per pair, overflowed the stack and aborted the process. Vendor hayro-postscript 0.1.0 with read() looping over the delimiters instead (from storytold/craft-libs#263), patched in beside hayro-cmap. Four object::tests cover long `<<` and `>>` runs and the skipped delimiters, plain and nested.
75 lines
2.0 KiB
Rust
75 lines
2.0 KiB
Rust
//! A small example that shows how to tokenize a PostScript program.
|
|
|
|
#![allow(missing_docs)]
|
|
|
|
use hayro_postscript::{Number, Object, Scanner};
|
|
use std::env;
|
|
use std::fs;
|
|
use std::process;
|
|
|
|
fn main() {
|
|
let path = match env::args().nth(1) {
|
|
Some(p) => p,
|
|
None => {
|
|
eprintln!("Usage: tokenize <file>");
|
|
process::exit(1);
|
|
}
|
|
};
|
|
|
|
let data = match fs::read(&path) {
|
|
Ok(d) => d,
|
|
Err(e) => {
|
|
eprintln!("Error reading {path}: {e}");
|
|
process::exit(1);
|
|
}
|
|
};
|
|
|
|
let mut scanner = Scanner::new(&data);
|
|
|
|
while !scanner.at_end() {
|
|
match scanner.parse_object() {
|
|
Ok(object) => {
|
|
print_object(&object);
|
|
println!();
|
|
}
|
|
Err(e) => eprintln!("Error: {e}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn print_object(object: &Object<'_>) {
|
|
match object {
|
|
Object::Number(Number::Integer(n)) => print!("Integer({n})"),
|
|
Object::Number(Number::Real(n)) => print!("Real({n})"),
|
|
Object::Name(name) => {
|
|
let kind = if name.is_literal() {
|
|
"literal"
|
|
} else {
|
|
"executable"
|
|
};
|
|
let text = name.as_str().unwrap_or("<non-ascii name>");
|
|
print!("Name({text}, {kind})");
|
|
}
|
|
Object::String(s) => {
|
|
let decoded = s.decode().unwrap_or_else(|_| Vec::new());
|
|
print!("String({})", String::from_utf8_lossy(&decoded));
|
|
}
|
|
Object::Array(arr) => {
|
|
print!("[");
|
|
let mut inner = arr.objects();
|
|
let mut first = true;
|
|
while !inner.at_end() {
|
|
if !first {
|
|
print!(" ");
|
|
}
|
|
first = false;
|
|
match inner.parse_object() {
|
|
Ok(obj) => print_object(&obj),
|
|
Err(e) => print!("Error({e})"),
|
|
}
|
|
}
|
|
print!("]");
|
|
}
|
|
}
|
|
}
|