Skip to content

Commit 89f2f45

Browse files
committed
Allow building the library without libstd at all
1 parent 8164dcd commit 89f2f45

File tree

9 files changed

+142
-53
lines changed

9 files changed

+142
-53
lines changed

macros/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ use rustc::plugin::Registry;
2222
// Internal macros for use in defining other macros.
2323
mod internal;
2424

25-
// Exported non-procedural macros.
26-
pub mod exported;
27-
2825
// Make these public so that rustdoc will generate documentation for them.
2926
pub mod named_entities;
3027
pub mod atom;

src/lib.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,19 @@
1717
// This helps us make a C-friendly library.
1818
#![no_std]
1919

20-
extern crate core;
2120
extern crate alloc;
22-
extern crate collections;
2321

22+
#[phase(plugin, link)]
23+
extern crate core;
24+
25+
#[cfg(not(for_c))]
2426
#[phase(plugin, link)]
2527
extern crate std;
2628

29+
#[phase(plugin, link)]
30+
extern crate collections;
31+
32+
#[cfg(not(for_c))]
2733
#[phase(plugin, link)]
2834
extern crate log;
2935

@@ -47,8 +53,12 @@ pub use util::atom::Atom;
4753
pub use util::namespace::Namespace;
4854

4955
pub use driver::{one_input, ParseOpts, parse_to, parse};
56+
57+
#[cfg(not(for_c))]
5058
pub use serialize::serialize;
5159

60+
mod macros;
61+
5262
mod util {
5363
#![macro_escape]
5464

@@ -60,13 +70,24 @@ mod util {
6070

6171
pub mod tokenizer;
6272
pub mod tree_builder;
73+
74+
#[cfg(not(for_c))]
6375
pub mod serialize;
6476

6577
/// Consumers of the parser API.
78+
#[cfg(not(for_c))]
6679
pub mod sink {
6780
pub mod common;
6881
pub mod rcdom;
6982
pub mod owned_dom;
7083
}
7184

7285
pub mod driver;
86+
87+
/// A fake `std` module so that `deriving` and other macros will work.
88+
/// See rust-lang/rust#16803.
89+
#[cfg(for_c)]
90+
mod std {
91+
pub use core::{clone, cmp, default, fmt, option, str};
92+
pub use collections::hash;
93+
}

macros/src/exported.rs renamed to src/macros.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@
77
// option. This file may not be copied, modified, or distributed
88
// except according to those terms.
99

10-
//! Exported non-procedural macros.
10+
#![macro_escape]
1111

12-
#[macro_export]
1312
macro_rules! unwrap_or_return ( ($opt:expr, $retval:expr) => (
1413
match $opt {
1514
None => return $retval,
1615
Some(x) => x,
1716
}
1817
))
1918

20-
#[macro_export]
2119
macro_rules! test_eq ( ($name:ident, $left:expr, $right:expr) => (
2220
#[test]
2321
fn $name() {
@@ -26,7 +24,6 @@ macro_rules! test_eq ( ($name:ident, $left:expr, $right:expr) => (
2624
))
2725

2826
/// Make a tuple of the addresses of some of a struct's fields.
29-
#[macro_export]
3027
macro_rules! addrs_of ( ($obj:expr : $($field:ident),+) => (
3128
( // make a tuple
3229
$(
@@ -37,7 +34,13 @@ macro_rules! addrs_of ( ($obj:expr : $($field:ident),+) => (
3734
)
3835
))
3936

40-
#[macro_export]
37+
// No format!() without libstd... just use the static message.
38+
#[cfg(for_c)]
39+
macro_rules! format_if ( ($pred:expr, $msg_static:expr, $msg_fmt:expr, $($arg:expr),*) => (
40+
::collections::str::Slice($msg_static)
41+
))
42+
43+
#[cfg(not(for_c))]
4144
macro_rules! format_if ( ($pred:expr, $msg_static:expr, $msg_fmt:expr, $($arg:expr),*) => (
4245
if $pred {
4346
::collections::str::Owned(format!($msg_fmt, $($arg),*))
@@ -46,10 +49,42 @@ macro_rules! format_if ( ($pred:expr, $msg_static:expr, $msg_fmt:expr, $($arg:ex
4649
}
4750
))
4851

49-
#[macro_export]
5052
macro_rules! time ( ($e:expr) => ({
5153
let t0 = ::time::precise_time_ns();
5254
let result = $e;
5355
let dt = ::time::precise_time_ns() - t0;
5456
(result, dt)
5557
}))
58+
59+
/// FIXME(rust-lang/rust#16806): copied from libcollections/macros.rs
60+
#[cfg(for_c)]
61+
macro_rules! vec(
62+
($($e:expr),*) => ({
63+
// leading _ to allow empty construction without a warning.
64+
let mut _temp = ::collections::vec::Vec::new();
65+
$(_temp.push($e);)*
66+
_temp
67+
});
68+
($($e:expr),+,) => (vec!($($e),+))
69+
)
70+
71+
// Disable logging when building without the runtime.
72+
#[cfg(for_c)]
73+
mod log {
74+
#![macro_escape]
75+
macro_rules! h5e_log (($($x:tt)*) => (()))
76+
macro_rules! h5e_debug (($($x:tt)*) => (()))
77+
macro_rules! h5e_info (($($x:tt)*) => (()))
78+
macro_rules! h5e_warn (($($x:tt)*) => (()))
79+
macro_rules! h5e_error (($($x:tt)*) => (()))
80+
}
81+
82+
#[cfg(not(for_c))]
83+
mod log {
84+
#![macro_escape]
85+
macro_rules! h5e_log (($($x:tt)*) => (log!($($x)*)))
86+
macro_rules! h5e_debug (($($x:tt)*) => (debug!($($x)*)))
87+
macro_rules! h5e_info (($($x:tt)*) => (info!($($x)*)))
88+
macro_rules! h5e_warn (($($x:tt)*) => (warn!($($x)*)))
89+
macro_rules! h5e_error (($($x:tt)*) => (error!($($x)*)))
90+
}

src/tokenizer/char_ref/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl<'sink, Sink: TokenSink> CharRefTokenizer {
115115
return Done;
116116
}
117117

118-
debug!("char ref tokenizer stepping in state {:?}", self.state);
118+
h5e_debug!("char ref tokenizer stepping in state {:?}", self.state);
119119
match self.state {
120120
Begin => self.do_begin(tokenizer),
121121
Octothorpe => self.do_octothorpe(tokenizer),

src/tokenizer/mod.rs

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,12 @@ use util::atom::Atom;
3131
use util::smallcharset::SmallCharSet;
3232

3333
use core::mem::replace;
34-
use core::iter::AdditiveIterator;
3534
use core::default::Default;
3635
use alloc::boxed::Box;
3736
use collections::{MutableSeq, MutableMap};
3837
use collections::vec::Vec;
3938
use collections::string::String;
40-
use collections::str::{MaybeOwned, Slice, Owned};
39+
use collections::str::{MaybeOwned, Slice};
4140
use collections::treemap::TreeMap;
4241

4342
pub mod states;
@@ -176,6 +175,10 @@ pub struct Tokenizer<'sink, Sink> {
176175
impl<'sink, Sink: TokenSink> Tokenizer<'sink, Sink> {
177176
/// Create a new tokenizer which feeds tokens to a particular `TokenSink`.
178177
pub fn new(sink: &'sink mut Sink, mut opts: TokenizerOpts) -> Tokenizer<'sink, Sink> {
178+
if opts.profile && cfg!(for_c) {
179+
fail!("Can't profile tokenizer when built as a C library");
180+
}
181+
179182
let start_tag_name = opts.last_start_tag_name.take().map(|s| Atom::from_buf(s));
180183
let state = *opts.initial_state.as_ref().unwrap_or(&states::Data);
181184
let discard_bom = opts.discard_bom;
@@ -253,11 +256,13 @@ impl<'sink, Sink: TokenSink> Tokenizer<'sink, Sink> {
253256
n if (n & 0xFFFE) == 0xFFFE => true,
254257
_ => false,
255258
} {
256-
let msg = Owned(format!("Bad character {:?}", c));
259+
// format_if!(true) will still use the static error when built for C.
260+
let msg = format_if!(true, "Bad character",
261+
"Bad character {:?}", c);
257262
self.emit_error(msg);
258263
}
259264

260-
debug!("got character {:?}", c);
265+
h5e_debug!("got character {:?}", c);
261266
self.current_char = c;
262267
Some(c)
263268
}
@@ -284,7 +289,7 @@ impl<'sink, Sink: TokenSink> Tokenizer<'sink, Sink> {
284289
}
285290

286291
let d = self.input_buffers.pop_except_from(set);
287-
debug!("got characters {}", d);
292+
h5e_debug!("got characters {}", d);
288293
match d {
289294
Some(FromSet(c)) => self.get_preprocessed_char(c).map(|x| FromSet(x)),
290295

@@ -306,21 +311,21 @@ impl<'sink, Sink: TokenSink> Tokenizer<'sink, Sink> {
306311
fn lookahead_and_consume(&mut self, n: uint, p: |&str| -> bool) -> Option<bool> {
307312
match self.input_buffers.pop_front(n) {
308313
None if self.at_eof => {
309-
debug!("lookahead: requested {:u} characters not available and never will be", n);
314+
h5e_debug!("lookahead: requested {:u} characters not available and never will be", n);
310315
Some(false)
311316
}
312317
None => {
313-
debug!("lookahead: requested {:u} characters not available", n);
318+
h5e_debug!("lookahead: requested {:u} characters not available", n);
314319
self.wait_for = Some(n);
315320
None
316321
}
317322
Some(s) => {
318323
if p(s.as_slice()) {
319-
debug!("lookahead: condition satisfied by {:?}", s);
324+
h5e_debug!("lookahead: condition satisfied by {:?}", s);
320325
// FIXME: set current input character?
321326
Some(true)
322327
} else {
323-
debug!("lookahead: condition not satisfied by {:?}", s);
328+
h5e_debug!("lookahead: condition not satisfied by {:?}", s);
324329
self.unconsume(s);
325330
Some(false)
326331
}
@@ -569,7 +574,7 @@ macro_rules! shorthand (
569574
// so it's behind a cfg flag.
570575
#[cfg(trace_tokenizer)]
571576
macro_rules! sh_trace ( ( $me:expr : $($cmds:tt)* ) => ({
572-
debug!(" {:s}", stringify!($($cmds)*));
577+
h5e_debug!(" {:s}", stringify!($($cmds)*));
573578
shorthand!($me:expr : $($cmds)*);
574579
}))
575580

@@ -654,17 +659,17 @@ impl<'sink, Sink: TokenSink> Tokenizer<'sink, Sink> {
654659

655660
match self.wait_for {
656661
Some(n) if !self.input_buffers.has(n) => {
657-
debug!("lookahead: requested {:u} characters still not available", n);
662+
h5e_debug!("lookahead: requested {:u} characters still not available", n);
658663
return false;
659664
}
660-
Some(n) => {
661-
debug!("lookahead: requested {:u} characters become available", n);
665+
Some(_n) => {
666+
h5e_debug!("lookahead: requested {:u} characters become available", _n);
662667
self.wait_for = None;
663668
}
664669
None => (),
665670
}
666671

667-
debug!("processing in state {:?}", self.state);
672+
h5e_debug!("processing in state {:?}", self.state);
668673
match self.state {
669674
//§ data-state
670675
states::Data => loop {
@@ -1255,24 +1260,36 @@ impl<'sink, Sink: TokenSink> Tokenizer<'sink, Sink> {
12551260
}
12561261

12571262
if self.opts.profile {
1258-
let mut results: Vec<(states::State, u64)>
1259-
= self.state_profile.iter().map(|(s, t)| (*s, *t)).collect();
1260-
results.sort_by(|&(_, x), &(_, y)| y.cmp(&x));
1261-
1262-
let total = results.iter().map(|&(_, t)| t).sum();
1263-
println!("\nTokenizer profile, in nanoseconds");
1264-
println!("\n{:12u} total in token sink", self.time_in_sink);
1265-
println!("\n{:12u} total in tokenizer", total);
1266-
1267-
for (k, v) in results.move_iter() {
1268-
let pct = 100.0 * (v as f64) / (total as f64);
1269-
println!("{:12u} {:4.1f}% {:?}", v, pct, k);
1270-
}
1263+
self.dump_profile();
1264+
}
1265+
}
1266+
1267+
#[cfg(for_c)]
1268+
fn dump_profile(&self) {
1269+
unreachable!();
1270+
}
1271+
1272+
#[cfg(not(for_c))]
1273+
fn dump_profile(&self) {
1274+
use core::iter::AdditiveIterator;
1275+
1276+
let mut results: Vec<(states::State, u64)>
1277+
= self.state_profile.iter().map(|(s, t)| (*s, *t)).collect();
1278+
results.sort_by(|&(_, x), &(_, y)| y.cmp(&x));
1279+
1280+
let total = results.iter().map(|&(_, t)| t).sum();
1281+
println!("\nTokenizer profile, in nanoseconds");
1282+
println!("\n{:12u} total in token sink", self.time_in_sink);
1283+
println!("\n{:12u} total in tokenizer", total);
1284+
1285+
for (k, v) in results.move_iter() {
1286+
let pct = 100.0 * (v as f64) / (total as f64);
1287+
println!("{:12u} {:4.1f}% {:?}", v, pct, k);
12711288
}
12721289
}
12731290

12741291
fn eof_step(&mut self) -> bool {
1275-
debug!("processing EOF in state {:?}", self.state);
1292+
h5e_debug!("processing EOF in state {:?}", self.state);
12761293
match self.state {
12771294
states::Data | states::RawData(Rcdata) | states::RawData(Rawtext)
12781295
| states::RawData(ScriptData) | states::Plaintext

src/tree_builder/actions.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ use tokenizer::states::{RawData, RawKind};
2424

2525
use util::atom::Atom;
2626
use util::namespace::{Namespace, HTML};
27-
use util::str::{to_escaped_string, AsciiExt};
27+
use util::str::AsciiExt;
28+
29+
#[cfg(not(for_c))]
30+
use util::str::to_escaped_string;
2831

2932
use core::mem::replace;
3033
use core::iter::{Rev, Enumerate};
@@ -108,11 +111,11 @@ pub trait TreeBuilderActions<Handle> {
108111
impl<'sink, Handle: Clone, Sink: TreeSink<Handle>>
109112
TreeBuilderActions<Handle> for super::TreeBuilder<'sink, Handle, Sink> {
110113

111-
fn unexpected<T: Show>(&mut self, thing: &T) -> ProcessResult {
114+
fn unexpected<T: Show>(&mut self, _thing: &T) -> ProcessResult {
112115
self.sink.parse_error(format_if!(
113116
self.opts.exact_errors,
114117
"Unexpected token",
115-
"Unexpected token {} in insertion mode {}", to_escaped_string(thing), self.mode));
118+
"Unexpected token {} in insertion mode {}", to_escaped_string(_thing), self.mode));
116119
Done
117120
}
118121

@@ -134,7 +137,7 @@ impl<'sink, Handle: Clone, Sink: TreeSink<Handle>>
134137
}
135138

136139
fn stop_parsing(&mut self) -> ProcessResult {
137-
warn!("stop_parsing not implemented, full speed ahead!");
140+
h5e_warn!("stop_parsing not implemented, full speed ahead!");
138141
Done
139142
}
140143

@@ -377,7 +380,7 @@ impl<'sink, Handle: Clone, Sink: TreeSink<Handle>>
377380
}
378381

379382
fn foster_parent_in_body(&mut self, token: Token) -> ProcessResult {
380-
warn!("foster parenting not implemented");
383+
h5e_warn!("foster parenting not implemented");
381384
self.foster_parenting = true;
382385
let res = self.step(InBody, token);
383386
// FIXME: what if res is Reprocess?

0 commit comments

Comments
 (0)