1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::collections::hash_map::Entry;
use syntax::ext::base::ExtCtxt;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::parse::PResult;
use super::DynasmData;
use serialize::{Stmt, Size, Ident};
use arch;
impl DynasmData {
pub fn evaluate_directive<'b>(&mut self, stmts: &mut Vec<Stmt>, ecx: &mut ExtCtxt, parser: &mut Parser<'b>) -> PResult<'b, ()> {
let start = parser.span;
let directive = parser.parse_ident()?;
match &*directive.name.as_str() {
"arch" => {
let arch = parser.parse_ident()?;
if let Some(a) = arch::from_str(&*arch.name.as_str()) {
self.current_arch = a;
} else {
ecx.span_err(parser.prev_span, &format!("Unknown architecture '{}'", &*arch.name.as_str()));
}
},
"feature" => {
let mut features = Vec::new();
let ident = parser.parse_ident()?;
features.push(Ident {span: parser.prev_span, node: ident});
while parser.eat(&token::Token::Comma) {
let ident = parser.parse_ident()?;
features.push(Ident {span: parser.prev_span, node: ident});
}
self.current_arch.set_features(ecx, &features);
},
"byte" => Self::directive_const(stmts, parser, Size::BYTE)?,
"word" => Self::directive_const(stmts, parser, Size::WORD)?,
"dword" => Self::directive_const(stmts, parser, Size::DWORD)?,
"qword" => Self::directive_const(stmts, parser, Size::QWORD)?,
"bytes" => {
let iterator = parser.parse_expr()?;
stmts.push(Stmt::Extend(iterator));
},
"align" => {
let value = parser.parse_expr()?;
stmts.push(Stmt::Align(value));
},
"alias" => {
let alias = parser.parse_ident()?.name;
parser.expect(&token::Comma)?;
let reg = parser.parse_ident()?.name;
match self.aliases.entry(alias.as_str().to_string()) {
Entry::Occupied(_) => {
ecx.span_err(start.with_hi(parser.prev_span.hi()),
&format!("Duplicate alias definition, alias '{}' was already defined", alias.as_str()));
},
Entry::Vacant(v) => {
v.insert(reg.as_str().to_string());
}
}
},
d => {
ecx.span_err(parser.span, &format!("unknown directive '{}'", d));
while !(parser.check(&token::Semi) && parser.check(&token::Eof)) {
parser.bump();
}
}
}
Ok(())
}
fn directive_const<'b>(stmts: &mut Vec<Stmt>, parser: &mut Parser<'b>, size: Size) -> PResult<'b, ()> {
if !parser.check(&token::Semi) && !parser.check(&token::Eof) {
stmts.push(Stmt::Var(parser.parse_expr()?, size));
while parser.eat(&token::Comma) {
stmts.push(Stmt::Var(parser.parse_expr()?, size));
}
}
Ok(())
}
}