1use crate::range::Range;
2use nom::combinator::all_consuming;
3use nom_greedyerror::error_position;
4use std::collections::{BTreeMap, HashMap};
5use std::convert::TryInto;
6use std::fs::File;
7use std::hash::BuildHasher;
8use std::io::{BufReader, Read};
9use std::path::{Path, PathBuf};
10use sv_parser_error::Error;
11use sv_parser_parser::{pp_parser, Span, SpanInfo};
12use sv_parser_syntaxtree::{
13 IncludeCompilerDirective, Locate, NodeEvent, RefNode, SourceDescription, TextMacroUsage,
14 WhiteSpace,
15};
16use std::collections::hash_map::RandomState;
17
18const RECURSIVE_LIMIT: usize = 64;
19
20#[derive(Debug)]
21pub struct PreprocessedText {
22 text: String,
23 origins: BTreeMap<Range, Origin>,
24}
25
26#[derive(Debug)]
27pub struct Origin {
28 range: Range,
29 origin: Option<(PathBuf, Range)>,
30}
31
32impl PreprocessedText {
33 fn new() -> Self {
34 PreprocessedText {
35 text: String::new(),
36 origins: BTreeMap::new(),
37 }
38 }
39
40 fn push<T: AsRef<Path>>(&mut self, s: &str, origin: Option<(T, Range)>) {
41 let base = self.text.len();
42 self.text.push_str(s);
43
44 let origin = if let Some((origin_path, origin_range)) = origin {
45 let origin_path = PathBuf::from(origin_path.as_ref());
46 Some((origin_path, origin_range))
47 } else {
48 None
49 };
50
51 let range = Range::new(base, base + s.len());
52 let origin = Origin { range, origin };
53 self.origins.insert(range, origin);
54 }
55
56 fn merge(&mut self, other: PreprocessedText) {
57 let base = self.text.len();
58 self.text.push_str(&other.text);
59 for (mut range, mut origin) in other.origins {
60 range.offset(base);
61 origin.range.offset(base);
62 self.origins.insert(range, origin);
63 }
64 }
65
66 pub fn text(&self) -> &str {
67 &self.text
68 }
69
70 pub fn origin(&self, pos: usize) -> Option<(&PathBuf, usize)> {
71 let origin = self.origins.get(&Range::new(pos, pos + 1));
72 if let Some(origin) = origin {
73 if let Some((ref origin_path, ref origin_range)) = origin.origin {
74 let ret_pos = pos - origin.range.begin + origin_range.begin;
75 Some((&origin_path, ret_pos))
76 } else {
77 None
78 }
79 } else {
80 None
81 }
82 }
83}
84
85#[derive(Clone, Debug, Eq, PartialEq)]
86pub struct Define {
87 pub identifier: String,
88 pub arguments: Vec<(String, Option<String>)>,
89 pub text: Option<DefineText>,
90}
91
92#[derive(Clone, Debug, Eq, PartialEq)]
93pub struct DefineText {
94 pub text: String,
95 pub origin: Option<(PathBuf, Range)>,
96}
97
98impl Define {
99 pub fn new(
100 ident: String,
101 args: Vec<(String, Option<String>)>,
102 text: Option<DefineText>,
103 ) -> Self {
104 Define {
105 identifier: ident,
106 arguments: args,
107 text,
108 }
109 }
110}
111
112impl DefineText {
113 pub fn new(text: String, origin: Option<(PathBuf, Range)>) -> Self {
114 DefineText { text, origin }
115 }
116}
117
118pub type Defines<V=RandomState> = HashMap<String, Option<Define>, V>;
119
120pub fn preprocess<T: AsRef<Path>, U: AsRef<Path>, V: BuildHasher>(
121 path: T,
122 pre_defines: &Defines<V>,
123 include_paths: &[U],
124 strip_comments: bool,
125 ignore_include: bool,
126) -> Result<(PreprocessedText, Defines), Error> {
127 preprocess_inner(
128 path,
129 pre_defines,
130 include_paths,
131 strip_comments,
132 ignore_include,
133 0, )
135}
136
137fn preprocess_inner<T: AsRef<Path>, U: AsRef<Path>, V: BuildHasher>(
138 path: T,
139 pre_defines: &Defines<V>,
140 include_paths: &[U],
141 strip_comments: bool,
142 ignore_include: bool,
143 include_depth: usize,
144) -> Result<(PreprocessedText, Defines), Error> {
145
146 let f = File::open(path.as_ref()).map_err(|x| Error::File {
147 source: x,
148 path: PathBuf::from(path.as_ref()),
149 })?;
150 let mut reader = BufReader::new(f);
151 let mut s = String::new();
152
153 if let Err(_) = reader.read_to_string(&mut s) {
154 Err(Error::ReadUtf8(PathBuf::from(path.as_ref())))
155 } else {
156 preprocess_str(
157 &s,
158 path,
159 pre_defines,
160 include_paths,
161 ignore_include,
162 strip_comments,
163 0, include_depth,
165 )
166 }
167}
168
169struct SkipNodes<'a> {
170 nodes: Vec<RefNode<'a>>,
171}
172
173impl<'a> SkipNodes<'a> {
174 fn new() -> Self {
175 Self { nodes: vec![] }
176 }
177
178 fn push(&mut self, node: RefNode<'a>) {
179 let mut have_locate = false;
182 for x in node.clone() {
183 if let RefNode::Locate(_) = x {
184 have_locate = true;
185 }
186 }
187 if have_locate {
188 self.nodes.push(node);
189 }
190 }
191
192 fn contains(&self, node: &RefNode<'a>) -> bool {
193 self.nodes.contains(node)
194 }
195}
196
197pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>, V: BuildHasher>(
198 s: &str,
199 path: T,
200 pre_defines: &Defines<V>,
201 include_paths: &[U],
202 ignore_include: bool,
203 strip_comments: bool,
204 resolve_depth: usize,
205 include_depth: usize,
206) -> Result<(PreprocessedText, Defines), Error> {
207
208 if include_depth > RECURSIVE_LIMIT {
215 return Err(Error::ExceedRecursiveLimit);
216 }
217
218 let mut skip = false;
219 let mut skip_whitespace = false;
220 let mut skip_nodes = SkipNodes::new();
221 let mut defines = HashMap::new();
222
223 let mut last_item_line = None;
224 let mut last_include_line = None;
225
226 let sv_cov_pre_defines = [
230 ("SV_COV_START", "0"),
231 ("SV_COV_STOP", "1"),
232 ("SV_COV_RESET", "2"),
233 ("SV_COV_CHECK", "3"),
234 ("SV_COV_MODULE", "10"),
235 ("SV_COV_HIER", "11"),
236 ("SV_COV_ASSERTION", "20"),
237 ("SV_COV_FSM_STATE", "21"),
238 ("SV_COV_STATEMENT", "22"),
239 ("SV_COV_TOGGLE", "23"),
240 ("SV_COV_OVERFLOW", "-2"),
241 ("SV_COV_ERROR", "-1"),
242 ("SV_COV_NOCOV", "0"),
243 ("SV_COV_OK", "1"),
244 ("SV_COV_PARTIAL", "2"),
245 ];
246 for (k, v) in sv_cov_pre_defines {
247 let define = Define {
248 identifier: k.to_string(),
249 arguments: Vec::new(),
250 text: Some(DefineText {text: v.to_string(), origin: None}),
251 };
252 defines.insert(k.to_string(), Some(define));
253 }
254
255 for (k, v) in pre_defines {
256 defines.insert(k.clone(), (*v).clone());
257 }
258
259 let span = Span::new_extra(&s, SpanInfo::default());
260 let (_, pp_text) = all_consuming(pp_parser)(span).map_err(|x| match x {
261 nom::Err::Incomplete(_) => Error::Preprocess(None),
262 nom::Err::Error(e) => {
263 if let Some(pos) = error_position(&e) {
264 Error::Preprocess(Some((PathBuf::from(path.as_ref()), pos)))
265 } else {
266 Error::Preprocess(None)
267 }
268 }
269 nom::Err::Failure(e) => {
270 if let Some(pos) = error_position(&e) {
271 Error::Preprocess(Some((PathBuf::from(path.as_ref()), pos)))
272 } else {
273 Error::Preprocess(None)
274 }
275 }
276 })?;
277
278 let mut ret = PreprocessedText::new();
279
280 for n in pp_text.into_iter().event() {
281 match n.clone() {
282 NodeEvent::Enter(x) => {
283 if skip_nodes.contains(&x) {
284 skip = true;
285 }
286 }
287 NodeEvent::Leave(x) => {
288 if skip_nodes.contains(&x) {
289 skip = false;
290 }
291 }
292 }
293 if skip {
294 continue;
295 }
296
297 match n.clone() {
298 NodeEvent::Enter(RefNode::SourceDescriptionNotDirective(x)) => {
299 let locate: Locate = x.try_into().unwrap();
300 if let Some(last_include_line) = last_include_line {
301 if last_include_line == locate.line {
302 return Err(Error::IncludeLine);
303 }
304 }
305 }
306 NodeEvent::Enter(RefNode::CompilerDirective(x)) => {
307 let locate: Locate = x.try_into().unwrap();
308 if let Some(last_include_line) = last_include_line {
309 if last_include_line == locate.line {
310 return Err(Error::IncludeLine);
311 }
312 }
313 }
314 NodeEvent::Leave(RefNode::SourceDescriptionNotDirective(x)) => {
315 let locate: Locate = x.try_into().unwrap();
316 if !locate.str(s).trim().is_empty() {
318 last_item_line = Some(locate.line);
319 }
320 }
321 NodeEvent::Leave(RefNode::CompilerDirective(x)) => {
322 let locate: Locate = x.try_into().unwrap();
323 last_item_line = Some(locate.line);
324 }
325 _ => (),
326 }
327
328 match n {
329 NodeEvent::Enter(RefNode::SourceDescriptionNotDirective(x)) => {
330 let locate: Locate = x.try_into().unwrap();
331 let range = Range::new(locate.offset, locate.offset + locate.len);
332 ret.push(locate.str(&s), Some((path.as_ref(), range)));
333 }
334 NodeEvent::Enter(RefNode::SourceDescription(SourceDescription::StringLiteral(x))) => {
335 let locate: Locate = (&**x).try_into().unwrap();
336 let range = Range::new(locate.offset, locate.offset + locate.len);
337 ret.push(locate.str(&s), Some((path.as_ref(), range)));
338 }
339 NodeEvent::Enter(RefNode::SourceDescription(SourceDescription::EscapedIdentifier(
340 x,
341 ))) => {
342 let locate: Locate = (&**x).try_into().unwrap();
343 let range = Range::new(locate.offset, locate.offset + locate.len);
344 ret.push(locate.str(&s), Some((path.as_ref(), range)));
345 }
346 NodeEvent::Enter(RefNode::ResetallCompilerDirective(x)) => {
347 let locate: Locate = x.try_into().unwrap();
348 let range = Range::new(locate.offset, locate.offset + locate.len);
349 ret.push(locate.str(&s), Some((path.as_ref(), range)));
350 skip_whitespace = true;
351 }
352 NodeEvent::Leave(RefNode::ResetallCompilerDirective(_)) => {
353 skip_whitespace = false;
354 }
355 NodeEvent::Enter(RefNode::TimescaleCompilerDirective(x)) => {
356 let locate: Locate = x.try_into().unwrap();
357 let range = Range::new(locate.offset, locate.offset + locate.len);
358 ret.push(locate.str(&s), Some((path.as_ref(), range)));
359 skip_whitespace = true;
360 }
361 NodeEvent::Leave(RefNode::TimescaleCompilerDirective(_)) => {
362 skip_whitespace = false;
363 }
364 NodeEvent::Enter(RefNode::DefaultNettypeCompilerDirective(x)) => {
365 let locate: Locate = x.try_into().unwrap();
366 let range = Range::new(locate.offset, locate.offset + locate.len);
367 ret.push(locate.str(&s), Some((path.as_ref(), range)));
368 skip_whitespace = true;
369 }
370 NodeEvent::Leave(RefNode::DefaultNettypeCompilerDirective(_)) => {
371 skip_whitespace = false;
372 }
373 NodeEvent::Enter(RefNode::UnconnectedDriveCompilerDirective(x)) => {
374 let locate: Locate = x.try_into().unwrap();
375 let range = Range::new(locate.offset, locate.offset + locate.len);
376 ret.push(locate.str(&s), Some((path.as_ref(), range)));
377 skip_whitespace = true;
378 }
379 NodeEvent::Leave(RefNode::UnconnectedDriveCompilerDirective(_)) => {
380 skip_whitespace = false;
381 }
382 NodeEvent::Enter(RefNode::NounconnectedDriveCompilerDirective(x)) => {
383 let locate: Locate = x.try_into().unwrap();
384 let range = Range::new(locate.offset, locate.offset + locate.len);
385 ret.push(locate.str(&s), Some((path.as_ref(), range)));
386 skip_whitespace = true;
387 }
388 NodeEvent::Leave(RefNode::NounconnectedDriveCompilerDirective(_)) => {
389 skip_whitespace = false;
390 }
391 NodeEvent::Enter(RefNode::CelldefineDriveCompilerDirective(x)) => {
392 let locate: Locate = x.try_into().unwrap();
393 let range = Range::new(locate.offset, locate.offset + locate.len);
394 ret.push(locate.str(&s), Some((path.as_ref(), range)));
395 skip_whitespace = true;
396 }
397 NodeEvent::Leave(RefNode::CelldefineDriveCompilerDirective(_)) => {
398 skip_whitespace = false;
399 }
400 NodeEvent::Enter(RefNode::EndcelldefineDriveCompilerDirective(x)) => {
401 let locate: Locate = x.try_into().unwrap();
402 let range = Range::new(locate.offset, locate.offset + locate.len);
403 ret.push(locate.str(&s), Some((path.as_ref(), range)));
404 skip_whitespace = true;
405 }
406 NodeEvent::Leave(RefNode::EndcelldefineDriveCompilerDirective(_)) => {
407 skip_whitespace = false;
408 }
409 NodeEvent::Enter(RefNode::Pragma(x)) => {
410 let locate: Locate = x.try_into().unwrap();
411 let range = Range::new(locate.offset, locate.offset + locate.len);
412 ret.push(locate.str(&s), Some((path.as_ref(), range)));
413 skip_whitespace = true;
414 }
415 NodeEvent::Leave(RefNode::Pragma(_)) => {
416 skip_whitespace = false;
417 }
418 NodeEvent::Enter(RefNode::LineCompilerDirective(x)) => {
419 let locate: Locate = x.try_into().unwrap();
420 let range = Range::new(locate.offset, locate.offset + locate.len);
421 ret.push(locate.str(&s), Some((path.as_ref(), range)));
422 skip_whitespace = true;
423 }
424 NodeEvent::Leave(RefNode::LineCompilerDirective(_)) => {
425 skip_whitespace = false;
426 }
427 NodeEvent::Enter(RefNode::KeywordsDirective(x)) => {
428 let locate: Locate = x.try_into().unwrap();
429 let range = Range::new(locate.offset, locate.offset + locate.len);
430 ret.push(locate.str(&s), Some((path.as_ref(), range)));
431 skip_whitespace = true;
432 }
433 NodeEvent::Leave(RefNode::KeywordsDirective(_)) => {
434 skip_whitespace = false;
435 }
436 NodeEvent::Enter(RefNode::EndkeywordsDirective(x)) => {
437 let locate: Locate = x.try_into().unwrap();
438 let range = Range::new(locate.offset, locate.offset + locate.len);
439 ret.push(locate.str(&s), Some((path.as_ref(), range)));
440 skip_whitespace = true;
441 }
442 NodeEvent::Leave(RefNode::EndkeywordsDirective(_)) => {
443 skip_whitespace = false;
444 }
445 NodeEvent::Enter(RefNode::UndefineCompilerDirective(x)) => {
446 let (_, _, ref name) = x.nodes;
447 let id = identifier((&name.nodes.0).into(), &s).unwrap();
448 defines.remove(&id);
449
450 let locate: Locate = x.try_into().unwrap();
451 let range = Range::new(locate.offset, locate.offset + locate.len);
452 ret.push(locate.str(&s), Some((path.as_ref(), range)));
453 skip_whitespace = true;
454 }
455 NodeEvent::Leave(RefNode::UndefineCompilerDirective(_)) => {
456 skip_whitespace = false;
457 }
458 NodeEvent::Enter(RefNode::UndefineallCompilerDirective(x)) => {
459 defines.clear();
460
461 let locate: Locate = x.try_into().unwrap();
462 let range = Range::new(locate.offset, locate.offset + locate.len);
463 ret.push(locate.str(&s), Some((path.as_ref(), range)));
464 skip_whitespace = true;
465 }
466 NodeEvent::Leave(RefNode::UndefineallCompilerDirective(_)) => {
467 skip_whitespace = false;
468 }
469 NodeEvent::Enter(RefNode::IfdefDirective(x)) => {
470 let (_, ref keyword, ref ifid, ref ifbody, ref elsif, ref elsebody, _, _) = x.nodes;
471 skip_nodes.push(keyword.into());
472 skip_nodes.push(ifid.into());
473
474 let ifid = identifier(ifid.into(), &s).unwrap();
475 let mut hit = false;
476 if defines.contains_key(&ifid) || is_predefined_text_macro(&ifid) {
477 hit = true;
478 } else {
479 skip_nodes.push(ifbody.into());
480 }
481
482 for x in elsif {
483 let (_, ref keyword, ref elsifid, ref elsifbody) = x;
484 skip_nodes.push(keyword.into());
485 skip_nodes.push(elsifid.into());
486
487 let elsifid = identifier(elsifid.into(), &s).unwrap();
488 if hit {
489 skip_nodes.push(elsifbody.into());
490 } else if defines.contains_key(&elsifid) || is_predefined_text_macro(&ifid) {
491 hit = true;
492 } else {
493 skip_nodes.push(elsifbody.into());
494 }
495 }
496
497 if let Some(elsebody) = elsebody {
498 let (_, ref keyword, ref elsebody) = elsebody;
499 skip_nodes.push(keyword.into());
500 if hit {
501 skip_nodes.push(elsebody.into());
502 }
503 }
504 }
505 NodeEvent::Enter(RefNode::WhiteSpace(x)) if !skip_whitespace && !strip_comments => {
506 if let WhiteSpace::Space(_) = x {
507 let locate: Locate = x.try_into().unwrap();
508 let range = Range::new(locate.offset + locate.len, locate.offset + locate.len);
509 ret.push(locate.str(&s), Some((path.as_ref(), range)));
510 }
511 }
512 NodeEvent::Enter(RefNode::Comment(x)) if !strip_comments => {
513 let locate: Locate = x.try_into().unwrap();
514 let range = Range::new(locate.offset, locate.offset + locate.len);
515 ret.push(locate.str(&s), Some((path.as_ref(), range)));
516 }
517 NodeEvent::Enter(RefNode::IfndefDirective(x)) => {
518 let (_, ref keyword, ref ifid, ref ifbody, ref elsif, ref elsebody, _, _) = x.nodes;
519 skip_nodes.push(keyword.into());
520 skip_nodes.push(ifid.into());
521
522 let ifid = identifier(ifid.into(), &s).unwrap();
523 let mut hit = false;
524 if !defines.contains_key(&ifid) && !is_predefined_text_macro(&ifid) {
525 hit = true;
526 } else {
527 skip_nodes.push(ifbody.into());
528 }
529
530 for x in elsif {
531 let (_, ref keyword, ref elsifid, ref elsifbody) = x;
532 skip_nodes.push(keyword.into());
533 skip_nodes.push(elsifid.into());
534
535 let elsifid = identifier(elsifid.into(), &s).unwrap();
536 if hit {
537 skip_nodes.push(elsifbody.into());
538 } else if defines.contains_key(&elsifid) || is_predefined_text_macro(&ifid) {
539 hit = true;
540 } else {
541 skip_nodes.push(elsifbody.into());
542 }
543 }
544
545 if let Some(elsebody) = elsebody {
546 let (_, ref keyword, ref elsebody) = elsebody;
547 skip_nodes.push(keyword.into());
548 if hit {
549 skip_nodes.push(elsebody.into());
550 }
551 }
552 }
553 NodeEvent::Enter(RefNode::TextMacroDefinition(x)) => {
554 skip_nodes.push(x.into());
555 skip = true;
556
557 let (_, _, ref proto, ref text) = x.nodes;
558 let (ref name, ref args) = proto.nodes;
559 let id = identifier(name.into(), &s).unwrap();
560
561 if !is_predefined_text_macro(id.as_str()) {
562 let mut define_args = Vec::new();
563 if let Some(args) = args {
564 let (_, ref args, _) = args.nodes;
565 let (ref args,) = args.nodes;
566 for arg in args.contents() {
567 let (ref arg, ref default) = arg.nodes;
568 let (ref arg, _) = arg.nodes;
569 let arg = String::from(arg.str(&s));
570
571 let default = if let Some((_, x)) = default {
572 let x: Locate = x.try_into().unwrap();
573 let x = String::from(x.str(&s));
574 Some(x)
575 } else {
576 None
577 };
578
579 define_args.push((arg, default));
580 }
581 }
582
583 let define_text = if let Some(text) = text {
584 let text: Locate = text.try_into().unwrap();
585 let range = Range::new(text.offset, text.offset + text.len);
586 let text = String::from(text.str(&s));
587 Some(DefineText {
588 text,
589 origin: Some((PathBuf::from(path.as_ref()), range)),
590 })
591 } else {
592 None
593 };
594
595 let define = Define {
596 identifier: id.clone(),
597 arguments: define_args,
598 text: define_text,
599 };
600
601 defines.insert(id, Some(define));
602 }
603
604 let locate: Locate = x.try_into().unwrap();
606 let range = Range::new(locate.offset, locate.offset + locate.len);
607 ret.push(locate.str(&s), Some((path.as_ref(), range)));
608 }
609 NodeEvent::Enter(RefNode::IncludeCompilerDirective(x)) if !ignore_include => {
610 skip_nodes.push(x.into());
611 skip = true;
612
613 let locate: Locate = x.try_into().unwrap();
614 last_include_line = Some(locate.line);
615
616 if let Some(last_item_line) = last_item_line {
620 if last_item_line == locate.line {
621 return Err(Error::IncludeLine);
622 }
623 }
624
625 let mut path = match x {
626 IncludeCompilerDirective::DoubleQuote(x) => {
627 let (_, ref keyword, ref literal) = x.nodes;
628 skip_nodes.push(keyword.into());
629
630 let (locate, _) = literal.nodes;
631 let p = locate.str(&s).trim_matches('"');
632 PathBuf::from(p)
633 }
634 IncludeCompilerDirective::AngleBracket(x) => {
635 let (_, ref keyword, ref literal) = x.nodes;
636 skip_nodes.push(keyword.into());
637
638 let (locate, _) = literal.nodes;
639 let p = locate.str(&s).trim_start_matches('<').trim_end_matches('>');
640 PathBuf::from(p)
641 }
642 IncludeCompilerDirective::TextMacroUsage(x) => {
643 let (_, ref keyword, ref x) = x.nodes;
644 skip_nodes.push(keyword.into());
645 skip_nodes.push(x.into());
646
647 if let Some((p, _, _)) = resolve_text_macro_usage(
648 x,
649 s,
650 path.as_ref(),
651 &defines,
652 include_paths,
653 strip_comments,
654 resolve_depth + 1,
655 )? {
656 let p = p.trim().trim_matches('"');
657 PathBuf::from(p)
658 } else {
659 PathBuf::from("")
660 }
661 }
662 };
663
664 if path.is_relative() && !path.exists() {
678 for include_path in include_paths {
679 let new_path = include_path.as_ref().join(&path);
680 if new_path.exists() {
681 path = new_path;
682 break;
683 }
684 }
685 }
686
687 let (include, new_defines) =
688 preprocess_inner(
689 path,
690 &defines,
691 include_paths,
692 strip_comments,
693 false, include_depth + 1).map_err(
695 |x| Error::Include {
696 source: Box::new(x),
697 },
698 )?;
699 defines = new_defines;
700 ret.merge(include);
701 }
702 NodeEvent::Enter(RefNode::TextMacroUsage(x)) => {
703 skip_nodes.push(x.into());
704 skip = true;
705
706 if let Some((text, origin, new_defines)) = resolve_text_macro_usage(
707 x,
708 s,
709 path.as_ref(),
710 &defines,
711 include_paths,
712 strip_comments,
713 resolve_depth + 1,
714 )? {
715 ret.push(&text, origin);
716 defines = new_defines;
717 }
718
719 let (ref _symbol, ref id, ref args) = x.nodes;
722 match args {
723 Some(p) => {
724 let (ref _opening, ref _args, ref closing) = p.nodes;
726 for x in closing {
727 match x {
728 RefNode::WhiteSpace(x) => {
729 let locate: Locate = x.try_into().unwrap();
730 let range = Range::new(locate.offset, locate.offset + locate.len);
731 ret.push(locate.str(&s), Some((path.as_ref(), range)));
732 }
733 _ => {
734 }
735 }
736 }
737 }
738 None => {
739 for x in id {
741 match x {
742 RefNode::WhiteSpace(x) => {
743 let locate: Locate = x.try_into().unwrap();
744 let range = Range::new(locate.offset, locate.offset + locate.len);
745 ret.push(locate.str(&s), Some((path.as_ref(), range)));
746 }
747 _ => {}
748 }
749 }
750 }
751 }
752 }
753 NodeEvent::Enter(RefNode::PositionCompilerDirective(x)) => {
754 skip_nodes.push(x.into());
755 skip = true;
756
757 let (_, ref x) = x.nodes;
758 let locate: Locate = x.try_into().unwrap();
759 let x = locate.str(s);
760 if x.starts_with("__FILE__") {
761 ret.push::<PathBuf>(
762 &x.replace(
763 "__FILE__",
764 &format!("\"{}\"", path.as_ref().to_string_lossy()),
765 ),
766 None,
767 );
768 } else if x.starts_with("__LINE__") {
769 ret.push::<PathBuf>(&x.replace("__LINE__", &format!("{}", locate.line)), None);
770 }
771 }
772 _ => (),
773 }
774 }
775
776 Ok((ret, defines))
777}
778
779fn identifier(node: RefNode, s: &str) -> Option<String> {
780 for x in node {
781 match x {
782 RefNode::SimpleIdentifier(x) => {
783 let x: Locate = x.nodes.0.try_into().unwrap();
784 return Some(String::from(x.str(s)));
785 }
786 RefNode::EscapedIdentifier(x) => {
787 let x: Locate = x.nodes.0.try_into().unwrap();
788 let x = x.str(s);
789 let x = &x[1..]; return Some(String::from(x));
791 }
792 _ => (),
793 }
794 }
795 None
796}
797
798fn get_str(node: RefNode, s: &str) -> String {
799 let mut ret = String::from("");
800 for x in node {
801 match x {
802 RefNode::Locate(x) => {
803 ret.push_str(x.str(s));
804 }
805 _ => (),
806 }
807 }
808 ret
809}
810
811fn is_predefined_text_macro(s: &str) -> bool {
812 match s {
813 "__LINE__" | "__FILE__" => {
814 true
815 }
816 _ => {
817 false
818 }
819 }
820}
821
822fn split_text(s: &str) -> Vec<String> {
823 let mut is_string = false;
824 let mut is_ident = false;
825 let mut is_ident_prev;
826 let mut x = String::from("");
827 let mut ret = vec![];
828
829 let mut is_comment = false;
834
835 let mut is_backquote_prev = false;
841
842 let mut is_leading_whitespace = true;
843 let mut is_backslash_prev = false;
844
845 let mut iter = s.chars().peekable();
846 while let Some(c) = iter.next() {
847
848 if is_leading_whitespace {
851 if c != '\\' && !c.is_ascii_whitespace() {
852 is_leading_whitespace = false;
854 } else if is_backslash_prev && c == '\n' {
855 is_leading_whitespace = false;
857 continue;
858 } else {
859 is_backslash_prev = c == '\\';
862 continue;
863 }
864 }
865
866 is_ident_prev = is_ident;
867 is_ident = c.is_ascii_alphanumeric() | (c == '_');
868
869 if c == '\n' && is_comment {
870 is_comment = false;
871 x.push(c);
872 } else if is_comment {
873 continue;
874 } else if c == '"' && is_backquote_prev {
875 x.push(c);
876 ret.push(x);
877 x = String::from("");
878 } else if c == '"' && !is_string {
879 ret.push(x);
880 x = String::from("");
881 x.push(c);
882 is_string = true;
883 } else if c == '"' && is_string {
884 x.push(c);
885 ret.push(x);
886 x = String::from("");
887 is_string = false;
888 } else if c == '/' && iter.peek() == Some(&'/') && !is_string {
889 is_comment = true;
890 } else if !is_string {
891 if is_ident != is_ident_prev {
892 ret.push(x);
893 x = String::from("");
894 }
895 x.push(c);
896 } else {
897 x.push(c);
898 }
899
900 is_backquote_prev = c == '`';
901 }
902 ret.push(x);
903 ret
904}
905
906fn resolve_text_macro_usage<T: AsRef<Path>, U: AsRef<Path>>(
907 x: &TextMacroUsage,
908 s: &str,
909 path: T,
910 defines: &Defines,
911 include_paths: &[U],
912 strip_comments: bool,
913 resolve_depth: usize,
914) -> Result<Option<(String, Option<(PathBuf, Range)>, Defines)>, Error> {
915 let (_, ref name, ref args) = x.nodes;
916 let id = identifier((&name.nodes.0).into(), &s).unwrap();
917
918 if resolve_depth > RECURSIVE_LIMIT {
919 return Err(Error::ExceedRecursiveLimit);
920 }
921
922 let mut args_str = String::from("");
923 let mut actual_args = Vec::new();
924 let no_args = args.is_none();
925 if let Some(args) = args {
926 args_str.push_str(&get_str((&args.nodes.0).into(), s));
927 args_str.push_str(&get_str((&args.nodes.1).into(), s));
928 args_str.push_str(&get_str((&args.nodes.2).into(), s));
929
930 let (_, ref args, _) = args.nodes;
931 let (ref args,) = args.nodes;
932 for arg in args.contents() {
933 if let Some(arg) = arg {
934 let (ref arg,) = arg.nodes;
935 let arg = arg.str(&s).trim_end();
936 actual_args.push(Some(arg));
937 } else {
938 actual_args.push(None);
939 }
940 }
941 }
942
943 let define = defines.get(&id);
944 if let Some(Some(define)) = define {
945 let mut arg_map = HashMap::new();
946
947 if !define.arguments.is_empty() && no_args {
948 return Err(Error::DefineNoArgs(define.identifier.clone()));
949 }
950
951 for (i, (arg, default)) in define.arguments.iter().enumerate() {
952 let value = match actual_args.get(i) {
953 Some(Some(actual_arg)) => *actual_arg,
954 Some(None) => {
955 if let Some(default) = default {
956 default
957 } else {
958 ""
959 }
960 }
961 None => {
962 if let Some(default) = default {
963 default
964 } else {
965 return Err(Error::DefineArgNotFound(String::from(arg)));
966 }
967 }
968 };
969 arg_map.insert(String::from(arg), value);
970 }
971
972 let paren = if define.arguments.is_empty() {
974 Some(args_str)
975 } else {
976 None
977 };
978
979 if let Some(ref text) = define.text {
980 let mut replaced = String::from("");
981 for text in split_text(&text.text) {
982 if let Some(value) = arg_map.get(&text) {
983 replaced.push_str(*value);
984 } else {
985 replaced.push_str(
986 &text
987 .replace("``", "") .replace("`\\`\"", "\\\"") .replace("`\"", "\"") .replace("\\\n", "\n") .replace("\\\r\n", "\r\n") .replace("\\\r", "\r"), );
994 }
995 }
996
997 if let Some(paren) = paren {
998 replaced.push_str(&paren);
999 }
1000
1001 let (replaced, new_defines) = preprocess_str(
1002 &replaced,
1003 path.as_ref(),
1004 &defines,
1005 include_paths,
1006 false,
1007 strip_comments,
1008 resolve_depth,
1009 0, )?;
1011 Ok(Some((
1012 String::from(replaced.text()),
1013 text.origin.clone(),
1014 new_defines,
1015 )))
1016 } else {
1017 Ok(None)
1018 }
1019 } else if define.is_some() {
1020 Ok(None)
1021 } else {
1022 Err(Error::DefineNotFound(id))
1023 }
1024}
1025
1026#[cfg(test)]
1027mod tests {
1028 use super::*;
1029 use std::env;
1030
1031 fn testfile_path(s: &str) -> String {
1032 format!(
1033 "{}/testcases/{}",
1034 env::var("CARGO_MANIFEST_DIR").unwrap(),
1035 s
1036 )
1037 }
1038
1039 fn testfile_contents(s: &str) -> String {
1040 let path: String = testfile_path(s);
1041
1042 let file = File::open(path).unwrap();
1043 let mut buf_reader = BufReader::new(file);
1044 let mut contents = String::new();
1045 buf_reader.read_to_string(&mut contents).unwrap();
1046
1047 contents
1048 }
1049
1050 fn preprocess_usualargs(s: &str) -> Result<(PreprocessedText, Defines), Error> {
1052 let include_paths = [testfile_path("")];
1053 preprocess(
1054 testfile_path(s), &HashMap::new(), &include_paths, false, false, )
1060 }
1061
1062 #[test]
1063 fn escaped_identifier() { let (ret, _) = preprocess_usualargs("escaped_identifier.sv").unwrap();
1065 assert_eq!(
1066 ret.text(),
1067 testfile_contents("expected/escaped_identifier.sv")
1068 );
1069 } #[test]
1072 #[allow(non_snake_case)]
1073 fn err_DefineNoArgs() { match preprocess_usualargs("err_DefineNoArgs.sv").unwrap_err() {
1075 Error::DefineNoArgs(identifier) => {
1076 assert_eq!(
1077 identifier,
1078 String::from("A")
1079 );
1080 }
1081 _ => {
1082 panic!("Error::DefineNoArgs not raised.");
1083 }
1084 };
1085 } #[test]
1088 #[allow(non_snake_case)]
1089 fn err_DefineNotFound() { match preprocess_usualargs("err_DefineNotFound.sv").unwrap_err() {
1091 Error::DefineNotFound(identifier) => {
1092 assert_eq!(
1093 identifier,
1094 String::from("A")
1095 );
1096 }
1097 _ => {
1098 panic!("Error::DefineNotFound not raised.");
1099 }
1100 };
1101 } #[test]
1104 #[allow(non_snake_case)]
1105 fn err_DefineArgNotFound() { match preprocess_usualargs("err_DefineArgNotFound.sv").unwrap_err() {
1107 Error::DefineArgNotFound(identifier) => {
1108 assert_eq!(
1109 identifier,
1110 String::from("c")
1111 );
1112 }
1113 _ => {
1114 panic!("Error::DefineArgNotFound not raised.");
1115 }
1116 };
1117 } #[test]
1120 #[allow(non_snake_case)]
1121 fn err_ReadUtf8() { match preprocess_usualargs("err_ReadUtf8.sv").unwrap_err() {
1123 Error::ReadUtf8(path) => {
1124 assert_eq!(
1125 path,
1126 PathBuf::from(format!(
1127 "{}/testcases/err_ReadUtf8.sv",
1128 env::var("CARGO_MANIFEST_DIR").unwrap(),
1129 ))
1130 );
1131 }
1132 _ => {
1133 panic!("Error::ReadUtf8 not raised.");
1134 }
1135 };
1136 } #[test]
1139 #[allow(non_snake_case)]
1140 fn IEEE18002017_keywords_if2_13642005() { let (ret, _) = preprocess_usualargs("IEEE18002017_keywords_if2_13642005.sv").unwrap();
1142 assert_eq!(
1143 ret.text(),
1144 testfile_contents("expected/IEEE18002017_keywords_if2_13642005.sv")
1145 );
1146 } #[test]
1149 #[allow(non_snake_case)]
1150 fn IEEE18002017_keywords_m2_13642001() { let (ret, _) = preprocess_usualargs("IEEE18002017_keywords_m2_13642001.sv").unwrap();
1152 assert_eq!(
1153 ret.text(),
1154 testfile_contents("expected/IEEE18002017_keywords_m2_13642001.sv")
1155 );
1156 } #[test]
1159 #[allow(non_snake_case)]
1160 fn IEEE18002017_keywords_m2_18002005() { let (ret, _) = preprocess_usualargs("IEEE18002017_keywords_m2_18002005.sv").unwrap();
1162 assert_eq!(
1163 ret.text(),
1164 testfile_contents("expected/IEEE18002017_keywords_m2_18002005.sv")
1165 );
1166 } #[test]
1169 #[allow(non_snake_case)]
1170 fn IEEE18002017_macro_argument_expansion() { let (ret, _) = preprocess_usualargs("IEEE18002017_macro_argument_expansion.sv").unwrap();
1172 assert_eq!(
1173 ret.text(),
1174 testfile_contents("expected/IEEE18002017_macro_argument_expansion.sv")
1175 );
1176 } #[test]
1179 #[allow(non_snake_case)]
1180 fn IEEE18002017_macro_delimit_tokens() { let (ret, _) = preprocess_usualargs("IEEE18002017_macro_delimit_tokens.sv").unwrap();
1182 assert_eq!(
1183 ret.text(),
1184 testfile_contents("expected/IEEE18002017_macro_delimit_tokens.sv")
1185 );
1186 } #[test]
1189 #[allow(non_snake_case)]
1190 fn IEEE18002017_macro_mix_quotes() { let (ret, _) = preprocess_usualargs("IEEE18002017_macro_mix_quotes.sv").unwrap();
1192 assert_eq!(
1193 ret.text(),
1194 testfile_contents("expected/IEEE18002017_macro_mix_quotes.sv")
1195 );
1196 } #[test]
1199 #[allow(non_snake_case)]
1200 fn IEEE18002017_macro_noexpand_string() { let (ret, _) = preprocess_usualargs("IEEE18002017_macro_noexpand_string.sv").unwrap();
1202 assert_eq!(
1203 ret.text(),
1204 testfile_contents("expected/IEEE18002017_macro_noexpand_string.sv")
1205 );
1206 } #[test]
1209 #[allow(non_snake_case)]
1210 fn IEEE18002017_macro_with_defaults() { let (ret, _) = preprocess_usualargs("IEEE18002017_macro_with_defaults.sv").unwrap();
1212 assert_eq!(
1213 ret.text(),
1214 testfile_contents("expected/IEEE18002017_macro_with_defaults.sv")
1215 );
1216 } #[test]
1219 #[allow(non_snake_case)]
1220 fn IEEE18002017_macro_without_defaults() { let (ret, _) = preprocess_usualargs("IEEE18002017_macro_without_defaults.sv").unwrap();
1222 assert_eq!(
1223 ret.text(),
1224 testfile_contents("expected/IEEE18002017_macro_without_defaults.sv")
1225 );
1226 } #[test]
1229 fn celldefine() { let (ret, _) = preprocess_usualargs("celldefine.sv").unwrap();
1231 assert_eq!(
1232 ret.text(),
1233 testfile_contents("celldefine.sv")
1234 );
1235 } #[test]
1238 fn coverage_constants() { let (ret, _) = preprocess_usualargs("coverage_constants.sv").unwrap();
1240 assert_eq!(
1241 ret.text(),
1242 testfile_contents("expected/coverage_constants.sv")
1243 );
1244 } #[test]
1247 fn default_nettype() { let (ret, _) = preprocess_usualargs("default_nettype.sv").unwrap();
1249 assert_eq!(
1250 ret.text(),
1251 testfile_contents("default_nettype.sv")
1252 );
1253 } #[test]
1256 fn ifdef_nested() { let (ret, _) = preprocess_usualargs("ifdef_nested.sv").unwrap();
1258 assert_eq!(
1259 ret.text(),
1260 testfile_contents("expected/ifdef_nested.sv")
1261 );
1262 } #[test]
1265 fn ifdef_predefined() { let mut defines = HashMap::new();
1267 defines.insert(String::from("behavioral"), None);
1268 let (ret, _) = preprocess(
1269 testfile_path("ifdef_predefined.sv"),
1270 &defines,
1271 &[] as &[String],
1272 false, false, )
1275 .unwrap();
1276 assert_eq!(
1277 ret.text(),
1278 testfile_contents("expected/ifdef_predefined.sv")
1279 )
1280 } #[test]
1283 fn ifdef_undefined() { let (ret, _) = preprocess_usualargs("ifdef_undefined.sv").unwrap();
1285 assert_eq!(
1286 ret.text(),
1287 testfile_contents("expected/ifdef_undefined.sv")
1288 );
1289 assert_eq!(
1290 ret.origin(10).unwrap().0,
1291 &PathBuf::from(testfile_path("ifdef_undefined.sv"))
1292 );
1293 assert_eq!(ret.origin(10).unwrap().1, 10);
1294 assert_eq!(ret.origin(50).unwrap().1, 98);
1295 assert_eq!(ret.origin(70).unwrap().1, 124);
1296 } #[test]
1299 fn ifndef_undefined() { let (ret, _) = preprocess_usualargs("ifndef_undefined.sv").unwrap();
1301 assert_eq!(
1302 ret.text(),
1303 testfile_contents("expected/ifndef_undefined.sv")
1304 );
1305 } #[test]
1308 fn include_ignore() { let include_paths = [testfile_path("")];
1310 let (ret, _) = preprocess(
1311 testfile_path("include_ignore.sv"),
1312 &HashMap::new(),
1313 &include_paths,
1314 false, true, )
1317 .unwrap();
1318 assert_eq!(
1319 ret.text(),
1320 testfile_contents("expected/include_ignore.sv")
1321 );
1322 } #[test]
1325 fn include_noindent() { let (ret, _) = preprocess_usualargs("include_noindent.sv").unwrap();
1327 assert_eq!(
1328 ret.text(),
1329 testfile_contents("expected/include_noindent.sv")
1330 );
1331
1332 let n = 10;
1336 assert_eq!(
1337 ret.origin(n).unwrap(),
1338 (&PathBuf::from(testfile_path("include_noindent.sv")), n)
1339 );
1340 assert_eq!(ret.text().chars().nth(n).unwrap(), '_');
1341
1342 let n = 50;
1345 assert_eq!(
1346 ret.origin(n).unwrap(),
1347 (&PathBuf::from(testfile_path("included.svh")), 73)
1348 );
1349 assert_eq!(ret.text().chars().nth(n).unwrap(), 'd');
1350
1351 let n = 70;
1354 assert_eq!(
1355 ret.origin(n).unwrap(),
1356 (&PathBuf::from(testfile_path("include_noindent.sv")), 53)
1357 );
1358 assert_eq!(ret.text().chars().nth(n).unwrap(), 'o');
1359 } #[test]
1362 fn include_quoted_a() { let ret = preprocess_usualargs("include_quoted_a.sv");
1364 assert_eq!(format!("{:?}", ret), "Err(Include { source: File { source: Os { code: 2, kind: NotFound, message: \"No such file or directory\" }, path: \"`PATH\" } })");
1365 } #[test]
1368 fn include_quoted_b() { let ret = preprocess_usualargs("include_quoted_b.sv");
1370 assert_eq!(format!("{:?}", ret), "Err(Include { source: File { source: Os { code: 2, kind: NotFound, message: \"No such file or directory\" }, path: \"`PATH\" } })");
1371 } #[test]
1374 fn include_quoted_c() { let (ret, _) = preprocess_usualargs("include_quoted_c.sv").unwrap();
1376 assert_eq!(
1377 ret.text(),
1378 testfile_contents("expected/include_quoted_c.sv")
1379 );
1380 } #[test]
1383 fn include_quoted_d() { let (ret, _) = preprocess_usualargs("include_quoted_d.sv").unwrap();
1385 assert_eq!(
1386 ret.text(),
1387 testfile_contents("expected/include_quoted_d.sv")
1388 );
1389 } #[test]
1392 fn include_recursive() { let ret = preprocess_usualargs("include_recursive.svh");
1394 let expected = format!(
1395 "Err({}ExceedRecursiveLimit{})",
1396 "Include { source: ".repeat(RECURSIVE_LIMIT+1),
1397 " }".repeat(RECURSIVE_LIMIT+1),
1398 );
1399 assert_eq!(format!("{:?}", ret), expected);
1400 } #[test]
1403 fn include_sameline_comment() { let (ret, _) = preprocess_usualargs("include_sameline_comment.sv").unwrap();
1405 assert_eq!(
1406 ret.text(),
1407 testfile_contents("expected/include_sameline_comment.sv")
1408 );
1409 assert_eq!(
1410 ret.origin(10).unwrap().0,
1411 &PathBuf::from(testfile_path("include_sameline_comment.sv"))
1412 );
1413 assert_eq!(ret.origin(10).unwrap().1, 10);
1414 assert_eq!(
1415 ret.origin(50).unwrap().0,
1416 &PathBuf::from(testfile_path("included.svh"))
1417 );
1418 assert_eq!(ret.origin(50).unwrap().1, 73);
1419 assert_eq!(
1420 ret.origin(70).unwrap().0,
1421 &PathBuf::from(testfile_path("include_sameline_comment.sv"))
1422 );
1423 assert_eq!(ret.origin(70).unwrap().1, 53);
1424 } #[test]
1427 fn include_sameline_include() { let ret = preprocess_usualargs("include_sameline_include.sv");
1429 assert_eq!(format!("{:?}", ret), "Err(IncludeLine)");
1430 } #[test]
1433 fn include_sameline_keyword() { let ret = preprocess_usualargs("include_sameline_keyword.sv");
1435 assert_eq!(format!("{:?}", ret), "Err(IncludeLine)");
1436 } #[test]
1439 fn include_withindent() { let (ret, _) = preprocess_usualargs("include_withindent.sv").unwrap();
1441 assert_eq!(
1442 ret.text(),
1443 testfile_contents("expected/include_withindent.sv")
1444 );
1445
1446 let n = 10;
1450 assert_eq!(
1451 ret.origin(n).unwrap(),
1452 (&PathBuf::from(testfile_path("include_withindent.sv")), n)
1453 );
1454 assert_eq!(ret.text().chars().nth(n).unwrap(), '_');
1455
1456 let n = 58;
1459 assert_eq!(
1460 ret.origin(n).unwrap(),
1461 (&PathBuf::from(testfile_path("included.svh")), 72)
1462 );
1463 assert_eq!(ret.text().chars().nth(n).unwrap(), 'n');
1464
1465 let n = 79;
1468 assert_eq!(
1469 ret.origin(n).unwrap(),
1470 (&PathBuf::from(testfile_path("include_withindent.sv")), 62)
1471 );
1472 assert_eq!(ret.text().chars().nth(n).unwrap(), 'o');
1473 } #[test]
1476 fn keywords() { let (ret, _) = preprocess_usualargs("keywords.sv").unwrap();
1478 assert_eq!(
1479 ret.text(),
1480 testfile_contents("keywords.sv")
1481 );
1482 } #[test]
1485 fn line() { let (ret, _) = preprocess_usualargs("line.sv").unwrap();
1487 assert_eq!(
1488 ret.text(),
1489 testfile_contents("line.sv")
1490 );
1491 } #[test]
1494 fn macro_arguments() { let (ret, _) = preprocess_usualargs("macro_arguments.sv").unwrap();
1496 assert_eq!(
1497 ret.text(),
1498 testfile_contents("expected/macro_arguments.sv")
1499 );
1500 } #[test]
1503 fn macro_basic() { let (ret, _) = preprocess_usualargs("macro_basic.sv").unwrap();
1505 assert_eq!(
1506 ret.text(),
1507 testfile_contents("expected/macro_basic.sv")
1508 );
1509 } #[test]
1512 fn macro_comment() { let (ret, _) = preprocess_usualargs("macro_comment.sv").unwrap();
1514 assert_eq!(
1515 ret.text(),
1516 testfile_contents("expected/macro_comment.sv")
1517 );
1518 } #[test]
1521 #[ignore = "Exposes unfixed PP parser bug."]
1522 fn macro_comment_embedded() { let (ret, _) = preprocess_usualargs("macro_comment_embedded.sv").unwrap();
1524 assert_eq!(
1525 ret.text(),
1526 testfile_contents("expected/macro_comment_embedded.sv")
1527 );
1528 } #[test]
1531 fn macro_delimiters() { let (ret, _) = preprocess_usualargs("macro_delimiters.sv").unwrap();
1533 assert_eq!(
1534 ret.text(),
1535 testfile_contents("expected/macro_delimiters.sv")
1536 );
1537 } #[test]
1540 #[allow(non_snake_case)]
1541 fn macro_FILE() { let (ret, _) = preprocess_usualargs("macro_FILE.sv").unwrap();
1543 assert_eq!(
1544 ret.text(),
1545 testfile_contents("expected/macro_FILE.sv")
1546 );
1547 } #[test]
1550 fn macro_identifier() { let (ret, _) = preprocess_usualargs("macro_identifier.sv").unwrap();
1552 assert_eq!(
1553 ret.text(),
1554 testfile_contents("expected/macro_identifier.sv")
1555 );
1556 } #[test]
1559 #[allow(non_snake_case)]
1560 fn macro_LINE() { let (ret, _) = preprocess_usualargs("macro_LINE.sv").unwrap();
1562 assert_eq!(
1563 ret.text(),
1564 testfile_contents("expected/macro_LINE.sv")
1565 );
1566 } #[test]
1569 fn macro_multiline_comment() { let (ret, _) = preprocess_usualargs("macro_multiline_comment.sv").unwrap();
1571 assert_eq!(
1572 ret.text(),
1573 testfile_contents("expected/macro_multiline_comment.sv")
1574 );
1575 } #[test]
1578 fn macro_recursion_direct() { let ret = preprocess_usualargs("macro_recursion_direct.sv");
1580 assert_eq!(format!("{:?}", ret), "Err(ExceedRecursiveLimit)");
1581 } #[test]
1584 fn macro_recursion_indirect() { let ret = preprocess_usualargs("macro_recursion_indirect.sv");
1586 assert_eq!(format!("{:?}", ret), "Err(ExceedRecursiveLimit)");
1587 } #[test]
1590 fn pragma() { let (ret, _) = preprocess_usualargs("pragma.sv").unwrap();
1592 assert_eq!(
1593 ret.text(),
1594 testfile_contents("pragma.sv")
1595 );
1596 } #[test]
1599 fn resetall() { let (ret, _) = preprocess_usualargs("resetall.sv").unwrap();
1601 assert_eq!(
1602 ret.text(),
1603 testfile_contents("resetall.sv")
1604 );
1605 } #[test]
1608 fn timescale() { let (ret, _) = preprocess_usualargs("timescale.sv").unwrap();
1610 assert_eq!(
1611 ret.text(),
1612 testfile_contents("timescale.sv")
1613 );
1614 } #[test]
1617 fn unconnected_drive() { let (ret, _) = preprocess_usualargs("unconnected_drive.sv").unwrap();
1619 assert_eq!(
1620 ret.text(),
1621 testfile_contents("unconnected_drive.sv")
1622 );
1623 } #[test]
1626 fn undef() { let (ret, _) = preprocess_usualargs("undef.sv").unwrap();
1628 assert_eq!(
1629 ret.text(),
1630 testfile_contents("expected/undef.sv")
1631 );
1632 } #[test]
1635 fn undefineall() { let (ret, _) = preprocess_usualargs("undefineall.sv").unwrap();
1637 assert_eq!(
1638 ret.text(),
1639 testfile_contents("expected/undefineall.sv")
1640 );
1641 } }