<commit_before>// * This file is part of the uutils coreutils package.
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

// spell-checker:ignore parenb parodd cmspar hupcl cstopb cread clocal crtscts CSIZE
// spell-checker:ignore ignbrk brkint ignpar parmrk inpck istrip inlcr igncr icrnl ixoff ixon iuclc ixany imaxbel iutf
// spell-checker:ignore opost olcuc ocrnl onlcr onocr onlret ofill ofdel nldly crdly tabdly bsdly vtdly ffdly
// spell-checker:ignore isig icanon iexten echoe crterase echok echonl noflsh xcase tostop echoprt prterase echoctl ctlecho echoke crtkill flusho extproc

use crate::Flag;

#[cfg(not(any(
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "ios",
    target_os = "macos",
    target_os = "netbsd",
    target_os = "openbsd"
)))]
use nix::sys::termios::BaudRate;
use nix::sys::termios::{ControlFlags as C, InputFlags as I, LocalFlags as L, OutputFlags as O};

pub const CONTROL_FLAGS: &[Flag<C>] = &[
    Flag::new("parenb", C::PARENB),
    Flag::new("parodd", C::PARODD),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "mips"))
    ))]
    Flag::new("cmspar", C::CMSPAR),
    Flag::new_grouped("cs5", C::CS5, C::CSIZE),
    Flag::new_grouped("cs6", C::CS6, C::CSIZE),
    Flag::new_grouped("cs7", C::CS7, C::CSIZE),
    Flag::new_grouped("cs8", C::CS8, C::CSIZE).sane(),
    Flag::new("hupcl", C::HUPCL),
    Flag::new("cstopb", C::CSTOPB),
    Flag::new("cread", C::CREAD).sane(),
    Flag::new("clocal", C::CLOCAL),
    Flag::new("crtscts", C::CRTSCTS),
];

pub const INPUT_FLAGS: &[Flag<I>] = &[
    Flag::new("ignbrk", I::IGNBRK),
    Flag::new("brkint", I::BRKINT).sane(),
    Flag::new("ignpar", I::IGNPAR),
    Flag::new("parmrk", I::PARMRK),
    Flag::new("inpck", I::INPCK),
    Flag::new("istrip", I::ISTRIP),
    Flag::new("inlcr", I::INLCR),
    Flag::new("igncr", I::IGNCR),
    Flag::new("icrnl", I::ICRNL).sane(),
    Flag::new("ixoff", I::IXOFF),
    Flag::new("tandem", I::IXOFF),
    Flag::new("ixon", I::IXON),
    // not supported by nix
    // Flag::new("iuclc", I::IUCLC),
    Flag::new("ixany", I::IXANY),
    Flag::new("imaxbel", I::IMAXBEL).sane(),
    Flag::new("iutf8", I::IUTF8),
];

pub const OUTPUT_FLAGS: &[Flag<O>] = &[
    Flag::new("opost", O::OPOST).sane(),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "linux",
        target_os = "openbsd"
    ))]
    Flag::new("olcuc", O::OLCUC),
    Flag::new("ocrnl", O::OCRNL),
    Flag::new("onlcr", O::ONLCR).sane(),
    Flag::new("onocr", O::ONOCR),
    Flag::new("onlret", O::ONLRET),
    Flag::new("ofill", O::OFILL),
    Flag::new("ofdel", O::OFDEL),
    Flag::new_grouped("nl0", O::NL0, O::NLDLY).sane(),
    Flag::new_grouped("nl1", O::NL1, O::NLDLY),
    Flag::new_grouped("cr0", O::CR0, O::CRDLY).sane(),
    Flag::new_grouped("cr1", O::CR1, O::CRDLY),
    Flag::new_grouped("cr2", O::CR2, O::CRDLY),
    Flag::new_grouped("cr3", O::CR3, O::CRDLY),
    Flag::new_grouped("tab0", O::TAB0, O::TABDLY).sane(),
    Flag::new_grouped("tab1", O::TAB1, O::TABDLY),
    Flag::new_grouped("tab2", O::TAB2, O::TABDLY),
    Flag::new_grouped("tab3", O::TAB3, O::TABDLY),
    Flag::new_grouped("bs0", O::BS0, O::BSDLY).sane(),
    Flag::new_grouped("bs1", O::BS1, O::BSDLY),
    Flag::new_grouped("vt0", O::VT0, O::VTDLY).sane(),
    Flag::new_grouped("vt1", O::VT1, O::VTDLY),
    Flag::new_grouped("ff0", O::FF0, O::FFDLY).sane(),
    Flag::new_grouped("ff1", O::FF1, O::FFDLY),
];

pub const LOCAL_FLAGS: &[Flag<L>] = &[
    Flag::new("isig", L::ISIG).sane(),
    Flag::new("icanon", L::ICANON).sane(),
    Flag::new("iexten", L::IEXTEN).sane(),
    Flag::new("echo", L::ECHO).sane(),
    Flag::new("echoe", L::ECHOE).sane(),
    Flag::new("crterase", L::ECHOE).hidden().sane(),
    Flag::new("echok", L::ECHOK).sane(),
    Flag::new("echonl", L::ECHONL),
    Flag::new("noflsh", L::NOFLSH),
    // Not supported by nix
    // Flag::new("xcase", L::XCASE),
    Flag::new("tostop", L::TOSTOP),
    Flag::new("echoprt", L::ECHOPRT),
    Flag::new("prterase", L::ECHOPRT).hidden(),
    Flag::new("echoctl", L::ECHOCTL).sane(),
    Flag::new("ctlecho", L::ECHOCTL).sane().hidden(),
    Flag::new("echoke", L::ECHOKE).sane(),
    Flag::new("crtkill", L::ECHOKE).sane().hidden(),
    Flag::new("flusho", L::FLUSHO),
    Flag::new("extproc", L::EXTPROC),
];

// BSD's use u32 as baud rate, to using the enum is unnecessary.
#[cfg(not(any(
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "ios",
    target_os = "macos",
    target_os = "netbsd",
    target_os = "openbsd"
)))]
pub const BAUD_RATES: &[(&str, BaudRate)] = &[
    ("0", BaudRate::B0),
    ("50", BaudRate::B50),
    ("75", BaudRate::B75),
    ("110", BaudRate::B110),
    ("134", BaudRate::B134),
    ("150", BaudRate::B150),
    ("200", BaudRate::B200),
    ("300", BaudRate::B300),
    ("600", BaudRate::B600),
    ("1200", BaudRate::B1200),
    ("1800", BaudRate::B1800),
    ("2400", BaudRate::B2400),
    ("9600", BaudRate::B9600),
    ("19200", BaudRate::B19200),
    ("38400", BaudRate::B38400),
    ("57600", BaudRate::B57600),
    ("115200", BaudRate::B115200),
    ("230400", BaudRate::B230400),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("500000", BaudRate::B500000),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("576000", BaudRate::B576000),
    #[cfg(any(target_os = "android", target_os = "linux",))]
    ("921600", BaudRate::B921600),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("1000000", BaudRate::B1000000),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("1152000", BaudRate::B1152000),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("1500000", BaudRate::B1500000),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("2000000", BaudRate::B2000000),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "sparc64"))
    ))]
    ("2500000", BaudRate::B2500000),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "sparc64"))
    ))]
    ("3000000", BaudRate::B3000000),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "sparc64"))
    ))]
    ("3500000", BaudRate::B3500000),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "sparc64"))
    ))]
    ("4000000", BaudRate::B4000000),
];
<commit_msg>stty: add cfg guards for flags that don't exist on BSD<commit_after>// * This file is part of the uutils coreutils package.
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

// spell-checker:ignore parenb parodd cmspar hupcl cstopb cread clocal crtscts CSIZE
// spell-checker:ignore ignbrk brkint ignpar parmrk inpck istrip inlcr igncr icrnl ixoff ixon iuclc ixany imaxbel iutf
// spell-checker:ignore opost olcuc ocrnl onlcr onocr onlret ofill ofdel nldly crdly tabdly bsdly vtdly ffdly
// spell-checker:ignore isig icanon iexten echoe crterase echok echonl noflsh xcase tostop echoprt prterase echoctl ctlecho echoke crtkill flusho extproc

use crate::Flag;

#[cfg(not(any(
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "ios",
    target_os = "macos",
    target_os = "netbsd",
    target_os = "openbsd"
)))]
use nix::sys::termios::BaudRate;
use nix::sys::termios::{ControlFlags as C, InputFlags as I, LocalFlags as L, OutputFlags as O};

pub const CONTROL_FLAGS: &[Flag<C>] = &[
    Flag::new("parenb", C::PARENB),
    Flag::new("parodd", C::PARODD),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "mips"))
    ))]
    Flag::new("cmspar", C::CMSPAR),
    Flag::new_grouped("cs5", C::CS5, C::CSIZE),
    Flag::new_grouped("cs6", C::CS6, C::CSIZE),
    Flag::new_grouped("cs7", C::CS7, C::CSIZE),
    Flag::new_grouped("cs8", C::CS8, C::CSIZE).sane(),
    Flag::new("hupcl", C::HUPCL),
    Flag::new("cstopb", C::CSTOPB),
    Flag::new("cread", C::CREAD).sane(),
    Flag::new("clocal", C::CLOCAL),
    Flag::new("crtscts", C::CRTSCTS),
];

pub const INPUT_FLAGS: &[Flag<I>] = &[
    Flag::new("ignbrk", I::IGNBRK),
    Flag::new("brkint", I::BRKINT).sane(),
    Flag::new("ignpar", I::IGNPAR),
    Flag::new("parmrk", I::PARMRK),
    Flag::new("inpck", I::INPCK),
    Flag::new("istrip", I::ISTRIP),
    Flag::new("inlcr", I::INLCR),
    Flag::new("igncr", I::IGNCR),
    Flag::new("icrnl", I::ICRNL).sane(),
    Flag::new("ixoff", I::IXOFF),
    Flag::new("tandem", I::IXOFF),
    Flag::new("ixon", I::IXON),
    // not supported by nix
    // Flag::new("iuclc", I::IUCLC),
    Flag::new("ixany", I::IXANY),
    Flag::new("imaxbel", I::IMAXBEL).sane(),
    #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
    Flag::new("iutf8", I::IUTF8),
];

pub const OUTPUT_FLAGS: &[Flag<O>] = &[
    Flag::new("opost", O::OPOST).sane(),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "linux",
        target_os = "openbsd"
    ))]
    Flag::new("olcuc", O::OLCUC),
    Flag::new("ocrnl", O::OCRNL),
    Flag::new("onlcr", O::ONLCR).sane(),
    Flag::new("onocr", O::ONOCR),
    Flag::new("onlret", O::ONLRET),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new("ofill", O::OFILL),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new("ofdel", O::OFDEL),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("nl0", O::NL0, O::NLDLY).sane(),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("nl1", O::NL1, O::NLDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("cr0", O::CR0, O::CRDLY).sane(),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("cr1", O::CR1, O::CRDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("cr2", O::CR2, O::CRDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("cr3", O::CR3, O::CRDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("tab0", O::TAB0, O::TABDLY).sane(),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("tab1", O::TAB1, O::TABDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("tab2", O::TAB2, O::TABDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("tab3", O::TAB3, O::TABDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("bs0", O::BS0, O::BSDLY).sane(),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("bs1", O::BS1, O::BSDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("vt0", O::VT0, O::VTDLY).sane(),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("vt1", O::VT1, O::VTDLY),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("ff0", O::FF0, O::FFDLY).sane(),
    #[cfg(any(
        target_os = "android",
        target_os = "haiku",
        target_os = "ios",
        target_os = "linux",
        target_os = "macos"
    ))]
    Flag::new_grouped("ff1", O::FF1, O::FFDLY),
];

pub const LOCAL_FLAGS: &[Flag<L>] = &[
    Flag::new("isig", L::ISIG).sane(),
    Flag::new("icanon", L::ICANON).sane(),
    Flag::new("iexten", L::IEXTEN).sane(),
    Flag::new("echo", L::ECHO).sane(),
    Flag::new("echoe", L::ECHOE).sane(),
    Flag::new("crterase", L::ECHOE).hidden().sane(),
    Flag::new("echok", L::ECHOK).sane(),
    Flag::new("echonl", L::ECHONL),
    Flag::new("noflsh", L::NOFLSH),
    // Not supported by nix
    // Flag::new("xcase", L::XCASE),
    Flag::new("tostop", L::TOSTOP),
    Flag::new("echoprt", L::ECHOPRT),
    Flag::new("prterase", L::ECHOPRT).hidden(),
    Flag::new("echoctl", L::ECHOCTL).sane(),
    Flag::new("ctlecho", L::ECHOCTL).sane().hidden(),
    Flag::new("echoke", L::ECHOKE).sane(),
    Flag::new("crtkill", L::ECHOKE).sane().hidden(),
    Flag::new("flusho", L::FLUSHO),
    Flag::new("extproc", L::EXTPROC),
];

// BSD's use u32 as baud rate, to using the enum is unnecessary.
#[cfg(not(any(
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "ios",
    target_os = "macos",
    target_os = "netbsd",
    target_os = "openbsd"
)))]
pub const BAUD_RATES: &[(&str, BaudRate)] = &[
    ("0", BaudRate::B0),
    ("50", BaudRate::B50),
    ("75", BaudRate::B75),
    ("110", BaudRate::B110),
    ("134", BaudRate::B134),
    ("150", BaudRate::B150),
    ("200", BaudRate::B200),
    ("300", BaudRate::B300),
    ("600", BaudRate::B600),
    ("1200", BaudRate::B1200),
    ("1800", BaudRate::B1800),
    ("2400", BaudRate::B2400),
    ("9600", BaudRate::B9600),
    ("19200", BaudRate::B19200),
    ("38400", BaudRate::B38400),
    ("57600", BaudRate::B57600),
    ("115200", BaudRate::B115200),
    ("230400", BaudRate::B230400),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("500000", BaudRate::B500000),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("576000", BaudRate::B576000),
    #[cfg(any(target_os = "android", target_os = "linux",))]
    ("921600", BaudRate::B921600),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("1000000", BaudRate::B1000000),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("1152000", BaudRate::B1152000),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("1500000", BaudRate::B1500000),
    #[cfg(any(target_os = "android", target_os = "linux"))]
    ("2000000", BaudRate::B2000000),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "sparc64"))
    ))]
    ("2500000", BaudRate::B2500000),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "sparc64"))
    ))]
    ("3000000", BaudRate::B3000000),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "sparc64"))
    ))]
    ("3500000", BaudRate::B3500000),
    #[cfg(any(
        target_os = "android",
        all(target_os = "linux", not(target_arch = "sparc64"))
    ))]
    ("4000000", BaudRate::B4000000),
];
<|endoftext|>


<commit_before>//! A general purpose `Batcher` implementation based on radix sort.

use timely::progress::frontier::Antichain;

use ::Diff;

use lattice::Lattice;
use trace::{Batch, Batcher, Builder};

/// Creates batches from unordered tuples.
pub struct MergeBatcher<K: Ord, V: Ord, T: Ord, R: Diff, B: Batch<K, V, T, R>> {
    sorter: MergeSorter<(K, V), T, R>,
    lower: Vec<T>,
    frontier: Antichain<T>,
    phantom: ::std::marker::PhantomData<B>,
}

impl<K, V, T, R, B> Batcher<K, V, T, R, B> for MergeBatcher<K, V, T, R, B>
where
    K: Ord+Clone,
    V: Ord+Clone,
    T: Lattice+Ord+Clone,
    R: Diff,
    B: Batch<K, V, T, R>,
{
    fn new() -> Self {
        MergeBatcher {
            sorter: MergeSorter::new(),
            frontier: Antichain::new(),
            lower: vec![T::minimum()],
            phantom: ::std::marker::PhantomData,
        }
    }

    #[inline(never)]
    fn push_batch(&mut self, batch: &mut Vec<((K,V),T,R)>) {
        self.sorter.push(::std::mem::replace(batch, Vec::new()));
    }

    // Sealing a batch means finding those updates with times not greater or equal to any time
    // in `upper`. All updates must have time greater or equal to the previously used `upper`,
    // which we call `lower`, by assumption that after sealing a batcher we receive no more
    // updates with times not greater or equal to `upper`.
    #[inline(never)]
    fn seal(&mut self, upper: &[T]) -> B {

        let mut builder = B::Builder::new();

        let mut merged = Vec::new();
        self.sorter.finish_into(&mut merged);

        let mut kept = Vec::new();
        let mut keep = Vec::with_capacity(1024);

        self.frontier.clear();

        // let mut keep_count = 0;
        // let mut seal_count = 0;

        for mut buffer in merged.drain(..) {
            for ((key, val), time, diff) in buffer.drain(..) {
                if upper.iter().any(|t| t.less_equal(&time)) {
                    // keep_count += 1;
                    self.frontier.insert(time.clone());
                    keep.push(((key, val), time, diff));
                    if keep.len() == keep.capacity() {
                        kept.push(keep);
                        // self.sorter.push(keep);
                        keep = Vec::with_capacity(1024);
                    }
                }
                else {
                    // seal_count += 1;
                    builder.push((key, val, time, diff));
                }
            }
        }
        if keep.len() > 0 {
            kept.push(keep);
        }
        if kept.len() > 0 {
            self.sorter.push_list(kept);
        }

        // println!("sealed: {:?}, kept: {:?}", seal_count, keep_count);

        let seal = builder.done(&self.lower[..], &upper[..], &self.lower[..]);
        self.lower = upper.to_vec();
        seal
    }

    // the frontier of elements remaining after the most recent call to `self.seal`.
    fn frontier(&mut self) -> &[T] {
        self.frontier.elements()
    }
}

use std::slice::{from_raw_parts};

pub struct VecQueue<T> {
    list: Vec<T>,
    head: usize,
    tail: usize,
}

impl<T> VecQueue<T> {
    #[inline(always)]
    pub fn new() -> Self { VecQueue::from(Vec::new()) }
    #[inline(always)]
    pub fn pop(&mut self) -> T {
        debug_assert!(self.head < self.tail);
        self.head += 1;
        unsafe { ::std::ptr::read(self.list.as_mut_ptr().offset(((self.head as isize) - 1) )) }
    }
    #[inline(always)]
    pub fn peek(&self) -> &T {
        debug_assert!(self.head < self.tail);
        unsafe { self.list.get_unchecked(self.head) }
    }
    #[inline(always)]
    pub fn _peek_tail(&self) -> &T {
        debug_assert!(self.head < self.tail);
        unsafe { self.list.get_unchecked(self.tail-1) }
    }
    #[inline(always)]
    pub fn _slice(&self) -> &[T] {
        debug_assert!(self.head < self.tail);
        unsafe { from_raw_parts(self.list.get_unchecked(self.head), self.tail - self.head) }
    }
    #[inline(always)]
    pub fn from(mut list: Vec<T>) -> Self {
        let tail = list.len();
        unsafe { list.set_len(0); }
        VecQueue {
            list: list,
            head: 0,
            tail: tail,
        }
    }
    // could leak, if self.head != self.tail.
    #[inline(always)]
    pub fn done(self) -> Vec<T> {
        debug_assert!(self.head == self.tail);
        self.list
    }
    #[inline(always)]
    pub fn len(&self) -> usize { self.tail - self.head }
    #[inline(always)]
    pub fn is_empty(&self) -> bool { self.head == self.tail }
}

#[inline(always)]
unsafe fn push_unchecked<T>(vec: &mut Vec<T>, element: T) {
    debug_assert!(vec.len() < vec.capacity());
    let len = vec.len();
    ::std::ptr::write(vec.get_unchecked_mut(len), element);
    vec.set_len(len + 1);
}

pub struct MergeSorter<D: Ord, T: Ord, R: Diff> {
    queue: Vec<Vec<Vec<(D, T, R)>>>,    // each power-of-two length list of allocations.
    stash: Vec<Vec<(D, T, R)>>,
}

impl<D: Ord, T: Ord, R: Diff> MergeSorter<D, T, R> {
    pub fn new() -> Self { MergeSorter { queue: Vec::new(), stash: Vec::new() } }

    #[inline(never)]
    pub fn _sort(&mut self, list: &mut Vec<Vec<(D, T, R)>>) {
        for batch in list.drain(..) {
            self.push(batch);
        }
        self.finish_into(list);
    }

    #[inline]
    pub fn push(&mut self, mut batch: Vec<(D, T, R)>) {

        batch.sort_unstable_by(|x,y| (&x.0, &x.1).cmp(&(&y.0, &y.1)));
        for index in 1 .. batch.len() {
            if batch[index].0 == batch[index - 1].0 && batch[index].1 == batch[index - 1].1 {
                batch[index].2 = batch[index].2 + batch[index - 1].2;
                batch[index - 1].2 = R::zero();
            }
        }
        batch.retain(|x| !x.2.is_zero());

        self.queue.push(vec![batch]);
        while self.queue.len() > 1 && (self.queue[self.queue.len()-1].len() >= self.queue[self.queue.len()-2].len() / 2) {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }
    }

    // This is awkward, because it isn't a power-of-two length any more, and we don't want
    // to break it down to be so.
    pub fn push_list(&mut self, list: Vec<Vec<(D, T, R)>>) {
        while self.queue.len() > 1 && self.queue[self.queue.len()-1].len() < list.len() {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }
        self.queue.push(list);
    }

    #[inline(never)]
    pub fn finish_into(&mut self, target: &mut Vec<Vec<(D, T, R)>>) {
        while self.queue.len() > 1 {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }

        if let Some(mut last) = self.queue.pop() {
            ::std::mem::swap(&mut last, target);
        }
    }

    // merges two sorted input lists into one sorted output list.
    #[inline(never)]
    fn merge_by(&mut self, list1: Vec<Vec<(D, T, R)>>, list2: Vec<Vec<(D, T, R)>>) -> Vec<Vec<(D, T, R)>> {

        use std::cmp::Ordering;

        let mut output = Vec::new();
        let mut result = Vec::with_capacity(1024);

        let mut list1 = VecQueue::from(list1);
        let mut list2 = VecQueue::from(list2);

        let mut head1 = if !list1.is_empty() { VecQueue::from(list1.pop()) } else { VecQueue::new() };
        let mut head2 = if !list2.is_empty() { VecQueue::from(list2.pop()) } else { VecQueue::new() };

        // while we have valid data in each input, merge.
        while !head1.is_empty() && !head2.is_empty() {

            while (result.capacity() - result.len()) > 0 && head1.len() > 0 && head2.len() > 0 {

                let cmp = {
                    let x = head1.peek();
                    let y = head2.peek();
                    (&x.0, &x.1).cmp(&(&y.0, &y.1))
                };
                match cmp {
                    Ordering::Less    => { unsafe { push_unchecked(&mut result, head1.pop()); } }
                    Ordering::Greater => { unsafe { push_unchecked(&mut result, head2.pop()); } }
                    Ordering::Equal   => {
                        let (data1, time1, diff1) = head1.pop();
                        let (_data2, _time2, diff2) = head2.pop();
                        let diff = diff1 + diff2;
                        if !diff.is_zero() {
                            unsafe { push_unchecked(&mut result, (data1, time1, diff)); }
                        }
                    }
                }
            }

            if result.capacity() == result.len() {
                output.push(result);
                result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            }

            if head1.is_empty() {
                let done1 = head1.done();
                if done1.capacity() == 1024 { self.stash.push(done1); }
                head1 = if !list1.is_empty() { VecQueue::from(list1.pop()) } else { VecQueue::new() };
            }
            if head2.is_empty() {
                let done2 = head2.done();
                if done2.capacity() == 1024 { self.stash.push(done2); }
                head2 = if !list2.is_empty() { VecQueue::from(list2.pop()) } else { VecQueue::new() };
            }
        }

        if result.len() > 0 { output.push(result); }
        else if result.capacity() > 0 { self.stash.push(result); }

        if !head1.is_empty() {
            let mut result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            for _ in 0 .. head1.len() { result.push(head1.pop()); }
            output.push(result);
        }
        while !list1.is_empty() {
            output.push(list1.pop());
        }

        if !head2.is_empty() {
            let mut result = self.stash.pop().unwrap_or(Vec::with_capacity(1024));
            for _ in 0 .. head2.len() { result.push(head2.pop()); }
            output.push(result);
        }
        while !list2.is_empty() {
            output.push(list2.pop());
        }

        output
    }
}

/// Reports the number of elements satisfing the predicate.
///
/// This methods *relies strongly* on the assumption that the predicate
/// stays false once it becomes false, a joint property of the predicate
/// and the slice. This allows `advance` to use exponential search to
/// count the number of elements in time logarithmic in the result.
#[inline(always)]
pub fn _advance<T, F: Fn(&T)->bool>(slice: &[T], function: F) -> usize {

	// start with no advance
	let mut index = 0;
	if index < slice.len() && function(&slice[index]) {

		// advance in exponentially growing steps.
		let mut step = 1;
		while index + step < slice.len() && function(&slice[index + step]) {
			index += step;
			step = step << 1;
		}

		// advance in exponentially shrinking steps.
		step = step >> 1;
		while step > 0 {
			if index + step < slice.len() && function(&slice[index + step]) {
				index += step;
			}
			step = step >> 1;
		}

		index += 1;
	}

	index
}
<commit_msg>improve buffer reuse<commit_after>//! A general purpose `Batcher` implementation based on radix sort.

use timely::progress::frontier::Antichain;

use ::Diff;

use lattice::Lattice;
use trace::{Batch, Batcher, Builder};

/// Creates batches from unordered tuples.
pub struct MergeBatcher<K: Ord, V: Ord, T: Ord, R: Diff, B: Batch<K, V, T, R>> {
    sorter: MergeSorter<(K, V), T, R>,
    lower: Vec<T>,
    frontier: Antichain<T>,
    phantom: ::std::marker::PhantomData<B>,
}

impl<K, V, T, R, B> Batcher<K, V, T, R, B> for MergeBatcher<K, V, T, R, B>
where
    K: Ord+Clone,
    V: Ord+Clone,
    T: Lattice+Ord+Clone,
    R: Diff,
    B: Batch<K, V, T, R>,
{
    fn new() -> Self {
        MergeBatcher {
            sorter: MergeSorter::new(),
            frontier: Antichain::new(),
            lower: vec![T::minimum()],
            phantom: ::std::marker::PhantomData,
        }
    }

    #[inline(never)]
    fn push_batch(&mut self, batch: &mut Vec<((K,V),T,R)>) {
        self.sorter.push(batch);
    }

    // Sealing a batch means finding those updates with times not greater or equal to any time
    // in `upper`. All updates must have time greater or equal to the previously used `upper`,
    // which we call `lower`, by assumption that after sealing a batcher we receive no more
    // updates with times not greater or equal to `upper`.
    #[inline(never)]
    fn seal(&mut self, upper: &[T]) -> B {

        let mut builder = B::Builder::new();

        let mut merged = Vec::new();
        self.sorter.finish_into(&mut merged);

        let mut kept = Vec::new();
        let mut keep = Vec::with_capacity(1024);

        self.frontier.clear();

        for mut buffer in merged.drain(..) {
            for ((key, val), time, diff) in buffer.drain(..) {
                if upper.iter().any(|t| t.less_equal(&time)) {
                    // keep_count += 1;
                    self.frontier.insert(time.clone());
                    keep.push(((key, val), time, diff));
                    if keep.len() == keep.capacity() {
                        kept.push(keep);
                        keep = self.sorter.empty();
                    }
                }
                else {
                    // seal_count += 1;
                    builder.push((key, val, time, diff));
                }
            }
        }
        if keep.len() > 0 {
            kept.push(keep);
        }
        if kept.len() > 0 {
            self.sorter.push_list(kept);
        }

        let seal = builder.done(&self.lower[..], &upper[..], &self.lower[..]);
        self.lower = upper.to_vec();
        seal
    }

    // the frontier of elements remaining after the most recent call to `self.seal`.
    fn frontier(&mut self) -> &[T] {
        self.frontier.elements()
    }
}

use std::slice::{from_raw_parts};

pub struct VecQueue<T> {
    list: Vec<T>,
    head: usize,
    tail: usize,
}

impl<T> VecQueue<T> {
    #[inline(always)]
    pub fn new() -> Self { VecQueue::from(Vec::new()) }
    #[inline(always)]
    pub fn pop(&mut self) -> T {
        debug_assert!(self.head < self.tail);
        self.head += 1;
        unsafe { ::std::ptr::read(self.list.as_mut_ptr().offset(((self.head as isize) - 1) )) }
    }
    #[inline(always)]
    pub fn peek(&self) -> &T {
        debug_assert!(self.head < self.tail);
        unsafe { self.list.get_unchecked(self.head) }
    }
    #[inline(always)]
    pub fn _peek_tail(&self) -> &T {
        debug_assert!(self.head < self.tail);
        unsafe { self.list.get_unchecked(self.tail-1) }
    }
    #[inline(always)]
    pub fn _slice(&self) -> &[T] {
        debug_assert!(self.head < self.tail);
        unsafe { from_raw_parts(self.list.get_unchecked(self.head), self.tail - self.head) }
    }
    #[inline(always)]
    pub fn from(mut list: Vec<T>) -> Self {
        let tail = list.len();
        unsafe { list.set_len(0); }
        VecQueue {
            list: list,
            head: 0,
            tail: tail,
        }
    }
    // could leak, if self.head != self.tail.
    #[inline(always)]
    pub fn done(self) -> Vec<T> {
        debug_assert!(self.head == self.tail);
        self.list
    }
    #[inline(always)]
    pub fn len(&self) -> usize { self.tail - self.head }
    #[inline(always)]
    pub fn is_empty(&self) -> bool { self.head == self.tail }
}

#[inline(always)]
unsafe fn push_unchecked<T>(vec: &mut Vec<T>, element: T) {
    debug_assert!(vec.len() < vec.capacity());
    let len = vec.len();
    ::std::ptr::write(vec.get_unchecked_mut(len), element);
    vec.set_len(len + 1);
}

pub struct MergeSorter<D: Ord, T: Ord, R: Diff> {
    queue: Vec<Vec<Vec<(D, T, R)>>>,    // each power-of-two length list of allocations.
    stash: Vec<Vec<(D, T, R)>>,
}

impl<D: Ord, T: Ord, R: Diff> MergeSorter<D, T, R> {

    #[inline]
    pub fn new() -> Self { MergeSorter { queue: Vec::new(), stash: Vec::new() } }

    #[inline]
    pub fn empty(&mut self) -> Vec<(D, T, R)> {
        self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024))
    }

    #[inline(never)]
    pub fn _sort(&mut self, list: &mut Vec<Vec<(D, T, R)>>) {
        for mut batch in list.drain(..) {
            self.push(&mut batch);
        }
        self.finish_into(list);
    }

    #[inline]
    pub fn push(&mut self, batch: &mut Vec<(D, T, R)>) {

        let mut batch = if self.stash.len() > 2 {
            ::std::mem::replace(batch, self.stash.pop().unwrap())
        }
        else {
            ::std::mem::replace(batch, Vec::new())
        };

        if batch.len() > 0 {
            batch.sort_unstable_by(|x,y| (&x.0, &x.1).cmp(&(&y.0, &y.1)));
            for index in 1 .. batch.len() {
                if batch[index].0 == batch[index - 1].0 && batch[index].1 == batch[index - 1].1 {
                    batch[index].2 = batch[index].2 + batch[index - 1].2;
                    batch[index - 1].2 = R::zero();
                }
            }
            batch.retain(|x| !x.2.is_zero());

            self.queue.push(vec![batch]);
            while self.queue.len() > 1 && (self.queue[self.queue.len()-1].len() >= self.queue[self.queue.len()-2].len() / 2) {
                let list1 = self.queue.pop().unwrap();
                let list2 = self.queue.pop().unwrap();
                let merged = self.merge_by(list1, list2);
                self.queue.push(merged);
            }
        }
    }

    // This is awkward, because it isn't a power-of-two length any more, and we don't want
    // to break it down to be so.
    pub fn push_list(&mut self, list: Vec<Vec<(D, T, R)>>) {
        while self.queue.len() > 1 && self.queue[self.queue.len()-1].len() < list.len() {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }
        self.queue.push(list);
    }

    #[inline(never)]
    pub fn finish_into(&mut self, target: &mut Vec<Vec<(D, T, R)>>) {
        while self.queue.len() > 1 {
            let list1 = self.queue.pop().unwrap();
            let list2 = self.queue.pop().unwrap();
            let merged = self.merge_by(list1, list2);
            self.queue.push(merged);
        }

        if let Some(mut last) = self.queue.pop() {
            ::std::mem::swap(&mut last, target);
        }
    }

    // merges two sorted input lists into one sorted output list.
    #[inline(never)]
    fn merge_by(&mut self, list1: Vec<Vec<(D, T, R)>>, list2: Vec<Vec<(D, T, R)>>) -> Vec<Vec<(D, T, R)>> {

        use std::cmp::Ordering;

        // TODO: `list1` and `list2` get dropped; would be better to reuse?
        let mut output = Vec::with_capacity(list1.len() + list2.len());
        let mut result = Vec::with_capacity(1024);

        let mut list1 = VecQueue::from(list1);
        let mut list2 = VecQueue::from(list2);

        let mut head1 = if !list1.is_empty() { VecQueue::from(list1.pop()) } else { VecQueue::new() };
        let mut head2 = if !list2.is_empty() { VecQueue::from(list2.pop()) } else { VecQueue::new() };

        // while we have valid data in each input, merge.
        while !head1.is_empty() && !head2.is_empty() {

            while (result.capacity() - result.len()) > 0 && head1.len() > 0 && head2.len() > 0 {

                let cmp = {
                    let x = head1.peek();
                    let y = head2.peek();
                    (&x.0, &x.1).cmp(&(&y.0, &y.1))
                };
                match cmp {
                    Ordering::Less    => { unsafe { push_unchecked(&mut result, head1.pop()); } }
                    Ordering::Greater => { unsafe { push_unchecked(&mut result, head2.pop()); } }
                    Ordering::Equal   => {
                        let (data1, time1, diff1) = head1.pop();
                        let (_data2, _time2, diff2) = head2.pop();
                        let diff = diff1 + diff2;
                        if !diff.is_zero() {
                            unsafe { push_unchecked(&mut result, (data1, time1, diff)); }
                        }
                    }
                }
            }

            if result.capacity() == result.len() {
                output.push(result);
                result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            }

            if head1.is_empty() {
                let done1 = head1.done();
                if done1.capacity() == 1024 { self.stash.push(done1); }
                head1 = if !list1.is_empty() { VecQueue::from(list1.pop()) } else { VecQueue::new() };
            }
            if head2.is_empty() {
                let done2 = head2.done();
                if done2.capacity() == 1024 { self.stash.push(done2); }
                head2 = if !list2.is_empty() { VecQueue::from(list2.pop()) } else { VecQueue::new() };
            }
        }

        if result.len() > 0 { output.push(result); }
        else if result.capacity() > 0 { self.stash.push(result); }

        if !head1.is_empty() {
            let mut result = self.stash.pop().unwrap_or_else(|| Vec::with_capacity(1024));
            for _ in 0 .. head1.len() { result.push(head1.pop()); }
            output.push(result);
        }
        while !list1.is_empty() {
            output.push(list1.pop());
        }

        if !head2.is_empty() {
            let mut result = self.stash.pop().unwrap_or(Vec::with_capacity(1024));
            for _ in 0 .. head2.len() { result.push(head2.pop()); }
            output.push(result);
        }
        while !list2.is_empty() {
            output.push(list2.pop());
        }

        output
    }
}

/// Reports the number of elements satisfing the predicate.
///
/// This methods *relies strongly* on the assumption that the predicate
/// stays false once it becomes false, a joint property of the predicate
/// and the slice. This allows `advance` to use exponential search to
/// count the number of elements in time logarithmic in the result.
#[inline(always)]
pub fn _advance<T, F: Fn(&T)->bool>(slice: &[T], function: F) -> usize {

	// start with no advance
	let mut index = 0;
	if index < slice.len() && function(&slice[index]) {

		// advance in exponentially growing steps.
		let mut step = 1;
		while index + step < slice.len() && function(&slice[index + step]) {
			index += step;
			step = step << 1;
		}

		// advance in exponentially shrinking steps.
		step = step >> 1;
		while step > 0 {
			if index + step < slice.len() && function(&slice[index + step]) {
				index += step;
			}
			step = step >> 1;
		}

		index += 1;
	}

	index
}
<|endoftext|>


<commit_before>s! {
    pub struct termios2 {
        pub c_iflag: ::tcflag_t,
        pub c_oflag: ::tcflag_t,
        pub c_cflag: ::tcflag_t,
        pub c_lflag: ::tcflag_t,
        pub c_line: ::cc_t,
        pub c_cc: [::cc_t; 23],
        pub c_ispeed: ::speed_t,
        pub c_ospeed: ::speed_t,
    }
}

// arch/mips/include/uapi/asm/socket.h
pub const SOL_SOCKET: ::c_int = 0xffff;

// Defined in unix/linux_like/mod.rs
// pub const SO_DEBUG: ::c_int = 0x0001;
pub const SO_REUSEADDR: ::c_int = 0x0004;
pub const SO_KEEPALIVE: ::c_int = 0x0008;
pub const SO_DONTROUTE: ::c_int = 0x0010;
pub const SO_BROADCAST: ::c_int = 0x0020;
pub const SO_LINGER: ::c_int = 0x0080;
pub const SO_OOBINLINE: ::c_int = 0x0100;
pub const SO_REUSEPORT: ::c_int = 0x0200;
pub const SO_TYPE: ::c_int = 0x1008;
// pub const SO_STYLE: ::c_int = SO_TYPE;
pub const SO_ERROR: ::c_int = 0x1007;
pub const SO_SNDBUF: ::c_int = 0x1001;
pub const SO_RCVBUF: ::c_int = 0x1002;
pub const SO_SNDLOWAT: ::c_int = 0x1003;
pub const SO_RCVLOWAT: ::c_int = 0x1004;
// NOTE: These definitions are now being renamed with _OLD postfix,
// but CI haven't support them yet.
// Some related consts could be found in b32.rs and b64.rs
pub const SO_SNDTIMEO: ::c_int = 0x1005;
pub const SO_RCVTIMEO: ::c_int = 0x1006;
// pub const SO_SNDTIMEO_OLD: ::c_int = 0x1005;
// pub const SO_RCVTIMEO_OLD: ::c_int = 0x1006;
pub const SO_ACCEPTCONN: ::c_int = 0x1009;
pub const SO_PROTOCOL: ::c_int = 0x1028;
pub const SO_DOMAIN: ::c_int = 0x1029;

pub const SO_NO_CHECK: ::c_int = 11;
pub const SO_PRIORITY: ::c_int = 12;
pub const SO_BSDCOMPAT: ::c_int = 14;
pub const SO_PASSCRED: ::c_int = 17;
pub const SO_PEERCRED: ::c_int = 18;
pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22;
pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23;
pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24;
pub const SO_BINDTODEVICE: ::c_int = 25;
pub const SO_ATTACH_FILTER: ::c_int = 26;
pub const SO_DETACH_FILTER: ::c_int = 27;
pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER;
pub const SO_PEERNAME: ::c_int = 28;
pub const SO_PEERSEC: ::c_int = 30;
pub const SO_SNDBUFFORCE: ::c_int = 31;
pub const SO_RCVBUFFORCE: ::c_int = 33;
pub const SO_PASSSEC: ::c_int = 34;
pub const SO_MARK: ::c_int = 36;
pub const SO_RXQ_OVFL: ::c_int = 40;
pub const SO_WIFI_STATUS: ::c_int = 41;
pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS;
pub const SO_PEEK_OFF: ::c_int = 42;
pub const SO_NOFCS: ::c_int = 43;
pub const SO_LOCK_FILTER: ::c_int = 44;
pub const SO_SELECT_ERR_QUEUE: ::c_int = 45;
pub const SO_BUSY_POLL: ::c_int = 46;
pub const SO_MAX_PACING_RATE: ::c_int = 47;
pub const SO_BPF_EXTENSIONS: ::c_int = 48;
pub const SO_INCOMING_CPU: ::c_int = 49;
pub const SO_ATTACH_BPF: ::c_int = 50;
pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER;
pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51;
pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52;
pub const SO_CNX_ADVICE: ::c_int = 53;
pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54;
pub const SO_MEMINFO: ::c_int = 55;
pub const SO_INCOMING_NAPI_ID: ::c_int = 56;
pub const SO_COOKIE: ::c_int = 57;
pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58;
pub const SO_PEERGROUPS: ::c_int = 59;
pub const SO_ZEROCOPY: ::c_int = 60;
pub const SO_TXTIME: ::c_int = 61;
pub const SCM_TXTIME: ::c_int = SO_TXTIME;
pub const SO_BINDTOIFINDEX: ::c_int = 62;
// NOTE: These definitions are now being renamed with _OLD postfix,
// but CI haven't support them yet.
// Some related consts could be found in b32.rs and b64.rs
pub const SO_TIMESTAMP: ::c_int = 29;
pub const SO_TIMESTAMPNS: ::c_int = 35;
pub const SO_TIMESTAMPING: ::c_int = 37;
// pub const SO_TIMESTAMP_OLD: ::c_int = 29;
// pub const SO_TIMESTAMPNS_OLD: ::c_int = 35;
// pub const SO_TIMESTAMPING_OLD: ::c_int = 37;
// pub const SO_TIMESTAMP_NEW: ::c_int = 63;
// pub const SO_TIMESTAMPNS_NEW: ::c_int = 64;
// pub const SO_TIMESTAMPING_NEW: ::c_int = 65;
// pub const SO_RCVTIMEO_NEW: ::c_int = 66;
// pub const SO_SNDTIMEO_NEW: ::c_int = 67;
// pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68;
// pub const SO_PREFER_BUSY_POLL: ::c_int = 69;
// pub const SO_BUSY_POLL_BUDGET: ::c_int = 70;

// Defined in unix/linux_like/mod.rs
// pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP;
pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS;
pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING;

pub const TIOCMGET: ::Ioctl = 0x741d;
pub const TIOCMBIS: ::Ioctl = 0x741b;
pub const TIOCMBIC: ::Ioctl = 0x741c;
pub const TIOCMSET: ::Ioctl = 0x741a;
pub const TCGETS2: ::Ioctl = 0x4030542a;
pub const TCSETS2: ::Ioctl = 0x8030542b;
pub const TCSETSW2: ::Ioctl = 0x8030542c;
pub const TCSETSF2: ::Ioctl = 0x8030542d;

pub const TIOCM_LE: ::c_int = 0x001;
pub const TIOCM_DTR: ::c_int = 0x002;
pub const TIOCM_RTS: ::c_int = 0x004;
pub const TIOCM_ST: ::c_int = 0x010;
pub const TIOCM_SR: ::c_int = 0x020;
pub const TIOCM_CTS: ::c_int = 0x040;
pub const TIOCM_CAR: ::c_int = 0x100;
pub const TIOCM_CD: ::c_int = TIOCM_CAR;
pub const TIOCM_RNG: ::c_int = 0x200;
pub const TIOCM_RI: ::c_int = TIOCM_RNG;
pub const TIOCM_DSR: ::c_int = 0x400;

pub const BOTHER: ::speed_t = 0o010000;
pub const IBSHIFT: ::tcflag_t = 16;

cfg_if! {
    if #[cfg(target_endian = "little")] {
        pub const BLKSSZGET: ::c_int = 0x20001268;
        pub const BLKPBSZGET: ::c_int = 0x2000127B;
    } else if #[cfg(target_endian = "big")] {
        pub const BLKSSZGET: ::c_int = 0x20001268;
        pub const BLKPBSZGET: ::c_int = 0x2000127B;
    }
}
<commit_msg>Removed endianess conditionals on mips ioctl<commit_after>s! {
    pub struct termios2 {
        pub c_iflag: ::tcflag_t,
        pub c_oflag: ::tcflag_t,
        pub c_cflag: ::tcflag_t,
        pub c_lflag: ::tcflag_t,
        pub c_line: ::cc_t,
        pub c_cc: [::cc_t; 23],
        pub c_ispeed: ::speed_t,
        pub c_ospeed: ::speed_t,
    }
}

// arch/mips/include/uapi/asm/socket.h
pub const SOL_SOCKET: ::c_int = 0xffff;

// Defined in unix/linux_like/mod.rs
// pub const SO_DEBUG: ::c_int = 0x0001;
pub const SO_REUSEADDR: ::c_int = 0x0004;
pub const SO_KEEPALIVE: ::c_int = 0x0008;
pub const SO_DONTROUTE: ::c_int = 0x0010;
pub const SO_BROADCAST: ::c_int = 0x0020;
pub const SO_LINGER: ::c_int = 0x0080;
pub const SO_OOBINLINE: ::c_int = 0x0100;
pub const SO_REUSEPORT: ::c_int = 0x0200;
pub const SO_TYPE: ::c_int = 0x1008;
// pub const SO_STYLE: ::c_int = SO_TYPE;
pub const SO_ERROR: ::c_int = 0x1007;
pub const SO_SNDBUF: ::c_int = 0x1001;
pub const SO_RCVBUF: ::c_int = 0x1002;
pub const SO_SNDLOWAT: ::c_int = 0x1003;
pub const SO_RCVLOWAT: ::c_int = 0x1004;
// NOTE: These definitions are now being renamed with _OLD postfix,
// but CI haven't support them yet.
// Some related consts could be found in b32.rs and b64.rs
pub const SO_SNDTIMEO: ::c_int = 0x1005;
pub const SO_RCVTIMEO: ::c_int = 0x1006;
// pub const SO_SNDTIMEO_OLD: ::c_int = 0x1005;
// pub const SO_RCVTIMEO_OLD: ::c_int = 0x1006;
pub const SO_ACCEPTCONN: ::c_int = 0x1009;
pub const SO_PROTOCOL: ::c_int = 0x1028;
pub const SO_DOMAIN: ::c_int = 0x1029;

pub const SO_NO_CHECK: ::c_int = 11;
pub const SO_PRIORITY: ::c_int = 12;
pub const SO_BSDCOMPAT: ::c_int = 14;
pub const SO_PASSCRED: ::c_int = 17;
pub const SO_PEERCRED: ::c_int = 18;
pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22;
pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23;
pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24;
pub const SO_BINDTODEVICE: ::c_int = 25;
pub const SO_ATTACH_FILTER: ::c_int = 26;
pub const SO_DETACH_FILTER: ::c_int = 27;
pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER;
pub const SO_PEERNAME: ::c_int = 28;
pub const SO_PEERSEC: ::c_int = 30;
pub const SO_SNDBUFFORCE: ::c_int = 31;
pub const SO_RCVBUFFORCE: ::c_int = 33;
pub const SO_PASSSEC: ::c_int = 34;
pub const SO_MARK: ::c_int = 36;
pub const SO_RXQ_OVFL: ::c_int = 40;
pub const SO_WIFI_STATUS: ::c_int = 41;
pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS;
pub const SO_PEEK_OFF: ::c_int = 42;
pub const SO_NOFCS: ::c_int = 43;
pub const SO_LOCK_FILTER: ::c_int = 44;
pub const SO_SELECT_ERR_QUEUE: ::c_int = 45;
pub const SO_BUSY_POLL: ::c_int = 46;
pub const SO_MAX_PACING_RATE: ::c_int = 47;
pub const SO_BPF_EXTENSIONS: ::c_int = 48;
pub const SO_INCOMING_CPU: ::c_int = 49;
pub const SO_ATTACH_BPF: ::c_int = 50;
pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER;
pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51;
pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52;
pub const SO_CNX_ADVICE: ::c_int = 53;
pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54;
pub const SO_MEMINFO: ::c_int = 55;
pub const SO_INCOMING_NAPI_ID: ::c_int = 56;
pub const SO_COOKIE: ::c_int = 57;
pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58;
pub const SO_PEERGROUPS: ::c_int = 59;
pub const SO_ZEROCOPY: ::c_int = 60;
pub const SO_TXTIME: ::c_int = 61;
pub const SCM_TXTIME: ::c_int = SO_TXTIME;
pub const SO_BINDTOIFINDEX: ::c_int = 62;
// NOTE: These definitions are now being renamed with _OLD postfix,
// but CI haven't support them yet.
// Some related consts could be found in b32.rs and b64.rs
pub const SO_TIMESTAMP: ::c_int = 29;
pub const SO_TIMESTAMPNS: ::c_int = 35;
pub const SO_TIMESTAMPING: ::c_int = 37;
// pub const SO_TIMESTAMP_OLD: ::c_int = 29;
// pub const SO_TIMESTAMPNS_OLD: ::c_int = 35;
// pub const SO_TIMESTAMPING_OLD: ::c_int = 37;
// pub const SO_TIMESTAMP_NEW: ::c_int = 63;
// pub const SO_TIMESTAMPNS_NEW: ::c_int = 64;
// pub const SO_TIMESTAMPING_NEW: ::c_int = 65;
// pub const SO_RCVTIMEO_NEW: ::c_int = 66;
// pub const SO_SNDTIMEO_NEW: ::c_int = 67;
// pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68;
// pub const SO_PREFER_BUSY_POLL: ::c_int = 69;
// pub const SO_BUSY_POLL_BUDGET: ::c_int = 70;

// Defined in unix/linux_like/mod.rs
// pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP;
pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS;
pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING;

pub const TIOCMGET: ::Ioctl = 0x741d;
pub const TIOCMBIS: ::Ioctl = 0x741b;
pub const TIOCMBIC: ::Ioctl = 0x741c;
pub const TIOCMSET: ::Ioctl = 0x741a;
pub const TCGETS2: ::Ioctl = 0x4030542a;
pub const TCSETS2: ::Ioctl = 0x8030542b;
pub const TCSETSW2: ::Ioctl = 0x8030542c;
pub const TCSETSF2: ::Ioctl = 0x8030542d;

pub const TIOCM_LE: ::c_int = 0x001;
pub const TIOCM_DTR: ::c_int = 0x002;
pub const TIOCM_RTS: ::c_int = 0x004;
pub const TIOCM_ST: ::c_int = 0x010;
pub const TIOCM_SR: ::c_int = 0x020;
pub const TIOCM_CTS: ::c_int = 0x040;
pub const TIOCM_CAR: ::c_int = 0x100;
pub const TIOCM_CD: ::c_int = TIOCM_CAR;
pub const TIOCM_RNG: ::c_int = 0x200;
pub const TIOCM_RI: ::c_int = TIOCM_RNG;
pub const TIOCM_DSR: ::c_int = 0x400;

pub const BOTHER: ::speed_t = 0o010000;
pub const IBSHIFT: ::tcflag_t = 16;

pub const BLKSSZGET: ::c_int = 0x20001268;
pub const BLKPBSZGET: ::c_int = 0x2000127B;
<|endoftext|>


<commit_before>s! {
    pub struct termios2 {
        pub c_iflag: ::tcflag_t,
        pub c_oflag: ::tcflag_t,
        pub c_cflag: ::tcflag_t,
        pub c_lflag: ::tcflag_t,
        pub c_line: ::cc_t,
        pub c_cc: [::cc_t; 23],
        pub c_ispeed: ::speed_t,
        pub c_ospeed: ::speed_t,
    }
}

// arch/mips/include/uapi/asm/socket.h
pub const SOL_SOCKET: ::c_int = 0xffff;

// Defined in unix/linux_like/mod.rs
// pub const SO_DEBUG: ::c_int = 0x0001;
pub const SO_REUSEADDR: ::c_int = 0x0004;
pub const SO_KEEPALIVE: ::c_int = 0x0008;
pub const SO_DONTROUTE: ::c_int = 0x0010;
pub const SO_BROADCAST: ::c_int = 0x0020;
pub const SO_LINGER: ::c_int = 0x0080;
pub const SO_OOBINLINE: ::c_int = 0x0100;
pub const SO_REUSEPORT: ::c_int = 0x0200;
pub const SO_TYPE: ::c_int = 0x1008;
// pub const SO_STYLE: ::c_int = SO_TYPE;
pub const SO_ERROR: ::c_int = 0x1007;
pub const SO_SNDBUF: ::c_int = 0x1001;
pub const SO_RCVBUF: ::c_int = 0x1002;
pub const SO_SNDLOWAT: ::c_int = 0x1003;
pub const SO_RCVLOWAT: ::c_int = 0x1004;
// NOTE: These definitions are now being renamed with _OLD postfix,
// but CI haven't support them yet.
// Some related consts could be found in b32.rs and b64.rs
pub const SO_SNDTIMEO: ::c_int = 0x1005;
pub const SO_RCVTIMEO: ::c_int = 0x1006;
// pub const SO_SNDTIMEO_OLD: ::c_int = 0x1005;
// pub const SO_RCVTIMEO_OLD: ::c_int = 0x1006;
pub const SO_ACCEPTCONN: ::c_int = 0x1009;
pub const SO_PROTOCOL: ::c_int = 0x1028;
pub const SO_DOMAIN: ::c_int = 0x1029;

pub const SO_NO_CHECK: ::c_int = 11;
pub const SO_PRIORITY: ::c_int = 12;
pub const SO_BSDCOMPAT: ::c_int = 14;
pub const SO_PASSCRED: ::c_int = 17;
pub const SO_PEERCRED: ::c_int = 18;
pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22;
pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23;
pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24;
pub const SO_BINDTODEVICE: ::c_int = 25;
pub const SO_ATTACH_FILTER: ::c_int = 26;
pub const SO_DETACH_FILTER: ::c_int = 27;
pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER;
pub const SO_PEERNAME: ::c_int = 28;
pub const SO_PEERSEC: ::c_int = 30;
pub const SO_SNDBUFFORCE: ::c_int = 31;
pub const SO_RCVBUFFORCE: ::c_int = 33;
pub const SO_PASSSEC: ::c_int = 34;
pub const SO_MARK: ::c_int = 36;
pub const SO_RXQ_OVFL: ::c_int = 40;
pub const SO_WIFI_STATUS: ::c_int = 41;
pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS;
pub const SO_PEEK_OFF: ::c_int = 42;
pub const SO_NOFCS: ::c_int = 43;
pub const SO_LOCK_FILTER: ::c_int = 44;
pub const SO_SELECT_ERR_QUEUE: ::c_int = 45;
pub const SO_BUSY_POLL: ::c_int = 46;
pub const SO_MAX_PACING_RATE: ::c_int = 47;
pub const SO_BPF_EXTENSIONS: ::c_int = 48;
pub const SO_INCOMING_CPU: ::c_int = 49;
pub const SO_ATTACH_BPF: ::c_int = 50;
pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER;
pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51;
pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52;
pub const SO_CNX_ADVICE: ::c_int = 53;
pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54;
pub const SO_MEMINFO: ::c_int = 55;
pub const SO_INCOMING_NAPI_ID: ::c_int = 56;
pub const SO_COOKIE: ::c_int = 57;
pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58;
pub const SO_PEERGROUPS: ::c_int = 59;
pub const SO_ZEROCOPY: ::c_int = 60;
pub const SO_TXTIME: ::c_int = 61;
pub const SCM_TXTIME: ::c_int = SO_TXTIME;
pub const SO_BINDTOIFINDEX: ::c_int = 62;
// NOTE: These definitions are now being renamed with _OLD postfix,
// but CI haven't support them yet.
// Some related consts could be found in b32.rs and b64.rs
pub const SO_TIMESTAMP: ::c_int = 29;
pub const SO_TIMESTAMPNS: ::c_int = 35;
pub const SO_TIMESTAMPING: ::c_int = 37;
// pub const SO_TIMESTAMP_OLD: ::c_int = 29;
// pub const SO_TIMESTAMPNS_OLD: ::c_int = 35;
// pub const SO_TIMESTAMPING_OLD: ::c_int = 37;
// pub const SO_TIMESTAMP_NEW: ::c_int = 63;
// pub const SO_TIMESTAMPNS_NEW: ::c_int = 64;
// pub const SO_TIMESTAMPING_NEW: ::c_int = 65;
// pub const SO_RCVTIMEO_NEW: ::c_int = 66;
// pub const SO_SNDTIMEO_NEW: ::c_int = 67;
// pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68;
// pub const SO_PREFER_BUSY_POLL: ::c_int = 69;
// pub const SO_BUSY_POLL_BUDGET: ::c_int = 70;

// Defined in unix/linux_like/mod.rs
// pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP;
pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS;
pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING;

pub const TIOCMGET: ::Ioctl = 0x741d;
pub const TIOCMBIS: ::Ioctl = 0x741b;
pub const TIOCMBIC: ::Ioctl = 0x741c;
pub const TIOCMSET: ::Ioctl = 0x741a;
pub const TCGETS2: ::Ioctl = 0x4030542a;
pub const TCSETS2: ::Ioctl = 0x8030542b;
pub const TCSETSW2: ::Ioctl = 0x8030542c;
pub const TCSETSF2: ::Ioctl = 0x8030542d;

pub const TIOCM_LE: ::c_int = 0x001;
pub const TIOCM_DTR: ::c_int = 0x002;
pub const TIOCM_RTS: ::c_int = 0x004;
pub const TIOCM_ST: ::c_int = 0x010;
pub const TIOCM_SR: ::c_int = 0x020;
pub const TIOCM_CTS: ::c_int = 0x040;
pub const TIOCM_CAR: ::c_int = 0x100;
pub const TIOCM_CD: ::c_int = TIOCM_CAR;
pub const TIOCM_RNG: ::c_int = 0x200;
pub const TIOCM_RI: ::c_int = TIOCM_RNG;
pub const TIOCM_DSR: ::c_int = 0x400;

pub const BOTHER: ::speed_t = 0o010000;
pub const IBSHIFT: ::tcflag_t = 16;

cfg_if! {
    if #[cfg(target_endian = "little")] {
        pub const BLKSSZGET: ::c_int = 0x1268;
        pub const BLKPBSZGET: ::c_int = 0x127B;
    } else if #[cfg(target_endian = "big")] {
        pub const BLKSSZGET: ::c_int = 0x6812;
        pub const BLKPBSZGET: ::c_int = 0x7B12;
    }
}
<commit_msg>Fix ioctl constants on mips big-endian<commit_after>s! {
    pub struct termios2 {
        pub c_iflag: ::tcflag_t,
        pub c_oflag: ::tcflag_t,
        pub c_cflag: ::tcflag_t,
        pub c_lflag: ::tcflag_t,
        pub c_line: ::cc_t,
        pub c_cc: [::cc_t; 23],
        pub c_ispeed: ::speed_t,
        pub c_ospeed: ::speed_t,
    }
}

// arch/mips/include/uapi/asm/socket.h
pub const SOL_SOCKET: ::c_int = 0xffff;

// Defined in unix/linux_like/mod.rs
// pub const SO_DEBUG: ::c_int = 0x0001;
pub const SO_REUSEADDR: ::c_int = 0x0004;
pub const SO_KEEPALIVE: ::c_int = 0x0008;
pub const SO_DONTROUTE: ::c_int = 0x0010;
pub const SO_BROADCAST: ::c_int = 0x0020;
pub const SO_LINGER: ::c_int = 0x0080;
pub const SO_OOBINLINE: ::c_int = 0x0100;
pub const SO_REUSEPORT: ::c_int = 0x0200;
pub const SO_TYPE: ::c_int = 0x1008;
// pub const SO_STYLE: ::c_int = SO_TYPE;
pub const SO_ERROR: ::c_int = 0x1007;
pub const SO_SNDBUF: ::c_int = 0x1001;
pub const SO_RCVBUF: ::c_int = 0x1002;
pub const SO_SNDLOWAT: ::c_int = 0x1003;
pub const SO_RCVLOWAT: ::c_int = 0x1004;
// NOTE: These definitions are now being renamed with _OLD postfix,
// but CI haven't support them yet.
// Some related consts could be found in b32.rs and b64.rs
pub const SO_SNDTIMEO: ::c_int = 0x1005;
pub const SO_RCVTIMEO: ::c_int = 0x1006;
// pub const SO_SNDTIMEO_OLD: ::c_int = 0x1005;
// pub const SO_RCVTIMEO_OLD: ::c_int = 0x1006;
pub const SO_ACCEPTCONN: ::c_int = 0x1009;
pub const SO_PROTOCOL: ::c_int = 0x1028;
pub const SO_DOMAIN: ::c_int = 0x1029;

pub const SO_NO_CHECK: ::c_int = 11;
pub const SO_PRIORITY: ::c_int = 12;
pub const SO_BSDCOMPAT: ::c_int = 14;
pub const SO_PASSCRED: ::c_int = 17;
pub const SO_PEERCRED: ::c_int = 18;
pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22;
pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23;
pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24;
pub const SO_BINDTODEVICE: ::c_int = 25;
pub const SO_ATTACH_FILTER: ::c_int = 26;
pub const SO_DETACH_FILTER: ::c_int = 27;
pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER;
pub const SO_PEERNAME: ::c_int = 28;
pub const SO_PEERSEC: ::c_int = 30;
pub const SO_SNDBUFFORCE: ::c_int = 31;
pub const SO_RCVBUFFORCE: ::c_int = 33;
pub const SO_PASSSEC: ::c_int = 34;
pub const SO_MARK: ::c_int = 36;
pub const SO_RXQ_OVFL: ::c_int = 40;
pub const SO_WIFI_STATUS: ::c_int = 41;
pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS;
pub const SO_PEEK_OFF: ::c_int = 42;
pub const SO_NOFCS: ::c_int = 43;
pub const SO_LOCK_FILTER: ::c_int = 44;
pub const SO_SELECT_ERR_QUEUE: ::c_int = 45;
pub const SO_BUSY_POLL: ::c_int = 46;
pub const SO_MAX_PACING_RATE: ::c_int = 47;
pub const SO_BPF_EXTENSIONS: ::c_int = 48;
pub const SO_INCOMING_CPU: ::c_int = 49;
pub const SO_ATTACH_BPF: ::c_int = 50;
pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER;
pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51;
pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52;
pub const SO_CNX_ADVICE: ::c_int = 53;
pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54;
pub const SO_MEMINFO: ::c_int = 55;
pub const SO_INCOMING_NAPI_ID: ::c_int = 56;
pub const SO_COOKIE: ::c_int = 57;
pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58;
pub const SO_PEERGROUPS: ::c_int = 59;
pub const SO_ZEROCOPY: ::c_int = 60;
pub const SO_TXTIME: ::c_int = 61;
pub const SCM_TXTIME: ::c_int = SO_TXTIME;
pub const SO_BINDTOIFINDEX: ::c_int = 62;
// NOTE: These definitions are now being renamed with _OLD postfix,
// but CI haven't support them yet.
// Some related consts could be found in b32.rs and b64.rs
pub const SO_TIMESTAMP: ::c_int = 29;
pub const SO_TIMESTAMPNS: ::c_int = 35;
pub const SO_TIMESTAMPING: ::c_int = 37;
// pub const SO_TIMESTAMP_OLD: ::c_int = 29;
// pub const SO_TIMESTAMPNS_OLD: ::c_int = 35;
// pub const SO_TIMESTAMPING_OLD: ::c_int = 37;
// pub const SO_TIMESTAMP_NEW: ::c_int = 63;
// pub const SO_TIMESTAMPNS_NEW: ::c_int = 64;
// pub const SO_TIMESTAMPING_NEW: ::c_int = 65;
// pub const SO_RCVTIMEO_NEW: ::c_int = 66;
// pub const SO_SNDTIMEO_NEW: ::c_int = 67;
// pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68;
// pub const SO_PREFER_BUSY_POLL: ::c_int = 69;
// pub const SO_BUSY_POLL_BUDGET: ::c_int = 70;

// Defined in unix/linux_like/mod.rs
// pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP;
pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS;
pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING;

pub const TIOCMGET: ::Ioctl = 0x741d;
pub const TIOCMBIS: ::Ioctl = 0x741b;
pub const TIOCMBIC: ::Ioctl = 0x741c;
pub const TIOCMSET: ::Ioctl = 0x741a;
pub const TCGETS2: ::Ioctl = 0x4030542a;
pub const TCSETS2: ::Ioctl = 0x8030542b;
pub const TCSETSW2: ::Ioctl = 0x8030542c;
pub const TCSETSF2: ::Ioctl = 0x8030542d;

pub const TIOCM_LE: ::c_int = 0x001;
pub const TIOCM_DTR: ::c_int = 0x002;
pub const TIOCM_RTS: ::c_int = 0x004;
pub const TIOCM_ST: ::c_int = 0x010;
pub const TIOCM_SR: ::c_int = 0x020;
pub const TIOCM_CTS: ::c_int = 0x040;
pub const TIOCM_CAR: ::c_int = 0x100;
pub const TIOCM_CD: ::c_int = TIOCM_CAR;
pub const TIOCM_RNG: ::c_int = 0x200;
pub const TIOCM_RI: ::c_int = TIOCM_RNG;
pub const TIOCM_DSR: ::c_int = 0x400;

pub const BOTHER: ::speed_t = 0o010000;
pub const IBSHIFT: ::tcflag_t = 16;

cfg_if! {
    if #[cfg(target_endian = "little")] {
        pub const BLKSSZGET: ::c_int = 0x1268;
        pub const BLKPBSZGET: ::c_int = 0x127B;
    } else if #[cfg(target_endian = "big")] {
        pub const BLKSSZGET: ::c_int = 0x20001268;
        pub const BLKPBSZGET: ::c_int = 0x2000127B;
    }
}
<|endoftext|>


<commit_before>//! Two- and three-dimensional array support.

use cl::*;
use cl::ll::*;
use mem::*;
use std::marker::PhantomData;
use std::mem;
use std::vec::Vec;
use libc::{size_t, c_void};

use hl::KernelArg;

pub struct Array3D<T> {
    width: usize,
    height: usize,
    depth: usize,
    dat: Vec<T>
}

pub struct Array3DCL<T> {
    width: usize,
    height: usize,
    depth: usize,
    buf: cl_mem,
    phantom: PhantomData<T>,
}

impl<T: Clone> Array3D<T> {
    pub fn new<F>(width: usize, height: usize, depth: usize,
                  val: F)
               -> Array3D<T>
        where F: Fn(usize, usize, usize) -> T
    {
        let mut dat: Vec<T> = Vec::new();
        for x in range(0, width) {
            for y in range(0, height) {
                for z in range(0, depth) {
                    dat.push(val(x, y, z));
                }
            }
        }

        Array3D {
            width: width,
            height: height,
            depth: depth,
            dat: dat
        }
    }

    pub fn set(&mut self, x: usize, y: usize, z: usize, val: T)
    {
        self.dat.as_mut_slice()[self.width*self.height*z + self.width*y + x] = val;
    }

    pub fn get(&self, x: usize, y: usize, z: usize) -> T
    {
        (&self.dat[..])[self.width*self.height*z + self.width*y + x].clone()
    }
}

#[unsafe_destructor]
impl<T> Drop for Array3DCL<T> {
    fn drop(&mut self) {
        unsafe {
            clReleaseMemObject(self.buf);
        }
    }
}

impl<'r, T> Put<Array3D<T>, Array3DCL<T>> for &'r Array3D<T>
{
    fn put<F>(&self, f: F)
           -> Array3DCL<T>
        where F: FnOnce(*const c_void, size_t) -> cl_mem
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        let out = f(p as *const c_void, (len * mem::size_of::<T>()) as size_t);

        Array3DCL{
            width: self.width,
            height: self.height,
            depth: self.depth,
            buf: out,
            phantom: PhantomData,
        }
    }
}

impl<T> Get<Array3DCL<T>, Array3D<T>> for Array3D<T>
{
    fn get<F>(arr: &Array3DCL<T>, f: F)
           -> Array3D<T>
        where F: FnOnce(size_t, *mut c_void, size_t)
    {
        let mut v: Vec<T> = Vec::with_capacity(arr.len());
        unsafe {
            v.set_len(arr.len());
        }

        let p = v.as_mut_ptr();
        let len = v.len();
        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t);

        Array3D {
            width: arr.width,
            height: arr.height,
            depth: arr.depth,
            dat: v,
        }
    }
}

impl<T> Write for Array3D<T> {
    fn write<F>(&self, f: F)
        where F: FnOnce(size_t, *const c_void, size_t)
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        f(0, p as *const c_void, (len * mem::size_of::<T>()) as size_t)
    }
}

impl<T> Read for Array3D<T> {
    fn read<F>(&mut self, f: F)
        where F: FnOnce(size_t, *mut c_void, size_t)
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t)
    }
}

impl<T> Buffer<T> for Array3DCL<T> {
    fn id_ptr(&self) -> *const cl_mem {
        &self.buf as *const cl_mem
    }

    fn len(&self) -> usize {
        self.width * self.height * self.depth
    }
}

impl<T> KernelArg for Array3DCL<T> {
    fn get_value(&self) -> (size_t, *const c_void)
    {
        (mem::size_of::<cl_mem>() as size_t,
         unsafe { self.id_ptr() } as *const c_void)
    }
}

pub struct Array2D<T> {
    width: usize,
    height: usize,
    dat: Vec<T>,
}

pub struct Array2DCL<T> {
    width: usize,
    height: usize,
    buf: cl_mem,
    phantom: PhantomData<T>,
}

impl<T: Clone> Array2D<T> {
    pub fn new<F>(width: usize, height: usize, val: F) -> Array2D<T>
        where F: Fn(usize, usize) -> T
    {
        let mut dat: Vec<T> = Vec::new();
        for x in range(0, width) {
            for y in range(0, height) {
                dat.push(val(x, y));
            }
        }
        Array2D {
            width: width,
            height: height,
            dat: dat,
        }
    }

    pub fn set(&mut self, x: usize, y: usize, val: T) {
        self.dat.as_mut_slice()[self.width*y + x] = val;
    }

    pub fn get(&self, x: usize, y: usize) -> T {
        (&self.dat[..])[self.width*y + x].clone()
    }
}

#[unsafe_destructor]
impl<T> Drop for Array2DCL<T> {
    fn drop(&mut self) {
        unsafe {
            clReleaseMemObject(self.buf);
        }
    }
}

impl<'r, T> Put<Array2D<T>, Array2DCL<T>> for &'r Array2D<T>
{
    fn put<F>(&self, f: F) -> Array2DCL<T>
        where F: FnOnce(*const c_void, size_t) -> cl_mem
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        let out = f(p as *const c_void, (len * mem::size_of::<T>()) as size_t);

        Array2DCL{
            width: self.width,
            height: self.height,
            buf: out,
            phantom: PhantomData,
        }
    }
}

impl<T> Get<Array2DCL<T>, Array2D<T>> for Array2D<T>
{
    fn get<F>(arr: &Array2DCL<T>, f: F)
           -> Array2D<T>
        where F: FnOnce(size_t, *mut c_void, size_t)
    {
        let mut v: Vec<T> = Vec::with_capacity(arr.len());
        unsafe {
            v.set_len(arr.len())
        }

        let p = v.as_mut_ptr();
        let len = v.len();
        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t);

        Array2D {
            width: arr.width,
            height: arr.height,
            dat: v
        }
    }
}

impl<T> Write for Array2D<T> {
    fn write<F>(&self, f: F)
        where F: FnOnce(size_t, *const c_void, size_t)
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        f(0, p as *const c_void, (len * mem::size_of::<T>()) as size_t)
    }
}

impl<T> Read for Array2D<T> {
    fn read<F>(&mut self, f: F)
        where F: FnOnce(size_t, *mut c_void, size_t)
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t)
    }
}

impl<T> Buffer<T> for Array2DCL<T> {
    fn id_ptr(&self) -> *const cl_mem {
        &self.buf as *const cl_mem
    }

    fn len(&self) -> usize {
        self.width * self.height
    }
}

impl<T> KernelArg for Array2DCL<T> {
    fn get_value(&self) -> (size_t, *const c_void)
    {
        (mem::size_of::<cl_mem>() as size_t,
         unsafe { self.id_ptr() } as *const c_void)
    }
}
<commit_msg>Add unsafe qualifier to id_ptr<commit_after>//! Two- and three-dimensional array support.

use cl::*;
use cl::ll::*;
use mem::*;
use std::marker::PhantomData;
use std::mem;
use std::vec::Vec;
use libc::{size_t, c_void};

use hl::KernelArg;

pub struct Array3D<T> {
    width: usize,
    height: usize,
    depth: usize,
    dat: Vec<T>
}

pub struct Array3DCL<T> {
    width: usize,
    height: usize,
    depth: usize,
    buf: cl_mem,
    phantom: PhantomData<T>,
}

impl<T: Clone> Array3D<T> {
    pub fn new<F>(width: usize, height: usize, depth: usize,
                  val: F)
               -> Array3D<T>
        where F: Fn(usize, usize, usize) -> T
    {
        let mut dat: Vec<T> = Vec::new();
        for x in range(0, width) {
            for y in range(0, height) {
                for z in range(0, depth) {
                    dat.push(val(x, y, z));
                }
            }
        }

        Array3D {
            width: width,
            height: height,
            depth: depth,
            dat: dat
        }
    }

    pub fn set(&mut self, x: usize, y: usize, z: usize, val: T)
    {
        self.dat.as_mut_slice()[self.width*self.height*z + self.width*y + x] = val;
    }

    pub fn get(&self, x: usize, y: usize, z: usize) -> T
    {
        (&self.dat[..])[self.width*self.height*z + self.width*y + x].clone()
    }
}

#[unsafe_destructor]
impl<T> Drop for Array3DCL<T> {
    fn drop(&mut self) {
        unsafe {
            clReleaseMemObject(self.buf);
        }
    }
}

impl<'r, T> Put<Array3D<T>, Array3DCL<T>> for &'r Array3D<T>
{
    fn put<F>(&self, f: F)
           -> Array3DCL<T>
        where F: FnOnce(*const c_void, size_t) -> cl_mem
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        let out = f(p as *const c_void, (len * mem::size_of::<T>()) as size_t);

        Array3DCL{
            width: self.width,
            height: self.height,
            depth: self.depth,
            buf: out,
            phantom: PhantomData,
        }
    }
}

impl<T> Get<Array3DCL<T>, Array3D<T>> for Array3D<T>
{
    fn get<F>(arr: &Array3DCL<T>, f: F)
           -> Array3D<T>
        where F: FnOnce(size_t, *mut c_void, size_t)
    {
        let mut v: Vec<T> = Vec::with_capacity(arr.len());
        unsafe {
            v.set_len(arr.len());
        }

        let p = v.as_mut_ptr();
        let len = v.len();
        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t);

        Array3D {
            width: arr.width,
            height: arr.height,
            depth: arr.depth,
            dat: v,
        }
    }
}

impl<T> Write for Array3D<T> {
    fn write<F>(&self, f: F)
        where F: FnOnce(size_t, *const c_void, size_t)
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        f(0, p as *const c_void, (len * mem::size_of::<T>()) as size_t)
    }
}

impl<T> Read for Array3D<T> {
    fn read<F>(&mut self, f: F)
        where F: FnOnce(size_t, *mut c_void, size_t)
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t)
    }
}

impl<T> Buffer<T> for Array3DCL<T> {
    unsafe fn id_ptr(&self) -> *const cl_mem {
        &self.buf as *const cl_mem
    }

    fn len(&self) -> usize {
        self.width * self.height * self.depth
    }
}

impl<T> KernelArg for Array3DCL<T> {
    fn get_value(&self) -> (size_t, *const c_void)
    {
        (mem::size_of::<cl_mem>() as size_t,
         unsafe { self.id_ptr() } as *const c_void)
    }
}

pub struct Array2D<T> {
    width: usize,
    height: usize,
    dat: Vec<T>,
}

pub struct Array2DCL<T> {
    width: usize,
    height: usize,
    buf: cl_mem,
    phantom: PhantomData<T>,
}

impl<T: Clone> Array2D<T> {
    pub fn new<F>(width: usize, height: usize, val: F) -> Array2D<T>
        where F: Fn(usize, usize) -> T
    {
        let mut dat: Vec<T> = Vec::new();
        for x in range(0, width) {
            for y in range(0, height) {
                dat.push(val(x, y));
            }
        }
        Array2D {
            width: width,
            height: height,
            dat: dat,
        }
    }

    pub fn set(&mut self, x: usize, y: usize, val: T) {
        self.dat.as_mut_slice()[self.width*y + x] = val;
    }

    pub fn get(&self, x: usize, y: usize) -> T {
        (&self.dat[..])[self.width*y + x].clone()
    }
}

#[unsafe_destructor]
impl<T> Drop for Array2DCL<T> {
    fn drop(&mut self) {
        unsafe {
            clReleaseMemObject(self.buf);
        }
    }
}

impl<'r, T> Put<Array2D<T>, Array2DCL<T>> for &'r Array2D<T>
{
    fn put<F>(&self, f: F) -> Array2DCL<T>
        where F: FnOnce(*const c_void, size_t) -> cl_mem
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        let out = f(p as *const c_void, (len * mem::size_of::<T>()) as size_t);

        Array2DCL{
            width: self.width,
            height: self.height,
            buf: out,
            phantom: PhantomData,
        }
    }
}

impl<T> Get<Array2DCL<T>, Array2D<T>> for Array2D<T>
{
    fn get<F>(arr: &Array2DCL<T>, f: F)
           -> Array2D<T>
        where F: FnOnce(size_t, *mut c_void, size_t)
    {
        let mut v: Vec<T> = Vec::with_capacity(arr.len());
        unsafe {
            v.set_len(arr.len())
        }

        let p = v.as_mut_ptr();
        let len = v.len();
        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t);

        Array2D {
            width: arr.width,
            height: arr.height,
            dat: v
        }
    }
}

impl<T> Write for Array2D<T> {
    fn write<F>(&self, f: F)
        where F: FnOnce(size_t, *const c_void, size_t)
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        f(0, p as *const c_void, (len * mem::size_of::<T>()) as size_t)
    }
}

impl<T> Read for Array2D<T> {
    fn read<F>(&mut self, f: F)
        where F: FnOnce(size_t, *mut c_void, size_t)
    {
        let p = self.dat.as_ptr();
        let len = self.dat.len();
        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t)
    }
}

impl<T> Buffer<T> for Array2DCL<T> {
    unsafe fn id_ptr(&self) -> *const cl_mem {
        &self.buf as *const cl_mem
    }

    fn len(&self) -> usize {
        self.width * self.height
    }
}

impl<T> KernelArg for Array2DCL<T> {
    fn get_value(&self) -> (size_t, *const c_void)
    {
        (mem::size_of::<cl_mem>() as size_t,
         unsafe { self.id_ptr() } as *const c_void)
    }
}
<|endoftext|>


<commit_before>
// TODO:
// Implement repeat command

use std::io::Write;
use vm::VirtualMachine;

pub struct CommandSystem {
    commands: Vec<Box<Command>>,
}
impl CommandSystem {
    pub fn new() -> CommandSystem {
        let mut system = CommandSystem {
            commands: Vec::new()
        };

        system.add_command(HelpCommand);
        system.add_command(ClearCommand);
        system.add_command(SourceCommand);
        system.add_command(ListCommand);
        system.add_command(RegistersCommand);
        system.add_command(StepCommand);
        system.add_command(ContinueCommand);
        system.add_command(BreakCommand);
        system.add_command(FlagsCommand);
        system.add_command(MemdmpCommand);
        system.add_command(MemsetCommand);
        system.add_command(MonitorCommand);

        system
    }

    pub fn add_command<C>(&mut self, command: C)
        where C: Command + 'static
    {
        self.commands.push(Box::new(command));
    }

    pub fn execute<S>(&self, command: S, mut vm: &mut VirtualMachine) -> bool
        where S: Into<String>
    {
        let command = command.into();
        let parts = command.split_whitespace().map(String::from).collect::<Vec<_>>();

        for command in &self.commands {
            if command.matches_name(parts[0].clone()) {
                command.execute(parts[1..].to_owned(), &self, &mut vm);
                return true;
            }
        }

        false
    }
}

pub trait Command {
    fn execute(&self, args: Vec<String>, system: &CommandSystem, vm: &mut VirtualMachine);

    fn get_names(&self) -> Vec<&str>;

    fn get_arg_info(&self) -> Option<&str> {
        None
    }

    fn get_help(&self) -> &str {
        "No help text provided!"
    }

    fn matches_name(&self, name: String) -> bool {
        for actual_name in self.get_names() {
            if actual_name == name {
                return true;
            }
        }
        return false
    }
}

struct HelpCommand;
impl Command for HelpCommand {
    fn execute(&self, _args: Vec<String>, system: &CommandSystem, vm: &mut VirtualMachine) {
        writeln!(vm.console, "Commands:").unwrap();

        // Creates strings containing all names, e.g. "help, h, ?"
        for command in system.commands.iter() {
            let name = command.get_names().join(", ");
            write!(vm.console, "   {}", name).unwrap();
            if let Some(arg_info) = command.get_arg_info() {
                write!(vm.console, ": {}", arg_info).unwrap();
            }
            writeln!(vm.console, "").unwrap();

            let help = command.get_help();
            let help_lines = help.trim().lines().map(|line| line.trim()).collect::<Vec<_>>();
            if !help_lines.is_empty() {
                for help_line in &help_lines {
                    writeln!(vm.console, "      {}", help_line).unwrap();;
                }
            }
        }
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["help", "h", "?"]
    }

    fn get_help(&self) -> &str {
        "Prints this help message"
    }
}

struct ClearCommand;
impl Command for ClearCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.console.clear();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["clear", "cls"]
    }

    fn get_help(&self) -> &str {
        "Clears the console"
    }
}

struct SourceCommand;
impl Command for SourceCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.dump_disassembly();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["source"]
    }

    fn get_help(&self) -> &str {
        "Lists the code currently running in the virtual
         machine. A '>' symbol indicates the current
         program counter."
    }
}

struct ListCommand;
impl Command for ListCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.dump_local_disassembly();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["list"]
    }

    fn get_help(&self) -> &str {
        "Lists the code surrounding the current
         program counter."
    }
}

struct RegistersCommand;
impl Command for RegistersCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.dump_registers();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["registers", "reg"]
    }

    fn get_help(&self) -> &str {
        "Lists the CPU registers and their current
         values."
    }
}

struct MonitorCommand;
impl Command for MonitorCommand {
    fn execute(&self, args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        if args.is_empty() && vm.is_memory_monitor_enabled() {
            vm.disable_memory_monitor();
            writeln!(vm.console, "Disabling memory monitor").unwrap();
            return;
        }

        if args.len() != 2 {
            writeln!(vm.console, "Expected 2 arguments, found {}", args.len()).unwrap();
            return;
        }

        let start = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
        if start.is_err() {
            writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[0]).unwrap();
            return;
        }
        let start = start.unwrap();

        let end = usize::from_str_radix(&args[1].replace("0x", "")[..], 16);
        if end.is_err() {
            writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[1]).unwrap();
            return;
        }
        let end = end.unwrap();

        vm.enable_memory_monitor(start..end);
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["monitor", "mon"]
    }

    fn get_arg_info(&self) -> Option<&str> {
        Some("start end")
    }

    fn get_help(&self) -> &str {
        "Dumps the memory between <start> and <end>
         (inclusive) every seconds. Press ENTER to
         stop monitoring."
    }
}

struct MemsetCommand;
impl Command for MemsetCommand {
    fn execute(&self, args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        if args.len() < 2 {
            writeln!(vm.console,
                "Expected 2 arguments. E.g.: memset 0x00 0x01 stores 0x01 at address 0x00"
            ).unwrap();
            return;
        }

        let start = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
        if start.is_err() {
            writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[0]).unwrap();
            return;
        }
        let start = start.unwrap();

        let bytes = {
            let mut bytes = Vec::new();
            for index in 1..args.len() {
                let byte = u8::from_str_radix(&args[index].replace("0x", "")[..], 16);
                if byte.is_err() {
                    writeln!(vm.console, "Expected hexadecimal byte, found {}", args[index]).unwrap();
                    return;
                }
                bytes.push(byte.unwrap());
            }
            bytes
        };

        for (index, byte) in bytes.iter().enumerate() {
            vm.cpu.memory[start + index] = *byte;
        }
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["memset", "set"]
    }

    fn get_arg_info(&self) -> Option<&str> {
        Some("addres value [values, ...]")
    }

    fn get_help(&self) -> &str {
        "Writes the given value to the given address.
         Multiple values will be written to consequent
         addresses."
    }
}

struct MemdmpCommand;
impl Command for MemdmpCommand {
    fn execute(&self, args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        if args.is_empty() || args.len() > 2 {
            writeln!(vm.console, "Expected either 1 or 2 arguments, found {}", args.len()).unwrap();
            return;
        }

        // Dump a page
        if args.len() == 1 {
            let page = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
            if page.is_err() {
                writeln!(vm.console, "Expected page index, found {}", args[0]).unwrap();
                return;
            }
            let page = page.unwrap();

            vm.dump_memory_page(page);

        // Dump a range
        } else if args.len() == 2 {
            let start = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
            if start.is_err() {
                writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[0]).unwrap();
                return;
            }
            let start = start.unwrap();

            let end = usize::from_str_radix(&args[1].replace("0x", "")[..], 16);
            if end.is_err() {
                writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[1]).unwrap();
                return;
            }
            let end = end.unwrap();

            vm.dump_memory_range(start, end);
        }
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["memdmp", "dmp"]
    }

    fn get_arg_info(&self) -> Option<&str> {
        Some("page OR start end")
    }

    fn get_help(&self) -> &str {
        "Dumps a single memory page, or a specified memory
         range from <start> to <end>."
    }
}

struct FlagsCommand;
impl Command for FlagsCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.dump_flags();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["flags"]
    }

    fn get_help(&self) -> &str {
        "Not yet implemented"
    }
}

struct BreakCommand;
impl Command for BreakCommand {
    fn execute(&self, args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        if args.len() > 1 {
            writeln!(vm.console, "Expected 0 or 1 arguments, found {}", args.len()).unwrap();
            return;
        }

        // Break at the given address
        if args.len() == 1 {
            let address = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
            if address.is_err() {
                writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[0]).unwrap();
            }
            let address = address.unwrap();

            if address <= u16::max_value() as usize {
                if vm.toggle_breakpoint(address) {
                    writeln!(vm.console, "Added breakpoint at {:04X}", address).unwrap();
                } else {
                    writeln!(vm.console, "Removed breakpoint at {:04X}", address).unwrap();
                }
            } else {
                writeln!(vm.console, "Address outside addressable range.").unwrap();
            }

        // Break at current program counter
        } else {
            vm.break_execution();
            writeln!(vm.console, "Breaking execution at {:04X}", vm.cpu.registers.PC).unwrap();
        }
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["break", "b"]
    }

    fn get_arg_info(&self) -> Option<&str> {
        Some("[address]")
    }

    fn get_help(&self) -> &str {
        "Toggles a breakpoint at the specified <address>.
         If the program counter hits this address, execution
         stops. If no address is specified, execution will
         be stopped at the current point, without inserting
         a program counter."
    }
}

struct ContinueCommand;
impl Command for ContinueCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.continue_execution();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["continue", "c"]
    }

    fn get_help(&self) -> &str {
        "Resumes program execution after the program
         has stopped at a breakpoint."
    }
}

struct StepCommand;
impl Command for StepCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.step_execution();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["step", "s"]
    }

    fn get_help(&self) -> &str {
        "Executes a single instruction, then stops
         execution"
    }
}

<commit_msg>Change program counter to breakpoint on line 386<commit_after>
use std::io::Write;
use vm::VirtualMachine;

pub struct CommandSystem {
    commands: Vec<Box<Command>>,
}
impl CommandSystem {
    pub fn new() -> CommandSystem {
        let mut system = CommandSystem {
            commands: Vec::new()
        };

        system.add_command(HelpCommand);
        system.add_command(ClearCommand);
        system.add_command(SourceCommand);
        system.add_command(ListCommand);
        system.add_command(RegistersCommand);
        system.add_command(StepCommand);
        system.add_command(ContinueCommand);
        system.add_command(BreakCommand);
        system.add_command(FlagsCommand);
        system.add_command(MemdmpCommand);
        system.add_command(MemsetCommand);
        system.add_command(MonitorCommand);

        system
    }

    pub fn add_command<C>(&mut self, command: C)
        where C: Command + 'static
    {
        self.commands.push(Box::new(command));
    }

    pub fn execute<S>(&self, command: S, mut vm: &mut VirtualMachine) -> bool
        where S: Into<String>
    {
        let command = command.into();
        let parts = command.split_whitespace().map(String::from).collect::<Vec<_>>();

        for command in &self.commands {
            if command.matches_name(parts[0].clone()) {
                command.execute(parts[1..].to_owned(), &self, &mut vm);
                return true;
            }
        }

        false
    }
}

pub trait Command {
    fn execute(&self, args: Vec<String>, system: &CommandSystem, vm: &mut VirtualMachine);

    fn get_names(&self) -> Vec<&str>;

    fn get_arg_info(&self) -> Option<&str> {
        None
    }

    fn get_help(&self) -> &str {
        "No help text provided!"
    }

    fn matches_name(&self, name: String) -> bool {
        for actual_name in self.get_names() {
            if actual_name == name {
                return true;
            }
        }
        return false
    }
}

struct HelpCommand;
impl Command for HelpCommand {
    fn execute(&self, _args: Vec<String>, system: &CommandSystem, vm: &mut VirtualMachine) {
        writeln!(vm.console, "Commands:").unwrap();

        // Creates strings containing all names, e.g. "help, h, ?"
        for command in system.commands.iter() {
            let name = command.get_names().join(", ");
            write!(vm.console, "   {}", name).unwrap();
            if let Some(arg_info) = command.get_arg_info() {
                write!(vm.console, ": {}", arg_info).unwrap();
            }
            writeln!(vm.console, "").unwrap();

            let help = command.get_help();
            let help_lines = help.trim().lines().map(|line| line.trim()).collect::<Vec<_>>();
            if !help_lines.is_empty() {
                for help_line in &help_lines {
                    writeln!(vm.console, "      {}", help_line).unwrap();;
                }
            }
        }
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["help", "h", "?"]
    }

    fn get_help(&self) -> &str {
        "Prints this help message"
    }
}

struct ClearCommand;
impl Command for ClearCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.console.clear();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["clear", "cls"]
    }

    fn get_help(&self) -> &str {
        "Clears the console"
    }
}

struct SourceCommand;
impl Command for SourceCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.dump_disassembly();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["source"]
    }

    fn get_help(&self) -> &str {
        "Lists the code currently running in the virtual
         machine. A '>' symbol indicates the current
         program counter."
    }
}

struct ListCommand;
impl Command for ListCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.dump_local_disassembly();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["list"]
    }

    fn get_help(&self) -> &str {
        "Lists the code surrounding the current
         program counter."
    }
}

struct RegistersCommand;
impl Command for RegistersCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.dump_registers();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["registers", "reg"]
    }

    fn get_help(&self) -> &str {
        "Lists the CPU registers and their current
         values."
    }
}

struct MonitorCommand;
impl Command for MonitorCommand {
    fn execute(&self, args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        if args.is_empty() && vm.is_memory_monitor_enabled() {
            vm.disable_memory_monitor();
            writeln!(vm.console, "Disabling memory monitor").unwrap();
            return;
        }

        if args.len() != 2 {
            writeln!(vm.console, "Expected 2 arguments, found {}", args.len()).unwrap();
            return;
        }

        let start = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
        if start.is_err() {
            writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[0]).unwrap();
            return;
        }
        let start = start.unwrap();

        let end = usize::from_str_radix(&args[1].replace("0x", "")[..], 16);
        if end.is_err() {
            writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[1]).unwrap();
            return;
        }
        let end = end.unwrap();

        vm.enable_memory_monitor(start..end);
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["monitor", "mon"]
    }

    fn get_arg_info(&self) -> Option<&str> {
        Some("start end")
    }

    fn get_help(&self) -> &str {
        "Dumps the memory between <start> and <end>
         (inclusive) every seconds. Press ENTER to
         stop monitoring."
    }
}

struct MemsetCommand;
impl Command for MemsetCommand {
    fn execute(&self, args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        if args.len() < 2 {
            writeln!(vm.console,
                "Expected 2 arguments. E.g.: memset 0x00 0x01 stores 0x01 at address 0x00"
            ).unwrap();
            return;
        }

        let start = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
        if start.is_err() {
            writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[0]).unwrap();
            return;
        }
        let start = start.unwrap();

        let bytes = {
            let mut bytes = Vec::new();
            for index in 1..args.len() {
                let byte = u8::from_str_radix(&args[index].replace("0x", "")[..], 16);
                if byte.is_err() {
                    writeln!(vm.console, "Expected hexadecimal byte, found {}", args[index]).unwrap();
                    return;
                }
                bytes.push(byte.unwrap());
            }
            bytes
        };

        for (index, byte) in bytes.iter().enumerate() {
            vm.cpu.memory[start + index] = *byte;
        }
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["memset", "set"]
    }

    fn get_arg_info(&self) -> Option<&str> {
        Some("addres value [values, ...]")
    }

    fn get_help(&self) -> &str {
        "Writes the given value to the given address.
         Multiple values will be written to consequent
         addresses."
    }
}

struct MemdmpCommand;
impl Command for MemdmpCommand {
    fn execute(&self, args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        if args.is_empty() || args.len() > 2 {
            writeln!(vm.console, "Expected either 1 or 2 arguments, found {}", args.len()).unwrap();
            return;
        }

        // Dump a page
        if args.len() == 1 {
            let page = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
            if page.is_err() {
                writeln!(vm.console, "Expected page index, found {}", args[0]).unwrap();
                return;
            }
            let page = page.unwrap();

            vm.dump_memory_page(page);

        // Dump a range
        } else if args.len() == 2 {
            let start = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
            if start.is_err() {
                writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[0]).unwrap();
                return;
            }
            let start = start.unwrap();

            let end = usize::from_str_radix(&args[1].replace("0x", "")[..], 16);
            if end.is_err() {
                writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[1]).unwrap();
                return;
            }
            let end = end.unwrap();

            vm.dump_memory_range(start, end);
        }
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["memdmp", "dmp"]
    }

    fn get_arg_info(&self) -> Option<&str> {
        Some("page OR start end")
    }

    fn get_help(&self) -> &str {
        "Dumps a single memory page, or a specified memory
         range from <start> to <end>."
    }
}

struct FlagsCommand;
impl Command for FlagsCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.dump_flags();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["flags"]
    }

    fn get_help(&self) -> &str {
        "Not yet implemented"
    }
}

struct BreakCommand;
impl Command for BreakCommand {
    fn execute(&self, args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        if args.len() > 1 {
            writeln!(vm.console, "Expected 0 or 1 arguments, found {}", args.len()).unwrap();
            return;
        }

        // Break at the given address
        if args.len() == 1 {
            let address = usize::from_str_radix(&args[0].replace("0x", "")[..], 16);
            if address.is_err() {
                writeln!(vm.console, "Expected hexadecimal memory address, found {}", args[0]).unwrap();
            }
            let address = address.unwrap();

            if address <= u16::max_value() as usize {
                if vm.toggle_breakpoint(address) {
                    writeln!(vm.console, "Added breakpoint at {:04X}", address).unwrap();
                } else {
                    writeln!(vm.console, "Removed breakpoint at {:04X}", address).unwrap();
                }
            } else {
                writeln!(vm.console, "Address outside addressable range.").unwrap();
            }

        // Break at current program counter
        } else {
            vm.break_execution();
            writeln!(vm.console, "Breaking execution at {:04X}", vm.cpu.registers.PC).unwrap();
        }
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["break", "b"]
    }

    fn get_arg_info(&self) -> Option<&str> {
        Some("[address]")
    }

    fn get_help(&self) -> &str {
        "Toggles a breakpoint at the specified <address>.
         If the program counter hits this address, execution
         stops. If no address is specified, execution will
         be stopped at the current point, without inserting
         a breakpoint."
    }
}

struct ContinueCommand;
impl Command for ContinueCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.continue_execution();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["continue", "c"]
    }

    fn get_help(&self) -> &str {
        "Resumes program execution after the program
         has stopped at a breakpoint."
    }
}

struct StepCommand;
impl Command for StepCommand {
    fn execute(&self, _args: Vec<String>, _system: &CommandSystem, vm: &mut VirtualMachine) {
        vm.step_execution();
    }

    fn get_names(&self) -> Vec<&str> {
        vec!["step", "s"]
    }

    fn get_help(&self) -> &str {
        "Executes a single instruction, then stops
         execution"
    }
}

<|endoftext|>