Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Converted fourcc! to loadable syntax extension
- Loading branch information
Showing
12 changed files
with
225 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
/*! | ||
Syntax extension to generate FourCCs. | ||
Once loaded, fourcc!() is called with a single 4-character string, | ||
and an optional ident that is either `big`, `little`, or `target`. | ||
The ident represents endianness, and specifies in which direction | ||
the characters should be read. If the ident is omitted, it is assumed | ||
to be `big`, i.e. left-to-right order. It returns a u32. | ||
# Examples | ||
To load the extension and use it: | ||
```rust,ignore | ||
#[phase(syntax)] | ||
extern mod fourcc; | ||
fn main() { | ||
let val = fourcc!("\xC0\xFF\xEE!") | ||
// val is 0xC0FFEE21 | ||
let big_val = fourcc!("foo ", big); | ||
// big_val is 0x21EEFFC0 | ||
} | ||
``` | ||
# References | ||
* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC) | ||
*/ | ||
|
||
#[crate_id = "fourcc#0.10-pre"]; | ||
#[crate_type = "rlib"]; | ||
#[crate_type = "dylib"]; | ||
#[license = "MIT/ASL2"]; | ||
|
||
#[feature(macro_registrar, managed_boxes)]; | ||
|
||
extern mod syntax; | ||
|
||
use syntax::ast; | ||
use syntax::ast::Name; | ||
use syntax::attr::contains; | ||
use syntax::codemap::{Span, mk_sp}; | ||
use syntax::ext::base; | ||
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr}; | ||
use syntax::ext::build::AstBuilder; | ||
use syntax::parse; | ||
use syntax::parse::token; | ||
use syntax::parse::token::InternedString; | ||
|
||
#[macro_registrar] | ||
#[cfg(not(test))] | ||
pub fn macro_registrar(register: |Name, SyntaxExtension|) { | ||
register(token::intern("fourcc"), | ||
NormalTT(~BasicMacroExpander { | ||
expander: expand_syntax_ext, | ||
span: None, | ||
}, | ||
None)); | ||
} | ||
|
||
use std::ascii::AsciiCast; | ||
|
||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult { | ||
let (expr, endian) = parse_tts(cx, tts); | ||
|
||
let little = match endian { | ||
None => target_endian_little(cx, sp), | ||
Some(Ident{ident, span}) => match token::get_ident(ident.name).get() { | ||
"little" => true, | ||
"big" => false, | ||
_ => { | ||
cx.span_err(span, "invalid endian directive in fourcc!"); | ||
target_endian_little(cx, sp) | ||
} | ||
} | ||
}; | ||
|
||
let s = match expr.node { | ||
// expression is a literal | ||
ast::ExprLit(lit) => match lit.node { | ||
// string literal | ||
ast::LitStr(ref s, _) => { | ||
if !s.get().is_ascii() { | ||
cx.span_err(expr.span, "non-ascii string literal in fourcc!"); | ||
} else if s.get().len() != 4 { | ||
cx.span_err(expr.span, "string literal with len != 4 in fourcc!"); | ||
} | ||
s | ||
} | ||
_ => { | ||
cx.span_err(expr.span, "unsupported literal in fourcc!"); | ||
return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32))); | ||
} | ||
}, | ||
_ => { | ||
cx.span_err(expr.span, "non-literal in fourcc!"); | ||
return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32))); | ||
} | ||
}; | ||
|
||
let mut val = 0u32; | ||
if little { | ||
for byte in s.get().bytes_rev().take(4) { | ||
val = (val << 8) | (byte as u32); | ||
} | ||
} else { | ||
for byte in s.get().bytes().take(4) { | ||
val = (val << 8) | (byte as u32); | ||
} | ||
} | ||
let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32)); | ||
MRExpr(e) | ||
} | ||
|
||
struct Ident { | ||
ident: ast::Ident, | ||
span: Span | ||
} | ||
|
||
fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) { | ||
let p = &mut parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_owned()); | ||
let ex = p.parse_expr(); | ||
let id = if p.token == token::EOF { | ||
None | ||
} else { | ||
p.expect(&token::COMMA); | ||
let lo = p.span.lo; | ||
let ident = p.parse_ident(); | ||
let hi = p.last_span.hi; | ||
Some(Ident{ident: ident, span: mk_sp(lo, hi)}) | ||
}; | ||
if p.token != token::EOF { | ||
p.unexpected(); | ||
} | ||
(ex, id) | ||
} | ||
|
||
fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool { | ||
let meta = cx.meta_name_value(sp, InternedString::new("target_endian"), | ||
ast::LitStr(InternedString::new("little"), ast::CookedStr)); | ||
contains(cx.cfg(), meta) | ||
} | ||
|
||
// Fixes LLVM assert on Windows | ||
#[test] | ||
fn dummy_test() { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.