blob: 959b029d899cc9c897c937a9bc40d1001a13628e [file] [log] [blame]
David Tolnaye54f3382020-05-12 19:58:36 -07001use crate::gen::out::OutFile;
David Tolnay4aae7c02020-10-28 12:35:42 -07002use crate::syntax::IncludeKind;
David Tolnay9c68b1a2020-03-06 11:12:55 -08003use std::fmt::{self, Display};
4
David Tolnay0e01d642020-10-16 12:54:44 -07005/// The complete contents of the "rust/cxx.h" header.
David Tolnay736cbca2020-03-11 16:49:18 -07006pub static HEADER: &str = include_str!("include/cxx.h");
David Tolnay7db73692019-10-20 14:51:12 -04007
David Tolnaye54f3382020-05-12 19:58:36 -07008pub(super) fn write(out: &mut OutFile, needed: bool, guard: &str) {
David Tolnay2a1eaac2020-02-24 02:01:47 -08009 let ifndef = format!("#ifndef {}", guard);
David Tolnaye54f3382020-05-12 19:58:36 -070010 let define = format!("#define {}", guard);
David Tolnay2a1eaac2020-02-24 02:01:47 -080011 let endif = format!("#endif // {}", guard);
David Tolnaye54f3382020-05-12 19:58:36 -070012
13 let mut offset = 0;
14 loop {
15 let begin = find_line(offset, &ifndef);
16 let end = find_line(offset, &endif);
17 if let (Some(begin), Some(end)) = (begin, end) {
18 if !needed {
19 return;
20 }
21 out.next_section();
22 if offset == 0 {
23 writeln!(out, "{}", ifndef);
24 writeln!(out, "{}", define);
25 }
26 for line in HEADER[begin + ifndef.len()..end].trim().lines() {
27 if line != define && !line.trim_start().starts_with("//") {
28 writeln!(out, "{}", line);
29 }
30 }
31 offset = end + endif.len();
32 } else if offset == 0 {
33 panic!("not found in cxx.h header: {}", guard)
34 } else {
35 writeln!(out, "{}", endif);
36 return;
37 }
David Tolnay7db73692019-10-20 14:51:12 -040038 }
39}
David Tolnay9c68b1a2020-03-06 11:12:55 -080040
David Tolnaye54f3382020-05-12 19:58:36 -070041fn find_line(mut offset: usize, line: &str) -> Option<usize> {
David Tolnay26ad0bd2020-03-17 21:34:05 -070042 loop {
43 offset += HEADER[offset..].find(line)?;
44 let rest = &HEADER[offset + line.len()..];
45 if rest.starts_with('\n') || rest.starts_with('\r') {
46 return Some(offset);
47 }
48 offset += line.len();
49 }
50}
51
David Tolnay4aae7c02020-10-28 12:35:42 -070052#[derive(PartialEq)]
53pub struct Include {
54 pub path: String,
55 pub kind: IncludeKind,
56}
57
David Tolnay3577d452020-03-17 21:48:13 -070058#[derive(Default, PartialEq)]
David Tolnay9c68b1a2020-03-06 11:12:55 -080059pub struct Includes {
David Tolnay4aae7c02020-10-28 12:35:42 -070060 custom: Vec<Include>,
David Tolnayb7a7cb62020-03-17 21:18:40 -070061 pub array: bool,
David Tolnay30430f12020-03-19 20:49:00 -070062 pub cstddef: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080063 pub cstdint: bool,
David Tolnayebef4a22020-03-17 15:33:47 -070064 pub cstring: bool,
David Tolnayb7a7cb62020-03-17 21:18:40 -070065 pub exception: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080066 pub memory: bool,
David Tolnay0ecd05a2020-07-29 16:32:03 -070067 pub new: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080068 pub string: bool,
69 pub type_traits: bool,
David Tolnay4791f1c2020-03-17 21:53:16 -070070 pub utility: bool,
David Tolnay8b7f8992020-04-25 13:06:08 -070071 pub vector: bool,
David Tolnayda38b7c2020-09-16 11:50:04 -040072 pub basetsd: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -080073}
74
75impl Includes {
76 pub fn new() -> Self {
77 Includes::default()
78 }
79
David Tolnay4aae7c02020-10-28 12:35:42 -070080 pub fn insert(&mut self, include: Include) {
81 self.custom.push(include);
David Tolnay9c68b1a2020-03-06 11:12:55 -080082 }
83}
84
David Tolnay4aae7c02020-10-28 12:35:42 -070085impl<'a> Extend<&'a String> for Includes {
86 fn extend<I: IntoIterator<Item = &'a String>>(&mut self, iter: I) {
87 self.custom.extend(iter.into_iter().map(|path| Include {
88 path: path.clone(),
89 kind: IncludeKind::Quoted,
90 }));
David Tolnay33d30292020-03-18 18:02:02 -070091 }
92}
93
David Tolnay9c68b1a2020-03-06 11:12:55 -080094impl Display for Includes {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 for include in &self.custom {
David Tolnay4aae7c02020-10-28 12:35:42 -070097 match include.kind {
98 IncludeKind::Quoted => {
99 writeln!(f, "#include \"{}\"", include.path.escape_default())?;
100 }
101 IncludeKind::Bracketed => {
102 writeln!(f, "#include <{}>", include.path)?;
103 }
David Tolnaybbcf2152020-05-11 19:04:25 -0700104 }
David Tolnay9c68b1a2020-03-06 11:12:55 -0800105 }
David Tolnayb7a7cb62020-03-17 21:18:40 -0700106 if self.array {
107 writeln!(f, "#include <array>")?;
108 }
David Tolnay30430f12020-03-19 20:49:00 -0700109 if self.cstddef {
110 writeln!(f, "#include <cstddef>")?;
111 }
David Tolnay9c68b1a2020-03-06 11:12:55 -0800112 if self.cstdint {
113 writeln!(f, "#include <cstdint>")?;
114 }
David Tolnayebef4a22020-03-17 15:33:47 -0700115 if self.cstring {
116 writeln!(f, "#include <cstring>")?;
117 }
David Tolnayb7a7cb62020-03-17 21:18:40 -0700118 if self.exception {
119 writeln!(f, "#include <exception>")?;
120 }
David Tolnay9c68b1a2020-03-06 11:12:55 -0800121 if self.memory {
122 writeln!(f, "#include <memory>")?;
123 }
David Tolnay0ecd05a2020-07-29 16:32:03 -0700124 if self.new {
125 writeln!(f, "#include <new>")?;
126 }
David Tolnay9c68b1a2020-03-06 11:12:55 -0800127 if self.string {
128 writeln!(f, "#include <string>")?;
129 }
130 if self.type_traits {
131 writeln!(f, "#include <type_traits>")?;
132 }
David Tolnay4791f1c2020-03-17 21:53:16 -0700133 if self.utility {
134 writeln!(f, "#include <utility>")?;
135 }
David Tolnay122905e2020-04-25 13:06:42 -0700136 if self.vector {
137 writeln!(f, "#include <vector>")?;
138 }
David Tolnayda38b7c2020-09-16 11:50:04 -0400139 if self.basetsd {
David Tolnay59b5ba12020-04-10 11:32:19 -0700140 writeln!(f, "#if defined(_WIN32)")?;
David Tolnayda38b7c2020-09-16 11:50:04 -0400141 writeln!(f, "#include <basetsd.h>")?;
David Tolnay59b5ba12020-04-10 11:32:19 -0700142 writeln!(f, "#endif")?;
143 }
David Tolnay9c68b1a2020-03-06 11:12:55 -0800144 Ok(())
145 }
146}