diff --git a/src/preprocess.rs b/src/preprocess.rs index 83fc0ce..6764c37 100644 --- a/src/preprocess.rs +++ b/src/preprocess.rs @@ -359,108 +359,110 @@ pub fn find_include_file(include_path: &String, origin: Option<&PathBuf>, search } } -fn line_muncher(line: &Line, original_lineno: &mut u32, level: &mut u32, level_true: &mut u32, origin: Option, definition_map: &mut HashMap, info: &mut PreprocessInfo, includefolders: &Vec) -> Result { - let mut output = String::from(""); - match line { - Line::DirectiveLine(dir) => match dir { - Directive::IncludeDirective(path) => { - if *level > *level_true { return Ok(output.to_string()); } +pub struct PreprocessHolder<'a> { + pub origin: Option, + pub definition_map: &'a mut HashMap, + pub info: &'a mut PreprocessInfo, + pub includefolders: &'a Vec, + pub original_lineno: u32, + pub level: u32, + pub level_true: u32, + pub line: std::slice::Iter<'a, Line>, +} - //let import_tree = &mut info.import_tree; - //let includer = import_tree.get(&path); - //if let Some(path) = includer { - // // @todo: complain - //} +impl<'a> PreprocessHolder<'a> { + fn line_muncher(&mut self, line: &Line, origin: Option) -> Result { + let mut output = String::from(""); + match line { + Line::DirectiveLine(dir) => match dir { + Directive::IncludeDirective(path) => { + if self.level > self.level_true { return Ok(output.to_string()); } - let file_path = find_include_file(&path, origin.as_ref(), includefolders)?; + //let import_tree = &mut info.import_tree; + //let includer = import_tree.get(&path); + //if let Some(path) = includer { + // // @todo: complain + //} - info.import_stack.push(file_path.clone()); + let file_path = find_include_file(&path, origin.as_ref(), self.includefolders)?; - let mut content = String::new(); - File::open(&file_path)?.read_to_string(&mut content)?; - let result = preprocess_rec(content, Some(file_path), definition_map, info, includefolders).prepend_error(format!("Failed to preprocess include \"{}\":", path))?; + self.info.import_stack.push(file_path.clone()); - info.import_stack.pop(); + let mut content = String::new(); + File::open(&file_path)?.read_to_string(&mut content)?; + let result = preprocess_rec(content, Some(file_path), self.definition_map, self.info, self.includefolders).prepend_error(format!("Failed to preprocess include \"{}\":", path))?; - output += &result; - }, - Directive::DefineDirective(def) => { - *original_lineno += u32::sum(def.value.iter().map(|t| match t { - Token::NewlineToken(_s, n) => *n, - Token::CommentToken(n) => *n, - _ => 0 - })); + self.info.import_stack.pop(); + + output += &result; + }, + Directive::DefineDirective(def) => { + self.original_lineno += u32::sum(def.value.iter().map(|t| match t { + Token::NewlineToken(_s, n) => *n, + Token::CommentToken(n) => *n, + _ => 0 + })); - if *level > *level_true { return Ok(output.to_string()); } + if self.level > self.level_true { return Ok(output.to_string()); } - if definition_map.remove(&def.name).is_some() { - // @todo: warn about redefine - } + if self.definition_map.remove(&def.name).is_some() { + // @todo: warn about redefine + } - definition_map.insert(def.name.clone(), def.clone()); - } - Directive::UndefDirective(name) => { - if *level > *level_true { return Ok(output.to_string()); } + self.definition_map.insert(def.name.clone(), def.clone()); + } + Directive::UndefDirective(name) => { + if self.level > self.level_true { return Ok(output.to_string()); } - definition_map.remove(name); - } - Directive::IfDefDirective(name) => { - *level_true += if *level_true == *level && definition_map.contains_key(name) { 1 } else { 0 }; - *level += 1; - } - Directive::IfNDefDirective(name) => { - *level_true += if *level_true == *level && !definition_map.contains_key(name) { 1 } else { 0 }; - *level += 1; - } - Directive::ElseDirective => { - if *level_true + 1 == *level { - *level_true = *level; - } else if *level_true == *level { - *level_true -= 1; + self.definition_map.remove(name); } - } - Directive::EndIfDirective => { - assert!(*level > 0); - *level -= 1; - if *level_true > *level { - *level_true -= 1; + Directive::IfDefDirective(name) => { + self.level_true += if self.level_true == self.level && self.definition_map.contains_key(name) { 1 } else { 0 }; + self.level += 1; } - } - }, - Line::TokenLine(tokens) => { - let stack: Vec = Vec::new(); - let resolved = Macro::resolve_all(&tokens, &definition_map, &stack).prepend_error("Failed to resolve macros:")?; + Directive::IfNDefDirective(name) => { + self.level_true += if self.level_true == self.level && !self.definition_map.contains_key(name) { 1 } else { 0 }; + self.level += 1; + } + Directive::ElseDirective => { + if self.level_true + 1 == self.level { + self.level_true = self.level; + } else if self.level_true == self.level { + self.level_true -= 1; + } + } + Directive::EndIfDirective => { + assert!(self.level > 0); + self.level -= 1; + if self.level_true > self.level { + self.level_true -= 1; + } + } + }, + Line::TokenLine(tokens) => { + let stack: Vec = Vec::new(); + let resolved = Macro::resolve_all(&tokens, &self.definition_map, &stack).prepend_error("Failed to resolve macros:")?; - let (mut result, newlines) = Token::concat(&resolved); - result = result.replace("\r\n", "\n").replace("\\\n", ""); - *original_lineno += newlines; + let (mut result, newlines) = Token::concat(&resolved); + result = result.replace("\r\n", "\n").replace("\\\n", ""); + self.original_lineno += newlines; - if *level > *level_true { return Ok(output.to_string()); } + if self.level > self.level_true { return Ok(output.to_string()); } - output += &result; - output += "\n"; + output += &result; + output += "\n"; - info.line_origins.push((*original_lineno, origin.clone())); + self.info.line_origins.push((self.original_lineno, origin.clone())); + } } - } - *original_lineno += 1; - - if *level > 0 { - // @todo: complain - } + self.original_lineno += 1; - Ok(output.to_string()) -} + if self.level > 0 { + // @todo: complain + } -pub struct PreprocessHolder<'a> { - pub origin: Option, - pub definition_map: &'a mut HashMap, - pub info: &'a mut PreprocessInfo, - pub includefolders: &'a Vec, - pub original_lineno: &'a mut u32, - pub level: &'a mut u32, - pub level_true: &'a mut u32, - pub line: std::slice::Iter<'a, Line>, + Ok(output.to_string()) + } } impl<'a> Iterator for PreprocessHolder<'a> { @@ -474,9 +476,6 @@ impl<'a> Iterator for PreprocessHolder<'a> { &mut self.level, &mut self.level_true, self.origin.clone(), - &mut self.definition_map, - &mut self.info, - self.includefolders ).unwrap()) } None => None @@ -490,15 +489,11 @@ fn preprocess_rec(input: String, origin: Option, definition_map: &mut H let lines = preprocess_grammar::file(&input).format_error(&origin, &input)?; let mut output = String::from(""); - let mut original_lineno = 1; - let mut level = 0; - let mut level_true = 0; - let pp = PreprocessHolder{ line: lines.iter(), - original_lineno: &mut original_lineno, - level: &mut level, - level_true: &mut level_true, + original_lineno: 1, + level: 0, + level_true: 0, origin: origin.clone(), definition_map, // Surely this needs to be mutable? info,