<commit_before>use std::io::prelude::*;

use util::{ReadExt, WriteExt};
use tls_result::TlsResult;

pub trait TlsItem {
    fn tls_write<W: WriteExt>(&self, writer: &mut W) -> TlsResult<()>;
    fn tls_read<R: ReadExt>(reader: &mut R) -> TlsResult<Self>;
    fn tls_size(&self) -> u64;
}

macro_rules! tls_primitive {
    ($t:ident) => (
        impl TlsItem for $t {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                stry_write_num!($t, writer, *self);
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$t> {
                let u = stry_read_num!($t, reader);
                Ok(u)
            }

            fn tls_size(&self) -> u64 { num_size!($t) }
        }
    )
}

tls_primitive!(u8);
tls_primitive!(u16);
tls_primitive!(u32);

macro_rules! tls_struct {
    (
        struct $name:ident {
            $(
                $item:ident: $t:ty
            ),+
        }
    ) => (
        pub struct $name {
            $(
                pub $item: $t,
            )+
        }

        impl TlsItem for $name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                $(
                    try!(self.$item.tls_write(writer));
                )+

                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$name> {
                $(
                    let $item: $t = try!(TlsItem::tls_read(reader));
                )+

                let result = $name {
                    $(
                        $item: $item,
                    )+
                };
                Ok(result)
            }

            fn tls_size(&self) -> u64 {
                let mut size = 0;
                $(
                    size += self.$item.tls_size();
                )+

                size
            }
        }
    )
}

macro_rules! tls_enum {
    (
        $repr_ty:ident,
        $(#[$a:meta])*
        enum $name:ident {
            $(
                $item:ident($n:expr)
            ),+
        }
    ) => (
        enum_from_primitive! {
            #[allow(non_camel_case_types)]
            #[derive(Copy, Clone, PartialEq)]
            $(#[$a])*
            pub enum $name {
                $(
                    $item = $n,
                )+
            }
        }

        impl TlsItem for $name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                stry_write_num!($repr_ty, writer, *self);
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$name> {
                let num = stry_read_num!($repr_ty, reader) as u64;
                let n: Option<$name> = ::num::traits::FromPrimitive::from_u64(num);
                match n {
                    Some(n) => Ok(n),
                    None => tls_err!(::tls_result::TlsErrorKind::DecodeError,
                                     "unexpected number: {}", num),
                }
            }

            fn tls_size(&self) -> u64 {
                num_size!($repr_ty)
            }
        }
    )
}

// usage:
// struct {
//     Type type;
//     "opaque" {
//         select (type) {
//             case TypeVariant1:
//                 ...
//             case TypeVariant2:
//                 ...
//         }
//     }
// } Struct;
macro_rules! tls_enum_struct {
    (
        $repr_ty:ident,
        $(#[$a:meta])*
        enum $enum_name:ident {
            $(
                $name:ident($body_ty:ident) = $num:tt // $num: integer literal
            ),+
        }
    ) => (
        #[allow(non_camel_case_types)]
        $(#[$a])*
        pub enum $enum_name {
            $(
                $name($body_ty),
            )+
        }

        impl TlsItem for $enum_name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                match *self {
                    $(
                        $enum_name::$name(ref body) => {
                            stry_write_num!($repr_ty, writer, tt_to_expr!($num));
                            try!(body.tls_write(writer));
                        }
                    )+
                }
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$enum_name> {
                let num = stry_read_num!($repr_ty, reader);
                match num {
                    $(
                        tt_to_pat!($num) => {
                            let body: $body_ty = try!(TlsItem::tls_read(reader));
                            Ok($enum_name::$name(body))
                        }
                    )+
                    _ => return tls_err!(::tls_result::TlsErrorKind::DecodeError,
                                         "unexpected value: {}", num),
                }
            }

            fn tls_size(&self) -> u64 {
                let prefix_size = num_size!($repr_ty);
                let body_size = match *self {
                    $(
                        $enum_name::$name(ref body) => body.tls_size(),
                    )+
                };
                prefix_size + body_size
            }
        }
    )
}

// fixed-sized u8/opaque array
macro_rules! tls_array {
    ($name:ident = [u8, ..$n:expr]) => (
        pub struct $name(Vec<u8>);

        impl $name {
            pub fn new(v: Vec<u8>) -> $crate::tls_result::TlsResult<$name> {
                let n: usize = $n;
                let len = v.len();
                if len != n {
                    return tls_err!($crate::tls_result::TlsErrorKind::InternalError,
                                    "bad size: {} != {}", len, n);
                } else {
                    Ok($name(v))
                }
            }
        }

        impl TlsItem for $name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> $crate::tls_result::TlsResult<()> {
                try!(writer.write(&self.0));
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> $crate::tls_result::TlsResult<$name> {
                let data = try!(reader.read_exact($n));
                Ok($name(data))
            }

            fn tls_size(&self) -> u64 {
                $n
            }
        }

        impl ::std::ops::Deref for $name {
            type Target = [u8];
            fn deref<'a>(&'a self) -> &'a [u8] {
                &self.0
            }
        }
    )
}

macro_rules! tls_vec {
    // $item_ty must implement TlsItem
    ($name:ident = $item_ty:ident($size_min:expr, $size_max:expr)) => (
        pub struct $name(Vec<$item_ty>);
        impl $name {
            pub fn new(v: Vec<$item_ty>) -> $crate::tls_result::TlsResult<$name> {
                #![allow(unused_comparisons)] // disable warnings for e.g. `size < 0`

                let size_min: u64 = $size_min;
                let size_max: u64 = $size_max;

                let ret = $name(v);
                let size: u64 = ret.data_size();
                if size < size_min {
                    return tls_err!($crate::tls_result::TlsErrorKind::DecodeError,
                                    "bad size: {} < {}",
                                    size,
                                    size_min);
                } else if size > size_max {
                    return tls_err!($crate::tls_result::TlsErrorKind::DecodeError,
                    "bad size: {} > {}",
                    size,
                    size_max);
                } else {
                    Ok(ret)
                }
            }

            pub fn unwrap(self) -> Vec<$item_ty> {
                let $name(data) = self;
                data
            }

            fn data_size(&self) -> u64 {
                let mut size = 0u64;
                for item in (**self).iter() {
                    size += item.tls_size();
                }
                size
            }
        }

        impl TlsItem for $name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                let len = self.data_size();

                let size_max: u64 = $size_max;

                if size_max < 1 << 8 {
                    stry_write_num!(u8, writer, len);
                } else if size_max < 1 << 16 {
                    stry_write_num!(u16, writer, len);
                } else if size_max < 1 << 24 {
                    stry_write_num!(u24, writer, len);
                } else if size_max < 1 << 32 {
                    stry_write_num!(u32, writer, len);
                } else {
                    stry_write_num!(u64, writer, len);
                }

                for item in (**self).iter() {
                    try!(item.tls_write(writer));
                }

                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$name> {
                let size_max: u64 = $size_max;

                let self_size = if size_max < 1 << 8 {
                    (stry_read_num!(u8, reader)) as u64
                } else if size_max < 1 << 16 {
                    (stry_read_num!(u16, reader)) as u64
                } else if size_max < 1 << 24 {
                    (stry_read_num!(u24, reader)) as u64
                } else if size_max < 1 << 32 {
                    (stry_read_num!(u32, reader)) as u64
                } else {
                    (stry_read_num!(u64, reader)) as u64
                };

                let mut items_size = 0u64;
                let mut items = Vec::new();
                while items_size < self_size {
                    let item: $item_ty = try!(TlsItem::tls_read(reader));
                    items_size += item.tls_size();
                    items.push(item);
                }
                if items_size != self_size {
                    return tls_err!(::tls_result::TlsErrorKind::DecodeError,
                                    "wrong size: {} expected, {} found",
                                    self_size,
                                    items_size);
                }

                $name::new(items)
            }

            fn tls_size(&self) -> u64 {
                let mut size = 0;

                let size_max: u64 = $size_max;

                if size_max < 1 << 8 {
                    size += 1;
                } else if size_max < 1 << 16 {
                    size += 2;
                } else if size_max < 1 << 24 {
                    size += 3;
                } else if size_max < 1 << 32 {
                    size += 4;
                } else {
                    size += 8;
                }

                size += self.data_size();
                size
            }
        }

        impl ::std::ops::Deref for $name {
            type Target = [$item_ty];
            fn deref<'a>(&'a self) -> &'a [$item_ty] {
                &self.0
            }
        }
    )
}

// this only works when the item is at the last
macro_rules! tls_option {
    ($t:ty) => (
        impl TlsItem for Option<$t> {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                match *self {
                    Some(ref data) => {
                        try!(data.tls_write(writer));
                    }
                    None => {}
                }
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<Option<$t>> {
                let mut rest = vec![];
                let len = try!(reader.read_to_end(&mut rest));
                if len == 0 {
                    return Ok(None);
                }

                let mut rest_reader = ::std::io::Cursor::new(rest);
                let extensions: $t = try!(TlsItem::tls_read(&mut rest_reader));
                Ok(Some(extensions))
            }

            fn tls_size(&self) -> u64 {
                match *self {
                    Some(ref data) => data.tls_size(),
                    None => 0,
                }
            }
        }
    )
}

// for macros
pub struct DummyItem;

impl TlsItem for DummyItem {
    fn tls_write<W: WriteExt>(&self, _writer: &mut W) -> TlsResult<()> { Ok(()) }
    fn tls_read<R: ReadExt>(_reader: &mut R) -> TlsResult<DummyItem> { Ok(DummyItem) }
    fn tls_size(&self) -> u64 { 0 }
}

// it is assumed that the data is at the end of stream. (calls `Read.read_to_end()`)
pub struct ObscureData(Vec<u8>);

impl TlsItem for ObscureData {
    fn tls_write<W: WriteExt>(&self, writer: &mut W) -> TlsResult<()> {
        try!(writer.write_all(&self.0));
        Ok(())
    }

    fn tls_read<R: ReadExt>(reader: &mut R) -> TlsResult<ObscureData> {
        let mut data = vec![];
        let _len = try!(reader.read_to_end(&mut data));
        Ok(ObscureData(data))
    }

    fn tls_size(&self) -> u64 { self.0.len() as u64 }
}

impl ObscureData {
    pub fn new(data: Vec<u8>) -> ObscureData {
        ObscureData(data)
    }

    pub fn unwrap(self) -> Vec<u8> {
        let ObscureData(data) = self;
        data
    }
}

impl ::std::ops::Deref for ObscureData {
    type Target = [u8];
    fn deref<'a>(&'a self) -> &'a [u8] {
        &self.0
    }
}
<commit_msg>tls_item: Implement TlsItem for u64<commit_after>use std::io::prelude::*;

use util::{ReadExt, WriteExt};
use tls_result::TlsResult;

pub trait TlsItem {
    fn tls_write<W: WriteExt>(&self, writer: &mut W) -> TlsResult<()>;
    fn tls_read<R: ReadExt>(reader: &mut R) -> TlsResult<Self>;
    fn tls_size(&self) -> u64;
}

macro_rules! tls_primitive {
    ($t:ident) => (
        impl TlsItem for $t {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                stry_write_num!($t, writer, *self);
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$t> {
                let u = stry_read_num!($t, reader);
                Ok(u)
            }

            fn tls_size(&self) -> u64 { num_size!($t) }
        }
    )
}

tls_primitive!(u8);
tls_primitive!(u16);
tls_primitive!(u32);
tls_primitive!(u64);

macro_rules! tls_struct {
    (
        struct $name:ident {
            $(
                $item:ident: $t:ty
            ),+
        }
    ) => (
        pub struct $name {
            $(
                pub $item: $t,
            )+
        }

        impl TlsItem for $name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                $(
                    try!(self.$item.tls_write(writer));
                )+

                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$name> {
                $(
                    let $item: $t = try!(TlsItem::tls_read(reader));
                )+

                let result = $name {
                    $(
                        $item: $item,
                    )+
                };
                Ok(result)
            }

            fn tls_size(&self) -> u64 {
                let mut size = 0;
                $(
                    size += self.$item.tls_size();
                )+

                size
            }
        }
    )
}

macro_rules! tls_enum {
    (
        $repr_ty:ident,
        $(#[$a:meta])*
        enum $name:ident {
            $(
                $item:ident($n:expr)
            ),+
        }
    ) => (
        enum_from_primitive! {
            #[allow(non_camel_case_types)]
            #[derive(Copy, Clone, PartialEq)]
            $(#[$a])*
            pub enum $name {
                $(
                    $item = $n,
                )+
            }
        }

        impl TlsItem for $name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                stry_write_num!($repr_ty, writer, *self);
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$name> {
                let num = stry_read_num!($repr_ty, reader) as u64;
                let n: Option<$name> = ::num::traits::FromPrimitive::from_u64(num);
                match n {
                    Some(n) => Ok(n),
                    None => tls_err!(::tls_result::TlsErrorKind::DecodeError,
                                     "unexpected number: {}", num),
                }
            }

            fn tls_size(&self) -> u64 {
                num_size!($repr_ty)
            }
        }
    )
}

// usage:
// struct {
//     Type type;
//     "opaque" {
//         select (type) {
//             case TypeVariant1:
//                 ...
//             case TypeVariant2:
//                 ...
//         }
//     }
// } Struct;
macro_rules! tls_enum_struct {
    (
        $repr_ty:ident,
        $(#[$a:meta])*
        enum $enum_name:ident {
            $(
                $name:ident($body_ty:ident) = $num:tt // $num: integer literal
            ),+
        }
    ) => (
        #[allow(non_camel_case_types)]
        $(#[$a])*
        pub enum $enum_name {
            $(
                $name($body_ty),
            )+
        }

        impl TlsItem for $enum_name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                match *self {
                    $(
                        $enum_name::$name(ref body) => {
                            stry_write_num!($repr_ty, writer, tt_to_expr!($num));
                            try!(body.tls_write(writer));
                        }
                    )+
                }
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$enum_name> {
                let num = stry_read_num!($repr_ty, reader);
                match num {
                    $(
                        tt_to_pat!($num) => {
                            let body: $body_ty = try!(TlsItem::tls_read(reader));
                            Ok($enum_name::$name(body))
                        }
                    )+
                    _ => return tls_err!(::tls_result::TlsErrorKind::DecodeError,
                                         "unexpected value: {}", num),
                }
            }

            fn tls_size(&self) -> u64 {
                let prefix_size = num_size!($repr_ty);
                let body_size = match *self {
                    $(
                        $enum_name::$name(ref body) => body.tls_size(),
                    )+
                };
                prefix_size + body_size
            }
        }
    )
}

// fixed-sized u8/opaque array
macro_rules! tls_array {
    ($name:ident = [u8, ..$n:expr]) => (
        pub struct $name(Vec<u8>);

        impl $name {
            pub fn new(v: Vec<u8>) -> $crate::tls_result::TlsResult<$name> {
                let n: usize = $n;
                let len = v.len();
                if len != n {
                    return tls_err!($crate::tls_result::TlsErrorKind::InternalError,
                                    "bad size: {} != {}", len, n);
                } else {
                    Ok($name(v))
                }
            }
        }

        impl TlsItem for $name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> $crate::tls_result::TlsResult<()> {
                try!(writer.write(&self.0));
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> $crate::tls_result::TlsResult<$name> {
                let data = try!(reader.read_exact($n));
                Ok($name(data))
            }

            fn tls_size(&self) -> u64 {
                $n
            }
        }

        impl ::std::ops::Deref for $name {
            type Target = [u8];
            fn deref<'a>(&'a self) -> &'a [u8] {
                &self.0
            }
        }
    )
}

macro_rules! tls_vec {
    // $item_ty must implement TlsItem
    ($name:ident = $item_ty:ident($size_min:expr, $size_max:expr)) => (
        pub struct $name(Vec<$item_ty>);
        impl $name {
            pub fn new(v: Vec<$item_ty>) -> $crate::tls_result::TlsResult<$name> {
                #![allow(unused_comparisons)] // disable warnings for e.g. `size < 0`

                let size_min: u64 = $size_min;
                let size_max: u64 = $size_max;

                let ret = $name(v);
                let size: u64 = ret.data_size();
                if size < size_min {
                    return tls_err!($crate::tls_result::TlsErrorKind::DecodeError,
                                    "bad size: {} < {}",
                                    size,
                                    size_min);
                } else if size > size_max {
                    return tls_err!($crate::tls_result::TlsErrorKind::DecodeError,
                    "bad size: {} > {}",
                    size,
                    size_max);
                } else {
                    Ok(ret)
                }
            }

            pub fn unwrap(self) -> Vec<$item_ty> {
                let $name(data) = self;
                data
            }

            fn data_size(&self) -> u64 {
                let mut size = 0u64;
                for item in (**self).iter() {
                    size += item.tls_size();
                }
                size
            }
        }

        impl TlsItem for $name {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                let len = self.data_size();

                let size_max: u64 = $size_max;

                if size_max < 1 << 8 {
                    stry_write_num!(u8, writer, len);
                } else if size_max < 1 << 16 {
                    stry_write_num!(u16, writer, len);
                } else if size_max < 1 << 24 {
                    stry_write_num!(u24, writer, len);
                } else if size_max < 1 << 32 {
                    stry_write_num!(u32, writer, len);
                } else {
                    stry_write_num!(u64, writer, len);
                }

                for item in (**self).iter() {
                    try!(item.tls_write(writer));
                }

                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<$name> {
                let size_max: u64 = $size_max;

                let self_size = if size_max < 1 << 8 {
                    (stry_read_num!(u8, reader)) as u64
                } else if size_max < 1 << 16 {
                    (stry_read_num!(u16, reader)) as u64
                } else if size_max < 1 << 24 {
                    (stry_read_num!(u24, reader)) as u64
                } else if size_max < 1 << 32 {
                    (stry_read_num!(u32, reader)) as u64
                } else {
                    (stry_read_num!(u64, reader)) as u64
                };

                let mut items_size = 0u64;
                let mut items = Vec::new();
                while items_size < self_size {
                    let item: $item_ty = try!(TlsItem::tls_read(reader));
                    items_size += item.tls_size();
                    items.push(item);
                }
                if items_size != self_size {
                    return tls_err!(::tls_result::TlsErrorKind::DecodeError,
                                    "wrong size: {} expected, {} found",
                                    self_size,
                                    items_size);
                }

                $name::new(items)
            }

            fn tls_size(&self) -> u64 {
                let mut size = 0;

                let size_max: u64 = $size_max;

                if size_max < 1 << 8 {
                    size += 1;
                } else if size_max < 1 << 16 {
                    size += 2;
                } else if size_max < 1 << 24 {
                    size += 3;
                } else if size_max < 1 << 32 {
                    size += 4;
                } else {
                    size += 8;
                }

                size += self.data_size();
                size
            }
        }

        impl ::std::ops::Deref for $name {
            type Target = [$item_ty];
            fn deref<'a>(&'a self) -> &'a [$item_ty] {
                &self.0
            }
        }
    )
}

// this only works when the item is at the last
macro_rules! tls_option {
    ($t:ty) => (
        impl TlsItem for Option<$t> {
            fn tls_write<W: WriteExt>(&self, writer: &mut W) -> ::tls_result::TlsResult<()> {
                match *self {
                    Some(ref data) => {
                        try!(data.tls_write(writer));
                    }
                    None => {}
                }
                Ok(())
            }

            fn tls_read<R: ReadExt>(reader: &mut R) -> ::tls_result::TlsResult<Option<$t>> {
                let mut rest = vec![];
                let len = try!(reader.read_to_end(&mut rest));
                if len == 0 {
                    return Ok(None);
                }

                let mut rest_reader = ::std::io::Cursor::new(rest);
                let extensions: $t = try!(TlsItem::tls_read(&mut rest_reader));
                Ok(Some(extensions))
            }

            fn tls_size(&self) -> u64 {
                match *self {
                    Some(ref data) => data.tls_size(),
                    None => 0,
                }
            }
        }
    )
}

// for macros
pub struct DummyItem;

impl TlsItem for DummyItem {
    fn tls_write<W: WriteExt>(&self, _writer: &mut W) -> TlsResult<()> { Ok(()) }
    fn tls_read<R: ReadExt>(_reader: &mut R) -> TlsResult<DummyItem> { Ok(DummyItem) }
    fn tls_size(&self) -> u64 { 0 }
}

// it is assumed that the data is at the end of stream. (calls `Read.read_to_end()`)
pub struct ObscureData(Vec<u8>);

impl TlsItem for ObscureData {
    fn tls_write<W: WriteExt>(&self, writer: &mut W) -> TlsResult<()> {
        try!(writer.write_all(&self.0));
        Ok(())
    }

    fn tls_read<R: ReadExt>(reader: &mut R) -> TlsResult<ObscureData> {
        let mut data = vec![];
        let _len = try!(reader.read_to_end(&mut data));
        Ok(ObscureData(data))
    }

    fn tls_size(&self) -> u64 { self.0.len() as u64 }
}

impl ObscureData {
    pub fn new(data: Vec<u8>) -> ObscureData {
        ObscureData(data)
    }

    pub fn unwrap(self) -> Vec<u8> {
        let ObscureData(data) = self;
        data
    }
}

impl ::std::ops::Deref for ObscureData {
    type Target = [u8];
    fn deref<'a>(&'a self) -> &'a [u8] {
        &self.0
    }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Nicholas Juszczak <juszczakn@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::fs;
use std::path::Path;

static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
static OPT_MODE: &str = "mode";
static OPT_PARENTS: &str = "parents";
static OPT_VERBOSE: &str = "verbose";

static ARG_DIRS: &str = "dirs";

fn get_usage() -> String {
    format!("{0} [OPTION]... [USER]", executable!())
}

/**
 * Handles option parsing
 */
pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    // Linux-specific options, not implemented
    // opts.optflag("Z", "context", "set SELinux security context" +
    // " of each created directory to CTX"),
    let matches = App::new(executable!())
        .version(crate_version!())
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(OPT_MODE)
                .short("m")
                .long(OPT_MODE)
                .help("set file mode")
                .default_value("755"),
        )
        .arg(
            Arg::with_name(OPT_PARENTS)
                .short("p")
                .long(OPT_PARENTS)
                .alias("parent")
                .help("make parent directories as needed"),
        )
        .arg(
            Arg::with_name(OPT_VERBOSE)
                .short("v")
                .long(OPT_VERBOSE)
                .help("print a message for each printed directory"),
        )
        .arg(
            Arg::with_name(ARG_DIRS)
                .multiple(true)
                .takes_value(true)
                .min_values(1),
        )
        .get_matches_from(args);

    let dirs: Vec<String> = matches
        .values_of(ARG_DIRS)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    let verbose = matches.is_present(OPT_VERBOSE);
    let recursive = matches.is_present(OPT_PARENTS);

    // Translate a ~str in octal form to u16, default to 755
    // Not tested on Windows
    let mode_match = matches.value_of(OPT_MODE);
    let mode: u16 = match mode_match {
        Some(m) => {
            let res: Option<u16> = u16::from_str_radix(m, 8).ok();
            match res {
                Some(r) => r,
                _ => crash!(1, "no mode given"),
            }
        }
        _ => 0o755_u16,
    };

    exec(dirs, recursive, mode, verbose)
}

/**
 * Create the list of new directories
 */
fn exec(dirs: Vec<String>, recursive: bool, mode: u16, verbose: bool) -> i32 {
    let mut status = 0;
    let empty = Path::new("");
    for dir in &dirs {
        let path = Path::new(dir);
        if !recursive {
            if let Some(parent) = path.parent() {
                if parent != empty && !parent.exists() {
                    show_error!(
                        "cannot create directory '{}': No such file or directory",
                        path.display()
                    );
                    status = 1;
                    continue;
                }
            }
        }
        status |= mkdir(path, recursive, mode, verbose);
    }
    status
}

/**
 * Wrapper to catch errors, return 1 if failed
 */
fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> i32 {
    let create_dir = if recursive {
        fs::create_dir_all
    } else {
        fs::create_dir
    };
    if let Err(e) = create_dir(path) {
        show_error!("{}: {}", path.display(), e.to_string());
        return 1;
    }

    if verbose {
        println!("{}: created directory '{}'", executable!(), path.display());
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn chmod(path: &Path, mode: u16) -> i32 {
        use std::fs::{set_permissions, Permissions};
        use std::os::unix::fs::PermissionsExt;

        let mode = Permissions::from_mode(u32::from(mode));

        if let Err(err) = set_permissions(path, mode) {
            show_error!("{}: {}", path.display(), err);
            return 1;
        }
        0
    }
    #[cfg(windows)]
    #[allow(unused_variables)]
    fn chmod(path: &Path, mode: u16) -> i32 {
        // chmod on Windows only sets the readonly flag, which isn't even honored on directories
        0
    }
    chmod(path, mode)
}
<commit_msg>mkdir: note that -m is not supported on windows<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Nicholas Juszczak <juszczakn@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::fs;
use std::path::Path;

static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
static OPT_MODE: &str = "mode";
static OPT_PARENTS: &str = "parents";
static OPT_VERBOSE: &str = "verbose";

static ARG_DIRS: &str = "dirs";

fn get_usage() -> String {
    format!("{0} [OPTION]... [USER]", executable!())
}

/**
 * Handles option parsing
 */
pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    // Linux-specific options, not implemented
    // opts.optflag("Z", "context", "set SELinux security context" +
    // " of each created directory to CTX"),
    let matches = App::new(executable!())
        .version(crate_version!())
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(OPT_MODE)
                .short("m")
                .long(OPT_MODE)
                .help("set file mode (not implemented on windows)")
                .default_value("755"),
        )
        .arg(
            Arg::with_name(OPT_PARENTS)
                .short("p")
                .long(OPT_PARENTS)
                .alias("parent")
                .help("make parent directories as needed"),
        )
        .arg(
            Arg::with_name(OPT_VERBOSE)
                .short("v")
                .long(OPT_VERBOSE)
                .help("print a message for each printed directory"),
        )
        .arg(
            Arg::with_name(ARG_DIRS)
                .multiple(true)
                .takes_value(true)
                .min_values(1),
        )
        .get_matches_from(args);

    let dirs: Vec<String> = matches
        .values_of(ARG_DIRS)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    let verbose = matches.is_present(OPT_VERBOSE);
    let recursive = matches.is_present(OPT_PARENTS);

    // Translate a ~str in octal form to u16, default to 755
    // Not tested on Windows
    let mode_match = matches.value_of(OPT_MODE);
    let mode: u16 = match mode_match {
        Some(m) => {
            let res: Option<u16> = u16::from_str_radix(m, 8).ok();
            match res {
                Some(r) => r,
                _ => crash!(1, "no mode given"),
            }
        }
        _ => 0o755_u16,
    };

    exec(dirs, recursive, mode, verbose)
}

/**
 * Create the list of new directories
 */
fn exec(dirs: Vec<String>, recursive: bool, mode: u16, verbose: bool) -> i32 {
    let mut status = 0;
    let empty = Path::new("");
    for dir in &dirs {
        let path = Path::new(dir);
        if !recursive {
            if let Some(parent) = path.parent() {
                if parent != empty && !parent.exists() {
                    show_error!(
                        "cannot create directory '{}': No such file or directory",
                        path.display()
                    );
                    status = 1;
                    continue;
                }
            }
        }
        status |= mkdir(path, recursive, mode, verbose);
    }
    status
}

/**
 * Wrapper to catch errors, return 1 if failed
 */
fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> i32 {
    let create_dir = if recursive {
        fs::create_dir_all
    } else {
        fs::create_dir
    };
    if let Err(e) = create_dir(path) {
        show_error!("{}: {}", path.display(), e.to_string());
        return 1;
    }

    if verbose {
        println!("{}: created directory '{}'", executable!(), path.display());
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn chmod(path: &Path, mode: u16) -> i32 {
        use std::fs::{set_permissions, Permissions};
        use std::os::unix::fs::PermissionsExt;

        let mode = Permissions::from_mode(u32::from(mode));

        if let Err(err) = set_permissions(path, mode) {
            show_error!("{}: {}", path.display(), err);
            return 1;
        }
        0
    }
    #[cfg(windows)]
    #[allow(unused_variables)]
    fn chmod(path: &Path, mode: u16) -> i32 {
        // chmod on Windows only sets the readonly flag, which isn't even honored on directories
        0
    }
    chmod(path, mode)
}
<|endoftext|>


<commit_before>// library ~ (core/bundler file)

// spell-checker:ignore (uucore/uutils) coreopts libc musl utmpx uucore uutils winapi

//## external crates

extern crate wild;

// * feature-gated external crates
#[cfg(feature = "failure")]
extern crate failure;
#[cfg(feature = "failure_derive")]
extern crate failure_derive;
#[cfg(all(feature = "lazy_static", target_os = "linux"))]
extern crate lazy_static;
#[cfg(feature = "nix")]
extern crate nix;
#[cfg(feature = "platform-info")]
extern crate platform_info;

// * feature-gated external crates (re-shared as public internal modules)
#[cfg(feature = "libc")]
pub extern crate libc;
#[cfg(feature = "winapi")]
pub extern crate winapi;

//## internal modules

mod macros; // crate macros (macro_rules-type; exported to `crate::...`)

mod features; // feature-gated code modules
mod mods; // core cross-platform modules

// * cross-platform modules
pub use mods::coreopts;
pub use mods::panic;

// * feature-gated modules
#[cfg(feature = "encoding")]
pub use features::encoding;
#[cfg(feature = "fs")]
pub use features::fs;
#[cfg(feature = "parse_time")]
pub use features::parse_time;
#[cfg(feature = "zero-copy")]
pub use features::zero_copy;

// * (platform-specific) feature-gated modules
// ** non-windows
#[cfg(all(not(windows), feature = "mode"))]
pub use features::mode;
// ** unix-only
#[cfg(all(unix, feature = "entries"))]
pub use features::entries;
#[cfg(all(unix, feature = "process"))]
pub use features::process;
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))]
pub use features::signals;
#[cfg(all(
    unix,
    not(target_os = "fuchsia"),
    not(target_env = "musl"),
    feature = "utmpx"
))]
pub use features::utmpx;
// ** windows-only
#[cfg(all(windows, feature = "wide"))]
pub use features::wide;

//## core functions

// args() ...
pub fn args() -> impl Iterator<Item = String> {
    wild::args()
}
<commit_msg>fix 'edition=2018' module import errors<commit_after>// library ~ (core/bundler file)

// spell-checker:ignore (uucore/uutils) coreopts libc musl utmpx uucore uutils winapi

//## external crates

extern crate wild;

// * feature-gated external crates
#[cfg(feature = "failure")]
extern crate failure;
#[cfg(feature = "failure_derive")]
extern crate failure_derive;
#[cfg(all(feature = "lazy_static", target_os = "linux"))]
extern crate lazy_static;
#[cfg(feature = "nix")]
extern crate nix;
#[cfg(feature = "platform-info")]
extern crate platform_info;

// * feature-gated external crates (re-shared as public internal modules)
#[cfg(feature = "libc")]
pub extern crate libc;
#[cfg(feature = "winapi")]
pub extern crate winapi;

//## internal modules

mod macros; // crate macros (macro_rules-type; exported to `crate::...`)

mod features; // feature-gated code modules
mod mods; // core cross-platform modules

// * cross-platform modules
pub use crate::mods::coreopts;
pub use crate::mods::panic;

// * feature-gated modules
#[cfg(feature = "encoding")]
pub use crate::features::encoding;
#[cfg(feature = "fs")]
pub use crate::features::fs;
#[cfg(feature = "parse_time")]
pub use crate::features::parse_time;
#[cfg(feature = "zero-copy")]
pub use crate::features::zero_copy;

// * (platform-specific) feature-gated modules
// ** non-windows
#[cfg(all(not(windows), feature = "mode"))]
pub use crate::features::mode;
// ** unix-only
#[cfg(all(unix, feature = "entries"))]
pub use crate::features::entries;
#[cfg(all(unix, feature = "process"))]
pub use crate::features::process;
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))]
pub use crate::features::signals;
#[cfg(all(
    unix,
    not(target_os = "fuchsia"),
    not(target_env = "musl"),
    feature = "utmpx"
))]
pub use crate::features::utmpx;
// ** windows-only
#[cfg(all(windows, feature = "wide"))]
pub use crate::features::wide;

//## core functions

// args() ...
pub fn args() -> impl Iterator<Item = String> {
    wild::args()
}
<|endoftext|>


<commit_before>extern crate libc;
use std::intrinsics;
use std::str;
use std::ffi::CStr;
use std::fmt::{Debug, Formatter, Error};

// Using an actual slice is causing issues with auto deref, instead implement a custom iterator and
// drop trait
pub struct Instructions {
    ptr: *const Insn,
    len: isize,
}

impl Instructions {
    // This method really shouldn't be public, but it was unclear how to make it visible in lib.rs
    // but not globally visible.
    pub fn from_raw_parts(ptr: *const Insn, len: isize) -> Instructions {
        Instructions {
            ptr: ptr,
            len: len,
        }
    }

    pub fn len(&self) -> isize {
        self.len
    }

    pub fn iter(&self) -> InstructionIterator {
        InstructionIterator { insns: &self, cur: 0 }
    }
}

pub struct InstructionIterator<'a> {
    insns: &'a Instructions,
    cur: isize,
}

impl<'a> Iterator for InstructionIterator<'a> {
    type Item = Insn;

    fn next(&mut self) -> Option<Insn> {
        if self.cur == self.insns.len {
            None
        } else {
            let obj = unsafe { intrinsics::offset(self.insns.ptr, self.cur) };
            self.cur += 1;
            Some(unsafe { *obj })
        }
    }
}

#[repr(C)]
#[derive(Copy)]
pub struct Insn {
    id: ::libc::c_uint,
    pub address: u64,
    pub size: u16,
    pub bytes: [u8; 16usize],
    pub mnemonic: [::libc::c_char; 32usize],
    pub op_str: [::libc::c_char; 160usize],
    detail: *mut libc::c_void, // Opaque cs_detail
}

impl Insn {
    pub fn mnemonic(&self) -> Option<&str> {
        let cstr = unsafe { CStr::from_ptr(self.mnemonic.as_ptr()) };
        str::from_utf8(cstr.to_bytes()).ok()
    }

    pub fn op_str(&self) -> Option<&str> {
        let cstr = unsafe { CStr::from_ptr(self.op_str.as_ptr()) };
        str::from_utf8(cstr.to_bytes()).ok()
    }
}

impl Debug for Insn {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        fmt.debug_struct("Insn")
            .field("address", &self.address)
            .field("size", &self.size)
            .field("mnemonic", &self.mnemonic())
            .field("op_str", &self.op_str())
            .finish()
    }
}
<commit_msg>Fixes for rust beta<commit_after>extern crate libc;
use std::intrinsics;
use std::ptr;
use std::str;
use std::ffi::CStr;
use std::fmt::{Debug, Formatter, Error};

// Using an actual slice is causing issues with auto deref, instead implement a custom iterator and
// drop trait
pub struct Instructions {
    ptr: *const Insn,
    len: isize,
}

impl Instructions {
    // This method really shouldn't be public, but it was unclear how to make it visible in lib.rs
    // but not globally visible.
    pub fn from_raw_parts(ptr: *const Insn, len: isize) -> Instructions {
        Instructions {
            ptr: ptr,
            len: len,
        }
    }

    pub fn len(&self) -> isize {
        self.len
    }

    pub fn iter(&self) -> InstructionIterator {
        InstructionIterator { insns: &self, cur: 0 }
    }
}

pub struct InstructionIterator<'a> {
    insns: &'a Instructions,
    cur: isize,
}

impl<'a> Iterator for InstructionIterator<'a> {
    type Item = Insn;

    fn next(&mut self) -> Option<Insn> {
        if self.cur == self.insns.len {
            None
        } else {
            let obj = unsafe { intrinsics::offset(self.insns.ptr, self.cur) };
            self.cur += 1;
            Some(unsafe { ptr::read(obj) })
        }
    }
}

#[repr(C)]
pub struct Insn {
    id: ::libc::c_uint,
    pub address: u64,
    pub size: u16,
    pub bytes: [u8; 16usize],
    pub mnemonic: [::libc::c_char; 32usize],
    pub op_str: [::libc::c_char; 160usize],
    detail: *mut libc::c_void, // Opaque cs_detail
}

impl Insn {
    pub fn mnemonic(&self) -> Option<&str> {
        let cstr = unsafe { CStr::from_ptr(self.mnemonic.as_ptr()) };
        str::from_utf8(cstr.to_bytes()).ok()
    }

    pub fn op_str(&self) -> Option<&str> {
        let cstr = unsafe { CStr::from_ptr(self.op_str.as_ptr()) };
        str::from_utf8(cstr.to_bytes()).ok()
    }
}

impl Debug for Insn {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        fmt.debug_struct("Insn")
            .field("address", &self.address)
            .field("size", &self.size)
            .field("mnemonic", &self.mnemonic())
            .field("op_str", &self.op_str())
            .finish()
    }
}
<|endoftext|>


<commit_before>use header::*;
use instructions::Instruction as Instr;
use num::FromPrimitive;

#[derive(Debug, Default)]
pub struct Interpreter {
    // File data
    header: RaptorHeader,
    bytecode: Vec<u8>,

    // Runtime stuff
    stack: Vec<i32>,
    memory: Vec<i32>,
    program_counter: usize,
}

impl Interpreter {
    pub fn new(mut data: Vec<u8>) -> Interpreter {
        let mut i = Interpreter {
            header: read_header(&data),
            bytecode: data.drain(HEADER_SIZE..).collect(),
            stack: Vec::new(),
            memory: Vec::new(),
            program_counter: 0,
        };
        i.memory.resize(i.header.var_count as usize, 0);
        i
    }

    pub fn run(&mut self, options: &::Options) {
        use std::ops::*;

        debug!("Running...");
        debug!("Bytecode: {:?}", self.bytecode);

        let debug = options.debug;

        // Main loop
        // Will break when .next() is None
        while self.program_counter != self.bytecode.len() {
            // info!("PC: {}", program_counter);

            // Use FromPrimitive trait to convert a value to its enum
            let instr = Instr::from_u8(self.bytecode[self.program_counter]);
            self.program_counter += 1;

            if instr.is_none() {
                warn!("Unimplemented instruction: {:04X}", self.bytecode[self.program_counter]);
                continue;
            }

            let instr = instr.unwrap();   // We're sure it's Some here, so unpack it.

            if options.debug {
                debug!("{:?}", instr);
            }

            macro_rules! push {
                ( $x:expr ) => {
                    (self.stack.push($x));
                };
            }
            macro_rules! pop {
                () => {
                    (self.stack.pop());
                };
            }
            macro_rules! operation {
                ($op:ident) => ({
                    let final_length: usize = self.stack.len().saturating_sub(2);
                    let val = self.stack.drain(final_length..).fold(
                        0, |acc, x| acc.$op(x)
                    );
                    self.stack.push(val);
                })
            }
            // TODO: More macros, less code

            match instr {
                Instr::NOP => {},
                Instr::HALT => {
                    println!("HALT issued, stopped execution.");
                    if (debug) {
                        debug!("STACK:\n{:?}", self.stack);
                        debug!("MEMORY:\n{:?}", self.memory);
                    }
                },
                Instr::ICONST => {
                    let b = self.get_next_4_bytes() as i32;
                    push!(b);
                },
                Instr::POP => { pop!(); },
                Instr::ADD =>       { operation!(add);    },
                Instr::SUB =>       { operation!(sub);    },
                Instr::MULTIPLY =>  { operation!(mul);    },
                Instr::DIVIDE =>    { operation!(div);    },
                Instr::MODULUS =>   { operation!(rem);    },
                Instr::RSHIFT =>    { operation!(shl);    },
                Instr::LSHIFT =>    { operation!(shr);    },
                Instr::AND =>       { operation!(bitand); },
                Instr::OR =>        { operation!(bitor);  },
                Instr::NOT =>       {
                    let val = self.stack.pop().unwrap();
                    push!(val.not());
                },
                Instr::COMP => {
                    let a = self.stack.pop(); let b = self.stack.pop();
                    self.stack.push(if a > b {1} else if a < b {-1} else {0});
                },
                Instr::COMP_LT => {
                    let a = self.stack.pop(); let b = self.stack.pop();
                    self.stack.push(if a > b {1} else {0});
                },
                Instr::COMP_EQ => {
                    let a = self.stack.pop(); let b = self.stack.pop();
                    self.stack.push(if a == b {1} else {0});
                },
                Instr::COMP_GT => {
                    let a = self.stack.pop(); let b = self.stack.pop();
                    self.stack.push(if a < b {1} else {0});
                },
                // TODO: Refactor RELJUMPs
                Instr::RELJUMP => {
                    let offset = self.get_next_4_bytes() as i32;
                    // Need this if because you can't have negative usizes
                    if offset > 0 {
                        if debug {debug!("RELJUMP: {}", offset);}
                        self.program_counter += offset as usize;
                    } else if offset < 0 {
                        if debug {debug!("RELJUMP: {}", offset);}
                        self.program_counter -= (-offset) as usize;
                    } else {
                        warn!("Invalid reljump offset: 0");
                    }
                },
                Instr::RELJUMP_GT => {},    // TODO
                Instr::RELJUMP_LT => {},    // TODO
                Instr::RELJUMP_EQ => {
                    let offset = self.get_next_4_bytes() as i32;
                    let top = self.stack.pop().unwrap();
                    if top == 0 {
                        if offset > 0 {
                            if debug {debug!("RELJUMP: {}", offset);}
                            self.program_counter += offset as usize;
                        } else if offset < 0 {
                            if debug {debug!("RELJUMP: {}", offset);}
                            self.program_counter -= (-offset) as usize;
                        } else {
                            warn!("Invalid reljump offset: 0");
                        }
                    } else {
                        if debug {debug!("Jump not taken"); }
                    }
                },
                Instr::STORE => {
                    let index = self.get_next_4_bytes() as usize;
                    self.memory[index] = self.stack.pop().unwrap();
                },
                Instr::LOAD => {
                    let index = self.get_next_4_bytes() as usize;
                    self.stack.push(self.memory[index]);
                },
                Instr::PRINT => {
                    println!("PRINT: {}", self.stack.pop().unwrap());
                },
                Instr::DUMP_STACK => {
                    println!("{:?}", self.stack);
                },
                Instr::DUMP_GLOBALS => {
                    println!("{:?}", self.memory);},
            }
        }
    }

    fn get_next_4_bytes(&mut self) -> u32 {
        let val = (self.bytecode[self.program_counter] as u32) << 24 |
                  (self.bytecode[self.program_counter + 1] as u32) << 16 |
                  (self.bytecode[self.program_counter + 2] as u32) << 8 |
                  (self.bytecode[self.program_counter + 3] as u32);
        self.program_counter += 4;
        debug!("get_next_4_bytes: 0x{:04X}", val);
        val
    }
}

// TODO: Add tests
<commit_msg>Fixed Stack & memory dumping formatting to be consistent<commit_after>use header::*;
use instructions::Instruction as Instr;
use num::FromPrimitive;

#[derive(Debug, Default)]
pub struct Interpreter {
    // File data
    header: RaptorHeader,
    bytecode: Vec<u8>,

    // Runtime stuff
    stack: Vec<i32>,
    memory: Vec<i32>,
    program_counter: usize,
}

impl Interpreter {
    pub fn new(mut data: Vec<u8>) -> Interpreter {
        let mut i = Interpreter {
            header: read_header(&data),
            bytecode: data.drain(HEADER_SIZE..).collect(),
            stack: Vec::new(),
            memory: Vec::new(),
            program_counter: 0,
        };
        i.memory.resize(i.header.var_count as usize, 0);
        i
    }

    pub fn run(&mut self, options: &::Options) {
        use std::ops::*;

        debug!("Running...");
        debug!("Bytecode: {:?}", self.bytecode);

        let debug = options.debug;

        // Main loop
        // Will break when .next() is None
        while self.program_counter != self.bytecode.len() {
            // info!("PC: {}", program_counter);

            // Use FromPrimitive trait to convert a value to its enum
            let instr = Instr::from_u8(self.bytecode[self.program_counter]);
            self.program_counter += 1;

            if instr.is_none() {
                warn!("Unimplemented instruction: {:04X}", self.bytecode[self.program_counter]);
                continue;
            }

            let instr = instr.unwrap();   // We're sure it's Some here, so unpack it.

            if options.debug {
                debug!("{:?}", instr);
            }

            macro_rules! push {
                ( $x:expr ) => {
                    (self.stack.push($x));
                };
            }
            macro_rules! pop {
                () => {
                    (self.stack.pop());
                };
            }
            macro_rules! operation {
                ($op:ident) => ({
                    let final_length: usize = self.stack.len().saturating_sub(2);
                    let val = self.stack.drain(final_length..).fold(
                        0, |acc, x| acc.$op(x)
                    );
                    self.stack.push(val);
                })
            }
            // TODO: More macros, less code

            match instr {
                Instr::NOP => {},
                Instr::HALT => {
                    println!("HALT issued, stopped execution.");
                    if debug {
                        debug!("Stack: {:?}", self.stack);
                        debug!("MEMORY: {:?}", self.memory);
                    }
                },
                Instr::ICONST => {
                    let b = self.get_next_4_bytes() as i32;
                    push!(b);
                },
                Instr::POP => { pop!(); },
                Instr::ADD =>       { operation!(add);    },
                Instr::SUB =>       { operation!(sub);    },
                Instr::MULTIPLY =>  { operation!(mul);    },
                Instr::DIVIDE =>    { operation!(div);    },
                Instr::MODULUS =>   { operation!(rem);    },
                Instr::RSHIFT =>    { operation!(shl);    },
                Instr::LSHIFT =>    { operation!(shr);    },
                Instr::AND =>       { operation!(bitand); },
                Instr::OR =>        { operation!(bitor);  },
                Instr::NOT =>       {
                    let val = self.stack.pop().unwrap();
                    push!(val.not());
                },
                Instr::COMP => {
                    let a = self.stack.pop(); let b = self.stack.pop();
                    self.stack.push(if a > b {1} else if a < b {-1} else {0});
                },
                Instr::COMP_LT => {
                    let a = self.stack.pop(); let b = self.stack.pop();
                    self.stack.push(if a > b {1} else {0});
                },
                Instr::COMP_EQ => {
                    let a = self.stack.pop(); let b = self.stack.pop();
                    self.stack.push(if a == b {1} else {0});
                },
                Instr::COMP_GT => {
                    let a = self.stack.pop(); let b = self.stack.pop();
                    self.stack.push(if a < b {1} else {0});
                },
                // TODO: Refactor RELJUMPs
                Instr::RELJUMP => {
                    let offset = self.get_next_4_bytes() as i32;
                    // Need this if because you can't have negative usizes
                    if offset > 0 {
                        if debug {debug!("RELJUMP: {}", offset);}
                        self.program_counter += offset as usize;
                    } else if offset < 0 {
                        if debug {debug!("RELJUMP: {}", offset);}
                        self.program_counter -= (-offset) as usize;
                    } else {
                        warn!("Invalid reljump offset: 0");
                    }
                },
                Instr::RELJUMP_GT => {},    // TODO
                Instr::RELJUMP_LT => {},    // TODO
                Instr::RELJUMP_EQ => {
                    let offset = self.get_next_4_bytes() as i32;
                    let top = self.stack.pop().unwrap();
                    if top == 0 {
                        if offset > 0 {
                            if debug {debug!("RELJUMP: {}", offset);}
                            self.program_counter += offset as usize;
                        } else if offset < 0 {
                            if debug {debug!("RELJUMP: {}", offset);}
                            self.program_counter -= (-offset) as usize;
                        } else {
                            warn!("Invalid reljump offset: 0");
                        }
                    } else {
                        if debug {debug!("Jump not taken"); }
                    }
                },
                Instr::STORE => {
                    let index = self.get_next_4_bytes() as usize;
                    self.memory[index] = self.stack.pop().unwrap();
                },
                Instr::LOAD => {
                    let index = self.get_next_4_bytes() as usize;
                    self.stack.push(self.memory[index]);
                },
                Instr::PRINT => {
                    println!("PRINT: {}", self.stack.pop().unwrap());
                },
                Instr::DUMP_STACK => {
                    println!("{:?}", self.stack);
                },
                Instr::DUMP_GLOBALS => {
                    println!("{:?}", self.memory);},
            }
        }
    }

    fn get_next_4_bytes(&mut self) -> u32 {
        let val = (self.bytecode[self.program_counter] as u32) << 24 |
                  (self.bytecode[self.program_counter + 1] as u32) << 16 |
                  (self.bytecode[self.program_counter + 2] as u32) << 8 |
                  (self.bytecode[self.program_counter + 3] as u32);
        self.program_counter += 4;
        debug!("get_next_4_bytes: 0x{:04X}", val);
        val
    }
}

// TODO: Add tests
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::sync::{Mutex, Arc};

use input::Input;
use keyboard::Key;
use view::View;
use frontends::{Frontend, EditorEvent};
use modes::{Mode, ModeType, InsertMode, NormalMode};
use overlay::{Overlay, OverlayEvent};
use buffer::Buffer;
use command::Command;
use command::{Action, BuilderEvent, Operation, Instruction};

/// The main Editor structure
///
/// This is the top-most structure in Iota.
pub struct Editor<'e, T: Frontend> {
    pub buffers: Vec<Arc<Mutex<Buffer>>>,
    view: View,
    running: bool,
    frontend: T,
    mode: Box<Mode + 'e>,
}

impl<'e, T: Frontend> Editor<'e, T> {
    /// Create a new Editor instance
    pub fn new(source: Input, mode: Box<Mode + 'e>, frontend: T) -> Editor<'e, T> {
        let height = frontend.get_window_height();
        let width = frontend.get_window_width();

        let mut buffers = Vec::new();
        let mut buffer = match source {
            Input::Filename(path) => {
                match path {
                    Some(s) => {
                        let file_name = &*s;
                        Buffer::new_from_file(PathBuf::new(file_name))
                    },
                    None    => Buffer::new(),
                }
            },
            Input::Stdin(reader) => {
                Buffer::new_from_reader(reader)
            },
        };

        buffers.push(Arc::new(Mutex::new(buffer)));

        let view = View::new(buffers[0].clone(), width, height);
        Editor {
            buffers: buffers,
            view: view,
            running: true,
            frontend: frontend,
            mode: mode,
        }
    }

    /// Handle key events
    ///
    /// Key events can be handled in an Overlay, OR in the current Mode.
    ///
    /// If there is an active Overlay, the key event is sent there, which gives
    /// back an OverlayEvent. We then parse this OverlayEvent and determine if
    /// the Overlay is finished and can be cleared. The response from the
    /// Overlay is then converted to a Command and sent off to be handled.
    ///
    /// If there is no active Overlay, the key event is sent to the current
    /// Mode, which returns a Command which we dispatch to handle_command.
    fn handle_key_event(&mut self, key: Option<Key>) {
        let key = match key {
            Some(k) => k,
            None => return
        };

        let mut remove_overlay = false;
        let command = match self.view.overlay {
            Overlay::None => self.mode.handle_key_event(key),
            _             => {
                let event = self.view.overlay.handle_key_event(key);
                match event {
                    OverlayEvent::Finished(response) => {
                        remove_overlay = true;
                        self.handle_overlay_response(response)
                    }

                    _ => { BuilderEvent::Incomplete }
                }
            }
        };

        if remove_overlay {
            self.view.overlay = Overlay::None;
            self.view.clear(&mut self.frontend);
        }

        if let BuilderEvent::Complete(c) = command {
            self.handle_command(c);
        }
    }

    /// Translate the response from an Overlay to a Command wrapped in a BuilderEvent
    ///
    /// In most cases, we will just want to convert the response directly to
    /// a Command, however in some cases we will want to perform other actions
    /// first, such as in the case of Overlay::SavePrompt.
    fn handle_overlay_response(&mut self, response: Option<String>) -> BuilderEvent {
        // FIXME: This entire method neext to be updated
        match response {
            Some(data) => {
                match self.view.overlay {

                    // FIXME: this is just a temporary fix
                    Overlay::Prompt { ref data, .. } => {
                        match &**data {
                            // FIXME: need to find a better system for these commands
                            //        They should be chainable
                            //          ie: wq - save & quit
                            //        They should also take arguments
                            //          ie w file.txt - write buffer to file.txt
                            "q" | "quit" => BuilderEvent::Complete(Command::exit_editor()),
                            "w" | "write" => BuilderEvent::Complete(Command::save_buffer()),

                            _ => BuilderEvent::Incomplete
                        }
                    }

                    Overlay::SavePrompt { .. } => {
                        let path = PathBuf::new(&*data);
                        self.view.buffer.lock().unwrap().file_path = Some(path);
                        BuilderEvent::Complete(Command::save_buffer())
                    }

                    Overlay::SelectFile { .. } => {
                        let path = PathBuf::new(data);
                        let buffer = Arc::new(Mutex::new(Buffer::new_from_file(path)));
                        self.buffers.push(buffer.clone());
                        self.view.set_buffer(buffer.clone());
                        self.view.clear(&mut self.frontend);
                        BuilderEvent::Complete(Command::noop())
                    }

                    _ => BuilderEvent::Incomplete,
                }
            }
            None => BuilderEvent::Incomplete
        }
    }

    /// Handle resize events
    ///
    /// width and height represent the new height of the window.
    fn handle_resize_event(&mut self, width: usize, height: usize) {
        self.view.resize(width, height);
    }

    /// Draw the current view to the frontend
    fn draw(&mut self) {
        self.view.draw(&mut self.frontend);
    }

    /// Handle the given command, performing the associated action
    fn handle_command(&mut self, command: Command) {
        let repeat = if command.number > 0 {
            command.number
        } else { 1 };
        for _ in 0..repeat {
            match command.action {
                Action::Instruction(i) => self.handle_instruction(i, command),
                Action::Operation(o) => self.handle_operation(o, command),
            }
        }
    }

    fn handle_instruction(&mut self, instruction: Instruction, command: Command) {
        match instruction {
            Instruction::SaveBuffer => { self.view.try_save_buffer() }
            Instruction::ExitEditor => { self.running = false; }
            Instruction::SetMark(mark) => {
                if let Some(object) = command.object {
                    self.view.move_mark(mark, object)
                }
            }
            Instruction::SetOverlay(overlay_type) => {
                self.view.set_overlay(overlay_type)
            }
            Instruction::SetMode(mode) => {
                match mode {
                    ModeType::Insert => { self.mode = Box::new(InsertMode::new()) }
                    ModeType::Normal => { self.mode = Box::new(NormalMode::new()) }
                }
            }
            Instruction::SwitchToLastBuffer => {
                self.view.switch_last_buffer();
                self.view.clear(&mut self.frontend);
            }

            _ => {}
        }
    }

    fn handle_operation(&mut self, operation: Operation, command: Command) {
        match operation {
            Operation::Insert(c) => {
                for _ in 0..command.number {
                    self.view.insert_char(c)
                }
            }
            Operation::DeleteObject => {
                if let Some(obj) = command.object {
                    self.view.delete_object(obj);
                }
            }
            Operation::DeleteFromMark(m) => {
                if command.object.is_some() {
                    self.view.delete_from_mark_to_object(m, command.object.unwrap())
                }
            }
            Operation::Undo => { self.view.undo() }
            Operation::Redo => { self.view.redo() }
        }
    }

    /// Start Iota!
    pub fn start(&mut self) {
        while self.running {
            self.draw();
            self.frontend.present();
            let event = self.frontend.poll_event();

            match event {
                EditorEvent::KeyEvent(key)         => self.handle_key_event(key),
                EditorEvent::Resize(width, height) => self.handle_resize_event(width, height),

                _ => {}
            }
        }
    }
}
<commit_msg>Make editor.buffers private<commit_after>use std::path::PathBuf;
use std::sync::{Mutex, Arc};

use input::Input;
use keyboard::Key;
use view::View;
use frontends::{Frontend, EditorEvent};
use modes::{Mode, ModeType, InsertMode, NormalMode};
use overlay::{Overlay, OverlayEvent};
use buffer::Buffer;
use command::Command;
use command::{Action, BuilderEvent, Operation, Instruction};

/// The main Editor structure
///
/// This is the top-most structure in Iota.
pub struct Editor<'e, T: Frontend> {
    buffers: Vec<Arc<Mutex<Buffer>>>,
    view: View,
    running: bool,
    frontend: T,
    mode: Box<Mode + 'e>,
}

impl<'e, T: Frontend> Editor<'e, T> {
    /// Create a new Editor instance
    pub fn new(source: Input, mode: Box<Mode + 'e>, frontend: T) -> Editor<'e, T> {
        let height = frontend.get_window_height();
        let width = frontend.get_window_width();

        let mut buffers = Vec::new();
        let mut buffer = match source {
            Input::Filename(path) => {
                match path {
                    Some(s) => {
                        let file_name = &*s;
                        Buffer::new_from_file(PathBuf::new(file_name))
                    },
                    None    => Buffer::new(),
                }
            },
            Input::Stdin(reader) => {
                Buffer::new_from_reader(reader)
            },
        };

        buffers.push(Arc::new(Mutex::new(buffer)));

        let view = View::new(buffers[0].clone(), width, height);
        Editor {
            buffers: buffers,
            view: view,
            running: true,
            frontend: frontend,
            mode: mode,
        }
    }

    /// Handle key events
    ///
    /// Key events can be handled in an Overlay, OR in the current Mode.
    ///
    /// If there is an active Overlay, the key event is sent there, which gives
    /// back an OverlayEvent. We then parse this OverlayEvent and determine if
    /// the Overlay is finished and can be cleared. The response from the
    /// Overlay is then converted to a Command and sent off to be handled.
    ///
    /// If there is no active Overlay, the key event is sent to the current
    /// Mode, which returns a Command which we dispatch to handle_command.
    fn handle_key_event(&mut self, key: Option<Key>) {
        let key = match key {
            Some(k) => k,
            None => return
        };

        let mut remove_overlay = false;
        let command = match self.view.overlay {
            Overlay::None => self.mode.handle_key_event(key),
            _             => {
                let event = self.view.overlay.handle_key_event(key);
                match event {
                    OverlayEvent::Finished(response) => {
                        remove_overlay = true;
                        self.handle_overlay_response(response)
                    }

                    _ => { BuilderEvent::Incomplete }
                }
            }
        };

        if remove_overlay {
            self.view.overlay = Overlay::None;
            self.view.clear(&mut self.frontend);
        }

        if let BuilderEvent::Complete(c) = command {
            self.handle_command(c);
        }
    }

    /// Translate the response from an Overlay to a Command wrapped in a BuilderEvent
    ///
    /// In most cases, we will just want to convert the response directly to
    /// a Command, however in some cases we will want to perform other actions
    /// first, such as in the case of Overlay::SavePrompt.
    fn handle_overlay_response(&mut self, response: Option<String>) -> BuilderEvent {
        // FIXME: This entire method neext to be updated
        match response {
            Some(data) => {
                match self.view.overlay {

                    // FIXME: this is just a temporary fix
                    Overlay::Prompt { ref data, .. } => {
                        match &**data {
                            // FIXME: need to find a better system for these commands
                            //        They should be chainable
                            //          ie: wq - save & quit
                            //        They should also take arguments
                            //          ie w file.txt - write buffer to file.txt
                            "q" | "quit" => BuilderEvent::Complete(Command::exit_editor()),
                            "w" | "write" => BuilderEvent::Complete(Command::save_buffer()),

                            _ => BuilderEvent::Incomplete
                        }
                    }

                    Overlay::SavePrompt { .. } => {
                        let path = PathBuf::new(&*data);
                        self.view.buffer.lock().unwrap().file_path = Some(path);
                        BuilderEvent::Complete(Command::save_buffer())
                    }

                    Overlay::SelectFile { .. } => {
                        let path = PathBuf::new(data);
                        let buffer = Arc::new(Mutex::new(Buffer::new_from_file(path)));
                        self.buffers.push(buffer.clone());
                        self.view.set_buffer(buffer.clone());
                        self.view.clear(&mut self.frontend);
                        BuilderEvent::Complete(Command::noop())
                    }

                    _ => BuilderEvent::Incomplete,
                }
            }
            None => BuilderEvent::Incomplete
        }
    }

    /// Handle resize events
    ///
    /// width and height represent the new height of the window.
    fn handle_resize_event(&mut self, width: usize, height: usize) {
        self.view.resize(width, height);
    }

    /// Draw the current view to the frontend
    fn draw(&mut self) {
        self.view.draw(&mut self.frontend);
    }

    /// Handle the given command, performing the associated action
    fn handle_command(&mut self, command: Command) {
        let repeat = if command.number > 0 {
            command.number
        } else { 1 };
        for _ in 0..repeat {
            match command.action {
                Action::Instruction(i) => self.handle_instruction(i, command),
                Action::Operation(o) => self.handle_operation(o, command),
            }
        }
    }

    fn handle_instruction(&mut self, instruction: Instruction, command: Command) {
        match instruction {
            Instruction::SaveBuffer => { self.view.try_save_buffer() }
            Instruction::ExitEditor => { self.running = false; }
            Instruction::SetMark(mark) => {
                if let Some(object) = command.object {
                    self.view.move_mark(mark, object)
                }
            }
            Instruction::SetOverlay(overlay_type) => {
                self.view.set_overlay(overlay_type)
            }
            Instruction::SetMode(mode) => {
                match mode {
                    ModeType::Insert => { self.mode = Box::new(InsertMode::new()) }
                    ModeType::Normal => { self.mode = Box::new(NormalMode::new()) }
                }
            }
            Instruction::SwitchToLastBuffer => {
                self.view.switch_last_buffer();
                self.view.clear(&mut self.frontend);
            }

            _ => {}
        }
    }

    fn handle_operation(&mut self, operation: Operation, command: Command) {
        match operation {
            Operation::Insert(c) => {
                for _ in 0..command.number {
                    self.view.insert_char(c)
                }
            }
            Operation::DeleteObject => {
                if let Some(obj) = command.object {
                    self.view.delete_object(obj);
                }
            }
            Operation::DeleteFromMark(m) => {
                if command.object.is_some() {
                    self.view.delete_from_mark_to_object(m, command.object.unwrap())
                }
            }
            Operation::Undo => { self.view.undo() }
            Operation::Redo => { self.view.redo() }
        }
    }

    /// Start Iota!
    pub fn start(&mut self) {
        while self.running {
            self.draw();
            self.frontend.present();
            let event = self.frontend.poll_event();

            match event {
                EditorEvent::KeyEvent(key)         => self.handle_key_event(key),
                EditorEvent::Resize(width, height) => self.handle_resize_event(width, height),

                _ => {}
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The HTML5 for Rust Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// 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.

#![crate_name="html5-external-test"]
#![crate_type="bin"]

#![feature(macro_rules)]

extern crate test;
extern crate serialize;
extern crate debug;

extern crate html5;

use std::os;
use std::from_str::FromStr;
use test::test_main;

mod tokenizer;
mod tree_builder;
mod util;

fn main() {
    let src_dir: Path = FromStr::from_str(
        os::getenv("HTML5_SRC_DIR").expect("HTML5_SRC_DIR not set").as_slice()
    ).expect("HTML5_SRC_DIR invalid");

    let mut tests = vec!();

    tests.push_all_move(tokenizer::tests(src_dir.clone()));
    tests.push_all_move(tree_builder::tests(src_dir));

    let args: Vec<String> = os::args().move_iter().collect();
    test_main(args.as_slice(), tests);
}
<commit_msg>Add env vars to control which tests we load<commit_after>// Copyright 2014 The HTML5 for Rust Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// 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.

#![crate_name="html5-external-test"]
#![crate_type="bin"]

#![feature(macro_rules)]

extern crate test;
extern crate serialize;
extern crate debug;

extern crate html5;

use std::os;
use std::from_str::FromStr;
use test::test_main;

mod tokenizer;
mod tree_builder;
mod util;

fn main() {
    let src_dir: Path = FromStr::from_str(
        os::getenv("HTML5_SRC_DIR").expect("HTML5_SRC_DIR not set").as_slice()
    ).expect("HTML5_SRC_DIR invalid");

    let mut tests = vec!();

    if os::getenv("HTML5_NO_TOK_TEST").is_none() {
        tests.push_all_move(tokenizer::tests(src_dir.clone()));
    }

    if os::getenv("HTM5_NO_TB_TEST").is_none() {
        tests.push_all_move(tree_builder::tests(src_dir));
    }

    let args: Vec<String> = os::args().move_iter().collect();
    test_main(args.as_slice(), tests);
}
<|endoftext|>