1use rucc_diag::Span;
16use rucc_lex::{Encoding, Token, TokenKind};
17
18use crate::pack::eat_punct;
19use crate::parser::Parser;
20
21#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum Comment {
24 Lib(String),
26 Linker(String),
28}
29
30impl Parser<'_> {
31 pub(crate) fn comment_line(&mut self, mut rest: &[Token], span: Span) {
33 if !eat_punct(&mut rest, "(") {
34 self.warn("E0745", "missing `(` after `#pragma comment` - ignored", span);
35 return;
36 }
37 let Some(kind) = rest.first().and_then(|token| token.ident()) else {
38 self.warn("E0745", "malformed `#pragma comment` - ignored", span);
39 return;
40 };
41 let kind = self.cx.interner.resolve(kind).to_owned();
42 rest = &rest[1..];
43 let text = if eat_punct(&mut rest, ",") {
44 let Some(text) = self.comment_text(&mut rest) else {
45 self.warn("E0745", "`#pragma comment` wants a string after the comma", span);
46 return;
47 };
48 Some(text)
49 } else {
50 None
51 };
52 if !eat_punct(&mut rest, ")") || !rest.is_empty() {
53 self.warn("E0745", "malformed `#pragma comment` - ignored", span);
54 return;
55 }
56 match (kind.as_str(), text) {
57 ("lib", Some(text)) => self.comments.push(Comment::Lib(text)),
58 ("linker", Some(text)) => self.comments.push(Comment::Linker(text)),
59 ("lib" | "linker", None) => {
60 let what = format!("`#pragma comment({kind})` wants a string - ignored");
61 self.warn("E0745", what, span);
62 }
63 ("compiler" | "exestr" | "user", _) => {}
64 _ => {
65 let what = format!("unknown kind `{kind}` in `#pragma comment` - ignored");
66 self.warn("E0745", what, span);
67 }
68 }
69 }
70
71 fn comment_text(&self, rest: &mut &[Token]) -> Option<String> {
73 let token = rest.first()?;
74 if token.kind != TokenKind::Str {
75 return None;
76 }
77 let literal = self.tokens.strings.get(token.value as usize)?;
78 if !matches!(literal.encoding, Encoding::Plain | Encoding::Utf8) {
79 return None;
80 }
81 *rest = &rest[1..];
82 let bytes: Vec<u8> = literal.elements.iter().map(|&element| element as u8).collect();
83 Some(String::from_utf8_lossy(&bytes).into_owned())
84 }
85}