]>
Commit | Line | Data |
---|---|---|
9fa01778 | 1 | //! The representation of a `#[doc(cfg(...))]` attribute. |
3b2f2976 | 2 | |
0731742a XL |
3 | // FIXME: Once the portability lint RFC is implemented (see tracking issue #41619), |
4 | // switch to use those structures instead. | |
3b2f2976 | 5 | |
3b2f2976 | 6 | use std::fmt::{self, Write}; |
dfeec247 | 7 | use std::mem; |
3b2f2976 | 8 | use std::ops; |
3b2f2976 | 9 | |
3dfed10e | 10 | use rustc_ast::{LitKind, MetaItem, MetaItemKind, NestedMetaItem}; |
60c5eb7d | 11 | use rustc_feature::Features; |
74b04a01 | 12 | use rustc_session::parse::ParseSess; |
dfeec247 | 13 | use rustc_span::symbol::{sym, Symbol}; |
3b2f2976 | 14 | |
dfeec247 | 15 | use rustc_span::Span; |
3b2f2976 | 16 | |
9fa01778 | 17 | use crate::html::escape::Escape; |
3b2f2976 | 18 | |
416331ca XL |
19 | #[cfg(test)] |
20 | mod tests; | |
21 | ||
dc9dc135 | 22 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
fc512014 | 23 | crate enum Cfg { |
3b2f2976 XL |
24 | /// Accepts all configurations. |
25 | True, | |
26 | /// Denies all configurations. | |
27 | False, | |
0731742a | 28 | /// A generic configuration option, e.g., `test` or `target_os = "linux"`. |
3b2f2976 | 29 | Cfg(Symbol, Option<Symbol>), |
9fa01778 | 30 | /// Negates a configuration requirement, i.e., `not(x)`. |
3b2f2976 | 31 | Not(Box<Cfg>), |
0731742a | 32 | /// Union of a list of configuration requirements, i.e., `any(...)`. |
3b2f2976 | 33 | Any(Vec<Cfg>), |
0731742a | 34 | /// Intersection of a list of configuration requirements, i.e., `all(...)`. |
3b2f2976 XL |
35 | All(Vec<Cfg>), |
36 | } | |
37 | ||
38 | #[derive(PartialEq, Debug)] | |
fc512014 XL |
39 | crate struct InvalidCfgError { |
40 | crate msg: &'static str, | |
41 | crate span: Span, | |
3b2f2976 XL |
42 | } |
43 | ||
44 | impl Cfg { | |
45 | /// Parses a `NestedMetaItem` into a `Cfg`. | |
46 | fn parse_nested(nested_cfg: &NestedMetaItem) -> Result<Cfg, InvalidCfgError> { | |
532ac7d7 XL |
47 | match nested_cfg { |
48 | NestedMetaItem::MetaItem(ref cfg) => Cfg::parse(cfg), | |
dfeec247 XL |
49 | NestedMetaItem::Literal(ref lit) => { |
50 | Err(InvalidCfgError { msg: "unexpected literal", span: lit.span }) | |
51 | } | |
3b2f2976 XL |
52 | } |
53 | } | |
54 | ||
55 | /// Parses a `MetaItem` into a `Cfg`. | |
56 | /// | |
0731742a | 57 | /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g., `unix` or |
3b2f2976 XL |
58 | /// `target_os = "redox"`. |
59 | /// | |
60 | /// If the content is not properly formatted, it will return an error indicating what and where | |
61 | /// the error is. | |
fc512014 | 62 | crate fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> { |
9fa01778 XL |
63 | let name = match cfg.ident() { |
64 | Some(ident) => ident.name, | |
dfeec247 XL |
65 | None => { |
66 | return Err(InvalidCfgError { | |
67 | msg: "expected a single identifier", | |
68 | span: cfg.span, | |
69 | }); | |
70 | } | |
9fa01778 | 71 | }; |
e74abb32 | 72 | match cfg.kind { |
3b2f2976 | 73 | MetaItemKind::Word => Ok(Cfg::Cfg(name, None)), |
e74abb32 | 74 | MetaItemKind::NameValue(ref lit) => match lit.kind { |
3b2f2976 XL |
75 | LitKind::Str(value, _) => Ok(Cfg::Cfg(name, Some(value))), |
76 | _ => Err(InvalidCfgError { | |
77 | // FIXME: if the main #[cfg] syntax decided to support non-string literals, | |
78 | // this should be changed as well. | |
79 | msg: "value of cfg option should be a string literal", | |
80 | span: lit.span, | |
81 | }), | |
82 | }, | |
83 | MetaItemKind::List(ref items) => { | |
84 | let mut sub_cfgs = items.iter().map(Cfg::parse_nested); | |
e1599b0c XL |
85 | match name { |
86 | sym::all => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)), | |
87 | sym::any => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)), | |
dfeec247 XL |
88 | sym::not => { |
89 | if sub_cfgs.len() == 1 { | |
90 | Ok(!sub_cfgs.next().unwrap()?) | |
91 | } else { | |
92 | Err(InvalidCfgError { msg: "expected 1 cfg-pattern", span: cfg.span }) | |
93 | } | |
94 | } | |
95 | _ => Err(InvalidCfgError { msg: "invalid predicate", span: cfg.span }), | |
3b2f2976 XL |
96 | } |
97 | } | |
98 | } | |
99 | } | |
100 | ||
101 | /// Checks whether the given configuration can be matched in the current session. | |
102 | /// | |
103 | /// Equivalent to `attr::cfg_matches`. | |
104 | // FIXME: Actually make use of `features`. | |
fc512014 | 105 | crate fn matches(&self, parse_sess: &ParseSess, features: Option<&Features>) -> bool { |
3b2f2976 XL |
106 | match *self { |
107 | Cfg::False => false, | |
108 | Cfg::True => true, | |
109 | Cfg::Not(ref child) => !child.matches(parse_sess, features), | |
110 | Cfg::All(ref sub_cfgs) => { | |
111 | sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(parse_sess, features)) | |
dfeec247 | 112 | } |
3b2f2976 XL |
113 | Cfg::Any(ref sub_cfgs) => { |
114 | sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(parse_sess, features)) | |
dfeec247 | 115 | } |
3b2f2976 XL |
116 | Cfg::Cfg(name, value) => parse_sess.config.contains(&(name, value)), |
117 | } | |
118 | } | |
119 | ||
120 | /// Whether the configuration consists of just `Cfg` or `Not`. | |
121 | fn is_simple(&self) -> bool { | |
122 | match *self { | |
123 | Cfg::False | Cfg::True | Cfg::Cfg(..) | Cfg::Not(..) => true, | |
124 | Cfg::All(..) | Cfg::Any(..) => false, | |
125 | } | |
126 | } | |
127 | ||
128 | /// Whether the configuration consists of just `Cfg`, `Not` or `All`. | |
129 | fn is_all(&self) -> bool { | |
130 | match *self { | |
131 | Cfg::False | Cfg::True | Cfg::Cfg(..) | Cfg::Not(..) | Cfg::All(..) => true, | |
132 | Cfg::Any(..) => false, | |
133 | } | |
134 | } | |
135 | ||
136 | /// Renders the configuration for human display, as a short HTML description. | |
137 | pub(crate) fn render_short_html(&self) -> String { | |
1b1a35ee | 138 | let mut msg = Display(self, Format::ShortHtml).to_string(); |
3b2f2976 XL |
139 | if self.should_capitalize_first_letter() { |
140 | if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) { | |
dfeec247 | 141 | msg[i..i + 1].make_ascii_uppercase(); |
3b2f2976 XL |
142 | } |
143 | } | |
144 | msg | |
145 | } | |
146 | ||
147 | /// Renders the configuration for long display, as a long HTML description. | |
148 | pub(crate) fn render_long_html(&self) -> String { | |
dfeec247 | 149 | let on = if self.should_use_with_in_description() { "with" } else { "on" }; |
0531ce1d | 150 | |
1b1a35ee XL |
151 | let mut msg = format!( |
152 | "This is supported {} <strong>{}</strong>", | |
153 | on, | |
154 | Display(self, Format::LongHtml) | |
155 | ); | |
3b2f2976 XL |
156 | if self.should_append_only_to_description() { |
157 | msg.push_str(" only"); | |
158 | } | |
159 | msg.push('.'); | |
160 | msg | |
161 | } | |
162 | ||
1b1a35ee XL |
163 | /// Renders the configuration for long display, as a long plain text description. |
164 | pub(crate) fn render_long_plain(&self) -> String { | |
165 | let on = if self.should_use_with_in_description() { "with" } else { "on" }; | |
166 | ||
167 | let mut msg = format!("This is supported {} {}", on, Display(self, Format::LongPlain)); | |
168 | if self.should_append_only_to_description() { | |
169 | msg.push_str(" only"); | |
170 | } | |
171 | msg | |
172 | } | |
173 | ||
3b2f2976 XL |
174 | fn should_capitalize_first_letter(&self) -> bool { |
175 | match *self { | |
176 | Cfg::False | Cfg::True | Cfg::Not(..) => true, | |
177 | Cfg::Any(ref sub_cfgs) | Cfg::All(ref sub_cfgs) => { | |
178 | sub_cfgs.first().map(Cfg::should_capitalize_first_letter).unwrap_or(false) | |
dfeec247 | 179 | } |
3dfed10e XL |
180 | Cfg::Cfg(name, _) => match name { |
181 | sym::debug_assertions | sym::target_endian => true, | |
3b2f2976 XL |
182 | _ => false, |
183 | }, | |
184 | } | |
185 | } | |
186 | ||
187 | fn should_append_only_to_description(&self) -> bool { | |
188 | match *self { | |
189 | Cfg::False | Cfg::True => false, | |
190 | Cfg::Any(..) | Cfg::All(..) | Cfg::Cfg(..) => true, | |
191 | Cfg::Not(ref child) => match **child { | |
192 | Cfg::Cfg(..) => true, | |
193 | _ => false, | |
dfeec247 | 194 | }, |
3b2f2976 XL |
195 | } |
196 | } | |
0531ce1d XL |
197 | |
198 | fn should_use_with_in_description(&self) -> bool { | |
199 | match *self { | |
48663c56 | 200 | Cfg::Cfg(name, _) if name == sym::target_feature => true, |
0531ce1d XL |
201 | _ => false, |
202 | } | |
203 | } | |
29967ef6 XL |
204 | |
205 | /// Attempt to simplify this cfg by assuming that `assume` is already known to be true, will | |
206 | /// return `None` if simplification managed to completely eliminate any requirements from this | |
207 | /// `Cfg`. | |
208 | /// | |
209 | /// See `tests::test_simplify_with` for examples. | |
210 | pub(crate) fn simplify_with(&self, assume: &Cfg) -> Option<Cfg> { | |
211 | if self == assume { | |
212 | return None; | |
213 | } | |
214 | ||
215 | if let Cfg::All(a) = self { | |
216 | let mut sub_cfgs: Vec<Cfg> = if let Cfg::All(b) = assume { | |
217 | a.iter().filter(|a| !b.contains(a)).cloned().collect() | |
218 | } else { | |
219 | a.iter().filter(|&a| a != assume).cloned().collect() | |
220 | }; | |
221 | let len = sub_cfgs.len(); | |
222 | return match len { | |
223 | 0 => None, | |
224 | 1 => sub_cfgs.pop(), | |
225 | _ => Some(Cfg::All(sub_cfgs)), | |
226 | }; | |
227 | } else if let Cfg::All(b) = assume { | |
228 | if b.contains(self) { | |
229 | return None; | |
230 | } | |
231 | } | |
232 | ||
233 | Some(self.clone()) | |
234 | } | |
3b2f2976 XL |
235 | } |
236 | ||
237 | impl ops::Not for Cfg { | |
238 | type Output = Cfg; | |
239 | fn not(self) -> Cfg { | |
240 | match self { | |
241 | Cfg::False => Cfg::True, | |
242 | Cfg::True => Cfg::False, | |
243 | Cfg::Not(cfg) => *cfg, | |
244 | s => Cfg::Not(Box::new(s)), | |
245 | } | |
246 | } | |
247 | } | |
248 | ||
249 | impl ops::BitAndAssign for Cfg { | |
250 | fn bitand_assign(&mut self, other: Cfg) { | |
251 | match (self, other) { | |
dfeec247 | 252 | (&mut Cfg::False, _) | (_, Cfg::True) => {} |
3b2f2976 XL |
253 | (s, Cfg::False) => *s = Cfg::False, |
254 | (s @ &mut Cfg::True, b) => *s = b, | |
dfeec247 XL |
255 | (&mut Cfg::All(ref mut a), Cfg::All(ref mut b)) => { |
256 | for c in b.drain(..) { | |
257 | if !a.contains(&c) { | |
258 | a.push(c); | |
259 | } | |
260 | } | |
261 | } | |
262 | (&mut Cfg::All(ref mut a), ref mut b) => { | |
263 | if !a.contains(b) { | |
264 | a.push(mem::replace(b, Cfg::True)); | |
265 | } | |
266 | } | |
3b2f2976 XL |
267 | (s, Cfg::All(mut a)) => { |
268 | let b = mem::replace(s, Cfg::True); | |
dfeec247 XL |
269 | if !a.contains(&b) { |
270 | a.push(b); | |
271 | } | |
3b2f2976 | 272 | *s = Cfg::All(a); |
dfeec247 | 273 | } |
3b2f2976 | 274 | (s, b) => { |
dfeec247 XL |
275 | if *s != b { |
276 | let a = mem::replace(s, Cfg::True); | |
277 | *s = Cfg::All(vec![a, b]); | |
278 | } | |
279 | } | |
3b2f2976 XL |
280 | } |
281 | } | |
282 | } | |
283 | ||
284 | impl ops::BitAnd for Cfg { | |
285 | type Output = Cfg; | |
286 | fn bitand(mut self, other: Cfg) -> Cfg { | |
287 | self &= other; | |
288 | self | |
289 | } | |
290 | } | |
291 | ||
292 | impl ops::BitOrAssign for Cfg { | |
293 | fn bitor_assign(&mut self, other: Cfg) { | |
294 | match (self, other) { | |
dfeec247 | 295 | (&mut Cfg::True, _) | (_, Cfg::False) => {} |
3b2f2976 XL |
296 | (s, Cfg::True) => *s = Cfg::True, |
297 | (s @ &mut Cfg::False, b) => *s = b, | |
dfeec247 XL |
298 | (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => { |
299 | for c in b.drain(..) { | |
300 | if !a.contains(&c) { | |
301 | a.push(c); | |
302 | } | |
303 | } | |
304 | } | |
305 | (&mut Cfg::Any(ref mut a), ref mut b) => { | |
306 | if !a.contains(b) { | |
307 | a.push(mem::replace(b, Cfg::True)); | |
308 | } | |
309 | } | |
3b2f2976 XL |
310 | (s, Cfg::Any(mut a)) => { |
311 | let b = mem::replace(s, Cfg::True); | |
dfeec247 XL |
312 | if !a.contains(&b) { |
313 | a.push(b); | |
314 | } | |
3b2f2976 | 315 | *s = Cfg::Any(a); |
dfeec247 | 316 | } |
3b2f2976 | 317 | (s, b) => { |
dfeec247 XL |
318 | if *s != b { |
319 | let a = mem::replace(s, Cfg::True); | |
320 | *s = Cfg::Any(vec![a, b]); | |
321 | } | |
322 | } | |
3b2f2976 XL |
323 | } |
324 | } | |
325 | } | |
326 | ||
327 | impl ops::BitOr for Cfg { | |
328 | type Output = Cfg; | |
329 | fn bitor(mut self, other: Cfg) -> Cfg { | |
330 | self |= other; | |
331 | self | |
332 | } | |
333 | } | |
334 | ||
1b1a35ee XL |
335 | #[derive(Clone, Copy)] |
336 | enum Format { | |
337 | LongHtml, | |
338 | LongPlain, | |
339 | ShortHtml, | |
340 | } | |
341 | ||
342 | impl Format { | |
343 | fn is_long(self) -> bool { | |
344 | match self { | |
345 | Format::LongHtml | Format::LongPlain => true, | |
346 | Format::ShortHtml => false, | |
347 | } | |
348 | } | |
349 | ||
350 | fn is_html(self) -> bool { | |
351 | match self { | |
352 | Format::LongHtml | Format::ShortHtml => true, | |
353 | Format::LongPlain => false, | |
354 | } | |
355 | } | |
356 | } | |
357 | ||
358 | /// Pretty-print wrapper for a `Cfg`. Also indicates what form of rendering should be used. | |
359 | struct Display<'a>(&'a Cfg, Format); | |
3b2f2976 XL |
360 | |
361 | fn write_with_opt_paren<T: fmt::Display>( | |
9fa01778 | 362 | fmt: &mut fmt::Formatter<'_>, |
3b2f2976 XL |
363 | has_paren: bool, |
364 | obj: T, | |
365 | ) -> fmt::Result { | |
366 | if has_paren { | |
367 | fmt.write_char('(')?; | |
368 | } | |
369 | obj.fmt(fmt)?; | |
370 | if has_paren { | |
371 | fmt.write_char(')')?; | |
372 | } | |
373 | Ok(()) | |
374 | } | |
375 | ||
1b1a35ee | 376 | impl<'a> fmt::Display for Display<'a> { |
9fa01778 | 377 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
3b2f2976 XL |
378 | match *self.0 { |
379 | Cfg::Not(ref child) => match **child { | |
380 | Cfg::Any(ref sub_cfgs) => { | |
dfeec247 XL |
381 | let separator = |
382 | if sub_cfgs.iter().all(Cfg::is_simple) { " nor " } else { ", nor " }; | |
3b2f2976 XL |
383 | for (i, sub_cfg) in sub_cfgs.iter().enumerate() { |
384 | fmt.write_str(if i == 0 { "neither " } else { separator })?; | |
1b1a35ee | 385 | write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; |
3b2f2976 XL |
386 | } |
387 | Ok(()) | |
388 | } | |
1b1a35ee XL |
389 | ref simple @ Cfg::Cfg(..) => write!(fmt, "non-{}", Display(simple, self.1)), |
390 | ref c => write!(fmt, "not ({})", Display(c, self.1)), | |
3b2f2976 XL |
391 | }, |
392 | ||
393 | Cfg::Any(ref sub_cfgs) => { | |
dfeec247 | 394 | let separator = if sub_cfgs.iter().all(Cfg::is_simple) { " or " } else { ", or " }; |
1b1a35ee XL |
395 | |
396 | let short_longhand = self.1.is_long() && { | |
397 | let all_crate_features = sub_cfgs | |
398 | .iter() | |
399 | .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_)))); | |
400 | let all_target_features = sub_cfgs | |
401 | .iter() | |
402 | .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_)))); | |
403 | ||
404 | if all_crate_features { | |
405 | fmt.write_str("crate features ")?; | |
406 | true | |
407 | } else if all_target_features { | |
408 | fmt.write_str("target features ")?; | |
409 | true | |
410 | } else { | |
411 | false | |
412 | } | |
413 | }; | |
414 | ||
3b2f2976 XL |
415 | for (i, sub_cfg) in sub_cfgs.iter().enumerate() { |
416 | if i != 0 { | |
417 | fmt.write_str(separator)?; | |
418 | } | |
1b1a35ee XL |
419 | if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { |
420 | if self.1.is_html() { | |
421 | write!(fmt, "<code>{}</code>", feat)?; | |
422 | } else { | |
423 | write!(fmt, "`{}`", feat)?; | |
424 | } | |
425 | } else { | |
426 | write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; | |
427 | } | |
3b2f2976 XL |
428 | } |
429 | Ok(()) | |
dfeec247 | 430 | } |
3b2f2976 XL |
431 | |
432 | Cfg::All(ref sub_cfgs) => { | |
1b1a35ee XL |
433 | let short_longhand = self.1.is_long() && { |
434 | let all_crate_features = sub_cfgs | |
435 | .iter() | |
436 | .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_)))); | |
437 | let all_target_features = sub_cfgs | |
438 | .iter() | |
439 | .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_)))); | |
440 | ||
441 | if all_crate_features { | |
442 | fmt.write_str("crate features ")?; | |
443 | true | |
444 | } else if all_target_features { | |
445 | fmt.write_str("target features ")?; | |
446 | true | |
447 | } else { | |
448 | false | |
449 | } | |
450 | }; | |
451 | ||
3b2f2976 XL |
452 | for (i, sub_cfg) in sub_cfgs.iter().enumerate() { |
453 | if i != 0 { | |
454 | fmt.write_str(" and ")?; | |
455 | } | |
1b1a35ee XL |
456 | if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { |
457 | if self.1.is_html() { | |
458 | write!(fmt, "<code>{}</code>", feat)?; | |
459 | } else { | |
460 | write!(fmt, "`{}`", feat)?; | |
461 | } | |
462 | } else { | |
463 | write_with_opt_paren(fmt, !sub_cfg.is_simple(), Display(sub_cfg, self.1))?; | |
464 | } | |
3b2f2976 XL |
465 | } |
466 | Ok(()) | |
dfeec247 | 467 | } |
3b2f2976 XL |
468 | |
469 | Cfg::True => fmt.write_str("everywhere"), | |
470 | Cfg::False => fmt.write_str("nowhere"), | |
471 | ||
472 | Cfg::Cfg(name, value) => { | |
3dfed10e XL |
473 | let human_readable = match (name, value) { |
474 | (sym::unix, None) => "Unix", | |
475 | (sym::windows, None) => "Windows", | |
476 | (sym::debug_assertions, None) => "debug-assertions enabled", | |
477 | (sym::target_os, Some(os)) => match &*os.as_str() { | |
3b2f2976 | 478 | "android" => "Android", |
3b2f2976 XL |
479 | "dragonfly" => "DragonFly BSD", |
480 | "emscripten" => "Emscripten", | |
481 | "freebsd" => "FreeBSD", | |
482 | "fuchsia" => "Fuchsia", | |
483 | "haiku" => "Haiku", | |
e74abb32 | 484 | "hermit" => "HermitCore", |
ba9703b0 | 485 | "illumos" => "illumos", |
3b2f2976 XL |
486 | "ios" => "iOS", |
487 | "l4re" => "L4Re", | |
488 | "linux" => "Linux", | |
489 | "macos" => "macOS", | |
3b2f2976 XL |
490 | "netbsd" => "NetBSD", |
491 | "openbsd" => "OpenBSD", | |
492 | "redox" => "Redox", | |
493 | "solaris" => "Solaris", | |
494 | "windows" => "Windows", | |
495 | _ => "", | |
496 | }, | |
3dfed10e | 497 | (sym::target_arch, Some(arch)) => match &*arch.as_str() { |
3b2f2976 XL |
498 | "aarch64" => "AArch64", |
499 | "arm" => "ARM", | |
e74abb32 | 500 | "asmjs" => "JavaScript", |
3b2f2976 XL |
501 | "mips" => "MIPS", |
502 | "mips64" => "MIPS-64", | |
503 | "msp430" => "MSP430", | |
504 | "powerpc" => "PowerPC", | |
505 | "powerpc64" => "PowerPC-64", | |
506 | "s390x" => "s390x", | |
507 | "sparc64" => "SPARC64", | |
508 | "wasm32" => "WebAssembly", | |
509 | "x86" => "x86", | |
510 | "x86_64" => "x86-64", | |
511 | _ => "", | |
512 | }, | |
3dfed10e | 513 | (sym::target_vendor, Some(vendor)) => match &*vendor.as_str() { |
3b2f2976 XL |
514 | "apple" => "Apple", |
515 | "pc" => "PC", | |
516 | "rumprun" => "Rumprun", | |
517 | "sun" => "Sun", | |
0731742a | 518 | "fortanix" => "Fortanix", |
dfeec247 | 519 | _ => "", |
3b2f2976 | 520 | }, |
3dfed10e | 521 | (sym::target_env, Some(env)) => match &*env.as_str() { |
3b2f2976 XL |
522 | "gnu" => "GNU", |
523 | "msvc" => "MSVC", | |
524 | "musl" => "musl", | |
525 | "newlib" => "Newlib", | |
526 | "uclibc" => "uClibc", | |
0731742a | 527 | "sgx" => "SGX", |
3b2f2976 XL |
528 | _ => "", |
529 | }, | |
3dfed10e XL |
530 | (sym::target_endian, Some(endian)) => return write!(fmt, "{}-endian", endian), |
531 | (sym::target_pointer_width, Some(bits)) => return write!(fmt, "{}-bit", bits), | |
1b1a35ee XL |
532 | (sym::target_feature, Some(feat)) => match self.1 { |
533 | Format::LongHtml => { | |
94b46f34 | 534 | return write!(fmt, "target feature <code>{}</code>", feat); |
dfeec247 | 535 | } |
1b1a35ee XL |
536 | Format::LongPlain => return write!(fmt, "target feature `{}`", feat), |
537 | Format::ShortHtml => return write!(fmt, "<code>{}</code>", feat), | |
538 | }, | |
539 | (sym::feature, Some(feat)) => match self.1 { | |
540 | Format::LongHtml => { | |
541 | return write!(fmt, "crate feature <code>{}</code>", feat); | |
542 | } | |
543 | Format::LongPlain => return write!(fmt, "crate feature `{}`", feat), | |
544 | Format::ShortHtml => return write!(fmt, "<code>{}</code>", feat), | |
545 | }, | |
3b2f2976 XL |
546 | _ => "", |
547 | }; | |
548 | if !human_readable.is_empty() { | |
549 | fmt.write_str(human_readable) | |
550 | } else if let Some(v) = value { | |
1b1a35ee XL |
551 | if self.1.is_html() { |
552 | write!( | |
553 | fmt, | |
554 | r#"<code>{}="{}"</code>"#, | |
555 | Escape(&name.as_str()), | |
556 | Escape(&v.as_str()) | |
557 | ) | |
558 | } else { | |
559 | write!(fmt, r#"`{}="{}"`"#, name, v) | |
560 | } | |
561 | } else if self.1.is_html() { | |
3dfed10e | 562 | write!(fmt, "<code>{}</code>", Escape(&name.as_str())) |
1b1a35ee XL |
563 | } else { |
564 | write!(fmt, "`{}`", name) | |
3b2f2976 XL |
565 | } |
566 | } | |
567 | } | |
568 | } | |
569 | } |