<commit_before>// The following definitions are correct for arm and i686,
// but may be wrong for mips

pub type c_long = i32;
pub type c_ulong = u32;
pub type mode_t = u16;
pub type off64_t = ::c_longlong;
pub type sigset_t = ::c_ulong;
pub type socklen_t = i32;
pub type time64_t = i64;
pub type __u64 = ::c_ulonglong;

s! {
    pub struct sigaction {
        pub sa_sigaction: ::sighandler_t,
        pub sa_mask: ::sigset_t,
        pub sa_flags: ::c_int,
        pub sa_restorer: ::Option<extern fn()>,
    }

    pub struct rlimit64 {
        pub rlim_cur: u64,
        pub rlim_max: u64,
    }

    pub struct stat {
        pub st_dev: ::c_ulonglong,
        __pad0: [::c_uchar; 4],
        __st_ino: ::ino_t,
        pub st_mode: ::c_uint,
        pub st_nlink: ::nlink_t,
        pub st_uid: ::uid_t,
        pub st_gid: ::gid_t,
        pub st_rdev: ::c_ulonglong,
        __pad3: [::c_uchar; 4],
        pub st_size: ::c_longlong,
        pub st_blksize: ::blksize_t,
        pub st_blocks: ::c_ulonglong,
        pub st_atime: ::c_long,
        pub st_atime_nsec: ::c_long,
        pub st_mtime: ::c_long,
        pub st_mtime_nsec: ::c_long,
        pub st_ctime: ::c_long,
        pub st_ctime_nsec: ::c_long,
        pub st_ino: ::c_ulonglong,
    }

    pub struct stat64 {
        pub st_dev: ::c_ulonglong,
        __pad0: [::c_uchar; 4],
        __st_ino: ::ino_t,
        pub st_mode: ::c_uint,
        pub st_nlink: ::nlink_t,
        pub st_uid: ::uid_t,
        pub st_gid: ::gid_t,
        pub st_rdev: ::c_ulonglong,
        __pad3: [::c_uchar; 4],
        pub st_size: ::c_longlong,
        pub st_blksize: ::blksize_t,
        pub st_blocks: ::c_ulonglong,
        pub st_atime: ::c_long,
        pub st_atime_nsec: ::c_long,
        pub st_mtime: ::c_long,
        pub st_mtime_nsec: ::c_long,
        pub st_ctime: ::c_long,
        pub st_ctime_nsec: ::c_long,
        pub st_ino: ::c_ulonglong,
    }

    pub struct statfs64 {
        pub f_type: u32,
        pub f_bsize: u32,
        pub f_blocks: u64,
        pub f_bfree: u64,
        pub f_bavail: u64,
        pub f_files: u64,
        pub f_ffree: u64,
        pub f_fsid: ::__fsid_t,
        pub f_namelen: u32,
        pub f_frsize: u32,
        pub f_flags: u32,
        pub f_spare: [u32; 4],
    }

    pub struct statvfs64 {
        pub f_bsize: ::c_ulong,
        pub f_frsize: ::c_ulong,
        pub f_blocks: ::c_ulong,
        pub f_bfree: ::c_ulong,
        pub f_bavail: ::c_ulong,
        pub f_files: ::c_ulong,
        pub f_ffree: ::c_ulong,
        pub f_favail: ::c_ulong,
        pub f_fsid: ::c_ulong,
        pub f_flag: ::c_ulong,
        pub f_namemax: ::c_ulong,
    }

    pub struct pthread_attr_t {
        pub flags: u32,
        pub stack_base: *mut ::c_void,
        pub stack_size: ::size_t,
        pub guard_size: ::size_t,
        pub sched_policy: i32,
        pub sched_priority: i32,
    }

    pub struct pthread_mutex_t { value: ::c_int }

    pub struct pthread_cond_t { value: ::c_int }

    pub struct pthread_rwlock_t {
        lock: pthread_mutex_t,
        cond: pthread_cond_t,
        numLocks: ::c_int,
        writerThreadId: ::c_int,
        pendingReaders: ::c_int,
        pendingWriters: ::c_int,
        attr: i32,
        __reserved: [::c_char; 12],
    }

    pub struct pthread_barrier_t {
        __private: [i32; 8],
    }

    pub struct pthread_spinlock_t {
        __private: [i32; 2],
    }

    pub struct passwd {
        pub pw_name: *mut ::c_char,
        pub pw_passwd: *mut ::c_char,
        pub pw_uid: ::uid_t,
        pub pw_gid: ::gid_t,
        pub pw_dir: *mut ::c_char,
        pub pw_shell: *mut ::c_char,
    }

    pub struct statfs {
        pub f_type: u32,
        pub f_bsize: u32,
        pub f_blocks: u64,
        pub f_bfree: u64,
        pub f_bavail: u64,
        pub f_files: u64,
        pub f_ffree: u64,
        pub f_fsid: ::__fsid_t,
        pub f_namelen: u32,
        pub f_frsize: u32,
        pub f_flags: u32,
        pub f_spare: [u32; 4],
    }

    pub struct sysinfo {
        pub uptime: ::c_long,
        pub loads: [::c_ulong; 3],
        pub totalram: ::c_ulong,
        pub freeram: ::c_ulong,
        pub sharedram: ::c_ulong,
        pub bufferram: ::c_ulong,
        pub totalswap: ::c_ulong,
        pub freeswap: ::c_ulong,
        pub procs: ::c_ushort,
        pub pad: ::c_ushort,
        pub totalhigh: ::c_ulong,
        pub freehigh: ::c_ulong,
        pub mem_unit: ::c_uint,
        pub _f: [::c_char; 8],
    }
}

s_no_extra_traits! {
    pub struct sigset64_t {
        __bits: [::c_ulong; 2]
    }
}

cfg_if! {
    if #[cfg(feature = "extra_traits")] {
        impl ::fmt::Debug for sigset64_t {
            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
                f.debug_struct("sigset64_t")
                    .field("__bits", &self.__bits)
                    .finish()
            }
        }
    }
}

// These constants must be of the same type of sigaction.sa_flags
pub const SA_NOCLDSTOP: ::c_int = 0x00000001;
pub const SA_NOCLDWAIT: ::c_int = 0x00000002;
pub const SA_NODEFER: ::c_int = 0x40000000;
pub const SA_ONSTACK: ::c_int = 0x08000000;
pub const SA_RESETHAND: ::c_int = 0x80000000;
pub const SA_RESTART: ::c_int = 0x10000000;
pub const SA_SIGINFO: ::c_int = 0x00000004;

pub const RTLD_GLOBAL: ::c_int = 2;
pub const RTLD_NOW: ::c_int = 0;
pub const RTLD_DEFAULT: *mut ::c_void = -1isize as *mut ::c_void;

pub const PTRACE_GETFPREGS: ::c_int = 14;
pub const PTRACE_SETFPREGS: ::c_int = 15;
pub const PTRACE_GETREGS: ::c_int = 12;
pub const PTRACE_SETREGS: ::c_int = 13;

pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { value: 0 };
pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { value: 0 };
pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
    lock: PTHREAD_MUTEX_INITIALIZER,
    cond: PTHREAD_COND_INITIALIZER,
    numLocks: 0,
    writerThreadId: 0,
    pendingReaders: 0,
    pendingWriters: 0,
    attr: 0,
    __reserved: [0; 12],
};
pub const PTHREAD_STACK_MIN: ::size_t = 4096 * 2;
pub const CPU_SETSIZE: ::size_t = 32;
pub const __CPU_BITS: ::size_t = 32;

pub const UT_LINESIZE: usize = 8;
pub const UT_NAMESIZE: usize = 8;
pub const UT_HOSTSIZE: usize = 16;

pub const SIGSTKSZ: ::size_t = 8192;
pub const MINSIGSTKSZ: ::size_t = 2048;

extern "C" {
    pub fn timegm64(tm: *const ::tm) -> ::time64_t;
}

cfg_if! {
    if #[cfg(target_arch = "x86")] {
        mod x86;
        pub use self::x86::*;
    } else if #[cfg(target_arch = "arm")] {
        mod arm;
        pub use self::arm::*;
    } else {
        // Unknown target_arch
    }
}
<commit_msg>Remove existing shadowed PTRACE_GETREGS/PTRACE_SETREGS<commit_after>// The following definitions are correct for arm and i686,
// but may be wrong for mips

pub type c_long = i32;
pub type c_ulong = u32;
pub type mode_t = u16;
pub type off64_t = ::c_longlong;
pub type sigset_t = ::c_ulong;
pub type socklen_t = i32;
pub type time64_t = i64;
pub type __u64 = ::c_ulonglong;

s! {
    pub struct sigaction {
        pub sa_sigaction: ::sighandler_t,
        pub sa_mask: ::sigset_t,
        pub sa_flags: ::c_int,
        pub sa_restorer: ::Option<extern fn()>,
    }

    pub struct rlimit64 {
        pub rlim_cur: u64,
        pub rlim_max: u64,
    }

    pub struct stat {
        pub st_dev: ::c_ulonglong,
        __pad0: [::c_uchar; 4],
        __st_ino: ::ino_t,
        pub st_mode: ::c_uint,
        pub st_nlink: ::nlink_t,
        pub st_uid: ::uid_t,
        pub st_gid: ::gid_t,
        pub st_rdev: ::c_ulonglong,
        __pad3: [::c_uchar; 4],
        pub st_size: ::c_longlong,
        pub st_blksize: ::blksize_t,
        pub st_blocks: ::c_ulonglong,
        pub st_atime: ::c_long,
        pub st_atime_nsec: ::c_long,
        pub st_mtime: ::c_long,
        pub st_mtime_nsec: ::c_long,
        pub st_ctime: ::c_long,
        pub st_ctime_nsec: ::c_long,
        pub st_ino: ::c_ulonglong,
    }

    pub struct stat64 {
        pub st_dev: ::c_ulonglong,
        __pad0: [::c_uchar; 4],
        __st_ino: ::ino_t,
        pub st_mode: ::c_uint,
        pub st_nlink: ::nlink_t,
        pub st_uid: ::uid_t,
        pub st_gid: ::gid_t,
        pub st_rdev: ::c_ulonglong,
        __pad3: [::c_uchar; 4],
        pub st_size: ::c_longlong,
        pub st_blksize: ::blksize_t,
        pub st_blocks: ::c_ulonglong,
        pub st_atime: ::c_long,
        pub st_atime_nsec: ::c_long,
        pub st_mtime: ::c_long,
        pub st_mtime_nsec: ::c_long,
        pub st_ctime: ::c_long,
        pub st_ctime_nsec: ::c_long,
        pub st_ino: ::c_ulonglong,
    }

    pub struct statfs64 {
        pub f_type: u32,
        pub f_bsize: u32,
        pub f_blocks: u64,
        pub f_bfree: u64,
        pub f_bavail: u64,
        pub f_files: u64,
        pub f_ffree: u64,
        pub f_fsid: ::__fsid_t,
        pub f_namelen: u32,
        pub f_frsize: u32,
        pub f_flags: u32,
        pub f_spare: [u32; 4],
    }

    pub struct statvfs64 {
        pub f_bsize: ::c_ulong,
        pub f_frsize: ::c_ulong,
        pub f_blocks: ::c_ulong,
        pub f_bfree: ::c_ulong,
        pub f_bavail: ::c_ulong,
        pub f_files: ::c_ulong,
        pub f_ffree: ::c_ulong,
        pub f_favail: ::c_ulong,
        pub f_fsid: ::c_ulong,
        pub f_flag: ::c_ulong,
        pub f_namemax: ::c_ulong,
    }

    pub struct pthread_attr_t {
        pub flags: u32,
        pub stack_base: *mut ::c_void,
        pub stack_size: ::size_t,
        pub guard_size: ::size_t,
        pub sched_policy: i32,
        pub sched_priority: i32,
    }

    pub struct pthread_mutex_t { value: ::c_int }

    pub struct pthread_cond_t { value: ::c_int }

    pub struct pthread_rwlock_t {
        lock: pthread_mutex_t,
        cond: pthread_cond_t,
        numLocks: ::c_int,
        writerThreadId: ::c_int,
        pendingReaders: ::c_int,
        pendingWriters: ::c_int,
        attr: i32,
        __reserved: [::c_char; 12],
    }

    pub struct pthread_barrier_t {
        __private: [i32; 8],
    }

    pub struct pthread_spinlock_t {
        __private: [i32; 2],
    }

    pub struct passwd {
        pub pw_name: *mut ::c_char,
        pub pw_passwd: *mut ::c_char,
        pub pw_uid: ::uid_t,
        pub pw_gid: ::gid_t,
        pub pw_dir: *mut ::c_char,
        pub pw_shell: *mut ::c_char,
    }

    pub struct statfs {
        pub f_type: u32,
        pub f_bsize: u32,
        pub f_blocks: u64,
        pub f_bfree: u64,
        pub f_bavail: u64,
        pub f_files: u64,
        pub f_ffree: u64,
        pub f_fsid: ::__fsid_t,
        pub f_namelen: u32,
        pub f_frsize: u32,
        pub f_flags: u32,
        pub f_spare: [u32; 4],
    }

    pub struct sysinfo {
        pub uptime: ::c_long,
        pub loads: [::c_ulong; 3],
        pub totalram: ::c_ulong,
        pub freeram: ::c_ulong,
        pub sharedram: ::c_ulong,
        pub bufferram: ::c_ulong,
        pub totalswap: ::c_ulong,
        pub freeswap: ::c_ulong,
        pub procs: ::c_ushort,
        pub pad: ::c_ushort,
        pub totalhigh: ::c_ulong,
        pub freehigh: ::c_ulong,
        pub mem_unit: ::c_uint,
        pub _f: [::c_char; 8],
    }
}

s_no_extra_traits! {
    pub struct sigset64_t {
        __bits: [::c_ulong; 2]
    }
}

cfg_if! {
    if #[cfg(feature = "extra_traits")] {
        impl ::fmt::Debug for sigset64_t {
            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
                f.debug_struct("sigset64_t")
                    .field("__bits", &self.__bits)
                    .finish()
            }
        }
    }
}

// These constants must be of the same type of sigaction.sa_flags
pub const SA_NOCLDSTOP: ::c_int = 0x00000001;
pub const SA_NOCLDWAIT: ::c_int = 0x00000002;
pub const SA_NODEFER: ::c_int = 0x40000000;
pub const SA_ONSTACK: ::c_int = 0x08000000;
pub const SA_RESETHAND: ::c_int = 0x80000000;
pub const SA_RESTART: ::c_int = 0x10000000;
pub const SA_SIGINFO: ::c_int = 0x00000004;

pub const RTLD_GLOBAL: ::c_int = 2;
pub const RTLD_NOW: ::c_int = 0;
pub const RTLD_DEFAULT: *mut ::c_void = -1isize as *mut ::c_void;

pub const PTRACE_GETFPREGS: ::c_int = 14;
pub const PTRACE_SETFPREGS: ::c_int = 15;

pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { value: 0 };
pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { value: 0 };
pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
    lock: PTHREAD_MUTEX_INITIALIZER,
    cond: PTHREAD_COND_INITIALIZER,
    numLocks: 0,
    writerThreadId: 0,
    pendingReaders: 0,
    pendingWriters: 0,
    attr: 0,
    __reserved: [0; 12],
};
pub const PTHREAD_STACK_MIN: ::size_t = 4096 * 2;
pub const CPU_SETSIZE: ::size_t = 32;
pub const __CPU_BITS: ::size_t = 32;

pub const UT_LINESIZE: usize = 8;
pub const UT_NAMESIZE: usize = 8;
pub const UT_HOSTSIZE: usize = 16;

pub const SIGSTKSZ: ::size_t = 8192;
pub const MINSIGSTKSZ: ::size_t = 2048;

extern "C" {
    pub fn timegm64(tm: *const ::tm) -> ::time64_t;
}

cfg_if! {
    if #[cfg(target_arch = "x86")] {
        mod x86;
        pub use self::x86::*;
    } else if #[cfg(target_arch = "arm")] {
        mod arm;
        pub use self::arm::*;
    } else {
        // Unknown target_arch
    }
}
<|endoftext|>


<commit_before>pub type c_char = i8;
pub type wchar_t = i32;
pub type greg_t = i32;

s! {
    pub struct _libc_fpreg {
        pub significand: [u16; 4],
        pub exponent: u16,
    }

    pub struct _libc_fpstate {
        pub cw: ::c_ulong,
        pub sw: ::c_ulong,
        pub tag: ::c_ulong,
        pub ipoff: ::c_ulong,
        pub cssel: ::c_ulong,
        pub dataoff: ::c_ulong,
        pub datasel: ::c_ulong,
        pub _st: [_libc_fpreg; 8],
        pub status: ::c_ulong,
    }

    pub struct mcontext_t {
        pub gregs: [greg_t; 19],
        pub fpregs: *mut _libc_fpstate,
        pub oldmask: ::c_ulong,
        pub cr2: ::c_ulong,
    }

    pub struct ucontext_t {
        pub uc_flags: ::c_ulong,
        pub uc_link: *mut ucontext_t,
        pub uc_stack: ::stack_t,
        pub uc_mcontext: mcontext_t,
        pub uc_sigmask: ::sigset_t,
        __private: [u8; 112],
    }

    pub struct ipc_perm {
        pub __key: ::key_t,
        pub uid: ::uid_t,
        pub gid: ::gid_t,
        pub cuid: ::uid_t,
        pub cgid: ::gid_t,
        pub mode: ::c_ushort,
        __pad1: ::c_ushort,
        pub __seq: ::c_ushort,
        __pad2: ::c_ushort,
        __unused1: ::c_ulong,
        __unused2: ::c_ulong
    }

    pub struct stat64 {
        pub st_dev: ::dev_t,
        __pad1: ::c_uint,
        __st_ino: ::ino_t,
        pub st_mode: ::mode_t,
        pub st_nlink: ::nlink_t,
        pub st_uid: ::uid_t,
        pub st_gid: ::gid_t,
        pub st_rdev: ::dev_t,
        __pad2: ::c_uint,
        pub st_size: ::off64_t,
        pub st_blksize: ::blksize_t,
        pub st_blocks: ::blkcnt64_t,
        pub st_atime: ::time_t,
        pub st_atime_nsec: ::c_long,
        pub st_mtime: ::time_t,
        pub st_mtime_nsec: ::c_long,
        pub st_ctime: ::time_t,
        pub st_ctime_nsec: ::c_long,
        pub st_ino: ::ino64_t,
    }

    pub struct shmid_ds {
        pub shm_perm: ::ipc_perm,
        pub shm_segsz: ::size_t,
        pub shm_atime: ::time_t,
        __unused1: ::c_ulong,
        pub shm_dtime: ::time_t,
        __unused2: ::c_ulong,
        pub shm_ctime: ::time_t,
        __unused3: ::c_ulong,
        pub shm_cpid: ::pid_t,
        pub shm_lpid: ::pid_t,
        pub shm_nattch: ::shmatt_t,
        __unused4: ::c_ulong,
        __unused5: ::c_ulong
    }

    pub struct msqid_ds {
        pub msg_perm: ::ipc_perm,
        pub msg_stime: ::time_t,
        __glibc_reserved1: ::c_ulong,
        pub msg_rtime: ::time_t,
        __glibc_reserved2: ::c_ulong,
        pub msg_ctime: ::time_t,
        __glibc_reserved3: ::c_ulong,
        __msg_cbytes: ::c_ulong,
        pub msg_qnum: ::msgqnum_t,
        pub msg_qbytes: ::msglen_t,
        pub msg_lspid: ::pid_t,
        pub msg_lrpid: ::pid_t,
        __glibc_reserved4: ::c_ulong,
        __glibc_reserved5: ::c_ulong,
    }
}

pub const O_DIRECT: ::c_int = 0x4000;
pub const O_DIRECTORY: ::c_int = 0x10000;
pub const O_NOFOLLOW: ::c_int = 0x20000;

pub const MAP_LOCKED: ::c_int = 0x02000;
pub const MAP_NORESERVE: ::c_int = 0x04000;
pub const MAP_32BIT: ::c_int = 0x0040;

pub const EDEADLOCK: ::c_int = 35;

pub const SO_PEERCRED: ::c_int = 17;
pub const SO_RCVLOWAT: ::c_int = 18;
pub const SO_SNDLOWAT: ::c_int = 19;
pub const SO_RCVTIMEO: ::c_int = 20;
pub const SO_SNDTIMEO: ::c_int = 21;

pub const FIOCLEX: ::c_ulong = 0x5451;
pub const FIONBIO: ::c_ulong = 0x5421;

pub const SYS_gettid: ::c_long = 224;
pub const SYS_perf_event_open: ::c_long = 336;

pub const PTRACE_GETFPXREGS: ::c_uint = 18;
pub const PTRACE_SETFPXREGS: ::c_uint = 19;
pub const PTRACE_SYSEMU: ::c_uint = 31;
pub const PTRACE_SYSEMU_SINGLESTEP: ::c_uint = 32;

pub const MCL_CURRENT: ::c_int = 0x0001;
pub const MCL_FUTURE: ::c_int = 0x0002;

pub const SIGSTKSZ: ::size_t = 8192;
pub const CBAUD: ::tcflag_t = 0o0010017;
pub const TAB1: ::c_int = 0x00000800;
pub const TAB2: ::c_int = 0x00001000;
pub const TAB3: ::c_int = 0x00001800;
pub const CR1: ::c_int  = 0x00000200;
pub const CR2: ::c_int  = 0x00000400;
pub const CR3: ::c_int  = 0x00000600;
pub const FF1: ::c_int  = 0x00008000;
pub const BS1: ::c_int  = 0x00002000;
pub const VT1: ::c_int  = 0x00004000;
pub const VWERASE: usize = 14;
pub const VREPRINT: usize = 12;
pub const VSUSP: usize = 10;
pub const VSTART: usize = 8;
pub const VSTOP: usize = 9;
pub const VDISCARD: usize = 13;
pub const VTIME: usize = 5;
pub const IXON: ::tcflag_t = 0x00000400;
pub const IXOFF: ::tcflag_t = 0x00001000;
pub const ONLCR: ::tcflag_t = 0x4;
pub const CSIZE: ::tcflag_t = 0x00000030;
pub const CS6: ::tcflag_t = 0x00000010;
pub const CS7: ::tcflag_t = 0x00000020;
pub const CS8: ::tcflag_t = 0x00000030;
pub const CSTOPB: ::tcflag_t = 0x00000040;
pub const CREAD: ::tcflag_t = 0x00000080;
pub const PARENB: ::tcflag_t = 0x00000100;
pub const PARODD: ::tcflag_t = 0x00000200;
pub const HUPCL: ::tcflag_t = 0x00000400;
pub const CLOCAL: ::tcflag_t = 0x00000800;
pub const ECHOKE: ::tcflag_t = 0x00000800;
pub const ECHOE: ::tcflag_t = 0x00000010;
pub const ECHOK: ::tcflag_t = 0x00000020;
pub const ECHONL: ::tcflag_t = 0x00000040;
pub const ECHOPRT: ::tcflag_t = 0x00000400;
pub const ECHOCTL: ::tcflag_t = 0x00000200;
pub const ISIG: ::tcflag_t = 0x00000001;
pub const ICANON: ::tcflag_t = 0x00000002;
pub const PENDIN: ::tcflag_t = 0x00004000;
pub const NOFLSH: ::tcflag_t = 0x00000080;

pub const VEOL: usize = 11;
pub const VEOL2: usize = 16;
pub const VMIN: usize = 6;
pub const IEXTEN: ::tcflag_t = 0x00008000;
pub const TOSTOP: ::tcflag_t = 0x00000100;
pub const FLUSHO: ::tcflag_t = 0x00001000;
pub const EXTPROC: ::tcflag_t = 0x00010000;
pub const TCGETS: ::c_ulong = 0x5401;
pub const TCSETS: ::c_ulong = 0x5402;
pub const TCSETSW: ::c_ulong = 0x5403;
pub const TCSETSF: ::c_ulong = 0x5404;
pub const TCGETA: ::c_ulong = 0x5405;
pub const TCSETA: ::c_ulong = 0x5406;
pub const TCSETAW: ::c_ulong = 0x5407;
pub const TCSETAF: ::c_ulong = 0x5408;
pub const TCSBRK: ::c_ulong = 0x5409;
pub const TCXONC: ::c_ulong = 0x540A;
pub const TCFLSH: ::c_ulong = 0x540B;
pub const TIOCINQ: ::c_ulong = 0x541B;
pub const TIOCGPGRP: ::c_ulong = 0x540F;
pub const TIOCSPGRP: ::c_ulong = 0x5410;
pub const TIOCOUTQ: ::c_ulong = 0x5411;
pub const TIOCGWINSZ: ::c_ulong = 0x5413;
pub const TIOCSWINSZ: ::c_ulong = 0x5414;
pub const FIONREAD: ::c_ulong = 0x541B;

extern {
    pub fn getcontext(ucp: *mut ucontext_t) -> ::c_int;
    pub fn setcontext(ucp: *const ucontext_t) -> ::c_int;
    pub fn makecontext(ucp: *mut ucontext_t,
                       func:  extern fn (),
                       argc: ::c_int, ...);
    pub fn swapcontext(uocp: *mut ucontext_t,
                       ucp: *const ucontext_t) -> ::c_int;
}
<commit_msg>Forgot the x86 changes<commit_after>pub type c_char = i8;
pub type wchar_t = i32;
pub type greg_t = i32;

s! {
    pub struct _libc_fpreg {
        pub significand: [u16; 4],
        pub exponent: u16,
    }

    pub struct _libc_fpstate {
        pub cw: ::c_ulong,
        pub sw: ::c_ulong,
        pub tag: ::c_ulong,
        pub ipoff: ::c_ulong,
        pub cssel: ::c_ulong,
        pub dataoff: ::c_ulong,
        pub datasel: ::c_ulong,
        pub _st: [_libc_fpreg; 8],
        pub status: ::c_ulong,
    }

    pub struct mcontext_t {
        pub gregs: [greg_t; 19],
        pub fpregs: *mut _libc_fpstate,
        pub oldmask: ::c_ulong,
        pub cr2: ::c_ulong,
    }

    pub struct ucontext_t {
        pub uc_flags: ::c_ulong,
        pub uc_link: *mut ucontext_t,
        pub uc_stack: ::stack_t,
        pub uc_mcontext: mcontext_t,
        pub uc_sigmask: ::sigset_t,
        __private: [u8; 112],
    }

    pub struct ipc_perm {
        pub __key: ::key_t,
        pub uid: ::uid_t,
        pub gid: ::gid_t,
        pub cuid: ::uid_t,
        pub cgid: ::gid_t,
        pub mode: ::c_ushort,
        __pad1: ::c_ushort,
        pub __seq: ::c_ushort,
        __pad2: ::c_ushort,
        __unused1: ::c_ulong,
        __unused2: ::c_ulong
    }

    pub struct stat64 {
        pub st_dev: ::dev_t,
        __pad1: ::c_uint,
        __st_ino: ::ino_t,
        pub st_mode: ::mode_t,
        pub st_nlink: ::nlink_t,
        pub st_uid: ::uid_t,
        pub st_gid: ::gid_t,
        pub st_rdev: ::dev_t,
        __pad2: ::c_uint,
        pub st_size: ::off64_t,
        pub st_blksize: ::blksize_t,
        pub st_blocks: ::blkcnt64_t,
        pub st_atime: ::time_t,
        pub st_atime_nsec: ::c_long,
        pub st_mtime: ::time_t,
        pub st_mtime_nsec: ::c_long,
        pub st_ctime: ::time_t,
        pub st_ctime_nsec: ::c_long,
        pub st_ino: ::ino64_t,
    }

    pub struct shmid_ds {
        pub shm_perm: ::ipc_perm,
        pub shm_segsz: ::size_t,
        pub shm_atime: ::time_t,
        __unused1: ::c_ulong,
        pub shm_dtime: ::time_t,
        __unused2: ::c_ulong,
        pub shm_ctime: ::time_t,
        __unused3: ::c_ulong,
        pub shm_cpid: ::pid_t,
        pub shm_lpid: ::pid_t,
        pub shm_nattch: ::shmatt_t,
        __unused4: ::c_ulong,
        __unused5: ::c_ulong
    }

    pub struct msqid_ds {
        pub msg_perm: ::ipc_perm,
        pub msg_stime: ::time_t,
        __glibc_reserved1: ::c_ulong,
        pub msg_rtime: ::time_t,
        __glibc_reserved2: ::c_ulong,
        pub msg_ctime: ::time_t,
        __glibc_reserved3: ::c_ulong,
        __msg_cbytes: ::c_ulong,
        pub msg_qnum: ::msgqnum_t,
        pub msg_qbytes: ::msglen_t,
        pub msg_lspid: ::pid_t,
        pub msg_lrpid: ::pid_t,
        __glibc_reserved4: ::c_ulong,
        __glibc_reserved5: ::c_ulong,
    }
}

pub const O_DIRECT: ::c_int = 0x4000;
pub const O_DIRECTORY: ::c_int = 0x10000;
pub const O_NOFOLLOW: ::c_int = 0x20000;

pub const MAP_LOCKED: ::c_int = 0x02000;
pub const MAP_NORESERVE: ::c_int = 0x04000;
pub const MAP_32BIT: ::c_int = 0x0040;

pub const EDEADLOCK: ::c_int = 35;

pub const SO_PEERCRED: ::c_int = 17;
pub const SO_RCVLOWAT: ::c_int = 18;
pub const SO_SNDLOWAT: ::c_int = 19;
pub const SO_RCVTIMEO: ::c_int = 20;
pub const SO_SNDTIMEO: ::c_int = 21;

pub const FIOCLEX: ::c_ulong = 0x5451;
pub const FIONBIO: ::c_ulong = 0x5421;

pub const SYS_gettid: ::c_long = 224;
pub const SYS_perf_event_open: ::c_long = 336;

pub const PTRACE_GETFPXREGS: ::c_uint = 18;
pub const PTRACE_SETFPXREGS: ::c_uint = 19;

pub const MCL_CURRENT: ::c_int = 0x0001;
pub const MCL_FUTURE: ::c_int = 0x0002;

pub const SIGSTKSZ: ::size_t = 8192;
pub const CBAUD: ::tcflag_t = 0o0010017;
pub const TAB1: ::c_int = 0x00000800;
pub const TAB2: ::c_int = 0x00001000;
pub const TAB3: ::c_int = 0x00001800;
pub const CR1: ::c_int  = 0x00000200;
pub const CR2: ::c_int  = 0x00000400;
pub const CR3: ::c_int  = 0x00000600;
pub const FF1: ::c_int  = 0x00008000;
pub const BS1: ::c_int  = 0x00002000;
pub const VT1: ::c_int  = 0x00004000;
pub const VWERASE: usize = 14;
pub const VREPRINT: usize = 12;
pub const VSUSP: usize = 10;
pub const VSTART: usize = 8;
pub const VSTOP: usize = 9;
pub const VDISCARD: usize = 13;
pub const VTIME: usize = 5;
pub const IXON: ::tcflag_t = 0x00000400;
pub const IXOFF: ::tcflag_t = 0x00001000;
pub const ONLCR: ::tcflag_t = 0x4;
pub const CSIZE: ::tcflag_t = 0x00000030;
pub const CS6: ::tcflag_t = 0x00000010;
pub const CS7: ::tcflag_t = 0x00000020;
pub const CS8: ::tcflag_t = 0x00000030;
pub const CSTOPB: ::tcflag_t = 0x00000040;
pub const CREAD: ::tcflag_t = 0x00000080;
pub const PARENB: ::tcflag_t = 0x00000100;
pub const PARODD: ::tcflag_t = 0x00000200;
pub const HUPCL: ::tcflag_t = 0x00000400;
pub const CLOCAL: ::tcflag_t = 0x00000800;
pub const ECHOKE: ::tcflag_t = 0x00000800;
pub const ECHOE: ::tcflag_t = 0x00000010;
pub const ECHOK: ::tcflag_t = 0x00000020;
pub const ECHONL: ::tcflag_t = 0x00000040;
pub const ECHOPRT: ::tcflag_t = 0x00000400;
pub const ECHOCTL: ::tcflag_t = 0x00000200;
pub const ISIG: ::tcflag_t = 0x00000001;
pub const ICANON: ::tcflag_t = 0x00000002;
pub const PENDIN: ::tcflag_t = 0x00004000;
pub const NOFLSH: ::tcflag_t = 0x00000080;

pub const VEOL: usize = 11;
pub const VEOL2: usize = 16;
pub const VMIN: usize = 6;
pub const IEXTEN: ::tcflag_t = 0x00008000;
pub const TOSTOP: ::tcflag_t = 0x00000100;
pub const FLUSHO: ::tcflag_t = 0x00001000;
pub const EXTPROC: ::tcflag_t = 0x00010000;
pub const TCGETS: ::c_ulong = 0x5401;
pub const TCSETS: ::c_ulong = 0x5402;
pub const TCSETSW: ::c_ulong = 0x5403;
pub const TCSETSF: ::c_ulong = 0x5404;
pub const TCGETA: ::c_ulong = 0x5405;
pub const TCSETA: ::c_ulong = 0x5406;
pub const TCSETAW: ::c_ulong = 0x5407;
pub const TCSETAF: ::c_ulong = 0x5408;
pub const TCSBRK: ::c_ulong = 0x5409;
pub const TCXONC: ::c_ulong = 0x540A;
pub const TCFLSH: ::c_ulong = 0x540B;
pub const TIOCINQ: ::c_ulong = 0x541B;
pub const TIOCGPGRP: ::c_ulong = 0x540F;
pub const TIOCSPGRP: ::c_ulong = 0x5410;
pub const TIOCOUTQ: ::c_ulong = 0x5411;
pub const TIOCGWINSZ: ::c_ulong = 0x5413;
pub const TIOCSWINSZ: ::c_ulong = 0x5414;
pub const FIONREAD: ::c_ulong = 0x541B;

extern {
    pub fn getcontext(ucp: *mut ucontext_t) -> ::c_int;
    pub fn setcontext(ucp: *const ucontext_t) -> ::c_int;
    pub fn makecontext(ucp: *mut ucontext_t,
                       func:  extern fn (),
                       argc: ::c_int, ...);
    pub fn swapcontext(uocp: *mut ucontext_t,
                       ucp: *const ucontext_t) -> ::c_int;
}
<|endoftext|>


<commit_before>extern crate serde_json;
extern crate futures;
extern crate futures_cpupool;

use std::vec::Vec;
use std::io;

use weld;
use slog;
use hyper::{Get, Post, Put, Delete, StatusCode};
use hyper::server::{Service, Request, Response};
use hyper;
use futures::Stream;
use futures::Future;
use futures::future::ok;

pub struct RestService {
    pub logger: slog::Logger,
    pub thread_pool: futures_cpupool::CpuPool,
}

impl RestService {
    /// Prepares an error response , logs it, wraps to BoxFuture.
    pub fn error(response: Response,
                 code: StatusCode,
                 message: &str)
                 -> futures::BoxFuture<Response, hyper::Error> {
        // error!(self.logger, "{}",&message);
        return ok(response.with_status(code).with_body(message.to_string())).boxed();
    }

    /// Prepares an success response, wraps to BoxFuture.
    pub fn success(response: Response,
                   value: &serde_json::Value)
                   -> futures::BoxFuture<Response, hyper::Error> {
        return ok(response.with_body(serde_json::to_vec(&value).unwrap())).boxed();
    }

    /// Splits '/'  and filters empty strings
    fn split_path(path: String) -> Vec<String> {
        path.split("/").filter(|x| !x.is_empty()).map(String::from).collect::<Vec<String>>()
    }

    /// Helps to decide id value.
    fn decide_id(part: Option<&String>) -> Result<i64, String> {
        match part {
            Some(val) => {
                if !val.is_empty() {
                    match i64::from_str_radix(val, 10) {
                        Ok(parsed) => Ok(parsed),
                        Err(e) => return Err(format!("Non parsable id Error: {}", e)),
                    }
                } else {
                    Ok(-1)
                }
            }
            None => Ok(-1),
        }
    }

    #[inline]
    /// Gets records or spesific record from db and returns as a result.
    fn get(table: String,
           id: i64,
           response: Response)
           -> futures::BoxFuture<Response, hyper::Error> {
        let mut db = weld::DATABASE.lock().unwrap();
        match db.read(table.as_str(), &id) {
            Some(record) => return Self::success(response, &record),
            None => return Self::error(response, StatusCode::NotFound, "Record not found"),
        }
    }

    #[inline]
    /// Creates the record. Returns the persisted version.
    fn post(req: Request,
            table: String,
            response: Response)
            -> futures::BoxFuture<Response, hyper::Error> {
        req.body()
            .concat()
            .and_then(move |body| {
                let mut db = weld::DATABASE.lock().unwrap();
                let mut payload: serde_json::Value =
                    serde_json::from_slice(body.to_vec().as_slice()).unwrap();
                match db.insert(table.as_str(), payload.as_object_mut().unwrap()) {
                    Some(record) => {
                        db.flush();
                        return Self::success(response, &record);
                    }
                    None => return Self::error(response, StatusCode::NotFound, "Record not found"),
                }
            })
            .boxed()
    }

    #[inline]
    /// Updates the record. Returns the persisted version.
    fn put(req: Request,
           table: String,
           id: i64,
           response: Response)
           -> futures::BoxFuture<Response, hyper::Error> {
        // TODO:: use path id when updating
        req.body()
            .concat()
            .and_then(move |body| {
                let mut db = weld::DATABASE.lock().unwrap();
                let mut payload: serde_json::Value =
                    serde_json::from_slice(body.to_vec().as_slice()).unwrap();
                match db.update(table.as_str(), payload.as_object().unwrap().clone()) {
                    Some(record) => {
                        db.flush();
                        return Self::success(response, &record);
                    }
                    None => return Self::error(response, StatusCode::NotFound, "Record not found"),
                }
            })
            .boxed()
    }

    #[inline]
    /// Deletes the record. Returns the data back.
    fn delete(table: String,
              id: i64,
              response: Response)
              -> futures::BoxFuture<Response, hyper::Error> {
        let mut db = weld::DATABASE.lock().unwrap();
        match db.delete(table.as_str(), &id) {
            Some(record) => {
                db.flush();
                return Self::success(response, &record);
            }
            None => return Self::error(response, StatusCode::NotFound, "Record not found"),
        }
    }
}

impl Service for RestService {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = futures::BoxFuture<Response, hyper::Error>;

    fn call(&self, req: Request) -> Self::Future {
        let parts = Self::split_path(req.path().to_string());
        let response = Response::new();
        // TODO: response.with_header("Content-Type", "application/json");
        match parts.len() {
            // Table list
            0 => {
                let db = weld::DATABASE.lock().unwrap();
                Self::success(response, &serde_json::to_value(&db.tables()).unwrap())
            }
            1 | 2 => {
                // Record list or record
                let table = parts.get(0).unwrap().clone();
                let id = match Self::decide_id(parts.get(1)) {
                    Ok(result) => result,
                    Err(e) => {
                        return Self::error(response, StatusCode::PreconditionFailed, e.as_str());
                    }
                };

                match req.method() {
                    &Get => Self::get(table, id, response),
                    &Post => Self::post(req, table, response),
                    &Put => Self::put(req, table, id, response),
                    &Delete => Self::delete(table, id, response),
                    _ => Self::error(response, StatusCode::MethodNotAllowed, "Method Not Allowed"),
                }
            }
            _ => {
                return Self::error(response,
                                   StatusCode::InternalServerError,
                                   "Nested structures are not implemented yet.");
            }
        }
    }
}
<commit_msg>Content Type json is default now<commit_after>extern crate serde_json;
extern crate futures;
extern crate futures_cpupool;

use std::vec::Vec;

use weld;
use slog;
use hyper::{Get, Post, Put, Delete, StatusCode};
use hyper::server::{Service, Request, Response};
use hyper;
use futures::Stream;
use futures::Future;
use futures::future::ok;

pub struct RestService {
    pub logger: slog::Logger,
    pub thread_pool: futures_cpupool::CpuPool,
}

impl RestService {
    /// Prepares an error response , logs it, wraps to BoxFuture.
    pub fn error(response: Response,
                 code: StatusCode,
                 message: &str)
                 -> futures::BoxFuture<Response, hyper::Error> {
        // error!(self.logger, "{}",&message);
        return ok(response.with_status(code).with_body(message.to_string())).boxed();
    }

    /// Prepares an success response, wraps to BoxFuture.
    pub fn success(response: Response,
                   value: &serde_json::Value)
                   -> futures::BoxFuture<Response, hyper::Error> {
        return ok(response.with_body(serde_json::to_vec(&value).unwrap())).boxed();
    }

    /// Splits '/'  and filters empty strings
    fn split_path(path: String) -> Vec<String> {
        path.split("/").filter(|x| !x.is_empty()).map(String::from).collect::<Vec<String>>()
    }

    /// Helps to decide id value.
    fn decide_id(part: Option<&String>) -> Result<i64, String> {
        match part {
            Some(val) => {
                if !val.is_empty() {
                    match i64::from_str_radix(val, 10) {
                        Ok(parsed) => Ok(parsed),
                        Err(e) => return Err(format!("Non parsable id Error: {}", e)),
                    }
                } else {
                    Ok(-1)
                }
            }
            None => Ok(-1),
        }
    }

    #[inline]
    /// Gets records or spesific record from db and returns as a result.
    fn get(table: String,
           id: i64,
           response: Response)
           -> futures::BoxFuture<Response, hyper::Error> {
        let mut db = weld::DATABASE.lock().unwrap();
        match db.read(table.as_str(), &id) {
            Some(record) => return Self::success(response, &record),
            None => return Self::error(response, StatusCode::NotFound, "Record not found"),
        }
    }

    #[inline]
    /// Creates the record. Returns the persisted version.
    fn post(req: Request,
            table: String,
            response: Response)
            -> futures::BoxFuture<Response, hyper::Error> {
        req.body()
            .concat()
            .and_then(move |body| {
                let mut db = weld::DATABASE.lock().unwrap();
                let mut payload: serde_json::Value =
                    serde_json::from_slice(body.to_vec().as_slice()).unwrap();
                match db.insert(table.as_str(), payload.as_object_mut().unwrap()) {
                    Some(record) => {
                        db.flush();
                        return Self::success(response, &record);
                    }
                    None => return Self::error(response, StatusCode::NotFound, "Record not found"),
                }
            })
            .boxed()
    }

    #[inline]
    /// Updates the record. Returns the persisted version.
    fn put(req: Request,
           table: String,
           id: i64,
           response: Response)
           -> futures::BoxFuture<Response, hyper::Error> {
        // TODO:: use path id when updating
        req.body()
            .concat()
            .and_then(move |body| {
                let mut db = weld::DATABASE.lock().unwrap();
                let mut payload: serde_json::Value =
                    serde_json::from_slice(body.to_vec().as_slice()).unwrap();
                match db.update(table.as_str(), payload.as_object().unwrap().clone()) {
                    Some(record) => {
                        db.flush();
                        return Self::success(response, &record);
                    }
                    None => return Self::error(response, StatusCode::NotFound, "Record not found"),
                }
            })
            .boxed()
    }

    #[inline]
    /// Deletes the record. Returns the data back.
    fn delete(table: String,
              id: i64,
              response: Response)
              -> futures::BoxFuture<Response, hyper::Error> {
        let mut db = weld::DATABASE.lock().unwrap();
        match db.delete(table.as_str(), &id) {
            Some(record) => {
                db.flush();
                return Self::success(response, &record);
            }
            None => return Self::error(response, StatusCode::NotFound, "Record not found"),
        }
    }
}

impl Service for RestService {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = futures::BoxFuture<Response, hyper::Error>;

    fn call(&self, req: Request) -> Self::Future {
        let parts = Self::split_path(req.path().to_string());
        let response = Response::new().with_header(hyper::header::ContentType::json());

        match parts.len() {
            // Table list
            0 => {
                let db = weld::DATABASE.lock().unwrap();
                Self::success(response, &serde_json::to_value(&db.tables()).unwrap())
            }
            1 | 2 => {
                // Record list or record
                let table = parts.get(0).unwrap().clone();
                let id = match Self::decide_id(parts.get(1)) {
                    Ok(result) => result,
                    Err(e) => {
                        return Self::error(response, StatusCode::PreconditionFailed, e.as_str());
                    }
                };

                match req.method() {
                    &Get => Self::get(table, id, response),
                    &Post => Self::post(req, table, response),
                    &Put => Self::put(req, table, id, response),
                    &Delete => Self::delete(table, id, response),
                    _ => Self::error(response, StatusCode::MethodNotAllowed, "Method Not Allowed"),
                }
            }
            _ => {
                return Self::error(response,
                                   StatusCode::InternalServerError,
                                   "Nested structures are not implemented yet.");
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate proc_macro;

// spell-checker:ignore () sigpipe uucore uumain

// ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e>
// ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua>

struct Tokens {
    expr: syn::Expr,
}

impl syn::parse::Parse for Tokens {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Tokens {
            expr: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn main(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let Tokens { expr } = syn::parse_macro_input!(stream as Tokens);
    // eprintln!("expr={:?}", expr);
    let expr = match expr {
        syn::Expr::Lit(expr) => {
            // eprintln!("found Expr::Lit => {:?}", expr);
            match expr.lit {
                syn::Lit::Str(ref lit) => {
                    let mut s = lit.value();
                    if !s.ends_with("::uumain") {
                        s += "::uumain";
                    }
                    syn::LitStr::new(&s, proc_macro2::Span::call_site())
                        .parse()
                        .unwrap()
                }
                _ => panic!(),
            }
        }
        syn::Expr::Path(expr) => {
            // eprintln!("found Expr::Path => {:?}", expr);
            // let i = &expr.path.segments.last().unwrap().ident;
            // eprintln!("... i => {:?}", i);
            if &expr.path.segments.last().unwrap().ident.to_string() != "uumain" {
                syn::parse_quote!( #expr::uumain )
            } else {
                expr
            }
        }
        _ => panic!(),
    };
    let f = quote::quote! { #expr(uucore::args().collect()) };
    // eprintln!("f = {:?}", f);
    let result = quote::quote! {
        fn main() {
            use std::io::Write;
            uucore::panic::install_sigpipe_hook();
            let code = #f;
            std::io::stdout().flush().expect("could not flush stdout");
            std::process::exit(code);
        }
    };
    proc_macro::TokenStream::from(result)
}
<commit_msg>change ~ use updated SIGPIPE in procs<commit_after>extern crate proc_macro;

// spell-checker:ignore () sigpipe uucore uumain

// ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e>
// ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua>

struct Tokens {
    expr: syn::Expr,
}

impl syn::parse::Parse for Tokens {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Tokens {
            expr: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn main(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let Tokens { expr } = syn::parse_macro_input!(stream as Tokens);
    // eprintln!("expr={:?}", expr);
    let expr = match expr {
        syn::Expr::Lit(expr) => {
            // eprintln!("found Expr::Lit => {:?}", expr);
            match expr.lit {
                syn::Lit::Str(ref lit) => {
                    let mut s = lit.value();
                    if !s.ends_with("::uumain") {
                        s += "::uumain";
                    }
                    syn::LitStr::new(&s, proc_macro2::Span::call_site())
                        .parse()
                        .unwrap()
                }
                _ => panic!(),
            }
        }
        syn::Expr::Path(expr) => {
            // eprintln!("found Expr::Path => {:?}", expr);
            // let i = &expr.path.segments.last().unwrap().ident;
            // eprintln!("... i => {:?}", i);
            if &expr.path.segments.last().unwrap().ident.to_string() != "uumain" {
                syn::parse_quote!( #expr::uumain )
            } else {
                expr
            }
        }
        _ => panic!(),
    };
    let f = quote::quote! { #expr(uucore::args().collect()) };
    // eprintln!("f = {:?}", f);
    let result = quote::quote! {
        fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic();
            let code = #f;
            std::io::stdout().flush().expect("could not flush stdout");
            std::process::exit(code);
        }
    };
    proc_macro::TokenStream::from(result)
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

mod function_wrapper_cpp;
pub(crate) mod type_to_cpp;

use crate::{conversion::analysis::fun::FnAnalysisBody, types::QualifiedName, CppFilePair};
use autocxx_parser::IncludeCppConfig;
use itertools::Itertools;
use std::collections::HashSet;
use type_to_cpp::{original_name_map_from_apis, type_to_cpp, CppNameMap};

use super::{
    analysis::fun::{
        function_wrapper::{FunctionWrapper, FunctionWrapperPayload},
        FnAnalysis,
    },
    api::Api,
    ConvertError,
};

#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash)]
struct Header {
    name: &'static str,
    system: bool,
}

impl Header {
    fn system(name: &'static str) -> Self {
        Header { name, system: true }
    }

    fn user(name: &'static str) -> Self {
        Header {
            name,
            system: false,
        }
    }

    fn include_stmt(&self) -> String {
        if self.system {
            format!("#include <{}>", self.name)
        } else {
            format!("#include \"{}\"", self.name)
        }
    }
}

struct AdditionalFunction {
    type_definition: Option<String>, // are output before main declarations
    declaration: Option<String>,
    definition: Option<String>,
    headers: Vec<Header>,
}

/// Generates additional C++ glue functions needed by autocxx.
/// In some ways it would be preferable to be able to pass snippets
/// of C++ through to `cxx` for inclusion in the C++ file which it
/// generates, and perhaps we'll explore that in future. But for now,
/// autocxx generates its own _additional_ C++ files which therefore
/// need to be built and included in linking procedures.
pub(crate) struct CppCodeGenerator<'a> {
    additional_functions: Vec<AdditionalFunction>,
    inclusions: String,
    original_name_map: CppNameMap,
    config: &'a IncludeCppConfig,
}

impl<'a> CppCodeGenerator<'a> {
    pub(crate) fn generate_cpp_code(
        inclusions: String,
        apis: &[Api<FnAnalysis>],
        config: &'a IncludeCppConfig,
    ) -> Result<Option<CppFilePair>, ConvertError> {
        let mut gen = CppCodeGenerator::new(inclusions, original_name_map_from_apis(apis), config);
        // The 'filter' on the following line is designed to ensure we don't accidentally
        // end up out of sync with needs_cpp_codegen
        gen.add_needs(apis.iter().filter(|api| api.needs_cpp_codegen()))?;
        Ok(gen.generate())
    }

    fn new(
        inclusions: String,
        original_name_map: CppNameMap,
        config: &'a IncludeCppConfig,
    ) -> Self {
        CppCodeGenerator {
            additional_functions: Vec::new(),
            inclusions,
            original_name_map,
            config,
        }
    }

    // It's important to keep this in sync with Api::needs_cpp_codegen.
    fn add_needs<'b>(
        &mut self,
        apis: impl Iterator<Item = &'a Api<FnAnalysis>>,
    ) -> Result<(), ConvertError> {
        for api in apis {
            match &api {
                Api::StringConstructor { .. } => self.generate_string_constructor(),
                Api::Function {
                    analysis:
                        FnAnalysisBody {
                            cpp_wrapper: Some(cpp_wrapper),
                            ..
                        },
                    ..
                } => self.generate_by_value_wrapper(cpp_wrapper)?,
                Api::ConcreteType { rs_definition, .. } => self.generate_typedef(
                    api.name(),
                    type_to_cpp(rs_definition, &self.original_name_map)?,
                ),
                Api::CType { typename, .. } => self.generate_ctype_typedef(typename),
                _ => panic!("Should have filtered on needs_cpp_codegen"),
            }
        }
        Ok(())
    }

    fn generate(&self) -> Option<CppFilePair> {
        if self.additional_functions.is_empty() {
            None
        } else {
            let headers: HashSet<Header> = self
                .additional_functions
                .iter()
                .map(|x| x.headers.iter().cloned())
                .flatten()
                .collect();
            let headers = headers.iter().map(|x| x.include_stmt()).join("\n");
            let type_definitions = self.concat_additional_items(|x| x.type_definition.as_ref());
            let declarations = self.concat_additional_items(|x| x.declaration.as_ref());
            let declarations = format!(
                "#ifndef __AUTOCXXGEN_H__\n#define __AUTOCXXGEN_H__\n\n{}\n{}\n{}\n{}#endif // __AUTOCXXGEN_H__\n",
                headers, self.inclusions, type_definitions, declarations
            );
            let definitions = self.concat_additional_items(|x| x.definition.as_ref());
            log::info!("Additional C++ decls:\n{}", declarations);
            let header_name = format!("autocxxgen_{}.h", self.config.get_mod_name());
            let definitions = format!("#include \"{}\"\n{}", header_name, definitions);
            log::info!("Additional C++ defs:\n{}", definitions);
            Some(CppFilePair {
                header: declarations.into_bytes(),
                implementation: definitions.into_bytes(),
                header_name,
            })
        }
    }

    fn concat_additional_items<F>(&self, field_access: F) -> String
    where
        F: FnMut(&AdditionalFunction) -> Option<&String>,
    {
        let mut s = self
            .additional_functions
            .iter()
            .map(field_access)
            .flatten()
            .join("\n");
        s.push('\n');
        s
    }

    fn generate_string_constructor(&mut self) {
        let makestring_name = self.config.get_makestring_name();
        let declaration = Some(format!("inline std::unique_ptr<std::string> {}(::rust::Str str) {{ return std::make_unique<std::string>(std::string(str)); }}", makestring_name));
        self.additional_functions.push(AdditionalFunction {
            type_definition: None,
            declaration,
            definition: None,
            headers: vec![
                Header::system("memory"),
                Header::system("string"),
                Header::user("cxx.h"),
            ],
        })
    }

    fn generate_by_value_wrapper(&mut self, details: &FunctionWrapper) -> Result<(), ConvertError> {
        // Even if the original function call is in a namespace,
        // we generate this wrapper in the global namespace.
        // We could easily do this the other way round, and when
        // cxx::bridge comes to support nested namespace mods then
        // we wil wish to do that to avoid name conflicts. However,
        // at the moment this is simpler because it avoids us having
        // to generate namespace blocks in the generated C++.
        let is_a_method = details.is_a_method;
        let name = &details.wrapper_function_name;
        let get_arg_name = |counter: usize| -> String {
            if is_a_method && counter == 0 {
                // For method calls that we generate, the first
                // argument name needs to be such that we recognize
                // it as a method in the second invocation of
                // bridge_converter after it's flowed again through
                // bindgen.
                // TODO this may not be the case any longer. We
                // may be able to remove this.
                "autocxx_gen_this".to_string()
            } else {
                format!("arg{}", counter)
            }
        };
        let args: Result<Vec<_>, _> = details
            .argument_conversion
            .iter()
            .enumerate()
            .map(|(counter, ty)| {
                Ok(format!(
                    "{} {}",
                    ty.unconverted_type(&self.original_name_map)?,
                    get_arg_name(counter)
                ))
            })
            .collect();
        let args = args?.join(", ");
        let ret_type = details
            .return_conversion
            .as_ref()
            .map_or(Ok("void".to_string()), |x| {
                x.converted_type(&self.original_name_map)
            })?;
        let declaration = format!("{} {}({})", ret_type, name, args);
        let arg_list: Result<Vec<_>, _> = details
            .argument_conversion
            .iter()
            .enumerate()
            .map(|(counter, conv)| {
                conv.cpp_conversion(&get_arg_name(counter), &self.original_name_map)
            })
            .collect();
        let mut arg_list = arg_list?.into_iter();
        let receiver = if is_a_method { arg_list.next() } else { None };
        let arg_list = arg_list.join(", ");
        let mut underlying_function_call = match &details.payload {
            FunctionWrapperPayload::Constructor => arg_list,
            FunctionWrapperPayload::FunctionCall(ns, id) => match receiver {
                Some(receiver) => format!("{}.{}({})", receiver, id.to_string(), arg_list),
                None => {
                    let underlying_function_call = ns
                        .into_iter()
                        .cloned()
                        .chain(std::iter::once(id.to_string()))
                        .join("::");
                    format!("{}({})", underlying_function_call, arg_list)
                }
            },
            FunctionWrapperPayload::StaticMethodCall(ns, ty_id, fn_id) => {
                let underlying_function_call = ns
                    .into_iter()
                    .cloned()
                    .chain([ty_id.to_string(), fn_id.to_string()].iter().cloned())
                    .join("::");
                format!("{}({})", underlying_function_call, arg_list)
            }
        };
        if let Some(ret) = &details.return_conversion {
            underlying_function_call = format!(
                "return {}",
                ret.cpp_conversion(&underlying_function_call, &self.original_name_map)?
            );
        };
        let definition = Some(format!(
            "{} {{ {}; }}",
            declaration, underlying_function_call,
        ));
        let declaration = Some(format!("{};", declaration));
        self.additional_functions.push(AdditionalFunction {
            type_definition: None,
            declaration,
            definition,
            headers: vec![Header::system("memory")],
        });
        Ok(())
    }

    fn generate_ctype_typedef(&mut self, tn: &QualifiedName) {
        let cpp_name = tn.to_cpp_name();
        self.generate_typedef(tn, cpp_name)
    }

    fn generate_typedef(&mut self, tn: &QualifiedName, definition: String) {
        let our_name = tn.get_final_item();
        self.additional_functions.push(AdditionalFunction {
            type_definition: Some(format!("typedef {} {};", definition, our_name)),
            declaration: None,
            definition: None,
            headers: Vec::new(),
        })
    }
}
<commit_msg>Re-inline functions<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

mod function_wrapper_cpp;
pub(crate) mod type_to_cpp;

use crate::{conversion::analysis::fun::FnAnalysisBody, types::QualifiedName, CppFilePair};
use autocxx_parser::IncludeCppConfig;
use itertools::Itertools;
use std::collections::HashSet;
use type_to_cpp::{original_name_map_from_apis, type_to_cpp, CppNameMap};

use super::{
    analysis::fun::{
        function_wrapper::{FunctionWrapper, FunctionWrapperPayload},
        FnAnalysis,
    },
    api::Api,
    ConvertError,
};

#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash)]
struct Header {
    name: &'static str,
    system: bool,
}

impl Header {
    fn system(name: &'static str) -> Self {
        Header { name, system: true }
    }

    fn user(name: &'static str) -> Self {
        Header {
            name,
            system: false,
        }
    }

    fn include_stmt(&self) -> String {
        if self.system {
            format!("#include <{}>", self.name)
        } else {
            format!("#include \"{}\"", self.name)
        }
    }
}

struct AdditionalFunction {
    type_definition: Option<String>, // are output before main declarations
    declaration: Option<String>,
    definition: Option<String>,
    headers: Vec<Header>,
}

/// Generates additional C++ glue functions needed by autocxx.
/// In some ways it would be preferable to be able to pass snippets
/// of C++ through to `cxx` for inclusion in the C++ file which it
/// generates, and perhaps we'll explore that in future. But for now,
/// autocxx generates its own _additional_ C++ files which therefore
/// need to be built and included in linking procedures.
pub(crate) struct CppCodeGenerator<'a> {
    additional_functions: Vec<AdditionalFunction>,
    inclusions: String,
    original_name_map: CppNameMap,
    config: &'a IncludeCppConfig,
}

impl<'a> CppCodeGenerator<'a> {
    pub(crate) fn generate_cpp_code(
        inclusions: String,
        apis: &[Api<FnAnalysis>],
        config: &'a IncludeCppConfig,
    ) -> Result<Option<CppFilePair>, ConvertError> {
        let mut gen = CppCodeGenerator::new(inclusions, original_name_map_from_apis(apis), config);
        // The 'filter' on the following line is designed to ensure we don't accidentally
        // end up out of sync with needs_cpp_codegen
        gen.add_needs(apis.iter().filter(|api| api.needs_cpp_codegen()))?;
        Ok(gen.generate())
    }

    fn new(
        inclusions: String,
        original_name_map: CppNameMap,
        config: &'a IncludeCppConfig,
    ) -> Self {
        CppCodeGenerator {
            additional_functions: Vec::new(),
            inclusions,
            original_name_map,
            config,
        }
    }

    // It's important to keep this in sync with Api::needs_cpp_codegen.
    fn add_needs<'b>(
        &mut self,
        apis: impl Iterator<Item = &'a Api<FnAnalysis>>,
    ) -> Result<(), ConvertError> {
        for api in apis {
            match &api {
                Api::StringConstructor { .. } => self.generate_string_constructor(),
                Api::Function {
                    analysis:
                        FnAnalysisBody {
                            cpp_wrapper: Some(cpp_wrapper),
                            ..
                        },
                    ..
                } => self.generate_by_value_wrapper(cpp_wrapper)?,
                Api::ConcreteType { rs_definition, .. } => self.generate_typedef(
                    api.name(),
                    type_to_cpp(rs_definition, &self.original_name_map)?,
                ),
                Api::CType { typename, .. } => self.generate_ctype_typedef(typename),
                _ => panic!("Should have filtered on needs_cpp_codegen"),
            }
        }
        Ok(())
    }

    fn generate(&self) -> Option<CppFilePair> {
        if self.additional_functions.is_empty() {
            None
        } else {
            let headers: HashSet<Header> = self
                .additional_functions
                .iter()
                .map(|x| x.headers.iter().cloned())
                .flatten()
                .collect();
            let headers = headers.iter().map(|x| x.include_stmt()).join("\n");
            let type_definitions = self.concat_additional_items(|x| x.type_definition.as_ref());
            let declarations = self.concat_additional_items(|x| x.declaration.as_ref());
            let declarations = format!(
                "#ifndef __AUTOCXXGEN_H__\n#define __AUTOCXXGEN_H__\n\n{}\n{}\n{}\n{}#endif // __AUTOCXXGEN_H__\n",
                headers, self.inclusions, type_definitions, declarations
            );
            let definitions = self.concat_additional_items(|x| x.definition.as_ref());
            log::info!("Additional C++ decls:\n{}", declarations);
            let header_name = format!("autocxxgen_{}.h", self.config.get_mod_name());
            let definitions = format!("#include \"{}\"\n{}", header_name, definitions);
            log::info!("Additional C++ defs:\n{}", definitions);
            Some(CppFilePair {
                header: declarations.into_bytes(),
                implementation: definitions.into_bytes(),
                header_name,
            })
        }
    }

    fn concat_additional_items<F>(&self, field_access: F) -> String
    where
        F: FnMut(&AdditionalFunction) -> Option<&String>,
    {
        let mut s = self
            .additional_functions
            .iter()
            .map(field_access)
            .flatten()
            .join("\n");
        s.push('\n');
        s
    }

    fn generate_string_constructor(&mut self) {
        let makestring_name = self.config.get_makestring_name();
        let declaration = Some(format!("inline std::unique_ptr<std::string> {}(::rust::Str str) {{ return std::make_unique<std::string>(std::string(str)); }}", makestring_name));
        self.additional_functions.push(AdditionalFunction {
            type_definition: None,
            declaration,
            definition: None,
            headers: vec![
                Header::system("memory"),
                Header::system("string"),
                Header::user("cxx.h"),
            ],
        })
    }

    fn generate_by_value_wrapper(&mut self, details: &FunctionWrapper) -> Result<(), ConvertError> {
        // Even if the original function call is in a namespace,
        // we generate this wrapper in the global namespace.
        // We could easily do this the other way round, and when
        // cxx::bridge comes to support nested namespace mods then
        // we wil wish to do that to avoid name conflicts. However,
        // at the moment this is simpler because it avoids us having
        // to generate namespace blocks in the generated C++.
        let is_a_method = details.is_a_method;
        let name = &details.wrapper_function_name;
        let get_arg_name = |counter: usize| -> String {
            if is_a_method && counter == 0 {
                // For method calls that we generate, the first
                // argument name needs to be such that we recognize
                // it as a method in the second invocation of
                // bridge_converter after it's flowed again through
                // bindgen.
                // TODO this may not be the case any longer. We
                // may be able to remove this.
                "autocxx_gen_this".to_string()
            } else {
                format!("arg{}", counter)
            }
        };
        let args: Result<Vec<_>, _> = details
            .argument_conversion
            .iter()
            .enumerate()
            .map(|(counter, ty)| {
                Ok(format!(
                    "{} {}",
                    ty.unconverted_type(&self.original_name_map)?,
                    get_arg_name(counter)
                ))
            })
            .collect();
        let args = args?.join(", ");
        let ret_type = details
            .return_conversion
            .as_ref()
            .map_or(Ok("void".to_string()), |x| {
                x.converted_type(&self.original_name_map)
            })?;
        let declaration = format!("{} {}({})", ret_type, name, args);
        let arg_list: Result<Vec<_>, _> = details
            .argument_conversion
            .iter()
            .enumerate()
            .map(|(counter, conv)| {
                conv.cpp_conversion(&get_arg_name(counter), &self.original_name_map)
            })
            .collect();
        let mut arg_list = arg_list?.into_iter();
        let receiver = if is_a_method { arg_list.next() } else { None };
        let arg_list = arg_list.join(", ");
        let mut underlying_function_call = match &details.payload {
            FunctionWrapperPayload::Constructor => arg_list,
            FunctionWrapperPayload::FunctionCall(ns, id) => match receiver {
                Some(receiver) => format!("{}.{}({})", receiver, id.to_string(), arg_list),
                None => {
                    let underlying_function_call = ns
                        .into_iter()
                        .cloned()
                        .chain(std::iter::once(id.to_string()))
                        .join("::");
                    format!("{}({})", underlying_function_call, arg_list)
                }
            },
            FunctionWrapperPayload::StaticMethodCall(ns, ty_id, fn_id) => {
                let underlying_function_call = ns
                    .into_iter()
                    .cloned()
                    .chain([ty_id.to_string(), fn_id.to_string()].iter().cloned())
                    .join("::");
                format!("{}({})", underlying_function_call, arg_list)
            }
        };
        if let Some(ret) = &details.return_conversion {
            underlying_function_call = format!(
                "return {}",
                ret.cpp_conversion(&underlying_function_call, &self.original_name_map)?
            );
        };
        let declaration = Some(format!(
            "{} {{ {}; }}",
            declaration, underlying_function_call,
        ));
        self.additional_functions.push(AdditionalFunction {
            type_definition: None,
            declaration,
            definition: None,
            headers: vec![Header::system("memory")],
        });
        Ok(())
    }

    fn generate_ctype_typedef(&mut self, tn: &QualifiedName) {
        let cpp_name = tn.to_cpp_name();
        self.generate_typedef(tn, cpp_name)
    }

    fn generate_typedef(&mut self, tn: &QualifiedName, definition: String) {
        let our_name = tn.get_final_item();
        self.additional_functions.push(AdditionalFunction {
            type_definition: Some(format!("typedef {} {};", definition, our_name)),
            declaration: None,
            definition: None,
            headers: Vec::new(),
        })
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Definitions and utilities for working with sinks.
//!
//! Sinks ("well-known flows" in terms of GRR nomenclature) are ever-existing
//! sessions on the GRR server that listen for various kinds of data. They are
//! a way to break away from the usual request-response workflow.
//!
//! For example, sinks can be used to notify the server about agent startup
//! (which is clearly not a response to a particular request) or to transfer
//! file blobs to a specialized storage.

use crate::action;
use crate::session;

/// Handle to a specific sink.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub struct Sink {
    /// An underlying identifier of the sink.
    id: &'static str,
}

impl Sink {

    /// A handle to the sink expecting startup information.
    pub const STARTUP: Sink = Sink { id: "/flows/F:Startup" };

    /// A handle to the transfer store sink.
    pub const TRANSFER_STORE: Sink = Sink { id: "/flows/F:TransferStore" };

    // TODO: Refactor sinks to use custom `Message` type rather than `Response`
    // and make response always have `request_id` and `response_id` fields.

    /// Wraps an action response to a sink-specific session response.
    pub fn wrap<R>(&self, response: R) -> session::Response<R>
    where
        R: action::Response,
    {
        session::Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }
    }
}
<commit_msg>Define parcel types.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Definitions and utilities for working with sinks.
//!
//! Sinks ("well-known flows" in terms of GRR nomenclature) are ever-existing
//! sessions on the GRR server that listen for various kinds of data. They are
//! a way to break away from the usual request-response workflow.
//!
//! For example, sinks can be used to notify the server about agent startup
//! (which is clearly not a response to a particular request) or to transfer
//! file blobs to a specialized storage.

use crate::action;
use crate::session;

/// Data sent to a server not belonging to a particular action call.
///
/// Sometimes the agent should send data to the server that is not connected
/// with a particular flow request. An example can be the agent startup data
/// sent to the server regardless of whether there was a request for it or not.
/// Another example can be file contents that are delivered to the server not
/// as part of the flow results but go to a separate store that has logic for
/// deduplicating data that we already collected in the past.
pub trait Parcel {
    /// Low-level Protocol Buffers type representing the parcel data.
    type Protobuf: protobuf::Message;

    /// A name of the corresponding RDF class in GRR.
    const RDF_NAME: &'static str;

    /// Converts the parcel to its low-level representation.
    fn into_proto(self) -> Self::Protobuf;

    /// Converts a Protocol Buffers message to high-level type.
    fn from_proto(message: Self::Protobuf) -> Self;
}

/// A parcel addressed to a particular server-side sink.
pub struct AddressedParcel<P: Parcel> {
    /// Destination of the parcel.
    dest: Sink,
    /// Actual parcel.
    parcel: P,
}

impl<P: Parcel> std::convert::TryInto<rrg_proto::jobs::GrrMessage> for AddressedParcel<P> {

    type Error = protobuf::ProtobufError;

    fn try_into(self) -> Result<rrg_proto::jobs::GrrMessage, protobuf::ProtobufError> {
        let mut message = rrg_proto::jobs::GrrMessage::new();
        message.set_session_id(String::from(self.dest.id));
        message.set_field_type(rrg_proto::jobs::GrrMessage_Type::MESSAGE);
        message.set_args_rdf_name(String::from(P::RDF_NAME));

        let proto = self.parcel.into_proto();
        message.set_args(protobuf::Message::write_to_bytes(&proto)?);

        Ok(message)
    }
}

/// Handle to a specific sink.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub struct Sink {
    /// An underlying identifier of the sink.
    id: &'static str,
}

impl Sink {

    /// A handle to the sink expecting startup information.
    pub const STARTUP: Sink = Sink { id: "/flows/F:Startup" };

    /// A handle to the transfer store sink.
    pub const TRANSFER_STORE: Sink = Sink { id: "/flows/F:TransferStore" };

    // TODO: Refactor sinks to use custom `Message` type rather than `Response`
    // and make response always have `request_id` and `response_id` fields.

    /// Adresses a given `parcel` to this sink.
    pub fn address<P: Parcel>(&self, parcel: P) -> AddressedParcel<P> {
        AddressedParcel {
            dest: *self,
            parcel,
        }
    }

    // TODO: Remove the function below once only parcels are used.
    /// Wraps an action response to a sink-specific session response.
    pub fn wrap<R>(&self, response: R) -> session::Response<R>
    where
        R: action::Response,
    {
        session::Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }
    }
}
<|endoftext|>


<commit_before>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use text_renderer::TextRenderer;
use sdl2::pixels::Color;
use std::io::Result;
use std::path::Path;
use uorustlibs::skills::Skills;

use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2_ttf::Font;

pub struct SkillsScene {
    pages: Vec<Texture>,
}

impl SkillsScene {
    pub fn new(text_renderer: &TextRenderer, renderer: &mut Renderer) -> BoxedScene<SceneName> {
        let skills = Skills::new(&Path::new("./assets/skills.idx"), &Path::new("./assets/skills.mul"));
        let text = match skills {
            Ok(skills) => {
                let items: Vec<Texture> = skills.skills.chunks(30).map(|chunk| {
                    let skills: Vec<String> = chunk.iter().map(|skill| {
                        let glyph = if skill.clickable {
                            "+"
                        } else {
                            "-"
                        };
                        format!("{} {}", glyph, skill.name)
                    }).collect();
                    text_renderer.create_text(renderer, &skills.join("\n"), Color::RGBA(255, 255, 255, 255))
                }).collect();
                items
            },
            Err(error) => {
                let text = format!("{}", error);
                let texture = text_renderer.create_text(renderer, &text, Color::RGBA(255, 255, 255, 255));
                vec![texture]
            }
        };
        Box::new(SkillsScene {
            pages: text,
        })
    }
}

impl<T> Scene<T> for SkillsScene {
    fn render(&self, renderer: &mut Renderer) {
        renderer.clear();
        let mut last_width = 0;
        for page in self.pages.iter() {
            let TextureQuery {width, height, .. } = page.query();
            let target = Rect::new(last_width, 0, width, height);
            renderer.copy(page, None, Some(target)).unwrap();
            last_width += width;
        }
        renderer.present();
    }

    fn handle_event(&self, event: &Event) -> Option<SceneChangeEvent<T>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Num1), .. } => {
                println!("2");
                None
            },
             _ => None
        }
    }
}
<commit_msg>Skills multipage<commit_after>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use text_renderer::TextRenderer;
use sdl2::pixels::Color;
use std::io::Result;
use std::path::Path;
use uorustlibs::skills::Skills;

use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2_ttf::Font;

pub struct SkillsScene {
    pages: Vec<Texture>,
}

impl SkillsScene {
    pub fn new(text_renderer: &TextRenderer, renderer: &mut Renderer) -> BoxedScene<SceneName> {
        let skills = Skills::new(&Path::new("./assets/skills.idx"), &Path::new("./assets/skills.mul"));
        let text = match skills {
            Ok(skills) => {
                let items: Vec<Texture> = skills.skills.chunks(30).map(|chunk| {
                    let skills: Vec<String> = chunk.iter().map(|skill| {
                        let glyph = if skill.clickable {
                            "+"
                        } else {
                            "-"
                        };
                        format!("{} {}", glyph, skill.name)
                    }).collect();
                    text_renderer.create_text(renderer, &skills.join("\n"), Color::RGBA(255, 255, 255, 255))
                }).collect();
                items
            },
            Err(error) => {
                let text = format!("{}", error);
                let texture = text_renderer.create_text(renderer, &text, Color::RGBA(255, 255, 255, 255));
                vec![texture]
            }
        };
        Box::new(SkillsScene {
            pages: text,
        })
    }
}

impl<T> Scene<T> for SkillsScene {
    fn render(&self, renderer: &mut Renderer) {
        renderer.clear();
        let mut last_width = 0;
        for page in self.pages.iter() {
            let TextureQuery {width, height, .. } = page.query();
            let target = Rect::new(last_width, 0, width, height);
            renderer.copy(page, None, Some(target)).unwrap();
            last_width += width as i32;
        }
        renderer.present();
    }

    fn handle_event(&self, event: &Event) -> Option<SceneChangeEvent<T>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Num1), .. } => {
                println!("2");
                None
            },
             _ => None
        }
    }
}
<|endoftext|>


<commit_before>pub struct Config {
    pub attester_count: u64,
    pub max_validators: u64,
    pub shard_count: u16,
    pub notaries_per_crosslink: u16
}

impl Config {
    pub fn standard() -> Self {
        Self {
            attester_count: 32,
            max_validators: 2u64.pow(24),
            shard_count: 20,
            notaries_per_crosslink: 100
        }
    }
}
<commit_msg>Add param to config<commit_after>use super::utils::types::U256;

pub struct Config {
    pub attester_count: u64,
    pub max_validators: u64,
    pub shard_count: u16,
    pub notaries_per_crosslink: u16,
    pub default_balance: U256,
    pub eject_balance: U256

}

impl Config {
    pub fn standard() -> Self {
        Self {
            attester_count: 32,
            max_validators: 2u64.pow(24),
            shard_count: 20,
            notaries_per_crosslink: 100,
            default_balance: U256::from(32000),
            eject_balance: U256::from(16000)
        }
    }
}
<|endoftext|>


<commit_before>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// arch/amd64/hw/apic/raw.rs
// - x86 APIC Raw hardware API
use prelude::*;

static TIMER_VEC: u8 = 0x7E;

pub struct LAPIC
{
	paddr: u64,
	mapping: ::memory::virt::AllocHandle,
	timer_isr: ::arch::interrupts::ISRHandle,
}

pub struct IOAPIC
{
	regs: ::sync::Mutex<IOAPICRegs>,
	num_lines: usize,
	first_irq: usize,
	handlers: ::sync::Spinlock< Vec< Option<super::IRQHandler> > >,
}

struct IOAPICRegs
{
	mapping: ::memory::virt::AllocHandle,
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum TriggerMode
{
	LevelHi,
	LevelLow,
	EdgeHi,
	EdgeLow,
}

#[allow(dead_code)]
#[repr(u8)]
#[derive(Copy,Clone)]
#[allow(non_camel_case_types)]
enum ApicReg
{
	LAPIC_ID  = 0x2,
	LAPIC_Ver = 0x3,
	TPR       = 0x8,	// Task Priority
	APR       = 0x9,	// Arbitration Priority
	PPR       = 0xA,	// Processor Priority
	EOI       = 0xB,
	RRD       = 0xC,	// Remote Read
	LocalDest = 0xD,	// Local Destination
	DestFmt   = 0xE,	// Destination Format
	SIR       = 0xF,	// Spurious Interrupt Vector
	InService = 0x10,	// In-Service Register (First of 8)
	TMR       = 0x18,	// Trigger Mode (1/8)
	IRR       = 0x20,	// Interrupt Request Register (1/8)
	ErrStatus = 0x28,	// Error Status
	LVTCMCI   = 0x2F,	// LVT CMCI Registers (?)
	ICR       = 0x30,	// Interrupt Command Register (1/2)
	LVTTimer  = 0x32,
	LVTThermalSensor = 0x33,
	LVTPermCounters  = 0x34,
	LVT_LINT0 = 0x35,
	LVT_LINT1 = 0x36,
	LVT_Error = 0x37,
	InitCount = 0x38,
	CurCount  = 0x39,
	TmrDivide = 0x3E,
}

#[repr(C,packed)]
struct APICReg
{
	data: u32,
	_rsvd: [u32; 3],
}

impl LAPIC
{
	pub fn new(paddr: u64) -> LAPIC
	{
		let ret = LAPIC {
			paddr: paddr,
			// Assume SAFE: Shouldn't be aliasing
			mapping: unsafe { ::memory::virt::map_hw_rw(paddr, 1, "APIC").unwrap() },
			timer_isr: Default::default(),
			};

		log_debug!("LAPIC {{ IDReg={:x}, Ver={:x}, SIR={:#x} }}",
			ret.read_reg(ApicReg::LAPIC_ID),
			ret.read_reg(ApicReg::LAPIC_Ver),
			ret.read_reg(ApicReg::SIR)
			);

		ret
	}
	/// Initialise the LAPIC structures once self is in its final location
	pub fn global_init(&mut self)
	{
		self.timer_isr = match ::arch::interrupts::bind_isr(TIMER_VEC, lapic_timer, self as *mut _ as *const (), 0)
			{
			Ok(v) => v,
			Err(e) => panic!("Unable to bind LAPIC timer: {:?}", e),
			};
	}
	/// Initialise the LAPIC (for this CPU)
	pub fn init(&self)
	{
		let oldaddr = unsafe{
			let mut a: u64;
			let mut d: u64;
			asm!("rdmsr" : "={eax}" (a), "={edx}" (d) : "{rcx}" (0x1Bu32) : "rdx");
			d << 32 | a
			};
		log_debug!("oldaddr = {:#x}", oldaddr);
		let is_bsp = oldaddr & 0x100;
		log_debug!("IRR[0..8] = [{:#x}, {:#x}, {:#x}, {:#x},  {:#x}, {:#x}, {:#x}, {:#x}]",
			self.read_reg(ApicReg::irr(0)),
			self.read_reg(ApicReg::irr(1)),
			self.read_reg(ApicReg::irr(2)),
			self.read_reg(ApicReg::irr(3)),
			self.read_reg(ApicReg::irr(4)),
			self.read_reg(ApicReg::irr(5)),
			self.read_reg(ApicReg::irr(6)),
			self.read_reg(ApicReg::irr(7))
			);

		//self.write_reg(ApicReg::SIR as usize, self.read_reg(ApicReg_SIR as usize) | (1 << 8));
		self.write_reg(ApicReg::SIR, 0x7F | (1 << 8));	// Enable LAPIC (and set Spurious to 127)
		self.write_reg(ApicReg::InitCount, 0x100000);
		self.write_reg(ApicReg::TmrDivide, 3);	// Timer Divide = 16
		self.write_reg(ApicReg::LVTTimer, TIMER_VEC as u32);	// Enable Timer
		self.write_reg(ApicReg::LVTThermalSensor, 0);	// "Disable" Thermal Sensor
		self.write_reg(ApicReg::LVTPermCounters, 0);	// "Disable" ? Counters
		self.write_reg(ApicReg::LVT_LINT0, 0);	// "Disable" LINT0
		self.write_reg(ApicReg::LVT_LINT1, 0);	// "Disable" LINT1
		self.write_reg(ApicReg::LVT_Error, 0);	// "Disable" Error
		// EOI - Just to make sure
		self.eoi(0);
		unsafe {
			asm!("wrmsr\nsti"
				: /* no out */
				: "{ecx}" (0x1Bu32), "{edx}" (self.paddr >> 32), "{eax}" (self.paddr | is_bsp | 0x800)
				: /* no clobbers */
				: "volatile"
				);

			// Quick debug
			let mut ef: u64; asm!("pushf\npop $0" : "=r" (ef)); log_debug!("EFLAGS = {:#x}", ef);
		}
	}
	pub fn eoi(&self, num: usize)
	{
		self.write_reg(ApicReg::EOI, num as u32);
	}

	fn read_reg(&self, reg: ApicReg) -> u32
	{
		let regs = self.mapping.as_ref::<[APICReg; 64]>(0);
		assert!( (reg as usize) < 64 );
		unsafe { ::core::intrinsics::volatile_load( &regs[reg as usize].data as *const _ ) }
	}
	fn write_reg(&self, idx: ApicReg, value: u32)
	{
		let regs = unsafe { self.mapping.as_int_mut::<[APICReg; 64]>(0) };
		assert!( (idx as usize) < 64 );
		unsafe { ::core::intrinsics::volatile_store( &mut regs[idx as usize].data as *mut _, value ) }
	}

	pub fn get_vec_status(&self, idx: u8) -> (bool,bool,bool, u32)
	{
		let reg = idx / 32;
		let bit = idx % 32;
		let mask = 1 << bit;
		let in_svc = self.read_reg(ApicReg::in_service(reg)) & mask != 0;
		let mode   = self.read_reg(ApicReg::tmr(reg)) & mask != 0;
		let in_req = self.read_reg(ApicReg::irr(reg)) & mask != 0;
		let err = self.read_reg(ApicReg::ErrStatus);

		(in_svc, mode, in_req, err)
	}

	fn local_timer(isr: usize, sp: *const (), _idx: usize)
	{
		assert!( !sp.is_null() );
		let s: &LAPIC = unsafe { &*(sp as *const LAPIC) };
		log_trace!("LAPIC Timer");
		s.eoi(isr);
	}
}
impl ApicReg
{
	fn in_service(reg: u8) -> ApicReg
	{
		assert!(reg < 8);
		unsafe { ::core::mem::transmute(ApicReg::InService as u8 + reg as u8) }
	}
	fn tmr(reg: u8) -> ApicReg
	{
		assert!(reg < 8);
		unsafe { ::core::mem::transmute(ApicReg::TMR as u8 + reg as u8) }
	}
	fn irr(reg: u8) -> ApicReg
	{
		assert!(reg < 8);
		unsafe { ::core::mem::transmute(ApicReg::IRR as u8 + reg as u8) }
	}
}

extern "C" fn lapic_timer(isr: usize, sp: *const (), _idx: usize)
{
	LAPIC::local_timer(isr, sp, _idx);
}

impl IOAPIC
{
	pub fn new(paddr: u64, base: usize) -> IOAPIC
	{
		let mut regs = IOAPICRegs::new(paddr);
		let v = regs.read(1);
		log_debug!("{:x} {:x} {:x}", v, v>>16, (v >> 16) & 0xFF);
		let num_lines = ((v >> 16) & 0xFF) as usize + 1;
		log_debug!("regs=[{:#x},{:#x},{:#x}]", regs.read(0), regs.read(1), regs.read(2));

		log_debug!("IOAPIC: {{ {:#x} - {} + {} }}", paddr, base, num_lines);
		IOAPIC {
			regs: ::sync::Mutex::new( regs ),
			num_lines: num_lines,
			first_irq: base,
			handlers: ::sync::Spinlock::new( Vec::from_fn(num_lines, |_| None) ),
			}
	}

	pub fn contains(&self, gsi: usize) -> bool {
		self.first_irq <= gsi && gsi < self.first_irq + self.num_lines
	}
	pub fn first(&self) -> usize {
		self.first_irq
	}
	pub fn get_callback(&self, idx: usize) -> Option<super::IRQHandler> {
		assert!( idx < self.num_lines );
		self.handlers.lock()[idx]
	}

	pub fn eoi(&self, _idx: usize)
	{
		// TODO: EOI in IOAPIC
	}
	pub fn set_irq(&self, idx: usize, vector: u8, apic: u32, mode: TriggerMode, cb: super::IRQHandler)
	{
		log_trace!("set_irq(idx={},vector={},apic={},mode={:?})", idx, vector, apic, mode);
		assert!( idx < self.num_lines );

		// Unsynchronised write. Need to use Spinlock (with IRQ hold)?
		{
			let _irql = ::sync::hold_interrupts();
			self.handlers.lock()[idx] = Some( cb );
		}
		let flags: u32 = match mode {
			TriggerMode::EdgeHi   => (0<<13)|(0<<15),
			TriggerMode::EdgeLow  => (1<<13)|(0<<15),
			TriggerMode::LevelHi  => (0<<13)|(1<<15),
			TriggerMode::LevelLow => (1<<13)|(1<<15),
			};

		let mut rh = self.regs.lock();
		log_debug!("Info = {:#x}", rh.read(0x10 + idx*2));
		rh.write(0x10 + idx*2 + 1, (apic as u32) << 56-32 );
		rh.write(0x10 + idx*2 + 0, flags | (vector as u32) );
	}
	pub fn disable_irq(&self, idx: usize)
	{
		let mut rh = self.regs.lock();
		log_debug!("Disable {}: Info = {:#x}", idx, rh.read(0x10 + idx*2));
		rh.write(0x10 + idx*2 + 0, 1<<16);
	}

	pub fn get_irq_reg(&self, idx: usize) -> u64
	{
		let mut rh = self.regs.lock();

		(rh.read(0x10 + idx*2 + 0) as u64) | (rh.read(0x10 + idx*2 + 1) as u64) << 32
	}
}

impl IOAPICRegs
{
	fn new( paddr: u64 ) -> IOAPICRegs
	{
		// Assume SAFE: Should not end up with aliasing
		let mapping = unsafe { ::memory::virt::map_hw_rw(paddr, 1, "IOAPIC").unwrap() };
		IOAPICRegs {
			mapping: mapping
		}
	}
	fn read(&mut self, idx: usize) -> u32
	{
		// Assume SAFE: Hardware accesses
		unsafe {
			let regs = self.mapping.as_mut::<[APICReg; 2]>(0);
			::core::intrinsics::volatile_store(&mut regs[0].data as *mut _, idx as u32);
			::core::intrinsics::volatile_load(&regs[1].data as *const _)
		}
	}
	fn write(&mut self, idx: usize, data: u32)
	{
		// Assume SAFE: Hardware accesses
		unsafe {
			let regs = self.mapping.as_mut::<[APICReg; 2]>(0);
			::core::intrinsics::volatile_store(&mut regs[0].data as *mut _, idx as u32);
			::core::intrinsics::volatile_store(&mut regs[1].data as *mut _, data)
		}
	}

}

// vim: ft=rust
<commit_msg>Kernel - Fix invalid parameters to asm! that caused LLVM crash<commit_after>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// arch/amd64/hw/apic/raw.rs
// - x86 APIC Raw hardware API
use prelude::*;

static TIMER_VEC: u8 = 0x7E;

pub struct LAPIC
{
	paddr: u64,
	mapping: ::memory::virt::AllocHandle,
	timer_isr: ::arch::interrupts::ISRHandle,
}

pub struct IOAPIC
{
	regs: ::sync::Mutex<IOAPICRegs>,
	num_lines: usize,
	first_irq: usize,
	handlers: ::sync::Spinlock< Vec< Option<super::IRQHandler> > >,
}

struct IOAPICRegs
{
	mapping: ::memory::virt::AllocHandle,
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum TriggerMode
{
	LevelHi,
	LevelLow,
	EdgeHi,
	EdgeLow,
}

#[allow(dead_code)]
#[repr(u8)]
#[derive(Copy,Clone)]
#[allow(non_camel_case_types)]
enum ApicReg
{
	LAPIC_ID  = 0x2,
	LAPIC_Ver = 0x3,
	TPR       = 0x8,	// Task Priority
	APR       = 0x9,	// Arbitration Priority
	PPR       = 0xA,	// Processor Priority
	EOI       = 0xB,
	RRD       = 0xC,	// Remote Read
	LocalDest = 0xD,	// Local Destination
	DestFmt   = 0xE,	// Destination Format
	SIR       = 0xF,	// Spurious Interrupt Vector
	InService = 0x10,	// In-Service Register (First of 8)
	TMR       = 0x18,	// Trigger Mode (1/8)
	IRR       = 0x20,	// Interrupt Request Register (1/8)
	ErrStatus = 0x28,	// Error Status
	LVTCMCI   = 0x2F,	// LVT CMCI Registers (?)
	ICR       = 0x30,	// Interrupt Command Register (1/2)
	LVTTimer  = 0x32,
	LVTThermalSensor = 0x33,
	LVTPermCounters  = 0x34,
	LVT_LINT0 = 0x35,
	LVT_LINT1 = 0x36,
	LVT_Error = 0x37,
	InitCount = 0x38,
	CurCount  = 0x39,
	TmrDivide = 0x3E,
}

#[repr(C,packed)]
struct APICReg
{
	data: u32,
	_rsvd: [u32; 3],
}

impl LAPIC
{
	pub fn new(paddr: u64) -> LAPIC
	{
		let ret = LAPIC {
			paddr: paddr,
			// Assume SAFE: Shouldn't be aliasing
			mapping: unsafe { ::memory::virt::map_hw_rw(paddr, 1, "APIC").unwrap() },
			timer_isr: Default::default(),
			};

		log_debug!("LAPIC {{ IDReg={:x}, Ver={:x}, SIR={:#x} }}",
			ret.read_reg(ApicReg::LAPIC_ID),
			ret.read_reg(ApicReg::LAPIC_Ver),
			ret.read_reg(ApicReg::SIR)
			);

		ret
	}
	/// Initialise the LAPIC structures once self is in its final location
	pub fn global_init(&mut self)
	{
		self.timer_isr = match ::arch::interrupts::bind_isr(TIMER_VEC, lapic_timer, self as *mut _ as *const (), 0)
			{
			Ok(v) => v,
			Err(e) => panic!("Unable to bind LAPIC timer: {:?}", e),
			};
	}
	/// Initialise the LAPIC (for this CPU)
	pub fn init(&self)
	{
		let oldaddr = unsafe{
			let mut a: u32;
			let mut d: u32;
			asm!("rdmsr" : "={eax}" (a), "={edx}" (d) : "{ecx}" (0x1Bu32) : "rdx");
			(d as u64) << 32 | a as u64
			};
		log_debug!("oldaddr = {:#x}", oldaddr);
		let is_bsp = oldaddr & 0x100;
		log_debug!("IRR[0..8] = [{:#x}, {:#x}, {:#x}, {:#x},  {:#x}, {:#x}, {:#x}, {:#x}]",
			self.read_reg(ApicReg::irr(0)),
			self.read_reg(ApicReg::irr(1)),
			self.read_reg(ApicReg::irr(2)),
			self.read_reg(ApicReg::irr(3)),
			self.read_reg(ApicReg::irr(4)),
			self.read_reg(ApicReg::irr(5)),
			self.read_reg(ApicReg::irr(6)),
			self.read_reg(ApicReg::irr(7))
			);

		//self.write_reg(ApicReg::SIR as usize, self.read_reg(ApicReg_SIR as usize) | (1 << 8));
		self.write_reg(ApicReg::SIR, 0x7F | (1 << 8));	// Enable LAPIC (and set Spurious to 127)
		self.write_reg(ApicReg::InitCount, 0x100000);
		self.write_reg(ApicReg::TmrDivide, 3);	// Timer Divide = 16
		self.write_reg(ApicReg::LVTTimer, TIMER_VEC as u32);	// Enable Timer
		self.write_reg(ApicReg::LVTThermalSensor, 0);	// "Disable" Thermal Sensor
		self.write_reg(ApicReg::LVTPermCounters, 0);	// "Disable" ? Counters
		self.write_reg(ApicReg::LVT_LINT0, 0);	// "Disable" LINT0
		self.write_reg(ApicReg::LVT_LINT1, 0);	// "Disable" LINT1
		self.write_reg(ApicReg::LVT_Error, 0);	// "Disable" Error
		// EOI - Just to make sure
		self.eoi(0);
		unsafe {
			asm!("wrmsr\nsti"
				: /* no out */
				: "{ecx}" (0x1Bu32), "{edx}" (self.paddr >> 32), "{eax}" (self.paddr | is_bsp | 0x800)
				: /* no clobbers */
				: "volatile"
				);

			// Quick debug
			let mut ef: u64; asm!("pushf\npop $0" : "=r" (ef)); log_debug!("EFLAGS = {:#x}", ef);
		}
	}
	pub fn eoi(&self, num: usize)
	{
		self.write_reg(ApicReg::EOI, num as u32);
	}

	fn read_reg(&self, reg: ApicReg) -> u32
	{
		let regs = self.mapping.as_ref::<[APICReg; 64]>(0);
		assert!( (reg as usize) < 64 );
		unsafe { ::core::intrinsics::volatile_load( &regs[reg as usize].data as *const _ ) }
	}
	fn write_reg(&self, idx: ApicReg, value: u32)
	{
		let regs = unsafe { self.mapping.as_int_mut::<[APICReg; 64]>(0) };
		assert!( (idx as usize) < 64 );
		unsafe { ::core::intrinsics::volatile_store( &mut regs[idx as usize].data as *mut _, value ) }
	}

	pub fn get_vec_status(&self, idx: u8) -> (bool,bool,bool, u32)
	{
		let reg = idx / 32;
		let bit = idx % 32;
		let mask = 1 << bit;
		let in_svc = self.read_reg(ApicReg::in_service(reg)) & mask != 0;
		let mode   = self.read_reg(ApicReg::tmr(reg)) & mask != 0;
		let in_req = self.read_reg(ApicReg::irr(reg)) & mask != 0;
		let err = self.read_reg(ApicReg::ErrStatus);

		(in_svc, mode, in_req, err)
	}

	fn local_timer(isr: usize, sp: *const (), _idx: usize)
	{
		assert!( !sp.is_null() );
		let s: &LAPIC = unsafe { &*(sp as *const LAPIC) };
		log_trace!("LAPIC Timer");
		s.eoi(isr);
	}
}
impl ApicReg
{
	fn in_service(reg: u8) -> ApicReg
	{
		assert!(reg < 8);
		unsafe { ::core::mem::transmute(ApicReg::InService as u8 + reg as u8) }
	}
	fn tmr(reg: u8) -> ApicReg
	{
		assert!(reg < 8);
		unsafe { ::core::mem::transmute(ApicReg::TMR as u8 + reg as u8) }
	}
	fn irr(reg: u8) -> ApicReg
	{
		assert!(reg < 8);
		unsafe { ::core::mem::transmute(ApicReg::IRR as u8 + reg as u8) }
	}
}

extern "C" fn lapic_timer(isr: usize, sp: *const (), _idx: usize)
{
	LAPIC::local_timer(isr, sp, _idx);
}

impl IOAPIC
{
	pub fn new(paddr: u64, base: usize) -> IOAPIC
	{
		let mut regs = IOAPICRegs::new(paddr);
		let v = regs.read(1);
		log_debug!("{:x} {:x} {:x}", v, v>>16, (v >> 16) & 0xFF);
		let num_lines = ((v >> 16) & 0xFF) as usize + 1;
		log_debug!("regs=[{:#x},{:#x},{:#x}]", regs.read(0), regs.read(1), regs.read(2));

		log_debug!("IOAPIC: {{ {:#x} - {} + {} }}", paddr, base, num_lines);
		IOAPIC {
			regs: ::sync::Mutex::new( regs ),
			num_lines: num_lines,
			first_irq: base,
			handlers: ::sync::Spinlock::new( Vec::from_fn(num_lines, |_| None) ),
			}
	}

	pub fn contains(&self, gsi: usize) -> bool {
		self.first_irq <= gsi && gsi < self.first_irq + self.num_lines
	}
	pub fn first(&self) -> usize {
		self.first_irq
	}
	pub fn get_callback(&self, idx: usize) -> Option<super::IRQHandler> {
		assert!( idx < self.num_lines );
		self.handlers.lock()[idx]
	}

	pub fn eoi(&self, _idx: usize)
	{
		// TODO: EOI in IOAPIC
	}
	pub fn set_irq(&self, idx: usize, vector: u8, apic: u32, mode: TriggerMode, cb: super::IRQHandler)
	{
		log_trace!("set_irq(idx={},vector={},apic={},mode={:?})", idx, vector, apic, mode);
		assert!( idx < self.num_lines );

		// Unsynchronised write. Need to use Spinlock (with IRQ hold)?
		{
			let _irql = ::sync::hold_interrupts();
			self.handlers.lock()[idx] = Some( cb );
		}
		let flags: u32 = match mode {
			TriggerMode::EdgeHi   => (0<<13)|(0<<15),
			TriggerMode::EdgeLow  => (1<<13)|(0<<15),
			TriggerMode::LevelHi  => (0<<13)|(1<<15),
			TriggerMode::LevelLow => (1<<13)|(1<<15),
			};

		let mut rh = self.regs.lock();
		log_debug!("Info = {:#x}", rh.read(0x10 + idx*2));
		rh.write(0x10 + idx*2 + 1, (apic as u32) << 56-32 );
		rh.write(0x10 + idx*2 + 0, flags | (vector as u32) );
	}
	pub fn disable_irq(&self, idx: usize)
	{
		let mut rh = self.regs.lock();
		log_debug!("Disable {}: Info = {:#x}", idx, rh.read(0x10 + idx*2));
		rh.write(0x10 + idx*2 + 0, 1<<16);
	}

	pub fn get_irq_reg(&self, idx: usize) -> u64
	{
		let mut rh = self.regs.lock();

		(rh.read(0x10 + idx*2 + 0) as u64) | (rh.read(0x10 + idx*2 + 1) as u64) << 32
	}
}

impl IOAPICRegs
{
	fn new( paddr: u64 ) -> IOAPICRegs
	{
		// Assume SAFE: Should not end up with aliasing
		let mapping = unsafe { ::memory::virt::map_hw_rw(paddr, 1, "IOAPIC").unwrap() };
		IOAPICRegs {
			mapping: mapping
		}
	}
	fn read(&mut self, idx: usize) -> u32
	{
		// Assume SAFE: Hardware accesses
		unsafe {
			let regs = self.mapping.as_mut::<[APICReg; 2]>(0);
			::core::intrinsics::volatile_store(&mut regs[0].data as *mut _, idx as u32);
			::core::intrinsics::volatile_load(&regs[1].data as *const _)
		}
	}
	fn write(&mut self, idx: usize, data: u32)
	{
		// Assume SAFE: Hardware accesses
		unsafe {
			let regs = self.mapping.as_mut::<[APICReg; 2]>(0);
			::core::intrinsics::volatile_store(&mut regs[0].data as *mut _, idx as u32);
			::core::intrinsics::volatile_store(&mut regs[1].data as *mut _, data)
		}
	}

}

// vim: ft=rust
<|endoftext|>