about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/fmt/mod.rs52
-rw-r--r--src/libstd/fmt/parse.rs87
-rw-r--r--src/libstd/fmt/rt.rs15
3 files changed, 135 insertions, 19 deletions
diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs
index a03f21d69c8..4032515f985 100644
--- a/src/libstd/fmt/mod.rs
+++ b/src/libstd/fmt/mod.rs
@@ -647,21 +647,6 @@ impl<'self> Formatter<'self> {
     // the format! syntax extension.
 
     fn run(&mut self, piece: &rt::Piece, cur: Option<&str>) {
-        let setcount = |slot: &mut Option<uint>, cnt: &parse::Count| {
-            match *cnt {
-                parse::CountIs(n) => { *slot = Some(n); }
-                parse::CountImplied => { *slot = None; }
-                parse::CountIsParam(i) => {
-                    let v = self.args[i].value;
-                    unsafe { *slot = Some(*(v as *util::Void as *uint)); }
-                }
-                parse::CountIsNextParam => {
-                    let v = self.curarg.next().unwrap().value;
-                    unsafe { *slot = Some(*(v as *util::Void as *uint)); }
-                }
-            }
-        };
-
         match *piece {
             rt::String(s) => { self.buf.write(s.as_bytes()); }
             rt::CurrentArgument(()) => { self.buf.write(cur.unwrap().as_bytes()); }
@@ -670,8 +655,8 @@ impl<'self> Formatter<'self> {
                 self.fill = arg.format.fill;
                 self.align = arg.format.align;
                 self.flags = arg.format.flags;
-                setcount(&mut self.width, &arg.format.width);
-                setcount(&mut self.precision, &arg.format.precision);
+                self.width = self.getcount(&arg.format.width);
+                self.precision = self.getcount(&arg.format.precision);
 
                 // Extract the correct argument
                 let value = match arg.position {
@@ -688,6 +673,39 @@ impl<'self> Formatter<'self> {
         }
     }
 
+    #[cfg(stage0)]
+    fn getcount(&mut self, cnt: &parse::Count) -> Option<uint> {
+        match *cnt {
+            parse::CountIs(n) => { Some(n) }
+            parse::CountImplied => { None }
+            parse::CountIsParam(i) => {
+                let v = self.args[i].value;
+                unsafe { Some(*(v as *util::Void as *uint)) }
+            }
+            parse::CountIsNextParam => {
+                let v = self.curarg.next().unwrap().value;
+                unsafe { Some(*(v as *util::Void as *uint)) }
+            }
+            parse::CountIsName(*) => unreachable!()
+        }
+    }
+
+    #[cfg(not(stage0))]
+    fn getcount(&mut self, cnt: &rt::Count) -> Option<uint> {
+        match *cnt {
+            rt::CountIs(n) => { Some(n) }
+            rt::CountImplied => { None }
+            rt::CountIsParam(i) => {
+                let v = self.args[i].value;
+                unsafe { Some(*(v as *util::Void as *uint)) }
+            }
+            rt::CountIsNextParam => {
+                let v = self.curarg.next().unwrap().value;
+                unsafe { Some(*(v as *util::Void as *uint)) }
+            }
+        }
+    }
+
     fn execute(&mut self, method: &rt::Method, arg: Argument) {
         match *method {
             // Pluralization is selection upon a numeric value specified as the
diff --git a/src/libstd/fmt/parse.rs b/src/libstd/fmt/parse.rs
index 1b8998b5c6c..11b869c930e 100644
--- a/src/libstd/fmt/parse.rs
+++ b/src/libstd/fmt/parse.rs
@@ -48,6 +48,7 @@ pub struct Argument<'self> {
 
 /// Specification for the formatting of an argument in the format string.
 #[deriving(Eq)]
+#[cfg(stage0)]
 pub struct FormatSpec<'self> {
     /// Optionally specified character to fill alignment with
     fill: Option<char>,
@@ -65,6 +66,26 @@ pub struct FormatSpec<'self> {
     ty: &'self str
 }
 
+/// Specification for the formatting of an argument in the format string.
+#[deriving(Eq)]
+#[cfg(not(stage0))]
+pub struct FormatSpec<'self> {
+    /// Optionally specified character to fill alignment with
+    fill: Option<char>,
+    /// Optionally specified alignment
+    align: Alignment,
+    /// Packed version of various flags provided
+    flags: uint,
+    /// The integer precision to use
+    precision: Count<'self>,
+    /// The string width requested for the resulting format
+    width: Count<'self>,
+    /// The descriptor string representing the name of the format desired for
+    /// this argument, this can be empty or any number of characters, although
+    /// it is required to be one word.
+    ty: &'self str
+}
+
 /// Enum describing where an argument for a format can be located.
 #[deriving(Eq)]
 #[allow(missing_doc)]
@@ -92,9 +113,22 @@ pub enum Flag {
 /// can reference either an argument or a literal integer.
 #[deriving(Eq)]
 #[allow(missing_doc)]
+#[cfg(stage0)]
 pub enum Count {
     CountIs(uint),
     CountIsParam(uint),
+    CountIsName(&'static str), // not actually used, see stage1
+    CountIsNextParam,
+    CountImplied,
+}
+
+#[deriving(Eq)]
+#[allow(missing_doc)]
+#[cfg(not(stage0))]
+pub enum Count<'self> {
+    CountIs(uint),
+    CountIsName(&'self str),
+    CountIsParam(uint),
     CountIsNextParam,
     CountImplied,
 }
@@ -344,10 +378,22 @@ impl<'self> Parser<'self> {
             spec.flags |= 1 << (FlagAlternate as uint);
         }
         // Width and precision
+        let mut havewidth = false;
         if self.consume('0') {
-            spec.flags |= 1 << (FlagSignAwareZeroPad as uint);
+            // small ambiguity with '0$' as a format string. In theory this is a
+            // '0' flag and then an ill-formatted format string with just a '$'
+            // and no count, but this is better if we instead interpret this as
+            // no '0' flag and '0$' as the width instead.
+            if self.consume('$') {
+                spec.width = CountIsParam(0);
+                havewidth = true;
+            } else {
+                spec.flags |= 1 << (FlagSignAwareZeroPad as uint);
+            }
+        }
+        if !havewidth {
+            spec.width = self.count();
         }
-        spec.width = self.count();
         if self.consume('.') {
             if self.consume('*') {
                 spec.precision = CountIsNextParam;
@@ -548,6 +594,7 @@ impl<'self> Parser<'self> {
     /// Parses a Count parameter at the current position. This does not check
     /// for 'CountIsNextParam' because that is only used in precision, not
     /// width.
+    #[cfg(stage0)]
     fn count(&mut self) -> Count {
         match self.integer() {
             Some(i) => {
@@ -560,6 +607,30 @@ impl<'self> Parser<'self> {
             None => { CountImplied }
         }
     }
+    #[cfg(not(stage0))]
+    fn count(&mut self) -> Count<'self> {
+        match self.integer() {
+            Some(i) => {
+                if self.consume('$') {
+                    CountIsParam(i)
+                } else {
+                    CountIs(i)
+                }
+            }
+            None => {
+                let tmp = self.cur.clone();
+                match self.word() {
+                    word if word.len() > 0 && self.consume('$') => {
+                        CountIsName(word)
+                    }
+                    _ => {
+                        self.cur = tmp;
+                        CountImplied
+                    }
+                }
+            }
+        }
+    }
 
     /// Parses a word starting at the current position. A word is considered to
     /// be an alphabetic character followed by any number of alphanumeric
@@ -783,6 +854,18 @@ mod tests {
             },
             method: None,
         })]);
+        same("{:a$.b$s}", ~[Argument(Argument {
+            position: ArgumentNext,
+            format: FormatSpec {
+                fill: None,
+                align: AlignUnknown,
+                flags: 0,
+                precision: CountIsName("b"),
+                width: CountIsName("a"),
+                ty: "s",
+            },
+            method: None,
+        })]);
     }
     #[test]
     fn format_flags() {
diff --git a/src/libstd/fmt/rt.rs b/src/libstd/fmt/rt.rs
index 90763836fc6..063d712dfa9 100644
--- a/src/libstd/fmt/rt.rs
+++ b/src/libstd/fmt/rt.rs
@@ -34,6 +34,7 @@ pub struct Argument<'self> {
     method: Option<&'self Method<'self>>
 }
 
+#[cfg(stage0)]
 pub struct FormatSpec {
     fill: char,
     align: parse::Alignment,
@@ -42,6 +43,20 @@ pub struct FormatSpec {
     width: parse::Count,
 }
 
+#[cfg(not(stage0))]
+pub struct FormatSpec {
+    fill: char,
+    align: parse::Alignment,
+    flags: uint,
+    precision: Count,
+    width: Count,
+}
+
+#[cfg(not(stage0))]
+pub enum Count {
+    CountIs(uint), CountIsParam(uint), CountIsNextParam, CountImplied,
+}
+
 pub enum Position {
     ArgumentNext, ArgumentIs(uint)
 }