]>
git.proxmox.com Git - rustc.git/blob - src/libsyntax/ext/source_util.rs
3866f5534c2ebb4b10c357b5bf252ce6665f47d2
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use codemap
::{Pos, Span}
;
16 use ext
::build
::AstBuilder
;
21 use util
::small_vector
::SmallVector
;
24 use std
::io
::prelude
::*;
25 use std
::path
::{Path, PathBuf}
;
28 // These macros all relate to the file system; they either return
29 // the column/row/filename of the expression, or they include
30 // a given file into the current one.
32 /// line!(): expands to the current line number
33 pub fn expand_line(cx
: &mut ExtCtxt
, sp
: Span
, tts
: &[ast
::TokenTree
])
34 -> Box
<base
::MacResult
+'
static> {
35 base
::check_zero_tts(cx
, sp
, tts
, "line!");
37 let topmost
= cx
.expansion_cause();
38 let loc
= cx
.codemap().lookup_char_pos(topmost
.lo
);
40 base
::MacEager
::expr(cx
.expr_u32(topmost
, loc
.line
as u32))
43 /* column!(): expands to the current column number */
44 pub fn expand_column(cx
: &mut ExtCtxt
, sp
: Span
, tts
: &[ast
::TokenTree
])
45 -> Box
<base
::MacResult
+'
static> {
46 base
::check_zero_tts(cx
, sp
, tts
, "column!");
48 let topmost
= cx
.expansion_cause();
49 let loc
= cx
.codemap().lookup_char_pos(topmost
.lo
);
51 base
::MacEager
::expr(cx
.expr_u32(topmost
, loc
.col
.to_usize() as u32))
54 /// file!(): expands to the current filename */
55 /// The filemap (`loc.file`) contains a bunch more information we could spit
57 pub fn expand_file(cx
: &mut ExtCtxt
, sp
: Span
, tts
: &[ast
::TokenTree
])
58 -> Box
<base
::MacResult
+'
static> {
59 base
::check_zero_tts(cx
, sp
, tts
, "file!");
61 let topmost
= cx
.expansion_cause();
62 let loc
= cx
.codemap().lookup_char_pos(topmost
.lo
);
63 let filename
= token
::intern_and_get_ident(&loc
.file
.name
);
64 base
::MacEager
::expr(cx
.expr_str(topmost
, filename
))
67 pub fn expand_stringify(cx
: &mut ExtCtxt
, sp
: Span
, tts
: &[ast
::TokenTree
])
68 -> Box
<base
::MacResult
+'
static> {
69 let s
= pprust
::tts_to_string(tts
);
70 base
::MacEager
::expr(cx
.expr_str(sp
,
71 token
::intern_and_get_ident(&s
[..])))
74 pub fn expand_mod(cx
: &mut ExtCtxt
, sp
: Span
, tts
: &[ast
::TokenTree
])
75 -> Box
<base
::MacResult
+'
static> {
76 base
::check_zero_tts(cx
, sp
, tts
, "module_path!");
77 let string
= cx
.mod_path()
79 .map(|x
| token
::get_ident(*x
).to_string())
80 .collect
::<Vec
<String
>>()
82 base
::MacEager
::expr(cx
.expr_str(
84 token
::intern_and_get_ident(&string
[..])))
87 /// include! : parse the given file as an expr
88 /// This is generally a bad idea because it's going to behave
90 pub fn expand_include
<'cx
>(cx
: &'cx
mut ExtCtxt
, sp
: Span
, tts
: &[ast
::TokenTree
])
91 -> Box
<base
::MacResult
+'cx
> {
92 let file
= match get_single_str_from_tts(cx
, sp
, tts
, "include!") {
94 None
=> return DummyResult
::expr(sp
),
96 // The file will be added to the code map by the parser
98 parse
::new_sub_parser_from_file(cx
.parse_sess(),
107 struct ExpandResult
<'a
> {
108 p
: parse
::parser
::Parser
<'a
>,
110 impl<'a
> base
::MacResult
for ExpandResult
<'a
> {
111 fn make_expr(mut self: Box
<ExpandResult
<'a
>>) -> Option
<P
<ast
::Expr
>> {
112 Some(self.p
.parse_expr())
114 fn make_items(mut self: Box
<ExpandResult
<'a
>>)
115 -> Option
<SmallVector
<P
<ast
::Item
>>> {
116 let mut ret
= SmallVector
::zero();
117 while self.p
.token
!= token
::Eof
{
118 match self.p
.parse_item() {
119 Some(item
) => ret
.push(item
),
120 None
=> panic
!(self.p
.span_fatal(
122 &format
!("expected item, found `{}`",
123 self.p
.this_token_to_string())
131 Box
::new(ExpandResult { p: p }
)
134 // include_str! : read the given file, insert it as a literal string expr
135 pub fn expand_include_str(cx
: &mut ExtCtxt
, sp
: Span
, tts
: &[ast
::TokenTree
])
136 -> Box
<base
::MacResult
+'
static> {
137 let file
= match get_single_str_from_tts(cx
, sp
, tts
, "include_str!") {
139 None
=> return DummyResult
::expr(sp
)
141 let file
= res_rel_file(cx
, sp
, Path
::new(&file
));
142 let mut bytes
= Vec
::new();
143 match File
::open(&file
).and_then(|mut f
| f
.read_to_end(&mut bytes
)) {
147 &format
!("couldn't read {}: {}",
150 return DummyResult
::expr(sp
);
153 match String
::from_utf8(bytes
) {
155 // Add this input file to the code map to make it available as
156 // dependency information
157 let filename
= format
!("{}", file
.display());
158 let interned
= token
::intern_and_get_ident(&src
[..]);
159 cx
.codemap().new_filemap(filename
, src
);
161 base
::MacEager
::expr(cx
.expr_str(sp
, interned
))
165 &format
!("{} wasn't a utf-8 file",
167 return DummyResult
::expr(sp
);
172 pub fn expand_include_bytes(cx
: &mut ExtCtxt
, sp
: Span
, tts
: &[ast
::TokenTree
])
173 -> Box
<base
::MacResult
+'
static> {
174 let file
= match get_single_str_from_tts(cx
, sp
, tts
, "include_bytes!") {
176 None
=> return DummyResult
::expr(sp
)
178 let file
= res_rel_file(cx
, sp
, Path
::new(&file
));
179 let mut bytes
= Vec
::new();
180 match File
::open(&file
).and_then(|mut f
| f
.read_to_end(&mut bytes
)) {
183 &format
!("couldn't read {}: {}", file
.display(), e
));
184 return DummyResult
::expr(sp
);
187 // Add this input file to the code map to make it available as
188 // dependency information, but don't enter it's contents
189 let filename
= format
!("{}", file
.display());
190 cx
.codemap().new_filemap(filename
, "".to_string());
192 base
::MacEager
::expr(cx
.expr_lit(sp
, ast
::LitBinary(Rc
::new(bytes
))))
197 // resolve a file-system path to an absolute file-system path (if it
199 fn res_rel_file(cx
: &mut ExtCtxt
, sp
: codemap
::Span
, arg
: &Path
) -> PathBuf
{
200 // NB: relative paths are resolved relative to the compilation unit
201 if !arg
.is_absolute() {
202 let mut cu
= PathBuf
::from(&cx
.codemap().span_to_filename(sp
));