mirror of
https://github.com/xomboverlord/xomb-bare-bones.git
synced 2026-01-11 10:16:36 +01:00
Version 1.0.0 of the XOmB Bare Bones distribution! With Bare Bones, all you get is booting up, printing some stuff out, and then looping into infinity (and beyond). Have fun!
This commit is contained in:
14
LICENSE
Normal file
14
LICENSE
Normal file
@@ -0,0 +1,14 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar
|
||||
14 rue de Plaisance, 75014 Paris, France
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
129
README
129
README
@@ -0,0 +1,129 @@
|
||||
This is the XOmB-barebones distribution. It comes with the bare minimum needed to get a booting OS in D.
|
||||
|
||||
Except we added kprintfln. You're welcome.
|
||||
|
||||
The updated version of this file is kept on our wiki, located here:
|
||||
http://wiki.xomb.org/index.php?title=XOmB_Bare_Bones
|
||||
|
||||
Don't expect this to be kept as up to date. We'll try, but the newest version will always be on the wiki, so check there.
|
||||
|
||||
The XOmB Bare Bones distribution is a minimal 64 bit OS written in D, distilled from the main project by [[User:Wilkie|wilkie]] and [[User:Steveklabnik|Steve Klabnik]].
|
||||
|
||||
|
||||
== About ==
|
||||
The [http://wiki.osdev.org osdev wiki] has a page called [http://wiki.osdev.org/Bare_Bones Bare Bones]. On it, they show how to make a minimal OS written in the C programming language. When we started [http://forum.osdev.org/viewtopic.php?f=15&t=18914 discussing programming an OS in D], some people indicated an interest in having a similar example, but in the D language.
|
||||
|
||||
We decided to oblige. We've distilled a minimal OS out of XOmB, and are releasing it as the "XOmB Bare Bones" distribution.
|
||||
|
||||
== Get XBB ==
|
||||
The git repository is located [http://github.com/xomboverlord/xomb-bare-bones/tree/master here]. If you haven't used git before, check out our [[Using Git]] tutorial.
|
||||
|
||||
The short lowdown:
|
||||
|
||||
git clone git://github.com/xomboverlord/xomb-bare-bones.git
|
||||
|
||||
|
||||
== Using XBB ==
|
||||
|
||||
First, a small word about compilers: GDC is dead. Unfortunatly, LDC isn't quite up to snuff yet, and while it's being worked on, unfortunatly, we have to stick with GDC. Expect things to get better in this area soon.
|
||||
|
||||
The first thing that you need to do in order to use XBB is create a cross compiler. Unfortunatly, our wiki is sparse on this subject at the moment, and so is the [http://wiki.osdev.org/GDC_Cross-Compiler osdev wiki]... we're sorry. That's coming soon.
|
||||
|
||||
After you have that up and running, you need to add a profile. We use dsss/rebuild to build stuff, and when we did it, it installed to /opt/etc/. So copy the gdc-xomb file from build/ (in the xomb-bare-bones directory) to /opt/etc/rebuild/ and you should be golden. Hopefully.
|
||||
|
||||
To build, just run
|
||||
<pre>dsss build</pre> from within the build/ directory. This will make 'xomb.iso'. Then feel free to run it with bochs, xen, or whatever.
|
||||
|
||||
And that's it! Pretty easy, right?
|
||||
|
||||
== XBB Features ==
|
||||
Considering that XBB is, well, bare-bones, it doesn't do much. kmain consists of one kprintfln! statement, which just prints a line to the screen. We've included a kprintfln! implementation to show off the power of D's templating system, but feel free to replace it, of course.
|
||||
|
||||
== XBB Organization ==
|
||||
|
||||
The XBB directory looks like this:
|
||||
$ tree -L 1
|
||||
.
|
||||
|-- LICENSE
|
||||
|-- README
|
||||
|-- build
|
||||
|-- kernel
|
||||
|
||||
2 directories, 2 files
|
||||
|
||||
We've moved all of the source into kernel, because you (at some point) will want to write userspace code. You'd probably want to make another directory in the main tree with all of that code in it. The main XOmB project has libos/ and tools/ and such.
|
||||
|
||||
=== LICENSE ===
|
||||
XBB is distributed under the [http://sam.zoy.org/wtfpl/ WTFPL]. This is the most free license we could possibly imagine that still contains a swear word, so have at it.
|
||||
|
||||
=== README ===
|
||||
The readme contains a copy of this page, though it's not updated quite as often as this page is.
|
||||
|
||||
=== build/ ===
|
||||
$ tree -L 1 build/
|
||||
build/
|
||||
|-- bochsrc
|
||||
|-- dsss.conf
|
||||
|-- dsss.last
|
||||
|-- dsss_objs
|
||||
|-- iso
|
||||
|-- linker.ld
|
||||
|-- xomb.dump
|
||||
`-- xomb.iso
|
||||
|
||||
2 directories, 6 files
|
||||
==== bochsrc ====
|
||||
Assuming you're running bochs, we've given you a bochsrc.
|
||||
|
||||
==== dsss.conf ====
|
||||
This file tells dsss how to build XBB.
|
||||
|
||||
==== dsss.last ====
|
||||
This is another file that dsss generates.
|
||||
|
||||
==== dsss_objs ====
|
||||
This directory contains all of the intermediate stuff that dsss needs to do its job.
|
||||
|
||||
==== iso ====
|
||||
This directory contains a copy of the actual FS contained in xomb.iso.
|
||||
|
||||
==== linker.ld ====
|
||||
This script lets ld know how it should link everything together.
|
||||
|
||||
==== xomb.dump ====
|
||||
A dump of the iso. Very useful for seeing exactly what asm gets generated after compiling things.
|
||||
|
||||
==== xomb.iso ====
|
||||
This is the actual .iso file that needs to be burnt to a CD (or run in some other manner) to run the OS!
|
||||
|
||||
=== kernel/ ===
|
||||
$ tree -L 1 kernel/
|
||||
kernel/
|
||||
|-- arch
|
||||
|-- config.d
|
||||
|-- core
|
||||
|-- dev
|
||||
`-- runtime
|
||||
|
||||
4 directories, 1 file
|
||||
|
||||
==== arch ====
|
||||
This directory contains everything pertaining to architecture. If you wanted to port XBB to arm or something, the code would go in here.
|
||||
|
||||
==== config.d ====
|
||||
This sets a bunch of configuration options, mostly relating to debugging information.
|
||||
|
||||
==== core ====
|
||||
This is where it all goes down. The core kernel code is located inside.
|
||||
|
||||
==== dev ====
|
||||
Everything in this directory pertains to devices.
|
||||
|
||||
==== runtime ====
|
||||
The kernel D runtime. This runtime is nowhere near robust as a full userspace runtime would be, as the kernel donesn't need such niceties as garbage collection. Just the bare minimum, thanks.
|
||||
|
||||
== For More Info ==
|
||||
Check out the individual source files for information on how specific things work. We've made an attempt to heavily comment everything, so that you can see in the code itself how things work.
|
||||
|
||||
If you find that you need more help, please [[Contact |contact]] us, and we'll do our best. Please let us know if there's anything that we can do to make this project better!
|
||||
|
||||
|
||||
4
build/.gitignore
vendored
Normal file
4
build/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
dsss_objs/*
|
||||
dsss.last
|
||||
xomb.dump
|
||||
xomb.iso
|
||||
5
build/bochsrc
Normal file
5
build/bochsrc
Normal file
@@ -0,0 +1,5 @@
|
||||
romimage: file=/usr/src/bochs-2.3.7/bios/BIOS-bochs-latest
|
||||
megs: 128
|
||||
ata1-slave: type=cdrom, path="./xomb.iso", status=inserted
|
||||
boot: cdrom
|
||||
cpu: count=2, reset_on_triple_fault=0
|
||||
64
build/dsss.conf
Normal file
64
build/dsss.conf
Normal file
@@ -0,0 +1,64 @@
|
||||
name = xomb
|
||||
|
||||
CC = x86_64-pc-elf-gcc
|
||||
CFLAGS = -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel
|
||||
|
||||
[*]
|
||||
buildflags=-dc=gdc-xomb
|
||||
|
||||
[../kernel/core/kmain.d]
|
||||
|
||||
buildflags=-dc=gdc-xomb -I..
|
||||
|
||||
# compile the assembly for the target
|
||||
|
||||
prebuild= \
|
||||
\
|
||||
\
|
||||
echo ; \
|
||||
echo Compiling Assembly for target: x86_64 ;\
|
||||
echo '--> boot.S';\
|
||||
x86_64-pc-elf-gcc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -c ../kernel/arch/x86_64/boot/boot.S -o dsss_objs/G/kernel.arch.x86_64.boot.boot.o ; \
|
||||
echo '--> load.S';\
|
||||
x86_64-pc-elf-gcc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -c ../kernel/arch/x86_64/boot/load.S -o dsss_objs/G/kernel.arch.x86_64.boot.load.o ; \
|
||||
#echo '--> trampoline.S';\
|
||||
#x86_64-pc-elf-gcc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -c ../kernel/arch/x86_64/boot/trampoline.S -o dsss_objs/G/kernel.arch.x86_64.boot.trampoline.o ;\
|
||||
\
|
||||
\
|
||||
echo ; \
|
||||
echo Compiling Kernel Runtime ; \
|
||||
echo '--> kernel/runtime/object.d';\
|
||||
x86_64-pc-elf-gdc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -I .. -I ../kernel/runtime/. -c ../kernel/runtime/object.d -o dsss_objs/G/kernel.runtime.object.o ;\
|
||||
echo '--> kernel/runtime/invariant.d';\
|
||||
x86_64-pc-elf-gdc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -I .. -I ../kernel/runtime/. -c ../kernel/runtime/invariant.d -o dsss_objs/G/kernel.runtime.invariant.o ;\
|
||||
echo '--> kernel/runtime/std/typeinfo/*';\
|
||||
x86_64-pc-elf-gdmd -q,-nostdlib,-nodefaultlibs,-g,-DUSE_ASSERT,-mcmodel=kernel -I.. -I../kernel/runtime/. -c `ls ../kernel/runtime/std/typeinfo/*.d` -oddsss_objs/G/. ;\
|
||||
echo '--> kernel/runtime/dstubs.d';\
|
||||
x86_64-pc-elf-gdc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -I .. -I ../kernel/runtime/. -c ../kernel/runtime/dstubs.d -o dsss_objs/G/kernel.runtime.dstubs.o ;\
|
||||
echo '--> kernel/runtime/util.d';\
|
||||
x86_64-pc-elf-gdc -nostdlib -nodefaultlibs -g -DUSE_ASSERT -mcmodel=kernel -I .. -I ../kernel/runtime/. -c ../kernel/runtime/util.d -o dsss_objs/G/kernel.runtime.util.o ;\
|
||||
\
|
||||
echo ; \
|
||||
echo Compiling Kernel Proper ;
|
||||
|
||||
# what the target is
|
||||
|
||||
target = xomb.iso
|
||||
|
||||
# we will need some post build foo to link and create the iso
|
||||
|
||||
postbuild = \
|
||||
\
|
||||
echo ; \
|
||||
echo Creating Kernel Executable; \
|
||||
echo '--> xomb';\
|
||||
x86_64-pc-elf-ld -nostdlib -nodefaultlibs -b elf64-x86-64 -T linker.ld -o iso/boot/xomb `ls dsss_objs/G/*.o`;\
|
||||
\
|
||||
echo ;\
|
||||
echo Creating Kernel Dump; \
|
||||
echo '--> xomb.dump';\
|
||||
rm -f xomb.dump && x86_64-pc-elf-objdump -d -S -r iso/boot/xomb > xomb.dump;\
|
||||
\
|
||||
echo ;\
|
||||
echo Compiling ISO; \
|
||||
mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 16 -boot-info-table -o xomb.iso ./iso
|
||||
35
build/gdc-xomb
Normal file
35
build/gdc-xomb
Normal file
@@ -0,0 +1,35 @@
|
||||
profile=phobos
|
||||
|
||||
compiler=x86_64-pc-elf-gdc
|
||||
|
||||
exeext=
|
||||
objext=o
|
||||
|
||||
|
||||
noversion=DigitalMars
|
||||
version=GNU
|
||||
testversion=linux
|
||||
testversion=darwin
|
||||
version=Unix
|
||||
version=Posix
|
||||
noversion=Windows
|
||||
noversion=Win32
|
||||
noversion=Win64
|
||||
testversion=X86
|
||||
testversion=PPC
|
||||
testversion=X86_64
|
||||
testversion=D_InlineAsm
|
||||
testversion=D_InlineAsm_X86
|
||||
testversion=D_InlineAsm_PPC
|
||||
testversion=D_InlineAsm_X86_64
|
||||
testversion=LittleEndian
|
||||
testversion=BigEndian
|
||||
|
||||
[compile]
|
||||
cmd=x86_64-pc-elf-gdmd -q,-nostdlib,-nodefaultlibs,-g,-DUSE_ASSERT,-mcmodel=kernel -I../kernel/runtime/ -c $i
|
||||
|
||||
[link]
|
||||
cmd=#
|
||||
|
||||
[postlink]
|
||||
cmd=echo "lol fuckers"
|
||||
129
build/iso/boot/grub/menu.lst
Normal file
129
build/iso/boot/grub/menu.lst
Normal file
@@ -0,0 +1,129 @@
|
||||
# menu.lst - See: grub(8), info grub, update-grub(8)
|
||||
# grub-install(8), grub-floppy(8),
|
||||
# grub-md5-crypt, /usr/share/doc/grub
|
||||
# and /usr/share/doc/grub-doc/.
|
||||
|
||||
## default num
|
||||
# Set the default entry to the entry number NUM. Numbering starts from 0, and
|
||||
# the entry number 0 is the default if the command is not used.
|
||||
#
|
||||
# You can specify 'saved' instead of a number. In this case, the default entry
|
||||
# is the entry saved with the command 'savedefault'.
|
||||
# WARNING: If you are using dmraid do not change this entry to 'saved' or your
|
||||
# array will desync and will not let you boot your system.
|
||||
default 0
|
||||
|
||||
## timeout sec
|
||||
# Set a timeout, in SEC seconds, before automatically booting the default entry
|
||||
# (normally the first entry defined).
|
||||
timeout 0
|
||||
|
||||
## hiddenmenu
|
||||
# Hides the menu by default (press ESC to see the menu)
|
||||
hiddenmenu
|
||||
|
||||
# Pretty colours
|
||||
#color cyan/blue white/blue
|
||||
|
||||
## password ['--md5'] passwd
|
||||
# If used in the first section of a menu file, disable all interactive editing
|
||||
# control (menu entry editor and command-line) and entries protected by the
|
||||
# command 'lock'
|
||||
# e.g. password topsecret
|
||||
# password --md5 $1$gLhU0/$aW78kHK1QfV3P2b2znUoe/
|
||||
# password topsecret
|
||||
|
||||
#
|
||||
# examples
|
||||
#
|
||||
# title Windows 95/98/NT/2000
|
||||
# root (hd0,0)
|
||||
# makeactive
|
||||
# chainloader +1
|
||||
#
|
||||
# title Linux
|
||||
# root (hd0,1)
|
||||
# kernel /vmlinuz root=/dev/hda2 ro
|
||||
#
|
||||
|
||||
#
|
||||
# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST
|
||||
|
||||
### BEGIN AUTOMAGIC KERNELS LIST
|
||||
## lines between the AUTOMAGIC KERNELS LIST markers will be modified
|
||||
## by the debian update-grub script except for the default options below
|
||||
|
||||
## DO NOT UNCOMMENT THEM, Just edit them to your needs
|
||||
|
||||
## ## Start Default Options ##
|
||||
## default kernel options
|
||||
## default kernel options for automagic boot options
|
||||
## If you want special options for specific kernels use kopt_x_y_z
|
||||
## where x.y.z is kernel version. Minor versions can be omitted.
|
||||
## e.g. kopt=root=/dev/hda1 ro
|
||||
## kopt_2_6_8=root=/dev/hdc1 ro
|
||||
## kopt_2_6_8_2_686=root=/dev/hdc2 ro
|
||||
# kopt=root=UUID=766f85b2-0ecb-45b7-8ad9-b108f2eba4a2 ro
|
||||
|
||||
## Setup crashdump menu entries
|
||||
## e.g. crashdump=1
|
||||
# crashdump=0
|
||||
|
||||
## default grub root device
|
||||
## e.g. groot=(hd0,0)
|
||||
# groot=(hd0,0)
|
||||
|
||||
## should update-grub create alternative automagic boot options
|
||||
## e.g. alternative=true
|
||||
## alternative=false
|
||||
# alternative=true
|
||||
|
||||
## should update-grub lock alternative automagic boot options
|
||||
## e.g. lockalternative=true
|
||||
## lockalternative=false
|
||||
# lockalternative=false
|
||||
|
||||
## additional options to use with the default boot option, but not with the
|
||||
## alternatives
|
||||
## e.g. defoptions=vga=791 resume=/dev/hda5
|
||||
# defoptions=quiet splash
|
||||
|
||||
## should update-grub lock old automagic boot options
|
||||
## e.g. lockold=false
|
||||
## lockold=true
|
||||
# lockold=false
|
||||
|
||||
## Xen hypervisor options to use with the default Xen boot option
|
||||
# xenhopt=
|
||||
|
||||
## Xen Linux kernel options to use with the default Xen boot option
|
||||
# xenkopt=console=tty0
|
||||
|
||||
## altoption boot targets option
|
||||
## multiple altoptions lines are allowed
|
||||
## e.g. altoptions=(extra menu suffix) extra boot options
|
||||
## altoptions=(recovery) single
|
||||
# altoptions=(recovery mode) single
|
||||
|
||||
## controls how many kernels should be put into the menu.lst
|
||||
## only counts the first occurence of a kernel, not the
|
||||
## alternative kernel options
|
||||
## e.g. howmany=all
|
||||
## howmany=7
|
||||
# howmany=all
|
||||
|
||||
## should update-grub create memtest86 boot option
|
||||
## e.g. memtest86=true
|
||||
## memtest86=false
|
||||
# memtest86=true
|
||||
|
||||
## should update-grub adjust the value of the default booted system
|
||||
## can be true or false
|
||||
# updatedefaultentry=false
|
||||
|
||||
## ## End Default Options ##
|
||||
|
||||
title XOmB
|
||||
kernel /boot/xomb
|
||||
#module /your/module
|
||||
### END PITTGEEKS AUTOMAGIC KERNELS LIST
|
||||
BIN
build/iso/boot/grub/stage2_eltorito
Normal file
BIN
build/iso/boot/grub/stage2_eltorito
Normal file
Binary file not shown.
125
build/linker.ld
Normal file
125
build/linker.ld
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
linker.ld
|
||||
|
||||
* This script is given as the only script to the linker
|
||||
* Will map boot.S to LMA, and then everything else
|
||||
will be linked to the VMA and mapped at the LMA
|
||||
* _etext, _edata, _end are defined here
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* KERNEL LINK LOCATIONS
|
||||
|
||||
these are the locations to map to
|
||||
they need to be set within boot.h
|
||||
as well
|
||||
|
||||
*/
|
||||
|
||||
kernel_VMA = 0xffffffff80000000;
|
||||
kernel_LMA = 0x100000;
|
||||
|
||||
/* start from the entry point */
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
/* link from LMA */
|
||||
. = kernel_LMA;
|
||||
|
||||
_boot = .;
|
||||
|
||||
/* boot.S is ran in linear addresses */
|
||||
.text_boot :
|
||||
{
|
||||
dsss_objs/G/kernel.arch.x86_64.boot.boot.o (.text)
|
||||
}
|
||||
|
||||
_eboot = .;
|
||||
|
||||
/* The following is for the trampoline code, if and when
|
||||
* multiprocessor support will be necessary.
|
||||
*/
|
||||
|
||||
/* PROVIDE(_trampoline = .);
|
||||
|
||||
.text_trampoline ALIGN(0x1000) :
|
||||
{
|
||||
dsss_objs/G/kernel.arch.x86_64.boot.trampoline.o (.text)
|
||||
}
|
||||
|
||||
PROVIDE(_etrampoline = .); */
|
||||
|
||||
/* link from VMA */
|
||||
. = . + kernel_VMA;
|
||||
|
||||
_text = .;
|
||||
|
||||
PROVIDE(_kernel = .);
|
||||
PROVIDE(_kernelBase = kernel_VMA);
|
||||
|
||||
/* the rest of the code links to higher memory */
|
||||
.text : AT(ADDR(.text) - kernel_VMA + kernel_LMA)
|
||||
{
|
||||
code = .;
|
||||
*(.text)
|
||||
*(.text*)
|
||||
|
||||
/* read only data */
|
||||
*(.rodata*)
|
||||
*(.rdata*)
|
||||
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
PROVIDE(_ekernel = .);
|
||||
|
||||
/* _etext defined */
|
||||
PROVIDE (_etext = .);
|
||||
|
||||
_data = .;
|
||||
|
||||
/* data section */
|
||||
.data : AT(ADDR(.data) - kernel_VMA + kernel_LMA)
|
||||
{
|
||||
data = .;
|
||||
*(.data)
|
||||
|
||||
/* constructors and deconstructors
|
||||
(if needed, doesn't hurt) */
|
||||
|
||||
start_ctors = .;
|
||||
*(.ctor*)
|
||||
end_ctors = .;
|
||||
|
||||
start_dtors = .;
|
||||
*(.dtor*)
|
||||
end_dtors = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
/* _edata defined */
|
||||
_edata = .; PROVIDE (edata = .);
|
||||
|
||||
/* static code */
|
||||
.bss : AT(ADDR(.bss) - kernel_VMA + kernel_LMA)
|
||||
{
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
/* */
|
||||
.ehframe : AT(ADDR(.ehframe) - kernel_VMA + kernel_LMA)
|
||||
{
|
||||
ehframe = .;
|
||||
*(.ehframe)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
/* _end defined */
|
||||
_end = .; PROVIDE (end = .);
|
||||
|
||||
}
|
||||
|
||||
|
||||
16
kernel/arch/select.d
Normal file
16
kernel/arch/select.d
Normal file
@@ -0,0 +1,16 @@
|
||||
module kernel.arch.select;
|
||||
|
||||
// This module shows D's mixin capabilities to load modules for different architecture targets.
|
||||
|
||||
const char[] architecture = "x86_64";
|
||||
|
||||
template PublicArchImport(char[] mod)
|
||||
{
|
||||
const char[] PublicArchImport = `
|
||||
|
||||
public import kernel.arch.` ~ architecture ~ `.` ~ mod ~ `;
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
275
kernel/arch/x86_64/boot/boot.S
Normal file
275
kernel/arch/x86_64/boot/boot.S
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
|
||||
boot.S - bootstrap the kernel
|
||||
|
||||
The 32 bit bootstrap code that serves these functions:
|
||||
|
||||
- contains multiboot header
|
||||
- contains 32 bit GDT
|
||||
- contains 32 bit IDT (for debugging, can be removed later)
|
||||
- contains page tables
|
||||
- lower 40MB are mapped 1-1
|
||||
- higher 40MB (from 0xffffffff80000000) are mapped from 0x0 on
|
||||
- after code in load.S runs, the lower half map should not be needed
|
||||
|
||||
- transitions into long mode:
|
||||
- enables PAE (physical-address-extensions)
|
||||
- setting PML4 (page-map-level-4)
|
||||
- setting EFER flags for LMA (long-mode-active) and SYSCALL-SYSRET
|
||||
- enables paging by setting the PG bit in CR0 (Control Register 0)
|
||||
- long jumps to code within load.S
|
||||
|
||||
- note: some addresses located within the higher half need to be converted
|
||||
to linear addresses: the stack, _edata, _end
|
||||
- this is because: the multiboot header expects linear addresses,
|
||||
the CPU expects stack at linear address, as it would for GDT, IDT, etc
|
||||
|
||||
*/
|
||||
|
||||
#define EXE_COMPAT_HACK
|
||||
|
||||
#define ASM 1
|
||||
#include "multiboot.h"
|
||||
|
||||
#include "boot.h"
|
||||
|
||||
.globl start, _start
|
||||
|
||||
.text
|
||||
|
||||
start:
|
||||
_start:
|
||||
.code32
|
||||
|
||||
/* Stash values for multiboot we won't touch until 64 bit mode */
|
||||
movl %ebx, %esi
|
||||
movl %eax, %edi
|
||||
|
||||
/* jump to the 32 bit common start */
|
||||
jmp (start32)
|
||||
|
||||
/* Align 32 bits boundary. */
|
||||
.align 4
|
||||
|
||||
/* Multiboot header. */
|
||||
|
||||
multiboot_header:
|
||||
/* magic */
|
||||
.long MULTIBOOT_HEADER_MAGIC
|
||||
/* flags */
|
||||
.long MULTIBOOT_HEADER_FLAGS
|
||||
/* checksum */
|
||||
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||
|
||||
#ifdef EXE_COMPAT_HACK
|
||||
|
||||
/* header_addr */
|
||||
.long (multiboot_header)
|
||||
/* load_addr */
|
||||
.long (_start)
|
||||
/* load_end_addr */
|
||||
.long (_edata-KERNEL_VMA_BASE)
|
||||
/* bss_end_addr */
|
||||
.long (_end-KERNEL_VMA_BASE)
|
||||
/* entry_addr */
|
||||
.long (start)
|
||||
#endif
|
||||
|
||||
.global start32, _start32
|
||||
|
||||
_start32:
|
||||
start32:
|
||||
|
||||
/* disable interrupts (CLear Interrupt flag) */
|
||||
cli
|
||||
|
||||
/* enable 64-bit page-translation-table entries by
|
||||
setting CR4.PAE=1. Paging not enabled until after
|
||||
long mode enabled */
|
||||
movl %cr4, %eax
|
||||
bts $5, %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
/* Create long mode page table and init CR3 to point to
|
||||
the base of the PML4 page table. */
|
||||
movl $(pml4_base), %eax
|
||||
movl %eax, %cr3
|
||||
|
||||
/* Enable Long mode and SYSCALL/SYSRET instructions */
|
||||
movl $0xc0000080, %ecx
|
||||
rdmsr
|
||||
bts $8, %eax
|
||||
bts $0, %eax
|
||||
wrmsr
|
||||
|
||||
/* Load the 32 bit GDT */
|
||||
lgdt (pGDT32)
|
||||
|
||||
/* Load the 32 bit IDT */
|
||||
lidt (pIDT32)
|
||||
|
||||
/* establish a stack for 32 bit code */
|
||||
mov $((stack-KERNEL_VMA_BASE) + STACK_SIZE), %esp
|
||||
|
||||
/* enable paging to activate long mode */
|
||||
movl %cr0, %eax
|
||||
bts $31, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
// make the jump to long mode!
|
||||
ljmp $CS_KERNEL, $(start64-KERNEL_VMA_BASE)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The following are a series of kernel structures used by the cpu
|
||||
// These are temporary and will be replaced by permanent ones when the
|
||||
// kernel is executed proper.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 32 BIT GDT
|
||||
|
||||
.align 4096
|
||||
.globl pGDT32
|
||||
pGDT32:
|
||||
.word GDT_END - GDT_TABLE - 1
|
||||
.quad GDT_TABLE - KERNEL_VMA_BASE
|
||||
|
||||
.align 4096
|
||||
GDT_TABLE:
|
||||
.quad 0x0000000000000000 /* NULL descriptor */
|
||||
.quad 0x00cf9a000000ffff /* __KERNEL32_CS */
|
||||
.quad 0x00af9a000000ffff /* __KERNEL_CS */
|
||||
.quad 0x0000000000000000 /* upper half of CS */
|
||||
.quad 0x00af93000000ffff /* __KERNEL_DS */
|
||||
.quad 0x0000000000000000 /* upper half of DS */
|
||||
.quad 0x00affa000000ffff /* __USER_CS */
|
||||
.quad 0x0000000000000000 /* upper half of CS */
|
||||
.quad 0x00aff3000000ffff /* __USER_DS */
|
||||
.quad 0x0000000000000000 /* upper half of DS */
|
||||
.quad 0,0 /* TSS */
|
||||
.quad 0,0 /* TSS */
|
||||
.quad 0,0 /* LDT */
|
||||
.quad 0,0 /* LDT */
|
||||
|
||||
// wtf?
|
||||
.quad 0,0,0 /* three TLS descriptors */
|
||||
.quad 0x0000f40000000000 /* node/CPU stored in limit */
|
||||
GDT_END:
|
||||
|
||||
|
||||
// 32 BIT IDT
|
||||
|
||||
.align 4096
|
||||
|
||||
|
||||
.globl pIDT32
|
||||
pIDT32:
|
||||
|
||||
|
||||
.word IDT_END - IDT_TABLE - 1
|
||||
.quad IDT_TABLE - KERNEL_VMA_BASE
|
||||
|
||||
#define IDT_LOCATION 0x106000
|
||||
|
||||
.align 4096
|
||||
IDT_TABLE:
|
||||
i = 0
|
||||
.rept 32
|
||||
.long 0x100000 | ((IDT_LOCATION + i) & 0xFFFF)
|
||||
.long ((IDT_LOCATION + i) & 0xFFFF0000) | 0x8E00
|
||||
i = i + 8
|
||||
.endr
|
||||
IDT_END:
|
||||
|
||||
.align 4096
|
||||
|
||||
int_handler_32:
|
||||
|
||||
i = 0
|
||||
.rept 32
|
||||
mov i, %eax
|
||||
iret
|
||||
i = i + 1
|
||||
.endr
|
||||
|
||||
int_handler_32_end:
|
||||
|
||||
.align 4096 // the others may not be needed, but this one MUST BE THERE
|
||||
.globl pml4_base
|
||||
|
||||
// PML4
|
||||
pml4_base:
|
||||
.quad (level3_ident_pgt + 0x0000000000000007)
|
||||
.fill 510,8,0
|
||||
.quad (level3_ident_pgt + 0x0000000000000007)
|
||||
|
||||
|
||||
// --- THIS SHOULD BE ALIGNED AT 4K --- //
|
||||
|
||||
.align 4096
|
||||
.globl level3_ident_pgt
|
||||
// PDP
|
||||
// PML3
|
||||
level3_ident_pgt:
|
||||
.quad (level2_ident_pgt + 0x07)
|
||||
.quad 0 //(level2_ident_pgt + 0x07)
|
||||
.quad (level2_ident_pgt + 0x07)
|
||||
|
||||
.rept (507)
|
||||
.quad 0
|
||||
.endr
|
||||
|
||||
.quad (level2_ident_pgt + 0x07)
|
||||
.quad 0 // (level2_ident_pgt + 0x07)
|
||||
|
||||
|
||||
|
||||
// --- THIS SHOULD BE ALIGNED AT 4K --- //
|
||||
|
||||
|
||||
.align 4096
|
||||
.globl level2_ident_pgt
|
||||
// flags 0x00087
|
||||
// PDE
|
||||
// PML2
|
||||
level2_ident_pgt:
|
||||
i = 0
|
||||
|
||||
// 15 TABLE ENTRIES
|
||||
.rept 15
|
||||
.quad (level1_ident_pgt + i + 0x0000000000000007)
|
||||
i = i + 4096
|
||||
.endr
|
||||
|
||||
.fill 497,8,0
|
||||
|
||||
|
||||
// --- THIS SHOULD BE ALIGNED AT 4K --- //
|
||||
|
||||
|
||||
// PTE
|
||||
// PML1
|
||||
.align 4096
|
||||
.globl level1_ident_pgt
|
||||
level1_ident_pgt:
|
||||
// UM
|
||||
// 40MB for bootup.
|
||||
i = 0
|
||||
|
||||
// 15 TABLES
|
||||
.rept (512 * 15)
|
||||
.quad i << 12 | 0x087
|
||||
i = i + 1
|
||||
.endr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
21
kernel/arch/x86_64/boot/boot.h
Normal file
21
kernel/arch/x86_64/boot/boot.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
|
||||
boot.h
|
||||
|
||||
- Contains information pertinant to the bootstrap about where
|
||||
the kernel is located
|
||||
|
||||
*/
|
||||
|
||||
/* the code section for the kernel
|
||||
0x10 = code section 2 ( right shift it by 3 ) */
|
||||
#define CS_KERNEL 0x10
|
||||
#define CS_KERNEL32 0x8
|
||||
|
||||
/* the location, in physical address (LMA) and virtual (VMA) */
|
||||
/* these should correspond to linker.ld */
|
||||
|
||||
#define KERNEL_LMA_BASE 0x100000
|
||||
#define KERNEL_VMA_BASE (0xffffffff80000000)
|
||||
#define KERNEL_LOCATION (KERNEL_VMA_BASE + KERNEL_LMA_BASE)
|
||||
|
||||
94
kernel/arch/x86_64/boot/load.S
Normal file
94
kernel/arch/x86_64/boot/load.S
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
|
||||
load.S
|
||||
|
||||
The 64 bit code that serves these functions:
|
||||
|
||||
- sets up stack
|
||||
- transfers %rip to higher half
|
||||
- clears cpu flags
|
||||
- calls kmain with multiboot information
|
||||
|
||||
*/
|
||||
|
||||
#define ASM 1
|
||||
|
||||
#include "multiboot.h"
|
||||
#include "boot.h"
|
||||
|
||||
|
||||
.text
|
||||
.code64
|
||||
|
||||
.globl start64, _start64
|
||||
|
||||
start64:
|
||||
_start64:
|
||||
|
||||
|
||||
/* Initialize the 64 bit stack pointer. */
|
||||
movq $((stack - KERNEL_VMA_BASE) + STACK_SIZE), %rsp
|
||||
|
||||
/* set up the stack for the return */
|
||||
pushq $CS_KERNEL
|
||||
pushq $long_entry
|
||||
|
||||
/* Go into canonical higher half */
|
||||
/* This trick is borrowed from the linux kernel,
|
||||
/arch/x86_64/kernel/head.S */
|
||||
|
||||
lretq
|
||||
|
||||
long_entry:
|
||||
|
||||
/* From here on out, we are running instructions
|
||||
Within the higher half (0xffffffff80000000 ... )
|
||||
|
||||
We can safely unmap the lower half, we do not
|
||||
need an identity mapping of the lower half. */
|
||||
|
||||
movq $(stack + STACK_SIZE), %rsp
|
||||
|
||||
/* Set cpu flags */
|
||||
pushq $0
|
||||
lss (%rsp), %eax
|
||||
popf
|
||||
|
||||
/* Sets the Input/Output Permission Level to 3, so
|
||||
that it will not check the IO permissions bitmap when access is requested. */
|
||||
|
||||
pushf
|
||||
popq %rax
|
||||
or $0x3000, %rax
|
||||
pushq %rax
|
||||
popf
|
||||
|
||||
addq $(KERNEL_VMA_BASE), %rsi
|
||||
|
||||
/* Push the pointer to the Multiboot information structure. */
|
||||
pushq %rsi
|
||||
/* Push the magic value. */
|
||||
pushq %rdi
|
||||
|
||||
/* Now enter the kmain function... */
|
||||
call EXT_C(kmain)
|
||||
|
||||
|
||||
|
||||
/* We should not get here */
|
||||
|
||||
loop:
|
||||
|
||||
hlt
|
||||
jmp loop
|
||||
|
||||
// --- STACK --- //
|
||||
.globl stack
|
||||
.align 4096
|
||||
|
||||
// Our stack area.
|
||||
stack:
|
||||
.rept STACK_SIZE
|
||||
.long 0
|
||||
.endr
|
||||
|
||||
104
kernel/arch/x86_64/boot/multiboot.h
Normal file
104
kernel/arch/x86_64/boot/multiboot.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* multiboot.h - the header for Multiboot */
|
||||
|
||||
/* Macros. */
|
||||
|
||||
/* The magic number for the Multiboot header. */
|
||||
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
||||
|
||||
/* The flags for the Multiboot header. */
|
||||
//#ifdef __ELF__
|
||||
//# define MULTIBOOT_HEADER_FLAGS 0x00000003
|
||||
//#else
|
||||
# define MULTIBOOT_HEADER_FLAGS 0x00010003
|
||||
//#endif
|
||||
|
||||
/* The magic number passed by a Multiboot-compliant boot loader. */
|
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
|
||||
|
||||
/* The size of our stack (16KB). */
|
||||
#define STACK_SIZE 0x4000
|
||||
|
||||
/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
|
||||
#ifdef HAVE_ASM_USCORE
|
||||
# define EXT_C(sym) _ ## sym
|
||||
#else
|
||||
# define EXT_C(sym) sym
|
||||
#endif
|
||||
|
||||
#ifndef ASM
|
||||
/* Do not include here in boot.S. */
|
||||
|
||||
/* Types. */
|
||||
|
||||
/* The Multiboot header. */
|
||||
typedef struct multiboot_header
|
||||
{
|
||||
unsigned long magic;
|
||||
unsigned long flags;
|
||||
unsigned long checksum;
|
||||
unsigned long header_addr;
|
||||
unsigned long load_addr;
|
||||
unsigned long load_end_addr;
|
||||
unsigned long bss_end_addr;
|
||||
unsigned long entry_addr;
|
||||
} multiboot_header_t;
|
||||
|
||||
/* The symbol table for a.out. */
|
||||
typedef struct aout_symbol_table
|
||||
{
|
||||
unsigned long tabsize;
|
||||
unsigned long strsize;
|
||||
unsigned long addr;
|
||||
unsigned long reserved;
|
||||
} aout_symbol_table_t;
|
||||
|
||||
/* The section header table for ELF. */
|
||||
typedef struct elf_section_header_table
|
||||
{
|
||||
unsigned long num;
|
||||
unsigned long size;
|
||||
unsigned long addr;
|
||||
unsigned long shndx;
|
||||
} elf_section_header_table_t;
|
||||
|
||||
/* The Multiboot information. */
|
||||
typedef struct multiboot_info
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long mem_lower;
|
||||
unsigned long mem_upper;
|
||||
unsigned long boot_device;
|
||||
unsigned long cmdline;
|
||||
unsigned long mods_count;
|
||||
unsigned long mods_addr;
|
||||
union
|
||||
{
|
||||
aout_symbol_table_t aout_sym;
|
||||
elf_section_header_table_t elf_sec;
|
||||
} u;
|
||||
unsigned long mmap_length;
|
||||
unsigned long mmap_addr;
|
||||
} multiboot_info_t;
|
||||
|
||||
/* The module structure. */
|
||||
typedef struct module
|
||||
{
|
||||
unsigned long mod_start;
|
||||
unsigned long mod_end;
|
||||
unsigned long string;
|
||||
unsigned long reserved;
|
||||
} module_t;
|
||||
|
||||
/* The memory map. Be careful that the offset 0 is base_addr_low
|
||||
but no size. */
|
||||
typedef struct memory_map
|
||||
{
|
||||
unsigned long size;
|
||||
unsigned long base_addr_low;
|
||||
unsigned long base_addr_high;
|
||||
unsigned long length_low;
|
||||
unsigned long length_high;
|
||||
unsigned long type;
|
||||
} memory_map_t;
|
||||
|
||||
#endif /* ! ASM */
|
||||
27
kernel/config.d
Normal file
27
kernel/config.d
Normal file
@@ -0,0 +1,27 @@
|
||||
//Config options
|
||||
|
||||
bool enable_kgdb = false;
|
||||
bool remote_debug = true; // Its like debugging for the debugger
|
||||
|
||||
// Kernel options
|
||||
// Make sure this is the same as the value in boot.h
|
||||
const ulong KERNEL_VM_BASE = 0xFFFFFFFF80000000;
|
||||
|
||||
// Debugging options
|
||||
// Setting DEBUG_ALL to true will cause *ALL* debug
|
||||
// flags to turn on. If you only want to see some
|
||||
// debug messages, turn DEBUG_ALL off, and only
|
||||
// turn on the debug messages you wish to see.
|
||||
const auto DEBUG_ALL = false;
|
||||
|
||||
// Individual debug options
|
||||
const auto DEBUG_PAGING = false;
|
||||
const auto DEBUG_PAGEFAULTS = false;
|
||||
const auto DEBUG_PMEM = false;
|
||||
const auto DEBUG_INTERRUPTS = false;
|
||||
const auto DEBUG_MPTABLE = false;
|
||||
const auto DEBUG_LAPIC = false;
|
||||
const auto DEBUG_IOAPIC = false;
|
||||
const auto DEBUG_APENTRY = false;
|
||||
const auto DEBUG_KBD = false;
|
||||
const auto DEBUG_SCHEDULER = false;
|
||||
41
kernel/core/kmain.d
Normal file
41
kernel/core/kmain.d
Normal file
@@ -0,0 +1,41 @@
|
||||
/* XOmB Bare Bones
|
||||
*
|
||||
* This is the bare minimum needed for an OS written in the D language.
|
||||
*
|
||||
* Note: The kmain will be called in the higher memory region.
|
||||
* The next step is setting up permanent kernel structures.
|
||||
*
|
||||
*/
|
||||
|
||||
module kernel.core.kmain;
|
||||
|
||||
// This module contains our powerful kprintf function
|
||||
import kernel.core.kprintf;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The main function for the kernel.
|
||||
// This will receive data from the boot loader.
|
||||
|
||||
// bootLoaderID is the unique identifier for a boot loader.
|
||||
// data is a structure given by the boot loader.
|
||||
|
||||
// For GRUB: the identifier is the magic number.
|
||||
// data is the pointer to the multiboot structure.
|
||||
extern(C) void kmain(int bootLoaderID, void *data)
|
||||
{
|
||||
|
||||
kprintfln!("{!cls}Welcome to {}! (version {}.{}.{})")("XOmB Bare Bones", 1,0,0);
|
||||
|
||||
|
||||
kprintfln!("{x} {x}")(bootLoaderID, data);
|
||||
|
||||
|
||||
// Ok, so we don't want to just infinite loop (if you want it to do something)
|
||||
// Replace this with your kernel logic!
|
||||
|
||||
for(;;) {}
|
||||
|
||||
}
|
||||
428
kernel/core/kprintf.d
Normal file
428
kernel/core/kprintf.d
Normal file
@@ -0,0 +1,428 @@
|
||||
// This module implements the print logic for the kernel
|
||||
|
||||
|
||||
module kernel.core.kprintf;
|
||||
|
||||
// Contains the interface to the VGA textmode driver.
|
||||
import kernel.dev.console;
|
||||
|
||||
// Contains some nice logic and cool templates.
|
||||
import kernel.core.util;
|
||||
|
||||
|
||||
|
||||
|
||||
/* This template will generate code for printing and will do
|
||||
* all parsing of the format string at compile time
|
||||
*
|
||||
* USAGE:
|
||||
* kprintf!("format string {specifier} ... ")(args...);
|
||||
*
|
||||
* EXAMPLES:
|
||||
* kprintf!("Integer: {}")(10);
|
||||
* kprintf!("{!cls}Cleared the screen.")();
|
||||
* kprintf!("{!pos:2,3}At position (2,3)")();
|
||||
* kprintf!("{!fg:LightBlue!bg:Gray}{}")(25);
|
||||
* kprintf!("{!fg:Red}redness")();
|
||||
* kprintf!("{x} Hex!")(145);
|
||||
* kprintf!("Curly Brace: {{")();
|
||||
*
|
||||
* COMMANDS:
|
||||
* !cls - Clears the screen.
|
||||
* !fg - Sets the foreground color, see the Color enum
|
||||
* in kernel/dev/console.d.
|
||||
* !bg - Sets the background color, same as above.
|
||||
* !pos - Moves the cursor to the x and y given, see example above.
|
||||
*
|
||||
* SPECIFIERS:
|
||||
* {x} - Prints the hex value.
|
||||
* {u} - Treats as unsigned.
|
||||
* {} - Prints common form.
|
||||
*
|
||||
* WHY IS IT COOL?
|
||||
* - Compile time parsing of format strings
|
||||
* - Type checking at compile time as well
|
||||
* - That means it can tell you that you are dumb before you execute.
|
||||
* - No need to specify type information.
|
||||
*
|
||||
* - So we can do this and not care about the
|
||||
* output of the function:
|
||||
*
|
||||
* auto blah = someFunction();
|
||||
* kprintf!("Some Arbitrary Info: {}")(blah);
|
||||
*
|
||||
* WOWWY WOW WOW!
|
||||
*
|
||||
*/
|
||||
|
||||
template kprintf(char[] Format)
|
||||
{
|
||||
void kprintf(Args...)(Args args)
|
||||
{
|
||||
mixin(ConvertFormat!(Format, Args));
|
||||
}
|
||||
}
|
||||
|
||||
/* This template will generate code like kprintf but will also
|
||||
* print a newline afterward.
|
||||
*
|
||||
* USAGE: See kprintf above.
|
||||
*
|
||||
*/
|
||||
template kprintfln(char[] Format)
|
||||
{
|
||||
void kprintfln(Args...)(Args args)
|
||||
{
|
||||
mixin(ConvertFormat!(Format, Args));
|
||||
Console.putChar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The crazy D templating logic that implements the kprintf
|
||||
|
||||
private
|
||||
{
|
||||
|
||||
// The following are functions that implement logic for printing different primatives.
|
||||
|
||||
void printInt(long i, char[] fmt)
|
||||
{
|
||||
char[20] buf;
|
||||
|
||||
if(fmt.length is 0)
|
||||
Console.putString(itoa(buf, 'd', i));
|
||||
else if(fmt[0] is 'd' || fmt[0] is 'D')
|
||||
Console.putString(itoa(buf, 'd', i));
|
||||
else if(fmt[0] is 'u' || fmt[0] is 'U')
|
||||
Console.putString(itoa(buf, 'u', i));
|
||||
else if(fmt[0] is 'x' || fmt[0] is 'X')
|
||||
Console.putString(itoa(buf, 'x', i));
|
||||
}
|
||||
|
||||
// Floats are not supported by the kernel, but the interface to this exists anyway.
|
||||
void printFloat(real f, char[] fmt)
|
||||
{
|
||||
Console.putString("?float?");
|
||||
}
|
||||
|
||||
void printChar(dchar c, char[] fmt)
|
||||
{
|
||||
Console.putChar(c);
|
||||
}
|
||||
|
||||
void printString(T)(T s, char[] fmt)
|
||||
{
|
||||
static assert(isStringType!(T));
|
||||
Console.putString(s);
|
||||
}
|
||||
|
||||
void printPointer(void* p, char[] fmt)
|
||||
{
|
||||
Console.putString("0x");
|
||||
char[20] buf;
|
||||
Console.putString(itoa(buf, 'x', cast(ulong)p));
|
||||
}
|
||||
|
||||
// The core template that will parse the format to find the string until a format specifier and return the length.
|
||||
template ExtractString(char[] format)
|
||||
{
|
||||
static if(format.length == 0)
|
||||
{
|
||||
const size_t ExtractString = 0;
|
||||
}
|
||||
else static if(format[0] is '{')
|
||||
{
|
||||
static if(format.length > 1 && format[1] is '{')
|
||||
const size_t ExtractString = 2 + ExtractString!(format[2 .. $]);
|
||||
else
|
||||
const size_t ExtractString = 0;
|
||||
}
|
||||
else
|
||||
const size_t ExtractString = 1 + ExtractString!(format[1 .. $]);
|
||||
}
|
||||
|
||||
// Extracts the format string and returns the length of that string.
|
||||
template ExtractFormatStringImpl(char[] format)
|
||||
{
|
||||
static assert(format.length !is 0, "Unterminated format specifier");
|
||||
|
||||
static if(format[0] is '}')
|
||||
const ExtractFormatStringImpl = 0;
|
||||
else
|
||||
const ExtractFormatStringImpl = 1 + ExtractFormatStringImpl!(format[1 .. $]);
|
||||
}
|
||||
|
||||
// This template compares the format given (eg {x} would be "x") against the type of the argument passed.
|
||||
template CheckFormatAgainstType(char[] rawFormat, size_t idx, T)
|
||||
{
|
||||
const char[] format = rawFormat[1 .. idx];
|
||||
|
||||
static if(isIntType!(T))
|
||||
{
|
||||
static assert(format == "" || format == "x" || format == "X" || format == "u" || format == "U",
|
||||
"Invalid integer format specifier '" ~ format ~ "'");
|
||||
}
|
||||
|
||||
// This is an inherited attribute to describe the length of the format string
|
||||
const size_t res = idx;
|
||||
}
|
||||
|
||||
// This template will compare a format with a type.
|
||||
template ExtractFormatString(char[] format, T)
|
||||
{
|
||||
const ExtractFormatString = CheckFormatAgainstType!(format, ExtractFormatStringImpl!(format), T).res;
|
||||
}
|
||||
|
||||
// This will get the length of a single command
|
||||
template ExtractCommandStringImpl(char[] format)
|
||||
{
|
||||
static if (format.length == 0 || format[0] is '}')
|
||||
{
|
||||
const int ExtractCommandStringImpl = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int ExtractCommandStringImpl = 1 + ExtractCommandStringImpl!(format[1..$]);
|
||||
}
|
||||
}
|
||||
|
||||
// This template will extract a command string, or set of command strings
|
||||
template ExtractCommandString(char[] format)
|
||||
{
|
||||
const ExtractCommandString = ExtractCommandStringImpl!(format);
|
||||
}
|
||||
|
||||
// This template will take a string 's' and convert any '{{' to a single '{'.
|
||||
// This is done after parsing the format string.
|
||||
template StripDoubleLeftBrace(char[] s)
|
||||
{
|
||||
static if(s.length is 0)
|
||||
const char[] StripDoubleLeftBrace = "";
|
||||
else static if(s.length is 1)
|
||||
const char[] StripDoubleLeftBrace = s;
|
||||
else
|
||||
{
|
||||
static if(s[0 .. 2] == "{{")
|
||||
const char[] StripDoubleLeftBrace = "{" ~ StripDoubleLeftBrace!(s[2 .. $]);
|
||||
else
|
||||
const char[] StripDoubleLeftBrace = s[0] ~ StripDoubleLeftBrace!(s[1 .. $]);
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the code to print the string.
|
||||
template MakePrintString(char[] s)
|
||||
{
|
||||
const char[] MakePrintString = "printString(\"" ~ StripDoubleLeftBrace!(s) ~ "\", \"\");\n";
|
||||
}
|
||||
|
||||
// This template will generate the code to print out the string.
|
||||
template MakePrintOther(T, char[] fmt, size_t idx)
|
||||
{
|
||||
static if(isIntType!(T))
|
||||
const char[] MakePrintOther = "printInt(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
|
||||
else static if(isCharType!(T))
|
||||
const char[] MakePrintOther = "printChar(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
|
||||
else static if(isStringType!(T))
|
||||
const char[] MakePrintOther = "printString(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
|
||||
else static if(isFloatType!(T))
|
||||
const char[] MakePrintOther = "printFloat(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
|
||||
else static if(isPointerType!(T))
|
||||
const char[] MakePrintOther = "printPointer(args[" ~ idx.stringof ~ "], \"" ~ fmt ~ "\");\n";
|
||||
else static if(isArrayType!(T))
|
||||
const char[] MakePrintOther = "printArray(args[" ~ idx.stringof ~ "], true, false);\n";
|
||||
else
|
||||
static assert(false, "I don't know how to handle argument " ~ idx.stringof ~ " of type '" ~ T.stringof ~ "'.");
|
||||
}
|
||||
|
||||
// For the !fg command
|
||||
template MakePrintCommand_fg(char[] format)
|
||||
{
|
||||
static if (format.length <= 1)
|
||||
{
|
||||
static assert(false, "Not enough parameters to the !fg command.");
|
||||
}
|
||||
else
|
||||
{
|
||||
const char[] MakePrintCommand_fg = "Console.setForeColor(Color." ~ format[1..$] ~ ");\n";
|
||||
}
|
||||
}
|
||||
|
||||
// For the !bg command
|
||||
template MakePrintCommand_bg(char[] format)
|
||||
{
|
||||
static if (format.length <= 1)
|
||||
{
|
||||
static assert(false, "Not enough parameters to the !bg command.");
|
||||
}
|
||||
else
|
||||
{
|
||||
const char[] MakePrintCommand_bg = "Console.setBackColor(Color." ~ format[1..$] ~ ");\n";
|
||||
}
|
||||
}
|
||||
|
||||
template MakePrintCommand_pos(char[] format)
|
||||
{
|
||||
static if (format.length <= 3)
|
||||
{
|
||||
static assert(false, "Not enough parameters to the !pos command. USAGE: {!pos:x,y} where x and y are integers.");
|
||||
}
|
||||
else
|
||||
{
|
||||
const char[] MakePrintCommand_pos = "Console.setPosition(" ~ format[1..$] ~ ");\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Output code to do the command.
|
||||
template MakePrintCommandGenerate(char[] format)
|
||||
{
|
||||
static if (format.length >= 3 && format[0..3] == "cls")
|
||||
{
|
||||
const char[] MakePrintCommandGenerate = "Console.clearScreen();\n";
|
||||
}
|
||||
else static if (format.length >= 2 && format[0..2] == "fg")
|
||||
{
|
||||
const char[] MakePrintCommandGenerate = MakePrintCommand_fg!(format[2..$]);
|
||||
}
|
||||
else static if (format.length >= 2 && format[0..2] == "bg")
|
||||
{
|
||||
const char[] MakePrintCommandGenerate = MakePrintCommand_bg!(format[2..$]);
|
||||
}
|
||||
else static if (format.length >= 3 && format[0..3] == "pos")
|
||||
{
|
||||
const char[] MakePrintCommandGenerate = MakePrintCommand_pos!(format[3..$]);
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(false, "Unknown Command, !" ~ format ~ ", for kprintf.");
|
||||
}
|
||||
}
|
||||
|
||||
// Finds the length of the command string
|
||||
template ExtractCommand(char[] format)
|
||||
{
|
||||
static if (format.length == 0 || format[0] is '}' || format[0] is '!')
|
||||
{
|
||||
const ExtractCommand = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ExtractCommand = 1 + ExtractCommand!(format[1..$]);
|
||||
}
|
||||
}
|
||||
|
||||
// This template will take everything up to a ! or a } and generate the code for that command
|
||||
template MakePrintCommandImpl(char[] format)
|
||||
{
|
||||
static if (format.length == 0)
|
||||
{
|
||||
const char[] res = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
static if (format[0] is '!')
|
||||
{
|
||||
const char[] res = MakePrintCommandImpl!(format[1..$]).res;
|
||||
}
|
||||
else
|
||||
{
|
||||
const lengthOfString = ExtractCommand!(format);
|
||||
|
||||
const char[] res = MakePrintCommandGenerate!(format[0..lengthOfString]) ~
|
||||
MakePrintCommandImpl!(format[lengthOfString..$]).res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// commands: !cls, !fg:color, !bg:color
|
||||
|
||||
// This template parses the command string (excluding the initial !) and generates the commands necessary.
|
||||
template MakePrintCommand(char[] format)
|
||||
{
|
||||
const char[] MakePrintCommand = MakePrintCommandImpl!(format).res;
|
||||
}
|
||||
|
||||
// This template implements the logic behind format extraction.
|
||||
template ConvertFormatImpl(char[] format, size_t argIdx, Types...)
|
||||
{
|
||||
static if(format.length == 0)
|
||||
{
|
||||
static assert(argIdx == Types.length, "More parameters than format specifiers");
|
||||
const char[] res = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for a token that starts with a left curly brace that would signify a format specifier.
|
||||
static if (format[0] is '{' && (!(format.length > 1 && (format[1] is '{' || format[1] is '!'))))
|
||||
{
|
||||
// We have a format specifier, but no arguments to convert?
|
||||
static assert(argIdx < Types.length, "More format specifiers than parameters");
|
||||
|
||||
// We will convert the string and generate code for the print.
|
||||
|
||||
// Get the format string
|
||||
const lengthOfString = ExtractFormatString!(format, Types[argIdx]);
|
||||
|
||||
// Generate the code and recall this template.
|
||||
const char[] res = MakePrintOther!(Types[argIdx], format[1 .. lengthOfString] , argIdx) ~
|
||||
ConvertFormatImpl!(format[lengthOfString + 1 .. $], argIdx + 1, Types).res;
|
||||
}
|
||||
else static if (format[0] is '{' && format.length > 1 && format[1] is '!')
|
||||
{
|
||||
// Command Token found, acts very similarly to a normal format specifier, expect it doesn't compare the types from the arguments.
|
||||
const lengthOfString = ExtractCommandString!(format);
|
||||
|
||||
// Generate the code and recall this template.
|
||||
const char[] res = MakePrintCommand!(format[2..lengthOfString])
|
||||
~ ConvertFormatImpl!(format[lengthOfString + 1 .. $], argIdx, Types).res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We want to know how long of a string we can print out without intervention
|
||||
const lengthOfString = ExtractString!(format);
|
||||
|
||||
// Then we can generate the code to print it out with the console and recall this template.
|
||||
const char[] res = MakePrintString!(format[0..lengthOfString]) ~
|
||||
ConvertFormatImpl!(format[lengthOfString..$], argIdx, Types).res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This template is the core routine. It will take the format and the arguments and generate the code to logically print out the string.
|
||||
template ConvertFormat(char[] format, Types...)
|
||||
{
|
||||
const char[] ConvertFormat = ConvertFormatImpl!(format, 0, Types).res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
383
kernel/core/util.d
Normal file
383
kernel/core/util.d
Normal file
@@ -0,0 +1,383 @@
|
||||
module kernel.core.util;
|
||||
|
||||
/**
|
||||
This method checks to see if the value stored in the bit number declared
|
||||
by the input variable "bit" in the flag declared by the input
|
||||
variable "flags" is set. Returns a 1 if it is set, returns a 0 if it is not set.
|
||||
Params:
|
||||
flags = The flags from the multiboot header the kernel wishes to check.
|
||||
bit = The number of the bit the kernel would like to check for data.
|
||||
Returns: Whether the bit "bit" in "flags" has a value (1 if it is set, 0 if it is not)
|
||||
*/
|
||||
uint CHECK_FLAG(uint flags, uint bit)
|
||||
{
|
||||
return ((flags) & (1 << (bit)));
|
||||
}
|
||||
|
||||
/**
|
||||
Given a struct type, gives a tuple of strings of the names of fields in the struct.
|
||||
*/
|
||||
public template FieldNames(S, int idx = 0)
|
||||
{
|
||||
static if(idx >= S.tupleof.length)
|
||||
alias Tuple!() FieldNames;
|
||||
else
|
||||
alias Tuple!(GetLastName!(S.tupleof[idx].stringof), FieldNames!(S, idx + 1)) FieldNames;
|
||||
}
|
||||
|
||||
private template GetLastName(char[] fullName, int idx = fullName.length - 1)
|
||||
{
|
||||
static if(idx < 0)
|
||||
const char[] GetLastName = fullName;
|
||||
else static if(fullName[idx] == '.')
|
||||
const char[] GetLastName = fullName[idx + 1 .. $];
|
||||
else
|
||||
const char[] GetLastName = GetLastName!(fullName, idx - 1);
|
||||
}
|
||||
|
||||
template Tuple(T...)
|
||||
{
|
||||
alias T Tuple;
|
||||
}
|
||||
|
||||
template Bitfield(alias data, Args...)
|
||||
{
|
||||
static assert(!(Args.length & 1), "Bitfield arguments must be an even number");
|
||||
const char[] Bitfield = BitfieldShim!((typeof(data)).stringof, data, Args).Ret;
|
||||
}
|
||||
|
||||
// Odd bug in D templates -- putting "data.stringof" as a template argument gives it the
|
||||
// string of the type, rather than the string of the symbol. This shim works around that.
|
||||
template BitfieldShim(char[] typeStr, alias data, Args...)
|
||||
{
|
||||
const char[] Name = data.stringof;
|
||||
const char[] Ret = BitfieldImpl!(typeStr, Name, 0, Args).Ret;
|
||||
}
|
||||
|
||||
template BitfieldImpl(char[] typeStr, char[] nameStr, int offset, Args...)
|
||||
{
|
||||
static if(Args.length == 0)
|
||||
const char[] Ret = "";
|
||||
else
|
||||
{
|
||||
const Name = Args[0];
|
||||
const Size = Args[1];
|
||||
const Mask = Bitmask!(Size);
|
||||
|
||||
const char[] Getter = "public " ~ typeStr ~ " " ~ Name ~ "() { return ( " ~
|
||||
nameStr ~ " >> " ~ Itoh!(offset) ~ " ) & " ~ Itoh!(Mask) ~ "; }";
|
||||
|
||||
const char[] Setter = "public void " ~ Name ~ "(" ~ typeStr ~ " val) { " ~
|
||||
nameStr ~ " = (" ~ nameStr ~ " & " ~ Itoh!(~(Mask << offset)) ~ ") | ((val & " ~
|
||||
Itoh!(Mask) ~ ") << " ~ Itoh!(offset) ~ "); }";
|
||||
|
||||
const char[] Ret = Getter ~ Setter ~ BitfieldImpl!(typeStr, nameStr, offset + Size, Args[2 .. $]).Ret;
|
||||
}
|
||||
}
|
||||
|
||||
template Itoa(long i)
|
||||
{
|
||||
static if(i < 0)
|
||||
const char[] Itoa = "-" ~ IntToStr!(-i, 10);
|
||||
else
|
||||
const char[] Itoa = IntToStr!(i, 10);
|
||||
}
|
||||
|
||||
template Itoh(long i)
|
||||
{
|
||||
const char[] Itoh = "0x" ~ IntToStr!(i, 16);
|
||||
}
|
||||
|
||||
template Digits(long i)
|
||||
{
|
||||
const char[] Digits = "0123456789abcdefghijklmnopqrstuvwxyz"[0 .. i];
|
||||
}
|
||||
|
||||
template IntToStr(ulong i, int base)
|
||||
{
|
||||
static if(i >= base)
|
||||
const char[] IntToStr = IntToStr!(i / base, base) ~ Digits!(base)[i % base];
|
||||
else
|
||||
const char[] IntToStr = "" ~ Digits!(base)[i % base];
|
||||
}
|
||||
|
||||
template Bitmask(long size)
|
||||
{
|
||||
const long Bitmask = (1L << size) - 1;
|
||||
}
|
||||
|
||||
template isStringType(T)
|
||||
{
|
||||
const bool isStringType = is(T : char[]) || is(T : wchar[]) || is(T : dchar[]);
|
||||
}
|
||||
|
||||
/**
|
||||
Sees if a type is char, wchar, or dchar.
|
||||
*/
|
||||
template isCharType(T)
|
||||
{
|
||||
const bool isCharType = is(T == char) || is(T == wchar) || is(T == dchar);
|
||||
}
|
||||
|
||||
/**
|
||||
Sees if a type is a signed or unsigned byte, short, int, or long.
|
||||
*/
|
||||
template isIntType(T)
|
||||
{
|
||||
const bool isIntType = is(T == int) || is(T == uint) || is(T == long) || is(T == ulong) ||
|
||||
is(T == short) || is(T == ushort) || is(T == byte) || is(T == ubyte) /* || is(T == cent) || is(T == ucent) */;
|
||||
}
|
||||
|
||||
/**
|
||||
Sees if a type is a signed or unsigned byte, short, int, or long.
|
||||
*/
|
||||
template isUnsignedIntType(T)
|
||||
{
|
||||
const bool isUnsignedIntType = is(T == uint) || is(T == ulong) ||
|
||||
is(T == ushort) || is(T == ubyte) /* || is(T == ucent) */;
|
||||
}
|
||||
|
||||
/**
|
||||
Sees if a type is a signed or unsigned byte, short, int, or long.
|
||||
*/
|
||||
template isSignedIntType(T)
|
||||
{
|
||||
const bool isSignedIntType = is(T == int) || is(T == long) ||
|
||||
is(T == short) || is(T == byte) /* || is(T == cent) */;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Sees if a type is float, double, or real.
|
||||
*/
|
||||
template isFloatType(T)
|
||||
{
|
||||
const bool isFloatType = is(T == float) || is(T == double) || is(T == real);
|
||||
}
|
||||
|
||||
/**
|
||||
Sees if a type is an array.
|
||||
*/
|
||||
template isArrayType(T)
|
||||
{
|
||||
const bool isArrayType = false;
|
||||
}
|
||||
|
||||
template isArrayType(T : T[])
|
||||
{
|
||||
const bool isArrayType = true;
|
||||
}
|
||||
|
||||
/**
|
||||
Sees if a type is an associative array.
|
||||
*/
|
||||
template isAAType(T)
|
||||
{
|
||||
const bool isAAType = is(typeof(T.init.values[0])[typeof(T.init.keys[0])] == T);
|
||||
}
|
||||
|
||||
/**
|
||||
Sees if a type is a pointer.
|
||||
*/
|
||||
template isPointerType(T)
|
||||
{
|
||||
const bool isPointerType = false;
|
||||
}
|
||||
|
||||
template isPointerType(T : T*)
|
||||
{
|
||||
const bool isPointerType = true;
|
||||
}
|
||||
|
||||
/**
|
||||
Get to the bottom of any chain of typedefs! Returns the first non-typedef'ed type.
|
||||
*/
|
||||
template realType(T)
|
||||
{
|
||||
static if(is(T Base == typedef) || is(T Base == enum))
|
||||
alias realType!(Base) realType;
|
||||
else
|
||||
alias T realType;
|
||||
}
|
||||
|
||||
/**
|
||||
See if a character is a lowercase character.
|
||||
*/
|
||||
template IsLower(char c)
|
||||
{
|
||||
const bool IsLower = c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
/**
|
||||
See if a character is an uppercase character.
|
||||
*/
|
||||
template IsUpper(char c)
|
||||
{
|
||||
const bool IsUpper = c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a character or string to lowercase.
|
||||
*/
|
||||
template ToLower(char c)
|
||||
{
|
||||
const char ToLower = IsUpper!(c) ? c + ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
template ToLower(char[] s)
|
||||
{
|
||||
static if(s.length == 0)
|
||||
const ToLower = ""c;
|
||||
else
|
||||
const ToLower = ToLower!(s[0]) ~ s[1 .. $];
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a character or string to uppercase.
|
||||
*/
|
||||
template ToUpper(char c)
|
||||
{
|
||||
const char ToUpper = IsLower!(c) ? c - ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
template ToUpper(char[] s)
|
||||
{
|
||||
static if(s.length == 0)
|
||||
const ToUpper = ""c;
|
||||
else
|
||||
const ToUpper = ToUpper!(s[0]) ~ s[1 .. $];
|
||||
}
|
||||
|
||||
/**
|
||||
Capitalize a word so that the first letter is capital.
|
||||
*/
|
||||
template Capitalize(char[] s)
|
||||
{
|
||||
static if(s.length == 0)
|
||||
const char[] Capitalize = ""c;
|
||||
else
|
||||
const char[] Capitalize = ToUpper!(s[0]) ~ ToLower!(s[1 .. $]);
|
||||
}
|
||||
|
||||
/**
|
||||
Compile-time map. Takes a template "function" which should take a single argument
|
||||
of the type of the elements of the list of values that follows. Resolves to a tuple.
|
||||
*/
|
||||
template Map(alias Templ, List...)
|
||||
{
|
||||
static if(List.length == 0)
|
||||
alias Tuple!() Map;
|
||||
else
|
||||
alias Tuple!(Templ!(List[0]), Map!(Templ, List[1 .. $])) Map;
|
||||
}
|
||||
|
||||
/**
|
||||
Compile-time reduce. Takes a template "function" that should take two arguments of the type
|
||||
of the elements of the list of values that follows. The list must be at least one element
|
||||
long. Resolves to a single value of the type that the template function returns.
|
||||
*/
|
||||
template Reduce(alias Templ, List...)
|
||||
{
|
||||
static assert(List.length > 0, "Reduce must be called on a list of at least one element");
|
||||
|
||||
static if(is(List[0]))
|
||||
{
|
||||
static if(List.length == 1)
|
||||
alias List[0] Reduce;
|
||||
else
|
||||
alias Reduce!(Templ, Tuple!(Templ!(List[0], List[1]), List[2 .. $])) Reduce;
|
||||
}
|
||||
else
|
||||
{
|
||||
static if(List.length == 1)
|
||||
const Reduce = List[0];
|
||||
else
|
||||
const Reduce = Reduce!(Templ, Tuple!(Templ!(List[0], List[1]), List[2 .. $]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Compile-time range. Given lower and upper bound, yields a tuple of integers in the
|
||||
range [min, max).
|
||||
*/
|
||||
template Range(uint min, uint max)
|
||||
{
|
||||
static if(min >= max)
|
||||
alias Tuple!() Range;
|
||||
else
|
||||
alias Tuple!(min, Range!(min + 1, max)) Range;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
template Range(uint max)
|
||||
{
|
||||
alias Range!(0, max) Range;
|
||||
}
|
||||
|
||||
/**
|
||||
Compile time metafunction meant to be used with Reduce. Concatenates its first two
|
||||
arguments and resolves to the result of that concatentation.
|
||||
*/
|
||||
template Cat(T...)
|
||||
{
|
||||
const Cat = T[0] ~ T[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// standard functions
|
||||
|
||||
|
||||
/**
|
||||
This function converts an integer to a string, depending on the base passed in.
|
||||
Params:
|
||||
buf = The function will save the translated string into this character array.
|
||||
base = The base of the integer value. If "d," it will be assumed to be decimal. If "x," the integer
|
||||
will be hexadecimal.
|
||||
d = The integer to translate.
|
||||
Returns: The translated string in a character array.
|
||||
*/
|
||||
char[] itoa(char[] buf, char base, long d)
|
||||
{
|
||||
size_t p = buf.length - 1;
|
||||
size_t startIdx = 0;
|
||||
ulong ud = d;
|
||||
bool negative = false;
|
||||
|
||||
int divisor = 10;
|
||||
|
||||
// If %d is specified and D is minus, put `-' in the head.
|
||||
if(base == 'd' && d < 0)
|
||||
{
|
||||
negative = true;
|
||||
ud = -d;
|
||||
}
|
||||
else if(base == 'x')
|
||||
divisor = 16;
|
||||
|
||||
// Divide UD by DIVISOR until UD == 0.
|
||||
do
|
||||
{
|
||||
int remainder = ud % divisor;
|
||||
buf[p--] = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
|
||||
}
|
||||
while (ud /= divisor)
|
||||
|
||||
if(negative)
|
||||
buf[p--] = '-';
|
||||
|
||||
return buf[p + 1 .. $];
|
||||
}
|
||||
191
kernel/dev/console.d
Normal file
191
kernel/dev/console.d
Normal file
@@ -0,0 +1,191 @@
|
||||
// This implements a console (text-mode) VGA driver.
|
||||
|
||||
module kernel.dev.console;
|
||||
|
||||
// This contains the hexidecimal values for various colors for printing to the screen.
|
||||
enum Color : ubyte
|
||||
{
|
||||
Black = 0x00,
|
||||
Blue = 0x01,
|
||||
Green = 0x02,
|
||||
Cyan = 0x03,
|
||||
Red = 0x04,
|
||||
Magenta = 0x05,
|
||||
Yellow = 0x06,
|
||||
LightGray = 0x07,
|
||||
Gray = 0x08,
|
||||
LightBlue = 0x09,
|
||||
LightGreen = 0x0A,
|
||||
LightCyan = 0x0B,
|
||||
LightRed = 0x0C,
|
||||
LightMagenta = 0x0D,
|
||||
LightYellow = 0x0E,
|
||||
White = 0x0F
|
||||
}
|
||||
|
||||
// This is the true interface to the console
|
||||
struct Console
|
||||
{
|
||||
static:
|
||||
public:
|
||||
|
||||
// The number of columns and lines on the screen.
|
||||
const uint COLUMNS = 80;
|
||||
const uint LINES = 24;
|
||||
|
||||
// The default color.
|
||||
const ubyte DEFAULTCOLORS = Color.LightGray;
|
||||
|
||||
ubyte* videoMemoryLocation = cast(ubyte*)0xFFFFFFFF800B8000;
|
||||
|
||||
// The cursor position
|
||||
private int xpos = 0;
|
||||
private int ypos = 0;
|
||||
|
||||
// The current color
|
||||
private ubyte colorAttribute = DEFAULTCOLORS;
|
||||
|
||||
// The width of a tab
|
||||
const auto TABSTOP = 4;
|
||||
|
||||
// This method will clear the screen and return the cursor to (0,0).
|
||||
void clearScreen()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < COLUMNS * LINES * 2; i++)
|
||||
{
|
||||
volatile *(videoMemoryLocation + i) = 0;
|
||||
}
|
||||
|
||||
xpos = 0;
|
||||
ypos = 0;
|
||||
}
|
||||
|
||||
// This method will return the current location of the cursor
|
||||
void getPosition(out int x, out int y)
|
||||
{
|
||||
x = xpos;
|
||||
y = ypos;
|
||||
}
|
||||
|
||||
// This method will set the current location of the cursor to the x and y given.
|
||||
void setPosition(int x, int y)
|
||||
{
|
||||
if (x < 0) { x = 0; }
|
||||
if (y < 0) { y = 0; }
|
||||
if (x >= COLUMNS) { x = COLUMNS - 1; }
|
||||
if (y >= LINES) { y = LINES - 1; }
|
||||
|
||||
xpos = x;
|
||||
ypos = y;
|
||||
}
|
||||
|
||||
// This method will post the character to the screen at the current location.
|
||||
void putChar(char c)
|
||||
{
|
||||
if (c == '\t')
|
||||
{
|
||||
// Insert a tab.
|
||||
xpos += TABSTOP;
|
||||
}
|
||||
else if (c != '\n' && c != '\r')
|
||||
{
|
||||
// Set the current piece of video memory to the character to print.
|
||||
volatile *(videoMemoryLocation + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
|
||||
volatile *(videoMemoryLocation + (xpos + ypos * COLUMNS) * 2 + 1) = colorAttribute;
|
||||
|
||||
// increase the cursor position
|
||||
xpos++;
|
||||
}
|
||||
|
||||
// if you have reached the end of the line, or printing a newline, increase the y position
|
||||
if (c == '\n' || c == '\r' || xpos >= COLUMNS)
|
||||
{
|
||||
xpos = 0;
|
||||
ypos++;
|
||||
|
||||
if (ypos >= LINES)
|
||||
{
|
||||
scrollDisplay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This mehtod will post a string to the screen at the current location.
|
||||
void putString(char[] s)
|
||||
{
|
||||
foreach(c; s)
|
||||
{
|
||||
putChar(c);
|
||||
}
|
||||
}
|
||||
|
||||
// This function sets the console colors back to their defaults.
|
||||
void resetColors()
|
||||
{
|
||||
colorAttribute = DEFAULTCOLORS;
|
||||
}
|
||||
|
||||
// This function will set the text foreground to a new color.
|
||||
void setForeColor(Color newColor)
|
||||
{
|
||||
colorAttribute = (colorAttribute & 0xf0) | newColor;
|
||||
}
|
||||
|
||||
// This function will set the text background to a new color.
|
||||
void setBackColor(Color newColor)
|
||||
{
|
||||
colorAttribute = (colorAttribute & 0x0f) | (newColor << 4);
|
||||
}
|
||||
|
||||
// This function will set both the foreground and background colors.
|
||||
void setColors(Color foreColor, Color backColor)
|
||||
{
|
||||
colorAttribute = (foreColor & 0x0f) | (backColor << 4);
|
||||
}
|
||||
|
||||
// This function will scroll the entire screen.
|
||||
void scrollDisplay(uint numLines)
|
||||
{
|
||||
// obviously, scrolling all lines results in a cleared display. Use the faster function.
|
||||
if (numLines >= LINES)
|
||||
{
|
||||
clearScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
int cury = 0;
|
||||
int offset1 = 0;
|
||||
int offset2 = numLines * COLUMNS;
|
||||
|
||||
// Go through and shift the correct amount.
|
||||
for ( ; cury <= LINES - numLines; cury++)
|
||||
{
|
||||
for (int curx = 0; curx < COLUMNS; curx++)
|
||||
{
|
||||
*(videoMemoryLocation + (curx + offset1) * 2) = *(videoMemoryLocation + (curx + offset1 + offset2) * 2);
|
||||
*(videoMemoryLocation + (curx + offset1) * 2 + 1) = *(videoMemoryLocation + (curx + offset1 + offset2) * 2 + 1);
|
||||
}
|
||||
|
||||
offset1 += COLUMNS;
|
||||
}
|
||||
|
||||
// clear the remaining lines
|
||||
for (; cury <= LINES; cury++)
|
||||
{
|
||||
for (int curx = 0; curx < COLUMNS; curx++)
|
||||
{
|
||||
*(videoMemoryLocation + (curx + offset1) * 2) = 0x00;
|
||||
*(videoMemoryLocation + (curx + offset1) * 2 + 1) = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
ypos -= numLines;
|
||||
|
||||
if (ypos < 0)
|
||||
{
|
||||
ypos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
1014
kernel/runtime/dstubs.d
Normal file
1014
kernel/runtime/dstubs.d
Normal file
File diff suppressed because it is too large
Load Diff
41
kernel/runtime/gcc/builtins.d
Normal file
41
kernel/runtime/gcc/builtins.d
Normal file
@@ -0,0 +1,41 @@
|
||||
/* GDC -- D front-end for GCC
|
||||
Copyright (C) 2004 David Friedman
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
Declarations are automatically created by the compiler. All
|
||||
declarations start with "__builtin_". Refer to _builtins.def in the
|
||||
GCC source for a list of functions. Not all of the functions are
|
||||
supported.
|
||||
|
||||
In addition to built-in functions, the following types are defined.
|
||||
|
||||
$(TABLE
|
||||
$(TR $(TD ___builtin_va_list) $(TD The target's va_list type ))
|
||||
$(TR $(TD ___builtin_Clong ) $(TD The D equivalent of the target's
|
||||
C "long" type ))
|
||||
$(TR $(TD ___builtin_Culong ) $(TD The D equivalent of the target's
|
||||
C "unsigned long" type ))
|
||||
$(TR $(TD ___builtin_machine_int ) $(TD Signed word-sized integer ))
|
||||
$(TR $(TD ___builtin_machine_uint) $(TD Unsigned word-sized integer ))
|
||||
$(TR $(TD ___builtin_pointer_int ) $(TD Signed pointer-sized integer ))
|
||||
$(TR $(TD ___builtin_pointer_uint) $(TD Unsigned pointer-sized integer ))
|
||||
)
|
||||
*/
|
||||
|
||||
module gcc.builtins;
|
||||
28
kernel/runtime/invariant.d
Normal file
28
kernel/runtime/invariant.d
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
void _d_invariant(Object o)
|
||||
{
|
||||
ClassInfo c;
|
||||
|
||||
//printf("__d_invariant(%p)\n", o);
|
||||
|
||||
// BUG: needs to be filename/line of caller, not library routine
|
||||
assert(o !is null); // just do null check, not invariant check
|
||||
|
||||
c = o.classinfo;
|
||||
|
||||
do
|
||||
{
|
||||
if(c.classInvariant)
|
||||
{
|
||||
(*c.classInvariant)(o);
|
||||
}
|
||||
|
||||
c = c.base;
|
||||
} while(c)
|
||||
}
|
||||
1053
kernel/runtime/object.d
Normal file
1053
kernel/runtime/object.d
Normal file
File diff suppressed because it is too large
Load Diff
34
kernel/runtime/std/c/stdarg.d
Normal file
34
kernel/runtime/std/c/stdarg.d
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
/*
|
||||
* Placed in public domain.
|
||||
* Written by Hauke Duden and Walter Bright
|
||||
*/
|
||||
|
||||
/* This is for use with variable argument lists with extern(D) linkage. */
|
||||
|
||||
module std.c.stdarg;
|
||||
|
||||
private import gcc.builtins;
|
||||
alias __builtin_va_list va_list;
|
||||
alias __builtin_va_end va_end;
|
||||
alias __builtin_va_copy va_copy;
|
||||
|
||||
// The va_start and va_arg template functions are magically
|
||||
// handled by the compiler.
|
||||
|
||||
template va_start(T)
|
||||
{
|
||||
void va_start(out va_list ap, inout T parmn)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template va_arg(T)
|
||||
{
|
||||
T va_arg(ref va_list _argptr)
|
||||
{
|
||||
return T.init;
|
||||
}
|
||||
}
|
||||
|
||||
264
kernel/runtime/std/intrinsic.d
Normal file
264
kernel/runtime/std/intrinsic.d
Normal file
@@ -0,0 +1,264 @@
|
||||
|
||||
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// Placed into the public domain
|
||||
|
||||
/* NOTE: This file has been patched from the original DMD distribution to
|
||||
work with the GDC compiler.
|
||||
|
||||
Modified by David Friedman, May 2006
|
||||
*/
|
||||
|
||||
/** These functions are built-in intrinsics to the compiler.
|
||||
*
|
||||
Intrinsic functions are functions built in to the compiler,
|
||||
usually to take advantage of specific CPU features that
|
||||
are inefficient to handle via external functions.
|
||||
The compiler's optimizer and code generator are fully
|
||||
integrated in with intrinsic functions, bringing to bear
|
||||
their full power on them.
|
||||
This can result in some surprising speedups.
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdIntrinsic
|
||||
*/
|
||||
|
||||
module std.intrinsic;
|
||||
|
||||
/**
|
||||
* Scans the bits in v starting with bit 0, looking
|
||||
* for the first set bit.
|
||||
* Returns:
|
||||
* The bit number of the first bit set.
|
||||
* The return value is undefined if v is zero.
|
||||
*/
|
||||
version (GNU)
|
||||
int bsf(uint v)
|
||||
{
|
||||
uint m = 1;
|
||||
uint i;
|
||||
for (i = 0; i < 32; i++,m<<=1) {
|
||||
if (v&m)
|
||||
return i;
|
||||
}
|
||||
return i; // supposed to be undefined
|
||||
}
|
||||
else
|
||||
int bsf(uint v);
|
||||
|
||||
/**
|
||||
* Scans the bits in v from the most significant bit
|
||||
* to the least significant bit, looking
|
||||
* for the first set bit.
|
||||
* Returns:
|
||||
* The bit number of the first bit set.
|
||||
* The return value is undefined if v is zero.
|
||||
* Example:
|
||||
* ---
|
||||
* import std.intrinsic;
|
||||
*
|
||||
* int main()
|
||||
* {
|
||||
* uint v;
|
||||
* int x;
|
||||
*
|
||||
* v = 0x21;
|
||||
* x = bsf(v);
|
||||
* printf("bsf(x%x) = %d\n", v, x);
|
||||
* x = bsr(v);
|
||||
* printf("bsr(x%x) = %d\n", v, x);
|
||||
* return 0;
|
||||
* }
|
||||
* ---
|
||||
* Output:
|
||||
* bsf(x21) = 0<br>
|
||||
* bsr(x21) = 5
|
||||
*/
|
||||
version (GNU)
|
||||
int bsr(uint v)
|
||||
{
|
||||
uint m = 0x80000000;
|
||||
uint i;
|
||||
for (i = 32; i ; i--,m>>>=1) {
|
||||
if (v&m)
|
||||
return i-1;
|
||||
}
|
||||
return i; // supposed to be undefined
|
||||
}
|
||||
else
|
||||
int bsr(uint v);
|
||||
|
||||
/**
|
||||
* Tests the bit.
|
||||
*/
|
||||
version (GNU)
|
||||
int bt(uint *p, uint bitnum)
|
||||
{
|
||||
return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ;
|
||||
}
|
||||
else
|
||||
int bt(uint *p, uint bitnum);
|
||||
|
||||
/**
|
||||
* Tests and complements the bit.
|
||||
*/
|
||||
version (GNU)
|
||||
int btc(uint *p, uint bitnum)
|
||||
{
|
||||
uint * q = p + (bitnum / (uint.sizeof*8));
|
||||
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
|
||||
int result = *q & mask;
|
||||
*q ^= mask;
|
||||
return result ? -1 : 0;
|
||||
}
|
||||
else
|
||||
int btc(uint *p, uint bitnum);
|
||||
|
||||
/**
|
||||
* Tests and resets (sets to 0) the bit.
|
||||
*/
|
||||
version (GNU)
|
||||
int btr(uint *p, uint bitnum)
|
||||
{
|
||||
uint * q = p + (bitnum / (uint.sizeof*8));
|
||||
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
|
||||
int result = *q & mask;
|
||||
*q &= ~mask;
|
||||
return result ? -1 : 0;
|
||||
}
|
||||
else
|
||||
int btr(uint *p, uint bitnum);
|
||||
|
||||
/**
|
||||
* Tests and sets the bit.
|
||||
* Params:
|
||||
* p = a non-NULL pointer to an array of uints.
|
||||
* index = a bit number, starting with bit 0 of p[0],
|
||||
* and progressing. It addresses bits like the expression:
|
||||
---
|
||||
p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
|
||||
---
|
||||
* Returns:
|
||||
* A non-zero value if the bit was set, and a zero
|
||||
* if it was clear.
|
||||
*
|
||||
* Example:
|
||||
* ---
|
||||
import std.intrinsic;
|
||||
|
||||
int main()
|
||||
{
|
||||
uint array[2];
|
||||
|
||||
array[0] = 2;
|
||||
array[1] = 0x100;
|
||||
|
||||
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
* ---
|
||||
* Output:
|
||||
<pre>
|
||||
btc(array, 35) = 0
|
||||
array = [0]:x2, [1]:x108
|
||||
btc(array, 35) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
bts(array, 35) = 0
|
||||
array = [0]:x2, [1]:x108
|
||||
btr(array, 35) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
bt(array, 1) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
</pre>
|
||||
*/
|
||||
version (GNU)
|
||||
int bts(uint *p, uint bitnum)
|
||||
{
|
||||
uint * q = p + (bitnum / (uint.sizeof*8));
|
||||
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
|
||||
int result = *q & mask;
|
||||
*q |= mask;
|
||||
return result ? -1 : 0;
|
||||
}
|
||||
else
|
||||
int bts(uint *p, uint bitnum);
|
||||
|
||||
|
||||
/**
|
||||
* Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
|
||||
byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
|
||||
becomes byte 0.
|
||||
*/
|
||||
version (GNU)
|
||||
uint bswap(uint v)
|
||||
{
|
||||
return ((v&0xFF)<<24)|((v&0xFF00)<<8)|((v&0xFF0000)>>>8)|((v&0xFF000000)>>>24);
|
||||
}
|
||||
else
|
||||
uint bswap(uint v);
|
||||
|
||||
|
||||
/**
|
||||
* Reads I/O port at port_address.
|
||||
*/
|
||||
version (GNU)
|
||||
ubyte inp(uint p) { return 0; }
|
||||
else
|
||||
ubyte inp(uint port_address);
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
version (GNU)
|
||||
ushort inpw(uint p) { return 0; }
|
||||
else
|
||||
ushort inpw(uint port_address);
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
version (GNU)
|
||||
uint inpl(uint p) { return 0; }
|
||||
else
|
||||
uint inpl(uint port_address);
|
||||
|
||||
|
||||
/**
|
||||
* Writes and returns value to I/O port at port_address.
|
||||
*/
|
||||
version (GNU)
|
||||
ubyte outp(uint p, ubyte v) { return v; }
|
||||
else
|
||||
ubyte outp(uint port_address, ubyte value);
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
version (GNU)
|
||||
ushort outpw(uint p, ushort v) { return v; }
|
||||
else
|
||||
ushort outpw(uint port_address, ushort value);
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
version (GNU)
|
||||
uint outpl(uint p, uint v) { return v; }
|
||||
else
|
||||
uint outpl(uint port_address, uint value);
|
||||
|
||||
|
||||
43
kernel/runtime/std/stdarg.d
Normal file
43
kernel/runtime/std/stdarg.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
/*
|
||||
* Placed in public domain.
|
||||
* Written by Hauke Duden and Walter Bright
|
||||
*/
|
||||
|
||||
/* This is for use with variable argument lists with extern(D) linkage. */
|
||||
|
||||
/* NOTE: This file has been patched from the original DMD distribution to
|
||||
work with the GDC compiler.
|
||||
|
||||
Modified by David Friedman, September 2004
|
||||
*/
|
||||
|
||||
module std.stdarg;
|
||||
|
||||
version (GNU) {
|
||||
// va_list might be a pointer, but assuming so is not portable.
|
||||
private import gcc.builtins;
|
||||
alias __builtin_va_list va_list;
|
||||
|
||||
// va_arg is handled magically by the compiler
|
||||
} else {
|
||||
alias void* va_list;
|
||||
}
|
||||
|
||||
template va_arg(T)
|
||||
{
|
||||
T va_arg(inout va_list _argptr)
|
||||
{
|
||||
/*
|
||||
T arg = *cast(T*)_argptr;
|
||||
_argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1));
|
||||
return arg;
|
||||
*/
|
||||
T t; return t;
|
||||
}
|
||||
}
|
||||
|
||||
private import std.c.stdarg;
|
||||
/* The existence of std.stdarg.va_copy isn't standard. Prevent
|
||||
conflicts by using '__'. */
|
||||
alias std.c.stdarg.va_copy __va_copy;
|
||||
96
kernel/runtime/std/typeinfo/ti_AC.d
Normal file
96
kernel/runtime/std/typeinfo/ti_AC.d
Normal file
@@ -0,0 +1,96 @@
|
||||
module std.typeinfo.ti_AC;
|
||||
|
||||
// Object[]
|
||||
|
||||
class TypeInfo_AC : TypeInfo
|
||||
{
|
||||
hash_t getHash(void *p)
|
||||
{ Object[] s = *cast(Object[]*)p;
|
||||
hash_t hash = 0;
|
||||
|
||||
foreach (Object o; s)
|
||||
{
|
||||
if (o)
|
||||
hash += o.toHash();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
Object[] s1 = *cast(Object[]*)p1;
|
||||
Object[] s2 = *cast(Object[]*)p2;
|
||||
|
||||
if (s1.length == s2.length)
|
||||
{
|
||||
for (size_t u = 0; u < s1.length; u++)
|
||||
{ Object o1 = s1[u];
|
||||
Object o2 = s2[u];
|
||||
|
||||
// Do not pass null's to Object.opEquals()
|
||||
if (o1 is o2 ||
|
||||
(!(o1 is null) && !(o2 is null) && o1.opEquals(o2)))
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
Object[] s1 = *cast(Object[]*)p1;
|
||||
Object[] s2 = *cast(Object[]*)p2;
|
||||
ptrdiff_t c;
|
||||
|
||||
c = cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length;
|
||||
if (c == 0)
|
||||
{
|
||||
for (size_t u = 0; u < s1.length; u++)
|
||||
{ Object o1 = s1[u];
|
||||
Object o2 = s2[u];
|
||||
|
||||
if (o1 is o2)
|
||||
continue;
|
||||
|
||||
// Regard null references as always being "less than"
|
||||
if (o1)
|
||||
{
|
||||
if (!o2)
|
||||
{ c = 1;
|
||||
break;
|
||||
}
|
||||
c = o1.opCmp(o2);
|
||||
if (c)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{ c = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
c = -1;
|
||||
else if (c > 0)
|
||||
c = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (Object[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(Object);
|
||||
}
|
||||
}
|
||||
|
||||
107
kernel/runtime/std/typeinfo/ti_Acdouble.d
Normal file
107
kernel/runtime/std/typeinfo/ti_Acdouble.d
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module std.typeinfo.ti_Acdouble;
|
||||
|
||||
private import std.typeinfo.ti_cdouble;
|
||||
|
||||
// cdouble[]
|
||||
|
||||
class TypeInfo_Ar : TypeInfo
|
||||
{
|
||||
char[] toString() { return "cdouble[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ cdouble[] s = *cast(cdouble[]*)p;
|
||||
size_t len = s.length;
|
||||
cdouble *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(uint *)str)[2];
|
||||
hash += (cast(uint *)str)[3];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
cdouble[] s1 = *cast(cdouble[]*)p1;
|
||||
cdouble[] s2 = *cast(cdouble[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_r._equals(s1[u], s2[u]);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
cdouble[] s1 = *cast(cdouble[]*)p1;
|
||||
cdouble[] s2 = *cast(cdouble[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_r._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (cdouble[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(cdouble);
|
||||
}
|
||||
}
|
||||
|
||||
105
kernel/runtime/std/typeinfo/ti_Acfloat.d
Normal file
105
kernel/runtime/std/typeinfo/ti_Acfloat.d
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module std.typeinfo.ti_Acfloat;
|
||||
|
||||
private import std.typeinfo.ti_cfloat;
|
||||
|
||||
// cfloat[]
|
||||
|
||||
class TypeInfo_Aq : TypeInfo
|
||||
{
|
||||
char[] toString() { return "cfloat[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ cfloat[] s = *cast(cfloat[]*)p;
|
||||
size_t len = s.length;
|
||||
cfloat *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
cfloat[] s1 = *cast(cfloat[]*)p1;
|
||||
cfloat[] s2 = *cast(cfloat[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_q._equals(s1[u], s2[u]);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
cfloat[] s1 = *cast(cfloat[]*)p1;
|
||||
cfloat[] s2 = *cast(cfloat[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_q._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (cfloat[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(cfloat);
|
||||
}
|
||||
}
|
||||
|
||||
108
kernel/runtime/std/typeinfo/ti_Acreal.d
Normal file
108
kernel/runtime/std/typeinfo/ti_Acreal.d
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module std.typeinfo.ti_Acreal;
|
||||
|
||||
private import std.typeinfo.ti_creal;
|
||||
|
||||
// creal[]
|
||||
|
||||
class TypeInfo_Ac : TypeInfo
|
||||
{
|
||||
char[] toString() { return "creal[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ creal[] s = *cast(creal[]*)p;
|
||||
size_t len = s.length;
|
||||
creal *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(uint *)str)[2];
|
||||
hash += (cast(uint *)str)[3];
|
||||
hash += (cast(uint *)str)[4];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
creal[] s1 = *cast(creal[]*)p1;
|
||||
creal[] s2 = *cast(creal[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_c._equals(s1[u], s2[u]);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
creal[] s1 = *cast(creal[]*)p1;
|
||||
creal[] s2 = *cast(creal[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_c._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (creal[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(creal);
|
||||
}
|
||||
}
|
||||
|
||||
116
kernel/runtime/std/typeinfo/ti_Adouble.d
Normal file
116
kernel/runtime/std/typeinfo/ti_Adouble.d
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module std.typeinfo.ti_Adouble;
|
||||
|
||||
private import std.typeinfo.ti_double;
|
||||
|
||||
// double[]
|
||||
|
||||
class TypeInfo_Ad : TypeInfo
|
||||
{
|
||||
char[] toString() { return "double[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ double[] s = *cast(double[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
double[] s1 = *cast(double[]*)p1;
|
||||
double[] s2 = *cast(double[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_d._equals(s1[u], s2[u]);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
double[] s1 = *cast(double[]*)p1;
|
||||
double[] s2 = *cast(double[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_d._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (double[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(double);
|
||||
}
|
||||
}
|
||||
|
||||
// idouble[]
|
||||
|
||||
class TypeInfo_Ap : TypeInfo_Ad
|
||||
{
|
||||
char[] toString() { return "idouble[]"; }
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(idouble);
|
||||
}
|
||||
}
|
||||
115
kernel/runtime/std/typeinfo/ti_Afloat.d
Normal file
115
kernel/runtime/std/typeinfo/ti_Afloat.d
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module std.typeinfo.ti_Afloat;
|
||||
|
||||
private import std.typeinfo.ti_float;
|
||||
|
||||
// float[]
|
||||
|
||||
class TypeInfo_Af : TypeInfo
|
||||
{
|
||||
char[] toString() { return "float[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ float[] s = *cast(float[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
float[] s1 = *cast(float[]*)p1;
|
||||
float[] s2 = *cast(float[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_f._equals(s1[u], s2[u]);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
float[] s1 = *cast(float[]*)p1;
|
||||
float[] s2 = *cast(float[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_f._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (float[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(float);
|
||||
}
|
||||
}
|
||||
|
||||
// ifloat[]
|
||||
|
||||
class TypeInfo_Ao : TypeInfo_Af
|
||||
{
|
||||
char[] toString() { return "ifloat[]"; }
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(ifloat);
|
||||
}
|
||||
}
|
||||
204
kernel/runtime/std/typeinfo/ti_Ag.d
Normal file
204
kernel/runtime/std/typeinfo/ti_Ag.d
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
module std.typeinfo.ti_Ag;
|
||||
import kernel.runtime.util;
|
||||
|
||||
// byte[]
|
||||
|
||||
class TypeInfo_Ag : TypeInfo
|
||||
{
|
||||
char[] toString() { return "byte[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ byte[] s = *cast(byte[]*)p;
|
||||
size_t len = s.length;
|
||||
byte *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ubyte *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 9;
|
||||
hash += (*cast(ushort *)str << 8) +
|
||||
(cast(ubyte *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
ubyte[] s1 = *cast(ubyte[]*)p1;
|
||||
ubyte[] s2 = *cast(ubyte[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(s1.ptr, s2.ptr, s1.length) == 0;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
byte[] s1 = *cast(byte[]*)p1;
|
||||
byte[] s2 = *cast(byte[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (byte[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(byte);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ubyte[]
|
||||
|
||||
class TypeInfo_Ah : TypeInfo_Ag
|
||||
{
|
||||
char[] toString() { return "ubyte[]"; }
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
ubyte[] s1 = *cast(ubyte[]*)p1;
|
||||
ubyte[] s2 = *cast(ubyte[]*)p2;
|
||||
|
||||
return memcmp(s1.ptr, s2.ptr, s1.length);
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(ubyte);
|
||||
}
|
||||
}
|
||||
|
||||
// void[]
|
||||
|
||||
class TypeInfo_Av : TypeInfo_Ah
|
||||
{
|
||||
char[] toString() { return "void[]"; }
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(void);
|
||||
}
|
||||
}
|
||||
|
||||
// bool[]
|
||||
|
||||
class TypeInfo_Ab : TypeInfo_Ah
|
||||
{
|
||||
char[] toString() { return "bool[]"; }
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(bool);
|
||||
}
|
||||
}
|
||||
|
||||
// char[]
|
||||
|
||||
class TypeInfo_Aa : TypeInfo_Ag
|
||||
{
|
||||
char[] toString() { return "char[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ char[] s = *cast(char[]*)p;
|
||||
hash_t hash = 0;
|
||||
|
||||
version (all)
|
||||
{
|
||||
foreach (char c; s)
|
||||
hash = hash * 11 + c;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = s.length;
|
||||
char *str = s;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ubyte *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 9;
|
||||
hash += (*cast(ushort *)str << 8) +
|
||||
(cast(ubyte *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(char);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
119
kernel/runtime/std/typeinfo/ti_Aint.d
Normal file
119
kernel/runtime/std/typeinfo/ti_Aint.d
Normal file
@@ -0,0 +1,119 @@
|
||||
|
||||
module std.typeinfo.ti_Aint;
|
||||
|
||||
import kernel.runtime.util;
|
||||
|
||||
// int[]
|
||||
|
||||
class TypeInfo_Ai : TypeInfo
|
||||
{
|
||||
char[] toString() { return "int[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ int[] s = *cast(int[]*)p;
|
||||
auto len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
int[] s1 = *cast(int[]*)p1;
|
||||
int[] s2 = *cast(int[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(ubyte*)s1.ptr, cast(ubyte*)s2.ptr, s1.length * int.sizeof) == 0;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
int[] s1 = *cast(int[]*)p1;
|
||||
int[] s2 = *cast(int[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (int[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(int);
|
||||
}
|
||||
}
|
||||
|
||||
// uint[]
|
||||
|
||||
class TypeInfo_Ak : TypeInfo_Ai
|
||||
{
|
||||
char[] toString() { return "uint[]"; }
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
uint[] s1 = *cast(uint[]*)p1;
|
||||
uint[] s2 = *cast(uint[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(uint);
|
||||
}
|
||||
}
|
||||
|
||||
// dchar[]
|
||||
|
||||
class TypeInfo_Aw : TypeInfo_Ak
|
||||
{
|
||||
char[] toString() { return "dchar[]"; }
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(dchar);
|
||||
}
|
||||
}
|
||||
|
||||
111
kernel/runtime/std/typeinfo/ti_Along.d
Normal file
111
kernel/runtime/std/typeinfo/ti_Along.d
Normal file
@@ -0,0 +1,111 @@
|
||||
|
||||
module std.typeinfo.ti_Along;
|
||||
|
||||
import kernel.runtime.util;
|
||||
|
||||
// long[]
|
||||
|
||||
class TypeInfo_Al : TypeInfo
|
||||
{
|
||||
char[] toString() { return "long[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ long[] s = *cast(long[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str + *(cast(uint *)str + 1);
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
long[] s1 = *cast(long[]*)p1;
|
||||
long[] s2 = *cast(long[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(ubyte*)s1.ptr, cast(ubyte*)s2.ptr, s1.length * long.sizeof) == 0;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
long[] s1 = *cast(long[]*)p1;
|
||||
long[] s2 = *cast(long[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (s1[u] < s2[u])
|
||||
return -1;
|
||||
else if (s1[u] > s2[u])
|
||||
return 1;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (long[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(long);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ulong[]
|
||||
|
||||
class TypeInfo_Am : TypeInfo_Al
|
||||
{
|
||||
char[] toString() { return "ulong[]"; }
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
ulong[] s1 = *cast(ulong[]*)p1;
|
||||
ulong[] s2 = *cast(ulong[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (s1[u] < s2[u])
|
||||
return -1;
|
||||
else if (s1[u] > s2[u])
|
||||
return 1;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(ulong);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
117
kernel/runtime/std/typeinfo/ti_Areal.d
Normal file
117
kernel/runtime/std/typeinfo/ti_Areal.d
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module std.typeinfo.ti_Areal;
|
||||
|
||||
private import std.typeinfo.ti_real;
|
||||
|
||||
// real[]
|
||||
|
||||
class TypeInfo_Ae : TypeInfo
|
||||
{
|
||||
char[] toString() { return "real[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ real[] s = *cast(real[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(ushort *)str)[4];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
real[] s1 = *cast(real[]*)p1;
|
||||
real[] s2 = *cast(real[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_e._equals(s1[u], s2[u]);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
real[] s1 = *cast(real[]*)p1;
|
||||
real[] s2 = *cast(real[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_e._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (real[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(real);
|
||||
}
|
||||
}
|
||||
|
||||
// ireal[]
|
||||
|
||||
class TypeInfo_Aj : TypeInfo_Ae
|
||||
{
|
||||
char[] toString() { return "ireal[]"; }
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(ireal);
|
||||
}
|
||||
}
|
||||
134
kernel/runtime/std/typeinfo/ti_Ashort.d
Normal file
134
kernel/runtime/std/typeinfo/ti_Ashort.d
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
module std.typeinfo.ti_Ashort;
|
||||
|
||||
import kernel.runtime.util;
|
||||
|
||||
// short[]
|
||||
|
||||
class TypeInfo_As : TypeInfo
|
||||
{
|
||||
char[] toString() { return "short[]"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{ short[] s = *cast(short[]*)p;
|
||||
size_t len = s.length;
|
||||
short *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
short[] s1 = *cast(short[]*)p1;
|
||||
short[] s2 = *cast(short[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(ubyte*)s1.ptr, cast(ubyte*)s2.ptr, s1.length * short.sizeof) == 0;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
short[] s1 = *cast(short[]*)p1;
|
||||
short[] s2 = *cast(short[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (short[]).sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(short);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ushort[]
|
||||
|
||||
class TypeInfo_At : TypeInfo_As
|
||||
{
|
||||
char[] toString() { return "ushort[]"; }
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
ushort[] s1 = *cast(ushort[]*)p1;
|
||||
ushort[] s2 = *cast(ushort[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(ushort);
|
||||
}
|
||||
}
|
||||
|
||||
// wchar[]
|
||||
|
||||
class TypeInfo_Au : TypeInfo_At
|
||||
{
|
||||
char[] toString() { return "wchar[]"; }
|
||||
|
||||
TypeInfo next()
|
||||
{
|
||||
return typeid(wchar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
76
kernel/runtime/std/typeinfo/ti_C.d
Normal file
76
kernel/runtime/std/typeinfo/ti_C.d
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module std.typeinfo.ti_C;
|
||||
|
||||
// Object
|
||||
|
||||
class TypeInfo_C : TypeInfo
|
||||
{
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
Object o = *cast(Object*)p;
|
||||
assert(o);
|
||||
return o.toHash();
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
Object o1 = *cast(Object*)p1;
|
||||
Object o2 = *cast(Object*)p2;
|
||||
|
||||
return o1 == o2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
Object o1 = *cast(Object*)p1;
|
||||
Object o2 = *cast(Object*)p2;
|
||||
int c = 0;
|
||||
|
||||
// Regard null references as always being "less than"
|
||||
if (!(o1 is o2))
|
||||
{
|
||||
if (o1)
|
||||
{ if (!o2)
|
||||
c = 1;
|
||||
else
|
||||
c = o1.opCmp(o2);
|
||||
}
|
||||
else
|
||||
c = -1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return Object.sizeof;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
39
kernel/runtime/std/typeinfo/ti_byte.d
Normal file
39
kernel/runtime/std/typeinfo/ti_byte.d
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
// byte
|
||||
|
||||
module std.typeinfo.ti_byte;
|
||||
|
||||
class TypeInfo_g : TypeInfo
|
||||
{
|
||||
char[] toString() { return "byte"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(byte *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(byte *)p1 == *cast(byte *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(byte *)p1 - *cast(byte *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return byte.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
byte t;
|
||||
|
||||
t = *cast(byte *)p1;
|
||||
*cast(byte *)p1 = *cast(byte *)p2;
|
||||
*cast(byte *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
67
kernel/runtime/std/typeinfo/ti_cdouble.d
Normal file
67
kernel/runtime/std/typeinfo/ti_cdouble.d
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
// cdouble
|
||||
|
||||
module std.typeinfo.ti_cdouble;
|
||||
|
||||
class TypeInfo_r : TypeInfo
|
||||
{
|
||||
char[] toString() { return "cdouble"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
|
||||
(cast(uint *)p)[2] + (cast(uint *)p)[3];
|
||||
}
|
||||
|
||||
static int _equals(cdouble f1, cdouble f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(cdouble f1, cdouble f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return cdouble.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
cdouble t;
|
||||
|
||||
t = *cast(cdouble *)p1;
|
||||
*cast(cdouble *)p1 = *cast(cdouble *)p2;
|
||||
*cast(cdouble *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static cdouble r;
|
||||
|
||||
return (cast(cdouble *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
66
kernel/runtime/std/typeinfo/ti_cfloat.d
Normal file
66
kernel/runtime/std/typeinfo/ti_cfloat.d
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
// cfloat
|
||||
|
||||
module std.typeinfo.ti_cfloat;
|
||||
|
||||
class TypeInfo_q : TypeInfo
|
||||
{
|
||||
char[] toString() { return "cfloat"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
static int _equals(cfloat f1, cfloat f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(cfloat f1, cfloat f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return cfloat.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
cfloat t;
|
||||
|
||||
t = *cast(cfloat *)p1;
|
||||
*cast(cfloat *)p1 = *cast(cfloat *)p2;
|
||||
*cast(cfloat *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static cfloat r;
|
||||
|
||||
return (cast(cfloat *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
43
kernel/runtime/std/typeinfo/ti_char.d
Normal file
43
kernel/runtime/std/typeinfo/ti_char.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
module std.typeinfo.ti_char;
|
||||
|
||||
class TypeInfo_a : TypeInfo
|
||||
{
|
||||
char[] toString() { return "char"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(char *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(char *)p1 == *cast(char *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(char *)p1 - *cast(char *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return char.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
char t;
|
||||
|
||||
t = *cast(char *)p1;
|
||||
*cast(char *)p1 = *cast(char *)p2;
|
||||
*cast(char *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static char c;
|
||||
|
||||
return (cast(char *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
68
kernel/runtime/std/typeinfo/ti_creal.d
Normal file
68
kernel/runtime/std/typeinfo/ti_creal.d
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
// creal
|
||||
|
||||
module std.typeinfo.ti_creal;
|
||||
|
||||
class TypeInfo_c : TypeInfo
|
||||
{
|
||||
char[] toString() { return "creal"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
|
||||
(cast(uint *)p)[2] + (cast(uint *)p)[3] +
|
||||
(cast(uint *)p)[4];
|
||||
}
|
||||
|
||||
static int _equals(creal f1, creal f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(creal f1, creal f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(creal *)p1, *cast(creal *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(creal *)p1, *cast(creal *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return creal.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
creal t;
|
||||
|
||||
t = *cast(creal *)p1;
|
||||
*cast(creal *)p1 = *cast(creal *)p2;
|
||||
*cast(creal *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static creal r;
|
||||
|
||||
return (cast(creal *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
45
kernel/runtime/std/typeinfo/ti_dchar.d
Normal file
45
kernel/runtime/std/typeinfo/ti_dchar.d
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
// dchar
|
||||
|
||||
module std.typeinfo.ti_dchar;
|
||||
|
||||
class TypeInfo_w : TypeInfo
|
||||
{
|
||||
char[] toString() { return "dchar"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(dchar *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(dchar *)p1 == *cast(dchar *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(dchar *)p1 - *cast(dchar *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return dchar.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
dchar t;
|
||||
|
||||
t = *cast(dchar *)p1;
|
||||
*cast(dchar *)p1 = *cast(dchar *)p2;
|
||||
*cast(dchar *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static dchar c;
|
||||
|
||||
return (cast(dchar *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
40
kernel/runtime/std/typeinfo/ti_delegate.d
Normal file
40
kernel/runtime/std/typeinfo/ti_delegate.d
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
// delegate
|
||||
|
||||
module std.typeinfo.ti_delegate;
|
||||
|
||||
alias void delegate(int) dg;
|
||||
|
||||
class TypeInfo_D : TypeInfo
|
||||
{
|
||||
hash_t getHash(void *p)
|
||||
{ long l = *cast(long *)p;
|
||||
|
||||
return cast(uint)(l + (l >> 32));
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(dg *)p1 == *cast(dg *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return dg.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
dg t;
|
||||
|
||||
t = *cast(dg *)p1;
|
||||
*cast(dg *)p1 = *cast(dg *)p2;
|
||||
*cast(dg *)p2 = t;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
68
kernel/runtime/std/typeinfo/ti_double.d
Normal file
68
kernel/runtime/std/typeinfo/ti_double.d
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
// double
|
||||
|
||||
module std.typeinfo.ti_double;
|
||||
|
||||
import kernel.runtime.util;
|
||||
//private import std.math;
|
||||
|
||||
class TypeInfo_d : TypeInfo
|
||||
{
|
||||
char[] toString() { return "double"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
static int _equals(double f1, double f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(isnan(f1) && isnan(f2));
|
||||
}
|
||||
|
||||
static int _compare(double d1, double d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (isnan(d1))
|
||||
{ if (isnan(d2))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(double *)p1, *cast(double *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(double *)p1, *cast(double *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return double.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
double t;
|
||||
|
||||
t = *cast(double *)p1;
|
||||
*cast(double *)p1 = *cast(double *)p2;
|
||||
*cast(double *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static double r;
|
||||
|
||||
return (cast(double *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
68
kernel/runtime/std/typeinfo/ti_float.d
Normal file
68
kernel/runtime/std/typeinfo/ti_float.d
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
// float
|
||||
|
||||
module std.typeinfo.ti_float;
|
||||
|
||||
import kernel.runtime.util;
|
||||
//private import std.math;
|
||||
|
||||
class TypeInfo_f : TypeInfo
|
||||
{
|
||||
char[] toString() { return "float"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
static int _equals(float f1, float f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(isnan(f1) && isnan(f2));
|
||||
}
|
||||
|
||||
static int _compare(float d1, float d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (isnan(d1))
|
||||
{ if (isnan(d2))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(float *)p1, *cast(float *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(float *)p1, *cast(float *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return float.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
float t;
|
||||
|
||||
t = *cast(float *)p1;
|
||||
*cast(float *)p1 = *cast(float *)p2;
|
||||
*cast(float *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static float r;
|
||||
|
||||
return (cast(float *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
12
kernel/runtime/std/typeinfo/ti_idouble.d
Normal file
12
kernel/runtime/std/typeinfo/ti_idouble.d
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
// idouble
|
||||
|
||||
module std.typeinfo.ti_idouble;
|
||||
|
||||
private import std.typeinfo.ti_double;
|
||||
|
||||
class TypeInfo_p : TypeInfo_d
|
||||
{
|
||||
char[] toString() { return "idouble"; }
|
||||
}
|
||||
|
||||
12
kernel/runtime/std/typeinfo/ti_ifloat.d
Normal file
12
kernel/runtime/std/typeinfo/ti_ifloat.d
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
// ifloat
|
||||
|
||||
module std.typeinfo.ti_ifloat;
|
||||
|
||||
private import std.typeinfo.ti_float;
|
||||
|
||||
class TypeInfo_o : TypeInfo_f
|
||||
{
|
||||
char[] toString() { return "ifloat"; }
|
||||
}
|
||||
|
||||
43
kernel/runtime/std/typeinfo/ti_int.d
Normal file
43
kernel/runtime/std/typeinfo/ti_int.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// int
|
||||
|
||||
module std.typeinfo.ti_int;
|
||||
|
||||
class TypeInfo_i : TypeInfo
|
||||
{
|
||||
char[] toString() { return "int"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(uint *)p1 == *cast(uint *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
if (*cast(int*) p1 < *cast(int*) p2)
|
||||
return -1;
|
||||
else if (*cast(int*) p1 > *cast(int*) p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return int.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = *cast(int *)p1;
|
||||
*cast(int *)p1 = *cast(int *)p2;
|
||||
*cast(int *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
12
kernel/runtime/std/typeinfo/ti_ireal.d
Normal file
12
kernel/runtime/std/typeinfo/ti_ireal.d
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
// ireal
|
||||
|
||||
module std.typeinfo.ti_ireal;
|
||||
|
||||
private import std.typeinfo.ti_real;
|
||||
|
||||
class TypeInfo_j : TypeInfo_e
|
||||
{
|
||||
char[] toString() { return "ireal"; }
|
||||
}
|
||||
|
||||
43
kernel/runtime/std/typeinfo/ti_long.d
Normal file
43
kernel/runtime/std/typeinfo/ti_long.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// long
|
||||
|
||||
module std.typeinfo.ti_long;
|
||||
|
||||
class TypeInfo_l : TypeInfo
|
||||
{
|
||||
char[] toString() { return "long"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(uint *)p + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(long *)p1 == *cast(long *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
if (*cast(long *)p1 < *cast(long *)p2)
|
||||
return -1;
|
||||
else if (*cast(long *)p1 > *cast(long *)p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return long.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = *cast(long *)p1;
|
||||
*cast(long *)p1 = *cast(long *)p2;
|
||||
*cast(long *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
47
kernel/runtime/std/typeinfo/ti_ptr.d
Normal file
47
kernel/runtime/std/typeinfo/ti_ptr.d
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
// pointer
|
||||
|
||||
module std.typeinfo.ti_ptr;
|
||||
|
||||
class TypeInfo_P : TypeInfo
|
||||
{
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return cast(uint)*cast(void* *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(void* *)p1 == *cast(void* *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
auto c = *cast(void* *)p1 - *cast(void* *)p2;
|
||||
if (c < 0)
|
||||
return -1;
|
||||
else if (c > 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return (void*).sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
void* t;
|
||||
|
||||
t = *cast(void* *)p1;
|
||||
*cast(void* *)p1 = *cast(void* *)p2;
|
||||
*cast(void* *)p2 = t;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
68
kernel/runtime/std/typeinfo/ti_real.d
Normal file
68
kernel/runtime/std/typeinfo/ti_real.d
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
// real
|
||||
|
||||
module std.typeinfo.ti_real;
|
||||
|
||||
import kernel.runtime.util;
|
||||
//private import std.math;
|
||||
|
||||
class TypeInfo_e : TypeInfo
|
||||
{
|
||||
char[] toString() { return "real"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4];
|
||||
}
|
||||
|
||||
static int _equals(real f1, real f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(isnan(f1) && isnan(f2));
|
||||
}
|
||||
|
||||
static int _compare(real d1, real d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (isnan(d1))
|
||||
{ if (isnan(d2))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(real *)p1, *cast(real *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(real *)p1, *cast(real *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return real.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
real t;
|
||||
|
||||
t = *cast(real *)p1;
|
||||
*cast(real *)p1 = *cast(real *)p2;
|
||||
*cast(real *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static real r;
|
||||
|
||||
return (cast(real *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
39
kernel/runtime/std/typeinfo/ti_short.d
Normal file
39
kernel/runtime/std/typeinfo/ti_short.d
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
// short
|
||||
|
||||
module std.typeinfo.ti_short;
|
||||
|
||||
class TypeInfo_s : TypeInfo
|
||||
{
|
||||
char[] toString() { return "short"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(short *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(short *)p1 == *cast(short *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(short *)p1 - *cast(short *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return short.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
short t;
|
||||
|
||||
t = *cast(short *)p1;
|
||||
*cast(short *)p1 = *cast(short *)p2;
|
||||
*cast(short *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
43
kernel/runtime/std/typeinfo/ti_ubyte.d
Normal file
43
kernel/runtime/std/typeinfo/ti_ubyte.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// ubyte
|
||||
|
||||
module std.typeinfo.ti_ubyte;
|
||||
|
||||
class TypeInfo_h : TypeInfo
|
||||
{
|
||||
char[] toString() { return "ubyte"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(ubyte *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(ubyte *)p1 == *cast(ubyte *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(ubyte *)p1 - *cast(ubyte *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return ubyte.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
ubyte t;
|
||||
|
||||
t = *cast(ubyte *)p1;
|
||||
*cast(ubyte *)p1 = *cast(ubyte *)p2;
|
||||
*cast(ubyte *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
class TypeInfo_b : TypeInfo_h
|
||||
{
|
||||
char[] toString() { return "bool"; }
|
||||
}
|
||||
43
kernel/runtime/std/typeinfo/ti_uint.d
Normal file
43
kernel/runtime/std/typeinfo/ti_uint.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// uint
|
||||
|
||||
module std.typeinfo.ti_uint;
|
||||
|
||||
class TypeInfo_k : TypeInfo
|
||||
{
|
||||
char[] toString() { return "uint"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(uint *)p1 == *cast(uint *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
if (*cast(uint*) p1 < *cast(uint*) p2)
|
||||
return -1;
|
||||
else if (*cast(uint*) p1 > *cast(uint*) p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return uint.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = *cast(uint *)p1;
|
||||
*cast(uint *)p1 = *cast(uint *)p2;
|
||||
*cast(uint *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
43
kernel/runtime/std/typeinfo/ti_ulong.d
Normal file
43
kernel/runtime/std/typeinfo/ti_ulong.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// ulong
|
||||
|
||||
module std.typeinfo.ti_ulong;
|
||||
|
||||
class TypeInfo_m : TypeInfo
|
||||
{
|
||||
char[] toString() { return "ulong"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(uint *)p + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(ulong *)p1 == *cast(ulong *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
if (*cast(ulong *)p1 < *cast(ulong *)p2)
|
||||
return -1;
|
||||
else if (*cast(ulong *)p1 > *cast(ulong *)p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return ulong.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
ulong t;
|
||||
|
||||
t = *cast(ulong *)p1;
|
||||
*cast(ulong *)p1 = *cast(ulong *)p2;
|
||||
*cast(ulong *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
39
kernel/runtime/std/typeinfo/ti_ushort.d
Normal file
39
kernel/runtime/std/typeinfo/ti_ushort.d
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
// ushort
|
||||
|
||||
module std.typeinfo.ti_ushort;
|
||||
|
||||
class TypeInfo_t : TypeInfo
|
||||
{
|
||||
char[] toString() { return "ushort"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(ushort *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(ushort *)p1 == *cast(ushort *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(ushort *)p1 - *cast(ushort *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return ushort.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
ushort t;
|
||||
|
||||
t = *cast(ushort *)p1;
|
||||
*cast(ushort *)p1 = *cast(ushort *)p2;
|
||||
*cast(ushort *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
44
kernel/runtime/std/typeinfo/ti_void.d
Normal file
44
kernel/runtime/std/typeinfo/ti_void.d
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
// void
|
||||
|
||||
module std.typeinfo.ti_void;
|
||||
|
||||
class TypeInfo_v : TypeInfo
|
||||
{
|
||||
char[] toString() { return "void"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(byte *)p1 == *cast(byte *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(byte *)p1 - *cast(byte *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return void.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
byte t;
|
||||
|
||||
t = *cast(byte *)p1;
|
||||
*cast(byte *)p1 = *cast(byte *)p2;
|
||||
*cast(byte *)p2 = t;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
44
kernel/runtime/std/typeinfo/ti_wchar.d
Normal file
44
kernel/runtime/std/typeinfo/ti_wchar.d
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
module std.typeinfo.ti_wchar;
|
||||
|
||||
|
||||
class TypeInfo_u : TypeInfo
|
||||
{
|
||||
char[] toString() { return "wchar"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(wchar *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(wchar *)p1 == *cast(wchar *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(wchar *)p1 - *cast(wchar *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return wchar.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
wchar t;
|
||||
|
||||
t = *cast(wchar *)p1;
|
||||
*cast(wchar *)p1 = *cast(wchar *)p2;
|
||||
*cast(wchar *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static wchar c;
|
||||
|
||||
return (cast(wchar *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
163
kernel/runtime/util.d
Normal file
163
kernel/runtime/util.d
Normal file
@@ -0,0 +1,163 @@
|
||||
// This module contains helpful functions found necessary by the runtime and gcc.
|
||||
|
||||
// contains: itoa, memcpy, memset, memmove, memcmp, strlen, isnan, toString
|
||||
|
||||
module kernel.runtime.util;
|
||||
|
||||
/**
|
||||
This function converts an integer to a string, depending on the base passed in.
|
||||
Params:
|
||||
buf = The function will save the translated string into this character array.
|
||||
base = The base of the integer value. If "d," it will be assumed to be decimal. If "x," the integer
|
||||
will be hexadecimal.
|
||||
d = The integer to translate.
|
||||
Returns: The translated string in a character array.
|
||||
*/
|
||||
char[] itoa(char[] buf, char base, long d)
|
||||
{
|
||||
size_t p = buf.length - 1;
|
||||
size_t startIdx = 0;
|
||||
ulong ud = d;
|
||||
bool negative = false;
|
||||
|
||||
int divisor = 10;
|
||||
|
||||
// If %d is specified and D is minus, put `-' in the head.
|
||||
if(base == 'd' && d < 0)
|
||||
{
|
||||
negative = true;
|
||||
ud = -d;
|
||||
}
|
||||
else if(base == 'x')
|
||||
divisor = 16;
|
||||
|
||||
// Divide UD by DIVISOR until UD == 0.
|
||||
do
|
||||
{
|
||||
int remainder = ud % divisor;
|
||||
buf[p--] = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
|
||||
}
|
||||
while (ud /= divisor)
|
||||
|
||||
if(negative)
|
||||
buf[p--] = '-';
|
||||
|
||||
return buf[p + 1 .. $];
|
||||
}
|
||||
|
||||
/**
|
||||
This function copies data from a source piece of memory to a destination piece of memory.
|
||||
Params:
|
||||
dest = A pointer to the piece of memory serving as the copy destination.
|
||||
src = A pointer to the piece of memory serving as the copy source.
|
||||
count = The number of bytes to copy form src to dest.
|
||||
Returns: A void pointer to the start of the destination data (dest).
|
||||
*/
|
||||
extern(C) void* memcpy(void* dest, void* src, size_t count)
|
||||
{
|
||||
ubyte* d = cast(ubyte*)dest;
|
||||
ubyte* s = cast(ubyte*)src;
|
||||
|
||||
for(size_t i = count; count; count--, d++, s++)
|
||||
*d = *s;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Memcpy and memmove only really have differences at the user level, where they have slightly
|
||||
different semantics. Here, they're pretty much the same.
|
||||
*/
|
||||
extern(C) void* memmove(void* dest, void* src, size_t count)
|
||||
{
|
||||
ubyte* d = cast(ubyte*)dest;
|
||||
ubyte* s = cast(ubyte*)src;
|
||||
|
||||
for(size_t i = count; count; count--, d++, s++)
|
||||
*d = *s;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
Compare two blocks of memory.
|
||||
|
||||
Params:
|
||||
a = Pointer to the first block.
|
||||
b = Pointer to the second block.
|
||||
n = The number of bytes to compare.
|
||||
|
||||
Returns:
|
||||
0 if they are equal, < 0 if a is less than b, and > 0 if a is greater than b.
|
||||
*/
|
||||
long memcmp(void* a, void* b, size_t n)
|
||||
{
|
||||
ubyte* str_a = cast(ubyte*)a;
|
||||
ubyte* str_b = cast(ubyte*)b;
|
||||
|
||||
for(size_t i = 0; i < n; i++)
|
||||
{
|
||||
if(*str_a != *str_b)
|
||||
return *str_a - *str_b;
|
||||
|
||||
str_a++;
|
||||
str_b++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
This function sets a particular piece of memory to a particular value.
|
||||
Params:
|
||||
addr = The address of the piece of memory you wish to write.
|
||||
val = The value you wish to write to memory.
|
||||
numBytes = The number of bytes you would like to write to memory.
|
||||
*/
|
||||
void memset(void *addr, ubyte val, uint numBytes){
|
||||
ubyte *data = cast(ubyte*) addr;
|
||||
|
||||
for(int i = 0; i < numBytes; i++){
|
||||
data[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This function determines the size of a passed-in string.
|
||||
Params:
|
||||
s = A pointer to the beginning of a character array, declaring a string.
|
||||
Returns: The size of the string in size_t format.
|
||||
*/
|
||||
size_t strlen(char* s)
|
||||
{
|
||||
size_t i = 0;
|
||||
for( ; *s != 0; i++, s++){}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
This function takes in a character pointer and returns a character array, or a string.
|
||||
Params:
|
||||
s = A pointer to the character(s) you wish to translate to a string.
|
||||
Returns: A character array (string) containing the information.
|
||||
*/
|
||||
char[] toString(char* s)
|
||||
{
|
||||
return s[0 .. strlen(s)];
|
||||
}
|
||||
|
||||
/**
|
||||
This function checks to see if a floating point number is a NaN.
|
||||
Params:
|
||||
e = The value / piece of information you would like to check for number status.
|
||||
Returns:
|
||||
0 if it isn't a NaN, non-zero if it is.
|
||||
*/
|
||||
int isnan(real e)
|
||||
{
|
||||
ushort* pe = cast(ushort *)&e;
|
||||
ulong* ps = cast(ulong *)&e;
|
||||
|
||||
return (pe[4] & 0x7FFF) == 0x7FFF &&
|
||||
*ps & 0x7FFFFFFFFFFFFFFF;
|
||||
}
|
||||
Reference in New Issue
Block a user