Merge branch 'master' of git://git.ucc.asn.au/tpg/acess2
authorJohn Hodge <[email protected]>
Mon, 16 Feb 2015 08:51:57 +0000 (16:51 +0800)
committerJohn Hodge <[email protected]>
Mon, 16 Feb 2015 08:51:57 +0000 (16:51 +0800)
434 files changed:
.gitignore
.travis.yml
AcessNative/Makefile
AcessNative/RunNative [new file with mode: 0755]
AcessNative/RunRootApp
AcessNative/RunTest
AcessNative/acesskernel_src/Makefile
AcessNative/acesskernel_src/include/arch.h
AcessNative/acesskernel_src/main.c
AcessNative/acesskernel_src/net_wrap.c
AcessNative/acesskernel_src/server.c
AcessNative/acesskernel_src/threads.c
AcessNative/acesskernel_src/threads_glue.c
AcessNative/acesskernel_src/vfs_handle.c
AcessNative/acesskernel_src/video.c
AcessNative/ld-acess_src/binary.c
AcessNative/ld-acess_src/common.h
AcessNative/ld-acess_src/elf_load.c
AcessNative/ld-acess_src/exports.c
AcessNative/ld-acess_src/exports.h
AcessNative/ld-acess_src/memory.c
AcessNative/ld-acess_src/request.c
AcessNative/ld-acess_src/syscalls.c
AcessNative/libacess-native.so_src/Makefile
AcessNative/libacess-native.so_src/exports.c
AcessNative/libacess-native.so_src/main.c
BuildConf/armv7/Makefile.cfg
BuildConf/x86/Makefile.cfg
BuildConf/x86_64/Makefile.cfg
Externals/common_automake.mk
Externals/config.mk
Externals/core.mk
Externals/cross-compiler/Makefile
Externals/cross-compiler/Makefile.common.mk [new file with mode: 0644]
Externals/cross-compiler/Makefile.cross [new file with mode: 0644]
Externals/cross-compiler/Makefile.rules.mk [new file with mode: 0644]
Externals/cross-compiler/patches/binutils/bfd/config.bfd.patch
Externals/cross-compiler/patches/binutils/gas/configure.tgt.patch
Externals/cross-compiler/patches/binutils/ld/Makefile.in.patch
Externals/cross-compiler/patches/binutils/ld/configure.tgt.patch
Externals/cross-compiler/patches/binutils/ld/emulparams/acess2_amd64.sh
Externals/cross-compiler/patches/binutils/ld/emulparams/acess2_arm.sh [new file with mode: 0644]
Externals/cross-compiler/patches/gcc/gcc/config.gcc.patch
Externals/cross-compiler/patches/gcc/gcc/config/acess2.h
Externals/cross-compiler/patches/gcc/gcc/config/acess2.opt [new file with mode: 0644]
Externals/cross-compiler/patches/gcc/libgcc/config.host.patch
Externals/curl/Makefile [new file with mode: 0644]
Externals/curl/patches/config.sub.patch [new file with mode: 0644]
Externals/glib/Makefile [new file with mode: 0644]
Externals/glib/patches/config.sub.patch [new file with mode: 0644]
Externals/libspiderscript/source
Externals/netsurf/Makefile
Externals/netsurf/patches/UNIFIED.patch
Externals/pkgconfig/Makefile [new file with mode: 0644]
Externals/pkgconfig/patches/config.sub.patch [new file with mode: 0644]
Externals/pkgconfig/patches/glib/config.sub.patch [new file with mode: 0644]
KernelLand/Kernel/GenSyscalls.pl
KernelLand/Kernel/Makefile
KernelLand/Kernel/arch/helpers.h
KernelLand/Kernel/arch/x86/common.inc.asm [new file with mode: 0644]
KernelLand/Kernel/arch/x86/desctab.asm
KernelLand/Kernel/arch/x86/mm_virt.c
KernelLand/Kernel/arch/x86/proc.asm
KernelLand/Kernel/arch/x86/proc.c
KernelLand/Kernel/arch/x86/time.c
KernelLand/Kernel/arch/x86/vm8086.c
KernelLand/Kernel/arch/x86_64/desctab.asm
KernelLand/Kernel/arch/x86_64/include/arch.h
KernelLand/Kernel/arch/x86_64/include/mm_virt.h
KernelLand/Kernel/arch/x86_64/lib.c
KernelLand/Kernel/arch/x86_64/mm_virt.c
KernelLand/Kernel/arch/x86_64/proc.asm
KernelLand/Kernel/arch/x86_64/proc.c
KernelLand/Kernel/bin/elf.c
KernelLand/Kernel/binary.c
KernelLand/Kernel/debug.c
KernelLand/Kernel/drv/dgram_pipe.c
KernelLand/Kernel/drv/fifo.c
KernelLand/Kernel/drv/proc.c
KernelLand/Kernel/drv/pty.c
KernelLand/Kernel/drv/serial.c
KernelLand/Kernel/drv/shm.c [new file with mode: 0644]
KernelLand/Kernel/drv/vterm.c
KernelLand/Kernel/drv/vterm.h
KernelLand/Kernel/drv/vterm_2d.c
KernelLand/Kernel/drv/vterm_input.c
KernelLand/Kernel/drv/vterm_output.c
KernelLand/Kernel/drv/vterm_termbuf.c
KernelLand/Kernel/drv/vterm_vt100.c
KernelLand/Kernel/drv/zero-one.c
KernelLand/Kernel/drvutil_video.c
KernelLand/Kernel/emergency_console.c [new file with mode: 0644]
KernelLand/Kernel/events.c
KernelLand/Kernel/heap.c
KernelLand/Kernel/include/acess.h
KernelLand/Kernel/include/acess_string.h
KernelLand/Kernel/include/apidoc_mainpage.h
KernelLand/Kernel/include/drv_pci.h
KernelLand/Kernel/include/logdebug.h
KernelLand/Kernel/include/memfs_helpers.h [new file with mode: 0644]
KernelLand/Kernel/include/syscalls.h
KernelLand/Kernel/include/syscalls.inc.asm
KernelLand/Kernel/include/threads.h
KernelLand/Kernel/include/vfs.h
KernelLand/Kernel/include/vfs_ext.h
KernelLand/Kernel/include/vfs_threads.h
KernelLand/Kernel/libc.c
KernelLand/Kernel/logging.c
KernelLand/Kernel/memfs_helpers.c [new file with mode: 0644]
KernelLand/Kernel/rwlock.c
KernelLand/Kernel/syscalls.c
KernelLand/Kernel/syscalls.lst
KernelLand/Kernel/system.c
KernelLand/Kernel/threads.c
KernelLand/Kernel/time.c
KernelLand/Kernel/vfs/handle.c
KernelLand/Kernel/vfs/io.c
KernelLand/Kernel/vfs/main.c
KernelLand/Kernel/vfs/mmap.c
KernelLand/Kernel/vfs/open.c
KernelLand/Kernel/vfs/select.c
KernelLand/Modules/Display/BochsGA/bochsvbe.c
KernelLand/Modules/Display/Tegra2Vid/main.c
KernelLand/Modules/Display/VESA/main.c
KernelLand/Modules/Display/VGA/vgaregs.c [new file with mode: 0644]
KernelLand/Modules/Filesystems/InitRD/GenerateInitRD.php
KernelLand/Modules/Filesystems/InitRD/files.lst
KernelLand/Modules/IPStack/icmp.c
KernelLand/Modules/IPStack/icmpv6.h
KernelLand/Modules/IPStack/ipstack.h
KernelLand/Modules/IPStack/ipv4.c
KernelLand/Modules/IPStack/ipv4.h
KernelLand/Modules/IPStack/ipv6.c
KernelLand/Modules/IPStack/ipv6.h
KernelLand/Modules/IPStack/tcp.c
KernelLand/Modules/IPStack/tcp.h
KernelLand/Modules/IPStack/udp.c
KernelLand/Modules/Input/Keyboard/main.c
KernelLand/Modules/Input/PS2KbMouse/8042.c
KernelLand/Modules/Interfaces/EDI/Makefile [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/acess-edi.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/edi.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/edi_devices.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/edi_dma_streams.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/edi_interrupts.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/edi_memory_mapping.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/edi_objects.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/edi_port_io.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/edi_pthreads.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi/helpers.h [deleted file]
KernelLand/Modules/Interfaces/EDI/edi_int.inc.c [deleted file]
KernelLand/Modules/Interfaces/EDI/edi_io.inc.c [deleted file]
KernelLand/Modules/Interfaces/EDI/main.c [deleted file]
KernelLand/Modules/Interfaces/UDI/Makefile
KernelLand/Modules/Interfaces/UDI/main.c
KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c
KernelLand/Modules/Interfaces/UDI/trans/gfx.c [new file with mode: 0644]
KernelLand/Modules/Interfaces/UDI/trans/gfx.udic [new file with mode: 0644]
KernelLand/Modules/Interfaces/UDI/trans/gfx_plan.txt [new file with mode: 0644]
KernelLand/Modules/Libraries/VirtIO/virtio.c
KernelLand/Modules/Makefile.tpl
KernelLand/Modules/Network/E1000/e1000.c
Makefile
Makefile.cfg
Notes/TODO
RunQemu
Tools/NetTest/Makefile
Tools/NetTest/vfs_shim.c
Tools/NetTest_Runner/Makefile
Tools/NetTest_Runner/include/stack.h
Tools/NetTest_Runner/include/test.h
Tools/NetTest_Runner/include/tests.h
Tools/NetTest_Runner/main.c
Tools/NetTest_Runner/net.c
Tools/NetTest_Runner/stack.c
Tools/NetTest_Runner/test_arp.c
Tools/NetTest_Runner/test_tcp.c
Tools/nativelib/Makefile
Tools/nativelib/include/threads_int.h
Tools/nativelib/threads.c
UDI/Tools/udibuild.ini
UDI/Tools/udibuild_src/build.c
UDI/Tools/udibuild_src/include/common.h
UDI/Tools/udibuild_src/main.c
UDI/drivers/gfx_bochs/bochsga_common.h [new file with mode: 0644]
UDI/drivers/gfx_bochs/bochsga_core.c [new file with mode: 0644]
UDI/drivers/gfx_bochs/bochsga_engines.h [new file with mode: 0644]
UDI/drivers/gfx_bochs/bochsga_pio.h [new file with mode: 0644]
UDI/drivers/gfx_bochs/udiprops.txt [new file with mode: 0644]
UDI/drivers/helpers.h [new file with mode: 0644]
UDI/drivers/helpers_gfx.h [new file with mode: 0644]
UDI/drivers/net_ne2000/ne2000_common.h
UDI/drivers/net_ne2000/ne2000_core.c
UDI/drivers/net_ne2000/ne2000_rx.c
UDI/drivers/net_ne2000/ne2000_tx.c
UDI/drivers/uart_16c550/uart16c550.c
UDI/gfx_spec_issues.txt [new file with mode: 0644]
UDI/include/udi.h
UDI/include/udi_gfx.h [new file with mode: 0644]
UDI/include/udi_gfx.h.ORIG [new file with mode: 0644]
UDI/include/udi_nic.h
UDI/include/udi_pci.h
UDI/include/udi_physio.h
Usermode/Applications/CLIShell_src/Makefile
Usermode/Applications/Makefile.cfg
Usermode/Applications/Makefile.tpl
Usermode/Applications/axwin3_src/Interface/Makefile
Usermode/Applications/axwin3_src/WM/Makefile
Usermode/Applications/axwin3_src/WM/common.mk
Usermode/Applications/axwin3_src/WM/renderers/widget/common.h
Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c
Usermode/Applications/axwin3_src/WM/wm.c
Usermode/Applications/axwin4_src/Common/include/ipc_proto.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Common/include/serialisation.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Common/serialisation.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Makefile [new file with mode: 0644]
Usermode/Applications/axwin4_src/Notes.txt [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/CClient.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/CConfig.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/CIPCChannel_AcessIPCPipe.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/CRect.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/CSurface.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/CWindow.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/Makefile [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/compositor.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/draw_control.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/draw_text.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CClient.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CColour.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CConfig.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CConfigIPC.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CConfigInput.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CConfigVideo.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CIPCChannel_AcessIPCPipe.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CRect.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CSurface.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/CWindow.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/IFontFace.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/IIPCChannel.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/IRegion.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/IVideo.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/IWindow.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/common.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/compositor.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/draw_control.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/draw_text.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/input.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/ipc.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/timing.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/include/video.hpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/input.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/ipc.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/main.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/resources/cursor.h [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/resources/font_8x16.h [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/timing.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/Server/video.cpp [new file with mode: 0644]
Usermode/Applications/axwin4_src/UI/Makefile [new file with mode: 0644]
Usermode/Applications/axwin4_src/UI/include/common.h [new file with mode: 0644]
Usermode/Applications/axwin4_src/UI/include/taskbar.h [new file with mode: 0644]
Usermode/Applications/axwin4_src/UI/main.c [new file with mode: 0644]
Usermode/Applications/axwin4_src/UI/taskbar.c [new file with mode: 0644]
Usermode/Applications/gui_ate_src/Makefile
Usermode/Applications/gui_terminal_src/Makefile
Usermode/Applications/gui_terminal_src/vt100.c
Usermode/Applications/init_src/main.c
Usermode/Applications/ip_src/Makefile
Usermode/Applications/irc_src/Makefile
Usermode/Applications/irc_src/common.h [new file with mode: 0644]
Usermode/Applications/irc_src/input.c [new file with mode: 0644]
Usermode/Applications/irc_src/input.h [new file with mode: 0644]
Usermode/Applications/irc_src/main.c
Usermode/Applications/irc_src/message.h [new file with mode: 0644]
Usermode/Applications/irc_src/pseudo_curses.c [new file with mode: 0644]
Usermode/Applications/irc_src/pseudo_curses.h [new file with mode: 0644]
Usermode/Applications/irc_src/server.c [new file with mode: 0644]
Usermode/Applications/irc_src/server.h [new file with mode: 0644]
Usermode/Applications/irc_src/window.c [new file with mode: 0644]
Usermode/Applications/irc_src/window.h [new file with mode: 0644]
Usermode/Applications/ping_src/Makefile
Usermode/Applications/telnet_src/Makefile
Usermode/Applications/telnetd_src/Makefile
Usermode/Applications/wget_src/Makefile
Usermode/Libraries/Makefile.cfg
Usermode/Libraries/Makefile.tpl
Usermode/Libraries/acess.ld_src/.gitignore [deleted file]
Usermode/Libraries/acess.ld_src/Makefile [deleted file]
Usermode/Libraries/acess.ld_src/acess_armv6.ld.h [deleted file]
Usermode/Libraries/acess.ld_src/acess_armv7.ld.h [deleted file]
Usermode/Libraries/acess.ld_src/acess_x86.ld.h [deleted file]
Usermode/Libraries/acess.ld_src/acess_x86_64.ld.h [deleted file]
Usermode/Libraries/acess.ld_src/rules.mk [deleted file]
Usermode/Libraries/crt0.o_src/Makefile
Usermode/Libraries/crt0.o_src/armv7-crti.S [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/armv7-crtn.S [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/crt0.c
Usermode/Libraries/crt0.o_src/crt0S.c [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/native-crti.S [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/native-crtn.S [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/x86-crti.S [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/x86-crtn.S [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/x86_64-crti.S [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/x86_64-crtn.S [new file with mode: 0644]
Usermode/Libraries/ld-acess.so_src/Makefile
Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h
Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h
Usermode/Libraries/ld-acess.so_src/arch/x86_64.asm.h
Usermode/Libraries/ld-acess.so_src/common.h
Usermode/Libraries/ld-acess.so_src/elf.c
Usermode/Libraries/ld-acess.so_src/elf32.h
Usermode/Libraries/ld-acess.so_src/elf64.h
Usermode/Libraries/ld-acess.so_src/elf_impl.c [new file with mode: 0644]
Usermode/Libraries/ld-acess.so_src/export.c
Usermode/Libraries/ld-acess.so_src/include_exp/acess/_native_syscallmod.h
Usermode/Libraries/ld-acess.so_src/include_exp/acess/devices/joystick.h [new file with mode: 0644]
Usermode/Libraries/ld-acess.so_src/include_exp/acess/devices/pty_cmds.h
Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h
Usermode/Libraries/ld-acess.so_src/loadlib.c
Usermode/Libraries/ld-acess.so_src/main.c
Usermode/Libraries/libaxwin4.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/include/CIPCChannel_AcessIPCPipe.hpp [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/include/IIPCChannel.hpp [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/include/common.hpp [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/include_exp/axwin4/axwin.h [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/include_exp/axwin4/definitions.h [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/ipc.cpp [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/ipc_acessipcpipe.cpp [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/main.c [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp [new file with mode: 0644]
Usermode/Libraries/libaxwin4.so_src/wm.cpp [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/Makefile
Usermode/Libraries/libc++.so_src/cxxabi.cc
Usermode/Libraries/libc++.so_src/exception_handling.cc [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/exception_handling_acxx.h [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/exception_handling_cxxabi.h [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/exceptions.cc [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/guard.cc
Usermode/Libraries/libc++.so_src/gxx_personality.cc [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/_libcxx_helpers.h [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/algorithm [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/allocator [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/cassert [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/cerrno [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/cstddef [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/cstdint [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/cstdio [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/cstdlib [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/cstring [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/cxxabi.h
Usermode/Libraries/libc++.so_src/include_exp/exception [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/functional [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/initializer_list [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/iterator [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/list [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/map [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/memory [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/mutex [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/new [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/stdexcept [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/string [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/system_error [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/type_traits [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/typeinfo
Usermode/Libraries/libc++.so_src/include_exp/utility [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/include_exp/vector [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/misc.cc
Usermode/Libraries/libc++.so_src/mutex.cc [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/new.cc
Usermode/Libraries/libc++.so_src/string.cc [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/system_error.cc [new file with mode: 0644]
Usermode/Libraries/libc++.so_src/typeinfo.cc
Usermode/Libraries/libc++_extras.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libc++_extras.so_src/TEST_cprintf.cpp [new file with mode: 0644]
Usermode/Libraries/libc++_extras.so_src/include_exp/cxxextras_printf [new file with mode: 0644]
Usermode/Libraries/libc.so_src/Makefile
Usermode/Libraries/libc.so_src/TEST_string.c [new file with mode: 0644]
Usermode/Libraries/libc.so_src/TEST_strtoi.c
Usermode/Libraries/libc.so_src/ctype.c
Usermode/Libraries/libc.so_src/errno.c
Usermode/Libraries/libc.so_src/heap.c
Usermode/Libraries/libc.so_src/heap_native.c [new file with mode: 0644]
Usermode/Libraries/libc.so_src/include_exp/ctype.h
Usermode/Libraries/libc.so_src/include_exp/errno.enum.h
Usermode/Libraries/libc.so_src/include_exp/inttypes.h
Usermode/Libraries/libc.so_src/include_exp/stdio.h
Usermode/Libraries/libc.so_src/include_exp/stdlib.h
Usermode/Libraries/libc.so_src/include_exp/string.h
Usermode/Libraries/libc.so_src/signals.c
Usermode/Libraries/libc.so_src/stdio.c
Usermode/Libraries/libc.so_src/string.c
Usermode/Libraries/libc.so_src/strtoi.c
Usermode/Libraries/libc.so_src/stub.c
Usermode/Libraries/libc.so_src/time.c
Usermode/Libraries/libc.so_src/timeconv.c
Usermode/Libraries/libiconv.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libiconv.so_src/iconv.c [new file with mode: 0644]
Usermode/Libraries/libiconv.so_src/include_exp/iconv.h [new file with mode: 0644]
Usermode/Libraries/libintl.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libintl.so_src/gettext.c [new file with mode: 0644]
Usermode/Libraries/libintl.so_src/include_exp/libintl.h [new file with mode: 0644]
Usermode/Libraries/libintl.so_src/main.c [new file with mode: 0644]
Usermode/Libraries/libm.so_src/include_exp/math.h
Usermode/Libraries/libnet.so_src/Makefile
Usermode/Libraries/libnet.so_src/TEST_dns.c [new file with mode: 0644]
Usermode/Libraries/libnet.so_src/address.c
Usermode/Libraries/libnet.so_src/dns.c [new file with mode: 0644]
Usermode/Libraries/libnet.so_src/hostnames.c [new file with mode: 0644]
Usermode/Libraries/libnet.so_src/include/dns.h [new file with mode: 0644]
Usermode/Libraries/libnet.so_src/include_exp/net.h
Usermode/Libraries/libnet.so_src/socket.c
Usermode/Libraries/libposix.so_src/Makefile
Usermode/Libraries/libposix.so_src/getopt.c [new file with mode: 0644]
Usermode/Libraries/libposix.so_src/include_exp/endian.h [new file with mode: 0644]
Usermode/Libraries/libposix.so_src/include_exp/getopt.h [new file with mode: 0644]
Usermode/Libraries/libposix.so_src/include_exp/glob.h [new file with mode: 0644]
Usermode/Libraries/libposix.so_src/include_exp/regex.h [new file with mode: 0644]
Usermode/Libraries/libposix.so_src/include_exp/strings.h [new file with mode: 0644]
Usermode/Libraries/libposix.so_src/include_exp/unistd.h
Usermode/Libraries/libposix.so_src/mktemp.c
Usermode/Libraries/libposix.so_src/unistd.c
Usermode/Libraries/libpsocket.so_src/Makefile
Usermode/Libraries/libpsocket.so_src/getaddrinfo.c
Usermode/Libraries/libpthread.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libpthread.so_src/include_exp/pthread.h [new file with mode: 0644]
Usermode/Libraries/libpthread.so_src/include_exp/sched.h [new file with mode: 0644]
Usermode/Libraries/libpthread.so_src/main.c [new file with mode: 0644]
Usermode/Libraries/libpthread.so_src/thread.c [new file with mode: 0644]
Usermode/Libraries/libresolv.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libresolv.so_src/include_exp/arpa/nameser.h [new file with mode: 0644]
Usermode/Libraries/libresolv.so_src/include_exp/resolv.h [new file with mode: 0644]
Usermode/Libraries/libresolv.so_src/resolv.c [new file with mode: 0644]
Usermode/Libraries/libunicode.so_src/include_exp/unicode.h
Usermode/common_settings.mk

index 7ed9ebe..365eb6c 100644 (file)
@@ -26,6 +26,7 @@ serial.txt
 *.gz
 *.img
 *.vmdk
+*.iso
 SrcDoc/
 APIDoc/
 Usermode/*/*/UTEST/stage
index d39dc5d..52dc032 100644 (file)
@@ -6,4 +6,6 @@ compiler: clang
 #env:
 # - ARCH=host HOST_ARCH=x86 USE_ACPICA=0
 # - ARCH=host HOST_ARCH=x86_64 CC="$CC -m64"
-script: "make utest mtest"
+script:
+ - "make utest-build mtest-build"
+ - "make -k utest-run mtest-run"
index 7448f4f..8d5d6c4 100644 (file)
@@ -1,6 +1,10 @@
 
 .PHONY: all clean
 
+V ?= @
+
 all clean:
        @$(MAKE) -C acesskernel_src $@
        @$(MAKE) -C ld-acess_src $@
+       @$(MAKE) -C libacess-native.so_src $@   
+       @$(MAKE) -C .. $@-user ARCH=native V=$(V)
diff --git a/AcessNative/RunNative b/AcessNative/RunNative
new file mode 100755 (executable)
index 0000000..406573d
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/bash
+#
+# Execute the specified root application using the ARCH=native build
+#
+_=$PWD; cd $(dirname $0); DIR=$PWD; cd $_
+DISTROOT=$(dirname $DIR)/Usermode/Output/native/
+VTERM=/Devices/pts/vt0
+echo $DISTROOT
+
+KERNEL_PID=$$
+function cleanup {
+       trap '' SIGINT
+       echo Cleaning up $KERNEL_PID
+       kill -INT $KERNEL_PID
+}
+
+trap cleanup SIGINT
+
+# 1. Start up AcessKernel
+# - Set DISTROOT to the output directory of ARCH=native
+# - Don't start a root application
+${DIR}/AcessKernel --distroot $DISTROOT > ${DIR}/log/native_AcessKernel.log 2>&1 &
+KERNEL_PID=$!
+echo Kernel is $KERNEL_PID
+sleep 1
+
+APP=gui4
+
+case $APP in
+gui4)
+       LD_LIBRARY_PATH=${DIR}:${DISTROOT}Libs AN_PREOPEN=$VTERM:$VTERM:$VTERM ${DBG} ${DISTROOT}Apps/AxWin/4.0/AxWinServer
+       ;;
+gui3)
+       LD_LIBRARY_PATH=${DIR}:${DISTROOT}Libs AN_PREOPEN=$VTERM:$VTERM:$VTERM ${DBG} ${DISTROOT}Apps/AxWin/3.0/AxWinWM
+       ;;
+*)
+       echo "Unknown application '$APP'"
+esac
+
+trap '' SIGINT
+cleanup
+
index 39a30fa..a3d31ab 100755 (executable)
@@ -1,3 +1,7 @@
 #!/bin/sh
 
+#
+# Spin up an application bound to VTerm 0 using ./ld-acess
+#
+
 $DBG ./ld-acess --open /Devices/VTerm/0 --open /Devices/VTerm/0 --open /Devices/VTerm/0 $*
index 6ea88b6..069ea14 100755 (executable)
@@ -1,4 +1,7 @@
 #!/bin/sh
+#
+# Runs the AcessNative kernel and spawns a native executable using ./ld-acess
+#
 trap '' 2
 #$1 ./AcessKernel --rootapp /Acess/SBin/login
 $1 ./AcessKernel --rootapp /Acess/Apps/AxWin/3.0/AxWinWM
index 9e8ce35..1197604 100644 (file)
@@ -15,7 +15,7 @@ KERNEL_SRC = ../../KernelLand/Kernel/
 LDACESS_SRC = ../../Usermode/Libraries/ld-acess.so_src/\r
 \r
 # - Kernel objects (from KernelLand/Kernel)\r
-KERNEL_OBJ := logging.o adt.o lib.o debug.o messages.o drvutil_disk.o drvutil_video.o\r
+KERNEL_OBJ := logging.o adt.o lib.o debug.o messages.o drvutil_disk.o drvutil_video.o memfs_helpers.o\r
 KERNEL_OBJ += mutex.o semaphore.o rwlock.o workqueue.o events.o\r
 #KERNEL_OBJ += libc.o\r
 KERNEL_OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/io.o vfs/dir.o\r
@@ -30,6 +30,7 @@ N_OBJ := main.o net_wrap.o
 # - Local objects (use the kernel includes)\r
 OBJ := helpers.o threads.o threads_glue.o server.o syscalls.o time.o\r
 OBJ += video.o keyboard.o mouse.o nativefs.o vfs_handle.o ui_sdl.o\r
+#OBJ += shm.o\r
 OBJ += net.o syscall_getpath.o\r
 \r
 BUILDINFO_OBJ := obj-$(PLATFORM)/buildinfo.o\r
@@ -46,6 +47,7 @@ KCPPFLAGS = -I include/ -I $(KERNEL_SRC)include/ -I$(LDACESS_SRC)include_exp/ -D
 CFLAGS += -Wall -g -std=gnu99\r
 CPPFLAGS += $(shell sdl-config --cflags) -I /usr/include/\r
 LDFLAGS += $(shell sdl-config --libs) -g -Wl,--defsym,__buildnum=$(BUILD_NUM)\r
+LDFLAGS += -Wl,-Map,obj-$(PLATFORM)/Map.txt\r
 \r
 ifeq ($(PLATFORM),win)\r
        BIN := ../AcessKernel.exe\r
index ab27de1..868a056 100644 (file)
@@ -28,6 +28,7 @@ typedef intptr_t      tPAddr;
 
 typedef        int     BOOL;
 
+extern void    exit(int status) __attribute__((noreturn));
 #define HALT_CPU()     exit(1)
 
 #include <stddef.h>
index ead4f33..4f5de23 100644 (file)
@@ -13,6 +13,7 @@
 #endif
 #include <unistd.h>
 #include <string.h>
+#include <stdbool.h>
 #include "../../KernelLand/Kernel/include/logdebug.h"
 
 #define VALGRIND_CLIENT        0
@@ -115,7 +116,7 @@ int main(int argc, char *argv[])
        VFS_MkDir("/Acess");    
        VFS_Mount(gsAcessDir, "/Acess", "nativefs", "");
 
-       Debug_SetKTerminal("/Devices/pts/vt7c");
+       Debug_SetKTerminal("/Devices/pts/vt7");
        
        // Start syscall server
        SyscallServer();
index 730eda0..33a5cf9 100644 (file)
@@ -8,6 +8,7 @@
 #define DEBUG  1
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdbool.h>
 #include "../../KernelLand/Kernel/include/logdebug.h"
 #include "net_wrap.h"
 #include <string.h>
index f3826db..4dd964c 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <SDL/SDL.h>
 #ifdef __WIN32__
@@ -227,6 +228,13 @@ int SyscallServer(void)
        server.sin_port = htons(SERVER_PORT);
        server.sin_addr.s_addr = htonl(INADDR_ANY);
        
+       #if USE_TCP
+       {
+               int val = 1;
+               setsockopt(gSocket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
+       }
+       #endif
+       
        // Bind
        if( bind(gSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1 )
        {
index 86b8a89..74d85fc 100644 (file)
@@ -199,9 +199,10 @@ int Threads_SetGID(tGID NewGID)
 }
 
 int *Threads_GetErrno(void) { return &gpCurrentThread->_errno; }
-char **Threads_GetCWD(void) { return &gpCurrentThread->Process->CWD; }
-char **Threads_GetChroot(void) { return &gpCurrentThread->Process->Chroot; }
-int *Threads_GetMaxFD(void) { return &gpCurrentThread->Process->MaxFD; };
+static tProcess *proc(tProcess *Proc) { return Proc ? Proc : gpCurrentThread->Process; }
+char **Threads_GetCWD   (tProcess *Proc) { return &proc(Proc)->CWD; }
+char **Threads_GetChroot(tProcess *Proc) { return &proc(Proc)->Chroot; }
+int *Threads_GetMaxFD   (tProcess *Proc) { return &proc(Proc)->MaxFD; };
 
 tTID Threads_WaitTID(int TID, int *Status)
 {
index fa83980..7c13780 100644 (file)
@@ -20,6 +20,7 @@ typedef void  **tShortSpinlock;
 #include <pthread.h>
 
 #define NORETURN       __attribute__((noreturn))
+#include <stdbool.h>
 #include <logdebug.h>  // Kernel land, but uses standards
 #include <errno.h>
 
index 6c3992f..93b6a9d 100644 (file)
@@ -79,7 +79,7 @@ void VFS_CloneHandleList(int PID)
        
        ent = VFS_int_GetUserHandles(PID, 1);
        
-       maxhandles = *Threads_GetMaxFD();
+       maxhandles = *Threads_GetMaxFD(NULL);
        memcpy(ent->Handles, cur->Handles, maxhandles*sizeof(tVFS_Handle));
        
        // Reference all
@@ -105,7 +105,7 @@ void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[])
 
        LOG("Copying %i FDs from %i", nFD, PID);
 
-       maxhandles = *Threads_GetMaxFD();
+       maxhandles = *Threads_GetMaxFD(NULL);
        if( nFD > maxhandles )
                nFD = maxhandles;
        for( int i = 0; i < nFD; i ++ )
@@ -156,7 +156,7 @@ tVFS_Handle *VFS_GetHandle(int FD)
        else
        {
                 int    pid = Threads_GetPID();
-                int    maxhandles = *Threads_GetMaxFD();
+                int    maxhandles = *Threads_GetMaxFD(NULL);
                
                tUserHandles *ent = VFS_int_GetUserHandles(pid, 0);
                if(!ent) {
@@ -193,7 +193,7 @@ int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode)
        else {
                tUserHandles    *ent;
                 int    pid = Threads_GetPID();
-                int    maxhandles = *Threads_GetMaxFD();
+                int    maxhandles = *Threads_GetMaxFD(NULL);
                
                ent = VFS_int_GetUserHandles(pid, 0);
                if(!ent) {
@@ -219,7 +219,7 @@ int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
        if(bIsUser)
        {
                tUserHandles    *ent;
-                int    maxhandles = *Threads_GetMaxFD();
+                int    maxhandles = *Threads_GetMaxFD(NULL);
                // Find the PID's handle list
                ent = VFS_int_GetUserHandles(Threads_GetPID(), 1);
                // Get a handle
@@ -254,7 +254,7 @@ void VFS_ClearHandles(int PID)
        tUserHandles *ent = VFS_int_GetUserHandles(PID, 0);
        if( !ent )      return;
        // Get a handle
-        int    maxhandles = *Threads_GetMaxFD();
+        int    maxhandles = *Threads_GetMaxFD(NULL);
        for( int i = 0; i < maxhandles; i ++ )
        {
                if(ent->Handles[i].Node)        continue;
index b1b65b0..d78f6da 100644 (file)
@@ -30,7 +30,9 @@ tVFS_NodeType gVideo_NodeType = {
 };
 tDevFS_Driver  gVideo_DriverStruct = {
        NULL, "NativeVideo",
-       {.Type = &gVideo_NodeType}
+       {
+               .Type = &gVideo_NodeType
+       }
 };
  int   giVideo_DriverID;
  int   giVideo_CurrentFormat;
@@ -255,6 +257,8 @@ int Video_IOCtl(tVFS_Node *Node, int ID, void *Data)
        // Video mode control
        // - We cheat, and only have one mode
        case VIDEO_IOCTL_GETSETMODE:
+               // - Abuse GETSETMODE to update size
+               Node->Size = giUI_Pitch * giUI_Height;
                return 0;
        case VIDEO_IOCTL_FINDMODE:
        case VIDEO_IOCTL_MODEINFO:
index 59be829..738c6e8 100644 (file)
@@ -6,6 +6,7 @@
  * - Provides binary loading and type abstraction
  */
 #define DEBUG  0
+#define _POSIX_C_SOURCE        200809L // needed for strdup
 #include "common.h"
 #include <stdint.h>
 #include <stdio.h>
@@ -228,7 +229,7 @@ void Binary_SetReadyToUse(void *Base)
        }
 }
 
-int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value, size_t *Size)
+int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value, size_t *Size, void *IgnoreBase)
 {
         int    i;
        tBinary *bin;
@@ -251,6 +252,7 @@ int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value, size_t *Size)
        // Search list of loaded binaries
        for(bin = gLoadedBinaries; bin; bin = bin->Next)
        {
+               if( bin->Base == IgnoreBase )   continue ;
                if( !bin->Ready )       continue;
                //printf(" Binary_GetSymbol: bin = %p{%p, %s}\n", bin, bin->Base, bin->Path);
                if( bin->Format->GetSymbol(bin->Base, (char*)SymbolName, Value, Size) )
index 9f67e9c..0bdc40f 100644 (file)
@@ -8,16 +8,16 @@
 #include <stdint.h>
 #include <string.h>
 
-extern int     Binary_GetSymbol(const char *SymbolName, uintptr_t *Value, size_t *Size);
+extern int     Binary_GetSymbol(const char *SymbolName, uintptr_t *Value, size_t *Size, void *IgnoreBase);
 extern void    *Binary_LoadLibrary(const char *Path);
 extern void    *Binary_Load(const char *Path, uintptr_t *EntryPoint);
 extern void    Binary_SetReadyToUse(void *Base);
 
 // HACKS - So this can share the usermode elf.c
-static inline int GetSymbol(const char *sym, void **val, size_t *sz)
+static inline int GetSymbol(const char *sym, void **val, size_t *sz, void *IgnoreBase)
 {
        uintptr_t rv;
-       if( !Binary_GetSymbol(sym, &rv, sz) )
+       if( !Binary_GetSymbol(sym, &rv, sz, IgnoreBase) )
                return 0;
        *val = (void*)rv;
        return 1;
index 19a8c13..76d9251 100644 (file)
@@ -64,17 +64,10 @@ void *Elf_Load(int FD)
 \r
 void *Elf32Load(int FD, Elf32_Ehdr *hdr)\r
 {\r
-       Elf32_Phdr      *phtab;\r
-        int    i;\r
-        int    iPageCount;\r
-       uint32_t        max, base;\r
-       uint32_t        addr;\r
-       uint32_t        baseDiff = 0;\r
-       \r
        ENTER("iFD", FD);\r
        \r
        // Check for a program header\r
-       if(hdr->phoff == 0) {\r
+       if(hdr->e_phoff == 0) {\r
                #if DEBUG_WARN\r
                Warning("ELF File does not contain a program header\n");\r
                #endif\r
@@ -83,25 +76,25 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
        }\r
        \r
        // Read Program Header Table\r
-       phtab = malloc( sizeof(Elf32_Phdr) * hdr->phentcount );\r
+       Elf32_Phdr* phtab = malloc( sizeof(Elf32_Phdr) * hdr->e_phnum );\r
        if( !phtab ) {\r
                LEAVE('n');\r
                return NULL;\r
        }\r
-       LOG("hdr.phoff = 0x%08x\n", hdr->phoff);\r
-       acess__SysSeek(FD, hdr->phoff, ACESS_SEEK_SET);\r
-       acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);\r
+       LOG("hdr.e_phoff = 0x%08x\n", hdr->e_phoff);\r
+       acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
+       acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->e_phnum);\r
        \r
        // Count Pages\r
-       iPageCount = 0;\r
-       LOG("hdr.phentcount = %i\n", hdr->phentcount);\r
-       for( i = 0; i < hdr->phentcount; i++ )\r
+       unsigned int iPageCount = 0;\r
+       LOG("hdr.e_phnum = %i\n", hdr->e_phnum);\r
+       for( unsigned int i = 0; i < hdr->e_phnum; i++ )\r
        {\r
                // Ignore Non-LOAD types\r
-               if(phtab[i].Type != PT_LOAD)\r
+               if(phtab[i].p_type != PT_LOAD)\r
                        continue;\r
-               iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12;\r
-               LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize);\r
+               iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;\r
+               LOG("phtab[%i] = {p_vaddr:0x%x, p_memsz:0x%x}\n", i, phtab[i].p_vaddr, phtab[i].MemSize);\r
        }\r
        \r
        LOG("iPageCount = %i\n", iPageCount);\r
@@ -115,20 +108,21 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
        //ret->Interpreter = NULL;\r
 \r
        // Prescan for base and size\r
-       max = 0;\r
-       base = 0xFFFFFFFF;\r
-       for( i = 0; i < hdr->phentcount; i ++)\r
+       uint32_t        max = 0;\r
+       uint32_t        base = UINT32_MAX;\r
+       for( unsigned int i = 0; i < hdr->e_phnum; i ++)\r
        {\r
-               if( phtab[i].Type != PT_LOAD )\r
+               if( phtab[i].p_type != PT_LOAD )\r
                        continue;\r
-               if( phtab[i].VAddr < base )\r
-                       base = phtab[i].VAddr;\r
-               if( phtab[i].VAddr + phtab[i].MemSize > max )\r
-                       max = phtab[i].VAddr + phtab[i].MemSize;\r
+               if( phtab[i].p_vaddr < base )\r
+                       base = phtab[i].p_vaddr;\r
+               if( phtab[i].p_vaddr + phtab[i].p_memsz > max )\r
+                       max = phtab[i].p_vaddr + phtab[i].p_memsz;\r
        }\r
 \r
        LOG("base = %08x, max = %08x\n", base, max);\r
 \r
+       uint32_t        baseDiff = 0;\r
        if( base == 0 ) {\r
                // Find a nice space (47 address bits allowed)\r
                base = FindFreeRange( max, 47 );\r
@@ -138,39 +132,39 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
        }\r
        \r
        // Load Pages\r
-       for( i = 0; i < hdr->phentcount; i++ )\r
+       for( unsigned int i = 0; i < hdr->e_phnum; i++ )\r
        {\r
                // Get Interpreter Name\r
-               if( phtab[i].Type == PT_INTERP )\r
+               if( phtab[i].p_type == PT_INTERP )\r
                {\r
                        char *tmp;\r
                        //if(ret->Interpreter)  continue;\r
-                       tmp = malloc(phtab[i].FileSize);\r
-                       acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
-                       acess__SysRead(FD, tmp, phtab[i].FileSize);\r
+                       tmp = malloc(phtab[i].p_filesz);\r
+                       acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+                       acess__SysRead(FD, tmp, phtab[i].p_filesz);\r
                        //ret->Interpreter = Binary_RegInterp(tmp);\r
                        LOG("Interpreter '%s'\n", tmp);\r
                        free(tmp);\r
                        continue;\r
                }\r
                // Ignore non-LOAD types\r
-               if(phtab[i].Type != PT_LOAD)    continue;\r
+               if(phtab[i].p_type != PT_LOAD)  continue;\r
                \r
-               LOG("phtab[%i] = PT_LOAD {Adj VAddr:0x%x, Offset:0x%x, FileSize:0x%x, MemSize:0x%x}\n",\r
-                       i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize, phtab[i].MemSize);\r
+               LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%x, p_offset:0x%x, p_filesz:0x%x, p_memsz:0x%x}\n",\r
+                       i, phtab[i].p_vaddr+baseDiff, phtab[i].p_offset, phtab[i].p_filesz, phtab[i].p_memsz);\r
                \r
-               addr = phtab[i].VAddr + baseDiff;\r
+               uint64_t addr = phtab[i].p_vaddr + baseDiff;\r
 \r
-               if( AllocateMemory( addr, phtab[i].MemSize ) ) {\r
-                       fprintf(stderr, "Elf_Load: Unable to map memory at %x (0x%x bytes)\n",\r
-                               addr, phtab[i].MemSize);\r
+               if( AllocateMemory( addr, phtab[i].p_memsz ) ) {\r
+                       fprintf(stderr, "Elf_Load: Unable to map memory at 0x%"PRIx64" (0x%x bytes)\n",\r
+                               addr, phtab[i].p_memsz);\r
                        free( phtab );\r
                        return NULL;\r
                }\r
                \r
-               acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
-               acess__SysRead(FD, PTRMK(void, addr), phtab[i].FileSize);\r
-               memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );\r
+               acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+               acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz);\r
+               memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );\r
        }\r
        \r
        // Clean Up\r
@@ -182,13 +176,6 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
 \r
 void *Elf64Load(int FD, Elf64_Ehdr *hdr)\r
 {\r
-       Elf64_Phdr      *phtab;\r
-        int    i;\r
-        int    iPageCount;\r
-       uint64_t        max, base;\r
-       uint64_t        addr;\r
-       uint64_t        baseDiff = 0;\r
-       \r
        ENTER("iFD", FD);\r
        \r
        if( sizeof(void*) == 4) {\r
@@ -205,25 +192,25 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr)
        }\r
        \r
        // Read Program Header Table\r
-       phtab = malloc( sizeof(Elf64_Phdr) * hdr->e_phnum );\r
+       Elf64_Phdr* phtab = malloc( sizeof(Elf64_Phdr) * hdr->e_phnum );\r
        if( !phtab ) {\r
                LEAVE('n');\r
                return NULL;\r
        }\r
-       LOG("hdr.phoff = 0x%08llx\n", (long long)hdr->e_phoff);\r
+       LOG("hdr.e_phoff = 0x%08llx\n", (long long)hdr->e_phoff);\r
        acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
        acess__SysRead(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);\r
        \r
        // Count Pages\r
-       iPageCount = 0;\r
-       LOG("hdr.phentcount = %i\n", hdr->e_phnum);\r
-       for( i = 0; i < hdr->e_phnum; i++ )\r
+       unsigned int iPageCount = 0;\r
+       LOG("hdr.e_phnum = %i\n", hdr->e_phnum);\r
+       for( unsigned int i = 0; i < hdr->e_phnum; i++ )\r
        {\r
                // Ignore Non-LOAD types\r
                if(phtab[i].p_type != PT_LOAD)\r
                        continue;\r
                iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12;\r
-               LOG("phtab[%i] = {VAddr:0x%llx, MemSize:0x%llx}\n",\r
+               LOG("phtab[%i] = {p_vaddr:0x%llx, p_memsz:0x%llx}\n",\r
                        i, (long long)phtab[i].p_vaddr, (long long)phtab[i].p_memsz);\r
        }\r
        \r
@@ -238,9 +225,9 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr)
        //ret->Interpreter = NULL;\r
 \r
        // Prescan for base and size\r
-       max = 0;\r
-       base = 0xFFFFFFFF;\r
-       for( i = 0; i < hdr->e_phnum; i ++)\r
+       uint64_t max = 0;\r
+       uint64_t base = UINT64_MAX;\r
+       for( unsigned int i = 0; i < hdr->e_phnum; i ++)\r
        {\r
                if( phtab[i].p_type != PT_LOAD )\r
                        continue;\r
@@ -252,16 +239,18 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr)
 \r
        LOG("base = %08lx, max = %08lx\n", base, max);\r
 \r
+       uint64_t        baseDiff = 0;\r
        if( base == 0 ) {\r
                // Find a nice space (31 address bits allowed)\r
                base = FindFreeRange( max, 31 );\r
                LOG("new base = %08lx\n", base);\r
-               if( base == 0 ) return NULL;\r
+               if( base == 0 )\r
+                       goto _err;\r
                baseDiff = base;\r
        }\r
        \r
        // Load Pages\r
-       for( i = 0; i < hdr->e_phnum; i++ )\r
+       for( unsigned int i = 0; i < hdr->e_phnum; i++ )\r
        {\r
                // Get Interpreter Name\r
                if( phtab[i].p_type == PT_INTERP )\r
@@ -280,19 +269,18 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr)
                // Ignore non-LOAD types\r
                if(phtab[i].p_type != PT_LOAD)  continue;\r
                \r
-               LOG("phtab[%i] = PT_LOAD {Adj VAddr:0x%llx, Offset:0x%llx, FileSize:0x%llx, MemSize:0x%llx}\n",\r
+               LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%llx, p_offset:0x%llx, p_filesz:0x%llx, p_memsz:0x%llx}\n",\r
                        i,\r
                        (long long)phtab[i].p_vaddr+baseDiff, (long long)phtab[i].p_offset,\r
                        (long long)phtab[i].p_filesz, (long long)phtab[i].p_memsz\r
                        );\r
                \r
-               addr = phtab[i].p_vaddr + baseDiff;\r
+               uint64_t addr = phtab[i].p_vaddr + baseDiff;\r
 \r
                if( AllocateMemory( addr, phtab[i].p_memsz ) ) {\r
                        fprintf(stderr, "Elf_Load: Unable to map memory at %"PRIx64" (0x%"PRIx64" bytes)\n",\r
                                (uint64_t)addr, (uint64_t)phtab[i].p_memsz);\r
-                       free( phtab );\r
-                       return NULL;\r
+                       goto _err;\r
                }\r
                \r
                acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
@@ -305,5 +293,9 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr)
        // Return\r
        LEAVE('p', base);\r
        return PTRMK(void, base);\r
+_err:\r
+       free(phtab);\r
+       LEAVE('n');\r
+       return NULL;\r
 }\r
 \r
index a898b5a..8064bb8 100644 (file)
@@ -53,7 +53,13 @@ int acess__SysOpen(const char *Path, unsigned int Flags)
 {
        if( strncmp(Path, "$$$$", 4) == 0 )
        {
-               return native_open(Path, Flags) | NATIVE_FILE_MASK;
+               return native_open(Path+4, Flags) | NATIVE_FILE_MASK;
+       }
+       if( strncmp(Path, "/Devices/shm/", 13) == 0 )
+       {
+               const char* tag = Path + 13;
+               Warning("TODO: Handle open SHM \"%s\"", tag);
+               return native_shm(tag, Flags) | NATIVE_FILE_MASK;
        }
        SYSTRACE("open(\"%s\", 0x%x)", Path, Flags);
        return _Syscall(SYS_OPEN, ">s >i", Path, Flags);
@@ -95,6 +101,10 @@ size_t acess__SysWrite(int FD, const void *Src, size_t Bytes) {
        SYSTRACE("_SysWrite(0x%x, 0x%x, %p\"%.*s\")", FD, Bytes, Src, Bytes, (char*)Src);
        return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src);
 }
+uint64_t acess__SysTruncate(int fd, uint64_t size) {
+       TODO();
+       return 0;
+}
 
 int acess__SysSeek(int FD, int64_t Ofs, int Dir)
 {
@@ -156,6 +166,26 @@ int acess__SysUnlink(const char *pathname)
        TODO();
        return 0;
 }
+void* acess__SysMMap(void *addr, size_t length, unsigned int _flags, int fd, uint64_t offset)
+{
+       TODO();
+       return NULL;
+}
+int acess__SysMUnMap(void *addr, size_t length)
+{
+       TODO();
+       return 0;
+}
+uint64_t acess__SysMarshalFD(int FD)
+{
+       TODO();
+       return 0;
+}
+int acess__SysUnMarshalFD(uint64_t Handle)
+{
+       TODO();
+       return -1;
+}
 
 int acess__SysOpenChild(int fd, char *name, int flags) {
        SYSTRACE("_SysOpenChild(0x%x, '%s', 0x%x)", fd, name, flags);
@@ -224,10 +254,7 @@ int acess__SysLoadModule(const char *Path)
 // --- Timekeeping ---
 int64_t acess__SysTimestamp(void)
 {
-       // TODO: Better impl
-       TODO();
-//     return now()*1000;
-       return 0;
+       return native_timestamp();
 }
 
 // --- Memory Management ---
@@ -418,19 +445,69 @@ int acess__SysWaitEvent(int Mask)
 }
 
 // --- Logging
+static void int_dbgheader(void )
+{
+       printf("[_SysDebug %i] ", giSyscall_ClientID);
+}
 void acess__SysDebug(const char *Format, ...)
 {
        va_list args;
        
        va_start(args, Format);
-       
-       printf("[_SysDebug %i] ", giSyscall_ClientID);
+       int_dbgheader();        
        vprintf(Format, args);
        printf("\n");
        
        va_end(args);
 }
 
+void acess__SysDebugHex(const char *tag, const void *data, size_t size)
+{
+       int_dbgheader();        
+       printf("%s (Hexdump of %p+%zi)\r\n", tag, data, size);
+
+       #define CH(n)   ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
+
+       const uint8_t   *cdat = data;
+       unsigned int    pos = 0;
+
+       while(size >= 16)
+       {
+               int_dbgheader();
+               printf("%04x:"
+                       " %02x %02x %02x %02x %02x %02x %02x %02x "
+                       " %02x %02x %02x %02x %02x %02x %02x %02x "
+                       " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
+                       pos,
+                       cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
+                       cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
+                       CH(0),  CH(1),  CH(2),  CH(3),  CH(4),  CH(5),  CH(6),  CH(7),
+                       CH(8),  CH(9),  CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
+                       );
+               size -= 16;
+               cdat += 16;
+               pos += 16;
+       }
+
+       {
+               int_dbgheader();
+               printf("%04x: ", pos);
+               for(int i = 0; i < size; i ++)
+                       printf("%02x ", cdat[i]);
+               for(int i = size; i < 16; i ++)
+                       printf("   ");
+               printf(" ");
+               for(int i = 0; i < size; i ++)
+               {
+                       if( i == 8 )
+                               printf(" ");
+                       printf("%c", CH(i));
+               }
+       
+               printf("\n");
+       }
+}
+
 void acess__exit(int Status)
 {
        DEBUG("_exit(%i)", Status);
@@ -489,6 +566,9 @@ const tSym  caBuiltinSymbols[] = {
        DEFSYM(_SysAllocate),
        DEFSYM(_SysSetMemFlags),
        DEFSYM(_SysDebug),
+       {"_ZN4_sys5debugEPKcz", &acess__SysDebug},
+       DEFSYM(_SysDebugHex),
+       {"_ZN4_sys7hexdumpEPKcPKvj", &acess__SysDebugHex},
        DEFSYM(_SysSetFaultHandler),
        DEFSYM(_SysWaitEvent),
        
index e8f2e4c..94987d0 100644 (file)
@@ -17,6 +17,7 @@ extern uint64_t       _Syscall(int SyscallID, const char *ArgTypes, ...);
 extern int     acess__errno;
 
 extern int     native_open(const char *Path, int Flags);
+extern int     native_shm(const char *Tag, int Flags);
 extern void    native_close(int FD);
 extern size_t  native_read(int FD, void *Dest, size_t Bytes);
 extern size_t  native_write(int FD, const void *Src, size_t Bytes);
@@ -26,6 +27,8 @@ extern uint64_t       native_tell(int FD);
 extern int     native_execve(const char *filename, const char *const argv[], const char *const envp[]);
 extern int     native_spawn(const char *filename, const char *const argv[], const char *const envp[]);
 
+extern int64_t native_timestamp(void);
+
 // Syscalls used by the linker
 extern int     acess__SysOpen(const char *Path, unsigned int Flags);
 extern void    acess__SysClose(int FD);
index c8166af..99238a5 100644 (file)
@@ -1,5 +1,6 @@
 /*
  */
+#define _GNU_SOURCE    // needed for MAP_ANONYMOUS to be avaliable
 #include "common.h"
 #include <stdio.h>
 #include <stdlib.h>
index fdf5748..690c7f7 100644 (file)
@@ -25,6 +25,7 @@
 # include <unistd.h>
 # include <sys/socket.h>
 # include <netinet/in.h>
+# include <sys/select.h>
 #endif
 #include "request.h"
 #include "../syscalls.h"
@@ -228,12 +229,12 @@ int SendRequest(tRequestHeader *Request, int RequestSize, int ResponseSize)
        // Send it off
        SendData(Request, RequestSize);
 
-       if( Request->CallID == SYS_EXIT )       return 0;
-
        // Wait for a response (no timeout)
        ReadData(Request, sizeof(*Request), 0);
+       
+       size_t  recvbytes = sizeof(*Request);
        // TODO: Sanity
-       size_t  recvbytes = sizeof(*Request), expbytes = Request->MessageLength;
+       size_t  expbytes = Request->MessageLength;
        char    *ptr = (void*)Request->Params;
        while( recvbytes < expbytes )
        {
index 60b7d95..3341a95 100644 (file)
@@ -13,6 +13,7 @@
 # include <spawn.h>    // posix_spawn
 #endif
 #include "request.h"
+#include <sys/time.h>
 
 #define assert(cnd) do{ \
        if( !(cnd) ) { \
@@ -171,7 +172,6 @@ uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
        tRequestHeader  *req;
        void    *dataPtr;
        uint64_t        retValue;
-        int    i;
        
        // DEBUG!
 //     printf("&tRequestHeader->Params = %i\n", offsetof(tRequestHeader, Params));
@@ -244,8 +244,11 @@ uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
                exit(127);
        }
        
+       if( !(req->NParams >= 2) ) {
+               fprintf(stderr, "syscalls.c: Too few return params (%i)", req->NParams);
+               exit(127);
+       }
        dataPtr = (void*)&req->Params[req->NParams];
-       assert(req->NParams >= 2);
        // return
        assert(req->Params[0].Type == ARG_TYPE_INT64);
        assert(req->Params[0].Length == sizeof(uint64_t));
@@ -264,7 +267,7 @@ uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
                exit(127);
        }
        retCount = 0;
-       for( i = 2; i < req->NParams; i ++ )
+       for( unsigned int i = 2; i < req->NParams; i ++ )
        {
                #if 0
                 int     j;
@@ -288,18 +291,40 @@ uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
        return retValue;
 }
 
+int native_int_getfd(void)
+{
+       for(int ret = 0; ret < MAX_FPS; ret ++ )
+               if( gaSyscall_LocalFPs[ret] == NULL )
+                       return ret;
+       return -1;
+}
 
 int native_open(const char *Path, int Flags)
 {
-       int     ret;
-       for(ret = 0; ret < MAX_FPS && gaSyscall_LocalFPs[ret]; ret ++ ) ;
-       if(ret == MAX_FPS)      return -1;
+       int     ret = native_int_getfd();
+       if(ret == -1)   return -1;
        // TODO: Handle directories
-       gaSyscall_LocalFPs[ret] = fopen(&Path[4], "r+");
+       gaSyscall_LocalFPs[ret] = fopen(Path, "r+");
        if(!gaSyscall_LocalFPs[ret])    return -1;
        return ret;
 }
 
+int native_shm(const char *Tag, int Flags)
+{
+       // int ret = native_int_getfd();
+       //if(ret == -1) return -1;
+       //if( strcmp(Tag, "anon") == 0 )
+       //      path = "/AcessNative/anon/RAND";
+       //      FD = shm_open(path, O_RDWD);
+       //shm_unlink(path);
+       //else
+       //      path = "/Acessnative/named/<TAG>";
+       // int FD = shm_open(path, O_RDWD);
+       //shm_unlink(path);
+       //gaSyscall_LocalFPs[ret] = 
+       return -1;
+}
+
 void native_close(int FD)
 {
        fclose( gaSyscall_LocalFPs[FD] );
@@ -357,3 +382,10 @@ int native_spawn(const char *filename, const char *const argv[], const char *con
        
        return rv;
 }
+
+int64_t native_timestamp(void)
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return tv.tv_sec*1000 + tv.tv_usec / 1000;
+}
index 9278311..2a0f0c4 100644 (file)
@@ -20,7 +20,7 @@ $(warning $(BINLINK))
 
 CFLAGS   += -Wall
 CFLAGS   += -Werror
-CFLAGS   += -g -shared -fPIC
+CFLAGS   += -g -shared -fPIC -std=c99
 CPPFLAGS += -DARCHDIR_is_x86_64=1
 LDFLAGS  += -g -shared -Wl,--no-undefined -lc
 
index 2f960c4..ad5aac4 100644 (file)
@@ -10,6 +10,9 @@ int *libc_geterrno(void)
        return &acess__errno;
 }
 
+void _ZN4_sys5debugEPKcz(const char *fmt, ...) __attribute__((alias("acess__SysDebug")));
+void _ZN4_sys7hexdumpEPKcPKvj(const char *tag, const void *ptr, size_t size) __attribute__((alias("acess__SysDebugHex")));
+
 #undef acess__SysSpawn
 
 int acess__SysSpawn(const char *binary, const char **argv, const char **envp, int nfd, int fds[], struct s_sys_spawninfo *info)
index 74d9d3c..b5f066f 100644 (file)
@@ -10,6 +10,8 @@
 #include <stdint.h>
 #include "../ld-acess_src/exports.h"
 
+extern int     gbSyscallDebugEnabled;
+
 #ifdef __WINDOWS__
 int DllMain(void)
 {
@@ -40,10 +42,13 @@ int libacessnative_init(int argc, char *argv[], char **envp)
 {
        Request_Preinit();
        
+       //gbSyscallDebugEnabled = 1;
+       
        const char *preopens = getenv_p(envp, ENV_VAR_PREOPENS);
        printf("preopens = %s\n", preopens);
        if( preopens )
        {
+                int    exp_fd = 0;
                while( *preopens )
                {
                        const char *splitter = strchr(preopens, ':');
@@ -59,8 +64,16 @@ int libacessnative_init(int argc, char *argv[], char **envp)
                        path[len] = 0;
                        int fd = acess__SysOpen(path, 6);       // WRITE,READ,no EXEC
                        if( fd == -1 ) {
-                               fprintf(stderr, "Unable to preopen '%s'\n", path);
+                               fprintf(stderr, "Unable to preopen '%s' errno=%i\n", path, acess__errno);
+                               exit(1);
+                       }
+                       if( fd != exp_fd ) {
+                               //  Oh... this is bad
+                               fprintf(stderr, "Pre-opening '%s' resulted in an incorrect FD (expected %i, got %i)",
+                                       path, exp_fd, fd);
+                               exit(1);
                        }
+                       exp_fd += 1;
                        
                        if( !splitter )
                                break;
@@ -77,7 +90,7 @@ int libacessnative_init(int argc, char *argv[], char **envp)
 int acessnative_spawn(const char *Binary, int SyscallID, const char * const * argv, const char * const * envp)
 {
         int    envc = 0;
-       while( envp[envc++] )
+       while( envp && envp[envc++] )
                envc ++;
 
        // Set environment variables for libacess-native
@@ -89,7 +102,7 @@ int acessnative_spawn(const char *Binary, int SyscallID, const char * const * ar
        
        const char *newenv[envc+2+1];
         int    i = 0;
-       for( ; envp[i]; i ++ )
+       for( ; envp && envp[i]; i ++ )
        {
                const char      *ev = envp[i];
                if( strncmp(ev, ENV_VAR_KEY"=", sizeof(ENV_VAR_KEY"=")) == 0 ) {
@@ -100,7 +113,7 @@ int acessnative_spawn(const char *Binary, int SyscallID, const char * const * ar
        }
        if( !bKeyHit )
                newenv[i++] = keystr;
-       newenv[i++] = "LD_LIBRARY_PATH=Libs/";  // HACK
+       newenv[i++] = getenv("LD_LIBRARY_PATH") - (sizeof("LD_LIBRARY_PATH=")-1);       // VERY hacky
        newenv[i] = NULL;
        
        // TODO: Detect native_spawn failing
@@ -127,17 +140,3 @@ void Warning(const char *format, ...)
        printf("\n");
 }
 
-void __libc_csu_fini()
-{
-}
-
-void __libc_csu_init()
-{
-}
-
-void __stack_chk_fail(void)
-{
-       fprintf(stderr, "__stack_chk_fail");
-       exit(1);
-}
-
index d2f0a0f..3180234 100644 (file)
@@ -1,12 +1,9 @@
 
+TRIPLET = arm-pc-acess2
 ARM_CPUNAME = gerneric-armv7
-CC = arm-eabi-gcc -mcpu=$(ARM_CPUNAME)
-AS = arm-eabi-gcc -mcpu=$(ARM_CPUNAME) -c
-LD = arm-eabi-ld
-OBJDUMP = arm-eabi-objdump
+#AS = $(TRIPLET)-gcc -mcpu=$(ARM_CPUNAME) -c
 DISASM := $(OBJDUMP) -d -S
 ARCHDIR = armv7
-STRIP = arm-eabi-strip
 
 ASSUFFIX = S
 
index 6559146..271059c 100644 (file)
@@ -2,15 +2,8 @@
 # Acess2 Build Configuration
 #
 
-CC = i586-elf-gcc
-CXX = i586-elf-g++
-#CC = clang -m32
-LD = i586-elf-ld
-#CC = gcc
-#LD = ld
+TRIPLET = i686-pc-acess2
 AS = nasm
-#OBJDUMP = i586-elf-objdump
-OBJDUMP = objdump
 RM = @rm -f
 STRIP = strip
 
index cc252bc..20dcbb2 100644 (file)
@@ -1,10 +1,6 @@
 
-#PREFIX := x86_64-pc-elf
-PREFIX := x86_64-none-elf
-
-CC := $(PREFIX)-gcc
-LD := $(PREFIX)-ld
-DISASM = $(PREFIX)-objdump -d -M x86-64 -S
+TRIPLET = x86_64-pc-acess2
+AS = nasm
 
 KERNEL_CFLAGS := -mcmodel=kernel -nostdlib -mno-red-zone -Wall -mno-sse
 DYNMOD_CFLAGS := -mcmodel=small -fPIC -mno-red-zone -mno-sse
index 70b1978..c7e67c3 100644 (file)
@@ -24,9 +24,9 @@ endif
 
 $(BDIR)/Makefile: _patch $(CONFIGSCRIPT) ../common_automake.mk Makefile 
        mkdir -p $(BDIR)
-       cd $(BDIR) && $(CONFIGURE_ENV) PATH=$(PATH) $(CONFIGURE_LINE)
+       cd $(BDIR) && $(CONFIGURE_ENV) PATH="$(PATH)" $(CONFIGURE_LINE)
 
 _build: $(BDIR)/Makefile
-       PATH=$(PATH) make $(BTARGETS) -C $(BDIR)
-       PATH=$(PATH) make DESTDIR=$(OUTDIR) $(ITARGETS) -C $(BDIR)
+       PATH="$(PATH)" make $(BTARGETS) -C $(BDIR)
+       PATH="$(PATH)" make DESTDIR=$(OUTDIR) $(ITARGETS) -C $(BDIR)
 
index 3d7913b..9db8f0d 100644 (file)
@@ -4,9 +4,11 @@
 -include ../../Makefile.cfg
 
 ifeq ($(ARCH),x86)
- BFD := i586
+ BFD := i686
 else ifeq ($(ARCH),x86_64)
  BFD := x86_64
+else ifeq ($(ARCH),armv7)
+ BFD := arm
 else
  $(error No BFD translation for $(ARCH) in Externals/config.mk)
 endif
index bc7a5b8..6c23a33 100644 (file)
@@ -73,7 +73,14 @@ $(DIR)/%: patches/%
 
 PATCHED_FILES := $(addprefix $(DIR)/,$(PATCHES))
 
-_patch: $(DIR) $(PATCHED_FILES) $(wildcard patches/UNIFIED.patch)
 ifneq ($(wildcard patches/UNIFIED.patch),)
+$(DIR)/_unified_applied: $(wildcard patches/UNIFIED.patch)
        cd $(DIR) && patch -p1 < ../patches/UNIFIED.patch
+       touch $@
+UNIFIED_TARGET=$(DIR)/_unified_applied
+else
+UNIFIED_TARGET=
 endif
+
+_patch: $(DIR) $(PATCHED_FILES) $(UNIFIED_TARGET)
+
index 9dde5d8..ae2df5a 100644 (file)
@@ -1,67 +1,28 @@
+#
+#
+#
+include Makefile.common.mk
 
+GCC_TARGETS := gcc
 
--include ../config.mk
+PREFIX := $(OUTDIR)
+BDIR := build-n-$(ARCH)/
+BDIR_GCC := $(BDIR)gcc
+BDIR_BINUTILS := $(BDIR)binutils
 
-GCC_ARCHIVE:=$(lastword $(sort $(wildcard gcc-*.tar.bz2)))
-GCC_DIR:=$(GCC_ARCHIVE:%.tar.bz2=%)
-BINUTILS_ARCHIVE:=$(lastword $(sort $(wildcard binutils-*.tar.bz2)))
-BINUTILS_DIR:=$(BINUTILS_ARCHIVE:%.tar.bz2=%)
+ENVVARS := PATH=$(OUTDIR)-BUILD/bin:$$PATH
 
-BINUTILS_CHANGES := config.sub bfd/config.bfd gas/configure.tgt ld/configure.tgt ld/emulparams/acess2_i386.sh ld/emulparams/acess2_amd64.sh ld/Makefile.in
-GCC_CHANGES := config.sub gcc/config.gcc gcc/config/acess2.h libgcc/config.host
-# libstdc++-v3/crossconfig.m4 config/override.m4
-
-TARGET=$(HOST)
-GCC_TARGETS := gcc target-libgcc
-# target-libstdc++-v3 
-
-PREFIX := $(OUTDIR)-BUILD
-BDIR_GCC := build-$(ARCH)/gcc
-BDIR_BINUTILS := build-$(ARCH)/binutils
-
-.PHONY: all clean binutils gcc include
-
-all: include binutils gcc
+include Makefile.rules.mk
 
 include:
        mkdir -p $(PREFIX)
-       mkdir -p $(SYSROOT)/usr
-       ln -sf $(ACESSDIR)/Usermode/include $(SYSROOT)/usr/include
-       ln -sf $(ACESSDIR)/Usermode/Output/$(ARCH)/Libs $(SYSROOT)/usr/lib
-
-gcc: $(GCC_DIR) $(PREFIX)/bin/$(TARGET)-gcc
-
-binutils: $(BINUTILS_DIR) $(PREFIX)/bin/$(TARGET)-ld
-
-clean:
-       $(RM) -rf $(BINUTILS_DIR) $(GCC_DIR) build-$(ARCH)
-
-$(BINUTILS_DIR) $(GCC_DIR): %: %.tar.bz2
-       tar -xf $<
-$(warning $(BINUTILS_DIR) $(GCC_DIR))
-
-$(GCC_DIR)/%: patches/gcc/%.patch
-       @echo [PATCH] $@
-       #@tar -xf $(GCC_ARCHIVE) $@
-       @patch $@ $<
-$(GCC_DIR)/%: patches/gcc/%
-       @echo [CP] $@
-       @cp $< $@
-
-$(BINUTILS_DIR)/%: patches/binutils/%.patch
-       @echo [PATCH] $@
-       #@tar -xf $(BINUTILS_ARCHIVE) $@
-       @patch $@ $<
-$(BINUTILS_DIR)/%: patches/binutils/%
-       @echo [CP] $@
-       @cp $< $@
 
 $(GCC_DIR)/libstdc++-v3/configure: $(GCC_DIR)/libstdc++-v3/crossconfig.m4
        cd $(GCC_DIR)/libstdc++-v3/ && autoconf
 
 $(BDIR_BINUTILS)/Makefile: $(addprefix $(BINUTILS_DIR)/,$(BINUTILS_CHANGES))
        @mkdir -p $(BDIR_BINUTILS)
-       @cd $(BDIR_BINUTILS) && ../../$(BINUTILS_DIR)/configure --target=$(TARGET) --prefix=$(PREFIX) --disable-nls "--with-sysroot=$(SYSROOT)" --enable-shared
+       @cd $(BDIR_BINUTILS) && ../../$(BINUTILS_DIR)/configure --target=$(TARGET) --prefix=$(PREFIX) --disable-nls --enable-shared --without-docdir
 
 $(PREFIX)/bin/$(TARGET)-ld: $(BDIR_BINUTILS)/Makefile
        @make -C $(BDIR_BINUTILS) all -j $(PARLEVEL)
@@ -69,10 +30,12 @@ $(PREFIX)/bin/$(TARGET)-ld: $(BDIR_BINUTILS)/Makefile
 
 $(BDIR_GCC)/Makefile: Makefile $(addprefix $(GCC_DIR)/,$(GCC_CHANGES)) $(GCC_DIR)/libstdc++-v3/configure
        @mkdir -p $(BDIR_GCC)
-       @cd $(BDIR_GCC) && PATH=$(PREFIX)/bin:$$PATH ../../$(GCC_DIR)/configure --target=$(TARGET) --prefix=$(PREFIX) --disable-nls --enable-langs=c,c++ --includedir=$(ACESSDIR)/Usermode/include "--with-sysroot=$(SYSROOT)"
+       @cd $(BDIR_GCC) && $(ENVVARS) ../../$(GCC_DIR)/configure --target=$(TARGET) --prefix=$(PREFIX) --disable-nls --enable-langs=c,c++ --includedir=$(ACESSDIR)/Usermode/include --without-docdir --enable-threads=posix
+       @echo "MAKEINFO = :" >> $(BDIR_GCC)/Makefile
 
 $(PREFIX)/bin/$(TARGET)-gcc: $(BDIR_GCC)/Makefile
-       @PATH=$(PREFIX)/bin:$$PATH make -C $(BDIR_GCC) $(GCC_TARGETS:%=all-%) -j $(PARLEVEL)
-       @PATH=$(PREFIX)/bin:$$PATH make -C $(BDIR_GCC) $(GCC_TARGETS:%=install-%)
+       @$(ENVVARS) make -C $(BDIR_GCC) $(GCC_TARGETS:%=all-%) -j $(PARLEVEL)
+       @$(ENVVARS) make -C $(BDIR_GCC)libstdc++-v3/ all-target-libsupc++ -j $(PARLEVEL)
+       @$(ENVVARS) make -C $(BDIR_GCC) $(GCC_TARGETS:%=install-%)
 
 
diff --git a/Externals/cross-compiler/Makefile.common.mk b/Externals/cross-compiler/Makefile.common.mk
new file mode 100644 (file)
index 0000000..b986044
--- /dev/null
@@ -0,0 +1,26 @@
+#
+#
+#
+-include ../config.mk
+
+GCC_ARCHIVE:=$(lastword $(sort $(wildcard gcc-*.tar.bz2)))
+GCC_DIR:=$(GCC_ARCHIVE:%.tar.bz2=%)
+BINUTILS_ARCHIVE:=$(lastword $(sort $(wildcard binutils-*.tar.bz2)))
+BINUTILS_DIR:=$(BINUTILS_ARCHIVE:%.tar.bz2=%)
+
+ifeq ($(GCC_ARCHIVE),)
+ $(warning Unable to find a GCC archive matching gcc-*.tar.bz2)
+ $(error No archive found)
+endif
+ifeq ($(BINUTILS_ARCHIVE),)
+ $(warning Unable to find a binutils archive matching binutils-*.tar.bz2)
+ $(error No archive found)
+endif
+
+BINUTILS_CHANGES := config.sub bfd/config.bfd gas/configure.tgt ld/configure.tgt ld/emulparams/acess2_i386.sh ld/emulparams/acess2_amd64.sh ld/emulparams/acess2_arm.sh ld/Makefile.in
+GCC_CHANGES := config.sub gcc/config.gcc gcc/config/acess2.h libgcc/config.host gcc/config/acess2.opt
+# libstdc++-v3/crossconfig.m4 config/override.m4
+
+TARGET=$(HOST)
+GCC_TARGETS := gcc target-libgcc
+# target-libstdc++-v3 
diff --git a/Externals/cross-compiler/Makefile.cross b/Externals/cross-compiler/Makefile.cross
new file mode 100644 (file)
index 0000000..c6a4edd
--- /dev/null
@@ -0,0 +1,39 @@
+#
+#
+#
+include Makefile.common.mk
+
+PREFIX := $(OUTDIR)-BUILD
+BDIR := build-$(ARCH)/
+BDIR_GCC := $(BDIR)gcc
+BDIR_BINUTILS := $(BDIR)binutils
+
+include Makefile.rules.mk
+
+include:
+       mkdir -p $(PREFIX)
+       mkdir -p $(SYSROOT)/usr
+       ln -sf $(ACESSDIR)/Usermode/include $(SYSROOT)/usr/include
+       ln -sf $(ACESSDIR)/Usermode/Output/$(ARCH)/Libs $(SYSROOT)/usr/lib
+
+$(GCC_DIR)/libstdc++-v3/configure: $(GCC_DIR)/libstdc++-v3/crossconfig.m4
+       cd $(GCC_DIR)/libstdc++-v3/ && autoconf
+
+$(BDIR_BINUTILS)/Makefile: $(addprefix $(BINUTILS_DIR)/,$(BINUTILS_CHANGES))
+       @mkdir -p $(BDIR_BINUTILS)
+       @cd $(BDIR_BINUTILS) && ../../$(BINUTILS_DIR)/configure --target=$(TARGET) --prefix=$(PREFIX) --disable-nls "--with-sysroot=$(SYSROOT)" --enable-shared --without-docdir
+
+$(PREFIX)/bin/$(TARGET)-ld: $(BDIR_BINUTILS)/Makefile
+       @make -C $(BDIR_BINUTILS) all -j $(PARLEVEL)
+       @make -C $(BDIR_BINUTILS) install
+
+$(BDIR_GCC)/Makefile: Makefile $(addprefix $(GCC_DIR)/,$(GCC_CHANGES)) $(GCC_DIR)/libstdc++-v3/configure
+       @mkdir -p $(BDIR_GCC)
+       @cd $(BDIR_GCC) && PATH=$(PREFIX)/bin:$$PATH ../../$(GCC_DIR)/configure --target=$(TARGET) --prefix=$(PREFIX) --disable-nls --enable-langs=c,c++ --includedir=$(ACESSDIR)/Usermode/include "--with-sysroot=$(SYSROOT)" --without-docdir --enable-threads=posix
+       @echo "MAKEINFO = :" >> $(BDIR_GCC)/Makefile
+
+$(PREFIX)/bin/$(TARGET)-gcc: $(BDIR_GCC)/Makefile
+       @PATH=$(PREFIX)/bin:$$PATH make -C $(BDIR_GCC) $(GCC_TARGETS:%=all-%) -j $(PARLEVEL)
+       @PATH=$(PREFIX)/bin:$$PATH make -C $(BDIR_GCC) $(GCC_TARGETS:%=install-%)
+
+
diff --git a/Externals/cross-compiler/Makefile.rules.mk b/Externals/cross-compiler/Makefile.rules.mk
new file mode 100644 (file)
index 0000000..48bf43d
--- /dev/null
@@ -0,0 +1,32 @@
+
+.PHONY: all clean binutils gcc include
+
+all: include binutils gcc
+
+clean:
+       $(RM) -rf $(BINUTILS_DIR) $(GCC_DIR) build-$(ARCH)
+
+gcc: $(GCC_DIR) $(PREFIX)/bin/$(TARGET)-gcc
+
+binutils: $(BINUTILS_DIR) $(PREFIX)/bin/$(TARGET)-ld
+
+$(BINUTILS_DIR) $(GCC_DIR): %: %.tar.bz2
+       tar -xf $<
+
+$(GCC_DIR)/%: patches/gcc/%.patch
+       @echo [PATCH] $@
+       @tar -xf $(GCC_ARCHIVE) $@
+       @patch $@ $<
+$(GCC_DIR)/%: patches/gcc/%
+       @echo [CP] $@
+       @cp $< $@
+
+$(BINUTILS_DIR)/%: patches/binutils/%.patch
+       @echo [PATCH] $@
+       @tar -xf $(BINUTILS_ARCHIVE) $@
+       @patch $@ $<
+$(BINUTILS_DIR)/%: patches/binutils/%
+       @echo [CP] $@
+       @cp $< $@
+
+
index 6b61642..0c01831 100644 (file)
@@ -12,7 +12,7 @@
 +    want64=true
 +    ;;
 +  arm-*-acess2)
-+    targ_defvec=bfd_elf32_arm_vec
-+    targ_selvecs="bfd_elf32_arm_vec"
++    targ_defvec=bfd_elf32_littlearm_vec
++    targ_selvecs="bfd_elf32_bigarm_vec"
 +    ;;
  # END OF targmatch.h
index a024c08..6148df1 100644 (file)
@@ -1,6 +1,7 @@
 --- gas/configure.tgt 2011-07-29 00:00:00.000000 +0000
 +++ gas/configure.tgt 2013-03-01 10:45:00.000000 +0800
-@@ -173,2 +173,3 @@
+@@ -173,2 +173,4 @@
    i386-sequent-bsd*)                  fmt=aout em=dynix ;;
 +  i386-*-acess2*)    fmt=elf ;;
++  arm-*-acess2*)    fmt=elf ;;
    i386-*-beospe*)                     fmt=coff em=pe ;;
index 7643961..becadff 100644 (file)
@@ -1,9 +1,11 @@
 --- ld/Makefile.in
 +++ ld/Makefile.in
-@@ -2627,2 +2627,6 @@
+@@ -2627,2 +2627,8 @@
        ${GENSCRIPTS} elf32xtensa "$(tdir_elf32xtensa)"
 +eacess2_i386.c: $(srcdir)/emulparams/acess2_i386.sh $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 +      ${GENSCRIPTS} acess2_i386 "$(tdir_acess2_i386)"
 +eacess2_amd64.c: $(srcdir)/emulparams/acess2_amd64.sh $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 +      ${GENSCRIPTS} acess2_amd64 "$(tdir_acess2_amd64)"
++eacess2_arm.c: $(srcdir)/emulparams/acess2_arm.sh $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
++      ${GENSCRIPTS} acess2_arm "$(tdir_acess2_arm)"
  eelf_i386.c: $(srcdir)/emulparams/elf_i386.sh \
index 8d6a302..1d5a485 100644 (file)
@@ -1,7 +1,8 @@
 --- ld/configure.tgt
 +++ ld/configure.tgt
-@@ -167,1 +167,3 @@
+@@ -167,1 +167,4 @@
  i[3-7]86-*-nto-qnx*)    targ_emul=i386nto ;;
 +i[3-7]86-*-acess2*)    targ_emul=acess2_i386 ;;
-+x86_64-*-acess2*)    targ_emul=acess2_amd64 ;;
++x86_64-*-acess2*)      targ_emul=acess2_amd64 ;;
++arm-*-acess2*)         targ_emul=acess2_arm ;;
 
index d31dae9..3d02785 100644 (file)
@@ -1,11 +1,12 @@
 SCRIPT_NAME=elf
-OUTPUT_FORMAT=elf64-x86_64
+OUTPUT_FORMAT=elf64-x86-64
 TEXT_START_ADDR=0x00400000
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
 COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
-TEMPLATE_NAME=elf64
+ELFSIZE=64
+TEMPLATE_NAME=elf32
 
-ARCH=x86_64
+ARCH="i386:x86-64"
 MACHINE=
 NOP=0x90909090
 GENERATE_SHLIB_SCRIPT=yes
diff --git a/Externals/cross-compiler/patches/binutils/ld/emulparams/acess2_arm.sh b/Externals/cross-compiler/patches/binutils/ld/emulparams/acess2_arm.sh
new file mode 100644 (file)
index 0000000..87ef5df
--- /dev/null
@@ -0,0 +1,19 @@
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf32-littlearm"
+BIG_OUTPUT_FORMAT="elf32-bigarm"
+LITTLE_OUTPUT_FORMAT="elf32-littlearm"
+TEXT_START_ADDR=0x8000
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
+TEMPLATE_NAME=elf32
+
+ARCH=arm
+MACHINE=
+GENERATE_SHLIB_SCRIPT=yes
+GENERATE_PIE_SCRIPT=yes
+
+NO_SMALL_DATA=yes
+SEPARATE_GOTPLT=12
+
+ELF_INTERPRETER_NAME=\"/Acess/Libs/ld-acess.so\"
+
index 4a1525f..c6f085e 100644 (file)
@@ -1,22 +1,34 @@
 --- gcc/config.gcc
 +++ gcc/config.gcc
-@@ -519,3 +519,10 @@
+@@ -519,3 +519,12 @@
  # Common parts for widely ported systems.
  case ${target} in
 +*-*-acess2*)
-+  extra_parts="crtbegin.o crtend.o"
++  extra_options="${extra_options} acess2.opt"
++  extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o crtendT.o"
 +  gas=yes
 +  gnu_ld=yes
 +  default_use_cxa_atexit=yes
 +  use_gcc_stdint=provide
++  thread_file=posix
 +  ;;
  *-*-darwin*)
 
-@@ -1192,2 +1196,7 @@
+@@ -1192,2 +1196,17 @@
        ;;
 +i[3-7]86-*-acess2*)
 +      tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h newlib-stdint.h acess2.h"
-+      tmake_file="i386/t-i386elf t-svr4"
++      tmake_file="i386/t-i386elf i386/t-crtstuff t-svr4"
++      use_fixproto=yes
++      ;;
++x86_64-*-acess2*)
++      tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h acess2.h"
++      tmake_file="i386/t-i386elf i386/t-crtstuff t-svr4"
++      use_fixproto=yes
++      ;;
++arm-*-acess2*)
++      tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h newlib-stdint.h acess2.h arm/aout.h arm/arm.h"
++      tmake_file="arm/t-arm arm/t-arm-elf arm/t-bpabi"
 +      use_fixproto=yes
 +      ;;
  i[34567]86-*-elf*)
index ec3c113..a22c535 100644 (file)
@@ -5,10 +5,17 @@
     builtin_define_std ("unix");      \
     builtin_assert ("system=acess2");   \
     builtin_assert ("system=unix");   \
+    builtin_assert ("system=posix");   \
   } while(0);
 
-#define LIB_SPEC       "-lc -lld-acess -lposix"
+#define LIB_SPEC       "-lc -lld-acess -lposix %{pthread:-lpthread}"
 #define LIBSTDCXX "c++"
+#undef STARTFILE_SPEC
+#undef ENDFILE_SPEC
+#define STARTFILE_SPEC "crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} %{shared:crt0S.o%s;:crt0.o%s}"
+#define ENDFILE_SPEC   "%{static:crtendT.o%s;shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+#undef LINK_SPEC
+#define LINK_SPEC      "%{shared:-shared} %{!shared:%{!static:%{rdynamic:-export-dynamic}%{!dynamic-linker:-dynamic-linker /Acess/Libs/ld-acess.so}}}"
 
 /*
 #undef TARGET_VERSION                                     // note that adding these two lines cause an error in gcc-4.7.0
diff --git a/Externals/cross-compiler/patches/gcc/gcc/config/acess2.opt b/Externals/cross-compiler/patches/gcc/gcc/config/acess2.opt
new file mode 100644 (file)
index 0000000..e9db7e5
--- /dev/null
@@ -0,0 +1,6 @@
+; Options for acess2
+
+pthread
+Driver
+
+;
index bcf7a4a..52725e3 100644 (file)
@@ -1,16 +1,22 @@
 --- libgcc/config.host
 +++ libgcc/config.host
-@@ -523,4 +523,12 @@
+@@ -523,4 +523,18 @@
  x86_64-*-elf*)
        tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
        ;;
 +i[3-7]86-*-acess2*)
-+      extra_parts="crtbegin.o crtend.o"
++      extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o crtendT.o"
 +      tmake_file="$tmake_file i386/t-crtstuff"
 +      ;;
 +x86_64-*-acess2*)
-+      extra_parts="crtbegin.o crtend.o"
++      extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o crtendT.o"
 +      tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
++      ;;
++arm-*-acess2*)
++      extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o crtendT.o"
++      tmake_file="${tmake_file} arm/t-arm arm/t-elf t-fixedpoint-gnu-prefix arm/t-bpabi t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
++      tm_file="$tm_file arm/bpabi-lib.h"
++      unwind_header=config/arm/unwind-arm.h
 +      ;;
  i[34567]86-*-freebsd*)
 
diff --git a/Externals/curl/Makefile b/Externals/curl/Makefile
new file mode 100644 (file)
index 0000000..e0c5eef
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Acess2 External: libcurl
+# - Makefile and patches by John Hodge (thePowersGang)
+#
+
+DEPS := 
+TARBALL_PATTERN := curl-*.tar.bz2
+TARBALL_TO_DIR_L := %.tar.bz2
+TARBALL_TO_DIR_R := %
+PATCHES := config.sub
+CONFIGURE_ARGS = LIBS=-lpsocket
+
+include ../common_automake.mk
+
diff --git a/Externals/curl/patches/config.sub.patch b/Externals/curl/patches/config.sub.patch
new file mode 100644 (file)
index 0000000..8380154
--- /dev/null
@@ -0,0 +1,7 @@
+--- bochs-2.6.2_orig/config.sub        2013-06-17 11:39:39.670720710 +0800
++++ bochs-2.6.2/config.sub     2013-06-17 11:48:09.149384231 +0800
+@@ -1356,2 +1356,3 @@
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
++            | -acess2 \
+             | -aos* | -aros* \
+
diff --git a/Externals/glib/Makefile b/Externals/glib/Makefile
new file mode 100644 (file)
index 0000000..953ef03
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Acess2 Externals - glib
+# - Patches and Makefile by John Hodge (thePowersGang)
+#
+
+DEPS := libffi
+_NAME := glib
+TARBALL_PATTERN := $(_NAME)-*.tar.xz
+TARBALL_TO_DIR_L := $(_NAME)-%.tar.xz
+TARBALL_TO_DIR_R := $(_NAME)-%
+PATCHES := config.sub
+CONFIGURE_ARGS := glib_cv_stack_grows=no ac_cv_func_posix_getpwuid_r=no ac_cv_func_posix_getgrgid_r=no
+CONFIGURE_ARGS += LDFLAGS=-lpsocket
+
+include ../common_automake.mk
+
+
diff --git a/Externals/glib/patches/config.sub.patch b/Externals/glib/patches/config.sub.patch
new file mode 100644 (file)
index 0000000..f600ad4
--- /dev/null
@@ -0,0 +1,8 @@
+--- glib/config.sub
++++ glib/config.sub
+@@ -1335,2 +1335,5 @@
+               ;;
++      -acess2)
++              os=-acess2
++              ;;
+       -solaris)
index a5d190a..9f2d7fa 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a5d190a89ca3f3a78c8b44a855b044ff4e713bb3
+Subproject commit 9f2d7faf34c16ceaee2f1bffe3d5558c41382523
index d4140c3..5b69f5d 100644 (file)
@@ -12,7 +12,12 @@ NOBDIR = yes
 
 include ../core.mk
 
-_build:
-       cd $(BDIR) && CC=$(HOST)-gcc TARGET=sdl make
+.PHONY: _check_local_deps
+
+_build: _check_local_deps
+       cd $(BDIR) && CC=$(HOST)-gcc TARGET=framebuffer make
+
+_check_local_deps:
+       @gperf --help >/dev/null || (echo "ERROR: netsurf's build system requires gperf"; false)
 
 
index e945631..f59d7c1 100644 (file)
@@ -108,3 +108,15 @@ diff -ru .orig/netsurf-full-3.0//src/libparserutils-0.1.2/src/utils/vector.c net
  {
        if (vector == NULL || vector->current_item < 0)
                return NULL;
+diff -ru .orig/netsurf-full-3.0//src/libnsfb-0.1.2/Makefile netsurf-full-3.0//src/libnsfb-0.1.0/Makefile
+--- .orig/netsurf-full-3.0//src/libnsfb-0.1.0/Makefile 2013-04-20 02:06:57.000000000 +0800
++++ netsurf-full-3.0//src/libnsfb-0.1.0/Makefile       2013-07-01 22:22:45.246689992 +0800
+@@ -31,5 +31,5 @@
+ # surfaces not detectable via pkg-config 
+ NSFB_ABLE_AVAILABLE := no
+-NSFB_LINUX_AVAILABLE := yes
++NSFB_LINUX_AVAILABLE := no
+ # Flags and setup for each support library
+ NSFB_ABLE_AVAILABLE := no
diff --git a/Externals/pkgconfig/Makefile b/Externals/pkgconfig/Makefile
new file mode 100644 (file)
index 0000000..bcd6305
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Acess2 Externals - pkgconfig
+# - Patches and Makefile by John Hodge (thePowersGang)
+#
+
+DEPS := 
+TARBALL_PATTERN := pkg-config-*.tar.gz
+TARBALL_TO_DIR_L := pkg-config-%.tar.gz
+TARBALL_TO_DIR_R := pkg-config-%
+PATCHES := 
+CONFIGURE_LINE = $(SDIR)/configure --prefix=$(BUILD_OUTDIR) --with-internal-glib
+
+include ../common_automake.mk
+
+
+
+
diff --git a/Externals/pkgconfig/patches/config.sub.patch b/Externals/pkgconfig/patches/config.sub.patch
new file mode 100644 (file)
index 0000000..b2d7389
--- /dev/null
@@ -0,0 +1,7 @@
+--- bochs-2.6.2_orig/config.sub        2013-06-17 11:39:39.670720710 +0800
++++ bochs-2.6.2/config.sub     2013-06-17 11:48:09.149384231 +0800
+@@ -1344,2 +1344,3 @@
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
++            | -acess2 \
+             | -aos* | -aros* \
+
diff --git a/Externals/pkgconfig/patches/glib/config.sub.patch b/Externals/pkgconfig/patches/glib/config.sub.patch
new file mode 100644 (file)
index 0000000..f600ad4
--- /dev/null
@@ -0,0 +1,8 @@
+--- glib/config.sub
++++ glib/config.sub
+@@ -1335,2 +1335,5 @@
+               ;;
++      -acess2)
++              os=-acess2
++              ;;
+       -solaris)
index fdf33e9..e7e3cbe 100755 (executable)
@@ -46,7 +46,9 @@ foreach my $call (@calls)
 }
 print HEADER "
 #define NUM_SYSCALLS   ",$i,"
-#define SYS_DEBUG      0x100
+#define SYS_DEBUGS     0x100
+#define SYS_DEBUGF     0x101
+#define SYS_DEBUGHEX   0x102
 
 #if !defined(__ASSEMBLER__) && !defined(NO_SYSCALL_STRS)
 static const char *cSYSCALL_NAMES[] = {
index cc4f230..895d90f 100644 (file)
@@ -56,13 +56,13 @@ BUILDINFO_SRC := $(OBJDIR)buildinfo.c$(OBJSUFFIX)
 OBJ := $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
 OBJ += pmemmap.o
 OBJ += heap.o logging.o debug.o lib.o libc.o adt.o time.o utf16.o debug_hooks.o
-OBJ += drvutil_video.o drvutil_disk.o
-OBJ += messages.o modules.o syscalls.o system.o
+OBJ += drvutil_video.o drvutil_disk.o memfs_helpers.o
+OBJ += messages.o modules.o syscalls.o system.o emergency_console.o
 OBJ += threads.o mutex.o semaphore.o workqueue.o events.o rwlock.o
 OBJ += drv/zero-one.o drv/proc.o drv/fifo.o drv/dgram_pipe.o drv/iocache.o drv/pci.o drv/vpci.o
 OBJ += drv/vterm.o drv/vterm_font.o drv/vterm_vt100.o drv/vterm_output.o drv/vterm_input.o drv/vterm_termbuf.o
 OBJ += drv/vterm_2d.o
-OBJ += drv/pty.o drv/serial.o
+OBJ += drv/pty.o drv/serial.o drv/shm.o
 OBJ += binary.o bin/elf.o bin/pe.o
 OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o
 OBJ += vfs/memfile.o vfs/nodecache.o vfs/handle.o vfs/select.o vfs/mmap.o
@@ -153,7 +153,7 @@ $(BUILDINFO_SRC): $(filter-out $(BUILDINFO_OBJ), $(OBJ)) $(MODS) arch/$(ARCHDIR)
        @echo "const char gsGitHash[] = \"$(_GITHASH)\";" >> $@
        @echo "const int giBuildNumber = $(BUILD_NUM);" >> $@
        @echo "const char gsBuildInfo[] = \"Acess2 v$(KERNEL_VERSION) $(ARCH)-$(PLATFORM)\\\\r\\\\n\"" >> $@
-       @echo "                           \"Build $(shell hostname --fqdn):$(BUILD_NUM) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@
+       @echo "                           \"Build $(shell hostname --fqdn):$(BUILD_NUM) $(shell date +%FT%T%z) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@
 # Compile rule for buildinfo (needs a special one because it's not a general source file)
 $(BUILDINFO_OBJ): $(BUILDINFO_SRC)
        @echo --- CC -o $@
index 4d85fcb..b478031 100644 (file)
 //  > If the `N` value is greater than `D`, we can set this bit
 #define DEF_DIVMOD(s) Uint##s __divmod##s(Uint##s N, Uint##s D, Uint##s*Rem){\
        Uint##s ret=0,add=1;\
-       while(N>=D&&add) {D<<=1;add<<=1;}\
-       while(add>1){\
-               add>>=1;D>>=1;\
+       while(N/2>=D&&add) {D<<=1;add<<=1;}\
+       while(add>0){\
                if(N>=D){ret+=add;N-=D;}\
+               add>>=1;D>>=1;\
        }\
        if(Rem)*Rem = N;\
        return ret;\
diff --git a/KernelLand/Kernel/arch/x86/common.inc.asm b/KernelLand/Kernel/arch/x86/common.inc.asm
new file mode 100644 (file)
index 0000000..ec7f844
--- /dev/null
@@ -0,0 +1,24 @@
+%macro PUSH_CC 0
+       ; Don't bother being too picky, just take the time
+       pusha
+%endmacro
+%macro PUSH_SEG        0
+       push ds
+       push es
+       push fs
+       push gs
+       mov ax, 0x10
+       mov ds, ax
+       mov es, ax
+       mov fs, ax
+       mov gs, ax
+%endmacro
+%macro POP_CC  0
+       popa
+%endmacro
+%macro POP_SEG 0
+       pop gs
+       pop fs
+       pop es
+       pop ds
+%endmacro
index 354a001..3382534 100644 (file)
@@ -1,6 +1,7 @@
 ; AcessOS Microkernel Version
 ;
 ; desctab.asm
+%include "arch/x86/common.inc.asm"
 [BITS 32]
 
 
@@ -182,14 +183,14 @@ Isr0xED:
        jmp .jmp
 
 [global Isr0xEE]
-[extern SchedulerBase]
+[extern Proc_EventTimer_LAPIC]
 ; AP's Timer Interrupt
 Isr0xEE:
        push eax        ; Line up with interrupt number
        mov eax, dr1    ; CPU Number
        push eax
        mov eax, [esp+4]        ; Load EAX back
-       jmp SchedulerBase
+       jmp Proc_EventTimer_LAPIC
 ; Spurious Interrupt
 [global Isr0xEF]
 Isr0xEF:
@@ -201,7 +202,7 @@ Isr0xEF:
 ; - Timer
 [global Isr240]
 [global Isr240.jmp]
-[extern SchedulerBase]
+[extern Proc_EventTimer_PIT]
 [extern SetAPICTimerCount]
 Isr240:
        push 0  ; Line up with Argument in errors
@@ -211,7 +212,7 @@ Isr240.jmp:
        %if USE_MP
        jmp SetAPICTimerCount   ; This is reset once the bus speed has been calculated
        %else
-       jmp SchedulerBase
+       jmp Proc_EventTimer_PIT
        %endif
 ; - Assignable
 %assign i      0xF1
@@ -254,11 +255,8 @@ ErrorCommon:
 ; --------------------------
 [extern SyscallHandler]
 SyscallCommon:
-       pusha
-       push ds
-       push es
-       push fs
-       push gs
+       PUSH_CC ; Actually a pusha
+       PUSH_SEG
        
        push esp
        call SyscallHandler
@@ -286,17 +284,8 @@ SyscallCommon:
 [global IRQCommon_handled]
 IRQCommon_handled equ IRQCommon.handled
 IRQCommon:
-       pusha
-       push ds
-       push es
-       push fs
-       push gs
-       
-       mov ax, 0x10
-       mov ds, ax
-       mov es, ax
-       mov fs, ax
-       mov gs, ax
+       PUSH_CC
+       PUSH_SEG
        
        push esp
        call IRQ_Handler
index aec6c60..8087518 100644 (file)
@@ -74,6 +74,7 @@ void  MM_InstallVirtual(void);
 void   MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs);
 void   MM_DumpTables_Print(tVAddr Start, Uint32 Orig, size_t Size, void *Node);
 //void MM_DumpTables(tVAddr Start, tVAddr End);
+tPAddr MM_GetPageFromAS(tProcess *Process, volatile const void *Addr);
 //void MM_ClearUser(void);
 tPAddr MM_DuplicatePage(tVAddr VAddr);
 
@@ -538,6 +539,23 @@ tPAddr MM_GetPhysAddr(volatile const void *Addr)
        return (gaPageTable[addr >> 12] & ~0xFFF) | (addr & 0xFFF);
 }
 
+/**
+ * \brief Get the address of a page from another addres space
+ * \return Refenced physical address (or 0 on error)
+ */
+tPAddr MM_GetPageFromAS(tProcess *Process, volatile const void *Addr)
+{
+       tPAddr  ret = 0;
+       GET_TEMP_MAPPING(Process->MemState.CR3);
+       tVAddr  addr = (tVAddr)Addr;
+       if( (gaTmpDir[addr >> 22] & 1) && (gaTmpTable[addr >> 12] & 1) ) {
+               ret = (gaTmpTable[addr >> 12] & ~0xFFF) | (addr & 0xFFF);
+               MM_RefPhys( ret );
+       }
+       REL_TEMP_MAPPING();
+       return ret;
+}
+
 /**
  * \fn void MM_SetCR3(Uint CR3)
  * \brief Sets the current process space
@@ -552,18 +570,17 @@ void MM_SetCR3(Uint CR3)
  */
 void MM_ClearUser(void)
 {
-       Uint    i, j;
-       
-       for( i = 0; i < (MM_USER_MAX>>22); i ++ )
+       ASSERTC(MM_PPD_MIN, ==, MM_USER_MAX);
+       for( unsigned int i = 0; i < (MM_USER_MAX>>22); i ++ )
        {
                // Check if directory is not allocated
                if( !(gaPageDir[i] & PF_PRESENT) ) {
                        gaPageDir[i] = 0;
                        continue;
                }
-               
+       
                // Deallocate tables
-               for( j = 0; j < 1024; j ++ )
+               for( unsigned int j = 0; j < 1024; j ++ )
                {
                        if( gaPageTable[i*1024+j] & 1 )
                                MM_DerefPhys( gaPageTable[i*1024+j] & ~0xFFF );
@@ -583,8 +600,6 @@ void MM_ClearUser(void)
  */
 void MM_ClearSpace(Uint32 CR3)
 {
-        int    i, j;
-       
        if(CR3 == (*gpPageCR3 & ~0xFFF)) {
                Log_Error("MMVirt", "Can't clear current address space");
                return ;
@@ -601,7 +616,7 @@ void MM_ClearSpace(Uint32 CR3)
        GET_TEMP_MAPPING(CR3);
        INVLPG( gaTmpDir );
 
-       for( i = 0; i < 1024; i ++ )
+       for( int i = 0; i < 1024; i ++ )
        {
                Uint32  *table = &gaTmpTable[i*1024];
                if( !(gaTmpDir[i] & PF_PRESENT) )
@@ -611,7 +626,7 @@ void MM_ClearSpace(Uint32 CR3)
 
                if( i < 768 || (i > MM_KERNEL_STACKS >> 22 && i < MM_KERNEL_STACKS_END >> 22) )
                {
-                       for( j = 0; j < 1024; j ++ )
+                       for( int j = 0; j < 1024; j ++ )
                        {
                                if( !(table[j] & 1) )
                                        continue;
@@ -1052,6 +1067,8 @@ void *MM_MapTemp(tPAddr PAddr)
                LOG("%i: %x", i, *pte);
                // Check if page used
                if(*pte & 1)    continue;
+               MM_RefPhys( PAddr );
+               
                // Mark as used
                *pte = PAddr | 3;
                INVLPG( TEMP_MAP_ADDR + (i << 12) );
@@ -1064,6 +1081,15 @@ void *MM_MapTemp(tPAddr PAddr)
        return NULL;
 }
 
+void *MM_MapTempFromProc(tProcess *Process, const void *VAddr)
+{
+       // Get paddr
+       tPAddr  paddr = MM_GetPageFromAS(Process, VAddr);
+       if( paddr == 0 )
+               return NULL;
+       return MM_MapTemp(paddr);
+}
+
 /**
  * \fn void MM_FreeTemp(tVAddr PAddr)
  * \brief Free's a temp mapping
@@ -1073,7 +1099,9 @@ void MM_FreeTemp(void *VAddr)
         int    i = (tVAddr)VAddr >> 12;
        //ENTER("xVAddr", VAddr);
        
-       if(i >= (TEMP_MAP_ADDR >> 12)) {
+       if(i >= (TEMP_MAP_ADDR >> 12))
+       {
+               MM_DerefPhys( gaPageTable[i] & ~0xFFF );
                gaPageTable[ i ] = 0;
                Semaphore_Signal(&gTempMappingsSem, 1);
        }
index b8c01bc..1987166 100644 (file)
@@ -1,5 +1,6 @@
 ; AcessOS Microkernel Version
 ; Start.asm
+%include "arch/x86/common.inc.asm"
 
 [bits 32]
 
@@ -11,19 +12,6 @@ KSTACK_USERSTATE_SIZE        equ     (4+8+1+5)*4     ; SRegs, GPRegs, CPU, IRET
 
 [section .text]
 
-[global NewTaskHeader]
-NewTaskHeader:
-       mov eax, [esp]
-       mov dr0, eax
-
-       mov eax, [esp+4]
-       add esp, 12     ; Thread, Function, Arg Count
-       call eax
-       
-       push eax        ; Ret val
-       push 0          ; 0 = This Thread
-       call Threads_Exit
-
 [extern MM_Clone]
 [global Proc_CloneInt]
 Proc_CloneInt:
@@ -38,7 +26,7 @@ Proc_CloneInt:
        mov esi, [esp+0x20+8]
        mov [esi], eax
        ; Undo the pusha
-       add esp, 0x20
+       popa
        mov eax, .newTask
        ret
 .newTask:
@@ -53,7 +41,7 @@ Proc_CloneInt:
 ; +16 = Old RIP save loc
 ; +20 = CR3
 SwitchTasks:
-       pusha
+       PUSH_CC
        
        ; Old IP
        mov eax, [esp+0x20+16]
@@ -78,7 +66,7 @@ SwitchTasks:
        jmp ecx
 
 .restore:
-       popa
+       POP_CC
        xor eax, eax
        ret
 
@@ -122,17 +110,8 @@ Proc_RestoreSSE:
 [extern Isr240.jmp]
 [global SetAPICTimerCount]
 SetAPICTimerCount:
-       pusha
-       push ds
-       push es
-       push fs
-       push gs
-       
-       mov ax, 0x10
-       mov ds, ax
-       mov es, ax
-       mov fs, ax
-       mov gs, ax
+       PUSH_CC
+       PUSH_SEG
        
        mov eax, [gpMP_LocalAPIC]
        mov ecx, [eax+0x320]
@@ -152,7 +131,7 @@ SetAPICTimerCount:
        mov DWORD [eax+0x380], 0
 
        ; Update Timer IRQ to the IRQ code
-       mov eax, SchedulerBase
+       mov eax, Proc_EventTimer_PIT
        sub eax, Isr240.jmp+5
        mov DWORD [Isr240.jmp+1], eax
 
@@ -160,72 +139,55 @@ SetAPICTimerCount:
 .ret:
        mov dx, 0x20
        mov al, 0x20
-       out dx, al              ; ACK IRQ
-       pop gs
-       pop fs
-       pop es
-       pop ds
-       popa
+       out 0x20, al            ; ACK IRQ
+       POP_SEG
+       POP_CC
        add esp, 8      ; CPU ID / Error Code
        iret
 %endif
-; --------------
-; Task Scheduler
-; --------------
-[extern Proc_Scheduler]
-[global SchedulerBase]
-SchedulerBase:
-       pusha
-       push ds
-       push es
-       push fs
-       push gs
+
+%if USE_MP
+[global Proc_EventTimer_LAPIC]
+Proc_EventTimer_LAPIC:
+       push eax
+       mov eax, SS:[gpMP_LocalAPIC]
+       mov DWORD SS:[eax + 0xB0], 0
+       pop eax
+       jmp Proc_EventTimer_Common
+%endif
+[global Proc_EventTimer_PIT]
+Proc_EventTimer_PIT:
+       push eax
+       mov al, 0x20
+       out 0x20, al            ; ACK IRQ
+       pop eax
+       jmp Proc_EventTimer_Common
+[extern Proc_HandleEventTimer]
+[global Proc_EventTimer_Common]
+Proc_EventTimer_Common:
+       PUSH_CC
+       PUSH_SEG
        
+       ; Clear the Trace/Trap flag
        pushf
        and BYTE [esp+1], 0xFE  ; Clear Trap Flag
        popf
-       
-       mov eax, dr0
-       push eax        ; Debug Register 0, Current Thread
-       
-       mov ax, 0x10
-       mov ds, ax
-       mov es, ax
-       mov fs, ax
-       mov gs, ax
+       ; Re-enable interrupts
+       ; - TODO: This is quite likely racy, if we get an interrupt flood
+       sti
        
        %if USE_MP
        call GetCPUNum
-       mov ebx, eax
        push eax        ; Push as argument
        %else
        push 0
        %endif
        
-       call Proc_Scheduler
+       call Proc_HandleEventTimer
 [global scheduler_return]
 scheduler_return:      ; Used by some hackery in Proc_DumpThreadCPUState
-       
        add esp, 4      ; Remove CPU Number (thread is poped later)
 
-       %if USE_MP
-       test ebx, ebx
-       jnz .sendEOI
-       %endif
-       
-       mov al, 0x20
-       out 0x20, al            ; ACK IRQ
-
-       %if USE_MP
-       jmp .ret
-.sendEOI:
-       mov eax, DWORD [gpMP_LocalAPIC]
-       mov DWORD [eax+0x0B0], 0
-       %endif
-.ret:
-       pop eax ; Debug Register 0, Current Thread
-       mov dr0, eax
-       
        jmp ReturnFromInterrupt
 
 ;
index 5637985..b1dcb99 100644 (file)
@@ -44,7 +44,6 @@ extern tGDT   gGDT[];
 extern tIDT    gIDT[];
 extern void    APWait(void);   // 16-bit AP pause code
 extern void    APStartup(void);        // 16-bit AP startup code
-extern void    NewTaskHeader(tThread *Thread, void *Fcn, int nArgs, ...);      // Actually takes cdecl args
 extern Uint    Proc_CloneInt(Uint *ESP, Uint32 *CR3, int bNoUserClone);
 extern Uint32  gaInitPageDir[1024];    // start.asm
 extern char    Kernel_Stack_Top[];
@@ -71,6 +70,7 @@ void  Proc_IdleThread(void *Ptr);
 //tThread      *Proc_GetCurThread(void);
 void   Proc_ChangeStack(void);
 // int Proc_NewKThread(void (*Fcn)(void*), void *Data);
+void   NewTaskHeader(tThread *Thread, void (*Fcn)(void*), void *Data); // Actually takes cdecl args
 // int Proc_Clone(Uint *Err, Uint Flags);
 Uint   Proc_MakeUserStack(void);
 //void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize);
@@ -78,7 +78,7 @@ void  Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) NO
 void   Proc_CallUser(Uint32 UserIP, Uint32 UserSP, const void *StackData, size_t StackDataLen);
 //void Proc_CallFaultHandler(tThread *Thread);
 //void Proc_DumpThreadCPUState(tThread *Thread);
-void   Proc_Scheduler(int CPU);
+void   Proc_HandleEventTimer(int CPU);
 
 // === GLOBALS ===
 // --- Multiprocessing ---
@@ -307,10 +307,12 @@ void Proc_IdleThread(void *Ptr)
        cpu->Current->ThreadName = strdup("Idle Thread");
        Threads_SetPriority( cpu->Current, -1 );        // Never called randomly
        cpu->Current->Quantum = 1;      // 1 slice quantum
-       for(;;) {
+       LOG("Idle thread for CPU %i ready", GetCPUNum());
+       for(;;)
+       {
                __asm__ __volatile__ ("sti");   // Make sure interrupts are enabled
-               __asm__ __volatile__ ("hlt");
-               Proc_Reschedule();
+               Proc_Reschedule();      // Reshedule
+               __asm__ __volatile__ ("hlt");   // And wait for an interrupt if we get scheduled again
        }
 }
 
@@ -432,10 +434,7 @@ void Proc_ClearThread(tThread *Thread)
 
 tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
 {
-       Uint    esp;
-       tThread *newThread;
-       
-       newThread = Threads_CloneTCB(0);
+       tThread *newThread = Threads_CloneTCB(0);
        if(!newThread)  return -1;
        
        // Create new KStack
@@ -445,12 +444,14 @@ tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
                free(newThread);
                return -1;
        }
+       
+       LOG("%p(%i %s) SP=%p", newThread, newThread->TID, newThread->ThreadName, newThread->KernelStack);
 
-       esp = newThread->KernelStack;
+       Uint esp = newThread->KernelStack;
        *(Uint*)(esp-=4) = (Uint)Data;  // Data (shadowed)
-       *(Uint*)(esp-=4) = 1;   // Number of params
        *(Uint*)(esp-=4) = (Uint)Fcn;   // Function to call
        *(Uint*)(esp-=4) = (Uint)newThread;     // Thread ID
+       *(Uint*)(esp-=4) = (Uint)0;     // Empty return address
        
        newThread->SavedState.ESP = esp;
        newThread->SavedState.EIP = (Uint)&NewTaskHeader;
@@ -463,15 +464,24 @@ tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
        return newThread->TID;
 }
 
+void NewTaskHeader(tThread *NewThread, void (*Fcn)(void*), void *Data)
+{
+       LOG("NewThread=%p, Fcn=%p, Data=%p", NewThread, Fcn, Data);
+       __asm__ __volatile__ ("mov %0, %%dr0" : : "r"(NewThread));
+       SHORTREL(&glThreadListLock);
+       Fcn(Data);
+       
+       Threads_Exit(0, 0);
+       for(;;);
+}
+
 /**
  * \fn int Proc_Clone(Uint *Err, Uint Flags)
  * \brief Clone the current process
  */
 tPID Proc_Clone(Uint Flags)
 {
-       tThread *newThread;
        tThread *cur = Proc_GetCurThread();
-       Uint    eip;
 
        // Sanity, please
        if( !(Flags & CLONE_VM) ) {
@@ -480,16 +490,22 @@ tPID Proc_Clone(Uint Flags)
        }
        
        // New thread
-       newThread = Threads_CloneTCB(Flags);
+       tThread *newThread = Threads_CloneTCB(Flags);
        if(!newThread)  return -1;
+       ASSERT(newThread->Process);
 
        newThread->KernelStack = cur->KernelStack;
 
        // Clone state
-       eip = Proc_CloneInt(&newThread->SavedState.ESP, &newThread->Process->MemState.CR3, Flags & CLONE_NOUSER);
+       Uint eip = Proc_CloneInt(&newThread->SavedState.ESP, &newThread->Process->MemState.CR3, Flags & CLONE_NOUSER);
        if( eip == 0 ) {
+               SHORTREL( &glThreadListLock );
+               LOG("In new thread");
                return 0;
        }
+       //ASSERT(newThread->Process);
+       //ASSERT(CheckMem(newThread->Process, sizeof(tProcess)));
+       //LOG("newThread->Process = %p", newThread->Process);
        newThread->SavedState.EIP = eip;
        newThread->SavedState.SSE = NULL;
        newThread->SavedState.bSSEModified = 0;
@@ -522,12 +538,13 @@ tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
                Warning("Proc_SpawnWorker - Out of heap space!\n");
                return NULL;
        }
+       LOG("new = (%i %s)", new->TID, new->ThreadName);
 
        // Create the stack contents
        stack_contents[3] = (Uint)Data;
-       stack_contents[2] = 1;
-       stack_contents[1] = (Uint)Fcn;
-       stack_contents[0] = (Uint)new;
+       stack_contents[2] = (Uint)Fcn;
+       stack_contents[1] = (Uint)new;
+       stack_contents[0] = 0;
        
        // Create a new worker stack (in PID0's address space)
        new->KernelStack = MM_NewWorkerStack(stack_contents, sizeof(stack_contents));
@@ -760,82 +777,82 @@ void Proc_DumpThreadCPUState(tThread *Thread)
 
 void Proc_Reschedule(void)
 {
-       tThread *nextthread, *curthread;
         int    cpu = GetCPUNum();
 
        // TODO: Wait for the lock?
-       if(IS_LOCKED(&glThreadListLock))        return;
+       if(IS_LOCKED(&glThreadListLock)) {
+               LOG("Thread list locked, not rescheduling");
+               return;
+       }
        
-       curthread = Proc_GetCurThread();
-
-       nextthread = Threads_GetNextToRun(cpu, curthread);
-
-       if(!nextthread || nextthread == curthread)
-               return ;
-
-       #if DEBUG_TRACE_SWITCH
-       // HACK: Ignores switches to the idle threads
-       if( nextthread->TID == 0 || nextthread->TID > giNumCPUs )
+       SHORTLOCK(&glThreadListLock);
+       
+       tThread *curthread = Proc_GetCurThread();
+       tThread *nextthread = Threads_GetNextToRun(cpu, curthread);
+       
+       if(nextthread && nextthread != curthread)
        {
-               LogF("\nSwitching CPU %i to %p (%i %s) - CR3 = 0x%x, EIP = %p, ESP = %p\n",
-                       GetCPUNum(),
-                       nextthread, nextthread->TID, nextthread->ThreadName,
-                       nextthread->Process->MemState.CR3,
-                       nextthread->SavedState.EIP,
-                       nextthread->SavedState.ESP
-                       );
-               LogF("OldCR3 = %P\n", curthread->Process->MemState.CR3);
-       }
-       #endif
+               #if DEBUG_TRACE_SWITCH
+               // HACK: Ignores switches to the idle threads
+               //if( nextthread->TID == 0 || nextthread->TID > giNumCPUs )
+               {
+                       LogF("\nSwitching CPU %i to %p (%i %s) - CR3 = 0x%x, EIP = %p, ESP = %p\n",
+                               GetCPUNum(),
+                               nextthread, nextthread->TID, nextthread->ThreadName,
+                               nextthread->Process->MemState.CR3,
+                               nextthread->SavedState.EIP,
+                               nextthread->SavedState.ESP
+                               );
+                       LogF(" from %p (%i %s) - CR3 = 0x%x, EIP = %p, ESP = %p\n",
+                               curthread, curthread->TID, curthread->ThreadName,
+                               curthread->Process->MemState.CR3,
+                               curthread->SavedState.EIP,
+                               curthread->SavedState.ESP
+                               );
+               }
+               #endif
 
-       // Update CPU state
-       gaCPUs[cpu].Current = nextthread;
-       gaCPUs[cpu].LastTimerThread = NULL;
-       gTSSs[cpu].ESP0 = nextthread->KernelStack-4;
-       __asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(nextthread) );
+               // Update CPU state
+               gaCPUs[cpu].Current = nextthread;
+               gaCPUs[cpu].LastTimerThread = NULL;
+               gTSSs[cpu].ESP0 = nextthread->KernelStack-4;
+               __asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(nextthread) );
 
-       // Save FPU/MMX/XMM/SSE state
-       if( curthread && curthread->SavedState.SSE )
-       {
-               Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
-               curthread->SavedState.bSSEModified = 0;
-               Proc_DisableSSE();
-       }
+               // Save FPU/MMX/XMM/SSE state
+               if( curthread && curthread->SavedState.SSE )
+               {
+                       Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
+                       curthread->SavedState.bSSEModified = 0;
+                       Proc_DisableSSE();
+               }
 
-       if( curthread )
-       {
-               SwitchTasks(
-                       nextthread->SavedState.ESP, &curthread->SavedState.ESP,
-                       nextthread->SavedState.EIP, &curthread->SavedState.EIP,
-                       nextthread->Process->MemState.CR3
-                       );
-       }
-       else
-       {
-               SwitchTasks(
-                       nextthread->SavedState.ESP, 0,
-                       nextthread->SavedState.EIP, 0,
-                       nextthread->Process->MemState.CR3
-                       );
+               if( curthread )
+               {
+                       SwitchTasks(
+                               nextthread->SavedState.ESP, &curthread->SavedState.ESP,
+                               nextthread->SavedState.EIP, &curthread->SavedState.EIP,
+                               nextthread->Process->MemState.CR3
+                               );
+               }
+               else
+               {
+                       SwitchTasks(
+                               nextthread->SavedState.ESP, 0,
+                               nextthread->SavedState.EIP, 0,
+                               nextthread->Process->MemState.CR3
+                               );
+               }
        }
-
-       return ;
+       
+       SHORTREL(&glThreadListLock);
 }
 
 /**
- * \fn void Proc_Scheduler(int CPU)
- * \brief Swap current thread and clears dead threads
+ * \brief Handle the per-CPU timer ticking
  */
-void Proc_Scheduler(int CPU)
+void Proc_HandleEventTimer(int CPU)
 {
-       #if USE_MP
-       if( GetCPUNum() )
-               gpMP_LocalAPIC->EOI.Val = 0;
-       else
-       #endif
-               outb(0x20, 0x20);
-       __asm__ __volatile__ ("sti");   
-
        // Call the timer update code
        Timer_CallTimers();
 
@@ -843,6 +860,8 @@ void Proc_Scheduler(int CPU)
        // If two ticks happen within the same task, and it's not an idle task, swap
        if( gaCPUs[CPU].Current->TID > giNumCPUs && gaCPUs[CPU].Current == gaCPUs[CPU].LastTimerThread )
        {
+               const tThread* const t = gaCPUs[CPU].Current;
+               LOG("Preempting thread %p(%i %s)", t, t->TID, t->ThreadName);
                Proc_Reschedule();
        }
        
index 54e59a5..b367c50 100644 (file)
@@ -103,6 +103,7 @@ void Time_Interrupt(int IRQ, void *Ptr)
        if( giTime_TSCAtLastTick )
        {
                giTime_TSCPerTick = curTSC - giTime_TSCAtLastTick;
+               //Debug("TSC Frequency is %llu-%llu = %llu Hz", curTSC, giTime_TSCAtLastTick, giTime_TSCPerTick*2);
        }
        giTime_TSCAtLastTick = curTSC;
        
index 93ea63a..f1b5005 100644 (file)
@@ -68,16 +68,14 @@ Uint32      gaVM8086_MemBitmap[VM8086_BLOCKCOUNT/32];
 // === FUNCTIONS ===
 int VM8086_Install(char **Arguments)
 {
-       tPID    pid;    
-
        Semaphore_Init(&gVM8086_TasksToDo, 0, 10, "VM8086", "TasksToDo");
        
        // Lock to avoid race conditions
        Mutex_Acquire( &glVM8086_Process );
        
        // Create BIOS Call process
-       pid = Proc_Clone(CLONE_VM);
-       //Log_Debug("VM8086", "pid = %i", pid);
+       tPID pid = Proc_Clone(CLONE_VM);
+       LOG("pid = %i", pid);
        if(pid == -1)
        {
                Log_Error("VM8086", "Unable to clone kernel into VM8086 worker");
@@ -87,15 +85,14 @@ int VM8086_Install(char **Arguments)
        {
                Uint    * volatile stacksetup;  // Initialising Stack
                Uint16  * volatile rmstack;     // Real Mode Stack
-                int    i;
 
-               //Log_Debug("VM8086", "Initialising worker");   
+               LOG("Initialising worker");
        
                // Set Image Name
                Threads_SetName("VM8086");
 
                // Map ROM Area
-               for(i=0xA0;i<0x100;i++) {
+               for(unsigned int i = 0xA0;i<0x100;i++) {
                        MM_RefPhys(i * 0x1000);
                        MM_Map( (void*)(i * 0x1000), i * 0x1000 );
                }
@@ -150,6 +147,7 @@ int VM8086_Install(char **Arguments)
                stacksetup--;   *stacksetup = 0x20|3;   // ES - Kernel
                stacksetup--;   *stacksetup = 0x20|3;   // FS
                stacksetup--;   *stacksetup = 0x20|3;   // GS
+               LOG("stacksetup = %p, entering vm8086");
                __asm__ __volatile__ (
                "mov %%eax,%%esp;\n\t"  // Set stack pointer
                "pop %%gs;\n\t"
@@ -164,6 +162,7 @@ int VM8086_Install(char **Arguments)
        gVM8086_WorkerPID = pid;
 
        // It's released when the GPF fires
+       LOG("Waiting for worker %i to start", gVM8086_WorkerPID);
        Mutex_Acquire( &glVM8086_Process );
        Mutex_Release( &glVM8086_Process );
        
index e833173..e5e3f24 100644 (file)
@@ -404,7 +404,7 @@ SyscallStub:
        mov [rsp+0x10], rdi     ; Arg1
        mov [rsp+0x18], rsi     ; Arg2
        mov [rsp+0x20], rdx     ; Arg3
-       mov [rsp+0x28], r10     ; Arg4
+       mov [rsp+0x28], r10     ; Arg4 (r10 used in place of rcx)
        mov [rsp+0x30], r8      ; Arg5
        mov [rsp+0x38], r9      ; Arg6
 
index ec7444c..1360b19 100644 (file)
@@ -105,5 +105,7 @@ extern void SHORTREL(struct sShortSpinlock *Lock);
 extern void    Debug_PutCharDebug(char ch);
 extern void    Debug_PutStringDebug(const char *Str);
 
+extern void    __AtomicTestSetLoop(Uint *Ptr, Uint Value);
+
 #endif
 
index 120afb3..b03875f 100644 (file)
@@ -48,6 +48,7 @@
 
 #define        MM_USER_MIN     0x00000000##00010000
 #define USER_LIB_MAX   0x00007000##00000000
+#define MM_USER_MAX    USER_LIB_MAX
 #define USER_STACK_PREALLOC    0x00000000##00002000    // 8 KiB
 #define USER_STACK_SZ  0x00000000##00020000    // 64 KiB
 #define USER_STACK_TOP 0x00008000##00000000
index b35db69..60770f6 100644 (file)
@@ -88,6 +88,8 @@ void SHORTLOCK(struct sShortSpinlock *Lock)
                Lock->Depth ++;
                return ;
        }
+       #else
+       ASSERT( !CPU_HAS_LOCK(Lock) );
        #endif
        
        // Wait for another CPU to release
@@ -146,6 +148,18 @@ void SHORTREL(struct sShortSpinlock *Lock)
        #endif
 }
 
+void __AtomicTestSetLoop(Uint *Ptr, Uint Value)
+{
+       __ASM__(
+               "1:\n\t"
+               "xor %%eax, %%eax;\n\t"
+               "lock cmpxchg %0, (%1);\n\t"    // if( Ptr==0 ) { ZF=1; Ptr=Value } else { ZF=0; _=Ptr }
+               "jnz 1b;\n\t"
+               :: "r"(Value), "r"(Ptr)
+               : "eax" // EAX clobbered
+               );
+}
+
 // === DEBUG IO ===
 #if USE_GDB_STUB
 void initGdbSerial(void)
@@ -358,11 +372,11 @@ void *memset(void *__dest, int __val, size_t __count)
                __asm__ __volatile__ ("rep stosb" : : "D"(__dest),"a"(__val),"c"(__count));
        else {
                Uint8   *dst = __dest;
+               size_t  qwords = __count / 8;
+               size_t  trail_bytes = __count % 8;
 
-               __asm__ __volatile__ ("rep stosq" : : "D"(dst),"a"(0),"c"(__count/8));
-               dst += __count & ~7;
-               __count = __count & 7;
-               while( __count-- )
+               __asm__ __volatile__ ("rep stosq" : "=D"(dst) : "D"(dst),"a"(0),"c"(qwords));
+               while( trail_bytes-- )
                        *dst++ = 0;
        }
        return __dest;
index 4e2968f..23f04ac 100644 (file)
 #define INVLPG_ALL()   __asm__ __volatile__ ("mov %cr3,%rax;\n\tmov %rax,%cr3;")
 #define INVLPG_GLOBAL()        __asm__ __volatile__ ("mov %cr4,%rax;\n\txorl $0x80, %eax;\n\tmov %rax,%cr4;\n\txorl $0x80, %eax;\n\tmov %rax,%cr4")
 
+// TODO: INVLPG_ALL is expensive
+#define GET_TEMP_MAPPING(cr3) do { \
+       __ASM__("cli"); \
+       __AtomicTestSetLoop( (Uint *)&TMPCR3(), (cr3) | 3 ); \
+       INVLPG_ALL(); \
+} while(0)
+#define REL_TEMP_MAPPING() do { \
+       TMPCR3() = 0; \
+       __ASM__("sti"); \
+} while(0)
+
 // === CONSTS ===
 //tPAddr       * const gaPageTable = MM_FRACTAL_BASE;
 
@@ -70,6 +81,7 @@ void  MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable
 void   MM_int_DumpTablesEnt(tVAddr RangeStart, size_t Length, tPAddr Expected);
 //void MM_DumpTables(tVAddr Start, tVAddr End);
  int   MM_GetPageEntryPtr(tVAddr Addr, BOOL bTemp, BOOL bAllocate, BOOL bLargePage, tPAddr **Pointer);
+tPAddr MM_GetPageFromAS(tProcess *Process, volatile const void *Addr);
  int   MM_MapEx(volatile void *VAddr, tPAddr PAddr, BOOL bTemp, BOOL bLarge);
 // int MM_Map(tVAddr VAddr, tPAddr PAddr);
 void   MM_Unmap(tVAddr VAddr);
@@ -78,7 +90,6 @@ void  MM_int_ClearTableLevel(tVAddr VAddr, int LevelBits, int MaxEnts);
  int   MM_GetPageEntry(tVAddr Addr, tPAddr *Phys, Uint *Flags);
 
 // === GLOBALS ===
-tMutex glMM_TempFractalLock;
 tShortSpinlock glMM_ZeroPage;
 tPAddr gMM_ZeroPage;
 
@@ -260,7 +271,7 @@ int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs)
        // Print Stack Backtrace
        Error_Backtrace(Regs->RIP, Regs->RBP);
        
-       MM_DumpTables(0, -1);
+       //MM_DumpTables(0, -1);
 
        return 1;       
 }
@@ -301,8 +312,6 @@ void MM_DumpTables(tVAddr Start, tVAddr End)
        const tPAddr    MASK = ~CHANGEABLE_BITS;        // Physical address and access bits
        tVAddr  rangeStart = 0;
        tPAddr  expected = CHANGEABLE_BITS;     // CHANGEABLE_BITS is used because it's not a vaild value
-       tVAddr  curPos;
-       Uint    page;
        tPAddr  expected_pml4 = PF_WRITE|PF_USER;       
        tPAddr  expected_pdp = PF_WRITE|PF_USER;        
        tPAddr  expected_pd = PF_WRITE|PF_USER; 
@@ -311,11 +320,12 @@ void MM_DumpTables(tVAddr Start, tVAddr End)
        
        End &= (1L << 48) - 1;
        
-       Start >>= 12;   End >>= 12;
+       Start >>= 12;
+       End >>= 12;
        
-       for(page = Start, curPos = Start<<12;
-               page < End;
-               curPos += 0x1000, page++)
+       // `page` will not overflow, End is 48-12 bits
+       tVAddr  curPos = Start << 12;
+       for(Uint page = Start; page <= End; curPos += 0x1000, page++)
        {
                //Debug("&PAGEMAPLVL4(%i page>>27) = %p", page>>27, &PAGEMAPLVL4(page>>27));
                //Debug("&PAGEDIRPTR(%i page>>18) = %p", page>>18, &PAGEDIRPTR(page>>18));
@@ -486,7 +496,7 @@ int MM_MapEx(volatile void *VAddr, tPAddr PAddr, BOOL bTemp, BOOL bLarge)
        
        *ent = PAddr | 3;
 
-       if( (tVAddr)VAddr < USER_MAX )
+       if( (tVAddr)VAddr <= USER_MAX )
                *ent |= PF_USER;
        INVLPG( VAddr );
 
@@ -626,6 +636,27 @@ tPAddr MM_GetPhysAddr(volatile const void *Ptr)
        return (*ptr & PADDR_MASK) | (Addr & 0xFFF);
 }
 
+/**
+ * \brief Get the address of a page from another addres space
+ * \return Refenced physical address (or 0 on error)
+ */
+tPAddr MM_GetPageFromAS(tProcess *Process, volatile const void *Addr)
+{
+       GET_TEMP_MAPPING(Process->MemState.CR3);
+       tPAddr  ret = 0;
+       tPAddr *ptr;
+       if(MM_GetPageEntryPtr((tVAddr)Addr, 1,0,0, &ptr) == 0)  // Temp, NoAlloc, NotLarge
+       {
+               if( *ptr & 1 )
+               {
+                       ret = (*ptr & ~0xFFF) | ((tVAddr)Addr & 0xFFF);
+                       MM_RefPhys( ret );
+               }
+       }
+       REL_TEMP_MAPPING();
+       return ret;
+}
+
 /**
  * \brief Sets the flags on a page
  */
@@ -862,15 +893,16 @@ void *MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        void    *ret;
        
        // Sanity Check
-       if(MaxBits < 12 || !PhysAddr)   return 0;
+       ASSERTCR(MaxBits, >=, 12, NULL);
        
        // Fast Allocate
        if(Pages == 1 && MaxBits >= PHYS_BITS)
        {
                phys = MM_AllocPhys();
-               *PhysAddr = phys;
                ret = MM_MapHWPages(phys, 1);
                MM_DerefPhys(phys);
+               if(PhysAddr)
+                       *PhysAddr = phys;
                return ret;
        }
        
@@ -881,7 +913,8 @@ void *MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        
        // Allocated successfully, now map
        ret = MM_MapHWPages(phys, Pages);
-       *PhysAddr = phys;
+       if(PhysAddr)
+               *PhysAddr = phys;
        // MapHWPages references the pages, so deref them back down to 1
        for(;Pages--;phys+=0x1000)
                MM_DerefPhys(phys);
@@ -898,9 +931,8 @@ void *MM_MapTemp(tPAddr PAddr)
 {
        const int max_slots = (MM_TMPMAP_END - MM_TMPMAP_BASE) / PAGE_SIZE;
        tVAddr  ret = MM_TMPMAP_BASE;
-        int    i;
        
-       for( i = 0; i < max_slots; i ++, ret += PAGE_SIZE )
+       for( int i = 0; i < max_slots; i ++, ret += PAGE_SIZE )
        {
                tPAddr  *ent;
                if( MM_GetPageEntryPtr( ret, 0, 1, 0, &ent) < 0 ) {
@@ -918,6 +950,15 @@ void *MM_MapTemp(tPAddr PAddr)
        return 0;
 }
 
+void *MM_MapTempFromProc(tProcess *Process, const void *VAddr)
+{
+       // Get paddr
+       tPAddr  paddr = MM_GetPageFromAS(Process, VAddr);
+       if( paddr == 0 )
+               return NULL;
+       return MM_MapTemp(paddr);
+}
+
 void MM_FreeTemp(void *Ptr)
 {
        MM_Deallocate(Ptr);
@@ -935,9 +976,7 @@ tPAddr MM_Clone(int bNoUserCopy)
        if(!ret)        return 0;
        
        // #2 Alter the fractal pointer
-       Mutex_Acquire(&glMM_TempFractalLock);
-       TMPCR3() = ret | 3;
-       INVLPG_ALL();
+       GET_TEMP_MAPPING(ret);
        
        // #3 Set Copy-On-Write to all user pages
        if( Threads_GetPID() != 0 && !bNoUserCopy )
@@ -1015,9 +1054,7 @@ tPAddr MM_Clone(int bNoUserCopy)
 //     MAGIC_BREAK();
 
        // #7 Return
-       TMPCR3() = 0;
-       INVLPG_ALL();
-       Mutex_Release(&glMM_TempFractalLock);
+       REL_TEMP_MAPPING();
 //     Log("MM_Clone: RETURN %P", ret);
        return ret;
 }
@@ -1061,9 +1098,7 @@ tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize)
         int    i;
        
        // #1 Set temp fractal to PID0
-       Mutex_Acquire(&glMM_TempFractalLock);
-       TMPCR3() = ((tPAddr)gInitialPML4 - KERNEL_BASE) | 3;
-       INVLPG_ALL();
+       GET_TEMP_MAPPING( ((tPAddr)gInitialPML4 - KERNEL_BASE) );
        
        // #2 Scan for a free stack addresss < 2^47
        for(ret = 0x100000; ret < (1ULL << 47); ret += KERNEL_STACK_SIZE)
@@ -1073,7 +1108,7 @@ tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize)
                if( !(*ptr & 1) )       break;
        }
        if( ret >= (1ULL << 47) ) {
-               Mutex_Release(&glMM_TempFractalLock);
+               REL_TEMP_MAPPING();
                return 0;
        }
        
@@ -1105,8 +1140,7 @@ tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize)
                MM_FreeTemp(tmp_addr);
        }
 
-       TMPCR3() = 0;
-       Mutex_Release(&glMM_TempFractalLock);
+       REL_TEMP_MAPPING();
        
        return ret + i*0x1000;
 }
index aff670a..afde354 100644 (file)
@@ -6,6 +6,8 @@
 [section .text]
 
 [extern Threads_Exit]
+[extern glThreadListLock]
+[extern SHORTREL]
 
 [global GetRIP]
 GetRIP:
@@ -18,6 +20,9 @@ NewTaskHeader:
        ; [rsp+0x08]: Function
        ; [rsp+0x10]: Argument
 
+       mov rdi, glThreadListLock
+       call SHORTREL
+       
        mov rdi, [rsp+0x10]
        mov rax, [rsp+0x8]
        add rsp, 0x10   ; Reclaim stack space (thread/fcn)
index 50b5054..7c73bf9 100644 (file)
@@ -508,7 +508,10 @@ tTID Proc_Clone(Uint Flags)
        
        // Save core machine state
        rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3, !!(Flags & CLONE_NOUSER));
-       if(rip == 0)    return 0;       // Child
+       if(rip == 0) {
+               SHORTREL(&glThreadListLock);
+               return 0;       // Child
+       }
        newThread->KernelStack = cur->KernelStack;
        newThread->SavedState.RIP = rip;
        newThread->SavedState.SSE = NULL;
@@ -735,62 +738,61 @@ void Proc_DumpThreadCPUState(tThread *Thread)
 
 void Proc_Reschedule(void)
 {
-       tThread *nextthread, *curthread;
         int    cpu = GetCPUNum();
 
-       // TODO: Wait for it?
-       if(IS_LOCKED(&glThreadListLock))        return;
-       
-       curthread = gaCPUs[cpu].Current;
-
-       nextthread = Threads_GetNextToRun(cpu, curthread);
+       if(CPU_HAS_LOCK(&glThreadListLock))
+               return;
+       SHORTLOCK(&glThreadListLock);
 
-       if(nextthread == curthread)     return ;
+       tThread *curthread = gaCPUs[cpu].Current;
+       tThread *nextthread = Threads_GetNextToRun(cpu, curthread);
+       
        if(!nextthread)
                nextthread = gaCPUs[cpu].IdleThread;
-       if(!nextthread)
-               return ;
-
-       #if DEBUG_TRACE_SWITCH
-       LogF("\nSwitching to task CR3 = 0x%x, RIP = %p, RSP = %p - %i (%s)\n",
-               nextthread->Process->MemState.CR3,
-               nextthread->SavedState.RIP,
-               nextthread->SavedState.RSP,
-               nextthread->TID,
-               nextthread->ThreadName
-               );
-       #endif
-
-       // Update CPU state
-       gaCPUs[cpu].Current = nextthread;
-       gTSSs[cpu].RSP0 = nextthread->KernelStack-sizeof(void*);
-       __asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
 
-       if( curthread )
+       if(nextthread && nextthread != curthread)
        {
-               // Save FPU/MMX/XMM/SSE state
-               if( curthread->SavedState.SSE )
+               #if DEBUG_TRACE_SWITCH
+               LogF("\nSwitching to task CR3 = 0x%x, RIP = %p, RSP = %p - %i (%s)\n",
+                       nextthread->Process->MemState.CR3,
+                       nextthread->SavedState.RIP,
+                       nextthread->SavedState.RSP,
+                       nextthread->TID,
+                       nextthread->ThreadName
+                       );
+               #endif
+
+               // Update CPU state
+               gaCPUs[cpu].Current = nextthread;
+               gTSSs[cpu].RSP0 = nextthread->KernelStack-sizeof(void*);
+               __asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
+
+               if( curthread )
                {
-                       Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
-                       curthread->SavedState.bSSEModified = 0;
-                       Proc_DisableSSE();
+                       // Save FPU/MMX/XMM/SSE state
+                       if( curthread->SavedState.SSE )
+                       {
+                               Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
+                               curthread->SavedState.bSSEModified = 0;
+                               Proc_DisableSSE();
+                       }
+                       SwitchTasks(
+                               nextthread->SavedState.RSP, &curthread->SavedState.RSP,
+                               nextthread->SavedState.RIP, &curthread->SavedState.RIP,
+                               nextthread->Process->MemState.CR3
+                               );
+               }
+               else
+               {
+                       Uint    tmp;
+                       SwitchTasks(
+                               nextthread->SavedState.RSP, &tmp,
+                               nextthread->SavedState.RIP, &tmp,
+                               nextthread->Process->MemState.CR3
+                               );
                }
-               SwitchTasks(
-                       nextthread->SavedState.RSP, &curthread->SavedState.RSP,
-                       nextthread->SavedState.RIP, &curthread->SavedState.RIP,
-                       nextthread->Process->MemState.CR3
-                       );
-       }
-       else
-       {
-               Uint    tmp;
-               SwitchTasks(
-                       nextthread->SavedState.RSP, &tmp,
-                       nextthread->SavedState.RIP, &tmp,
-                       nextthread->Process->MemState.CR3
-                       );
        }
-       return ;
+       SHORTREL(&glThreadListLock);
 }
 
 /**
index 7f65d89..37172cf 100644 (file)
@@ -15,8 +15,8 @@
 #if BITS <= 32\r
 # define DISABLE_ELF64\r
 #endif\r
-static int     GetSymbol(const char *Name, void **Value, size_t *Size);\r
-static int     GetSymbol(const char *Name, void **Value, size_t *Size) {\r
+static int     GetSymbol(const char *Name, void **Value, size_t *Size, void *IgnoreBase);\r
+static int     GetSymbol(const char *Name, void **Value, size_t *Size, void *IgnoreBase) {\r
        Uint val;\r
        if(!Binary_GetSymbol(Name, &val)) {\r
                Log_Notice("ELF", "Lookup of '%s' failed", Name);\r
@@ -205,15 +205,14 @@ tBinary *Elf_Load32(int FD, Elf32_Ehdr *Header)
 {\r
        tBinary *ret;\r
        Elf32_Phdr      *phtab;\r
-        int    i, j;\r
-        int    iLoadCount;\r
+        int    j;\r
 \r
        ENTER("xFD", FD);\r
 \r
        // Check architecture with current CPU\r
        // - TODO: Support kernel level emulation\r
        #if ARCH_IS_x86\r
-       if( Header->machine != EM_386 )\r
+       if( Header->e_machine != EM_386 )\r
        {\r
                Log_Warning("ELF", "Unknown architecure on ELF-32");\r
                LEAVE_RET('n');\r
@@ -222,7 +221,7 @@ tBinary *Elf_Load32(int FD, Elf32_Ehdr *Header)
        #endif\r
 \r
        // Check for a program header\r
-       if(Header->phoff == 0) {\r
+       if(Header->e_phoff == 0) {\r
                #if DEBUG_WARN\r
                Log_Warning("ELF", "File does not contain a program header (phoff == 0)");\r
                #endif\r
@@ -231,25 +230,25 @@ tBinary *Elf_Load32(int FD, Elf32_Ehdr *Header)
        }\r
        \r
        // Read Program Header Table\r
-       phtab = malloc( sizeof(Elf32_Phdr) * Header->phentcount );\r
+       phtab = malloc( sizeof(Elf32_Phdr) * Header->e_phnum );\r
        if( !phtab ) {\r
                LEAVE('n');\r
                return NULL;\r
        }\r
-       LOG("hdr.phoff = 0x%08x", Header->phoff);\r
-       VFS_Seek(FD, Header->phoff, SEEK_SET);\r
-       VFS_Read(FD, sizeof(Elf32_Phdr)*Header->phentcount, phtab);\r
+       LOG("hdr.phoff = 0x%08x", Header->e_phoff);\r
+       VFS_Seek(FD, Header->e_phoff, SEEK_SET);\r
+       VFS_Read(FD, sizeof(Elf32_Phdr)*Header->e_phnum, phtab);\r
        \r
        // Count Pages\r
-       iLoadCount = 0;\r
-       LOG("Header->phentcount = %i", Header->phentcount);\r
-       for( i = 0; i < Header->phentcount; i++ )\r
+       unsigned iLoadCount = 0;\r
+       LOG("Header->phentcount = %i", Header->e_phnum);\r
+       for( int i = 0; i < Header->e_phnum; i++ )\r
        {\r
                // Ignore Non-LOAD types\r
-               if(phtab[i].Type != PT_LOAD)\r
+               if(phtab[i].p_type != PT_LOAD)\r
                        continue;\r
                iLoadCount ++;\r
-               LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}", i, phtab[i].VAddr, phtab[i].MemSize);\r
+               LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}", i, phtab[i].p_vaddr, phtab[i].p_memsz);\r
        }\r
        \r
        LOG("iLoadCount = %i", iLoadCount);\r
@@ -257,56 +256,55 @@ tBinary *Elf_Load32(int FD, Elf32_Ehdr *Header)
        // Allocate Information Structure\r
        ret = malloc( sizeof(tBinary) + sizeof(tBinarySection)*iLoadCount );\r
        // Fill Info Struct\r
-       ret->Entry = Header->entrypoint;\r
+       ret->Entry = Header->e_entry;\r
        ret->Base = -1;         // Set Base to maximum value\r
        ret->NumSections = iLoadCount;\r
        ret->Interpreter = NULL;\r
        \r
        // Load Pages\r
        j = 0;\r
-       for( i = 0; i < Header->phentcount; i++ )\r
+       for( int i = 0; i < Header->e_phnum; i++ )\r
        {\r
                //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
                LOG("phtab[%i] = {", i);\r
-               LOG(" .Type = 0x%08x", phtab[i].Type);\r
-               LOG(" .Offset = 0x%08x", phtab[i].Offset);\r
-               LOG(" .VAddr = 0x%08x", phtab[i].VAddr);\r
-               LOG(" .PAddr = 0x%08x", phtab[i].PAddr);\r
-               LOG(" .FileSize = 0x%08x", phtab[i].FileSize);\r
-               LOG(" .MemSize = 0x%08x", phtab[i].MemSize);\r
-               LOG(" .Flags = 0x%08x", phtab[i].Flags);\r
-               LOG(" .Align = 0x%08x", phtab[i].Align);\r
+               LOG(" .Type = 0x%08x",   phtab[i].p_type);\r
+               LOG(" .Offset = 0x%08x", phtab[i].p_offset);\r
+               LOG(" .VAddr = 0x%08x",  phtab[i].p_vaddr);\r
+               LOG(" .PAddr = 0x%08x",  phtab[i].p_paddr);\r
+               LOG(" .FileSize = 0x%08x", phtab[i].p_filesz);\r
+               LOG(" .MemSize = 0x%08x", phtab[i].p_memsz);\r
+               LOG(" .Flags = 0x%08x",  phtab[i].p_flags);\r
+               LOG(" .Align = 0x%08x",  phtab[i].p_align);\r
                LOG(" }");\r
                // Get Interpreter Name\r
-               if( phtab[i].Type == PT_INTERP )\r
+               if( phtab[i].p_type == PT_INTERP )\r
                {\r
-                       char *tmp;\r
                        if(ret->Interpreter)    continue;\r
-                       tmp = malloc(phtab[i].FileSize);\r
-                       VFS_Seek(FD, phtab[i].Offset, 1);\r
-                       VFS_Read(FD, phtab[i].FileSize, tmp);\r
+                       char* tmp = malloc(phtab[i].p_filesz);\r
+                       VFS_Seek(FD, phtab[i].p_offset, 1);\r
+                       VFS_Read(FD, phtab[i].p_filesz, tmp);\r
                        ret->Interpreter = Binary_RegInterp(tmp);\r
                        LOG("Interpreter '%s'", tmp);\r
                        free(tmp);\r
                        continue;\r
                }\r
                // Ignore non-LOAD types\r
-               if(phtab[i].Type != PT_LOAD)    continue;\r
+               if(phtab[i].p_type != PT_LOAD)  continue;\r
                \r
                // Find Base\r
-               if(phtab[i].VAddr < ret->Base)  ret->Base = phtab[i].VAddr;\r
+               if(phtab[i].p_vaddr < ret->Base)        ret->Base = phtab[i].p_vaddr;\r
                \r
                LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}",\r
-                       i, phtab[i].VAddr, phtab[i].Offset, phtab[i].FileSize);\r
+                       i, phtab[i].p_vaddr, phtab[i].p_offset, phtab[i].p_filesz);\r
                \r
-               ret->LoadSections[j].Offset = phtab[i].Offset;\r
-               ret->LoadSections[j].FileSize = phtab[i].FileSize;\r
-               ret->LoadSections[j].Virtual = phtab[i].VAddr;\r
-               ret->LoadSections[j].MemSize = phtab[i].MemSize;\r
+               ret->LoadSections[j].Offset   = phtab[i].p_offset;\r
+               ret->LoadSections[j].FileSize = phtab[i].p_filesz;\r
+               ret->LoadSections[j].Virtual  = phtab[i].p_vaddr;\r
+               ret->LoadSections[j].MemSize  = phtab[i].p_memsz;\r
                ret->LoadSections[j].Flags = 0;\r
-               if( !(phtab[i].Flags & PF_W) )\r
+               if( !(phtab[i].p_flags & PF_W) )\r
                        ret->LoadSections[j].Flags |= BIN_SECTFLAG_RO;\r
-               if( phtab[i].Flags & PF_X )\r
+               if( phtab[i].p_flags & PF_X )\r
                        ret->LoadSections[j].Flags |= BIN_SECTFLAG_EXEC;\r
                j ++;\r
        }\r
index 3dab6a9..5170dac 100644 (file)
@@ -231,23 +231,19 @@ int Proc_int_Execve(const char *File, const char **ArgV, const char **EnvP, int
        }
 
        // --- Get argc 
-       for( argc = 0; ArgV && ArgV[argc]; argc ++ );
+       for( argc = 0; ArgV && ArgV[argc]; argc ++ )
+               ;
        
        // --- Set Process Name
        Threads_SetName(File);
        
        // --- Clear User Address space
-       // NOTE: This is a little roundabout, maybe telling ClearUser to not touch the
-       //       PPD area would be a better idea.
        if( bClearUser )
        {
-                int    nfd = *Threads_GetMaxFD();
-               void    *handles;
-               handles = VFS_SaveHandles(nfd, NULL);
-               VFS_CloseAllUserHandles();
+               // MM_ClearUser should preserve handles
                MM_ClearUser();
-               VFS_RestoreHandles(nfd, handles);
-               VFS_FreeSavedHandles(nfd, handles);
+               // - NOTE: Not a reliable test, but helps for now
+               ASSERTC( VFS_IOCtl(0, 0, NULL), !=, -1 );
        }
        
        // --- Load new binary
@@ -334,6 +330,8 @@ tVAddr Binary_Load(const char *Path, tVAddr *EntryPoint)
        if(pBinary->Interpreter) {
                tVAddr  start;
                if( Binary_Load(pBinary->Interpreter, &start) == 0 ) {
+                       Log_Error("Binary", "Can't load interpeter '%s' for '%s'",
+                               pBinary->Interpreter, Path);
                        LEAVE('x', 0);
                        return 0;
                }
index d0de25a..eed38de 100644 (file)
@@ -7,7 +7,7 @@
 #include <debug_hooks.h>
 
 #define        DEBUG_MAX_LINE_LEN      256
-#define        LOCK_DEBUG_OUTPUT       1       // Avoid interleaving of output lines?
+#define        LOCK_DEBUG_OUTPUT       0       // Avoid interleaving of output lines?
 #define TRACE_TO_KTERM         0       // Send ENTER/DEBUG/LEAVE to debug?
 
 // === IMPORTS ===
@@ -21,7 +21,7 @@ static void   Debug_Putchar(char ch);
 static void    Debug_Puts(int bUseKTerm, const char *Str);
 void   Debug_DbgOnlyFmt(const char *format, va_list args);
 void   Debug_FmtS(int bUseKTerm, const char *format, ...);
-void   Debug_Fmt(int bUseKTerm, const char *format, va_list args);
+bool   Debug_Fmt(int bUseKTerm, const char *format, va_list args);
 void   Debug_SetKTerminal(const char *File);
 
 // === GLOBALS ===
@@ -77,9 +77,8 @@ static void Debug_Puts(int UseKTerm, const char *Str)
                IPStack_SendDebugText(Str);
 
        // Output to the kernel terminal
-       if( UseKTerm && gbDebug_IsKPanic < 2 && giDebug_KTerm != -1)
+       if( UseKTerm && gbDebug_IsKPanic < 2 && giDebug_KTerm != -1 && gbInPutChar == 0)
        {
-               if(gbInPutChar) return ;
                gbInPutChar = 1;
                VFS_Write(giDebug_KTerm, len, Str);
                gbInPutChar = 0;
@@ -91,17 +90,18 @@ void Debug_DbgOnlyFmt(const char *format, va_list args)
        Debug_Fmt(0, format, args);
 }
 
-void Debug_Fmt(int bUseKTerm, const char *format, va_list args)
+bool Debug_Fmt(int bUseKTerm, const char *format, va_list args)
 {
        char    buf[DEBUG_MAX_LINE_LEN];
        buf[DEBUG_MAX_LINE_LEN-1] = 0;
-       int len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
+       size_t len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
        Debug_Puts(bUseKTerm, buf);
        if( len > DEBUG_MAX_LINE_LEN-1 ) {
                // do something
                Debug_Puts(bUseKTerm, "[...]");
+               return false;
        }
-       return ;
+       return true;
 }
 
 void Debug_FmtS(int bUseKTerm, const char *format, ...)
@@ -131,25 +131,27 @@ void Debug_KernelPanic(void)
 /**
  * \fn void LogF(const char *Msg, ...)
  * \brief Raw debug log (no new line, no prefix)
+ * \return True if all of the provided text was printed
  */
-void LogF(const char *Fmt, ...)
+bool LogF(const char *Fmt, ...)
 {
-       va_list args;
-
        #if LOCK_DEBUG_OUTPUT
-       if(CPU_HAS_LOCK(&glDebug_Lock)) return ;
+       if(CPU_HAS_LOCK(&glDebug_Lock)) {
+               Debug_Puts("[#]");
+               return true;
+       }
        SHORTLOCK(&glDebug_Lock);
        #endif
        
+       va_list args;
        va_start(args, Fmt);
-
-       Debug_Fmt(1, Fmt, args);
-
+       bool rv = Debug_Fmt(1, Fmt, args);
        va_end(args);
        
        #if LOCK_DEBUG_OUTPUT
        SHORTREL(&glDebug_Lock);
        #endif
+       return rv;
 }
 /**
  * \fn void Debug(const char *Msg, ...)
@@ -249,12 +251,12 @@ void Panic(const char *Fmt, ...)
        
        Debug_KernelPanic();
        
+       Debug_Puts(1, "\x1b[31m");
        Debug_Puts(1, "Panic: ");
        va_start(args, Fmt);
        Debug_Fmt(1, Fmt, args);
        va_end(args);
-       Debug_Putchar('\r');
-       Debug_Putchar('\n');
+       Debug_Puts(1, "\x1b[0m\r\n");
 
        Proc_PrintBacktrace();
        //Threads_Dump();
@@ -265,16 +267,13 @@ void Panic(const char *Fmt, ...)
 
 void Debug_SetKTerminal(const char *File)
 {
-        int    tmp;
        if(giDebug_KTerm != -1) {
-               tmp = giDebug_KTerm;
+               // Clear FD to -1 before closing (prevents writes to closed FD)
+               int oldfd = giDebug_KTerm;
                giDebug_KTerm = -1;
-               VFS_Close(tmp);
+               VFS_Close(oldfd);
        }
-       tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
-//     Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
-       giDebug_KTerm = tmp;
-//     Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
+       giDebug_KTerm = VFS_Open(File, VFS_OPENFLAG_WRITE);
 }
 
 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
@@ -431,16 +430,16 @@ void Debug_HexDump(const char *Header, const void *Data, size_t Length)
        Uint    pos = 0;
        LogF("%014lli ", now());
        Debug_Puts(1, Header);
-       LogF(" (Hexdump of %p)\r\n", Data);
+       LogF(" (Hexdump of %p+%i)\r\n", Data, Length);
 
        #define CH(n)   ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
 
        while(Length >= 16)
        {
                LogF("%014lli Log: %04x:"
-                       " %02x %02x %02x %02x %02x %02x %02x %02x"
-                       " %02x %02x %02x %02x %02x %02x %02x %02x"
-                       "  %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
+                       " %02x %02x %02x %02x %02x %02x %02x %02x "
+                       " %02x %02x %02x %02x %02x %02x %02x %02x "
+                       " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
                        now(),
                        pos,
                        cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
index c13ca2a..667190e 100644 (file)
@@ -34,6 +34,7 @@ struct sIPCPipe_Endpoint
        tMutex  lList;
        tIPCPipe_Packet *OutHead;
        tIPCPipe_Packet *OutTail;
+       size_t  ByteCount;
        tVFS_Node       Node;
 };
 struct sIPCPipe_Channel
@@ -50,8 +51,8 @@ struct sIPCPipe_Server
        tIPCPipe_Server *Prev;
        char    *Name;
        size_t  MaxBlockSize;   // Max size of a 'packet'
-       size_t  QueueByteLimit; // Maximum number of bytes held in kernel for this server
-       size_t  CurrentByteCount;
+       // NOTE: Not strictly enforced, can go MaxBlockSize-1 over
+       size_t  QueueByteLimit; // Maximum number of bytes held in kernel for each endpoint
        tVFS_Node       ServerNode;
        tRWLock lChannelList;
        tIPCPipe_Channel        *FirstClient;
@@ -85,6 +86,7 @@ tVFS_NodeType gIPCPipe_ServerNodeType = {
 };
 tVFS_NodeType  gIPCPipe_ChannelNodeType = {
        .TypeName = "IPC Pipe - Channel",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read = IPCPipe_Client_Read,
        .Write = IPCPipe_Client_Write,
        .Close = IPCPipe_Client_Close
@@ -210,8 +212,10 @@ tVFS_Node *IPCPipe_Root_FindDir(tVFS_Node *Node, const char *Name, Uint Flags)
        new_client->Server = srv;
        new_client->ClientEP.Node.Type = &gIPCPipe_ChannelNodeType;
        new_client->ClientEP.Node.ImplPtr = new_client;
+       new_client->ClientEP.Node.Size = -1;
        new_client->ServerEP.Node.Type = &gIPCPipe_ChannelNodeType;
        new_client->ServerEP.Node.ImplPtr = new_client;
+       new_client->ServerEP.Node.Size = -1;
 
        // Append to server list
        RWLock_AcquireWrite(&srv->lChannelList);
@@ -324,13 +328,13 @@ size_t IPCPipe_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *D
        
        // Wait for a packet to be ready
        tTime   timeout_z = 0, *timeout = ((Flags & VFS_IOFLAG_NOBLOCK) ? &timeout_z : NULL);
-       int rv = VFS_SelectNode(Node, VFS_SELECT_READ, timeout, "IPCPipe Endpoint");
+       int rv = VFS_SelectNode(Node, VFS_SELECT_READ|VFS_SELECT_ERROR, timeout, "IPCPipe Endpoint");
        if( !rv ) {
                errno = (Flags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
                LEAVE('i', -1);
                return -1;
        }
-       if( channel->Server == NULL ) {
+       if( (rv & VFS_SELECT_ERROR) || channel->Server == NULL ) {
                //errno = EIO;
                LEAVE('i', -1);
                return -1;
@@ -351,6 +355,7 @@ size_t IPCPipe_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *D
        if(!rep->OutHead)
                rep->OutTail = NULL;
        VFS_MarkAvaliable(Node, !!rep->OutHead);
+       VFS_MarkFull(&rep->Node, 0);    //      Just read a packet, remote shouldn't be full
        Mutex_Release(&rep->lList);
 
        // Return
@@ -363,7 +368,7 @@ size_t IPCPipe_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *D
        }
        else
        {
-               Log_Warning("IPCPipe", "No packet ready but semaphore returned");
+               Log_Warning("IPCPipe", "No packet ready but select returned");
        }
        
        LEAVE('i', ret);
@@ -387,8 +392,21 @@ size_t IPCPipe_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const
                LEAVE('i', 0);
                return 0;
        }
-
-       // TODO: Ensure that no more than DEF_MAX_BYTE_LIMIT bytes are in flight at one time
+       
+       // Wait for a packet to be ready
+       tTime   timeout_z = 0, *timeout = ((Flags & VFS_IOFLAG_NOBLOCK) ? &timeout_z : NULL);
+       int rv = VFS_SelectNode(Node, VFS_SELECT_WRITE|VFS_SELECT_ERROR, timeout, "IPCPipe Endpoint");
+       ASSERTC(rv, >=, 0);
+       if( !rv ) {
+               errno = (Flags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+               LEAVE('i', -1);
+               return -1;
+       }
+       if( (rv & VFS_SELECT_ERROR) ||  channel->Server == NULL ) {
+               //errno = EIO;
+               LEAVE('i', -1);
+               return -1;
+       }
 
        // Create packet structure
        tIPCPipe_Packet *pkt = malloc(sizeof(tIPCPipe_Packet)+Length);
@@ -413,6 +431,12 @@ size_t IPCPipe_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const
        else
                lep->OutHead = pkt;
        lep->OutTail = pkt;
+       
+       lep->ByteCount += Length;
+       if( lep->ByteCount >= channel->Server->QueueByteLimit ) {
+               VFS_MarkFull(Node, 1);
+       }
+       
        Mutex_Release(&lep->lList);
 
        // Signal other end
index de3192a..6d5d483 100644 (file)
 #include <modules.h>
 #include <fs_devfs.h>
 #include <semaphore.h>
+#include <memfs_helpers.h>
 
 // === CONSTANTS ===
 #define DEFAULT_RING_SIZE      2048
 #define PF_BLOCKING            1
 
 // === TYPES ===
-typedef struct sPipe {
-       struct sPipe    *Next;
-       char    *Name;
+typedef struct sPipe
+{
+       tMemFS_FileHdr  FileHdr;
        tVFS_Node       Node;
        Uint    Flags;
         int    ReadPos;
@@ -42,6 +43,9 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, 0x0032, FIFO, FIFO_Install, NULL, NULL);
+tMemFS_DirHdr  gFIFO_RootDir = {
+       .FileHdr = { .Name = "FIFO" },
+};
 tVFS_NodeType  gFIFO_DirNodeType = {
        .TypeName = "FIFO Dir Node",
        .ReadDir = FIFO_ReadDir,
@@ -71,7 +75,6 @@ tVFS_Node     gFIFO_AnonNode = {
        .NumACLs = 1,
        .ACLs = &gVFS_ACL_EveryoneRW,
        };
-tPipe  *gFIFO_NamedPipes = NULL;
 
 // === CODE ===
 /**
@@ -80,6 +83,7 @@ tPipe *gFIFO_NamedPipes = NULL;
  */
 int FIFO_Install(char **Options)
 {
+       MemFS_InitDir( &gFIFO_RootDir );
        DevFS_AddDevice( &gFIFO_DriverInfo );
        return MODULE_ERR_OK;
 }
@@ -98,22 +102,14 @@ int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
  */
 int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
 {
-       tPipe   *tmp = gFIFO_NamedPipes;
-       
        // Entry 0 is Anon Pipes
-       if(Id == 0) {
+       if(Id == 0)
+       {
                strcpy(Dest, "anon");
                return 0;
        }
        
-       // Find the id'th node
-       while(--Id && tmp)      tmp = tmp->Next;
-       // If the list ended, error return
-       if(!tmp)
-               return -EINVAL;
-       // Return good
-       strncpy(Dest, tmp->Name, FILENAME_MAX);
-       return 0;
+       return MemFS_ReadDir(&gFIFO_RootDir, Id-1, Dest);
 }
 
 /**
@@ -123,11 +119,8 @@ int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
  */
 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
 {
-       tPipe   *tmp;
-       if(!Filename)   return NULL;
-       
-       // NULL String Check
-       if(Filename[0] == '\0') return NULL;
+       ASSERTR(Filename, NULL);
+       ASSERTR(Filename[0], NULL);
        
        // Anon Pipe
        if( strcmp(Filename, "anon") == 0 )
@@ -135,19 +128,15 @@ tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
                if( Flags & VFS_FDIRFLAG_STAT ) {
                        //return &gFIFI_TemplateAnonNode;
                }
-               tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
-               return &tmp->Node;
+               tPipe *ret = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
+               return &ret->Node;
        }
        
        // Check Named List
-       tmp = gFIFO_NamedPipes;
-       while(tmp)
-       {
-               if(strcmp(tmp->Name, Filename) == 0)
-                       return &tmp->Node;
-               tmp = tmp->Next;
-       }
-       return NULL;
+       tPipe *ret = (tPipe*)MemFS_FindDir(&gFIFO_RootDir, Filename);
+       if(!ret)
+               return NULL;
+       return &ret->Node;
 }
 
 /**
@@ -155,6 +144,25 @@ tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
  */
 tVFS_Node *FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
 {
+       UNIMPLEMENTED();
+       return NULL;
+}
+
+/**
+ * \brief Delete a pipe
+ */
+int FIFO_Unlink(tVFS_Node *Node, const char *OldName)
+{
+       if(Node != &gFIFO_DriverInfo.RootNode)  return 0;
+       
+       // Can't relink anon
+       if(strcmp(OldName, "anon"))     return 0;
+       
+       // Find node
+       tPipe* pipe = (tPipe*)MemFS_Remove(&gFIFO_RootDir, OldName);
+       if(!pipe)       return 0;
+       
+       free(pipe);
        return 0;
 }
 
@@ -171,54 +179,23 @@ void FIFO_Reference(tVFS_Node *Node)
  */
 void FIFO_Close(tVFS_Node *Node)
 {
-       tPipe   *pipe;
        if(!Node->ImplPtr)      return ;
        
        Node->ReferenceCount --;
        if(Node->ReferenceCount)        return ;
        
-       pipe = Node->ImplPtr;
+       tPipe   *pipe = Node->ImplPtr;
        
-       if(strcmp(pipe->Name, "anon") == 0) {
-               Log_Debug("FIFO", "Pipe %p closed", Node->ImplPtr);
-               free(Node->ImplPtr);
+       if(strcmp(pipe->FileHdr.Name, "anon") == 0)
+       {
+               Log_Debug("FIFO", "Pipe %p closed", pipe);
+               free(pipe);
                return ;
        }
        
        return ;
 }
 
-/**
- * \brief Delete a pipe
- */
-int FIFO_Unlink(tVFS_Node *Node, const char *OldName)
-{
-       tPipe   *pipe;
-       
-       if(Node != &gFIFO_DriverInfo.RootNode)  return 0;
-       
-       // Can't relink anon
-       if(strcmp(OldName, "anon"))     return 0;
-       
-       // Find node
-       for(pipe = gFIFO_NamedPipes;
-               pipe;
-               pipe = pipe->Next)
-       {
-               if(strcmp(pipe->Name, OldName) == 0)
-                       break;
-       }
-       if(!pipe)       return 0;
-       
-       // Unlink the pipe
-       if(Node->ImplPtr) {
-               free(Node->ImplPtr);
-               return 1;
-       }
-       
-       return 0;
-}
-
 /**
  * \brief Read from a fifo pipe
  */
@@ -412,10 +389,8 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
        ret->Buffer = (void*)( (Uint)ret + sizeof(tPipe) + sizeof(tVFS_ACL) );
        
        // Set name (and FIFO name)
-       ret->Name = ret->Buffer + Size;
-       strcpy(ret->Name, Name);
-       // - Start empty, max of `Size`
-       //Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
+       ret->FileHdr.Name = ret->Buffer + Size;
+       strcpy((char*)ret->FileHdr.Name, Name);
        
        // Set Node
        ret->Node.ReferenceCount = 1;
index 03288ae..60bf4dd 100644 (file)
@@ -50,9 +50,8 @@ tVFS_NodeType gSysFS_DirNodeType = {
        .FindDir = SysFS_Comm_FindDir
        };
 tSysFS_Ent     gSysFS_Version_Kernel = {
-       NULL, NULL,     // Nexts
-       &gSysFS_Version,        // Parent
-       {
+       .Parent = &gSysFS_Version,      // Parent
+       .Node = {
                .Inode = 1,     // File #1
                .ImplPtr = NULL,
                .ImplInt = (Uint)&gSysFS_Version_Kernel,        // Self-Link
@@ -61,12 +60,11 @@ tSysFS_Ent  gSysFS_Version_Kernel = {
                .ACLs = &gVFS_ACL_EveryoneRO,
                .Type = &gSysFS_FileNodeType
        },
-       "Kernel"
+       .Name = {"Kernel"}
 };
 tSysFS_Ent     gSysFS_Version = {
-       NULL, NULL,
-       &gSysFS_Root,
-       {
+       .Parent = &gSysFS_Root,
+       .Node = {
                .Size = 1,
                .ImplPtr = &gSysFS_Version_Kernel,
                .ImplInt = (Uint)&gSysFS_Version,       // Self-Link
@@ -75,7 +73,7 @@ tSysFS_Ent    gSysFS_Version = {
                .Flags = VFS_FFLAG_DIRECTORY,
                .Type = &gSysFS_DirNodeType
        },
-       "Version"
+       .Name = {"Version"}
 };
 // Root of the SysFS tree (just used to keep the code clean)
 tSysFS_Ent     gSysFS_Root = {
@@ -86,7 +84,7 @@ tSysFS_Ent    gSysFS_Root = {
                .ImplPtr = &gSysFS_Version,
                .ImplInt = (Uint)&gSysFS_Root   // Self-Link
        },
-       "/"
+       {"/"}
 };
 tDevFS_Driver  gSysFS_DriverInfo = {
        NULL, "system",
index 3b30b99..d1f74c5 100644 (file)
@@ -85,6 +85,7 @@ tVFS_NodeType gPTY_NodeType_Root = {
 };
 tVFS_NodeType  gPTY_NodeType_Client = {
        .TypeName = "PTY-Client",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read = PTY_ReadClient,
        .Write = PTY_WriteClient,
        .IOCtl = PTY_IOCtl,
@@ -93,6 +94,7 @@ tVFS_NodeType gPTY_NodeType_Client = {
 };
 tVFS_NodeType  gPTY_NodeType_Server = {
        .TypeName = "PTY-Server",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read = PTY_ReadServer,
        .Write = PTY_WriteServer,
        .IOCtl = PTY_IOCtl,
@@ -235,6 +237,7 @@ tPTY *PTY_Create(const char *Name, void *Handle, tPTY_OutputFcn Output, tPTY_Req
        if( InitialMode )
                ret->Mode = *InitialMode;
        // - Client node
+       ret->ClientNode.Size = -1;
        ret->ClientNode.ImplPtr = ret;
        ret->ClientNode.Type = &gPTY_NodeType_Client;
        ret->ClientNode.UID = Threads_GetUID();
@@ -624,12 +627,14 @@ size_t PTY_WriteClient(tVFS_Node *Node, off_t Offset, size_t Length, const void
        // If the server has terminated, send SIGPIPE
        if( pty->ServerNode && pty->ServerNode->ReferenceCount == 0 )
        {
+               LOG("SIGPIPE, server has terminated");
                Threads_PostSignal(SIGPIPE);
                errno = EIO;
                return -1;
        }       
 
        // Write to either FIFO or directly to output function
+       LOG("pty->OutputFcn = %p", pty->OutputFcn);
        if( pty->OutputFcn ) {
                pty->OutputFcn(pty->OutputHandle, Length, Buffer);
                return Length;
@@ -810,6 +815,8 @@ int PTY_IOCtl(tVFS_Node *Node, int ID, void *Data)
        
        int     is_server = !pty || Node == pty->ServerNode;
 
+       LOG("(%i,%p) %s", ID, Data, (is_server?"Server":"Client"));
+
        switch(ID)
        {
        case DRV_IOCTL_TYPE:    return DRV_TYPE_TERMINAL;
index bc7597e..df13fc7 100644 (file)
@@ -5,6 +5,7 @@
  * drv/serial.c
  * - Common serial port code
  */
+#define DEBUG  0
 #include <acess.h>
 #include <modules.h>
 #include <fs_devfs.h>
@@ -65,6 +66,7 @@ tSerialPort *Serial_CreatePort(tSerial_OutFcn output, void *handle)
 
 void Serial_ByteReceived(tSerialPort *Port, char Ch)
 {
+       LOG("Port=%p,Ch=%i", Port, Ch);
        if( !Port )
                return ;
        if( Port == gSerial_KernelDebugPort )
@@ -109,6 +111,7 @@ void Serial_ByteReceived(tSerialPort *Port, char Ch)
        }
        if( Ch == '\r' )
                Ch = '\n';
+       LOG("Dispatch to PTY");
        PTY_SendInput(Port->PTY, &Ch, 1);
 }
 
diff --git a/KernelLand/Kernel/drv/shm.c b/KernelLand/Kernel/drv/shm.c
new file mode 100644 (file)
index 0000000..da32141
--- /dev/null
@@ -0,0 +1,302 @@
+/* 
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * drv/shm.c
+ * - Shared memory "device"
+ */
+#define DEBUG  0
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include <memfs_helpers.h> 
+#include <semaphore.h>
+
+#define PAGE_COUNT(v)  (((v)+(PAGE_SIZE-1))/PAGE_SIZE)
+
+// === TYPES ===
+#define PAGES_PER_BLOCK        1024
+typedef struct sSHM_BufferBlock
+{
+       struct sSHM_BufferBlock *Next;
+       tPAddr  Pages[PAGES_PER_BLOCK];
+} tSHM_BufferBlock;
+typedef struct
+{
+       tMemFS_FileHdr  FileHdr;
+       tVFS_Node       Node;
+       size_t  nPages;
+       tSHM_BufferBlock        FirstBlock;
+} tSHM_Buffer;
+
+// === PROTOTYPES ===
+ int   SHM_Install(char **Arguments);
+ int   SHM_Uninstall(void);
+tSHM_Buffer    *SHM_CreateBuffer(const char *Name);
+bool   SHM_AddPages(tSHM_Buffer *Buffer, size_t num);
+void   SHM_DeleteBuffer(tSHM_Buffer *Buffer);
+// - Root directory
+ int   SHM_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX]);
+tVFS_Node      *SHM_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags);
+tVFS_Node      *SHM_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+ int   SHM_Unlink(tVFS_Node *Node, const char *OldName);
+// - Buffers
+void   SHM_Reference(tVFS_Node *Node);
+void   SHM_Close(tVFS_Node *Node);
+off_t  SHM_Truncate(tVFS_Node *Node, off_t NewSize);
+size_t SHM_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags);
+size_t SHM_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags);
+ int   SHM_MMap(struct sVFS_Node *Node, off_t Offset, size_t Length, void *Dest);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x0100, SHM, SHM_Install, SHM_Uninstall, NULL);
+tMemFS_DirHdr  gSHM_RootDir = {
+       .FileHdr = {.Name = "SHMRoot"}
+};
+tVFS_NodeType  gSHM_DirNodeType = {
+       .TypeName = "SHM Root",
+       .ReadDir = SHM_ReadDir,
+       .FindDir = SHM_FindDir,
+       .MkNod   = SHM_MkNod,
+       .Unlink  = SHM_Unlink,
+};
+tVFS_NodeType  gSHM_FileNodeType = {
+       .TypeName = "SHM Buffer",
+       .Read  = SHM_Read,
+       .Write = SHM_Write,
+       .Close = SHM_Close,
+       .MMap  = SHM_MMap,
+       .Truncate = SHM_Truncate,
+       .Reference = SHM_Reference,
+};
+tDevFS_Driver  gSHM_DriverInfo = {
+       .Name = "shm",
+       .RootNode = {
+               .Size = 0,
+               .NumACLs = 1,
+               .ACLs = &gVFS_ACL_EveryoneRW,
+               .Flags = VFS_FFLAG_DIRECTORY,
+               .Type = &gSHM_DirNodeType
+       }
+};
+
+// === CODE ===
+int SHM_Install(char **Arguments)
+{
+       MemFS_InitDir(&gSHM_RootDir);
+       DevFS_AddDevice( &gSHM_DriverInfo );
+       return MODULE_ERR_OK;
+}
+int SHM_Uninstall(void)
+{
+       return MODULE_ERR_OK;
+}
+tSHM_Buffer *SHM_CreateBuffer(const char *Name)
+{
+       tSHM_Buffer *ret = calloc(1, sizeof(tSHM_Buffer) + strlen(Name) + 1);
+       MemFS_InitFile(&ret->FileHdr);
+       ret->FileHdr.Name = (const char*)(ret+1);
+       strcpy((char*)ret->FileHdr.Name, Name);
+       ret->Node.ImplPtr = ret;
+       ret->Node.Type = &gSHM_FileNodeType;
+       ret->Node.ReferenceCount = 1;
+       return ret;
+}
+bool SHM_AddPages(tSHM_Buffer *Buffer, size_t num)
+{
+       tSHM_BufferBlock        *block = &Buffer->FirstBlock;
+       // Search for final block
+       size_t  idx = Buffer->nPages;
+       while( block->Next ) {
+               block = block->Next;
+               idx -= PAGES_PER_BLOCK;
+       }
+       ASSERTC(idx, <=, PAGES_PER_BLOCK);
+       
+       for( size_t i = 0; i < num; i ++ )
+       {
+               if( idx == PAGES_PER_BLOCK )
+               {
+                       block->Next = calloc(1, sizeof(tSHM_BufferBlock));
+                       if(!block->Next) {
+                               Log_Warning("SHM", "Out of memory, allocating new buffer block");
+                               return false;
+                       }
+                       block = block->Next;
+                       idx = 0;
+               }
+               ASSERT(block->Pages[idx] == 0);
+               block->Pages[idx] = MM_AllocPhys();
+               if( !block->Pages[idx] ) {
+                       Log_Warning("SHM", "Out of memory, allocating page");
+                       return false;
+               }
+               Buffer->nPages += 1;
+               idx ++;
+       }
+       return true;
+}
+void SHM_DeleteBuffer(tSHM_Buffer *Buffer)
+{
+       ASSERTCR(Buffer->Node.ReferenceCount,==,0,);
+       
+       // TODO: Destroy multi-block nodes
+       ASSERT(Buffer->FirstBlock.Next == NULL);
+       
+       free(Buffer);
+}
+// - Root directory
+int SHM_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
+{
+       return MemFS_ReadDir(&gSHM_RootDir, Id, Dest);
+}
+
+/**
+ * \brief Open a shared memory buffer
+ *
+ * \note Opening 'anon' will always succeed, and will create an anonymous mapping
+ */
+tVFS_Node *SHM_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
+{
+       if( strcmp(Filename, "anon") == 0 )
+       {
+               tSHM_Buffer *ret = SHM_CreateBuffer("");
+               return &ret->Node;
+       }
+       
+       tMemFS_FileHdr  *file = MemFS_FindDir(&gSHM_RootDir, Filename);
+       if( !file )
+               return NULL;
+       
+       return &((tSHM_Buffer*)file)->Node;
+}
+
+
+/**
+ * \brief Create a named shared memory file
+ */
+tVFS_Node *SHM_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
+{
+       if( MemFS_FindDir(&gSHM_RootDir, Name) )
+               return NULL;
+       
+       tSHM_Buffer *ret = SHM_CreateBuffer(Name);
+       if( !MemFS_Insert(&gSHM_RootDir, &ret->FileHdr) )
+       {
+               ret->Node.ReferenceCount = 0;
+               SHM_DeleteBuffer(ret);
+               return NULL;
+       }
+
+       return &ret->Node;
+}
+
+/**
+ * \breif Remove a named shared memory buffer (will be deleted when all references drop)
+ */
+int SHM_Unlink(tVFS_Node *Node, const char *OldName)
+{
+       tMemFS_FileHdr  *file = MemFS_Remove(&gSHM_RootDir, OldName);
+       if( !file )
+               return 1;
+
+       tSHM_Buffer *buf = (tSHM_Buffer*)file;
+       if( buf->Node.ReferenceCount == 0 )
+       {
+               SHM_DeleteBuffer(buf);
+       }
+       else
+       {
+               // dangling references, let them clean themselves up later
+       }
+       return 0;
+}
+// - Buffers
+void SHM_Reference(tVFS_Node *Node)
+{
+       Node->ReferenceCount ++;
+}
+void SHM_Close(tVFS_Node *Node)
+{
+       Node->ReferenceCount --;
+       if( Node->ReferenceCount == 0 )
+       {
+               // TODO: How to tell if a buffer should be deleted here?
+               UNIMPLEMENTED();
+       }
+}
+off_t SHM_Truncate(tVFS_Node *Node, off_t NewSize)
+{
+       ENTER("pNode XNewSize", Node, NewSize);
+       tSHM_Buffer     *buffer = Node->ImplPtr;
+       LOG("Node->Size = 0x%llx", Node->Size);
+       if( PAGE_COUNT(NewSize) != PAGE_COUNT(Node->Size) )
+       {
+                int    page_difference = PAGE_COUNT(NewSize) - PAGE_COUNT(Node->Size);
+               LOG("page_difference = %i", page_difference);
+               if( page_difference < 0 )
+               {
+                       // Truncate down
+                       // TODO: What if underlying pages are mapped?... should it matter?
+                       UNIMPLEMENTED();
+               }
+               else
+               {
+                       // Truncate up
+                       SHM_AddPages(buffer, page_difference);
+               }
+       }
+       else
+       {
+               LOG("Page count hasn't changed");
+       }
+       Node->Size = NewSize;
+       LEAVE('X', NewSize);
+       return NewSize;
+}
+size_t SHM_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
+{
+       UNIMPLEMENTED();
+       return -1;
+}
+size_t SHM_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
+{
+       // TODO: Should first write determine the fixed size of the buffer?
+       UNIMPLEMENTED();
+       return -1;
+}
+int SHM_MMap(struct sVFS_Node *Node, off_t Offset, size_t Length, void *Dest)
+{
+       tSHM_Buffer     *buf = Node->ImplPtr;
+       if( Offset > Node->Size )       return 1;
+       if( Offset + Length > Node->Size )      return 1;
+       
+       const int pagecount = (Length + Offset % PAGE_SIZE) / PAGE_SIZE;
+       int pagenum = Offset / PAGE_SIZE;
+       
+       tSHM_BufferBlock        *block = &buf->FirstBlock;
+       while( pagenum > PAGES_PER_BLOCK ) {
+               block = block->Next;
+               ASSERT(block);
+               pagenum -= PAGES_PER_BLOCK;
+       }
+       
+       tPage *dst = Dest;
+       for( int i = 0; i < pagecount; i ++ )
+       {
+               if( pagenum == PAGES_PER_BLOCK ) {
+                       block = block->Next;
+                       ASSERT(block);
+                       pagenum = 0;
+               }
+               
+               ASSERT(block->Pages[pagenum]);
+               LOG("%p => %i:%P", dst, pagenum, block->Pages[pagenum]);
+               MM_Map(dst, block->Pages[pagenum]);
+               
+               pagenum ++;
+               dst ++;
+       }
+       return 0;
+}
+
index 2c6a0d2..2175570 100644 (file)
@@ -5,7 +5,7 @@
  * drv/vterm.c
  * - Virtual Terminal - Initialisation and VFS Interface
  */
-#define DEBUG  1
+#define DEBUG  0
 #include "vterm.h"
 #include <fs_devfs.h>
 #include <modules.h>
@@ -34,7 +34,6 @@ extern void   Debug_SetKTerminal(const char *File);
 // === PROTOTYPES ===
  int   VT_Install(char **Arguments);
  int   VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data);
-void   VT_int_PutFBData(tVTerm *Term, size_t Offset, size_t Length, const void *Data);
 void   VT_PTYOutput(void *Handle, size_t Length, const void *Data);
  int   VT_PTYResize(void *Handle, const struct ptydims *Dims); 
  int   VT_PTYModeset(void *Handle, const struct ptymode *Mode);
@@ -369,15 +368,16 @@ void VT_PTYOutput(void *Handle, size_t Length, const void *Data)
                VT_int_PutString(term, Data, Length);
                break;
        case PTYBUFFMT_FB:
-               // TODO: How do offset?
+               // TODO: How can the offset be done cleanly? (Ask the PTY for its offset?)
+               Warning("TODO: Offsets for VT_PTYOutput FBData");
                VT_int_PutFBData(term, 0, Length, Data);
                break;
        case PTYBUFFMT_2DCMD:
-               // TODO: Impliment 2D commands
                VT_int_Handle2DCmd(term, Length, Data);
                break;
        case PTYBUFFMT_3DCMD:
-               // TODO: Impliment 3D commands
+               // TODO: Implement 3D commands
+               Warning("TODO: VTerm 3D commands");
                break;
        }
 }
index 05aad87..75128ba 100644 (file)
@@ -94,6 +94,11 @@ struct sVTerm
                 int    CachePos;
                char    Cache[32];
                size_t  PreEat;
+               union {
+                       struct {
+                               size_t  Offset;
+                       } Push;
+               } CmdInfo;
        } Cmd2D;
 
        tPTY    *PTY;
@@ -134,6 +139,7 @@ extern void VT_int_ClearLine(tVTerm *Term, int Num);
 extern void    VT_int_ClearInLine(tVTerm *Term, int Row, int FirstCol, int LastCol);
 extern void    VT_int_Resize(tVTerm *Term, int NewWidth, int NewHeight);
 extern void    VT_int_ToggleAltBuffer(tVTerm *Term, int Enabled);
+extern void    VT_int_PutFBData(tVTerm *Term, size_t Offset, size_t Length, const void *Buffer);
 
 extern tVT_Pos *VT_int_GetWritePosPtr(tVTerm *Term);
 extern size_t  VT_int_GetBufferRows(tVTerm *Term);
index 4b750ab..086c2b4 100644 (file)
@@ -14,6 +14,7 @@ void  VT_int_SetCursorBitmap(tVTerm *Term, int W, int H);
 size_t VT_int_FillCursorBitmap(tVTerm *Term, size_t DataOfs, size_t Length, const void *Data);
  int   VT_int_2DCmd_SetCursorPos(void *Handle, size_t Offset, size_t Length, const void *Data);
  int   VT_int_2DCmd_SetCursorBitmap(void *Handle, size_t Offset, size_t Length, const void *Data);
+ int   VT_int_2DCmd_SendData(void *Handle, size_t Offset, size_t Length, const void *Data);
 
 // === CODE ===
 void VT_int_SetCursorPos(tVTerm *Term, int X, int Y)
@@ -102,18 +103,15 @@ int VT_int_2DCmd_SetCursorBitmap(void *Handle, size_t Offset, size_t Length, con
                Length -= ret;
                Data = (const char*)Data + ret;
                Offset += ret;
-               if( Length == 0 )
-                       return -ret;
        }
+       
+       ASSERTC(Offset, >=, sizeof(cmd));
 
-
-       if( Offset < sizeof(cmd) ) {
-               // oops?
-               return ret;
+       if( Length > 0 )
+       {
+               ret += VT_int_FillCursorBitmap(Handle, Offset - sizeof(cmd), Length, Data);
        }
 
-       ret += VT_int_FillCursorBitmap(Handle, Offset - sizeof(cmd), Length, Data);
-
        LOG("%i + %i ==? %i", ret, Offset, term->Cmd2D.CurrentSize);
        if( ret + Offset >= term->Cmd2D.CurrentSize )
                return ret;
@@ -121,6 +119,46 @@ int VT_int_2DCmd_SetCursorBitmap(void *Handle, size_t Offset, size_t Length, con
        return -ret;
 }
 
+int VT_int_2DCmd_SendData(void *Handle, size_t Offset, size_t Length, const void *Data)
+{
+       tVTerm  *term = Handle;
+       struct ptycmd_senddata  cmd;
+       size_t  ret = 0;
+       
+       if( Offset == 0 )
+       {
+               if( Length < sizeof(cmd) )
+                       return 0;
+               memcpy(&cmd, Data, sizeof(cmd));
+               
+               ret = sizeof(cmd);
+               Offset += ret;
+               Length -= ret;
+               Data = (const char*)Data + ret;
+               
+               term->Cmd2D.CmdInfo.Push.Offset = cmd.ofs*4;
+       }
+       
+       ASSERTC(Offset, >=, sizeof(cmd));
+       
+       if( Length > 0 )
+       {
+               size_t  bytes = MIN(term->Width*term->Height*4 - term->Cmd2D.CmdInfo.Push.Offset, Length);
+               LOG("bytes = %i (0x%x), Length = %i", bytes, bytes, Length);
+               
+               VT_int_PutFBData(term, term->Cmd2D.CmdInfo.Push.Offset, bytes, Data );
+               term->Cmd2D.CmdInfo.Push.Offset += bytes;
+               ret += bytes;
+               
+               LOG("bytes(%i) ==? 0 || ret(%i) + Offset(%i) ==? %i",
+                       bytes, ret, Offset, term->Cmd2D.CurrentSize);
+               if( bytes == 0 || ret + Offset >= term->Cmd2D.CurrentSize )
+                       return ret;
+       }
+       
+       return -ret;
+}
+
 // > 0: Command complete
 // = 0: Not enough data to start
 // < 0: Ate -n bytes, still need more
@@ -128,6 +166,7 @@ typedef int (*tVT_2DCmdHandler)(void *Handle, size_t Offset, size_t Length, cons
 tVT_2DCmdHandler       gVT_2DCmdHandlers[] = {
        [PTY2D_CMD_SETCURSORPOS] = VT_int_2DCmd_SetCursorPos,
        [PTY2D_CMD_SETCURSORBMP] = VT_int_2DCmd_SetCursorBitmap,
+       [PTY2D_CMD_SEND] = VT_int_2DCmd_SendData,
 };
 const int      ciVT_Num2DCmdHandlers = sizeof(gVT_2DCmdHandlers)/sizeof(gVT_2DCmdHandlers[0]);
 
@@ -137,7 +176,7 @@ void VT_int_Handle2DCmd(void *Handle, size_t Length, const void *Data)
        tVTerm  *term = Handle;
 
        LOG("Length = 0x%x", Length);
-       // If a command terminated early, we have to clean up its data
+       // If a command didn't consume all the data it said it would, we have to clean up
 _eat:
        if( term->Cmd2D.PreEat )
        {
@@ -164,7 +203,10 @@ _eat:
                }
                // else begin a new command
                else
-               {               
+               {
+                       // If the new data would fit in the cache, or the cache is already populated
+                       // use the cache
+                       // - The cache should fit the header for every command, so all good
                        if( Length < cachesize || term->Cmd2D.CachePos != 0 )
                        {
                                adjust = term->Cmd2D.CachePos;
@@ -174,25 +216,33 @@ _eat:
                                dataptr = (void*)term->Cmd2D.Cache;
                                len = term->Cmd2D.CachePos;
                        }
-                       else {
+                       else
+                       {
                                dataptr = (void*)bdata;
                                len = Length;
                                adjust = 0;
                        }
                        const struct ptycmd_header      *hdr = dataptr;
 
-                       if( len < sizeof(*hdr) ) {
+                       // If there's not enough for the common header, wait for more
+                       if( len < sizeof(*hdr) )
+                       {
                                return ;
                        }                       
 
+                       // Parse header
                        term->Cmd2D.Offset = 0;
                        term->Cmd2D.Current = hdr->cmd;
                        term->Cmd2D.CurrentSize = (hdr->len_low | (hdr->len_hi << 8)) * 4;
-                       if( term->Cmd2D.CurrentSize == 0 )
+                       if( term->Cmd2D.CurrentSize == 0 ) {
+                               Log_Warning("VTerm", "Command size too small (==0)");
                                term->Cmd2D.CurrentSize = 2;
+                       }
                        LOG("Started %i with %s data",
                                term->Cmd2D.Current, (dataptr == bdata ? "direct" : "cache"));
                }
+
+               // Sanity check
                if( term->Cmd2D.Current >= ciVT_Num2DCmdHandlers || !gVT_2DCmdHandlers[term->Cmd2D.Current] )
                {
                        Log_Notice("VTerm", "2D Comand %i not handled", term->Cmd2D.Current);
@@ -203,42 +253,60 @@ _eat:
                        term->Cmd2D.PreEat = term->Cmd2D.CurrentSize;
                        goto _eat;
                }
-               else
+               
+               const tVT_2DCmdHandler* handler = &gVT_2DCmdHandlers[term->Cmd2D.Current];
+               #if 0
+               if( term->Cmd2D.Offset == 0 )
                {
-                       int rv = gVT_2DCmdHandlers[term->Cmd2D.Current](Handle, term->Cmd2D.Offset, len, dataptr);
-                       LOG("2DCmd %i: rv=%i", term->Cmd2D.Current, rv);
-                       if( rv == 0 && term->Cmd2D.Offset == 0 ) {
-                               // 0: Not enough data for header
-                               ASSERT( term->Cmd2D.CachePos != cachesize );
-                               // Clear current command because this command hasn't started yet
-                               term->Cmd2D.Current = 0;
-                               // Return, restart happens once all data is ready
+                       if( len < handler->HeaderLength ) {
                                return ;
                        }
-                       size_t used_bytes = (rv < 0 ? -rv : rv) - adjust;
-                       Length -= used_bytes;
-                       bdata += used_bytes;
-                       term->Cmd2D.CachePos = 0;
-                       if( rv < 0 ) {
-                               ASSERT( -rv <= len );
-                               LOG(" Incomplete");
-                               term->Cmd2D.Offset += -rv;
-                               continue ;
-                       }
-                       ASSERT(rv <= len);
+                       rv = handler->Header(Handle, len, dataptr);
+               }
+               else
+               {
+                       rv = hander->Body(Handle, term->Cmd2D.Offset, len, dataptr);
+               }
+               #endif
+               
+               // Call Handler 
+               int rv = (*handler)(Handle, term->Cmd2D.Offset, len, dataptr);
+               LOG("2DCmd %i: rv=%i", term->Cmd2D.Current, rv);
+               
+               // If it returned 0 on the first call, it lacks space for the header
+               if( rv == 0 && term->Cmd2D.Offset == 0 )
+               {
+                       ASSERT( term->Cmd2D.CachePos != cachesize );
+                       // Clear current command because this command hasn't started yet
                        term->Cmd2D.Current = 0;
+                       // Return, restart happens once all data is ready
+                       return ;
+               }
 
-                       // Eat up any uneaten data
-                       // - TODO: Need to eat across writes
-                       ASSERT( term->Cmd2D.Offset + rv <= term->Cmd2D.CurrentSize );
-                       if( term->Cmd2D.Offset + rv < term->Cmd2D.CurrentSize )
-                       {
-                               size_t  diff = term->Cmd2D.CurrentSize - (term->Cmd2D.Offset + rv);
-                               LOG("Left %i bytes", diff);
-                               term->Cmd2D.PreEat = diff;
-                               goto _eat;
-                       }
-                       LOG("Done (%i bytes left)", Length);
+               // Consume the byte count returned (adjust is the number of bytes that were already cached)
+               size_t used_bytes = (rv < 0 ? -rv : rv) - adjust;
+               Length -= used_bytes;
+               bdata += used_bytes;
+               term->Cmd2D.CachePos = 0;
+               // If a negative count was returned, more data is expected
+               if( rv < 0 ) {
+                       ASSERT( -rv <= len );
+                       LOG(" Incomplete");
+                       term->Cmd2D.Offset += -rv;
+                       continue ;
+               }
+               ASSERT(rv <= len);
+               term->Cmd2D.Current = 0;
+
+               // Eat up any uneaten data
+               ASSERT( term->Cmd2D.Offset + rv <= term->Cmd2D.CurrentSize );
+               if( term->Cmd2D.Offset + rv < term->Cmd2D.CurrentSize )
+               {
+                       size_t  diff = term->Cmd2D.CurrentSize - (term->Cmd2D.Offset + rv);
+                       LOG("Left %i bytes", diff);
+                       term->Cmd2D.PreEat = diff;
+                       goto _eat;
                }
+               LOG("Done (%i bytes left)", Length);
        }
 }
index 6c25cc8..aa517d9 100644 (file)
@@ -95,20 +95,30 @@ void VT_KBCallBack(Uint32 Codepoint)
                
 //             Log_Debug("VTerm", "Magic Ctrl-Alt-0x%x", term->RawScancode);   
 
+               const unsigned int scroll_step = term->TextHeight / 2;
+               // Note the lack of giVT_Scrollback+1, view top can't go above size-onescreen
+               const unsigned int scroll_max = term->TextHeight * giVT_Scrollback;
                switch(term->RawScancode)
                {
-               // Scrolling
+               // VTerm scrolling
+               // - Scrolls half a screen at a time
+               // - View up (text goes down)
                case KEYSYM_PGUP:
                        if( term->Flags & VT_FLAG_ALTBUF )
                                return ;
-                       term->ViewTopRow = MAX(0, term->ViewTopRow - 1);
+                       Log_Debug("VTerm", "ScrollUp - Old=%i, step=%i", term->ViewTopRow, scroll_step);
+                       term->ViewTopRow = (term->ViewTopRow > scroll_step ? term->ViewTopRow - scroll_step : 0);
+                       Log_Debug("VTerm", "ScrollUp - New=%i", term->ViewTopRow);
                        VT_int_UpdateScreen(term, 1);
                        return;
+               // - View down (text goes up)
                case KEYSYM_PGDN:
                        if( term->Flags & VT_FLAG_ALTBUF )
                                return ;
-                       // Note the lack of giVT_Scrollback+1, view top can't go above size-onescreen
-                       term->ViewTopRow = MIN(term->ViewTopRow + 1, term->Height * giVT_Scrollback);
+                       
+                       Log_Debug("VTerm", "ScrollDown - Old=%i, max=%i", term->ViewTopRow, scroll_max);
+                       term->ViewTopRow = MIN(term->ViewTopRow + scroll_step, scroll_max);
+                       Log_Debug("VTerm", "ScrollDown - New=%i", term->ViewTopRow);
                        VT_int_UpdateScreen(term, 1);
                        return;
                }
index 532d268..95c552f 100644 (file)
@@ -5,9 +5,9 @@
  * drv/vterm_input.c
  * - Virtual Terminal - Input code
  */
+#define DEBUG  0
 #include "vterm.h"
 #include <api_drv_video.h>
-#define DEBUG  0
 
 // === CODE ===
 /**
@@ -52,8 +52,12 @@ void VT_int_ScrollFramebuffer( tVTerm *Term, int Count )
        // Only update if this is the current terminal
        if( Term != gpVT_CurTerm )      return;
        
+       ENTER("pTerm iCount",
+               Term, Count);
+       
        if( Count > Term->ScrollHeight )        Count = Term->ScrollHeight;
        if( Count < -Term->ScrollHeight )       Count = -Term->ScrollHeight;
+       LOG("Count = %i", Count);
        
        // Switch to 2D Command Stream
        tmp = VIDEO_BUFFMT_2DSTREAM;
@@ -81,6 +85,7 @@ void VT_int_ScrollFramebuffer( tVTerm *Term, int Count )
        // Restore old mode (this function is only called during text mode)
        tmp = VIDEO_BUFFMT_TEXT;
        VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &tmp);
+       LEAVE('-');
 }
 
 void VT_int_UpdateCursor( tVTerm *Term, int bShow )
@@ -88,6 +93,8 @@ void VT_int_UpdateCursor( tVTerm *Term, int bShow )
        tVideo_IOCtl_Pos        csr_pos;
 
        if( Term != gpVT_CurTerm )      return ;
+       
+       ENTER("pTerm bShow", Term, bShow);
 
        if( !bShow )
        {
@@ -119,6 +126,7 @@ void VT_int_UpdateCursor( tVTerm *Term, int bShow )
                csr_pos.y = Term->VideoCursorY;
        }
        VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSOR, &csr_pos);
+       LEAVE('-');
 }      
 
 /**
@@ -127,15 +135,21 @@ void VT_int_UpdateCursor( tVTerm *Term, int bShow )
  */
 void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll )
 {
+       ENTER("pTerm iUpdateAll", Term, UpdateAll);
        // Only update if this is the current terminal
-       if( Term != gpVT_CurTerm )      return;
-       
+       if( Term != gpVT_CurTerm ) {
+               LOG("Term != gpVT_CurTerm (%p)", gpVT_CurTerm);
+               LEAVE('-');
+               return;
+       }
+               
        switch( Term->Mode )
        {
        case TERM_MODE_TEXT: {
                size_t view_pos = (Term->Flags & VT_FLAG_ALTBUF) ? 0 : Term->ViewTopRow*Term->TextWidth;
                const tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
                const tVT_Char *buffer = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltBuf : Term->Text;
+               LOG("view_pos = %i, wrpos = %p (R%i,C%i), buffer=%p", view_pos, wrpos, wrpos->Row, wrpos->Col, buffer);
                // Re copy the entire screen?
                if(UpdateAll) {
                        VFS_WriteAt(
@@ -148,6 +162,7 @@ void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll )
                // Only copy the current line
                else {
                        size_t  ofs = wrpos->Row * Term->TextWidth;
+                       LOG("ofs = %i", ofs);
                        VFS_WriteAt(
                                giVT_OutputDevHandle,
                                (ofs - view_pos)*sizeof(tVT_Char),
@@ -161,5 +176,6 @@ void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll )
        }
        
        VT_int_UpdateCursor(Term, 1);
+       LEAVE('-');
 }
 
index 5078722..1a14f82 100644 (file)
@@ -25,6 +25,7 @@ extern int    Term_HandleVT100(tVTerm *Term, int Len, const char *Buf);
  */
 void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count)
 {
+       ENTER("pTerm pBuffer iCount", Term, Buffer, Count);
        // Iterate
        for( int ofs = 0; ofs < Count; )
        {
@@ -43,7 +44,9 @@ void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count)
                ofs += esc_len;
        }
        // Update Screen
-       VT_int_UpdateScreen( Term, 1 );
+       LOG("Update");
+       VT_int_UpdateScreen( Term, 0 );
+       LEAVE('-');
 }
 
 void VT_int_PutRawString(tVTerm *Term, const Uint8 *String, size_t Bytes)
@@ -76,7 +79,7 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch)
        {
                ASSERTC(wrpos->Col, <=, Term->TextWidth);
                VT_int_UpdateScreen( Term, 0 );
-               //wrpos->Row ++;
+               wrpos->Row ++;
                wrpos->Col = 0;
        }
 
@@ -121,6 +124,7 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch)
        case '\0':      // Ignore NULL byte
                return;
        case '\n':
+               LOG("Newline, update @ %i", write_pos);
                VT_int_UpdateScreen( Term, 0 ); // Update the line before newlining
                wrpos->Row ++;
                // TODO: Force scroll?
@@ -165,10 +169,13 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch)
                buffer[ write_pos ].Ch = Ch;
                buffer[ write_pos ].Colour = Term->CurColour;
                // Update the line before wrapping
-               if( (write_pos + 1) % Term->TextWidth == 0 )
+               if( (write_pos + 1) % Term->TextWidth == 0 ) {
+                       LOG("Line wrap, update @ %i", write_pos);
                        VT_int_UpdateScreen( Term, 0 );
-               write_pos ++;
+                       // NOTE: Code at the top of PutChar handles the actual wrapping
+               }
                wrpos->Col ++;
+               write_pos ++;
                break;
        }
        
@@ -176,11 +183,12 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch)
 
        HEAP_VALIDATE();
        
-       //LEAVE('-');
+       // TODO: Schedule a delayed screen update
 }
 
 void VT_int_ScrollText(tVTerm *Term, int Count)
 {
+       ENTER("pTerm iCount", Term, Count);
        tVT_Char        *buf;
         int    scroll_top, scroll_height;
        
@@ -274,6 +282,7 @@ void VT_int_ScrollText(tVTerm *Term, int Count)
        *wrpos = init_wrpos;
 
        HEAP_VALIDATE();
+       LEAVE('-');
 }
 
 /**
index 4428b64..0d59a66 100644 (file)
@@ -44,7 +44,7 @@ void Display_ScrollDown(tTerminal *Term, int CountDown)
        LOG("(%i)", CountDown);
        VT_int_UpdateScreen(Term, 0);
        if( Term->Flags & VT_FLAG_ALTBUF )
-               VT_int_ScrollText(Term, CountDown);
+               VT_int_ScrollText(Term, -CountDown);
        else
        {
                if(Term->ViewTopRow + CountDown < 0)
index fa2b502..b21d1ef 100644 (file)
@@ -23,33 +23,38 @@ size_t      CoreDevs_Read_GRandom(tVFS_Node *Node, off_t Offset, size_t Length, void
 MODULE_DEFINE(0, 0x0100, CoreDevs, CoreDevs_Install, NULL, NULL);
 tVFS_NodeType  gCoreDevs_NT_Null = {
        .TypeName = "CoreDevs-null",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read  = CoreDevs_Read_Null,
        .Write = CoreDevs_Write
 };
 tVFS_NodeType  gCoreDevs_NT_Zero = {
        .TypeName = "CoreDevs-zero",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read  = CoreDevs_Read_Zero,
        .Write = CoreDevs_Write
 };
 tVFS_NodeType  gCoreDevs_NT_One = {
        .TypeName = "CoreDevs-one",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read  = CoreDevs_Read_One,
        .Write = CoreDevs_Write
 };
 tVFS_NodeType  gCoreDevs_NT_FRandom = {
        .TypeName = "CoreDevs-frandom",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read  = CoreDevs_Read_FRandom,
        .Write = CoreDevs_Write
 };
 tVFS_NodeType  gCoreDevs_NT_GRandom = {
        .TypeName = "CoreDevs-grandom",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read  = CoreDevs_Read_GRandom,
        .Write = CoreDevs_Write
 };
 tDevFS_Driver  gCoreDevs_Null = {
        NULL, "null",
        {
-       .Size = 0, .NumACLs = 1,
+       .Size = -1, .NumACLs = 1,
        .ACLs = &gVFS_ACL_EveryoneRW,
        .Type = &gCoreDevs_NT_Null
        }
@@ -57,7 +62,7 @@ tDevFS_Driver gCoreDevs_Null = {
 tDevFS_Driver  gCoreDevs_Zero = {
        NULL, "zero",
        {
-       .Size = 0, .NumACLs = 1,
+       .Size = -1, .NumACLs = 1,
        .ACLs = &gVFS_ACL_EveryoneRW,
        .Type = &gCoreDevs_NT_Zero
        }
@@ -65,7 +70,7 @@ tDevFS_Driver gCoreDevs_Zero = {
 tDevFS_Driver  gCoreDevs_One = {
        NULL, "one",
        {
-       .Size = 0, .NumACLs = 1,
+       .Size = -1, .NumACLs = 1,
        .ACLs = &gVFS_ACL_EveryoneRW,
        .Type = &gCoreDevs_NT_One
        }
@@ -73,7 +78,7 @@ tDevFS_Driver gCoreDevs_One = {
 tDevFS_Driver  gCoreDevs_FRandom = {
        NULL, "frandom",
        {
-       .Size = 0, .NumACLs = 1,
+       .Size = -1, .NumACLs = 1,
        .ACLs = &gVFS_ACL_EveryoneRW,
        .Type = &gCoreDevs_NT_FRandom,
        .DataAvaliable = 1
@@ -82,7 +87,7 @@ tDevFS_Driver gCoreDevs_FRandom = {
 tDevFS_Driver  gCoreDevs_GRandom = {
        NULL, "grandom",
        {
-       .Size = 0, .NumACLs = 1,
+       .Size = -1, .NumACLs = 1,
        .ACLs = &gVFS_ACL_EveryoneRW,
        .Type = &gCoreDevs_NT_GRandom,
        .DataAvaliable = 1
index 4343ab6..2bffb1a 100644 (file)
@@ -536,8 +536,6 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf)
 void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf)
 {
         int    bytes_per_px = (Buf->Depth + 7) / 8;
-        int    y, save_pitch;
-       Uint8   *dest, *src;
 
        // Just a little sanity
        if( !Buf->CursorBitmap || Buf->CursorX == -1 )  return ;
@@ -546,16 +544,21 @@ void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf)
 //     Debug("DrvUtil_Video_RemoveCursor: (Buf=%p) dest_x=%i, dest_y=%i", Buf, Buf->CursorDestX, Buf->CursorDestY);
 
        // Set up
-       save_pitch = Buf->CursorBitmap->W * bytes_per_px;
-       dest = (Uint8*)Buf->Framebuffer + Buf->CursorDestY * Buf->Pitch + Buf->CursorDestX*bytes_per_px;
-       src = Buf->CursorSaveBuf;
-       
+       size_t  save_pitch = Buf->CursorBitmap->W * bytes_per_px;
+       Uint8   *dst = (Uint8*)Buf->Framebuffer + Buf->CursorDestY * Buf->Pitch + Buf->CursorDestX*bytes_per_px;
+       const Uint8     *src = Buf->CursorSaveBuf;
+
+       ASSERT(Buf->Framebuffer);
+       ASSERT(src);
+       ASSERT(CheckMem(dst, Buf->CursorRenderH*Buf->Pitch));
+       ASSERT(CheckMem(src, Buf->CursorRenderH*save_pitch));
+
        // Copy each line back
-       for( y = 0; y < Buf->CursorRenderH; y ++ )
+       for( int y = 0; y < Buf->CursorRenderH; y ++ )
        {
-               memcpy( dest, src, Buf->CursorRenderW * bytes_per_px );
+               memcpy( dst, src, Buf->CursorRenderW * bytes_per_px );
                src += save_pitch;
-               dest += Buf->Pitch;
+               dst += Buf->Pitch;
        }
        
        // Set the cursor as removed
diff --git a/KernelLand/Kernel/emergency_console.c b/KernelLand/Kernel/emergency_console.c
new file mode 100644 (file)
index 0000000..dd6d708
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Acess 2 Kernel
+ * - By John Hodge (thePowersGang)
+ * 
+ * emergency_console.c
+ * - Kernel-land emergency console/shell
+ */
+#include <acess.h>
+#include <stdarg.h>
+
+#define STDIN  0
+#define STDOUT 1
+#define STDERR 2
+
+// === PROTOTYPES ===
+void EmergencyConsole(void);
+// -- Commands
+void Command_ls(const char* path);
+void Command_hd(const char* path);
+void Command_mount(const char *fs, const char *dev, const char *point);
+// --
+static char **split_args(char *line);
+static char *read_line(int fd);
+static int dprintf(int fd, const char *fmt, ...);// __attribute__((printf(2,3)));
+
+// === CODE ===
+void EmergencyConsole(void)
+{
+       for(;;)
+       {
+               dprintf(STDOUT, "(kernel)$ ");
+               char *line = read_line(STDIN);
+               
+               // Explode line into args
+               char **args = split_args(line);
+               // Get command from first arg
+               ASSERT(args);
+               ASSERT(args[0]);
+               if( strcmp(args[0], "help") == 0 ) {
+                       dprintf(STDOUT,
+                               "Commands:\n"
+                               "ls <path> - List the contents of a directory\n"
+                               "hd <path> - Dump a file in a 16 bytes/line hex format\n"
+                               "mount <fs> <device> <point> - Mount a filesystem\n"
+                               );
+               }
+               else if( strcmp(args[0], "ls") == 0 ) {
+                       Command_ls(args[1]); 
+               }
+               else if( strcmp(args[0], "hd") == 0 ) {
+                       Command_hd(args[1]);
+               }
+               else if( strcmp(args[0], "mount") == 0 ) {
+                       Command_mount(args[1], args[2], args[3]);
+               }
+               else
+               {
+                       dprintf(STDERR, "Unknown command '%s'\n", args[0]);
+               }
+               // Free args
+               free(args);
+               free(line);
+       }
+}
+
+void Command_ls(const char* path)
+{
+       dprintf(STDERR, "ls: TODO - Implement\n");
+}
+void Command_hd(const char* path)
+{
+       dprintf(STDERR, "hd: TODO - Implement\n");
+}
+void Command_mount(const char *fs, const char *dev, const char *point)
+{
+       dprintf(STDERR, "mount: TODO - Implement\n");
+}
+
+// Allocates return array (NUL terminated), but mangles input string
+static int split_args_imp(char *line, char **buf)
+{
+        int    argc = 0;
+        int    pos = 0;
+       enum {
+               MODE_SPACE,
+               MODE_NORM,
+               MODE_SQUOTE,
+               MODE_DQUOTE,
+       } mode = MODE_SPACE;
+       for( char *chp = line; *chp; chp ++ )
+       {
+               if( *chp == ' ' ) {
+                       if( mode != MODE_SPACE ) {
+                               if(buf) buf[argc][pos] = '\0';
+                               argc ++;
+                       }
+                       mode = MODE_SPACE;
+                       continue ;
+               }
+               
+               switch( mode )
+               {
+               case MODE_SPACE:
+                       if( buf )
+                               buf[argc] = chp;
+                       pos = 0;
+               case MODE_NORM:
+                       switch( *chp )
+                       {
+                       case '"':
+                               mode = MODE_DQUOTE;
+                               break;
+                       case '\'':
+                               mode = MODE_SQUOTE;
+                               break;
+                       case '\\':
+                               chp ++;
+                               switch( *chp )
+                               {
+                               case '\0':
+                                       dprintf(STDERR, "err: Trailing '\\'\n");
+                                       break;
+                               case '\\':
+                               case '\'':
+                               case '"':
+                                       if(buf) buf[argc][pos++] = *chp;
+                                       break;
+                               default:
+                                       dprintf(STDERR, "err: Unkown escape '%c'\n", *chp);
+                                       break;
+                               }
+                               break;
+                       default:
+                               if(buf) buf[argc][pos++] = *chp;
+                               break;
+                       }
+                       break;
+               case MODE_SQUOTE:
+                       switch( *chp )
+                       {
+                       case '\'':
+                               mode = MODE_NORM;
+                               break;
+                       case '\0':
+                               dprintf(STDERR, "err: Unterminated \' string\n");
+                               break;
+                       default:
+                               if(buf) buf[argc][pos++] = *chp;
+                               break;
+                       }
+                       break;
+               case MODE_DQUOTE:
+                       switch( *chp )
+                       {
+                       case '\"':
+                               mode = MODE_NORM;
+                               break;
+                       case '\\':
+                               chp ++;
+                               switch(*chp)
+                               {
+                               case '\0':
+                                       dprintf(STDERR, "err: Trailing '\\' in \" string\n");
+                                       break;
+                               case '\\':
+                               case '"':
+                                       if(buf) buf[argc][pos++] = *chp;
+                                       break;
+                               default:
+                                       dprintf(STDERR, "err: Unkown escape '%c'\n", *chp);
+                                       break;
+                               }
+                               break;
+                       case '\0':
+                               dprintf(STDERR, "err: Unterminated \" string\n");
+                               break;
+                       default:
+                               if(buf) buf[argc][pos++] = *chp;
+                               break;
+                       }
+                       break;
+               }
+       }
+
+       if(buf) buf[argc][pos++] = '\0';
+       argc ++;
+       return argc;
+}
+static char **split_args(char *line)
+{
+       // 1. Count
+       int count = split_args_imp(line, NULL);
+       char **ret = malloc( (count + 1) * sizeof(char*) );
+       
+       split_args_imp(line, ret);
+       ret[count] = NULL;
+       return ret;
+}
+
+static char *read_line(int fd)
+{
+       // Read line (or up to ~128 bytes)
+       // - This assumes a default PTY state (i.e. line buffered, echo on)
+       char *ret = malloc(128);
+       size_t len = VFS_Read(STDIN, 128, ret);
+       ret[len] = 0;
+       return ret;
+}
+
+static int dprintf(int fd, const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       size_t len = vsnprintf(NULL, 0, fmt, args);
+       va_end(args);
+       
+       char buf[len+1];
+       va_start(args, fmt);
+       vsnprintf(buf, len+1, fmt, args);
+       va_end(args);
+       
+       VFS_Write(fd, len, buf);
+       
+       return len;
+}
+
index b0225ef..a572d43 100644 (file)
@@ -7,8 +7,8 @@
  */
 #define DEBUG  0
 #include <acess.h>
-#include <threads_int.h>
 #include <events.h>
+#include <threads_int.h>
 
 // === CODE ===
 void Threads_PostEvent(tThread *Thread, Uint32 EventMask)
@@ -87,7 +87,7 @@ Uint32 Threads_WaitEvents(Uint32 EventMask)
        {
                Threads_int_Sleep(THREAD_STAT_EVENTSLEEP, NULL, EventMask,
                        &us, NULL, &us->IsLocked);
-               // Woken when lock is acquired
+               // Woken when an event fires
                SHORTLOCK( &us->IsLocked );
        }
        
index f7054ea..ba4c9ad 100755 (executable)
@@ -353,6 +353,8 @@ void Heap_Deallocate(const char *File, int Line, void *Ptr)
        // INVLPTR is returned from Heap_Allocate when the allocation
        // size is zero.
        if( Ptr == INVLPTR )    return;
+       // free(NULL) is a no-op
+       if( Ptr == NULL )       return;
        
        // Alignment Check
        if( (tVAddr)Ptr % sizeof(void*) != 0 ) {
index fe1a0f9..83611bb 100644 (file)
@@ -27,7 +27,7 @@
 #define DEPRECATED     __attribute__((deprecated))
 //! Mark a parameter as unused
 #define UNUSED(x)      UNUSED_##x __attribute__((unused))
-//! 
+//! Apply alignment to a variable 
 #define ALIGN(x)       __attribute__((aligned(x)))
 
 /**
@@ -85,11 +85,11 @@ extern const char   gsBuildInfo[];
  * \{
  * \todo Move to mm_virt.h
  */
-#define        MM_PFLAG_RO             0x01    // Writes disallowed
-#define        MM_PFLAG_EXEC   0x02    // Allow execution
-#define        MM_PFLAG_NOPAGE 0x04    // Prevent from being paged out
-#define        MM_PFLAG_COW    0x08    // Copy-On-Write
-#define        MM_PFLAG_KERNEL 0x10    // Kernel-Only (Ring0)
+#define        MM_PFLAG_RO     0x01    //!< Writes disallowed
+#define        MM_PFLAG_EXEC   0x02    //!< Allow execution
+#define        MM_PFLAG_NOPAGE 0x04    //!< Prevent from being paged out
+#define        MM_PFLAG_COW    0x08    //!< Copy-On-Write
+#define        MM_PFLAG_KERNEL 0x10    //!< Kernel-Only (Ring0)
 /**
  * \}
  */
@@ -143,7 +143,9 @@ typedef struct sKernelSymbol {
  * \name IRQ hander registration
  * \{
  */
+//! Register a callback for when an IRQ is raised
 extern int     IRQ_AddHandler(int Num, void (*Callback)(int, void*), void *Ptr);
+//! Remove a previously registered IRQ handler
 extern void    IRQ_RemHandler(int Handle);
 /**
  * \}
@@ -240,6 +242,15 @@ extern Uint        MM_GetFlags(volatile const void *VAddr);
  * \note There is only a limited ammount of slots avaliable
  */
 extern void    *MM_MapTemp(tPAddr PAddr);
+/**
+ * \brief Peform a temporary map of a page from another process
+ * \param Process      Source process
+ * \param Address      Source virtual address
+ * \return Virtual address of page in memory
+ * \note Limited slots
+ */
+struct sProcess;
+extern void    *MM_MapTempFromProc(struct sProcess *Process, const void *Address);
 /**
  * \brief Free a temporarily mapped page
  * \param Ptr  Pointer to page base
index 12e9ba4..b640793 100644 (file)
@@ -10,7 +10,7 @@
 #include <stdarg.h>
 
 /**
- * \name Strings
+ * \name String Manipulation
  * \{
  */
 // - stdio.h in userland
@@ -38,6 +38,7 @@ extern unsigned long  strtoul(const char *str, char **end, int base);
 extern signed long long        strtoll(const char *str, char **end, int base);
 extern signed long     strtol(const char *str, char **end, int base);
 
+//! \brief String comparison (case-insensitive)
 extern int     strucmp(const char *Str1, const char *Str2);
 extern int     strpos(const char *Str, char Ch);
 extern int     strpos8(const char *str, Uint32 search);
index 8b5b85f..7a5e427 100644 (file)
@@ -23,6 +23,8 @@
  *    user.
  *  - Drivers for specific types of hardware must behave in the specific
  *    way described here.
+ * - \ref library      "Library Functions"
+ *  - Kernel's version of libc and other helper functions
  * 
  * \page drivers Device Drivers
  * 
index 1032814..bdc8c85 100644 (file)
@@ -82,5 +82,6 @@ extern Uint8  PCI_GetIRQ(tPCIDev id);
 extern Uint32  PCI_GetBAR(tPCIDev id, int BAR);\r
 extern Uint64  PCI_GetValidBAR(tPCIDev id, int BAR, tPCI_BARType BARType);\r
 //extern Uint16        PCI_AssignPort(tPCIDev id, int bar, int count);\r
+//extern void* PCI_MapMemBAR(tPCIDev id, int BAR, tPCI_BARType BARType, size_t* Size, tPAddr* PAddr);\r
 \r
 #endif\r
index 0710c6b..f13187e 100644 (file)
@@ -38,7 +38,7 @@ extern void   Log_Debug(const char *Ident, const char *Message, ...);
 extern void    Debug_KernelPanic(void);        //!< Initiate a kernel panic
 extern void    Panic(const char *Msg, ...) NORETURN;   //!< Print a panic message (initiates a kernel panic)
 extern void    Warning(const char *Msg, ...);  //!< Print a warning message
-extern void    LogF(const char *Fmt, ...);     //!< Print a log message without a trailing newline
+extern bool    LogF(const char *Fmt, ...);     //!< Print a log message without a trailing newline
 extern void    LogFV(const char *Fmt, va_list Args);   //!< va_list non-newline log message
 extern void    Log(const char *Fmt, ...);      //!< Print a log message
 extern void    Debug(const char *Fmt, ...);    //!< Print a debug message (doesn't go to KTerm)
@@ -49,6 +49,7 @@ extern void   Debug_Leave(const char *FuncName, char RetType, ...);
 extern void    Debug_HexDump(const char *Header, const void *Data, size_t Length);
 
 #define UNIMPLEMENTED()        Warning("'%s' unimplemented", __func__)
+#define TODO(fmt, ...) Panic("TODO: ", fmt ,## __VA_ARGS__)
 #if DEBUG
 # define ENTER(_types...)      Debug_Enter((char*)__func__, _types)
 # define LOG(_fmt...)  Debug_Log((char*)__func__, _fmt)
@@ -72,8 +73,8 @@ extern void   Debug_HexDump(const char *Header, const void *Data, size_t Length);
 #define assert(expr)   ASSERTV(expr, "")
 #define ASSERT(expr)   ASSERTV(expr, "")
 #define ASSERTR(expr,rv)       ASSERTRV(expr, rv, "")
-#define ASSERTC(l,rel,r)       ASSERTV(l rel r, ": 0x%x"#rel"0x%x", l, r)
-#define ASSERTCR(l,rel,r,rv)   ASSERTRV(l rel r, rv, ": 0x%x"#rel"0x%x", l, r)
+#define ASSERTC(l,rel,r)       ASSERTV ((l) rel (r), ": 0x%x"#rel"0x%x", (Uint)l, (Uint)r)
+#define ASSERTCR(l,rel,r,rv)   ASSERTRV((l) rel (r), rv, ": 0x%x"#rel"0x%x", (Uint)l, (Uint)r)
 /**
  * \}
  */
diff --git a/KernelLand/Kernel/include/memfs_helpers.h b/KernelLand/Kernel/include/memfs_helpers.h
new file mode 100644 (file)
index 0000000..c20e170
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * memfs_helpers.h
+ * - Helpers for in-memory filesystems
+ *
+ * Provides name lookup, iteration, and node insertion
+ */
+#ifndef _MEMFS_HELPERS_H_
+#define _MEMFS_HELPERS_H_
+
+#include <vfs.h>
+
+typedef struct sMemFS_FileHdr  tMemFS_FileHdr;
+typedef struct sMemFS_DirHdr   tMemFS_DirHdr;
+
+extern void    MemFS_InitDir (tMemFS_DirHdr  *Dir);
+extern void    MemFS_InitFile(tMemFS_FileHdr *File);
+
+/*
+ * \brief Fetch the name of the file at the specified position
+ * \return standard tVFS_NodeType.ReadDir return values
+ */
+extern int     MemFS_ReadDir(tMemFS_DirHdr *Dir, int Pos, char Name[FILENAME_MAX]);
+/*
+ * \brief Look up a file in a directory
+ */
+extern tMemFS_FileHdr  *MemFS_FindDir(tMemFS_DirHdr *Dir, const char *Name);
+/**
+ * \brief Remove a named file from a directory
+ * \return File header for \a Name, or NULL if not found
+ */
+extern tMemFS_FileHdr  *MemFS_Remove(tMemFS_DirHdr *Dir, const char *Name);
+/**
+ * \brief Insert a pre-constructed file header into the directory
+ * \param Dir  Directory
+ * \return false if name already exists
+ */
+extern bool    MemFS_Insert(tMemFS_DirHdr *Dir, tMemFS_FileHdr *File);
+
+struct sMemFS_FileHdr
+{
+       tMemFS_FileHdr  *Next;
+       const char      *Name;
+};
+
+struct sMemFS_DirHdr
+{
+       tMemFS_FileHdr  FileHdr;
+       //tRWLock       Lock;
+       tMemFS_FileHdr  *FirstChild;
+};
+
+#endif
+
index 9916458..9c68195 100644 (file)
 #define SYS_COPYFD     69      // Create a copy of a file handle
 #define SYS_FDCTL      70      // Modify flags of a file descriptor
 #define SYS_READ       71      // Read from an open file
-#define SYS_WRITE      72      // Write to an open file
-#define SYS_IOCTL      73      // Perform an IOCtl Call
-#define SYS_SEEK       74      // Seek to a new position in the file
-#define SYS_READDIR    75      // Read from an open directory
-#define SYS_GETACL     76      // Get an ACL Value
-#define SYS_SETACL     77      // Set an ACL Value
-#define SYS_FINFO      78      // Get file information
-#define SYS_MKDIR      79      // Create a new directory
-#define SYS_LINK       80      // Create a new link to a file
-#define SYS_SYMLINK    81      // Create a symbolic link
-#define SYS_UNLINK     82      // Delete a file
-#define SYS_TELL       83      // Return the current file position
-#define SYS_CHDIR      84      // Change current directory
-#define SYS_GETCWD     85      // Get current directory
-#define SYS_MOUNT      86      // Mount a filesystem
-#define SYS_SELECT     87      // Wait for file handles
+#define SYS_READAT     72      // Read from an open file (with offset)
+#define SYS_WRITE      73      // Write to an open file
+#define SYS_WRITEAT    74      // Write to an open file (with offset)
+#define SYS_TRUNCATE   75      // Change the size of an open file
+#define SYS_IOCTL      76      // Perform an IOCtl Call
+#define SYS_SEEK       77      // Seek to a new position in the file
+#define SYS_READDIR    78      // Read from an open directory
+#define SYS_GETACL     79      // Get an ACL Value
+#define SYS_SETACL     80      // Set an ACL Value
+#define SYS_FINFO      81      // Get file information
+#define SYS_MKDIR      82      // Create a new directory
+#define SYS_LINK       83      // Create a new link to a file
+#define SYS_SYMLINK    84      // Create a symbolic link
+#define SYS_UNLINK     85      // Delete a file
+#define SYS_TELL       86      // Return the current file position
+#define SYS_CHDIR      87      // Change current directory
+#define SYS_GETCWD     88      // Get current directory
+#define SYS_MOUNT      89      // Mount a filesystem
+#define SYS_SELECT     90      // Wait for file handles
+#define SYS_MMAP       91      // Map a file into this address space
+#define SYS_MUNMAP     92      // Unmap a file
+#define SYS_MARSHALFD  93      // Create a reference to a FD suitable for handing to another process
+#define SYS_UNMARSHALFD        94      // Accept a marshaled FD
 
-#define NUM_SYSCALLS   88
-#define SYS_DEBUG      0x100
+#define NUM_SYSCALLS   95
+#define SYS_DEBUGS     0x100
+#define SYS_DEBUGF     0x101
+#define SYS_DEBUGHEX   0x102
 
 #if !defined(__ASSEMBLER__) && !defined(NO_SYSCALL_STRS)
 static const char *cSYSCALL_NAMES[] = {
@@ -147,7 +156,10 @@ static const char *cSYSCALL_NAMES[] = {
        "SYS_COPYFD",
        "SYS_FDCTL",
        "SYS_READ",
+       "SYS_READAT",
        "SYS_WRITE",
+       "SYS_WRITEAT",
+       "SYS_TRUNCATE",
        "SYS_IOCTL",
        "SYS_SEEK",
        "SYS_READDIR",
@@ -163,6 +175,10 @@ static const char *cSYSCALL_NAMES[] = {
        "SYS_GETCWD",
        "SYS_MOUNT",
        "SYS_SELECT",
+       "SYS_MMAP",
+       "SYS_MUNMAP",
+       "SYS_MARSHALFD",
+       "SYS_UNMARSHALFD",
 
        ""
 };
index ee3c887..35743b1 100644 (file)
 %define SYS_COPYFD     69       ;Create a copy of a file handle
 %define SYS_FDCTL      70       ;Modify flags of a file descriptor
 %define SYS_READ       71       ;Read from an open file
-%define SYS_WRITE      72       ;Write to an open file
-%define SYS_IOCTL      73       ;Perform an IOCtl Call
-%define SYS_SEEK       74       ;Seek to a new position in the file
-%define SYS_READDIR    75       ;Read from an open directory
-%define SYS_GETACL     76       ;Get an ACL Value
-%define SYS_SETACL     77       ;Set an ACL Value
-%define SYS_FINFO      78       ;Get file information
-%define SYS_MKDIR      79       ;Create a new directory
-%define SYS_LINK       80       ;Create a new link to a file
-%define SYS_SYMLINK    81       ;Create a symbolic link
-%define SYS_UNLINK     82       ;Delete a file
-%define SYS_TELL       83       ;Return the current file position
-%define SYS_CHDIR      84       ;Change current directory
-%define SYS_GETCWD     85       ;Get current directory
-%define SYS_MOUNT      86       ;Mount a filesystem
-%define SYS_SELECT     87       ;Wait for file handles
+%define SYS_READAT     72       ;Read from an open file (with offset)
+%define SYS_WRITE      73       ;Write to an open file
+%define SYS_WRITEAT    74       ;Write to an open file (with offset)
+%define SYS_TRUNCATE   75       ;Change the size of an open file
+%define SYS_IOCTL      76       ;Perform an IOCtl Call
+%define SYS_SEEK       77       ;Seek to a new position in the file
+%define SYS_READDIR    78       ;Read from an open directory
+%define SYS_GETACL     79       ;Get an ACL Value
+%define SYS_SETACL     80       ;Set an ACL Value
+%define SYS_FINFO      81       ;Get file information
+%define SYS_MKDIR      82       ;Create a new directory
+%define SYS_LINK       83       ;Create a new link to a file
+%define SYS_SYMLINK    84       ;Create a symbolic link
+%define SYS_UNLINK     85       ;Delete a file
+%define SYS_TELL       86       ;Return the current file position
+%define SYS_CHDIR      87       ;Change current directory
+%define SYS_GETCWD     88       ;Get current directory
+%define SYS_MOUNT      89       ;Mount a filesystem
+%define SYS_SELECT     90       ;Wait for file handles
+%define SYS_MMAP       91       ;Map a file into this address space
+%define SYS_MUNMAP     92       ;Unmap a file
+%define SYS_MARSHALFD  93       ;Create a reference to a FD suitable for handing to another process
+%define SYS_UNMARSHALFD        94       ;Accept a marshaled FD
index ed90d0b..0203932 100644 (file)
@@ -21,6 +21,7 @@ enum eFaultNumbers
 #define GETMSG_IGNORE  ((void*)-1)
 
 typedef struct sThread tThread;
+typedef struct sProcess        tProcess;
 
 // === FUNCTIONS ===
 extern tThread *Proc_GetCurThread(void);
@@ -32,9 +33,9 @@ extern int    Threads_SetGID(tUID ID);
 extern tTID    Threads_WaitTID(int TID, int *Status);
 
 
-extern int     *Threads_GetMaxFD(void);
-extern char    **Threads_GetCWD(void);
-extern char    **Threads_GetChroot(void);
+extern int     *Threads_GetMaxFD(tProcess *Process);
+extern char    **Threads_GetCWD(tProcess *Process);
+extern char    **Threads_GetChroot(tProcess *Process);
 
 extern int     Proc_SendMessage(Uint Dest, int Length, void *Data);
 extern int     Proc_GetMessage(Uint *Source, Uint BufSize, void *Buffer);
index f766613..b030627 100644 (file)
@@ -216,6 +216,21 @@ typedef struct sVFS_Node
  * \}
  */
 
+/**
+ * \name tVFS_NodeType.Type flags
+ * \brief Flags for node types
+ * \{
+ */
+//\! Calls to VFS_Write should not generate calls to .Trunctate
+//\! 
+//\! If this flag is set, writing over the end of the file will not call .Truncate automatically
+#define VFS_NODETYPEFLAG_NOAUTOEXPAND  0x001
+//\! Node type describes a stream (offset ignored, seeking disallowed)
+#define VFS_NODETYPEFLAG_STREAM        0x002
+/**
+ * \}
+ */
+
 /**
  * \brief Functions for a specific node type
  */
@@ -226,6 +241,11 @@ struct sVFS_NodeType
         */
        const char      *TypeName;
 
+       /**
+        * \brief Flags describing operational quirks
+        */
+       unsigned int    Flags;
+
        /**
         * \name Common Functions
         * \brief Functions that are used no matter the value of .Flags
@@ -293,7 +313,18 @@ struct sVFS_NodeType
         * \return Boolean Failure
         * \note If NULL, the VFS implements it using .Read
         */
-        int    (*MMap)(struct sVFS_Node *Node, off_t Offset, int Length, void *Dest);
+        int    (*MMap)(struct sVFS_Node *Node, off_t Offset, size_t Length, void *Dest);
+       
+       /**
+        * \brief Resize a file
+        * \param Node  Pointer to this node
+        * \param NewSize       New file size
+        * \return Actual new file size
+        * \note If NULL, \a Write may be called with Offset + Length > Size
+        *
+        * Called to increase/decrease the size of a file. If the 
+        */
+       off_t   (*Truncate)(struct sVFS_Node *Node, off_t NewSize);
        
        /**
         * \}
@@ -469,7 +500,7 @@ extern tVFS_ACL     *VFS_UnixToAcessACL(Uint Mode, Uint Owner, Uint Group);
  * \param Type Type of wait
  * \param Timeout      Time to wait (NULL for infinite wait)
  * \param Name Name to show in debug output
- * \return Number of nodes that actioned (0 or 1)
+ * \return Bitset of Type flags that applied
  */
 extern int     VFS_SelectNode(tVFS_Node *Node, int Type, tTime *Timeout, const char *Name);
 
index 65a8162..42d9865 100644 (file)
@@ -226,6 +226,20 @@ extern int VFS_DuplicateFD(int SrcFD, int DstFD);
  */
 extern int     VFS_SetFDFlags(int FD, int Mask, int Value);
 
+/**
+ * \brief Save specified file handle such that it can be passed between processes
+ * \param FD   File descriptor to save
+ * \return Marshalled handle, or (uint64_t)-1 on error
+ */
+extern Uint64  VFS_MarshalHandle(int FD);
+
+/**
+ * \brief Restore a marshalled handle into the current process
+ * \param Handle returned by VFS_MarshalHandle
+ * \return File descriptor, or -1 on error
+ */
+extern int     VFS_UnmarshalHandle(Uint64 Handle);
+
 /**
  * \brief Get file information from an open file
  * \param FD   File handle returned by ::VFS_Open
@@ -314,6 +328,16 @@ extern size_t      VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer);
  */
 extern size_t  VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer);
 
+/**
+ * \brief Set the valid size of a file
+ * \param FD   File descriptor
+ * \param Size New file size
+ * \return Actual new file size (-1 if error occurred)
+ *
+ * \note Not all files support this call (will return ENOTIMPL)
+ */
+extern off_t   VFS_Truncate(int FD, off_t Size);
+
 /**
  * \brief Sends an IOCtl request to the driver
  * \param FD   File handle returned by ::VFS_Open
index 95ec227..a9829de 100644 (file)
@@ -10,7 +10,7 @@
 
 // === FUNCTIONS ===
 extern void    VFS_ReferenceUserHandles(void);
-extern void    VFS_CloseAllUserHandles(void);
+extern void    VFS_CloseAllUserHandles(struct sProcess *Process);
 
 extern void    *VFS_SaveHandles(int NumFDs, int *FDs);
 extern void    VFS_RestoreHandles(int NumFDs, void *Handles);
index 2e08a17..572184d 100644 (file)
@@ -74,6 +74,7 @@ EXPORT(CheckMem);
 // === CODE ===
 // - Import userland stroi.c file
 #define _LIB_H_
+#define _SysDebug(f,v...)      Log_Debug("libc", f ,## v)
 #include "../../Usermode/Libraries/libc.so_src/strtoi.c"
 
 int ParseInt(const char *string, int *Val)
@@ -380,7 +381,7 @@ int vsnprintf(char *__s, const size_t __maxlen, const char *__format, va_list ar
                                break;
                        }
                        p = va_arg(args, char*);        // Get Argument
-                       if( !p || !CheckString(p) )     p = "(inval)";  // Avoid #PFs  
+                       if( p && !CheckString(p) )      goto invalString;       // Avoid #PFs  
                printString:
                        if(!p)          p = "(null)";
                        len = strlen(p);
@@ -388,6 +389,20 @@ int vsnprintf(char *__s, const size_t __maxlen, const char *__format, va_list ar
                        while(*p && precision--) { PUTCH(*p); p++;} 
                        if( bPadLeft )  while(len++ < minSize)  PUTCH(pad);
                        break;
+               invalString:    
+                       PUTCH('(');PUTCH('i');PUTCH('n');PUTCH('v');PUTCH('a'); PUTCH('l');PUTCH(':');
+                       PUTCH('*');PUTCH('0');PUTCH('x');
+                       val = (tVAddr)p;
+                       for( len = BITS/4; len -- && ((val>>(len*4))&15) == 0; )
+                               ;
+                       len ++;
+                       if( len == 0 )
+                               PUTCH( '0' );
+                       else
+                               while( len -- )
+                                       PUTCH( cUCDIGITS[ (val>>(len*4))&15 ] );
+                       PUTCH(')');
+                       break;
                
                case 'C':       // Non-Null Terminated Character Array
                        p = va_arg(args, char*);
index 46d4c04..3ccfef2 100644 (file)
@@ -158,18 +158,18 @@ void Log_Int_PrintMessage(tLogEntry *Entry)
        if( CPU_HAS_LOCK(&glLogOutput) )
                return ;        // TODO: Error?
        SHORTLOCK( &glLogOutput );
-       LogF("%s%014lli",
+       bool completed = LogF(
+               "%s%014lli%s [%-8s] %i - %.*s\x1B[0m\r\n",
                csaLevelColours[Entry->Level],
-               Entry->Time
-               );
-       LogF("%s [%-8s] %i - %.*s",
+               Entry->Time,
                csaLevelCodes[Entry->Level],
                Entry->Ident,
                Threads_GetTID(),
                Entry->Length,
                Entry->Data
                );
-       LogF("\x1B[0m\r\n");    // Separate in case Entry->Data is too long
+       if( !completed )
+               LogF("\x1B[0m\r\n");    // Separate in case Entry->Data is too long
        SHORTREL( &glLogOutput );
 }
 
diff --git a/KernelLand/Kernel/memfs_helpers.c b/KernelLand/Kernel/memfs_helpers.c
new file mode 100644 (file)
index 0000000..a7e5fc4
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * memfs_helpers.c
+ * - Helpers for in-memory filesystems
+ */
+#include <memfs_helpers.h>
+
+// === CODE ===
+void MemFS_InitDir(tMemFS_DirHdr *Dir)
+{
+       MemFS_InitFile(&Dir->FileHdr);
+}
+void MemFS_InitFile(tMemFS_FileHdr *File)
+{
+       File->Next = NULL;
+}
+
+int MemFS_ReadDir(tMemFS_DirHdr *Dir, int Pos, char Name[FILENAME_MAX])
+{
+        int    i = 0;
+       // TODO: Lock
+       for( tMemFS_FileHdr *file = Dir->FirstChild; file; file = file->Next, i ++ )
+       {
+               if( i == Pos )
+               {
+                       strncpy(Name, file->Name, FILENAME_MAX);
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+tMemFS_FileHdr *MemFS_FindDir(tMemFS_DirHdr *Dir, const char *Name)
+{
+       // TODO: Lock
+       for( tMemFS_FileHdr *file = Dir->FirstChild; file; file = file->Next )
+       {
+               if( strcmp(file->Name, Name) == 0 )
+                       return file;
+       }
+       return NULL;
+}
+tMemFS_FileHdr *MemFS_Remove(tMemFS_DirHdr *Dir, const char *Name)
+{
+       UNIMPLEMENTED();
+       return NULL;
+}
+bool MemFS_Insert(tMemFS_DirHdr *Dir, tMemFS_FileHdr *File)
+{
+       UNIMPLEMENTED();
+       return false;
+}
+
index c39ce10..1fd6459 100644 (file)
@@ -21,7 +21,8 @@ int RWLock_AcquireRead(tRWLock *Lock)
        SHORTLOCK( &Lock->Protector );
        
        // Check if the lock is already held by a writer
-       if( Lock->Owner )
+       // - OR, there's a writer waiting to write
+       if( Lock->Owner || Lock->WriterWaiting )
        {
                LOG("Waiting");
                Threads_int_Sleep(THREAD_STAT_RWLOCKSLEEP, Lock, 0,
index d2f9185..7b4855c 100644 (file)
        if(tmp[i]) break;\
 } while(0)
 
+#if BITS==64
+#define ARG64(idx1,idx2)       ***ARG64 not used on 64-bit***
+#else
+#define ARG64(idx1, idx2)      (Regs->Arg##idx1|(((Uint64)Regs->Arg##idx2)<<32))
+#endif
+
 // === IMPORTS ===
 extern Uint    Binary_Load(const char *file, Uint *entryPoint);
 
@@ -250,7 +256,7 @@ void SyscallHandler(tSyscallRegs *Regs)
                #if BITS == 64
                ret = VFS_Seek( Regs->Arg1, Regs->Arg2, Regs->Arg3 );
                #else
-               ret = VFS_Seek( Regs->Arg1, Regs->Arg2|(((Uint64)Regs->Arg3)<<32), Regs->Arg4 );
+               ret = VFS_Seek( Regs->Arg1, ARG64(2, 3), Regs->Arg4 );
                #endif
                break;
                
@@ -262,11 +268,41 @@ void SyscallHandler(tSyscallRegs *Regs)
                CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 );
                ret = VFS_Write( Regs->Arg1, Regs->Arg3, (void*)Regs->Arg2 );
                break;
+       case SYS_WRITEAT:
+               #if BITS == 64
+               CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg3 );
+               ret = VFS_WriteAt( Regs->Arg1, Regs->Arg2, Regs->Arg3, (void*)Regs->Arg4 );
+               #else
+               CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg4 );
+               Debug("VFS_WriteAt(%i, %lli, %i, %p)",
+                       Regs->Arg1, ARG64(2, 3), Regs->Arg4, (void*)Regs->Arg5);
+               ret = VFS_WriteAt( Regs->Arg1, ARG64(2, 3), Regs->Arg4, (void*)Regs->Arg5 );
+               #endif
+               break;
        
        case SYS_READ:
                CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 );
                ret = VFS_Read( Regs->Arg1, Regs->Arg3, (void*)Regs->Arg2 );
                break;
+       case SYS_READAT:
+               CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg2 );
+               #if BITS == 64
+               ret = VFS_ReadAt( Regs->Arg1, Regs->Arg2, Regs->Arg3, (void*)Regs->Arg4 );
+               #else
+               ret = VFS_ReadAt( Regs->Arg1, Regs->Arg2, ARG64(3, 4), (void*)Regs->Arg5 );
+               #endif
+               break;
+       
+       case SYS_TRUNCATE:
+               ret = VFS_Truncate(
+                       Regs->Arg1,
+                       #if BITS == 32
+                       ARG64(2,3)
+                       #else
+                       Regs->Arg2
+                       #endif
+                       );
+               break;
        
        case SYS_FINFO:
                CHECK_NUM_NONULL( (void*)Regs->Arg2, sizeof(tFInfo) + Regs->Arg3*sizeof(tVFS_ACL) );
@@ -369,6 +405,21 @@ void SyscallHandler(tSyscallRegs *Regs)
                        );
                break;
 
+       case SYS_MMAP:
+               ret = (tVAddr)VFS_MMap(
+                       (void*)Regs->Arg1, Regs->Arg2,
+                       Regs->Arg3&0xFFFF, Regs->Arg3>>16,
+                       Regs->Arg4,
+                       #if BITS == 32
+                       ARG64(5,6)
+                       #else
+                       Regs->Arg5
+                       #endif
+                       );
+               break;
+       case SYS_MUNMAP:
+               ret = VFS_MUnmap( (void*)Regs->Arg1, Regs->Arg2 );
+               break;
        
        // Create a directory
        case SYS_MKDIR:
@@ -378,16 +429,37 @@ void SyscallHandler(tSyscallRegs *Regs)
        
        case SYS_UNLINK:
                Log_Error("Syscalls", "TODO: Impliment SYS_UNLINK");
-               // Fall
+               break;
+       
+       case SYS_MARSHALFD:
+               ret = VFS_MarshalHandle(Regs->Arg1);
+               break;
+       case SYS_UNMARSHALFD:
+               #if BITS == 64
+               ret = VFS_UnmarshalHandle( Regs->Arg1 );
+               #else
+               ret = VFS_UnmarshalHandle( ARG64(1,2) );
+               #endif
+               break;
+
        // -- Debug
        //#if DEBUG_BUILD
-       case SYS_DEBUG:
+       case SYS_DEBUGS:
+               CHECK_STR_NONULL( (char*)Regs->Arg1 );
+               Log("Log: %08lli [%i] %s", now(), Threads_GetTID(), (const char*)Regs->Arg1);
+               break;
+       case SYS_DEBUGF:
                CHECK_STR_NONULL( (char*)Regs->Arg1 );
                LogF("Log: %08lli [%i] ", now(), Threads_GetTID());
                LogF((const char*)Regs->Arg1,
                        Regs->Arg2, Regs->Arg3, Regs->Arg4, Regs->Arg5, Regs->Arg6);
                LogF("\r\n");
                break;
+       case SYS_DEBUGHEX:
+               CHECK_STR_NONULL( (char*)Regs->Arg1 );
+               CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 );
+               Debug_HexDump( (const char*)Regs->Arg1, (void*)Regs->Arg2, Regs->Arg3 );
+               break;
        //#endif
        
        // -- Default (Return Error)
index 42ae03c..bea821b 100644 (file)
@@ -53,7 +53,10 @@ SYS_CLOSE    Close a file
 SYS_COPYFD     Create a copy of a file handle
 SYS_FDCTL      Modify flags of a file descriptor
 SYS_READ       Read from an open file
+SYS_READAT     Read from an open file (with offset)
 SYS_WRITE      Write to an open file
+SYS_WRITEAT    Write to an open file (with offset)
+SYS_TRUNCATE   Change the size of an open file
 SYS_IOCTL      Perform an IOCtl Call
 SYS_SEEK       Seek to a new position in the file
 SYS_READDIR    Read from an open directory
@@ -69,3 +72,8 @@ SYS_CHDIR     Change current directory
 SYS_GETCWD     Get current directory
 SYS_MOUNT      Mount a filesystem
 SYS_SELECT     Wait for file handles
+SYS_MMAP       Map a file into this address space
+SYS_MUNMAP     Unmap a file
+SYS_MARSHALFD  Create a reference to a FD suitable for handing to another process
+SYS_UNMARSHALFD        Accept a marshaled FD
+
index 0c701c3..9892af3 100644 (file)
@@ -14,6 +14,7 @@ extern int    Modules_LoadBuiltins(void);
 extern void    Modules_SetBuiltinParams(char *Name, char *ArgString);
 extern void    Debug_SetKTerminal(const char *File);
 extern void    Timer_CallbackThread(void *);
+extern void    EmergencyConsole(void);
 
 // === PROTOTYPES ===
 void   System_Init(char *Commandline);
@@ -22,6 +23,7 @@ void  System_ExecuteCommandLine(void);
 void   System_ParseVFS(char *Arg);
 void   System_ParseModuleArgs(char *Arg);
 void   System_ParseSetting(char *Arg);
+void   System_EmergencyConsole(void);
 
 // === GLOBALS ===
 const char     *gsInitBinary = "/Acess/SBin/init";
@@ -41,6 +43,7 @@ void System_Init(char *CommandLine)
        Modules_LoadBuiltins();
        Arch_LoadBootModules();
        
+       Log_Log("Config", "Running command line '%s", CommandLine);
        System_ExecuteCommandLine();
        
        // - Execute the Config Script
@@ -52,12 +55,24 @@ void System_Init(char *CommandLine)
                VFS_Open("/Devices/pts/vt0", VFS_OPENFLAG_WRITE|VFS_OPENFLAG_USER);     // 1: stdout
                VFS_DuplicateFD(1, 2);  // 2: stderr
                Proc_Execve(gsInitBinary, args, &args[1], 0);
+               
+               System_EmergencyConsole();
+               
                Log_KernelPanic("System", "Unable to spawn init '%s'", gsInitBinary);
        }
        
        // Set the debug to be echoed to the terminal
        Log_Log("Config", "Kernel now echoes to VT7 (Ctrl-Alt-F8)");
        Debug_SetKTerminal("/Devices/pts/vt7");
+       
+       // Run a thread to reap unowned threads
+       for( ;; )
+       {
+                int    status;
+               // TODO: Inform init when a thread dies
+               int tid = Threads_WaitTID(-1, &status);
+               Log_Debug("Thread0", "Thread %i exited with status %i", tid, status);
+       }
 }
 
 /**
@@ -265,3 +280,8 @@ void System_ParseSetting(char *Arg)
        }
 }
 
+void System_EmergencyConsole(void)
+{
+       // TODO: Support an emergency kernel-land console (with FS viewing support)
+       EmergencyConsole();
+}
index 545896c..469c5ec 100644 (file)
@@ -4,6 +4,7 @@
  * threads.c
  * - Common Thread Control
  */
+#define DEBUG  0
 #include <acess.h>
 #include <threads.h>
 #include <threads_int.h>
@@ -198,7 +199,7 @@ void Threads_Delete(tThread *Thread)
                        proc->Next->Prev = proc->Prev;
 
                // VFS Cleanup
-               VFS_CloseAllUserHandles();
+               VFS_CloseAllUserHandles( proc );
                // Architecture cleanup
                Proc_ClearProcess( proc );
                // VFS Configuration strings
@@ -329,11 +330,10 @@ void Threads_SetPriority(tThread *Thread, int Pri)
  */
 tThread *Threads_CloneTCB(Uint Flags)
 {
-       tThread *cur, *new;
-       cur = Proc_GetCurThread();
+       tThread *cur = Proc_GetCurThread();
        
        // Allocate and duplicate
-       new = malloc(sizeof(tThread));
+       tThread *new = malloc(sizeof(tThread));
        if(new == NULL) { errno = -ENOMEM; return NULL; }
        memcpy(new, cur, sizeof(tThread));
        
@@ -480,18 +480,26 @@ tTID Threads_WaitTID(int TID, int *Status)
                tTID    ret = -1;
                if( ev & THREAD_EVENT_DEADCHILD )
                {
+                       tThread * const us = Proc_GetCurThread();
                        // A child died, get the TID
-                       tThread *us = Proc_GetCurThread();
                        ASSERT(us->LastDeadChild);
-                       ret = us->LastDeadChild->TID;
+                       tThread *dead_thread = us->LastDeadChild;
+                       us->LastDeadChild = dead_thread->Next;
+                       if( us->LastDeadChild )
+                               Threads_PostEvent( us, THREAD_EVENT_DEADCHILD );
+                       else
+                               Threads_ClearEvent( THREAD_EVENT_DEADCHILD );
+                       Mutex_Release(&us->DeadChildLock);
+                       
+                       ret = dead_thread->TID;
                        // - Mark as dead (as opposed to undead)
-                       ASSERT(us->LastDeadChild->Status == THREAD_STAT_ZOMBIE);
-                       us->LastDeadChild->Status = THREAD_STAT_DEAD;
+                       ASSERTC(dead_thread->Status, ==, THREAD_STAT_ZOMBIE);
+                       dead_thread->Status = THREAD_STAT_DEAD;
                        // - Set return status
                        if(Status)
-                               *Status = us->LastDeadChild->RetStatus;
-                       us->LastDeadChild = NULL;
-                       Mutex_Release(&us->DeadChildLock);
+                               *Status = dead_thread->RetStatus;
+                       
+                       Threads_Delete( dead_thread );
                }
                else
                {
@@ -722,9 +730,11 @@ void Threads_Kill(tThread *Thread, int Status)
        SHORTREL( &glThreadListLock );
        // TODO: It's possible that we could be timer-preempted here, should disable that... somehow
        Mutex_Acquire( &Thread->Parent->DeadChildLock );        // released by parent
+       Thread->Next = Thread->Parent->LastDeadChild;
        Thread->Parent->LastDeadChild = Thread;
        Threads_PostEvent( Thread->Parent, THREAD_EVENT_DEADCHILD );
        
+       // Process cleanup happens on reaping
        Log("Thread %i went *hurk* (%i)", Thread->TID, Status);
        
        // And, reschedule
@@ -750,6 +760,7 @@ void Threads_Yield(void)
 void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
 {
        tThread *us = Proc_GetCurThread();
+       LOG("us = %p(%i %s), status=%i", us, us->TID, us->ThreadName, Status);
        ASSERT(Status != THREAD_STAT_ACTIVE);
        ASSERT(Status != THREAD_STAT_DEAD);
        while( us->Status == Status )
@@ -1246,17 +1257,20 @@ int *Threads_GetErrno(void)
 }
 
 // --- Configuration ---
-int *Threads_GetMaxFD(void)
+int *Threads_GetMaxFD(tProcess *Process)
 {
-       return &Proc_GetCurThread()->Process->MaxFD;
+       if(!Process)    Process = Proc_GetCurThread()->Process;
+       return &Process->MaxFD;
 }
-char **Threads_GetChroot(void)
+char **Threads_GetChroot(tProcess *Process)
 {
-       return &Proc_GetCurThread()->Process->RootDir;
+       if(!Process)    Process = Proc_GetCurThread()->Process;
+       return &Process->RootDir;
 }
-char **Threads_GetCWD(void)
+char **Threads_GetCWD(tProcess *Process)
 {
-       return &Proc_GetCurThread()->Process->CurrentWorkingDir;
+       if(!Process)    Process = Proc_GetCurThread()->Process;
+       return &Process->CurrentWorkingDir;
 }
 // ---
 
@@ -1314,22 +1328,16 @@ void Threads_int_DumpThread(tThread *thread)
  */
 void Threads_DumpActive(void)
 {
-       tThread *thread;
-       tThreadList     *list;
-       #if SCHEDULER_TYPE == SCHED_RR_PRI
-        int    i;
-       #endif
-       
        Log("Active Threads: (%i reported)", giNumActiveThreads);
        
        #if SCHEDULER_TYPE == SCHED_RR_PRI
-       for( i = 0; i < MIN_PRIORITY+1; i++ )
+       for( int i = 0; i < MIN_PRIORITY+1; i++ )
        {
-               list = &gaActiveThreads[i];
+               tThreadList *list = &gaActiveThreads[i];
        #else
-               list = &gActiveThreads;
+               tThreadList *list = &gActiveThreads;
        #endif
-               for(thread=list->Head;thread;thread=thread->Next)
+               for(tThread *thread = list->Head; thread; thread = thread->Next)
                {
                        Threads_int_DumpThread(thread);
                        if(thread->Status != THREAD_STAT_ACTIVE)
@@ -1465,6 +1473,7 @@ tThread *Threads_int_GetRunnable(void)
        // Single-list round-robin
        // -----------------------------------
        tThread *thread = gActiveThreads.Head;
+       LOG("thread = %p", thread);
        if( thread )
        {
                gActiveThreads.Head = thread->Next;
@@ -1486,23 +1495,20 @@ tThread *Threads_int_GetRunnable(void)
  */
 tThread *Threads_GetNextToRun(int CPU, tThread *Last)
 {
-       // If this CPU has the lock, we must let it complete
-       if( CPU_HAS_LOCK( &glThreadListLock ) )
-               return Last;
+       ASSERT( CPU_HAS_LOCK(&glThreadListLock) );
        
        // Don't change threads if the current CPU has switches disabled
-       if( gaThreads_NoTaskSwitch[CPU] )
+       if( gaThreads_NoTaskSwitch[CPU] ) {
+               LOG("- Denied");
                return Last;
-
-       // Lock thread list
-       SHORTLOCK( &glThreadListLock );
+       }
        
        // Make sure the current (well, old) thread is marked as de-scheduled   
        if(Last)        Last->CurCPU = -1;
 
        // No active threads, just take a nap
        if(giNumActiveThreads == 0) {
-               SHORTREL( &glThreadListLock );
+               LOG("- No active");
                #if DEBUG_TRACE_TICKETS
                Log("No active threads");
                #endif
@@ -1545,7 +1551,7 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last)
 
        // Call actual scheduler        
        tThread *thread = Threads_int_GetRunnable();
-               
+       
        // Anything to do?
        if( thread )
        {
@@ -1571,8 +1577,6 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last)
                Warning("No runnable thread for CPU%i", CPU);
        }
        
-       SHORTREL( &glThreadListLock );
-       
        return thread;
 }
 
index 15b6190..478c41f 100644 (file)
@@ -76,8 +76,9 @@ void Timer_CallTimers()
 {
        // Tick the random number generator every time timers are checked
        rand();
-       
+
        SHORTLOCK(&gTimers_ListLock);
+       LOG("gTimers = %p (%lli ms)", gTimers, (gTimers ? gTimers->FiresAfter : 0));
        while( gTimers && gTimers->FiresAfter < now() )
        {
                ASSERT( gTimers != gTimers->Next );     
index 661ced8..d500aa9 100644 (file)
@@ -39,7 +39,7 @@ tVFS_Handle *VFS_GetHandle(int FD)
                if(FD >= MAX_KERNEL_FILES)      return NULL;
                h = &gaKernelHandles[ FD ];
        } else {
-               if(FD >= *Threads_GetMaxFD())   return NULL;
+               if(FD >= *Threads_GetMaxFD(NULL))       return NULL;
                h = &gaUserHandles[ FD ];
        }
        
@@ -59,7 +59,7 @@ int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode)
                h = &gaKernelHandles[FD];
        }
        else {
-               if( FD >= *Threads_GetMaxFD())  return -1;
+               if( FD >= *Threads_GetMaxFD(NULL))      return -1;
                h = &gaUserHandles[FD];
        }
        h->Node = Node;
@@ -72,7 +72,7 @@ int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
        // Check for a user open
        if(bIsUser)
        {
-                int    max_handles = *Threads_GetMaxFD();
+                int    max_handles = *Threads_GetMaxFD(NULL);
                // Allocate Buffer
                if( MM_GetPhysAddr( gaUserHandles ) == 0 )
                {
@@ -132,14 +132,13 @@ int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
 
 void VFS_ReferenceUserHandles(void)
 {
-        int    i;
-        int    max_handles = *Threads_GetMaxFD();
+       const int       max_handles = *Threads_GetMaxFD(NULL);
 
        // Check if this process has any handles
        if( MM_GetPhysAddr( gaUserHandles ) == 0 )
                return ;
        
-       for( i = 0; i < max_handles; i ++ )
+       for( int i = 0; i < max_handles; i ++ )
        {
                tVFS_Handle     *h;
                h = &gaUserHandles[i];
@@ -150,22 +149,34 @@ void VFS_ReferenceUserHandles(void)
        }
 }
 
-void VFS_CloseAllUserHandles(void)
+void VFS_CloseAllUserHandles(struct sProcess *Process)
 {
-        int    max_handles = *Threads_GetMaxFD();
+       const int       max_handles = *Threads_GetMaxFD(Process);
+       ENTER("pProcess", Process);
 
+       if( max_handles >= PAGE_SIZE / sizeof(tVFS_Handle) )
+               TODO("More than a page of handles");
+
+       tVFS_Handle     *handles = MM_MapTempFromProc(Process, gaUserHandles);
+       LOG("handles=%p", handles);
        // Check if this process has any handles
-       if( MM_GetPhysAddr( gaUserHandles ) == 0 )
+       if( !handles ) {
+               LEAVE('-');
                return ;
+       }
        
        for( int i = 0; i < max_handles; i ++ )
        {
-               tVFS_Handle     *h;
-               h = &gaUserHandles[i];
+               tVFS_Handle     *h = &handles[i];
+               LOG("handles[%i].Node = %p", i, h->Node);
                if( !h->Node )
                        continue ;
                _CloseNode(h->Node);
+               h->Node = NULL;
        }
+       
+       MM_FreeTemp(handles);
+       LEAVE('-');
 }
 
 /**
@@ -174,7 +185,7 @@ void VFS_CloseAllUserHandles(void)
 void *VFS_SaveHandles(int NumFDs, int *FDs)
 {
        tVFS_Handle     *ret;
-        int    max_handles = *Threads_GetMaxFD();
+       const int       max_handles = *Threads_GetMaxFD(NULL);
        
        // Check if this process has any handles
        if( MM_GetPhysAddr( gaUserHandles ) == 0 )
@@ -235,11 +246,16 @@ void *VFS_SaveHandles(int NumFDs, int *FDs)
 void VFS_RestoreHandles(int NumFDs, void *Handles)
 {
        tVFS_Handle     *handles = Handles;
-        int    max_handles = *Threads_GetMaxFD();
+       const int       max_handles = *Threads_GetMaxFD(NULL);
 
        // NULL = nothing to do
        if( !Handles )
-               return ;        
+               return ;
+       
+       if( NumFDs > max_handles ) {
+               Log_Notice("VFS", "RestoreHandles: Capping from %i FDs to %i", NumFDs, max_handles);
+               NumFDs = max_handles;
+       }
 
        // Allocate user handle area (and dereference existing handles)
        for( int i = 0; i < NumFDs; i ++ )
index 271e920..35c1ebf 100644 (file)
@@ -100,16 +100,32 @@ size_t VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer)
  */
 size_t VFS_Write(int FD, size_t Length, const void *Buffer)
 {
-       tVFS_Handle     *h;
-       size_t  ret;
-       
-       h = VFS_GetHandle(FD);
+       tVFS_Handle     *h = VFS_GetHandle(FD);
        if(!h) {
                LOG("FD%i is not open", FD);
                errno = EBADF;
                return -1;
        }
        
+       size_t ret = VFS_WriteAt(FD, h->Position, Length, Buffer);
+       if(ret == (size_t)-1)   return -1;
+
+       if( !(h->Node->Type->Flags & VFS_NODETYPEFLAG_STREAM) )
+               h->Position += ret;
+       return ret;
+}
+
+/**
+ * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
+ * \brief Write data to a file at a given offset
+ */
+size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer)
+{
+       LOG("FD=%i,Offset=%lli,Length=%i,Buffer=%p",
+               FD, Offset, Length, Buffer);
+       tVFS_Handle     *h = VFS_GetHandle(FD);
+       if(!h)  return -1;
+       
        if( !(h->Mode & VFS_OPENFLAG_WRITE) ) {
                LOG("FD%i not opened for writing", FD);
                errno = EBADF;
@@ -121,57 +137,63 @@ size_t VFS_Write(int FD, size_t Length, const void *Buffer)
                return -1;
        }
 
-       if( !h->Node->Type || !h->Node->Type->Write ) {
+       const tVFS_NodeType*    nodetype = h->Node->Type;
+       if(!nodetype || !nodetype->Write) {
                LOG("FD%i has no write method", FD);
                errno = EINTERNAL;
                return 0;
        }
-
-       if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
+       
+       if( !MM_GetPhysAddr(nodetype->Write) ) {
                Log_Error("VFS", "Node type %p(%s) write method is junk %p",
-                       h->Node->Type, h->Node->Type->TypeName,
-                       h->Node->Type->Write);
+                       nodetype, nodetype->TypeName, nodetype->Write);
                errno = EINTERNAL;
                return -1;
        }
        
-       Uint flags = 0;
-       flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
-       ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer, flags);
-       if(ret != Length)       LOG("%i/%i written", ret, Length);
-       if(ret == (size_t)-1)   return -1;
-
-       h->Position += ret;
-       return ret;
-}
-
-/**
- * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
- * \brief Write data to a file at a given offset
- */
-size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer)
-{
-       tVFS_Handle     *h;
-       size_t  ret;
-       
-       h = VFS_GetHandle(FD);
-       if(!h)  return -1;
-       
-       if( !(h->Mode & VFS_OPENFLAG_WRITE) )   return -1;
-       if( h->Node->Flags & VFS_FFLAG_DIRECTORY )      return -1;
-
-       if(!h->Node->Type || !h->Node->Type->Write)     return 0;
-
-       if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
-               Log_Error("VFS", "Node type %p(%s) write method is junk %p",
-                       h->Node->Type, h->Node->Type->TypeName,
-                       h->Node->Type->Write);
-               return -1;
+       // Bounds checks
+       if( h->Node->Size != (Uint64)-1 && Offset > h->Node->Size ) {
+               Log_Notice("VFS", "Write starting past EOF of FD%x (%lli > %lli)",
+                       FD, Offset, h->Node->Size);
+               //errno = ESPIPE;
+               return 0;
+       }
+       if( Offset + Length > h->Node->Size )
+       {
+               // Going OOB
+               if( !nodetype->Truncate )
+               {
+                       LOG("No .Truncate method, emiting write past EOF");
+               }
+               else if( nodetype->Flags & VFS_NODETYPEFLAG_NOAUTOEXPAND )
+               {
+                       LOG("NOAUTOEXPAND set, truncating length from %i to %i",
+                               Length, h->Node->Size - Offset);
+                       Length = h->Node->Size - Offset;
+               }
+               else if( nodetype->Truncate(h->Node, Offset + Length) != Offset + Length )
+               {
+                       // oh... fail? Truncate to current size
+                       LOG(".Truncate failed, truncating length from %i to %i",
+                               Length, h->Node->Size - Offset);
+                       Length = h->Node->Size - Offset;
+               }
+               else
+               {
+                       // Expansion, node size should now fit
+                       LOG("Expanded file");
+               }
        }
+       
+       // Create flag set
        Uint flags = 0;
        flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
-       ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer, flags);
+       
+       // Dispatch the read!
+       size_t ret = nodetype->Write(h->Node, Offset, Length, Buffer, flags);
        if(ret == (size_t)-1)   return -1;
+       if(ret != Length)       LOG("%i/%i written", ret, Length);
+
        return ret;
 }
 
@@ -198,11 +220,14 @@ Uint64 VFS_Tell(int FD)
  */
 int VFS_Seek(int FD, Sint64 Offset, int Whence)
 {
-       tVFS_Handle     *h;
-       
-       h = VFS_GetHandle(FD);
+       tVFS_Handle     *h = VFS_GetHandle(FD);
        if(!h)  return -1;
        
+       if( (h->Node->Type->Flags & VFS_NODETYPEFLAG_STREAM) ) {
+               LOG("Seeking in stream");
+               return -1;
+       }
+       
        // Set relative to current position
        if(Whence == 0) {
                LOG("(FD%x)->Position += %lli", FD, Offset);
@@ -225,15 +250,34 @@ int VFS_Seek(int FD, Sint64 Offset, int Whence)
        return 0;
 }
 
+/*
+ * Truncate/Expand a file's allocation
+ */
+off_t VFS_Truncate(int FD, off_t Size)
+{
+       tVFS_Handle     *h = VFS_GetHandle(FD);
+       if(!h) {
+               errno = EBADF;
+               return -1;
+       }
+       
+       if( !h->Node->Type->Truncate)
+       {
+               Log_Notice("VFS", "Nodetype '%s' doesn't have a Truncate method", h->Node->Type->TypeName);
+               errno = ENOTIMPL;
+               return -1;      
+       }
+       
+       return h->Node->Type->Truncate(h->Node, Size);
+}
+
 /**
  * \fn int VFS_IOCtl(int FD, int ID, void *Buffer)
  * \brief Call an IO Control on a file
  */
 int VFS_IOCtl(int FD, int ID, void *Buffer)
 {
-       tVFS_Handle     *h;
-       
-       h = VFS_GetHandle(FD);
+       tVFS_Handle     *h = VFS_GetHandle(FD);
        if(!h) {
                LOG("FD%i is invalid", FD);
                errno = EINVAL;
index 0261eca..4ed7829 100644 (file)
@@ -59,9 +59,10 @@ int VFS_Init(void)
        VFS_MkDir("/Devices");
        VFS_MkDir("/Mount");
        VFS_Mount("dev", "/Devices", "devfs", "");
-               
-       Log_Debug("VFS", "Setting max files");
-       *Threads_GetMaxFD() = 32;
+       
+       // Set default max user file count
+       // - Applies to PID0, but propagated to all children
+       *Threads_GetMaxFD(NULL) = 32;
        return 0;
 }
 
index b6d5c2d..9016d56 100644 (file)
@@ -10,6 +10,7 @@
 #include <vfs.h>
 #include <vfs_ext.h>
 #include <vfs_int.h>
+#include <mm_virt.h>   // MM_USER_MAX
 
 #define MMAP_PAGES_PER_BLOCK   16
 
@@ -25,31 +26,63 @@ struct sVFS_MMapPageBlock
 // === PROTOTYPES ===
 //void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset);
 void   *VFS_MMap_Anon(void *Destination, size_t Length, Uint FlagsSet, Uint FlagsMask);
+int    VFS_MMap_MapPage(tVFS_Node *Node, unsigned int PageNum, tVFS_MMapPageBlock *pb, void *mapping_dest, unsigned int Protection);
 //int  VFS_MUnmap(void *Addr, size_t Length);
+bool   _range_free(const tPage *Base, Uint NumPages);
 
 // === CODE ===
 void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset)
 {
-       tVAddr  mapping_base;
-        int    npages, pagenum;
-       tVFS_MMapPageBlock      *pb, *prev;
-
-       ENTER("pDestHint iLength xProtection xFlags xFD XOffset", DestHint, Length, Protection, Flags, FD, Offset);
+       ENTER("pDestHint xLength xProtection xFlags xFD XOffset", DestHint, Length, Protection, Flags, FD, Offset);
 
        if( Flags & MMAP_MAP_ANONYMOUS )
                Offset = (tVAddr)DestHint & 0xFFF;
        
-       npages = ((Offset & (PAGE_SIZE-1)) + Length + (PAGE_SIZE - 1)) / PAGE_SIZE;
-       pagenum = Offset / PAGE_SIZE;
+       unsigned int npages = ((Offset & (PAGE_SIZE-1)) + Length + (PAGE_SIZE - 1)) / PAGE_SIZE;
+       unsigned int pagenum = Offset / PAGE_SIZE;
+       LOG("npages=%u,pagenum=%u", npages, pagenum);
+
+       tVAddr mapping_base = (tVAddr)DestHint;
 
-       mapping_base = (tVAddr)DestHint;
+       if( Flags & MMAP_MAP_FIXED )
+       {
+               ASSERT( (Flags & MMAP_MAP_FIXED) && DestHint != NULL );
+               // Keep and use the hint
+               // - TODO: Validate that the region pointed to by the hint is correct
+       }
+       else
+       {
+               Log_Warning("VFS", "MMap: TODO Handle non-fixed mappings");
+               
+               // Locate a free location in the address space (between brk and MM_USER_MAX)
+               // TODO: Prefer first location after DestHint, but can go below
+               
+               // Search downwards from the top of user memory
+               mapping_base = 0;
+               for( tPage *dst = (tPage*)MM_USER_MAX - npages; dst > (tPage*)PAGE_SIZE; dst -- )
+               {
+                       if( _range_free(dst, npages) ) {
+                               mapping_base = (tVAddr)dst;
+                               break;
+                       }
+               }
+               if( mapping_base == 0 )
+               {
+                       Log_Warning("VFS", "MMap: Out of address space");
+                       errno = ENOMEM;
+                       LEAVE('n');
+                       return NULL;
+               }
+       }
        tPage   *mapping_dest = (void*)(mapping_base & ~(PAGE_SIZE-1));
 
-       if( DestHint == NULL )
+       if( !_range_free(mapping_dest, npages) )
        {
-               // TODO: Locate space for the allocation
-               LEAVE('n');
-               return NULL;
+               LOG("Specified range is not free");
+               //errno = EINVAL;
+               //LEAVE('n');
+               //return NULL;
+               Log_Warning("VFS", "MMap: Overwriting/replacing maps at %p+%x", mapping_base, Length);
        }
 
        // Handle anonymous mappings
@@ -67,14 +100,14 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
        
        Mutex_Acquire( &h->Node->Lock );
 
+       tVFS_MMapPageBlock      *pb, **pb_pnp = (tVFS_MMapPageBlock**)&h->Node->MMapInfo;
        // Search for existing mapping for each page
        // - Sorted list of 16 page blocks
-       for(
-               pb = h->Node->MMapInfo, prev = NULL;
-               pb && pb->BaseOffset + MMAP_PAGES_PER_BLOCK <= pagenum;
-               prev = pb, pb = pb->Next
-               )
-               ;
+       for( pb = h->Node->MMapInfo; pb; pb_pnp = &pb->Next, pb = pb->Next )
+       {
+               if( pb->BaseOffset + MMAP_PAGES_PER_BLOCK > pagenum )
+                       break;
+       }
 
        LOG("pb = %p, pb->BaseOffset = %X", pb, pb ? pb->BaseOffset : 0);
 
@@ -89,74 +122,22 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                }
                pb->Next = old_pb;
                pb->BaseOffset = pagenum - pagenum % MMAP_PAGES_PER_BLOCK;
-               if(prev)
-                       prev->Next = pb;
-               else
-                       h->Node->MMapInfo = pb;
+               *pb_pnp = pb;
        }
 
        // - Map (and allocate) pages
        while( npages -- )
        {
-               assert( pagenum >= pb->BaseOffset );
-               assert( pagenum - pb->BaseOffset < MMAP_PAGES_PER_BLOCK );
+               ASSERTC( pagenum, >=, pb->BaseOffset );
+               ASSERTC( pagenum - pb->BaseOffset, <, MMAP_PAGES_PER_BLOCK );
                if( MM_GetPhysAddr( mapping_dest ) == 0 )
                {
-                       if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 )
-                       {
-                               tVFS_NodeType   *nt = h->Node->Type;
-                               if( !nt ) 
-                               {
-                                       // TODO: error
-                               }
-                               else if( nt->MMap )
-                                       nt->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest);
-                               else
-                               {
-                                        int    read_len;
-                                       // Allocate pages and read data
-                                       if( MM_Allocate(mapping_dest) == 0 ) {
-                                               // TODO: Unwrap
-                                               Mutex_Release( &h->Node->Lock );
-                                               LEAVE('n');
-                                               return NULL;
-                                       }
-                                       // TODO: Clip read length
-                                       read_len = nt->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE,
-                                               mapping_dest, 0);
-                                       // TODO: This was commented out, why?
-                                       if( read_len != PAGE_SIZE ) {
-                                               memset( (char*)mapping_dest + read_len, 0, PAGE_SIZE-read_len );
-                                       }
-                               }
-                               pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
-                               MM_SetPageNode( pb->PhysAddrs[pagenum - pb->BaseOffset], h->Node );
-                               MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] );
-                               LOG("Read and map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
-                                       pb->PhysAddrs[pagenum - pb->BaseOffset]);
-                       }
-                       else
+                       LOG("Map page to %p", mapping_dest);
+                       if( VFS_MMap_MapPage(h->Node, pagenum, pb, mapping_dest, Protection) )
                        {
-                               MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] );
-                               MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] );
-                               LOG("Cached map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
-                                       pb->PhysAddrs[pagenum - pb->BaseOffset]);
-                       }
-                       h->Node->ReferenceCount ++;
-               
-                       // Set flags
-                       if( !(Protection & MMAP_PROT_WRITE) ) {
-                               MM_SetFlags(mapping_dest, MM_PFLAG_RO, MM_PFLAG_RO);
-                       }
-                       else {
-                               MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO);
-                       }
-                       
-                       if( Protection & MMAP_PROT_EXEC ) {
-                               MM_SetFlags(mapping_dest, MM_PFLAG_EXEC, MM_PFLAG_EXEC);
-                       }
-                       else {
-                               MM_SetFlags(mapping_dest, 0, MM_PFLAG_EXEC);
+                               Mutex_Release( &h->Node->Lock );
+                               LEAVE('n');
+                               return NULL;
                        }
                }
                else
@@ -167,25 +148,27 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                                MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO);
                        }
                }
-               if( Flags & MMAP_MAP_PRIVATE )
+               if( Flags & MMAP_MAP_PRIVATE ) {
+                       // TODO: Don't allow the page to change underneath either
                        MM_SetFlags(mapping_dest, MM_PFLAG_COW, MM_PFLAG_COW);
+               }
                pagenum ++;
                mapping_dest ++;
 
                // Roll on to next block if needed
                if(pagenum - pb->BaseOffset == MMAP_PAGES_PER_BLOCK)
                {
-                       if( pb->Next && pb->Next->BaseOffset == pagenum )
-                               pb = pb->Next;
-                       else
+                       if( !pb->Next || pb->Next->BaseOffset != pagenum )
                        {
-                               tVFS_MMapPageBlock      *oldpb = pb;
-                               pb = malloc( sizeof(tVFS_MMapPageBlock) );
-                               pb->Next = oldpb->Next;
-                               pb->BaseOffset = pagenum;
-                               memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
-                               oldpb->Next = pb;
+                               if( pb->Next )  ASSERTC(pb->Next->BaseOffset % MMAP_PAGES_PER_BLOCK, ==, 0);
+                               tVFS_MMapPageBlock      *newpb = malloc( sizeof(tVFS_MMapPageBlock) );
+                               newpb->Next = pb->Next;
+                               newpb->BaseOffset = pagenum;
+                               memset(newpb->PhysAddrs, 0, sizeof(newpb->PhysAddrs));
+                               pb->Next = newpb;
                        }
+       
+                       pb = pb->Next;
                }
        }
        
@@ -263,7 +246,81 @@ void *VFS_MMap_Anon(void *Destination, size_t Length, Uint FlagsSet, Uint FlagsM
        return Destination;
 }
 
+int VFS_MMap_MapPage(tVFS_Node *Node, unsigned int pagenum, tVFS_MMapPageBlock *pb, void *mapping_dest, unsigned int Protection)
+{
+       if( pb->PhysAddrs[pagenum - pb->BaseOffset] != 0 )
+       {
+               MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] );
+               MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] );
+               LOG("Cached map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
+                       pb->PhysAddrs[pagenum - pb->BaseOffset]);
+       }
+       else
+       {
+               tVFS_NodeType   *nt = Node->Type;
+               if( !nt ) 
+               {
+                       // TODO: error
+               }
+               else if( nt->MMap )
+                       nt->MMap(Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest);
+               else
+               {
+                        int    read_len;
+                       // Allocate pages and read data
+                       if( MM_Allocate(mapping_dest) == 0 ) {
+                               // TODO: Unwrap
+                               return 1;
+                       }
+                       // TODO: Clip read length
+                       read_len = nt->Read(Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest, 0);
+                       // TODO: This was commented out, why?
+                       if( read_len != PAGE_SIZE ) {
+                               memset( (char*)mapping_dest + read_len, 0, PAGE_SIZE-read_len );
+                       }
+               }
+               pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
+               MM_SetPageNode( pb->PhysAddrs[pagenum - pb->BaseOffset], Node );
+               MM_RefPhys( pb->PhysAddrs[pagenum - pb->BaseOffset] );
+               LOG("Read and map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
+                       pb->PhysAddrs[pagenum - pb->BaseOffset]);
+       }
+       // TODO: Huh?
+       Node->ReferenceCount ++;
+
+       // Set flags
+       if( !(Protection & MMAP_PROT_WRITE) ) {
+               MM_SetFlags(mapping_dest, MM_PFLAG_RO, MM_PFLAG_RO);
+       }
+       else {
+               MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO);
+       }
+       
+       if( Protection & MMAP_PROT_EXEC ) {
+               MM_SetFlags(mapping_dest, MM_PFLAG_EXEC, MM_PFLAG_EXEC);
+       }
+       else {
+               MM_SetFlags(mapping_dest, 0, MM_PFLAG_EXEC);
+       }
+       
+       return 0;
+}
+
 int VFS_MUnmap(void *Addr, size_t Length)
 {
+       UNIMPLEMENTED();
        return 0;
 }
+
+bool _range_free(const tPage *Base, Uint NumPages)
+{
+       for( int i = 0; i < NumPages; i ++ )
+       {
+               if( MM_GetPhysAddr(Base + i) )
+               {
+                       // Oh.
+                       return false;
+               }
+       }
+       return true;
+}
index f0b5734..e5a206f 100644 (file)
 #define MAX_PATH_SLASHES       256
 #define MAX_NESTED_LINKS       4
 #define MAX_PATH_LEN   255
+#define MAX_MARSHALLED_HANDLES 16      // Max outstanding
 
 // === IMPORTS ===
 extern tVFS_Mount      *gVFS_RootMount;
 extern tVFS_Node       *VFS_MemFile_Create(const char *Path);
 
+// === TYPES ===
+typedef struct sVFS_MarshaledHandle
+{
+       Uint32  Magic;
+       tTime   AllocTime;
+       tVFS_Handle     Handle;
+} tVFS_MarshalledHandle;
+
 // === PROTOTYPES ===
 void   _ReferenceMount(tVFS_Mount *Mount, const char *DebugTag);
 void   _DereferenceMount(tVFS_Mount *Mount, const char *DebugTag);
  int   VFS_int_CreateHandle(tVFS_Node *Node, tVFS_Mount *Mount, int Mode);
 
+// === GLOBALS ===
+tMutex glVFS_MarshalledHandles;
+tVFS_MarshalledHandle  gaVFS_MarshalledHandles[MAX_MARSHALLED_HANDLES];
+
 // === CODE ===
 void _ReferenceMount(tVFS_Mount *Mount, const char *DebugTag)
 {
@@ -49,9 +62,9 @@ char *VFS_GetAbsPath(const char *Path)
        char    *tmpStr;
        int             iPos = 0;
        int             iPos2 = 0;
-       const char      *chroot = *Threads_GetChroot();
+       const char      *chroot = *Threads_GetChroot(NULL);
         int    chrootLen;
-       const char      *cwd = *Threads_GetCWD();
+       const char      *cwd = *Threads_GetCWD(NULL);
         int    cwdLen;
        
        ENTER("sPath", Path);
@@ -343,7 +356,7 @@ restart_parse:
                        }
                        
                        if(iNestedLinks > MAX_NESTED_LINKS) {
-                               Log_Notice("VFS", "VFS_ParsePath - Nested link limit exceeded");
+                               Log_Notice("VFS", "VFS_ParsePath - Nested link limit exceeded on '%.*s'", ofs, Path);
                                errno = ENOENT;
                                goto _error;
                        }
@@ -378,7 +391,8 @@ restart_parse:
                // Handle Non-Directories
                if( !(curNode->Flags & VFS_FFLAG_DIRECTORY) )
                {
-                       Log_Warning("VFS", "VFS_ParsePath - Path segment is not a directory");
+                       Log_Warning("VFS", "VFS_ParsePath - Path segment '%.*s' is not a directory (curNode{%p}->Flags = 0x%x)",
+                               ofs+nextSlash, Path, curNode, curNode->Flags);
                        errno = ENOTDIR;
                        goto _error;
                }
@@ -407,7 +421,7 @@ restart_parse:
 
        // Check final finddir call     
        if( !curNode->Type || !curNode->Type->FindDir ) {
-               Log_Warning("VFS", "VFS_ParsePath - FindDir doesn't exist for element of '%s'", Path);
+               Log_Warning("VFS", "VFS_ParsePath - FindDir doesn't exist for leaf of '%s' (dir '%.*s')", Path, ofs, Path);
                errno = ENOENT;
                goto _error;
        }
@@ -733,6 +747,7 @@ int VFS_Reopen(int FD, const char *Path, int Flags)
 
        int newf = VFS_Open(Path, Flags);
        if( newf == -1 ) {
+               // errno = set by VFS_Open
                return -1;
        }
        
@@ -759,11 +774,13 @@ void VFS_Close(int FD)
        h = VFS_GetHandle(FD);
        if(h == NULL) {
                Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x", FD);
+               errno = EINVAL;
                return;
        }
 
        if( h->Node == NULL ) {
                Log_Warning("VFS", "Non-open handle passed to VFS_Close, 0x%x", FD);
+               errno = EINVAL;
                return ;
        }       
 
@@ -771,6 +788,7 @@ void VFS_Close(int FD)
        if(h->Node->Close && !MM_GetPhysAddr(h->Node->Close)) {
                Log_Warning("VFS", "Node %p's ->Close method is invalid (%p)",
                        h->Node, h->Node->Close);
+               errno = EINTERNAL;
                return ;
        }
        #endif
@@ -858,7 +876,7 @@ int VFS_ChDir(const char *Dest)
        VFS_Close(fd);
        
        {
-               char    **cwdptr = Threads_GetCWD();
+               char    **cwdptr = Threads_GetCWD(NULL);
                // Free old working directory
                if( *cwdptr )   free( *cwdptr );
                // Set new
@@ -910,7 +928,7 @@ int VFS_ChRoot(const char *New)
 
        // Update       
        {
-               char    **chroot_ptr = Threads_GetChroot();
+               char    **chroot_ptr = Threads_GetChroot(NULL);
                if( *chroot_ptr )       free( *chroot_ptr );
                *chroot_ptr = buf;
        }
@@ -920,6 +938,96 @@ int VFS_ChRoot(const char *New)
        return 1;
 }
 
+/*
+ * Marshal a handle so that it can be transferred between processes
+ */
+Uint64 VFS_MarshalHandle(int FD)
+{
+       tVFS_Handle     *h = VFS_GetHandle(FD);
+       if(!h || !h->Node) {
+               errno = EBADF;
+               return -1;
+       }
+       
+       // Allocate marshal location
+        int    ret = -1;
+       Mutex_Acquire(&glVFS_MarshalledHandles);
+       for( int i = 0; i < MAX_MARSHALLED_HANDLES; i ++ )
+       {
+               tVFS_MarshalledHandle*  mh = &gaVFS_MarshalledHandles[i];
+               if( mh->Handle.Node == NULL ) {
+                       mh->Handle.Node = h->Node;
+                       mh->AllocTime = now();
+                       ret = i;
+               }
+               if( now() - mh->AllocTime > 2000 ) {
+                       Log_Notice("VFS", "TODO: Expire marshalled handle");
+               }
+       }
+       Mutex_Release(&glVFS_MarshalledHandles);
+       if( ret < 0 ) {
+               // TODO: Need to clean up lost handles to avoid DOS
+               Log_Warning("VFS", "Out of marshaled handle slots");
+               errno = EAGAIN;
+               return -1;
+       }
+       
+       // Populate
+       tVFS_MarshalledHandle*  mh = &gaVFS_MarshalledHandles[ret];
+       mh->Handle = *h;
+       _ReferenceMount(h->Mount, "MarshalHandle");
+       _ReferenceNode(h->Node);
+       mh->Magic = rand();
+       
+       return (Uint64)mh->Magic << 32 | ret;
+}
+
+/*
+ * Un-marshal a handle into the current process
+ * NOTE: Does not support unmarshalling into kernel handle list
+ */
+int VFS_UnmarshalHandle(Uint64 Handle)
+{
+       Uint32  magic = Handle >> 32;
+        int    id = Handle & 0xFFFFFFFF;
+       
+       // Range check
+       if( id >= MAX_MARSHALLED_HANDLES ) {
+               LOG("ID too high (%i > %i)", id, MAX_MARSHALLED_HANDLES);
+               errno = EINVAL;
+               return -1;
+       }
+       
+       
+       // Check validity
+       tVFS_MarshalledHandle   *mh = &gaVFS_MarshalledHandles[id];
+       if( mh->Handle.Node == NULL ) {
+               LOG("Target node is NULL");
+               errno = EINVAL;
+               return -1;
+       }
+       if( mh->Magic != magic ) {
+               LOG("Magic mismatch (0x%08x != 0x%08x)", magic, mh->Magic);
+               errno = EACCES;
+               return -1;
+       }
+       
+       Mutex_Acquire(&glVFS_MarshalledHandles);
+       // - Create destination handle
+        int    ret = VFS_AllocHandle(true, mh->Handle.Node, mh->Handle.Mode);
+       // - Clear allocation
+       mh->Handle.Node = NULL;
+       Mutex_Release(&glVFS_MarshalledHandles);
+       if( ret == -1 ) {
+               errno = ENFILE;
+               return -1;
+       }
+       
+       // No need to reference node/mount, new handle takes marshalled reference
+       
+       return ret;
+}
+
 // === EXPORTS ===
 EXPORT(VFS_Open);
 EXPORT(VFS_Close);
index 660bca8..a18b91c 100644 (file)
@@ -55,13 +55,14 @@ void        VFS_int_Select_SignalAll(tVFS_SelectList *List);
 // === FUNCTIONS ===
 int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *Name)
 {
-       tThread *thisthread = Proc_GetCurThread();
-        int    ret, type;
+       tThread * const thisthread = Proc_GetCurThread();
+        int    ret;
        
        ENTER("pNode iTypeFlags pTimeout sName", Node, TypeFlags, Timeout, Name);
        
        // Initialise
-       for( type = 0; type < 3; type ++ )
+       ret = 0;
+       for( int type = 0; type < 3; type ++ )
        {
                tVFS_SelectList **list;
                 int    *flag, wanted, maxAllowed;
@@ -77,17 +78,19 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N
                VFS_int_Select_AddThread(*list, thisthread, maxAllowed);
                if( *flag == wanted )
                {
-                       VFS_int_Select_RemThread(*list, thisthread);
-                       LEAVE('i', 1);
-                       return 1;
+                       ret |= (1 << type);
                }
        }
 
        // Wait for things      
-       if( !Timeout )
+       if( ret )
+       {
+               // Skip wait, conditions already met
+               LOG("ret = %i, skipping wait", ret);
+       }
+       else if( !Timeout )
        {
                LOG("Semaphore_Wait()");
-               // TODO: Actual timeout
                Threads_WaitEvents( THREAD_EVENT_VFS|THREAD_EVENT_SIGNAL );
        }
        else if( *Timeout > 0 )
@@ -95,7 +98,6 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N
                tTimer *t = Time_AllocateTimer(NULL, NULL);
                // Clear timer event
                Threads_ClearEvent( THREAD_EVENT_TIMER );
-               // TODO: Convert *Timeout?
                LOG("Timeout %lli ms", *Timeout);
                Time_ScheduleTimer( t, *Timeout );
                // Wait for the timer or a VFS event
@@ -105,13 +107,13 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N
        
        // Get return value
        ret = 0;
-       for( type = 0; type < 3; type ++ )
+       for( int type = 0; type < 3; type ++ )
        {
                tVFS_SelectList **list;
                 int    *flag, wanted, maxAllowed;
                if( !(TypeFlags & (1 << type)) )        continue;
                VFS_int_Select_GetType(type, Node, &list, &flag, &wanted, &maxAllowed);
-               LOG("VFS_int_Select_RemThread()");
+               LOG("VFS_int_Select_RemThread() for %i", type);
                ASSERT(*list);
                VFS_int_Select_RemThread(*list, thisthread);
                ret = ret || *flag == wanted;
index a6338ae..7674ed9 100644 (file)
@@ -118,8 +118,15 @@ int BGA_Install(char **Arguments)
        dev = PCI_GetDevice(0x1234, 0x1111, 0);\r
        if(dev == -1)\r
                base = VBE_DISPI_LFB_PHYSICAL_ADDRESS;\r
-       else\r
-               base = PCI_GetBAR(dev, 0);\r
+       else {\r
+               Log_Debug("BGA", "BARs %x,%x,%x,%x,%x,%x",\r
+                       PCI_GetBAR(dev, 0), PCI_GetBAR(dev, 1), PCI_GetBAR(dev, 2),\r
+                       PCI_GetBAR(dev, 3), PCI_GetBAR(dev, 4), PCI_GetBAR(dev, 5));\r
+               base = PCI_GetValidBAR(dev, 0, PCI_BARTYPE_MEM);\r
+               // TODO: Qemu/bochs have MMIO versions of the registers in BAR2\r
+               // - This range is non-indexed\r
+               //mmio_base = PCI_GetValidBAR(dev, 2, PCI_BARTYPE_MEM);\r
+       }\r
 \r
        // Map Framebuffer to hardware address\r
        gBGA_Framebuffer = (void *) MM_MapHWPages(base, 768);   // 768 pages (3Mb)\r
index 9ca7098..a249fd8 100644 (file)
@@ -196,7 +196,7 @@ int Tegra2Vid_IOCtl(tVFS_Node *Node, int ID, void *Data)
        
        switch(ID)
        {
-       BASE_IOCTLS(DRV_TYPE_VIDEO, "PL110", VERSION, csaTegra2Vid_IOCtls);
+       BASE_IOCTLS(DRV_TYPE_VIDEO, "Tegra2", VERSION, csaTegra2Vid_IOCtls);
 
        case VIDEO_IOCTL_SETBUFFORMAT:
                DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );
index 32022ef..62fb25a 100644 (file)
 #include <limits.h>\r
 \r
 // === CONSTANTS ===\r
-#define USE_BIOS       1\r
+#ifdef ARCHDIR_is_x86\r
+# define USE_BIOS      1\r
+#else\r
+# define USE_BIOS      0\r
+#endif\r
 #define VESA_DEFAULT_FRAMEBUFFER       (KERNEL_BASE|0xA0000)\r
 #define BLINKING_CURSOR        0\r
 #if BLINKING_CURSOR\r
@@ -33,6 +37,7 @@ size_t        Vesa_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
  int   Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data);\r
 void   Vesa_int_HideCursor(void);\r
 void   Vesa_int_ShowCursor(void);\r
+ int   Vesa_int_SetCursor(tVideo_IOCtl_Bitmap *Cursor);\r
 void   Vesa_FlipCursor(void *Arg);\r
 Uint16 VBE_int_GetWord(const tVT_Char *Char);\r
 void   VBE_int_Text_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);\r
@@ -124,6 +129,10 @@ int VBE_int_GetModeList(void)
        \r
        // Allocate Info Block\r
        info = VM8086_Allocate(gpVesa_BiosState, 512, &infoPtr.seg, &infoPtr.ofs);\r
+       if( info == NULL ) {\r
+               Log_Warning("VBE", "VM8086 allocation error");\r
+               return MODULE_ERR_NOTNEEDED;\r
+       }\r
        // Set Requested Version\r
        memcpy(info->signature, "VBE2", 4);\r
        // Set Registers\r
@@ -361,13 +370,16 @@ int Vesa_IOCtl(tVFS_Node *Node, int ID, void *Data)
        case VIDEO_IOCTL_SETBUFFORMAT:\r
                Vesa_int_HideCursor();\r
                ret = gVesa_BufInfo.BufferFormat;\r
-               if(Data)        gVesa_BufInfo.BufferFormat = *(int*)Data;\r
+               if(Data)\r
+                       gVesa_BufInfo.BufferFormat = *(int*)Data;\r
                if(gVesa_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
-                       DrvUtil_Video_SetCursor( &gVesa_BufInfo, &gDrvUtil_TextModeCursor );\r
+                       Vesa_int_SetCursor(&gDrvUtil_TextModeCursor);\r
                Vesa_int_ShowCursor();\r
                return ret;\r
        \r
        case VIDEO_IOCTL_SETCURSOR:     // Set cursor position\r
+               if( !CheckMem(Data, sizeof(tVideo_IOCtl_Pos)) )\r
+                       return -EINVAL;\r
                Vesa_int_HideCursor();\r
                giVesaCursorX = ((tVideo_IOCtl_Pos*)Data)->x;\r
                giVesaCursorY = ((tVideo_IOCtl_Pos*)Data)->y;\r
@@ -375,9 +387,7 @@ int Vesa_IOCtl(tVFS_Node *Node, int ID, void *Data)
                return 0;\r
        \r
        case VIDEO_IOCTL_SETCURSORBITMAP:\r
-               if( gpVesaCurMode->flags & FLAG_LFB )\r
-                       DrvUtil_Video_SetCursor( &gVesa_BufInfo, Data );\r
-               return 0;\r
+               return Vesa_int_SetCursor(Data);\r
        }\r
        return 0;\r
 }\r
@@ -451,9 +461,9 @@ int Vesa_Int_SetMode(int mode)
        \r
        Mutex_Release( &glVesa_Lock );\r
 \r
-       // TODO: Disableable backbuffer\r
-       gVesa_BufInfo.BackBuffer  = realloc(gVesa_BufInfo.BackBuffer,\r
-               modeptr->height * modeptr->pitch);\r
+       // TODO: Allow disabling of back-buffer\r
+       gVesa_DriverStruct.RootNode.Size = modeptr->height * modeptr->pitch;\r
+       gVesa_BufInfo.BackBuffer  = realloc(gVesa_BufInfo.BackBuffer, modeptr->height * modeptr->pitch);\r
        gVesa_BufInfo.Framebuffer = gpVesa_Framebuffer;\r
        gVesa_BufInfo.Pitch = modeptr->pitch;\r
        gVesa_BufInfo.Width = modeptr->width;\r
@@ -607,6 +617,21 @@ void Vesa_int_ShowCursor(void)
        }\r
 }\r
 \r
+int Vesa_int_SetCursor(tVideo_IOCtl_Bitmap *Cursor)\r
+{\r
+       if( !CheckMem(Cursor, sizeof(tVideo_IOCtl_Bitmap)) )\r
+               return -EINVAL;\r
+       \r
+       if( gpVesaCurMode && gpVesaCurMode->flags & FLAG_LFB )\r
+       {\r
+               DrvUtil_Video_SetCursor( &gVesa_BufInfo, Cursor );\r
+       }\r
+       else\r
+       {\r
+       }\r
+       return 0;\r
+}\r
+\r
 /**\r
  * \brief Swaps the text cursor on/off\r
  */\r
diff --git a/KernelLand/Modules/Display/VGA/vgaregs.c b/KernelLand/Modules/Display/VGA/vgaregs.c
new file mode 100644 (file)
index 0000000..fa1bc84
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Acess2 VGA Driver
+ * - By John Hodge (thePowersGang)
+ */
+
+#define VGA_CRTC_IDX   0x3B4
+#define VGA_CRTC_DATA  0x3B5
+#define VGA_FEAT_IS1   0x3BA   // Features / Input Status 1 (B/W Chips)
+#define VGA_ATTR_WRITE 0x3C0
+#define VGA_ATTR_READ  0x3C1
+#define VGA_MISC_IS0   0x3C2   // Misc Output / Input Status 0
+#define VGA_MBSLEEP    0x3C3   // "Motherboard Sleep"
+#define VGA_SEQ_IDX    0x3C4
+#define VGA_SEQ_DATA   0x3C5
+#define VGA_DACMASK    0x3C6
+#define VGA_PADR_DACST 0x3C7
+#define VGA_PIXWRMODE  0x3C8
+#define VGA_PIXDATA    0x3C9
+#define VGA_FEATRD     0x3CA
+//                     0x3CB
+#define VGA_MISCOUT    0x3CC
+//                     0x3CD
+#define VGA_GRAPH_IDX  0x3CE
+#define VGA_GRAPH_DATA 0x3CF
+//                     0x3D0 -- 0x3D3
+#define VGA_CRTC_IDX   0x3D4
+#define VGA_CRTC_DATA  0x3D5
+//                     0x3D6 -- 0x3D9
+#define VGA_FEAT_IS1_C 0x3DA   // Features / Input Status 1 (Colour Chips)
+
+// === CODE ===
+void VGA_WriteAttr(Uint8 Index, Uint8 Data)
+{
+       Index &= 0x1F;
+       SHORTLOCK(&glVGA_Attr);
+       inb(0x3DA);
+       outb(VGA_ATTR_WRITE, Index);
+       outb(VGA_ATTR_WRITE, Data);
+       SHORTREL(&glVGA_Attr);
+}
+
+Uint8 VGA_ReadAttr(Uint8 Index)
+{
+       Uint8   ret;
+       SHORTLOCK(&glVGA_Attr);
+       inb(0x3DA);
+       outb(VGA_ATTR_WRITE, Index);
+       ret = inb(VGA_ATTR_READ);
+       SHORTREL(&glVGA_Attr);
+       return ret;
+}
+
+void VGA_WriteSeq(Uint8 Index, Uint8 Data)
+{
+       outb(VGA_SEQ_IDX, Index);
+       outb(VGA_SEQ_DATA, Data);
+}
+Uint8 VGA_ReadSeq(Uint8 Index)
+{
+       outb(VGA_SEQ_IDX, Index);
+       return inb(VGA_SEQ_DATA);
+}
+void VGA_WriteGraph(Uint8 Index, Uint8 Data)
+{
+       outb(VGA_GRAPH_IDX, Index);
+       outb(VGA_GRAPH_DATA, Data);
+}
+Uint8 VGA_ReadGraph(Uint8 Index)
+{
+       outb(VGA_GRAPH_IDX, Index);
+       return inb(VGA_GRAPH_DATA);
+}
+
+void VGA_WriteMiscOut(Uint8 Data)
+{
+       outb(VGA_MISC_IS0, Data);
+}
+Uint8 VGA_ReadMiscOut(void)
+{
+       return inb(VGA_MISCOUT);
+}
index 5034b4b..52377e6 100644 (file)
@@ -12,6 +12,8 @@ $gOutput = <<<EOF
 
 EOF;
 
+define("DEBUG_ENABLED", false);
+
 $ACESSDIR = getenv("ACESSDIR");
 $ARCH = getenv("ARCH");
 
@@ -143,7 +145,8 @@ EOF;
                {
                        $path = $item[1];
                        
-                       echo $path,"\n";
+                       if( DEBUG_ENABLED )
+                               echo $path,"\n";
                        $size = filesize($path);
        
                        $_sym = "_binary_".str_replace(array("/","-",".","+"), "_", $path)."_start";
index efae3be..bac8284 100644 (file)
@@ -35,6 +35,7 @@ Dir "Libs" {
        File "__BIN__/Libs/liburi.so"
        File "__BIN__/Libs/libimage_sif.so"
        File "__BIN__/Libs/libaxwin3.so"
+       File "__BIN__/Libs/libaxwin4.so"
        File "__BIN__/Libs/libposix.so"
        File "__BIN__/Libs/libpsocket.so"
        File "__BIN__/Libs/libunicode.so"
@@ -61,6 +62,10 @@ Dir "Apps" {
                        File "toolbar_open.sif" "__SRC__/Usermode/Applications/axwin3_src/WM/resources/.toolbar_open.sif"
                        File "toolbar_save.sif" "__SRC__/Usermode/Applications/axwin3_src/WM/resources/.toolbar_save.sif"
                }
+               Dir "4.0" {
+                       File "__BIN__/Apps/AxWin/4.0/AxWinServer"
+                       File "__BIN__/Apps/AxWin/4.0/AxWinUI"
+               }
        }
 }
 #Dir "Keen5" {
index fa9927e..f34d790 100644 (file)
@@ -26,7 +26,7 @@ struct {
  */
 void ICMP_Initialise()
 {
-       IPv4_RegisterCallback(IP4PROT_ICMP, ICMP_GetPacket);
+       IPv4_RegisterCallback(IP4PROT_ICMP, ICMP_GetPacket, NULL);
 }
 
 /**
@@ -64,12 +64,15 @@ void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buff
                {
                case 3: // Port Unreachable
                        Log_Debug("ICMPv4", "Destination Unreachable (Port Unreachable)");
+                       IPv4_HandleError( Interface, IPERR_PORT_UNREACHABLE,
+                               htons(Length)-sizeof(tICMPHeader), hdr->Data );
                        break;
                default:
                        Log_Debug("ICMPv4", "Destination Unreachable (Code %i)", hdr->Code);
+                       IPv4_HandleError( Interface, IPERR_MISC,
+                               htons(Length)-sizeof(tICMPHeader), hdr->Data );
                        break;
                }
-//             IPv4_Unreachable( Interface, hdr->Code, htons(hdr->Length)-sizeof(tICMPHeader), hdr->Data );
                break;
        
        // -- 8: Echo Request
index bda70b1..66f6134 100644 (file)
@@ -26,32 +26,32 @@ typedef struct {
        Uint16  RouterLifetime; // Seconds, life time as a default router (wtf does that mean?)
        Uint32  ReachableTime;
        Uint32  RetransTimer;   // Miliseconds, time between transmissions of RAs from this router
-       Uint8   Options[];
+       Uint8   Options[0];
 } PACKED tICMPv6_RA;
 
 typedef struct {
        Uint32  Reserved;
        tIPv6   TargetAddress;
-       Uint8   Options[];
+       Uint8   Options[0];
 } PACKED tICMPv6_NS;
 
 typedef struct {
        Uint32  Flags;
        tIPv6   TargetAddress;
-       Uint8   Options[];
+       Uint8   Options[0];
 } PACKED tICMPv6_NA;
 
 typedef struct {
        Uint32  Reserved;
        tIPv6   TargetAddress;
        tIPv6   DestinationAddress;
-       Uint8   Options[];
+       Uint8   Options[0];
 } PACKED tICMPv6_Redirect;
 
 typedef struct {
        Uint8   Type;   // 1,2
        Uint8   Length; // Length of field in units of 8 bytes (incl header), typically 1
-       Uint8   Address[];
+       Uint8   Address[0];
 } PACKED tICMPv6_Opt_LinkAddr;
 
 typedef struct {
@@ -62,7 +62,7 @@ typedef struct {
        Uint32  ValidLifetime;
        Uint32  PreferredLifetime;
        Uint32  _reserved2;
-       tIPv6   Prefix[];
+       tIPv6   Prefix[0];
 } PACKED tICMPv6_Opt_Prefix;
 
 typedef struct {
@@ -70,7 +70,7 @@ typedef struct {
        Uint8   Length;
        Uint16  _rsvd1;
        Uint32  _rsvd2;
-       Uint8   Data[]; // All or part of the redirected message (not exceeding MTU)
+       Uint8   Data[0];        // All or part of the redirected message (not exceeding MTU)
 } PACKED tICMPv6_Opt_Redirect;
 
 typedef struct {
index ddcdde9..3833ce7 100644 (file)
@@ -15,7 +15,16 @@ typedef struct sAdapter      tAdapter;
 typedef struct sInterface      tInterface;
 typedef struct sSocketFile     tSocketFile;
 
-typedef void   (*tIPCallback)(tInterface *Interface, void *Address, int Length, void *Buffer);
+typedef enum eIPErrorMode
+{
+       IPERR_MISC,
+       IPERR_HOST_UNREACHABLE,
+       IPERR_PORT_UNREACHABLE,
+} tIPErrorMode;
+
+// NOTE: Non-const to allow reuse of Rx buffer for prepping Tx
+typedef void   tIPRxCallback(tInterface *Interface, void *Address, int Length, void *Buffer);
+typedef void   tIPErrorCallback(tInterface *Interface, tIPErrorMode mode, const void *Address, int Length, const void *Buffer);
 
 enum eInterfaceTypes {
        AF_NULL,
index 000fe39..371fe40 100644 (file)
@@ -20,7 +20,7 @@ extern  int   ICMP_Ping(tInterface *Interface, tIPv4 Addr);
 
 // === PROTOTYPES ===
  int   IPv4_Initialise();
- int   IPv4_RegisterCallback(int ID, tIPCallback Callback);
+// int IPv4_RegisterCallback(int ID, tIPRxCallback Callback, );
 void   IPv4_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
 tInterface     *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
 Uint32 IPv4_Netmask(int FixedBits);
@@ -28,7 +28,10 @@ Uint16       IPv4_Checksum(const void *Buf, size_t Length);
  int   IPv4_Ping(tInterface *Iface, tIPv4 Addr);
 
 // === GLOBALS ===
-tIPCallback    gaIPv4_Callbacks[256];
+struct {
+       tIPRxCallback*  rx_cb;
+       tIPErrorCallback*       err_cb;
+} gaIPv4_Callbacks[256];
 
 // === CODE ===
 /**
@@ -46,11 +49,12 @@ int IPv4_Initialise()
  * \param ID   8-bit packet type ID
  * \param Callback     Callback function
  */
-int IPv4_RegisterCallback(int ID, tIPCallback Callback)
+int IPv4_RegisterCallback(int ID, tIPRxCallback *RxCallback, tIPErrorCallback *ErrCallback)
 {
        if( ID < 0 || ID > 255 )        return 0;
-       if( gaIPv4_Callbacks[ID] )      return 0;
-       gaIPv4_Callbacks[ID] = Callback;
+       if( gaIPv4_Callbacks[ID].rx_cb )        return 0;
+       gaIPv4_Callbacks[ID].rx_cb = RxCallback;
+       gaIPv4_Callbacks[ID].err_cb = ErrCallback;
        return 1;
 }
 
@@ -66,14 +70,12 @@ int IPv4_RegisterCallback(int ID, tIPCallback Callback)
  */
 int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPStackBuffer *Buffer)
 {
-       tMacAddr        to;
        tIPv4Header     hdr;
-        int    length;
 
-       length = IPStack_Buffer_GetLength(Buffer);
+       int length = IPStack_Buffer_GetLength(Buffer);
        
        // --- Resolve destination MAC address
-       to = HWCache_Resolve(Iface, &Address);
+       tMacAddr to = HWCache_Resolve(Iface, &Address);
        if( MAC_EQU(to, cMAC_ZERO) ) {
                // No route to host
                Log_Notice("IPv4", "No route to host %i.%i.%i.%i",
@@ -134,7 +136,6 @@ int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPS
 void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
 {
        tIPv4Header     *hdr = Buffer;
-       tInterface      *iface;
        Uint8   *data;
         int    dataLength;
         int    ret;
@@ -197,7 +198,7 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
        data = &hdr->Options[0];
        
        // Get Interface (allowing broadcasts)
-       iface = IPv4_GetInterface(Adapter, hdr->Destination, 1);
+       tInterface *iface = IPv4_GetInterface(Adapter, hdr->Destination, 1);
        
        // Firewall rules
        if( iface ) {
@@ -255,12 +256,29 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
        }
        
        // Send it on
-       if( !gaIPv4_Callbacks[hdr->Protocol] ) {
+       if( !gaIPv4_Callbacks[hdr->Protocol].rx_cb ) {
                Log_Log("IPv4", "Unknown Protocol %i", hdr->Protocol);
                return ;
        }
        
-       gaIPv4_Callbacks[hdr->Protocol]( iface, &hdr->Source, dataLength, data );
+       gaIPv4_Callbacks[hdr->Protocol].rx_cb( iface, &hdr->Source, dataLength, data );
+}
+
+/*
+ * Handles an error from the ICMPv4 code, 'Buf' contains part of an IPv4 packet
+ */
+void IPv4_HandleError(tInterface *Iface, tIPErrorMode Mode, size_t Length, const void *Buf)
+{
+       if(Length < sizeof(tIPv4Header))        return;
+       const tIPv4Header*      hdr = Buf;
+       if(hdr->Version != 4)   return;
+       
+       // Get Data and Data Length
+       size_t dataLength = MIN(Length, ntohs(hdr->TotalLength)) - sizeof(tIPv4Header);
+       const void *data = &hdr->Options[0];
+       
+       if( gaIPv4_Callbacks[hdr->Protocol].err_cb )
+               gaIPv4_Callbacks[hdr->Protocol].err_cb(Iface, Mode, &hdr->Source, dataLength, data);
 }
 
 /**
@@ -272,16 +290,14 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
  */
 tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
 {
-       tInterface      *iface = NULL, *zero_iface = NULL;
-       Uint32  netmask;
-       Uint32  addr, this;
+       tInterface      *zero_iface = NULL;
 
        ENTER("pAdapter xAddress bBroadcast", Adapter, Address, Broadcast);     
 
-       addr = ntohl( Address.L );
+       Uint32 addr = ntohl( Address.L );
        LOG("addr = 0x%x", addr);
        
-       for( iface = gIP_Interfaces; iface; iface = iface->Next)
+       for( tInterface *iface = gIP_Interfaces; iface; iface = iface->Next)
        {
                if( iface->Adapter != Adapter ) continue;
                if( iface->Type != 4 )  continue;
@@ -307,8 +323,8 @@ tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
                if( !Broadcast )        continue;
                
                // Check for broadcast
-               this = ntohl( ((tIPv4*)iface->Address)->L );
-               netmask = IPv4_Netmask(iface->SubnetBits);
+               Uint32 this = ntohl( ((tIPv4*)iface->Address)->L );
+               Uint32 netmask = IPv4_Netmask(iface->SubnetBits);
                LOG("iface addr = 0x%x, netmask = 0x%x (bits = %i)", this, netmask, iface->SubnetBits);
 
                if( (addr & netmask) == (this & netmask) && (addr & ~netmask) == (0xFFFFFFFF & ~netmask) )
index dd78788..c31b751 100644 (file)
@@ -47,9 +47,11 @@ struct sIPv4Header
 #define IPV4_ETHERNET_ID       0x0800
 
 // === FUNCTIONS ===
-extern int     IPv4_RegisterCallback(int ID, tIPCallback Callback);
+extern int     IPv4_RegisterCallback(int ID, tIPRxCallback *RxCallback, tIPErrorCallback *ErrCallback);
 extern Uint16  IPv4_Checksum(const void *Buf, size_t Length);
 extern Uint32  IPv4_Netmask(int FixedBits);
 extern int     IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, tIPStackBuffer *Buffer);
 
+extern void    IPv4_HandleError(tInterface *Iface, tIPErrorMode Mode, size_t Length, const void *Buf);
+
 #endif
index 2ac0574..0e6df53 100644 (file)
@@ -14,12 +14,12 @@ extern Uint32       IPv4_Netmask(int FixedBits);
 
 // === PROTOTYPES ===
  int   IPv6_Initialise();
- int   IPv6_RegisterCallback(int ID, tIPCallback Callback);
+// int IPv6_RegisterCallback(int ID, tIPCallback Callback);
 void   IPv6_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
 tInterface     *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
 
 // === GLOBALS ===
-tIPCallback    gaIPv6_Callbacks[256];
+tIPRxCallback* gaIPv6_Callbacks[256];
 
 // === CODE ===
 /**
@@ -36,7 +36,7 @@ int IPv6_Initialise()
  * \param ID   8-bit packet type ID
  * \param Callback     Callback function
  */
-int IPv6_RegisterCallback(int ID, tIPCallback Callback)
+int IPv6_RegisterCallback(int ID, tIPRxCallback* Callback)
 {
        if( ID < 0 || ID > 255 )        return 0;
        if( gaIPv6_Callbacks[ID] )      return 0;
index 35cd742..086dfbb 100644 (file)
@@ -32,12 +32,12 @@ struct sIPv6Header
        Uint8   HopLimit;
        tIPv6   Source;
        tIPv6   Destination;
-       char    Data[];
+       char    Data[0];
 };
 
 #define IPV6_ETHERNET_ID       0x86DD
 
-extern int     IPv6_RegisterCallback(int ID, tIPCallback Callback);
+extern int     IPv6_RegisterCallback(int ID, tIPRxCallback* Callback);
 extern int     IPv6_SendPacket(tInterface *Iface, tIPv6 Destination, int Protocol, tIPStackBuffer *Buffer);
 
 #endif
index bbf7951..2854f30 100644 (file)
@@ -2,7 +2,7 @@
  * Acess2 IP Stack
  * - TCP Handling
  */
-#define DEBUG  1
+#define DEBUG  0
 #include "ipstack.h"
 #include "ipv4.h"
 #include "ipv6.h"
@@ -18,7 +18,7 @@
 #define TCP_WINDOW_SIZE        0x2000
 #define TCP_RECIEVE_BUFFER_SIZE        0x8000
 #define TCP_DACK_THRESHOLD     4096
-#define TCP_DACK_TIMEOUT       500
+#define TCP_DACK_TIMEOUT       100
 
 #define TCP_DEBUG      0       // Set to non-0 to enable TCP packet logging
 
@@ -28,7 +28,9 @@ void  TCP_StartConnection(tTCPConnection *Conn);
 void   TCP_SendPacket(tTCPConnection *Conn, tTCPHeader *Header, size_t DataLen, const void *Data);
 void   TCP_int_SendPacket(tInterface *Interface, const void *Dest, tTCPHeader *Header, size_t Length, const void *Data);
 void   TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
-void   TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length);
+void   TCP_IPError(tInterface *Interface, tIPErrorMode Mode, const void *Address, int Length, const void *Buffer);
+ int   TCP_INT_HandleServerPacket(tInterface *Interface, tTCPListener *Server, const void *Address, tTCPHeader *Header, size_t Length);
+ int   TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length);
 int    TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t Length);
 void   TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection);
 void   TCP_int_SendDelayedACK(void *ConnPtr);
@@ -66,6 +68,7 @@ tVFS_NodeType gTCP_ServerNodeType = {
        };
 tVFS_NodeType  gTCP_ClientNodeType = {
        .TypeName = "TCP Client/Connection",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read  = TCP_Client_Read,
        .Write = TCP_Client_Write,
        .IOCtl = TCP_Client_IOCtl,
@@ -92,7 +95,7 @@ void TCP_Initialise(void)
        giTCP_NextOutPort += rand()%128;
        IPStack_AddFile(&gTCP_ServerFile);
        IPStack_AddFile(&gTCP_ClientFile);
-       IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
+       IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket, TCP_IPError);
        IPv6_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
 }
 
@@ -146,10 +149,22 @@ void TCP_int_SendPacket(tInterface *Interface, const void *Dest, tTCPHeader *Hea
                IPStack_Buffer_AppendSubBuffer(buffer, Length, 0, Data, NULL, NULL);
        IPStack_Buffer_AppendSubBuffer(buffer, sizeof(*Header), 0, Header, NULL, NULL);
 
-       LOG("Sending %i+%i to %s:%i", sizeof(*Header), Length,
+       #if TCP_DEBUG
+       Log_Log("TCP", "TCP_int_SendPacket: <Local>:%i to [%s]:%i (%i data), Flags = %s%s%s%s%s%s%s%s",
+               ntohs(Header->SourcePort),
                IPStack_PrintAddress(Interface->Type, Dest),
-               ntohs(Header->DestPort)
+               ntohs(Header->DestPort),
+               Length,
+               (Header->Flags & TCP_FLAG_CWR) ? "CWR " : "",
+               (Header->Flags & TCP_FLAG_ECE) ? "ECE " : "",
+               (Header->Flags & TCP_FLAG_URG) ? "URG " : "",
+               (Header->Flags & TCP_FLAG_ACK) ? "ACK " : "",
+               (Header->Flags & TCP_FLAG_PSH) ? "PSH " : "",
+               (Header->Flags & TCP_FLAG_RST) ? "RST " : "",
+               (Header->Flags & TCP_FLAG_SYN) ? "SYN " : "",
+               (Header->Flags & TCP_FLAG_FIN) ? "FIN " : ""
                );
+       #endif
 
        Header->Checksum = 0;
        Header->Checksum = TCP_int_CalculateChecksum(Interface->Type, Interface->Address, Dest,
@@ -168,7 +183,7 @@ void TCP_int_SendPacket(tInterface *Interface, const void *Dest, tTCPHeader *Hea
        }
 }
 
-void TCP_int_SendRSTTo(tInterface *Interface, void *Address, size_t Length, const tTCPHeader *Header)
+void TCP_int_SendRSTTo(tInterface *Interface, const void *Address, size_t Length, const tTCPHeader *Header)
 {
        tTCPHeader      out_hdr = {0};
        
@@ -244,96 +259,20 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                {
                        // Check that it is coming in on the same interface
                        if(conn->Interface != Interface)        continue;
-
                        // Check Source Port
-                       Log_Log("TCP", "TCP_GetPacket: conn->RemotePort(%i) == hdr->SourcePort(%i)",
-                               conn->RemotePort, ntohs(hdr->SourcePort));
                        if(conn->RemotePort != ntohs(hdr->SourcePort))  continue;
-
                        // Check Source IP
-                       Log_Debug("TCP", "TCP_GetPacket: conn->RemoteIP(%s)",
-                               IPStack_PrintAddress(conn->Interface->Type, &conn->RemoteIP));
-                       Log_Debug("TCP", "                == Address(%s)",
-                               IPStack_PrintAddress(conn->Interface->Type, Address));
                        if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
                                continue ;
 
                        Log_Log("TCP", "TCP_GetPacket: Matches connection %p", conn);
                        // We have a response!
-                       TCP_INT_HandleConnectionPacket(conn, hdr, Length);
-
-                       return;
+                       if( TCP_INT_HandleConnectionPacket(conn, hdr, Length) == 0 )
+                               return;
+                       break ;
                }
 
-               
-               if( hdr->Flags & TCP_FLAG_RST ) {
-                       LOG("RST, ignore");
-                       return ;
-               }
-               else if( hdr->Flags & TCP_FLAG_ACK ) {
-                       LOG("ACK, send RST");
-                       TCP_int_SendRSTTo(Interface, Address, Length, hdr);
-                       return ;
-               }
-               else if( !(hdr->Flags & TCP_FLAG_SYN) ) {
-                       LOG("Other, ignore");
-                       return ;
-               }
-               Log_Log("TCP", "TCP_GetPacket: Opening Connection");
-               
-               // TODO: Check for halfopen max
-               
-               tTCPConnection *conn = TCP_int_CreateConnection(Interface, TCP_ST_SYN_RCVD);
-               conn->LocalPort = srv->Port;
-               conn->RemotePort = ntohs(hdr->SourcePort);
-               
-               switch(Interface->Type)
-               {
-               case 4: conn->RemoteIP.v4 = *(tIPv4*)Address;   break;
-               case 6: conn->RemoteIP.v6 = *(tIPv6*)Address;   break;
-               default:        ASSERTC(Interface->Type,==,4);  return;
-               }
-               
-               conn->NextSequenceRcv = ntohl( hdr->SequenceNumber ) + 1;
-               conn->HighestSequenceRcvd = conn->NextSequenceRcv;
-               conn->NextSequenceSend = rand();
-               conn->LastACKSequence = ntohl( hdr->SequenceNumber );
-               
-               conn->Node.ImplInt = srv->NextID ++;
-               
-               // Hmm... Theoretically, this lock will never have to wait,
-               // as the interface is locked to the watching thread, and this
-               // runs in the watching thread. But, it's a good idea to have
-               // it, just in case
-               // Oh, wait, there is a case where a wildcard can be used
-               // (srv->Interface == NULL) so having the lock is a good idea
-               SHORTLOCK(&srv->lConnections);
-               conn->Server = srv;
-               conn->Prev = srv->ConnectionsTail;
-               if(srv->Connections) {
-                       ASSERT(srv->ConnectionsTail);
-                       srv->ConnectionsTail->Next = conn;
-               }
-               else {
-                       ASSERT(!srv->ConnectionsTail);
-                       srv->Connections = conn;
-               }
-               srv->ConnectionsTail = conn;
-               if(!srv->NewConnections)
-                       srv->NewConnections = conn;
-               VFS_MarkAvaliable( &srv->Node, 1 );
-               SHORTREL(&srv->lConnections);
-               Semaphore_Signal(&srv->WaitingConnections, 1);
-
-               // Send the SYN ACK
-               hdr->Flags |= TCP_FLAG_ACK;
-               hdr->AcknowlegementNumber = htonl(conn->NextSequenceRcv);
-               hdr->SequenceNumber = htonl(conn->NextSequenceSend);
-               hdr->DestPort = hdr->SourcePort;
-               hdr->SourcePort = htons(srv->Port);
-               hdr->DataOffset = (sizeof(tTCPHeader)/4) << 4;
-               TCP_SendPacket( conn, hdr, 0, NULL );
-               conn->NextSequenceSend ++;
+               TCP_INT_HandleServerPacket(Interface, srv, Address, hdr, Length);
                return ;
        }
 
@@ -348,13 +287,13 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                        if(conn->RemotePort != ntohs(hdr->SourcePort))  continue;
 
                        // Check Source IP
-                       if(conn->Interface->Type == 6 && !IP6_EQU(conn->RemoteIP.v6, *(tIPv6*)Address))
-                               continue;
-                       if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address))
-                               continue;
+                       if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
+                               continue ;
 
-                       TCP_INT_HandleConnectionPacket(conn, hdr, Length);
-                       return ;
+                       // Handle or fall through
+                       if( TCP_INT_HandleConnectionPacket(conn, hdr, Length) == 0 )
+                               return ;
+                       break;
                }
        }
        
@@ -366,13 +305,116 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
        }
 }
 
+void TCP_IPError(tInterface *Interface, tIPErrorMode Mode, const void *Address, int Length, const void *Buffer)
+{
+       if( Length < sizeof(tTCPHeader) )       return ;
+       
+       const tTCPHeader        *hdr = Buffer;
+       
+       // TODO: Handle errors for server connections
+       
+       for( tTCPConnection *conn = gTCP_OutbountCons; conn; conn = conn->Next )
+       {
+               if(conn->Interface != Interface)
+                       continue;
+               if(conn->RemotePort != ntohs(hdr->SourcePort))
+                       continue;
+               if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
+                       continue ;
+               
+               // Mark an error on the interface
+               VFS_MarkError(&conn->Node, 1);
+               return ;
+       }
+}
+
+/*
+ * Handle packets in LISTEN state
+ */
+int TCP_INT_HandleServerPacket(tInterface *Interface, tTCPListener *Server, const void *Address, tTCPHeader *Header, size_t Length)
+{
+       if( Header->Flags & TCP_FLAG_RST ) {
+               LOG("RST, ignore");
+               return 0;
+       }
+       else if( Header->Flags & TCP_FLAG_ACK ) {
+               LOG("ACK, send RST");
+               TCP_int_SendRSTTo(Interface, Address, Length, Header);
+               return 0;
+       }
+       else if( !(Header->Flags & TCP_FLAG_SYN) ) {
+               LOG("Other, ignore");
+               return 0;
+       }
+       
+       Log_Log("TCP", "TCP_GetPacket: Opening Connection");
+       
+       // TODO: Check security (a TCP Option)
+       // TODO: Check SEG.PRC 
+       // TODO: Check for halfopen max
+       
+       tTCPConnection *conn = TCP_int_CreateConnection(Interface, TCP_ST_SYN_RCVD);
+       conn->LocalPort = Server->Port;
+       conn->RemotePort = ntohs(Header->SourcePort);
+       
+       switch(Interface->Type)
+       {
+       case 4: conn->RemoteIP.v4 = *(tIPv4*)Address;   break;
+       case 6: conn->RemoteIP.v6 = *(tIPv6*)Address;   break;
+       default:        ASSERTC(Interface->Type,==,4);  return 0;
+       }
+       
+       conn->NextSequenceRcv = ntohl( Header->SequenceNumber ) + 1;
+       conn->HighestSequenceRcvd = conn->NextSequenceRcv;
+       conn->NextSequenceSend = rand();
+       conn->LastACKSequence = ntohl( Header->SequenceNumber );
+       
+       conn->Node.ImplInt = Server->NextID ++;
+       conn->Node.Size = -1;
+       
+       // Hmm... Theoretically, this lock will never have to wait,
+       // as the interface is locked to the watching thread, and this
+       // runs in the watching thread. But, it's a good idea to have
+       // it, just in case
+       // Oh, wait, there is a case where a wildcard can be used
+       // (Server->Interface == NULL) so having the lock is a good idea
+       SHORTLOCK(&Server->lConnections);
+       conn->Server = Server;
+       conn->Prev = Server->ConnectionsTail;
+       if(Server->Connections) {
+               ASSERT(Server->ConnectionsTail);
+               Server->ConnectionsTail->Next = conn;
+       }
+       else {
+               ASSERT(!Server->ConnectionsTail);
+               Server->Connections = conn;
+       }
+       Server->ConnectionsTail = conn;
+       if(!Server->NewConnections)
+               Server->NewConnections = conn;
+       VFS_MarkAvaliable( &Server->Node, 1 );
+       SHORTREL(&Server->lConnections);
+       Semaphore_Signal(&Server->WaitingConnections, 1);
+
+       // Send the SYN ACK
+       Header->Flags = TCP_FLAG_ACK|TCP_FLAG_SYN;
+       Header->AcknowlegementNumber = htonl(conn->NextSequenceRcv);
+       Header->SequenceNumber = htonl(conn->NextSequenceSend);
+       Header->DestPort = Header->SourcePort;
+       Header->SourcePort = htons(Server->Port);
+       Header->DataOffset = (sizeof(tTCPHeader)/4) << 4;
+       TCP_SendPacket( conn, Header, 0, NULL );
+       conn->NextSequenceSend ++;
+       return 0;
+}
+
 /**
  * \brief Handles a packet sent to a specific connection
  * \param Connection   TCP Connection pointer
  * \param Header       TCP Packet pointer
  * \param Length       Length of the packet
  */
-void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length)
+int TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Header, int Length)
 {
         int    dataLen;
        Uint32  sequence_num;
@@ -381,7 +423,11 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
        // TODO: Check if this needs to be here
        if( Connection->State == TCP_ST_FINISHED ) {
                Log_Log("TCP", "Packet ignored - connection finnished");
-               return ;
+               return 1;
+       }
+       if( Connection->State == TCP_ST_FORCE_CLOSE ) {
+               Log_Log("TCP", "Packet ignored - connection reset");
+               return 1;
        }
        
        // Syncronise sequence values
@@ -432,7 +478,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                        if( Header->Flags & TCP_FLAG_ACK )
                        {       
                                Log_Log("TCP", "ACKing SYN-ACK");
-                               Connection->State = TCP_ST_OPEN;
+                               Connection->State = TCP_ST_ESTABLISHED;
                                VFS_MarkFull(&Connection->Node, 0);
                                TCP_INT_SendACK(Connection, "SYN-ACK");
                        }
@@ -447,19 +493,34 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
        
        // SYN-ACK sent, expecting ACK
        case TCP_ST_SYN_RCVD:
+               if( Header->Flags & TCP_FLAG_RST )
+               {
+                       Log_Log("TCP", "RST Received, closing");
+                       Connection->State = TCP_ST_FORCE_CLOSE;
+                       VFS_MarkError(&Connection->Node, 1);
+                       return 0;
+               }
                if( Header->Flags & TCP_FLAG_ACK )
                {
                        // TODO: Handle max half-open limit
                        Log_Log("TCP", "Connection fully opened");
-                       Connection->State = TCP_ST_OPEN;
+                       Connection->State = TCP_ST_ESTABLISHED;
                        VFS_MarkFull(&Connection->Node, 0);
                }
                break;
                
        // --- Established State ---
-       case TCP_ST_OPEN:
+       case TCP_ST_ESTABLISHED:
                // - Handle State changes
                //
+               if( Header->Flags & TCP_FLAG_RST )
+               {
+                       Log_Log("TCP", "Conn %p closed, received RST");
+                       // Error outstanding transactions
+                       Connection->State = TCP_ST_FORCE_CLOSE;
+                       VFS_MarkError(&Connection->Node, 1);
+                       return 0;
+               }
                if( Header->Flags & TCP_FLAG_FIN ) {
                        Log_Log("TCP", "Conn %p closed, recieved FIN", Connection);
                        VFS_MarkError(&Connection->Node, 1);
@@ -467,7 +528,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                        TCP_INT_SendACK(Connection, "FIN Received");
                        Connection->State = TCP_ST_CLOSE_WAIT;
                        // CLOSE WAIT requires the client to close
-                       return ;
+                       return 0;
                }
        
                // Check for an empty packet
@@ -475,7 +536,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                        if( Header->Flags == TCP_FLAG_ACK )
                        {
                                Log_Log("TCP", "ACK only packet");
-                               return ;
+                               return 0;
                        }
                        // TODO: Is this right? (empty packet counts as one byte)
                        if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
@@ -483,7 +544,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                        Connection->NextSequenceRcv ++;
                        Log_Log("TCP", "Empty Packet, inc and ACK the current sequence number");
                        TCP_INT_SendACK(Connection, "Empty");
-                       return ;
+                       return 0;
                }
                
                // NOTES:
@@ -610,7 +671,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                        Connection->State = TCP_ST_FIN_WAIT2;
                        Log_Debug("TCP", "Conn %p closed, sent FIN ACKed", Connection);
                        VFS_MarkError(&Connection->Node, 1);
-                       return ;
+                       return 0;
                }
                break;
        
@@ -630,7 +691,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
                        Connection->State = TCP_ST_TIME_WAIT;
                        Log_Debug("TCP", "Conn %p CLOSING -> TIME WAIT", Connection);
                        VFS_MarkError(&Connection->Node, 1);
-                       return ;
+                       return 0;
                }
                break;
        
@@ -642,12 +703,17 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
        case TCP_ST_FINISHED:
                Log_Log("TCP", "Packets when CLOSED, ignoring");
                break;
+       case TCP_ST_FORCE_CLOSE:
+               Log_Log("TCP", "Packets when force CLOSED, ignoring");
+               return 1;
        
        //default:
        //      Log_Warning("TCP", "Unhandled TCP state %i", Connection->State);
        //      break;
        }
        
+       return 0;
+       
 }
 
 /**
@@ -690,10 +756,15 @@ int TCP_INT_AppendRecieved(tTCPConnection *Connection, const void *Data, size_t
 void TCP_INT_UpdateRecievedFromFuture(tTCPConnection *Connection)
 {
        // Calculate length of contiguous bytes
-       const int       length = Connection->HighestSequenceRcvd - Connection->NextSequenceRcv;
+       const size_t    length = Connection->HighestSequenceRcvd - Connection->NextSequenceRcv;
        Uint32  index = Connection->NextSequenceRcv % TCP_WINDOW_SIZE;
        size_t  runlength = length;
-       LOG("length=%i, index=0x%x", length, index);
+       LOG("HSR=0x%x,NSR=0x%x", Connection->HighestSequenceRcvd, Connection->NextSequenceRcv);
+       if( Connection->HighestSequenceRcvd == Connection->NextSequenceRcv )
+       {
+               return ;
+       }
+       LOG("length=%u, index=0x%x", length, index);
        for( int i = 0; i < length; i ++ )
        {
                 int    bit = index % 8;
@@ -854,6 +925,7 @@ tTCPConnection *TCP_int_CreateConnection(tInterface *Interface, enum eTCPConnect
        conn->LocalPort = -1;
        conn->RemotePort = -1;
 
+       conn->Node.Size = -1;
        conn->Node.ReferenceCount = 1;
        conn->Node.ImplPtr = conn;
        conn->Node.NumACLs = 1;
@@ -867,6 +939,7 @@ tTCPConnection *TCP_int_CreateConnection(tInterface *Interface, enum eTCPConnect
        Semaphore_Init(conn->SentBufferSpace, 0, TCP_SEND_BUFFER_SIZE, "TCP SentBuffer", conn->Name);
        #endif
        
+       conn->HighestSequenceRcvd = 0;
        #if CACHE_FUTURE_PACKETS_IN_BYTES
        // Future recieved data (ahead of the expected sequence number)
        conn->FuturePacketData = (Uint8*)conn + sizeof(tTCPConnection);
@@ -1116,7 +1189,8 @@ tVFS_Node *TCP_Client_Init(tInterface *Interface)
        conn->Server = NULL;
        conn->Prev = NULL;
        conn->Next = gTCP_OutbountCons;
-       gTCP_OutbountCons->Prev = conn;
+       if(gTCP_OutbountCons)
+               gTCP_OutbountCons->Prev = conn;
        gTCP_OutbountCons = conn;
        SHORTREL(&glTCP_OutbountCons);
 
@@ -1133,13 +1207,14 @@ size_t TCP_Client_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffe
        tTCPConnection  *conn = Node->ImplPtr;
        size_t  len;
        
-       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
        LOG("conn = %p {State:%i}", conn, conn->State);
        
        // If the connection has been closed (state > ST_OPEN) then clear
        // any stale data in the buffer (until it is empty (until it is empty))
-       if( conn->State > TCP_ST_OPEN )
+       if( conn->State > TCP_ST_ESTABLISHED )
        {
+               LOG("Connection closed");
                Mutex_Acquire( &conn->lRecievedPackets );
                len = RingBuffer_Read( Buffer, conn->RecievedBuffer, Length );
                Mutex_Release( &conn->lRecievedPackets );
@@ -1216,6 +1291,8 @@ void TCP_INT_SendDataPacket(tTCPConnection *Connection, size_t Length, const voi
        
        TCP_SendPacket( Connection, packet, Length, Data );
        
+       // TODO: Start a retransmit time (if data is not ACKed in x seconds, send again)
+       
        Connection->NextSequenceSend += Length;
 }
 
@@ -1235,7 +1312,7 @@ size_t TCP_Client_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void
 //     #endif
        
        // Don't allow a write to a closed connection
-       if( conn->State > TCP_ST_OPEN ) {
+       if( conn->State > TCP_ST_ESTABLISHED ) {
                VFS_MarkError(Node, 1);
                errno = 0;
                LEAVE('i', -1);
@@ -1394,7 +1471,7 @@ void TCP_Client_Close(tVFS_Node *Node)
        }
        Node->ReferenceCount --;
        
-       if( conn->State == TCP_ST_CLOSE_WAIT || conn->State == TCP_ST_OPEN )
+       if( conn->State == TCP_ST_CLOSE_WAIT || conn->State == TCP_ST_ESTABLISHED )
        {
                packet.SourcePort = htons(conn->LocalPort);
                packet.DestPort = htons(conn->RemotePort);
@@ -1416,10 +1493,14 @@ void TCP_Client_Close(tVFS_Node *Node)
                Log_Warning("TCP", "Closing connection that was never opened");
                TCP_int_FreeTCB(conn);
                break;
+       case TCP_ST_FORCE_CLOSE:
+               conn->State = TCP_ST_FINISHED;
+               TCP_int_FreeTCB(conn);
+               break;
        case TCP_ST_CLOSE_WAIT:
                conn->State = TCP_ST_LAST_ACK;
                break;
-       case TCP_ST_OPEN:
+       case TCP_ST_ESTABLISHED:
                conn->State = TCP_ST_FIN_WAIT1;
                while( conn->State == TCP_ST_FIN_WAIT1 )
                        Threads_Yield();
index 43828f1..0e260fc 100644 (file)
@@ -94,7 +94,7 @@ enum eTCPConnectionState
        TCP_ST_SYN_SENT,        // 1 - SYN sent by local, waiting for SYN-ACK
        TCP_ST_SYN_RCVD,        // 2 - SYN recieved, SYN-ACK sent
        
-       TCP_ST_OPEN,            // 3 - Connection open
+       TCP_ST_ESTABLISHED,     // 3 - Connection open
        
        // Local Close
        TCP_ST_FIN_WAIT1,       // 4 - FIN sent, waiting for reply (ACK or FIN)
@@ -102,9 +102,10 @@ enum eTCPConnectionState
        TCP_ST_CLOSING,         // 6 - Waiting for ACK of FIN (FIN sent and recieved)
        TCP_ST_TIME_WAIT,       // 7 - Waiting for timeout after local close
        // Remote close
-       TCP_ST_CLOSE_WAIT,      // 8 - FIN recieved, waiting for user to close (error set, wait for node close)
-       TCP_ST_LAST_ACK,        // 9 - FIN sent and recieved, waiting for ACK
-       TCP_ST_FINISHED         // 10 - Essentially closed, all packets are invalid
+       TCP_ST_FORCE_CLOSE,     // 8  - RST recieved, waiting for user close
+       TCP_ST_CLOSE_WAIT,      // 9  - FIN recieved, waiting for user to close (error set, wait for node close)
+       TCP_ST_LAST_ACK,        // 10 - FIN sent and recieved, waiting for ACK
+       TCP_ST_FINISHED         // 11 - Essentially closed, all packets are invalid
 };
 
 struct sTCPConnection
index 325a09e..9037439 100644 (file)
@@ -15,7 +15,7 @@
 // === PROTOTYPES ===
 void   UDP_Initialise();
 void   UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
-void   UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer);
+void   UDP_IPError(tInterface *Interface, tIPErrorMode Code, const void *Address, int Length, const void *Buffer);
 void   UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, const void *Address, Uint16 Port, const void *Data, size_t Length);
 // --- Client Channels
 tVFS_Node      *UDP_Channel_Init(tInterface *Interface);
@@ -33,6 +33,8 @@ Uint16        UDP_int_FinaliseChecksum(Uint16 Value);
 
 // === GLOBALS ===
 tVFS_NodeType  gUDP_NodeType = {
+       .TypeName = "UDP",
+       .Flags = VFS_NODETYPEFLAG_STREAM,
        .Read = UDP_Channel_Read,
        .Write = UDP_Channel_Write,
        .IOCtl = UDP_Channel_IOCtl,
@@ -54,8 +56,7 @@ tSocketFile   gUDP_SocketFile = {NULL, "udp", UDP_Channel_Init};
 void UDP_Initialise()
 {
        IPStack_AddFile(&gUDP_SocketFile);
-       //IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket, UDP_Unreachable);
-       IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
+       IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket, UDP_IPError);
 }
 
 /**
@@ -65,13 +66,15 @@ void UDP_Initialise()
 int UDP_int_ScanList(tUDPChannel *List, tInterface *Interface, void *Address, int Length, void *Buffer)
 {
        tUDPHeader      *hdr = Buffer;
-       tUDPChannel     *chan;
-       tUDPPacket      *pack;
-        int    len;
        
-       for(chan = List; chan; chan = chan->Next)
+       for(tUDPChannel *chan = List; chan; chan = chan->Next)
        {
                // Match local endpoint
+               LOG("(%p):%i - %s/%i:%i",
+                       chan->Interface, chan->LocalPort,
+                       IPStack_PrintAddress(chan->Remote.AddrType, &chan->Remote.Addr), chan->RemoteMask,
+                       chan->Remote.Port
+                       );
                if(chan->Interface && chan->Interface != Interface)     continue;
                if(chan->LocalPort != ntohs(hdr->DestPort))     continue;
                
@@ -91,8 +94,8 @@ int UDP_int_ScanList(tUDPChannel *List, tInterface *Interface, void *Address, in
                
                Log_Log("UDP", "Recieved packet for %p", chan);
                // Create the cached packet
-               len = ntohs(hdr->Length);
-               pack = malloc(sizeof(tUDPPacket) + len);
+               int len = ntohs(hdr->Length);
+               tUDPPacket *pack = malloc(sizeof(tUDPPacket) + len);
                pack->Next = NULL;
                memcpy(&pack->Remote.Addr, Address, IPStack_GetAddressSize(Interface->Type));
                pack->Remote.Port = ntohs(hdr->SourcePort);
@@ -142,7 +145,7 @@ void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
 /**
  * \brief Handle an ICMP Unrechable Error
  */
-void UDP_Unreachable(tInterface *Interface, int Code, void *Address, int Length, void *Buffer)
+void UDP_IPError(tInterface *Interface, tIPErrorMode Code, const void *Address, int Length, const void *Buffer)
 {
        
 }
@@ -157,7 +160,11 @@ void UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, const void *Address, U
 {
        tUDPHeader      hdr;
 
-       if(Channel->Interface && Channel->Interface->Type != AddrType)  return ;
+       if(Channel->Interface && Channel->Interface->Type != AddrType) {
+               LOG("Bad interface type for channel packet, IF is %i, but packet is %i",
+                       Channel->Interface->Type, AddrType);
+               return ;
+       }
        
        // Create the packet
        hdr.SourcePort = htons( Channel->LocalPort );
@@ -175,6 +182,7 @@ void UDP_SendPacketTo(tUDPChannel *Channel, int AddrType, const void *Address, U
                IPStack_Buffer_AppendSubBuffer(buffer, Length, 0, Data, NULL, NULL);
                IPStack_Buffer_AppendSubBuffer(buffer, sizeof(hdr), 0, &hdr, NULL, NULL);
                // TODO: What if Channel->Interface is NULL here?
+               ASSERT(Channel->Interface);
                IPv4_SendPacket(Channel->Interface, *(tIPv4*)Address, IP4PROT_UDP, 0, buffer);
                break;
        default:
@@ -189,6 +197,7 @@ tVFS_Node *UDP_Channel_Init(tInterface *Interface)
        tUDPChannel     *new;
        new = calloc( sizeof(tUDPChannel), 1 );
        new->Interface = Interface;
+       new->Node.Size = -1;
        new->Node.ImplPtr = new;
        new->Node.NumACLs = 1;
        new->Node.ACLs = &gVFS_ACL_EveryoneRW;
@@ -202,49 +211,59 @@ tVFS_Node *UDP_Channel_Init(tInterface *Interface)
        return &new->Node;
 }
 
-/**
- * \brief Read from the channel file (wait for a packet)
- */
-size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
+tUDPPacket *UDP_Channel_WaitForPacket(tUDPChannel *chan, Uint VFSFlags)
 {
-       tUDPChannel     *chan = Node->ImplPtr;
-       tUDPPacket      *pack;
-       tUDPEndpoint    *ep;
-        int    ofs, addrlen;
-       
-       if(chan->LocalPort == 0) {
-               Log_Notice("UDP", "Channel %p sent with no local port", chan);
-               return 0;
-       }
-       
-       while(chan->Queue == NULL)      Threads_Yield();
+       // EVIL - Yield until queue is created (avoids races)
+       while(chan->Queue == NULL)
+               Threads_Yield();
        
        for(;;)
        {
-               tTime   timeout_z = 0, *timeout = (Flags & VFS_IOFLAG_NOBLOCK) ? &timeout_z : NULL;
-               int rv = VFS_SelectNode(Node, VFS_SELECT_READ, timeout, "UDP_Channel_Read");
-               if( rv ) {
-                       errno = (Flags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+               tTime   timeout_z = 0, *timeout = (VFSFlags & VFS_IOFLAG_NOBLOCK) ? &timeout_z : NULL;
+               int rv = VFS_SelectNode(&chan->Node, VFS_SELECT_READ, timeout, "UDP_Channel_Read");
+               if( rv == 0 ) {
+                       errno = (VFSFlags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+                       return NULL;
                }
                SHORTLOCK(&chan->lQueue);
                if(chan->Queue == NULL) {
                        SHORTREL(&chan->lQueue);
                        continue;
                }
-               pack = chan->Queue;
+               tUDPPacket *pack = chan->Queue;
                chan->Queue = pack->Next;
                if(!chan->Queue) {
                        chan->QueueEnd = NULL;
-                       VFS_MarkAvaliable(Node, 0);     // Nothing left
+                       VFS_MarkAvaliable(&chan->Node, 0);      // Nothing left
                }
                SHORTREL(&chan->lQueue);
-               break;
+               return pack;
+       }
+       // Unreachable
+}
+
+/**
+ * \brief Read from the channel file (wait for a packet)
+ */
+size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
+{
+       tUDPChannel     *chan = Node->ImplPtr;
+       
+       if(chan->LocalPort == 0) {
+               Log_Notice("UDP", "Channel %p sent with no local port", chan);
+               return 0;
+       }
+       
+       tUDPPacket      *pack = UDP_Channel_WaitForPacket(chan, Flags);
+       if( !pack ) {
+               return 0;
        }
 
+       size_t addrlen = IPStack_GetAddressSize(pack->Remote.AddrType);
+       tUDPEndpoint *ep = Buffer;
+       size_t ofs = 4 + addrlen;
+       
        // Check that the header fits
-       addrlen = IPStack_GetAddressSize(pack->Remote.AddrType);
-       ep = Buffer;
-       ofs = 4 + addrlen;
        if(Length < ofs) {
                free(pack);
                Log_Notice("UDP", "Insuficient space for header in buffer (%i < %i)", (int)Length, ofs);
@@ -300,6 +319,8 @@ static const char *casIOCtls_Channel[] = {
        "getset_remoteport",
        "getset_remotemask",
        "set_remoteaddr",
+       "sendto",
+       "recvfrom",
        NULL
        };
 /**
@@ -351,14 +372,21 @@ int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data)
        
        case 6: // getset_remotemask (returns bool success)
                if(!Data)       LEAVE_RET('i', chan->RemoteMask);
-               if(!CheckMem(Data, sizeof(int)))        LEAVE_RET('i', -1);
+               if(!CheckMem(Data, sizeof(int))) {
+                       LOG("Data pointer invalid");
+                       LEAVE_RET('i', -1);
+               }
                if( !chan->Interface ) {
                        LOG("Can't set remote mask on NULL interface");
                        LEAVE_RET('i', -1);
                }
-               if( *(int*)Data > IPStack_GetAddressSize(chan->Interface->Type) )
+                int    mask = *(int*)Data;
+                int    addr_bits = IPStack_GetAddressSize(chan->Interface->Type) * 8;
+               if( mask > addr_bits ) {
+                       LOG("Mask too large (%i > max %i)", mask, addr_bits);
                        LEAVE_RET('i', -1);
-               chan->RemoteMask = *(int*)Data;
+               }
+               chan->RemoteMask = mask;
                LEAVE('i', chan->RemoteMask);
                return chan->RemoteMask;        
 
@@ -371,9 +399,73 @@ int UDP_Channel_IOCtl(tVFS_Node *Node, int ID, void *Data)
                        LOG("Invalid pointer");
                        LEAVE_RET('i', -1);
                }
+               LOG("Set remote addr %s", IPStack_PrintAddress(chan->Interface->Type, Data));
+               chan->Remote.AddrType = chan->Interface->Type;
                memcpy(&chan->Remote.Addr, Data, IPStack_GetAddressSize(chan->Interface->Type));
                LEAVE('i', 0);
                return 0;
+       case 8: {       // sendto
+               if(!CheckMem(Data, 2*sizeof(void*)+2)) {
+                       LOG("Data pointer invalid");
+                       LEAVE_RET('i', -1);
+               }
+               const struct sSendToArgs {
+                       const tUDPEndpoint* ep;
+                       const void* buf;
+                       const Uint16 buflen;
+               } info = *(const struct sSendToArgs*)Data;
+               LOG("sendto(buf=%p + %u, ep=%p)", info.buf, info.buflen, info.ep);
+               if(!CheckMem(info.ep, 2+2) || !CheckMem(info.ep, 2+2+IPStack_GetAddressSize(info.ep->AddrType)) ) {
+                       LEAVE_RET('i', -1);
+               }
+               if(!CheckMem(info.buf, info.buflen)) {
+                       LEAVE_RET('i', -1);
+               }
+               
+               UDP_SendPacketTo(chan, info.ep->AddrType, &info.ep->Addr, info.ep->Port,
+                       info.buf, (size_t)info.buflen);
+               
+               LEAVE_RET('i', info.buflen); }
+       case 9: {       // recvfrom
+               if(!CheckMem(Data, 2*sizeof(void*)+2)) {
+                       LOG("Data pointer invalid");
+                       LEAVE_RET('i', -1);
+               }
+               const struct sRecvFromArgs {
+                       tUDPEndpoint* ep;
+                       void* buf;
+                       Uint16 buflen;
+               } info = *(const struct sRecvFromArgs*)Data;
+               LOG("recvfrom(buf=%p + %u, ep=%p)", info.buf, info.buflen, info.ep);
+               if(!CheckMem(info.ep, 2+2)) {
+                       LEAVE_RET('i', -1);
+               }
+               if(!CheckMem(info.buf, info.buflen)) {
+                       LEAVE_RET('i', -1);
+               }
+               
+               tUDPPacket      *pack = UDP_Channel_WaitForPacket(chan, 0);
+               if( pack == NULL ) {
+                       LOG("No packet");
+                       LEAVE_RET('i', 0);
+               }
+               
+               size_t  addrsize = IPStack_GetAddressSize(pack->Remote.AddrType);
+               if( !CheckMem(info.ep, 2+2+addrsize) ) {
+                       LOG("Insufficient space for source address");
+                       free(pack);
+                       LEAVE_RET('i', -1);
+               }
+               info.ep->Port = pack->Remote.Port;
+               info.ep->AddrType = pack->Remote.AddrType;
+               memcpy(&info.ep->Addr, &pack->Remote.Addr, addrsize);
+               
+               size_t  retlen = (info.buflen < pack->Length ? info.buflen : pack->Length);
+               memcpy(info.buf, pack->Data, retlen);
+
+               free(pack);
+       
+               LEAVE_RET('i', retlen); }
        }
        LEAVE_RET('i', 0);
 }
index 377ae30..32688df 100644 (file)
@@ -117,19 +117,16 @@ int Keyboard_IOCtl(tVFS_Node *Node, int Id, void *Data)
  */
 tKeyboard *Keyboard_CreateInstance(int MaxSym, const char *Name)
 {
-       tKeyboard       *ret;
-        int    sym_bitmap_size = (MaxSym + 7)/8;
-        int    string_size = strlen(Name) + 1;
+       size_t  sym_bitmap_size = (MaxSym + 7)/8;
+       size_t  string_size = strlen(Name) + 1;
 
-       ret = malloc( sizeof(tKeyboard) + sym_bitmap_size + string_size );
+       tKeyboard *ret = calloc( 1, sizeof(tKeyboard) + sym_bitmap_size + string_size );
        if( !ret ) {
                return NULL;
        }
-       // Clear
-       memset(ret, 0, sizeof(tKeyboard) + sym_bitmap_size );
        // Set name
-       ret->Name = (char*)ret + sizeof(tKeyboard) + sym_bitmap_size;
-       memcpy(ret->Name, Name, string_size);
+       ret->Name = (char*)( &ret->KeyStates[sym_bitmap_size] );
+       strcpy(ret->Name, Name);
        // Set node and default keymap
        ret->Node = &gKB_DevInfo.RootNode;
        ret->Keymap = &gKeymap_KBDUS;
index f71fff7..d76322c 100644 (file)
@@ -24,10 +24,9 @@ void KBC8042_Init(void)
        IRQ_AddHandler(12, KBC8042_MouseHandler, NULL); // Set IRQ
        
        {
-               Uint8   temp;
                // Attempt to get around a strange bug in Bochs/Qemu by toggling
                // the controller on and off
-               temp = inb(0x61);
+               Uint8 temp = inb(0x61);
                outb(0x61, temp | 0x80);
                outb(0x61, temp & 0x7F);
                inb(0x60);      // Clear keyboard buffer
diff --git a/KernelLand/Modules/Interfaces/EDI/Makefile b/KernelLand/Modules/Interfaces/EDI/Makefile
deleted file mode 100644 (file)
index a93a8b7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# 
-# EDI - Extensible Driver Interface
-# 
-# Acess Interface
-
-
-OBJ = main.o edi.o
-NAME = EDI
-
--include ../Makefile.tpl
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/acess-edi.h b/KernelLand/Modules/Interfaces/EDI/edi/acess-edi.h
deleted file mode 100644 (file)
index 4071388..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*! \file acess-edi.h
- * \brief Acess Specific EDI Objects
- * 
- * Contains documentation and information for
- * - Timers
- */
-
-/* Copyright (c)  2006  John Hodge
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-#ifndef ACESS_EDI_H
-#define ACESS_EDI_H
-
-#include "edi_objects.h"
-
-/// \brief Name of Acess EDI Time Class
-#define        ACESS_TIMER_CLASS       "ACESSEDI-TIMER"
-
-#ifndef IMPLEMENTING_EDI
-/*! \brief int32_t ACESSEDI-TIMER.init_timer(uint32_t Delay, void (*Callback)(int), int Arg);
- *
- * Takes a timer pointer and intialises the timer object to fire after \a Delay ms
- * When the timer fires, \a Callback is called with \a Arg passed to it.
- */
-EDI_DEFVAR int32_t (*init_timer)(object_pointer port_object, uint32_t Delay, void (*fcn)(int), int arg);
-
-/*! \brief void ACESSEDI-TIMER.disable_timer();
- * 
- * Disables the timer and prevents it from firing
- * After this has been called, the timer can then be initialised again.
- */
-EDI_DEFVAR void (*disable_timer)(object_pointer port_object);
-
-
-#endif // defined(IMPLEMENTING_EDI)
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/edi.h b/KernelLand/Modules/Interfaces/EDI/edi/edi.h
deleted file mode 100644 (file)
index 273f7a3..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef EDI_H
-
-/* Copyright (c)  2006  Eli Gottlieb.
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-#define EDI_H
-/*! \file edi.h
- * \brief The unitive EDI header to include others, start EDI, and stop EDI.
- *
- * Data structures and algorithms this header represents:
- *     DATA STRUCTURE: CLASS QUOTAS - The runtime and the driver have the right to set a quota on how many objects of a given class
- * owned by that party the other may construct.  These quotas are kept internally by the driver or runtime, are optional and are
- * exposed to the other party via the quota() function (for quotas of runtime-owned classes) and the k_quota() function pointer given
- * to the runtime by the driver.
- *
- *     ALGORITHMS: INITIALIZATION AND SHUTDOWN - On initialization of the runtime's EDI environment for this driver it calls the
- * driver's driver_init() routine (which must match driver_init_t) to initialize the driver with a list of EDI objects the runtime
- * thinks the driver should run with.  The driver then initializes.  This can include calling edi_negotiate_resources() to try and
- * obtain more or different objects.  Eventually driver_init() returns an edi_initialization_t structure containing its quota
- * function and the list of classes belonging to the driver which the runtime can construct.  Either the driver or the runtime can
- * shut down EDI by calling edi_shutdown(), which in turn calls the driver's driver_finish() routine.  On shutdown all objects, of
- * classes belonging to both the runtime and driver, are destroyed. */
-
-#include "edi_objects.h"
-#include "edi_dma_streams.h"
-#include "edi_pthreads.h"
-#include "edi_port_io.h"
-#include "edi_memory_mapping.h"
-#include "edi_devices.h"
-#include "edi_interrupts.h"
-
-/*! \brief A pointer to a function the runtime can call if it fails to construct one of the driver's classes to find out what the
- * runtime's quota is for that class.
- *
- * A pointer to a function which takes an edi_string_t as a parameter and returns in int32_t.  This function follows the same
- * semantics as the quota() function, returning the number of objects of the given class that can be constructed, -1 for infinity or
- * -2 for an erroneous class name.  It is used to tell the runtime the location of such a function in the driver so that the runtime
- * can check quotas on driver-owned classes. */
-typedef int32_t (*k_quota_t)(edi_string_t resource_class);
-/*!\struct edi_initialization_t
- * \brief Structure containing driver classes available to the runtime and the driver's quota function after the driver has initialized. 
- *
- * Structure containing driver classes available to runtime, the driver's quota function and the driver's name provided to the runtime
- * after the driver has initialized.  driver_bus, vendor_id, and device_id are all optional fields which coders should consider
- * supplementary information.  Kernels can require these fields if they so please, but doing so for devices which don't run on a Vendor
- * ID/Product ID supporting bus is rather unwise. */
-typedef struct {
-       /*!\brief The number of driver classes in the driver_classes array. */
-       int32_t num_driver_classes;
-       /*!\brief An array of declarations of driver classes available to the runtime. 
-        *
-        * This array should not necessarily contain the entire list of EDI classes implemented by the driver.  Instead, it should
-        * contain a list of those classes which the driver has correctly initialized itself to provide instances of with full
-        * functionality. */
-       edi_class_declaration_t *driver_classes;
-       /*!\brief The driver's quota function. */
-       k_quota_t k_quota;
-       /*!\brief The driver's name. */
-       edi_string_t driver_name;
-       /*!\brief The bus of the device this driver wants to drive, if applicable.
-        *
-        * The driver does not have to supply this field, and can also supply "MULTIPLE BUSES" here to indicate that it drives devices
-        * on multiple buses. */
-       edi_string_t driver_bus;
-       /*!\brief The driver's vendor ID, if applicable.
-        *
-        * The driver does not need to supply this field, and should supply -1 to indicate that it does not wish to. */
-       int16_t vendor_id;
-       /*!\brief The driver's device ID, if applicable.
-        *
-        * The driver does not need to supply this field, but can supply it along with vendor_id.  If either vendor_id or this field are
-        * set to -1 the runtime should consider this field not supplied. */
-       int16_t driver_id;
-} edi_initialization_t;        
-/*!\brief A pointer to a driver's initialization function.
- *
- * The protocol for the driver's initialization function.  The runtime gives the driver a set of EDI objects representing the
- * resources it thinks the driver should run with.  This function returns an edi_initialization_t structure containing declarations
- * of the EDI classes the driver can make available to the runtime after initialization.  If any member of that structure contains 0
- * or NULL, it is considered invalid and the runtime should destroy the driver without calling its driver_finish() routine. */
-typedef edi_initialization_t (*driver_init_t)(int32_t num_resources,edi_object_metadata_t *resources);
-/*!\brief Requests more resources from the runtime.  Can be called during driver initialization.
- *
- * Called to negotiate with the runtime for the right to create further EDI objects/obtain further resources owned by the runtime.
- * When the driver calls this routine, the runtime decides whether to grant more resources.  If yes, this call returns true, and the
- * driver can proceed to try and create the objects it desires, in addition to destroying EDI objects it doesn't want.  Otherwise,
- * it returns false.
- * The driver must deal with whatever value this routine returns. */
-bool edi_negotiate_resources();
-
-/*! \brief Returns the driver's quota of objects for a given runtime-owned class. 
- *
- * This function takes an edi_string_t with the name of a runtime-owned class in it and returns the number of objects of that class
- * which drivers can construct, -1 for infinity, or -2 for an erroneous class name. */
-int32_t quota(edi_string_t resource_class);
-/*! \brief Sends a string to the operating systems debug output or logging facilities. */
-void edi_debug_write(uint32_t debug_string_length, char *debug_string);
-/*! \brief This call destroys all objects and shuts down the entire EDI environment of the driver. 
- *
- * This function shuts down EDI as described in INITIALIZATION AND SHUTDOWN above.  All objects are destroyed, EDI functions can no
- * longer be successfully called, etc.  This function only succeeds when EDI has already been initialized, so it returns -1 when EDI
- * hasn't been, 1 on success, or 0 for all other errors. */
-int32_t shutdown_edi(void);
-
-/*!\brief A pointer to the driver's finishing/shutdown function.
- *
- * The protocol for the driver's shutting down.  This function should do anything the driver wants done before it dies. */
-typedef void (*driver_finish_t)();
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/edi_devices.h b/KernelLand/Modules/Interfaces/EDI/edi/edi_devices.h
deleted file mode 100644 (file)
index 245e01f..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef EDI_DEVICES_H
-
-/* Copyright (c)  2006  Eli Gottlieb.
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-/* Edited by thePowersGang (John Hodge) June 2009
- * - Add #ifdef EDI_MAIN_FILE
- */
-
-#define EDI_DEVICES_H
-
-/*! \file edi_devices.h
- * \brief Declaration and description of simple classes for implementation by EDI drivers to represent hardware devices.
- *
- * Data structures and algorithms this header represents:
- *
- *     DATA STRUCTURE AND ALGORITHM: BASIC DEVICES - There are two functions, select() for waiting on devices and ioctl() for
- * controlling them, common to many POSIX devices.  Implementations of EDI-CHARACTER-DEVICE or EDI-BLOCK-DEVICE may implement either of
- * these or both, and users of such objects much query for the methods to see if they're supported.  Obviously, runtime or driver
- * developers don't *need* to support these.
- *
- *     DATA STRUCTURE AND ALGORITHM: CHARACTER DEVICES - The class EDI-CHARACTER-DEVICE provides a very basic interface to character
- * devices, which read and write streams of characters.  As such, this class only provides read() and write().  The calls attempt a
- * likeness to POSIX.
- *
- *     DATA STRUCTURE AND ALGORITHM: BLOCK DEVICES - The class EDI-BLOCK-DEVICE provides a very basic interface to block devices, which
- * can read(), write() and seek() to blocks of a specific size in an array of blocks with a specific size.  Its declarations and
- * semantics should behave like those of most POSIX operating systems.
- *
- * Note that EDI runtimes should not implement these classes.  Their declarations are provided for drivers to implement. */
-
-#include "edi_objects.h"
-
-/* Methods common to all EDI device classes specified in this header. */
-
-/*!\brief EAGAIN returned by functions for block and character devices.
- *
- * Means that the amount of data the device has ready is less than count. */
-#define EAGAIN -1
-/*!\brief EBADOBJ returned by functions for block and character devices.
- *
- * Means that the object passed as the method's this point was not a valid object of the needed class. */
-#define EBADOBJ -2
-/*!\brief EINVAL returned by functions for block and character devices.
- *
- * Means that the method got passed invalid parameters. */
-#ifdef EINVAL
-# undef EINVAL
-#endif
-#define EINVAL -3
-
-/*!\brief select() type to wait until device is writable. */
-#define EDI_SELECT_WRITABLE 0
-/*!\brief select() type to wait until device is readable. */
-#define EDI_SELECT_READABLE 1
-
-/*!\brief Argument to seek().  Sets the block offset (ie: the "current block" index) to the given whence value. */
-#define EDI_SEEK_SET 0
-/*!\brief Argument to seek().  Sets the block offset (ie: the "current block" index) to its current value + whence. */
-#define EDI_SEEK_CURRENT 1
-
-#ifdef EDI_MAIN_FILE
-/*!\brief Arguments to EDI's basic select() function. */
-edi_variable_declaration_t select_arguments[2] = {{"pointer void","device",1},
-                                                {"unsigned int32_t","select_type",1}};
-/*!\brief Declaration of EDI's basic select() function. 
- *
- * Contrary to the POSIX version, this select() puts its error codes in its return value. */
-edi_function_declaration_t select_declaration = {"int32_t","edi_device_select",0,2,select_arguments,NULL};
-#else
-extern edi_function_declaration_t select_declaration;  // Declare for non main files
-#endif
-
-#ifdef EDI_MAIN_FILE
-/*!\brief Arguments to EDI's basic ioctl() function. */
-edi_variable_declaration_t ioctl_arguments[3] = {{"pointer void","device",1},{"int32_t","request",1},{"pointer void","argp",1}};
-/*!\brief Declaration of EDI's basic ioctl() function. 
- *
- * Contrary to the POSIX version, this ioctl() puts its error codes in its return value. */
-edi_function_declaration_t ioctl_declaration = {"int32_t","edi_device_ioctl",0,3,ioctl_arguments,NULL};
-#else
-extern edi_class_declaration_t ioctl_declaration;      // Declare for non main files
-#endif
-
-#ifdef EDI_MAIN_FILE
-/*!\brief Declaration of the arguments EDI-CHARACTER-DEVICE's read() and write() methods. */
-edi_variable_declaration_t chardev_read_write_arguments[3] = {{"pointer void","chardev",1},
-                                                             {"pointer void","buffer",1},
-                                                             {"unsigned int32_t","char_count",1}};
-/*!\brief Declarations of the methods of EDI-CHARACTER-DEVICE, read() and write().
- *
- * The code pointers of these function declarations are all given as NULL.  Driver developers implementing EDI-CHARACTER-DEVICE should
- * fill in these entries with pointers to their own functions. */
-EDI_DEFVAR edi_function_declaration_t chardev_methods[2]= {{"int32_t","edi_chardev_read",0,3,chardev_read_write_arguments,NULL},
-                                               {"int32_t","edi_chardev_write",0,3,chardev_read_write_arguments,NULL}};
-/*!\brief Declaration of the EDI-CHARACTER-DEVICE class.
- *
- * Driver developers implementing this class should fill in their own values for constructor, destructor, and possibly even parent
- * before passing the filled-in structure to the EDI runtime. */
-EDI_DEFVAR edi_class_declaration_t chardev_class = {"EDI-CHARACTER-DEVICE",0,2,chardev_methods,NULL,NULL,NULL};
-#else
-extern edi_class_declaration_t chardev_class;  // Declare for non main files
-#endif
-
-#ifdef EDI_MAIN_FILE
-/*!\brief Arguments to EDI-BLOCK-DEVICE's read() and write() methods. */
-edi_variable_declaration_t blockdev_read_write_arguments[3] = {{"pointer void","blockdev",1},
-                                                              {"pointer void","buffer",1},
-                                                              {"unsigned int32_t","blocks",1}};
-/*!\brief Arguments to EDI-BLOCK-DEVICE's seek() method. */
-edi_variable_declaration_t blockdev_seek_arguments[3] = {{"pointer void","blockdev",1},
-                                                        {"int32_t","offset",1},
-                                                        {"int32_t","whence",1}};
-/*!\brief Declaration of the methods of EDI-BLOCK-DEVICE, read(), write(), seek(), and get_block_size(). 
- *
- * The code pointers of these function declarations are all given as NULL.  Driver developers implementing EDI-BLOCK-DEVICE should fill
- * these entries in with pointers to their own functions. */
-edi_function_declaration_t blockdev_methods[4] = {{"int32_t","edi_blockdev_read",0,3,blockdev_read_write_arguments,NULL},
-                                                 {"int32_t","edi_blockdev_write",0,3,blockdev_read_write_arguments,NULL},
-                                                 {"int32_t","edi_blockdev_seek",0,3,blockdev_seek_arguments,NULL},
-                                                 {"unsigned int32_t","edi_blockdev_get_block_size",0,0,NULL,NULL}};
-/*!\brief Declaration of the EDI-BLOCK-DEVICE class.
- *
- * Driver developers implementing this class should fill in their own values for constructor, destructor, and possibly even parent
- * before passing the filled-in structure to the EDI runtime. */
-edi_class_declaration_t blockdev_class = {"EDI-BLOCK-DEVICE",0,4,blockdev_methods,NULL,NULL,NULL};
-#else
-extern edi_class_declaration_t blockdev_class; // Declare for non main files
-#endif
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/edi_dma_streams.h b/KernelLand/Modules/Interfaces/EDI/edi/edi_dma_streams.h
deleted file mode 100644 (file)
index 8ab80cc..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef EDI_DMA_STREAMS_H
-
-/* Copyright (c)  2006  Eli Gottlieb.
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-#define EDI_DMA_STREAMS_H
-
-/*! \file edi_dma_streams.h 
- * \brief EDI's stream subclass for handling Direct Memory Access hardware.
- *
- * Data structures and algorithms this header represents:
- *
- *     DATA STRUCTURE: DMA STREAMS - DMA streams are objects of the class EDI-STREAM-DMA used to pass data between a buffer of
- * memory and the computer's DMA hardware.  It is the responsibility of the object to allocate memory for its stream memory buffer
- * which can be used with DMA hardware and to program the DMA hardware for transmissions.  DMA streams can be bidirectional if the
- * correct DMA mode is used. */
-
-#include "edi_objects.h"
-
-#define DMA_STREAM_CLASS       "EDI-STREAM-DMA"
-
-/*! \brief The name of the EDI DMA stream class.
- *
- * An edi_string_t with the class name "EDI-STREAM-DMA" in it. */
-#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI)
-const edi_string_t dma_stream_class = DMA_STREAM_CLASS;
-#else
-extern const edi_string_t dma_stream_class;
-#endif
-
-#ifndef IMPLEMENTING_EDI
-/*! \brief int32_t EDI-STREAM-DMA.init_dma_stream(unsigned int32_t channel,unsigned int32_t mode,unsigned int32_t buffer_pages);
- *
- * Pointer to the init_dma_stream() method of class EDI-STREAM-DMA, which initializes a DMA stream with a DMA channel, DMA mode, and
- * the number of DMA-accessible memory pages to keep as a buffer.  It will only work once per stream object.  It's possible return
- * values are 1 for sucess, -1 for invalid DMA channel, -2 for invalid DMA mode, -3 for inability to allocate enough buffer pages and
- * 0 for all other errors. */
-EDI_DEFVAR  int32_t (*init_dma_stream)(object_pointer stream, uint32_t channel, uint32_t mode, uint32_t buffer_pages);
-/*! \brief int32_t EDI-STREAM-DMA.transmit(data_pointer *anchor,unsigned int32 num_bytes,bool sending);
- *
- * Pointer to the dma_stream_transmit() method of class EDI-STREAM-DMA, which transmits the given number of bytes of data through
- * the DMA stream to/from the given anchor (either source or destination), in the given direction.  It returns 1 on success, -1 on
- * an uninitialized or invalid DMA stream object, -2 when the anchor was NULL or otherwise invalid, -3 if the DMA stream can't
- * transmit in the given direction, and 0 for all other errors. */
-EDI_DEFVAR int32_t (*dma_stream_transmit)(object_pointer stream, data_pointer anchor, uint32_t num_bytes, bool sending);
-#endif
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/edi_interrupts.h b/KernelLand/Modules/Interfaces/EDI/edi/edi_interrupts.h
deleted file mode 100644 (file)
index ef2ffc9..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef EDI_INTERRUPTS_H
-
-/* Copyright (c)  2006  Eli Gottlieb.
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-#define EDI_INTERRUPTS_H
-
-/*! \file edi_interrupts.h
- * \brief Declaration and description of EDI's interrupt handling class.
- *
- * Data structures and algorithms this header represents:
- *     DATA STRUCTURE AND ALGORITHM: INTERRUPT OBJECTS - The class EDI-INTERRUPT encapsulates the handling of machine interrupts.
- * It is initialized with an interrupt number to handle and a handler routine to call when that interrupt occurs.  Only a couple of
- * guarantees are made to the driver regarding the runtime's implementation of interrupt handling: 1) That the driver's handler is
- * called for every time the interrupt associated with a valid and initialized interrupt object occurs, in the order of the
- * occurences, 2) That the runtime handle the architecture-specific (general to the entire machine, not just this device)
- * end-of-interrupt code when the driver is called without first returning from the machine interrupt.  Note that the runtime hands
- * out interrupt numbers at its own discretion and policy. */
-
-#include "edi_objects.h"
-
-/*! \brief Macro constant containing the name of the interrupt class
- */
-#define INTERRUPTS_CLASS       "EDI-INTERRUPT"
-/*! \brief The name of EDI's interrupt-handling class.
- *
- * An edi_string_t holding the name of the runtime-implemented interrupt object class.  It's value is "EDI-INTERRUPT". */
-#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI)
-const edi_string_t interrupts_class = INTERRUPTS_CLASS;
-#else
-extern const edi_string_t interrupts_class;
-#endif
-
-/*! \brief A pointer to an interrupt handling function.
- *
- * A pointer to a function called to handle interrupts.  Its unsigned int32_t parameter is the interrupt number that is being
- * handled. */
-typedef void (*interrupt_handler_t)(uint32_t interrupt_number);
-
-#ifndef IMPLEMENTING_EDI
-/*! \brief Initializes an interrupt object with an interrupt number and a pointer to a handler function.
- *
- * A pointer to the init_interrupt() method of class EDI-INTERRUPT.  This method initializes a newly-created interrupt object with an
- * interrupt number and a pointer to the driver's handler of type interrupt_handler_t.  It can only be called once per object, and
- * returns 1 on success, fails with -1 when the interrupt number is invalid or unacceptable to the runtime, fails with -2 when the
- * pointer to the driver's interrupt handler is invalid, and fails with -3 for all other errors. */
-EDI_DEFVAR int32_t (*init_interrupt)(object_pointer interrupt, uint32_t interrupt_number, interrupt_handler_t handler);
-/*! \brief Get this interrupt object's interrupt number. */
-EDI_DEFVAR uint32_t (*interrupt_get_irq)(object_pointer interrupt);
-/*! \brief Set a new handler for this interrupt object. */
-EDI_DEFVAR void (*interrupt_set_handler)(object_pointer interrupt, interrupt_handler_t handler);
-/*! \brief Return from this interrupt, letting the runtime run any necessary End-Of-Interrupt code.
- *
- * A pointer to the interrupt_return() method of class EDI-INTERRUPT.  This method returns from the interrupt designated by the
- * calling interrupt object.  If there is a machine-wide end-of-interrupt procedure and the driver was called during the handling of
- * the machine interrupt (as opposed to delaying the handling and letting the runtime EOI), the runtime runs it during this method.
- * This method has no return value, since once it's called control leaves the calling thread. */
-EDI_DEFVAR void (*interrupt_return)(object_pointer interrupt);
-#endif
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/edi_memory_mapping.h b/KernelLand/Modules/Interfaces/EDI/edi/edi_memory_mapping.h
deleted file mode 100644 (file)
index ba8dff3..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef EDI_MEMORY_MAPPING_H
-
-/* Copyright (c)  2006  Eli Gottlieb.
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-#define EDI_MEMORY_MAPPING_H
-
-/*! \file edi_memory_mapping.h
- * \brief Declaration and description of EDI's class for mapping physical pages into the driver's address space.
- *
- * Data structures and algorithms this header represents:
- *     ALGORITHM: MEMORY MAPPINGS - Memory mapping objects of the class EDI-MEMORY-MAPPING are used to give virtual (driver-visible)
- * addresses to sections of physical memory.  These can either be memory mappings belonging to hardware devices or plain RAM which
- * the driver wants page-aligned.  A memory mapping object is initialized with the physical address for the memory mapping and the
- * number of pages the mapping takes up, or simply the desired length of the a physically contiguous buffer in pages.  The class's
- * two methods map the section of memory into and out of the driver's virtual address space. */
-
-#include "edi_objects.h"
-
-/*! \brief The name of EDI's memory mapping class.
- *
- * An edi_string_t with the name of the memory mapping class, "EDI-MEMORY-MAPPING". */
-#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI)
-const edi_string_t memory_mapping_class = "EDI-MEMORY-MAPPING";
-#else
-extern const edi_string_t memory_mapping_class;
-#endif
-
-/*! \brief Flag representing Strong Uncacheable caching method. */
-#define CACHING_STRONG_UNCACHEABLE 0
-/*! \brief Flag representing Uncacheable caching method. */
-#define CACHING_UNCACHEABLE 1
-/*! \brief Flag representing Write combining caching method. */
-#define CACHING_WRITE_COMBINING 2
-/*! \brief Flag representing Write Through caching method. */
-#define CACHING_WRITE_THROUGH 3
-/*! \brief Flag representing Write Back caching method. */
-#define CACHING_WRITE_BACK 3
-/*! \brief Flag representing Write Protected caching method. */
-#define CACHING_WRITE_PROTECTED 3
-
-#ifndef IMPLEMENTING_EDI
-/*! \brief Initialize an EDI-MEMORY-MAPPING object with a physical address range.
- *
- * This method takes the start_physical_address of a memory mapping and the number of pages in that mapping and uses these arguments
- * to initialize an EDI-MEMORY-MAPPING object.  It can only be called once per object.  It returns 1 when successful, -1 when an
- * invalid physical address is given (one that the runtime knows is neither a physical memory mapping belonging to a device nor
- * normal RAM), -2 when the number of pages requested is bad (for the same reasons as the starting address can be bad), and 0 for
- * all other errors. 
- *
- * Note that this method can't be invoked on an object which has already initialized via init_memory_mapping_with_pages(). */
-EDI_DEFVAR int32_t (*init_memory_mapping_with_address)(object_pointer mapping, data_pointer start_physical_address, uint32_t pages);
-/*! \brief Initialize an EDI-MEMORY-MAPPING object by requesting a number of new physical pages.
- *
- * This method takes a desired number of physical pages for a memory mapping, and uses that number to initialize an
- * EDI-MEMORY-MAPPING object by creating a buffer of contiguous physical pages.  It can only be called once per object.  It returns
- * 1 when successful, -1 when the request for pages cannot be fulfilled, and 0 for all other errors.
- *
- * Note that this method cannot be called if init_memory_mapping_with_address() has already been used on the given object. */
-EDI_DEFVAR int32_t (*init_memory_mapping_with_pages)(object_pointer mapping, uint32_t pages);
-/*! \brief Map the memory-mapping into this driver's visible address space.
- *
- * This asks the runtime to map a given memory mapping into the driver's virtual address space.  Its parameter is the address of a
- * data_pointer to place the virtual address of the mapping into.  This method returns 1 on success, -1 on an invalid argument, -2
- * for an uninitialized object, and 0 for all other errors. */
-EDI_DEFVAR int32_t (*map_in_mapping)(object_pointer mapping, data_pointer *address_mapped_to);
-/*! \brief Unmap the memory mapping from this driver's visible address space.
- *
- * This method tries to map the given memory mapping out of the driver's virtual address space.  It returns 1 for success, -1
- * for an uninitialized memory mapping object, -2 if the mapping isn't mapped into the driver's address space already, and 0
- * for all other errors. */
-EDI_DEFVAR int32_t (*map_out_mapping)(object_pointer mapping);
-
-/*! \brief Set the caching flags for a memory mapping. */
-EDI_DEFVAR void (*mapping_set_caching_method)(object_pointer mapping, uint32_t caching_method);
-/*! \brief Get the current caching method for a memory mapping. */
-EDI_DEFVAR uint32_t (*mapping_get_caching_method)(object_pointer mapping);
-/*! \brief Flush write-combining buffers on CPU to make sure changes to memory mapping actually get written.  Only applies to a Write Combining caching method (I think.).*/
-EDI_DEFVAR void (*flush_write_combining_mapping)(object_pointer mapping);
-#endif
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/edi_objects.h b/KernelLand/Modules/Interfaces/EDI/edi/edi_objects.h
deleted file mode 100644 (file)
index 0e47951..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-#ifndef EDI_OBJECTS_H
-
-/* Copyright (c)  2006  Eli Gottlieb.
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-#define EDI_OBJECTS_H
-
-/*! \file edi_objects.h
- * \brief The header file for basic EDI types and the object system.
- *
- * This file contains declarations of EDI's primitive data types, as well as structures and functions for with the object system.
- * It represents these data structures and algorithms:
- * 
- *     DATA STRUCTURE: THE CLASS LIST - EDI implementing runtime's must keep an internal list of classes implemented by the runtime
- *     and separate lists of classes implemented by each driver.  Whoever implements a class is said to "own" that class.  The
- *     internal format of this list is up to the runtime coders, but it must be possible to recreate the original list of
- *     edi_class_declaration structures the driver declared to the runtime from it.  This list is declared to the runtime in an
- *     initialization function in the header edi.h.  The object_class member of an edi_object_metadata structure must point to that
- *     object's class's entry in this list.
- *     
- *     ALGORITHM AND DATA STRUCTURE: CLASSES AND INHERITANCE - Classes are described using edi_class_declaration_t structures and
- *     follow very simple rules.  All data is private and EDI provides no way to access instance data, so there are no member
- *     variable declarations.  However, if the data isn't memory-protected (for example, driver data on the driver heap) EDI allows
- *     the possibility of pointer access to data, since runtime and driver coders could make use of that behavior.  Classes may have
- *     one ancestor by declaring so in their class declaration structure, and if child methods are different then parent methods
- *     the children always override their parents.  An EDI runtime must also be able to check the existence and ownership of a given
- *     class given its name in an edi_string_t.
- *     
- *     ALGORITHM: OBJECT CREATION AND DESTRUCTION - An EDI runtime should be able to call the constructor of a named class, put the
- *     resulting object_pointer into an edi_object_metadata_t and return that structure.  The runtime should also be able to call an
- *     object's class's destructor when given a pointer to a valid edi_metadata_t for an already-existing object.  Data equivalent
- *     to an edi_object_metadata_t should also be tracked by the runtime for every object in existence in case of sudden EDI shutdown
- *     (see edi.h).
- *
- *     ALGORITHM: RUNTIME TYPE INFORMATION - When passed the data_pointer member of an edi_object_metadata_t to a valid object, an
- *     EDI runtime must be able to return an edi_string_t containing the name of that object's class and to return function_pointers
- *     to methods when the required information to find the correct method is given by calling a class's method getting function.*/
-
-/* If the EDI headers are linked with the standard C library, they use its type definitions.  Otherwise, equivalent definitions are
- * made.*/
-#if __STDC_VERSION__ == 199901L
-# include <stdbool.h>
-# include <stdint.h>
-#else
-# ifndef NULL
-#  define      NULL    ((void*)0)
-# endif
-typedef unsigned char bool;
-# define true 1
-# define false 0
-typedef char int8_t;
-typedef short int16_t;
-typedef long int32_t;
-typedef long long int64_t;
-typedef unsigned char  uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned long  uint32_t;
-typedef unsigned long long     uint64_t;
-#endif
-
-/*! \brief Define a variable in the header
- */
-#ifdef EDI_MAIN_FILE
-# define EDI_DEFVAR
-#else
-# define EDI_DEFVAR    extern
-#endif
-
-/*! \brief A pointer to the in-memory instance of an object.
- *
- * This type is sized just like a general C pointer type (whatever*) for the target architecture.  It's passed as a first parameter
- * to all methods, thus allowing EDI classes to be implemented as C++ classes and providing some protection from confusing objects
- * with normal pointers.  Equivalent to a C++ this pointer or an Object Pascal Self argument. */
-typedef void *object_pointer;
-/*! \brief A basic pointer type pointing to arbitrary data in an arbitrary location. */
-typedef void *data_pointer;
-/*! \brief A basic function pointer type.
- *
- * A pointer to a piece of code which can be called and return to its caller, used to distinguish between pointers to code and
- * pointers to data.  Its size is hardware-dependent. */
-typedef void (*function_pointer)(void);
-/*! \brief The length of an EDI string without its null character. */
-#define EDI_STRING_LENGTH 31
-/*! \brief A type representing a 31-character long string with a terminating NULL character at the end.  All of EDI uses this type
- * for strings.
- *
- * A null-terminated string type which stores characters in int8s.  It allows for 31 characters in each string, with the final
- * character being the NULL terminator.  Functions which use this type must check that its final character is NULL, a string which
- * doesn't not have this property is invalid and insecure.  I (the author of EDI) know and understand that this form of a string
- * suffers from C programmer's disease, but I can't use anything else without either making string use far buggier or dragging
- * everyone onto a better language than C.  */
-typedef int8_t edi_string_t[0x20];
-/*! \brief A type representing a pointer form of #edi_string_t suitable for function returns
- */
-typedef int8_t *edi_string_ptr_t;
-
-/*! \var EDI_BASE_TYPES
- * \brief A constant array of edi_string_t's holding every available EDI primitive type. */
-/*! \var EDI_TYPE_MODIFIERS
- * \brief A constant array of edi_string_t's holding available modifiers for EDI primitive types. */
-#ifdef IMPLEMENTING_EDI
- const edi_string_t EDI_BASE_TYPES[9] = {"void","bool","int8_t","int16_t","int32_t","int64_t","function_pointer","intreg","edi_string_t"};
- const edi_string_t EDI_TYPE_MODIFIERS[2] = {"pointer","unsigned"};
-#else
- //extern const edi_string_t EDI_BASE_TYPES[9] = {"void","bool","int8_t","int16_t","int32_t","int64_t","function_pointer","intreg", "edi_string_t"};
- //extern const edi_string_t EDI_TYPE_MODIFIERS[2] = {"pointer","unsigned"};
- extern const edi_string_t EDI_BASE_TYPES[9];
- extern const edi_string_t EDI_TYPE_MODIFIERS[2];
-#endif
-
-/*! \struct edi_object_metadata_t
- * \brief A packed structure holding all data to identify an object to the EDI object system. */
-typedef struct {
-       /*! \brief Points to the instance data of the object represented by this structure.
-        *
-        * An object_pointer to the object this structure refers to.  The this pointer, so to speak. */
-       object_pointer object;
-       /*! \brief Points the internal record kept by the runtime describing the object's class.
-        *
-        * Points to wherever the runtime has stored the class data this object was built from.  The class data doesn't need to be
-        * readable to the driver, and so this pointer can point to an arbitrary runtime-reachable location. */
-       data_pointer object_class;
-} edi_object_metadata_t;
-
-/*! \struct edi_variable_declaration_t
- * \brief The data structure used to describe a variable declaration to the EDI object system.
- *
- * The data structure used to describe a variable declaration to the EDI object system.  The context of the declaration depends on
- * where the data structure appears, ie: alone, in a class declaration, in a parameter list, etc. */
-typedef struct {
-       /*! \brief The type of the declared variable. 
-        *
-        * The type of the variable, which must be a valid EDI primitive type as specified in the constant EDI_BASE_TYPES and
-        * possibly modified by a modifier specified in the constant EDI_TYPE_MODIFIERS. */
-       edi_string_t type;
-       /*! \brief The name of the declared variable. */
-       edi_string_t name;
-       /*! \brief Number of array entries if this variable is an array declaration. 
-        *
-        * An int32_t specifying the number of variables of 'type' in the array 'name'.  For a single variable this value should
-        * simply be set to 1, for values greater than 1 a packed array of contiguous variables is being declared, and a value of 0
-        * is invalid. */
-       int32_t array_length;
-} edi_variable_declaration_t;
-
-/*! \struct edi_function_declaration_t
- * \brief The data structure used to declare a function to the EDI object system. */
-typedef struct {
-       /*! \brief The return type of the function.  The same type rules which govern variable definitions apply here. */
-       edi_string_t return_type;
-       /*! \brief The name of the declared function. */
-       edi_string_t name;
-       /*! \brief The version number of the function, used to tell different implementations of the same function apart. */
-       uint32_t version;
-       /*! \brief The number of arguments passed to the function.
-        *
-        * The number of entries in the member arguments that the object system should care about.  Caring about less misses
-        * parameters to functions, caring about more results in buffer overflows. */
-       uint32_t num_arguments;
-       /*! \brief An array of the declared function's arguments.
-        *
-        * A pointer to an array num_arguments long containing edi_variable_declaration_t's for each argument to the declared
-        * function.*/
-       edi_variable_declaration_t *arguments;
-       /*!\brief A pointer to the declared function's code in memory. */
-       function_pointer code;
-} edi_function_declaration_t;
-
-/*! \brief A pointer to a function for constructing instances of a class.
- *
- * A pointer to a function which takes no parameters and returns an object_pointer pointing to the newly made instance of a class.
- * It is the constructor's responsibility to allocate memory for the new object.  Each EDI class needs one of these. */
-typedef object_pointer (*edi_constructor_t)(void);
-/*! \brief A pointer to a function for destroying instances of a class.
- *
- * A pointer to a function which takes an object_pointer as a parameter and returns void.  This is the destructor counterpart to a
- * class's edi_constructor_t, it destroys the object pointed to by its parameter and frees the object's memory.  Every class must
- * have one */
-typedef void (*edi_destructor_t)(object_pointer);
-
-/*! \brief Information the driver must give the runtime about its classes so EDI can construct them and call their methods.
- *
- * A structure used to declare a class to an EDI runtime so instances of it can be constructed by the EDI object system. */
-typedef struct {
-       /*! \brief The name of the class declared by the structure. */
-       edi_string_t name;
-       /*! \brief The version of the class.  This number is used to tell identically named but differently
-        * implemented classes apart.*/
-       uint32_t version;
-       /*! \brief The number of methods in the 'methods' function declaration array. */
-       uint32_t num_methods;
-       /*! \brief An array of edi_function_declaration_t declaring the methods of this class. */
-       edi_function_declaration_t *methods;
-       /*! \brief Allocates the memory for a new object of the declared class and constructs the object.  Absolutely required.*/
-       edi_constructor_t constructor;
-       /*! \brief Destroys the given object of the declared class and frees its memory. Absolutely required. */
-       edi_destructor_t destructor;
-       /*! \brief A pointer to another EDI class declaration structure specifying the declared class's parent class. 
-        *
-        * Points to a parent class declared in another class declaration.  It can be NULL to mean this class has no parent. */
-       struct edi_class_declaration_t *parent;
-} edi_class_declaration_t;
-
-/*! \brief Checks the existence of the named class.
- *
- * This checks for the existence on THE CLASS LIST of the class named by its edi_string_t parameter and returns a signed int32_t.  If
- * the class isn't found (ie: it doesn't exist as far as EDI is concerned) -1 is returned, if the class is owned by the driver
- * (implemented by the driver and declared to the runtime by the driver) 0, and if the class is owned by the runtime (implemented by
- * the runtime) 1. */
-int32_t check_class_existence(edi_string_t class_name);
-/*! \brief Constructs an object of the named class and returns its object_pointer and a data_pointer to its class data.
- *
- * Given a valid class name in an edi_string_t this function constructs the specified class and returns an edi_metadata_t describing
- * the new object as detailed in OBJECT CREATION AND DESTRUCTION.  If the construction fails it returns a structure full of NULL
- * pointers. */
-edi_object_metadata_t construct_object(edi_string_t class_name);
-/*! \brief Destroys the given object using its class data.
- *
- * As specified in OBJECT CREATION AND DESTRUCTION this function should destroy an object when given its valid edi_metadata_t.  The
- * destruction is accomplished by calling the class's destructor. */
-void destroy_object(edi_object_metadata_t object);
-/*! \brief Obtains a function pointer to a named method of a given class. 
- *
- * When given a valid data_pointer object_class from an edi_object_metadata_t and an edi_string_t representing the name of the
- * desired method retrieves a function_pointer to the method's machine code in memory.  If the desired method isn't found, NULL is
- * returned. */
-function_pointer get_method_by_name(data_pointer object_class,edi_string_t method_name);
-/*! \brief Obtains a function pointer to a method given by a declaration of the given class if the class's method matches the
- * declaration. 
- *
- * Works just like get_method_by_name(), but by giving an edi_function_declaration_t for the desired method instead of just its name.
- * Performs detailed checking against THE CLASS LIST to make sure that the method returned exactly matches the declaration passed
- * in. */
-function_pointer get_method_by_declaration(data_pointer object_class,edi_function_declaration_t declaration);
-
-/* Runtime typing information. */
-/*! \brief Returns the name of the class specified by a pointer to class data. 
- *
- * Given the data_pointer to an object's class data as stored in an edi_object_metadata_t retrieves the name of the object's class
- * and returns it in an edi_string_t. */
-edi_string_ptr_t get_object_class(data_pointer object_class);
-/*! \brief Returns the name of a class's parent class.
- *
- * When given an edi_string_t with a class name in it, returns another edi_string_t containing the name of the class's parent, or an
- * empty string. */
-edi_string_ptr_t get_class_parent(edi_string_t some_class);
-/*! \brief Returns the internal class data of a named class (if it exists) or NULL.
- *
- * When given an edi_string_t with a valid class name in it, returns a pointer to the runtime's internal class data for that class.
- * Otherwise, it returns NULL. */
-data_pointer get_internal_class(edi_string_t some_class);
-
-#endif 
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/edi_port_io.h b/KernelLand/Modules/Interfaces/EDI/edi/edi_port_io.h
deleted file mode 100644 (file)
index a2a1773..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef EDI_PORT_IO_H
-
-/* Copyright (c)  2006  Eli Gottlieb.
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-/* Modified by thePowersGang (John Hodge)
- * - Surround variable definitions with an #ifdef IMPLEMENTING_EDI
- */
-
-#define EDI_PORT_IO_H
-
-/*! \file edi_port_io.h
- * \brief Declaration and description of EDI's port I/O class.
- *
- * Data structures and algorithms this header represents:
- *
- *     DATA STRUCTURE AND ALGORITHM: PORT I/O OBJECTS - A class named "EDI-IO-PORT" is defined as an encapsulation of the port I/O
- * used on some machine architectures.  Each object of this class represents a single I/O port which can be read from and written to
- * in various sizes.  Each port can be held by one object only at a time. */
-
-#include "edi_objects.h"
-
-/*! \brief Macro to create methods for reading from ports.
- *
- * This macro creates four similar methods, differing in the size of the type they read from the I/O port held by the object.  Their
- * parameter is a pointer to the output type, which is filled with the value read from the I/O port.  They return 1 for success, -1
- * for an uninitialized I/O port object, and 0 for other errors. */
-#define port_read_method(type,name) int32_t (*name)(object_pointer port_object, type *out)
-/*! \brief Macro to create methods for writing to ports.
- *
- * This macro creates four more similar methods, differing in the size of the type they write to the I/O port held by the object.
- * Their parameter is the value to write to the port.  They return 1 for success, -1 for an uninitialized I/O port object and 0 for
- * other errors. */
-#define port_write_method(type,name) int32_t (*name)(object_pointer port_object, type in)
-
-/*! \brief Name of EDI I/O port class. (Constant)
- *
- * A CPP constant with the value of #io_port_class */
-#define        IO_PORT_CLASS   "EDI-IO-PORT"
-/*! \brief Name of EDI I/O port class.
- *
- * An edi_string_t containing the class name "EDI-IO-PORT". */
-#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI)
-const edi_string_t io_port_class = IO_PORT_CLASS;
-#else
-extern const edi_string_t io_port_class;
-#endif
-
-#ifndef IMPLEMENTING_EDI
-/*! \brief int32_t EDI-IO-PORT.init_io_port(unsigned int16_t port);
- *
- * This method takes an unsigned int16_t representing a particular I/O port and initializes the invoked EDI-IO-PORT object with it.
- * The method returns 1 if successful, -1 if the I/O port could not be obtained for the object, and 0 for all other errors. */
-EDI_DEFVAR int32_t (*init_io_port)(object_pointer port_object, uint16_t port);
-/*! \brief Get the port number from a port object. */
-EDI_DEFVAR uint16_t (*get_port_number)(object_pointer port);
-/*! \brief Method created by port_read_method() in order to read bytes (int8s) from I/O ports. */
-EDI_DEFVAR int32_t (*read_byte_io_port)(object_pointer port_object, int8_t *out);
-/*! \brief Method created by port_read_method() in order to read words (int16s) from I/O ports. */
-EDI_DEFVAR int32_t (*read_word_io_port)(object_pointer port_object, int16_t *out);
-/*! \brief Method created by port_read_method() in order to read longwords (int32s) from I/O ports. */
-EDI_DEFVAR int32_t (*read_long_io_port)(object_pointer port_object, int32_t *out);
-/*! \brief Method created by port_read_method() in order to read long longwords (int64s) from I/O ports. */
-EDI_DEFVAR int32_t (*read_longlong_io_port)(object_pointer port_object,int64_t *out);
-/*! \brief Method of EDI-IO-PORT to read long strings of data from I/O ports.
- *
- * Reads arbitrarily long strings of data from the given I/O port.  Returns 1 for success, -1 for an uninitialized port object, -2
- * for a bad pointer to the destination buffer, and 0 for all other errors. */
-EDI_DEFVAR int32_t (*read_string_io_port)(object_pointer port_object, uint32_t data_length, uint8_t *out);
-/*! \brief Method created by port_write_method() in order to write bytes (int8s) to I/O ports. */
-EDI_DEFVAR int32_t (*write_byte_io_port)(object_pointer port_object, int8_t in);
-/*! \brief Method created by port_write_method() in order to write words (int16s) to I/O ports. */
-EDI_DEFVAR int32_t (*write_word_io_port)(object_pointer port_object, int16_t in);
-/*! \brief Method created by port_write_method() in order to write longwords (int32s) to I/O ports. */
-EDI_DEFVAR int32_t (*write_long_io_port)(object_pointer port_object, int32_t in);
-/*! \brief Method created by port_write_method() in order to write long longwords (int64s) to I/O ports. */
-EDI_DEFVAR int32_t (*write_longlong_io_port)(object_pointer port_object, int64_t in);
-/*! \brief Method of EDI-IO-PORT to write long strings of data to I/O ports.
- *
- * Writes arbitrarily long strings of data to the given I/O port.  Returns 1 for success, -1 for an uninitialized port object, -2
- * for a bad pointer to the source buffer, and 0 for all other errors. */
-EDI_DEFVAR int32_t (*write_string_io_port)(object_pointer port_object, uint32_t data_length, uint8_t *in);
-
-#endif // defined(IMPLEMENTING_EDI)
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/edi_pthreads.h b/KernelLand/Modules/Interfaces/EDI/edi/edi_pthreads.h
deleted file mode 100644 (file)
index c21fa75..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef EDI_PTHREADS
-
-/* Copyright (c)  2006  Eli Gottlieb.
- * Permission is granted to copy, distribute and/or modify this document
- * under the terms of the GNU Free Documentation License, Version 1.2
- * or any later version published by the Free Software Foundation;
- * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
- * Texts.  A copy of the license is included in the file entitled "COPYING". */
-
-#define EDI_PTHREADS
-/*!\file edi_pthreads.h
- * \brief A basic subset of POSIX Threads functionality, providing threading and thread synchronization.
- *
- * A very basic POSIX Threads interface.  Note that pthreads are not a class, because none of these calls really gels with
- * object-oriented programming.  Also, if drivers aren't processes or threads under the implementing operating system a small
- * threading system must be implemented in-runtime just to multiplex the pthreads of EDI drivers.  Sorry about that.
- *
- * Data structures and algorithms this header represents:
- *
- *     ALGORITHM AND DATA STRUCTURE: POSIX Threading - The runtime must provide enough of a POSIX threading interface to implement
- * the calls described here.  The actual multithreading must be performed by the runtime, and the runtime can implement that
- * multithreading however it likes as long as the given POSIX Threads subset works.  There is, however, a caveat: since the runtime
- * calls the driver like it would a library, the driver must perceive all calls made to it by the runtime as running under one thread.
- * From this thread the driver can create others.  Such behavior is a quirk of EDI, and does not come from the POSIX standard.
- * However, it is necessary to provide the driver with a thread for its own main codepaths.  For further details on a given POSIX
- * Threading routine, consult its Unix manual page. */
-
-#include "edi_objects.h"
-
-/* Placeholder type definitions.  Users of the PThreads interface only ever need to define pointers to these types. */
-/*!\brief Opaque POSIX Threading thread attribute type. */
-typedef void pthread_attr_t;
-/*!\brief Opaque POSIX Threading mutex (mutual exclusion semaphore) type. */
-typedef void pthread_mutex_t;
-/*!\brief Opaque POSIX Threading mutex attribute type. */
-typedef void pthread_mutex_attr_t;
-
-/*!\struct sched_param
- * \brief POSIX Threading scheduler parameters for a thread. */
-typedef struct {
-       /*!\brief The priority of the thread. */
-       int32_t sched_priority;
-} sched_param;
-
-/*!\brief POSIX Threading thread identifier. */
-typedef uint32_t pthread_t;
-/*!\brief POSIX Threading thread function type.
- *
- * A function pointer to a thread function, with the required signature of a thread function.  A thread function takes one untyped
- * pointer as an argument and returns an untyped pointer.  Such a function is a thread's main routine: it's started with the thread,
- * and the thread exits if it returns. */
-typedef void *(*pthread_function_t)(void*);
-
-/*!\brief Insufficient resources. */
-#define EAGAIN -1
-/*!\brief Invalid parameter. */
-#define EINVAL -2
-/*!\brief Permission denied. */
-#define EPERM -3
-/*!\brief Operation not supported. */
-#define ENOTSUP -4
-/*!\brief Priority scheduling for POSIX/multiple schedulers is not implemented. */
-#define ENOSYS -5
-/*!\brief Out of memory. */
-#define ENOMEM -6
-/*!\brief Deadlock.  Crap. */
-#define EDEADLK -7
-/*!\brief Busy.  Mutex already locked. */
-#define EBUSY -8
-
-/*!\brief Scheduling policy for regular, non-realtime scheduling.  The default. */
-#define SCHED_OTHER 0
-/*!\brief Real-time, first-in first-out scheduling policy.  Requires special (superuser, where such a thing exists) permissions. */
-#define SCHED_FIFO 1
-/*!\brief Real-time, round-robin scheduling policy.  Requires special (superuser, where such a thing exists) permissions. */
-#define SCHED_RR 0
-
-/*!\brief Creates a new thread with the given attributes, thread function and arguments, giving back the thread ID of the new
- * thread.
- *
- * pthread_create() creates a new thread of control that executes concurrently with the calling thread.  The new thread applies the
- * function start_routine, passing it arg as its argument.  The attr argument specifies thread attributes to apply to the new thread;
- * it can also be NULL for the default thread attributes (joinable with default scheduling policy).  On success this function returns
- * 0 and places the identifier of the new thread into thread_id.  On an error, pthread_create() can return EAGAIN if insufficient
- * runtime resources are available to create the requested thread, EINVAL a value specified by attributes is invalid, or EPERM if the
- * caller doesn't have permissions to set the given attributes.
- *
- * For further information: man 3 pthread_create */
-int32_t pthread_create(pthread_t *thread_id, const pthread_attr_t *attributes, pthread_function_t thread_function, void *arguments);
-/*!\brief Terminates the execution of the calling thread.  The thread's exit code with by status, and this routine never returns. */
-void pthread_exit(void *status);
-/*!\brief Returns the thread identifier of the calling thread. */
-pthread_t pthread_self();
-/*!\brief Compares two thread identifiers.
- *
- * Determines of the given two thread identifiers refer to the same thread.  If so, returns non-zero.  Otherwise, 0 is returned. */
-int32_t pthread_equal(pthread_t thread1, pthread_t thread2);
-/*!\brief Used by the calling thread to relinquish use of the processor.  The thread then waits in the run queue to be scheduled
- * again. */
-void pthread_yield();
-
-/*!\brief Gets the scheduling policy of the given attributes.
- *
- * Places the scheduling policy for attributes into policy.  Returns 0 on success, EINVAL if attributes was invalid, and ENOSYS if
- * priority scheduling/multiple scheduler support is not implemented. */
-int32_t pthread_attr_getschedpolicy(const pthread_attr_t *attributes, int32_t *policy);
-/*!\brief Sets the scheduling policy of the given attributes.
- *
- * Requests a switch of scheduling policy to policy for the given attributes.  Can return 0 for success, EINVAL if the given policy
- * is not one of SCHED_OTHER, SCHED_FIFO or SCHED_RR or ENOTSUP if policy is either SCHED_FIFO or SCHED_RR and the driver is not
- * running with correct privileges. */
-int32_t pthread_attr_setschedpolicy(pthread_attr_t *attributes, int32_t policy);
-
-/*!\brief Gets the scheduling paramaters (priority) from the given attributes.
- *
- * On success, stores scheduling parameters in param from attributes, and returns 0.  Otherwise, returns non-zero error code, such
- * as EINVAL if the attributes object is invalid. */
-int32_t pthread_attr_getschedparam(const pthread_attr_t *attributes, sched_param *param);
-/*!\brief Sets the scheduling parameters (priority) of the given attributes.
- *
- * Requests that the runtime set the scheduling parameters (priority) of attributes from param. Returns 0 for success, EINVAL for an
- * invalid attributes object, ENOSYS when multiple schedulers/priority scheduling is not implemented, and ENOTSUP when the value of
- * param isn't supported/allowed. */
-int32_t pthread_attr_setschedparam(pthread_attr_t *attributes, const sched_param *param);
-
-/*!\brief The thread obtains its scheduling properties explicitly from its attributes structure. */
-#define PTHREAD_EXPLICIT_SCHED 1
-/*!\brief The thread inherits its scheduling properties from its parent thread. */
-#define PTHREAD_INHERIT_SCHED 0
-
-/*!\brief Returns the inheritsched attribute of the given attributes.
- *
- * On success, returns 0 and places the inheritsched attribute from attributes into inherit.  This attribute specifies where the
- * thread's scheduling properites shall come from, and can be set to PTHREAD_EXPLICIT_SCHED or PTHREAD_INHERIT_SCHED.  On failure it
- * returns EINVAL if attributes was invalid or ENOSYS if multiple schedulers/priority scheduling isn't implemented. */
-int32_t pthread_attr_getinheritsched(const pthread_attr_t *attributes, int32_t *inherit);
-/*!\brief Sets the inheritsched attribute of the given attributes.
- *
- * On success, places inherit into the inheritsched attribute of attributes and returns 0.  inherit must either contain
- * PTHREAD_EXPLICIT_SCHED or PTHREAD_INHERIT_SCHED.  On failure, this routine returns EINVAL if attributes is invalid, ENOSYS when
- * multiple schedulers/priority scheduling isn't implemented, and ENOSUP if the inheritsched attribute isn't supported. */
-int32_t pthread_attr_setinheritsched(pthread_attr_t *attributes, int32_t inherit);
-
-/*!\brief Creates a new POSIX Threads mutex, which will initially be unlocked.
- *
- * Creates a new mutex with the given attributes.  If attributes is NULL, the default attributes will be used.  The mutex starts out
- * unlocked.  On success, the new mutex resides in the mutex structure pointed to by mutex, and this routine routines 0.  On failure,
- * it returns EAGAIN if the system lacked sufficient non-memory resources to initialize the mutex, EBUSY if the given mutex is
- * already initialized and in use, EINVAL if either parameter is invalid, and ENOMEM if the system lacks the memory for a new
- * mutex.  Note: All EDI mutexes are created with the default attributes, and are of type PTHREAD_MUTEX_ERRORCHECK.  This means
- * undefined behavior can never result from an badly placed function call. */
-int32_t pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutex_attr_t *attributes);
-/*!\brief Locks the given mutex.
- *
- * Locks the given mutex.  If the mutex is already locked, blocks the calling thread until it can acquire the lock.  When this
- * routine returns successfully, it will return 0 and the calling thread will own the lock of the mutex.  If the call fails, it can
- * return EINVAL when mutex is invalid or EDEADLK if the calling thread already owns the mutex. */
-int32_t pthread_mutex_lock(pthread_mutex_t *mutex);
-/*!\brief Unlocks the given mutex.
- *
- * Unlocks the given mutex, returning 0 on success.  On failure, it can return EINVAL when mutex is invalid or EPERM when the
- * calling thread doesn't own the mutex. */
-int32_t pthread_mutex_unlock(pthread_mutex_t *mutex);
-/*!\brief Tries to lock the given mutex, returning immediately even if the mutex is already locked.
- *
- * Attempts to lock the given mutex, but returns immediately if it can't acquire a lock.  Returns 0 when it has acquired a lock,
- * EBUSY if the mutex is already locked, or EINVAL if mutex is invalid. */
-int32_t pthread_mutex_trylock(pthread_mutex_t *mutex);
-/*!\brief Destroys the given mutex, or at least the internal structure of it. 
- *
- * Deletes the given mutex, making mutex invalid until it should be initialized by pthread_mutex_init().  Returns 0 on success,
- * EINVAL when mutex is invalid, or EBUSY when mutex is locked or referenced by another thread. */
-int32_t pthread_mutex_destroy (pthread_mutex_t *mutex);
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi/helpers.h b/KernelLand/Modules/Interfaces/EDI/edi/helpers.h
deleted file mode 100644 (file)
index d7bc138..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef HELPERS_H
-
-#define HELPERS_H
-
-#include <edi.h>
-
-// Locally Defined
-bool edi_string_equal(edi_string_t x,edi_string_t y);
-bool descends_from(data_pointer object_class,edi_string_t desired_class);
-data_pointer get_actual_class(edi_string_t ancestor,int32_t num_objects,edi_object_metadata_t *objects);
-
-// Local Copy/set
-void *memcpyd(void *dest, void *src, unsigned int count);
-
-// Implementation Defined Common functions
-void *memcpy(void *dest, void *src, unsigned int count);
-void *memmove(void *dest, void *src, unsigned int count);
-void *realloc(void *ptr, unsigned int size);
-
-#endif
diff --git a/KernelLand/Modules/Interfaces/EDI/edi_int.inc.c b/KernelLand/Modules/Interfaces/EDI/edi_int.inc.c
deleted file mode 100644 (file)
index 0ab3359..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * AcessOS EDI Interface
- * - IRQ Class
- * 
- * By John Hodge (thePowersGang)
- * 
- * This file has been released into the public domain.
- * You are free to use it as you wish.
- */
-#include "edi/edi.h"
-
-// === TYPES ===
-typedef struct {
-       uint16_t        State;  // 0: Unallocated, 1: Allocated, 2: Initialised, (Bit 0x8000 set if in heap)
-       uint16_t        Num;
-       interrupt_handler_t     Handler;
-} tEdiIRQ;
-
-// === PROTOTYPES ===
-void EDI_Int_IRQ_Handler(tRegs *Regs);
-
-// === GLOBALS ===
-tEdiIRQ        gEdi_IRQObjects[16];
-
-// === FUNCTIONS ===
-/**
- * \fn object_pointer Edi_Int_IRQ_Construct(void)
- * \brief Creates a new IRQ Object
- * \return     Pointer to object
- */
-object_pointer Edi_Int_IRQ_Construct(void)
-{
-        int    i;
-       // Search for a free irq
-       for( i = 0; i < 16; i ++ )
-       {
-               if(gEdi_IRQObjects[i].State)    continue;
-               gEdi_IRQObjects[i].State = 1;
-               gEdi_IRQObjects[i].Num = 0;
-               gEdi_IRQObjects[i].Handler = NULL;
-               return &gEdi_IRQObjects[i];
-       }
-       return NULL;
-}
-
-/**
- * \fn void Edi_Int_IRQ_Destruct(object_pointer Object)
- * \brief Destruct an IRQ Object
- * \param Object       Object to destroy
- */
-void Edi_Int_IRQ_Destruct(object_pointer Object)
-{
-       tEdiIRQ *obj;
-       
-       VALIDATE_PTR(Object,);
-       obj = GET_DATA(Object);
-       
-       if( !obj->State )       return;
-       
-       if( obj->Handler )
-               irq_uninstall_handler( obj->Num );
-       
-       if( obj->State & 0x8000 ) {     // If in heap, free
-               free(Object);
-       } else {        // Otherwise, mark as unallocated
-               obj->State = 0;
-       }
-}
-
-/**
- * \fn int32_t Edi_Int_IRQ_InitInt(object_pointer Object, uint16_t Num, interrupt_handler_t Handler)
- * \brief Initialises an IRQ
- * \param Object       Object Pointer (this)
- * \param Num  IRQ Number to use
- * \param Handler      Callback for IRQ
- */
-int32_t        Edi_Int_IRQ_InitInt(object_pointer Object, uint16_t Num, interrupt_handler_t Handler)
-{
-       tEdiIRQ *obj;
-       
-       //LogF("Edi_Int_IRQ_InitInt: (Object=0x%x, Num=%i, Handler=0x%x)\n", Object, Num, Handler);
-       
-       VALIDATE_PTR(Object,0);
-       obj = GET_DATA(Object);
-       
-       if( !obj->State )       return 0;
-       
-       if(Num > 15)    return 0;
-       
-       // Install the IRQ if a handler is passed
-       if(Handler) {
-               if( !irq_install_handler(Num, Edi_Int_IRQ_Handler) )
-                       return 0;
-               obj->Handler = Handler;
-       }
-       
-       obj->Num = Num;
-       obj->State &= ~0x3FFF;
-       obj->State |= 2;        // Set initialised flag
-       return 1;
-}
-
-/**
- * \fn uint16_t Edi_Int_IRQ_GetInt(object_pointer Object)
- * \brief Returns the irq number associated with the object
- * \param Object       IRQ Object to get number from
- * \return IRQ Number
- */
-uint16_t Edi_Int_IRQ_GetInt(object_pointer Object)
-{
-       tEdiIRQ *obj;
-       
-       VALIDATE_PTR(Object,0);
-       obj = GET_DATA(Object);
-       
-       if( !obj->State )       return 0;
-       return obj->Num;
-}
-
-/**
- * \fn void EDI_Int_IRQ_SetHandler(object_pointer Object, interrupt_handler_t Handler)
- * \brief Set the IRQ handler for an IRQ object
- * \param Object       IRQ Object to alter
- * \param Handler      Function to use as handler
- */
-void EDI_Int_IRQ_SetHandler(object_pointer Object, interrupt_handler_t Handler)
-{
-       tEdiIRQ *obj;
-       
-       // Get Data Pointer
-       VALIDATE_PTR(Object,);
-       obj = GET_DATA(Object);
-       
-       // Sanity Check arguments
-       if( !obj->State )       return ;
-       
-       // Only register the mediator if it is not already
-       if( Handler && !obj->Handler )
-               if( !irq_install_handler(obj->Num, Edi_Int_IRQ_Handler) )
-                       return ;
-       obj->Handler = Handler;
-}
-
-/**
- * \fn void EDI_Int_IRQ_Return(object_pointer Object)
- * \brief Return from interrupt
- * \param Object       IRQ Object
- * \note Due to the structure of acess interrupts, this is a dummy
- */
-void EDI_Int_IRQ_Return(object_pointer Object)
-{
-}
-
-/**
- * \fn void Edi_Int_IRQ_Handler(struct regs *Regs)
- * \brief EDI IRQ Handler - Calls the handler 
- * \param Regs Register state at IRQ call
- */
-void Edi_Int_IRQ_Handler(struct regs *Regs)
-{
-        int    i;
-       for( i = 0; i < 16; i ++ )
-       {
-               if(!gEdi_IRQObjects[i].State)   continue;       // Unused, Skip
-               if(gEdi_IRQObjects[i].Num != Regs->int_no)      continue;       // Another IRQ, Skip
-               if(!gEdi_IRQObjects[i].Handler) continue;       // No Handler, Skip
-               gEdi_IRQObjects[i].Handler( Regs->int_no );     // Call Handler
-               return;
-       }
-}
-
-
-// === CLASS DECLARATION ===
-static edi_function_declaration_t      scEdi_Int_Functions_IRQ[] = {
-               {"int32_t", "init_interrupt", 1, 3, NULL, //scEdi_Int_Variables_IO[0],
-                       (function_pointer)Edi_Int_IRQ_InitInt
-                       },
-               {"uint32_t", "interrupt_get_irq", 1, 1, NULL, //scEdi_Int_Variables_IO[1],
-                       (function_pointer)Edi_Int_IRQ_GetInt
-                       },
-               {"void", "interrupt_set_handler", 1, 2, NULL, //scEdi_Int_Variables_IO[2],
-                       (function_pointer)Edi_Int_IRQ_GetInt
-                       },
-               {"void", "interrupt_return", 1, 1, NULL, //scEdi_Int_Variables_IO[3],
-                       (function_pointer)Edi_Int_IRQ_GetInt
-                       }
-       };
-static edi_class_declaration_t scEdi_Int_Class_IRQ = 
-       {
-               INTERRUPTS_CLASS, 1, 12,
-               scEdi_Int_Functions_IRQ,
-               Edi_Int_IRQ_Construct,
-               Edi_Int_IRQ_Destruct,
-               NULL
-       };
diff --git a/KernelLand/Modules/Interfaces/EDI/edi_io.inc.c b/KernelLand/Modules/Interfaces/EDI/edi_io.inc.c
deleted file mode 100644 (file)
index 8a6ef22..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * AcessOS EDI Interface
- * - IO Port Class
- * 
- * By John Hodge (thePowersGang)
- * 
- * This file has been released into the public domain.
- * You are free to use it as you wish.
- */
-#include "edi/edi.h"
-
-// === TYPES ===
-typedef struct {
-       uint16_t        State;  // 0: Unallocated, 1: Allocated, 2: Initialised, (Bit 0x8000 set if in heap)
-       uint16_t        Num;
-} tEdiPort;
-
-// === GLOBALS ===
-#define        NUM_PREALLOC_PORTS      128
-tEdiPort       gEdi_PortObjects[NUM_PREALLOC_PORTS];
-
-// === FUNCTIONS ===
-/**
- * \fn object_pointer Edi_Int_IO_Construct(void)
- * \brief Creates a new IO Port Object
- * \return     Pointer to object
- */
-object_pointer Edi_Int_IO_Construct(void)
-{
-       tEdiPort        *ret;
-        int    i;
-       // Search for a free preallocated port
-       for( i = 0; i < NUM_PREALLOC_PORTS; i ++ )
-       {
-               if(gEdi_PortObjects[i].State)   continue;
-               gEdi_PortObjects[i].State = 1;
-               gEdi_PortObjects[i].Num = 0;
-               return &gEdi_PortObjects[i];
-       }
-       // Else, use heap space
-       ret = malloc( sizeof(tEdiPort) );
-       ret->State = 0x8001;
-       ret->Num = 0;
-       return ret;
-}
-
-/**
- * \fn void Edi_Int_IO_Destruct(object_pointer Object)
- * \brief Destruct an IO Port Object
- * \param Object       Object to destroy
- */
-void Edi_Int_IO_Destruct(object_pointer Object)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object,);
-       obj = GET_DATA(Object);
-       
-       if(obj->State & 0x8000) {       // If in heap, free
-               free(Object);
-       } else {        // Otherwise, mark as unallocated
-               obj->State = 0;
-       }
-}
-
-/**
- * \fn int32_t Edi_Int_IO_InitPort(object_pointer Object, uint16_t Port)
- * \brief Initialises an IO Port
- * \param Object       Object Pointer (this)
- * \param Port Port Number to use
- */
-int32_t        Edi_Int_IO_InitPort(object_pointer Object, uint16_t Port)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       
-       if( !obj->State )       return 0;
-       obj->Num = Port;
-       obj->State &= ~0x3FFF;
-       obj->State |= 2;        // Set initialised flag
-       return 1;
-}
-
-/**
- * \fn uint16_t Edi_Int_IO_GetPortNum(object_pointer Object)
- * \brief Returns the port number associated with the object
- * \param Object       Port Object to get number from
- * \return Port Number
- */
-uint16_t Edi_Int_IO_GetPortNum(object_pointer Object)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       // Check if valid
-       if( !obj->State )       return 0;
-       // Return Port No
-       return obj->Num;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_ReadByte(object_pointer Object, uint8_t *out)
- * \brief Read a byte from an IO port
- * \param Object       Port Object
- * \param out  Pointer to put read data
- */
-int32_t Edi_Int_IO_ReadByte(object_pointer Object, uint8_t *out)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "inb %%dx, %%al" : "=a" (*out) : "d" ( obj->Num ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_ReadWord(object_pointer Object, uint16_t *out)
- * \brief Read a word from an IO port
- * \param Object       Port Object
- * \param out  Pointer to put read data
- */
-int32_t Edi_Int_IO_ReadWord(object_pointer Object, uint16_t *out)
-{
-       
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "inw %%dx, %%ax" : "=a" (*out) : "d" ( obj->Num ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_ReadDWord(object_pointer Object, uint32_t *out)
- * \brief Read a double word from an IO port
- * \param Object       Port Object
- * \param out  Pointer to put read data
- */
-int32_t Edi_Int_IO_ReadDWord(object_pointer Object, uint32_t *out)
-{
-       
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*out) : "d" ( obj->Num ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_ReadQWord(object_pointer Object, uint64_t *out)
- * \brief Read a quad word from an IO port
- * \param Object       Port Object
- * \param out  Pointer to put read data
- */
-int32_t Edi_Int_IO_ReadQWord(object_pointer Object, uint64_t *out)
-{
-       uint32_t        *out32 = (uint32_t*)out;
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*out32) : "d" ( obj->Num ) );
-       __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*(out32+1)) : "d" ( obj->Num+4 ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_ReadString(object_pointer Object, uint32_t Length, uint8_t *out)
- * \brief Read a byte from an IO port
- * \param Object       Port Object
- * \param Length       Number of bytes to read
- * \param out  Pointer to put read data
- */
-int32_t Edi_Int_IO_ReadString(object_pointer Object, uint32_t Length, uint8_t *out)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "rep insb" : : "c" (Length), "D" (out), "d" ( obj->Num ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_WriteByte(object_pointer Object, uint8_t in)
- * \brief Write a byte from an IO port
- * \param Object       Port Object
- * \param in   Data to write
- */
-int32_t Edi_Int_IO_WriteByte(object_pointer Object, uint8_t in)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "outb %%al, %%dx" : : "a" (in), "d" ( obj->Num ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_WriteWord(object_pointer Object, uint16_t in)
- * \brief Write a word from an IO port
- * \param Object       Port Object
- * \param in   Data to write
- */
-int32_t Edi_Int_IO_WriteWord(object_pointer Object, uint16_t in)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "outw %%ax, %%dx" : : "a" (in), "d" ( obj->Num ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_WriteDWord(object_pointer Object, uint32_t in)
- * \brief Write a double word from an IO port
- * \param Object       Port Object
- * \param in   Data to write
- */
-int32_t Edi_Int_IO_WriteDWord(object_pointer Object, uint32_t in)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (in), "d" ( obj->Num ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_WriteQWord(object_pointer Object, uint64_t in)
- * \brief Write a quad word from an IO port
- * \param Object       Port Object
- * \param in   Data to write
- */
-int32_t Edi_Int_IO_WriteQWord(object_pointer Object, uint64_t in)
-{
-       uint32_t        *in32 = (uint32_t*)&in;
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (*in32), "d" ( obj->Num ) );
-       __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (*(in32+1)), "d" ( obj->Num+4 ) );
-       
-       return 1;
-}
-
-/**
- * \fn int32_t Edi_Int_IO_WriteString(object_pointer Object, uint32_t Length, uint8_t *in)
- * \brief Read a byte from an IO port
- * \param Object       Port Object
- * \param Length       Number of bytes to write
- * \param in   Pointer to of data to write
- */
-int32_t Edi_Int_IO_WriteString(object_pointer Object, uint32_t Length, uint8_t *in)
-{
-       tEdiPort        *obj;
-       // Get Data Pointer
-       VALIDATE_PTR(Object, 0);
-       obj = GET_DATA(Object);
-       if( !obj->State )       return 0;
-       if( obj->State & 1 )    return -1;      // Unintialised
-       
-       __asm__ __volatile__ ( "rep outsb" : : "c" (Length), "D" (in), "d" ( obj->Num ) );
-       
-       return 1;
-}
-
-// === CLASS DECLARATION ===
-/*static edi_variable_declaration_t    *scEdi_Int_Variables_IO[] = {
-       {
-               {"pointer", "port_object", 0},
-               {"uint16_t", "port", 0}
-       },
-       {
-               {"pointer", "port_object", 0}
-       },
-       {
-               {"pointer", "port_object", 0},
-               {"pointer int8_t", "out", 0}
-       }
-};*/
-static edi_function_declaration_t      scEdi_Int_Functions_IO[] = {
-               {"int32_t", "init_io_port", 1, 2, NULL, //scEdi_Int_Variables_IO[0],
-                       (function_pointer)Edi_Int_IO_InitPort
-                       },
-               {"uint16_t", "get_port_number", 1, 1, NULL, //scEdi_Int_Variables_IO[1],
-                       (function_pointer)Edi_Int_IO_GetPortNum
-                       },
-               {"int32_t", "read_byte_io_port", 1, 2, NULL, //scEdi_Int_Variables_IO[2],
-                       (function_pointer)Edi_Int_IO_ReadByte
-                       },
-               {"int32_t", "read_word_io_port", 1, 2, NULL/*{
-                               {"pointer", "port_object", 0},
-                               {"pointer int16_t", "out", 0}
-                       }*/,
-                       (function_pointer)Edi_Int_IO_ReadWord
-                       },
-               {"int32_t", "read_long_io_port", 1, 2, NULL/*{
-                               {"pointer", "port_object", 0},
-                               {"pointer int32_t", "out", 0}
-                       }*/,
-                       (function_pointer)Edi_Int_IO_ReadDWord
-                       },
-               {"int32_t", "read_longlong_io_port", 1, 2, NULL/*{
-                               {"pointer", "port_object", 0},
-                               {"pointer int64_t", "out", 0}
-                       }*/,
-                       (function_pointer)Edi_Int_IO_ReadQWord
-                       },
-               {"int32_t", "read_string_io_port", 1, 3, NULL/*{
-                               {"pointer", "port_object", 0},
-                               {"int32_T", "data_length", 0},
-                               {"pointer int64_t", "out", 0}
-                       }*/,
-                       (function_pointer)Edi_Int_IO_ReadString
-                       },
-                       
-               {"int32_t", "write_byte_io_port", 1, 2, NULL/*{
-                               {"pointer", "port_object", 0},
-                               {"int8_t", "in", 0}
-                       }*/,
-                       (function_pointer)Edi_Int_IO_WriteByte},
-               {"int32_t", "write_word_io_port", 1, 2, NULL/*{
-                               {"pointer", "port_object", 0},
-                               {"int16_t", "in", 0}
-                       }*/,
-                       (function_pointer)Edi_Int_IO_WriteWord},
-               {"int32_t", "write_long_io_port", 1, 2, NULL/*{
-                               {"pointer", "port_object", 0},
-                               {"int32_t", "in", 0}
-                       }*/,
-                       (function_pointer)Edi_Int_IO_WriteDWord},
-               {"int32_t", "write_longlong_io_port", 1, 2, NULL/*{
-                               {"pointer", "port_object", 0},
-                               {"int64_t", "in", 0}
-                       }*/,
-                       (function_pointer)Edi_Int_IO_WriteQWord}
-       };
-static edi_class_declaration_t scEdi_Int_Class_IO = 
-       {
-               IO_PORT_CLASS, 1, 12,
-               scEdi_Int_Functions_IO,
-               Edi_Int_IO_Construct,
-               Edi_Int_IO_Destruct,
-               NULL
-       };
diff --git a/KernelLand/Modules/Interfaces/EDI/main.c b/KernelLand/Modules/Interfaces/EDI/main.c
deleted file mode 100644 (file)
index c3d0272..0000000
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * Acess2 EDI Layer
- */
-#define DEBUG  0
-#define VERSION        ((0<<8)|1)
-#include <acess.h>
-#include <modules.h>
-#include <fs_devfs.h>
-#define        IMPLEMENTING_EDI        1
-#include "edi/edi.h"
-
-#define        VALIDATE_PTR(_ptr,_err) do{if(!(_ptr))return _err; }while(0)
-#define        GET_DATA(_ptr)  (Object)
-
-#include "edi_io.inc.c"
-#include "edi_int.inc.c"
-
-// === STRUCTURES ===
-typedef struct sAcessEdiDriver {
-       struct sAcessEdiDriver  *Next;
-       tDevFS_Driver   Driver;
-        int    FileCount;
-       struct {
-               char    *Name;
-               tVFS_Node       Node;
-       }       *Files;
-       edi_object_metadata_t   *Objects;
-       edi_initialization_t    Init;
-       driver_finish_t Finish;
-} tAcessEdiDriver;
-
-// === PROTOTYPES ===
- int   EDI_Install(char **Arguments);
- int   EDI_DetectDriver(void *Base);
- int   EDI_LoadDriver(void *Base);
-vfs_node *EDI_FS_ReadDir(vfs_node *Node, int Pos);
-vfs_node *EDI_FS_FindDir(vfs_node *Node, char *Name);
- int   EDI_FS_CharRead(vfs_node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
- int   EDI_FS_CharWrite(vfs_node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
- int   EDI_FS_IOCtl(vfs_node *Node, int Id, void *Data);
-data_pointer EDI_GetInternalClass(edi_string_t ClassName);
-
-// === GLOBALS ===
-MODULE_DEFINE(0, VERSION, EDI, EDI_Install, NULL, NULL);
-tModuleLoader  gEDI_Loader = {
-       NULL, "EDI", EDI_DetectDriver, EDI_LoadDriver, NULL
-};
-tSpinlock      glEDI_Drivers;
-tAcessEdiDriver        *gEdi_Drivers = NULL;
-edi_class_declaration_t        *gcEdi_IntClasses[] = {
-       &scEdi_Int_Class_IO, &scEdi_Int_Class_IRQ
-};
-#define        NUM_INT_CLASSES (sizeof(gcEdi_IntClasses)/sizeof(gcEdi_IntClasses[0]))
-char *csCharNumbers[] = {"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9"};
-char *csBlockNumbers[] = {"blk0", "blk1", "blk2", "blk3", "blk4", "blk5", "blk6", "blk7", "blk8", "blk9"};
-
-// === CODE ===
-/**
- * \fn int EDI_Install(char **Arguments)
- * \brief Stub intialisation routine
- */
-int EDI_Install(char **Arguments)
-{
-       Module_RegisterLoader( &gEDI_Loader );
-       return 1;
-}
-
-/**
- * \brief Detects if a driver should be loaded by the EDI subsystem
- */
-int EDI_DetectDriver(void *Base)
-{
-       if( Binary_FindSymbol(BASE, "driver_init", NULL) == 0 )
-               return 0;
-       
-       return 1;
-}
-
-/**
- * \fn int Edi_LoadDriver(void *Base)
- * \brief Load an EDI Driver from a loaded binary
- * \param Base Binary Handle
- * \return 0 on success, non zero on error
- */
-int EDI_LoadDriver(void *Base)
-{
-       driver_init_t   init;
-       driver_finish_t finish;
-       tAcessEdiDriver *info;
-        int    i, j;
-        int    devfsId;
-       edi_class_declaration_t *classes;
-
-       ENTER("pBase", Base);
-       
-       // Get Functions
-       if( !Binary_FindSymbol(Base, "driver_init", (Uint*)&init)
-       ||      !Binary_FindSymbol(Base, "driver_finish", (Uint*)&finish) )
-       {
-               Warning("[EDI  ] Driver %p does not provide both `driver_init` and `driver_finish`\n", Base);
-               Binary_Unload(Base);
-               return 0;
-       }
-       
-       // Allocate Driver Information
-       info = malloc( sizeof(tAcessEdiDriver) );
-       info->Finish = finish;
-       
-       // Initialise Driver
-       info->Init = init( 0, NULL );   // TODO: Implement Resources
-       
-       LOG("info->Init.driver_name = '%s'", info->Init.driver_name);
-       LOG("info->Init.num_driver_classes = %i", info->Init.num_driver_classes);
-       
-       // Count mappable classes
-       classes = info->Init.driver_classes;
-       info->FileCount = 0;
-       info->Objects = NULL;
-       for( i = 0, j = 0; i < info->Init.num_driver_classes; i++ )
-       {
-               if( strncmp(classes[i].name, "EDI-CHARACTER-DEVICE", 32) == 0 )
-               {
-                       data_pointer    *obj;
-                       // Initialise Object Instances
-                       for( ; (obj = classes[i].constructor()); j++ ) {
-                               LOG("%i - Constructed '%s'", j, classes[i].name);
-                               info->FileCount ++;
-                               info->Objects = realloc(info->Objects, sizeof(*info->Objects)*info->FileCount);
-                               info->Objects[j].object = obj;
-                               info->Objects[j].object_class = &classes[i];
-                       }
-               }
-               else
-                       LOG("%i - %s", i, classes[i].name);
-       }
-       
-       if(info->FileCount)
-       {
-                int    iNumChar = 0;
-               // Create VFS Nodes
-               info->Files = malloc( info->FileCount * sizeof(*info->Files) );
-               memset(info->Files, 0, info->FileCount * sizeof(*info->Files));
-               j = 0;
-               for( j = 0; j < info->FileCount; j++ )
-               {
-                       classes = info->Objects[j].object_class;
-                       if( strncmp(classes->name, "EDI-CHARACTER-DEVICE", 32) == 0 )
-                       {
-                               LOG("%i - %s", j, csCharNumbers[iNumChar]);
-                               info->Files[j].Name = csCharNumbers[iNumChar];
-                               info->Files[j].Node.NumACLs = 1;
-                               info->Files[j].Node.ACLs = &gVFS_ACL_EveryoneRW;
-                               info->Files[j].Node.ImplPtr = &info->Objects[j];
-                               info->Files[j].Node.Read = EDI_FS_CharRead;
-                               info->Files[j].Node.Write = EDI_FS_CharWrite;
-                               info->Files[j].Node.IOCtl = EDI_FS_IOCtl;
-                               info->Files[j].Node.CTime =
-                                       info->Files[j].Node.MTime =
-                                       info->Files[j].Node.ATime = now();
-                               
-                               iNumChar ++;
-                               continue;
-                       }
-               }
-               
-               // Create DevFS Driver
-               info->Driver.ioctl = EDI_FS_IOCtl;
-               memsetda(&info->Driver.rootNode, 0, sizeof(vfs_node) / 4);
-               info->Driver.Name = info->Init.driver_name;
-               info->Driver.RootNode.Flags = VFS_FFLAG_DIRECTORY;
-               info->Driver.RootNode.NumACLs = 1;
-               info->Driver.RootNode.ACLs = &gVFS_ACL_EveryoneRX;
-               info->Driver.RootNode.Length = info->FileCount;
-               info->Driver.RootNode.ImplPtr = info;
-               info->Driver.RootNode.ReadDir = EDI_FS_ReadDir;
-               info->Driver.RootNode.FindDir = EDI_FS_FindDir;
-               info->Driver.RootNode.IOCtl = EDI_FS_IOCtl;
-               
-               // Register
-               devfsId = dev_addDevice( &info->Driver );
-               if(devfsId == -1) {
-                       free(info->Files);      // Free Files
-                       info->Finish(); // Clean up driver
-                       free(info);             // Free info structure
-                       Binary_Unload(iDriverBase);     // Unload library
-                       return -3;      // Return error
-               }
-       }
-       
-       // Append to loaded list;
-       LOCK(&glEDI_Drivers);
-       info->Next = gEDI_Drivers;
-       gEDI_Drivers = info;
-       RELEASE(&glEDI_Drivers);
-       
-       LogF("[EDI ] Loaded Driver '%s' (%s)\n", info->Init.driver_name, Path);
-       LEAVE('i', 1);
-       return 1;
-}
-
-// --- Filesystem Interaction ---
-/**
- * \brief Read from a drivers class list
- * \param Node Driver's Root Node
- * \param Pos  Index of file to get
- */
-char *EDI_FS_ReadDir(tVFS_Node *Node, int Pos)
-{
-       tAcessEdiDriver *info;
-       
-       // Sanity Check
-       if(!Node)       return NULL;
-       
-       // Get Information Structure
-       info = (void *) Node->ImplPtr;
-       if(!info)       return NULL;
-       
-       // Check Position
-       if(Pos < 0)     return NULL;
-       if(Pos >= info->FileCount)      return NULL;
-       
-       return strdup( info->Files[Pos].Name );
-}
-
-/**
- * \fn tVFS_Node *EDI_FS_FindDir(tVFS_Node *Node, char *Name)
- * \brief Find a named file in a driver
- * \param Node Driver's Root Node
- * \param Name Name of file to find
- */
-tVFS_Node *EDI_FS_FindDir(tVFS_Node *Node, char *Name)
-{
-       tAcessEdiDriver *info;
-        int    i;
-       
-       // Sanity Check
-       if(!Node)       return NULL;
-       if(!Name)       return NULL;
-       
-       // Get Information Structure
-       info = (void *) Node->ImplPtr;
-       if(!info)       return NULL;
-       
-       for( i = 0; i < info->FileCount; i++ )
-       {
-               if(strcmp(info->Files[i].name, Name) == 0)
-                       return &info->Files[i].Node;
-       }
-       
-       return NULL;
-}
-
-/**
- * \fn Uint64 EDI_FS_CharRead(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
- * \brief Read from an EDI Character Device
- * \param Node File Node
- * \param Offset       Offset into file (ignored)
- * \param Length       Number of characters to read
- * \param Buffer       Destination for data
- * \return     Number of characters read
- */
-Uint64 EDI_FS_CharRead(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
-{
-       edi_object_metadata_t   *meta;
-       edi_class_declaration_t *class;
-       
-       // Sanity Check
-       if(!Node || !Buffer)    return 0;
-       if(Length <= 0) return 0;
-       // Get Object Metadata
-       meta = (void *) Node->ImplPtr;
-       if(!meta)       return 0;
-       
-       // Get Class
-       class = meta->object_class;
-       if(!class)      return 0;
-       
-       // Read from object
-       if( ((tAnyFunction) class->methods[0].code)( meta->object, Buffer, Length ))
-               return Length;
-
-       return 0;
-}
-
-/**
- * \fn Uint64 EDI_FS_CharWrite(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
- * \brief Write to an EDI Character Device
- * \param Node File Node
- * \param Offset       Offset into file (ignored)
- * \param Length       Number of characters to write
- * \param Buffer       Source for data
- * \return     Number of characters written
- */
-Uint64 EDI_FS_CharWrite(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
-{
-       edi_object_metadata_t   *meta;
-       edi_class_declaration_t *class;
-       
-       // Sanity Check
-       if(!Node || !Buffer)    return 0;
-       if(Length <= 0) return 0;
-       // Get Object Metadata
-       meta = (void *) Node->ImplPtr;
-       if(!meta)       return 0;
-       
-       // Get Class
-       class = meta->object_class;
-       if(!class)      return 0;
-       
-       // Write to object
-       if( ((tAnyFunction) class->methods[1].code)( meta->object, Buffer, Length ))
-               return Length;
-
-       return 0;
-}
-
-/**
- * \fn int EDI_FS_IOCtl(tVFS_Node *Node, int Id, void *Data)
- * \brief Perfom an IOCtl call on the object
- */
-int EDI_FS_IOCtl(tVFS_Node *Node, int Id, void *Data)
-{
-       return 0;
-}
-
-// --- EDI Functions ---
-/**
- * \fn data_pointer EDI_GetDefinedClass(edi_string_t ClassName)
- * \brief Gets the structure of a driver defined class
- * \param ClassName    Name of class to find
- * \return Class definition or NULL
- */
-data_pointer EDI_GetDefinedClass(edi_string_t ClassName)
-{
-        int    i;
-       tAcessEdiDriver *drv;
-       edi_class_declaration_t *classes;
-       
-       for(drv = gEdi_Drivers;
-               drv;
-               drv = drv->Next )
-       {
-               classes = drv->Init.driver_classes;
-               for( i = 0; i < drv->Init.num_driver_classes; i++ )
-               {
-                       if( strncmp(classes[i].name, ClassName, 32) == 0 )
-                               return &classes[i];
-               }
-       }
-       return NULL;
-}
-
-/**
- * \fn int32_t EDI_CheckClassExistence(edi_string_t ClassName)
- * \brief Checks if a class exists
- * \param ClassName    Name of class
- * \return 1 if the class exists, -1 otherwise
- */
-int32_t EDI_CheckClassExistence(edi_string_t ClassName)
-{
-       //LogF("check_class_existence: (ClassName='%s')\n", ClassName);
-       if(EDI_GetInternalClass(ClassName))
-               return 1;
-               
-       if(EDI_GetDefinedClass(ClassName))      // Driver Defined
-               return 1;
-       
-       return -1;
-}
-
-/**
- * \fn edi_object_metadata_t EDI_ConstructObject(edi_string_t ClassName)
- * \brief Construct an instance of an class (an object)
- * \param ClassName    Name of the class to construct
- */
-edi_object_metadata_t EDI_ConstructObject(edi_string_t ClassName)
-{
-       edi_object_metadata_t   ret = {0, 0};
-       edi_class_declaration_t *class;
-       
-       //LogF("EDI_ConstructObject: (ClassName='%s')\n", ClassName);
-       
-       // Get class definition
-       if( !(class = EDI_GetInternalClass(ClassName)) )        // Internal
-               if( !(class = EDI_GetDefinedClass(ClassName)) ) // Driver Defined
-                       return ret;             // Return ERROR
-       
-       // Initialise
-       ret.object = class->constructor();
-       if( !ret.object )
-               return ret;     // Return ERROR
-       
-       // Set declaration pointer
-       ret.object_class = class;
-       
-       //LogF("EDI_ConstructObject: RETURN {0x%x,0x%x}\n", ret.object, ret.object_class);
-       return ret;
-}
-
-/**
- * \fn void EDI_DestroyObject(edi_object_metadata_t Object)
- * \brief Destroy an instance of a class
- * \param Object       Object to destroy
- */
-void EDI_DestroyObject(edi_object_metadata_t Object)
-{
-       if( !Object.object )    return;
-       if( !Object.object_class )      return;
-       
-       ((edi_class_declaration_t*)(Object.object_class))->destructor( &Object );
-}
-
-/**
- * \fn function_pointer EDI_GetMethodByName(data_pointer ObjectClass, edi_string_t MethodName)
- * \brief Get a method of a class by it's name
- * \param ObjectClass  Pointer to a ::edi_object_metadata_t of the object
- * \param MethodName   Name of the desired method
- * \return Function address or NULL
- */
-function_pointer EDI_GetMethodByName(data_pointer ObjectClass, edi_string_t MethodName)
-{
-       edi_class_declaration_t *dec = ObjectClass;
-        int    i;
-       
-       //LogF("get_method_by_name: (ObjectClass=0x%x, MethodName='%s')\n", ObjectClass, MethodName);
-       
-       if(!ObjectClass)        return NULL;
-       
-       for(i = 0; i < dec->num_methods; i++)
-       {
-               if(strncmp(MethodName, dec->methods[i].name, 32) == 0)
-                       return dec->methods[i].code;
-       }
-       return NULL;
-}
-
-#if 0
-function_pointer get_method_by_declaration(data_pointer Class, edi_function_declaration_t Declaration);
-#endif
-
-/**
- * \fn edi_string_ptr_t EDI_GetClassParent(edi_string_t ClassName)
- * \brief Get the parent of the named class
- * \todo Implement
- */
-edi_string_ptr_t EDI_GetClassParent(edi_string_t ClassName)
-{
-       WarningEx("EDI", "`get_class_parent` is unimplemented");
-       return NULL;
-}
-
-/**
- * \fn data_pointer EDI_GetInternalClass(edi_string_t ClassName)
- * \brief Get a builtin class
- * \param ClassName    Name of class to find
- * \return Pointer to the ::edi_class_declaration_t of the class
- */
-data_pointer EDI_GetInternalClass(edi_string_t ClassName)
-{
-        int    i;
-       //LogF("get_internal_class: (ClassName='%s')\n", ClassName);
-       for( i = 0; i < NUM_INT_CLASSES; i++ )
-       {
-               if( strncmp( gcEdi_IntClasses[i]->name, ClassName, 32 ) == 0 ) {
-                       return gcEdi_IntClasses[i];
-               }
-       }
-       //LogF("get_internal_class: RETURN NULL\n");
-       return NULL;
-}
-
-/**
- * \fn edi_string_ptr_t EDI_GetObjectClass(data_pointer Object)
- * \brief Get the name of the object of \a Object
- * \param Object       Object to get name of
- * \return Pointer to the class name
- */
-edi_string_ptr_t EDI_GetObjectClass(data_pointer ObjectClass)
-{
-       edi_object_metadata_t   *Metadata = ObjectClass;
-       // Sanity Check
-       if(!ObjectClass)        return NULL;
-       if(!(edi_class_declaration_t*) Metadata->object_class)  return NULL;
-       
-       // Return Class Name
-       return ((edi_class_declaration_t*) Metadata->object_class)->name;
-}
-
-// === EXPORTS ===
-EXPORTAS(EDI_CheckClassExistence, check_class_existence);
-EXPORTAS(EDI_ConstructObject, construct_object);
-EXPORTAS(EDI_DestroyObject, destroy_object);
-EXPORTAS(EDI_GetMethodByName, get_method_by_name);
-EXPORTAS(EDI_GetClassParent, get_class_parent);
-EXPORTAS(EDI_GetInternalClass, get_internal_class);
-EXPORTAS(EDI_GetObjectClass, get_object_class);
index 3b1387b..9b39740 100644 (file)
@@ -2,6 +2,7 @@
 #
 
 CPPFLAGS = -I../../../../UDI/include -Iinclude
+CPPFLAGS += -D UDI_VERSION=0x101 -D UDI_PHYSIO_VERSION=0x101 -D UDI_NIC_VERSION=0x101
 
 # - UDI Library Files
 LIB_OBJS := core/logging.o core/strmem.o core/imc.o core/mem.o core/buf.o
index 1c9fc29..4a655f0 100644 (file)
@@ -37,6 +37,10 @@ tUDI_DriverModule    *gpUDI_LoadedModules;
  */
 int UDI_Install(char **Arguments)
 {
+       if( Arguments && Arguments[0] && strcmp(Arguments[0], "disable") == 0 ) {
+               // Module disabled by user
+               return MODULE_ERR_NOTNEEDED;
+       }
        Module_RegisterLoader( &gUDI_Loader );
 
        Proc_SpawnWorker(UDI_int_DeferredThread, NULL);
@@ -121,10 +125,10 @@ static udi_boolean_t _get_token_bool(const char *str, const char **outstr)
 static udi_index_t _get_token_idx(const char *str, const char **outstr)
 {
        char    *end;
-       int ret = strtol(str, &end, 10);
-       if( ret < 0 || ret > 255 ) {
-               Log_Notice("UDI", "Value '%.*s' out of range for udi_index_t",
-                       end-str, str);
+       unsigned long ret = strtoul(str, &end, 10);
+       if( ret > 255 ) {
+               Log_Notice("UDI", "Value '%.*s' (0x%lx) out of range for udi_index_t",
+                       end-str, str, ret);
                *outstr = NULL;
                return 0;
        }
@@ -145,8 +149,8 @@ static udi_ubit16_t _get_token_uint16(const char *str, const char **outstr)
        char    *end;
        unsigned long ret = strtoul(str, &end, 10);
        if( ret > 0xFFFF ) {
-               Log_Notice("UDI", "Value '%.*s' out of range for udi_ubit16_t",
-                       end-str, str);
+               Log_Notice("UDI", "Value '%.*s' (0x%lx) out of range for udi_ubit16_t",
+                       end-str, str, ret);
                *outstr = NULL;
                return 0;
        }
@@ -419,12 +423,14 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
         int    child_bind_index = 0;
         int    device_index = 0;
         int    next_unpop_region = 1;
+       #define IF_ERROR(op)    if(!str){error_hit=1;op;}
        for( int i = 0; i < nLines; i ++ )
        {
                const char *str = udipropsptrs[i];
                if( !*str )
                        continue ;
                 int    sym = _get_token_sym_v(str, &str, true, caUDI_UdipropsNames);
+               //LOG("Processing option '%s'", (sym >= 0 ? caUDI_UdipropsNames[sym] : "ERR"));
                switch(sym)
                {
                case UDIPROPS__properties_version:
@@ -439,7 +445,7 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                case UDIPROPS__meta: {
                        tUDI_MetaLangRef *ml = &driver_module->MetaLangs[ml_index++];
                        ml->meta_idx = _get_token_idx(str, &str);
-                       if( !str )      continue;
+                       IF_ERROR(continue);
                        ml->interface_name = str;
                        // TODO: May need to trim trailing spaces
                        ml->metalang = UDI_int_GetMetaLangByName(ml->interface_name);
@@ -455,7 +461,7 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                        tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
                        msg->locale = cur_locale;
                        msg->index = _get_token_uint16(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        msg->string = str;
                        //Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
                        break;
@@ -467,7 +473,7 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                case UDIPROPS__region:
                        {
                        udi_index_t rgn_idx = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        // Search for region index (just in case internal_bind_ops appears earlier)
                        tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
                        if( rgn_idx > 0 )
@@ -516,7 +522,7 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                                        rgn->OverrunTime = _get_token_uint32(str, &str);
                                        break;
                                }
-                               if( !str )      break ;
+                               IF_ERROR(break);
                        }
                        break;
                        }
@@ -524,12 +530,13 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                        {
                        tUDI_BindOps    *bind = &driver_module->Parents[parent_index++];
                        bind->meta_idx = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        bind->region_idx = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        bind->ops_idx = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        bind->bind_cb_idx = _get_token_idx(str, &str);
+                       IF_ERROR(continue);
                        if( *str ) {
                                // Expected EOL, didn't get it :(
                        }
@@ -541,9 +548,9 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                        {
                        // Get region using index
                        udi_index_t meta = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        udi_index_t rgn_idx = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        
                        // Search for region index (just in case the relevant 'region' comes after)
                        tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
@@ -569,11 +576,11 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                        rgn->BindMeta = meta;
                        
                        rgn->PriBindOps = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        rgn->SecBindOps = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        rgn->BindCb = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        if( *str ) {
                                // TODO: Please sir, I want an EOL
                        }
@@ -583,10 +590,11 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                        {
                        tUDI_BindOps    *bind = &driver_module->ChildBindOps[child_bind_index++];
                        bind->meta_idx = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        bind->region_idx = _get_token_idx(str, &str);
-                       if( !str )      continue ;
+                       IF_ERROR(continue);
                        bind->ops_idx = _get_token_idx(str, &str);
+                       IF_ERROR(continue);
                        if( *str ) {
                                // Expected EOL, didn't get it :(
                        }
@@ -607,26 +615,27 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                        {
                         int    n_attr = 0;
                        // Count properties (and validate)
-                       _get_token_idx(str, &str);      // message
-                       if( !str )      continue;
+                       _get_token_uint16(str, &str);   // message
+                       IF_ERROR(continue);
                        _get_token_idx(str, &str);      // meta
-                       if( !str )      continue;
+                       IF_ERROR(continue);
                        while( *str )
                        {
                                _get_token_str(str, &str, NULL);
-                               if( !str )      break;
+                               IF_ERROR(break);
                                _get_token_sym(str, &str, true, "string", "ubit32", "boolean", "array", NULL);
-                               if( !str )      break;
+                               IF_ERROR(break);
                                _get_token_str(str, &str, NULL);
-                               if( !str )      break;
+                               IF_ERROR(break);
                                n_attr ++;
                        }
                        // Rewind and actually parse
+                       // - Eat the 'device' token and hence reset 'str'
                        _get_token_str(udipropsptrs[i], &str, NULL);
                        
                        tUDI_PropDevSpec *dev = NEW_wA(tUDI_PropDevSpec, Attribs, n_attr);
                        driver_module->Devices[device_index++] = dev;;
-                       dev->MessageNum = _get_token_idx(str, &str);
+                       dev->MessageNum = _get_token_uint16(str, &str);
                        dev->MetaIdx = _get_token_idx(str, &str);
                        dev->nAttribs = n_attr;
                        n_attr = 0;
@@ -634,10 +643,10 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                        {
                                udi_instance_attr_list_t *at = &dev->Attribs[n_attr];
                                _get_token_str(str, &str, at->attr_name);
-                               if( !str )      break;
+                               IF_ERROR(break);
                                at->attr_type = _get_token_sym(str, &str, true,
                                        " ", "string", "array", "ubit32", "boolean", NULL);
-                               if( !str )      break;
+                               IF_ERROR(break);
                                udi_ubit32_t    val;
                                switch( dev->Attribs[n_attr].attr_type )
                                {
@@ -662,7 +671,7 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                                        UDI_ATTR32_SET(at->attr_value, _get_token_bool(str, &str));
                                        break;
                                }
-                               if( !str )      break;
+                               IF_ERROR(break);
                                n_attr ++;
                        }
                        
@@ -675,7 +684,7 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
        }
        free(udipropsptrs);
        if( error_hit ) {
-               Log_Error("UDI", "Error encountered while parsing udiprops for '%s' (%p), bailing",
+               Log_Error("UDI", "Error encountered while parsing udiprops for '%s' (LoadBase=%p), bailing",
                        driver_module->ModuleName, LoadBase);
                for( int i = 0; i < device_index; i ++ )
                        free(driver_module->Devices[i]);
@@ -688,10 +697,14 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, co
                free(driver_module);
                return NULL;
        }
+       ASSERTC(device_index, ==, driver_module->nDevices);
 
-       for( int i = 0; i < driver_module->nDevices; i ++ )
+       for( int i = 0; i < driver_module->nDevices; i ++ ) {
+               ASSERT(driver_module);
+               ASSERT(driver_module->Devices[i]);
                driver_module->Devices[i]->Metalang = UDI_int_GetMetaLang(driver_module,
                        driver_module->Devices[i]->MetaIdx);
+       }
        
        // Sort message list
        // TODO: Sort message list
index deb7825..9909655 100644 (file)
@@ -6,6 +6,9 @@
  * - PCI Bus Driver
  */
 #define DEBUG  0
+#define UDI_VERSION    0x101
+#define UDI_PHYSIO_VERSION     0x101
+#define UDI_PCI_VERSION        0x101
 #include <udi.h>
 #include <udi_physio.h>
 #include <udi_pci.h>
diff --git a/KernelLand/Modules/Interfaces/UDI/trans/gfx.c b/KernelLand/Modules/Interfaces/UDI/trans/gfx.c
new file mode 100644 (file)
index 0000000..73efc10
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Acess2 UDI Layer
+ * - By John Hodge (thePowersGang)
+ *
+ * trans/gfx.c
+ * - Graphics interface
+ */
+#define DEBUG  1
+#define UDI_VERSION 0x101
+#define UDI_GFX_VERSION 0x101
+#include <udi.h>
+#include <udi_gfx.h>
+#include <acess.h>
+#include <api_drv_video.h>
+
+// === TYPES ===
+typedef struct rdata_s
+{
+       
+} rdata_t;
+
+// === PROTOTYPES ===
+// --- Management metalang
+void acessgfx_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level);
+void acessgfx_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID);
+void acessgfx_final_cleanup_req(udi_mgmt_cb_t *cb);
+// --- GFX Binding
+void acessgfx_channel_event_ind(udi_channel_event_cb_t *cb);
+void acessgfx_bind_ack(udi_gfx_bind_cb_t *cb, udi_index_t sockets, udi_index_t engines, udi_status_t status);
+void acessgfx_unbind_ack(udi_gfx_bind_cb_t *cb);
+void acessgfx_set_connector_ack(udi_gfx_state_cb_t *cb);
+void acessgfx_get_connector_ack(udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+void acessgfx_range_connector_ack(udi_gfx_range_cb_t *cb);
+void acessgfx_set_engine_ack(udi_gfx_state_cb_t *cb);
+void acessgfx_get_engine_ack(udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+void acessgfx_range_engine_ack(udi_gfx_range_cb_t *cb);
+void acessgfx_command_ack(udi_gfx_command_cb_t *cb);
+
+// === CODE ===
+void acessgfx_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
+{
+       rdata_t *rdata = UDI_GCB(cb)->context;
+       
+       // Set up structures that don't need interegating the card to do
+       
+       udi_usage_res(cb);
+}
+
+void acessgfx_channel_event_ind(udi_channel_event_cb_t *cb)
+{
+       rdata_t *rdata = UDI_GCB(cb)->context;
+       
+       switch(cb->event)
+       {
+       case UDI_CHANNEL_CLOSED:
+               udi_channel_event_complete(cb);
+               return;
+       case UDI_CHANNEL_BOUND:
+               rdata->active_cb = UDI_GCB(cb);
+               acessgfx_channel_event_ind$bound(cb->params.parent_bound.bind_cb);
+               return;
+       default:
+               // TODO: emit an error of some form?
+               return;
+       }
+}
+
+void acessgfx_channel_event_ind$bound(udi_gfx_bind_cb_t *cb)
+{
+       rdata_t *rdata = UDI_GCB(bind_cb)->context;
+       
+       // request metalanguage-level bind
+       udi_gfx_bind_req(bind_cb);
+       // Continued in acessgfx_bind_ack
+}
+
+void acessgfx_bind_ack(udi_gfx_bind_cb_t *cb, udi_index_t sockets, udi_index_t engines, udi_status_t status)
+{
+       rdata_t *rdata = UDI_GCB(bind_cb)->context;
+       
+       if( status != UDI_OK ) {
+               // binding failed
+               
+               return ;
+       }
+       
+       // 
+}
+
+// === UDI Bindings ===
+
diff --git a/KernelLand/Modules/Interfaces/UDI/trans/gfx.udic b/KernelLand/Modules/Interfaces/UDI/trans/gfx.udic
new file mode 100644 (file)
index 0000000..d61579d
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Acess2 UDI Layer
+ * - By John Hodge (thePowersGang)
+ *
+ * trans/gfx.c
+ * - Graphics interface
+ */
+#define DEBUG  1
+#define UDI_VERSION 0x101
+#define UDI_GFX_VERSION 0x101
+#include <udi.h>
+#include <udi_gfx.h>
+#include <acess.h>
+#include <api_drv_video.h>
+
+// === TYPES ===
+typedef struct rdata_s
+{
+       
+} rdata_t;
+
+// === CODE ===
+void usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
+{
+       // Set up structures that don't need interegating the card to do
+       
+}
+
+@1=GFX_CLIENT channel_event_ind(udi_channel_event_cb_t *cb)
+{
+       udi_gfx_bind_cb_t       *bind_cb = cb->params.parent_bound.bind_cb;
+       switch(cb->event)
+       {
+       case UDI_CHANNEL_CLOSED:
+               return;
+       case UDI_CHANNEL_BOUND:
+               [sockets, engines, status] = udi_gfx_bind_req(bind_cb);
+               if( status != UDI_OK ) {
+                       return;
+               }
+               // allocate a CB
+               [new_cb] = udi_cb_alloc(bind_cb, ACESSGFX_CB_STATE);
+               udi_gfx_state_cb_t *state_cb = new_cb;
+               for( int i = 0; i < engines; i ++ )
+               {
+                       state_cb->subsystem = i;
+                       state_cb->attribute = UDI_GFX_PROP_PIXELFORMAT;
+                       [pixfmt] = @TRY_NAK[status] udi_gfx_get_engine_req(state_cb)
+                       {
+                               // Shit to do if NAK happens
+                               return ;
+                               // break PIXFMT_NONE;
+                       }
+                       
+                       // TODO: Annotate udi_gfx_state_cb_t to note values are kept?
+                       state_cb->subsystem = i;
+                       state_cb->attribute = UDI_GFX_PROP_OPERATOR_INDEX;
+                       [count] = udi_gfx_get_engine_req(state_cb);
+                       for( int j = 0; j < count; j ++ )
+                       {
+                               state_cb->attribute = j;
+                               [operator, arg_1, arg_2, arg_3] = udi_gfx_engine_getop_req(state_cb);
+                               Log_Debug("UDIGFX", "%i/%i: %i 0x%x 0x%x 0x%x",
+                                       i, j,
+                                       operator, arg_1, arg_2, arg_3);
+                       }
+               }
+               return;
+       default:
+               // TODO: emit an error of some form?
+               return;
+       }
+}
+
+// === UDI Bindings ===
+
+
+// vim: ft=c
diff --git a/KernelLand/Modules/Interfaces/UDI/trans/gfx_plan.txt b/KernelLand/Modules/Interfaces/UDI/trans/gfx_plan.txt
new file mode 100644 (file)
index 0000000..b8e4bb9
--- /dev/null
@@ -0,0 +1,12 @@
+
+Upon binding:
+
+1. Enumerate connectors (types and possible inputs)
+2. For all engines that can have their input be -1, get pixel format
+  a. Parse operator list into a tree
+3. Create MIN(n_conns,n_edge) video devices
+  a. Each device represents an edge engine (engine selected on modeset)
+
+Notes:
+- Need to figure out what engine(s) to use as framebuffer, and what ones to use as cursor
+ > Allow user/admin intervention to set these relations (based on an identifier from the driver)
index 614bd35..4631b72 100644 (file)
@@ -390,7 +390,8 @@ void VirtIO_ReleaseBuffer(tVirtIO_Buf *Buffer)
        do {
                has_next = !!(queue->Entries[idx].Flags & VRING_DESC_F_NEXT);
                int next_idx = queue->Entries[idx].Next;
-               ASSERTC(!has_next || next_idx,!=,idx);
+               if( has_next )
+                       ASSERTC(next_idx,!=,idx);
                
                VirtIO_int_ReleaseQDesc(queue, idx);
        
index a5ea222..c96d8b0 100644 (file)
@@ -62,17 +62,17 @@ endif
 
 ifneq ($(BUILDTYPE),static)
 $(BIN): %.kmd.$(ARCH): $(OBJ)
-       @echo --- $(LD) -o $@
+       @echo --- [LD] -o $@
        @$(LD) --allow-shlib-undefined -shared -nostdlib -o $@ $(OBJ) -defsym=DriverInfo=_DriverInfo_$(FULLNAME) $(LDFLAGS)
        @$(DISASM) $(BIN) > $(BIN).dsm
 else
 $(BIN): %.xo.$(ARCH): $(OBJ)
-       @echo --- $(LD) -o $@
+       @echo --- [LD] -o $@
        @$(LD) -r -o $@ $(OBJ) $(LDFLAGS)
 endif
 
 obj-$(_SUFFIX)/%.o: %.c Makefile $(CFGFILES)
-       @echo --- $(CC) -o $@
+       @echo --- [CC] -o $@
        @mkdir -p $(dir $@)
        @$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
        @$(CC) -M $(CPPFLAGS) -MT $@ -MP -o obj-$(_SUFFIX)/$*.d $<
index 0ad49b0..600f334 100644 (file)
@@ -64,6 +64,7 @@ int E1000_Install(char **Arguments)
        // Allocate card array
        gaE1000_Cards = calloc(sizeof(tCard), card_count);
        if( !gaE1000_Cards ) {
+               Log_Warning("E1000", "Allocation of %i card structures failed", card_count);
                return MODULE_ERR_MALLOC;
        }       
 
@@ -88,6 +89,7 @@ int E1000_Install(char **Arguments)
                        Log_Debug("E1000", "Card %i: %P IRQ %i", card_idx, card->MMIOBasePhys, card->IRQ);
 
                        if( E1000_int_InitialiseCard(card) ) {
+                               Log_Warning("E1000", "Initialisation of card #%i failed", card_idx);
                                return MODULE_ERR_MALLOC;
                        }
                        
index 0edc983..a2e46d1 100644 (file)
--- a/Makefile
+++ b/Makefile
 
 SUBMAKE = $(MAKE) --no-print-directory
 
-USRLIBS := crt0.o acess.ld ld-acess.so libc.so libc++.so libposix.so
+USRLIBS := crt0.o ld-acess.so libc.so libposix.so libc++.so
 USRLIBS += libreadline.so libnet.so liburi.so libpsocket.so
 USRLIBS += libimage_sif.so libunicode.so libm.so
+USRLIBS += libaxwin4.so
 
 EXTLIBS := 
 #libspiderscript
@@ -23,6 +24,7 @@ USRAPPS += insmod
 USRAPPS += bomb lspci
 USRAPPS += ip dhcpclient ping telnet irc wget telnetd
 USRAPPS += axwin3 gui_ate gui_terminal
+USRAPPS += axwin4
 
 define targetclasses
  AI_$1      := $$(addprefix allinstall-,$$($1))
@@ -66,15 +68,31 @@ all-install:        install-Filesystem SyscallList ai-user ai-kmode
 clean: clean-kmode clean-user
 install:       install-Filesystem SyscallList install-user install-kmode
 
-utest: $(USRLIBS:%=utest-%)
+utest-build: $(USRLIBS:%=utest-build-%)
+utest-run: $(USRLIBS:%=utest-run-%)
+utest: utest-build utest-run
 
-$(USRLIBS:%=utest-%): utest-%:
+utest-build-%:
        @CC=$(NCC) $(SUBMAKE) -C Usermode/Libraries/$*_src generate_exp
-       @CC=$(NCC) $(SUBMAKE) -C Usermode/Libraries/$*_src utest -k
+       @CC=$(NCC) $(SUBMAKE) -C Usermode/Libraries/$*_src utest-build
+utest-run-%:
+       @CC=$(NCC) $(SUBMAKE) -C Usermode/Libraries/$*_src utest-run -k
 
 # TODO: Module tests using DiskTool and NetTest
-mtest:
+mtest: mtest-build mtest-run
        @echo > /dev/null
+mtest-build:
+       # Network
+       @echo "== Build Module Tests"
+       @echo "-- nativelib"
+       @CC=$(NCC) $(SUBMAKE) -C Tools/nativelib
+       @echo "-- NetTest"
+       @CC=$(NCC) $(SUBMAKE) -C Tools/NetTest
+       @echo "-- NetTest Runner"
+       @CC=$(NCC) $(SUBMAKE) -C Tools/NetTest_Runner
+mtest-run:
+       @echo "=== Network Module Test ==="
+       @cd Tools && ./nettest_runner
 
 SyscallList: include/syscalls.h
 include/syscalls.h: KernelLand/Kernel/Makefile KernelLand/Kernel/syscalls.lst
@@ -85,13 +103,13 @@ _build_stmod  := BUILDTYPE=static $(SUBMAKE) -C KernelLand/Modules/
 _build_kernel := $(SUBMAKE) -C KernelLand/Kernel
 
 define rules
-$$(ALL_$1): all-%:
+$$(ALL_$1): all-%: $(CC)
        +@echo === $2 && $3 all
-$$(AI_$1): allinstall-%:
+$$(AI_$1): allinstall-%: $(CC)
        +@echo === $2 && $3 all install
-$$(CLEAN_$1): clean-%:
+$$(CLEAN_$1): clean-%: $(CC)
        +@echo === $2 && $3 clean
-$$(INSTALL_$1): install-%:
+$$(INSTALL_$1): install-%: $(CC)
        +@$3 install
 endef
 
@@ -100,13 +118,23 @@ $(eval $(call rules,MODULES,Module: $$*,$(_build_stmod)$$*))
 $(eval $(call rules,USRLIBS,User Library: $$*,$(SUBMAKE) -C Usermode/Libraries/$$*_src))
 $(eval $(call rules,EXTLIBS,External Library: $$*,$(SUBMAKE) -C Externals/$$*))
 $(eval $(call rules,USRAPPS,User Application: $$*,$(SUBMAKE) -C Usermode/Applications/$$*_src))
-all-Kernel:
+all-Kernel: $(CC)
        +@echo === Kernel && $(_build_kernel) all
-allinstall-Kernel:
+allinstall-Kernel: $(CC)
        +@echo === Kernel && $(_build_kernel) all install
-clean-Kernel:
+clean-Kernel: $(CC)
        +@$(_build_kernel) clean
-install-Kernel:
+install-Kernel: $(CC)
        @$(_build_kernel) install
-install-Filesystem:
+install-Filesystem: $(CC)
        @$(SUBMAKE) install -C Usermode/Filesystem
+
+ifeq ($(ARCHDIR),native)
+.PHONY: $(CC)
+else
+$(CC):
+       @echo ---
+       @echo $(CC) does not exist, recompiling
+       @echo ---
+       make -C Externals/cross-compiler/ -f Makefile.cross
+endif
index 022a02e..d12710c 100644 (file)
@@ -2,12 +2,15 @@
 # Acess2 Build Configuration
 #
 
+V ?= @
+
 ACESSDIR := $(dir $(lastword $(MAKEFILE_LIST)))
 ACESSDIR := $(shell cd $(ACESSDIR) && pwd)
 
 # Install destination configuration
 DISTROOT := -i $(ACESSDIR)/Acess2.img ::/Acess2
 NCC := $(CC)
+NCXX := $(CXX)
 xCP := mcopy -D o
 xMKDIR := mmd -D s
 
@@ -16,7 +19,6 @@ xMKDIR := mmd -D s
 # Default build programs
 #CC := gcc
 #LD := ld
-AS := nasm
 DISASM := objdump -d -S
 RM := @rm -f
 STRIP := strip
@@ -35,12 +37,26 @@ ifeq ($(ARCHDIR),)
        ARCHDIR := x86
 endif
 
+# Default compilers
+ifneq ($(ARCHDIR),native)
+CC  = $(COMPILERDIR)bin/$(TRIPLET)-gcc
+CXX = $(COMPILERDIR)bin/$(TRIPLET)-g++
+LD  = $(COMPILERDIR)bin/$(TRIPLET)-ld
+OBJDUMP = $(COMPILERDIR)bin/$(TRIPLET)-objdump
+ ifeq ($(AS),as)
+  AS = $(COMPILERDIR)bin/$(TRIPLET)-gcc -c
+ endif
+endif
+
 ifneq ($(ARCH),host)
  ifneq ($(ARCHDIR),$(ARCH))
   include $(ACESSDIR)/BuildConf/$(ARCHDIR)/Makefile.cfg
  endif
 endif
 
+COMPILERDIR := $(ACESSDIR)/Externals/Output/$(ARCHDIR)-BUILD/
+PATH := $(COMPILERDIR)bin/ $(PATH)
+
 ifeq ($(PLATFORM),)
        PLATFORM := default
 endif
index 601e78a..dbc46fa 100644 (file)
@@ -1,8 +1,5 @@
-Implement Ctrl-C in vterm
 Fix TCP code
 Get IPv6 working
-Implement a DHCP client
-Get UDI working (udiref)
 Finalise AxWin API structure
 Implement input in AxWin
 Write TFTP filesystem driver
diff --git a/RunQemu b/RunQemu
index e69a55e..1202613 100755 (executable)
--- a/RunQemu
+++ b/RunQemu
@@ -80,6 +80,11 @@ while [ $# -ne 0 ]; do
                QEMU_PARAMS=$QEMU_PARAMS" -device pci-serial,chardev=serial2"
                QEMU_PARAMS=$QEMU_PARAMS" -chardev socket,id=serial2,host=localhost,port=10023,server,telnet"
                ;;
+       -sata)
+               QEMU_PARAMS=$QEMU_PARAMS" -device ich9-ahci,id=ahci"
+               QEMU_PARAMS=$QEMU_PARAMS" -drive if=none,id=sata_disk,file=HDD_sata.img"
+               QEMU_PARAMS=$QEMU_PARAMS" -device ide-drive,drive=sata_disk,bus=ahci.0"
+               ;;
        esac
        shift
 done
index f76c8b4..913a9be 100644 (file)
@@ -23,7 +23,7 @@ L_OBJ = vfs_shim.o nic.o tcpclient.o tcpserver.o helpers.o cmdline_backend.o
 N_OBJ = main.o tap.o mode_cmdline.o
 
 # Compilation Options
-CFLAGS := -Wall -std=gnu99 -g -Werror -O0 -pthread
+CFLAGS := -Wall -std=gnu99 -g -O0 -pthread
 CPPFLAGS := -I include/ -I ../nativelib/include
 K_CPPFLAGS := -I $(KERNEL_SRC)include -I $(MODULE_SRC) -I ../../Usermode/Libraries/ld-acess.so_src/include_exp/
 LDFLAGS += -Wl,--defsym,__buildnum=$(BUILD_NUM) -g -L .. -lpthread -lnativelib
index 6d42064..d2d1d5f 100644 (file)
@@ -12,7 +12,7 @@
 // === CODE ===
 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
 {
-       const int maxfd = *Threads_GetMaxFD();
+       const int maxfd = *Threads_GetMaxFD(NULL);
        tVFS_Handle     *handles = *Threads_GetHandlesPtr();
        if( !handles ) {
                handles = calloc( maxfd, sizeof(tVFS_Handle) );
@@ -34,7 +34,7 @@ int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
 
 tVFS_Handle *VFS_GetHandle(int FD)
 {
-       const int maxfd = *Threads_GetMaxFD();
+       const int maxfd = *Threads_GetMaxFD(NULL);
        tVFS_Handle     *handles = *Threads_GetHandlesPtr();
        if( !handles )
                return NULL;
@@ -47,7 +47,7 @@ tVFS_Handle *VFS_GetHandle(int FD)
 
 int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode)
 {
-       const int maxfd = *Threads_GetMaxFD();
+       const int maxfd = *Threads_GetMaxFD(NULL);
        tVFS_Handle     *handles = *Threads_GetHandlesPtr();
        if( !handles )
                return -1;
index e957579..59704c7 100644 (file)
@@ -6,7 +6,7 @@ OBJ += link.o
 OBJ += test_arp.o test_tcp.o
 BIN := ../nettest_runner
 
-CFLAGS := -Wall -std=c99
+CFLAGS := -Wall -std=c99 -g
 CPPFLAGS := -Iinclude
 LIBS := 
 
@@ -23,7 +23,7 @@ $(BIN): $(OBJ)
        @echo [CC] -o $@
        @$(CC) $(LINKFLAGS) -o $@ $(OBJ) $(LIBS)
 
-obj/%.o: %.c
+obj/%.o: %.c Makefile
        @mkdir -p $(dir $@)
        @echo [CC] -c -o $@
        @$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< -MMD -MP
index 7ac2083..0110f04 100644 (file)
@@ -12,7 +12,7 @@ extern void   Stack_AddInterface(const char *Name, int AddrType, const void *Addr,
 extern void    Stack_AddRoute(int Type, const void *Network, int MaskBits, const void *NextHop);
 
 extern void    Stack_AddArg(const char *Fmt, ...);
-extern int     Stack_Start(const char *Subcommand);
+extern int     Stack_Start(const char *TestName, const char *Subcommand);
 extern void    Stack_Kill(void);
 
 extern int     Stack_SendCommand(const char *CommandString, ...);
index bf2da15..9ad23c3 100644 (file)
@@ -6,6 +6,7 @@
 #include <stddef.h>
 
 #define TEST_SETNAME(name)     test_setname(name)
+#define TEST_STEP(name)        do{}while(0)    //test_setstep(name)
 #define TEST_ASSERT(cnd)       do{if(!(cnd)) {test_assertion_fail(__FILE__,__LINE__,"%s",#cnd);return false;}}while(0)
 #define TEST_ASSERT_REL(a,r,b) do{long long a_val=(a),b_val=(b);if(!(a_val r b_val)) {test_assertion_fail(__FILE__,__LINE__,"%s(0x%llx)%s%s(0x%llx)",#a,a_val,#r,#b,b_val);return false;}}while(0)
 #define TEST_WARN(msg...)      test_message(__FILE__,__LINE__,msg)
@@ -16,5 +17,18 @@ extern void  test_assertion_fail(const char *filename, int line, const char *test
 extern void    test_trace(const char *msg, ...);
 extern void    test_trace_hexdump(const char *hdr, const void *data, size_t len);
 
+// Some helpful macros
+// - They require some names to be present
+#define RX_HEADER \
+       size_t  rxlen, ofs, len; \
+       do { ofs = 0; ofs = ofs; len = 0; len = len; } while(0);\
+       char rxbuf[MTU]
+#define TEST_HEADER \
+       TEST_SETNAME(__func__);\
+       RX_HEADER
+
+#define TEST_ASSERT_rx()       TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) )
+#define TEST_ASSERT_no_rx()    TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 )
+
 #endif
 
index a96f388..f6cc135 100644 (file)
@@ -10,6 +10,7 @@
 
 extern bool    Test_ARP_Basic(void);
 extern bool    Test_TCP_Basic(void);
+extern bool    Test_TCP_Reset(void);
 extern bool    Test_TCP_WindowSizes(void);
 
 #endif
index b1d95c1..5c175d7 100644 (file)
@@ -23,43 +23,54 @@ int main(int argc, char *argv[])
                return 1;
 
        typedef bool t_test(void);
-       t_test  *tests[] = {
-               Test_ARP_Basic,
-               Test_TCP_Basic,
-               Test_TCP_WindowSizes,
-               NULL
+       struct {
+               t_test  *fcn;
+               const char *name;
+       } tests[] = {
+               #define _(fcn)  {fcn, #fcn}
+               _(Test_ARP_Basic),
+               _(Test_TCP_Basic),
+               //_(Test_TCP_WindowSizes),
+               _(Test_TCP_Reset),
+               {NULL,NULL}
                };
 
+       // Truncate the two output files
        // TODO: Move to stack.c
-       FILE    *fp;
-       fp = fopen("stdout.txt", "w");  fclose(fp);
-       fp = fopen("stderr.txt", "w");  fclose(fp);
+       fclose( fopen("stdout.txt", "w") );
+       fclose( fopen("stderr.txt", "w") );
        
        Net_Open(0, "/tmp/acess2net");
 
-       for(int i = 0; tests[i]; i ++ )
+        int    n_pass = 0;
+        int    n_fail = 0;
+       for(int i = 0; tests[i].fcn; i ++ )
        {
                Stack_AddDevice("/tmp/acess2net", (char[]){TEST_MAC});
                Stack_AddInterface("eth0", 4, (const char[]){TEST_IP}, 24);
                Stack_AddRoute(4, "\0\0\0\0", 0, (const char[]){HOST_IP});
-               if( Stack_Start("cmdline") )
+               if( Stack_Start(tests[i].name, "cmdline") )
                        goto teardown;
                
                if( Net_Receive(0, 1, &argc, 1000) == 0 )
                        goto teardown;
                
-               if( tests[i]() )
-                       printf("%s: PASS\n", gsTestName);
+               bool    result = tests[i].fcn();
+               
+               printf("%s: %s\n", gsTestName, (result ? "PASS" : "FAIL"));
+               if(result)
+                       n_pass ++;
                else
-                       printf("%s: FAIL\n", gsTestName);
+                       n_fail ++;
        
        teardown:
                Stack_Kill();
        }
        Net_Close(0);
        unlink("/tmp/acess2net");
+       printf("--- All tests done %i pass, %i fail\n", n_pass, n_fail);
 
-       return 0;
+       return n_fail;
 }
 
 void PrintUsage(const char *ProgName)
index 231df50..4cbf3c8 100644 (file)
@@ -9,6 +9,8 @@
 #include <sys/select.h>
 #include "net.h"
 #include <stdint.h>
+#include <unistd.h>    // unlink/...
+#include <sys/time.h>  // gettimeofday
 
 #define CONNECT_TIMEOUT        10*1000
 #define MAX_IFS        4
@@ -145,7 +147,7 @@ size_t Net_Receive(int IfNum, size_t MaxLen, void *DestBuf, unsigned int Timeout
        
        if( Net_int_EnsureConnected(IfNum) && WaitOnFD(If->FD, false, Timeout) )
        {
-               size_t rv = recvfrom(If->FD, DestBuf, MaxLen, 0, &If->addr, &If->addrlen);
+               size_t rv = recvfrom(If->FD, DestBuf, MaxLen, 0, (struct sockaddr*)&If->addr, &If->addrlen);
                Net_int_SavePacket(If, rv, DestBuf);
                return rv;
        }
@@ -160,7 +162,7 @@ void Net_Send(int IfNum, size_t Length, const void *Buf)
        if( !WaitOnFD(If->FD, true, CONNECT_TIMEOUT) )
                return ;
        Net_int_SavePacket(If, Length, Buf);
-       int rv = sendto(If->FD, Buf, Length, 0, &If->addr, If->addrlen);
+       int rv = sendto(If->FD, Buf, Length, 0, (struct sockaddr*)&If->addr, If->addrlen);
        if( rv < 0 )
                perror("Net_Send - send");
 }
index 7d5e261..07f8be7 100644 (file)
@@ -12,6 +12,8 @@
 
 #include <fcntl.h>
 #include <spawn.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 #define MAX_ARGS       16
 
@@ -53,6 +55,7 @@ void Stack_AddInterface(const char *Name, int AddrType, const void *Addr, int Ma
                break;
        default:
                assert(AddrType == 4);
+               fprintf(stderr, "Stack_AddInterface: Bad address type %i\n", AddrType);
                exit(1);
        }
 }
@@ -63,14 +66,24 @@ void Stack_AddRoute(int Type, const void *Network, int MaskBits, const void *Nex
 
 void Stack_AddArg(const char *Fmt, ...)
 {
+       if( giNumStackArgs == MAX_ARGS ) {
+               fprintf(stderr, "ERROR: Too many arguments to stack, %i max\n", MAX_ARGS);
+               return ;
+       }
        va_list args;
+       
        va_start(args, Fmt);
        size_t len = vsnprintf(NULL, 0, Fmt, args);
        va_end(args);
+
        char *arg = malloc(len+1);
+       assert(arg);
+
        va_start(args, Fmt);
        vsnprintf(arg, len+1, Fmt, args);
        va_end(args);
+       
+       assert( arg[len] == '\0' );
        gasStackArgs[giNumStackArgs++] = arg;
 }
 
@@ -81,7 +94,7 @@ void sigchld_handler(int signum)
        fprintf(stderr, "FAILURE: Child exited (%i)\n", status);
 }
 
-int Stack_Start(const char *Subcommand)
+int Stack_Start(const char *RunName, const char *Subcommand)
 {
        Stack_AddArg(Subcommand);
        
@@ -96,8 +109,8 @@ int Stack_Start(const char *Subcommand)
        fcntl(giStack_InFD, F_SETFD, FD_CLOEXEC);
 
        FILE    *fp;
-       fp = fopen("stdout.txt", "a"); fprintf(fp, "--- Startup\n"); fclose(fp);
-       fp = fopen("stderr.txt", "a"); fprintf(fp, "--- Startup\n"); fclose(fp);
+       fp = fopen("stdout.txt", "a"); fprintf(fp, "--- TEST: %s\n", RunName); fclose(fp);
+       fp = fopen("stderr.txt", "a"); fprintf(fp, "--- TEST: %s\n", RunName); fclose(fp);
 
        posix_spawn_file_actions_t      fa;
        posix_spawn_file_actions_init(&fa);
@@ -123,6 +136,10 @@ void Stack_Kill(void)
                kill(giStack_PID, SIGTERM);
                giStack_PID = 0;
        }
+       
+       for( int i = 1; i < giNumStackArgs; i ++ )
+               free(gasStackArgs[i]);
+       giNumStackArgs = 1;
 }
 
 int Stack_SendCommand(const char *Fmt, ...)
index 92acc71..9c6f044 100644 (file)
@@ -6,25 +6,26 @@
 #include "stack.h"
 #include "arp.h"
 
+static const int       ERX_TIMEOUT = 1000;     // Expect RX timeout (timeout=failure)
+static const int       NRX_TIMEOUT = 250;      // Not expect RX timeout (timeout=success)
+
 bool Test_ARP_Basic(void)
 {
-       TEST_SETNAME(__func__);
-       size_t  rxlen;
-       char rxbuf[MTU];
+       TEST_HEADER;
        
        // Request test machine's IP
        ARP_SendRequest(0, BLOB(TEST_IP));
-       TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) );
+       TEST_ASSERT_rx();
        TEST_ASSERT( ARP_Pkt_IsResponse(rxlen, rxbuf, BLOB(TEST_IP), BLOB(TEST_MAC)) );
 
        // Request host machine's IP
        ARP_SendRequest(0, BLOB(HOST_IP));
-       TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) == 0 );
+       TEST_ASSERT_no_rx();
 
        #if 0   
        // Ask test machine to request our IP
        Stack_SendCommand("arprequest "HOST_IP_STR);
-       TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) );
+       TEST_ASSERT_rx();
        TEST_ASSERT( ARP_Pkt_IsRequest(rxlen, rxbuf, HOST_IP) );
 
        // Respond
@@ -32,7 +33,7 @@ bool Test_ARP_Basic(void)
        
        // Ask test machine to request our IP again (expecting nothing)
        Stack_SendCommand("arprequest "HOST_IP_STR);
-       TEST_ASSERT( !Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) );
+       TEST_ASSERT_no_rx();
        #endif
        
        return true;
index 36942a5..42aa2d5 100644 (file)
@@ -4,6 +4,7 @@
  *
  * test_tcp.c
  * - Tests for the behavior of the "Transmission Control Protocol"
+ * - These tests are written off RFC793
  */
 #include "test.h"
 #include "tests.h"
 #include "tcp.h"
 #include <string.h>
 
-#define TEST_ASSERT_rx()       TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) )
-#define TEST_ASSERT_no_rx()    TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 )
-const int      ERX_TIMEOUT = 1000;     // Expect RX timeout (timeout=failure)
-const int      NRX_TIMEOUT = 250;      // Not expect RX timeout (timeout=success)
-const int      RETX_TIMEOUT = 1000;    // OS PARAM - Retransmit timeout
-const int      LOST_TIMEOUT = 1000;    // OS PARAM - Time before sending an ACK 
-const int      DACK_TIMEOUT = 500;     // OS PARAM - Timeout for delayed ACKs
-const size_t   DACK_BYTES = 4096;      // OS PARAM - Threshold for delayed ACKs
+#define TEST_TIMERS    0
+
+static const int       ERX_TIMEOUT = 1000;     // Expect RX timeout (timeout=failure)
+static const int       NRX_TIMEOUT = 250;      // Not expect RX timeout (timeout=success)
+static const int       RETX_TIMEOUT = 1000;    // OS PARAM - Retransmit timeout
+static const int       LOST_TIMEOUT = 1000;    // OS PARAM - Time before sending an ACK 
+static const int       DACK_TIMEOUT = 500;     // OS PARAM - Timeout for delayed ACKs
+static const size_t    DACK_BYTES = 4096;      // OS PARAM - Threshold for delayed ACKs
 
 bool Test_TCP_Basic(void)
 {
-       TEST_SETNAME(__func__);
-       size_t  rxlen, ofs, len;
-       char rxbuf[MTU];
+       TEST_HEADER;
 
        tTCPConn        testconn = {
                .IFNum = 0, .AF = 4,
@@ -48,6 +47,7 @@ bool Test_TCP_Basic(void)
        // > RFC793 Pg.65
        
        // 1.1. Send SYN packet
+       TEST_STEP("1.1. Send SYN packet to CLOSED");
        TCP_SendC(&testconn, TCP_SYN, testblob_len, testblob);
        testconn.RSeq = 0;
        testconn.LSeq += testblob_len;
@@ -57,6 +57,7 @@ bool Test_TCP_Basic(void)
        TEST_ASSERT_REL(ofs, ==, rxlen);
        
        // 1.2. Send a SYN,ACK packet
+       TEST_STEP("1.2. Send SYN,ACK packet to CLOSED");
        testconn.RSeq = 12345;
        TCP_SendC(&testconn, TCP_SYN|TCP_ACK, 0, NULL);
        // Expect a TCP_RST with SEQ=ACK
@@ -66,6 +67,7 @@ bool Test_TCP_Basic(void)
        testconn.LSeq ++;
        
        // 1.3. Send a RST packet
+       TEST_STEP("1.2. Send RST packet to CLOSED");
        TCP_SendC(&testconn, TCP_RST, 0, NULL);
        // Expect nothing
        TEST_ASSERT_no_rx();
@@ -183,7 +185,7 @@ bool Test_TCP_Basic(void)
        // 2.6. Close connection (TCP FIN)
        TCP_SendC(&testconn, TCP_ACK|TCP_FIN, 0, NULL);
        testconn.LSeq ++;       // Empty = 1 byte
-       // Expect ACK? (Does acess do delayed ACKs here?)
+       // Expect ACK? (Does Acess do delayed ACKs here?)
        TEST_ASSERT_rx();
        TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK) );
        TEST_ASSERT_REL( len, ==, 0 );
@@ -206,20 +208,41 @@ bool Test_TCP_Basic(void)
        return true;
 }
 
+bool Test_TCP_int_OpenConnection(tTCPConn *Conn)
+{
+       RX_HEADER;
+       // >> SYN
+       TCP_SendC(Conn, TCP_SYN, 0, NULL);
+       Conn->LSeq ++;
+       TEST_ASSERT_rx();
+       // << SYN|ACK (save remote sequence number)
+       TCP_SkipCheck_Seq(true);
+       TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, Conn, TCP_SYN|TCP_ACK) );
+       TEST_ASSERT_REL(len, ==, 0);
+       Conn->RSeq = TCP_Pkt_GetSeq(rxlen, rxbuf, Conn->AF) + 1;
+       // >> ACK
+       TCP_SendC(Conn, TCP_ACK, 0, NULL);
+       TEST_ASSERT_no_rx();
+       return true;
+}
+
+#if 0
 bool Test_TCP_SYN_RECEIVED(void)
 {
-       TEST_SETNAME(__func__);
+       TEST_HEADER;
+       
        // 1. Get into SYN-RECEIVED
+       TCP_SendC(&testconn, TCP_SYN, 0, NULL);
        
        // 2. Send various non-ACK packets
        return false;
 }
+#endif
 
-bool Test_TCP_WindowSizes(void)
+bool Test_TCP_Reset(void)
 {
-       TEST_SETNAME(__func__);
-       size_t  rxlen, ofs, len;
-       char rxbuf[MTU];
+       TEST_HEADER;
+       
        tTCPConn        testconn = {
                .IFNum = 0,
                .AF = 4,
@@ -231,20 +254,71 @@ bool Test_TCP_WindowSizes(void)
                .RSeq = 0x600,
                .Window = 128
        };
-       char    testdata[152];
-       memset(testdata, 0xAB, sizeof(testdata));
-       
+
        Stack_SendCommand("tcp_echo_server %i", testconn.RPort);
-       // > Open Connection
+
+       // 1. Response in listen-based SYN-RECEIVED
+       // >> SYN
        TCP_SendC(&testconn, TCP_SYN, 0, NULL);
        testconn.LSeq ++;
+       // << SYN|ACK :: Now in SYN-RECEIVED
        TEST_ASSERT_rx();
        TCP_SkipCheck_Seq(true);
        TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_SYN|TCP_ACK) );
        TEST_ASSERT_REL(len, ==, 0);
        testconn.RSeq = TCP_Pkt_GetSeq(rxlen, rxbuf, testconn.AF) + 1;
+       // >> RST (not ACK)
+       TCP_SendC(&testconn, TCP_RST, 0, NULL);
+       // << nothing (connection should now be dead)
+       TEST_ASSERT_no_rx();
+       // >> ACK (this should be to a closed conneciton, see LISTEN[ACK] above)
        TCP_SendC(&testconn, TCP_ACK, 0, NULL);
+       // << RST
+       TEST_ASSERT_rx();
+       TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_RST) );
+       TEST_ASSERT_REL(len, ==, 0);
+       
+       // 2. Response in open-based SYN-RECEIVED? (What is that?)
+       TEST_WARN("TODO: RFC793 pg70 mentions OPEN-based SYN-RECEIVED");
+       
+       testconn.LPort += 1234;
+       // ESTABLISHED[RST] - RFC793:Pg70
+       // 2. Response in ESTABLISHED 
+       TEST_ASSERT( Test_TCP_int_OpenConnection(&testconn) );
+       // >> RST
+       TCP_SendC(&testconn, TCP_RST, 0, NULL);
+       // << no response, connection closed
        TEST_ASSERT_no_rx();
+       // >> ACK (LISTEN[ACK])
+       TCP_SendC(&testconn, TCP_ACK, 0, NULL);
+       // << RST
+       TEST_ASSERT_rx();
+       TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_RST) );
+       TEST_ASSERT_REL(len, ==, 0);
+       
+       return true;
+}
+
+bool Test_TCP_WindowSizes(void)
+{
+       TEST_HEADER;
+       tTCPConn        testconn = {
+               .IFNum = 0,
+               .AF = 4,
+               .LAddr = BLOB(HOST_IP),
+               .RAddr = BLOB(TEST_IP),
+               .LPort = 44359,
+               .RPort = 9,
+               .LSeq = 0x600,
+               .RSeq = 0x600,
+               .Window = 128
+       };
+       char    testdata[152];
+       memset(testdata, 0xAB, sizeof(testdata));
+       
+       Stack_SendCommand("tcp_echo_server %i", testconn.RPort);
+       // > Open Connection
+       TEST_ASSERT( Test_TCP_int_OpenConnection(&testconn) );
        
        // 1. Test remote respecting our transmission window (>=1 byte)
        // > Send more data than our RX window
@@ -265,7 +339,47 @@ bool Test_TCP_WindowSizes(void)
        TEST_ASSERT_REL(len, ==, 1);
        testconn.RSeq += len;
        // 2. Test remote handling our window being 0 (should only send ACKs)
+       // TODO: 
        // 3. Test that remote drops data outside of its RX window
        // 3.1. Ensure that data that wraps the end of the RX window is handled correctly
+       // TODO: 
+       return false;
+}
+
+// RFC793 pg41
+bool Test_TCP_Retransmit(void)
+{
+       TEST_HEADER;
+       tTCPConn        testconn = {
+               .IFNum = 0,
+               .AF = 4,
+               .LAddr = BLOB(HOST_IP),
+               .RAddr = BLOB(TEST_IP),
+               .LPort = 44359,
+               .RPort = 9,
+               .LSeq = 0x600,
+               .RSeq = 0x600,
+               .Window = 128
+       };
+       char    testdata[128];
+       memset(testdata, 0xAB, sizeof(testdata));
+
+       TEST_STEP("1. Open and connect to TCP server");
+       Stack_SendCommand("tcp_echo_server %i", testconn.RPort);
+       TEST_ASSERT( Test_TCP_int_OpenConnection(&testconn) );
+       
+       
+       TEST_STEP("2. Send data and expect it to be echoed");
+       TCP_SendC(&testconn, TCP_PSH, sizeof(testdata), testdata);
+       testconn.LSeq += sizeof(testdata);
+       TEST_ASSERT_rx();
+       TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK|TCP_PSH) );
+       
+       TEST_STEP("3. Expect nothing for TCP_RTX_TIMEOUT_1");
+       TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, RETX_TIMEOUT-100) == 0 );
+       
+       TEST_STEP("4. Expect a retransmit");
+       TEST_ASSERT_rx();
+       
        return false;
 }
index 1a50d88..8a8fc33 100644 (file)
@@ -19,7 +19,7 @@ KOBJ := $(KOBJ:%.o=obj/_Kernel/%.o)
 OBJ := $(NOBJ) $(LOBJ) $(KOBJ)
 BIN := ../libnativelib.a
 
-CFLAGS := -Wall -std=c99 -Werror
+CFLAGS := -Wall -std=c99
 CPPFLAGS := -I include
 
 
index 7bd91c1..08bb4f7 100644 (file)
@@ -103,12 +103,12 @@ extern int        Threads_int_CreateThread(struct sThread *Thread);
 extern int     Threads_int_ThreadingEnabled(void);
 
 
-extern tThread *Proc_GetCurThread(void);
-extern tThread *Threads_RemActive(void);
-extern void    Threads_AddActive(tThread *Thread);
+extern struct sThread  *Proc_GetCurThread(void);
+extern struct sThread  *Threads_RemActive(void);
+extern void    Threads_AddActive(struct sThread *Thread);
 extern void    Threads_int_WaitForStatusEnd(enum eThreadStatus Status);
-extern int     Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
-extern void    Semaphore_ForceWake(tThread *Thread);
+extern int     Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, struct sThread **ListHead, struct sThread **ListTail, tShortSpinlock *Lock);
+extern void    Semaphore_ForceWake(struct sThread *Thread);
 
 extern tThreadIntMutex *Threads_int_MutexCreate(void);
 extern void    Threads_int_MutexDestroy(tThreadIntMutex *Mutex);
index dafdc40..f804473 100644 (file)
@@ -40,9 +40,12 @@ tGID Threads_GetGID(void) { return 0; }
 
 tTID Threads_GetTID(void) { return lpThreads_This ? lpThreads_This->TID : 0; }
 
-int *Threads_GetMaxFD(void)        { return &lpThreads_This->Process->MaxFDs;  }
-char **Threads_GetCWD(void)        { return &lpThreads_This->Process->CWD;     }
-char **Threads_GetChroot(void)     { return &lpThreads_This->Process->Chroot;  }
+static inline tProcess* getproc(tProcess *Process) {
+       return (Process ? Process : lpThreads_This->Process);
+}
+int *Threads_GetMaxFD(tProcess *Process)       { return &getproc(Process)->MaxFDs;  }
+char **Threads_GetCWD(tProcess *Process)        { return &getproc(Process)->CWD;     }
+char **Threads_GetChroot(tProcess *Process)     { return &getproc(Process)->Chroot;  }
 void **Threads_GetHandlesPtr(void) { return &lpThreads_This->Process->Handles; }
 
 void Threads_Yield(void)
index 227adc0..c5187fa 100644 (file)
@@ -1,6 +1,8 @@
 [COMMON]
 
 [ia32]
-CFLAGS=-ffreestanding -I/home/tpg/Projects/GitClones/acess2/UDI/include/
+CFLAGS=-ffreestanding -I/home/tpg/Projects/GitClones/acess2/UDI/include/ -Wall -Wextra -Wno-unused-parameter
+# -std=c89
+# -Wc++-compat
 CC=i586-elf-gcc
 LD=i586-elf-ld
index 4d0b294..88f0473 100644 (file)
@@ -40,6 +40,9 @@ int Build_CompileFile(tIniFile *opts, const char *abi, tUdiprops *udiprops, tUdi
                srcfile->CompileOpts ? srcfile->CompileOpts : "",
                srcfile->Filename, objfile);
        printf("--- Compiling: %s\n", srcfile->Filename);
+       if( gbTraceEnabled ) {
+               printf(">> %s\n", cmd);
+       }
         int rv = system(cmd);
        free(cmd);
        free(objfile);
@@ -110,7 +113,9 @@ int Build_LinkObjects(tIniFile *opts, const char *abi, tUdiprops *udiprops)
                abi, udiprops->ModuleName, objfiles_str, udiprops_c
                );
        printf("--- Linking: bin/%s/%s\n", abi, udiprops->ModuleName);
-       printf("%s\n", cmd);
+       if( gbTraceEnabled ) {
+               printf(">> %s\n", cmd);
+       }
        int rv = system(cmd);
        free(cmd);
        free(udiprops_c);
index 0cb419b..2f92913 100644 (file)
@@ -9,6 +9,7 @@
 #define _COMMON_H_
 
 #include <stdarg.h>
+#include <stdbool.h>
 
 #ifndef __GNUC__
 # define __attribute__(...)
@@ -16,5 +17,7 @@
 
 extern char    *mkstr(const char *fmt, ...) __attribute__((format(printf,1,2)));
 
+extern bool    gbTraceEnabled;
+
 #endif
 
index b5b0042..f933cc1 100644 (file)
@@ -29,6 +29,7 @@
 void   Usage(const char *progname);
 
 // === GLOBALS ===
+bool   gbTraceEnabled = false;
 const char *gsRuntimeDir = RUNTIME_DIR;
 const char *gsOpt_ConfigFile;
 const char *gsOpt_WorkingDir;
diff --git a/UDI/drivers/gfx_bochs/bochsga_common.h b/UDI/drivers/gfx_bochs/bochsga_common.h
new file mode 100644 (file)
index 0000000..5d40cfa
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * UDI Bochs Graphics Driver
+ * By John Hodge (thePowersGang)
+ *
+ * bochsga_common.c
+ * - Common definitions
+ */
+#ifndef _BOCHSGA_COMMON_H_
+#define _BOCHSGA_COMMON_H_
+
+/**
+ * Definitions to match udiprops.txt
+ * \{
+ */
+#define BOCHSGA_META_BUS       1
+#define BOCHSGA_META_GFX       2
+
+#define BOCHSGA_OPS_DEV        1
+#define BOCHSGA_OPS_GFX        2
+
+#define BOCHSGA_CB_BUS_BIND    1
+#define BOCHSGA_CB_GFX_BIND    2
+#define BOCHSGA_CB_GFX_STATE   3
+#define BOCHSGA_CB_GFX_RANGE   4
+#define BOCHSGA_CB_GFX_COMMAND 5
+
+#define BOCHSGA_MSGNUM_PROPUNK 1001
+#define BOCHSGA_MSGNUM_BUFUNK  1002
+/**
+ * \}
+ */
+
+#include "bochsga_pio.h"
+
+typedef struct {
+       udi_ubit32_t    width;
+       udi_ubit32_t    height;
+       udi_index_t     bitdepth;
+} engine_t;
+
+#define N_ENGINES      1
+
+/**
+ * Region data
+ */
+typedef struct
+{
+       udi_cb_t        *active_cb;
+       struct {
+               udi_index_t     pio_index;
+       } init;
+
+       udi_pio_handle_t        pio_handles[N_PIO];
+       
+       udi_boolean_t   output_enable;
+       struct {
+               udi_ubit32_t    width;
+               udi_ubit32_t    height;
+               udi_ubit8_t     bitdepth;
+               udi_index_t     engine;
+       } outputstate;
+       struct {
+               udi_ubit32_t    max_width;      // 1024 or 1280
+               udi_ubit32_t    max_height;     // 768 or 1024
+       } limits;
+       
+       engine_t        engines[N_ENGINES];
+} rdata_t;
+
+#define BOCHSGA_MIN_WIDTH      360
+#define BOCHSGA_MIN_HEIGHT     240
+
+#endif
+
diff --git a/UDI/drivers/gfx_bochs/bochsga_core.c b/UDI/drivers/gfx_bochs/bochsga_core.c
new file mode 100644 (file)
index 0000000..458f893
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * UDI Bochs Graphics Driver
+ * By John Hodge (thePowersGang)
+ *
+ * bochsga_core.c
+ * - Core Code
+ */
+#define UDI_VERSION    0x101
+#define UDI_PHYSIO_VERSION     0x101
+#define UDI_GFX_VERSION        0x101
+#define UDI_PCI_VERSION        0x101
+#include <udi.h>
+#include <udi_physio.h>
+#include <udi_gfx.h>
+#include <udi_pci.h>
+#define DEBUG_ENABLED  1
+#include "../helpers.h"
+#include "../helpers_gfx.h"
+#include "bochsga_common.h"
+
+/* --- Management Metalang -- */
+void bochsga_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
+{
+       //rdata_t       *rdata = UDI_GCB(cb)->context;
+       /*udi_trace_write(rdata->init_context, UDI_TREVENT_LOCAL_PROC_ENTRY, 0, );*/
+
+       /* TODO: Set up region data */
+
+       udi_usage_res(cb);
+}
+
+void bochsga_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
+{
+       //rdata_t       *rdata = UDI_GCB(cb)->context;
+       udi_instance_attr_list_t *attr_list = cb->attr_list;
+       
+       switch(enumeration_level)
+       {
+       case UDI_ENUMERATE_START:
+       case UDI_ENUMERATE_START_RESCAN:
+               cb->attr_valid_length = attr_list - cb->attr_list;
+               udi_enumerate_ack(cb, UDI_ENUMERATE_OK, BOCHSGA_OPS_GFX);
+               break;
+       case UDI_ENUMERATE_NEXT:
+               udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
+               break;
+       }
+}
+void bochsga_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
+{
+}
+void bochsga_final_cleanup_req(udi_mgmt_cb_t *cb)
+{
+}
+/* --- */
+void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb);
+void bochsga_bus_dev_bus_bind_ack(udi_bus_bind_cb_t *cb, udi_dma_constraints_t dma_constraints, udi_ubit8_t perferred_endianness, udi_status_t status);
+void bochsga_bus_dev_bind__pio_map(udi_cb_t *cb, udi_pio_handle_t new_pio_handle);
+void bochsga_bus_dev_bind__intr_chanel(udi_cb_t *gcb, udi_channel_t new_channel);
+void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb);
+
+void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb)
+{
+       udi_cb_t        *gcb = UDI_GCB(cb);
+       rdata_t *rdata = gcb->context;
+       
+       switch(cb->event)
+       {
+       case UDI_CHANNEL_CLOSED:
+               break;
+       case UDI_CHANNEL_BOUND: {
+               rdata->active_cb = gcb;
+               udi_bus_bind_cb_t *bus_bind_cb = UDI_MCB(cb->params.parent_bound.bind_cb, udi_bus_bind_cb_t);
+               udi_bus_bind_req( bus_bind_cb );
+               // continue at bochsga_bus_dev_bus_bind_ack
+               return; }
+       }
+}
+void bochsga_bus_dev_bus_bind_ack(udi_bus_bind_cb_t *cb,
+       udi_dma_constraints_t dma_constraints, udi_ubit8_t perferred_endianness, udi_status_t status)
+{
+       udi_cb_t        *gcb = UDI_GCB(cb);
+       rdata_t *rdata = gcb->context;
+       
+       /* Set up PIO handles */
+       rdata->init.pio_index = -1;
+       bochsga_bus_dev_bind__pio_map(gcb, UDI_NULL_PIO_HANDLE);
+       /* V V V V */
+}
+void bochsga_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle)
+{
+       rdata_t *rdata = gcb->context;
+       if( rdata->init.pio_index != (udi_index_t)-1 )
+       {
+               rdata->pio_handles[rdata->init.pio_index] = new_pio_handle;
+       }
+       
+       rdata->init.pio_index ++;
+       if( rdata->init.pio_index < N_PIO )
+       {
+               const struct s_pio_ops  *ops = &bochsga_pio_ops[rdata->init.pio_index];
+               udi_pio_map(bochsga_bus_dev_bind__pio_map, gcb,
+                       ops->regset_idx, ops->base_offset, ops->length,
+                       ops->trans_list, ops->list_length,
+                       UDI_PIO_LITTLE_ENDIAN, 0, 0
+                       );
+               return ;
+       }
+       
+       udi_channel_event_complete( UDI_MCB(rdata->active_cb, udi_channel_event_cb_t), UDI_OK);
+       // = = = = =
+}
+void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb)
+{
+}
+void bochsga_bus_dev_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status)
+{
+}
+void bochsga_bus_dev_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb)
+{
+}
+
+/* ---  GFX Provider ops -- */
+void bochsga_gfx_channel_event_ind(udi_channel_event_cb_t *cb)
+{
+       /* No operation */
+}
+void bochsga_gfx_bind_req(udi_gfx_bind_cb_t *cb)
+{
+       /* TODO: ACK bind if nothing already bound */
+}
+void bochsga_gfx_unbind_req(udi_gfx_bind_cb_t *cb)
+{
+       /* TODO: Release internal state? */
+}
+void bochsga_gfx_set_connector_req$pio(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t status, udi_ubit16_t result)
+{
+       udi_gfx_state_cb_t *cb = UDI_MCB(gcb, udi_gfx_state_cb_t);
+       udi_gfx_set_connector_ack(cb);
+}
+void bochsga_gfx_set_connector_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
+{
+       udi_cb_t        *gcb = UDI_GCB(cb);
+       rdata_t *rdata = gcb->context;
+       
+       switch(cb->attribute)
+       {
+       case UDI_GFX_PROP_ENABLE:
+               if( rdata->output_enable != !!value )
+               {
+                       rdata->output_enable = !!value;
+                       udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
+                               rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
+                       return ;
+               }
+               udi_gfx_set_connector_ack(cb);
+               return;
+       /* Change input engine */
+       case UDI_GFX_PROP_INPUT:
+               udi_gfx_set_connector_ack(cb);
+               return;
+       /* Alter output dimensions */
+       case UDI_GFX_PROP_WIDTH:
+               if( value % 8 != 0 ) {
+                       /* Qemu doesn't like resolutions not a multiple of 8 */
+                       return ;
+               }
+               if( !(320 <= value && value <= rdata->limits.max_width) ) {
+                       return ;
+               } 
+               rdata->outputstate.width = value;
+               udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
+                       rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
+               return;
+       case UDI_GFX_PROP_HEIGHT:
+               if( !(240 <= value && value <= rdata->limits.max_height) ) {
+                       return ;
+               } 
+               rdata->outputstate.height = value;
+               udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
+                       rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
+               return;
+       }
+       CONTIN(bochsga_gfx_set_connector_req, udi_log_write,
+               (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+               (udi_status_t status)
+               );
+       udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
+       udi_gfx_set_connector_ack(cb /*, UDI_STAT_NOT_SUPPORTED*/);
+}
+void bochsga_gfx_get_connector_req(udi_gfx_state_cb_t *cb)
+{
+       udi_cb_t        *gcb = UDI_GCB(cb);
+       rdata_t *rdata = gcb->context;
+       
+       switch(cb->attribute)
+       {
+       case UDI_GFX_PROP_ENABLE:
+               udi_gfx_get_connector_ack(cb, !!rdata->output_enable);
+               return;
+       case UDI_GFX_PROP_INPUT:
+               udi_gfx_get_connector_ack(cb, 0);
+               return;
+       case UDI_GFX_PROP_WIDTH:
+               udi_gfx_get_connector_ack(cb, rdata->outputstate.width);
+               return;
+       case UDI_GFX_PROP_HEIGHT:
+               udi_gfx_get_connector_ack(cb, rdata->outputstate.height);
+               return;
+       case UDI_GFX_PROP_CONNECTOR_TYPE:
+               udi_gfx_get_connector_ack(cb, UDI_GFX_CONNECTOR_HIDDEN);
+               return;
+       case UDI_GFX_PROP_SIGNAL:
+               udi_gfx_get_connector_ack(cb, UDI_GFX_SIGNAL_INTEGRATED);
+               return;
+       }
+       CONTIN(bochsga_gfx_get_connector_req, udi_log_write,
+               (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+               (udi_status_t status)
+               );
+       udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
+       udi_gfx_get_connector_ack(cb, 0);
+}
+void bochsga_gfx_range_connector_req(udi_gfx_range_cb_t *cb)
+{
+       udi_cb_t        *gcb = UDI_GCB(cb);
+       rdata_t *rdata = gcb->context;
+       
+       switch(cb->attribute)
+       {
+       case UDI_GFX_PROP_ENABLE:
+               /* 2 values: 0 and 1 */
+               gfxhelpers_return_range_set(udi_gfx_range_connector_ack, cb, 2, 0, 1);
+               return;
+       case UDI_GFX_PROP_INPUT:
+               /* Fix 0 */
+               gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, 0);
+               return;
+       case UDI_GFX_PROP_WIDTH:
+               /* qemu restricts to 8 step */
+               gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb,
+                       BOCHSGA_MIN_WIDTH, rdata->limits.max_width, 8);
+               return;
+       case UDI_GFX_PROP_HEIGHT:
+               /* step of 8 for neatness */
+               gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb,
+                       BOCHSGA_MIN_HEIGHT, rdata->limits.max_height, 8);
+               return;
+       case UDI_GFX_PROP_CONNECTOR_TYPE:
+               gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_CONNECTOR_HIDDEN);
+               return;
+       case UDI_GFX_PROP_SIGNAL:
+               gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_SIGNAL_INTEGRATED);
+               return;
+       }
+       CONTIN(bochsga_gfx_range_connector_req, udi_log_write,
+               (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+               (udi_status_t status)
+               );
+       udi_gfx_range_cb_t      *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
+       udi_gfx_range_connector_ack(cb);
+}
+
+/* --- Engine Manipulation --- */
+void bochsga_gfx_set_engine_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
+{
+       udi_cb_t        *gcb = UDI_GCB(cb);
+       rdata_t *rdata = gcb->context;
+       
+       if( cb->subsystem >= N_ENGINES ) {
+               udi_gfx_get_engine_ack(cb, 0);
+               return;
+       }
+       
+       engine_t *engine = &rdata->engines[cb->subsystem];
+       
+       switch(cb->attribute)
+       {
+       case UDI_GFX_PROP_WIDTH:
+               engine->width = value;
+               udi_gfx_set_engine_ack(cb);
+               return;
+       case UDI_GFX_PROP_HEIGHT:
+               engine->height = value;
+               udi_gfx_set_engine_ack(cb);
+               return;
+       }
+       CONTIN(bochsga_gfx_set_engine_req, udi_log_write,
+               (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+               (udi_status_t status)
+               );
+       udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
+       udi_gfx_set_engine_ack(cb);
+}
+void bochsga_gfx_get_engine_req(udi_gfx_state_cb_t *cb)
+{
+       udi_cb_t        *gcb = UDI_GCB(cb);
+       rdata_t *rdata = gcb->context;
+       
+       if( cb->subsystem >= N_ENGINES ) {
+               udi_gfx_get_engine_ack(cb, 0);
+               return;
+       }
+       
+       const engine_t *engine = &rdata->engines[cb->subsystem];
+       
+       switch(cb->attribute)
+       {
+       case UDI_GFX_PROP_ENABLE:
+               udi_gfx_get_engine_ack(cb, 1);
+               return;
+       
+       case UDI_GFX_PROP_INPUT:
+               udi_gfx_get_engine_ack(cb, -1);
+               return;
+       
+       case UDI_GFX_PROP_WIDTH:
+               udi_gfx_get_engine_ack(cb, engine->width);
+               return;
+       case UDI_GFX_PROP_HEIGHT:
+               udi_gfx_get_engine_ack(cb, engine->height);
+               return;
+       
+       case UDI_GFX_PROP_STOCK_FORMAT:
+               udi_gfx_get_engine_ack(cb, UDI_GFX_STOCK_FORMAT_R8G8B8);
+               return;
+       }
+       CONTIN(bochsga_gfx_get_engine_req, udi_log_write,
+               (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+               (udi_status_t status)
+               );
+       udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
+       udi_gfx_get_engine_ack(cb, 0);
+}
+void bochsga_gfx_range_engine_req(udi_gfx_range_cb_t *cb)
+{
+       udi_cb_t        *gcb = UDI_GCB(cb);
+       rdata_t *rdata = gcb->context;
+       (void)rdata;
+       
+       if( cb->subsystem >= N_ENGINES ) {
+               udi_gfx_range_engine_ack(cb);
+               return;
+       }
+       
+       //engine_t *engine = &rdata->engines[cb->subsystem];
+       
+       switch(cb->attribute)
+       {
+       case UDI_GFX_PROP_ENABLE:
+               gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, 1);
+               return;
+       case UDI_GFX_PROP_INPUT:
+               gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, -1);
+               return;
+       
+       case UDI_GFX_PROP_STOCK_FORMAT:
+               gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, UDI_GFX_STOCK_FORMAT_B8G8R8);
+               return;
+       }
+       CONTIN(bochsga_gfx_range_engine_req, udi_log_write,
+               (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+               (udi_status_t status)
+               );
+       udi_gfx_range_cb_t *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
+       udi_gfx_range_engine_ack( cb );
+}
+void bochsga_gfx_get_engine_operator_req(udi_gfx_range_cb_t *cb)
+{
+       /* TODO: Get Engine operator */
+       udi_gfx_get_engine_operator_ack(cb, 0, 0,0,0);
+}
+void bochsga_gfx_connector_command_req(udi_gfx_command_cb_t *cb)
+{
+       /* Need to parse the GLX stream */
+       udi_gfx_connector_command_ack(cb);
+}
+void bochsga_gfx_engine_command_req(udi_gfx_command_cb_t *cb)
+{
+       /* Need to parse the GLX stream */
+       udi_gfx_engine_command_ack(cb);
+}
+void bochsga_gfx_buffer_info_req(udi_gfx_buffer_info_cb_t *cb)
+{
+       udi_cb_t *gcb = UDI_GCB(cb);
+       switch(cb->buffer_index)
+       {
+       case 0:
+               udi_gfx_buffer_info_ack(cb, 1024, 768, 24, 0);
+               return;
+       default:
+               break;
+       }
+       CONTIN(bochsga_gfx_buffer_info_req, udi_log_write,
+               (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_BUFUNK, __func__, cb->buffer_index),
+               (udi_status_t status)
+               );
+       udi_gfx_buffer_info_cb_t *cb = UDI_MCB(gcb, udi_gfx_buffer_info_cb_t);
+       udi_gfx_buffer_info_ack(cb, 0,0,0,0);
+}
+void bochsga_gfx_buffer_write_req(udi_gfx_buffer_cb_t *cb)
+{
+}
+void bochsga_gfx_buffer_read_req(udi_gfx_buffer_cb_t *cb)
+{
+}
+
+/*
+====================================================================
+Management ops
+====================================================================
+*/
+udi_mgmt_ops_t bochsga_mgmt_ops = {
+       bochsga_usage_ind,
+       bochsga_enumerate_req,
+       bochsga_devmgmt_req,
+       bochsga_final_cleanup_req
+};
+udi_ubit8_t    bochsga_mgmt_op_flags[4] = {0,0,0,0};
+/* - Bus Ops */
+udi_bus_device_ops_t   bochsga_bus_dev_ops = {
+       bochsga_bus_dev_channel_event_ind,
+       bochsga_bus_dev_bus_bind_ack,
+       bochsga_bus_dev_bus_unbind_ack,
+       bochsga_bus_dev_intr_attach_ack,
+       bochsga_bus_dev_intr_detach_ack
+};
+udi_ubit8_t    bochsga_bus_dev_ops_flags[5] = {0};
+/* - GFX provider ops */
+udi_gfx_provider_ops_t bochsga_gfx_ops = {
+       bochsga_gfx_channel_event_ind,
+       bochsga_gfx_bind_req,
+       bochsga_gfx_unbind_req,
+       bochsga_gfx_set_connector_req,
+       bochsga_gfx_set_engine_req,
+       bochsga_gfx_get_connector_req,
+       bochsga_gfx_get_engine_req,
+       bochsga_gfx_range_connector_req,
+       bochsga_gfx_range_engine_req,
+       bochsga_gfx_get_engine_operator_req,
+       bochsga_gfx_connector_command_req,
+       bochsga_gfx_engine_command_req,
+       bochsga_gfx_buffer_info_req,
+       bochsga_gfx_buffer_read_req,
+       bochsga_gfx_buffer_write_req,
+};
+udi_ubit8_t    bochsga_gfx_ops_flags[10] = {0};
+/* -- */
+udi_primary_init_t     bochsga_pri_init = {
+       .mgmt_ops = &bochsga_mgmt_ops,
+       .mgmt_op_flags = bochsga_mgmt_op_flags,
+       .mgmt_scratch_requirement = 0,
+       .enumeration_attr_list_length = 0,
+       .rdata_size = sizeof(rdata_t),
+       .child_data_size = 0,
+       .per_parent_paths = 0
+};
+udi_ops_init_t bochsga_ops_list[] = {
+       {
+               BOCHSGA_OPS_DEV, BOCHSGA_META_BUS, UDI_BUS_DEVICE_OPS_NUM,
+               0,
+               (udi_ops_vector_t*)&bochsga_bus_dev_ops,
+               bochsga_bus_dev_ops_flags
+       },
+       {
+               BOCHSGA_OPS_GFX, BOCHSGA_META_GFX, UDI_GFX_PROVIDER_OPS_NUM,
+               0,
+               (udi_ops_vector_t*)&bochsga_gfx_ops,
+               bochsga_gfx_ops_flags
+       },
+       {0}
+};
+udi_cb_init_t bochsga_cb_init_list[] = {
+       {BOCHSGA_CB_BUS_BIND,    BOCHSGA_META_BUS, UDI_BUS_BIND_CB_NUM, 0, 0,NULL},
+       {BOCHSGA_CB_GFX_BIND,    BOCHSGA_META_GFX, UDI_GFX_BIND_CB_NUM, 0, 0,NULL},
+       {BOCHSGA_CB_GFX_STATE,   BOCHSGA_META_GFX, UDI_GFX_STATE_CB_NUM, 0, 0,NULL},
+       {BOCHSGA_CB_GFX_RANGE,   BOCHSGA_META_GFX, UDI_GFX_RANGE_CB_NUM, 0, 0,NULL},
+       {BOCHSGA_CB_GFX_COMMAND, BOCHSGA_META_GFX, UDI_GFX_COMMAND_CB_NUM, 0, 0,NULL},
+       {0}
+};
+const udi_init_t       udi_init_info = {
+       .primary_init_info = &bochsga_pri_init,
+       .ops_init_list = bochsga_ops_list,
+       .cb_init_list = bochsga_cb_init_list,
+};
diff --git a/UDI/drivers/gfx_bochs/bochsga_engines.h b/UDI/drivers/gfx_bochs/bochsga_engines.h
new file mode 100644 (file)
index 0000000..272f0be
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 
+ */
+
+#define BOCHSGA_ENGINE_PROP_BUFFER     (UDI_GFX_PROP_CUSTOM+0)
+
+/* === CONSTANTS === */
+const gfxhelpers_op_t  bochsga_engine_ops_8bpp[] = {
+};
+const gfxhelpers_op_t  bochsga_engine_ops_32bpp[] = {
+       {UDI_GFX_OPERATOR_RGB,    1,  2,  3},   /* #0 Output RGB from ops #1,#2,#3 */
+       {UDI_GFX_OPERATOR_SEG,    4, 16,  8},   /* #1 Extract 8 bits from bit 16 of #4 */
+       {UDI_GFX_OPERATOR_SEG,    4,  8,  8},   /* #2 8 bits from ofs 8 of #4 */
+       {UDI_GFX_OPERATOR_SEG,    4,  0,  8},   /* #3 8 bits from ofs 0 of #4 */
+       {UDI_GFX_OPERATOR_BUFFER, 5,  6, 32},   /* #4 32 bits from buffer #5 ofs #6 */
+       {UDI_GFX_OPERATOR_ATTR,   0, BOCHSGA_ENGINE_PROP_BUFFER, 0},    /* #5 Buffer index */
+       {UDI_GFX_OPERATOR_MAD,    7,  8,  9},   /* #6 Get offset (#8 * #7 + #9) */
+       {UDI_GFX_OPERATOR_ATTR,   0, UDI_GFX_PROP_SOURCE_WIDTH, 0},     /* #7 Read buffer width */
+       {UDI_GFX_OPERATOR_Y,      0,  0,  0},   /* #8 Y coordinate */
+       {UDI_GFX_OPERATOR_X,      0,  0,  0}    /* #9 X coordinate */
+};
+
+typedef struct {
+       udi_ubit8_t     bitdepth;
+       gfxhelpers_op_map_t     op_map;
+} engine_static_t;
+
+const engine_static_t  bochsga_engine_defs[] = {
+       {.bitdepth = 8, .op_map = {ARRAY_COUNT(bochsga_engine_ops_8bpp), bochsga_engine_ops_8bpp}},
+       {.bitdepth = 16},
+       {.bitdepth = 24},
+       {.bitdepth = 32, .op_map = {ARRAY_COUNT(bochsga_engine_ops_8bpp), bochsga_engine_ops_32bpp}},
+};
+#define N_ENGINES      ARRAY_COUNT(bochsga_engine_defs)
diff --git a/UDI/drivers/gfx_bochs/bochsga_pio.h b/UDI/drivers/gfx_bochs/bochsga_pio.h
new file mode 100644 (file)
index 0000000..f5ddf26
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * TODO
+ */
+#ifndef _BOCHSGA_PIO_H_
+#define _BOCHSGA_PIO_H_
+
+udi_pio_trans_t        bochsga_pio_enable[] = {
+       {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0},
+       };
+
+enum {
+       BOCHSGA_PIO_ENABLE,
+};
+
+const struct s_pio_ops bochsga_pio_ops[] = {
+       [BOCHSGA_PIO_ENABLE] = UDIH_PIO_OPS_ENTRY(bochsga_pio_enable, 0, UDI_PCI_BAR_2, 0x400, 0xB*2),
+//     UDIH_PIO_OPS_ENTRY(bochsga_pio_enable, 0, UDI_PCI_BAR_2, 0x400, 0xB*2),
+       };
+#define N_PIO  (sizeof(bochsga_pio_ops)/sizeof(struct s_pio_ops))
+
+#endif
+
diff --git a/UDI/drivers/gfx_bochs/udiprops.txt b/UDI/drivers/gfx_bochs/udiprops.txt
new file mode 100644 (file)
index 0000000..8b43d5c
--- /dev/null
@@ -0,0 +1,43 @@
+properties_version 0x101
+supplier 1
+contact 2
+name 3
+shortname bochsga
+release 5 1.0
+
+requires udi 0x101
+requires udi_physio 0x101
+requires udi_bridge 0x101
+requires udi_gfx 0x101
+
+meta 1 udi_bridge
+meta 2 udi_gfx
+#meta 3 udi_gio
+
+parent_bind_ops 1 0 1 1        # bridge, rgn 0, ops 1, cb 1
+child_bind_ops 2 0 2   # Provider
+#parent_bind_ops 3 0 2 3       # GIO bound to 3D provider
+
+#enumerates 102 1 1 3  gio_type string software3d
+
+# - Classic non-PCI version
+device 100 1  bus string system  sysbus_io_addr_lo ubit32 0x01CE  sysbus_io_size ubit32 2  sysbys_mem_addr_lo ubit32 0xE0000000 sysbus_mem_size 0x400000
+# - PCI Version (Non-indexed registers at offset 0x500 in BAR2 MMIO)
+device 101 1  bus string pci  pci_vendor_id ubit32 0x1234  pci_device_id ubit32 0x1111  pci_base_class ubit32 0x03  pci_sub_clais ubit32 0x00  pci_prog_if ubit32 0x00
+
+# Messages
+message 1      John Hodge (thePowersGang)
+message 2      [email protected]
+message 3      Bochs Graphics Adapter
+message        5       BochsGA
+message 100    BochsGA ISA Device
+message 101    BochsGA PCI Device
+
+message 1001   "Unknown property passed to %s: %i"
+
+module bochsga
+region 0
+
+# Source-only udiprops
+compile_options -Wall
+source_files bochsga_core.c
diff --git a/UDI/drivers/helpers.h b/UDI/drivers/helpers.h
new file mode 100644 (file)
index 0000000..dde9816
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * UDI Driver helper macros
+ */
+#ifndef _UDI_HELPERS_H_
+#define _UDI_HELPERS_H_
+
+#if DEBUG_ENABLED
+# define DEBUG_OUT(fmt, v...)  udi_debug_printf("%s: "fmt"\n", __func__ ,## v) 
+#else
+# define DEBUG_OUT(...)        do{}while(0)
+#endif
+
+#define ARRAY_COUNT(arr)       (sizeof(arr)/sizeof(arr[0]))
+
+#define __EXPJOIN(a,b) a##b
+#define _EXPJOIN(a,b)  __EXPJOIN(a,b)
+#define _EXPLODE(params...)    params
+#define _ADDGCB(params...)     (udi_cb_t *gcb, params)
+#define CONTIN(suffix, call, args, params)     extern void _EXPJOIN(suffix##$,__LINE__) _ADDGCB params;\
+       call( _EXPJOIN(suffix##$,__LINE__), gcb, _EXPLODE args); } \
+       void _EXPJOIN(suffix##$,__LINE__) _ADDGCB params { \
+       rdata_t *rdata = gcb->context; \
+       (void)rdata;
+
+/* Copied from http://projectudi.cvs.sourceforge.net/viewvc/projectudi/udiref/driver/udi_dpt/udi_dpt.h */
+#define UDIH_SET_ATTR_BOOLEAN(attr, name, val) \
+               udi_strcpy((attr)->attr_name, (name)); \
+               (attr)->attr_type = UDI_ATTR_BOOLEAN; \
+               (attr)->attr_length = sizeof(udi_boolean_t); \
+               UDI_ATTR32_SET((attr)->attr_value, (val))
+
+#define UDIH_SET_ATTR32(attr, name, val)       \
+               udi_strcpy((attr)->attr_name, (name)); \
+               (attr)->attr_type = UDI_ATTR_UBIT32; \
+               (attr)->attr_length = sizeof(udi_ubit32_t); \
+               UDI_ATTR32_SET((attr)->attr_value, (val))
+
+#define UDIH_SET_ATTR_ARRAY8(attr, name, val, len) \
+               udi_strcpy((attr)->attr_name, (name)); \
+               (attr)->attr_type = UDI_ATTR_ARRAY8; \
+               (attr)->attr_length = (len); \
+               udi_memcpy((attr)->attr_value, (val), (len))
+
+#define UDIH_SET_ATTR_STRING(attr, name, val, len) \
+               udi_strcpy((attr)->attr_name, (name)); \
+               (attr)->attr_type = UDI_ATTR_STRING; \
+               (attr)->attr_length = (len); \
+               udi_strncpy_rtrim((char *)(attr)->attr_value, (val), (len))
+#define UDIH_SET_ATTR_STRFMT(attr, name, maxlen, fmt, v...) \
+               udi_strcpy((attr)->attr_name, (name)); \
+               (attr)->attr_type = UDI_ATTR_STRING; \
+               (attr)->attr_length = udi_snprintf((char *)(attr)->attr_value, (maxlen), (fmt) ,## v )
+
+/**
+ * \brief UDI PIO Helpers
+ */
+struct s_pio_ops {
+       udi_pio_trans_t *trans_list;
+       udi_ubit16_t    list_length;
+       udi_ubit16_t    pio_attributes;
+       udi_ubit32_t    regset_idx;
+       udi_ubit32_t    base_offset;
+       udi_ubit32_t    length;
+};
+#define UDIH_PIO_OPS_ENTRY(list, attr, regset, base, len)      {list, ARRAY_COUNT(list), attr, regset, base, len}
+
+
+#define UDIH_INIT_PIO(fcnname, _array, index_field, final_code) \
+       void fcnname(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle) {\
+               rdata_t *rdata = gcb->context; \
+               if( rdata->index_field != (udi_index_t)-1 ) { \
+                       rdata->pio_handles[rdata->index_field] = new_pio_handle; \
+               }\
+               rdata->index_field ++; \
+               if( rdata->index_field < sizeof(_array)/sizeof(_array[0]) ) { \
+                       const struct s_pio_ops  *ops = &pio_ops[rdata->index_field]; \
+                       udi_pio_map(bus_dev_bind__pio_map, gcb, \
+                               ops->regset_idx, ops->base_offset, ops->length, \
+                               ops->trans_list, ops->list_length, \
+                               UDI_PIO_LITTLE_ENDIAN, 0, 0 \
+                               ); \
+                       return ; \
+               } \
+               final_code \
+       }
+
+#endif
diff --git a/UDI/drivers/helpers_gfx.h b/UDI/drivers/helpers_gfx.h
new file mode 100644 (file)
index 0000000..999a408
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * UDI Driver Helper Macros
+ *
+ * GFX-specific helpers
+ */
+#ifndef _HELPERS_GFX_H_
+#define _HELPERS_GFX_H_
+
+#if __STDC_VERSION__ < 199901L
+# define       inline
+#endif
+
+typedef struct {
+       udi_index_t     op;
+       udi_ubit32_t    arg_1;
+       udi_ubit32_t    arg_2;
+       udi_ubit32_t    arg_3;
+} gfxhelpers_op_t;
+
+typedef struct {
+       udi_index_t     op_count;
+       const gfxhelpers_op_t   *ops;
+} gfxhelpers_op_map_t;
+
+static inline void gfxhelpers_return_range_simple(
+       udi_gfx_range_connector_ack_op_t *callback, udi_gfx_range_cb_t *cb,
+       udi_ubit32_t min, udi_ubit32_t max, udi_ubit32_t step
+       )
+{
+       
+}
+
+static inline void gfxhelpers_return_range_set(
+       udi_gfx_range_connector_ack_op_t *callback, udi_gfx_range_cb_t *cb,
+       udi_ubit32_t count, ...
+       )
+{
+       
+}
+
+static inline void gfxhelpers_return_range_fixed(
+       udi_gfx_range_connector_ack_op_t *callback, udi_gfx_range_cb_t *cb,
+       udi_ubit32_t value
+       )
+{
+       gfxhelpers_return_range_simple(callback, cb, value, value, 1);
+}
+
+#endif
+
index b6a1689..d4e58aa 100644 (file)
@@ -8,8 +8,14 @@
 #ifndef _NE2000_COMMON_H_
 #define _NE2000_COMMON_H_
 
+#define UDI_VERSION    0x101
+#define UDI_PHYSIO_VERSION     0x101
+#define UDI_PCI_VERSION 0x101
+#define UDI_NIC_VERSION        0x101
+
 #include <udi.h>
 #include <udi_physio.h>
+#include <udi_pci.h>
 #include <udi_nic.h>
 
 #include "ne2000_hw.h"
@@ -77,10 +83,15 @@ typedef struct
                (attr)->attr_type = UDI_ATTR_STRING; \
                (attr)->attr_length = (len); \
                udi_strncpy_rtrim((char *)(attr)->attr_value, (val), (len))
-#define NE2K_SET_ATTR_STRFMT(attr, name, maxlen, fmt, v...) \
+#define NE2K_SET_ATTR_STRFMT(attr, name, maxlen, fmt, ...) \
                udi_strcpy((attr)->attr_name, (name)); \
                (attr)->attr_type = UDI_ATTR_STRING; \
-               (attr)->attr_length = udi_snprintf((char *)(attr)->attr_value, (maxlen), (fmt) ,## v )
+               (attr)->attr_length = udi_snprintf((char *)(attr)->attr_value, (maxlen), (fmt) ,## __VA_ARGS__ )
+
+extern udi_usage_ind_op_t      ne2k_usage_ind;
+extern udi_enumerate_req_op_t  ne2k_enumerate_req;
+extern udi_devmgmt_req_op_t    ne2k_devmgmt_req;
+extern udi_final_cleanup_req_op_t      ne2k_final_cleanup_req;
 
 extern udi_channel_event_ind_op_t      ne2k_bus_dev_channel_event_ind;
 extern udi_bus_bind_ack_op_t   ne2k_bus_dev_bus_bind_ack;
index 2e44db1..d630a8d 100644 (file)
@@ -5,8 +5,6 @@
  * ne2000_core.c
  * - UDI initialisation 
  */
-#include <udi.h>
-#include <udi_nic.h>
 #include "ne2000_common.h"
 
 enum {
@@ -66,6 +64,9 @@ void ne2k_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
        case UDI_ENUMERATE_NEXT:
                udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
                break;
+       default:
+               udi_assert(!"invalid enumeration_level");
+               break;
        }
 }
 void ne2k_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
@@ -90,6 +91,9 @@ void ne2k_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb)
                udi_bus_bind_req( bus_bind_cb );
                // continue at ne2k_bus_dev_bus_bind_ack
                return; }
+       default:
+               udi_assert(!"invalid channel event");
+               break;
        }
 }
 void ne2k_bus_dev_bus_bind_ack(udi_bus_bind_cb_t *cb,
@@ -240,7 +244,7 @@ void ne2k_nd_ctrl_bind__rx_chan_ok(udi_cb_t *gcb, udi_channel_t new_channel)
        cb->max_perfect_multicast = 0;
        cb->max_total_multicast = 0;
        cb->mac_addr_len = 6;
-       memcpy(cb->mac_addr, rdata->macaddr, 6);
+       udi_memcpy(cb->mac_addr, rdata->macaddr, 6);
        udi_nsr_bind_ack( cb, UDI_OK );
        // = = = =
 }
index dda3577..9b4b3c3 100644 (file)
@@ -5,6 +5,8 @@
  * ne2000_rx.c
  * - Receive Code
  */
+#define UDI_VERSION    0x101
+#define UDI_NIC_VERSION        0x101
 #include <udi.h>
 #include <udi_nic.h>
 #include "ne2000_common.h"
@@ -45,7 +47,7 @@ void ne2k_intr__rx_ok(udi_cb_t *gcb)
                rdata->rx_next_cb = rx_cb->chain;
                rx_cb->chain = NULL;
                udi_debug_printf("ne2k_intr__rx_ok: Initialising buffer\n");
-               udi_buf_write(ne2k_rx__buf_allocated, UDI_GCB(rx_cb), NULL, 1520, rx_cb->rx_buf, 0, 0, NULL);
+               udi_buf_write(ne2k_rx__buf_allocated, UDI_GCB(rx_cb), NULL, 1520, rx_cb->rx_buf, 0, 0, UDI_NULL_BUF_PATH);
        }
        else
        {
index b943ae8..0e54fad 100644 (file)
@@ -5,6 +5,8 @@
  * ne2000_tx.c
  * - Transmit Code
  */
+#define UDI_VERSION    0x101
+#define UDI_NIC_VERSION        0x101
 #include <udi.h>
 #include <udi_nic.h>
 #include "ne2000_common.h"
index cfe7770..510bc47 100644 (file)
@@ -5,8 +5,12 @@
  * uart16c550.c
  * - UDI initialisation 
  */
+#define UDI_VERSION    0x101
+#define UDI_PCI_VERSION        0x101
+#define UDI_PHYSIO_VERSION     0x101
 #include <udi.h>
 #include <udi_physio.h>
+#include <udi_pci.h>
 #include "uart16c550_common.h"
 
 #include "uart16c550_pio.h"
@@ -100,7 +104,7 @@ void uart_bus_dev_bus_bind_ack(udi_bus_bind_cb_t *cb,
 void uart_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle)
 {
        rdata_t *rdata = gcb->context;
-       if( rdata->init.pio_index != -1 )
+       if( rdata->init.pio_index != (udi_index_t)-1 )
        {
                rdata->pio_handles[rdata->init.pio_index] = new_pio_handle;
        }
diff --git a/UDI/gfx_spec_issues.txt b/UDI/gfx_spec_issues.txt
new file mode 100644 (file)
index 0000000..e97aea4
--- /dev/null
@@ -0,0 +1,31 @@
+
+
+- Indexed engine operator list (would be better as second set of calls)
+ > Arguments can be passed using custom attributes
+- GL-centric operations (would be better with read_buffer/write_buffer calls)
+- No status returned from operations most
+- Input data format specifcation
+ > Engine operator list specifies it, but in an abstract way (which would require quite smart code to determine)
+ > Doable though, but having a RO property on the engine that notes if it uses a standard pixel format would be nice
+
+
+Engine inspection API:
+> Readonly? Property for number of operations
+ - Readonly because modifcation of the count is not possible
+ - Attributes can be read, so that's your config mechanisim
+> udi_gfx_engine_getop_req(udi_gfx_state_cb_t *cb);
+> udi_gfx_engine_getop_ack(udi_gfx_state_cb_t *cb, udi_ubit8_t operation, udi_ubit32_t arg1, udi_ubit32_t arg2, udi_ubit32_t arg3);
+
+
+Buffer manipulation API:
+
+  struct {
+      udi_cb_t gcb;
+      udi_index_t buffer_idx;
+      udi_ubit32_t offset;
+      udi_buffer_t *data;
+  } udi_gfx_buffer_cb_t;
+
+> udi_gfx_buffer_write_req(udi_gfx_buffer_cb_t *cb);
+> udi_gfx_buffer_write_ack(udi_gfx_buffer_cb_t *cb, udi_status_t status);
+> (OPTIONAL) udi_gfx_buffer_read_req(udi_gfx_buffer_cb_t *cb);
index 50c7077..76dac7b 100644 (file)
@@ -4,6 +4,16 @@
 #ifndef _UDI_H_
 #define _UDI_H_
 
+#ifndef UDI_VERSION
+# error "Please define UDI_VERSION before including"
+#endif
+#if UDI_VERSION < 0x100
+# error "Requesting an unsupported UDI version (pre 1.0)"
+#endif
+#if UDI_VERSION > 0x101
+# error "Requesting an unsupported UDI version (post 1.01)"
+#endif
+
 #include <stdint.h>
 #include <stdarg.h>
 
diff --git a/UDI/include/udi_gfx.h b/UDI/include/udi_gfx.h
new file mode 100644 (file)
index 0000000..cd7db75
--- /dev/null
@@ -0,0 +1,850 @@
+/**
+ * Summary: udi_gfx.h
+ * Contains the graphics metalanguage interface details
+ *
+ * Author:
+ *     Marcel Sondaar
+ *
+ * License:
+ *     <Public Domain>
+ *
+ * Origin:
+ *     http:/*www.d-rift.nl/combuster/mos3/?p=viewsource&file=/include/common/udi_gfx.h*/
+ */
+
+/* note that the specification, and thus, the contents of this file is not fixed.*/
+
+#ifndef __UDI_GFX_H__
+#define __UDI_GFX_H__
+
+#include <udi.h>
+
+#ifndef UDI_GFX_VERSION
+#error "UDI_GFX_VERSION not defined."
+#elif UDI_GFX_VERSION != 0x101
+#error "UDI_GFX_VERSION not supported."
+#endif
+
+/**
+ * Enumeration: UDI_GFX_PROP
+ * Lists the various UDI properties
+ */
+
+/* General state properties*/
+/* Constant: UDI_GFX_PROP_ENABLE
+ *
+ * Valid values:
+ *     0 - disabled
+ *     1 - enabled
+ *     2 - reset
+ *
+ * Ranges:
+ *     Must include at least 1
+ *
+ * The primary state of the connector or engine. An enabled state indicates
+ * it is functioning and generating live output. A disabled state is one where
+ * it is not contributing to any output but is otherwise functional. Finally
+ * the reset state is where the driver is free to deallocate all resources 
+ * corresponding to this component and trash any state not referenced by other
+ * components.
+ *
+ * A disabled or reset engine forwards all data from the previous stage 
+ * unmodified. The disabled state indicates that the component might be 
+ * returned to its enabled state within short notice.
+ *
+ * A disabled connector will not send pixel data, but can perform other 
+ * initialisation communication such as DDC. A reset connector will not respond
+ * in any fashion and can not be used for other purposes. Hardware is expected
+ * to be powered down in such state.
+ *
+ * Users should expect significant delays when moving components in and out of
+ * the reset state. Moving engines between the enabled and disabled state should
+ * take effect within one frame, such transition should take effect on a frame 
+ * boundary when supported.
+ */
+#define UDI_GFX_PROP_ENABLE 0
+
+#define UDI_GFX_PROP_ENABLE_DISABLED 0
+#define UDI_GFX_PROP_ENABLE_ENABLED 1
+#define UDI_GFX_PROP_ENABLE_RESET 2
+/* Constant: UDI_GFX_PROP_INPUT
+ *
+ * Valid values:
+ *     Any valid engine ID, provided no dependency cycles are created, or -1
+ *
+ * Ranges:
+ *     Any non-empty set of valid values. Often hardwired.
+ *
+ * Points to the engine that is processed before this unit. In the case of a 
+ * connector, it points to the last engine in a pipeline, and each engine points 
+ * to the next engine in the sequence. A value of -1 indicates a source that 
+ * only yields black pixels. Implementations must not allow cyclic structures. 
+ * Changing this value may reallocate resources, and engines that are no longer 
+ * referenced may lose their data (but not their state) when it is not part of 
+ * any pipeline. If preservation is required, the ENABLE state should be used
+ * instead. Valid ranges includes one or more from the list of engines and -1 
+ * combined. In most cases, this property can not be modified.
+ */
+#define UDI_GFX_PROP_INPUT 1
+/* Constant: UDI_GFX_PROP_WIDTH
+ *
+ * Valid values:
+ *     Any non-zero positive number.
+ *
+ * Ranges:
+ *     Contains at least one valid value. Often only multiples of UNIT_WIDTH
+ *     or a power of two are allowed. May be hardwired.
+ *
+ * Contains the amount of pixels in the horizontal direction. For connectors, 
+ * this is the amount of data pixels rendered horizontally. For engines, this 
+ * is the width in pixels of the image. Pixels requested from an engine outside 
+ * the range (0..width-1) are defined according to the <UDI_GFX_PROP_CLIP> 
+ * property. In some cases, hardware may support only fixed combinations of 
+ * width and height. In such cases, changing the width will also change the 
+ * height to a corresponding valid number. Valid ranges include any values
+ * strictly above zero. For connectors, expect large continuous ranges, large
+ * ranges with a certain modulus, a limited number of fixed values, or a
+ * constant value.
+ */
+#define UDI_GFX_PROP_WIDTH 2
+/* Constant: UDI_GFX_PROP_HEIGHT
+ *
+ * Valid values:
+ *     Any non-zero positive number.
+ *
+ * Ranges:
+ *     Contains at least one valid value. Often only multiples of UNIT_HEIGHT
+ *     or a power of two are allowed. May be hardwired.
+ *
+ * Contains the amount of pixels in the vertical direction. Functions similar
+ * to the width property, but changing it will not alter the width property,
+ * and it's range at any time contains the valid range for the currently
+ * selected width.
+ */
+#define UDI_GFX_PROP_HEIGHT 3
+
+/* Constant: UDI_GFX_PROP_CUSTOM
+ * The first property index of the driver's custom range. These are not assigned
+ * directly assigned by the UDI specification, but may be specified in the
+ * operator tree.
+ */
+#define UDI_GFX_PROP_CUSTOM 1024
+
+/* engine properties*/
+
+/* Constant: UDI_GFX_PROP_CLIP
+ *
+ * Valid values:
+ *     0 - points outside width x height are passed unmodified from input
+ *     1 - the engine's contents is tiled with size width x height
+ *     2 - points outside the width overflow into the y coordinate
+ *     3 - points outside the height overflow into the x coordinate
+ *
+ * Ranges:
+ *     Hardwired zero for connectors. Any non-empty subset for engines, usually
+ *     hardwired.
+ *
+ * For engines, contains the behaviour for pixels requested outside the width
+ * and height of the engine. Can be either 0 (pass from next stage), 1 (the
+ * coordinates are wrapped modulus the height and width), 2 (the coordinates
+ * overflow onto the next scanline horizontally, and wrap vertically), 3 (the
+ * coordinates overflow onto the next column vertically, and wrap horizontally).
+ * Valid ranges contain one or more of these options. For overlays and sprites,
+ * a value 0 is common. For framebuffers, 2 is the most common value. For
+ * connectors, this property is always 0 since they do not store pixel data
+ */
+#define UDI_GFX_PROP_CLIP 4
+
+/* Constant: UDI_GFX_PROP_UNIT_WIDTH
+ *
+ * Valid values:
+ *     Any non-zero positive value
+ *
+ * Ranges:
+ *     Any non-empty set of valid values. May be hardwired to 1 for
+ *     framebuffers, or a range of small values for hardware scaling, or any
+ *     larger hardwired number or set for tiling engines.
+ *
+ * Tiles are used to indicate that the hardware groups sets of pixels and have
+ * each group share certain properties, i.e. color or tile index, or share the
+ * same chroma subsample with only a different intensity. If the engine has no
+ * such grouping, or shares all properties over the entire contents, the value
+ * of this property should be 1. Some tile examples include rescaling, where a
+ * tile width of 2 indicates a pixel doubling in X direction, or in text mode
+ * where a tile width of 8 or 9 corresponds with the width of common bitmap
+ * fonts
+ */
+#define UDI_GFX_PROP_UNIT_WIDTH 5
+
+/* Constant: UDI_GFX_PROP_UNIT_HEIGHT
+ *
+ * Valid values:
+ *     Any non-zero positive value
+ *
+ * Ranges:
+ *     Any non-empty set of valid values. May be hardwired to 1 for
+ *     framebuffers, or a range of small values for hardware scaling, or any
+ *     larger hardwired number or set for tiling engines.
+ *
+ * See <UDI_GFX_PROP_UNIT_WIDTH>, but for the Y direction. Common values are
+ * 1-2 for framebuffers (doublescanning on or off), identical to the tile
+ * width, or mostly independent.
+ */
+#define UDI_GFX_PROP_UNIT_HEIGHT 6
+
+/* Constant: UDI_GFX_PROP_TRANSLATEX
+ * 
+ * Valid values:
+ *     Any, signed value.
+ *
+ * Ranges:
+ *     Any non-empty set. Typical values are hardwired zero, continuous
+ *     between -WIDTH and WIDTH, -WIDTH to zero inclusive, or all possible values
+ *
+ * The horizontal offset where drawing starts. A positive value means the top-left 
+ * corner moves towards the right end of the screen, a negative value moves the
+ * origin off the screen on the left side. Clipped areas moved off the screen do 
+ * not reappear on the opposite side.
+ *
+ * With clipping enabled, this field combined with <UDI_GFX_PROP_WIDTH> 
+ * determines the area where the image should be drawn, which is the horizontal 
+ * range from UDI_GFX_PROP_TRANSLATEX to UDI_GFX_PROP_WIDTH + 
+ * UDI_GFX_PROP_TRANSLATEX - 1
+ */
+#define UDI_GFX_PROP_TRANSLATEX 7
+
+/* Constant: UDI_GFX_PROP_TRANSLATEY
+ *
+ * Valid values:
+ *     Any signed value.
+ *
+ * Ranges:
+ *     Any non-empty set. Typical values are hardwired zero, continuous
+ *     between -WIDTH and WIDTH, or all possible values
+ *
+ * See <UDI_GFX_PROP_TRANSLATEX> but for the Y direction.
+ */
+#define UDI_GFX_PROP_TRANSLATEY 8
+
+#define UDI_GFX_PROP_GL_VERSION 14
+#define UDI_GFX_PROP_GLES_VERSION 15
+#define UDI_GFX_PROP_STATE_BLOCK 16
+#define UDI_GFX_PROP_COLOR_BITS 22
+#define UDI_GFX_PROP_GL_TARGET 23
+
+/* Constant: UDI_GFX_PROP_STOCK_FORMAT
+ *
+ * Value:
+ *     Zero, or any constant from <UDI_GFX_STOCK_FORMAT>
+ *
+ * Ranges:
+ *     Any non-empty set of valid values.
+ *
+ * This field indicates the storage format is one from a limited set of 
+ * typical configurations. If the field is zero, the engine is not knowingly
+ * configured as a common framebuffer. If nonzero, the operator chain and any
+ * dependent settings are defined to be functionally equivalent to that of a
+ * typical framebuffer device.
+ *
+ * The value zero does not imply that the device does not actually follow a
+ * set convention. This saves drivers from writing elaborate checking code
+ * to determine the condition in question.
+ *
+ * Writing this field potentially modifies other property fields within the
+ * same engine to establish the requested configuration. Manually writing such 
+ * properties after changing this setting may in turn revert this property to
+ * the zero state, even if there was no modification or the behaviour is still
+ * as previously advertised by this property.
+ */
+#define UDI_GFX_PROP_STOCK_FORMAT 27
+
+/* Constant: UDI_GFX_PROP_OPERATOR_COUNT
+ * 
+ * Valid values:
+ *     Any non-zero positive number
+ * 
+ * Ranges:
+ *     Most likely constant. Can be any set of valid values.
+ *
+ * The current value is the number of entries in the operator tree that can
+ * be requested for this engine using <udi_gfx_get_engine_operator_req> and
+ * <udi_gfx_get_engine_operator_ack>
+ */
+#define UDI_GFX_PROP_OPERATOR_COUNT 28
+
+#if 0
+/* properties for removal:*/
+#define UDI_GFX_PROP_STORE_COUNT 24       /* not generic*/
+#define UDI_GFX_PROP_STORE_WIDTH 9        /* not generic*/
+#define UDI_GFX_PROP_STORE_HEIGHT 10      /* not generic*/
+#define UDI_GFX_PROP_STORE_BITS 11        /* not generic*/
+#define UDI_GFX_PROP_PALETTE 1024         /* optional, can be derived from the operator tree*/
+#define UDI_GFX_PROP_BUFFER 1025          /* optional, can be derived from the operator tree*/
+#define UDI_GFX_PROP_TILESHEET 1026       /* optional, can be derived from the operator tree*/
+#define UDI_GFX_PROP_OPERATOR_INDEX 17    /* deprecated for dedicated methods*/
+#define UDI_GFX_PROP_OPERATOR_OPCODE 18   /* deprecated for dedicated methods*/
+#define UDI_GFX_PROP_OPERATOR_ARG_1 19    /* deprecated for dedicated methods*/
+#define UDI_GFX_PROP_OPERATOR_ARG_2 20    /* deprecated for dedicated methods*/
+#define UDI_GFX_PROP_OPERATOR_ARG_3 21    /* deprecated for dedicated methods*/
+#define UDI_GFX_PROP_SOURCE_WIDTH 12      /* should have been documented when I still knew what it did.*/
+#define UDI_GFX_PROP_SOURCE_HEIGHT 13     /* should have been documented when I still knew what it did.*/
+#define UDI_GFX_PROP_INPUTX 25            /* should have been documented when I still knew what it did.*/
+#define UDI_GFX_PROP_INPUTY 26            /* should have been documented when I still knew what it did.*/
+#endif
+
+/* connector properties*/
+#define UDI_GFX_PROP_SIGNAL 23
+#define UDI_GFX_PROP_CONNECTOR_TYPE 24
+#define UDI_GFX_PROP_VGA_H_FRONT_PORCH 25
+#define UDI_GFX_PROP_VGA_H_BACK_PORCH 26
+#define UDI_GFX_PROP_VGA_H_SYNC 27
+#define UDI_GFX_PROP_VGA_V_FRONT_PORCH 28
+#define UDI_GFX_PROP_VGA_V_BACK_PORCH 29
+#define UDI_GFX_PROP_VGA_V_SYNC 30
+#define UDI_GFX_PROP_DOT_CLOCK 31
+#define UDI_GFX_PROP_VGA_H_SYNC_POL 32
+#define UDI_GFX_PROP_VGA_V_SYNC_POL 33
+
+/**
+ * Enumeration: UDI_GFX_SIGNAL
+ * Lists the various signal types
+ */
+#define UDI_GFX_SIGNAL_HIDDEN 0
+#define UDI_GFX_SIGNAL_INTEGRATED 0
+#define UDI_GFX_SIGNAL_RGBHV 1
+#define UDI_GFX_SIGNAL_RGBS 2
+#define UDI_GFX_SIGNAL_RGSB 3
+#define UDI_GFX_SIGNAL_YPBPR 4
+#define UDI_GFX_SIGNAL_DVID 5
+#define UDI_GFX_SIGNAL_YUV 6
+#define UDI_GFX_SIGNAL_YIQ 7
+#define UDI_GFX_SIGNAL_Y_UV 8
+#define UDI_GFX_SIGNAL_Y_IQ 9
+#define UDI_GFX_SIGNAL_HDMI 10
+#define UDI_GFX_SIGNAL_TEXT 11
+#define UDI_GFX_SIGNAL_CUSTOM 12
+
+/**
+ * Enumeration: UDI_GFX_CONNECTOR
+ * Lists the various external connectors
+ */
+#define UDI_GFX_CONNECTOR_HIDDEN 0
+#define UDI_GFX_CONNECTOR_VGA 1
+#define UDI_GFX_CONNECTOR_DVI 2
+#define UDI_GFX_CONNECTOR_SVIDEO 3
+#define UDI_GFX_CONNECTOR_COMPONENT 4
+#define UDI_GFX_CONNECTOR_HDMI 5
+#define UDI_GFX_CONNECTOR_RF 6
+#define UDI_GFX_CONNECTOR_SCART 7
+#define UDI_GFX_CONNECTOR_COMPOSITE 8
+#define UDI_GFX_CONNECTOR_MEMBUFFER 9
+
+/**
+ * Enumeration: UDI_GFX_OPERATOR
+ * Lists the display output operator
+ */
+#define UDI_GFX_OPERATOR_RGB     0 /* output = (color) red(a1) + green(a2) + blue(a3) (each component is UDI_GFX_PROP_COLOR_BITS*/
+#define UDI_GFX_OPERATOR_YUV     1 /* output = (color) Y(a1) + U(a2) + V(a3)*/
+#define UDI_GFX_OPERATOR_YIQ     2 /* output = (color) Y(a1) + I(a2) + Q(a3)*/
+#define UDI_GFX_OPERATOR_I       3 /* output = (color) intensity(a1)*/
+#define UDI_GFX_OPERATOR_ALPHA   4 /* output = (color) a1 + alpha(a2)*/
+#define UDI_GFX_OPERATOR_ADD     5 /* output = a1 + a2 + v3*/
+#define UDI_GFX_OPERATOR_SUB     6 /* output = a1 - a2 - v3*/
+#define UDI_GFX_OPERATOR_MUL     7 /* output = a1 * a2*/
+#define UDI_GFX_OPERATOR_DIV     8 /* output = a1 / a2*/
+#define UDI_GFX_OPERATOR_MAD     9 /* output = a1 * a2 + a3*/
+#define UDI_GFX_OPERATOR_FRC    10 /* output = (a1 * a2) / a3*/
+#define UDI_GFX_OPERATOR_SHR    11 /* output = a1 >> (a2 + v3)*/
+#define UDI_GFX_OPERATOR_SHL    12 /* output = a1 << (a2 + v3)*/
+#define UDI_GFX_OPERATOR_ROR    13 /* output = a1 >> a2 (over a3 bits)*/
+#define UDI_GFX_OPERATOR_ROL    14 /* output = a1 << a2 (over a3 bits)*/
+#define UDI_GFX_OPERATOR_SAR    15 /* output = a1 >> a2 (width is a3 bits, i.e. empties are filled with bit a3-1)*/
+#define UDI_GFX_OPERATOR_SAL    16 /* output = a1 <<< (a2 + v3) (empties filled with bit 0)*/
+#define UDI_GFX_OPERATOR_AND    17 /* output = a1 & a2*/
+#define UDI_GFX_OPERATOR_OR     18 /* output = a1 | a2 | v3*/
+#define UDI_GFX_OPERATOR_NOT    19 /* output = ~a1*/
+#define UDI_GFX_OPERATOR_XOR    20 /* output = a1 ^ a2 ^ v3*/
+#define UDI_GFX_OPERATOR_NEG    21 /* output = -a1*/
+#define UDI_GFX_OPERATOR_SEG    22 /* output = (a1 >> v2) & (2**v3-1) (select v3 bits starting from bit v2)*/
+#define UDI_GFX_OPERATOR_RANGE  23 /* output = (a1 > a2) ? a2 : ((a1 < a3) ? a3 : a1)*/
+#define UDI_GFX_OPERATOR_CONST  24 /* output = v1*/
+#define UDI_GFX_OPERATOR_ATTR   25 /* output = property[a1 + v2]*/
+#define UDI_GFX_OPERATOR_SWITCH 26 /* output = output[(a1 % v3) + v2]*/
+#define UDI_GFX_OPERATOR_BUFFER 27 /* output = buffer[a1][a2] (buffer is v3 bits per entry)*/
+#define UDI_GFX_OPERATOR_X      28 /* output = output x pixel*/
+#define UDI_GFX_OPERATOR_Y      29 /* output = output y pixel*/
+#define UDI_GFX_OPERATOR_TX     30 /* output = horizontal tile index belonging to output pixel*/
+#define UDI_GFX_OPERATOR_TY     31 /* output = vertical tile index belonging to output pixel*/
+#define UDI_GFX_OPERATOR_TXOFF  32 /* output = horizontal offset from start of tile*/
+#define UDI_GFX_OPERATOR_TYOFF  33 /* output = vertical offset from start of tile*/
+#define UDI_GFX_OPERATOR_INPUT  34 /* output = input engine[x][y]   component v1*/
+#define UDI_GFX_OPERATOR_DINPUT 35 /* output = input engine[a1][a2] component v3*/
+
+/* Enumeration: UDI_GFX_STOCK_FORMAT
+ * Lists stock configurations
+ *
+ * When a stock configuration is used, the device is set to behave as a 
+ * simple framebuffer device. The <UDI_GFX_PROP_WIDTH> and <UDI_GFX_PROP_HEIGHT>
+ * determine the virtual size of the framebuffer, and <UDI_GFX_PROP_TRANSLATEX>
+ * and <UDI_GFX_PROP_TRANSLATEY> indicate the offset into that framebuffer 
+ * that is visible (which are typically restricted to negative values)
+ */
+#define UDI_GFX_STOCK_FORMAT_UNKNOWN  0
+#define UDI_GFX_STOCK_FORMAT_R8G8B8X8 1
+#define UDI_GFX_STOCK_FORMAT_B8G8R8X8 2
+#define UDI_GFX_STOCK_FORMAT_R8G8B8   3
+#define UDI_GFX_STOCK_FORMAT_B8G8R8   4
+#define UDI_GFX_STOCK_FORMAT_R5G6B5   5
+#define UDI_GFX_STOCK_FORMAT_B5G6R5   6
+#define UDI_GFX_STOCK_FORMAT_R5G5B5X1 7
+#define UDI_GFX_STOCK_FORMAT_B5G5R5X1 8
+#define UDI_GFX_STOCK_FORMAT_N8 9
+
+/* Enumeration: UDI_GFX_BUFFER_INFO_FLAG*/
+/* Lists behavioural patterns for direct buffer accesses.*/
+/**/
+#define UDI_GFX_BUFFER_INFO_FLAG_R              0x0001  /* buffer can be read*/
+#define UDI_GFX_BUFFER_INFO_FLAG_W              0x0002  /* buffer can be written*/
+#define UDI_GFX_BUFFER_INFO_FLAG_BITALIGN_ENTRY 0x0004  /* for non-multiple-of-eight buffer slot sizes, align on byte boundary every unit*/
+#define UDI_GFX_BUFFER_INFO_FLAG_BITALIGN_ROW   0x0008  /* for non-multiple-of-eight buffer slot sizes, align only the start of the row*/
+
+
+/* Constant: UDI_GFX_PROVIDER_OPS_NUM*/
+/* the ops number used for the graphics driver*/
+#define UDI_GFX_PROVIDER_OPS_NUM 1
+
+/* Constant: UDI_GFX_CLIENT_OPS_NUM*/
+/* the ops number used for the graphics application*/
+#define UDI_GFX_CLIENT_OPS_NUM 2
+
+/* Structure: udi_gfx_bind_cb_t*/
+/* Contains the operations of a driver binding request*/
+typedef struct {
+    /* Variable: gcb*/
+    /* The main control block*/
+    udi_cb_t gcb;    
+} udi_gfx_bind_cb_t;
+#define UDI_GFX_BIND_CB_NUM 1
+
+/* Function: udi_block_bind_req*/
+/* function pointer prototype for connecting to a block device*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_block_bind_cb_t>*/
+/**/
+typedef void udi_gfx_bind_req_op_t (udi_gfx_bind_cb_t *cb );
+udi_gfx_bind_req_op_t udi_gfx_bind_req;
+
+/* Function: udi_gfx_bind_ack*/
+/* function pointer prototype for acknowledging a connection request*/
+/* */
+/* in:*/
+/*     cb      - A pointer to a <udi_gfx_bind_cb_t>*/
+/*     sockets - The number of addressable socket components*/
+/*     engines - The number of addressable engine components*/
+/*     status  - The result of the bind operation*/
+/**/
+typedef void udi_gfx_bind_ack_op_t (udi_gfx_bind_cb_t *cb, udi_index_t sockets, udi_index_t engines, udi_status_t status );
+udi_gfx_bind_ack_op_t udi_gfx_bind_ack;
+
+/* Function: udi_gfx_unbind_req*/
+/* function pointer prototype for disconnecting a block device*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_block_bind_cb_t>*/
+/**/
+typedef void udi_gfx_unbind_req_op_t (udi_gfx_bind_cb_t *cb );
+udi_gfx_unbind_req_op_t udi_gfx_unbind_req;
+
+/* Function: udi_gfx_unbind_ack*/
+/* function pointer prototype for connecting to a block device*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_bind_cb_t>*/
+/**/
+typedef void udi_gfx_unbind_ack_op_t (udi_gfx_bind_cb_t *cb );
+udi_gfx_unbind_ack_op_t udi_gfx_unbind_ack;
+
+/* Structure: udi_gfx_state_cb_t*/
+/* Contains the operations of a read/write transaction*/
+typedef struct {
+    /* Variable: gcb*/
+    /* The main control block*/
+    udi_cb_t gcb;    
+    udi_ubit32_t subsystem;
+    udi_ubit32_t attribute;
+} udi_gfx_state_cb_t;
+#define UDI_GFX_STATE_CB_NUM 2
+
+/* Function: udi_gfx_set_engine_req*/
+/* function pointer prototype for setting an engine state*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_set_engine_req_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+udi_gfx_set_engine_req_op_t udi_gfx_set_engine_req;
+
+/* Function: udi_gfx_set_connector_req*/
+/* function pointer prototype for setting an connector state*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_set_connector_req_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+udi_gfx_set_connector_req_op_t udi_gfx_set_connector_req;
+
+/* Function: udi_gfx_set_engine_ack*/
+/* function pointer prototype for setting an engine state*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_set_engine_ack_op_t (udi_gfx_state_cb_t *cb );
+udi_gfx_set_engine_ack_op_t udi_gfx_set_engine_ack;
+
+/* Function: udi_gfx_set_connector_ack*/
+/* function pointer prototype for setting an engine state*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_set_connector_ack_op_t (udi_gfx_state_cb_t *cb );
+udi_gfx_set_connector_ack_op_t udi_gfx_set_connector_ack;
+
+/* Function: udi_gfx_get_engine_req*/
+/* function pointer prototype for setting an engine state*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_get_engine_req_op_t (udi_gfx_state_cb_t *cb );
+udi_gfx_get_engine_req_op_t udi_gfx_get_engine_req;
+
+/* Function: udi_gfx_get_connector_req*/
+/* function pointer prototype for setting an connector state*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_get_connector_req_op_t (udi_gfx_state_cb_t *cb );
+udi_gfx_get_connector_req_op_t udi_gfx_get_connector_req;
+
+/* Function: udi_gfx_get_engine_ack*/
+/* function pointer prototype for setting an engine state*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_get_engine_ack_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+udi_gfx_get_engine_ack_op_t udi_gfx_get_engine_ack;
+
+/* Function: udi_gfx_get_connector_ack*/
+/* function pointer prototype for setting an engine state*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_get_connector_ack_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+udi_gfx_get_connector_ack_op_t udi_gfx_get_connector_ack;
+
+/* Function: udi_gfx_set_engine_nak*/
+/* function pointer prototype for setting an engine state*/
+/* */
+/* in:*/
+/*     cb     - A pointer to a <udi_gfx_state_cb_t>*/
+/*     status - An UDI status value indicative of the error*/
+/**/
+typedef void udi_gfx_set_engine_nak_op_t (udi_gfx_state_cb_t *cb, udi_status_t status);
+udi_gfx_set_engine_nak_op_t udi_gfx_set_engine_nak;
+
+/* Function: udi_gfx_set_connector_nak*/
+/* function pointer prototype for setting an engine state*/
+/* */
+/* in:*/
+/*     cb     - A pointer to a <udi_gfx_state_cb_t>*/
+/*     status - An UDI status value indicative of the error*/
+/**/
+typedef void udi_gfx_set_connector_nak_op_t (udi_gfx_state_cb_t *cb, udi_status_t status);
+udi_gfx_set_connector_nak_op_t udi_gfx_get_connector_nak;
+
+/* Structure: udi_gfx_range_cb_t*/
+/* Contains the operations of a range request transaction*/
+typedef struct {
+    /* Variable: gcb*/
+    /* The main control block*/
+    udi_cb_t gcb;    
+    udi_ubit32_t subsystem;
+    udi_ubit32_t attribute;
+    udi_buf_t * rangedata;  
+} udi_gfx_range_cb_t;
+#define UDI_GFX_RANGE_CB_NUM 3
+
+/* Function: udi_gfx_range_engine_req*/
+/* function pointer prototype for getting an engine property range*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_range_cb_t>*/
+/**/
+typedef void udi_gfx_range_engine_req_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_range_engine_req_op_t udi_gfx_range_engine_req;
+
+/* Function: udi_gfx_range_connector_req*/
+/* function pointer prototype for getting a connector property range*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_range_cb_t>*/
+/**/
+typedef void udi_gfx_range_connector_req_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_range_connector_req_op_t udi_gfx_range_connector_req;
+
+/* Function: udi_gfx_range_engine_ack*/
+/* function pointer prototype for replying an engine property range*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_range_cb_t>*/
+/**/
+typedef void udi_gfx_range_engine_ack_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_range_engine_ack_op_t udi_gfx_range_engine_ack;
+
+/* Function: udi_gfx_range_connector_ack*/
+/* function pointer prototype for replying a connector property range*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_range_cb_t>*/
+/**/
+typedef void udi_gfx_range_connector_ack_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_range_connector_ack_op_t udi_gfx_range_connector_ack;
+
+/* Function: udi_gfx_get_engine_operator_req*/
+/* function pointer prototype for requesting the engine operator layout*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_state_cb_t>*/
+/**/
+typedef void udi_gfx_get_engine_operator_req_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_get_engine_operator_req_op_t udi_gfx_get_engine_operator_req;
+
+/* Function: udi_gfx_get_engine_operator_ack*/
+/* function pointer prototype for replying the engine operator layout*/
+/* */
+/* in:*/
+/*     cb   - A pointer to a <udi_gfx_state_cb_t>*/
+/*     op   - The operator performed at this index*/
+/*     arg1 - the first argument to this operator*/
+/*     arg2 - the second argument to this operator*/
+/*     arg3 - the third argument to this operator*/
+/**/
+typedef void udi_gfx_get_engine_operator_ack_op_t (udi_gfx_range_cb_t *cb, udi_ubit32_t op, udi_ubit32_t arg1, udi_ubit32_t arg2, udi_ubit32_t arg3 );
+udi_gfx_get_engine_operator_ack_op_t udi_gfx_get_engine_operator_ack;
+
+
+
+/* Structure: udi_gfx_command_cb_t*/
+/* Contains the operations of a command sequence*/
+typedef struct {
+    /* Variable: gcb*/
+    /* The main control block*/
+    udi_cb_t gcb;    
+    udi_buf_t * commanddata;
+} udi_gfx_command_cb_t;
+#define UDI_GFX_COMMAND_CB_NUM 4
+
+/* Function: udi_gfx_connector_command_req*/
+/* function pointer prototype for sending command data to the output connector*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_command_cb_t>*/
+/**/
+typedef void udi_gfx_connector_command_req_op_t (udi_gfx_command_cb_t *cb );
+udi_gfx_connector_command_req_op_t udi_gfx_connector_command_req;
+
+/* Function: udi_gfx_engine_command_req*/
+/* function pointer prototype for sending command data to the engine*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_command_cb_t>*/
+/**/
+typedef void udi_gfx_engine_command_req_op_t (udi_gfx_command_cb_t *cb );
+udi_gfx_engine_command_req_op_t udi_gfx_engine_command_req;
+
+/* Function: udi_gfx_connector_command_ack*/
+/* function pointer prototype for sending command data replies*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_command_cb_t>*/
+/**/
+typedef void udi_gfx_connector_command_ack_op_t (udi_gfx_command_cb_t *cb);
+udi_gfx_connector_command_ack_op_t udi_gfx_connector_command_ack;
+
+/* Function: udi_gfx_engine_command_ack*/
+/* function pointer prototype for sending engine data replies*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_command_cb_t>*/
+/**/
+typedef void udi_gfx_engine_command_ack_op_t (udi_gfx_command_cb_t *cb);
+udi_gfx_engine_command_ack_op_t udi_gfx_engine_command_ack;
+
+/* Structure: udi_gfx_buffer_cb_t*/
+/* Contains a description of a buffer, or area thereof*/
+typedef struct {
+    /* Variable: gcb*/
+    /* The main control block*/
+    udi_cb_t gcb;    
+    udi_ubit32_t buffer_index;
+} udi_gfx_buffer_info_cb_t;
+
+/* Function: udi_gfx_buffer_info_req*/
+/* function pointer prototype for getting buffer configuration information*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_command_cb_t>*/
+/**/
+typedef void udi_gfx_buffer_info_req_op_t (udi_gfx_buffer_info_cb_t *cb);
+udi_gfx_buffer_info_req_op_t udi_gfx_buffer_info_req;
+
+/* Function: udi_gfx_buffer_info_ack*/
+/* function pointer prototype for getting buffer configuration information*/
+/* */
+/* in:*/
+/*     cb       - A pointer to a <udi_gfx_command_cb_t>*/
+/*     width    - The width of the buffer*/
+/*     height   - The height of the buffer*/
+/*     bitsper  - The number of bits read from the buffer per pixel unit*/
+/*     flags    - A bitfield of <UDI_GFX_BUFFER_FLAGS> indicating the exposed */
+/*                capabilities of this buffer*/
+/**/
+/* Note that bitsper might not be a multiple of eight.*/
+/**/
+typedef void udi_gfx_buffer_info_ack_op_t (udi_gfx_buffer_info_cb_t *cb, udi_ubit32_t width, udi_ubit32_t height, udi_ubit32_t bitsper, udi_ubit32_t flags);
+udi_gfx_buffer_info_ack_op_t udi_gfx_buffer_info_ack;
+
+/* Structure: udi_gfx_buffer_cb_t*/
+/* Contains a description of a buffer, or area thereof*/
+typedef struct {
+    /* Variable: gcb*/
+    /* The main control block*/
+    udi_cb_t gcb;    
+    udi_ubit32_t buffer_index;
+    udi_ubit32_t x;
+    udi_ubit32_t y;
+    udi_ubit32_t width;
+    udi_ubit32_t height;
+    udi_buf_t * buffer;
+} udi_gfx_buffer_cb_t;
+
+/* Function: udi_gfx_buffer_write_req_op_t*/
+/* function pointer prototype for writing raw hardware buffers*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_buffer_cb_t>*/
+/**/
+typedef void udi_gfx_buffer_write_req_op_t (udi_gfx_buffer_cb_t *cb);
+udi_gfx_buffer_write_req_op_t udi_gfx_buffer_write_req;
+
+/* Function: udi_gfx_buffer_write_req_op_t*/
+/* function pointer prototype for reading raw hardware buffers*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_buffer_cb_t>*/
+/**/
+typedef void udi_gfx_buffer_read_req_op_t (udi_gfx_buffer_cb_t *cb);
+udi_gfx_buffer_read_req_op_t udi_gfx_buffer_read_req;
+
+/* Function: udi_gfx_buffer_write_ack_op_t*/
+/* function pointer prototype for writing raw hardware buffers*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_buffer_cb_t>*/
+/**/
+typedef void udi_gfx_buffer_write_ack_op_t (udi_gfx_buffer_cb_t *cb);
+udi_gfx_buffer_write_ack_op_t udi_gfx_buffer_write_ack;
+
+/* Function: udi_gfx_buffer_write_ack_op_t*/
+/* function pointer prototype for reading raw hardware buffers*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_buffer_cb_t>*/
+/**/
+typedef void udi_gfx_buffer_read_ack_op_t (udi_gfx_buffer_cb_t *cb);
+udi_gfx_buffer_read_ack_op_t udi_gfx_buffer_read_ack;
+
+/* Function: udi_gfx_buffer_write_nak_op_t*/
+/* error handling for buffer writes*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_buffer_cb_t>*/
+/**/
+typedef void udi_gfx_buffer_write_nak_op_t (udi_gfx_buffer_cb_t *cb, udi_status_t status);
+udi_gfx_buffer_write_nak_op_t udi_gfx_buffer_write_nak;
+
+/* Function: udi_gfx_buffer_write_nak_op_t*/
+/* error handling for buffer reads*/
+/* */
+/* in:*/
+/*     cb - A pointer to a <udi_gfx_buffer_cb_t>*/
+/**/
+typedef void udi_gfx_buffer_read_nak_op_t (udi_gfx_buffer_cb_t *cb, udi_status_t status);
+udi_gfx_buffer_read_nak_op_t udi_gfx_buffer_read_nak;
+
+/* Structure: udi_gfx_provider_ops_t
+ * 
+ * The graphics metalanguage entry points (provider side)
+ */
+typedef const struct {
+    udi_channel_event_ind_op_t          *channel_event_ind_op;
+    udi_gfx_bind_req_op_t               *gfx_bind_req_op;
+    udi_gfx_unbind_req_op_t             *gfx_unbind_req_op;
+    udi_gfx_set_connector_req_op_t      *gfx_set_connector_req_op;
+    udi_gfx_set_engine_req_op_t         *gfx_set_engine_req_op;
+    udi_gfx_get_connector_req_op_t      *gfx_get_connector_req_op;
+    udi_gfx_get_engine_req_op_t         *gfx_get_engine_req_op;
+    udi_gfx_range_connector_req_op_t    *gfx_range_connector_req_op;
+    udi_gfx_range_engine_req_op_t       *gfx_range_engine_req_op;
+    udi_gfx_get_engine_operator_req_op_t*gfx_get_engine_operator_req_op;
+    udi_gfx_connector_command_req_op_t  *gfx_connector_command_req_op;
+    udi_gfx_engine_command_req_op_t     *gfx_engine_command_req_op;
+    udi_gfx_buffer_info_req_op_t        *gfx_buffer_info_req_op;
+    udi_gfx_buffer_read_req_op_t        *gfx_buffer_read_req_op;
+    udi_gfx_buffer_write_req_op_t       *gfx_buffer_write_req_op;
+} udi_gfx_provider_ops_t;
+
+/* Structure: udi_gfx_client_ops_t
+ *
+ * The graphics metalanguage entry points (client side)
+ */
+typedef const struct {
+    udi_channel_event_ind_op_t          *channel_event_ind_op;
+    udi_gfx_bind_ack_op_t               *gfx_bind_ack_op;
+    udi_gfx_unbind_ack_op_t             *gfx_unbind_ack_op;
+    udi_gfx_set_connector_ack_op_t      *gfx_set_connector_ack_op;
+    udi_gfx_set_engine_ack_op_t         *gfx_set_engine_ack_op;
+    udi_gfx_set_connector_nak_op_t      *gfx_set_connector_nak_op;
+    udi_gfx_set_engine_nak_op_t         *gfx_set_engine_nak_op;
+    udi_gfx_get_connector_ack_op_t      *gfx_get_connector_ack_op;
+    udi_gfx_get_engine_ack_op_t         *gfx_get_engine_ack_op;
+    udi_gfx_range_connector_ack_op_t    *gfx_range_connector_ack_op;
+    udi_gfx_range_engine_ack_op_t       *gfx_range_engine_ack_op;
+    udi_gfx_get_engine_operator_req_op_t*gfx_get_engine_operator_ack_op;
+    udi_gfx_connector_command_ack_op_t  *gfx_connector_command_ack_op;
+    udi_gfx_engine_command_ack_op_t     *gfx_engine_command_ack_op;
+    udi_gfx_buffer_info_ack_op_t        *gfx_buffer_info_ack_op;
+    udi_gfx_buffer_read_ack_op_t        *gfx_buffer_read_ack_op;
+    udi_gfx_buffer_write_ack_op_t       *gfx_buffer_write_ack_op;
+    udi_gfx_buffer_read_nak_op_t        *gfx_buffer_read_nak_op;
+    udi_gfx_buffer_write_nak_op_t       *gfx_buffer_write_nak_op;
+} udi_gfx_client_ops_t;
+
+
+/* temporary*/
+#ifndef UDI_ANNOY_ME
+void EngineReturnSimpleRange (int source, int index, int prop, int first, int last, int modulus);
+void ConnectorReturnSimpleRange (int source, int index, int prop, int first, int last, int modulus);
+void EngineReturnConstantRange (int source, int index, int prop, int value);
+void ConnectorReturnConstantRange (int source, int index, int prop, int value);
+void EngineReturnBooleanRange (int source, int index, int prop, int value1, int value2);
+void ConnectorReturnBooleanRange (int source, int index, int prop, int value1, int value2);
+#endif
+
+#endif
diff --git a/UDI/include/udi_gfx.h.ORIG b/UDI/include/udi_gfx.h.ORIG
new file mode 100644 (file)
index 0000000..fcaa5b7
--- /dev/null
@@ -0,0 +1,848 @@
+/**\r
+ * Summary: udi_gfx.h\r
+ * Contains the graphics metalanguage interface details\r
+ *\r
+ * Author:\r
+ *     Marcel Sondaar\r
+ *\r
+ * License:\r
+ *     <Public Domain>\r
+ *\r
+ * Origin:\r
+ *     http://www.d-rift.nl/combuster/mos3/?p=viewsource&file=/include/common/udi_gfx.h\r
+ */\r
+\r
+// note that the specification, and thus, the contents of this file is not fixed.\r
+\r
+#ifndef __UDI_GFX_H__\r
+#define __UDI_GFX_H__\r
+\r
+#include <udi.h>\r
+\r
+#ifndef UDI_GFX_VERSION\r
+#error "UDI_GFX_VERSION not defined."\r
+#elif UDI_GFX_VERSION != 0x101\r
+#error "UDI_GFX_VERSION not supported."\r
+#endif\r
+\r
+/**\r
+ * Enumeration: UDI_GFX_PROP\r
+ * Lists the various UDI properties\r
+ */\r
+\r
+// General state properties\r
+/* Constant: UDI_GFX_PROP_ENABLE\r
+ *\r
+ * Valid values:\r
+ *     0 - disabled\r
+ *     1 - enabled\r
+ *     2 - reset\r
+ *\r
+ * Ranges:\r
+ *     Must include at least 1\r
+ *\r
+ * The primary state of the connector or engine. An enabled state indicates\r
+ * it is functioning and generating live output. A disabled state is one where\r
+ * it is not contributing to any output but is otherwise functional. Finally\r
+ * the reset state is where the driver is free to deallocate all resources \r
+ * corresponding to this component and trash any state not referenced by other\r
+ * components.\r
+ *\r
+ * A disabled or reset engine forwards all data from the previous stage \r
+ * unmodified. The disabled state indicates that the component might be \r
+ * returned to its enabled state within short notice.\r
+ *\r
+ * A disabled connector will not send pixel data, but can perform other \r
+ * initialisation communication such as DDC. A reset connector will not respond\r
+ * in any fashion and can not be used for other purposes. Hardware is expected\r
+ * to be powered down in such state.\r
+ *\r
+ * Users should expect significant delays when moving components in and out of\r
+ * the reset state. Moving engines between the enabled and disabled state should\r
+ * take effect within one frame, such transition should take effect on a frame \r
+ * boundary when supported.\r
+ */\r
+#define UDI_GFX_PROP_ENABLE 0\r
+\r
+#define UDI_GFX_PROP_ENABLE_DISABLED 0\r
+#define UDI_GFX_PROP_ENABLE_ENABLED 1\r
+#define UDI_GFX_PROP_ENABLE_RESET 2\r
+/* Constant: UDI_GFX_PROP_INPUT\r
+ *\r
+ * Valid values:\r
+ *     Any valid engine ID, provided no dependency cycles are created, or -1\r
+ *\r
+ * Ranges:\r
+ *     Any non-empty set of valid values. Often hardwired.\r
+ *\r
+ * Points to the engine that is processed before this unit. In the case of a \r
+ * connector, it points to the last engine in a pipeline, and each engine points \r
+ * to the next engine in the sequence. A value of -1 indicates a source that \r
+ * only yields black pixels. Implementations must not allow cyclic structures. \r
+ * Changing this value may reallocate resources, and engines that are no longer \r
+ * referenced may lose their data (but not their state) when it is not part of \r
+ * any pipeline. If preservation is required, the ENABLE state should be used\r
+ * instead. Valid ranges includes one or more from the list of engines and -1 \r
+ * combined. In most cases, this property can not be modified.\r
+ */\r
+#define UDI_GFX_PROP_INPUT 1\r
+/* Constant: UDI_GFX_PROP_WIDTH\r
+ *\r
+ * Valid values:\r
+ *     Any non-zero positive number.\r
+ *\r
+ * Ranges:\r
+ *     Contains at least one valid value. Often only multiples of UNIT_WIDTH\r
+ *     or a power of two are allowed. May be hardwired.\r
+ *\r
+ * Contains the amount of pixels in the horizontal direction. For connectors, \r
+ * this is the amount of data pixels rendered horizontally. For engines, this \r
+ * is the width in pixels of the image. Pixels requested from an engine outside \r
+ * the range (0..width-1) are defined according to the <UDI_GFX_PROP_CLIP> \r
+ * property. In some cases, hardware may support only fixed combinations of \r
+ * width and height. In such cases, changing the width will also change the \r
+ * height to a corresponding valid number. Valid ranges include any values\r
+ * strictly above zero. For connectors, expect large continuous ranges, large\r
+ * ranges with a certain modulus, a limited number of fixed values, or a\r
+ * constant value.\r
+ */\r
+#define UDI_GFX_PROP_WIDTH 2\r
+/* Constant: UDI_GFX_PROP_HEIGHT\r
+ *\r
+ * Valid values:\r
+ *     Any non-zero positive number.\r
+ *\r
+ * Ranges:\r
+ *     Contains at least one valid value. Often only multiples of UNIT_HEIGHT\r
+ *     or a power of two are allowed. May be hardwired.\r
+ *\r
+ * Contains the amount of pixels in the vertical direction. Functions similar\r
+ * to the width property, but changing it will not alter the width property,\r
+ * and it's range at any time contains the valid range for the currently\r
+ * selected width.\r
+ */\r
+#define UDI_GFX_PROP_HEIGHT 3\r
+\r
+/* Constant: UDI_GFX_PROP_CUSTOM\r
+ * The first property index of the driver's custom range. These are not assigned\r
+ * directly assigned by the UDI specification, but may be specified in the\r
+ * operator tree.\r
+ */\r
+#define UDI_GFX_PROP_CUSTOM 1024\r
+\r
+// engine properties\r
+\r
+/* Constant: UDI_GFX_PROP_CLIP\r
+ *\r
+ * Valid values:\r
+ *     0 - points outside width x height are passed unmodified from input\r
+ *     1 - the engine's contents is tiled with size width x height\r
+ *     2 - points outside the width overflow into the y coordinate\r
+ *     3 - points outside the height overflow into the x coordinate\r
+ *\r
+ * Ranges:\r
+ *     Hardwired zero for connectors. Any non-empty subset for engines, usually\r
+ *     hardwired.\r
+ *\r
+ * For engines, contains the behaviour for pixels requested outside the width\r
+ * and height of the engine. Can be either 0 (pass from next stage), 1 (the\r
+ * coordinates are wrapped modulus the height and width), 2 (the coordinates\r
+ * overflow onto the next scanline horizontally, and wrap vertically), 3 (the\r
+ * coordinates overflow onto the next column vertically, and wrap horizontally).\r
+ * Valid ranges contain one or more of these options. For overlays and sprites,\r
+ * a value 0 is common. For framebuffers, 2 is the most common value. For\r
+ * connectors, this property is always 0 since they do not store pixel data\r
+ */\r
+#define UDI_GFX_PROP_CLIP 4\r
+\r
+/* Constant: UDI_GFX_PROP_UNIT_WIDTH\r
+ *\r
+ * Valid values:\r
+ *     Any non-zero positive value\r
+ *\r
+ * Ranges:\r
+ *     Any non-empty set of valid values. May be hardwired to 1 for\r
+ *     framebuffers, or a range of small values for hardware scaling, or any\r
+ *     larger hardwired number or set for tiling engines.\r
+ *\r
+ * Tiles are used to indicate that the hardware groups sets of pixels and have\r
+ * each group share certain properties, i.e. color or tile index, or share the\r
+ * same chroma subsample with only a different intensity. If the engine has no\r
+ * such grouping, or shares all properties over the entire contents, the value\r
+ * of this property should be 1. Some tile examples include rescaling, where a\r
+ * tile width of 2 indicates a pixel doubling in X direction, or in text mode\r
+ * where a tile width of 8 or 9 corresponds with the width of common bitmap\r
+ * fonts\r
+ */\r
+#define UDI_GFX_PROP_UNIT_WIDTH 5\r
+\r
+/* Constant: UDI_GFX_PROP_UNIT_HEIGHT\r
+ *\r
+ * Valid values:\r
+ *     Any non-zero positive value\r
+ *\r
+ * Ranges:\r
+ *     Any non-empty set of valid values. May be hardwired to 1 for\r
+ *     framebuffers, or a range of small values for hardware scaling, or any\r
+ *     larger hardwired number or set for tiling engines.\r
+ *\r
+ * See <UDI_GFX_PROP_UNIT_WIDTH>, but for the Y direction. Common values are\r
+ * 1-2 for framebuffers (doublescanning on or off), identical to the tile\r
+ * width, or mostly independent.\r
+ */\r
+#define UDI_GFX_PROP_UNIT_HEIGHT 6\r
+\r
+/* Constant: UDI_GFX_PROP_TRANSLATEX\r
+ * \r
+ * Valid values:\r
+ *     Any, signed value.\r
+ *\r
+ * Ranges:\r
+ *     Any non-empty set. Typical values are hardwired zero, continuous\r
+ *     between -WIDTH and WIDTH, -WIDTH to zero inclusive, or all possible values\r
+ *\r
+ * The horizontal offset where drawing starts. A positive value means the top-left \r
+ * corner moves towards the right end of the screen, a negative value moves the\r
+ * origin off the screen on the left side. Clipped areas moved off the screen do \r
+ * not reappear on the opposite side.\r
+ *\r
+ * With clipping enabled, this field combined with <UDI_GFX_PROP_WIDTH> \r
+ * determines the area where the image should be drawn, which is the horizontal \r
+ * range from UDI_GFX_PROP_TRANSLATEX to UDI_GFX_PROP_WIDTH + \r
+ * UDI_GFX_PROP_TRANSLATEX - 1\r
+ */\r
+#define UDI_GFX_PROP_TRANSLATEX 7\r
+\r
+/* Constant: UDI_GFX_PROP_TRANSLATEY\r
+ *\r
+ * Valid values:\r
+ *     Any signed value.\r
+ *\r
+ * Ranges:\r
+ *     Any non-empty set. Typical values are hardwired zero, continuous\r
+ *     between -WIDTH and WIDTH, or all possible values\r
+ *\r
+ * See <UDI_GFX_PROP_TRANSLATEX> but for the Y direction.\r
+ */\r
+#define UDI_GFX_PROP_TRANSLATEY 8\r
+\r
+#define UDI_GFX_PROP_GL_VERSION 14\r
+#define UDI_GFX_PROP_GLES_VERSION 15\r
+#define UDI_GFX_PROP_STATE_BLOCK 16\r
+#define UDI_GFX_PROP_COLOR_BITS 22\r
+#define UDI_GFX_PROP_GL_TARGET 23\r
+\r
+/* Constant: UDI_GFX_PROP_STOCK_FORMAT\r
+ *\r
+ * Value:\r
+ *     Zero, or any constant from <UDI_GFX_STOCK_FORMAT>\r
+ *\r
+ * Ranges:\r
+ *     Any non-empty set of valid values.\r
+ *\r
+ * This field indicates the storage format is one from a limited set of \r
+ * typical configurations. If the field is zero, the engine is not knowingly\r
+ * configured as a common framebuffer. If nonzero, the operator chain and any\r
+ * dependent settings are defined to be functionally equivalent to that of a\r
+ * typical framebuffer device.\r
+ *\r
+ * The value zero does not imply that the device does not actually follow a\r
+ * set convention. This saves drivers from writing elaborate checking code\r
+ * to determine the condition in question.\r
+ *\r
+ * Writing this field potentially modifies other property fields within the\r
+ * same engine to establish the requested configuration. Manually writing such \r
+ * properties after changing this setting may in turn revert this property to\r
+ * the zero state, even if there was no modification or the behaviour is still\r
+ * as previously advertised by this property.\r
+ */\r
+#define UDI_GFX_PROP_STOCK_FORMAT 27\r
+\r
+/* Constant: UDI_GFX_PROP_OPERATOR_COUNT\r
+ * \r
+ * Valid values:\r
+ *     Any non-zero positive number\r
+ * \r
+ * Ranges:\r
+ *     Most likely constant. Can be any set of valid values.\r
+ *\r
+ * The current value is the number of entries in the operator tree that can\r
+ * be requested for this engine using <udi_gfx_get_engine_operator_req> and\r
+ * <udi_gfx_get_engine_operator_ack>\r
+ */\r
+#define UDI_GFX_PROP_OPERATOR_COUNT 28\r
+\r
+// properties for removal:\r
+#define UDI_GFX_PROP_STORE_COUNT 24       // not generic\r
+#define UDI_GFX_PROP_STORE_WIDTH 9        // not generic\r
+#define UDI_GFX_PROP_STORE_HEIGHT 10      // not generic\r
+#define UDI_GFX_PROP_STORE_BITS 11        // not generic\r
+#define UDI_GFX_PROP_PALETTE 1024         // optional, can be derived from the operator tree\r
+#define UDI_GFX_PROP_BUFFER 1025          // optional, can be derived from the operator tree\r
+#define UDI_GFX_PROP_TILESHEET 1026       // optional, can be derived from the operator tree\r
+#define UDI_GFX_PROP_OPERATOR_INDEX 17    // deprecated for dedicated methods\r
+#define UDI_GFX_PROP_OPERATOR_OPCODE 18   // deprecated for dedicated methods\r
+#define UDI_GFX_PROP_OPERATOR_ARG_1 19    // deprecated for dedicated methods\r
+#define UDI_GFX_PROP_OPERATOR_ARG_2 20    // deprecated for dedicated methods\r
+#define UDI_GFX_PROP_OPERATOR_ARG_3 21    // deprecated for dedicated methods\r
+#define UDI_GFX_PROP_SOURCE_WIDTH 12      // should have been documented when I still knew what it did.\r
+#define UDI_GFX_PROP_SOURCE_HEIGHT 13     // should have been documented when I still knew what it did.\r
+#define UDI_GFX_PROP_INPUTX 25            // should have been documented when I still knew what it did.\r
+#define UDI_GFX_PROP_INPUTY 26            // should have been documented when I still knew what it did.\r
+\r
+// connector properties\r
+#define UDI_GFX_PROP_SIGNAL 23\r
+#define UDI_GFX_PROP_CONNECTOR_TYPE 24\r
+#define UDI_GFX_PROP_VGA_H_FRONT_PORCH 25\r
+#define UDI_GFX_PROP_VGA_H_BACK_PORCH 26\r
+#define UDI_GFX_PROP_VGA_H_SYNC 27\r
+#define UDI_GFX_PROP_VGA_V_FRONT_PORCH 28\r
+#define UDI_GFX_PROP_VGA_V_BACK_PORCH 29\r
+#define UDI_GFX_PROP_VGA_V_SYNC 30\r
+#define UDI_GFX_PROP_DOT_CLOCK 31\r
+#define UDI_GFX_PROP_VGA_H_SYNC_POL 32\r
+#define UDI_GFX_PROP_VGA_V_SYNC_POL 33\r
+\r
+/**\r
+ * Enumeration: UDI_GFX_SIGNAL\r
+ * Lists the various signal types\r
+ */\r
+#define UDI_GFX_SIGNAL_HIDDEN 0\r
+#define UDI_GFX_SIGNAL_INTEGRATED 0\r
+#define UDI_GFX_SIGNAL_RGBHV 1\r
+#define UDI_GFX_SIGNAL_RGBS 2\r
+#define UDI_GFX_SIGNAL_RGSB 3\r
+#define UDI_GFX_SIGNAL_YPBPR 4\r
+#define UDI_GFX_SIGNAL_DVID 5\r
+#define UDI_GFX_SIGNAL_YUV 6\r
+#define UDI_GFX_SIGNAL_YIQ 7\r
+#define UDI_GFX_SIGNAL_Y_UV 8\r
+#define UDI_GFX_SIGNAL_Y_IQ 9\r
+#define UDI_GFX_SIGNAL_HDMI 10\r
+#define UDI_GFX_SIGNAL_TEXT 11\r
+#define UDI_GFX_SIGNAL_CUSTOM 12\r
+\r
+/**\r
+ * Enumeration: UDI_GFX_CONNECTOR\r
+ * Lists the various external connectors\r
+ */\r
+#define UDI_GFX_CONNECTOR_HIDDEN 0\r
+#define UDI_GFX_CONNECTOR_VGA 1\r
+#define UDI_GFX_CONNECTOR_DVI 2\r
+#define UDI_GFX_CONNECTOR_SVIDEO 3\r
+#define UDI_GFX_CONNECTOR_COMPONENT 4\r
+#define UDI_GFX_CONNECTOR_HDMI 5\r
+#define UDI_GFX_CONNECTOR_RF 6\r
+#define UDI_GFX_CONNECTOR_SCART 7\r
+#define UDI_GFX_CONNECTOR_COMPOSITE 8\r
+#define UDI_GFX_CONNECTOR_MEMBUFFER 9\r
+\r
+/**\r
+ * Enumeration: UDI_GFX_OPERATOR\r
+ * Lists the display output operator\r
+ */\r
+#define UDI_GFX_OPERATOR_RGB     0 // output = (color) red(a1) + green(a2) + blue(a3) (each component is UDI_GFX_PROP_COLOR_BITS\r
+#define UDI_GFX_OPERATOR_YUV     1 // output = (color) Y(a1) + U(a2) + V(a3)\r
+#define UDI_GFX_OPERATOR_YIQ     2 // output = (color) Y(a1) + I(a2) + Q(a3)\r
+#define UDI_GFX_OPERATOR_I       3 // output = (color) intensity(a1)\r
+#define UDI_GFX_OPERATOR_ALPHA   4 // output = (color) a1 + alpha(a2)\r
+#define UDI_GFX_OPERATOR_ADD     5 // output = a1 + a2 + v3\r
+#define UDI_GFX_OPERATOR_SUB     6 // output = a1 - a2 - v3\r
+#define UDI_GFX_OPERATOR_MUL     7 // output = a1 * a2\r
+#define UDI_GFX_OPERATOR_DIV     8 // output = a1 / a2\r
+#define UDI_GFX_OPERATOR_MAD     9 // output = a1 * a2 + a3\r
+#define UDI_GFX_OPERATOR_FRC    10 // output = (a1 * a2) / a3\r
+#define UDI_GFX_OPERATOR_SHR    11 // output = a1 >> (a2 + v3)\r
+#define UDI_GFX_OPERATOR_SHL    12 // output = a1 << (a2 + v3)\r
+#define UDI_GFX_OPERATOR_ROR    13 // output = a1 >> a2 (over a3 bits)\r
+#define UDI_GFX_OPERATOR_ROL    14 // output = a1 << a2 (over a3 bits)\r
+#define UDI_GFX_OPERATOR_SAR    15 // output = a1 >> a2 (width is a3 bits, i.e. empties are filled with bit a3-1)\r
+#define UDI_GFX_OPERATOR_SAL    16 // output = a1 <<< (a2 + v3) (empties filled with bit 0)\r
+#define UDI_GFX_OPERATOR_AND    17 // output = a1 & a2\r
+#define UDI_GFX_OPERATOR_OR     18 // output = a1 | a2 | v3\r
+#define UDI_GFX_OPERATOR_NOT    19 // output = ~a1\r
+#define UDI_GFX_OPERATOR_XOR    20 // output = a1 ^ a2 ^ v3\r
+#define UDI_GFX_OPERATOR_NEG    21 // output = -a1\r
+#define UDI_GFX_OPERATOR_SEG    22 // output = (a1 >> v2) & (2**v3-1) (select v3 bits starting from bit v2)\r
+#define UDI_GFX_OPERATOR_RANGE  23 // output = (a1 > a2) ? a2 : ((a1 < a3) ? a3 : a1)\r
+#define UDI_GFX_OPERATOR_CONST  24 // output = v1\r
+#define UDI_GFX_OPERATOR_ATTR   25 // output = property[a1 + v2]\r
+#define UDI_GFX_OPERATOR_SWITCH 26 // output = output[(a1 % v3) + v2]\r
+#define UDI_GFX_OPERATOR_BUFFER 27 // output = buffer[a1][a2] (buffer is v3 bits per entry)\r
+#define UDI_GFX_OPERATOR_X      28 // output = output x pixel\r
+#define UDI_GFX_OPERATOR_Y      29 // output = output y pixel\r
+#define UDI_GFX_OPERATOR_TX     30 // output = horizontal tile index belonging to output pixel\r
+#define UDI_GFX_OPERATOR_TY     31 // output = vertical tile index belonging to output pixel\r
+#define UDI_GFX_OPERATOR_TXOFF  32 // output = horizontal offset from start of tile\r
+#define UDI_GFX_OPERATOR_TYOFF  33 // output = vertical offset from start of tile\r
+#define UDI_GFX_OPERATOR_INPUT  34 // output = input engine[x][y]   component v1\r
+#define UDI_GFX_OPERATOR_DINPUT 35 // output = input engine[a1][a2] component v3\r
+\r
+/* Enumeration: UDI_GFX_STOCK_FORMAT\r
+ * Lists stock configurations\r
+ *\r
+ * When a stock configuration is used, the device is set to behave as a \r
+ * simple framebuffer device. The <UDI_GFX_PROP_WIDTH> and <UDI_GFX_PROP_HEIGHT>\r
+ * determine the virtual size of the framebuffer, and <UDI_GFX_PROP_TRANSLATEX>\r
+ * and <UDI_GFX_PROP_TRANSLATEY> indicate the offset into that framebuffer \r
+ * that is visible (which are typically restricted to negative values)\r
+ */\r
+#define UDI_GFX_STOCK_FORMAT_UNKNOWN  0\r
+#define UDI_GFX_STOCK_FORMAT_R8G8B8X8 1\r
+#define UDI_GFX_STOCK_FORMAT_B8G8R8X8 2\r
+#define UDI_GFX_STOCK_FORMAT_R8G8B8   3\r
+#define UDI_GFX_STOCK_FORMAT_B8G8R8   4\r
+#define UDI_GFX_STOCK_FORMAT_R5G6B5   5\r
+#define UDI_GFX_STOCK_FORMAT_B5G6R5   6\r
+#define UDI_GFX_STOCK_FORMAT_R5G5B5X1 7\r
+#define UDI_GFX_STOCK_FORMAT_B5G5R5X1 8\r
+#define UDI_GFX_STOCK_FORMAT_N8 9\r
+\r
+// Enumeration: UDI_GFX_BUFFER_INFO_FLAG\r
+// Lists behavioural patterns for direct buffer accesses.\r
+//\r
+#define UDI_GFX_BUFFER_INFO_FLAG_R              0x0001  // buffer can be read\r
+#define UDI_GFX_BUFFER_INFO_FLAG_W              0x0002  // buffer can be written\r
+#define UDI_GFX_BUFFER_INFO_FLAG_BITALIGN_ENTRY 0x0004  // for non-multiple-of-eight buffer slot sizes, align on byte boundary every unit\r
+#define UDI_GFX_BUFFER_INFO_FLAG_BITALIGN_ROW   0x0008  // for non-multiple-of-eight buffer slot sizes, align only the start of the row\r
+\r
+\r
+// Constant: UDI_GFX_PROVIDER_OPS_NUM\r
+// the ops number used for the graphics driver\r
+#define UDI_GFX_PROVIDER_OPS_NUM 1\r
+\r
+// Constant: UDI_GFX_CLIENT_OPS_NUM\r
+// the ops number used for the graphics application\r
+#define UDI_GFX_CLIENT_OPS_NUM 2\r
+\r
+// Structure: udi_gfx_bind_cb_t\r
+// Contains the operations of a driver binding request\r
+typedef struct {\r
+    // Variable: gcb\r
+    // The main control block\r
+    udi_cb_t gcb;    \r
+} udi_gfx_bind_cb_t;\r
+#define UDI_GFX_BIND_CB_NUM 1\r
+\r
+// Function: udi_block_bind_req\r
+// function pointer prototype for connecting to a block device\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_block_bind_cb_t>\r
+//\r
+typedef void udi_gfx_bind_req_op_t (udi_gfx_bind_cb_t *cb );\r
+udi_gfx_bind_req_op_t udi_gfx_bind_req;\r
+\r
+// Function: udi_gfx_bind_ack\r
+// function pointer prototype for acknowledging a connection request\r
+// \r
+// in:\r
+//     cb      - A pointer to a <udi_gfx_bind_cb_t>\r
+//     sockets - The number of addressable socket components\r
+//     engines - The number of addressable engine components\r
+//     status  - The result of the bind operation\r
+//\r
+typedef void udi_gfx_bind_ack_op_t (udi_gfx_bind_cb_t *cb, udi_index_t sockets, udi_index_t engines, udi_status_t status );\r
+udi_gfx_bind_ack_op_t udi_gfx_bind_ack;\r
+\r
+// Function: udi_gfx_unbind_req\r
+// function pointer prototype for disconnecting a block device\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_block_bind_cb_t>\r
+//\r
+typedef void udi_gfx_unbind_req_op_t (udi_gfx_bind_cb_t *cb );\r
+udi_gfx_unbind_req_op_t udi_gfx_unbind_req;\r
+\r
+// Function: udi_gfx_unbind_ack\r
+// function pointer prototype for connecting to a block device\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_bind_cb_t>\r
+//\r
+typedef void udi_gfx_unbind_ack_op_t (udi_gfx_bind_cb_t *cb );\r
+udi_gfx_unbind_ack_op_t udi_gfx_unbind_ack;\r
+\r
+// Structure: udi_gfx_state_cb_t\r
+// Contains the operations of a read/write transaction\r
+typedef struct {\r
+    // Variable: gcb\r
+    // The main control block\r
+    udi_cb_t gcb;    \r
+    udi_ubit32_t subsystem;\r
+    udi_ubit32_t attribute;\r
+} udi_gfx_state_cb_t;\r
+#define UDI_GFX_STATE_CB_NUM 2\r
+\r
+// Function: udi_gfx_set_engine_req\r
+// function pointer prototype for setting an engine state\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_set_engine_req_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);\r
+udi_gfx_set_engine_req_op_t udi_gfx_set_engine_req;\r
+\r
+// Function: udi_gfx_set_connector_req\r
+// function pointer prototype for setting an connector state\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_set_connector_req_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);\r
+udi_gfx_set_connector_req_op_t udi_gfx_set_connector_req;\r
+\r
+// Function: udi_gfx_set_engine_ack\r
+// function pointer prototype for setting an engine state\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_set_engine_ack_op_t (udi_gfx_state_cb_t *cb );\r
+udi_gfx_set_engine_ack_op_t udi_gfx_set_engine_ack;\r
+\r
+// Function: udi_gfx_set_connector_ack\r
+// function pointer prototype for setting an engine state\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_set_connector_ack_op_t (udi_gfx_state_cb_t *cb );\r
+udi_gfx_set_connector_ack_op_t udi_gfx_set_connector_ack;\r
+\r
+// Function: udi_gfx_get_engine_req\r
+// function pointer prototype for setting an engine state\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_get_engine_req_op_t (udi_gfx_state_cb_t *cb );\r
+udi_gfx_get_engine_req_op_t udi_gfx_get_engine_req;\r
+\r
+// Function: udi_gfx_get_connector_req\r
+// function pointer prototype for setting an connector state\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_get_connector_req_op_t (udi_gfx_state_cb_t *cb );\r
+udi_gfx_get_connector_req_op_t udi_gfx_get_connector_req;\r
+\r
+// Function: udi_gfx_get_engine_ack\r
+// function pointer prototype for setting an engine state\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_get_engine_ack_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);\r
+udi_gfx_get_engine_ack_op_t udi_gfx_get_engine_ack;\r
+\r
+// Function: udi_gfx_get_connector_ack\r
+// function pointer prototype for setting an engine state\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_get_connector_ack_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);\r
+udi_gfx_get_connector_ack_op_t udi_gfx_get_connector_ack;\r
+\r
+// Function: udi_gfx_set_engine_nak\r
+// function pointer prototype for setting an engine state\r
+// \r
+// in:\r
+//     cb     - A pointer to a <udi_gfx_state_cb_t>\r
+//     status - An UDI status value indicative of the error\r
+//\r
+typedef void udi_gfx_set_engine_nak_op_t (udi_gfx_state_cb_t *cb, udi_status_t status);\r
+udi_gfx_set_engine_nak_op_t udi_gfx_set_engine_nak;\r
+\r
+// Function: udi_gfx_set_connector_nak\r
+// function pointer prototype for setting an engine state\r
+// \r
+// in:\r
+//     cb     - A pointer to a <udi_gfx_state_cb_t>\r
+//     status - An UDI status value indicative of the error\r
+//\r
+typedef void udi_gfx_set_connector_nak_op_t (udi_gfx_state_cb_t *cb, udi_status_t status);\r
+udi_gfx_set_connector_nak_op_t udi_gfx_get_connector_nak;\r
+\r
+// Structure: udi_gfx_range_cb_t\r
+// Contains the operations of a range request transaction\r
+typedef struct {\r
+    // Variable: gcb\r
+    // The main control block\r
+    udi_cb_t gcb;    \r
+    udi_ubit32_t subsystem;\r
+    udi_ubit32_t attribute;\r
+    udi_buf_t * rangedata;  \r
+} udi_gfx_range_cb_t;\r
+#define UDI_GFX_RANGE_CB_NUM 3\r
+\r
+// Function: udi_gfx_range_engine_req\r
+// function pointer prototype for getting an engine property range\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_range_cb_t>\r
+//\r
+typedef void udi_gfx_range_engine_req_op_t (udi_gfx_range_cb_t *cb );\r
+udi_gfx_range_engine_req_op_t udi_gfx_range_engine_req;\r
+\r
+// Function: udi_gfx_range_connector_req\r
+// function pointer prototype for getting a connector property range\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_range_cb_t>\r
+//\r
+typedef void udi_gfx_range_connector_req_op_t (udi_gfx_range_cb_t *cb );\r
+udi_gfx_range_connector_req_op_t udi_gfx_range_connector_req;\r
+\r
+// Function: udi_gfx_range_engine_ack\r
+// function pointer prototype for replying an engine property range\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_range_cb_t>\r
+//\r
+typedef void udi_gfx_range_engine_ack_op_t (udi_gfx_range_cb_t *cb );\r
+udi_gfx_range_engine_ack_op_t udi_gfx_range_engine_ack;\r
+\r
+// Function: udi_gfx_range_connector_ack\r
+// function pointer prototype for replying a connector property range\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_range_cb_t>\r
+//\r
+typedef void udi_gfx_range_connector_ack_op_t (udi_gfx_range_cb_t *cb );\r
+udi_gfx_range_connector_ack_op_t udi_gfx_range_connector_ack;\r
+\r
+// Function: udi_gfx_get_engine_operator_req\r
+// function pointer prototype for requesting the engine operator layout\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_state_cb_t>\r
+//\r
+typedef void udi_gfx_get_engine_operator_req_op_t (udi_gfx_range_cb_t *cb );\r
+udi_gfx_get_engine_operator_req_op_t udi_gfx_get_engine_operator_req;\r
+\r
+// Function: udi_gfx_get_engine_operator_ack\r
+// function pointer prototype for replying the engine operator layout\r
+// \r
+// in:\r
+//     cb   - A pointer to a <udi_gfx_state_cb_t>\r
+//     op   - The operator performed at this index\r
+//     arg1 - the first argument to this operator\r
+//     arg2 - the second argument to this operator\r
+//     arg3 - the third argument to this operator\r
+//\r
+typedef void udi_gfx_get_engine_operator_ack_op_t (udi_gfx_range_cb_t *cb, udi_ubit32_t op, udi_ubit32_t arg1, udi_ubit32_t arg2, udi_ubit32_t arg3 );\r
+udi_gfx_get_engine_operator_ack_op_t udi_gfx_get_engine_operator_ack;\r
+\r
+\r
+\r
+// Structure: udi_gfx_command_cb_t\r
+// Contains the operations of a command sequence\r
+typedef struct {\r
+    // Variable: gcb\r
+    // The main control block\r
+    udi_cb_t gcb;    \r
+    udi_buf_t * commanddata;\r
+} udi_gfx_command_cb_t;\r
+#define UDI_GFX_COMMAND_CB_NUM 4\r
+\r
+// Function: udi_gfx_connector_command_req\r
+// function pointer prototype for sending command data to the output connector\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_command_cb_t>\r
+//\r
+typedef void udi_gfx_connector_command_req_op_t (udi_gfx_command_cb_t *cb );\r
+udi_gfx_connector_command_req_op_t udi_gfx_connector_command_req;\r
+\r
+// Function: udi_gfx_engine_command_req\r
+// function pointer prototype for sending command data to the engine\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_command_cb_t>\r
+//\r
+typedef void udi_gfx_engine_command_req_op_t (udi_gfx_command_cb_t *cb );\r
+udi_gfx_engine_command_req_op_t udi_gfx_engine_command_req;\r
+\r
+// Function: udi_gfx_connector_command_ack\r
+// function pointer prototype for sending command data replies\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_command_cb_t>\r
+//\r
+typedef void udi_gfx_connector_command_ack_op_t (udi_gfx_command_cb_t *cb);\r
+udi_gfx_connector_command_ack_op_t udi_gfx_connector_command_ack;\r
+\r
+// Function: udi_gfx_engine_command_ack\r
+// function pointer prototype for sending engine data replies\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_command_cb_t>\r
+//\r
+typedef void udi_gfx_engine_command_ack_op_t (udi_gfx_command_cb_t *cb);\r
+udi_gfx_engine_command_ack_op_t udi_gfx_engine_command_ack;\r
+\r
+// Structure: udi_gfx_buffer_cb_t\r
+// Contains a description of a buffer, or area thereof\r
+typedef struct {\r
+    // Variable: gcb\r
+    // The main control block\r
+    udi_cb_t gcb;    \r
+    udi_ubit32_t buffer_index;\r
+} udi_gfx_buffer_info_cb_t;\r
+\r
+// Function: udi_gfx_buffer_info_req\r
+// function pointer prototype for getting buffer configuration information\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_command_cb_t>\r
+//\r
+typedef void udi_gfx_buffer_info_req_op_t (udi_gfx_buffer_info_cb_t *cb);\r
+udi_gfx_buffer_info_req_op_t udi_gfx_buffer_info_req;\r
+\r
+// Function: udi_gfx_buffer_info_ack\r
+// function pointer prototype for getting buffer configuration information\r
+// \r
+// in:\r
+//     cb       - A pointer to a <udi_gfx_command_cb_t>\r
+//     width    - The width of the buffer\r
+//     height   - The height of the buffer\r
+//     bitsper  - The number of bits read from the buffer per pixel unit\r
+//     flags    - A bitfield of <UDI_GFX_BUFFER_FLAGS> indicating the exposed \r
+//                capabilities of this buffer\r
+//\r
+// Note that bitsper might not be a multiple of eight.\r
+//\r
+typedef void udi_gfx_buffer_info_ack_op_t (udi_gfx_buffer_info_cb_t *cb, udi_ubit32_t width, udi_ubit32_t height, udi_ubit32_t bitsper, udi_ubit32_t flags);\r
+udi_gfx_buffer_info_ack_op_t udi_gfx_buffer_info_ack;\r
+\r
+// Structure: udi_gfx_buffer_cb_t\r
+// Contains a description of a buffer, or area thereof\r
+typedef struct {\r
+    // Variable: gcb\r
+    // The main control block\r
+    udi_cb_t gcb;    \r
+    udi_ubit32_t buffer_index;\r
+    udi_ubit32_t x;\r
+    udi_ubit32_t y;\r
+    udi_ubit32_t width;\r
+    udi_ubit32_t height;\r
+    udi_buf_t * buffer;\r
+} udi_gfx_buffer_cb_t;\r
+\r
+// Function: udi_gfx_buffer_write_req_op_t\r
+// function pointer prototype for writing raw hardware buffers\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_buffer_cb_t>\r
+//\r
+typedef void udi_gfx_buffer_write_req_op_t (udi_gfx_buffer_cb_t *cb);\r
+udi_gfx_buffer_write_req_op_t udi_gfx_buffer_write_req;\r
+\r
+// Function: udi_gfx_buffer_write_req_op_t\r
+// function pointer prototype for reading raw hardware buffers\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_buffer_cb_t>\r
+//\r
+typedef void udi_gfx_buffer_read_req_op_t (udi_gfx_buffer_cb_t *cb);\r
+udi_gfx_buffer_read_req_op_t udi_gfx_buffer_read_req;\r
+\r
+// Function: udi_gfx_buffer_write_ack_op_t\r
+// function pointer prototype for writing raw hardware buffers\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_buffer_cb_t>\r
+//\r
+typedef void udi_gfx_buffer_write_ack_op_t (udi_gfx_buffer_cb_t *cb);\r
+udi_gfx_buffer_write_ack_op_t udi_gfx_buffer_write_ack;\r
+\r
+// Function: udi_gfx_buffer_write_ack_op_t\r
+// function pointer prototype for reading raw hardware buffers\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_buffer_cb_t>\r
+//\r
+typedef void udi_gfx_buffer_read_ack_op_t (udi_gfx_buffer_cb_t *cb);\r
+udi_gfx_buffer_read_ack_op_t udi_gfx_buffer_read_ack;\r
+\r
+// Function: udi_gfx_buffer_write_nak_op_t\r
+// error handling for buffer writes\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_buffer_cb_t>\r
+//\r
+typedef void udi_gfx_buffer_write_nak_op_t (udi_gfx_buffer_cb_t *cb, udi_status_t status);\r
+udi_gfx_buffer_write_nak_op_t udi_gfx_buffer_write_nak;\r
+\r
+// Function: udi_gfx_buffer_write_nak_op_t\r
+// error handling for buffer reads\r
+// \r
+// in:\r
+//     cb - A pointer to a <udi_gfx_buffer_cb_t>\r
+//\r
+typedef void udi_gfx_buffer_read_nak_op_t (udi_gfx_buffer_cb_t *cb, udi_status_t status);\r
+udi_gfx_buffer_read_nak_op_t udi_gfx_buffer_read_nak;\r
+\r
+/* Structure: udi_gfx_provider_ops_t\r
+ * \r
+ * The graphics metalanguage entry points (provider side)\r
+ */\r
+typedef const struct {\r
+    udi_channel_event_ind_op_t          *channel_event_ind_op;\r
+    udi_gfx_bind_req_op_t               *gfx_bind_req_op;\r
+    udi_gfx_unbind_req_op_t             *gfx_unbind_req_op;\r
+    udi_gfx_set_connector_req_op_t      *gfx_set_connector_req_op;\r
+    udi_gfx_set_engine_req_op_t         *gfx_set_engine_req_op;\r
+    udi_gfx_get_connector_req_op_t      *gfx_get_connector_req_op;\r
+    udi_gfx_get_engine_req_op_t         *gfx_get_engine_req_op;\r
+    udi_gfx_range_connector_req_op_t    *gfx_range_connector_req_op;\r
+    udi_gfx_range_engine_req_op_t       *gfx_range_engine_req_op;\r
+    udi_gfx_get_engine_operator_req_op_t*gfx_get_engine_operator_req_op;\r
+    udi_gfx_connector_command_req_op_t  *gfx_connector_command_req_op;\r
+    udi_gfx_engine_command_req_op_t     *gfx_engine_command_req_op;\r
+    udi_gfx_buffer_info_req_op_t        *gfx_buffer_info_req_op;\r
+    udi_gfx_buffer_read_req_op_t        *gfx_buffer_read_req_op;\r
+    udi_gfx_buffer_write_req_op_t       *gfx_buffer_write_req_op;\r
+} udi_gfx_provider_ops_t;\r
+\r
+/* Structure: udi_gfx_client_ops_t\r
+ *\r
+ * The graphics metalanguage entry points (client side)\r
+ */\r
+typedef const struct {\r
+    udi_channel_event_ind_op_t          *channel_event_ind_op;\r
+    udi_gfx_bind_ack_op_t               *gfx_bind_ack_op;\r
+    udi_gfx_unbind_ack_op_t             *gfx_unbind_ack_op;\r
+    udi_gfx_set_connector_ack_op_t      *gfx_set_connector_ack_op;\r
+    udi_gfx_set_engine_ack_op_t         *gfx_set_engine_ack_op;\r
+    udi_gfx_set_connector_nak_op_t      *gfx_set_connector_nak_op;\r
+    udi_gfx_set_engine_nak_op_t         *gfx_set_engine_nak_op;\r
+    udi_gfx_get_connector_ack_op_t      *gfx_get_connector_ack_op;\r
+    udi_gfx_get_engine_ack_op_t         *gfx_get_engine_ack_op;\r
+    udi_gfx_range_connector_ack_op_t    *gfx_range_connector_ack_op;\r
+    udi_gfx_range_engine_ack_op_t       *gfx_range_engine_ack_op;\r
+    udi_gfx_get_engine_operator_req_op_t*gfx_get_engine_operator_ack_op;\r
+    udi_gfx_connector_command_ack_op_t  *gfx_connector_command_ack_op;\r
+    udi_gfx_engine_command_ack_op_t     *gfx_engine_command_ack_op;\r
+    udi_gfx_buffer_info_ack_op_t        *gfx_buffer_info_ack_op;\r
+    udi_gfx_buffer_read_ack_op_t        *gfx_buffer_read_ack_op;\r
+    udi_gfx_buffer_write_ack_op_t       *gfx_buffer_write_ack_op;\r
+    udi_gfx_buffer_read_nak_op_t        *gfx_buffer_read_nak_op;\r
+    udi_gfx_buffer_write_nak_op_t       *gfx_buffer_write_nak_op;\r
+} udi_gfx_client_ops_t;\r
+\r
+\r
+// temporary\r
+#ifndef UDI_ANNOY_ME\r
+void EngineReturnSimpleRange (int source, int index, int prop, int first, int last, int modulus);\r
+void ConnectorReturnSimpleRange (int source, int index, int prop, int first, int last, int modulus);\r
+void EngineReturnConstantRange (int source, int index, int prop, int value);\r
+void ConnectorReturnConstantRange (int source, int index, int prop, int value);\r
+void EngineReturnBooleanRange (int source, int index, int prop, int value1, int value2);\r
+void ConnectorReturnBooleanRange (int source, int index, int prop, int value1, int value2);\r
+#endif\r
+\r
+#endif\r
index 169a81b..7b5659a 100644 (file)
@@ -8,6 +8,10 @@
 #ifndef _UDI_NIC_H_
 #define _UDI_NIC_H_
 
+#ifndef UDI_NIC_VERSION
+# error "UDI_NIC_VERSION must be defined"
+#endif
+
 // === CBs ===
 #define UDI_NIC_STD_CB_NUM     1
 #define UDI_NIC_BIND_CB_NUM    2
index f65c6fd..16e54a1 100644 (file)
@@ -8,6 +8,9 @@
 #ifndef _UDI_PCI_H_
 #define _UDI_PCI_H_
 
+#if UDI_PCI_VERSION != 0x101
+# error "udi_pci.h requires UDI_PCI_VERSION set to 0x101"
+#endif
 #ifndef _UDI_PHYSIO_H_
 # error "udi_pci.h requires udi_physio.h"
 #endif
index f7643c8..7023687 100644 (file)
@@ -6,9 +6,9 @@
 
 #include <udi.h>
 
-//#ifndef UDI_PHYSIO_VERSION
-//# error "UDI_PHYSIO_VERSION must be defined"
-//#endif
+#ifndef UDI_PHYSIO_VERSION
+# error "UDI_PHYSIO_VERSION must be defined"
+#endif
 
 #define UDI_DL_PIO_HANDLE_T    200
 #define UDI_DL_DMA_CONSTRAINTS_T       201
@@ -128,6 +128,4 @@ struct udi_scgth_s
 #include <physio/meta_bus.h>
 #include "physio/pio.h"
 
-#include "physio/pci.h"
-
 #endif
index e500edd..76d8f57 100644 (file)
@@ -3,7 +3,8 @@
 -include ../Makefile.cfg\r
 \r
 CPPFLAGS += -I./include\r
-LDFLAGS  += -lreadline\r
+LDFLAGS  +=\r
+LIBS     += -lreadline\r
 \r
 BIN = CLIShell\r
 OBJ = main.o lib.o\r
index ef17a14..be17100 100644 (file)
@@ -7,25 +7,24 @@ include $(_appsdir)../Makefile.cfg
 
 ifeq ($(ARCHDIR),native)
  ASFLAGS = -felf
- CPPFLAGS = -Wall
- CFLAGS = $(CPPFLAGS)
- LDFLAGS = -L $(OUTPUTDIR)Libs -lacess-native -lc_acess
-#LIBGCC_PATH = $(ACESSDIR)/AcessNative/symbol_renames.ld
+ LDFLAGS :=
+ LIBS := -lacess-native -lc_acess
 else
  ASFLAGS = -felf
- CPPFLAGS = -ffreestanding
- CFLAGS   = -fno-stack-protector -fno-builtin $(CPPFLAGS) -Wall
- LDFLAGS  = -T $(OUTPUTDIR)Libs/acess.ld -L $(OUTPUTDIR)Libs -I /Acess/Libs/ld-acess.so -lld-acess -lc $(OUTPUTDIR)Libs/crtbegin.o $(OUTPUTDIR)Libs/crtend.o -lposix
- LIBGCC_PATH = $(shell $(CC) -print-libgcc-file-name)
+ LDFLAGS :=
+ LIBS = -lld-acess
 endif
 
+LDFLAGS += -rpath-link $(OUTPUTDIR)Libs        # Needed so that dynamic libraries are linked correctly
+CXXFLAGS += -std=gnu++11
+CPPFLAGS +=
+CFLAGS   += -Wall
+
 -include $(_appsdir)../common_settings.mk
-LDFLAGS += -rpath-link $(OUTPUTDIR)Libs
 
 # Extra-verbose errors!
 #CFLAGS += -Wall -Wextra -Wwrite-strings -Wshadow -Wswitch-default -Wswitch-enum -Wstrict-overflow=5 -Wfloat-equal -Wundef -Wmissing-declarations -Wlogical-op  -Wformat=2 -Winit-self -Wmissing-include-dirs -Wswitch-default -Wswitch-enum -Wsync-nand -Wunused -Wstrict-overflow=5 -Wfloat-equal -Wundef -Wno-endif-labels -Wshadow -Wunsafe-loop-optimizations -Wbad-function-cast -Wc++-compat -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wlogical-op -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-declarations -Wnormalized=nfc -Wpacked -Wpadded -Wredundant-decls -Wnested-externs -Winline -Winvalid-pch -Wdisabled-optimization -Woverlength-strings
 
-CRTBEGIN = $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o)
-CRTEND = $(shell $(CC) $(CFLAGS) -print-file-name=crtend.o)
-
 DIR = Bin
+
+# vim: ft=make
index a6c8508..d72ac6a 100644 (file)
@@ -3,23 +3,26 @@
 # - Application Template Makefile
 #
 
-CFLAGS  += -g
-LDFLAGS += -g
-
-LDFLAGS += -Map $(_OBJPREFIX)Map.txt
-
-ifneq ($(lastword $(subst -, ,$(basename $(LD)))),ld)
-  comma=,
-  LDFLAGS := $(subst -rpath-link ,-Wl$(comma)-rpath-link$(comma),$(LDFLAGS))
-  LDFLAGS := $(subst -Map ,-Wl$(comma)-Map$(comma),$(LDFLAGS))
-endif
+CFLAGS   += -g
+CXXFLAGS += -g
+LDFLAGS  += -g
 
 _BIN := $(OUTPUTDIR)$(DIR)/$(BIN)
 _OBJPREFIX := obj-$(ARCH)/
 
-_LIBS := $(filter -l%,$(LDFLAGS))
+LDFLAGS += -Map $(_OBJPREFIX)Map.txt
+
+comma=,
+LDFLAGS := $(subst -rpath-link ,-Wl$(comma)-rpath-link$(comma),$(LDFLAGS))
+LDFLAGS := $(subst -Map ,-Wl$(comma)-Map$(comma),$(LDFLAGS))
+
+_LIBS := $(filter -l%,$(LIBS))
 _LIBS := $(patsubst -l%,$(OUTPUTDIR)Libs/lib%.so,$(_LIBS))
 
+ifeq ($(ARCHDIR),native)
+ LDFLAGS := $(patsubst -lc++,-lc++_acess,$(LDFLAGS))
+ LIBS := $(patsubst -lc++,-lc++_acess,$(LIBS))
+endif
 ifeq ($(VERBOSE),)
 V := @
 else
@@ -28,6 +31,9 @@ endif
 
 OBJ := $(addprefix $(_OBJPREFIX),$(OBJ))
 
+#LINK_OBJS := $(CRTI) $(CRTBEGIN) $(CRT0) $(OBJ) $(LIBGCC_PATH) $(CRTEND) $(CRTN)
+LINK_OBJS := $(OBJ)
+
 DEPFILES := $(OBJ:%.o=%.dep)
 
 .PHONY : all clean install
@@ -45,10 +51,14 @@ install: $(_BIN)
        @$(xCP) $(_BIN)_ $(DISTROOT)/$(DIR)/$(BIN)
        @$(RM) $(_BIN)_
 
-$(_BIN): $(OUTPUTDIR)Libs/acess.ld $(OUTPUTDIR)Libs/crt0.o $(_LIBS) $(OBJ)
+$(_BIN): $(_LIBS) $(LINK_OBJS) $(CRT0) $(CRTI) $(CRTN)
        @mkdir -p $(dir $(_BIN))
        @echo [LD] -o $@
-       $V$(LD) -g $(LDFLAGS) -o $@ $(CRTBEGIN) $(OBJ) $(LIBGCC_PATH) $(CRTEND)
+ifneq ($(USE_CXX_LINK),)
+       $V$(CXX) -g $(LDFLAGS) -o $(_BIN) $(LINK_OBJS) $(LIBS)
+else
+       $V$(CC)  -g $(LDFLAGS) -o $(_BIN) $(LINK_OBJS) $(LIBS)
+endif
        $V$(DISASM) $(_BIN) > $(_OBJPREFIX)$(BIN).dsm
 
 $(_OBJPREFIX)%.o: %.c
@@ -56,8 +66,7 @@ $(_OBJPREFIX)%.o: %.c
 ifneq ($(_OBJPREFIX),)
        @mkdir -p $(dir $@)
 endif
-       $V$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
-       $V$(CC) -M -MP -MT $@ $(CPPFLAGS) $< -o $(_OBJPREFIX)$*.dep
+       $V$(CC)  $(CFLAGS)   $(CPPFLAGS) -c $< -o $@ -MQ $@ -MP -MD -MF $(_OBJPREFIX)$*.dep
 
 $(_OBJPREFIX)%.o: %.cpp
        @echo [CXX] -o $@
index d96cc5e..d530364 100644 (file)
@@ -8,7 +8,7 @@ DIR := Apps/AxWin/3.0
 BIN := AxWinUI
 OBJ := main.o
 
-LDFLAGS += -laxwin3
+LIBS += -laxwin3
 
 -include ../../Makefile.tpl
 
index 5854a39..595044d 100644 (file)
@@ -8,7 +8,7 @@ BIN := AxWinWM
 OBJ := main.o input.o video.o ipc_acess.o
 include common.mk
 
-LDFLAGS += -lnet
+LIBS += -lnet
 
 -include ../../Makefile.tpl
 
index e354e0c..81ab327 100644 (file)
@@ -18,7 +18,7 @@ OBJ += renderers/widget/textinput.o
 OBJ += renderers/widget/spacer.o
 OBJ += renderers/widget/subwin.o
 
-LDFLAGS += -limage_sif -luri -lunicode
+LIBS += -limage_sif -luri -lunicode
 
 PNGIMAGES := toolbar_new.png toolbar_save.png toolbar_open.png
 IMG2SIF = ../../../../Tools/img2sif
index 2564716..9c87bde 100644 (file)
@@ -49,7 +49,7 @@ extern void   Widget_Fire(tElement *Element);
 #define DEFWIDGETTYPE(_type, _name, _flags, _attribs...) \
 tWidgetDef     _widget_typedef_##_type = {.Name=_name,.Flags=(_flags),_attribs};\
 void _widget_set_##_type(void) __attribute__((constructor));\
-void _widget_set_##_type(void) { _SysDebug("hai!\n"); Widget_int_SetTypeDef(_type, &_widget_typedef_##_type);}
+void _widget_set_##_type(void) { Widget_int_SetTypeDef(_type, &_widget_typedef_##_type); }
 
 #endif
 
index 8335241..de862bf 100644 (file)
@@ -118,7 +118,7 @@ void Widget_TextInput_Init(tElement *Element)
        info->DrawOfs = 0;
        info->CursorXOfs = 0;
        info->CursorByteOfs = 0;
-       info->Length = NULL;
+       info->Length = 0;
 
        // No need to explicitly update parent min dims, as the AddElement routine does that    
 }
index b304cac..cc7e86e 100644 (file)
@@ -13,6 +13,7 @@
 #include <wm_messages.h>
 #include <decorator.h>
 #include <axwin3/keysyms.h>
+#include <wm_hotkeys.h>
 
 // === IMPORTS ===
 extern int     Renderer_Menu_Init(void);
diff --git a/Usermode/Applications/axwin4_src/Common/include/ipc_proto.hpp b/Usermode/Applications/axwin4_src/Common/include/ipc_proto.hpp
new file mode 100644 (file)
index 0000000..a2e1bc9
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * ipc_proto.hpp
+ * - IPC Protocol Header
+ */
+#ifndef _IPC_PROTO_H_
+#define _IPC_PROTO_H_
+
+namespace AxWin {
+
+enum
+{
+       IPCMSG_NULL,
+       IPCMSG_REPLY,
+       IPCMSG_PING,
+       IPCMSG_GETGLOBAL,
+       IPCMSG_SETGLOBAL,
+
+       IPCMSG_CREATEWIN,
+       IPCMSG_CLOSEWIN,
+       IPCMSG_SETWINATTR,
+       IPCMSG_GETWINATTR,
+       IPCMSG_SENDIPC,
+       IPCMSG_GETWINBUF,       // get a handle to the window's buffer
+       
+       // - Window drawing commands
+       IPCMSG_DAMAGERECT,      //  (u16 win, u16 x, u16 y, u16 w, u16 h) - Force reblit of area
+       //IPCMSG_DRAWGROUP,     // (u16 win, u16 group_id) - (hint) Switch to this group
+       //IPCMSG_CLEAR, // (u16 win) - (hint) Clear current drawing group
+       IPCMSG_PUSHDATA,        // (u16 win, u16 x, u16 y, u16 w, u16 h, void data)
+       IPCMSG_BLIT,    // (win, sx, sy, dx, dy, w, h) - Blit locally
+       IPCMSG_DRAWCTL, // (win, x, y, w, h, ctlid) - Draw
+       IPCMSG_DRAWTEXT,        // (win, x, y, fontid, text) - Draw text using an internal font
+       IPCMSG_FILLRECT,        // (win, x, y, w, h, colour)
+       IPCMSG_DRAWRECT,        // (win, x, y, w, h, colour)
+       
+       // - Client-bound commands
+       IPCMSG_INPUTEVENT,      // (u8 event, u16 win, ...)
+};
+
+enum eIPC_GlobalAttrs
+{
+       IPC_GLOBATTR_SCREENDIMS,        // Screen dimensions - Readonly
+       IPC_GLOBATTR_MAXAREA,   // Maximum window area for screen (hint only, not enforced)
+};
+
+enum eIPC_WinAttrs
+{
+       IPC_WINATTR_SHOW,       // u8   - Window shown
+       IPC_WINATTR_FLAGS,      // u32  - Decoration enabled, always-on-top
+       IPC_WINATTR_POSITION,   // s16, s16
+       IPC_WINATTR_DIMENSIONS, // u16, u16
+       IPC_WINATTR_TITLE,      // string
+};
+
+enum eIPC_InputEvents
+{
+       IPC_INEV_KEYBOARD,      // (u16 keysym, u8 keydown, string text)
+       IPC_INEV_MOUSEBTN,      // (u16 x, u16 y)
+       IPC_INEV_MOUSEMOVE,     // (u16 x, u16 y, u8 btn, u8 btndown)
+};
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp b/Usermode/Applications/axwin4_src/Common/include/serialisation.hpp
new file mode 100644 (file)
index 0000000..54293c1
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * serialisation.hpp
+ * - Generic (de)serialisation code
+ */
+#ifndef _SERIALISATION_H_
+#define _SERIALISATION_H_
+
+#include <cstdint>
+#include <cstddef>
+#include <exception>
+#include <string>
+#include <vector>
+
+namespace AxWin {
+
+class CDeserialiseException:
+       public ::std::exception
+{
+};
+
+class CDeserialiser
+{
+       ::std::vector<uint8_t>  m_vect;
+       size_t  m_offset;
+public:
+       CDeserialiser():
+               CDeserialiser(::std::vector<uint8_t>())
+       {}
+       CDeserialiser(const ::std::vector<uint8_t>& vect);
+       CDeserialiser(::std::vector<uint8_t>&& vect);
+       CDeserialiser(const CDeserialiser& x) { *this = x; };
+       CDeserialiser& operator=(const CDeserialiser& x);
+       bool    IsConsumed() const;
+       ::uint8_t       ReadU8();
+       ::uint16_t      ReadU16();
+       ::int16_t       ReadS16();
+       ::uint32_t      ReadU32();
+       ::uint64_t      ReadU64();
+       const ::std::vector<uint8_t>    ReadBuffer();
+       const ::std::string     ReadString();
+private:
+       void RangeCheck(const char *Method, size_t bytes) throw(::std::out_of_range);
+};
+
+class CSerialiser
+{
+       ::std::vector<uint8_t>  m_data;
+public:
+       CSerialiser();
+       void WriteU8(::uint8_t val);
+       void WriteU16(::uint16_t val);
+       void WriteS16(::int16_t val);
+       void WriteU32(::uint32_t val);
+       void WriteU64(::uint64_t val);
+       void WriteBuffer(size_t n, const void* val);
+       void WriteString(const char* val, size_t n);
+       void WriteString(const char* val) {
+               WriteString(val, ::std::char_traits<char>::length(val));
+       }
+       void WriteString(const ::std::string& val) {
+               WriteString(val.data(), val.size());
+       }
+       void WriteSub(const CSerialiser& val);
+       
+       const ::std::vector<uint8_t>& Compact();
+};
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Common/serialisation.cpp b/Usermode/Applications/axwin4_src/Common/serialisation.cpp
new file mode 100644 (file)
index 0000000..016b000
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * serialisation.cpp
+ * - IPC Serialisation
+ */
+#include <serialisation.hpp>
+#include <cstddef>
+#include <stdexcept>
+#include <acess/sys.h> // SysDebug
+
+namespace AxWin {
+
+CDeserialiser::CDeserialiser(const ::std::vector<uint8_t>& vector):
+       m_vect(vector),
+       m_offset(0)
+{
+}
+CDeserialiser::CDeserialiser(::std::vector<uint8_t>&& vector):
+       m_vect(vector),
+       m_offset(0)
+{
+}
+CDeserialiser& CDeserialiser::operator=(const CDeserialiser& x)
+{
+       m_vect = x.m_vect;
+       m_offset = x.m_offset;
+}
+
+bool CDeserialiser::IsConsumed() const
+{
+       return m_offset == m_vect.size();
+}
+
+::uint8_t CDeserialiser::ReadU8()
+{
+       RangeCheck("CDeserialiser::ReadU8", 1);
+       uint8_t rv = m_vect[m_offset];
+       m_offset ++;
+       return rv;
+}
+
+::uint16_t CDeserialiser::ReadU16()
+{
+       RangeCheck("CDeserialiser::ReadU16", 2);
+       uint16_t rv = m_vect[m_offset] | ((uint16_t)m_vect[m_offset+1] << 8);
+       m_offset += 2;
+       return rv;
+}
+
+::int16_t CDeserialiser::ReadS16()
+{
+       uint16_t rv_u = ReadU16();
+       if( rv_u < 0x8000 )
+               return rv_u;
+       else
+               return ~rv_u + 1;
+}
+
+::uint32_t CDeserialiser::ReadU32()
+{
+       uint32_t rv = ReadU16();
+       rv |= (uint32_t)ReadU16() << 16;
+       return rv;
+}
+
+::uint64_t CDeserialiser::ReadU64()
+{
+       uint64_t rv = ReadU32();
+       rv |= (uint64_t)ReadU32() << 32;
+       return rv;
+}
+
+const ::std::vector<uint8_t> CDeserialiser::ReadBuffer()
+{
+       RangeCheck("CDeserialiser::ReadBuffer(len)", 2);
+       size_t  size = ReadU16();
+       
+       auto range_start = m_vect.begin() + int(m_offset);
+       ::std::vector<uint8_t> ret( range_start, range_start + int(size) );
+       m_offset += size;
+       return ret;
+}
+
+const ::std::string CDeserialiser::ReadString()
+{
+       RangeCheck("CDeserialiser::ReadString(len)", 1);
+       uint8_t len = ReadU8();
+       
+       RangeCheck("CDeserialiser::ReadString(data)", len);
+       ::std::string ret( reinterpret_cast<const char*>(m_vect.data()+m_offset), len );
+       m_offset += len;
+       return ret;
+}
+
+void CDeserialiser::RangeCheck(const char *Method, size_t bytes) throw(::std::out_of_range)
+{
+       if( m_offset + bytes > m_vect.size() ) {
+               ::_SysDebug("%s - out of range %i+%i >= %i", Method, m_offset, bytes, m_vect.size());
+               throw ::std::out_of_range(Method);
+       }
+}
+
+CSerialiser::CSerialiser()
+{
+}
+
+void CSerialiser::WriteU8(::uint8_t Value)
+{
+       m_data.push_back(Value);
+}
+
+void CSerialiser::WriteU16(::uint16_t Value)
+{
+       m_data.push_back(Value & 0xFF);
+       m_data.push_back(Value >> 8);
+}
+
+void CSerialiser::WriteS16(::int16_t Value)
+{
+       if( Value < 0 )
+       {
+               ::uint16_t rawval = 0x10000 - (::int32_t)Value;
+               WriteU16(rawval);
+       }
+       else
+       {
+               WriteU16(Value);
+       }
+}
+
+void CSerialiser::WriteU32(::uint32_t Value)
+{
+       m_data.push_back(Value & 0xFF);
+       m_data.push_back(Value >>  8);
+       m_data.push_back(Value >> 16);
+       m_data.push_back(Value >> 24);
+}
+
+void CSerialiser::WriteU64(::uint64_t Value)
+{
+       WriteU32(Value);
+       WriteU32(Value>>32);
+}
+
+void CSerialiser::WriteBuffer(size_t n, const void* val)
+{
+       const uint8_t*  val8 = static_cast<const uint8_t*>(val);
+       if( n > 0xFFFF )
+               throw ::std::length_error("CSerialiser::WriteBuffer");
+       m_data.reserve( m_data.size() + 2 + n );
+       WriteU16(n);
+       for( size_t i = 0; i < n; i ++ )
+               m_data.push_back(val8[i]);
+}
+
+void CSerialiser::WriteString(const char* val, size_t n)
+{
+       if( n > 0xFF )
+               throw ::std::length_error("CSerialiser::WriteString");
+       m_data.reserve( m_data.size() + 1 + n );
+       WriteU8(n);
+       for( size_t i = 0; i < n; i ++ )
+               m_data.push_back(val[i]);
+}
+
+void CSerialiser::WriteSub(const CSerialiser& val)
+{
+       // TODO: Append reference to sub-buffer contents
+       m_data.reserve( m_data.size() + val.m_data.size() );
+       for( auto byte : val.m_data )
+               m_data.push_back( byte );
+}
+
+const ::std::vector<uint8_t>& CSerialiser::Compact()
+{
+       return m_data;
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Makefile b/Usermode/Applications/axwin4_src/Makefile
new file mode 100644 (file)
index 0000000..28fb532
--- /dev/null
@@ -0,0 +1,5 @@
+%:
+       @echo --- AxWin4 Server
+       @make -C Server/ $*
+       @echo --- AxWin4 UI
+       @make -C UI/ $*
diff --git a/Usermode/Applications/axwin4_src/Notes.txt b/Usermode/Applications/axwin4_src/Notes.txt
new file mode 100644 (file)
index 0000000..ee09686
--- /dev/null
@@ -0,0 +1,47 @@
+Layers:
+
+IPC / Client management
+Compositor / Window Manager
+Renderer / Window Contents
+
+Renderers
+Window Management
+> "WM_CreateWindow(Parent, Class, Name)"
+Window Drawing
+> "WD_Fill"
+> "WD_Blit"
+> "WD_LockSurface"
+> "WD_UnlockSurface"
+Decorations
+> ".InitWindow"
+> ".Render"
++ "WM_SetBorder"
+Compositing
+> Dirty rectangling, use 2DCmd to selectively blit
+> Request kernel/server buffers if possible
+
+
+Clients own windows
+Windows are composed of multiple regions that conform to several types (see below)
+- Re-draw is handled by using these regions
+
+Server-side rendering primitives:
+ # Apply to regions, rendered in fixed order, each has an ID
+> Auto-scaling bitmaps
+ - Control backed by an image with three/five regions per axis
+  Edge Fixed, Fill, Center Fixed, Fill, Edge Fixed
+ - Definition is via two pixel counts (edge width, fill width), rest is derived
+ - Command to switch backing image to another already provided
+> Tiling bitmaps + filled rects
+> Text (single line)
+> Canvas (Takes drawing commands, draws to internal buffer)
+> Shared buffer (of an unspecified pixel format)
+
+=== Config options ===
+- Root App
+- Display device (- = stdout)
+- Keyboard device (- = stdin)
+- Mouse device
+- Pipe suffix, port number, etc.
+- Key bindings
+
diff --git a/Usermode/Applications/axwin4_src/Server/CClient.cpp b/Usermode/Applications/axwin4_src/Server/CClient.cpp
new file mode 100644 (file)
index 0000000..2abcb9b
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CClient.cpp
+ * - IPC Client
+ */
+#include <CClient.hpp>
+#include <IIPCChannel.hpp>
+#include <ipc.hpp>
+#include <draw_text.hpp>       // for the fonts
+
+namespace AxWin {
+
+CClient::CClient(::AxWin::IIPCChannel& channel):
+       m_channel(channel),
+       m_id(0)
+{
+       
+}
+
+CClient::~CClient()
+{
+       ::AxWin::IPC::DeregisterClient(*this);
+}
+
+CWindow* CClient::GetWindow(int ID)
+{
+       try {
+               return m_windows.at(ID);
+       }
+       catch(const std::exception& e) {
+               return NULL;
+       }
+}
+
+void CClient::SetWindow(int ID, CWindow* window)
+{
+       //_SysDebug("SetWindow(ID=%i,window=%p)", ID, window);
+       auto it = m_windows.find(ID);
+       if( it != m_windows.end() ) {
+               _SysDebug("CLIENT BUG: Window ID %i is already used by %p", ID, it->second);
+       }
+       else {
+               m_windows[ID] = window;
+       }
+}
+
+IFontFace& CClient::GetFont(unsigned int id)
+{
+       static CFontFallback    fallback_font;
+       if( id == 0 ) {
+               _SysDebug("GetFont: %i = %p", id, &fallback_font);
+               return fallback_font;
+       }
+       assert(!"TODO: CClient::GetFont id != 0");
+}
+
+void CClient::HandleMessage(CDeserialiser& message)
+{
+       try {
+               IPC::HandleMessage(*this, message);
+               if( !message.IsConsumed() )
+               {
+                       _SysDebug("NOTICE - CClient::HandleMessage - Trailing data in message");
+               }
+       }
+       catch( const ::std::exception& e )
+       {
+               _SysDebug("ERROR - Exception while processing message from client: %s", e.what());
+       }
+       catch( ... )
+       {
+               _SysDebug("ERROR - Unknown exception while processing message from client");
+       }
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Server/CConfig.cpp b/Usermode/Applications/axwin4_src/Server/CConfig.cpp
new file mode 100644 (file)
index 0000000..eec783b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CConfig.cpp
+ * - Configuration
+ */
+#include <CConfig.hpp>
+
+namespace AxWin {
+
+CConfig::CConfig()
+{
+}
+
+bool CConfig::parseCommandline(int argc, char *argv[])
+{
+       return false;
+}
+
+CConfigVideo::CConfigVideo()
+{
+}
+
+CConfigInput::CConfigInput():
+       mouse_device("/Devices/Mouse/system")
+{
+}
+
+CConfigIPC::CConfigIPC()
+{
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Server/CIPCChannel_AcessIPCPipe.cpp b/Usermode/Applications/axwin4_src/Server/CIPCChannel_AcessIPCPipe.cpp
new file mode 100644 (file)
index 0000000..0d894e3
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CIPCChannel_AcessIPCPipe.cpp
+ * - IPC Channel :: Acess' IPC Pipe /Devices/ipcpipe/<name>
+ */
+#include <ipc.hpp>
+#include <CIPCChannel_AcessIPCPipe.hpp>
+#include <cerrno>
+#include <system_error>
+#include <acess/sys.h>
+#include <algorithm>
+
+namespace AxWin {
+
+CIPCChannel_AcessIPCPipe::CIPCChannel_AcessIPCPipe(const ::std::string& suffix)
+{
+       ::std::string   path = "/Devices/ipcpipe/" + suffix;
+       m_fd = _SysOpen(path.c_str(), OPENFLAG_CREATE);
+       if(m_fd == -1) {
+               _SysDebug("Failed to open %s: %s", path.c_str(), strerror(errno));
+               throw ::std::system_error(errno, ::std::system_category());
+       }
+}
+CIPCChannel_AcessIPCPipe::~CIPCChannel_AcessIPCPipe()
+{
+       _SysClose(m_fd);
+}
+
+int CIPCChannel_AcessIPCPipe::FillSelect(fd_set& rfds)
+{
+        int    maxfd = m_fd;
+       FD_SET(m_fd, &rfds);
+       
+       for( auto& clientref : m_clients )
+       {
+               maxfd = ::std::max(maxfd, clientref.m_fd);
+               FD_SET(clientref.m_fd, &rfds);
+       }
+       
+       return maxfd+1;
+}
+
+void CIPCChannel_AcessIPCPipe::HandleSelect(const fd_set& rfds)
+{
+       if( FD_ISSET(m_fd, &rfds) )
+       {
+               int newfd = _SysOpenChild(m_fd, "newclient", OPENFLAG_READ|OPENFLAG_WRITE);
+               if( newfd == -1 ) {
+                       _SysDebug("ERROR - Failure to open new client on FD%i", m_fd);
+               }
+               else {
+                       _SysDebug("CIPCChannel_AcessIPCPipe::HandleSelect - New client on FD %i with FD%i",
+                               m_fd, newfd);
+                       
+                       // emplace creates a new object within the list
+                       m_clients.emplace( m_clients.end(), *this, newfd );
+                       IPC::RegisterClient( m_clients.back() );
+               }
+       }
+
+       for( auto it = m_clients.begin(); it != m_clients.end();  )
+       {
+               CClient_AcessIPCPipe& clientref = *it;
+               ++ it;
+               
+               if( FD_ISSET(clientref.m_fd, &rfds) )
+               {
+                       try {
+                               clientref.HandleReceive();
+                       }
+                       catch( const ::std::exception& e ) {
+                               _SysDebug("ERROR - Exception processing IPCPipe FD%i: '%s', removing",
+                                       clientref.m_fd, e.what()
+                                       );
+                               it = m_clients.erase(--it);
+                       }
+               }
+       }
+}
+
+
+CClient_AcessIPCPipe::CClient_AcessIPCPipe(::AxWin::IIPCChannel& channel, int fd):
+       CClient(channel),
+       m_fd(fd)
+{
+}
+
+CClient_AcessIPCPipe::~CClient_AcessIPCPipe()
+{
+       _SysClose(m_fd);
+       _SysDebug("Closed client FD%i", m_fd);
+}
+
+void CClient_AcessIPCPipe::SendMessage(CSerialiser& message)
+{
+       const ::std::vector<uint8_t>&   data = message.Compact();
+       
+       _SysDebug("CClient_AcessIPCPipe::SendMessage - %i bytes to %i", data.size(), m_fd);
+       //_SysDebugHex("CClient_AcessIPCPipe::SendMessage", data.data(), data.size());
+       _SysWrite(m_fd, data.data(), data.size());
+}
+
+void CClient_AcessIPCPipe::HandleReceive()
+{
+       ::std::vector<uint8_t>  rxbuf(0x1000);
+       size_t len = _SysRead(m_fd, rxbuf.data(), rxbuf.capacity());
+       if( len == (size_t)-1 )
+               throw ::std::system_error(errno, ::std::system_category());
+       _SysDebug("CClient_AcessIPCPipe::HandleReceive - Rx %i/%i bytes", len, rxbuf.capacity());
+       //_SysDebugHex("CClient_AcessIPCPipe::HandleReceive", rxbuf.data(), len);
+       rxbuf.resize(len);
+       
+       CDeserialiser   msg( ::std::move(rxbuf) );
+       CClient::HandleMessage( msg );
+}
+
+};
+
diff --git a/Usermode/Applications/axwin4_src/Server/CRect.cpp b/Usermode/Applications/axwin4_src/Server/CRect.cpp
new file mode 100644 (file)
index 0000000..acbcc27
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CRect.cpp
+ * - Rectangle
+ */
+#include <CRect.hpp>
+#include <algorithm>
+#include <acess/sys.h>
+
+namespace AxWin {
+
+CRect::CRect(int x, int y, unsigned int w, unsigned int h):
+       m_x(x), m_y(y),
+       m_w(w), m_h(h),
+       m_x2(x+w), m_y2(y+h)
+{
+}
+
+void CRect::Move(int NewX, int NewY)
+{
+       // TODO: Add a parent rectangle, and prevent this from fully leaving its bounds
+       m_x = NewX;
+       m_y = NewY;
+       m_x2 = m_x + m_w;
+       m_y2 = m_y + m_h;
+}
+
+void CRect::Resize(int NewW, int NewH)
+{
+       m_w = NewW;
+       m_h = NewH;
+       m_x2 = m_x + m_w;
+       m_y2 = m_y + m_h;
+}
+
+bool CRect::HasIntersection(const CRect& other) const
+{
+       // If other's origin is past our far corner
+       if( m_x2 < other.m_x )
+               return false;
+       if( m_y2 < other.m_y )
+               return false;
+       
+       // If other's far corner is before our origin
+       if( m_x > other.m_x2 )
+               return false;
+       if( m_y > other.m_y2 )
+               return false;
+       return true;
+}
+
+CRect CRect::Intersection(const CRect& other) const
+{
+       int x1 = ::std::max(m_x, other.m_x);
+       int y1 = ::std::max(m_y, other.m_y);
+       int x2 = ::std::min(m_x2, other.m_x2);
+       int y2 = ::std::min(m_y2, other.m_y2);
+       
+       if( x2 <= x1 || y2 <= y1 )
+               return CRect();
+       
+       return CRect(x1, y1, x2-x1, y2-y1);
+}
+
+CRect CRect::RelativeIntersection(const CRect& area)
+{
+       CRect   ret = Intersection(area);
+       ret.m_x -= m_x;
+       ret.m_x2 -= m_x;
+       ret.m_y -= m_y;
+       ret.m_y2 -= m_y;
+       return ret;
+}
+
+};
+
diff --git a/Usermode/Applications/axwin4_src/Server/CSurface.cpp b/Usermode/Applications/axwin4_src/Server/CSurface.cpp
new file mode 100644 (file)
index 0000000..d0eddc4
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CWindow.cpp
+ * - Window
+ */
+#include <CSurface.hpp>
+#include <cassert>
+#include <stdexcept>
+#include <cstring>
+#include <system_error>
+#include <cerrno>
+#include <CColour.hpp>
+
+namespace AxWin {
+
+CSurface::CSurface(int x, int y, unsigned int w, unsigned int h):
+       m_rect(x,y, w,h),
+       m_fd(-1),
+       m_data(0)
+{
+       if( w > 0 && h > 0 )
+       {
+               m_data = new uint32_t[w * h];
+       }
+}
+
+CSurface::~CSurface()
+{
+       if( m_fd == -1 ) {
+               delete[] m_data;
+       }
+       else {
+               size_t  size = m_rect.m_w*m_rect.m_h*4;
+               _SysMUnMap(m_data, size);
+       }
+}
+
+uint64_t CSurface::GetSHMHandle()
+{
+       size_t  size = m_rect.m_w*m_rect.m_h*4;
+       if( m_fd == -1 )
+       {
+               // 2. Allocate a copy in SHM
+               m_fd = _SysOpen("/Devices/shm/anon", OPENFLAG_WRITE|OPENFLAG_READ);
+               if(m_fd == -1) {
+                       _SysDebug("GetSHMHandle: Unable to open anon SHM");
+                       return -1;
+               }
+               // 1. Free local buffer
+               delete m_data;
+               _SysTruncate(m_fd, size);
+       }
+       else
+       {
+               _SysMUnMap(m_data, size);
+       }
+       // 3. mmap shm copy
+       m_data = static_cast<uint32_t*>( _SysMMap(nullptr, size, MMAP_PROT_WRITE, 0, m_fd, 0) );
+       if(!m_data)     throw ::std::system_error(errno, ::std::system_category());
+       
+       return _SysMarshalFD(m_fd);
+}
+
+void CSurface::Resize(unsigned int W, unsigned int H)
+{
+       if( m_fd == -1 )
+       {
+               // Easy realloc
+               // TODO: Should I maintain window contents sanely? NOPE!
+               delete m_data;
+               m_data = new uint32_t[W * H];
+       }
+       else
+       {
+               //_SysIOCtl(m_fd, SHM_IOCTL_SETSIZE, W*H*4);
+       }
+       m_rect.Resize(W, H);
+}
+
+void CSurface::DrawScanline(unsigned int row, unsigned int x_ofs, unsigned int w, const void* data)
+{
+       if( row >= m_rect.m_h )
+               throw ::std::out_of_range("CSurface::DrawScanline row");
+       if( x_ofs >= m_rect.m_w )
+               throw ::std::out_of_range("CSurface::DrawScanline x_ofs");
+
+       if( w > m_rect.m_w )
+               throw ::std::out_of_range("CSurface::DrawScanline width");
+       
+       size_t  ofs = row*m_rect.m_w + x_ofs;
+       ::memcpy( &m_data[ofs], data, w*4 );
+}
+
+void CSurface::BlendScanline(unsigned int row, unsigned int x_ofs, unsigned int w, const void* data)
+{
+       if( row >= m_rect.m_h )
+               throw ::std::out_of_range("CSurface::DrawScanline row");
+       if( x_ofs >= m_rect.m_w )
+               throw ::std::out_of_range("CSurface::DrawScanline x_ofs");
+
+       if( w > m_rect.m_w )
+               throw ::std::out_of_range("CSurface::DrawScanline width");
+       
+       const uint32_t* in_data = (const uint32_t*)data;
+       size_t  ofs = row*m_rect.m_w + x_ofs;
+       for( unsigned int x = 0; x < w; x ++ )
+       {
+               CColour out = CColour::from_argb(m_data[ofs+x]).blend( CColour::from_argb(in_data[x]) );
+               m_data[ofs+x] = out.to_argb();
+       }
+}
+
+void CSurface::FillScanline(unsigned int row, unsigned int x_ofs, unsigned int w, uint32_t colour)
+{
+       if( row >= m_rect.m_h )
+               throw ::std::out_of_range("CSurface::FillScanline row");
+       if( x_ofs >= m_rect.m_w )
+               throw ::std::out_of_range("CSurface::FillScanline x_ofs");
+
+       if( w > m_rect.m_w )
+               throw ::std::out_of_range("CSurface::FillScanline width");
+       
+       size_t  ofs = row*m_rect.m_w + x_ofs;
+       while( w -- )
+               m_data[ofs++] = colour;
+}
+
+const uint32_t* CSurface::GetScanline(unsigned int row, unsigned int x_ofs) const
+{
+       if( row >= m_rect.m_h )
+               throw ::std::out_of_range("CSurface::GetScanline row");
+       if( x_ofs >= m_rect.m_w )
+               throw ::std::out_of_range("CSurface::GetScanline x_ofs");
+
+       return &m_data[row * m_rect.m_w + x_ofs];
+}
+
+
+};     // namespace AxWin
+
+
diff --git a/Usermode/Applications/axwin4_src/Server/CWindow.cpp b/Usermode/Applications/axwin4_src/Server/CWindow.cpp
new file mode 100644 (file)
index 0000000..022d6b4
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CWindow.cpp
+ * - Window
+ */
+#include <CWindow.hpp>
+#include <CCompositor.hpp>
+#include <assert.h>
+#include <ipc.hpp>
+
+namespace AxWin {
+
+CWindow::CWindow(CCompositor& compositor, CClient& client, const ::std::string& name, unsigned int id):
+       m_surface(0,0,0,0),
+       m_compositor(compositor),
+       m_client(client),
+       m_id(id),
+       m_name(name),
+       m_is_shown(false)
+{
+       _SysDebug("CWindow::CWindow()");
+}
+
+CWindow::~CWindow()
+{
+}
+
+void CWindow::Repaint(const CRect& rect)
+{
+       if( m_is_shown )
+       {
+               CRect   outrect(
+                       m_surface.m_rect.m_x + rect.m_x, 
+                       m_surface.m_rect.m_y + rect.m_y, 
+                       rect.m_w, rect.m_h
+                       );
+               m_compositor.DamageArea(outrect);
+       }
+}
+
+void CWindow::Show(bool bShow)
+{
+       if( m_is_shown == bShow )
+               return;
+       
+       if( bShow )
+               m_compositor.ShowWindow( this );
+       else
+               m_compositor.HideWindow( this );
+       m_is_shown = bShow;
+}
+
+void CWindow::Move(int X, int Y)
+{
+       m_surface.m_rect.Move(X, Y);
+}
+void CWindow::Resize(unsigned int W, unsigned int H)
+{
+       m_surface.Resize(W, H);
+       IPC::SendMessage_NotifyDims(m_client, m_id, W, H);
+}
+void CWindow::SetFlags(uint32_t Flags)
+{
+       // TODO: CWindow::SetFlags
+       _SysDebug("TOOD: CWindow::SetFlags");
+}
+uint64_t CWindow::ShareSurface()
+{
+       assert(!"TODO: CWindow::ShareSurface");
+       return 0;
+}
+
+void CWindow::MouseButton(int ButtonID, int X, int Y, bool Down)
+{
+       IPC::SendMessage_MouseButton(m_client, m_id, X, Y, ButtonID, Down);
+}
+
+void CWindow::MouseMove(int NewX, int NewY)
+{
+       // TODO: Only enable move events if client requests them
+       //IPC::SendMessage_MouseMove(m_client, m_id, NewX, NewY);
+}
+
+void CWindow::KeyEvent(::uint32_t Scancode, const ::std::string &Translated, bool Down)
+{
+       IPC::SendMessage_KeyEvent(m_client, m_id, Scancode, Down, Translated.c_str());
+}
+
+
+void CWindow::DrawScanline(unsigned int row, unsigned int x, unsigned int w, const uint8_t *data)
+{
+       m_surface.DrawScanline(row, x, w, data);
+       CRect   damaged( m_surface.m_rect.m_x+x, m_surface.m_rect.m_y+row, w, 1 );
+       m_compositor.DamageArea(damaged);
+}
+
+void CWindow::FillScanline(unsigned int row, unsigned int x, unsigned int w, const uint32_t colour)
+{
+       m_surface.FillScanline(row, x, w, colour);
+       CRect   damaged( m_surface.m_rect.m_x+x, m_surface.m_rect.m_y+row, w, 1 );
+       m_compositor.DamageArea(damaged);
+}
+
+};
+
diff --git a/Usermode/Applications/axwin4_src/Server/Makefile b/Usermode/Applications/axwin4_src/Server/Makefile
new file mode 100644 (file)
index 0000000..b85fc08
--- /dev/null
@@ -0,0 +1,26 @@
+
+include ../../Makefile.cfg
+
+DIR := Apps/AxWin/4.0
+
+CPPFLAGS += -Iinclude/ -I../Common/include/
+OBJ := main.o ipc.o CConfig.o video.o input.o timing.o
+OBJ += compositor.o CWindow.o
+OBJ += Common__serialisation.o
+OBJ += CClient.o
+OBJ += CIPCChannel_AcessIPCPipe.o
+OBJ += CRect.o CSurface.o
+OBJ += draw_control.o draw_text.o
+BIN := AxWinServer
+
+LIBS += -lc++ -lunicode
+#CXXFLAGS += -O3
+USE_CXX_LINK = 1 
+
+include ../../Makefile.tpl
+
+$(_OBJPREFIX)Common__%.o: ../Common/%.cpp
+       @echo [CXX] -o $@
+       @mkdir -p $(dir $@)
+       $V$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@ -MQ $@ -MP -MD -MF $(@:%.o=%.dep)
+
diff --git a/Usermode/Applications/axwin4_src/Server/compositor.cpp b/Usermode/Applications/axwin4_src/Server/compositor.cpp
new file mode 100644 (file)
index 0000000..e488380
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * compositor.cpp
+ * - Window compositor
+ */
+#include <video.hpp>
+#include <CCompositor.hpp>
+#include <CClient.hpp>
+#include <ipc.hpp>
+#include <cassert>
+
+namespace AxWin {
+
+CCompositor::CCompositor(CVideo& video):
+       // TODO: Support multiple screens
+       m_video(video),
+       m_focussed_window(nullptr),
+       m_windowIDBuffer(video.width(), video.height())
+{
+       // 
+}
+
+void CCompositor::ShowWindow(CWindow* window)
+{
+       DamageArea(window->m_surface.m_rect);
+       // TODO: Append to separate sub-lists (or to separate lists all together)
+       //   if flags AXWIN4_WNDFLAG_KEEPBELOW or AXWIN4_WNDFLAG_KEEPABOVE are set
+       m_windows.push_back(window);
+}
+void CCompositor::HideWindow(CWindow* window)
+{
+       DamageArea(window->m_surface.m_rect);
+       m_windows.remove(window);
+}
+
+bool CCompositor::GetScreenDims(unsigned int ScreenID, unsigned int* W, unsigned int* H)
+{
+       assert(W && H);
+       if( ScreenID != 0 )
+       {
+               *W = 0;
+               *H = 0;
+               return false;
+       }
+       else
+       {
+               m_video.GetDims(*W, *H);
+               return true;
+       }
+}
+
+void CCompositor::Redraw()
+{
+       // Redraw the screen and clear damage rects
+       if( m_damageRects.empty() ) {
+               //_SysDebug("- No damaged regions");
+               return ;
+       }
+       
+       // Build up foreground grid (Rects and windows)
+       // - This should already be built (mutated on window move/resize/reorder)
+       
+       // For all windows, check for intersection with damage rects
+       for( auto rect : m_damageRects )
+       {
+               // window list should be sorted by draw order (lowest first)
+               for( auto window : m_windows )
+               {
+                       if( window->m_is_shown && rect.HasIntersection( window->m_surface.m_rect ) )
+                       {
+                               // TODO: just reblit
+                               CRect   rel_rect = window->m_surface.m_rect.RelativeIntersection(rect);
+                               _SysDebug("Reblit (%i,%i) %ix%i", rel_rect.m_x, rel_rect.m_y, rel_rect.m_w, rel_rect.m_h);
+                               BlitFromSurface( window->m_surface, rel_rect );
+                               //window->Repaint( rel_rect );
+                               m_windowIDBuffer.set(rel_rect.m_x, rel_rect.m_y, rel_rect.m_w, rel_rect.m_h, window);
+                       }
+               }
+               
+               // TODO: Blit from windows to a local surface, then blit from there to screen here
+       }
+
+       m_damageRects.clear();
+       m_video.Flush();
+}
+
+void CCompositor::DamageArea(const CRect& area)
+{
+       m_damageRects.push_back( area );
+       // 1. Locate intersection with any existing damaged areas
+       // 2. Append after removing intersections
+}
+
+void CCompositor::BlitFromSurface(const CSurface& dest, const CRect& src_rect)
+{
+       for( unsigned int i = 0; i < src_rect.m_h; i ++ )
+       {
+               m_video.BlitLine(
+                       dest.GetScanline(src_rect.m_y+i, src_rect.m_x),
+                       dest.m_rect.m_y + src_rect.m_y + i,
+                       dest.m_rect.m_x + src_rect.m_x,
+                       src_rect.m_w
+                       );
+       }
+}
+
+void CCompositor::MouseMove(unsigned int Cursor, unsigned int X, unsigned int Y, int dX, int dY)
+{
+       //_SysDebug("MouseButton(%i, %i,%i, %+i,%+i)", Cursor, X, Y, dX, dY);
+       m_video.SetCursorPos(X+dX, Y+dY);
+       CWindow *dstwin = getWindowForCoord(X, Y);
+       if( dstwin )
+       {
+               // Pass event on to window
+               dstwin->MouseMove(X, Y);
+       }
+}
+
+void CCompositor::MouseButton(unsigned int Cursor, unsigned int X, unsigned int Y, eMouseButton Button, bool Press)
+{
+       _SysDebug("MouseButton(%i, %i,%i, %i=%i)", Cursor, X, Y, Button, Press);
+       CWindow *dstwin = getWindowForCoord(X, Y);
+       _SysDebug("- dstwin = %p", dstwin);
+       if( dstwin )
+       {
+               // 1. Give focus and bring to front
+               // 2. Send event
+               dstwin->MouseButton(Button, X, Y, Press);
+       }
+}
+
+void CCompositor::KeyState(unsigned int KeyboardID, uint32_t KeySym, bool Press, uint32_t Codepoint)
+{
+       _SysDebug("KeyState(%i, 0x%x, %b, 0x%x)", KeyboardID, KeySym, Press, Codepoint);
+       // TODO: Global hotkeys
+       if( m_focussed_window )
+       {
+               m_focussed_window->KeyEvent(KeySym, "", Press);
+       }
+}
+
+CWindow* CCompositor::getWindowForCoord(unsigned int X, unsigned int Y)
+{
+       return m_windowIDBuffer.get(X, Y);
+}
+
+// --------------------------------------------------------------------
+CWindowIDBuffer::CWindowIDBuffer(unsigned int W, unsigned int H):
+       m_w(W),
+       m_buf(W*H)
+{
+}
+void CWindowIDBuffer::set(unsigned int X, unsigned int Y, unsigned int W, unsigned int H, CWindow* win)
+{
+       TWindowID       ent = {
+               .Client = win->client().id(),
+               .Window = win->id(),
+               };
+       for( unsigned int row = 0; row < H; row ++ )
+       {
+               TWindowID* dst = &m_buf[ (Y+row) * m_w ];
+               for( unsigned int col = 0; col < W; col ++ )
+                       dst[col] = ent;
+       }
+}
+CWindow* CWindowIDBuffer::get(unsigned int X, unsigned int Y)
+{
+       if( X >= m_w )
+               return nullptr;
+       unsigned int pos = Y*m_w + X;
+       if( pos >= m_buf.size() )
+               return nullptr;
+       auto id = m_buf[pos];
+       //_SysDebug("CWindowIDBuffer::get id = {%i,%i}", id.Client, id.Window);
+       auto client = ::AxWin::IPC::GetClientByID(id.Client);
+       if( client == nullptr ) {
+               //_SysDebug("CWindowIDBuffer::get client=%p", client);
+               return nullptr;
+       }
+       return client->GetWindow(id.Window);
+}
+
+}      // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Server/draw_control.cpp b/Usermode/Applications/axwin4_src/Server/draw_control.cpp
new file mode 100644 (file)
index 0000000..ef105e7
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * draw_control.cpp
+ * - Common "Control" Drawing
+ *
+ * Handles drawing of resizable controls defined by a bitmap and four region sizes
+ */
+#include <draw_control.hpp>
+#include <axwin4/definitions.h>
+#include <acess/sys.h>
+#include <cassert>
+
+// === CODE ===
+namespace AxWin {
+
+CControl::CControl(int EdgeX, int FillX, int InnerX, int EdgeY, int FillY, int InnerY, ::std::vector<uint32_t>&& data):
+       m_edge_x(EdgeX),
+       m_fill_x(FillX),
+       m_inner_x(InnerX),
+       m_edge_y(EdgeY),
+       m_fill_y(FillY),
+       m_inner_y(InnerY),
+       m_data(data)
+{
+       _SysDebug("CControl(X={E:%i,F:%i,I:%i}, Y={E:%i,F:%i,I:%i}, data={Size:%i})",
+               m_edge_x, m_fill_x, m_inner_x, m_edge_y, m_fill_y, m_inner_y, m_data.size());
+}
+
+void CControl::Render(CSurface& dest, const CRect& rect) const
+{
+       if( rect.m_w < m_edge_x*2 + m_fill_x*2 + m_inner_x )
+               return ;
+       if( rect.m_h < m_edge_y*2 + m_fill_y*2 + m_inner_y )
+               return ;
+       
+       const int ctrl_width = m_edge_x + m_fill_x + m_inner_x + (m_inner_x ? m_fill_x : 0) + m_edge_x;
+       
+       const int top_fill_end = rect.m_h / 2 - m_inner_y;
+       const int bot_fill_start = top_fill_end + m_inner_y;
+       const int bot_fill_end   = rect.m_h - m_edge_y;
+       
+       ::std::vector<uint32_t> scanline( rect.m_w );
+        int    y = 0;
+        int    base_ofs = 0;
+       // EdgeY
+       for( int i = 0; i < m_edge_y; i ++ )
+               renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+       base_ofs += m_edge_y;
+       // FillY
+       assert(m_fill_y > 0 || y == top_fill_end);
+       while( y < top_fill_end )
+       {
+               for( int i = 0; i < m_fill_y && y < top_fill_end; i ++ )
+                       renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+       }
+       base_ofs += m_fill_y;
+       // InnerY
+       if( m_inner_y > 0 )
+       {
+               for( int i = 0; i < m_inner_y; i ++ )
+                       renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+               base_ofs += m_inner_y;
+       }
+       else
+       {
+               base_ofs -= m_fill_x;
+       }
+       // FillY
+       while( y < bot_fill_end )
+       {
+               for( int i = 0; i < m_fill_y && y < bot_fill_end; i ++ )
+                       renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+       }
+       base_ofs += m_fill_y;
+       // EdgeY
+       for( int i = 0; i < m_edge_y; i ++ )
+               renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+       base_ofs += m_edge_y;
+}
+
+void CControl::renderLine(CSurface& dest, int y, ::std::vector<uint32_t>& scanline, const CRect& rect, const uint32_t* ctrl_line) const
+{
+       //_SysDebug("renderLine: (y=%i,rect={(%i,%i) %ix%i}", y, rect.m_x, rect.m_y, rect.m_w, rect.m_h);
+       const int left_fill_end = rect.m_w / 2 - m_inner_x;
+       const int right_fill_end = rect.m_w - m_edge_x;
+       
+        int    x = 0;
+        int    base_ofs = 0;
+       // EdgeX
+       for( int i = 0; i < m_edge_x; i ++ )
+               scanline[x++] = ctrl_line[base_ofs + i];
+       base_ofs += m_edge_x;
+       // FillX
+       while( x < left_fill_end )
+       {
+               for( int i = 0; i < m_fill_x && x < left_fill_end; i ++ )
+                       scanline[x++] = ctrl_line[base_ofs + i];
+       }
+       base_ofs += m_fill_x;
+       // InnerX
+       if( m_inner_x > 0 )
+       {
+               for( int i = 0; i < m_inner_x; i ++ )
+                       scanline[x++] = ctrl_line[base_ofs + i];
+               base_ofs += m_inner_x;
+       }
+       else
+       {
+               base_ofs -= m_fill_x;
+       }
+       // FillX
+       while( x < right_fill_end )
+       {
+               for( int i = 0; i < m_fill_x && x < right_fill_end; i ++ )
+                       scanline[x++] = ctrl_line[base_ofs + i];
+       }
+       base_ofs += m_fill_x;
+       // EdgeX
+       for( int i = 0; i < m_edge_x; i ++ )
+               scanline[x++] = ctrl_line[base_ofs + i];
+       base_ofs += m_edge_x;
+       
+       dest.DrawScanline(rect.m_y + y, rect.m_x, rect.m_w, scanline.data());
+}
+
+// ---- Standard Controls ---
+// Standard button control
+CControl StdButton(2, 1, 0, 2, 1, 0, ::std::vector<uint32_t> {
+       0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0,
+       0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0,
+       0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0,
+       0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0,
+       0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0,
+       });
+
+// Toolbar
+CControl StdToolbar(2, 1, 0, 2, 1, 0, ::std::vector<uint32_t> {
+       0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+       0x000000, 0xA0A0A0, 0x0A0000, 0xA0A0A0, 0x000000,
+       0x000000, 0xA0A0A0, 0xFFFFFF, 0xA0A0A0, 0x000000,
+       0x000000, 0xA0A0A0, 0x0A0000, 0xA0A0A0, 0x000000,
+       0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+       });
+
+// Text Area
+CControl StdText(2, 1, 0, 2, 1, 0, ::std::vector<uint32_t> {
+       0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+       0x000000, 0xA0A0A0, 0x0A0000, 0xA0A0A0, 0x000000,
+       0x000000, 0xA0A0A0, 0xFFFFFF, 0xA0A0A0, 0x000000,
+       0x000000, 0xA0A0A0, 0x0A0000, 0xA0A0A0, 0x000000,
+       0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+       });
+
+const CControl* CControl::GetByName(const ::std::string& name)
+{
+       if( name == "StdButton" )
+               return &StdButton;
+       if( name == "StdText" )
+               return &StdText;
+       // TODO: Use another exception
+       return nullptr;
+}
+
+const CControl* CControl::GetByID(uint16_t id)
+{
+       switch(id)
+       {
+       case AXWIN4_CTL_BUTTON: return &StdButton;
+       case AXWIN4_CTL_TOOLBAR:        return &StdToolbar;
+       case AXWIN4_CTL_TEXTBOX:        return &StdText;
+       default:        return nullptr;
+       }
+}
+
+};     // AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Server/draw_text.cpp b/Usermode/Applications/axwin4_src/Server/draw_text.cpp
new file mode 100644 (file)
index 0000000..7e9e7b8
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * draw_text.cpp
+ * - Text Drawing
+ *
+ * Handles font selection and drawing of text to windows
+ */
+#include <draw_text.hpp>
+#include <axwin4/definitions.h>
+#include <unicode.h>   // libunicode (acess)
+extern "C" {
+#include <assert.h>    // assert... and _SysDebug
+};
+#include "resources/font_8x16.h"
+
+// === CODE ===
+namespace AxWin {
+
+// -- Primitive fallback font
+CFontFallback::CFontFallback()
+{
+}
+
+CRect CFontFallback::Size(const ::std::string& text, unsigned int Size) const
+{
+       return CRect(0,0, text.size() * Size * FONT_WIDTH / FONT_HEIGHT, Size);
+}
+
+/**
+ * \param Text height in pixels (not in points)
+ */
+void CFontFallback::Render(CSurface& dest, const CRect& rect, const ::std::string& text, unsigned int Size)
+{
+       unsigned int font_step = Size * FONT_WIDTH / FONT_HEIGHT;
+       CRect   pos = rect;
+       for( auto codepoint : ::libunicode::utf8string(text) )
+       {
+               renderAtRes(dest, pos, codepoint, Size, 0x000000);
+               pos.Translate(font_step, 0);
+       }
+}
+
+void CFontFallback::renderAtRes(CSurface& dest, const CRect& rect, uint32_t cp, unsigned int Size, uint32_t FGC)
+{
+       unsigned int char_idx = unicodeToCharmap(cp);
+       assert(char_idx < 256);
+       const uint8_t*  char_ptr = &VTermFont[char_idx * FONT_HEIGHT];
+       unsigned int    out_h = Size;
+       unsigned int    out_w = (Size * FONT_WIDTH / FONT_HEIGHT);
+       uint32_t        char_data[out_w];
+       if( Size == FONT_HEIGHT ) {
+               // Standard blit
+               for( unsigned int row = 0; row < out_h; row ++ )
+               {
+                       for( unsigned int col = 0; col < out_w; col ++ )
+                       {
+                               uint8_t alpha = getValueAtRaw(char_ptr, col, row);
+                               char_data[col] = ((uint32_t)alpha << 24) | (FGC & 0xFFFFFF);
+                       }
+                       dest.BlendScanline(rect.m_y + row, rect.m_x, FONT_WIDTH, char_data);
+               }
+       }
+       else if( Size < FONT_HEIGHT ) {
+               // Down-scaled blit
+               // NOTE: uses the same code as the upscale blit (probably not correct, need to replace)
+               for( unsigned int row = 0; row < out_h; row ++ )
+               {
+                       unsigned int yf16 = row * FONT_HEIGHT * 0x10000 / out_h;
+                       for( unsigned int col = 0; col < out_w; col ++ )
+                       {
+                               unsigned int xf16 = col * FONT_WIDTH * 0x10000 / out_w;
+                               uint8_t alpha = getValueAtPt(char_ptr, xf16, yf16);
+                               //_SysDebug("row %i (%05x), col %i (%05x): alpha = %02x", row, yf16, col, xf16, alpha);
+                               char_data[col] = ((uint32_t)alpha << 24) | (FGC & 0xFFFFFF);
+                       }
+                       dest.BlendScanline(rect.m_y + row, rect.m_x, out_w, char_data);
+               }
+       }
+       else {
+               // up-scaled blit
+               for( unsigned int row = 0; row < out_h; row ++ )
+               {
+                       unsigned int yf16 = row * FONT_HEIGHT * 0x10000 / out_h;
+                       for( unsigned int col = 0; col < out_w; col ++ )
+                       {
+                               unsigned int xf16 = col * FONT_WIDTH * 0x10000 / out_w;
+                               uint8_t alpha = getValueAtPt(char_ptr, xf16, yf16);
+                               //_SysDebug("row %i (%05x), col %i (%05x): alpha = %02x", row, yf16, col, xf16, alpha);
+                               char_data[col] = ((uint32_t)alpha << 24) | (FGC & 0xFFFFFF);
+                       }
+                       dest.BlendScanline(rect.m_y + row, rect.m_x, out_w, char_data);
+               }
+       }
+}
+// X and Y are fixed-point 16.16 values
+uint8_t CFontFallback::getValueAtPt(const uint8_t* char_ptr, unsigned int xf16, unsigned int yf16)
+{
+       unsigned int ix = xf16 >> 16;
+       unsigned int iy = yf16 >> 16;
+       unsigned int fx = xf16 & 0xFFFF;
+       unsigned int fy = yf16 & 0xFFFF;
+       
+       if( fx == 0 && fy == 0 ) {
+               return getValueAtRaw(char_ptr, ix, iy);
+       }
+       else if( fx == 0 ) {
+               float y = (float)fy / 0x10000;
+               uint8_t v0 = getValueAtRaw(char_ptr, ix, iy  );
+               uint8_t v1 = getValueAtRaw(char_ptr, ix, iy+1);
+               return v0 * (1 - y) + v1 * y;
+       }
+       else if( fy == 0 ) {
+               float x = (float)fx / 0x10000;
+               uint8_t v0 = getValueAtRaw(char_ptr, ix  , iy);
+               uint8_t v1 = getValueAtRaw(char_ptr, ix+1, iy);
+               return v0 * (1 - x) + v1 * x;
+       }
+       else {
+               float x = (float)fx / 0x10000;
+               float y = (float)fx / 0x10000;
+               // [0,0](1 - x)(1 - y) + [1,0]x(1-y) + [0,1](1-x)y + [1,1]xy
+               uint8_t v00 = getValueAtRaw(char_ptr, ix, iy);
+               uint8_t v01 = getValueAtRaw(char_ptr, ix, iy+1);
+               uint8_t v10 = getValueAtRaw(char_ptr, ix+1, iy);
+               uint8_t v11 = getValueAtRaw(char_ptr, ix+1, iy+1);
+               //_SysDebug("x,y = %04x %04x", (unsigned)(x * 0x10000), (unsigned)(y * 0x10000));
+               //_SysDebug("v = %02x %02x %02x %02x", v00, v01, v10, v11);
+               float val1 = v00 * (1 - x) * (1 - y);
+               float val2 = v10 * x * (1 - y);
+               float val3 = v01 * (1 - x) * y;
+               float val4 = v11 * x * y;
+               //_SysDebug("vals = %04x %04x %04x %04x",
+               //      (unsigned)(val1 * 0x10000),
+               //      (unsigned)(val2 * 0x10000),
+               //      (unsigned)(val3 * 0x10000),
+               //      (unsigned)(val4 * 0x10000)
+               //      );
+               
+               return (uint8_t)(val1 + val2 + val3 + val4);
+       }
+}
+
+uint8_t CFontFallback::getValueAtRaw(const uint8_t* char_ptr, unsigned int x, unsigned int y)
+{
+       //if( x == 0 || y == 0 )
+       //      return 0;
+       //x --; y --;
+       if(x >= FONT_WIDTH || y >= FONT_HEIGHT)
+               return 0;
+       return (char_ptr[y] & (1 << (7-x))) ? 255 : 0;
+}
+
+unsigned int CFontFallback::unicodeToCharmap(uint32_t cp) const
+{
+       if(cp >= ' ' && cp < 0x7F)
+               return cp;
+       switch(cp)
+       {
+       default:
+               return 0;
+       }
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CClient.hpp b/Usermode/Applications/axwin4_src/Server/include/CClient.hpp
new file mode 100644 (file)
index 0000000..2a23f15
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * CClient.hpp
+ * - IPC Client
+ */
+#ifndef _CCLIENT_H_
+#define _CCLIENT_H_
+
+#include "CWindow.hpp"
+#include "serialisation.hpp"
+#include <map>
+#include <cassert>
+#include "IFontFace.hpp"
+
+namespace AxWin {
+
+class IIPCChannel;
+
+class CClient
+{
+       unsigned int    m_id;
+       IIPCChannel&    m_channel;
+       
+       ::std::map<unsigned int,CWindow*>       m_windows;
+       //CWindow*      m_windows[1];
+public:
+       CClient(::AxWin::IIPCChannel& channel);
+       virtual ~CClient();
+       
+       void set_id(unsigned int id) { assert(m_id == 0); m_id = id; }
+       unsigned int id() const { return m_id; }
+       
+       CWindow*        GetWindow(int ID);
+       void    SetWindow(int ID, CWindow* window);
+       
+       IFontFace&      GetFont(unsigned int id);
+       
+       virtual void    SendMessage(CSerialiser& reply) = 0;
+       void    HandleMessage(CDeserialiser& message);
+};
+
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CColour.hpp b/Usermode/Applications/axwin4_src/Server/include/CColour.hpp
new file mode 100644 (file)
index 0000000..d47d7e0
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CColour.hpp
+ * - Generic colour handling and blending
+ */
+#ifndef _CCOLOUR_HPP_
+#define _CCOLOUR_HPP_
+
+namespace AxWin {
+
+class CColour
+{
+       static const uint8_t    uint8_max = 0xFF;
+       static const unsigned int comp_max = 0x7FFF;
+       
+       unsigned int    m_alpha;
+       unsigned int    m_red;
+       unsigned int    m_green;
+       unsigned int    m_blue;
+
+private:
+       static unsigned int u8_to_ui(uint8_t u8v) {
+               return (unsigned int)u8v * comp_max / uint8_max;
+       }
+       static uint8_t ui_to_u8(unsigned int uiv) {
+               return uiv * uint8_max / comp_max;
+       }
+       // Perform an alpha-based blend on two components
+       static unsigned int alpha_blend(unsigned int alpha_comp, unsigned int left, unsigned int right) {
+               return (left * (comp_max - alpha_comp) + right * alpha_comp) / comp_max;
+       }
+       // Float values:
+       // - infinity == saturation, 1 == nothing
+       // fv = MAX / (MAX - uiv)
+       static float ui_to_float(unsigned int uiv) {
+               return (float)comp_max / (comp_max - uiv);
+       }
+       // uiv = MAX - MAX / fv
+       static unsigned int float_to_ui(float fv) {
+               return comp_max - comp_max / fv;
+       }
+       // perform a non-oversaturating blend of two colours (using an inverse relationship)
+       static unsigned int add_blend(unsigned int a, unsigned int b) {
+               return float_to_ui( ui_to_float(a) + ui_to_float(b) );
+       }
+
+       CColour(unsigned int r, unsigned int g, unsigned int b, unsigned int a):
+               m_alpha(a), m_red(r), m_green(g), m_blue(b)
+       {
+       }
+public:
+
+       static CColour from_argb(uint32_t val) {
+               return CColour(
+                       u8_to_ui((val>>16) & 0xFF),
+                       u8_to_ui((val>> 8) & 0xFF),
+                       u8_to_ui((val>> 0) & 0xFF),
+                       u8_to_ui((val>>24) & 0xFF)
+                       );
+       }
+       
+       uint32_t to_argb() const {
+               uint32_t        rv = 0;
+               rv |= (uint32_t)ui_to_u8(m_red)   << 16;
+               rv |= (uint32_t)ui_to_u8(m_green) <<  8;
+               rv |= (uint32_t)ui_to_u8(m_blue)  <<  0;
+               rv |= (uint32_t)ui_to_u8(m_alpha) << 24;
+               return rv;
+       }
+       
+       // performs a blend of the two colours, maintaining the target alpha, using the source alpha as the blend control
+       CColour& blend(const CColour& other) {
+               m_red   = alpha_blend(other.m_alpha, m_red  , other.m_red  );
+               m_green = alpha_blend(other.m_alpha, m_green, other.m_green);
+               m_blue  = alpha_blend(other.m_alpha, m_blue , other.m_blue );
+               return *this;
+       }
+       // Add all components
+       CColour& operator+(const CColour& other) {
+               m_alpha = add_blend(m_alpha, other.m_alpha);
+               m_red   = add_blend(m_red  , other.m_red  );
+               m_green = add_blend(m_green, other.m_green);
+               m_blue  = add_blend(m_blue , other.m_blue );
+               return *this;
+       }
+};
+
+}      // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp b/Usermode/Applications/axwin4_src/Server/include/CCompositor.hpp
new file mode 100644 (file)
index 0000000..fe24303
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * CCompositor.hpp
+ * - Window Compositor
+ */
+#ifndef _CCOMPOSITOR_H_
+#define _CCOMPOSITOR_H_
+
+#include <string>
+#include <list>
+#include <vector>
+#include "CRect.hpp"
+#include "CWindow.hpp"
+
+namespace AxWin {
+
+class CClient;
+class CVideo;
+
+
+enum eMouseButton
+{
+       MOUSEBTN_MAIN,  // Left
+       MOUSEBTN_SECONDARY,     // Right
+       MOUSEBTN_MIDDLE,        // Scroll wheel
+       MOUSEBTN_BTN4,
+       MOUSEBTN_BTN5,
+};
+
+class CWindowIDBuffer
+{
+       struct TWindowID
+       {
+               uint16_t        Client;
+               uint16_t        Window;
+       };
+       unsigned int    m_w;
+       ::std::vector<TWindowID>        m_buf;
+public:
+       CWindowIDBuffer(unsigned int W, unsigned int H);
+       
+       void set(unsigned int X, unsigned int Y, unsigned int W, unsigned int H, CWindow* win);
+       CWindow* get(unsigned int X, unsigned int Y);
+};
+
+class CCompositor
+{
+       CVideo& m_video;
+       ::std::list<CRect>      m_damageRects;
+       ::std::list<CWindow*>   m_windows;
+       CWindow*        m_focussed_window;
+
+       CWindowIDBuffer m_windowIDBuffer;       // One 32-bit value per pixel
+       
+public:
+       CCompositor(CVideo& video);
+
+       CWindow* CreateWindow(CClient& client, const ::std::string& name);
+
+       void    ShowWindow(CWindow* window);
+       void    HideWindow(CWindow* window);
+
+       bool    GetScreenDims(unsigned int ScrenID, unsigned int *Width, unsigned int *Height);
+
+       void    Redraw();
+       void    DamageArea(const CRect& rect);
+       void    BlitFromSurface(const CSurface& dest, const CRect& src_rect);
+       
+       void    MouseMove(unsigned int Cursor, unsigned int X, unsigned int Y, int dX, int dY);
+       void    MouseButton(unsigned int Cursor, unsigned int X, unsigned int Y, eMouseButton Button, bool Press);
+       
+       void    KeyState(unsigned int KeyboardID, uint32_t KeySym, bool Press, uint32_t Codepoint);
+public:
+       CWindow*        getWindowForCoord(unsigned int X, unsigned int Y);
+};
+
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CConfig.hpp b/Usermode/Applications/axwin4_src/Server/include/CConfig.hpp
new file mode 100644 (file)
index 0000000..aff7fc8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * CConfig.hpp
+ * - Configuration class
+ */
+#ifndef _CCONFIG_H_
+#define _CCONFIG_H_
+
+#include "CConfigInput.hpp"
+#include "CConfigVideo.hpp"
+#include "CConfigIPC.hpp"
+
+namespace AxWin {
+
+class CConfig
+{
+public:
+       CConfig();
+       
+       bool parseCommandline(int argc, char *argv[]);
+       
+       CConfigInput    m_input;
+       CConfigVideo    m_video;
+       CConfigIPC      m_ipc;
+};
+
+}
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CConfigIPC.hpp b/Usermode/Applications/axwin4_src/Server/include/CConfigIPC.hpp
new file mode 100644 (file)
index 0000000..053e376
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * CConfigIPC.hpp
+ * - Configuration class
+ */
+#ifndef _CCONFIGIPC_H_
+#define _CCONFIGIPC_H_
+
+#include <string>
+
+namespace AxWin {
+
+class CConfigIPC_Channel
+{
+public:
+       ::std::string   m_name;
+       ::std::string   m_argument;
+};
+
+class CConfigIPC
+{
+public:
+       CConfigIPC();
+};
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CConfigInput.hpp b/Usermode/Applications/axwin4_src/Server/include/CConfigInput.hpp
new file mode 100644 (file)
index 0000000..28553ca
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * CConfig.hpp
+ * - Configuration class
+ */
+#ifndef _CCONFIGINPUT_H_
+#define _CCONFIGINPUT_H_
+
+#include <string>
+
+namespace AxWin {
+
+class CConfigInput
+{
+public:
+       CConfigInput();
+       
+       ::std::string   mouse_device;
+};
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CConfigVideo.hpp b/Usermode/Applications/axwin4_src/Server/include/CConfigVideo.hpp
new file mode 100644 (file)
index 0000000..9a81fb7
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * CConfigVideo.hpp
+ * - Configuration class
+ */
+#ifndef _CCONFIGVIDEO_H_
+#define _CCONFIGVIDEO_H_
+
+namespace AxWin {
+
+class CConfigVideo
+{
+public:
+       CConfigVideo();
+};
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CIPCChannel_AcessIPCPipe.hpp b/Usermode/Applications/axwin4_src/Server/include/CIPCChannel_AcessIPCPipe.hpp
new file mode 100644 (file)
index 0000000..c4ec004
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CIPCChannel_AcessIPCPipe.hpp
+ * - IPC Channel :: Acess' IPC Pipe /Devices/ipcpipe/<name>
+ */
+#ifndef _CIPCCHANNEL_ACESSIPCPIPE_HPP_
+#define _CIPCCHANNEL_ACESSIPCPIPE_HPP_
+
+#include <IIPCChannel.hpp>
+#include <CClient.hpp>
+#include <string>
+#include <list>
+
+namespace AxWin {
+
+class CClient_AcessIPCPipe:
+       public CClient
+{
+       friend class CIPCChannel_AcessIPCPipe;
+        int    m_fd;
+public:
+       CClient_AcessIPCPipe(IIPCChannel& channel, int fd);
+       ~CClient_AcessIPCPipe();
+       
+       void SendMessage(CSerialiser& message);
+       
+       void HandleReceive();
+};
+
+class CIPCChannel_AcessIPCPipe:
+       public IIPCChannel
+{
+        int    m_fd;
+       ::std::list<CClient_AcessIPCPipe>       m_clients;
+public:
+       CIPCChannel_AcessIPCPipe(const ::std::string& suffix);
+       virtual ~CIPCChannel_AcessIPCPipe();
+       
+       virtual int  FillSelect(fd_set& rfds);
+       virtual void HandleSelect(const fd_set& rfds);
+};
+
+}      // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CRect.hpp b/Usermode/Applications/axwin4_src/Server/include/CRect.hpp
new file mode 100644 (file)
index 0000000..3c344b2
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ */
+#ifndef _CRECT_H_
+#define _CRECT_H_
+
+namespace AxWin {
+
+class CRect
+{
+public:
+       CRect():
+               CRect(0,0,0,0)
+       {
+       };
+       CRect(int X, int Y, unsigned int W, unsigned int H);
+       
+       void Translate(int DX, int DY) {
+               m_x += DX;      m_x2 += DX;
+               m_y += DY;      m_y2 += DY;
+       }
+       void Move(int NewX, int NewY);
+       void Resize(int NewW, int NewH);
+       
+       bool HasIntersection(const CRect& other) const;
+       CRect Intersection(const CRect& other) const;
+       
+       CRect RelativeIntersection(const CRect& area);
+       
+       int     m_x;
+       int     m_y;
+       int     m_w;
+       int     m_h;
+       int     m_x2;
+       int     m_y2;
+};
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp b/Usermode/Applications/axwin4_src/Server/include/CSurface.hpp
new file mode 100644 (file)
index 0000000..ac20d0f
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ */
+#ifndef _CSURFACE_H_
+#define _CSURFACE_H_
+
+#include <cstdint>
+#include "CRect.hpp"
+
+namespace AxWin {
+
+class CSurface
+{
+public:
+       CSurface(int x, int y, unsigned int w, unsigned int h);
+       ~CSurface();
+
+       uint64_t GetSHMHandle();
+       
+       void Resize(unsigned int new_w, unsigned int new_h);
+       
+       void DrawScanline(unsigned int row, unsigned int x_ofs, unsigned int w, const void* data);
+       void BlendScanline(unsigned int row, unsigned int x_ofs, unsigned int w, const void* data);
+       void FillScanline(unsigned int row, unsigned int x, unsigned int w, uint32_t colour);
+       const uint32_t* GetScanline(unsigned int row, unsigned int x_ofs) const;
+       
+       CRect   m_rect;
+       uint32_t*       m_data;
+private:
+       int     m_fd;
+};
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp b/Usermode/Applications/axwin4_src/Server/include/CWindow.hpp
new file mode 100644 (file)
index 0000000..e902659
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * CWindow.hpp
+ * - Window class
+ */
+#ifndef _CWINDOW_HPP_
+#define _CWINDOW_HPP_
+
+#include <string>
+#include <vector>
+#include <cstdint>
+#include "CRect.hpp"
+#include "CSurface.hpp"
+
+namespace AxWin {
+
+class CClient;
+class CCompositor;
+class CRegion;
+
+class CWindow
+{
+public:
+       CWindow(CCompositor& compositor, CClient& client, const ::std::string &name, unsigned int id);
+       ~CWindow();
+       
+       const CClient& client() const { return m_client; }
+       const unsigned int id() const { return m_id; }
+       
+       void Repaint(const CRect& rect);
+
+       void Show(bool bShow);  
+       void Move(int X, int Y);
+       void Resize(unsigned int W, unsigned int H);
+       void SetFlags(uint32_t Flags);
+       
+       uint64_t ShareSurface();
+       
+       void MouseButton(int ButtonID, int X, int Y, bool Down);
+       void MouseMove(int NewX, int NewY);
+       void KeyEvent(::uint32_t Scancode, const ::std::string &Translated, bool Down);
+
+       void DrawScanline(unsigned int row, unsigned int x, unsigned int w, const uint8_t *data);
+       void FillScanline(unsigned int row, unsigned int x, unsigned int w, const uint32_t colour);
+       
+       bool    m_is_shown;
+       CSurface        m_surface;
+private:
+       CCompositor&    m_compositor;
+       CClient&        m_client;
+       unsigned int    m_id;
+       const ::std::string     m_name;
+       ::std::vector<CRegion*> m_regions;
+};
+
+};     // namespace AxWin
+
+#endif
+
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/IFontFace.hpp b/Usermode/Applications/axwin4_src/Server/include/IFontFace.hpp
new file mode 100644 (file)
index 0000000..76ba042
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * IFont.hpp
+ * - Text drawing (font rendering) primitive
+ */
+#ifndef _IFONT_HPP_
+#define _IFONT_HPP_
+
+#include <string>
+#include "CRect.hpp"
+#include "CSurface.hpp"
+
+namespace AxWin {
+
+class IFontFace
+{
+public:
+       virtual CRect Size(const ::std::string& text, unsigned int Size) const = 0;
+       virtual void Render(CSurface& dest, const CRect& rect, const ::std::string& text, unsigned int Size) = 0;
+};
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/IIPCChannel.hpp b/Usermode/Applications/axwin4_src/Server/include/IIPCChannel.hpp
new file mode 100644 (file)
index 0000000..5dc88e2
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * IIPCChannel.hpp
+ * - IPC Channel interface
+ */
+#ifndef _IIPCCHANNEL_H_
+#define _IIPCCHANNEL_H_
+
+extern "C" {
+#include <acess/sys.h>
+}
+
+namespace AxWin {
+
+class IIPCChannel
+{
+public:
+       virtual ~IIPCChannel();
+       
+       virtual int     FillSelect(::fd_set& rfds) = 0;
+       virtual void    HandleSelect(const ::fd_set& rfds) = 0;
+};
+
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/IRegion.hpp b/Usermode/Applications/axwin4_src/Server/include/IRegion.hpp
new file mode 100644 (file)
index 0000000..8208aa5
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * IRegion.hpp
+ * - Representation of a primitive region in a window (part of the window render list)
+ */
+#ifndef _IREGION_HPP_
+#define _IREGION_HPP_
+
+#include <string>
+#include <vector>
+#include "CRect.hpp"
+
+namespace AxWin {
+
+class IRegion
+{
+protected:
+       CWindow&        m_parentWindow;
+public:
+       virtual IRegion(CWindow& parent, const ::AxWin::Rect& position);
+       virtual ~IRegion();
+       
+       virtual void Redraw(const ::AxWin::Rect& area) = 0;
+       virtual bool SetAttr(unsigned int Index, const IPCAttrib& Value) = 0;
+};
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/IVideo.hpp b/Usermode/Applications/axwin4_src/Server/include/IVideo.hpp
new file mode 100644 (file)
index 0000000..aa4fc52
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * IVideo.hpp
+ * - Graphics backend abstraction
+ */
+#ifndef _IVIDEO_HPP_
+#define _IVIDEO_HPP_
+
+namespace AxWin {
+
+class IVideo
+{
+public:
+       virtual ~IVideo();
+       
+       // Allocate a new hardware surface
+       IHWSurface&     AllocateHWSurface(uint16_t Width, uint16_t Height);
+       
+       // Request redraw of backbuffer
+       void    Flip();
+};
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/IWindow.hpp b/Usermode/Applications/axwin4_src/Server/include/IWindow.hpp
new file mode 100644 (file)
index 0000000..83dd97f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * IWindow.hpp
+ * - Window abstract base class
+ */
+#ifndef _IWINDOW_HPP_
+#define _IWINDOW_HPP_
+
+#include <string>
+#include <vector>
+#include <cstdint>
+#include "CRect.hpp"
+
+namespace AxWin {
+
+class IWindow
+{
+public:
+       IWindow(const ::std::string &name);
+       virtual ~IWindow();
+       
+       virtual void Repaint() = 0;
+       
+       virtual void MouseButton(int ButtonID, int X, int Y, bool Down);
+       virtual void MouseMove(int NewX, int NewY);
+       virtual void KeyEvent(::uint32_t Scancode, const ::std::string &Translated, bool Down);
+protected:
+       const ::std::string     m_name;
+};
+
+}      // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/common.hpp b/Usermode/Applications/axwin4_src/Server/include/common.hpp
new file mode 100644 (file)
index 0000000..1a1facc
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <exception>
+
+namespace AxWin {
+
+class InitFailure:
+       public ::std::exception
+{
+       const char *m_what;
+public:
+       InitFailure(const char *reason):
+               m_what(reason)
+       {
+       }
+       
+       virtual const char* what() const throw();
+};
+
+}      // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/compositor.hpp b/Usermode/Applications/axwin4_src/Server/include/compositor.hpp
new file mode 100644 (file)
index 0000000..403d943
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * compositor.hpp
+ * - Compositor Interface Header
+ */
+#ifndef _COMPOSITOR_H_
+#define _COMPOSITOR_H_
+
+namespace AxWin {
+
+class CCompositor;
+
+namespace Compositor {
+
+};     // namespace Compositor
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/draw_control.hpp b/Usermode/Applications/axwin4_src/Server/include/draw_control.hpp
new file mode 100644 (file)
index 0000000..3797e2e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ */
+#ifndef _DRAW_CONTROL_HPP_
+#define _DRAW_CONTROL_HPP_
+
+#include <vector>
+#include <string>
+#include <cstdint>
+#include <CSurface.hpp>
+
+namespace AxWin {
+
+class CControl
+{
+       unsigned int    m_edge_x;
+       unsigned int    m_edge_y;
+       unsigned int    m_fill_x;
+       unsigned int    m_fill_y;
+       unsigned int    m_inner_x;
+       unsigned int    m_inner_y;
+       ::std::vector<uint32_t> m_data;
+public:
+       CControl(int EdgeX, int FillX, int InnerX, int EdgeY, int FillY, int InnerY, ::std::vector<uint32_t>&& data);
+       void Render(CSurface& dest, const CRect& rect) const;
+       
+       static const CControl*  GetByName(const ::std::string& name);
+       static const CControl*  GetByID(uint16_t id);
+       
+private:
+       void renderLine(CSurface& dest, int y, ::std::vector<uint32_t>& scanline, const CRect& rect, const uint32_t* ctrl_line) const;
+};
+
+
+}
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/draw_text.hpp b/Usermode/Applications/axwin4_src/Server/include/draw_text.hpp
new file mode 100644 (file)
index 0000000..4bf28a6
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * draw_text.hpp
+ * - Text drawing classes
+ */
+#ifndef _DRAW_TEXT_HPP_
+#define _DRAW_TEXT_HPP_
+
+#include "IFontFace.hpp"
+
+namespace AxWin {
+
+class CFontFallback:
+       public IFontFace
+{
+public:
+       CFontFallback();
+
+       CRect Size(const ::std::string& text, unsigned int Size) const override;
+       void Render(CSurface& dest, const CRect& rect, const ::std::string& text, unsigned int Size) override;
+private:
+       void renderAtRes(CSurface& dest, const CRect& rect, uint32_t cp, unsigned int Size, uint32_t FGC);
+       static uint8_t getValueAtPt(const uint8_t* char_ptr, unsigned int xf16, unsigned int yf16);
+       static uint8_t getValueAtRaw(const uint8_t* char_ptr, unsigned int x, unsigned int y);
+       unsigned int unicodeToCharmap(uint32_t cp) const;
+};
+
+#if FREETYPE_ENABLED
+class CFontFT:
+       public IFontFace
+{
+       FT_Face m_face;
+public:
+       CFontFT(const char *Filename);
+       ~CFontFT();
+
+       CRect Size(const ::std::string& text, unsigned int Size) const override;
+       void Render(CSurface& dest, const CRect& rect, const ::std::string& text, unsigned int Size) override;
+};
+#endif // FREETYPE_ENABLED
+
+}
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/input.hpp b/Usermode/Applications/axwin4_src/Server/include/input.hpp
new file mode 100644 (file)
index 0000000..f8b27ce
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * input.hpp
+ * - Input Interface Header
+ */
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+#include <acess/sys.h>
+
+namespace AxWin {
+
+class CCompositor;
+
+class CInput
+{
+       CCompositor&    m_compositor;
+        int    m_keyboardFD;
+        int    m_mouseFD;
+       
+       unsigned int m_mouseX;
+       unsigned int m_mouseY;
+       unsigned int m_mouseBtns;
+public:
+       CInput(const CConfigInput& config, CCompositor& compositor);
+        int FillSelect(::fd_set& rfds);
+       void HandleSelect(::fd_set& rfds);
+};
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/ipc.hpp b/Usermode/Applications/axwin4_src/Server/include/ipc.hpp
new file mode 100644 (file)
index 0000000..50b0dbe
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * ipc.hpp
+ * - IPC Interface Header
+ */
+#ifndef _IPC_H_
+#define _IPC_H_
+
+#include <exception>
+
+extern "C" {
+#include <acess/sys.h>
+};
+
+#include <serialisation.hpp>
+#include <CConfigIPC.hpp>
+
+namespace AxWin {
+
+class CCompositor;
+class CClient;
+
+namespace IPC {
+
+extern void    Initialise(const CConfigIPC& config, CCompositor& compositor);
+extern int     FillSelect(::fd_set& rfds);
+extern void    HandleSelect(const ::fd_set& rfds);
+extern void    RegisterClient(CClient& client);
+extern CClient*        GetClientByID(uint16_t id);
+extern void    DeregisterClient(CClient& client);
+
+extern void    SendMessage_NotifyDims(CClient& client, unsigned int WinID, unsigned int NewW, unsigned int NewH);
+extern void    SendMessage_MouseButton(CClient& client, unsigned int WinID, unsigned int X, unsigned int Y, uint8_t Button, bool Pressed);
+extern void    SendMessage_MouseMove(CClient& client, unsigned int WinID, unsigned int X, unsigned int Y);
+extern void    SendMessage_KeyEvent(CClient& client, unsigned int WinID, uint32_t KeySym, bool Pressed, const char *Translated);
+
+extern void    HandleMessage(CClient& client, CDeserialiser& message);
+
+class CClientFailure:
+       public ::std::exception
+{
+       const std::string m_what;
+public:
+       CClientFailure(std::string&& what);
+       ~CClientFailure() throw();
+       const char *what() const throw();
+};
+
+};     // namespace IPC
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/timing.hpp b/Usermode/Applications/axwin4_src/Server/include/timing.hpp
new file mode 100644 (file)
index 0000000..df5d814
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * timing.hpp
+ * - Timing Interface Header
+ */
+#ifndef _TIMING_H_
+#define _TIMING_H_
+
+#include <cstdint>
+
+namespace AxWin {
+namespace Timing {
+
+extern ::int64_t       GetTimeToNextEvent();
+extern void    CheckEvents();
+
+};     // namespace Timing
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/include/video.hpp b/Usermode/Applications/axwin4_src/Server/include/video.hpp
new file mode 100644 (file)
index 0000000..3738099
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang) 
+ *
+ * video.hpp
+ * - Graphics Interface Header
+ */
+#ifndef _VIDEO_H_
+#define _VIDEO_H_
+
+#include <cstdint>
+#include "CConfigVideo.hpp"
+
+namespace AxWin {
+
+class CVideo
+{
+        int    m_fd;
+       unsigned int    m_width;
+       unsigned int    m_height;
+        int    m_bufferFormat;
+public:
+       CVideo(const CConfigVideo& config);
+
+       void GetDims(unsigned int& w, unsigned int& h); 
+       unsigned int width()  const { return m_width;  }
+       unsigned int height() const { return m_height; }
+
+       void BlitLine(const uint32_t* src, unsigned int dst_y, unsigned int dst_x, unsigned int width);
+       void Flush();
+       void SetCursorPos(int X, int Y);
+
+private:
+       void SetBufFormat(unsigned int FormatID);
+       void SetCursorBitmap();
+};
+
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/input.cpp b/Usermode/Applications/axwin4_src/Server/input.cpp
new file mode 100644 (file)
index 0000000..a0ab646
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * input.cpp
+ * - Input
+ */
+#include <CConfigInput.hpp>
+#include <input.hpp>
+#include <CCompositor.hpp>
+#include <algorithm>
+#include <acess/devices/joystick.h>
+#include <cerrno>
+#include <system_error>
+
+namespace AxWin {
+
+CInput::CInput(const ::AxWin::CConfigInput& config, CCompositor& compositor):
+       m_compositor(compositor),
+       m_keyboardFD(0),
+       m_mouseFD(-1)
+{
+       m_mouseFD = _SysOpen(config.mouse_device.c_str(), OPENFLAG_READ|OPENFLAG_WRITE);
+       if( m_mouseFD == -1 )
+               throw ::std::system_error(errno, ::std::system_category());
+       
+       m_mouseX = 640/2;
+       m_mouseY = 480/2;
+       
+       struct mouse_attribute  attr;
+       // X : Limit + Position
+       attr.Num = 0;
+       attr.Value = 640;
+       _SysIOCtl(m_mouseFD, JOY_IOCTL_GETSETAXISLIMIT, &attr);
+       attr.Value = m_mouseX;
+       _SysIOCtl(m_mouseFD, JOY_IOCTL_GETSETAXISPOSITION, &attr);
+       // Y: Limit + Position
+       attr.Num = 1;
+       attr.Value = 480;
+       _SysIOCtl(m_mouseFD, JOY_IOCTL_GETSETAXISLIMIT, &attr);
+       attr.Value = m_mouseY;
+       _SysIOCtl(m_mouseFD, JOY_IOCTL_GETSETAXISPOSITION, &attr);
+}
+
+int CInput::FillSelect(::fd_set& rfds)
+{
+       FD_SET(m_keyboardFD, &rfds);
+       if( m_mouseFD != -1 )
+               FD_SET(m_mouseFD, &rfds);
+       return ::std::max(m_keyboardFD, m_mouseFD)+1;
+}
+
+void CInput::HandleSelect(::fd_set& rfds)
+{
+       if( FD_ISSET(m_keyboardFD, &rfds) )
+       {
+               uint32_t        codepoint;
+               static uint32_t scancode;
+               #define KEY_CODEPOINT_MASK      0x3FFFFFFF
+               
+               size_t readlen = _SysRead(m_keyboardFD, &codepoint, sizeof(codepoint));
+               if( readlen != sizeof(codepoint) )
+               {
+                       // oops, error
+                       _SysDebug("Terminal read failed? (%i != %i)", readlen, sizeof(codepoint));
+               }
+       
+//             _SysDebug("Keypress 0x%x", codepoint);
+       
+               switch(codepoint & 0xC0000000)
+               {
+               case 0x00000000:        // Key pressed
+                       m_compositor.KeyState(0, scancode, true, codepoint & KEY_CODEPOINT_MASK);
+                       break;
+               case 0x40000000:        // Key release
+                       m_compositor.KeyState(0, scancode, false, codepoint & KEY_CODEPOINT_MASK);
+                       scancode = 0;
+                       break;
+               case 0x80000000:        // Key refire
+                       m_compositor.KeyState(0, scancode, true, codepoint & KEY_CODEPOINT_MASK);
+                       scancode = 0;
+                       break;
+               case 0xC0000000:        // Raw scancode
+                       scancode = codepoint & KEY_CODEPOINT_MASK;
+                       break;
+               }
+       }
+       
+       if( m_mouseFD != -1 && FD_ISSET(m_mouseFD, &rfds) )
+       {
+               const int c_n_axies = 4;
+               const int c_n_buttons = 5;
+               struct mouse_axis       *axies;
+               uint8_t *buttons;
+
+               char data[sizeof(struct mouse_header) + sizeof(*axies)*c_n_axies + c_n_buttons];
+               struct mouse_header     *mouseinfo = (struct mouse_header*)data;
+
+               _SysSeek(m_mouseFD, 0, SEEK_SET);
+               int len = _SysRead(m_mouseFD, data, sizeof(data));
+               if( len < 0 )
+                       throw ::std::system_error(errno, ::std::system_category());
+               
+               len -= sizeof(*mouseinfo);
+               if( len < 0 ) {
+                       _SysDebug("Mouse data undersized (%i bytes short on header)", len);
+                       return ;
+               }
+               if( mouseinfo->NAxies > c_n_axies || mouseinfo->NButtons > c_n_buttons ) {
+                       _SysDebug("%i axies, %i buttons above prealloc counts (%i, %i)",
+                               mouseinfo->NAxies, mouseinfo->NButtons, c_n_axies, c_n_buttons
+                               );
+                       return ;
+               }
+               if( len < sizeof(*axies)*mouseinfo->NAxies + mouseinfo->NButtons ) {
+                       _SysDebug("Mouse data undersized (body doesn't fit %i < %i)",
+                               len, sizeof(*axies)*mouseinfo->NAxies + mouseinfo->NButtons
+                               );
+                       return ;
+               }
+
+               // What? No X/Y?
+               if( mouseinfo->NAxies < 2 ) {
+                       _SysDebug("Mouse data lacks X/Y");
+                       return ;
+               }
+       
+               axies = (struct mouse_axis*)( mouseinfo + 1 );
+               buttons = (uint8_t*)( axies + mouseinfo->NAxies );
+
+               // TODO: Use cursor range only to caputre motion (ignore reported position)
+               m_compositor.MouseMove(0,
+                       m_mouseX, m_mouseY,
+                       axies[0].CursorPos - m_mouseX, axies[1].CursorPos - m_mouseY
+                       );
+               m_mouseX = axies[0].CursorPos;
+               m_mouseY = axies[1].CursorPos;
+
+               for( int i = 0; i < mouseinfo->NButtons; i ++ )
+               {
+                        int    bit = 1 << i;
+                        int    cur = buttons[i] > 128;
+                       if( !!(m_mouseBtns & bit) != cur )
+                       {
+                               m_compositor.MouseButton(0, m_mouseX, m_mouseY, (eMouseButton)i, cur);
+                               // Flip button state
+                               m_mouseBtns ^= bit;
+                       }
+               }
+       }
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Server/ipc.cpp b/Usermode/Applications/axwin4_src/Server/ipc.cpp
new file mode 100644 (file)
index 0000000..f522ac2
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * ipc.cpp
+ * - Client-Server communication (dispatch)
+ */
+#define __STDC_LIMIT_MACROS
+#include <ipc.hpp>
+#include <list>
+#include <IIPCChannel.hpp>
+#include <algorithm>
+#include <CClient.hpp>
+#include <serialisation.hpp>
+#include <ipc_proto.hpp>
+#include <CCompositor.hpp>
+extern "C" {
+#include <assert.h>
+};
+#include <CIPCChannel_AcessIPCPipe.hpp>
+#include <draw_control.hpp>
+#include <draw_text.hpp>
+
+namespace AxWin {
+namespace IPC {
+
+CCompositor*   gpCompositor;
+::std::list<IIPCChannel*>      glChannels;
+::std::map<uint16_t,CClient*>  glClients;
+uint16_t       giNextClient = 1;
+
+void Initialise(const CConfigIPC& config, CCompositor& compositor)
+{
+       gpCompositor = &compositor;
+       
+       ::std::string pipe_basepath = "axwin4";
+       glChannels.push_back( new CIPCChannel_AcessIPCPipe( pipe_basepath ) );
+
+       //glChannels.push_back( new CIPCChannel_TCP("0.0.0.0:2100") );
+       
+       //for( auto channel : config.m_channels )
+       //{
+       //      channels.push_back(  );
+       //}
+}
+
+int FillSelect(fd_set& rfds)
+{
+       int ret = 0;
+       for( const auto channel : glChannels )
+       {
+               assert(channel);
+               ret = ::std::max(ret, channel->FillSelect(rfds));
+       }
+       return ret;
+}
+
+void HandleSelect(const fd_set& rfds)
+{
+       for( const auto channel : glChannels )
+       {
+               assert(channel);
+               channel->HandleSelect(rfds);
+       }
+}
+
+void RegisterClient(CClient& client)
+{
+       _SysDebug("RegisterClient(&client=%p)", &client);
+       // allocate a client ID, and save
+       for( int i = 0; i < 100; i ++ )
+       {
+               uint16_t id = giNextClient++;
+               if(giNextClient == 0)   giNextClient = 1;
+               auto r = glClients.insert( ::std::pair<uint16_t,CClient*>(id, &client) );
+               if( r.second == true )
+               {
+                       client.set_id(id);
+                       return;
+               }
+       }
+       // Wut? 100 attempts and fail!
+       assert(!"Todo - Better way of handling client ID reuse");
+}
+
+CClient* GetClientByID(uint16_t id)
+{
+       auto it = glClients.find(id);
+       if(it == glClients.end()) {
+               //_SysDebug("Client %i not registered", id);
+               return nullptr;
+       }
+       else {
+               //_SysDebug("Client %i %i = %p", id, it->first, it->second);
+               return it->second;
+       }
+}
+
+void DeregisterClient(CClient& client)
+{
+       glClients.erase( client.id() );
+}
+
+
+void SendMessage_NotifyDims(CClient& client, unsigned int WinID, unsigned int NewW, unsigned int NewH)
+{
+       _SysDebug("TODO: IPC::SendMessage_NotifyDims");
+}
+void SendMessage_MouseButton(CClient& client, unsigned int WinID, unsigned int X, unsigned int Y, uint8_t Button, bool Pressed)
+{
+       CSerialiser     msg;
+       msg.WriteU8(IPCMSG_INPUTEVENT);
+       msg.WriteU8(IPC_INEV_MOUSEBTN);
+       msg.WriteU16(WinID);
+       msg.WriteU16(X);
+       msg.WriteU16(Y);
+       msg.WriteU8(Button);
+       msg.WriteU8(Pressed ? 0 : 1);
+       client.SendMessage(msg);
+}
+void SendMessage_MouseMove(CClient& client, unsigned int WinID, unsigned int X, unsigned int Y)
+{
+       _SysDebug("TODO: IPC::SendMessage_MouseMove");
+}
+void SendMessage_KeyEvent(CClient& client, unsigned int WinID, uint32_t KeySym, bool Pressed, const char *Translated)
+{
+       CSerialiser     msg;
+       msg.WriteU8(IPCMSG_INPUTEVENT);
+       msg.WriteU8(IPC_INEV_KEYBOARD);
+       msg.WriteU16(WinID);
+       msg.WriteU16(KeySym);
+       msg.WriteU8(Pressed ? 0 : 1);
+       msg.WriteString(Translated);
+       client.SendMessage(msg);
+}
+
+
+void HandleMessage_Nop(CClient& client, CDeserialiser& message)
+{
+       // Do nothing
+}
+void HandleMessage_Reply(CClient& client, CDeserialiser& message)
+{
+       // Reply to a sent message
+       // - Not many messages need server-bound replies
+       int orig_command = message.ReadU8();
+       switch(orig_command)
+       {
+       case IPCMSG_PING:
+               // Ping reply, mark client as still responding
+               break;
+       default:
+               // Unexpected reply
+               break;
+       }
+}
+
+void HandleMessage_Ping(CClient& client, CDeserialiser& message)
+{
+       // A client has asked for a ping, we pong them back
+       CSerialiser     reply;
+       reply.WriteU8(IPCMSG_REPLY);
+       reply.WriteU8(IPCMSG_PING);
+       client.SendMessage(reply);
+}
+
+void HandleMessage_GetGlobalAttr(CClient& client, CDeserialiser& message)
+{
+       uint16_t        attr_id = message.ReadU16();
+       
+       CSerialiser     reply;
+       reply.WriteU8(IPCMSG_REPLY);
+       reply.WriteU8(IPCMSG_GETGLOBAL);
+       reply.WriteU16(attr_id);
+       
+       switch(attr_id)
+       {
+       case IPC_GLOBATTR_SCREENDIMS: {
+               uint8_t screen_id = message.ReadU8();
+               unsigned int w, h;
+               gpCompositor->GetScreenDims(screen_id, &w, &h);
+               reply.WriteU16( (w <= UINT16_MAX ? w : UINT16_MAX) );
+               reply.WriteU16( (h <= UINT16_MAX ? h : UINT16_MAX) );
+               break; }
+       case IPC_GLOBATTR_MAXAREA:
+               assert(!"TODO: IPC_GLOBATTR_MAXAREA");
+               break;
+       default:
+               throw IPC::CClientFailure("Bad global attribute ID");
+       }
+       
+       client.SendMessage(reply);
+}
+
+void HandleMessage_SetGlobalAttr(CClient& client, CDeserialiser& message)
+{
+       uint16_t        attr_id = message.ReadU16();
+       
+       switch(attr_id)
+       {
+       case IPC_GLOBATTR_SCREENDIMS:
+               // Setting readonly
+               break;
+       case IPC_GLOBATTR_MAXAREA:
+               assert(!"TODO: IPC_GLOBATTR_MAXAREA");
+               break;
+       default:
+               throw IPC::CClientFailure("Bad global attribute ID");
+       }
+}
+
+void HandleMessage_CreateWindow(CClient& client, CDeserialiser& message)
+{
+       uint16_t        new_id = message.ReadU16();
+       //uint16_t      parent_id = message.ReadU16();
+       //CWindow* parent = client.GetWindow( parent_id );
+       ::std::string   name = message.ReadString();
+       
+       ::_SysDebug("_CreateWindow: (%i, '%s')", new_id, name.c_str());
+       client.SetWindow( new_id, new CWindow(*gpCompositor, client, name, new_id) );
+}
+
+void HandleMessage_DestroyWindow(CClient& client, CDeserialiser& message)
+{
+       uint16_t        win_id = message.ReadU16();
+       _SysDebug("_DestroyWindow: (%i)", win_id);
+       
+       CWindow*        win = client.GetWindow(win_id);
+       if(!win) {
+               throw IPC::CClientFailure("_DestroyWindow: Bad window");
+       }
+       client.SetWindow(win_id, 0);    
+       
+       // TODO: Directly inform compositor?
+       delete win;
+}
+
+void HandleMessage_SetWindowAttr(CClient& client, CDeserialiser& message)
+{
+       uint16_t        win_id = message.ReadU16();
+       uint16_t        attr_id = message.ReadU16();
+       _SysDebug("_SetWindowAttr: (Win=%i, ID=%i)", win_id, attr_id);
+       
+       CWindow*        win = client.GetWindow(win_id);
+       if(!win) {
+               throw IPC::CClientFailure("_SetWindowAttr - Bad window");
+       }
+       
+       switch(attr_id)
+       {
+       case IPC_WINATTR_DIMENSIONS: {
+               uint16_t new_w = message.ReadU16();
+               uint16_t new_h = message.ReadU16();
+               win->Resize(new_w, new_h);
+               break; }
+       case IPC_WINATTR_POSITION: {
+               int16_t new_x = message.ReadS16();
+               int16_t new_y = message.ReadS16();
+               win->Move(new_x, new_y);
+               break; }
+       case IPC_WINATTR_SHOW:
+               win->Show( message.ReadU8() != 0 );
+               break;
+       case IPC_WINATTR_FLAGS:
+               win->SetFlags( message.ReadU8() );      // TODO: U8? why so small?
+               break;
+       case IPC_WINATTR_TITLE:
+               assert(!"TODO: IPC_WINATTR_TITLE");
+               break;
+       default:
+               _SysDebug("HandleMessage_SetWindowAttr - Bad attr %u", attr_id);
+               throw IPC::CClientFailure("Bad window attr");
+       }
+}
+
+void HandleMessage_GetWindowAttr(CClient& client, CDeserialiser& message)
+{
+       assert(!"TODO HandleMessage_GetWindowAttr");
+}
+
+void HandleMessage_SendIPC(CClient& client, CDeserialiser& message)
+{
+       assert(!"TODO HandleMessage_SendIPC");
+}
+
+void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message)
+{
+       uint16_t        win_id = message.ReadU16();
+       _SysDebug("_GetWindowBuffer: (%i)", win_id);
+       
+       CWindow*        win = client.GetWindow(win_id);
+       if(!win) {
+               throw IPC::CClientFailure("_PushData: Bad window");
+       }
+       
+       uint64_t handle = win->m_surface.GetSHMHandle();
+       
+       CSerialiser     reply;
+       reply.WriteU8(IPCMSG_REPLY);
+       reply.WriteU8(IPCMSG_GETWINBUF);
+       reply.WriteU16(win_id);
+       reply.WriteU64(handle);
+       client.SendMessage(reply);
+}
+
+void HandleMessage_DamageRect(CClient& client, CDeserialiser& message)
+{
+       uint16_t        winid = message.ReadU16();
+       uint16_t        x = message.ReadU16();
+       uint16_t        y = message.ReadU16();
+       uint16_t        w = message.ReadU16();
+       uint16_t        h = message.ReadU16();
+       
+       _SysDebug("_DamageRect: (%i %i,%i %ix%i)", winid, x, y, w, h);
+       
+       CWindow*        win = client.GetWindow(winid);
+       if(!win) {
+               throw IPC::CClientFailure("_PushData: Bad window");
+       }
+       
+       CRect   area(x,y,w,h);
+       
+       win->Repaint(area);
+}
+
+void HandleMessage_PushData(CClient& client, CDeserialiser& message)
+{
+       uint16_t        win_id = message.ReadU16();
+       uint16_t        x = message.ReadU16();
+       uint16_t        y = message.ReadU16();
+       uint16_t        w = message.ReadU16();
+       uint16_t        h = message.ReadU16();
+       _SysDebug("_PushData: (%i, (%i,%i) %ix%i)", win_id, x, y, w, h);
+       
+       CWindow*        win = client.GetWindow(win_id);
+       if(!win) {
+               throw IPC::CClientFailure("_PushData: Bad window");
+       }
+       
+       for( unsigned int row = 0; row < h; row ++ )
+       {
+               const ::std::vector<uint8_t> scanline_data = message.ReadBuffer();
+               if( scanline_data.size() != w * 4 ) {
+                       _SysDebug("ERROR _PushData: Scanline buffer size mismatch (%i,%i)",
+                               scanline_data.size(), w*4);
+                       continue ;
+               }
+               win->DrawScanline(y+row, x, w, scanline_data.data());
+       }
+}
+void HandleMessage_Blit(CClient& client, CDeserialiser& message)
+{
+       assert(!"TODO HandleMessage_Blit");
+}
+void HandleMessage_DrawCtl(CClient& client, CDeserialiser& message)
+{
+       uint16_t        win_id = message.ReadU16();
+       uint16_t        x = message.ReadU16();
+       uint16_t        y = message.ReadU16();
+       uint16_t        w = message.ReadU16();
+       uint16_t        h = message.ReadU16();
+       uint16_t        ctrl_id = message.ReadU16();
+       uint16_t        frame = message.ReadU16();
+       _SysDebug("_DrawCtl: (%i, (%i,%i) %ix%i Ctl%i frame?=0x%04x)", win_id, x, y, w, h, ctrl_id, frame);
+       
+       CWindow*        win = client.GetWindow(win_id);
+       if(!win) {
+               throw IPC::CClientFailure("_DrawCtl: Bad window");
+       }
+       
+       const CControl* ctrl = CControl::GetByID(ctrl_id);
+       if(!ctrl) {
+               throw IPC::CClientFailure("_DrawCtl: Invalid control ID");
+       }
+       
+       CRect   area(x,y,w,h);
+       ctrl->Render(win->m_surface, area);
+}
+void HandleMessage_DrawText(CClient& client, CDeserialiser& message)
+{
+       uint16_t        win_id = message.ReadU16();
+       uint16_t        x = message.ReadU16();
+       uint16_t        y = message.ReadU16();
+       uint16_t        w = message.ReadU16();
+       uint16_t        h = message.ReadU16();
+       uint16_t        font_id = message.ReadU16();
+       ::std::string   str = message.ReadString();
+       _SysDebug("_DrawText: (%i (%i,%i) %ix%i Font%i \"%s\")", win_id, x, y, w, h, font_id, str.c_str());
+       
+       CWindow*        win = client.GetWindow(win_id);
+       if(!win) {
+               throw IPC::CClientFailure("_DrawText: Bad window");
+       }
+       
+       // 1. Get font from client structure
+       IFontFace& fontface = client.GetFont(font_id);
+       
+       // 2. Render
+       CRect   area(x, y, w, h);
+       fontface.Render(win->m_surface, area, str, h);
+}
+
+void HandleMessage_FillRect(CClient& client, CDeserialiser& message)
+{
+       uint16_t        win_id = message.ReadU16();
+       uint16_t        x = message.ReadU16();
+       uint16_t        y = message.ReadU16();
+       uint16_t        w = message.ReadU16();
+       uint16_t        h = message.ReadU16();
+       uint32_t        colour = message.ReadU32();
+       _SysDebug("_FillRect: (%i (%i,%i) %ix%i %06x)", win_id, x, y, w, h, colour);
+       
+       CWindow*        win = client.GetWindow(win_id);
+       if(!win) {
+               throw IPC::CClientFailure("_FillRect: Bad window");
+       }
+       
+       while(h -- ) {
+               win->FillScanline(y++, x, w, colour);
+       }
+}
+
+void HandleMessage_DrawRect(CClient& client, CDeserialiser& message)
+{
+       uint16_t        win_id = message.ReadU16();
+       uint16_t        x = message.ReadU16();
+       uint16_t        y = message.ReadU16();
+       uint16_t        w = message.ReadU16();
+       uint16_t        h = message.ReadU16();
+       uint32_t        colour = message.ReadU32();
+       _SysDebug("_DrawRect: (%i (%i,%i) %ix%i %06x)", win_id, x, y, w, h, colour);
+       
+       CWindow*        win = client.GetWindow(win_id);
+       if(!win) {
+               throw IPC::CClientFailure("_DrawRect: Bad window");
+       }
+       
+       if(h == 0) {
+       }
+       else if(h == 1) {
+               win->FillScanline(y, x, w, colour);
+       }
+       else if(h == 2) {
+               win->FillScanline(y++, x, w, colour);
+               win->FillScanline(y++, x, w, colour);
+       }
+       else {
+               win->FillScanline(y++, x, w, colour);
+               while( h -- > 2 ) {
+                       win->FillScanline(y, x, 1, colour);
+                       win->FillScanline(y, x+w-1, 1, colour);
+                       y ++;
+               }
+               win->FillScanline(y++, x, w, colour);
+       }
+}
+
+typedef void   MessageHandler_op_t(CClient& client, CDeserialiser& message);
+
+MessageHandler_op_t    *message_handlers[] = {
+       [IPCMSG_NULL]       = &HandleMessage_Nop,
+       [IPCMSG_REPLY]      = &HandleMessage_Reply,
+       [IPCMSG_PING]       = &HandleMessage_Ping,
+       [IPCMSG_GETGLOBAL]  = &HandleMessage_GetGlobalAttr,
+       [IPCMSG_SETGLOBAL]  = &HandleMessage_SetGlobalAttr,
+       
+       [IPCMSG_CREATEWIN]  = &HandleMessage_CreateWindow,
+       [IPCMSG_CLOSEWIN]   = &HandleMessage_DestroyWindow,
+       [IPCMSG_SETWINATTR] = &HandleMessage_SetWindowAttr,
+       [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr,
+       [IPCMSG_SENDIPC]    = &HandleMessage_SendIPC,   // Use the GUI server for low-bandwith IPC
+       [IPCMSG_GETWINBUF]  = &HandleMessage_GetWindowBuffer,
+       [IPCMSG_DAMAGERECT] = &HandleMessage_DamageRect,
+       [IPCMSG_PUSHDATA]   = &HandleMessage_PushData,  // to a window's buffer
+       [IPCMSG_BLIT]       = &HandleMessage_Blit,      // Copy data from one part of the window to another
+       [IPCMSG_DRAWCTL]    = &HandleMessage_DrawCtl,   // Draw a control
+       [IPCMSG_DRAWTEXT]   = &HandleMessage_DrawText,  // Draw text
+       [IPCMSG_FILLRECT]   = &HandleMessage_FillRect,  // Fill a rectangle
+       [IPCMSG_DRAWRECT]   = &HandleMessage_DrawRect,  // Draw (outline) a rectangle
+};
+
+void HandleMessage(CClient& client, CDeserialiser& message)
+{
+       const unsigned int num_commands = sizeof(message_handlers)/sizeof(IPC::MessageHandler_op_t*);
+       unsigned int command = message.ReadU8();
+       if( command >= num_commands ) {
+               // Drop, invalid command
+               _SysDebug("HandleMessage: Command %u is invalid (out of range for %u)", command, num_commands);
+               return ;
+       }
+       
+       (message_handlers[command])(client, message);
+}
+
+CClientFailure::CClientFailure(std::string&& what):
+       m_what(what)
+{
+}
+const char *CClientFailure::what() const throw()
+{
+       return m_what.c_str();
+}
+CClientFailure::~CClientFailure() throw()
+{
+}
+
+};     // namespace IPC
+
+IIPCChannel::~IIPCChannel()
+{
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Server/main.cpp b/Usermode/Applications/axwin4_src/Server/main.cpp
new file mode 100644 (file)
index 0000000..1b64da4
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Acess2 GUI v4 (AxWin4)
+ * - By John Hodge (thePowesGang)
+ * 
+ * main.cpp
+ * - Program main
+ */
+#include <CConfig.hpp>
+#include <ipc.hpp>
+#include <input.hpp>
+#include <video.hpp>
+#include <CCompositor.hpp>
+#include <timing.hpp>
+#include <exception>
+#include <algorithm>
+#include <common.hpp>
+
+#include <system_error>
+#include <cerrno>
+
+extern "C" {
+#include <stdio.h>
+#include <stdint.h>
+};
+
+using namespace AxWin;
+
+// === CODE ===
+int main(int argc, char *argv[])
+{
+       // - Load configuration (from file and argv)
+       CConfig config;
+       try {
+               config.parseCommandline(argc, argv);
+       }
+       catch(const std::exception& e) {
+               fprintf(stderr, "Exception: %s\n", e.what());
+               _SysDebug("Config threw exception: %s", e.what());
+               return 1;
+       }
+       
+       CVideo* vid = 0;
+       CCompositor*    compositor = 0;
+       CInput* input = 0;
+       
+       try {
+               // - Open graphics
+               vid = new CVideo(config.m_video);
+               ::_SysDebug("vid = %p", vid);
+               // - Initialise compositor structures
+               compositor = new CCompositor(/*config.m_compositor,*/ *vid);
+               ::_SysDebug("compositor = %p", compositor);
+               // - Open input
+               input = new CInput(config.m_input, *compositor);
+               ::_SysDebug("input = %p", input);
+               //  > Handles hotkeys?
+               // - Bind IPC channels
+               IPC::Initialise(config.m_ipc, *compositor);
+               ::_SysDebug("IPC up");
+               // - Start root child process (from config)
+               // TODO: Spin up child process
+               
+               {
+                       const char *interface_app = "/Acess/Apps/AxWin/4.0/AxWinUI";
+                       const char *argv[] = {interface_app, NULL};
+                        int    rv = _SysSpawn(interface_app, argv, NULL, 0, NULL, NULL);
+                       if( rv < 0 ) {
+                               _SysDebug("_SysSpawn chucked a sad, rv=%i, errno=%i", rv, _errno);
+                               throw ::std::system_error(errno, ::std::system_category());
+                       }
+               }
+       }
+       catch(const ::std::exception& e) {
+               fprintf(stderr, "Startup threw exception: %s\n", e.what());
+               _SysDebug("Startup threw exception: %s", e.what());
+               delete input;
+               delete compositor;
+               delete vid;
+               return 1;
+       }
+       
+       // - Event loop
+       for( ;; )
+       {
+                int    nfd = 0;
+               fd_set  rfds, efds;
+               
+               FD_ZERO(&rfds);
+               FD_ZERO(&efds);
+       
+               nfd = ::std::max(nfd, input->FillSelect(rfds));
+               nfd = ::std::max(nfd, IPC::FillSelect(rfds));
+               
+               for( int i = 0; i < nfd; i ++ )
+                       if( FD_ISSET(i, &rfds) )
+                               FD_SET(i, &efds);
+
+               #if 0
+               for( int i = 0; i < nfd; i ++ ) {
+                       if( FD_ISSET(i, &rfds) ) {
+                               _SysDebug("FD%i", i);
+                       }
+               }
+               #endif
+               
+               // TODO: Support _SysSendMessage IPC?
+               int64_t timeout = Timing::GetTimeToNextEvent();
+               int64_t *timeoutp;
+               if( timeout >= 0 ) {
+                       ::_SysDebug("Calling select with timeout %lli", timeout);
+                       timeoutp = &timeout;
+               }
+               else {
+                       //::_SysDebug("Calling select with no timeout");
+                       timeoutp = 0;
+               }
+               int rv = ::_SysSelect(nfd, &rfds, NULL, NULL/*&efds*/, timeoutp, 0);
+               
+               #if 0
+               for( int i = 0; i < nfd; i ++ ) {
+                       if( FD_ISSET(i, &rfds) ) {
+                               _SysDebug("FD%i", i);
+                       }
+               }
+               #endif
+               //_SysDebug("rv=%i, timeout=%lli", rv, timeout);
+               
+               try {
+                       Timing::CheckEvents();
+                       
+                       input->HandleSelect(rfds);
+                       IPC::HandleSelect(rfds);
+                       
+                       compositor->Redraw();
+               }
+               catch(...) {
+                       ::_SysDebug("Exception during select handling");
+               }
+       }
+       return 0;
+}
+
+namespace AxWin {
+
+const char* InitFailure::what() const throw()
+{
+       return m_what;
+}
+
+
+}
+
diff --git a/Usermode/Applications/axwin4_src/Server/resources/cursor.h b/Usermode/Applications/axwin4_src/Server/resources/cursor.h
new file mode 100644 (file)
index 0000000..be2d77b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ */
+#ifndef _RESORUCE_CURSOR_H
+#define _RESORUCE_CURSOR_H
+
+#include <stdint.h>
+
+static struct {
+       uint16_t        W, H;
+       uint32_t        Data[8*16];
+} __attribute__((packed)) cCursorBitmap = {
+       8, 16,
+       {
+               0xFF000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFF000000, 0xFF000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFF000000, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000,
+               0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000,
+               0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0xFF000000, 0xFF000000,
+               0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000,
+               0xFF000000, 0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000,
+               0xFF000000, 0xFF000000, 0x00000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000,
+               0xFF000000, 0x00000000, 0x00000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFF000000, 0xFF000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+       }
+};
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/Server/resources/font_8x16.h b/Usermode/Applications/axwin4_src/Server/resources/font_8x16.h
new file mode 100644 (file)
index 0000000..b9bad5d
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Taken from http://cvs.savannah.gnu.org/viewvc/vgabios/vgafonts.h?root=vgabios&view=markup
+ * Altered for Acess2
+ */
+#define FONT_WIDTH     8
+#define FONT_HEIGHT    16
+static uint8_t VTermFont[256*16]=
+{
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+       0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
+       0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+       0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
+       0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
+       0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
+       0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00,
+       0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+       0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+       0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+       0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00,
+       0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+       0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00,
+       0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00,
+       0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+       0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+       0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+       0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+       0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
diff --git a/Usermode/Applications/axwin4_src/Server/timing.cpp b/Usermode/Applications/axwin4_src/Server/timing.cpp
new file mode 100644 (file)
index 0000000..e61c8e2
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * timing.cpp
+ * - Timing code
+ */
+#include <timing.hpp>
+
+namespace AxWin {
+namespace Timing {
+
+int64_t GetTimeToNextEvent()
+{
+       return -1;
+}
+
+void CheckEvents()
+{
+       
+}
+
+};     // namespace Timing
+};     // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/Server/video.cpp b/Usermode/Applications/axwin4_src/Server/video.cpp
new file mode 100644 (file)
index 0000000..50686c6
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * video.cpp
+ * - Graphics output
+ */
+#include <cstddef>
+#include <video.hpp>
+#include <common.hpp>
+
+extern "C" {
+#include <acess/sys.h>
+#include <acess/devices/pty.h>
+#include <acess/devices/pty_cmds.h>
+#include "resources/cursor.h"
+}
+
+namespace AxWin {
+
+CVideo::CVideo(const CConfigVideo& config):
+       m_fd(1),
+       m_width(0),
+       m_height(0),
+       m_bufferFormat(PTYBUFFMT_TEXT)
+{
+       // Obtain dimensions
+       {
+               if( _SysIOCtl(m_fd, DRV_IOCTL_TYPE, NULL) != DRV_TYPE_TERMINAL )
+                       throw AxWin::InitFailure("stdin isn't a terminal");
+               struct ptydims  dims;
+               if( _SysIOCtl(m_fd, PTY_IOCTL_GETDIMS, &dims) == -1 )
+                       throw AxWin::InitFailure("Failed to get dimensions from stdin");
+               m_width = dims.PW;
+               m_height = dims.PH;
+               if( m_width == 0 || m_height == 0 )
+                       throw AxWin::InitFailure("Terminal not capable of graphics");
+       }
+       
+       _SysDebug("m_width=%i, m_height=%i", m_width, m_height);
+       SetCursorBitmap();
+       
+       SetCursorPos( m_width/2, m_height/2 );
+       
+       SetBufFormat(PTYBUFFMT_FB);
+       uint32_t        data[m_width];
+       for( unsigned int i = 0; i < m_height; i ++ )
+               BlitLine(data, i, 0, m_width);
+}
+
+void CVideo::GetDims(unsigned int& w, unsigned int& h)
+{
+       w = m_width;
+       h = m_height;
+}
+
+void CVideo::BlitLine(const uint32_t* src, unsigned int dst_y, unsigned int dst_x, unsigned int width)
+{
+       //_SysDebug("CVideo::BlitLine (%p, %i, %i, %i)", src, dst_y, dst_x, width);
+       //_SysDebugHex("CVideo::BlitLine", src, width*4);
+       size_t  cmdlen = (sizeof(struct ptycmd_senddata) + width*4)/4;
+       //_SysDebug(" - Offset = %i, cmdlen = %i", (dst_y * m_width + dst_x) * 4, cmdlen);
+       struct ptycmd_senddata  cmd = {
+               {PTY2D_CMD_SEND, uint8_t(cmdlen & 0xFF), uint16_t(cmdlen>>8)},
+               (dst_y * m_width + dst_x)
+       };
+       SetBufFormat(PTYBUFFMT_2DCMD);
+       _SysWrite(m_fd, &cmd, sizeof(cmd));
+       _SysWrite(m_fd, src, width*4);
+}
+
+void CVideo::Flush()
+{
+       // TODO: Write to a local copy of the framebuffer in BlitLine, and then flush out in this function
+}
+
+void CVideo::SetBufFormat(unsigned int FormatID)
+{
+       if( m_bufferFormat != FormatID )
+       {
+               
+               struct ptymode mode = {.OutputMode = FormatID, .InputMode = 0};
+               int rv = _SysIOCtl( m_fd, PTY_IOCTL_SETMODE, &mode );
+               if( rv ) {
+                       throw ::AxWin::InitFailure("Can't set PTY to framebuffer mode");
+               }
+               
+               m_bufferFormat = FormatID;
+       }
+}
+
+void CVideo::SetCursorBitmap()
+{
+       // Set cursor position and bitmap
+       struct ptycmd_header    hdr = {PTY2D_CMD_SETCURSORBMP,0,0};
+       size_t size = sizeof(hdr) + sizeof(cCursorBitmap) + cCursorBitmap.W*cCursorBitmap.H*4;
+       hdr.len_low = size / 4;
+       hdr.len_hi = size / (256*4);
+       
+       SetBufFormat(PTYBUFFMT_2DCMD);
+       _SysWrite(m_fd, &hdr, sizeof(hdr));
+       _SysDebug("SetCursorBitmap - size = %i (%04x:%02x * 4)", size, hdr.len_hi, hdr.len_low);
+       _SysWrite(m_fd, &cCursorBitmap, size-sizeof(hdr));
+}
+
+void CVideo::SetCursorPos(int X, int Y)
+{
+       struct ptycmd_setcursorpos      cmd;
+       cmd.hdr.cmd = PTY2D_CMD_SETCURSORPOS;
+       cmd.hdr.len_low = sizeof(cmd)/4;
+       cmd.hdr.len_hi = 0;
+       cmd.x = X;
+       cmd.y = Y;
+
+       SetBufFormat(PTYBUFFMT_2DCMD);  
+       _SysWrite(m_fd, &cmd, sizeof(cmd));
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Applications/axwin4_src/UI/Makefile b/Usermode/Applications/axwin4_src/UI/Makefile
new file mode 100644 (file)
index 0000000..f225d5f
--- /dev/null
@@ -0,0 +1,12 @@
+
+include ../../Makefile.cfg
+
+DIR := Apps/AxWin/4.0
+
+OBJ := main.o taskbar.o
+
+BIN := AxWinUI
+
+LIBS += -laxwin4
+
+include ../../Makefile.tpl
diff --git a/Usermode/Applications/axwin4_src/UI/include/common.h b/Usermode/Applications/axwin4_src/UI/include/common.h
new file mode 100644 (file)
index 0000000..f51cca6
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+extern unsigned int    giScreenWidth;
+extern unsigned int    giScreenHeight;
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/UI/include/taskbar.h b/Usermode/Applications/axwin4_src/UI/include/taskbar.h
new file mode 100644 (file)
index 0000000..728cece
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ */
+#ifndef _TASKBAR_H_
+#define _TASKBAR_H_
+
+#include <stdbool.h>
+
+extern void Taskbar_Create(void);
+extern void Taskbar_Redraw(void);
+
+#endif
+
diff --git a/Usermode/Applications/axwin4_src/UI/main.c b/Usermode/Applications/axwin4_src/UI/main.c
new file mode 100644 (file)
index 0000000..624e381
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * AxWin4 GUI - UI Core
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Program core
+ */
+#include <axwin4/axwin.h>
+#include <assert.h>
+#include "include/common.h"
+#include "include/taskbar.h"
+
+// === PROTOTYPES ===
+tAxWin4_Window *CreateBGWin(int w, int h);
+
+// === GLOABLS ===
+unsigned int   giScreenWidth = 640;
+unsigned int   giScreenHeight = 480;
+
+// === CODE ===
+int main(int argc, const char *argv[])
+{
+       assert( AxWin4_Connect("ipcpipe:///Devices/ipcpipe/axwin4") );
+       
+       AxWin4_GetScreenDimensions(0, &giScreenWidth, &giScreenHeight);
+       
+       tAxWin4_Window *bgwin = CreateBGWin(giScreenWidth, giScreenHeight);
+       Taskbar_Create();
+       
+       _SysDebug("Beginning queue");
+       while( AxWin4_WaitEventQueue(0) )
+               ;
+       _SysDebug("Clean exit");
+       
+       return 0;
+}
+
+tAxWin4_Window *CreateBGWin(int w, int h)
+{
+       tAxWin4_Window  *bgwin = AxWin4_CreateWindow("background");
+       AxWin4_MoveWindow(bgwin, 0,0);
+       AxWin4_ResizeWindow(bgwin, w,h);
+       AxWin4_SetWindowFlags(bgwin, AXWIN4_WNDFLAG_NODECORATE|AXWIN4_WNDFLAG_KEEPBELOW);
+       
+       // Load background image
+       uint32_t *buf = AxWin4_GetWindowBuffer(bgwin);
+       if( buf )
+       {
+               for( size_t y = 0; y < h; y ++ )
+               {
+                       for(size_t x = 0; x < w; x ++ )
+                       {
+                               uint8_t r = y * 256 / h;
+                               uint8_t g = 0;
+                               uint8_t b = x * 256 / w;
+                               buf[y*w+x] = (r << 16) | (g << 8) | b;
+                       }
+               }
+       }
+       else
+       {
+               AxWin4_FillRect(bgwin, 0, 0, w, h, 0x8888CC);
+       }
+       //AxWin4_DamageRect(bgwin, 0, 0, w, h);
+       AxWin4_ShowWindow(bgwin, true);
+       
+       return bgwin;
+}
+
diff --git a/Usermode/Applications/axwin4_src/UI/taskbar.c b/Usermode/Applications/axwin4_src/UI/taskbar.c
new file mode 100644 (file)
index 0000000..b62a042
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * AxWin4 GUI - UI Core
+ * - By John Hodge (thePowersGang)
+ *
+ * taskbar.c
+ * - Main toolbar (aka Taskbar) 
+ */
+#include <axwin4/axwin.h>
+#include "include/common.h"
+#include "include/taskbar.h"
+#include <time.h>
+
+// === CONSTANTS ===
+#define TASKBAR_HEIGHT 30
+#define TASKBAR_BORDER 3       // Border between window edge and controls
+#define TASKBAR_SYSBTN_SIZE    (TASKBAR_HEIGHT-TASKBAR_BORDER*2)
+#define TASKBAR_WIN_MAXSIZE    100
+#define TASKBAR_WIN_MINSIZE    24
+#define TASKBAR_CLOCKSIZE      60
+
+// === TYPES ===
+typedef struct sTaskbar_Win    tTaskbar_Win;
+struct sTaskbar_Win
+{
+       tTaskbar_Win    *Next;
+       const char      *Title;
+};
+
+// === PROTOTYPES ===
+
+// === GLOBALS ===
+tAxWin4_Window *gpTaskbar_Window;
+unsigned int giTaskbar_NumWins = 0;
+tTaskbar_Win   *gpTaskbar_FirstWin;
+
+// === CODE ===
+void Taskbar_Create(void)
+{
+       gpTaskbar_Window = AxWin4_CreateWindow("taskbar");
+       tAxWin4_Window * const win = gpTaskbar_Window;
+
+       AxWin4_MoveWindow(win, 0, 0);
+       AxWin4_ResizeWindow(win, giScreenWidth, TASKBAR_HEIGHT);
+       
+       AxWin4_SetWindowFlags(win, AXWIN4_WNDFLAG_NODECORATE);
+       Taskbar_Redraw();
+       AxWin4_ShowWindow(win, true);
+}
+
+void Taskbar_Redraw(void)
+{
+       const int       w = giScreenWidth;
+       const int       h = TASKBAR_HEIGHT;
+       
+       const int       active_height = h - TASKBAR_BORDER*2;
+       const int       winlist_start_x = TASKBAR_BORDER+TASKBAR_SYSBTN_SIZE+TASKBAR_BORDER;
+       const int       clock_start_x = w - (TASKBAR_BORDER+TASKBAR_CLOCKSIZE);
+       
+       // Window background: Toolbar skin
+       AxWin4_DrawControl(gpTaskbar_Window, 0, 0, w, h, AXWIN4_CTL_TOOLBAR, 0);
+       
+       // System button
+       // TODO: Use an image instead
+       AxWin4_DrawControl(gpTaskbar_Window, TASKBAR_BORDER, TASKBAR_BORDER, TASKBAR_SYSBTN_SIZE, active_height, AXWIN4_CTL_BUTTON, 0);
+       
+       // Windows
+       // TODO: Maintain/request a list of windows
+       if( giTaskbar_NumWins )
+       {
+               int winbutton_size = (clock_start_x - winlist_start_x) / giTaskbar_NumWins;
+               if(winbutton_size > TASKBAR_WIN_MAXSIZE)        winbutton_size = TASKBAR_WIN_MAXSIZE;
+               int x = winlist_start_x;
+               for(tTaskbar_Win *win = gpTaskbar_FirstWin; win; win = win->Next )
+               {
+                       AxWin4_DrawControl(gpTaskbar_Window, x, TASKBAR_BORDER, winbutton_size, active_height, AXWIN4_CTL_BUTTON, 0);
+               }
+       }
+       
+       // Clock
+       {
+               char timestr[5];
+               time_t  rawtime;
+               time(&rawtime);
+               strftime(timestr, 5, "%H%M", localtime(&rawtime));
+               //AxWin4_DrawControl(gpTaskbar_Window, clock_start_x, TASKBAR_BORDER, TASKBAR_CLOCKSIZE, active_height, AXWIN4_CTL_BOX);
+               
+               AxWin4_DrawText(gpTaskbar_Window, clock_start_x, TASKBAR_BORDER, TASKBAR_CLOCKSIZE, active_height, 0, timestr);
+       }
+       
+       AxWin4_DamageRect(gpTaskbar_Window, 0, 0, w, h);
+}
+
index fe1b214..25e256e 100644 (file)
@@ -2,7 +2,7 @@
 
 -include ../Makefile.cfg
 
-LDFLAGS += -laxwin3
+LIBS += -laxwin3
 
 OBJ = main.o strings.o toolbar.o
 BIN = ate
index a38f135..be64500 100644 (file)
@@ -2,7 +2,7 @@
 
 -include ../Makefile.cfg
 
-LDFLAGS += -laxwin3 -lunicode
+LIBS += -laxwin3 -lunicode
 
 OBJ = main.o vt100.o display.o
 BIN = terminal
index 0f00bd9..6a2321e 100644 (file)
@@ -17,6 +17,8 @@
 # include <assert.h>
 # include <stdlib.h>   // malloc/free
 
+# define ASSERTC(a, r, b)      assert(a r b)
+
 static inline int MIN(int a, int b)
 {
        return a < b ? a : b;
@@ -170,7 +172,7 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf)
                        if( ret <= old_inc_len ) {
                                _SysDebug("Term_HandleVT100: ret(%i) <= old_inc_len(%i), inc_len=%i, '%*C'",
                                        ret, old_inc_len, st->cache_len, st->cache_len, st->cache);
-                               assert(ret > old_inc_len);
+                               ASSERTC(ret, >, old_inc_len);
                        }
                        st->cache_len = 0;
                        //_SysDebug("%i bytes of escape code '%.*s' (return %i)",
@@ -186,6 +188,10 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf)
 
        switch( *Buf )
        {
+       case '\a':
+               // Alarm, aka bell
+               //Display_SoundBell(Term);
+               break;
        case '\b':
                // backspace is aprarently just supposed to cursor left (if possible)
                Display_MoveCursor(Term, 0, -1);
@@ -442,9 +448,13 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                        Display_MoveCursor(Term, 0, -(args[0] != 0 ? args[0] : 1));
                        break;
                case 'H':
-                       if( argc != 2 ) {
+                       if( argc == 0 ) {
+                               Display_SetCursor(Term, 0, 0);
                        }
-                       else {
+                       else if( argc == 1 ) {
+                               Display_SetCursor(Term, args[0]-1, 0);
+                       }
+                       else if( argc == 2 ) {
                                // Adjust 1-based cursor position to 0-based
                                Display_SetCursor(Term, args[0]-1, args[1]-1);
                        }
@@ -483,12 +493,12 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                                break;
                        }
                        break;
-               case 'S':       // Scroll text up n=1
-                       Display_ScrollDown(Term, (argc >= 1 ? args[0] : 1));
-                       break;
-               case 'T':       // Scroll text down n=1
+               case 'S':       // Scroll text up n=1 (expose bottom)
                        Display_ScrollDown(Term, -(argc >= 1 ? args[0] : 1));
                        break;
+               case 'T':       // Scroll text down n=1 (expose top)
+                       Display_ScrollDown(Term, (argc >= 1 ? args[0] : 1));
+                       break;
                case 'c':       // Send Device Attributes
                        switch(args[0])
                        {
@@ -529,6 +539,40 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                                // Reset
                                Display_ResetAttributes(Term);
                        }
+                       else if( args[0] == 48 )
+                       {
+                               // ISO-8613-3 Background
+                               if( args[1] == 2 ) {
+                                       uint32_t        col = 0;
+                                       col |= (uint32_t)args[2] << 16;
+                                       col |= (uint32_t)args[3] << 8;
+                                       col |= (uint32_t)args[4] << 0;
+                                       Display_SetBackground(Term, col);
+                               }
+                               else if( args[1] == 5 ) {
+                                       _SysDebug("TODO: Support xterm palette BG %i", args[2]);
+                               }
+                               else {
+                                       _SysDebug("VT100 Unknown mode set \e[48;%im", args[1]);
+                               }
+                       }
+                       else if( args[0] == 38 )
+                       {
+                               // ISO-8613-3 Foreground
+                               if( args[1] == 2 ) {
+                                       uint32_t        col = 0;
+                                       col |= (uint32_t)args[2] << 16;
+                                       col |= (uint32_t)args[3] << 8;
+                                       col |= (uint32_t)args[4] << 0;
+                                       Display_SetForeground(Term, col);
+                               }
+                               else if( args[1] == 5 ) {
+                                       _SysDebug("TODO: Support xterm palette FG %i", args[2]);
+                               }
+                               else {
+                                       _SysDebug("VT100 Unknown mode set \e[38;%im", args[1]);
+                               }
+                       }
                        else
                        {
                                for( int i = 0; i < argc; i ++ )
@@ -549,6 +593,9 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                                        case 4:
                                                _SysDebug("TODO: \\e[4m - Underscore");
                                                break;
+                                       //case 5:
+                                       //      _SysDebug("TODO: \\e[5m - Blink/bold");
+                                       //      break;
                                        case 7:
                                                _SysDebug("TODO: \\e[7m - Reverse");
                                                break;
@@ -570,6 +617,14 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                                                st->CurBG = 0;
                                                Display_SetBackground( Term, caVT100Colours[ st->CurBG ] );
                                                break;
+                                       case 90 ... 97:
+                                               st->CurFG = args[i]-90 + 8;
+                                               Display_SetForeground( Term, caVT100Colours[ st->CurBG ] );
+                                               break;;
+                                       case 100 ... 107:
+                                               st->CurBG = args[i]-100 + 8;
+                                               Display_SetBackground( Term, caVT100Colours[ st->CurBG ] );
+                                               break;;
                                        default:
                                                _SysDebug("Unknown mode set \\e[%im", args[i]);
                                                break;
@@ -582,7 +637,7 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                        break;
                // Set scrolling region
                case 'r':
-                       Display_SetScrollArea(Term, args[0], (args[1] - args[0]));
+                       Display_SetScrollArea(Term, args[0]-1, (args[1] - args[0])+1);
                        break;
                
                case 's':
index 11833a0..73411b9 100644 (file)
@@ -7,6 +7,7 @@
 #include <string.h>
 #include "common.h"
 #include <ctype.h>
+#include <inttypes.h>
 
 // === CONSTANTS ===
 #define DEFAULT_SHELL  "/Acess/SBin/login"
@@ -452,6 +453,8 @@ int SpawnKTerm(tInitProgram *Program)
         int    in = _SysOpen(path, OPENFLAG_READ);
         int    out = _SysOpen(path, OPENFLAG_WRITE);
        
+       _SysDebug("Spawning virtual terminal '%s' with term '%s'",
+               path, Program->Command[0]);
        return SpawnCommand(in, out, out, Program->Command, env);
 }
 
@@ -475,6 +478,8 @@ int SpawnSTerm(tInitProgram *Program)
        _SysIOCtl(in, SERIAL_IOCTL_GETSETFORMAT, &Program->TypeInfo.STerm.FormatBits);
        #endif
 
+       _SysDebug("Spawning serial terminal '%s' with term '%s'",
+               Program->TypeInfo.STerm.Path, Program->Command[0]);
        return SpawnCommand(in, out, out, Program->Command, NULL);
 }
 
@@ -495,17 +500,15 @@ int SpawnDaemon(tInitProgram *Program)
        // Log spawn header
        {
                char    buffer[101];
-               size_t len = snprintf(buffer, 100, "[%lli] init spawning ", _SysTimestamp());
+               size_t len = snprintf(buffer, 100, "[%"PRIi64"] init spawning ", _SysTimestamp());
                _SysWrite(out, buffer, len);
-               char ch = '\'';
                for( int i = 0; Program->Command[i]; i ++ )
                {
-                       _SysWrite(out, &ch, 1);
+                       _SysWrite(out, "'", 1);
                        _SysWrite(out, Program->Command[i], strlen(Program->Command[i]));
-                       _SysWrite(out, &ch, 1);
+                       _SysWrite(out, "'", 1);
                }
-               ch = '\n';
-               _SysWrite(out, &ch, 1);
+               _SysWrite(out, "\n", 1);
        }
        
        return SpawnCommand(in, out, err, Program->Command, NULL);
index 1c976b5..e3ff4e9 100644 (file)
@@ -2,7 +2,8 @@
 
 -include ../Makefile.cfg
 
-LDFLAGS += -lnet
+LDFLAGS +=
+LIBS    += -lnet
 
 OBJ = main.o addr.o routes.o
 BIN = ip
index 9fab060..78d803e 100644 (file)
@@ -2,9 +2,10 @@
 
 -include ../Makefile.cfg
 
-LDFLAGS += -lnet -lreadline
+LIBS += -lnet -lreadline
 
-OBJ = main.o
+OBJ = main.o server.o input.o
+OBJ += window.o pseudo_curses.o
 BIN = irc
 
 -include ../Makefile.tpl
diff --git a/Usermode/Applications/irc_src/common.h b/Usermode/Applications/irc_src/common.h
new file mode 100644 (file)
index 0000000..e374328
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include "pseudo_curses.h"
+
+typedef struct sServer tServer;
+
+extern void    _SysDebug(const char *format, ...);
+
+extern int     writef(int FD, const char *Format, ...);
+extern int     OpenTCP(const char *AddressString, short PortNumber);
+extern char    *GetValue(char *Src, int *Ofs);
+
+extern void    Redraw_Screen(void);
+extern void    Exit(const char *Reason) __attribute__((noreturn));
+
+#endif
+
diff --git a/Usermode/Applications/irc_src/input.c b/Usermode/Applications/irc_src/input.c
new file mode 100644 (file)
index 0000000..b99935c
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ */
+#include "input.h"
+#include "window.h"
+#include "server.h"
+#include <readline.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+// === PROTOTYPES ===
+void   Input_FillSelect(int *nfds, fd_set *rfds);
+void   Input_HandleSelect(int nfds, const fd_set *rfds);
+ int   ParseUserCommand(char *String);
+
+// === GLOBALS ===
+tReadline      *gpInput_ReadlineInfo;
+
+// === CODE ===
+void Input_FillSelect(int *nfds, fd_set *rfds)
+{
+       if( !gpInput_ReadlineInfo ) {
+               gpInput_ReadlineInfo = Readline_Init(1);
+       }
+       
+       FD_SET(0, rfds);
+       if(*nfds < 0+1)
+               *nfds = 0+1;
+}
+
+void Input_HandleSelect(int nfds, const fd_set *rfds)
+{
+       // User input
+       if(FD_ISSET(0, rfds))
+       {
+               char    *cmd = Readline_NonBlock(gpInput_ReadlineInfo);
+               if( cmd )
+               {
+                       if( cmd[0] )
+                       {
+                               ParseUserCommand(cmd);
+                       }
+                       free(cmd);
+                       // Prompt
+                       SetCursorPos(giTerminal_Height, 1);
+                       printf("\x1B[2K");      // Clear line
+                       int prompt_len = printf("[%s] ", Window_GetName(NULL));
+                       SetCursorPos(giTerminal_Height, prompt_len+1);
+                       fflush(stdout);
+               }
+       }
+}
+
+void Cmd_join(char *ArgString)
+{
+        int    pos=0;
+       char    *channel_name = GetValue(ArgString, &pos);
+       
+       tServer *srv = Window_GetServer(NULL);
+       
+       if( srv )
+       {
+               Windows_SwitchTo( Window_Create(srv, channel_name) );
+               Redraw_Screen();
+               Server_SendCommand(srv, "JOIN :%s", channel_name);
+       }
+}
+
+void Cmd_quit(char *ArgString)
+{
+       const char *quit_message = ArgString;
+       if( quit_message == NULL || quit_message[0] == '\0' )
+               quit_message = "/quit - Acess2 IRC Client";
+       
+       Servers_CloseAll(quit_message);
+       
+       Exit(NULL);     // NULL = user requested
+}
+
+void Cmd_window(char *ArgString)
+{
+        int    pos = 0;
+       char    *window_id = GetValue(ArgString, &pos);
+        int    window_num = atoi(window_id);
+       
+       if( window_num > 0 )
+       {
+               // Get `window_num`th window
+               tWindow *win = Windows_GetByIndex(window_num-1);
+               if( win )
+               {
+                       Windows_SwitchTo( win );
+               }
+               else
+               {
+                       // Otherwise, silently ignore
+               }
+       }
+       else
+       {
+               window_num = 1;
+               for( tWindow *win; (win = Windows_GetByIndex(window_num-1)); window_num ++ )
+               {
+                       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, NULL, "%i: %s", window_num, Window_GetName(win));
+               }
+       }
+}
+
+void Cmd_me(char *ArgString)
+{
+       tServer *srv = Window_GetServer(NULL);
+       if( srv && Window_IsChat(NULL) ) {
+               Window_AppendMessage(NULL, MSG_CLASS_ACTION, Server_GetNick(srv), "%s", ArgString);
+               Server_SendCommand(srv, "PRIVMSG %s :\1ACTION %s\1\n", Window_GetName(NULL), ArgString);
+       }
+}
+
+const struct {
+       const char *Name;
+       void    (*Fcn)(char *ArgString);
+} caCommands[] = {
+       {"join", Cmd_join},
+       {"quit", Cmd_quit},
+       {"window", Cmd_window},
+       {"win",    Cmd_window},
+       {"w",      Cmd_window},
+};
+const int ciNumCommands = sizeof(caCommands)/sizeof(caCommands[0]);
+
+/**
+ * \brief Handle a line from the prompt
+ */
+int ParseUserCommand(char *String)
+{
+       if( String[0] == '/' )
+       {
+               char    *command;
+                int    pos = 0;
+               
+               command = GetValue(String, &pos)+1;
+
+               // TODO: Prefix matches
+                int    cmdIdx = -1;
+               for( int i = 0; i < ciNumCommands; i ++ )
+               {
+                       if( strcmp(command, caCommands[i].Name) == 0 ) {
+                               cmdIdx = i;
+                               break;
+                       }
+               }
+               if( cmdIdx != -1 ) {
+                       caCommands[cmdIdx].Fcn(String+pos);
+               }
+               else
+               {
+                       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, NULL, "Unknown command %s", command);
+               }
+       }
+       else
+       {
+               // Message
+               // - Only send if server is valid and window name is non-empty
+               tServer *srv = Window_GetServer(NULL);
+               if( srv && Window_IsChat(NULL) ) {
+                       Window_AppendMessage(NULL, MSG_CLASS_MESSAGE, Server_GetNick(srv), "%s", String);
+                       Server_SendCommand(srv, "PRIVMSG %s :%s\n", Window_GetName(NULL), String);
+               }
+       }
+       
+       return 0;
+}
diff --git a/Usermode/Applications/irc_src/input.h b/Usermode/Applications/irc_src/input.h
new file mode 100644 (file)
index 0000000..dee859e
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ */
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+#include <acess/sys.h>
+
+extern void    Input_FillSelect(int *nfds, fd_set *rfds);
+extern void    Input_HandleSelect(int nfds, const fd_set *rfds);
+
+#endif
+
index 1ca53c2..6169519 100755 (executable)
@@ -6,94 +6,47 @@
 #include <stdio.h>
 #include <string.h>
 #include <net.h>
-#include <readline.h>
-#include <acess/devices/pty.h>
 #include <stdarg.h>
+#include <acess/devices/pty.h>
 
-// === TYPES ===
-typedef struct sServer {
-       struct sServer  *Next;
-        int    FD;
-       char    InBuf[BUFSIZ+1];
-        int    ReadPos;
-       char    Name[];
-} tServer;
-
-typedef struct sMessage
-{
-       struct sMessage *Next;
-       time_t  Timestamp;
-       tServer *Server;
-        int    Type;
-       char    *Source;        // Pointer into `Data`
-       char    Data[];
-}      tMessage;
-
-typedef struct sWindow
-{
-       struct sWindow  *Next;
-       tMessage        *Messages;
-       tServer *Server;        //!< Canonical server (can be NULL)
-        int    ActivityLevel;
-       char    Name[]; // Channel name / remote user
-}      tWindow;
+#include "common.h"
+#include "input.h"
+#include "window.h"
+#include "server.h"
 
-enum eMessageTypes
-{
-       MSG_TYPE_NULL,
-       MSG_TYPE_SERVER,        // Server message
-       
-       MSG_TYPE_NOTICE,        // NOTICE command
-       MSG_TYPE_JOIN,  // JOIN command
-       MSG_TYPE_PART,  // PART command
-       MSG_TYPE_QUIT,  // QUIT command
-       
-       MSG_TYPE_STANDARD,      // Standard line
-       MSG_TYPE_ACTION,        // /me
-       
-       MSG_TYPE_UNK
-};
+// === TYPES ===
 
 // === PROTOTYPES ===
  int   main(int argc, const char *argv[], const char *envp[]);
  int   MainLoop(void);
  int   ParseArguments(int argc, const char *argv[]);
- int   ParseUserCommand(char *String);
 // --- 
-tServer        *Server_Connect(const char *Name, const char *AddressString, short PortNumber);
-tMessage       *Message_AppendF(tServer *Server, int Type, const char *Source, const char *Dest, const char *Message, ...) __attribute__((format(__printf__,5,6)));
-tMessage       *Message_Append(tServer *Server, int Type, const char *Source, const char *Dest, const char *Message);
-tWindow        *Window_Create(tServer *Server, const char *Name);
 void   Redraw_Screen(void);
-
- int   ProcessIncoming(tServer *Server);
 // --- Helpers
-void   SetCursorPos(int Row, int Col);
+void   Exit(const char *Reason);
  int   writef(int FD, const char *Format, ...);
  int   OpenTCP(const char *AddressString, short PortNumber);
 char   *GetValue(char *Str, int *Ofs);
-static inline int      isdigit(int ch);
 
 // === GLOBALS ===
-char   *gsUsername = "user";
-char   *gsHostname = "acess";
-char   *gsRealName = "Acess2 IRC Client";
-char   *gsNickname = "acess";
-tServer        *gpServers;
-tWindow        gWindow_Status = {
-       NULL, NULL, NULL,       // No next, empty list, no server
-       0, {""} // No activity, empty name (rendered as status)
-};
-tWindow        *gpWindows = &gWindow_Status;
-tWindow        *gpCurrentWindow = &gWindow_Status;
- int   giTerminal_Width = 80;
- int   giTerminal_Height = 25;
+const char     *gsExitReason = "No reason [BUG]";
 
 // ==== CODE ====
 void ExitHandler(void)
 {
        printf("\x1B[?1047l");
-       printf("Quit\n");
+       printf("Quit: %s\n", gsExitReason);
+
+       // stty +echo,canon
+       struct ptymode  mode = {.InputMode = 0, .OutputMode = 0};
+       mode.InputMode = PTYIMODE_CANON|PTYIMODE_ECHO;
+       _SysIOCtl(0, PTY_IOCTL_SETMODE, &mode);
+}
+
+void Exit(const char *Reason)
+{
+       gsExitReason = (Reason ? Reason : "User Requested");
+       exit( (Reason ? 1 : 0) );
 }
 
 int main(int argc, const char *argv[], const char *envp[])
@@ -105,117 +58,61 @@ int main(int argc, const char *argv[], const char *envp[])
        
        atexit(ExitHandler);
        
-       if( _SysIOCtl(1, DRV_IOCTL_TYPE, NULL) != DRV_TYPE_TERMINAL ) {
-               fprintf(stderr, "note: assuming 80x25, can't get terminal dimensions\n");
-               giTerminal_Width = 80;
-               giTerminal_Height = 25;
-       }
-       else {
-               struct ptydims  dims;
-               _SysIOCtl(1, PTY_IOCTL_GETDIMS, &dims);
-               giTerminal_Width = dims.W;
-               giTerminal_Height = dims.H;
-       }
+       ACurses_Init();
        
        printf("\x1B[?1047h");
-       printf("\x1B[%i;%ir", 0, giTerminal_Height-1);
-       
-       SetCursorPos(giTerminal_Height-1, 1);
-       printf("[(status)] ");
+       printf("\x1B[%i;%ir", 2, giTerminal_Height-2);
        
        // HACK: Static server entry
        // UCC (University [of Western Australia] Computer Club) IRC Server
-       gWindow_Status.Server = Server_Connect( "UCC", "130.95.13.18", 6667 );
+//     tServer *starting_server = Server_Connect( "UCC", "130.95.13.18", 6667 );
        // Freenode (#osdev)
-//     gWindow_Status.Server = Server_Connect( "Freenode", "89.16.176.16", 6667 );
+       tServer *starting_server = Server_Connect( "Freenode", "84.240.3.129", 6667 );
        // Local servers
 //     gWindow_Status.Server = Server_Connect( "VMHost", "10.0.2.2", 6667 );
 //     gWindow_Status.Server = Server_Connect( "BitlBee", "192.168.1.39", 6667 );
        
-       if( !gWindow_Status.Server )
-               return -1;
+       Windows_SetStatusServer(starting_server);
+       Windows_RepaintCurrent();
+       SetCursorPos(giTerminal_Height-1, 1);
+       printf("[(status)] ");
        
        MainLoop();
-       
-       for( tServer *srv = gpServers; srv; srv = srv->Next )
-               _SysClose(srv->FD);
+
+       Servers_CloseAll("Client closing");
        
        return 0;
 }
 
 int MainLoop(void)
 {
-       SetCursorPos(giTerminal_Height-1, 1);
+       SetCursorPos(giTerminal_Height, 1);
        printf("[(status)] ");
        fflush(stdout);
        
-       tReadline *readline_info = Readline_Init(1);
+       // stty -echo,canon
+       struct ptymode  mode = {.InputMode = 0, .OutputMode = 0};
+       _SysIOCtl(0, PTY_IOCTL_SETMODE, &mode);
        
        for( ;; )
        {
                fd_set  readfds, errorfds;
-                int    maxFD = 0;
+                int    nfds = 1;
                
                FD_ZERO(&readfds);
                FD_ZERO(&errorfds);
-               FD_SET(0, &readfds);    // stdin
-               
-               fflush(stdout);
                
-               // Fill server FDs in fd_set
-               for( tServer *srv = gpServers; srv; srv = srv->Next )
-               {
-                       FD_SET(srv->FD, &readfds);
-                       FD_SET(srv->FD, &errorfds);
-                       if( srv->FD > maxFD )
-                               maxFD = srv->FD;
-               }
+               Input_FillSelect(&nfds, &readfds);
+               Servers_FillSelect(&nfds, &readfds, &errorfds);
                
-               int rv = _SysSelect(maxFD+1, &readfds, 0, &errorfds, NULL, 0);
-               if( rv == -1 )  break;
+               int rv = _SysSelect(nfds, &readfds, 0, &errorfds, NULL, 0);
+               if( rv < 0 )    break;
                
-               if(FD_ISSET(0, &readfds))
-               {
-                       // User input
-                       char    *cmd = Readline_NonBlock(readline_info);
-                       if( cmd )
-                       {
-                               if( cmd[0] )
-                               {
-                                       ParseUserCommand(cmd);
-                               }
-                               free(cmd);
-                               // Prompt
-                               SetCursorPos(giTerminal_Height-1, 1);
-                               printf("\x1B[2K");      // Clear line
-                               if( gpCurrentWindow->Name[0] )
-                                       printf("[%s:%s] ",
-                                               gpCurrentWindow->Server->Name, gpCurrentWindow->Name);
-                               else
-                                       printf("[(status)] ");
-                       }
-               }
+               // user input
+               Input_HandleSelect(nfds, &readfds);
                
                // Server response
-               for( tServer *srv = gpServers; srv; srv = srv->Next )
-               {
-                       if(FD_ISSET(srv->FD, &readfds))
-                       {
-                               if( ProcessIncoming(srv) != 0 ) {
-                                       // Oops, error
-                                       _SysDebug("ProcessIncoming failed on FD%i (Server %p %s)",
-                                               srv->FD, srv, srv->Name);
-                                       return 1;
-                               }
-                       }
-                       
-                       if(FD_ISSET(srv->FD, &errorfds))
-                       {
-                               _SysDebug("Error on FD%i (Server %p %s)",
-                                       srv->FD, srv, srv->Name);
-                               return 1;
-                       }
-               }
+               Servers_HandleSelect(nfds, &readfds, &errorfds);
        }
        return 0;
 }
@@ -228,547 +125,12 @@ int ParseArguments(int argc, const char *argv[])
        return 0;
 }
 
-
-void Cmd_join(char *ArgString)
-{
-        int    pos=0;
-       char    *channel_name = GetValue(ArgString, &pos);
-       
-       if( gpCurrentWindow->Server )
-       {
-               gpCurrentWindow = Window_Create(gpCurrentWindow->Server, channel_name);
-               Redraw_Screen();
-               writef(gpCurrentWindow->Server->FD, "JOIN :%s\n", channel_name);
-       }
-}
-
-void Cmd_quit(char *ArgString)
-{
-       const char *quit_message = ArgString;
-       if( quit_message == NULL || quit_message[0] == '\0' )
-               quit_message = "/quit - Acess2 IRC Client";
-       
-       for( tServer *srv = gpServers; srv; srv = srv->Next )
-       {
-               writef(srv->FD, "QUIT :%s\n", quit_message);
-       }
-       
-       exit(0);
-}
-
-void Cmd_window(char *ArgString)
-{
-        int    pos = 0;
-       char    *window_id = GetValue(ArgString, &pos);
-        int    window_num = atoi(window_id);
-       
-       if( window_num > 0 )
-       {
-               tWindow *win;
-               window_num --;  // Move to base 0
-               // Get `window_num`th window
-               for( win = gpWindows; win && window_num--; win = win->Next );
-               if( win ) {
-                       gpCurrentWindow = win;
-                       Redraw_Screen();
-               }
-               // Otherwise, silently ignore
-       }
-       else
-       {
-               window_num = 1;
-               for( tWindow *win = gpWindows; win; win = win->Next, window_num ++ )
-               {
-                       if( win->Name[0] ) {
-                               Message_AppendF(NULL, MSG_TYPE_SERVER, "client", "",
-                                       "%i: %s/%s", window_num, win->Server->Name, win->Name);
-                       }
-                       else {
-                               Message_AppendF(NULL, MSG_TYPE_SERVER, "client", "",
-                                       "%i: (status)", window_num);
-                       }
-               }
-       }
-}
-
-const struct {
-       const char *Name;
-       void    (*Fcn)(char *ArgString);
-} caCommands[] = {
-       {"join", Cmd_join},
-       {"quit", Cmd_quit},
-       {"window", Cmd_window},
-       {"win",    Cmd_window},
-       {"w",      Cmd_window},
-};
-const int ciNumCommands = sizeof(caCommands)/sizeof(caCommands[0]);
-
-/**
- * \brief Handle a line from the prompt
- */
-int ParseUserCommand(char *String)
-{
-       if( String[0] == '/' )
-       {
-               char    *command;
-                int    pos = 0;
-               
-               command = GetValue(String, &pos)+1;
-
-               // TODO: Prefix matches
-                int    cmdIdx = -1;
-               for( int i = 0; i < ciNumCommands; i ++ )
-               {
-                       if( strcmp(command, caCommands[i].Name) == 0 ) {
-                               cmdIdx = i;
-                               break;
-                       }
-               }
-               if( cmdIdx != -1 ) {
-                       caCommands[cmdIdx].Fcn(String+pos);
-               }
-               else
-               {
-                       Message_AppendF(NULL, MSG_TYPE_SERVER, "client", "", "Unknown command %s", command);
-               }
-       }
-       else
-       {
-               // Message
-               // - Only send if server is valid and window name is non-empty
-               if( gpCurrentWindow->Server && gpCurrentWindow->Name[0] )
-               {
-                       Message_Append(gpCurrentWindow->Server, MSG_TYPE_STANDARD,
-                               gsNickname, gpCurrentWindow->Name, String);
-                       writef(gpCurrentWindow->Server->FD,
-                               "PRIVMSG %s :%s\n", gpCurrentWindow->Name,
-                               String
-                               );
-               }
-       }
-       
-       return 0;
-}
-
-/**
- * \brief Connect to a server
- */
-tServer *Server_Connect(const char *Name, const char *AddressString, short PortNumber)
-{
-       tServer *ret;
-       
-       ret = calloc(1, sizeof(tServer) + strlen(Name) + 1);
-       
-       strcpy(ret->Name, Name);
-       
-       // Connect to the remove server
-       ret->FD = OpenTCP( AddressString, PortNumber );
-       if( ret->FD == -1 ) {
-               fprintf(stderr, "%s: Unable to create socket\n", Name);
-               return NULL;
-       }
-       
-       // Append to open list
-       ret->Next = gpServers;
-       gpServers = ret;
-       
-       // Read some initial data
-       Message_Append(NULL, MSG_TYPE_SERVER, Name, "", "Connection opened");
-       ProcessIncoming(ret);
-       
-       // Identify
-       writef(ret->FD, "USER %s %s %s : %s\n", gsUsername, gsHostname, AddressString, gsRealName);
-       writef(ret->FD, "NICK %s\n", gsNickname);
-       Message_Append(NULL, MSG_TYPE_SERVER, Name, "", "Identified");
-       //printf("%s: Identified\n", Name);
-       
-       return ret;
-}
-
-tMessage *Message_AppendF(tServer *Server, int Type, const char *Source, const char *Dest, const char *Message, ...)
-{
-       va_list args;
-        int    len;
-       va_start(args, Message);
-       len = vsnprintf(NULL, 0, Message, args);
-       va_end(args);
-       
-       char    buf[len+1];
-       va_start(args, Message);
-       vsnprintf(buf, len+1, Message, args);
-       va_end(args);
-       
-       return Message_Append(Server, Type, Source, Dest, buf);
-}
-
-tMessage *Message_Append(tServer *Server, int Type, const char *Source, const char *Dest, const char *Message)
-{
-       tWindow *win = NULL;
-        int    msgLen = strlen(Message);
-       
-       // Server==NULL indicates an internal message
-       if( Server == NULL || Source[0] == '\0' )
-       {
-               win = &gWindow_Status;
-       }
-       // Determine if it's a channel or PM
-       else if( Dest[0] == '#' || Dest[0] == '&' )     // TODO: Better determining here
-       {
-               for(win = gpWindows; win; win = win->Next)
-               {
-                       if( win->Server == Server && strcmp(win->Name, Dest) == 0 )
-                       {
-                               break;
-                       }
-               }
-               if( !win ) {
-                       //win = Window_Create(Server, Dest);
-                       win = &gWindow_Status;  // Stick it in the status window, just in case
-               }
-       }
-       #if 0
-       else if( strcmp(Dest, Server->Nick) != 0 )
-       {
-               // Umm... message for someone who isn't us?
-               win = &gWindow_Status;  // Stick it in the status window, just in case
-       }
-       #endif
-       // Server message?
-       else if( strchr(Source, '.') )  // TODO: And again, less hack please
-       {
-               #if 1
-               for(win = gpWindows; win; win = win->Next)
-               {
-                       if( win->Server == Server && strcmp(win->Name, Source) == 0 )
-                       {
-                               break;
-                       }
-               }
-               #endif
-               if( !win ) {
-                       win = &gWindow_Status;
-               }
-               
-               // Set source to the server name (instead of the hostname)
-               Source = Server->Name;
-       }
-       // Private message
-       else
-       {
-               for(win = gpWindows; win; win = win->Next)
-               {
-                       if( win->Server == Server && strcmp(win->Name, Source) == 0 )
-                       {
-                               break;
-                       }
-               }
-               if( !win ) {
-                       win = Window_Create(Server, Dest);
-               }
-       }
-
-       // Create message cache 
-       _SysDebug("Win (%s) msg: <%s> %s", win->Name, Source, Message);
-       tMessage        *ret;
-       ret = malloc( sizeof(tMessage) + msgLen + 1 + strlen(Source) + 1 );
-       ret->Source = ret->Data + msgLen + 1;
-       strcpy(ret->Source, Source);
-       strcpy(ret->Data, Message);
-       ret->Type = Type;
-       ret->Server = Server;
-       
-       // Append to window message list
-       ret->Next = win->Messages;
-       win->Messages = ret;
-       
-       // Print now if current window
-       if( win == gpCurrentWindow )
-       {
-               printf("\33[s");
-               printf("\33[T");        // Scroll down 1 (free space below)
-               SetCursorPos(giTerminal_Height-2, 1);
-                int    prefixlen = strlen(Source) + 3;
-                int    avail = giTerminal_Width - prefixlen;
-                int    msglen = strlen(Message);
-               printf("[%s] %.*s", Source, avail, Message);
-               while( msglen > avail ) {
-                       msglen -= avail;
-                       Message += avail;
-                       printf("\33[T");
-                       SetCursorPos(giTerminal_Height-2, prefixlen+1);
-                       printf("%.*s", avail, Message);
-               }
-               printf("\x1b[u");
-       }
-       
-       return ret;
-}
-
-tWindow *Window_Create(tServer *Server, const char *Name)
-{
-       tWindow *ret, *prev = NULL;
-        int    num = 1;
-       
-       // Get the end of the list
-       // TODO: Cache this instead
-       for( ret = gpCurrentWindow; ret; prev = ret, ret = ret->Next )
-               num ++;
-       
-       ret = malloc(sizeof(tWindow) + strlen(Name) + 1);
-       ret->Messages = NULL;
-       ret->Server = Server;
-       ret->ActivityLevel = 1;
-       strcpy(ret->Name, Name);
-       
-       if( prev ) {
-               ret->Next = prev->Next;
-               prev->Next = ret;
-       }
-       else {  // Shouldn't happen really
-               ret->Next = gpWindows;
-               gpWindows = ret;
-       }
-       
-//     printf("Win %i %s:%s created\n", num, Server->Name, Name);
-       
-       return ret;
-}
-
 void Redraw_Screen(void)
 {
-        int    y = 0;
-       tMessage        *msg;
-
        printf("\x1B[2J");      // Clear screen
-       printf("\x1B[0;0H");    // Reset cursor
-
-       msg = gpCurrentWindow->Messages;
-       
-       // TODO: Title bar?
-
-       // Note: This renders from the bottom up
-       for( y = giTerminal_Height - 1; y -- && msg; msg = msg->Next)
-       {
-                int    msglen = strlen(msg->Data);
-                int    prefix_len = 3 + strlen(msg->Source);
-                int    line_avail = giTerminal_Width - prefix_len;
-                int    i = 0, done = 0;
-               
-               y -= msglen / line_avail;       // Extra lines (y-- above handles the 1 line case)
-               SetCursorPos(y, 1);
-               printf("[%s] ", msg->Source);
-               
-               while(done < msglen) {
-                       done += printf("%.*s", line_avail, msg->Data+done);
-                       i ++;
-                       SetCursorPos(y+i, prefix_len+1);
-               }
-       }
-
-       // Bottom line is rendered by the prompt
-}
-
-void Cmd_PRIVMSG(tServer *Server, const char *Dest, const char *Src, const char *Message)
-{
-       Message_Append(Server, MSG_TYPE_STANDARD, Dest, Src, Message);
-       //printf("<%s:%s:%s> %s\n", Server->Name, Dest, Src, Message);
-}
+       printf("\x1B[H");       // Reset cursor
 
-void ParseServerLine_Numeric(tServer *Server, const char *ident, int Num, char *Line)
-{
-        int    pos = 0;
-       const char *message;
-       const char *user = GetValue(Line, &pos);
-       
-       if( Line[pos] == ':' ) {
-               message = Line + pos + 1;
-       }
-       else {
-               message = GetValue(Line, &pos);
-       }
-       
-       switch(Num)
-       {
-       case 332:       // Topic
-               user = message; // Channel
-               message = Line + pos + 1;       // Topic
-               Message_AppendF(Server, MSG_TYPE_SERVER, user, user, "Topic: %s", message);
-               break;
-       case 333:       // Topic set by
-               user = message; // Channel
-               message = GetValue(Line, &pos); // User
-               GetValue(Line, &pos);   // Timestamp
-               Message_AppendF(Server, MSG_TYPE_SERVER, user, user, "Set by %s", message);
-               break;
-       case 353:       // /NAMES list
-               // <user> = <channel> :list
-               // '=' was eaten in and set to message
-               user = GetValue(Line, &pos);    // Actually channel
-               message = Line + pos + 1;       // List
-               Message_AppendF(Server, MSG_TYPE_SERVER, user, user, "Names: %s", message);
-               break;
-       case 366:       // end of /NAMES list
-               // <user> <channel> :msg
-               user = message;
-               message = Line + pos + 1;
-               Message_Append(Server, MSG_TYPE_SERVER, user, user, message);
-               break;
-       case 372:       // MOTD Data
-       case 375:       // MOTD Start
-       case 376:       // MOTD End
-               
-       default:
-               //printf("[%s] %i %s\n", Server->Name, num, message);
-               Message_Append(Server, MSG_TYPE_SERVER, ident, user, message);
-               break;
-       }
-}
-
-void ParseServerLine_String(tServer *Server, const char *ident, const char *cmd, char *Line)
-{
-        int    pos = 0;
-       _SysDebug("ident=%s,cmd=%s,Line=%s", ident, cmd, Line);
-       if( strcmp(cmd, "NOTICE") == 0 )
-       {
-               const char *class = GetValue(Line, &pos);
-               _SysDebug("NOTICE class='%s'", class);
-               
-               const char *message = (Line[pos] == ':') ? Line + pos + 1 : GetValue(Line, &pos);
-               
-               //printf("[%s] NOTICE %s: %s\n", Server->Name, ident, message);
-               char *ident_bang = strchr(ident, '!');
-               if( ident_bang ) {
-                       *ident_bang = '\0';
-               }
-               Message_Append(Server, MSG_TYPE_NOTICE, ident, "", message);
-       }
-       else if( strcmp(cmd, "PRIVMSG") == 0 )
-       {
-               const char *dest = GetValue(Line, &pos);
-               const char *message = (Line[pos] == ':') ? Line + pos + 1 : GetValue(Line, &pos);
-
-               // TODO: Catch when the privmsg is addressed to the user
-
-//             Cmd_PRIVMSG(Server, dest, ident, message);
-               char *ident_bang = strchr(ident, '!');
-               if( ident_bang ) {
-                       *ident_bang = '\0';
-               }
-               Message_Append(Server, MSG_TYPE_STANDARD, ident, dest, message);
-       }
-       else if( strcmp(cmd, "JOIN" ) == 0 )
-       {
-               const char      *channel = Line + pos + 1;
-               
-               Message_AppendF(Server, MSG_TYPE_JOIN, "", channel, "%s has joined", ident);
-               //Window_Create(Server, channel);
-       }
-       else if( strcmp(cmd, "PART" ) == 0 )
-       {
-               const char      *channel = Line + pos + 1;
-               
-               Message_AppendF(Server, MSG_TYPE_PART, "", channel, "%s has left", ident);
-               //Window_Create(Server, channel);
-       }
-       else
-       {
-               Message_AppendF(Server, MSG_TYPE_SERVER, "", "", "Unknown message %s (%s)", cmd, Line);
-       }
-}
-
-/**
- */
-void ParseServerLine(tServer *Server, char *Line)
-{
-        int    pos = 0;
-
-       _SysDebug("[%s] %s", Server->Name, Line);       
-       
-       // Message?
-       if( *Line == ':' )
-       {
-               pos ++;
-               const char *ident = GetValue(Line, &pos);       // Ident (user or server)
-               const char *cmd = GetValue(Line, &pos);
-               
-               // Numeric command
-               if( isdigit(cmd[0]) && isdigit(cmd[1]) && isdigit(cmd[2]) )
-               {
-                        int    num;
-                       num  = (cmd[0] - '0') * 100;
-                       num += (cmd[1] - '0') * 10;
-                       num += (cmd[2] - '0') * 1;
-
-                       ParseServerLine_Numeric(Server, ident, num, Line+pos);
-               }
-               else
-               {
-                       ParseServerLine_String(Server, ident, cmd, Line+pos);
-               }
-       }
-       else {
-               const char *cmd = GetValue(Line, &pos);
-               
-               if( strcmp(cmd, "PING") == 0 ) {
-                       writef(Server->FD, "PONG %s\n", Line+pos);
-               }
-               else {
-                       // Command to client
-                       Message_AppendF(NULL, MSG_TYPE_UNK, "", "", "Client Command: %s", Line);
-               }
-       }
-}
-
-/**
- * \brief Process incoming lines from the server
- */
-int ProcessIncoming(tServer *Server)
-{      
-       char    *ptr, *newline;
-        int    len;
-       
-       // While there is data in the buffer, read it into user memory and 
-       // process it line by line
-       // ioctl#8 on a TCP client gets the number of bytes in the recieve buffer
-       // - Used to avoid blocking
-       #if NON_BLOCK_READ
-       while( (len = _SysIOCtl(Server->FD, 8, NULL)) > 0 )
-       {
-       #endif
-               // Read data
-               len = _SysRead(Server->FD, &Server->InBuf[Server->ReadPos], BUFSIZ - Server->ReadPos);
-               if( len == -1 ) {
-                       return -1;
-               }
-               Server->InBuf[Server->ReadPos + len] = '\0';
-               
-               // Break into lines
-               ptr = Server->InBuf;
-               while( (newline = strchr(ptr, '\n')) )
-               {
-                       *newline = '\0';
-                       if( newline[-1] == '\r' )       newline[-1] = '\0';
-                       ParseServerLine(Server, ptr);
-                       ptr = newline + 1;
-               }
-               
-               // Handle incomplete lines
-               if( ptr - Server->InBuf < len + Server->ReadPos ) {
-                       // Update the read position
-                       // InBuf ReadPos    ptr          ReadPos+len
-                       // | old | new used | new unused |
-                       Server->ReadPos = len + Server->ReadPos - (ptr - Server->InBuf);
-                       // Copy stuff back (moving "new unused" to the start of the buffer)
-                       memcpy(Server->InBuf, ptr, Server->ReadPos);
-               }
-               else {
-                       Server->ReadPos = 0;
-               }
-       #if NON_BLOCK_READ
-       }
-       #endif
-       
-       return 0;
+       Windows_RepaintCurrent();
 }
 
 /**
@@ -863,12 +225,3 @@ char *GetValue(char *Src, int *Ofs)
        return ret;
 }
 
-void SetCursorPos(int Row, int Col)
-{
-       printf("\x1B[%i;%iH", Row, Col);
-}
-
-static inline int isdigit(int ch)
-{
-       return '0' <= ch && ch < '9';
-}
diff --git a/Usermode/Applications/irc_src/message.h b/Usermode/Applications/irc_src/message.h
new file mode 100644 (file)
index 0000000..0b86f12
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ */
+#ifndef _MESSAGE_H_
+#define _MESSAGE_H_
+
+enum eMessageTypes
+{
+       MSG_TYPE_NULL,
+       MSG_TYPE_SERVER,        // Server message
+       
+       MSG_TYPE_NOTICE,        // NOTICE command
+       MSG_TYPE_JOIN,  // JOIN command
+       MSG_TYPE_PART,  // PART command
+       MSG_TYPE_QUIT,  // QUIT command
+       
+       MSG_TYPE_STANDARD,      // Standard line
+       MSG_TYPE_ACTION,        // /me
+       
+       MSG_TYPE_UNK
+};
+
+enum eMessageClass
+{
+       MSG_CLASS_BARE, // source is unused, just gets timestamped
+       MSG_CLASS_CLIENT,       // source optional, prefixed by '-!-'
+       MSG_CLASS_WALL,         // [SOURCE] MSG         -- Server-provided message
+       MSG_CLASS_MESSAGE,      // <SOURCE> MSG
+       MSG_CLASS_ACTION,       // * SOURCE MSG
+};
+
+typedef struct sMessage        tMessage;
+
+//extern tMessage      *Message_AppendF(tServer *Server, int Type, const char *Src, const char *Dst, const char *Fmt, ...) __attribute__((format(__printf__,5,6)));
+//extern tMessage      *Message_Append(tServer *Server, int Type, const char *Source, const char *Dest, const char *Message);
+
+#endif
+
diff --git a/Usermode/Applications/irc_src/pseudo_curses.c b/Usermode/Applications/irc_src/pseudo_curses.c
new file mode 100644 (file)
index 0000000..23ee137
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ */
+#include "pseudo_curses.h"
+#include <stdbool.h>
+#include <acess/sys.h>
+#include <acess/devices/pty.h>
+#include <stdio.h>
+
+// === PROTOTYPES ===
+bool   ACurses_GetDims_Acess(void);
+bool   ACurses_GetDims_SerialTermHack(void);
+
+// === GLOBALS ===
+ int   giTerminal_Width = 80;
+ int   giTerminal_Height = 25;
+
+// === CODE ===
+void ACurses_Init(void)
+{
+       if( ACurses_GetDims_Acess() ) {
+       }
+       else if( ACurses_GetDims_SerialTermHack() ) {
+       }
+       else {
+               _SysDebug("note: assuming 80x25, can't get terminal dimensions");
+               giTerminal_Width = 80;
+               giTerminal_Height = 25;
+       }
+}
+
+bool ACurses_GetDims_Acess(void)
+{
+       if( _SysIOCtl(1, DRV_IOCTL_TYPE, NULL) != DRV_TYPE_TERMINAL )
+               return false;
+       
+       struct ptydims  dims;
+       if( _SysIOCtl(1, PTY_IOCTL_GETDIMS, &dims) == -1 )
+               return false;
+       giTerminal_Width = dims.W;
+       giTerminal_Height = dims.H;
+       return true;
+}
+
+bool ACurses_GetDims_SerialTermHack(void)
+{
+       _SysDebug("ACurses_GetDims_SerialTermHack: Trying");
+       // Set cursor to 1000,1000 , request cursor position, reset cursor to 0,0
+       static const char req[] = "\033[1000;1000H\033[6n\033[H";
+       fflush(stdin);
+       _SysWrite(1, req, sizeof(req));
+       int64_t timeout = 1000;
+       fd_set fds;
+       FD_ZERO(&fds);
+       FD_SET(0, &fds);
+       _SysSelect(1, &fds, NULL, NULL, &timeout, 0);
+       if( !FD_ISSET(0, &fds) )
+               return false;
+       
+       if( fgetc(stdin) != '\x1b' )
+               return false;
+       if( fgetc(stdin) != '[' )
+               return false;
+       if( fscanf(stdin, "%i;%i", &giTerminal_Width, &giTerminal_Height) != 2 )
+               return false;
+       if( fgetc(stdin) != 'R' )
+               return false;
+       
+       return true;
+}
+
+void SetCursorPos(int Row, int Col)
+{
+       printf("\x1B[%i;%iH", Row, Col);
+}
+
diff --git a/Usermode/Applications/irc_src/pseudo_curses.h b/Usermode/Applications/irc_src/pseudo_curses.h
new file mode 100644 (file)
index 0000000..0548e92
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ */
+#ifndef _ACURSES_H_
+#define _ACURSES_H_
+
+extern int     giTerminal_Width;
+extern int     giTerminal_Height;
+
+extern void    ACurses_Init(void);
+extern void    SetCursorPos(int Row, int Col);
+
+#endif
+
diff --git a/Usermode/Applications/irc_src/server.c b/Usermode/Applications/irc_src/server.c
new file mode 100644 (file)
index 0000000..1b85df4
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "server.h"
+#include "window.h"
+#include <acess/sys.h>
+#include <ctype.h>     // isdigit
+#include <stdio.h>     // vsnprintf
+
+// === PROTOTYPES ===
+tServer        *Server_Connect(const char *Name, const char *AddressString, short PortNumber);
+ int   Server_HandleIncoming(tServer *Server);
+void   ParseServerLine(tServer *Server, char *Line);
+
+// === GLOBALS ===
+const char     *gsUsername = "user";
+const char     *gsHostname = "acess";
+const char     *gsRealName = "An Acess User";
+const char     *gsNickname = "acess";
+const char     *gsVersionResponse = "Acess2 IRC Client / Running on some VM probably";
+tServer        *gpServers;
+
+// === CODE ===
+void Servers_FillSelect(int *nfds, fd_set *rfds, fd_set *efds)
+{
+       for( tServer *srv = gpServers; srv; srv = srv->Next )
+       {
+               FD_SET(srv->FD, rfds);
+               FD_SET(srv->FD, efds);
+               if( srv->FD >= *nfds )
+                       *nfds = srv->FD+1;
+       }
+}
+
+void Servers_HandleSelect(int nfds, const fd_set *rfds, const fd_set *efds)
+{
+       for( tServer *srv = gpServers; srv; srv = srv->Next )
+       {
+               if(FD_ISSET(srv->FD, rfds))
+               {
+                        int    rv = Server_HandleIncoming(srv);
+                       if(rv)
+                       {
+                               // Oops, error
+                               _SysDebug("ProcessIncoming failed on FD%i (Server %p %s)",
+                                       srv->FD, srv, srv->Name);
+                               Exit("Processing error");
+                       }
+               }
+               
+               if(FD_ISSET(srv->FD, efds))
+               {
+                       _SysDebug("Error on FD%i (Server %p %s)",
+                               srv->FD, srv, srv->Name);
+                       Exit("Socket error");
+               }
+       }
+}
+
+void Servers_CloseAll(const char *QuitMessage)
+{
+       while( gpServers )
+       {
+               tServer *srv = gpServers;
+               gpServers = srv->Next;
+       
+               Server_SendCommand(srv, "QUIT :%s", QuitMessage);
+               _SysClose(srv->FD);
+               free(srv);
+       }
+}
+
+/**
+ * \brief Connect to a server
+ */
+tServer *Server_Connect(const char *Name, const char *AddressString, short PortNumber)
+{
+       tServer *ret;
+       
+       ret = calloc(1, sizeof(tServer) + strlen(Name) + 1);
+       
+       strcpy(ret->Name, Name);
+       
+       // Connect to the remove server
+       ret->FD = OpenTCP( AddressString, PortNumber );
+       if( ret->FD == -1 ) {
+               free(ret);
+               Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, Name, "Unable to create socket");
+               return NULL;
+       }
+       
+       ret->Nick = strdup(gsNickname);
+       
+       // Append to open list
+       ret->Next = gpServers;
+       gpServers = ret;
+       
+       // Read some initial data
+       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, Name, "Unable to create socket");
+       Server_HandleIncoming(ret);
+       
+       // Identify
+       Server_SendCommand(ret, "USER %s %s %s : %s", gsUsername, gsHostname, AddressString, gsRealName);
+       Server_SendCommand(ret, "NICK %s", ret->Nick);
+       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, Name, "Identified");
+       
+       return ret;
+}
+
+const char *Server_GetNick(const tServer *Server)
+{
+       return Server ? Server->Nick : "NULL";
+}
+const char *Server_GetName(const tServer *Server)
+{
+       return Server ? Server->Name : "NULL";
+}
+
+void Server_SendCommand(tServer *Server, const char *Format, ...)
+{
+       va_list args;
+        int    len;
+       
+       va_start(args, Format);
+       len = vsnprintf(NULL, 0, Format, args);
+       va_end(args);
+       
+       char    buf[len+1];
+       va_start(args, Format);
+       vsnprintf(buf, len+1, Format, args);
+       va_end(args);
+       
+       _SysWrite(Server->FD, buf, len);
+       _SysWrite(Server->FD, "\n", 1);
+}
+
+void Cmd_PRIVMSG(tServer *Server, const char *Dest, const char *Src, const char *Message)
+{
+       tWindow *win;
+       if( strcmp(Dest, Server->Nick) == 0 ) {
+               win = Windows_GetByNameOrCreate(Server, Src);
+       }
+       else {
+               win = Windows_GetByNameOrCreate(Server, Dest);
+       }
+       
+       // Detect CTCP
+       if( Message[0] == '\1' && Message[strlen(Message)-1] == '\1' )
+       {
+               Message += 1;
+               // message is a CTCP command
+               if( strcmp(Message, "VERSION\1") == 0 )
+               {
+                       // Put a message in the status window, and reply
+                       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, Server->Name, "CTCP VERSION request from %s", Src);
+                       // - Always reply via NOTICE
+                       Server_SendCommand(Server, "NOTICE %s :\1VERSION %s\1", Src, gsVersionResponse);
+               }
+               else if( strncmp(Message, "ACTION ", 7) == 0 )
+               {
+                       Message += 7;
+                       // Put a message in the status window, and reply
+                       Window_AppendMessage(win, MSG_CLASS_ACTION, Src, "%.*s", (int)(strlen(Message)-1), Message);
+               }
+               else
+               {
+                       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, Server->Name, "Unknown CTCP '%s' from %s",
+                               Message, Src);
+               }
+       }
+       else
+       {
+               Window_AppendMessage(win, MSG_CLASS_MESSAGE, Src, "%s", Message);
+       }
+}
+
+/**
+ * \brief Process incoming lines from the server
+ */
+int Server_HandleIncoming(tServer *Server)
+{      
+       char    *ptr, *newline;
+        int    len;
+       
+       // While there is data in the buffer, read it into user memory and 
+       // process it line by line
+       // ioctl#8 on a TCP client gets the number of bytes in the recieve buffer
+       // - Used to avoid blocking
+       #if NON_BLOCK_READ
+       while( (len = _SysIOCtl(Server->FD, 8, NULL)) > 0 )
+       {
+       #endif
+               // Read data
+               len = _SysRead(Server->FD, &Server->InBuf[Server->ReadPos], sizeof(Server->InBuf) - Server->ReadPos);
+               if( len == -1 ) {
+                       return -1;
+               }
+               Server->InBuf[Server->ReadPos + len] = '\0';
+               
+               // Break into lines
+               ptr = Server->InBuf;
+               while( (newline = strchr(ptr, '\n')) )
+               {
+                       *newline = '\0';
+                       if( newline[-1] == '\r' )       newline[-1] = '\0';
+                       ParseServerLine(Server, ptr);
+                       ptr = newline + 1;
+               }
+               
+               // Handle incomplete lines
+               if( ptr - Server->InBuf < len + Server->ReadPos ) {
+                       // Update the read position
+                       // InBuf ReadPos    ptr          ReadPos+len
+                       // | old | new used | new unused |
+                       Server->ReadPos = len + Server->ReadPos - (ptr - Server->InBuf);
+                       // Copy stuff back (moving "new unused" to the start of the buffer)
+                       memcpy(Server->InBuf, ptr, Server->ReadPos);
+               }
+               else {
+                       Server->ReadPos = 0;
+               }
+       #if NON_BLOCK_READ
+       }
+       #endif
+       
+       return 0;
+}
+
+void ParseServerLine_Numeric(tServer *Server, const char *ident, int Num, char *Line)
+{
+        int    pos = 0;
+       const char *message;
+       const char *user = GetValue(Line, &pos);
+       const char      *timestamp;
+       
+       if( Line[pos] == ':' ) {
+               message = Line + pos + 1;
+       }
+       else {
+               message = GetValue(Line, &pos);
+       }
+       
+       switch(Num)
+       {
+       case 332:       // Topic
+               user = message; // Channel
+               message = Line + pos + 1;       // Topic
+               Window_AppendMsg_Topic( Windows_GetByNameOrCreate(Server, user), message );
+               break;
+       case 333:       // Topic set by
+               user = message; // Channel
+               message = GetValue(Line, &pos); // User
+               timestamp = GetValue(Line, &pos);       // Timestamp
+               Window_AppendMsg_TopicTime( Windows_GetByNameOrCreate(Server, user), message, timestamp );
+               break;
+       case 353:       // /NAMES list
+               // TODO: Parse the /names list and store it locally, dump to window when end is seen
+               // <user> = <channel> :list
+               // '=' was eaten in and set to message
+               user = GetValue(Line, &pos);    // Actually channel
+               message = Line + pos + 1;       // List
+               Window_AppendMessage( Windows_GetByNameOrCreate(Server, user), MSG_CLASS_CLIENT, "NAMES", message );
+               break;
+       case 366:       // end of /NAMES list
+               // <user> <channel> :msg
+               // - Ignored
+               break;
+
+       case   1:       // welcome
+       case   2:       // host name and version (text)
+       case   3:       // host uptime
+       case   4:       // host name, version, and signature
+       case   5:       // parameters
+       
+       case 250:       // Highest connection count
+       case 251:       // user count (network)
+       case 252:       // Operator count
+       case 253:       // Unidentified connections
+       case 254:       // Channel count
+       case 255:       // Server's stats
+       case 265:       // Local users -- min max :Text representation
+       case 266:       // Global users (same as above)
+       
+       case 372:       // MOTD Data
+       case 375:       // MOTD Start
+       case 376:       // MOTD End
+               Window_AppendMessage( WINDOW_STATUS, MSG_CLASS_WALL, Server->Name, "%s", message);
+               break;
+               
+       default:
+               //printf("[%s] %i %s\n", Server->Name, num, message);
+               Window_AppendMessage( WINDOW_STATUS, MSG_CLASS_WALL, Server->Name, "Unknown %i %s", Num, message);
+               break;
+       }
+}
+
+void ParseServerLine_String(tServer *Server, const char *ident, const char *cmd, char *Line)
+{
+        int    pos = 0;
+       _SysDebug("ident=%s,cmd=%s,Line=%s", ident, cmd, Line);
+       if( strcmp(cmd, "NOTICE") == 0 )
+       {
+               const char *class = GetValue(Line, &pos);
+               const char *message = (Line[pos] == ':') ? Line + pos + 1 : GetValue(Line, &pos);
+               _SysDebug("NOTICE class='%s'", class);
+               
+               char *ident_bang = strchr(ident, '!');
+               if( ident_bang ) {
+                       *ident_bang = '\0';
+               }
+               // TODO: Colour codes
+               Window_AppendMessage( WINDOW_STATUS, MSG_CLASS_WALL, Server->Name, "%s %s", ident, message);
+       }
+       else if( strcmp(cmd, "PRIVMSG") == 0 )
+       {
+               const char *dest = GetValue(Line, &pos);
+               const char *message = (Line[pos] == ':') ? Line + pos + 1 : GetValue(Line, &pos);
+
+               char *ident_bang = strchr(ident, '!');
+               if( ident_bang ) {
+                       *ident_bang = '\0';
+               }
+               Cmd_PRIVMSG(Server, dest, ident, message);
+       }
+       else if( strcmp(cmd, "JOIN" ) == 0 )
+       {
+               const char      *channel = Line + pos + 1;
+               
+               Window_AppendMsg_Join( Windows_GetByNameOrCreate(Server, channel), ident );
+       }
+       else if( strcmp(cmd, "PART" ) == 0 )
+       {
+               const char      *channel = Line + pos + 1;
+               
+               Window_AppendMsg_Part( Windows_GetByNameOrCreate(Server, channel), ident, "" );
+       }
+       else if( strcmp(cmd, "MODE" ) == 0 )
+       {
+               // ident MODE channel flags nick[ nick...]
+               const char      *channel = GetValue(Line, &pos);
+               const char      *flags = GetValue(Line, &pos);
+               const char      *args = Line + pos;
+               
+               Window_AppendMsg_Mode( Windows_GetByNameOrCreate(Server, channel), ident, flags, args );
+       }
+       else if( strcmp(cmd, "KICK" ) == 0 )
+       {
+               // ident KICK channel nick :reason
+               const char      *channel = GetValue(Line, &pos);
+               const char      *nick = GetValue(Line, &pos);
+               const char      *message = Line + pos + 1;
+               
+               Window_AppendMsg_Kick( Windows_GetByNameOrCreate(Server, channel), ident, nick, message );
+               if( strcmp(nick, Server->Nick) == 0 ) {
+                       // Oh, that was me :(
+                       // - what do?
+               }
+       }
+       else
+       {
+               Window_AppendMessage( WINDOW_STATUS, MSG_CLASS_BARE, Server->Name, "Unknown command '%s' %s", cmd, Line);
+       }
+}
+
+/**
+ */
+void ParseServerLine(tServer *Server, char *Line)
+{
+        int    pos = 0;
+
+       _SysDebug("[%s] %s", Server->Name, Line);       
+       
+       // Message?
+       if( *Line == ':' )
+       {
+               pos ++;
+               const char *ident = GetValue(Line, &pos);       // Ident (user or server)
+               const char *cmd = GetValue(Line, &pos);
+               
+               // Numeric command
+               if( isdigit(cmd[0]) && isdigit(cmd[1]) && isdigit(cmd[2]) )
+               {
+                        int    num;
+                       num  = (cmd[0] - '0') * 100;
+                       num += (cmd[1] - '0') * 10;
+                       num += (cmd[2] - '0') * 1;
+
+                       ParseServerLine_Numeric(Server, ident, num, Line+pos);
+               }
+               else
+               {
+                       ParseServerLine_String(Server, ident, cmd, Line+pos);
+               }
+       }
+       else {
+               const char *cmd = GetValue(Line, &pos);
+               
+               if( strcmp(cmd, "PING") == 0 ) {
+                       Server_SendCommand(Server, "PONG %s", Line+pos);
+               }
+               else {
+                       // Command to client
+                       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, Server->Name, "UNK Client Command: %s", Line);
+               }
+       }
+}
diff --git a/Usermode/Applications/irc_src/server.h b/Usermode/Applications/irc_src/server.h
new file mode 100644 (file)
index 0000000..edc9bd0
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ */
+#ifndef _SERVER_H_
+#define _SERVER_H_
+
+#include "common.h"
+
+typedef struct sServer {
+       struct sServer  *Next;
+        int    FD;
+       char    InBuf[1024+1];
+        int    ReadPos;
+       char    *Nick;
+       char    Name[];
+} tServer;
+
+extern void    Servers_FillSelect(int *nfds, fd_set *rfds, fd_set *efds);
+extern void    Servers_HandleSelect(int nfds, const fd_set *rfds, const fd_set *efds);
+extern void    Servers_CloseAll(const char *QuitMessage);
+
+extern tServer *Server_Connect(const char *Name, const char *AddressString, short PortNumber);
+extern  int    Server_HandleIncoming(tServer *Server);
+
+extern const char      *Server_GetNick(const tServer *Server);
+extern const char      *Server_GetName(const tServer *Server);
+
+extern void    Server_SendCommand(tServer *Server, const char *Format, ...) __attribute__((format(__printf__,2,3)));
+
+#endif
+
diff --git a/Usermode/Applications/irc_src/window.c b/Usermode/Applications/irc_src/window.c
new file mode 100644 (file)
index 0000000..ba12880
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ */
+#include "window.h"
+#include <stddef.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>     // TODO: replace with calls into ACurses_*
+#include <stdlib.h>
+#include <assert.h>
+#include "server.h"
+#include <ctype.h>
+
+struct sMessage
+{
+       struct sMessage *Next;
+       time_t  Timestamp;
+       enum eMessageClass      Class;
+       char    *Source;        // Pointer to the end of `Data`
+       size_t  PrefixLen;
+       char    Data[];
+};
+
+struct sWindow
+{
+       struct sWindow  *Next;
+       tMessage        *Messages;
+       tServer *Server;        //!< Canonical server (can be NULL)
+        int    ActivityLevel;
+       char    Name[]; // Channel name / remote user
+};
+
+// === PROTOTYPES ===
+void   Windows_RepaintCurrent(void);
+size_t WordBreak(const char *Line, size_t avail);
+size_t Windows_int_PaintMessagePrefix(const tMessage *Message, bool EnablePrint);
+size_t Windows_int_PaintMessageLine(const tMessage *Message, size_t Offset, bool EnablePrint);
+ int   Windows_int_GetMessageLines(const tMessage *Message);
+ int   Windows_int_PaintMessage(tMessage *Message);
+
+// === GLOBALS ===
+tWindow        gWindow_Status = {
+       NULL, NULL, NULL,       // No next, empty list, no server
+       0, {"(status)"} // No activity, empty name (rendered as status)
+};
+tWindow        *gpWindows = &gWindow_Status;
+tWindow        *gpCurrentWindow = &gWindow_Status;
+
+// === CODE ===
+void Windows_RepaintCurrent(void)
+{
+       // TODO: Title bar?
+       SetCursorPos(1, 1);
+       printf("\x1b[37;44m\x1b[2K%s\x1b[0m\n", gpCurrentWindow->Name);
+
+        int    avail_rows = giTerminal_Height - 3;
+
+       // Note: This renders from the bottom up
+       tMessage *msg = gpCurrentWindow->Messages;
+       for( int y = avail_rows; msg && y > 0; )
+       {
+               int lines = Windows_int_GetMessageLines(msg);
+               y -= lines;
+               size_t  ofs = 0;
+               size_t  len;
+                int    i = 0;
+               do {
+                       SetCursorPos(2 + y+i, 1);
+                       len = Windows_int_PaintMessageLine(msg, ofs, (y+i >= 0));
+                       ofs += len;
+                       i ++;
+               } while( len > 0 );
+               msg = msg->Next;
+       }
+
+       // Status line is our department
+       SetCursorPos(giTerminal_Height-1, 1);
+       printf("\x1b[37;44m\x1b[2K[%s] [%s/%s]\x1b[0m", Server_GetNick(gpCurrentWindow->Server),
+               Server_GetName(gpCurrentWindow->Server), gpCurrentWindow->Name);
+       fflush(stdout);
+       // Bottom line is rendered by the prompt
+}
+
+size_t WordBreak(const char *Line, size_t avail)
+{
+       // If sufficient space, don't need to break on a word
+       if( strlen(Line) < avail )
+               return strlen(Line);
+       
+       // Search backwards from end of space for a non-alpha-numeric character
+       size_t  ret = avail-1;
+       while( ret > 0 && isalnum(Line[ret]) )
+               ret --;
+       
+       // if one wasn't found in a sane area, just split
+       if( ret < avail-20 || ret == 0 )
+               return avail;
+       
+       return ret;
+}
+
+size_t Windows_int_PaintMessagePrefix(const tMessage *Message, bool EnablePrint)
+{
+       size_t  len = 0;
+       
+       unsigned long   seconds_today = Message->Timestamp/1000 % (24 * 3600);
+       if(EnablePrint)
+               printf("%02i:%02i:%02i ", seconds_today/3600, (seconds_today/60)%60, seconds_today%60);
+       else
+               len += snprintf(NULL, 0, "%02i:%02i:%02i ", seconds_today/3600, (seconds_today/60)%60, seconds_today%60);
+       
+       const char *format;
+       switch(Message->Class)
+       {
+       case MSG_CLASS_BARE:
+               format = "";
+               break;
+       case MSG_CLASS_CLIENT:
+               if(Message->Source)
+                       format = "[%s] -!- ";
+               else 
+                       format = "-!- ";
+               break;
+       case MSG_CLASS_WALL:
+               format = "[%s] ";
+               break;
+       case MSG_CLASS_MESSAGE:
+               format = "<%s> ";
+               break;
+       case MSG_CLASS_ACTION:
+               format = "* %s ";
+               break;
+       }
+       
+       if( EnablePrint )
+               len += printf(format, Message->Source);
+       else
+               len += snprintf(NULL, 0, format, Message->Source);
+
+       return len;
+}
+
+size_t Windows_int_PaintMessageLine(const tMessage *Message, size_t Offset, bool EnablePrint)
+{
+       _SysDebug("Windows_int_PaintMessageLine: Message=%p,Offset=%i,EnablePrint=%b",
+               Message, (int)Offset, EnablePrint);
+       if( Offset > strlen(Message->Data) ) {
+               _SysDebug("Windows_int_PaintMessageLine: No message left");
+               return 0;
+       }
+       _SysDebug("Windows_int_PaintMessageLine: Message->Data=\"%.*s\"+\"%s\"",
+               (int)Offset, Message->Data, Message->Data+Offset);
+       
+       size_t  avail = giTerminal_Width - Message->PrefixLen;
+       const char *msg_data = Message->Data + Offset;
+       int used = WordBreak(msg_data, avail);
+       
+       if( EnablePrint )
+       {
+               if( Offset == 0 )
+                       Windows_int_PaintMessagePrefix(Message, true);
+               else {
+                       for(int i = 0; i < Message->PrefixLen; i ++)
+                               printf(" ");
+                       //printf("\x1b[%iC", Message->PrefixLen);
+               }
+               printf("%.*s", used, msg_data);
+       }
+       
+       _SysDebug("used(%i) >= strlen(msg_data)(%i)", used, strlen(msg_data));
+       if( used >= strlen(msg_data) )
+               return 0;
+       
+       return Offset + used;
+}
+
+int Windows_int_GetMessageLines(const tMessage *Message)
+{
+       assert(Message->PrefixLen);
+       const size_t    avail = giTerminal_Height - Message->PrefixLen;
+       const size_t    msglen = strlen(Message->Data);
+       size_t  offset = 0;
+        int    nLines = 0;
+       do {
+               offset += WordBreak(Message->Data+offset, avail);
+               nLines ++;
+       } while(offset < msglen);
+       return nLines;
+}
+
+void Windows_SwitchTo(tWindow *Window)
+{
+       gpCurrentWindow = Window;
+       Redraw_Screen();
+}
+
+void Windows_SetStatusServer(tServer *Server)
+{
+       gWindow_Status.Server = Server;
+}
+
+tWindow *Windows_GetByIndex(int Index)
+{
+       tWindow *win;
+       for( win = gpWindows; win && Index--; win = win->Next )
+               ;
+       return win;
+}
+
+tWindow *Windows_GetByNameEx(tServer *Server, const char *Name, bool CreateAllowed)
+{
+       tWindow *ret, *prev = NULL;
+        int    num = 1;
+       
+       // Get the end of the list and check for duplicates
+       // TODO: Cache this instead
+       for( ret = &gWindow_Status; ret; prev = ret, ret = ret->Next )
+       {
+               if( ret->Server == Server && strcmp(ret->Name, Name) == 0 )
+               {
+                       return ret;
+               }
+               num ++;
+       }
+       if( !CreateAllowed ) {
+               return NULL;
+       }
+       
+       ret = malloc(sizeof(tWindow) + strlen(Name) + 1);
+       ret->Messages = NULL;
+       ret->Server = Server;
+       ret->ActivityLevel = 1;
+       strcpy(ret->Name, Name);
+       
+       if( prev ) {
+               ret->Next = prev->Next;
+               prev->Next = ret;
+       }
+       else {  // Shouldn't happen really
+               ret->Next = gpWindows;
+               gpWindows = ret;
+       }
+       
+//     printf("Win %i %s:%s created\n", num, Server->Name, Name);
+       
+       return ret;
+}
+
+tWindow *Windows_GetByName(tServer *Server, const char *Name)
+{
+       return Windows_GetByNameEx(Server, Name, false);
+}
+
+tWindow *Window_Create(tServer *Server, const char *Name)
+{
+       return Windows_GetByNameEx(Server, Name, true);
+}
+
+
+tWindow *Window_int_ParseSpecial(const tWindow *Window)
+{
+       if( Window == NULL )
+               return gpCurrentWindow;
+       if( Window == WINDOW_STATUS )
+               return &gWindow_Status;
+       return (tWindow*)Window;
+}
+
+const char *Window_GetName(const tWindow *Window) {
+       return Window_int_ParseSpecial(Window)->Name;
+}
+tServer        *Window_GetServer(const tWindow *Window) {
+       return Window_int_ParseSpecial(Window)->Server;
+}
+bool Window_IsChat(const tWindow *Window) {
+       return Window_int_ParseSpecial(Window) != &gWindow_Status;
+}
+
+// -----------------------------
+//  Messages
+// -----------------------------
+void Window_AppendMessage(tWindow *Window, enum eMessageClass Class, const char *Source, const char *Message, ...)
+{
+       Window = Window_int_ParseSpecial(Window);
+
+       va_list args;
+       
+       va_start(args, Message);
+       size_t len = vsnprintf(NULL, 0, Message, args);
+       va_end(args);
+       
+       tMessage *msg = malloc( sizeof(tMessage) + len+1 + (Source?strlen(Source)+1:0) );
+       assert(msg);
+       
+       msg->Class = Class;
+       msg->Source = (Source ? msg->Data + len+1 : NULL);
+       msg->Timestamp = _SysTimestamp();
+       
+       va_start(args, Message);
+       vsnprintf(msg->Data, len+1, Message, args);
+       va_end(args);
+       
+       if( Source ) {
+               strcpy(msg->Source, Source);
+       }
+       
+       msg->PrefixLen = Windows_int_PaintMessagePrefix(msg, false);
+       
+       msg->Next = Window->Messages;
+       Window->Messages = msg;
+       
+       if( Window == gpCurrentWindow )
+       {
+               // Scroll if needed, and redraw?
+               // - Lazy option of draw at bottom of screen
+               printf("\33[s");        // Save cursor
+               size_t  offset = 0, len;
+               do {
+                       printf("\33[S");        // Scroll down 1 (free space below)
+                       SetCursorPos(giTerminal_Height-2, 1);
+                       len = Windows_int_PaintMessageLine(msg, offset, true);
+                       offset += len;
+               } while( len > 0 );
+               printf("\33[u");        // Restore cursor
+               fflush(stdout);
+       }
+}
+
+void Window_AppendMsg_Join(tWindow *Window, const char *Usermask)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "%s has joined %s", Usermask, Window->Name);
+}
+void Window_AppendMsg_Quit(tWindow *Window, const char *Usermask, const char *Reason)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "%s has joined quit (%s)", Usermask, Reason);
+}
+void Window_AppendMsg_Part(tWindow *Window, const char *Usermask, const char *Reason)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "%s has joined left %s (%s)", Usermask, Window->Name, Reason);
+}
+void Window_AppendMsg_Topic(tWindow *Window, const char *Topic)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "Topic of %s is %s", Window->Name, Topic);
+}
+void Window_AppendMsg_TopicTime(tWindow *Window, const char *User, const char *Timestamp)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "Topic set by %s at %s", User, Timestamp);
+}
+void Window_AppendMsg_Kick(tWindow *Window, const char *Operator, const char *Nick, const char *Reason)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "%s was kicked from %s by %s [%s]",
+               Nick, Window->Name, Operator, Reason);
+}
+void Window_AppendMsg_Mode(tWindow *Window, const char *Operator, const char *Flags, const char *Args)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "mode/%s [%s %s] by %s",
+               Window->Name, Flags, Args, Operator);
+}
+
diff --git a/Usermode/Applications/irc_src/window.h b/Usermode/Applications/irc_src/window.h
new file mode 100644 (file)
index 0000000..620e1a5
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ */
+#ifndef _WINDOW_H_
+#define _WINDOW_H_
+
+#include "common.h"
+#include "message.h"
+#include <stdbool.h>
+
+typedef struct sWindow tWindow;
+extern void    Windows_RepaintCurrent(void);
+
+extern void    Windows_SetStatusServer(tServer *Server);
+extern tWindow *Window_Create(tServer *Server, const char *Name);
+extern tWindow *Windows_GetByIndex(int Index);
+extern tWindow *Windows_GetByName(tServer *Server, const char *Name);
+static inline tWindow  *Windows_GetByNameOrCreate(tServer *Server, const char *Name) {
+       return Window_Create(Server, Name);
+}
+extern void    Windows_SwitchTo(tWindow *Window);
+
+extern void    Window_AppendMessage(tWindow *Window, enum eMessageClass Class, const char *Source, const char *Message, ...)
+       __attribute__((format(__printf__,4,5)));
+extern void    Window_AppendMsg_Join(tWindow *Window, const char *Usermask);
+extern void    Window_AppendMsg_Quit(tWindow *Window, const char *Usermask, const char *Reason);
+extern void    Window_AppendMsg_Part(tWindow *Window, const char *Usermask, const char *Reason);
+extern void    Window_AppendMsg_Kick(tWindow *Window, const char *Operator, const char *Nick, const char *Reason);
+extern void    Window_AppendMsg_Mode(tWindow *Window, const char *Operator, const char *Flags, const char *Args);
+extern void    Window_AppendMsg_Topic(tWindow *Window, const char *Topic);
+extern void    Window_AppendMsg_TopicTime(tWindow *Window, const char *User, const char *Timestmap);
+
+extern const char      *Window_GetName(const tWindow *Window);
+extern tServer *Window_GetServer(const tWindow *Window);
+extern bool    Window_IsChat(const tWindow *Window);
+
+#define WINDOW_STATUS  ((void*)-1)
+
+#endif
index 64c4649..3893fa0 100644 (file)
@@ -2,7 +2,7 @@
 
 -include ../Makefile.cfg
 
-LDFLAGS += -lnet
+LIBS += -lnet
 
 OBJ = main.o
 BIN = ping
index bbcac85..7d61245 100644 (file)
@@ -2,7 +2,7 @@
 
 -include ../Makefile.cfg
 
-LDFLAGS += -lnet -lreadline
+LIBS += -lnet -lreadline
 
 OBJ = main.o
 BIN = telnet
index a85a071..d7d6ee6 100644 (file)
@@ -2,7 +2,7 @@
 
 -include ../Makefile.cfg
 
-LDFLAGS += -lnet
+LIBS += -lnet
 
 OBJ = main.o
 BIN = telnetd
index e6f5a01..db28b27 100644 (file)
@@ -3,7 +3,8 @@
 -include ../Makefile.cfg
 
 CFLAGS += -std=gnu99
-LDFLAGS += -lnet -lpsocket -luri
+LIBS += -lnet -lpsocket -luri
+
 OBJ = main.o
 BIN = wget
 
index 5920059..b10117e 100644 (file)
@@ -4,11 +4,14 @@
 _libsdir := $(dir $(lastword $(MAKEFILE_LIST)))
 -include $(_libsdir)../Makefile.cfg
 
+USE_CXX_LINK :=
+PRELINK :=
 MAKEDEP  = $(CC) -M
 
 ifeq ($(ARCHDIR),native)
  ASFLAGS += -D ARCHDIR=$(ARCHDIR) -D __ASSEMBLER__=1
- LDFLAGS := -lacess-native
+ LDFLAGS := 
+ LIBS := -lacess-native
  #CPPFLAGS := -D SoMain="__attribute__ ((constructor(101))) libacessnative_init"
  ifeq ($(PLATFORM),windows)
  else
@@ -26,13 +29,16 @@ else ifneq ($(HOST_ARCH),)
   CFLAGS += -fPIC
   CXXFLAGS += -fPIC
  endif
+ LIBS := -lld-acess
 else
- CPPFLAGS := -ffreestanding
  CFLAGS   := -fno-stack-protector -fPIC
- CXXFLAGS   := -fno-stack-protector -fPIC
- LDFLAGS  := -I/Acess/Libs/ld-acess.so -lld-acess `$(CC) -print-libgcc-file-name`
+ CXXFLAGS := -fno-stack-protector -fPIC
+ LDFLAGS  := 
+ LIBS := -lld-acess
 endif
-LDFLAGS += -g -nostdlib -shared -eSoMain -x --no-undefined -L$(OUTPUTDIR)Libs/
+LDFLAGS += -g -shared -eSoStart -L$(OUTPUTDIR)Libs/ --no-undefined
+CXXFLAGS += -std=gnu++11
+#CPPFLAGS += -D 'SoMain(...)=SoMain(__VA_ARGS__) __attribute__ ((visibility ("hidden"))); int SoMain(__VA_ARGS__)'
 
 -include $(_libsdir)../common_settings.mk
 
index a99ff14..3b8d2f5 100644 (file)
@@ -10,21 +10,28 @@ ifeq ($(ARCH),native)
  LDFLAGS := $(LDFLAGS:-lc=-lc_acess)
 endif
 
-_LD_CMD := $(lastword $(subst -, ,$(firstword $(LD))))
-ifneq ($(_LD_CMD),ld)
-  LDFLAGS := $(subst -soname ,-Wl$(comma)-soname$(comma),$(LDFLAGS))
-  LDFLAGS := $(subst -Map ,-Wl$(comma)-Map$(comma),$(LDFLAGS))
-  LDFLAGS := $(LDFLAGS:-x=-Wl,-x)
-  LDFLAGS := $(LDFLAGS:--%=-Wl,--%)
-endif
-
 _BIN := $(addprefix $(OUTPUTDIR)Libs/,$(BIN))
 _XBIN := $(addprefix $(OUTPUTDIR)Libs/,$(EXTRABIN))
 _OBJPREFIX := obj-$(ARCH)/
+LDFLAGS += -Map $(_OBJPREFIX)Map.txt
+
+_LD_CMD := $(lastword $(subst -, ,$(firstword $(LD))))
+LDFLAGS := $(subst -soname ,-Wl$(comma)-soname$(comma),$(LDFLAGS))
+LDFLAGS := $(subst -Map ,-Wl$(comma)-Map$(comma),$(LDFLAGS))
+LDFLAGS := $(LDFLAGS:-x=-Wl,-x)
+LDFLAGS := $(LDFLAGS:--%=-Wl,--%)
 
 _LIBS := $(filter -l%,$(LDFLAGS))
 _LIBS := $(patsubst -l%,$(OUTPUTDIR)Libs/lib%.so,$(_LIBS))
 
+ifeq ($(ARCHDIR),native)
+ LIBS := $(patsubst -lc,-lc_acess,$(LIBS))
+ LIBS := $(patsubst -lc++,-lc++_acess,$(LIBS))
+ ifneq ($(BIN),libc_acess.so)
+  LIBS += -lc_acess
+ endif
+endif
+
 OBJ := $(addprefix $(_OBJPREFIX),$(OBJ))
 
 UTESTS := $(patsubst TEST_%.c,%,$(wildcard TEST_*.c))
@@ -36,14 +43,15 @@ else
 V := @
 endif
 
-.PHONY: all clean install postbuild
+.PHONY: all clean install postbuild utest-build utest-run generate_exp
 
 all: _libs $(_BIN) $(_XBIN)
 
 .PHONY: _libs
 
+.PRECIOUS: .no
 
-HEADERS := $(patsubst include_exp/%,../../include/%,$(shell find include_exp/ -name \*.h))
+HEADERS := $(patsubst include_exp/%,../../include/%,$(shell find include_exp/ -name \*.h 2>/dev/null))
 _libs: $(HEADERS)
 
 ../../include/%: include_exp/%
@@ -54,16 +62,13 @@ _libs: $(HEADERS)
 
 utest: utest-build utest-run
 
-generate_exp: $(UTESTS:%=EXP_%.txt)
-       @echo > /dev/null
-
 utest-build: $(UTESTS:%=TEST_%)
 
 utest-run: $(UTESTS:%=runtest-%)
-       @echo > /dev/null
 
-$(UTESTS:%=runtest-%): runtest-%: TEST_% EXP_%.txt
-       ./TEST_$* | diff EXP_$*.txt -
+$(UTESTS:%=runtest-%): runtest-%: TEST_%
+       @echo --- [TEST] $*
+       @./TEST_$*
 
 clean:
        $(RM) $(_BIN) $(_XBIN) $(OBJ) $(_BIN).dsm $(DEPFILES) $(EXTRACLEAN)
@@ -81,23 +86,33 @@ endif
 #      for f in $(INCFILES); do ln -s $f $(ACESSDIR)/include/$f; done
 #endif
 
-$(_BIN): $(OBJ)
+LINK_OBJS = $(PRELINK) $(OBJ)
+$(_BIN): $(CRTI) $(LINK_OBJS) $(CRTN) $(CRT0S)
        @mkdir -p $(dir $(_BIN))
        @echo [LD] -o $(BIN) $(OBJ)
-       $V$(LD) $(LDFLAGS) -o $(_BIN) $(OBJ) $(shell $(CC) -print-libgcc-file-name)
-       $V$(DISASM) -D -S $(_BIN) > $(_OBJPREFIX)$(BIN).dsm
+ifneq ($(USE_CXX_LINK),)
+       $V$(CXX) $(LDFLAGS) -o $(_BIN) $(LINK_OBJS) $(LIBS)
+else
+       $V$(CC) $(LDFLAGS) -o $(_BIN) $(LINK_OBJS) $(LIBS)
+endif
+       $V$(DISASM) -C $(_BIN) > $(_OBJPREFIX)$(BIN).dsm
 
-$(_OBJPREFIX)%.o: %.c
+$(_OBJPREFIX)%.o: %.c Makefile
        @echo [CC] -o $@
        @mkdir -p $(dir $@)
        $V$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< -MMD -MP -MT $@ -MF [email protected]
 
-$(_OBJPREFIX)%.o: %.cc
+$(_OBJPREFIX)%.o: %.cc Makefile
        @echo [CXX] -o $@
        @mkdir -p $(dir $@)
        $V$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< -MMD -MP -MT $@ -MF [email protected]
 
-$(_OBJPREFIX)%.ao: %.$(ASSUFFIX)
+$(_OBJPREFIX)%.o: %.cpp Makefile
+       @echo [CXX] -o $@
+       @mkdir -p $(dir $@)
+       $V$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< -MMD -MP -MT $@ -MF [email protected]
+
+$(_OBJPREFIX)%.ao: %.$(ASSUFFIX) Makefile
        @echo [AS] -o $@
        @mkdir -p $(dir $@)
        $V$(AS) $(ASFLAGS) -o $@ $<
@@ -115,10 +130,14 @@ $(OUTPUTDIR)Libs/%:
 
 obj-native/%.no: %.c
        @mkdir -p $(dir $@)
-       $(NCC) -c $< -o $@ -Wall -std=gnu99 -MD -MP -MF [email protected]
+       @echo [CC Native] -o $@
+       @$(NCC) -g -c $< -o $@ -Wall -std=gnu99 -MD -MP -MF [email protected] '-D_SysDebug(f,v...)=fprintf(stderr,"DEBUG "f"\n",##v)' -include stdio.h
 
 TEST_%: obj-native/TEST_%.no obj-native/%.no
-       $(NCC) -o $@ $^
+       @echo [CC Native] -o $@
+       @$(NCC) -g -o $@ $^
+
+.PRECIOUS: $(UTESTS:%=obj-native/%.no) $(UTESTS:%=obj-native/TEST_%.no)
 
 -include $(UTESTS:%=obj-native/TEST_%.no.dep)
 -include $(UTESTS:%=obj-native/%.no.dep)
diff --git a/Usermode/Libraries/acess.ld_src/.gitignore b/Usermode/Libraries/acess.ld_src/.gitignore
deleted file mode 100644 (file)
index 3932ffb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-acess_native.ld.h
diff --git a/Usermode/Libraries/acess.ld_src/Makefile b/Usermode/Libraries/acess.ld_src/Makefile
deleted file mode 100644 (file)
index 25a5c56..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Acess2
-# - Common usermode linker script
-#
-
-
--include ../Makefile.cfg
-
-BIN = $(OUTPUTDIR)Libs/acess.ld
-
-.PHONY: all clean install utest generate_exp
-
-all: $(BIN)
-
-clean:
-       $(RM) $(BIN)
-
-install: $(BIN)
-
-# How does one unit test a linker script?
-utest generate_exp:
-       @echo > /dev/null
-
-$(BIN):        acess_$(ARCHDIR).ld.h
-       @mkdir -p $(dir $(BIN))
-       cpp -nostdinc -U i386 -P -C $< -o $@ -D__LIBDIR=$(OUTPUTDIR)Libs
-
-acess_$(ARCHDIR).ld.h:
-       $(LD) --verbose | awk '{ if( substr($$0,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/SEARCH_DIR\(.*\)/SEARCH_DIR(__LIBDIR)/' > $@
diff --git a/Usermode/Libraries/acess.ld_src/acess_armv6.ld.h b/Usermode/Libraries/acess.ld_src/acess_armv6.ld.h
deleted file mode 100644 (file)
index 0ea7f90..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/* Script for -z combreloc: combine and sort reloc sections */
-OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
-             "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SEARCH_DIR(__LIBDIR)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x8000)); . = SEGMENT_START("text-segment", 0x8000);
-  .interp         : { *(.interp) }
-  .note.gnu.build-id : { *(.note.gnu.build-id) }
-  .hash           : { *(.hash) }
-  .gnu.hash       : { *(.gnu.hash) }
-  .dynsym         : { *(.dynsym) }
-  .dynstr         : { *(.dynstr) }
-  .gnu.version    : { *(.gnu.version) }
-  .gnu.version_d  : { *(.gnu.version_d) }
-  .gnu.version_r  : { *(.gnu.version_r) }
-  .rel.dyn        :
-    {
-      *(.rel.init)
-      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
-      *(.rel.fini)
-      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
-      *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
-      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
-      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
-      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
-      *(.rel.ctors)
-      *(.rel.dtors)
-      *(.rel.got)
-      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
-      PROVIDE_HIDDEN (__rel_iplt_start = .);
-      *(.rel.iplt)
-      PROVIDE_HIDDEN (__rel_iplt_end = .);
-      PROVIDE_HIDDEN (__rela_iplt_start = .);
-      PROVIDE_HIDDEN (__rela_iplt_end = .);
-    }
-  .rela.dyn       :
-    {
-      *(.rela.init)
-      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
-      *(.rela.fini)
-      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
-      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
-      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
-      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
-      *(.rela.ctors)
-      *(.rela.dtors)
-      *(.rela.got)
-      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
-      PROVIDE_HIDDEN (__rel_iplt_start = .);
-      PROVIDE_HIDDEN (__rel_iplt_end = .);
-      PROVIDE_HIDDEN (__rela_iplt_start = .);
-      *(.rela.iplt)
-      PROVIDE_HIDDEN (__rela_iplt_end = .);
-    }
-  .rel.plt        :
-    {
-      *(.rel.plt)
-    }
-  .rela.plt       :
-    {
-      *(.rela.plt)
-    }
-  .init           :
-  {
-    KEEP (*(.init))
-  } =0
-  .plt            : { *(.plt) }
-  .iplt           : { *(.iplt) }
-  .text           :
-  {
-    *(.text.unlikely .text.*_unlikely)
-    *(.text.exit .text.exit.*)
-    *(.text.startup .text.startup.*)
-    *(.text.hot .text.hot.*)
-    *(.text .stub .text.* .gnu.linkonce.t.*)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-    *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)
-  } =0
-  .fini           :
-  {
-    KEEP (*(.fini))
-  } =0
-  PROVIDE (__etext = .);
-  PROVIDE (_etext = .);
-  PROVIDE (etext = .);
-  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
-  .rodata1        : { *(.rodata1) }
-  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
-   PROVIDE_HIDDEN(__exidx_start = .);
-  .ARM.exidx   : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
-   PROVIDE_HIDDEN(__exidx_end = .);
-  .eh_frame_hdr : { *(.eh_frame_hdr) }
-  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
-  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  */
-  . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));
-  /* Exception handling  */
-  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
-  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
-  /* Thread Local Storage sections  */
-  .tdata         : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
-  .tbss                  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
-  .preinit_array     :
-  {
-    PROVIDE_HIDDEN (__preinit_array_start = .);
-    KEEP (*(.preinit_array))
-    PROVIDE_HIDDEN (__preinit_array_end = .);
-  }
-  .init_array     :
-  {
-    PROVIDE_HIDDEN (__init_array_start = .);
-    KEEP (*(SORT(.init_array.*)))
-    KEEP (*(.init_array))
-    PROVIDE_HIDDEN (__init_array_end = .);
-  }
-  .fini_array     :
-  {
-    PROVIDE_HIDDEN (__fini_array_start = .);
-    KEEP (*(SORT(.fini_array.*)))
-    KEEP (*(.fini_array))
-    PROVIDE_HIDDEN (__fini_array_end = .);
-  }
-  .ctors          :
-  {
-    /* gcc uses crtbegin.o to find the start of
-       the constructors, so we make sure it is
-       first.  Because this is a wildcard, it
-       doesn't matter if the user does not
-       actually link against crtbegin.o; the
-       linker won't look for a file to match a
-       wildcard.  The wildcard also means that it
-       doesn't matter which directory crtbegin.o
-       is in.  */
-    KEEP (*crtbegin.o(.ctors))
-    KEEP (*crtbegin?.o(.ctors))
-    /* We don't want to include the .ctor section from
-       the crtend.o file until after the sorted ctors.
-       The .ctor section from the crtend file contains the
-       end of ctors marker and it must be last */
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
-    KEEP (*(SORT(.ctors.*)))
-    KEEP (*(.ctors))
-  }
-  .dtors          :
-  {
-    KEEP (*crtbegin.o(.dtors))
-    KEEP (*crtbegin?.o(.dtors))
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
-    KEEP (*(SORT(.dtors.*)))
-    KEEP (*(.dtors))
-  }
-  .jcr            : { KEEP (*(.jcr)) }
-  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
-  .dynamic        : { *(.dynamic) }
-  .got            : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
-  .data           :
-  {
-    __data_start = . ;
-    *(.data .data.* .gnu.linkonce.d.*)
-    SORT(CONSTRUCTORS)
-  }
-  .data1          : { *(.data1) }
-  _edata = .; PROVIDE (edata = .);
-  __bss_start = .;
-  __bss_start__ = .;
-  .bss            :
-  {
-   *(.dynbss)
-   *(.bss .bss.* .gnu.linkonce.b.*)
-   *(COMMON)
-   /* Align here to ensure that the .bss section occupies space up to
-      _end.  Align after .bss to ensure correct alignment even if the
-      .bss section disappears because there are no input sections.
-      FIXME: Why do we need it? When there is no .bss section, we don't
-      pad the .data section.  */
-   . = ALIGN(. != 0 ? 32 / 8 : 1);
-  }
-  _bss_end__ = . ; __bss_end__ = . ;
-  . = ALIGN(32 / 8);
-  . = ALIGN(32 / 8);
-  __end__ = . ;
-  _end = .; PROVIDE (end = .);
-  /* Stabs debugging sections.  */
-  .stab          0 : { *(.stab) }
-  .stabstr       0 : { *(.stabstr) }
-  .stab.excl     0 : { *(.stab.excl) }
-  .stab.exclstr  0 : { *(.stab.exclstr) }
-  .stab.index    0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment       0 : { *(.comment) }
-  /* DWARF debug sections.
-     Symbols in the DWARF debugging sections are relative to the beginning
-     of the section so we begin them at 0.  */
-  /* DWARF 1 */
-  .debug          0 : { *(.debug) }
-  .line           0 : { *(.line) }
-  /* GNU DWARF 1 extensions */
-  .debug_srcinfo  0 : { *(.debug_srcinfo .zdebug_srcinfo) }
-  .debug_sfnames  0 : { *(.debug_sfnames .zdebug_sfnames) }
-  /* DWARF 1.1 and DWARF 2 */
-  .debug_aranges  0 : { *(.debug_aranges .zdebug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames .zdebug_pubnames) }
-  /* DWARF 2 */
-  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.* .zdebug_info) }
-  .debug_abbrev   0 : { *(.debug_abbrev .zdebug_abbrev) }
-  .debug_line     0 : { *(.debug_line .zdebug_line) }
-  .debug_frame    0 : { *(.debug_frame .zdebug_frame) }
-  .debug_str      0 : { *(.debug_str .zdebug_str) }
-  .debug_loc      0 : { *(.debug_loc .zdebug_loc) }
-  .debug_macinfo  0 : { *(.debug_macinfo .zdebug_macinfo) }
-  /* SGI/MIPS DWARF 2 extensions */
-  .debug_weaknames 0 : { *(.debug_weaknames .zdebug_weaknames) }
-  .debug_funcnames 0 : { *(.debug_funcnames .zdebug_funcnames) }
-  .debug_typenames 0 : { *(.debug_typenames .zdebug_typenames) }
-  .debug_varnames  0 : { *(.debug_varnames .zdebug_varnames) }
-  /* DWARF 3 */
-  .debug_pubtypes 0 : { *(.debug_pubtypes .zdebug_pubtypes) }
-  .debug_ranges   0 : { *(.debug_ranges .zdebug_ranges) }
-    .stack         0x80000 :
-  {
-    _stack = .;
-    *(.stack)
-  }
-  .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
-  .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
-  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
-}
-
-
diff --git a/Usermode/Libraries/acess.ld_src/acess_armv7.ld.h b/Usermode/Libraries/acess.ld_src/acess_armv7.ld.h
deleted file mode 100644 (file)
index 24c4af3..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/* Script for -z combreloc: combine and sort reloc sections */
-OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
-             "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(start)
-SEARCH_DIR(__LIBDIR)
-INPUT(crt0.o)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x8000)); . = SEGMENT_START("text-segment", 0x8000) + SIZEOF_HEADERS;
-  .interp         : { *(.interp) }
-  .note.gnu.build-id : { *(.note.gnu.build-id) }
-  .hash           : { *(.hash) }
-  .gnu.hash       : { *(.gnu.hash) }
-  .dynsym         : { *(.dynsym) }
-  .dynstr         : { *(.dynstr) }
-  .gnu.version    : { *(.gnu.version) }
-  .gnu.version_d  : { *(.gnu.version_d) }
-  .gnu.version_r  : { *(.gnu.version_r) }
-  .rel.dyn        :
-    {
-      *(.rel.init)
-      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
-      *(.rel.fini)
-      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
-      *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
-      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
-      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
-      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
-      *(.rel.ctors)
-      *(.rel.dtors)
-      *(.rel.got)
-      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
-      PROVIDE_HIDDEN (__rel_iplt_start = .);
-      *(.rel.iplt)
-      PROVIDE_HIDDEN (__rel_iplt_end = .);
-      PROVIDE_HIDDEN (__rela_iplt_start = .);
-      PROVIDE_HIDDEN (__rela_iplt_end = .);
-    }
-  .rela.dyn       :
-    {
-      *(.rela.init)
-      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
-      *(.rela.fini)
-      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
-      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
-      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
-      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
-      *(.rela.ctors)
-      *(.rela.dtors)
-      *(.rela.got)
-      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
-      PROVIDE_HIDDEN (__rel_iplt_start = .);
-      PROVIDE_HIDDEN (__rel_iplt_end = .);
-      PROVIDE_HIDDEN (__rela_iplt_start = .);
-      *(.rela.iplt)
-      PROVIDE_HIDDEN (__rela_iplt_end = .);
-    }
-  .rel.plt        :
-    {
-      *(.rel.plt)
-    }
-  .rela.plt       :
-    {
-      *(.rela.plt)
-    }
-  .init           :
-  {
-    KEEP (*(.init))
-  } =0
-  .plt            : { *(.plt) }
-  .iplt           : { *(.iplt) }
-  .text           :
-  {
-    *(.text.unlikely .text.*_unlikely)
-    *(.text.exit .text.exit.*)
-    *(.text.startup .text.startup.*)
-    *(.text.hot .text.hot.*)
-    *(.text .stub .text.* .gnu.linkonce.t.*)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-    *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)
-  } =0
-  .fini           :
-  {
-    KEEP (*(.fini))
-  } =0
-  PROVIDE (__etext = .);
-  PROVIDE (_etext = .);
-  PROVIDE (etext = .);
-  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
-  .rodata1        : { *(.rodata1) }
-  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
-   PROVIDE_HIDDEN (__exidx_start = .);
-  .ARM.exidx   : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
-   PROVIDE_HIDDEN (__exidx_end = .);
-  .eh_frame_hdr : { *(.eh_frame_hdr) }
-  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
-  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  */
-  . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));
-  /* Exception handling  */
-  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
-  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
-  /* Thread Local Storage sections  */
-  .tdata         : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
-  .tbss                  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
-  .preinit_array     :
-  {
-    PROVIDE_HIDDEN (__preinit_array_start = .);
-    KEEP (*(.preinit_array))
-    PROVIDE_HIDDEN (__preinit_array_end = .);
-  }
-  .init_array     :
-  {
-    PROVIDE_HIDDEN (__init_array_start = .);
-    KEEP (*(SORT(.init_array.*)))
-    KEEP (*(.init_array))
-    PROVIDE_HIDDEN (__init_array_end = .);
-  }
-  .fini_array     :
-  {
-    PROVIDE_HIDDEN (__fini_array_start = .);
-    KEEP (*(SORT(.fini_array.*)))
-    KEEP (*(.fini_array))
-    PROVIDE_HIDDEN (__fini_array_end = .);
-  }
-  .ctors          :
-  {
-    /* gcc uses crtbegin.o to find the start of
-       the constructors, so we make sure it is
-       first.  Because this is a wildcard, it
-       doesn't matter if the user does not
-       actually link against crtbegin.o; the
-       linker won't look for a file to match a
-       wildcard.  The wildcard also means that it
-       doesn't matter which directory crtbegin.o
-       is in.  */
-    KEEP (*crtbegin.o(.ctors))
-    KEEP (*crtbegin?.o(.ctors))
-    /* We don't want to include the .ctor section from
-       the crtend.o file until after the sorted ctors.
-       The .ctor section from the crtend file contains the
-       end of ctors marker and it must be last */
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
-    KEEP (*(SORT(.ctors.*)))
-    KEEP (*(.ctors))
-  }
-  .dtors          :
-  {
-    KEEP (*crtbegin.o(.dtors))
-    KEEP (*crtbegin?.o(.dtors))
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
-    KEEP (*(SORT(.dtors.*)))
-    KEEP (*(.dtors))
-  }
-  .jcr            : { KEEP (*(.jcr)) }
-  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
-  .dynamic        : { *(.dynamic) }
-  .got            : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
-  .data           :
-  {
-    __data_start = . ;
-    *(.data .data.* .gnu.linkonce.d.*)
-    SORT(CONSTRUCTORS)
-  }
-  .data1          : { *(.data1) }
-  _edata = .; PROVIDE (edata = .);
-  __bss_start = .;
-  __bss_start__ = .;
-  .bss            :
-  {
-   *(.dynbss)
-   *(.bss .bss.* .gnu.linkonce.b.*)
-   *(COMMON)
-   /* Align here to ensure that the .bss section occupies space up to
-      _end.  Align after .bss to ensure correct alignment even if the
-      .bss section disappears because there are no input sections.
-      FIXME: Why do we need it? When there is no .bss section, we don't
-      pad the .data section.  */
-   . = ALIGN(. != 0 ? 32 / 8 : 1);
-  }
-  _bss_end__ = . ; __bss_end__ = . ;
-  . = ALIGN(32 / 8);
-  . = ALIGN(32 / 8);
-  __end__ = . ;
-  _end = .; PROVIDE (end = .);
-  /* Stabs debugging sections.  */
-  .stab          0 : { *(.stab) }
-  .stabstr       0 : { *(.stabstr) }
-  .stab.excl     0 : { *(.stab.excl) }
-  .stab.exclstr  0 : { *(.stab.exclstr) }
-  .stab.index    0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment       0 : { *(.comment) }
-  /* DWARF debug sections.
-     Symbols in the DWARF debugging sections are relative to the beginning
-     of the section so we begin them at 0.  */
-  /* DWARF 1 */
-  .debug          0 : { *(.debug) }
-  .line           0 : { *(.line) }
-  /* GNU DWARF 1 extensions */
-  .debug_srcinfo  0 : { *(.debug_srcinfo .zdebug_srcinfo) }
-  .debug_sfnames  0 : { *(.debug_sfnames .zdebug_sfnames) }
-  /* DWARF 1.1 and DWARF 2 */
-  .debug_aranges  0 : { *(.debug_aranges .zdebug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames .zdebug_pubnames) }
-  /* DWARF 2 */
-  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.* .zdebug_info) }
-  .debug_abbrev   0 : { *(.debug_abbrev .zdebug_abbrev) }
-  .debug_line     0 : { *(.debug_line .zdebug_line) }
-  .debug_frame    0 : { *(.debug_frame .zdebug_frame) }
-  .debug_str      0 : { *(.debug_str .zdebug_str) }
-  .debug_loc      0 : { *(.debug_loc .zdebug_loc) }
-  .debug_macinfo  0 : { *(.debug_macinfo .zdebug_macinfo) }
-  /* SGI/MIPS DWARF 2 extensions */
-  .debug_weaknames 0 : { *(.debug_weaknames .zdebug_weaknames) }
-  .debug_funcnames 0 : { *(.debug_funcnames .zdebug_funcnames) }
-  .debug_typenames 0 : { *(.debug_typenames .zdebug_typenames) }
-  .debug_varnames  0 : { *(.debug_varnames .zdebug_varnames) }
-  /* DWARF 3 */
-  .debug_pubtypes 0 : { *(.debug_pubtypes .zdebug_pubtypes) }
-  .debug_ranges   0 : { *(.debug_ranges .zdebug_ranges) }
-    .stack         0x80000 :
-  {
-    _stack = .;
-    *(.stack)
-  }
-  .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
-  .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
-  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
-}
-
-
diff --git a/Usermode/Libraries/acess.ld_src/acess_x86.ld.h b/Usermode/Libraries/acess.ld_src/acess_x86.ld.h
deleted file mode 100644 (file)
index e81c0a5..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")\r
-OUTPUT_ARCH(i386)\r
-ENTRY(start)\r
-SEARCH_DIR(__LIBDIR)\r
-INPUT(crt0.o)\r
-SECTIONS\r
-{\r
-  /* Read-only sections, merged into text segment: */\r
-  PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS;\r
-  .interp         : { *(.interp) }\r
-  .note.gnu.build-id : { *(.note.gnu.build-id) }\r
-  .hash           : { *(.hash) }\r
-  .gnu.hash       : { *(.gnu.hash) }\r
-  .dynsym         : { *(.dynsym) }\r
-  .dynstr         : { *(.dynstr) }\r
-  .gnu.version    : { *(.gnu.version) }\r
-  .gnu.version_d  : { *(.gnu.version_d) }\r
-  .gnu.version_r  : { *(.gnu.version_r) }\r
-  .rel.dyn        :\r
-    {\r
-      *(.rel.init)\r
-      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)\r
-      *(.rel.fini)\r
-      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)\r
-      *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)\r
-      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)\r
-      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)\r
-      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)\r
-      *(.rel.ctors)\r
-      *(.rel.dtors)\r
-      *(.rel.got)\r
-      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)\r
-    }\r
-  .rela.dyn       :\r
-    {\r
-      *(.rela.init)\r
-      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)\r
-      *(.rela.fini)\r
-      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)\r
-      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)\r
-      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)\r
-      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)\r
-      *(.rela.ctors)\r
-      *(.rela.dtors)\r
-      *(.rela.got)\r
-      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)\r
-    }\r
-  .rel.plt        : { *(.rel.plt) }\r
-  .rela.plt       : { *(.rela.plt) }\r
-  .init           :\r
-  {\r
-    KEEP (*(.init))\r
-  } =0x90909090\r
-  .plt            : { *(.plt) }\r
-  .text           :\r
-  {\r
-    *(.text .stub .text.* .gnu.linkonce.t.*)\r
-    /* .gnu.warning sections are handled specially by elf32.em.  */\r
-    *(.gnu.warning)\r
-  } =0x90909090\r
-  .fini           :\r
-  {\r
-    KEEP (*(.fini))\r
-  } =0x90909090\r
-  PROVIDE (__etext = .);\r
-  PROVIDE (_etext = .);\r
-  PROVIDE (etext = .);\r
-  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }\r
-  .rodata1        : { *(.rodata1) }\r
-  .eh_frame_hdr : { *(.eh_frame_hdr) }\r
-  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }\r
-  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }\r
-  /* Adjust the address for the data segment.  We want to adjust up to\r
-     the same address within the page on the next page up.  */\r
-  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));\r
-  /* Exception handling  */\r
-  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }\r
-  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }\r
-  /* Thread Local Storage sections  */\r
-  .tdata         : { *(.tdata .tdata.* .gnu.linkonce.td.*) }\r
-  .tbss                  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }\r
-  .preinit_array     :\r
-  {\r
-    PROVIDE_HIDDEN (__preinit_array_start = .);\r
-    KEEP (*(.preinit_array))\r
-    PROVIDE_HIDDEN (__preinit_array_end = .);\r
-  }\r
-  .init_array     :\r
-  {\r
-     PROVIDE_HIDDEN (__init_array_start = .);\r
-     KEEP (*(SORT(.init_array.*)))\r
-     KEEP (*(.init_array))\r
-     PROVIDE_HIDDEN (__init_array_end = .);\r
-  }\r
-  .fini_array     :\r
-  {\r
-    PROVIDE_HIDDEN (__fini_array_start = .);\r
-    KEEP (*(.fini_array))\r
-    KEEP (*(SORT(.fini_array.*)))\r
-    PROVIDE_HIDDEN (__fini_array_end = .);\r
-  }\r
-  .ctors          :\r
-  {\r
-    /* gcc uses crtbegin.o to find the start of\r
-       the constructors, so we make sure it is\r
-       first.  Because this is a wildcard, it\r
-       doesn't matter if the user does not\r
-       actually link against crtbegin.o; the\r
-       linker won't look for a file to match a\r
-       wildcard.  The wildcard also means that it\r
-       doesn't matter which directory crtbegin.o\r
-       is in.  */\r
-    KEEP (*crtbegin.o(.ctors))\r
-    KEEP (*crtbegin?.o(.ctors))\r
-    /* We don't want to include the .ctor section from\r
-       the crtend.o file until after the sorted ctors.\r
-       The .ctor section from the crtend file contains the\r
-       end of ctors marker and it must be last */\r
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))\r
-    KEEP (*(SORT(.ctors.*)))\r
-    KEEP (*(.ctors))\r
-  }\r
-  .dtors          :\r
-  {\r
-    KEEP (*crtbegin.o(.dtors))\r
-    KEEP (*crtbegin?.o(.dtors))\r
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))\r
-    KEEP (*(SORT(.dtors.*)))\r
-    KEEP (*(.dtors))\r
-  }\r
-  .jcr            : { KEEP (*(.jcr)) }\r
-  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }\r
-  .dynamic        : { *(.dynamic) }\r
-  .got            : { *(.got) }\r
-  . = DATA_SEGMENT_RELRO_END (12, .);\r
-  .got.plt        : { *(.got.plt) }\r
-  .data           :\r
-  {\r
-    *(.data .data.* .gnu.linkonce.d.*)\r
-    SORT(CONSTRUCTORS)\r
-  }\r
-  .data1          : { *(.data1) }\r
-  _edata = .; PROVIDE (edata = .);\r
-  __bss_start = .;\r
-  .bss            :\r
-  {\r
-   *(.dynbss)\r
-   *(.bss .bss.* .gnu.linkonce.b.*)\r
-   *(COMMON)\r
-   /* Align here to ensure that the .bss section occupies space up to\r
-      _end.  Align after .bss to ensure correct alignment even if the\r
-      .bss section disappears because there are no input sections.\r
-      FIXME: Why do we need it? When there is no .bss section, we don't\r
-      pad the .data section.  */\r
-   . = ALIGN(. != 0 ? 32 / 8 : 1);\r
-  }\r
-  . = ALIGN(32 / 8);\r
-  . = ALIGN(32 / 8);\r
-  _end = .; PROVIDE (end = .);\r
-  . = DATA_SEGMENT_END (.);\r
-  /* Stabs debugging sections.  */\r
-  .stab          0 : { *(.stab) }\r
-  .stabstr       0 : { *(.stabstr) }\r
-  .stab.excl     0 : { *(.stab.excl) }\r
-  .stab.exclstr  0 : { *(.stab.exclstr) }\r
-  .stab.index    0 : { *(.stab.index) }\r
-  .stab.indexstr 0 : { *(.stab.indexstr) }\r
-  .comment       0 : { *(.comment) }\r
-  /* DWARF debug sections.\r
-     Symbols in the DWARF debugging sections are relative to the beginning\r
-     of the section so we begin them at 0.  */\r
-  /* DWARF 1 */\r
-  .debug          0 : { *(.debug) }\r
-  .line           0 : { *(.line) }\r
-  /* GNU DWARF 1 extensions */\r
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }\r
-  .debug_sfnames  0 : { *(.debug_sfnames) }\r
-  /* DWARF 1.1 and DWARF 2 */\r
-  .debug_aranges  0 : { *(.debug_aranges) }\r
-  .debug_pubnames 0 : { *(.debug_pubnames) }\r
-  /* DWARF 2 */\r
-  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }\r
-  .debug_abbrev   0 : { *(.debug_abbrev) }\r
-  .debug_line     0 : { *(.debug_line) }\r
-  .debug_frame    0 : { *(.debug_frame) }\r
-  .debug_str      0 : { *(.debug_str) }\r
-  .debug_loc      0 : { *(.debug_loc) }\r
-  .debug_macinfo  0 : { *(.debug_macinfo) }\r
-  /* SGI/MIPS DWARF 2 extensions */\r
-  .debug_weaknames 0 : { *(.debug_weaknames) }\r
-  .debug_funcnames 0 : { *(.debug_funcnames) }\r
-  .debug_typenames 0 : { *(.debug_typenames) }\r
-  .debug_varnames  0 : { *(.debug_varnames) }\r
-  /* DWARF 3 */\r
-  .debug_pubtypes 0 : { *(.debug_pubtypes) }\r
-  .debug_ranges   0 : { *(.debug_ranges) }\r
-  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }\r
-  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) }\r
-}\r
diff --git a/Usermode/Libraries/acess.ld_src/acess_x86_64.ld.h b/Usermode/Libraries/acess.ld_src/acess_x86_64.ld.h
deleted file mode 100644 (file)
index 469e4af..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-OUTPUT_FORMAT("elf64-x86-64")\r
-/* OUTPUT_ARCH(x86_64) */\r
-ENTRY(start)\r
-SEARCH_DIR(__LIBDIR)\r
-INPUT(crt0.o)\r
-SECTIONS\r
-{\r
-  /* Read-only sections, merged into text segment: */\r
-  PROVIDE (__executable_start = 0x00400000); . = 0x00400000 + SIZEOF_HEADERS;\r
-  .interp         : { *(.interp) }\r
-  .note.gnu.build-id : { *(.note.gnu.build-id) }\r
-  .hash           : { *(.hash) }\r
-  .gnu.hash       : { *(.gnu.hash) }\r
-  .dynsym         : { *(.dynsym) }\r
-  .dynstr         : { *(.dynstr) }\r
-  .gnu.version    : { *(.gnu.version) }\r
-  .gnu.version_d  : { *(.gnu.version_d) }\r
-  .gnu.version_r  : { *(.gnu.version_r) }\r
-  .rel.dyn        :\r
-    {\r
-      *(.rel.init)\r
-      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)\r
-      *(.rel.fini)\r
-      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)\r
-      *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)\r
-      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)\r
-      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)\r
-      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)\r
-      *(.rel.ctors)\r
-      *(.rel.dtors)\r
-      *(.rel.got)\r
-      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)\r
-    }\r
-  .rela.dyn       :\r
-    {\r
-      *(.rela.init)\r
-      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)\r
-      *(.rela.fini)\r
-      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)\r
-      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)\r
-      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)\r
-      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)\r
-      *(.rela.ctors)\r
-      *(.rela.dtors)\r
-      *(.rela.got)\r
-      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)\r
-    }\r
-  .rel.plt        : { *(.rel.plt) }\r
-  .rela.plt       : { *(.rela.plt) }\r
-  .init           :\r
-  {\r
-    KEEP (*(.init))\r
-  } =0x90909090\r
-  .plt            : { *(.plt) }\r
-  .text           :\r
-  {\r
-    *(.text .stub .text.* .gnu.linkonce.t.*)\r
-    /* .gnu.warning sections are handled specially by elf32.em.  */\r
-    *(.gnu.warning)\r
-  } =0x90909090\r
-  .fini           :\r
-  {\r
-    KEEP (*(.fini))\r
-  } =0x90909090\r
-  PROVIDE (__etext = .);\r
-  PROVIDE (_etext = .);\r
-  PROVIDE (etext = .);\r
-  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }\r
-  .rodata1        : { *(.rodata1) }\r
-  .eh_frame_hdr : { *(.eh_frame_hdr) }\r
-  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }\r
-  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }\r
-  /* Adjust the address for the data segment.  We want to adjust up to\r
-     the same address within the page on the next page up.  */\r
-  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));\r
-  /* Exception handling  */\r
-  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }\r
-  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }\r
-  /* Thread Local Storage sections  */\r
-  .tdata         : { *(.tdata .tdata.* .gnu.linkonce.td.*) }\r
-  .tbss                  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }\r
-  .preinit_array     :\r
-  {\r
-    PROVIDE_HIDDEN (__preinit_array_start = .);\r
-    KEEP (*(.preinit_array))\r
-    PROVIDE_HIDDEN (__preinit_array_end = .);\r
-  }\r
-  .init_array     :\r
-  {\r
-     PROVIDE_HIDDEN (__init_array_start = .);\r
-     KEEP (*(SORT(.init_array.*)))\r
-     KEEP (*(.init_array))\r
-     PROVIDE_HIDDEN (__init_array_end = .);\r
-  }\r
-  .fini_array     :\r
-  {\r
-    PROVIDE_HIDDEN (__fini_array_start = .);\r
-    KEEP (*(.fini_array))\r
-    KEEP (*(SORT(.fini_array.*)))\r
-    PROVIDE_HIDDEN (__fini_array_end = .);\r
-  }\r
-  .ctors          :\r
-  {\r
-    /* gcc uses crtbegin.o to find the start of\r
-       the constructors, so we make sure it is\r
-       first.  Because this is a wildcard, it\r
-       doesn't matter if the user does not\r
-       actually link against crtbegin.o; the\r
-       linker won't look for a file to match a\r
-       wildcard.  The wildcard also means that it\r
-       doesn't matter which directory crtbegin.o\r
-       is in.  */\r
-    KEEP (*crtbegin.o(.ctors))\r
-    KEEP (*crtbegin?.o(.ctors))\r
-    /* We don't want to include the .ctor section from\r
-       the crtend.o file until after the sorted ctors.\r
-       The .ctor section from the crtend file contains the\r
-       end of ctors marker and it must be last */\r
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))\r
-    KEEP (*(SORT(.ctors.*)))\r
-    KEEP (*(.ctors))\r
-  }\r
-  .dtors          :\r
-  {\r
-    KEEP (*crtbegin.o(.dtors))\r
-    KEEP (*crtbegin?.o(.dtors))\r
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))\r
-    KEEP (*(SORT(.dtors.*)))\r
-    KEEP (*(.dtors))\r
-  }\r
-  .jcr            : { KEEP (*(.jcr)) }\r
-  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }\r
-  .dynamic        : { *(.dynamic) }\r
-  .got            : { *(.got) }\r
-  . = DATA_SEGMENT_RELRO_END (12, .);\r
-  .got.plt        : { *(.got.plt) }\r
-  .data           :\r
-  {\r
-    *(.data .data.* .gnu.linkonce.d.*)\r
-    SORT(CONSTRUCTORS)\r
-  }\r
-  .data1          : { *(.data1) }\r
-  _edata = .; PROVIDE (edata = .);\r
-  __bss_start = .;\r
-  .bss            :\r
-  {\r
-   *(.dynbss)\r
-   *(.bss .bss.* .gnu.linkonce.b.*)\r
-   *(COMMON)\r
-   /* Align here to ensure that the .bss section occupies space up to\r
-      _end.  Align after .bss to ensure correct alignment even if the\r
-      .bss section disappears because there are no input sections.\r
-      FIXME: Why do we need it? When there is no .bss section, we don't\r
-      pad the .data section.  */\r
-   . = ALIGN(. != 0 ? 32 / 8 : 1);\r
-  }\r
-  . = ALIGN(32 / 8);\r
-  . = ALIGN(32 / 8);\r
-  _end = .; PROVIDE (end = .);\r
-  . = DATA_SEGMENT_END (.);\r
-  /* Stabs debugging sections.  */\r
-  .stab          0 : { *(.stab) }\r
-  .stabstr       0 : { *(.stabstr) }\r
-  .stab.excl     0 : { *(.stab.excl) }\r
-  .stab.exclstr  0 : { *(.stab.exclstr) }\r
-  .stab.index    0 : { *(.stab.index) }\r
-  .stab.indexstr 0 : { *(.stab.indexstr) }\r
-  .comment       0 : { *(.comment) }\r
-  /* DWARF debug sections.\r
-     Symbols in the DWARF debugging sections are relative to the beginning\r
-     of the section so we begin them at 0.  */\r
-  /* DWARF 1 */\r
-  .debug          0 : { *(.debug) }\r
-  .line           0 : { *(.line) }\r
-  /* GNU DWARF 1 extensions */\r
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }\r
-  .debug_sfnames  0 : { *(.debug_sfnames) }\r
-  /* DWARF 1.1 and DWARF 2 */\r
-  .debug_aranges  0 : { *(.debug_aranges) }\r
-  .debug_pubnames 0 : { *(.debug_pubnames) }\r
-  /* DWARF 2 */\r
-  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }\r
-  .debug_abbrev   0 : { *(.debug_abbrev) }\r
-  .debug_line     0 : { *(.debug_line) }\r
-  .debug_frame    0 : { *(.debug_frame) }\r
-  .debug_str      0 : { *(.debug_str) }\r
-  .debug_loc      0 : { *(.debug_loc) }\r
-  .debug_macinfo  0 : { *(.debug_macinfo) }\r
-  /* SGI/MIPS DWARF 2 extensions */\r
-  .debug_weaknames 0 : { *(.debug_weaknames) }\r
-  .debug_funcnames 0 : { *(.debug_funcnames) }\r
-  .debug_typenames 0 : { *(.debug_typenames) }\r
-  .debug_varnames  0 : { *(.debug_varnames) }\r
-  /* DWARF 3 */\r
-  .debug_pubtypes 0 : { *(.debug_pubtypes) }\r
-  .debug_ranges   0 : { *(.debug_ranges) }\r
-  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }\r
-  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) }\r
-}\r
diff --git a/Usermode/Libraries/acess.ld_src/rules.mk b/Usermode/Libraries/acess.ld_src/rules.mk
deleted file mode 100644 (file)
index f2f3de0..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-include $(BASE)header.mk
-
-# Variables
-BIN = $(OUTPUTDIR)Libs/acess.ld
-
-# Rules
-.PHONY: all-$(DIR)
-
-all-$(DIR): $(BIN)
-clean-$(DIR):
-       $(RM) $(BIN)
-
-$(BIN):        $(DIR)/acess_$(ARCHDIR).ld.h
-       @mkdir -p $(dir $(BIN))
-       cpp -nostdinc -U i386 -P -C $< -o $@ -D__LIBDIR=$(OUTPUTDIR)Libs
-
-$(DIR)/acess_$(ARCHDIR).ld.h:
-       $(LD) --verbose | awk '{ if( substr($$0,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/SEARCH_DIR\(.*\)/SEARCH_DIR(__LIBDIR)/' > $@
-
-include $(BASE)footer.mk
index 7ddc5f4..29bdb0e 100644 (file)
@@ -4,9 +4,11 @@
 
 -include ../Makefile.cfg
 
-BIN = $(OUTPUTDIR)Libs/crt0.o $(OUTPUTDIR)Libs/crtbegin.o $(OUTPUTDIR)Libs/crtend.o
+BIN = $(OUTPUTDIR)Libs/crt0.o $(OUTPUTDIR)Libs/crt0S.o $(OUTPUTDIR)Libs/crti.o $(OUTPUTDIR)Libs/crtn.o
 
-.PHONY: all clean install utest generate_exp
+CFLAGS := -std=c99
+
+.PHONY: all clean install utest utest-build generate_exp
 
 all: $(BIN)
 
@@ -16,22 +18,16 @@ clean:
        $(RM) $(BIN)
 
 # Disabled unit tests
-utest generate_exp:
+utest generate_exp utest-build utest-run:
        @echo > /dev/null
 
-$(OUTPUTDIR)Libs/%.o: %.c
+$(OUTPUTDIR)Libs/%S.o: %S.c Makefile
        @mkdir -p $(dir $@)
-       $(CC) -c $< -o $@
-
-#$(OUTPUTDIR)Libs/crt0.o: obj-$(ARCH)/crt0_asm.o obj-$(ARCH)/crt0_c.o
-#      @mkdir -p $(dir $@)
-#      $(LD) -r -o $@ $?
-
-#obj-$(ARCH)/crt0_asm.o: crt0.$(ARCHDIR).$(ASSUFFIX)
-#      @mkdir -p $(dir $@)
-#      $(AS) $(ASFLAGS) $< -o $@
-
-#obj-$(ARCH)/crt0_c.o: crt0.c
-#      @mkdir -p $(dir $@)
-#      $(CC) -c $< -o $@
+       $(CC) $(CFLAGS) -c $< -o $@ -fPIC
+$(OUTPUTDIR)Libs/%.o: %.c Makefile
+       @mkdir -p $(dir $@)
+       $(CC) $(CFLAGS) -c $< -o $@
+$(OUTPUTDIR)Libs/%.o: $(ARCHDIR)-%.S
+       @mkdir -p $(dir $@)
+       $(CC) $(CFLAGS) -c $< -o $@
 
diff --git a/Usermode/Libraries/crt0.o_src/armv7-crti.S b/Usermode/Libraries/crt0.o_src/armv7-crti.S
new file mode 100644 (file)
index 0000000..310cd6a
--- /dev/null
@@ -0,0 +1,31 @@
+.section .init
+.global _init
+.type _init, function
+_init:
+#ifdef __thumb__
+       .thumb
+       
+       push    {r3, r4, r5, r6, r7, lr}
+#else
+       .arm
+       mov     ip, sp
+       stmdb   sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
+       sub     fp, ip, #4
+#endif
+       /* gcc will nicely put the contents of crtbegin.o's .init section here. */
+
+.section .fini
+.global _fini
+.type _fini, function
+_fini:
+#ifdef __thumb__
+       .thumb
+       
+       push    {r3, r4, r5, r6, r7, lr}
+#else
+       .arm
+       mov     ip, sp
+       stmdb   sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
+       sub     fp, ip, #4
+#endif
+       /* gcc will nicely put the contents of crtbegin.o's .fini section here. */
diff --git a/Usermode/Libraries/crt0.o_src/armv7-crtn.S b/Usermode/Libraries/crt0.o_src/armv7-crtn.S
new file mode 100644 (file)
index 0000000..1c3e111
--- /dev/null
@@ -0,0 +1,41 @@
+.section .init
+       /* gcc will nicely put the contents of crtend.o's .init section here. */
+#ifdef __thumb__
+       .thumb
+       
+       pop     {r3, r4, r5, r6, r7}
+       pop     {r3}
+       mov     lr, r3
+#else
+       .arm
+       
+       sub     sp, fp, #40
+       ldmfd   sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr}
+#endif
+       
+#if defined __THUMB_INTERWORK__ || defined __thumb__
+       bx      lr
+#else
+       mov     pc, lr
+#endif
+
+.section .fini
+       /* gcc will nicely put the contents of crtend.o's .fini section here. */
+#ifdef __thumb__
+       .thumb
+       
+       pop     {r3, r4, r5, r6, r7}
+       pop     {r3}
+       mov     lr, r3
+#else
+       .arm
+       
+       sub     sp, fp, #40
+       ldmfd   sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr}
+#endif
+       
+#if defined __THUMB_INTERWORK__ || defined __thumb__
+       bx      lr
+#else
+       mov     pc, lr
+#endif
index 8363aea..3cdbe11 100644 (file)
@@ -9,7 +9,8 @@ typedef void    (*constructor_t)(void);
 constructor_t  _crtbegin_ctors[0] __attribute__((section(".ctors")));
 
 exithandler_t  _crt0_exit_handler;
-//extern constructor_t _crtbegin_ctors[];
+extern void    _init(void);
+extern void    _fini(void);
 extern void    _exit(int status) __attribute__((noreturn));
 extern int     main(int argc, char *argv[], char **envp);
 
@@ -17,16 +18,16 @@ void _start(int argc, char *argv[], char **envp) __attribute__ ((alias("start"))
 
 void start(int argc, char *argv[], char **envp)
 {
-        int    i;
-        int    rv;
-       
-       for( i = 0; _crtbegin_ctors[i]; i ++ )
+       // TODO: isn't this handled by _init?
+       for( int i = 0; _crtbegin_ctors[i]; i ++ )
                _crtbegin_ctors[i]();
+       
+       _init();
 
-       rv = main(argc, argv, envp);
+       int rv = main(argc, argv, envp);
        
        if( _crt0_exit_handler )
                _crt0_exit_handler();
-
+       _fini();
        _exit(rv);
 }
diff --git a/Usermode/Libraries/crt0.o_src/crt0S.c b/Usermode/Libraries/crt0.o_src/crt0S.c
new file mode 100644 (file)
index 0000000..1f35ce4
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Acess2
+ * - CRT0 Shared library version
+ */
+
+typedef        void    (*exithandler_t)(void);
+typedef        void    (*constructor_t)(void);
+
+extern void    _SysDebug(const char *, ...);
+extern void    _init(void);
+extern void    _fini(void);
+extern int     SoMain(void *Base, int argc, char *argv[], char **envp) __attribute__((weak));
+
+int SoStart(void *Base, int argc, char *argv[], char **envp)
+{
+       //_SysDebug("SoStart(%p,%i,%p)", Base, argc, argv);
+       _init();
+
+       if( SoMain )
+               return SoMain(Base, argc, argv, envp);
+       else
+               return 0;
+}
diff --git a/Usermode/Libraries/crt0.o_src/native-crti.S b/Usermode/Libraries/crt0.o_src/native-crti.S
new file mode 100644 (file)
index 0000000..01c8127
--- /dev/null
@@ -0,0 +1,11 @@
+.section .init
+.global _init
+.type _init, @function
+_init:
+       /* gcc will nicely put the contents of crtbegin.o's .init section here. */
+
+.section .fini
+.global _fini
+.type _fini, @function
+_fini:
+       /* gcc will nicely put the contents of crtbegin.o's .fini section here. */
diff --git a/Usermode/Libraries/crt0.o_src/native-crtn.S b/Usermode/Libraries/crt0.o_src/native-crtn.S
new file mode 100644 (file)
index 0000000..f884c09
--- /dev/null
@@ -0,0 +1,7 @@
+.section .init
+       /* gcc will nicely put the contents of crtend.o's .init section here. */
+       ret
+
+.section .fini
+       ret
+       /* gcc will nicely put the contents of crtend.o's .fini section here. */
diff --git a/Usermode/Libraries/crt0.o_src/x86-crti.S b/Usermode/Libraries/crt0.o_src/x86-crti.S
new file mode 100644 (file)
index 0000000..cebea3e
--- /dev/null
@@ -0,0 +1,15 @@
+.section .init
+.global _init
+.type _init, @function
+_init:
+       push %ebp
+       movl %esp, %ebp
+       /* gcc will nicely put the contents of crtbegin.o's .init section here. */
+
+.section .fini
+.global _fini
+.type _fini, @function
+_fini:
+       push %ebp
+       movl %esp, %ebp
+       /* gcc will nicely put the contents of crtbegin.o's .fini section here. */
diff --git a/Usermode/Libraries/crt0.o_src/x86-crtn.S b/Usermode/Libraries/crt0.o_src/x86-crtn.S
new file mode 100644 (file)
index 0000000..33957bf
--- /dev/null
@@ -0,0 +1,9 @@
+.section .init
+       /* gcc will nicely put the contents of crtend.o's .init section here. */
+       popl %ebp
+       ret
+
+.section .fini
+       /* gcc will nicely put the contents of crtend.o's .fini section here. */
+       popl %ebp
+       ret
diff --git a/Usermode/Libraries/crt0.o_src/x86_64-crti.S b/Usermode/Libraries/crt0.o_src/x86_64-crti.S
new file mode 100644 (file)
index 0000000..fb7dad3
--- /dev/null
@@ -0,0 +1,15 @@
+.section .init
+.global _init
+.type _init, @function
+_init:
+       push %rbp
+       mov %rsp, %rbp
+       /* gcc will nicely put the contents of crtbegin.o's .init section here. */
+
+.section .fini
+.global _fini
+.type _fini, @function
+_fini:
+       push %rbp
+       mov %rsp, %rbp
+       /* gcc will nicely put the contents of crtbegin.o's .fini section here. */
diff --git a/Usermode/Libraries/crt0.o_src/x86_64-crtn.S b/Usermode/Libraries/crt0.o_src/x86_64-crtn.S
new file mode 100644 (file)
index 0000000..ec78f0b
--- /dev/null
@@ -0,0 +1,9 @@
+.section .init
+       /* gcc will nicely put the contents of crtend.o's .init section here. */
+       pop %rbp
+       ret
+
+.section .fini
+       /* gcc will nicely put the contents of crtend.o's .fini section here. */
+       pop %rbp
+       ret
index 4dc881c..d6691e4 100644 (file)
@@ -11,10 +11,12 @@ EXTRABIN := libld-acess.so
 EXTRACLEAN = $(_OBJPREFIX)_stublib.o
 INCFILES := sys/sys.h
 
-CFLAGS   = -g -Wall -fno-builtin -fno-stack-protector -fPIC -std=c99
+#CPPFLAGS += -D DISABLE_ELF64
+CFLAGS   = -g -Wall -fno-builtin -fno-stack-protector -fPIC -std=c99 -ffreestanding
 # -fno-leading-underscore
 CFLAGS  += $(CPPFLAGS)
-LDFLAGS  = -g -T arch/$(ARCHDIR).ld -Map map.txt --export-dynamic
+LDFLAGS  = -ffreestanding -nostdlib -g -Wl,-T,arch/$(ARCHDIR).ld -Map map.txt --export-dynamic -x
+LIBS := $(LIBGCC_PATH)
 
 ifeq ($(ARCH),native)
 XBIN := $(addprefix $(OUTPUTDIR)Libs/,$(EXTRABIN)) 
@@ -31,15 +33,15 @@ include ../Makefile.tpl
 # create libld-acess.so
 $(_XBIN): $(_OBJPREFIX)_stublib.o
        @echo [LD] -o -shared libld-acess.so
-       $(LD) -shared -o $@ $<
+       $V$(LD) -shared -o $@ $<
 #      @$(LD) $(LDFLAGS) -o $@ $(OBJ)
 
 
 # Override .ao to look in the object prefix for the source
-$(_OBJPREFIX)arch/$(ARCHDIR).ao_: $(_OBJPREFIX)arch/$(ARCHDIR).$(ASSUFFIX)
+$(_OBJPREFIX)arch/$(ARCHDIR).ao_: $(_OBJPREFIX)arch/$(ARCHDIR).$(ASSUFFIX) Makefile
        @echo [AS] -o $@
        @mkdir -p $(dir $@)
-       @$(AS) $(ASFLAGS) -o $@ $<
+       $V$(AS) $(ASFLAGS) -o $@ $<
 
 #.PRECIOUS: $(OBJ:%.ao=%.asm)
 
@@ -47,7 +49,7 @@ $(_OBJPREFIX)arch/$(ARCHDIR).ao_: $(_OBJPREFIX)arch/$(ARCHDIR).$(ASSUFFIX)
 $(_OBJPREFIX)arch/$(ARCHDIR).$(ASSUFFIX): arch/$(ARCHDIR).$(ASSUFFIX).h arch/syscalls.s.h
        @echo [CPP] -o $@
        @mkdir -p $(dir $@)
-       @$(CPP) $(CPPFLAGS) -P -D__ASSEMBLER__ $< -o $@
+       $V$(CPP) $(CPPFLAGS) -P -D__ASSEMBLER__ $< -o $@
 
 $(_OBJPREFIX)arch/$(ARCHDIR).$(ASSUFFIX): $(ACESSDIR)/KernelLand/Kernel/include/syscalls.h
 
index 351c841..7e604f1 100644 (file)
@@ -16,7 +16,7 @@ _start:
        
        b _exit
 
-@ Stupid GCC
+// Stupid GCC
 .globl __ucmpdi2
 __ucmpdi2:
        cmp r0, r2
@@ -32,8 +32,8 @@ __ucmpdi2:
        mov r0, #1
        mov pc, lr
 
-@ Well, can't blame it
-@ - Clear the instruction cache
+//@ Well, can't blame it
+// - Clear the instruction cache
 .globl __clear_cache
 __clear_cache:
        svc #0x1001
index 7f0acb8..1b9c3e8 100644 (file)
@@ -37,7 +37,11 @@ SYSCALL1(_SysSetFaultHandler, SYS_SETFAULTHANDLER)
 
 SYSCALL1(_SysLoadModule, SYS_LOADMOD)
 
-SYSCALL6(_SysDebug, 0x100)
+SYSCALL6(_ZN4_sys5debugEPKcz, SYS_DEBUGF)
+SYSCALL6(_SysDebug, SYS_DEBUGF)
+//SYSCALL3(_SysDebugS, SYS_DEBUGS)
+SYSCALL3(_SysDebugHex, SYS_DEBUGHEX)
+
 SYSCALL1(_SysGetPhys, SYS_GETPHYS)     // uint64_t _SysGetPhys(uint addr)
 SYSCALL1(_SysAllocate, SYS_ALLOCATE)   // uint64_t _SysAllocate(uint addr)
 SYSCALL3(_SysSetMemFlags, SYS_SETFLAGS)        // uint32_t SysSetMemFlags(uint addr, uint flags, uint mask)
@@ -49,7 +53,10 @@ SYSCALL2(_SysCopyFD, SYS_COPYFD)     // int, int
 SYSCALL3(_SysFDFlags, SYS_FDCTL)       // int, int, int
 SYSCALL1(_SysClose, SYS_CLOSE) // int
 SYSCALL3(_SysRead, SYS_READ)   // int, uint, void*
+SYSCALL5(_SysReadAt, SYS_READAT)       // int, uint, uint64, void*
 SYSCALL3(_SysWrite, SYS_WRITE) // int, uint, void*
+SYSCALL5(_SysWriteAt, SYS_WRITEAT)     // int, uint, uint64, void*
+SYSCALL3(_SysTruncate, SYS_TRUNCATE)   // int, uint64
 SYSCALL4(_SysSeek, SYS_SEEK)   // int, uint64_t, int
 SYSCALL1(_SysTell, SYS_TELL)   // int
 SYSCALL3(_SysFInfo, SYS_FINFO) // int, void*, int
@@ -63,3 +70,9 @@ SYSCALL6(_SysSelect, SYS_SELECT)      // int, fd_set*, fd_set*, fd_set*, tTime*, uint
 SYSCALL1(_SysMkDir, SYS_MKDIR) // const char*
 SYSCALL1(_SysUnlink, SYS_UNLINK)       // const char*
 
+SYSCALL6(_SysMMap, SYS_MMAP)
+SYSCALL2(_SysMUnMap, SYS_MUNMAP)
+
+SYSCALL1(_SysMarshalFD, SYS_MARSHALFD)
+SYSCALL2(_SysUnMarshalFD, SYS_UNMARSHALFD)
+
index 350585a..b80e092 100644 (file)
@@ -56,9 +56,11 @@ _errno:      dw      0       ; Placed in .text, to allow use of relative addressing
 [global %1:func]
 %1:
        push rbx
+       push rbp
        mov eax, %2
        SYSCALL_OP
        mov [DWORD rel _errno], ebx
+       pop rbp
        pop rbx
        ret
 %endmacro
index ac07f9c..e0620c2 100644 (file)
@@ -41,7 +41,7 @@ extern void   *DoRelocate(void *Base, char **envp, const char *Filename);
 // === Library/Symbol Manipulation ==
 extern void    *LoadLibrary(const char *Filename, const char *SearchDir, char **envp);
 extern void    AddLoaded(const char *File, void *base);
-extern int     GetSymbol(const char *Name, void **Value, size_t *size);
+extern int     GetSymbol(const char *Name, void **Value, size_t *size, void *IgnoreBase);
 extern int     GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
 
 // === Library Functions ===
index 71e9a92..fa2e3f4 100644 (file)
@@ -4,8 +4,10 @@
  *
  * elf.c
  * - ELF32/ELF64 relocation
+ *
+ * TODO: Have GetSymbol() return a symbol "strength" on success. Allows STB_WEAK to be overriden by STB_GLOBAL
  */
-#ifndef DEBUG  // This code is #include'd from the kernel, so DEBUG may already be defined
+#ifndef KERNEL_VERSION
 # define DEBUG 0
 #endif
 
@@ -15,6 +17,7 @@
 
 #include "common.h"
 #include <stdint.h>
+#include <stdbool.h>
 #ifndef assert
 # include <assert.h>
 #endif
 #include "elf64.h"
 
 #if DEBUG
-# define       DEBUGS(v...)    SysDebug("ld-acess - " v)
+# define DEBUG_OUT(...)        SysDebug(__VA_ARGS__)
 #else
-# define       DEBUGS(...)     
+# define DEBUG_OUT(...)        do{}while(0)    //((void)(__VA_ARGS__))
 #endif
 
+#define WARNING(f,...) SysDebug("WARN: "f ,## __VA_ARGS__)     // Malformed file
+#define NOTICE(f,...)  SysDebug("NOTICE: "f ,## __VA_ARGS__)   // Missing relocation
+//#define TRACE(f,...) DEBUG_OUT("TRACE:%s:%i "f, __func__, __LINE__ ,## __VA_ARGS__)  // Debugging trace
+#define TRACE(f,...)   DEBUG_OUT("TRACE:%s "f, __func__,## __VA_ARGS__)        // Debugging trace
+
 #ifndef DISABLE_ELF64
 # define SUPPORT_ELF64
 #endif
 // === CONSTANTS ===
 #if DEBUG
 //static const char    *csaDT_NAMES[] = {"DT_NULL", "DT_NEEDED", "DT_PLTRELSZ", "DT_PLTGOT", "DT_HASH", "DT_STRTAB", "DT_SYMTAB", "DT_RELA", "DT_RELASZ", "DT_RELAENT", "DT_STRSZ", "DT_SYMENT", "DT_INIT", "DT_FINI", "DT_SONAME", "DT_RPATH", "DT_SYMBOLIC", "DT_REL", "DT_RELSZ", "DT_RELENT", "DT_PLTREL", "DT_DEBUG", "DT_TEXTREL", "DT_JMPREL"};
-static const char      *csaR_NAMES[] = {"R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32", "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT", "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC", "R_386_LAST"};
+//static const char    *csaR_NAMES[] = {"R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32", "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT", "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC", "R_386_LAST"};
+#endif
+
+#ifdef SUPPORT_ELF64
 #endif
 
 // === PROTOTYPES ===
 void   *ElfRelocate(void *Base, char **envp, const char *Filename);
  int   ElfGetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
-void   *Elf32Relocate(void *Base, char **envp, const char *Filename);
- int   Elf32GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
- int   elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
- int   elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
- int   elf_doRelocate_unk(uint32_t , uint32_t *, Elf32_Addr , int , int , const char *, intptr_t);
+void   *Elf32_Relocate(void *Base, char **envp, const char *Filename);
+ int   Elf32_GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
 #ifdef SUPPORT_ELF64
-int    _Elf64DoReloc_X86_64(void *Base, const char *strtab, Elf64_Sym *symtab, Elf64_Xword r_info, void *ptr, Elf64_Sxword addend);
-void   *Elf64Relocate(void *Base, char **envp, const char *Filename);
- int   Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
+void   *Elf64_Relocate(void *Base, char **envp, const char *Filename);
+ int   Elf64_GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
 #endif
 uint32_t       ElfHashString(const char *name);
 
@@ -64,10 +71,10 @@ void *ElfRelocate(void *Base, char **envp, const char *Filename)
        switch(hdr->e_ident[4])
        {
        case ELFCLASS32:
-               return Elf32Relocate(Base, envp, Filename);
+               return Elf32_Relocate(Base, envp, Filename);
 #ifdef SUPPORT_ELF64
        case ELFCLASS64:
-               return Elf64Relocate(Base, envp, Filename);
+               return Elf64_Relocate(Base, envp, Filename);
 #endif
        default:
                SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]);
@@ -85,10 +92,10 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret, size_t *Size)
        switch(hdr->e_ident[4])
        {
        case ELFCLASS32:
-               return Elf32GetSymbol(Base, Name, ret, Size);
+               return Elf32_GetSymbol(Base, Name, ret, Size);
 #ifdef SUPPORT_ELF64
        case ELFCLASS64:
-               return Elf64GetSymbol(Base, Name, ret, Size);
+               return Elf64_GetSymbol(Base, Name, ret, Size);
 #endif
        default:
                SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]);
@@ -96,482 +103,219 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret, size_t *Size)
        }
 }
 
-int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type,
-               int bRela, const char *Sym, intptr_t iBaseDiff)
+// --------------------------------------------------------------------
+// Elf32 support
+// --------------------------------------------------------------------
+#define ELFTYPE        Elf32
+#include "elf_impl.c"
+#undef ELFTYPE
+
+Elf32_RelocFcn elf_doRelocate_386;
+Elf32_RelocFcn elf_doRelocate_arm;
+
+int elf_doRelocate_386(const Elf32_RelocInfo *Info, Elf32_Word r_info, Elf32_Word* ptr, Elf32_Addr addend, bool bRela)
 {
-       void    *symval;
-       switch( type )
+       const Elf32_Sym *sym = &Info->symtab[ ELF32_R_SYM(r_info) ];
+       void    *symval = (void*)(intptr_t)sym->st_value;
+       size_t  size = sym->st_size;
+       TRACE("%i '%s'", ELF32_R_TYPE(r_info), Info->strtab + sym->st_name);
+       switch( ELF32_R_TYPE(r_info) )
        {
        // Standard 32 Bit Relocation (S+A)
        case R_386_32:
-               if( !GetSymbol(Sym, &symval, NULL) )
-                       return 1;
-               DEBUGS(" elf_doRelocate: R_386_32 *0x%x += %p('%s')",
-                               ptr, symval, Sym);
+               TRACE("R_386_32 *0x%x = %p + 0x%x", ptr, symval, addend);
                *ptr = (intptr_t)symval + addend;
                break;
                
        // 32 Bit Relocation wrt. Offset (S+A-P)
        case R_386_PC32:
-               DEBUGS(" elf_doRelocate: '%s'", Sym);
-               if( !GetSymbol(Sym, &symval, NULL) )    return 1;
-               DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%p - 0x%x",
-                       ptr, *ptr, symval, (intptr_t)ptr );
+               TRACE("R_386_PC32 *0x%x = 0x%x + 0x%p - 0x%x", ptr, *ptr, symval, (intptr_t)ptr );
                *ptr = (intptr_t)symval + addend - (intptr_t)ptr;
                //*ptr = val + addend - ((Uint)ptr - iBaseDiff);
                break;
 
        // Absolute Value of a symbol (S)
        case R_386_GLOB_DAT:
+               TRACE("R_386_GLOB_DAT *0x%x = %p", ptr, symval);        if(0)
        case R_386_JMP_SLOT:
-               DEBUGS(" elf_doRelocate: '%s'", Sym);
-               if( !GetSymbol(Sym, &symval, NULL) )    return 1;
-               DEBUGS(" elf_doRelocate: %s *0x%x = %p", csaR_NAMES[type], ptr, symval);
+               TRACE("R_386_JMP_SLOT *0x%x = %p", ptr, symval);
                *ptr = (intptr_t)symval;
                break;
 
        // Base Address (B+A)
        case R_386_RELATIVE:
-               DEBUGS(" elf_doRelocate: R_386_RELATIVE *0x%x = 0x%x + 0x%x", ptr, iBaseDiff, addend);
-               *ptr = iBaseDiff + addend;
+               TRACE("R_386_RELATIVE *0x%x = 0x%x + 0x%x", ptr, Info->iBaseDiff, addend);
+               *ptr = Info->iBaseDiff + addend;
                break;
 
        case R_386_COPY: {
-               size_t  size;
-               if( !GetSymbol(Sym, &symval, &size) )   return 1;
-               DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, symval, size);
-               memcpy(ptr, symval, size);
+               void *old_symval = symval;
+               GetSymbol(Info->strtab + sym->st_name, &symval, &size, Info->Base);
+               if( symval == old_symval )
+               {
+                       if( ELF32_ST_BIND(sym->st_info) != STB_WEAK )
+                       {
+                               WARNING("sym={val:%p,size:0x%x,info:0x%x,other:0x%x,shndx:%i}",
+                                       sym->st_value, sym->st_size, sym->st_info, sym->st_other, sym->st_shndx);
+                               WARNING("Can't find required external symbol '%s' for R_386_COPY", Info->strtab + sym->st_name);
+                               return 1;
+                       }
+                       // Don't bother doing the memcpy
+                       TRACE("R_386_COPY (%p, %p, %i)", ptr, symval, size);
+               }
+               else
+               {
+                       TRACE("R_386_COPY (%p, %p, %i)", ptr, symval, size);
+                       memcpy(ptr, symval, size);
+               }
                break; }
 
        default:
-               SysDebug("elf_doRelocate_386: Unknown relocation %i", type);
+               WARNING("Unknown relocation %i", ELF32_ST_TYPE(r_info));
                return 2;
        }
        return 0;
 }
 
-int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+int elf_doRelocate_arm(const Elf32_RelocInfo *Info, Elf32_Word r_info, Elf32_Word* ptr, Elf32_Addr addend, bool bRela)
 {
-       uint32_t        val;
-       switch(type)
+       const Elf32_Sym *sym = &Info->symtab[ ELF32_R_SYM(r_info) ];
+       void    *symval = (void*)(intptr_t)sym->st_value;
+       size_t  size = sym->st_size;
+       TRACE("%i '%s'", ELF32_R_TYPE(r_info), Info->strtab + sym->st_name);
+       uintptr_t       val = (uintptr_t)symval;
+       switch( ELF32_R_TYPE(r_info) )
        {
        // (S + A) | T
        case R_ARM_ABS32:
-               DEBUGS(" elf_doRelocate_arm: R_ARM_ABS32 %p (%s + %x)", ptr, Sym, addend);
-               if( !GetSymbol(Sym, (void**)&val, NULL) )       return 1;
+               TRACE("R_ARM_ABS32 %p (%p + %x)", ptr, symval, addend);
                *ptr = val + addend;
                break;
        case R_ARM_GLOB_DAT:
-               DEBUGS(" elf_doRelocate_arm: R_ARM_GLOB_DAT %p (%s + %x)", ptr, Sym, addend);
-               if( !GetSymbol(Sym, (void**)&val, NULL) )       return 1;
+               TRACE("R_ARM_GLOB_DAT %p (%p + %x)", ptr, symval, addend);
                *ptr = val + addend;
                break;
        case R_ARM_JUMP_SLOT:
                if(!bRela)      addend = 0;
-               DEBUGS(" elf_doRelocate_arm: R_ARM_JUMP_SLOT %p (%s + %x)", ptr, Sym, addend);
-               if( !GetSymbol(Sym, (void**)&val, NULL) )       return 1;
+               TRACE("R_ARM_JUMP_SLOT %p (%p + %x)", ptr, symval, addend);
                *ptr = val + addend;
                break;
        // Copy
-       case R_ARM_COPY: {
-               size_t  size;
-               void    *src;
-               if( !GetSymbol(Sym, &src, &size) )      return 1;
-               DEBUGS(" elf_doRelocate_arm: R_ARM_COPY (%p, %p, %i)", ptr, src, size);
-               memcpy(ptr, src, size);
-               break; }
+       case R_ARM_COPY:
+               TRACE("R_ARM_COPY (%p, %p, %i)", ptr, symval, size);
+               memcpy(ptr, symval, size);
+               break;
        // Delta between link and runtime locations + A
        case R_ARM_RELATIVE:
-               DEBUGS(" elf_doRelocate_arm: R_ARM_RELATIVE %p (0x%x + 0x%x)", ptr, iBaseDiff, addend);
-               if(Sym[0] != '\0') {
+               TRACE("R_ARM_RELATIVE %p (0x%x + 0x%x)", ptr, Info->iBaseDiff, addend);
+               if(ELF32_R_SYM(r_info) != 0) {
                        // TODO: Get delta for a symbol
-                       SysDebug("elf_doRelocate_arm: TODO - Implment R_ARM_RELATIVE for symbols");
+                       WARNING("TODO - Implment R_ARM_RELATIVE for symbols");
                        return 2;
                }
                else {
-                       *ptr = iBaseDiff + addend;
+                       *ptr = Info->iBaseDiff + addend;
                }
                break;
        default:
-               SysDebug("elf_doRelocate_arm: Unknown Relocation, %i", type);
+               WARNING("Unknown Relocation, %i", ELF32_R_TYPE(r_info));
                return 2;
        }
        return 0;
 }
 
-int elf_doRelocate_unk(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
-{
-       return 1;
-}
-
-void *Elf32Relocate(void *Base, char **envp, const char *Filename)
+Elf32_RelocFcn*        Elf32_GetRelocFcn(unsigned Machine)
 {
-       Elf32_Ehdr      *hdr = Base;
-       Elf32_Phdr      *phtab;
-       char    *libPath;
-       intptr_t        iRealBase = -1;
-       intptr_t        iBaseDiff;
-        int    iSegmentCount;
-       Elf32_Rel       *rel = NULL;
-       Elf32_Rela      *rela = NULL;
-       void    *plt = NULL;
-        int    relSz=0, relEntSz=8;
-        int    relaSz=0, relaEntSz=8;
-        int    pltSz=0, pltType=0;
-       Elf32_Dyn       *dynamicTab = NULL;     // Dynamic Table Pointer
-       char    *dynstrtab = NULL;      // .dynamic String Table
-       Elf32_Sym       *dynsymtab;
-       int     (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff);
-       
-       DEBUGS("ElfRelocate: (Base=0x%x)", Base);
-       
-       // Check magic header
-       
-       
-       // Parse Program Header to get Dynamic Table
-       phtab = (void*)( (uintptr_t)Base + hdr->phoff );
-       iSegmentCount = hdr->phentcount;
-       for(int i = 0; i < iSegmentCount; i ++)
+       switch(Machine)
        {
-               switch(phtab[i].Type)
-               {
-               case PT_LOAD:
-                       // Determine linked base address
-                       if( iRealBase > phtab[i].VAddr)
-                               iRealBase = phtab[i].VAddr;
-                       break;
-               case PT_DYNAMIC:
-                       // Find Dynamic Section
-                       if(!dynamicTab) {
-                               dynamicTab = (void *) (intptr_t) phtab[i].VAddr;
-                       }
-                       else {
-                               DEBUGS(" WARNING - elf_relocate: Multiple PT_DYNAMIC segments");
-                       }
-                       break;
-               }
-       }
-       
-       // Page Align real base
-       iRealBase &= ~0xFFF;
-       DEBUGS(" elf_relocate: True Base = 0x%x, Compiled Base = 0x%x", Base, iRealBase);
-       
-       // Adjust "Real" Base
-       iBaseDiff = (intptr_t)Base - iRealBase;
-
-//     hdr->entrypoint += iBaseDiff;   // Adjust Entrypoint
-       
-       // Check if a PT_DYNAMIC segement was found
-       if(!dynamicTab) {
-               SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base);
-               return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff);
+       case EM_386:    return elf_doRelocate_386;
+       case EM_ARM:    return elf_doRelocate_arm;
+       default:        return NULL;
        }
+}
 
-       // Allow writing to read-only segments, just in case they need to be relocated
-       // - Will be reversed at the end of the function
-       for( int i = 0; i < iSegmentCount; i ++ )
-       {
-               if(phtab[i].Type == PT_LOAD && !(phtab[i].Flags & PF_W) ) {
-                       uintptr_t       addr = phtab[i].VAddr + iBaseDiff;
-                       uintptr_t       end = addr + phtab[i].MemSize;
-                       for( ; addr < end; addr += PAGE_SIZE )
-                               _SysSetMemFlags(addr, 0, 1);    // Unset RO
-               }
-       }
 
-       // Adjust Dynamic Table
-       dynamicTab = (void *)( (intptr_t)dynamicTab + iBaseDiff );
-       
-       // === Get Symbol table and String Table ===
-       dynsymtab = NULL;
-       for( int j = 0; dynamicTab[j].d_tag != DT_NULL; j++)
-       {
-               switch(dynamicTab[j].d_tag)
-               {
-               // --- Symbol Table ---
-               case DT_SYMTAB:
-                       DEBUGS(" elf_relocate: DYNAMIC Symbol Table 0x%x (0x%x)",
-                               dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff);
-                       dynsymtab = (void*)((intptr_t)dynamicTab[j].d_val + iBaseDiff);
-                       //if(iBaseDiff != 0)    dynamicTab[j].d_val += iBaseDiff;
-                       break;
-               // --- String Table ---
-               case DT_STRTAB:
-                       DEBUGS(" elf_relocate: DYNAMIC String Table 0x%x (0x%x)",
-                               dynamicTab[j].d_val, dynamicTab[j].d_val + iBaseDiff);
-                       dynstrtab = (void*)((intptr_t)dynamicTab[j].d_val + iBaseDiff);
-                       //if(iBaseDiff != 0)    dynamicTab[j].d_val += iBaseDiff;
-                       break;
-               // --- Hash Table --
-               case DT_HASH:
-                       //if(iBaseDiff != 0)    dynamicTab[j].d_val += iBaseDiff;
-//                     iSymCount = ((Elf32_Word*)(intptr_t)dynamicTab[j].d_val)[1];
-                       break;
-               }
-       }
+// --------------------------------------------------------------------
+// Elf64 support
+// --------------------------------------------------------------------
+#ifdef SUPPORT_ELF64
 
-       if(dynsymtab == NULL) {
-               SysDebug("ld-acess.so - WARNING: No Dynamic Symbol table in %p, returning", hdr);
-               return (void *)(intptr_t) (hdr->entrypoint + iBaseDiff);
-       }
+#define ELFTYPE        Elf64
+#include "elf_impl.c"
+#undef ELFTYPE
 
-       // === Add to loaded list (can be imported now) ===
-       AddLoaded( Filename, Base );
+Elf64_RelocFcn elf_doRelocate_x86_64;
 
-       // === Parse Relocation Data ===
-       DEBUGS(" elf_relocate: dynamicTab = 0x%x", dynamicTab);
-       for( int j = 0; dynamicTab[j].d_tag != DT_NULL; j++)
-       {
-               switch(dynamicTab[j].d_tag)
-               {
-               // --- Shared Library Name ---
-               case DT_SONAME:
-                       DEBUGS(" elf_relocate: .so Name '%s'", dynstrtab+dynamicTab[j].d_val);
-                       break;
-               // --- Needed Library ---
-               case DT_NEEDED:
-                       libPath = dynstrtab + dynamicTab[j].d_val;
-                       DEBUGS(" dynstrtab = %p, d_val = 0x%x", dynstrtab, dynamicTab[j].d_val);
-                       DEBUGS(" Required Library '%s'", libPath);
-                       if(LoadLibrary(libPath, NULL, envp) == 0) {
-                               #if DEBUG
-                               DEBUGS(" elf_relocate: Unable to load '%s'", libPath);
-                               #else
-                               SysDebug("Unable to load required library '%s'", libPath);
-                               #endif
-                               return 0;
-                       }
-                       DEBUGS(" Lib loaded");
-                       break;
-               // --- PLT/GOT ---
-//             case DT_PLTGOT: pltgot = (void*)(iBaseDiff + dynamicTab[j].d_val);      break;
-               case DT_JMPREL: plt = (void*)(iBaseDiff + dynamicTab[j].d_val); break;
-               case DT_PLTREL: pltType = dynamicTab[j].d_val;  break;
-               case DT_PLTRELSZ:       pltSz = dynamicTab[j].d_val;    break;
-               
-               // --- Relocation ---
-               case DT_REL:    rel = (void*)(iBaseDiff + dynamicTab[j].d_val); break;
-               case DT_RELSZ:  relSz = dynamicTab[j].d_val;    break;
-               case DT_RELENT: relEntSz = dynamicTab[j].d_val; break;
-               case DT_RELA:   rela = (void*)(iBaseDiff + dynamicTab[j].d_val);        break;
-               case DT_RELASZ: relaSz = dynamicTab[j].d_val;   break;
-               case DT_RELAENT:        relaEntSz = dynamicTab[j].d_val;        break;
-               
-               // --- Symbol Table ---
-               case DT_SYMTAB:
-               // --- Hash Table ---
-               case DT_HASH:
-               // --- String Table ---
-               case DT_STRTAB:
-                       break;
-               
-               // --- Unknown ---
-               default:
-                       if(dynamicTab[j].d_tag > DT_JMPREL)     continue;
-                       //DEBUGS(" elf_relocate: %i-%i = %s,0x%x",
-                       //      i,j, csaDT_NAMES[dynamicTab[j].d_tag],dynamicTab[j].d_val);
-                       break;
-               }
-       }
-       
-       DEBUGS(" elf_relocate: Beginning Relocation");
-
-        int    fail = 0;
-
-       switch(hdr->machine)
+int elf_doRelocate_x86_64(const Elf64_RelocInfo *Info, Elf64_Xword r_info, Elf64_Xword* ptr, Elf64_Addr addend, bool bRela)
+{
+       const Elf64_Sym *sym = &Info->symtab[ ELF64_R_SYM(r_info) ];
+       void    *symval = (void*)(intptr_t)sym->st_value;
+       size_t  size = sym->st_size;
+       TRACE("%i '%s'", ELF64_R_TYPE(r_info), Info->strtab + sym->st_name);
+       switch( ELF64_R_TYPE(r_info) )
        {
-       case EM_386:
-               do_relocate = elf_doRelocate_386;
+       case R_X86_64_NONE:
                break;
-       case EM_ARM:
-               do_relocate = elf_doRelocate_arm;
+       case R_X86_64_64:
+               TRACE("R_X86_64_64 *0x%x = %p + 0x%x", ptr, symval, addend);
+               *ptr = (intptr_t)symval + addend;
                break;
-       default:
-               SysDebug("Elf32Relocate: Unknown machine type %i", hdr->machine);
-               do_relocate = elf_doRelocate_unk;
-               fail = 1;
+       // Absolute Value of a symbol (S)
+       case R_X86_64_GLOB_DAT:
+               TRACE("R_X86_64_GLOB_DAT *0x%x = %p", ptr, symval);     if(0)
+       case R_X86_64_JUMP_SLOT:
+               TRACE("R_X86_64_JUMP_SLOT *0x%x = %p", ptr, symval);
+               *ptr = (intptr_t)symval;
                break;
-       }
-       
-       DEBUGS("do_relocate = %p (%p or %p)", do_relocate, &elf_doRelocate_386, &elf_doRelocate_arm);
 
-       #define _doRelocate(r_info, ptr, bRela, addend) \
-               do_relocate(r_info, ptr, addend, ELF32_R_TYPE(r_info), bRela, \
-                       dynstrtab + dynsymtab[ELF32_R_SYM(r_info)].nameOfs, iBaseDiff);
+       // Base Address (B+A)
+       case R_X86_64_RELATIVE:
+               TRACE("R_X86_64_RELATIVE *0x%x = 0x%x + 0x%x", ptr, Info->iBaseDiff, addend);
+               *ptr = Info->iBaseDiff + addend;
+               break;
 
-       // Parse Relocation Entries
-       if(rel && relSz)
-       {
-               Elf32_Word      *ptr;
-               DEBUGS(" elf_relocate: rel=0x%x, relSz=0x%x, relEntSz=0x%x", rel, relSz, relEntSz);
-               int max = relSz / relEntSz;
-               for( int i = 0; i < max; i++ )
-               {
-                       //DEBUGS("  Rel %i: 0x%x+0x%x", i, iBaseDiff, rel[i].r_offset);
-                       ptr = (void*)(iBaseDiff + rel[i].r_offset);
-                       fail |= _doRelocate(rel[i].r_info, ptr, 0, *ptr);
-               }
-       }
-       // Parse Relocation Entries
-       if(rela && relaSz)
-       {
-               Elf32_Word      *ptr;
-               DEBUGS(" elf_relocate: rela=0x%x, relaSz=0x%x, relaEntSz=0x%x", rela, relaSz, relaEntSz);
-               int count = relaSz / relaEntSz;
-               for( int i = 0; i < count; i++ )
-               {
-                       ptr = (void*)(iBaseDiff + rela[i].r_offset);
-                       fail |= _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend);
-               }
-       }
-       
-       // === Process PLT (Procedure Linkage Table) ===
-       if(plt && pltSz)
-       {
-               Elf32_Word      *ptr;
-               DEBUGS(" elf_relocate: Relocate PLT, plt=0x%x", plt);
-               if(pltType == DT_REL)
+       case R_X86_64_COPY: {
+               void *old_symval = symval;
+               GetSymbol(Info->strtab + sym->st_name, &symval, &size, Info->Base);
+               if( symval == old_symval )
                {
-                       Elf32_Rel       *pltRel = plt;
-                       int count = pltSz / sizeof(Elf32_Rel);
-                       DEBUGS(" elf_relocate: PLT Reloc Type = Rel, %i entries", count);
-                       for(int i = 0; i < count; i ++)
+                       if( ELF64_ST_BIND(sym->st_info) != STB_WEAK )
                        {
-                               ptr = (void*)(iBaseDiff + pltRel[i].r_offset);
-                               fail |= _doRelocate(pltRel[i].r_info, ptr, 0, *ptr);
+                               WARNING("sym={val:%p,size:0x%x,info:0x%x,other:0x%x,shndx:%i}",
+                                       sym->st_value, sym->st_size, sym->st_info, sym->st_other, sym->st_shndx);
+                               WARNING("Can't find required external symbol '%s' for R_X86_64_COPY", Info->strtab + sym->st_name);
+                               return 1;
                        }
+                       // Don't bother doing the memcpy
+                       TRACE("R_X86_64_COPY (%p, %p, %i)", ptr, symval, size);
                }
                else
                {
-                       Elf32_Rela      *pltRela = plt;
-                       int count = pltSz / sizeof(Elf32_Rela);
-                       DEBUGS(" elf_relocate: PLT Reloc Type = Rela, %i entries", count);
-                       for(int i=0;i<count;i++)
-                       {
-                               ptr = (void*)(iRealBase + pltRela[i].r_offset);
-                               fail |= _doRelocate(pltRela[i].r_info, ptr, 1, pltRela[i].r_addend);
-                       }
-               }
-       }
-
-       // Re-set readonly
-       for( int i = 0; i < iSegmentCount; i ++ )
-       {
-               // If load and not writable
-               if(phtab[i].Type == PT_LOAD && !(phtab[i].Flags & PF_W) ) {
-                       uintptr_t       addr = phtab[i].VAddr + iBaseDiff;
-                       uintptr_t       end = addr + phtab[i].MemSize;
-                       for( ; addr < end; addr += PAGE_SIZE )
-                               _SysSetMemFlags(addr, 1, 1);    // Unset RO
+                       TRACE("R_X86_64_COPY (%p, %p, %i)", ptr, symval, size);
+                       memcpy(ptr, symval, size);
                }
+               break; }
+       default:
+               WARNING("Unknown Relocation, %i", ELF64_R_TYPE(r_info));
+               return 2;
        }
-
-       if( fail ) {
-               DEBUGS("ElfRelocate: Failure");
-               return NULL;
-       }       
-
-       #undef _doRelocate
-
-       DEBUGS("ElfRelocate: RETURN 0x%x to %p", hdr->entrypoint + iBaseDiff, __builtin_return_address(0));
-       return (void*)(intptr_t)( hdr->entrypoint + iBaseDiff );
+       return 0;
 }
 
-int Elf32GetSymbol(void *Base, const char *Name, void **ret, size_t *Size)
+Elf64_RelocFcn* Elf64_GetRelocFcn(unsigned Machine)
 {
-       Elf32_Ehdr      *hdr = Base;
-       Elf32_Sym       *symtab = NULL;
-        int    nbuckets = 0;
-       Elf32_Word      *pBuckets = NULL;
-       Elf32_Word      *pChains;
-       uint32_t        iNameHash;
-       const char      *dynstrtab = NULL;
-       uintptr_t       iBaseDiff = -1;
-       Elf32_Phdr      *phtab;
-       Elf32_Dyn       *dynTab = NULL;
-
-       // Locate the tables
-       phtab = (void*)( (uintptr_t)Base + hdr->phoff );
-       for( int i = 0; i < hdr->phentcount; i ++ )
+       switch(Machine)
        {
-               if(phtab[i].Type == PT_LOAD && iBaseDiff > phtab[i].VAddr)
-                       iBaseDiff = phtab[i].VAddr;
-               if( phtab[i].Type == PT_DYNAMIC ) {
-                       dynTab = (void*)(intptr_t)phtab[i].VAddr;
-               }
-       }
-       if( !dynTab ) {
-               SysDebug("ERROR - Unable to find DYNAMIC segment in %p", Base);
-               return 0;
+       case EM_X86_64: return elf_doRelocate_x86_64;
+       default:        return NULL;
        }
-       iBaseDiff = (intptr_t)Base - iBaseDiff; // Make iBaseDiff actually the diff
-       dynTab = (void*)( (intptr_t)dynTab + iBaseDiff );
-       for( int i = 0; dynTab[i].d_tag != DT_NULL; i++)
-       {
-               switch(dynTab[i].d_tag)
-               {
-               // --- Symbol Table ---
-               case DT_SYMTAB:
-                       symtab = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff);        // Rebased in Relocate
-                       break;
-               case DT_STRTAB:
-                       dynstrtab = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff);
-                       break;
-               // --- Hash Table --
-               case DT_HASH:
-                       pBuckets = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff);
-                       break;
-               }
-       }
-       
-       if( !symtab ) {
-               SysDebug("ERRO - No DT_SYMTAB in %p", Base);
-               return 0;
-       }
-       if( !pBuckets ) {
-               SysDebug("ERRO - No DT_HASH in %p", Base);
-               return 0;
-       }
-       if( !dynstrtab ) {
-               SysDebug("ERRO - No DT_STRTAB in %p", Base);
-               return 0;
-       }
-
-       // ... ok... maybe they haven't been relocated
-       if( (uintptr_t)symtab < (uintptr_t)Base )
-       {
-               symtab    = (void*)( (uintptr_t)symtab    + iBaseDiff );
-               pBuckets  = (void*)( (uintptr_t)pBuckets  + iBaseDiff );
-               dynstrtab = (void*)( (uintptr_t)dynstrtab + iBaseDiff );
-               SysDebug("Executable not yet relocated");
-       }
-
-       nbuckets = pBuckets[0];
-//     iSymCount = pBuckets[1];
-       pBuckets = &pBuckets[2];
-       pChains = &pBuckets[ nbuckets ];
-       assert(pChains);
+}
 
-       // Get hash
-       iNameHash = ElfHashString(Name);
-       iNameHash %= nbuckets;
+#endif // SUPPORT_ELF64
 
-       // Walk Chain
-       int idx = pBuckets[ iNameHash ];
-       do {
-               Elf32_Sym *sym = &symtab[idx];
-               assert(sym);
-               if(sym->shndx != SHN_UNDEF && strcmp(dynstrtab + sym->nameOfs, Name) == 0) {
-                       *ret = (void*)( (uintptr_t)sym->value + iBaseDiff );
-                       if(Size)        *Size = sym->size;
-                       return 1;
-               }
-       } while( (idx = pChains[idx]) != STN_UNDEF && idx != pBuckets[iNameHash] );
-       
-       return 0;
-}
 
 #ifdef SUPPORT_ELF64
+#if 0
 typedef int (*t_elf64_doreloc)(void *Base, const char *strtab, Elf64_Sym *symtab, Elf64_Xword r_info, void *ptr, Elf64_Sxword addend);
 
 int _Elf64DoReloc_X86_64(void *Base, const char *strtab, Elf64_Sym *symtab, Elf64_Xword r_info, void *ptr, Elf64_Sxword addend)
@@ -586,20 +330,20 @@ int _Elf64DoReloc_X86_64(void *Base, const char *strtab, Elf64_Sym *symtab, Elf6
        case R_X86_64_NONE:
                break;
        case R_X86_64_64:
-               if( !GetSymbol(symname, &symval, NULL)  )       return 1;
+               if( !GetSymbol(symname, &symval, NULL, NULL)  ) return 1;
                *(uint64_t*)ptr = (uintptr_t)symval + addend;
                break;
        case R_X86_64_COPY: {
                size_t  size;
-               if( !GetSymbol(symname, &symval, &size)  )      return 1;
+               if( !GetSymbol(symname, &symval, &size, NULL)  )        return 1;
                memcpy(ptr, symval, size);
                } break;
        case R_X86_64_GLOB_DAT:
-               if( !GetSymbol(symname, &symval, NULL)  )       return 1;
+               if( !GetSymbol(symname, &symval, NULL, NULL)  ) return 1;
                *(uint64_t*)ptr = (uintptr_t)symval;
                break;
        case R_X86_64_JUMP_SLOT:
-               if( !GetSymbol(symname, &symval, NULL)  )       return 1;
+               if( !GetSymbol(symname, &symval, NULL, NULL)  ) return 1;
                *(uint64_t*)ptr = (uintptr_t)symval;
                break;
        case R_X86_64_RELATIVE:
@@ -630,18 +374,18 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
        void    *pltrel = NULL;
         int    plt_size = 0, plt_type = 0;
 
-       DEBUGS("Elf64Relocate: hdr = {");
-       DEBUGS("Elf64Relocate:  e_ident = '%.16s'", hdr->e_ident);
-       DEBUGS("Elf64Relocate:  e_type = 0x%x", hdr->e_type);
-       DEBUGS("Elf64Relocate:  e_machine = 0x%x", hdr->e_machine);
-       DEBUGS("Elf64Relocate:  e_version = 0x%x", hdr->e_version);
-       DEBUGS("Elf64Relocate:  e_entry = %p", hdr->e_entry);
-       DEBUGS("Elf64Relocate:  e_phoff = 0x%llx", hdr->e_phoff);
-       DEBUGS("Elf64Relocate:  e_shoff = 0x%llx", hdr->e_shoff);
-       DEBUGS("Elf64Relocate:  e_flags = 0x%x", hdr->e_flags);
-       DEBUGS("Elf64Relocate:  e_ehsize = 0x%x", hdr->e_ehsize);
-       DEBUGS("Elf64Relocate:  e_phentsize = 0x%x", hdr->e_phentsize);
-       DEBUGS("Elf64Relocate:  e_phnum = %i", hdr->e_phnum);
+       TRACE("hdr = {");
+       TRACE(" e_ident = '%.16s'", hdr->e_ident);
+       TRACE(" e_type = 0x%x", hdr->e_type);
+       TRACE(" e_machine = 0x%x", hdr->e_machine);
+       TRACE(" e_version = 0x%x", hdr->e_version);
+       TRACE(" e_entry = %p", hdr->e_entry);
+       TRACE(" e_phoff = 0x%llx", hdr->e_phoff);
+       TRACE(" e_shoff = 0x%llx", hdr->e_shoff);
+       TRACE(" e_flags = 0x%x", hdr->e_flags);
+       TRACE(" e_ehsize = 0x%x", hdr->e_ehsize);
+       TRACE(" e_phentsize = 0x%x", hdr->e_phentsize);
+       TRACE(" e_phnum = %i", hdr->e_phnum);
 
        // Scan for the dynamic table (and find the compiled base)
        phtab = (void*)((uintptr_t)Base + (uintptr_t)hdr->e_phoff);
@@ -655,7 +399,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
 
        baseDiff = (uintptr_t)Base - compiledBase;
 
-       DEBUGS("baseDiff = %p", baseDiff);
+       TRACE("baseDiff = %p", baseDiff);
 
        if(dyntab == NULL) {
                SysDebug(" Elf64Relocate: No PT_DYNAMIC segment in image %p, returning", Base);
@@ -696,14 +440,14 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
        // Second pass on dynamic table
        for(i = 0; dyntab[i].d_tag != DT_NULL; i ++)
        {
-               DEBUGS("dyntab[%i].d_tag = %i", i, dyntab[i].d_tag);
+               TRACE("dyntab[%i].d_tag = %i", i, dyntab[i].d_tag);
                switch(dyntab[i].d_tag)
                {
                case DT_SONAME: break;
 
                case DT_NEEDED: {
                        char *libPath = strtab + dyntab[i].d_un.d_val;
-                       DEBUGS("Elf64Relocate: libPath = '%s'", libPath);
+                       TRACE("Elf64Relocate: libPath = '%s'", libPath);
                        if(LoadLibrary(libPath, NULL, envp) == 0) {
                                SysDebug("ld-acess - Elf64Relocate: Unable to load '%s'", libPath);
                                return NULL;
@@ -752,6 +496,8 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
                }
        }
 
+       // TODO: Relocate symbols
+       
        // Relocation function
        t_elf64_doreloc fpElf64DoReloc = &_Elf64DoReloc_X86_64;
        #define _Elf64DoReloc(info, ptr, addend)        fpElf64DoReloc(Base, strtab, symtab, info, ptr, addend)
@@ -759,7 +505,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
        int fail = 0;
        if( rel )
        {
-               DEBUGS("rel_count = %i", rel_count);
+               TRACE("rel_count = %i", rel_count);
                for( i = 0; i < rel_count; i ++ )
                {
                        uint64_t *ptr = (void *)(uintptr_t)( rel[i].r_offset + baseDiff );
@@ -769,7 +515,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
 
        if( rela )
        {
-               DEBUGS("rela_count = %i", rela_count);
+               TRACE("rela_count = %i", rela_count);
                for( i = 0; i < rela_count; i ++ )
                {
                        uint64_t *ptr = (void *)(uintptr_t)( rela[i].r_offset + baseDiff );
@@ -782,7 +528,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
                if( plt_type == DT_REL ) {
                        Elf64_Rel       *plt = pltrel;
                         int    count = plt_size / sizeof(Elf64_Rel);
-                       DEBUGS("plt rel count = %i", count);
+                       TRACE("plt rel count = %i", count);
                        for( i = 0; i < count; i ++ )
                        {
                                uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff );
@@ -792,7 +538,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
                else {
                        Elf64_Rela      *plt = pltrel;
                         int    count = plt_size / sizeof(Elf64_Rela);
-                       DEBUGS("plt rela count = %i", count);
+                       TRACE("plt rela count = %i", count);
                        for( i = 0; i < count; i ++ )
                        {
                                uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff );
@@ -802,13 +548,13 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
        }
 
        if( fail ) {
-               DEBUGS("Elf64Relocate: Failure");
+               TRACE("Failure");
                return NULL;
        }
 
        {
        void *ret = (void *)(uintptr_t)(hdr->e_entry + baseDiff);
-       DEBUGS("Elf64Relocate: Relocations done, return %p", ret);
+       TRACE("Relocations done, return %p", ret);
        return ret;
        }
 }
@@ -887,7 +633,7 @@ int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size)
        if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) {
                *Ret = (void*)( (intptr_t)symtab[i].st_value + iBaseDiff );
                if(Size)        *Size = symtab[i].st_size;
-               DEBUGS("%s = %p", Name, *Ret);
+               TRACE("%s = %p", Name, *Ret);
                return 1;
        }
        
@@ -897,7 +643,7 @@ int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size)
                if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) {
                        *Ret = (void*)((intptr_t)symtab[i].st_value + iBaseDiff);
                        if(Size)        *Size = symtab[i].st_size;
-                       DEBUGS("%s = %p", Name, *Ret);
+                       TRACE("%s = %p", Name, *Ret);
                        return 1;
                }
        }
@@ -905,7 +651,7 @@ int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size)
        return 0;
 }
 #endif
-
+#endif
 
 uint32_t ElfHashString(const char *name)
 {
index 2e9c1c4..40c801c 100644 (file)
@@ -12,6 +12,7 @@ typedef uint16_t      Elf32_Half;
 typedef uint32_t       Elf32_Addr;
 typedef uint32_t       Elf32_Off;
 typedef uint32_t       Elf32_Word;
+typedef uint32_t       Elf32_Xword;    // < not strictly correct... but meh
 typedef int32_t        Elf32_Sword;
 
 #define ELFCLASS32     1
@@ -26,19 +27,19 @@ typedef int32_t     Elf32_Sword;
 */
 struct sElf32_Ehdr {
        uint8_t e_ident[16];    //!< Identifier Bytes
-       Elf32_Half      filetype;       //!< File Type
-       Elf32_Half      machine;        //!< Machine / Arch
-       Elf32_Word      version;        //!< Version (File?)
-       Elf32_Addr      entrypoint;     //!< Entry Point
-       Elf32_Off       phoff;  //!< Program Header Offset
-       Elf32_Word      shoff;  //!< Section Header Offset
-       Elf32_Word      flags;  //!< Flags
-       Elf32_Half      headersize;     //!< Header Size
-       Elf32_Half      phentsize;      //!< Program Header Entry Size
-       Elf32_Half      phentcount;     //!< Program Header Entry Count
-       Elf32_Half      shentsize;      //!< Section Header Entry Size
-       Elf32_Half      shentcount;     //!< Section Header Entry Count
-       Elf32_Half      shstrindex;     //!< Section Header String Table Index
+       Elf32_Half      e_filetype;     //!< File Type
+       Elf32_Half      e_machine;      //!< Machine / Arch
+       Elf32_Word      e_version;      //!< Version (File?)
+       Elf32_Addr      e_entry;        //!< Entry Point
+       Elf32_Off       e_phoff;        //!< Program Header Offset
+       Elf32_Word      e_shoff;        //!< Section Header Offset
+       Elf32_Word      e_flags;        //!< Flags
+       Elf32_Half      e_headersize;   //!< Header Size
+       Elf32_Half      e_phentsize;    //!< Program Header Entry Size
+       Elf32_Half      e_phnum;        //!< Program Header Entry Count
+       Elf32_Half      e_shentsize;    //!< Section Header Entry Size
+       Elf32_Half      e_shentcount;   //!< Section Header Entry Count
+       Elf32_Half      e_shstrindex;   //!< Section Header String Table Index
 };
 
 /**
@@ -112,15 +113,24 @@ struct sElf32_Shent {
 #endif
 
 struct elf_sym_s {
-       Elf32_Word      nameOfs;
-       Elf32_Addr      value;  //Address
-       Elf32_Word      size;
-       uint8_t info;
-       uint8_t other;
-       Elf32_Half      shndx;
+       Elf32_Word      st_name;
+       Elf32_Addr      st_value;       //Address
+       Elf32_Word      st_size;
+       uint8_t         st_info;
+       uint8_t         st_other;
+       Elf32_Half      st_shndx;
 };
 #define        STN_UNDEF       0       // Undefined Symbol
 
+#define ELF32_ST_BIND(i)       ((i)>>4)
+#define ELF32_ST_TYPE(i)       ((i)&0xF)
+
+enum {
+       STB_LOCAL,
+       STB_GLOBAL,
+       STB_WEAK,
+};
+
 enum {
        PT_NULL,        //0
        PT_LOAD,        //1
@@ -138,14 +148,14 @@ enum {
 #define PF_R   4
 
 struct sElf32_Phdr {
-       Elf32_Word      Type;
-       Elf32_Off       Offset;
-       Elf32_Addr      VAddr;
-       Elf32_Addr      PAddr;
-       Elf32_Word      FileSize;
-       Elf32_Word      MemSize;
-       Elf32_Word      Flags;
-       Elf32_Word      Align;
+       Elf32_Word      p_type;
+       Elf32_Off       p_offset;
+       Elf32_Addr      p_vaddr;
+       Elf32_Addr      p_paddr;
+       Elf32_Word      p_filesz;
+       Elf32_Word      p_memsz;
+       Elf32_Word      p_flags;
+       Elf32_Word      p_align;
 };
 
 struct elf32_rel_s {
index fb39782..9d04e8a 100644 (file)
@@ -69,7 +69,7 @@ typedef struct
        union {
                Elf64_Xword     d_val;
                Elf64_Addr      d_ptr;
-       } d_un;
+       };// d_un;
 } Elf64_Dyn;
 
 typedef struct
@@ -97,6 +97,8 @@ typedef struct
 
 #define ELF64_R_SYM(info)      ((info) >> 32)
 #define ELF64_R_TYPE(info)     ((info) & 0xFFFFFFFF)
+#define ELF64_ST_BIND(i)       ((i)>>4)
+#define ELF64_ST_TYPE(i)       ((i)&0xF)
 
 enum eElf64_RelocTypes_x86_64
 {
diff --git a/Usermode/Libraries/ld-acess.so_src/elf_impl.c b/Usermode/Libraries/ld-acess.so_src/elf_impl.c
new file mode 100644 (file)
index 0000000..a89a26f
--- /dev/null
@@ -0,0 +1,506 @@
+
+#ifndef ELFTYPE
+# error "ELFTYPE must be defined to either ELf32 or Elf64 to use this file"
+#endif
+
+#define __PREF(t,s)    t##_##s
+#define _PREF(t,s)     __PREF(t,s)
+#define PREF(sym)      _PREF(ELFTYPE,sym)
+
+typedef struct
+{
+       void    *Base;
+       intptr_t        iBaseDiff;
+       const char      *strtab;
+       const PREF(Sym) *symtab;
+} PREF(RelocInfo);
+
+typedef int PREF(RelocFcn)(const PREF(RelocInfo)* Info, PREF(Xword) t_info, PREF(Xword)* ptr, PREF(Addr) addend, bool bRela);
+
+// - Extern
+static PREF(RelocFcn)* PREF(GetRelocFcn)(unsigned Machine);
+// - Local
+static PREF(RelocFcn) PREF(doRelocate_unk);
+static void PREF(int_GetBaseDyntab)(void* Base, const PREF(Phdr)* phtab, unsigned phentcount, intptr_t* iBaseDiff_p, PREF(Dyn)** dynamicTab_p);
+static int PREF(GetSymbolVars)(void *Base, const PREF(Sym)** symtab, const PREF(Word)** pBuckets, const char **dynstrtab, uintptr_t* piBaseDiff);
+static int PREF(GetSymbolInfo)(void *Base, const char *Name, void **Addr, size_t *Size, int* Section, int *Binding, int *Type);
+
+// - Relocate
+void *PREF(Relocate)(void *Base, char **envp, const char *Filename)
+{
+       TRACE("(Base=0x%x)", Base);
+       const PREF(Ehdr)        *hdr = Base;
+       
+       // Check magic header
+       // TODO: Validate header?
+       
+       
+       // Parse Program Header to get Dynamic Table
+       // - Determine the linked base of the executable
+       const PREF(Phdr)        *phtab = (void*)( (uintptr_t)Base + hdr->e_phoff );
+       
+       intptr_t        iBaseDiff = 0;
+       PREF(Dyn)*      dynamicTab = NULL;
+       
+       PREF(int_GetBaseDyntab)(Base, phtab, hdr->e_phnum, &iBaseDiff, &dynamicTab);
+       
+       // Check if a PT_DYNAMIC segement was found
+       if(!dynamicTab)
+       {
+               SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base);
+               return (void *)(intptr_t)(hdr->e_entry + iBaseDiff);
+       }
+
+       // Allow writing to read-only segments, just in case they need to be relocated
+       // - Will be reversed at the end of the function
+       for( unsigned i = 0; i < hdr->e_phnum; i ++ )
+       {
+               if(phtab[i].p_type == PT_LOAD && !(phtab[i].p_flags & PF_W) )
+               {
+                       uintptr_t       addr = phtab[i].p_vaddr + iBaseDiff;
+                       uintptr_t       end = addr + phtab[i].p_memsz;
+                       for( ; addr < end; addr += PAGE_SIZE )
+                               _SysSetMemFlags(addr, 0, 1);    // Unset RO
+               }
+       }
+       
+       // === Get Symbol table and String Table ===
+       char    *dynstrtab = NULL;      // .dynamic String Table
+       PREF(Sym)       *dynsymtab = NULL;
+       PREF(Word)      *hashtable = NULL;
+       unsigned        iSymCount = 0;
+       for( unsigned j = 0; dynamicTab[j].d_tag != DT_NULL; j++)
+       {
+               const PREF(Dyn) *dt = &dynamicTab[j];
+               switch(dt->d_tag)
+               {
+               // --- Symbol Table ---
+               case DT_SYMTAB:
+                       TRACE("DYNAMIC Symbol Table 0x%x (0x%x)", dt->d_val, dt->d_val + iBaseDiff);
+                       dynsymtab = (void*)((intptr_t)dt->d_val + iBaseDiff);
+                       break;
+               // --- String Table ---
+               case DT_STRTAB:
+                       TRACE("DYNAMIC String Table 0x%x (0x%x)", dt->d_val, dt->d_val + iBaseDiff);
+                       dynstrtab = (void*)((intptr_t)dt->d_val + iBaseDiff);
+                       break;
+               // --- Hash Table --
+               case DT_HASH:
+                       TRACE("DYNAMIC Hash table %p (%p)", dt->d_val, dt->d_val + iBaseDiff);
+                       hashtable = (void*)((intptr_t)dt->d_val + iBaseDiff);
+                       iSymCount = hashtable[1];
+                       break;
+               }
+       }
+
+       if(dynsymtab == NULL) {
+               SysDebug("ld-acess.so - WARNING: No Dynamic Symbol table in %p, returning", hdr);
+               return (void *)(intptr_t) (hdr->e_entry + iBaseDiff);
+       }
+       
+       // Apply base offset to locally defined symbols
+       // - #0 is defined as ("" SHN_UNDEF), so skip it
+       for( unsigned i = 1; i < iSymCount; i ++ )
+       {
+               PREF(Sym)       *sym = &dynsymtab[i];
+               const char *name = dynstrtab + sym->st_name;
+               (void)name;
+               if( sym->st_shndx == SHN_UNDEF )
+               {
+                       TRACE("Sym %i'%s' deferred (SHN_UNDEF)", i, name);
+               }
+               else if( sym->st_shndx == SHN_ABS )
+               {
+                       // Leave as is
+                       TRACE("Sym %i'%s' untouched", i, name);
+               }
+               else
+               {
+                       void *newval;
+                       size_t  newsize;
+                       if( ELF32_ST_BIND(sym->st_info) != STB_WEAK )
+                       {
+                               TRACE("Sym %i'%s' = %p (local)", i, name, sym->st_value + iBaseDiff);
+                               sym->st_value += iBaseDiff;
+                       }
+                       // If GetSymbol doesn't return a strong/global symbol value
+                       else if( GetSymbol(name, &newval, &newsize, Base) != 1 )
+                       {
+                               TRACE("Sym %i'%s' = %p (Local weak)", i, name, sym->st_value + iBaseDiff);
+                               sym->st_value += iBaseDiff;
+                       }
+                       else
+                       {
+                               TRACE("Sym %i'%s' = %p+0x%x (Extern weak)", i, name, newval, newsize);
+                               sym->st_value = (uintptr_t)newval;
+                               sym->st_size = newsize;
+                       }
+               }
+       }
+
+       // === Add to loaded list (can be imported now) ===
+       AddLoaded( Filename, Base );
+
+       // === Parse Relocation Data ===
+       PREF(Rel)       *rel = NULL;
+       PREF(Rela)      *rela = NULL;
+       void    *plt = NULL;
+        int    relSz=0, relEntSz=8;
+        int    relaSz=0, relaEntSz=8;
+        int    pltSz=0, pltType=0;
+       TRACE("dynamicTab = 0x%x", dynamicTab);
+       for( int j = 0; dynamicTab[j].d_tag != DT_NULL; j++)
+       {
+               const PREF(Dyn) *dt = &dynamicTab[j];
+               switch(dt->d_tag)
+               {
+               // --- Shared Library Name ---
+               case DT_SONAME:
+                       TRACE(".so Name '%s'", dynstrtab + dt->d_val);
+                       break;
+               // --- Needed Library ---
+               case DT_NEEDED: {
+                       //assert(dt->d_val < sizeof_dynstrtab); // Disabled, no sizeof_dynstrtab
+                       const char      *libPath = dynstrtab + dt->d_val;
+                       TRACE(" Required Library '%s'", libPath);
+                       if(LoadLibrary(libPath, NULL, envp) == 0) {
+                               SysDebug("Unable to load required library '%s'", libPath);
+                               return 0;
+                       }
+                       TRACE(" Lib loaded");
+                       break; }
+               // --- PLT/GOT ---
+//             case DT_PLTGOT: pltgot = (void*)(iBaseDiff + dt->d_val);        break;
+               case DT_JMPREL: plt = (void*)(iBaseDiff + dt->d_val);   break;
+               case DT_PLTREL: pltType = dt->d_val;    break;
+               case DT_PLTRELSZ:       pltSz = dt->d_val;      break;
+               
+               // --- Relocation ---
+               case DT_REL:    rel = (void*)(iBaseDiff + dt->d_val);   break;
+               case DT_RELSZ:  relSz = dt->d_val;      break;
+               case DT_RELENT: relEntSz = dt->d_val;   break;
+               case DT_RELA:   rela = (void*)(iBaseDiff + dt->d_val);  break;
+               case DT_RELASZ: relaSz = dt->d_val;     break;
+               case DT_RELAENT:        relaEntSz = dt->d_val;  break;
+               
+               // --- Symbol Table ---
+               case DT_SYMTAB:
+               // --- Hash Table ---
+               case DT_HASH:
+               // --- String Table ---
+               case DT_STRTAB:
+                       break;
+               
+               // --- Unknown ---
+               default:
+                       if(dt->d_tag > DT_JMPREL)       continue;
+                       //DEBUGS(" elf_relocate: %i-%i = %s,0x%x",
+                       //      i,j, csaDT_NAMES[dynamicTab[j].d_tag],dynamicTab[j].d_val);
+                       break;
+               }
+       }
+       
+       // Resolve symbols (second pass)
+       // - #0 is defined as ("" SHN_UNDEF), so skip it
+        int    fail = 0;
+       for( int i = 1; i < iSymCount; i ++ )
+       {
+               PREF(Sym)       *sym = &dynsymtab[i];
+               const char *name = dynstrtab + sym->st_name;
+               if( sym->st_shndx == SHN_UNDEF )
+               {
+                       void *newval;
+                       size_t  newsize;
+                       if( !GetSymbol(name, &newval, &newsize, Base) ) {
+                               if( ELF32_ST_BIND(sym->st_info) != STB_WEAK ) {
+                                       // Not a weak binding, set fail and move on
+                                       WARNING("%s: Can't find required symbol '%s' for '%s'", __func__, name, Filename);
+                                       fail = 1;
+                                       continue ;
+                               }
+                               // Leave the symbol value as-is
+                       }
+                       else {
+                               TRACE("Sym %i'%s' bound to %p+0x%x", i, name, newval, newsize);
+                               sym->st_value = (intptr_t)newval;
+                               sym->st_size = newsize;
+                       }
+               }
+               else if( sym->st_shndx == SHN_ABS )
+               {
+                       // Leave as is
+               }
+               else
+               {
+                       // Handled previously
+                       // TODO: What about weak locally-defined symbols?
+                       //assert( ELF32_ST_BIND(sym->st_info) != STB_WEAK );
+               }
+       }
+       if( fail ) {
+               WARNING("Relocation of '%s' failed", Filename);
+               return NULL;
+       }
+       
+       TRACE("Beginning Relocation on '%s'", Filename);
+
+
+       PREF(RelocFcn)* do_relocate = PREF(GetRelocFcn)(hdr->e_machine);
+       if( do_relocate == 0 )
+       {
+               SysDebug("%s: Unknown machine type %i", __func__, hdr->e_machine);
+               do_relocate = PREF(doRelocate_unk);
+               fail = 1;
+       }
+       
+       TRACE("do_relocate = %p", do_relocate);
+
+       #define _doRelocate(r_info, ptr, bRela, addend) \
+               do_relocate(&reloc_info, r_info, ptr, addend, bRela);
+
+       PREF(RelocInfo) reloc_info = {
+               .Base = Base,
+               .iBaseDiff = iBaseDiff,
+               .strtab = dynstrtab,
+               .symtab = dynsymtab
+       };
+
+       // Parse Relocation Entries
+       if(rel && relSz)
+       {
+               TRACE("rel=0x%x, relSz=0x%x, relEntSz=0x%x", rel, relSz, relEntSz);
+               int max = relSz / relEntSz;
+               for( int i = 0; i < max; i++ )
+               {
+                       PREF(Xword) *ptr = (void*)(iBaseDiff + rel[i].r_offset);
+                       fail |= _doRelocate(rel[i].r_info, ptr, 0, *ptr);
+               }
+       }
+       // Parse Relocation Entries
+       if(rela && relaSz)
+       {
+               TRACE("rela=0x%x, relaSz=0x%x, relaEntSz=0x%x", rela, relaSz, relaEntSz);
+               int count = relaSz / relaEntSz;
+               for( int i = 0; i < count; i++ )
+               {
+                       void *ptr = (void*)(iBaseDiff + rela[i].r_offset);
+                       fail |= _doRelocate(rela[i].r_info, ptr, 1, rela[i].r_addend);
+               }
+       }
+       
+       // === Process PLT (Procedure Linkage Table) ===
+       if(plt && pltSz)
+       {
+               TRACE("Relocate PLT, plt=0x%x", plt);
+               if(pltType == DT_REL)
+               {
+                       PREF(Rel)       *pltRel = plt;
+                       int count = pltSz / sizeof(*pltRel);
+                       TRACE("PLT Reloc Type = Rel, %i entries", count);
+                       for(int i = 0; i < count; i ++)
+                       {
+                               PREF(Xword) *ptr = (void*)(iBaseDiff + pltRel[i].r_offset);
+                               fail |= _doRelocate(pltRel[i].r_info, ptr, 0, *ptr);
+                       }
+               }
+               else
+               {
+                       PREF(Rela)      *pltRela = plt;
+                       int count = pltSz / sizeof(*pltRela);
+                       TRACE("PLT Reloc Type = Rela, %i entries", count);
+                       for(int i=0;i<count;i++)
+                       {
+                               void *ptr = (void*)(iBaseDiff + pltRela[i].r_offset);
+                               fail |= _doRelocate(pltRela[i].r_info, ptr, 1, pltRela[i].r_addend);
+                       }
+               }
+       }
+
+       // Re-set readonly
+       for( int i = 0; i < hdr->e_phnum; i ++ )
+       {
+               // If load and not writable
+               if(phtab[i].p_type == PT_LOAD && !(phtab[i].p_flags & PF_W) )
+               {
+                       uintptr_t       addr = phtab[i].p_vaddr + iBaseDiff;
+                       uintptr_t       end = addr + phtab[i].p_memsz;
+                       for( ; addr < end; addr += PAGE_SIZE )
+                               _SysSetMemFlags(addr, 1, 1);    // Unset RO
+               }
+       }
+
+       if( fail ) {
+               TRACE("ElfRelocate: Failure");
+               return NULL;
+       }       
+
+       #undef _doRelocate
+
+       TRACE("RETURN 0x%x to %p", hdr->e_entry + iBaseDiff, __builtin_return_address(0));
+       return (void*)(intptr_t)( hdr->e_entry + iBaseDiff );
+}
+
+void PREF(int_GetBaseDyntab)(void* Base, const PREF(Phdr)* phtab, unsigned phentcount, intptr_t* iBaseDiff_p, PREF(Dyn)** dynamicTab_p)
+{
+       uintptr_t       iRealBase = UINTPTR_MAX;
+       assert(dynamicTab_p);
+       
+       for(unsigned i = 0; i < phentcount; i ++)
+       {
+               switch(phtab[i].p_type)
+               {
+               case PT_LOAD:
+                       // Determine linked base address
+                       if( iRealBase > phtab[i].p_vaddr)
+                               iRealBase = phtab[i].p_vaddr;
+                       break;
+               case PT_DYNAMIC:
+                       // Find Dynamic Section
+                       if(!*dynamicTab_p) {
+                               *dynamicTab_p = (void *) (intptr_t) phtab[i].p_vaddr;
+                       }
+                       else {
+                               WARNING("elf_relocate: Multiple PT_DYNAMIC segments");
+                       }
+                       break;
+               }
+       }
+       
+       // Page Align real base
+       iRealBase &= ~0xFFF;
+       
+       // Adjust "Real" Base
+       const intptr_t  iBaseDiff = (intptr_t)Base - iRealBase;
+       *iBaseDiff_p = iBaseDiff;
+
+       // Adjust Dynamic Table
+       if( *dynamicTab_p )
+       {
+               *dynamicTab_p = (void *)( (intptr_t)*dynamicTab_p + iBaseDiff );
+       }
+
+       TRACE("True Base = 0x%x, Compiled Base = 0x%x, Difference = 0x%x", Base, iRealBase, *iBaseDiff_p);
+}
+
+int PREF(doRelocate_unk)(const PREF(RelocInfo)* Info, PREF(Xword) r_info, PREF(Xword)* ptr, PREF(Addr) addend, bool bRela)
+{
+       return 1;
+}
+
+int PREF(GetSymbolVars)(void *Base, const PREF(Sym)** symtab, const PREF(Word)** pBuckets, const char **dynstrtab, uintptr_t* piBaseDiff)
+{
+       const PREF(Ehdr)*       hdr = Base;
+       PREF(Dyn)*      dynTab = NULL;
+       intptr_t        iBaseDiff = -1;
+       
+       PREF(int_GetBaseDyntab)(Base, (void*)( (uintptr_t)Base + hdr->e_phoff ), hdr->e_phnum, &iBaseDiff, &dynTab);
+       if( !dynTab ) {
+               SysDebug("ERROR - Unable to find DYNAMIC segment in %p", Base);
+               return 1;
+       }
+       
+       for( int i = 0; dynTab[i].d_tag != DT_NULL; i++)
+       {
+               switch(dynTab[i].d_tag)
+               {
+               // --- Symbol Table ---
+               case DT_SYMTAB:
+                       *symtab = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff);       // Rebased in Relocate
+                       break;
+               case DT_STRTAB:
+                       *dynstrtab = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff);
+                       break;
+               // --- Hash Table --
+               case DT_HASH:
+                       *pBuckets = (void*)((intptr_t)dynTab[i].d_val + iBaseDiff);
+                       break;
+               }
+       }
+       
+       if( !*symtab ) {
+               SysDebug("ERRO - No DT_SYMTAB in %p", Base);
+               return 1;
+       }
+       if( !*pBuckets ) {
+               SysDebug("ERRO - No DT_HASH in %p", Base);
+               return 1;
+       }
+       if( !*dynstrtab ) {
+               SysDebug("ERRO - No DT_STRTAB in %p", Base);
+               return 1;
+       }
+
+       // ... ok... maybe they haven't been relocated
+       if( (uintptr_t)*symtab < (uintptr_t)Base )
+       {
+               SysDebug("Executable not yet relocated (symtab,pBuckets,dynstrtab = %p,%p,%p + 0x%x)",
+                       *symtab,*pBuckets,*dynstrtab, iBaseDiff);
+               *symtab    = (void*)( (uintptr_t)*symtab    + iBaseDiff );
+               *pBuckets  = (void*)( (uintptr_t)*pBuckets  + iBaseDiff );
+               *dynstrtab = (void*)( (uintptr_t)*dynstrtab + iBaseDiff );
+       }
+       *piBaseDiff = iBaseDiff;
+       return 0;
+}
+
+int PREF(GetSymbolInfo)(void *Base, const char *Name, void **Addr, size_t *Size, int* Section, int *Binding, int *Type)
+{
+       // Locate the tables
+       uintptr_t       iBaseDiff = -1;
+       const PREF(Sym)*        symtab = NULL;
+       const PREF(Word)*       pBuckets = NULL;
+       const char      *dynstrtab = NULL;
+       if( PREF(GetSymbolVars)(Base, &symtab, &pBuckets, &dynstrtab, &iBaseDiff) )
+               return 1;
+
+       unsigned nbuckets = pBuckets[0];
+//     int iSymCount = pBuckets[1];
+       pBuckets = &pBuckets[2];
+       
+       const PREF(Word)*       pChains = &pBuckets[ nbuckets ];
+       assert(pChains);
+
+       // Get hash
+       unsigned iNameHash = ElfHashString(Name);
+       iNameHash %= nbuckets;
+
+       // Walk Chain
+       unsigned idx = pBuckets[ iNameHash ];
+       do {
+               const PREF(Sym)*        sym = &symtab[idx];
+               assert(sym);
+               if( strcmp(dynstrtab + sym->st_name, Name) == 0 )
+               {
+                       TRACE("*sym = {value:0x%x,size:0x%x,info:0x%x,other:0x%x,shndx:%i}",
+                               sym->st_value, sym->st_size, sym->st_info,
+                               sym->st_other, sym->st_shndx);
+                       if(Addr)        *Addr = (void*)(intptr_t)( sym->st_value );
+                       if(Size)        *Size = sym->st_size;
+                       if(Binding)     *Binding = ELF32_ST_BIND(sym->st_info);
+                       if(Type)        *Type = ELF32_ST_TYPE(sym->st_info);
+                       if(Section)     *Section = sym->st_shndx;
+                       return 0;
+               }
+       } while( (idx = pChains[idx]) != STN_UNDEF && idx != pBuckets[iNameHash] );
+       
+       TRACE("No symbol");
+       return 1;
+}
+
+int PREF(GetSymbol)(void *Base, const char *Name, void **ret, size_t *Size)
+{
+        int    section, binding;
+       TRACE("%s(%p,%s,...)", __func__, Base, Name);
+       if( PREF(GetSymbolInfo)(Base, Name, ret, Size, &section, &binding, NULL) )
+               return 0;
+       if( section == SHN_UNDEF ) {
+               TRACE("%s: Undefined %p", __func__, *ret, (Size?*Size:0), section);
+               return 0;
+       }
+       if( binding == STB_WEAK ) {
+               TRACE("%s: Weak, return %p+0x%x,section=%i", __func__, *ret, (Size?*Size:0), section);
+               return 2;
+       }
+       TRACE("%s: Found %p+0x%x,section=%i", __func__, *ret, (Size?*Size:0), section);
+       return 1;
+}
index 10c5c5c..e40dd8e 100644 (file)
@@ -11,6 +11,7 @@ extern int32_t        __modsi3(int32_t Num, int32_t Den);
 extern uint32_t        __udivsi3(uint32_t Num, uint32_t Den);
 extern uint32_t        __umodsi3(uint32_t Num, uint32_t Den);
 extern void    ldacess_DumpLoadedLibraries(void);
+extern void    _ZN4_sys5debugEPKcz(const char *,...);  // C++ "_sys::debug" used by STL debug
 
 #define _STR(x)        #x
 #define STR(x) _STR(x)
index 9da4e43..b3d78bf 100644 (file)
@@ -24,6 +24,7 @@
 #define _SysUnloadBin  acess__SysUnloadBin
 #define _SysSetFaultHandler    acess__SysSetFaultHandler
 #define _SysDebug      acess__SysDebug
+#define _SysDebugHex   acess__SysDebugHex
 #define _SysGetPhys    acess__SysGetPhys
 #define _SysAllocate   acess__SysAllocate
 #define _SysSetMemFlags        acess__SysSetMemFlags
@@ -34,6 +35,7 @@
 #define _SysFDFlags    acess__SysFDFlags
 #define _SysClose      acess__SysClose
 #define _SysRead       acess__SysRead
+#define _SysTruncate   acess__SysTruncate
 #define _SysWrite      acess__SysWrite
 #define _SysSeek       acess__SysSeek
 #define _SysTell       acess__SysTell
@@ -46,5 +48,9 @@
 #define _SysSelect     acess__SysSelect
 #define _SysMkDir      acess__SysMkDir
 #define _SysUnlink     acess__SysUnlink
+#define _SysMMap       acess__SysMMap
+#define _SysMUnMap     acess__SysMUnMap
+#define _SysMarshalFD  acess__SysMarshalFD
+#define _SysUnMarshalFD        acess__SysUnMarshalFD
 
 #define _errno acess__errno
diff --git a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/devices/joystick.h b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/devices/joystick.h
new file mode 100644 (file)
index 0000000..e5d670f
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Acess2 System Calls
+ * - By John Hodge (thePowersGang)
+ *
+ * acess/devices/joystick.h
+ * - Joystick IOCtls and structures
+ */
+#ifndef _SYS_DEVICES_JOYSTICK_H
+#define _SYS_DEVICES_JOYSTICK_H
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+struct mouse_attribute
+{
+       uint32_t        Num;
+       uint32_t        Value;
+};
+
+struct mouse_header
+{
+       uint16_t        NAxies;
+       uint16_t        NButtons;
+};
+
+struct mouse_axis
+{
+        int16_t        MinValue;
+        int16_t        MaxValue;
+        int16_t        CurValue;
+       uint16_t        CursorPos;
+};
+
+enum {
+       JOY_IOCTL_GETSETAXISLIMIT = 6,
+       JOY_IOCTL_GETSETAXISPOSITION,
+};
+
+#if __cplusplus
+}
+#endif
+
+#endif
+
index 2ec0cd0..fde5d83 100644 (file)
@@ -25,6 +25,7 @@ enum
 struct ptycmd_header
 {
        uint8_t         cmd;
+       // NOTE: Length is encoded as a count of 32-bit words
        uint8_t         len_low;
        uint16_t        len_hi;
 } PACKED;
@@ -44,5 +45,11 @@ struct ptycmd_setcursorbmp
        char    data[];
 } PACKED;
 
+struct ptycmd_senddata
+{
+       struct ptycmd_header    hdr;
+       uint32_t        ofs;
+} PACKED;
+
 #endif
 
index d32f8c3..4e0f145 100644 (file)
@@ -40,6 +40,14 @@ extern "C" {
 #define FILEFLAG_SYMLINK       0x20
 #define CLONE_VM       0x10
 
+#define MMAP_PROT_READ 0x001   //!< Readable memory
+#define MMAP_PROT_WRITE        0x002   //!< Writable memory
+#define MMAP_PROT_EXEC 0x004   //!< Executable memory
+#define MMAP_MAP_SHARED        0x001   //!< Shared with all other users of the FD
+#define MMAP_MAP_PRIVATE       0x002   //!< Local (COW) copy
+#define MMAP_MAP_FIXED         0x004   //!< Load to a fixed address
+#define MMAP_MAP_ANONYMOUS     0x008   //!< Not associated with a FD
+
 #ifdef ARCHDIR_is_native
 # include "_native_syscallmod.h"
 #endif
@@ -51,6 +59,7 @@ extern int    _errno;
 
 // === FUNCTIONS ===
 extern void    _SysDebug(const char *format, ...);
+extern void    _SysDebugHex(const char *Label, const void *Data, size_t Size);
 // --- Proc ---
 extern void    _exit(int status)       __attribute__((noreturn));
 extern int     _SysKill(int pid, int sig);
@@ -88,9 +97,12 @@ extern int   _SysReopen(int fd, const char *path, int flags);
 extern int     _SysCopyFD(int srcfd, int dstfd);
 extern int     _SysFDFlags(int fd, int mask, int newflags);
 extern size_t  _SysRead(int fd, void *buffer, size_t length);
+extern size_t  _SysReadAt(int fd, uint64_t offset, size_t length, void *buffer);
+extern uint64_t        _SysTruncate(int fd, uint64_t size);
 extern int     _SysClose(int fd);
 extern int     _SysFDCtl(int fd, int option, ...);
 extern size_t  _SysWrite(int fd, const void *buffer, size_t length);
+extern size_t  _SysWriteAt(int fd, uint64_t offset, size_t length, const void *buffer);
 extern int     _SysSeek(int fd, int64_t offset, int whence);
 extern uint64_t        _SysTell(int fd);
 extern int     _SysIOCtl(int fd, int id, void *data);
@@ -102,6 +114,16 @@ extern int _SysSelect(int nfds, fd_set *read, fd_set *write, fd_set *err, int64_
 //#define select(nfs, rdfds, wrfds, erfds, timeout)    _SysSelect(nfs, rdfds, wrfds, erfds, timeout, 0)
 extern int     _SysMkDir(const char *dirname);
 extern int     _SysUnlink(const char *pathname);
+extern void*   _SysMMap(void *addr, size_t length, unsigned int _flags, int fd, uint64_t offset);
+#ifdef _SysMMap
+# undef _SysMMap
+# define _SysMMap(addr,length,flags,prot,fd,offset)    acess__SysMMap(addr,length,(flags|(prot<<16)), fd, offset)
+#else
+# define _SysMMap(addr,length,flags,prot,fd,offset)    _SysMMap(addr,length,(flags|(prot<<16)), fd, offset)
+#endif
+extern int     _SysMUnMap(void *addr, size_t length);
+extern uint64_t        _SysMarshalFD(int FD);
+extern int     _SysUnMarshalFD(uint64_t Handle);
 
 // --- IPC ---
 extern int     _SysSendMessage(int dest, size_t length, const void *Data);
index 88aafc3..31dcbd8 100644 (file)
@@ -4,6 +4,7 @@
 */
 #include "common.h"
 #include <stdint.h>
+#include <stdbool.h>
 #include <acess/sys.h>
 
 #define DEBUG  0
@@ -14,8 +15,7 @@
 # define DEBUGS(v...)  
 #endif
 
-// === PROTOTYPES ===
-void   *IsFileLoaded(const char *file);
+#define MAX_QUEUED_ENTRYPOINTS 8
 
 // === IMPORTS ===
 extern const struct {
@@ -26,10 +26,21 @@ extern const int    ciNumLocalExports;
 extern char    **gEnvP;
 extern char    gLinkedBase[];
 
+// === TYPES ===
+typedef void   tLibEntry(void *, int, char *[], char**);
+
+// === PROTOTYPES ===
+void   *IsFileLoaded(const char *file);
+
 // === GLOABLS ===
 tLoadedLib     gLoadedLibraries[MAX_LOADED_LIBRARIES];
 char   gsLoadedStrings[MAX_STRINGS_BYTES];
 char   *gsNextAvailString = gsLoadedStrings;
+struct sQueuedEntry {
+       void    *Base;
+       tLibEntry       *Entry;
+}      gaQueuedEntrypoints[MAX_QUEUED_ENTRYPOINTS];
+ int   giNumQueuedEntrypoints;
 //tLoadLib     *gpLoadedLibraries = NULL;
 
 // === CODE ===
@@ -45,6 +56,20 @@ void ldacess_DumpLoadedLibraries(void)
        }
 }
 
+/**
+ * \brief Call queued up entry points (after relocations completed) 
+ */
+void CallQueuedEntrypoints(char **EnvP)
+{
+       while( giNumQueuedEntrypoints )
+       {
+               giNumQueuedEntrypoints --;
+               const struct sQueuedEntry       *qe = &gaQueuedEntrypoints[giNumQueuedEntrypoints];
+               DEBUGS("Calling EP %p for %p", qe->Entry, qe->Base);
+               qe->Entry(qe->Base, 0, NULL, EnvP);
+       }
+}
+
 const char *FindLibrary(char *DestBuf, const char *SoName, const char *ExtraSearchDir)
 {      
        // -- #1: Executable Specified
@@ -72,14 +97,12 @@ const char *FindLibrary(char *DestBuf, const char *SoName, const char *ExtraSear
 void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp)
 {
        char    sTmpName[1024];
-       const char      *filename;
        void    *base;
-       void    (*fEntry)(void *, int, char *[], char**);
        
        DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=%p)", SoName, SearchDir, envp);
        
        // Create Temp Name
-       filename = FindLibrary(sTmpName, SoName, SearchDir);
+       const char *filename = FindLibrary(sTmpName, SoName, SearchDir);
        if(filename == NULL) {
                DEBUGS("LoadLibrary: RETURN 0");
                return 0;
@@ -91,6 +114,7 @@ void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp)
 
        DEBUGS(" LoadLibrary: SysLoadBin()");   
        // Load Library
+       tLibEntry       *fEntry;
        base = _SysLoadBin(filename, (void**)&fEntry);
        if(!base) {
                DEBUGS("LoadLibrary: RETURN 0");
@@ -106,10 +130,17 @@ void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp)
        }
        
        // Call Entrypoint
-       DEBUGS(" LoadLibrary: '%s' Entry %p", SoName, fEntry);
-       fEntry(base, 0, NULL, gEnvP);
+       // - TODO: Queue entrypoint calls
+       if( giNumQueuedEntrypoints >= MAX_QUEUED_ENTRYPOINTS ) {
+               SysDebug("ERROR - Maximum number of queued entrypoints exceeded on %p '%s'",
+                       base, SoName);
+               return 0;
+       }
+       gaQueuedEntrypoints[giNumQueuedEntrypoints].Base  = base;
+       gaQueuedEntrypoints[giNumQueuedEntrypoints].Entry = fEntry;
+       giNumQueuedEntrypoints ++;
        
-       DEBUGS("LoadLibrary: RETURN 1");
+       DEBUGS("LoadLibrary: RETURN success");
        return base;
 }
 
@@ -223,34 +254,50 @@ void Unload(void *Base)
  \fn Uint GetSymbol(const char *name)
  \brief Gets a symbol value from a loaded library
 */
-int GetSymbol(const char *name, void **Value, size_t *Size)
+int GetSymbol(const char *name, void **Value, size_t *Size, void *IgnoreBase)
 {
-        int    i;
-       
-       //SysDebug("ciNumLocalExports = %i", ciNumLocalExports);
-       for(i=0;i<ciNumLocalExports;i++)
+       //SysDebug("GetSymbol: (%s)");
+       for( int i = 0; i < ciNumLocalExports; i ++ )
        {
                if( strcmp(caLocalExports[i].Name, name) == 0 ) {
                        *Value = caLocalExports[i].Value;
                        if(Size)
                                *Size = 0;
+                       //SysDebug("GetSymbol: Local %p+0x%x", *Value, 0);
                        return 1;
                }
        }
-       
-       // Entry 0 is ld-acess, ignore it
-       for(i = 0; i < MAX_LOADED_LIBRARIES; i ++)
+
+       bool have_weak = false; 
+       for(int i = 0; i < MAX_LOADED_LIBRARIES && gLoadedLibraries[i].Base != 0; i ++)
        {
-               if(gLoadedLibraries[i].Base == 0)
-                       break;
+               // Allow ignoring the current module
+               if( gLoadedLibraries[i].Base == IgnoreBase ) {
+                       //SysDebug("GetSymbol: Ignore %p", gLoadedLibraries[i].Base);
+                       continue ;
+               }
                
                //SysDebug(" GetSymbol: Trying 0x%x, '%s'",
                //      gLoadedLibraries[i].Base, gLoadedLibraries[i].Name);
-               if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, Value, Size))
-                       return 1;
+               void    *tmpval;
+               size_t  tmpsize;
+               int rv = GetSymbolFromBase(gLoadedLibraries[i].Base, name, &tmpval, &tmpsize);
+               if(rv)
+               {
+                       *Value = tmpval;
+                       *Size = tmpsize;
+                       if( rv == 1 ) {
+                               return 1;
+                       }
+                       have_weak = true;
+               }
+       }
+       if(have_weak) {
+               return 2;
+       }
+       else {
+               return 0;
        }
-       SysDebug("GetSymbol: === Symbol '%s' not found ===", name);
-       return 0;
 }
 
 /**
index 40c603e..976ceec 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdint.h>\r
 #include <stddef.h>\r
 #include "common.h"\r
+#undef SoMain\r
 \r
 // === PROTOTYPES ===\r
 void   *DoRelocate(void *base, char **envp, const char *Filename);\r
@@ -14,6 +15,7 @@ void  *DoRelocate(void *base, char **envp, const char *Filename);
 extern char    gLinkedBase[];\r
 char   **gEnvP;\r
 extern int     memcmp(const void *m1, const void *m2, size_t size);\r
+extern void    CallQueuedEntrypoints(char **EnvP);\r
  \r
 // === CODE ===\r
 /**\r
@@ -41,7 +43,6 @@ void *SoMain(void *base, int argc, char **argv, char **envp)
        }\r
 \r
        // Otherwise do relocations\r
-       //ret = DoRelocate( base, envp, "Executable" );\r
        ret = DoRelocate( base, NULL, "Executable" );\r
        if( ret == 0 ) {\r
                SysDebug("ld-acess - SoMain: Relocate failed, base=0x%x\n", base);\r
@@ -49,7 +50,10 @@ void *SoMain(void *base, int argc, char **argv, char **envp)
                for(;;);\r
        }\r
 \r
-       SysDebug("ld-acess - SoMain: ret = %p", ret);   \r
+       // Call queued entry points (from libraries)\r
+       CallQueuedEntrypoints(envp);\r
+\r
+       SysDebug("ld-acess - SoMain: Program entry %p", ret);   \r
        return ret;\r
 }\r
 \r
diff --git a/Usermode/Libraries/libaxwin4.so_src/Makefile b/Usermode/Libraries/libaxwin4.so_src/Makefile
new file mode 100644 (file)
index 0000000..c530c55
--- /dev/null
@@ -0,0 +1,29 @@
+# Acess2 AxWin4 Library
+# Makefile
+
+-include ../Makefile.cfg
+
+AXWIN4DIR := ../../Applications/axwin4_src/
+
+CPPFLAGS += -I$(AXWIN4DIR)Common/include/
+CFLAGS   += -Wextra
+CXXFLAGS +=
+ASFLAGS  +=
+LDFLAGS  += -soname libaxwin4.so -Map map.txt
+LIBS  += -lc -lc++
+
+OBJ  = main.o ipc.o ipc_acessipcpipe.o
+OBJ += wm.o window_drawing.o
+OBJ += Common__serialisation.o
+BIN = libaxwin4.so
+
+include ../Makefile.tpl
+
+$(_OBJPREFIX)Common__%.o: $(AXWIN4DIR)/Common/%.cpp
+       @echo [CXX] -o $@
+       @mkdir -p $(dir $@)
+       $V$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@ -MQ $@ -MP -MD -MF $(@:%=%.dep)
+
+
+
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/include/CIPCChannel_AcessIPCPipe.hpp b/Usermode/Libraries/libaxwin4.so_src/include/CIPCChannel_AcessIPCPipe.hpp
new file mode 100644 (file)
index 0000000..d04d052
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Acess2 GUIv4 Library
+ * - By John Hodge (thePowersGang)
+ *
+ * CIPCChannel_AcessIPCPipe.h
+ * - Acess IPC Datagram pipe
+ */
+#ifndef _LIBAXWIN4_CIPCCHANNEL_ACESSIPCPIPE_H_
+#define _LIBAXWIN4_CIPCCHANNEL_ACESSIPCPIPE_H_
+
+#include "IIPCChannel.hpp"
+
+namespace AxWin {
+
+class CIPCChannel_AcessIPCPipe:
+       public IIPCChannel
+{
+        int    m_fd;
+public:
+       CIPCChannel_AcessIPCPipe(const char *Path);
+       virtual ~CIPCChannel_AcessIPCPipe();
+       virtual int     FillSelect(fd_set& fds);
+       virtual bool    HandleSelect(const fd_set& fds);
+       virtual void    Send(CSerialiser& message);
+};
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/include/IIPCChannel.hpp b/Usermode/Libraries/libaxwin4.so_src/include/IIPCChannel.hpp
new file mode 100644 (file)
index 0000000..c4a514f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Acess2 GUIv4 Library
+ * - By John Hodge (thePowersGang)
+ *
+ * IIPCChannel.h
+ * - IPC Channel interface
+ */
+#ifndef _LIBAXWIN4_IIPCCHANNEL_H_
+#define _LIBAXWIN4_IIPCCHANNEL_H_
+
+#include <serialisation.hpp>
+
+#include <acess/sys.h>
+
+namespace AxWin {
+
+class IIPCChannel
+{
+public:
+       virtual ~IIPCChannel();
+       virtual int     FillSelect(fd_set& fds) = 0;
+       /**
+        * \return False if the connection has dropped/errored
+        */
+       virtual bool    HandleSelect(const fd_set& fds) = 0;
+       
+       virtual void    Send(CSerialiser& message) = 0;
+};
+
+};     // namespace AxWin
+
+#endif
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/include/common.hpp b/Usermode/Libraries/libaxwin4.so_src/include/common.hpp
new file mode 100644 (file)
index 0000000..e3aa807
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Acess2 GUIv4 Library
+ * - By John Hodge (thePowersGang)
+ *
+ * common.h
+ * - Library internal header
+ */
+#ifndef _LIBAXWIN4_COMMON_H_
+#define _LIBAXWIN4_COMMON_H_
+
+#include <serialisation.hpp>
+
+namespace AxWin {
+
+extern void    SendMessage(CSerialiser& message);
+extern void    RecvMessage(CDeserialiser& message);
+extern CDeserialiser   GetSyncReply(CSerialiser& request, unsigned int Message);
+
+};
+
+struct sAxWin4_Window
+{
+       unsigned int    m_id;
+        int    m_fd;
+       void    *m_buffer;
+};
+
+#endif
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/include_exp/axwin4/axwin.h b/Usermode/Libraries/libaxwin4.so_src/include_exp/axwin4/axwin.h
new file mode 100644 (file)
index 0000000..255b0e1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Acess2 GUIv4 (AxWin4)
+ * - By John Hodge (thePowersGang)
+ *
+ * axwin4/axwin.h
+ * - Client library interface header
+ */
+#ifndef _LIBAXWIN4_AXWIN4_AXWIN_H_
+#define _LIBAXWIN4_AXWIN4_AXWIN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <acess/sys.h>
+
+typedef struct sAxWin4_Window  tAxWin4_Window;
+
+// - Abstractions of core IPC methods
+extern bool    AxWin4_Connect(const char *URI);
+
+extern bool    AxWin4_WaitEventQueue(uint64_t Timeout);        
+extern bool    AxWin4_WaitEventQueueSelect(int nFDs, fd_set *rfds, fd_set *wfds, fd_set *efds, uint64_t Timeout);
+
+extern void    AxWin4_GetScreenDimensions(unsigned int ScreenIndex, unsigned int *Width, unsigned int *Height);
+
+extern tAxWin4_Window  *AxWin4_CreateWindow(const char *Name);
+extern void    AxWin4_DestroyWindow(tAxWin4_Window *Window);
+
+// Callbacks
+typedef int tAxWin4_KeyCallback(tAxWin4_Window* Winow, unsigned int Key, const char *Translated);
+extern void    AxWin4_SetCallback_Key(tAxWin4_Window* Window, tAxWin4_KeyCallback* cb);
+typedef int tAxWin4_MouseBtnCallback(tAxWin4_Window* Winow, unsigned int Mouse, unsigned int X, unsigned int Y, unsigned int Button, bool IsPress);
+extern void    AxWin4_SetCallback_MouseBtn(tAxWin4_Window* Window, tAxWin4_MouseBtnCallback* cb);
+typedef int tAxWin4_MouseMoveCallback(tAxWin4_Window* Winow, unsigned int Mouse, unsigned int X, unsigned int Y);
+
+extern void    AxWin4_ShowWindow(tAxWin4_Window *Window, bool Shown);
+extern void    AxWin4_SetWindowFlags(tAxWin4_Window *Window, unsigned int NewFlags);
+extern void    AxWin4_SetTitle(tAxWin4_Window *Window, const char *Title);
+extern void    AxWin4_MoveWindow(tAxWin4_Window *Window, int X, int Y);
+extern void    AxWin4_ResizeWindow(tAxWin4_Window *Window, unsigned int W, unsigned int H);
+
+extern void    AxWin4_DamageRect(tAxWin4_Window *Window, unsigned int X, unsigned int Y, unsigned int W, unsigned int H);
+extern void*   AxWin4_GetWindowBuffer(tAxWin4_Window *Window);
+
+/**
+ * \brief Set the render clipping region. Any attempts to render outside this area will silently fail
+ * \param Window       Target window
+ *
+ * \note Allows clipping other render functions to avoid excessive redraws
+ * \note Cleared when \a AxWin4_DamageRect is called, or when called with a zero width or height
+ */
+extern void    AxWin4_SetRenderClip(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H);
+
+/**
+ * \brief Draw a user-supplied bitmap to the window
+ * \param Data Bitmap data in the same format as the window's back buffer
+ * \note VERY SLOW
+ */
+extern void    AxWin4_DrawBitmap(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, void *Data);
+/**
+ * \brief Draw a "control" to the window
+ * \param Window       Target window
+ * \param X    Destination X
+ * \param Y    Destination Y
+ * \param W    Control width
+ * \param H    Control height
+ * \param ControlID    Specifies which control to use. Can be a global or application-registered (See eAxWin4_GlobalControls)
+ * \param Frame        Control frame number. Used to specify a variant of the control (e.g. hovered/pressed)
+ *
+ * Controls are server-side bitmaps that can be arbitarily scaled to fit a region.
+ */
+extern void    AxWin4_DrawControl(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, uint16_t ControlID, unsigned int Frame);
+
+extern void    AxWin4_FillRect(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, uint32_t Colour);
+
+extern void    AxWin4_DrawText(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, uint16_t FontID, const char *String);
+
+#include "definitions.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/include_exp/axwin4/definitions.h b/Usermode/Libraries/libaxwin4.so_src/include_exp/axwin4/definitions.h
new file mode 100644 (file)
index 0000000..5fe7e4d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Acess2 GUIv4 (AxWin4)
+ * - By John Hodge (thePowersGang)
+ *
+ * axwin4/definitions.h
+ * - Shared definitions (Client and server)
+ */
+#ifndef _LIBAXWIN4_AXWIN4_DEFINITIONS_H_
+#define _LIBAXWIN4_AXWIN4_DEFINITIONS_H_
+
+/**
+ * \name Window Flags
+ * \{
+ */
+#define AXWIN4_WNDFLAG_NODECORATE      0x01    //!< Disable automatic inclusion of window decorations
+#define AXWIN4_WNDFLAG_KEEPBELOW       0x02    //!< Keep the window below all others, even when it has focus
+#define AXWIN4_WNDFLAG_KEEPABOVE       0x04    //!< Keep window above all others, ecen when it loses focus
+/**
+ * \}
+ */
+
+/**
+ * \brief Global controls
+ */
+enum eAxWin4_GlobalControls {
+       AXWIN4_CTL_BUTTON,      //!< Standard button (possibly rounded edges)
+       AXWIN4_CTL_BOX,         //!< Grouping box in a window
+       AXWIN4_CTL_TOOLBAR,     //!< Toolbar (raised region)
+       AXWIN4_CTL_TEXTBOX,     //!< Text edit box
+};
+
+enum eAxWin4_GlobalFonts {
+       AXWIN4_FONT_DEFAULT,    //!< Default font (usually a sans-serif)
+       AXWIN4_FONT_MONOSPACE,  //!< Default monospace font
+};
+
+#endif
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/ipc.cpp b/Usermode/Libraries/libaxwin4.so_src/ipc.cpp
new file mode 100644 (file)
index 0000000..d0455f5
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * AxWin4 Interface Library
+ * - By John Hodge (thePowersGang)
+ *
+ * ipc.c
+ * - IPC Abstraction
+ */
+#include <axwin4/axwin.h>
+#include "include/common.hpp"
+#include "include/IIPCChannel.hpp"
+#include "include/CIPCChannel_AcessIPCPipe.hpp"
+#include <ipc_proto.hpp>
+#include <algorithm>
+#include <mutex>
+#include <stdexcept>
+
+#include <cstring>
+#include <cstdio>
+
+namespace AxWin {
+
+IIPCChannel*   gIPCChannel;
+::std::mutex   glSyncReply;
+bool   gSyncReplyActive;
+bool   gSyncReplyValid;
+CDeserialiser  gSyncReplyBuf;
+
+extern "C" bool AxWin4_Connect(const char *URI)
+{
+       _SysDebug("AxWin4_Connect('%s')", URI);
+       if( gIPCChannel ) {
+               return false;
+       }
+       try {
+               if( strncmp(URI, "ipcpipe://", 3+4+3) == 0 )
+               {
+                       gIPCChannel = new CIPCChannel_AcessIPCPipe(URI+3+4+3);
+               }
+               else
+               {
+                       _SysDebug("Unknown protocol");
+                       return false;
+               }
+       }
+       catch( const ::std::exception& e )
+       {
+               fprintf(stderr, "AxWin4_Connect: %s\n", e.what());
+               return false;
+       }
+       return true;
+}
+
+extern "C" bool AxWin4_PeekEventQueue(void)
+{
+       return false;
+}
+
+extern "C" bool AxWin4_WaitEventQueue(uint64_t Timeout)
+{
+       return AxWin4_WaitEventQueueSelect(0, NULL, NULL, NULL, Timeout);
+}
+
+extern "C" bool AxWin4_WaitEventQueueSelect(int nFDs, fd_set *rfds, fd_set *wfds, fd_set *efds, uint64_t Timeout)
+{
+       fd_set  local_rfds;
+       if( !rfds ) {
+               FD_ZERO(&local_rfds);
+               rfds = &local_rfds;
+       }
+       
+       int64_t select_timeout = Timeout;
+       int64_t *select_timeout_p = (Timeout ? &select_timeout : 0);
+       
+       nFDs = ::std::max(nFDs, gIPCChannel->FillSelect(*rfds));
+       _SysSelect(nFDs, rfds, wfds, efds, select_timeout_p, 0);
+       return gIPCChannel->HandleSelect(*rfds);
+}
+
+void SendMessage(CSerialiser& message)
+{
+       gIPCChannel->Send(message);
+}
+void RecvMessage(CDeserialiser& message)
+{
+       uint8_t id = message.ReadU8();
+       _SysDebug("RecvMessage: id=%i", id);
+       switch(id)
+       {
+       case IPCMSG_PING:
+               // If we hear ping, we must pong
+               {
+               CSerialiser     pong;
+               pong.WriteU8(IPCMSG_REPLY);
+               pong.WriteU8(IPCMSG_PING);
+               SendMessage(pong);
+               }
+               break;
+       case IPCMSG_REPLY:
+               // Flag reply and take a copy of this message
+               if( !gSyncReplyActive )
+               {
+                       _SysDebug("Unexpected reply message %i", message.ReadU8());
+               }
+               else if( gSyncReplyValid )
+               {
+                       // Oh... that was unexpected
+                       _SysDebug("Unexpected second reply message %i", message.ReadU8());
+               }
+               else
+               {
+                       gSyncReplyValid = true;
+                       gSyncReplyBuf = message;
+               }
+               break;
+       // TODO: Handle messages from server (input events, IPC)
+       // TODO: If an event is currently being processed, save the message in a queue to be handled when processing is complete
+       // - This will prevent deep recursion (and make server errors aparent)
+       case IPCMSG_INPUTEVENT:
+               _SysDebug("TODO: Input events");
+               break;
+       default:
+               _SysDebug("TODO: RecvMessage(%i)", id);
+               break;
+       }
+}
+
+CDeserialiser GetSyncReply(CSerialiser& request, unsigned int Message)
+{
+       ::std::lock_guard<std::mutex>   lock(glSyncReply);
+       gSyncReplyActive = true;
+       gSyncReplyValid = false;
+       // Send once lock is acquired
+       SendMessage(request);
+       
+       while( !gSyncReplyValid )
+       {
+               // Tick along
+               if( !AxWin4_WaitEventQueue(0) )
+                       throw ::std::runtime_error("Connection dropped while waiting for reply");
+       }
+       gSyncReplyActive = false;
+       
+       uint8_t id = gSyncReplyBuf.ReadU8();
+       if( id != Message )
+       {
+               _SysDebug("Unexpected reply message id=%i, expected %i",
+                       id, Message);
+               throw ::std::runtime_error("Sequencing error, unexpected reply");
+       }
+       
+       // Use move to avoid copying
+       return ::std::move(gSyncReplyBuf);
+}
+
+extern "C" void AxWin4_GetScreenDimensions(unsigned int ScreenIndex, unsigned int *Width, unsigned int *Height)
+{
+       CSerialiser     req;
+       req.WriteU8(IPCMSG_GETGLOBAL);
+       req.WriteU16(IPC_GLOBATTR_SCREENDIMS);
+       req.WriteU8(ScreenIndex);
+       
+       CDeserialiser   response = GetSyncReply(req, IPCMSG_GETGLOBAL);
+       if( response.ReadU16() != IPC_GLOBATTR_SCREENDIMS ) {
+               
+       }
+       
+       *Width = response.ReadU16();
+       *Height = response.ReadU16();
+       
+       _SysDebug("AxWin4_GetScreenDimensions: %i = %ix%i", ScreenIndex, *Width, *Height);
+}
+
+IIPCChannel::~IIPCChannel()
+{
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/ipc_acessipcpipe.cpp b/Usermode/Libraries/libaxwin4.so_src/ipc_acessipcpipe.cpp
new file mode 100644 (file)
index 0000000..87cc6c9
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * AxWin4 Interface Library
+ * - By John Hodge (thePowersGang)
+ *
+ * ipc_acessipcpipe.c
+ * - Acess2 /Devices/ipcpipe/ IPC Channel
+ */
+#include "include/common.hpp"
+#include "include/CIPCChannel_AcessIPCPipe.hpp"
+#include <system_error>
+#include <cerrno>
+
+namespace AxWin {
+
+CIPCChannel_AcessIPCPipe::CIPCChannel_AcessIPCPipe(const char *Path)
+{
+       m_fd = _SysOpen(Path, OPENFLAG_READ|OPENFLAG_WRITE);
+       if( m_fd == -1 ) {
+               throw ::std::system_error(errno, ::std::system_category());
+       }
+}
+
+CIPCChannel_AcessIPCPipe::~CIPCChannel_AcessIPCPipe()
+{
+}
+
+int CIPCChannel_AcessIPCPipe::FillSelect(fd_set& fds)
+{
+       FD_SET(m_fd, &fds);
+       return m_fd+1;
+}
+
+bool CIPCChannel_AcessIPCPipe::HandleSelect(const fd_set& fds)
+{
+       if( FD_ISSET(m_fd, &fds) )
+       {
+               ::std::vector<uint8_t>  rxbuf(4096);
+               size_t len = _SysRead(m_fd, rxbuf.data(), rxbuf.capacity());
+               if( len == (size_t)-1 )
+                       throw ::std::system_error(errno, ::std::system_category());
+               rxbuf.resize(len);
+               _SysDebug("CClient_AcessIPCPipe::HandleReceive - Rx %i/%i bytes", len, rxbuf.capacity());
+               //_SysDebugHex("CClient_AcessIPCPipe::HandleReceive", rxbuf.data(), len);
+               
+               CDeserialiser   msg(rxbuf);
+               ::AxWin::RecvMessage( msg );
+       }
+       return true;
+}
+
+void CIPCChannel_AcessIPCPipe::Send(CSerialiser& message)
+{
+       const ::std::vector<uint8_t>& serialised = message.Compact();
+       if(serialised.size() > 0x1000 ) {
+               throw ::std::length_error("CIPCChannel_AcessIPCPipe::Send");
+       }
+       _SysDebug("CIPCChannel_AcessIPCPipe::Send(%i bytes)", serialised.size());
+       //_SysDebugHex("CIPCChannel_AcessIPCPipe::Send",     serialised.data(), serialised.size());
+       
+       size_t rv = _SysWrite(m_fd, serialised.data(), serialised.size());
+       if( rv != serialised.size() ) {
+               throw ::std::system_error(errno, ::std::system_category());
+       }
+}
+
+
+};     // namespace AxWin
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/main.c b/Usermode/Libraries/libaxwin4.so_src/main.c
new file mode 100644 (file)
index 0000000..5d55582
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ */
+// === CODE ===
+int SoMain(void)
+{
+       return 0;
+}
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp b/Usermode/Libraries/libaxwin4.so_src/window_drawing.cpp
new file mode 100644 (file)
index 0000000..e6a4448
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * AxWin4 Interface Library
+ * - By John Hodge (thePowersGang)
+ *
+ * window_drawing.cpp
+ * - Window drawing code
+ */
+#include <axwin4/axwin.h>
+#include "include/common.hpp"
+#include <ipc_proto.hpp>
+#include <algorithm>   // min
+
+namespace AxWin {
+
+void _push_data(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, const void *Data)
+{
+       CSerialiser     message;
+       //_SysDebug("_push_data - (%i,%i), %ix%i %p", X, Y, W, H, Data);
+       message.WriteU8(IPCMSG_PUSHDATA);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(X);
+       message.WriteU16(Y);
+       message.WriteU16(W);
+       message.WriteU16(H);
+       message.WriteBuffer(H*W*4, Data);
+       ::AxWin::SendMessage(message);
+}
+
+extern "C" void AxWin4_DrawBitmap(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, void *Data)
+{
+       // TODO: Split message up into blocks such that it can be dispatched
+       if( W > 128 )
+       {
+               const uint32_t* data32 = static_cast<uint32_t*>(Data);
+               const unsigned int rows_per_message = 1;        // 2048 / W;
+               for( unsigned int row = 0; row < H; row += rows_per_message )
+               {
+                       _push_data(Window, X, Y+row, W, ::std::min(rows_per_message,H-row), data32);
+                       data32 += W*rows_per_message;
+               }
+       }
+       else
+       {
+               _push_data(Window, X, Y, W, H, Data);
+       }
+}
+
+extern "C" void AxWin4_DrawControl(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, uint16_t ID, unsigned int Frame)
+{
+       CSerialiser     message;
+       //_SysDebug("AxWin4_DrawControl: (Window->ID=%i, (%i,%i) %ix%i %i 0x%06x", Window->m_id, X, Y, W, H, ID, Frame);
+       message.WriteU8(IPCMSG_DRAWCTL);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(X);
+       message.WriteU16(Y);
+       message.WriteU16(W);
+       message.WriteU16(H);
+       message.WriteU16(ID);
+       message.WriteU16(Frame);
+       ::AxWin::SendMessage(message);
+}
+
+extern "C" void AxWin4_FillRect(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, uint32_t Colour)
+{      
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_FILLRECT);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(X);
+       message.WriteU16(Y);
+       message.WriteU16(W);
+       message.WriteU16(H);
+       message.WriteU32(Colour);
+       ::AxWin::SendMessage(message);
+}
+
+extern "C" void AxWin4_DrawText(tAxWin4_Window *Window, int X, int Y, unsigned int W, unsigned int H, uint16_t FontID, const char *String)
+{
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_DRAWTEXT);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(X);
+       message.WriteU16(Y);
+       message.WriteU16(W);
+       message.WriteU16(H);
+       message.WriteU16(FontID);
+       message.WriteString(String);
+       ::AxWin::SendMessage(message);
+}
+
+};     // namespace AxWin
+
diff --git a/Usermode/Libraries/libaxwin4.so_src/wm.cpp b/Usermode/Libraries/libaxwin4.so_src/wm.cpp
new file mode 100644 (file)
index 0000000..cae79c7
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * AxWin4 Interface Library
+ * - By John Hodge (thePowersGang)
+ *
+ * wm.cpp
+ * - Window Management
+ */
+#include <axwin4/axwin.h>
+#include "include/common.hpp"
+#include <ipc_proto.hpp>
+#include <vector>
+#include <algorithm>
+#include <mutex>
+#include <cassert>
+
+namespace AxWin {
+
+static const int       MAX_WINDOW_ID = 16;
+static ::std::mutex    glWindowList;
+static ::std::vector<tAxWin4_Window*>  gWindowList;
+
+extern "C" tAxWin4_Window *AxWin4_CreateWindow(const char *Name)
+{
+       // Allocate a window ID
+       ::std::lock_guard<std::mutex>   lock(glWindowList);
+       int id = ::std::find(gWindowList.begin(), gWindowList.end(), nullptr) - gWindowList.begin();
+       if( id >= MAX_WINDOW_ID ) {
+               throw ::std::runtime_error("AxWin4_CreateWindow - Out of IDs (TODO: Better exception)");
+       }
+       if( id == gWindowList.size() )
+       {
+               gWindowList.push_back(nullptr);
+       }
+       assert(gWindowList[id] == nullptr);
+       
+       // Create window structure locally
+       tAxWin4_Window *ret = new tAxWin4_Window();
+       gWindowList[id] = ret;
+       ret->m_id = id;
+       ret->m_fd = -1;
+       ret->m_buffer = nullptr;
+       // Request creation of window
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_CREATEWIN);
+       message.WriteU16(ret->m_id);
+       message.WriteString(Name);
+       ::AxWin::SendMessage(message);
+       return ret;
+}
+
+extern "C" void AxWin4_ShowWindow(tAxWin4_Window *Window, bool Show)
+{
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_SETWINATTR);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(IPC_WINATTR_SHOW);
+       message.WriteU8( (Show ? 1 : 0) );
+       ::AxWin::SendMessage(message);
+}
+
+extern "C" void AxWin4_SetWindowFlags(tAxWin4_Window *Window, unsigned int Flags)
+{
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_SETWINATTR);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(IPC_WINATTR_FLAGS);
+       message.WriteU8( Flags );
+       ::AxWin::SendMessage(message);
+}
+
+extern "C" void AxWin4_MoveWindow(tAxWin4_Window *Window, int X, int Y)
+{
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_SETWINATTR);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(IPC_WINATTR_POSITION);
+       message.WriteS16(X);
+       message.WriteS16(Y);
+       ::AxWin::SendMessage(message);
+}
+extern "C" void AxWin4_ResizeWindow(tAxWin4_Window *Window, unsigned int W, unsigned int H)
+{
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_SETWINATTR);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(IPC_WINATTR_DIMENSIONS);
+       message.WriteU16(W);
+       message.WriteU16(H);
+       ::AxWin::SendMessage(message);
+}
+
+extern "C" void AxWin4_SetTitle(tAxWin4_Window *Window, const char *Title)
+{
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_SETWINATTR);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(IPC_WINATTR_TITLE);
+       message.WriteString(Title);
+       ::AxWin::SendMessage(message);
+}
+
+extern "C" void AxWin4_DamageRect(tAxWin4_Window *Window, unsigned int X, unsigned int Y, unsigned int W, unsigned int H)
+{
+       CSerialiser     message;
+       message.WriteU8(IPCMSG_DAMAGERECT);
+       message.WriteU16(Window->m_id);
+       message.WriteU16(X);
+       message.WriteU16(Y);
+       message.WriteU16(W);
+       message.WriteU16(H);
+       ::AxWin::SendMessage(message);
+}
+
+extern "C" void *AxWin4_GetWindowBuffer(tAxWin4_Window *Window)
+{
+       if( Window->m_fd == -1 )
+       {
+               CSerialiser     req;
+               req.WriteU8(IPCMSG_GETWINBUF);
+               req.WriteU16(Window->m_id);
+               
+               CDeserialiser   response = GetSyncReply(req, IPCMSG_GETWINBUF);
+               unsigned int rspwin = response.ReadU16();
+               if( rspwin != Window->m_id )
+               {
+                       _SysDebug("AxWin4_GetWindowBuffer: GETWINBUF reply for different window (%u != %u)", rspwin, Window->m_id);
+                       return NULL;
+               }
+               
+               uint64_t handle = response.ReadU64();
+               Window->m_fd = _SysUnMarshalFD(handle);
+               if( Window->m_fd == -1 ) {
+                       _SysDebug("AxWin4_GetWindowBuffer: Unable to unmarshal resultant FD (0x%llx)", handle);
+                       return NULL;
+               }
+               
+               _SysDebug("AxWin4_GetWindowBuffer: %llx = %i", handle, Window->m_fd);
+       }
+
+       if( !Window->m_buffer )
+       {
+               size_t  size = 640*480*4;
+               Window->m_buffer = _SysMMap(NULL, size, MMAP_PROT_WRITE, MMAP_MAP_SHARED, Window->m_fd, 0);
+       }
+
+       return Window->m_buffer;
+}
+
+};     // namespace AxWin
+
index 6cec94f..7253837 100644 (file)
@@ -7,13 +7,22 @@ CPPFLAGS +=
 CFLAGS   += -Wall -Werror -Wextra\r
 CXXFLAGS += -Wall -Werror -Wextra\r
 ASFLAGS  +=\r
-LDFLAGS  += -Map map.txt -lc\r
+LDFLAGS  += -nostdlib\r
+PRELINK  := $(CRTI) $(CRTBEGINS) $(CRT0S)\r
+LIBS     += -lc $(LIBGCC_PATH) $(CRTENDS) $(CRTN)\r
+USE_CXX_LINK := yes\r
 \r
 OBJ  = misc.o new.o guard.o cxxabi.o typeinfo.o\r
+OBJ += string.o mutex.o\r
+OBJ += exceptions.o exception_handling.o system_error.o\r
+OBJ += gxx_personality.o\r
+ifeq ($(ARCHDIR),native)\r
+# - Include libgcc_eh (separate in linux), and the linux libc (space avoids hack in Makefile.tpl)\r
+LIBS += -lgcc_eh -l c\r
+endif\r
 DEPFILES := $(OBJ:%.o=%.d)\r
 BIN = libc++.so\r
 ifeq ($(ARCHDIR),native)\r
- OBJ := $(filter-out heap.o,$(OBJ))\r
  BIN = libc++_acess.so\r
 endif\r
 \r
index adda291..bd35690 100644 (file)
@@ -4,8 +4,13 @@
  *
  * cxxabi.cc
  * - C++ ABI Namespace
+ * 
+ * NOTE: GCC follows the Itaniumâ„¢ C++ ABI on all platforms
+ * http://mentorembedded.github.io/cxx-abi/abi.html
+ * http://libcxxabi.llvm.org/spec.html
  */
 #include <cxxabi.h>
+#include <acess/sys.h>
 
 namespace __cxxabiv1 {
 
@@ -30,3 +35,28 @@ __vmi_class_type_info::~__vmi_class_type_info()
 
 };     // namespace __cxxabiv1
 
+extern "C" void __cxa_bad_cast ()
+{
+       _SysDebug("__cxa_bad_cast");
+       for(;;);
+       //throw ::std::bad_cast;
+}
+
+extern "C" void __cxa_bad_typeid ()
+{
+       _SysDebug("__cxa_bad_typeid");
+       for(;;);
+       //throw ::std::bad_typeid;
+}
+
+extern "C" void* __dynamic_cast(
+       const void *sub,
+       const __cxxabiv1::__class_type_info *src,
+       const __cxxabiv1::__class_type_info *dst,
+       ptrdiff_t src2dst_offset
+       )
+{
+       _SysDebug("TODO: __dynamic_cast %p %s to %s, hint=%p", sub, dst->name(), src->name(), src2dst_offset);
+       return NULL;
+}
+
diff --git a/Usermode/Libraries/libc++.so_src/exception_handling.cc b/Usermode/Libraries/libc++.so_src/exception_handling.cc
new file mode 100644 (file)
index 0000000..81d4605
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Acess2 C++ Support Library
+ * - By John Hodge (thePowersGang)
+ *
+ * exception_handling.cc
+ * - Exception handling code (defined by C++ ABI)
+ *
+ * References:
+ * - LLVM Exception handling
+ *  > http://llvm.org/docs/ExceptionHandling.html
+ * - Itanium C++ ABI
+ *  >http://mentorembedded.github.io/cxx-abi/abi-eh.html
+ * - HP's "aC++" Document, Ch 7 "Exception Handling Tables"
+ *  > http://mentorembedded.github.io/cxx-abi/exceptions.pdf
+ */
+#include <typeinfo>
+#include <cstdint>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <exception>
+#include "exception_handling_cxxabi.h"
+
+#include <acess/sys.h>
+
+#define DEBUG_ENABLED  1
+
+#if DEBUG_ENABLED
+# define       DEBUG(v...)     ::_SysDebug(v)
+#else
+# define       DEBUG(v...)     do{}while(0)
+#endif
+
+/*__thread*/ struct __cxa_eh_globals {
+       __cxa_exception *caughtExceptions;
+       unsigned  int   uncaughtExceptions;
+} eh_globals;
+
+/*__thread*/ struct {
+       __cxa_exception info;
+       char    buf[32];
+} emergency_exception;
+/*__thread*/ bool      emergency_exception_used;
+
+static bool TEST_AND_SET(bool& flag) {
+       bool ret = flag;
+       flag = true;
+       return ret;
+}
+
+// === CODE ===
+extern "C" __cxa_eh_globals *__cxa_get_globals(void)
+{
+       return &eh_globals;
+}
+extern "C" __cxa_eh_globals *__cxa_get_globals_fast(void)
+{
+       return &eh_globals;
+}
+extern "C" void __cxa_call_unexpected(void *)
+{
+       // An unexpected exception was thrown from a function that lists its possible exceptions
+       _SysDebug("__cxa_call_unexpected - TODO");
+       for(;;);
+}
+
+extern "C" void *__cxa_allocate_exception(size_t thrown_size)
+{
+       DEBUG("__cxa_allocate_exception(%i)", thrown_size);
+       __cxa_exception *ret = static_cast<__cxa_exception*>( malloc( sizeof(__cxa_exception) + thrown_size ) );
+       if( !ret ) {
+               if( thrown_size <= sizeof(emergency_exception.buf) && TEST_AND_SET(emergency_exception_used) )
+               {
+                       ret = &emergency_exception.info;
+               }
+       }
+       if( !ret ) {
+               _SysDebug("__cxa_allocate_exception - No free space");
+               ::std::terminate();
+       }
+       DEBUG("__cxa_allocate_exception: return %p", ret+1);
+       return ret + 1;
+}
+
+extern "C" void __cxa_free_exception(void *thrown_exception)
+{
+       DEBUG("__cxa_free_exception(%p)", thrown_exception);
+       if(thrown_exception == &emergency_exception.buf) {
+               //assert(emergency_exception_used);
+               emergency_exception_used = false;
+       }
+       else {
+               __cxa_exception *except = static_cast<__cxa_exception*>( thrown_exception ) - 1;
+               free(except);
+       }
+}
+
+extern "C" void __cxa_throw(void *thrown_exception, std::type_info *tinfo, void (*dest)(void*))
+{
+       #if DEBUG_ENABLED
+       DEBUG("__cxa_throw(%p,%p,%p) '%s' by %p",
+               thrown_exception, tinfo, dest, tinfo->name(), __builtin_return_address(0)
+               );
+       {
+               const ::std::exception* e = reinterpret_cast<const ::std::exception*>(thrown_exception);
+               DEBUG("- e.what() = '%s'", e->what());
+       }
+       #endif
+
+       __cxa_exception *except = static_cast<__cxa_exception*>( thrown_exception ) - 1;
+       
+       except->unexpectedHandler = 0;
+       except->terminateHandler = 0;
+       except->exceptionType = tinfo;
+       except->exceptionDestructor = dest;
+       memcpy(&except->unwindHeader.exception_class, EXCEPTION_CLASS_ACESS, 8);
+       __cxa_get_globals()->uncaughtExceptions ++;
+       
+       int rv = _Unwind_RaiseException( &except->unwindHeader );
+       
+       ::_SysDebug("__cxa_throw(%p,%s) :: UNCAUGHT %i", thrown_exception, tinfo->name(), rv);
+       ::std::terminate();
+}
+
+extern "C" void *__cxa_begin_catch(_Unwind_Exception *exceptionObject)
+{
+       __cxa_exception *except = reinterpret_cast<__cxa_exception*>( exceptionObject+1 )-1;
+       DEBUG("__cxa_begin_catch(%p) - except=%p", exceptionObject, except);
+       
+       except->handlerCount ++;
+       
+       except->nextException = __cxa_get_globals()->caughtExceptions;
+       __cxa_get_globals()->caughtExceptions = except;
+       
+       __cxa_get_globals_fast()->uncaughtExceptions --;
+       
+       return except+1;
+}
+
+extern "C" void __cxa_end_catch()
+{
+       struct __cxa_exception  *except = __cxa_get_globals()->caughtExceptions;
+       DEBUG("__cxa_end_catch - %p", except);
+       except->handlerCount --;
+       __cxa_get_globals()->caughtExceptions = except->nextException;
+       
+       if( except->handlerCount == 0 ) {
+               __cxa_free_exception(except+1);
+       }
+}
+
+
diff --git a/Usermode/Libraries/libc++.so_src/exception_handling_acxx.h b/Usermode/Libraries/libc++.so_src/exception_handling_acxx.h
new file mode 100644 (file)
index 0000000..536016e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Acess2 C++ Support Library
+ * - By John Hodge (thePowersGang)
+ *
+ * exception_handling_acxx.h
+ * - C++ Exception handling definions from HP's aC++ document
+ *
+ * Reference: http://mentorembedded.github.io/cxx-abi/exceptions.pdf
+ */
+#ifndef _EXCEPTION_HANLDING_ACXX_H_
+#define _EXCEPTION_HANLDING_ACXX_H_
+
+/**
+ * \brief Language Specific Data Area
+ * \note Pointer obtained via _Unwind_GetLanguageSpecificData
+ */
+struct sLSDA_Header
+{
+       const void      *Base;
+       uintptr_t       LPStart;
+       uint8_t         TTEncoding;
+       uintptr_t       TypePtrBase;    // base address for type pointers
+       uintptr_t       TTBase; // Base address for type offsets
+       uint8_t CallSiteEncoding;
+       const void      *CallSiteTable;
+       const void      *ActionTable;
+};
+
+/* Pointer encodings, from dwarf2.h.  */ 
+#define DW_EH_PE_absptr         0x00 
+#define DW_EH_PE_omit           0xff 
+
+// - Data format (mask with 0x0F)
+#define DW_EH_PE_fmtmask       0x0F
+#define DW_EH_PE_uleb128        0x01 
+#define DW_EH_PE_udata2         0x02 
+#define DW_EH_PE_udata4         0x03 
+#define DW_EH_PE_udata8         0x04 
+#define DW_EH_PE_sleb128        0x09 
+#define DW_EH_PE_sdata2         0x0A 
+#define DW_EH_PE_sdata4         0x0B 
+#define DW_EH_PE_sdata8         0x0C 
+#define DW_EH_PE_signed         0x08 
+// - Data maipulation (0x70)
+#define DW_EH_PE_relmask       0x70
+#define DW_EH_PE_pcrel          0x10 
+#define DW_EH_PE_textrel        0x20 
+#define DW_EH_PE_datarel        0x30 
+#define DW_EH_PE_funcrel        0x40 
+#define DW_EH_PE_aligned        0x50 
+#define DW_EH_PE_indirect       0x80 
+
+typedef        uint64_t        leb128u_t;
+typedef         int64_t        leb128s_t;
+
+
+#endif
+
diff --git a/Usermode/Libraries/libc++.so_src/exception_handling_cxxabi.h b/Usermode/Libraries/libc++.so_src/exception_handling_cxxabi.h
new file mode 100644 (file)
index 0000000..69f3735
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Acess2 C++ Support Library
+ * - By John Hodge (thePowersGang)
+ *
+ * exception_handling_cxxabi.h
+ * - C++ Exception Handling definitions from the Itanium C++ ABI
+ */
+#ifndef _EXCEPTION_HANLDING_CXXABI_H_
+#define _EXCEPTION_HANLDING_CXXABI_H_
+
+typedef void *(unexpected_handler)(void);
+typedef void *(terminate_handler)(void);
+
+struct _Unwind_Context;
+
+typedef enum {
+       _URC_NO_REASON = 0,
+       _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+       _URC_FATAL_PHASE2_ERROR = 2,
+       _URC_FATAL_PHASE1_ERROR = 3,
+       _URC_NORMAL_STOP = 4,
+       _URC_END_OF_STACK = 5,
+       _URC_HANDLER_FOUND = 6,
+       _URC_INSTALL_CONTEXT = 7,
+       _URC_CONTINUE_UNWIND = 8
+} _Unwind_Reason_Code;
+
+typedef int    _Unwind_Action;
+static const _Unwind_Action    _UA_SEARCH_PHASE  = 1;
+static const _Unwind_Action    _UA_CLEANUP_PHASE = 2;
+static const _Unwind_Action    _UA_HANDLER_FRAME = 4;
+static const _Unwind_Action    _UA_FORCE_UNWIND  = 8;
+
+typedef void   (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code reason, struct _Unwind_Exception *exc);
+
+struct _Unwind_Exception
+{
+       uint64_t        exception_class;
+       _Unwind_Exception_Cleanup_Fn    exception_cleanup;
+       uint64_t        private_1;
+       uint64_t        private_2;
+};
+
+struct __cxa_exception
+{
+       std::type_info* exceptionType;
+       void (*exceptionDestructor)(void *);
+       unexpected_handler*     unexpectedHandler;
+       terminate_handler*      terminateHandler;
+       __cxa_exception*        nextException;
+       
+       int     handlerCount;
+       
+       int     handlerSwitchValue;
+       const char*     actionRecord;
+       const char*     languageSpecificData;
+       void*   catchTemp;
+       void*   adjustedPtr;
+       
+       _Unwind_Exception       unwindHeader;
+};
+
+#define EXCEPTION_CLASS_ACESS  "Ac20C++\0"
+
+typedef _Unwind_Reason_Code    (*_Unwind_Stop_Fn)(int version, _Unwind_Action actions, uint64_t exception_class, struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context, void *stop_parameter);
+
+// Exports
+extern "C" void __cxa_call_unexpected(void *);
+extern "C" void *__cxa_allocate_exception(size_t thrown_size);
+extern "C" void __cxa_free_exception(void *thrown_exception);
+extern "C" void __cxa_throw(void *thrown_exception, std::type_info *tinfo, void (*dest)(void*));
+extern "C" void *__cxa_begin_catch(_Unwind_Exception *exceptionObject);
+extern "C" void __cxa_end_catch();
+
+// Imports
+extern "C" _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exception_object);
+extern "C" _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, void *stop_parameter);
+extern "C" void        _Unwind_DeleteException(struct _Unwind_Exception *exception_object);
+extern "C" uint64_t    _Unwind_GetGR(struct _Unwind_Context *context, int index);
+extern "C" void        _Unwind_SetGR(struct _Unwind_Context *context, int index, uint64_t new_value);
+extern "C" uint64_t    _Unwind_GetIP(struct _Unwind_Context *context);
+extern "C" void        _Unwind_SetIP(struct _Unwind_Context *context, uint64_t new_value);
+extern "C" uint64_t    _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context);
+extern "C" uint64_t    _Unwind_GetRegionStart(struct _Unwind_Context *context);
+
+#endif
+
+
diff --git a/Usermode/Libraries/libc++.so_src/exceptions.cc b/Usermode/Libraries/libc++.so_src/exceptions.cc
new file mode 100644 (file)
index 0000000..cc7c8c2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * exceptions.cc
+ * - exception and friends
+ */
+#include <string>
+#include <exception>
+#include <stdexcept>
+#include <acess/sys.h>
+
+// === CODE ===
+namespace std {
+
+exception::exception() throw()
+{
+}
+exception::exception(const exception&) throw()
+{
+}
+exception& exception::operator=(const exception&) throw()
+{
+       return *this;
+}
+exception::~exception() throw()
+{
+}
+const char* exception::what() const throw()
+{
+       return "generic exception";
+}
+
+void terminate()
+{
+       _SysDebug("terminate()");
+       _exit(0);
+}
+
+_bits::str_except::str_except(const string& what_arg):
+       m_str(what_arg)
+{
+}
+_bits::str_except::~str_except() noexcept
+{
+}
+_bits::str_except& _bits::str_except::operator=(const str_except& e) noexcept
+{
+       m_str = e.m_str;
+       return *this;
+}
+const char* _bits::str_except::what() const throw()
+{
+       return m_str.c_str();
+}
+
+// --- Standar Exceptions ---
+logic_error::logic_error(const string& what_str):
+       _bits::str_except(what_str)
+{
+}
+
+out_of_range::out_of_range(const string& what_str):
+       logic_error(what_str)
+{
+}
+
+length_error::length_error(const string& what_str):
+       logic_error(what_str)
+{
+}
+
+runtime_error::runtime_error(const string& what_str):
+       _bits::str_except(what_str)
+{
+}
+
+}      // namespace std
+
index a075a7b..6468a67 100644 (file)
@@ -6,24 +6,33 @@
  * - One-time construction API
  */
 #include <stdint.h>
+#include <acess/sys.h>
+#include <cstdlib>
+
+#define FLAG_INIT_COMPLETE     (1<<0)
+#define FLAG_INIT_LOCKED       (1<<1)
 
 extern "C" int __cxa_guard_acquire ( int64_t *guard_object )
 {
        // TODO: Mutex!
-       if( *guard_object )
-               return 1;
-       *guard_object = 1;
-       return 0;
+       if( *guard_object == FLAG_INIT_COMPLETE )
+               return 0;
+       if( *guard_object == FLAG_INIT_LOCKED ) {
+               _SysDebug("ERROR: __cxa_guard_acquire - nested");
+       }
+       *guard_object = FLAG_INIT_LOCKED;
+       return 1;
 }
 
 extern "C" void __cxa_guard_release ( int64_t *guard_object )
 {
-       *guard_object = 0;
+       *guard_object = FLAG_INIT_COMPLETE;
 }
 
 extern "C" void __cxa_guard_abort ( int64_t *guard_object )
 {
-       *guard_object = 0;
-       // TODO: abort
+       *guard_object = FLAG_INIT_COMPLETE;
+       _SysDebug("__cxa_guard_abort");
+       abort();
 }
 
diff --git a/Usermode/Libraries/libc++.so_src/gxx_personality.cc b/Usermode/Libraries/libc++.so_src/gxx_personality.cc
new file mode 100644 (file)
index 0000000..fbd1623
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * Acess2 C++ Support Library
+ * - By John Hodge (thePowersGang)
+ *
+ * gxx_personality.cc
+ * - Implementation of GNU C++ Exception handling "Personality"
+ */
+#include <typeinfo>
+#include <cstdint>     // [u]intN_t
+#include <cstdlib>     // abort
+#include <cstring>     // memcmp
+#include "exception_handling_acxx.h"
+#include "exception_handling_cxxabi.h"
+#include <acess/sys.h>
+#include <cassert>
+#include <cxxabi.h>    // __dynamic_cast
+
+#define DEBUG_ENABLED  1
+
+#if DEBUG_ENABLED
+# define DEBUG(v...)   ::_SysDebug(v)
+#else
+# define DEBUG(v...)   do{}while(0)
+#endif
+
+// === PROTOTYPES ===
+extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
+               struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context);
+static int get_frame_action(const sLSDA_Header &header, _Unwind_Context *context, const std::type_info *throw_type,
+       uint64_t &landingpad, int64_t &switch_value);
+static bool exception_matches_single(const std::type_info *throw_type, const struct sLSDA_Header &header, int type_index);
+static bool exception_matches_list(const std::type_info *throw_type, const struct sLSDA_Header &header, int list_index);
+static void read_lsda_header(const void *&ptr, _Unwind_Context *context, struct sLSDA_Header *header);
+static size_t _get_encoded_size(int encoding);
+static uint64_t _get_base(uint8_t encoding, _Unwind_Context *context);
+static uint64_t _read_encoded(const void *&ptr, _Unwind_Context *context, int encoding, uint64_t base);
+static uint64_t _read_encoded(const void *&ptr, _Unwind_Context *context, int encoding);
+template <typename T> static T read(const void *&ptr);
+static uint64_t _read_leb128u(const void *&ptr);
+static int64_t _read_leb128s(const void *&ptr);
+
+// === CODE ===
+extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
+               struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context)
+{
+       //::_SysDebug("__gxx_personality_v0(%i, 0x%x, 0x%llx, ...)", version, actions, exceptionClass);
+       //::_SysDebug("__gxx_personality_v0(..., %p, %p)", exceptionObject, context);
+       
+       //if( exceptionObject ) {
+       //      ::_SysDebug("exception_object: Class 0x%llx", exceptionObject->exception_class);
+       //}
+       //if( context )
+       //{
+       //      ::_SysDebug("context: IP 0x%llx", _Unwind_GetIP(context));
+       //      ::_SysDebug("context: RegionStart 0x%llx", _Unwind_GetRegionStart(context));
+       //      ::_SysDebug("context: LangSpecData 0x%llx", _Unwind_GetLanguageSpecificData(context));
+       //}
+       
+       if( version != 1 ) {
+               ::_SysDebug("%s: Unexpected version %i != exp 1", __func__, version);
+               return _URC_FATAL_PHASE1_ERROR;
+       }
+       
+       const void *lsda_ptr = (const void*)_Unwind_GetLanguageSpecificData(context);
+       struct sLSDA_Header     header;
+       read_lsda_header(lsda_ptr, context, &header);
+
+       const void *exception_object = exceptionObject + 1;
+       const __cxa_exception *exception_info = static_cast<const __cxa_exception*>(exception_object) - 1;
+       std::type_info *throw_type = (
+               memcmp(&exceptionClass,EXCEPTION_CLASS_ACESS,8) == 0 ? exception_info->exceptionType : NULL
+               );
+
+       uint64_t        landingpad = 0;
+        int64_t        switch_value = 0;
+       int frame_action = get_frame_action(header, context, throw_type,  landingpad, switch_value);
+
+       if( (actions & _UA_SEARCH_PHASE) && (actions & _UA_CLEANUP_PHASE) )
+       {
+               _SysDebug("__gxx_personality_v0: ERROR Both _UA_SEARCH_PHASE and _UA_CLEANUP_PHASE set");
+               abort();
+       }       
+
+       // Search
+       if( actions & _UA_SEARCH_PHASE )
+       {
+               // If a handler was found
+               if( frame_action == 2 ) {
+                       // - return _URC_HANDLER_FOUND
+                       DEBUG("SEARCH: 0x%llx Handler %p(%i)",
+                               _Unwind_GetIP(context), landingpad, switch_value);
+                       return _URC_HANDLER_FOUND;
+               }
+               // - If no handler (either nothing, or cleanups), return _URC_CONTINUE_UNWIND
+               DEBUG("SEARCH: 0x%llx no handler %p(%i)",
+                       _Unwind_GetIP(context), landingpad, switch_value);
+               return _URC_CONTINUE_UNWIND;
+       }
+
+       // Cleanup      
+       if( actions & _UA_CLEANUP_PHASE )
+       {
+               // No action, continue
+               if( frame_action == 0 ) {
+                       return _URC_CONTINUE_UNWIND;
+               }
+               assert(landingpad);
+       
+               if( actions & _UA_FORCE_UNWIND )
+               {
+                       // Unwind forced, override switch_value to 0
+                       // - Disables any attempt to handle exception
+                       switch_value = 0;
+               }
+       
+               DEBUG("Install context IP=0x%x, R%i=%p/R%i=%i",
+                       (uintptr_t)landingpad,
+                       __builtin_eh_return_data_regno(0), exceptionObject,
+                       __builtin_eh_return_data_regno(1), switch_value
+                       );
+               _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject);
+               _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), switch_value);
+               _Unwind_SetIP(context, landingpad);
+               return _URC_INSTALL_CONTEXT;
+       }
+       
+       _SysDebug("__gxx_personality_v0: Neither _UA_SEARCH_PHASE or _UA_CLEANUP_PHASE set");
+       return _URC_FATAL_PHASE1_ERROR;
+}
+
+int get_frame_action(const sLSDA_Header &header, _Unwind_Context *context, const std::type_info* throw_type,
+       uint64_t &landingpad, int64_t &switch_value)
+{
+       uint64_t ip = _Unwind_GetIP(context) - _Unwind_GetRegionStart(context);
+       DEBUG("get_frame_action: IP = 0x%llx + 0x%llx", _Unwind_GetRegionStart(context), ip);
+       // Check if there is a handler for this exception in this frame
+       // - Search call site table for this return address (corresponds to a try block)
+       uintptr_t       cs_ldgpad;
+       uint64_t        cs_action;
+       const void *lsda_ptr = header.CallSiteTable;
+       while( lsda_ptr < header.ActionTable )
+       {
+               uintptr_t cs_start  = _read_encoded(lsda_ptr, context, header.CallSiteEncoding);
+               uintptr_t cs_len    = _read_encoded(lsda_ptr, context, header.CallSiteEncoding);
+               cs_ldgpad = _read_encoded(lsda_ptr, context, header.CallSiteEncoding);
+               cs_action = _read_leb128u(lsda_ptr);
+               
+               // If IP falls below this entry, it's not on the list
+               if( ip <= cs_start ) {
+                       lsda_ptr = header.ActionTable;
+                       break ;
+               }
+               if( ip > cs_start + cs_len )
+                       continue;
+               
+               break;
+       }
+       if( lsda_ptr > header.ActionTable ) {
+               _SysDebug("__gxx_personality_v0: Malformed Call Site Table, reading overran the end (%p>%p)",
+                       lsda_ptr, header.ActionTable);
+       }
+       if( lsda_ptr >= header.ActionTable ) {
+               // No match!
+               DEBUG("__gxx_personality_v0: No entry for IP 0x%x", ip);
+               return 0;
+       }
+       
+       // Found it
+       if( cs_ldgpad == 0 ) {
+               DEBUG("No landingpad, hence no action");
+               if( cs_action != 0 ) {
+                       _SysDebug("%s: NOTICE cs_ldgpad==0 but cs_action(0x%llx)!=0",
+                               __func__, cs_action);
+               }
+               return 0;
+       }
+       else if( cs_action == 0 ) {
+               DEBUG("No action, cleanups only");
+               switch_value = 0;
+               landingpad = header.LPStart + cs_ldgpad;
+               return 1;       // 1 = cleanup only
+       }
+       else {
+               switch_value = 0;
+               landingpad = header.LPStart + cs_ldgpad;
+               // catch() handler
+               bool    has_cleanups = false;   // set to true to override return value
+               const void *action_list = (const char*)header.ActionTable + (cs_action-1);
+               for(;;) // broken by 0 length entry
+               {
+                       leb128s_t filter = _read_leb128s(action_list);
+                       leb128s_t disp = _read_leb128s(action_list);
+                       if( filter == 0 )
+                       {
+                               // Cleanup
+                               has_cleanups = true;
+                       }
+                       else if( filter < 0 )
+                       {
+                               // Exception specifcation
+                               if( !exception_matches_list(throw_type, header, -filter) )
+                               {
+                                       switch_value = filter;
+                                       return 2;
+                               }
+                       }
+                       else
+                       {
+                               // Catch
+                               if( exception_matches_single(throw_type, header, filter) )
+                               {
+                                       switch_value = filter;
+                                       return 2;
+                               }
+                       }
+                       
+                       if( disp == 0 )
+                               break;
+                       action_list = (const char*)action_list + disp-1;
+               }
+               
+               // If a cleanup request was seen, tell the caller that we want to handle it
+               if( has_cleanups ) {
+                       return 1;       // 1 = cleanup only
+               }
+               // Else, there's nothing here to handle
+               return 0;
+       }
+}
+
+const ::std::type_info *get_type_info(const struct sLSDA_Header &header, int type_index)
+{
+       size_t  encoded_size = _get_encoded_size(header.TTEncoding);
+       assert(encoded_size > 0);
+       const void *ptr = (const void*)(header.TTBase - encoded_size * type_index);
+       assert( header.TTBase );
+       assert( ptr > header.ActionTable );
+       
+       uintptr_t type_ptr = _read_encoded(ptr, NULL, header.TTEncoding, header.TypePtrBase);
+       return reinterpret_cast< ::std::type_info* >(type_ptr);
+}
+
+const ::std::type_info *get_exception_type(const void *exception_object)
+{
+       if( !exception_object )
+               return NULL;
+       const struct _Unwind_Exception  *u_execept = (const struct _Unwind_Exception*)exception_object;
+       const struct __cxa_exception *except = (const struct __cxa_exception*)(u_execept + 1) - 1;
+       if( memcmp(&except->unwindHeader.exception_class, EXCEPTION_CLASS_ACESS, 8) != 0 )
+               return NULL;
+       
+       return except->exceptionType;
+}
+
+bool exception_matches_single(const std::type_info *throw_type, const struct sLSDA_Header &header, int type_index)
+{
+       const ::std::type_info *catch_type = get_type_info(header, type_index);
+       DEBUG("catch_type = %p", catch_type);
+
+       if( !catch_type )
+       {
+               DEBUG("catch(...)");
+               return true;
+       }
+       else if( !throw_type )
+       {
+               DEBUG("threw UNK");
+               return false;
+       }
+       else
+       {
+               DEBUG("catch(%s), throw %s", catch_type->name(), throw_type->name());
+               size_t ofs = 0;
+               if( !catch_type->__is_child(*throw_type, ofs) ) {
+                       _SysDebug("> No match");
+                       return false;
+               }
+               
+               return true;
+       }
+}
+bool exception_matches_list(const std::type_info *throw_type, const struct sLSDA_Header &header, int list_index)
+{
+       _SysDebug("TODO: exception_matches_list %i", list_index);
+       abort();
+       (void)throw_type;
+       (void)header;
+       return true;
+}
+
+template <typename T> T read(const void *&ptr)
+{
+       T rv = *reinterpret_cast<const T*>(ptr);
+       ptr = (const char*)ptr + sizeof(T);
+       return rv;
+}
+
+static void read_lsda_header(const void *&ptr, _Unwind_Context *context, struct sLSDA_Header *header)
+{
+       header->Base = ptr;
+       
+       uint8_t start_encoding = read<uint8_t>(ptr);
+       if( start_encoding == DW_EH_PE_omit )
+               header->LPStart = _Unwind_GetRegionStart(context);
+       else
+               header->LPStart = _read_encoded(ptr, context, start_encoding);
+       
+       header->TTEncoding = read<uint8_t>(ptr);
+       if( header->TTEncoding == DW_EH_PE_omit )
+               header->TTBase = 0;
+       else {
+               ptrdiff_t       tt_ofs = _read_leb128u(ptr);
+               header->TTBase = (uintptr_t)ptr + tt_ofs;
+       }
+       header->TypePtrBase = _get_base(header->TTEncoding, context);
+
+       header->CallSiteEncoding = read<uint8_t>(ptr);
+       uint64_t call_site_size = _read_leb128u(ptr);
+       header->CallSiteTable = ptr;
+       header->ActionTable = (const void*)( (uintptr_t)ptr + call_site_size );
+       
+       #if 0
+       ::_SysDebug("LSDA header:");
+       ::_SysDebug("->LPStart = 0x%lx", header->LPStart);
+       ::_SysDebug("->TTEncoding = 0x%02x", header->TTEncoding);
+       ::_SysDebug("->TTBase = 0x%lx", header->TTBase);
+       ::_SysDebug("->CallSiteEncoding = 0x%02x", header->CallSiteEncoding);
+       ::_SysDebug("->CallSiteTable = %p", header->CallSiteTable);
+       ::_SysDebug("->ActionTable = %p", header->ActionTable);
+       #endif
+}
+
+static size_t _get_encoded_size(int encoding)
+{
+       switch(encoding & DW_EH_PE_fmtmask)
+       {
+       case DW_EH_PE_absptr:   // absolute
+               return sizeof(void*);
+       case DW_EH_PE_udata4:
+               return 4;
+       default:
+               _SysDebug("_get_encoded_size: Unknown encoding 0x%02x", encoding);
+               return 0;
+       }
+}
+
+/*
+ * \brief Read a DWARF encoded pointer from the stream
+ */
+static uint64_t _read_encoded(const void *&ptr, _Unwind_Context *context, int encoding, uint64_t base)
+{
+       (void)context;
+       if( encoding == DW_EH_PE_aligned ) {
+               void    **aligned = (void**)( ((uintptr_t)ptr + sizeof(void*) - 1) & -(sizeof(void*)-1) );
+               ptr = (void*)( (uintptr_t)aligned + sizeof(void*) );
+               return (uintptr_t)*aligned;
+       }
+       uint64_t        rv;
+       uintptr_t       orig_ptr = (uintptr_t)ptr;
+       switch(encoding & DW_EH_PE_fmtmask)
+       {
+       case DW_EH_PE_absptr:   // absolute
+               rv = (uintptr_t)read<void*>(ptr);
+               break;
+       case DW_EH_PE_uleb128:
+               rv = _read_leb128u(ptr);
+               break;
+       case DW_EH_PE_sleb128:
+               rv = _read_leb128s(ptr);
+               break;
+       case DW_EH_PE_udata2:
+               rv = read<uint16_t>(ptr);
+               break;
+       case DW_EH_PE_udata4:
+               rv = read<uint32_t>(ptr);
+               break;
+       case DW_EH_PE_udata8:
+               rv = read<uint64_t>(ptr);
+               break;
+       default:
+               ::_SysDebug("_read_encoded: Unknown encoding format 0x%x", encoding & DW_EH_PE_fmtmask);
+               ::abort();
+       }
+       if( rv != 0 )
+       {
+               if( (encoding & DW_EH_PE_relmask) == DW_EH_PE_pcrel ) {
+                       rv += orig_ptr;
+               }
+               else {
+                       rv += base;
+               }
+               
+               if( encoding & DW_EH_PE_indirect ) {
+                       rv = (uintptr_t)*(void**)(uintptr_t)rv;
+               }
+               else {
+                       // nothing
+               }
+       }
+       return rv;
+}
+static uint64_t _get_base(uint8_t encoding, _Unwind_Context *context)
+{
+       if( encoding == 0xFF )
+               return 0;
+       switch(encoding & DW_EH_PE_relmask)
+       {
+       case DW_EH_PE_absptr:
+       case DW_EH_PE_pcrel:
+       case DW_EH_PE_aligned:
+               return 0;
+       //case DW_EH_PE_textrel:
+               //return _Unwind_GetTextRelBase(context);
+       //case DW_EH_PE_datarel:
+               //return _Unwind_GetDataRelBase(context);
+       case DW_EH_PE_funcrel:
+               return _Unwind_GetRegionStart(context);
+       default:
+               ::_SysDebug("_get_base: Unknown encoding relativity 0x%x", (encoding & DW_EH_PE_relmask));
+               ::abort();
+               for(;;);
+       }
+}
+static uint64_t _read_encoded(const void *&ptr, _Unwind_Context *context, int encoding)
+{
+       return _read_encoded(ptr, context, encoding, _get_base(encoding, context));
+}
+
+static uint64_t _read_leb128_raw(const void *&ptr, int *sizep)
+{
+        int    size = 0;
+       uint64_t val = 0;
+       const uint8_t   *ptr8 = static_cast<const uint8_t*>(ptr);
+       do
+       {
+               val |= (*ptr8 & 0x7F) << (size*7);
+               size ++;
+       } while( *ptr8++ & 0x80 );
+       
+       ptr = ptr8;
+       *sizep = size;
+       
+       return val;
+}
+
+static uint64_t _read_leb128u(const void *&ptr)
+{
+        int    unused_size;
+       return _read_leb128_raw(ptr, &unused_size);
+}
+static int64_t _read_leb128s(const void *&ptr)
+{
+        int    size;
+       uint64_t val = _read_leb128_raw(ptr, &size);
+       if( size*7 <= 64 && (val & (1 << (size*7-1))) )
+       {
+               val |= 0xFFFFFFFFFFFFFFFF << (size*7);
+       }
+       return val;
+}
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/_libcxx_helpers.h b/Usermode/Libraries/libc++.so_src/include_exp/_libcxx_helpers.h
new file mode 100644 (file)
index 0000000..bd3b805
--- /dev/null
@@ -0,0 +1,31 @@
+
+#ifndef _LIBCXX__LIBCXX_HELEPRS_H_
+#define _LIBCXX__LIBCXX_HELEPRS_H_
+
+#if __cplusplus > 199711L      // C++11 check
+# define _CXX11_AVAIL  1
+#else
+# define _CXX11_AVAIL  0
+#endif
+
+#define _libcxx_assert(cnd) do { \
+       if(!(cnd)) {\
+               ::_sys::debug("libc++ assert failure %s:%i - %s", __FILE__, __LINE__, #cnd);\
+               ::_sys::abort(); \
+       } \
+} while(0)
+
+namespace _sys {
+extern void abort() __asm__ ("abort") __attribute__((noreturn));
+extern void debug(const char *, ...);
+extern void hexdump(const char *, const void *, unsigned int);
+};
+
+#if _CXX11_AVAIL
+#define _CXX11_MOVE(val)       ::std::move(val)
+#else
+#define _CXX11_MOVE(val)       val
+#endif
+
+#endif
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/algorithm b/Usermode/Libraries/libc++.so_src/include_exp/algorithm
new file mode 100644 (file)
index 0000000..c08e28f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * algorithm (header)
+ * - C++'s generic algorithms
+ */
+#ifndef _LIBCXX_ALGORITHM_
+#define _LIBCXX_ALGORITHM_
+
+#include <utility>
+
+#include "_libcxx_helpers.h"
+
+namespace std {
+
+// --- Non-modifiying sequence operations ---
+#if _CXX11_AVAIL
+// TODO: all_of
+// TODO: any_of
+// TODO: none_of
+#endif
+template <class InputIterator, class Function>
+Function for_each(InputIterator first, InputIterator last, Function fn)
+{
+       while( first != last )
+       {
+               fn( *first );
+               ++ first;
+       }
+       return _CXX11_MOVE(fn);
+}
+
+template <class InputIterator, class T>
+InputIterator find(InputIterator first, InputIterator last, const T& val)
+{
+       while( first != last )
+       {
+               if( *first == val )
+                       return first;
+               ++ first;
+       }
+       return last;
+}
+// TODO: find_if
+// TODO: find_if_not (C++11)
+// TODO: find_end
+// TODO: find_first_of
+
+// Maximum
+template <class T>
+const T& max(const T& a, const T& b)
+{
+       return (a<b) ? b : a;
+}
+
+template <class T, class Compare>
+const T& max(const T& a, const T& b, Compare comp)
+{
+       return comp(a, b) ? b : a;
+}
+
+template <class T>
+const T& min(const T& a, const T& b)
+{
+       return (a<b) ? a : b;
+}
+
+template <class T, class Compare>
+const T& min(const T& a, const T& b, Compare comp)
+{
+       return comp(a, b) ? a : b;
+}
+
+};     // namespace std
+
+#endif
+
+// vim: ft=cpp
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/allocator b/Usermode/Libraries/libc++.so_src/include_exp/allocator
new file mode 100644 (file)
index 0000000..1608a3c
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * string (header)
+ * - C++'s String type
+ */
+#ifndef _LIBCXX_ALLOCATOR_
+#define _LIBCXX_ALLOCATOR_
+
+#include "_libcxx_helpers.h"
+
+#include "new"
+#include "cstddef"
+#include "utility"
+
+namespace std {
+
+template <class T> class allocator;
+
+namespace _bits {
+
+template <class T>
+class allocator_real
+{
+public:
+       typedef T       value_type;
+       typedef T*      pointer;
+       typedef T&      reference;
+       typedef const T* const_pointer;
+       typedef const T&        const_reference;
+       typedef size_t  size_type;
+       typedef ptrdiff_t       difference_type;
+       
+       template <class Type>
+       struct rebind
+       {
+               typedef allocator<Type> other;
+       };
+       
+       allocator_real() throw() {
+       }
+       allocator_real(const allocator_real& alloc __attribute__((unused))) throw() {
+       }
+       template <class U>
+       allocator_real(const allocator_real<U>& alloc) throw() {
+       }
+       ~allocator_real() throw() {
+       }
+       
+       pointer address(reference x) const {
+               return &x;
+       }
+       const_pointer address(const_reference x) const {
+               return &x;
+       }
+       pointer allocate(size_type n, const void* hint=0) {
+               hint = hint;
+               return static_cast<pointer>( ::operator new (n * sizeof(value_type)) );
+       }
+       void deallocate(pointer p, size_type n) {
+               n=n;
+               ::operator delete(p);
+       }
+       size_type max_size() {
+               return ((size_type)-1) / sizeof(value_type);
+       }
+       void construct( pointer p, const_reference val ) {
+               new ((void*)p) value_type (val);
+       }
+       // C++11
+       #if _CXX11_AVAIL
+       template<class U, class... Args>
+       void construct( U* p, Args&&... args ) {
+               ::new ((void*)p) U (::std::forward<Args>(args)...);
+       }
+       #endif
+       void destroy(pointer p) {
+               p->~value_type();
+       }
+};
+
+template <class T>
+class allocator_noconstruct:
+       public ::std::_bits::allocator_real<T>
+{
+public:
+       void construct( typename allocator_real<T>::pointer p, typename allocator_real<T>::const_reference val ) {
+               *p = val;
+       }
+       void destroy(typename allocator_real<T>::pointer p) {
+       }
+};
+
+};
+
+template <class T>
+class allocator:
+       public _bits::allocator_real<T>
+{
+};
+
+#if 1
+template <>
+class allocator<unsigned char>:
+       public _bits::allocator_noconstruct<unsigned char>
+{
+};
+template <>
+class allocator<unsigned long>:
+       public _bits::allocator_noconstruct<unsigned long>
+{
+};
+#endif
+
+};
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/cassert b/Usermode/Libraries/libc++.so_src/include_exp/cassert
new file mode 100644 (file)
index 0000000..d11b746
--- /dev/null
@@ -0,0 +1,3 @@
+extern "C" {
+#include <assert.h>
+}
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/cerrno b/Usermode/Libraries/libc++.so_src/include_exp/cerrno
new file mode 100644 (file)
index 0000000..3ebd48a
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ */
+extern "C" {
+#include <errno.h>
+}
+// vim: ft=cpp
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/cstddef b/Usermode/Libraries/libc++.so_src/include_exp/cstddef
new file mode 100644 (file)
index 0000000..b7b0c13
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * cstddef (header)
+ * - C++ wrapper around stddef.h
+ */
+#ifndef _LIBCXX_CSTDDEF_
+#define _LIBCXX_CSTDDEF_
+
+extern "C" {
+#include <stddef.h>
+};
+
+#endif
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/cstdint b/Usermode/Libraries/libc++.so_src/include_exp/cstdint
new file mode 100644 (file)
index 0000000..c5575d9
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * cstdint (header)
+ * - C++ wrapper around stdint.h
+ */
+#ifndef _LIBCXX_CSTDINT_
+#define _LIBCXX_CSTDINT_
+
+extern "C" {
+#include <stdint.h>
+};
+
+#endif
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/cstdio b/Usermode/Libraries/libc++.so_src/include_exp/cstdio
new file mode 100644 (file)
index 0000000..f41fd05
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ */
+extern "C" {
+#include <stdio.h>
+}
+// vim: ft=cpp
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/cstdlib b/Usermode/Libraries/libc++.so_src/include_exp/cstdlib
new file mode 100644 (file)
index 0000000..7d119a7
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * cstdlib (header)
+ * - C++ wrapper around stdlib.h
+ */
+#ifndef _LIBCXX_CSTDLIB_
+#define _LIBCXX_CSTDLIB_
+
+extern "C" {
+#include <stdlib.h>
+};
+
+#endif
+
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/cstring b/Usermode/Libraries/libc++.so_src/include_exp/cstring
new file mode 100644 (file)
index 0000000..66149e0
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * cstring (header)
+ * - C++ wrapper around string.h
+ */
+#ifndef _LIBCXX_CSTRING_
+#define _LIBCXX_CSTRING_
+
+extern "C" {
+#include <string.h>
+};
+
+#endif
+
+
index a8e1f5c..2fbe897 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _LIBCXX__CXXABI_H_
 #define _LIBCXX__CXXABI_H_
 
+#include <cstddef>
+
 #include <typeinfo>
 
 namespace __cxxabiv1 {
@@ -71,6 +73,13 @@ public:
        };
 };
 
+extern "C" void* __dynamic_cast(
+               const void *sub,
+               const __class_type_info *src,
+               const __class_type_info *dst,
+               ptrdiff_t src2dst_offset
+               );
+
 };     // namespace __cxxabiv1
 
 #endif
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/exception b/Usermode/Libraries/libc++.so_src/include_exp/exception
new file mode 100644 (file)
index 0000000..9e1469d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * exception (header)
+ * - C++'s base exception type
+ */
+#ifndef _LIBCXX_EXCEPTION_
+#define _LIBCXX_EXCEPTION_
+
+#define noexcept       throw()
+
+namespace std {
+
+class exception
+{
+public:
+       exception() noexcept;
+       exception(const exception& e) noexcept;
+       exception& operator= (const exception& e) noexcept;
+       virtual ~exception() noexcept;
+       virtual const char* what() const noexcept;
+};
+
+class bad_exception:
+       public exception
+{
+public:
+       bad_exception() noexcept;
+       const char* what() const noexcept;
+};
+
+typedef void (*terminate_handler)();
+typedef void (*unexpected_handler)();
+
+extern void set_terminate(terminate_handler f) throw();
+extern void set_unexpected(unexpected_handler f) throw();
+extern void terminate();
+extern void unexpected();
+extern bool uncaught_exception() throw();
+
+};     // namespace std
+
+#endif
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/functional b/Usermode/Libraries/libc++.so_src/include_exp/functional
new file mode 100644 (file)
index 0000000..1ac05de
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * functional (header)
+ * - Funcional programming features
+ */
+#ifndef _LIBCXX_FUNCTIONAL_
+#define _LIBCXX_FUNCTIONAL_
+
+#include "_libcxx_helpers.h"
+
+namespace std {
+
+template <class T>
+struct less
+{
+       bool operator() (const T& x, const T& y) const {
+               return x < y;
+       }
+       typedef T       first_argument_type;
+       typedef T       second_argument_type;
+       typedef bool    result_type;
+};
+
+};     // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/initializer_list b/Usermode/Libraries/libc++.so_src/include_exp/initializer_list
new file mode 100644 (file)
index 0000000..565980f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * vector (header)
+ * - C++'s vector (dynamic array) type
+ */
+#ifndef _LIBCXX__INITIALIZER_LIST_
+#define _LIBCXX__INITIALIZER_LIST_
+
+namespace std {
+
+template <class T>
+class initializer_list
+{
+public:
+       typedef T       value_type;
+       typedef const T&        reference;
+       typedef const T&        const_reference;
+       typedef size_t  size_type;
+       typedef const T*        iterator;
+       typedef const T*        const_iterator;
+private:
+       // ORDER MATTERS : The first item must be a pointer to the array, the second must be the size
+       value_type*     m_values;
+       size_type       m_len;
+public:        
+       constexpr initializer_list() noexcept:
+               m_len(0)
+       {
+       }
+
+       size_type size() const noexcept
+       {
+               return m_len;
+       }
+       
+       const T* begin() const noexcept
+       {
+               return &m_values[0];
+       }
+       const T* end() const noexcept
+       {
+               return &m_values[m_len];
+       }
+};
+
+};
+
+template <class T> const T* begin(const ::std::initializer_list<T>& il) { return il.begin(); }
+template <class T> const T* end  (const ::std::initializer_list<T>& il) { return il.end(); }
+
+#endif
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/iterator b/Usermode/Libraries/libc++.so_src/include_exp/iterator
new file mode 100644 (file)
index 0000000..e58ab80
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ */
+#ifndef _LIBCXX_ITERATOR_
+#define _LIBCXX_ITERATOR_
+
+namespace std {
+
+struct input_iterator_tag {};
+struct output_iterator_tag {};
+struct forward_iterator_tag {};
+struct bidirectional_iterator_tag {};
+struct random_access_iterator_tag {};
+
+template <class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&>
+class iterator
+{
+public:
+       typedef T       value_type;     
+       typedef Distance        difference_type;
+       typedef Pointer pointer_type;
+       typedef Reference       reference;
+       typedef Category        iterator_category;
+};
+
+template <class Iterator> class iterator_traits;
+template <class T> class iterator_traits<T*>;
+template <class T> class iterator_traits<const T*>;
+
+
+};     // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/list b/Usermode/Libraries/libc++.so_src/include_exp/list
new file mode 100644 (file)
index 0000000..3bc614e
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * list (header)
+ * - List container
+ */
+#ifndef _LIBCXX_LIST_
+#define _LIBCXX_LIST_
+
+#include <cstddef>
+#include "allocator"
+#include "stdexcept"
+#include "utility"
+
+namespace std {
+
+namespace _bits {
+template <class ListType, class T> class list_iterator;
+template <class T> class list_item;
+}
+
+template <class T, class Alloc = allocator<T> >
+class list
+{
+       typedef ::std::_bits::list_item<T>      item_type;
+       typedef ::std::_bits::list_item<const T>        const_item_type;
+       friend class ::std::_bits::list_iterator<list, T>;
+       
+       typedef typename Alloc::template rebind<item_type>::other       item_allocator;
+public:
+       typedef T value_type;
+       typedef Alloc   allocator_type;
+       typedef typename allocator_type::reference      reference;
+       typedef typename allocator_type::const_reference        const_reference;
+       typedef typename allocator_type::pointer        pointer;
+       typedef typename allocator_type::const_pointer  const_pointer;
+       typedef _bits::list_iterator<list,T>    iterator;
+       typedef _bits::list_iterator<list,const T>      const_iterator;
+       typedef int     difference_type;
+       typedef size_t  size_type;
+
+private:
+       item_allocator  m_item_allocator;
+       allocator_type  m_allocator;
+       item_type       *m_start;
+       item_type       *m_end;
+       size_type       m_item_count;
+
+public:
+       list(const allocator_type& alloc = allocator_type()):
+               m_item_allocator(),
+               m_allocator(alloc),
+               m_start(0), m_end(0)
+       {
+       }
+       list(size_t n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type()):
+               list()
+       {
+               assign(n, val);
+       }
+       list(const list& x);
+       ~list() {
+               clear();
+       }
+       
+       list& operator =(const list& x);
+       
+       iterator begin() {
+               return iterator(*this, m_start);
+       }
+       const_iterator begin() const {
+               return const_iterator(*this, m_start);
+       }
+
+       iterator end() {
+               return iterator(*this, 0);
+       }
+       const_iterator end() const {
+               return const_iterator(*this, 0);
+       }
+       
+       bool empty() const {
+               return !m_start;
+       }
+       size_t size() const {
+               return m_item_count;
+       }
+       size_t max_size() const {
+               return (size_type)-1 / sizeof(item_type);
+       }
+       
+       T& front() {
+               return m_start->value;
+       }
+       const T& front() const {
+               return m_start->value;
+       }
+       T& back() {
+               return m_end->value;
+       }
+       const T& back() const {
+               return m_end->value;
+       }
+       
+       void assign(size_type n, const value_type& val) {
+               clear();
+               for( size_t i = 0; i < n; i ++ )
+               {
+                       push_back(val);
+               }
+       }
+       
+       void push_front(const value_type& val) {
+               insert(front(), val);
+       }
+       void pop_front() {
+               erase(front());
+       }
+       void push_back(const value_type& val) {
+               insert(end(), val);
+       }
+       void pop_back() {
+               erase(end());
+       }
+       
+       template <class... Args>
+       iterator emplace(iterator position, Args&&... args) {
+               item_type *newi = m_item_allocator.allocate(1);
+               m_allocator.construct(&newi->value, ::std::forward<Args>(args)...);
+               return insert_item(position, newi);
+       }
+       
+       iterator insert(iterator position, const value_type& val) {
+               item_type *newi = m_item_allocator.allocate(1);
+               m_allocator.construct(&newi->value, val);
+               return insert_item(position, newi);
+       }
+       void insert(iterator position, size_type n, const value_type& val) {
+               for( size_type i = 0; i < n; i ++ )
+               {
+                       position = insert(position, val);
+               }
+       }
+       iterator erase(iterator position) {
+               if( position == end() ) {
+               }
+               else {
+                       item_type *oldi = position.m_cur;
+                       ++ position;
+                       
+                       if(oldi->prev)
+                               oldi->prev->next = oldi->next;
+                       else
+                               m_start = oldi->next;
+                       if(oldi->next)
+                               oldi->next->prev = oldi->prev;
+                       else
+                               m_end = oldi->prev;
+
+                       m_item_count --;
+                       m_allocator.destroy(&oldi->value);
+                       m_item_allocator.deallocate(oldi, 1);
+               }
+               return position;
+       }
+       
+       void clear() {
+               while( m_start ) {
+                       item_type* item = m_start;
+                       m_start = m_start->next;
+                       delete item;
+               }
+               m_item_count = 0;
+       }
+
+       void splice(iterator position, list& x) {
+               splice(position, x, x.begin(), x.end());
+       }
+       void splice(iterator position, list& x, iterator i) {
+               splice(position, x, i, x.end());
+       }
+       void splice(iterator position, list& x, iterator first, iterator last);
+
+private:
+       class _equal
+       {
+               const value_type&       m_val;
+       public:
+               _equal(const value_type& val):
+                       m_val(val)
+               {
+               };
+               bool operator() (const value_type& v1)
+               {
+                       return m_val == v1;
+               }
+       };
+public:
+       void remove(const value_type& val) {
+               remove_if(_equal(val));
+       }
+       template <class Predicate> void remove_if(Predicate pred) {
+               for( iterator it = begin(); it != end(); )
+               {
+                       if( pred(*it) )
+                               it = erase(it);
+                       else
+                               ++ it;
+               }
+       }
+       
+       void unique();
+       template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);
+       
+       void merge(list& x);
+       template <class Compare> void merge(list& x, Compare comp);
+       
+       void sort();
+       template <class Compare> void sort(Compare comp);
+       
+       void reverse() throw();
+private:
+       iterator insert_item(iterator position, item_type *newi) {
+               m_item_count ++;
+               if( m_start == 0 ) {
+                       newi->next = 0;
+                       newi->prev = m_end;
+                       m_start = newi;
+                       m_end = newi;
+                       return end();
+               }
+               if( position == end() ) {
+                       newi->next = 0;
+                       newi->prev = m_end;
+                       //assert(m_end);
+                       m_end->next = newi;
+                       m_end = newi;
+               }
+               else if( position == begin() ) {
+                       newi->next = m_start;
+                       newi->prev = 0;
+                       //assert(m_start);
+                       m_start->prev = newi;
+                       m_start = newi;
+               }
+               else {
+                       newi->prev = position.m_cur->prev;
+                       newi->next = position.m_cur;
+                       position.m_cur->prev->next = newi;
+                       position.m_cur->prev = newi;
+               }
+               return ++iterator(*this, newi);
+       }
+};
+
+
+namespace _bits {
+
+template <class T>
+struct list_item
+{
+       typedef T       value_type;
+       list_item<T>    *next;
+       list_item<T>    *prev;
+       value_type      value;
+};
+
+template <class ListType, class T>
+class list_iterator//:
+       //public bidirectional_iterator_tag;
+{
+       const ListType* m_list;
+       list_item<T>    *m_cur;
+       friend ListType;
+public:
+       list_iterator(const list_iterator& x):
+               m_list(x.m_list),
+               m_cur (x.m_cur)
+       {
+       }
+       list_iterator& operator=(const list_iterator& x) {
+               m_list = x.m_list;
+               m_cur  = x.m_cur;
+       }
+       
+       bool operator == (const list_iterator& other) const {
+               return m_cur == other.m_cur;
+       }
+       bool operator != (const list_iterator& other) const {
+               return !(*this == other);
+       }
+       
+       T& operator * () {
+               return m_cur->value;
+       }
+       T& operator -> () {
+               return m_cur->value;
+       }
+       list_iterator& operator ++ () {
+               if(!m_cur)
+                       throw ::std::logic_error("list iterator ++ on end");
+               m_cur = m_cur->next;
+               return *this;
+       }
+       list_iterator& operator -- () {
+               if( m_cur == m_list->m_start )
+                       throw ::std::logic_error("list iterator -- on start");
+               if(!m_cur)
+                       m_cur = m_list->m_end;
+               else
+                       m_cur = m_cur->prev;
+               return *this;
+       }
+       
+private:
+       list_iterator(const ListType& list, list_item<T> *item):
+               m_list(&list),
+               m_cur(item)
+       {
+       }
+};
+
+};     // namespace _bits
+
+};     // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/map b/Usermode/Libraries/libc++.so_src/include_exp/map
new file mode 100644 (file)
index 0000000..2f9031b
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * map (header)
+ * - C++'s map type
+ */
+#ifndef _LIBCXX_MAP_
+#define _LIBCXX_MAP_
+
+#include "_libcxx_helpers.h"
+#include <allocator>
+#include <stdexcept>
+#include <iterator>
+#include <utility>
+#include <functional>  // less
+
+namespace std {
+
+namespace _bits {
+
+template <class Val, class Map>
+class map_iterator:
+       public ::std::iterator< ::std::bidirectional_iterator_tag, Val >
+{
+       friend Map;
+       typedef Val     value_type;
+       Map     *m_map;
+       size_t  m_index;
+public:
+       map_iterator():
+               m_map(0), m_index(0)
+       {
+       }
+       map_iterator(Map *map, typename Map::size_type ofs):
+               m_map(map), m_index(ofs)
+       {
+       }
+       map_iterator(const map_iterator& x) {
+               *this = x;
+       }
+       map_iterator& operator=(const map_iterator& x) {
+               m_map = x.m_map;
+               m_index = x.m_index;
+               return *this;
+       }
+       
+       map_iterator& operator++() {
+               m_index ++;
+       }
+       map_iterator& operator--() {
+               m_index --;
+       }
+       
+       bool operator==(const map_iterator& x) const {
+               return m_index == x.m_index;
+       }
+       bool operator!=(const map_iterator& x) const {
+               return !(*this == x);
+       }
+       value_type& operator*() {
+               _libcxx_assert(m_index < m_map->m_size);
+               return m_map->m_items[m_index];
+       }
+       value_type* operator->() {
+               _libcxx_assert(m_index < m_map->m_size);
+               return &m_map->m_items[m_index];
+       }
+};
+
+}      // namespace _bits
+
+template <class Key, class T, class Compare=less<Key>, class Alloc=allocator<pair<const Key,T> > >
+class map
+{
+       typedef map     this_type;
+public:
+       typedef Key     key_type;
+       typedef T       mapped_type;
+       typedef pair<const Key, T>      value_type;
+       typedef Compare key_compare;
+       typedef Alloc   allocator_type;
+       typedef typename allocator_type::reference      reference;
+       typedef typename allocator_type::const_reference        const_reference;
+       typedef typename allocator_type::pointer        pointer;
+       typedef typename allocator_type::const_pointer  const_pointer;
+       typedef _bits::map_iterator<value_type,this_type>       iterator;
+       typedef _bits::map_iterator<const value_type,this_type> const_iterator;
+       typedef size_t  size_type;
+
+private:
+       friend class ::std::_bits::map_iterator<value_type, this_type>;
+       friend class ::std::_bits::map_iterator<const value_type, this_type>;
+
+       key_compare     m_comp;
+       allocator_type  m_alloc;
+       value_type*     m_items;        // sorted array
+       size_type       m_size;
+       size_type       m_capacity;
+
+public:
+       map(const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()):
+               m_comp(comp),
+               m_alloc(alloc),
+               m_items(0), m_size(0), m_capacity(0)
+       {
+       }
+       template <class InputInterator>
+       map(InputInterator first, InputInterator last):
+               map()
+       {
+               insert(first, last);
+       }
+       map(const map& x):
+               map(x.m_comp, x.m_alloc)
+       {
+               *this = x;
+       }
+       ~map() {
+               clear();
+               reserve(0);
+       }
+       map& operator=(const map& x) {
+               clear();
+               reserve(x.m_size);
+               for( size_type i = 0; i < x.m_size; i ++ ) {
+                       emplace_hint( end(), x.m_items[i] );
+               }
+               return *this;
+       }
+       
+       // Iterators
+       iterator begin() {
+               return iterator(this, 0);
+       }
+       const_iterator begin() const {
+               return const_iterator(this, 0);
+       }
+       iterator end() {
+               return iterator(this, m_size);
+       }
+       const_iterator end() const {
+               return const_iterator(this, m_size);
+       }
+       #if _CXX11_AVAIL
+       const_iterator cbegin() const {
+               return const_iterator(this, 0);
+       }
+       const_iterator cend() const {
+               return const_iterator(this, m_size);
+       }
+       #endif
+       //reverse_iterator rbegin();
+       //const_reverse_iterator rbegin() const;
+       //const_reverse_iterator crbegin() const;
+       //reverse_iterator rend();
+       //const reverse_iterator rend() const;
+       //const reverse_iterator crend() const;
+       
+       // Capacity
+       bool empty() const {
+               return m_size == 0;
+       }
+       size_type size() const {
+               return m_size;
+       }
+       size_type max_size() const {
+               return (size_type)-1 / sizeof(value_type);
+       }
+       
+       // Element access
+       mapped_type& operator[](const key_type& k) {
+               iterator it = upper_bound(k);
+               if( it == end() || m_comp(k, it->first) ) {     // if k < it->first, no match
+                       insert_at(it.m_index, value_type(k,mapped_type()) );
+               }
+               return it->second;
+       }
+       #if _CXX11_AVAIL
+       mapped_type& at(const key_type& k) {
+               iterator it = lower_bound(k);
+               if( it == end() || m_comp(it->first, k) )
+                       throw ::std::out_of_range("::std:map::at");
+               return it->second;
+       }
+       const mapped_type& at(const key_type& k) const {
+               iterator it = lower_bound(k);
+               if( it == end() || m_comp(it->first, k) )
+                       throw ::std::out_of_range("::std:map::at");
+               return it->second;
+       }
+       #endif
+       
+       // Modifiers
+       // - insert
+       pair<iterator,bool> insert(const value_type& val)
+       {
+               const key_type& k = val.first;
+               iterator it = upper_bound(k);
+               if( it == end() || m_comp(k, it->first) ) {     // if k < it->first, no match
+                       insert_at(it.m_index, val);
+                       return pair<iterator,bool>(it, true);
+               }
+               else {
+                       return pair<iterator,bool>(it, false);
+               }
+       }
+       iterator insert(iterator position, const value_type& val);
+       template <class InputInterator>
+       void insert(InputInterator first, InputInterator last);
+       // - erase
+       void erase(iterator position)
+       {
+               auto pos = position;
+               erase(pos, ++position);
+       }
+       size_type erase(const key_type& k)
+       {
+               auto it = find(k);
+               if( it != end() ) {
+                       erase(it);
+                       return 1;
+               }
+               else {
+                       return 0;
+               }
+       }
+       void erase(iterator first, iterator last)
+       {
+               _libcxx_assert(first.m_index <= last.m_index);
+               unsigned int ofs = first.m_index;
+               unsigned int count = last.m_index - first.m_index;
+               for( unsigned int i = 0; i < count; i ++ )
+               {
+                       // Construct new item
+                       m_alloc.destroy(&m_items[ofs]);
+                       m_size --;
+                       // Move following items down
+                       shift_items(&m_items[ofs+1], &m_items[ofs], m_size-ofs);
+               }
+       }
+       // - swap
+       void swap(map& x);
+       // - clear
+       void clear() {
+               for( size_type i = 0; i < m_size; i ++ ) {
+                       m_alloc.destroy( &m_items[i] );
+               }
+               m_size = 0;
+       }
+       // - emplace
+       #if _CXX11_AVAIL
+       template <class... Args>
+       pair<iterator,bool> emplace(Args&&... args) {
+               return emplace_hint(begin(), args...);
+       }
+       template <class... Args>
+       pair<iterator,bool> emplace_hint(iterator position, Args&&... args);
+       #endif
+       
+       // TODO: Observers
+       
+       // Operators
+       iterator find(const key_type& k) {
+               iterator it = lower_bound(k);
+               if( it == end() || m_comp(it->first, k) )       // if it->first < k
+                       return end();
+               return it;
+       }
+       const_iterator find(const key_type& k) const {
+               const_iterator it = lower_bound(k);
+               if( it == end() || m_comp(it->first, k) )       // if it->first < k
+                       return end();
+               return it;
+       }
+       size_type count(const key_type& k) {
+               if( find(k) == end() )
+                       return 0;
+               return 1;
+       }
+       iterator lower_bound(const key_type& k) {
+               size_type idx;
+               if( _search(k, idx) ) {
+                       // found, return direct iterator
+                       return iterator(this, idx);
+               }
+               else {
+                       // not found, return iterator to before
+                       if( idx == 0 )  return begin();
+                       return iterator(this, idx-1);
+               }
+       }
+       const_iterator lower_bound(const key_type& k) const {
+               size_type idx;
+               if( _search(k, idx) ) {
+                       // found, return direct iterator
+                       return iterator(this, idx);
+               }
+               else {
+                       // not found, return iterator to before
+                       if( idx == 0 )  return begin();
+                       return iterator(this, idx-1);
+               }
+       }
+       iterator upper_bound(const key_type& k) {
+               size_type idx;
+               _search(k, idx);
+               // idx == item or just after it
+               return iterator(this, idx);
+       }
+       const_iterator upper_bound(const key_type& k) const {
+               size_type idx;
+               _search(k, idx);
+               return const_iterator(this, idx);
+       }
+       pair<iterator,iterator> equal_range(const key_type& k);
+       pair<const_iterator,const_iterator> equal_range(const key_type& k) const;
+
+private:
+       // Change reservation to fit 'n' items
+       // - NOTE: Will also resize down
+       void reserve(size_type n) {
+               n = (n + 31) & ~31;
+               if( n > max_size() )
+                       throw ::std::length_error("::std::map::reserve");
+               if( n != m_capacity )
+               {
+                       auto new_area = m_alloc.allocate(n);
+                       for( size_type i = 0; i < m_size && i < n; i ++ )
+                               m_alloc.construct(&new_area[i], m_items[i]);
+                       for( size_type i = n; i < m_size; i ++ )
+                               m_alloc.destroy( &m_items[i] );
+                       m_alloc.deallocate(m_items, m_capacity);
+                       m_items = new_area;
+                       m_capacity = n;
+                       if(m_size > n)
+                               m_size = n;
+               }
+       }
+       // Returns the index above or equal to 'k'
+       // - TODO: Reimplement as a binary search
+       bool _search(const key_type& k, size_type &pos_out) const {
+               #if 0
+               size_type pos = m_size / 2;
+               size_type step = m_size / 4;
+               while( step > 0 ) {
+                       const key_type& item_key = m_items[pos].first;
+                       if( m_comp(item_key, k) )
+                               pos += step;
+                       else if( m_comp(k, item_key) )
+                               pos -= step;
+                       else {
+                               pos_out = pos;
+                               return true;
+                       }
+                       step /= 2;
+               }
+               pos_out = pos;
+               return false;
+               #else
+               //::_sys::debug("map::_search (m_size=%i)", m_size);
+               for( size_type pos = 0; pos < m_size; pos ++ )
+               {
+                       const key_type& item_key = m_items[pos].first;
+                       if( m_comp(item_key, k) ) {
+                               continue;
+                       }
+                       else if( m_comp(k, item_key) ) {
+                               //::_sys::debug("map::_search - Passed %i", pos);
+                               pos_out = pos;
+                               return false;
+                       }
+                       else {
+                               //::_sys::debug("map::_search - Found %i", pos);
+                               pos_out = pos;
+                               return true;
+                       }
+               }
+               //::_sys::debug("map::_search - Off end %i", m_size);
+               pos_out = m_size;
+               return false;
+               #endif
+       }
+       void insert_at(size_type ofs, const value_type& val) {
+               //_libcxx_assert( ofs == 0 || m_comp(m_items[ofs-1].first, val.first) );
+               //_libcxx_assert( ofs == m_size || m_comp(m_items[ofs].first, val.first) );
+               // Resize up
+               reserve( m_size + 1 );
+               // Move following items up
+               shift_items(&m_items[ofs], &m_items[ofs+1], m_size-ofs);
+               // Construct new item
+               m_alloc.construct(&m_items[ofs], val);
+               m_size ++;
+       }
+       void shift_items(value_type *start, value_type *end, size_type count) {
+               if( start < end ) {
+                       for( size_type i = count; i --; ) {
+                               #if _CXX11_AVAIL && 0
+                               m_alloc.construct(&end[i], ::std::move(start[i]));
+                               #else
+                               m_alloc.construct(&end[i], start[i]);
+                               m_alloc.destroy(&start[i]);
+                               #endif
+                       }
+               }
+               else {
+                       for( size_type i = 0; i < count; i ++ ) {
+                       }
+               }
+       }
+};
+
+}      // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/memory b/Usermode/Libraries/libc++.so_src/include_exp/memory
new file mode 100644 (file)
index 0000000..b604fbe
--- /dev/null
@@ -0,0 +1,20 @@
+
+#ifndef _LIBCXX_MEMORY_
+#define _LIBCXX_MEMORY_
+
+namespace std {
+
+template <>
+class allocator<void>
+{
+public:
+  typedef void* pointer;
+  typedef const void* const_pointer;
+  typedef void value_type;
+  template <class U> struct rebind { typedef allocator<U> other; };
+};
+
+}
+
+#endif
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/mutex b/Usermode/Libraries/libc++.so_src/include_exp/mutex
new file mode 100644 (file)
index 0000000..d3d9ffd
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * mutex (header)
+ * - C++11's tutex handling
+ */
+#ifndef _LIBCXX_MUTEX_
+#define _LIBCXX_MUTEX_
+
+#include "_libcxx_helpers.h"
+
+#if !_CXX11_AVAIL
+# error        "<mutex> requires C++11 support"
+#endif
+
+namespace std {
+
+#if _CXX11_AVAIL
+
+class mutex
+{
+public:
+       constexpr mutex() noexcept:
+               m_flag(false)
+       {
+       }
+       mutex(const mutex&) = delete;
+       mutex& operator=(const mutex&) = delete;
+       ~mutex();
+       
+       void lock();
+       bool try_lock();
+       void unlock();
+
+       typedef void*   native_handle;
+private:
+       // TODO: Proper userland mutex support
+       bool    m_flag;
+};
+
+struct defer_lock_t {};
+struct try_to_lock_t {};
+struct adopt_lock_t {};
+
+template< class Mutex >
+class lock_guard
+{
+public:
+       typedef Mutex   mutex_type;
+private:
+       mutex_type&     m_lock;
+public:
+       lock_guard(mutex_type& m):
+               m_lock(m)
+       {
+               m_lock.lock();
+       }
+       lock_guard(mutex_type& m, std::adopt_lock_t t):
+               m_lock(m)
+       {
+               // Adopted
+       }
+       ~lock_guard() {
+               m_lock.unlock();
+       }
+};
+
+#endif
+
+};     // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/new b/Usermode/Libraries/libc++.so_src/include_exp/new
new file mode 100644 (file)
index 0000000..b895832
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * new (header)
+ * - C++'s new operators
+ */
+#ifndef _LIBCXX_NEW_
+#define _LIBCXX_NEW_
+
+
+#include "cstddef"
+
+//extern void* operator new(size_t size) throw (::std::bad_alloc);
+//extern void* operator new(size_t size, const std::nothrow_t& nothrow_value) throw();
+inline void* operator new(size_t /*size*/, void* ptr) throw() {
+       return ptr;
+}
+
+//extern void* operator new[](size_t size) throw (::std::bad_alloc);
+//extern void* operator new[](size_t size, const std::nothrow_t& nothrow_value) throw();
+inline void* operator new[](size_t /*size*/, void* ptr) throw() {
+       return ptr;
+}
+
+#include "exception"
+
+namespace std {
+
+class bad_alloc:
+       public ::std::exception
+{
+public:
+       bad_alloc() noexcept;
+       ~bad_alloc() noexcept;
+       
+       const char *what() const noexcept;
+};
+
+}      // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/stdexcept b/Usermode/Libraries/libc++.so_src/include_exp/stdexcept
new file mode 100644 (file)
index 0000000..7556207
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * string (header)
+ * - C++'s String type
+ */
+#ifndef _LIBCXX_STDEXCEPT_
+#define _LIBCXX_STDEXCEPT_
+
+#include "exception"
+#include "string"
+
+namespace std {
+
+namespace _bits {
+
+class str_except:
+       public exception
+{
+       ::std::string   m_str;
+public:
+       explicit str_except(const string& what_arg);
+       virtual ~str_except() noexcept;
+       str_except& operator= (const str_except& e) noexcept;
+       virtual const char* what() const noexcept;
+};
+
+} // namespace _bits
+
+class logic_error:
+       public _bits::str_except
+{
+public:
+       explicit logic_error(const string& what_arg);
+};
+
+class runtime_error:
+       public _bits::str_except
+{
+public:
+       explicit runtime_error(const string& what_arg);
+};
+
+class out_of_range:
+       public logic_error
+{
+public:
+       explicit out_of_range(const string& what_arg);
+};
+
+class length_error:
+       public logic_error
+{
+public:
+       explicit length_error(const string& what_arg);
+};
+
+};     // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/string b/Usermode/Libraries/libc++.so_src/include_exp/string
new file mode 100644 (file)
index 0000000..f36077d
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * string (header)
+ * - C++'s String type
+ */
+#ifndef _LIBCXX_STRING_
+#define _LIBCXX_STRING_
+
+#include "_libcxx_helpers.h"
+#include <allocator>
+#include <initializer_list>
+
+namespace std {
+
+template <class charT>
+struct char_traits
+{
+};
+
+template <>
+struct char_traits<char>
+{
+       typedef char    char_type;
+       typedef int     int_type;
+       //typedef streamoff     off_type;
+       //typedef streampos     pos_type;
+       //typedef mbstate_t     state_type;
+       
+       static bool eq(const char_type& c, const char_type& d) {
+               return c == d;
+       }
+       static bool lt(const char_type& c, const char_type& d) {
+               return c < d;
+       }
+       static size_t length(const char_type* s) {
+               size_t  ret = 0;
+               while(*s++)     ret ++;
+               return ret;
+       }
+       static int compare (const char_type* p, const char_type* q, size_t n) {
+               while (n--) {
+                       if( !eq(*p,*q) )
+                               return lt(*p,*q) ? -1 : 1;
+                       ++p; ++q;
+               }
+               return 0;
+       }
+};
+
+template <>
+struct char_traits<wchar_t>
+{
+       typedef wchar_t char_type;
+       typedef int     int_type;
+       //typedef streamoff     off_type;
+       //typedef streampos     pos_type;
+       //typedef mbstate_t     state_type;
+       
+       static size_t length(const char_type* s) {
+               size_t  ret = 0;
+               while(*s++)     ret ++;
+               return ret;
+       }
+       static bool eq(const char_type& c, const char_type& d) {
+               return c == d;
+       }
+       static bool lt(const char_type& c, const char_type& d) {
+               return c < d;
+       }
+};
+
+extern void _throw_out_of_range(const char *message);
+
+template < class charT, class traits=char_traits<charT>, class Alloc=allocator<charT> >
+class basic_string
+{
+public:
+       typedef traits  traits_type;
+       typedef Alloc   allocator_type;
+       typedef charT   value_type;
+       typedef typename allocator_type::reference      reference;
+       typedef typename allocator_type::const_reference        const_reference;
+       typedef size_t  size_type;
+       
+       typedef charT*  iterator;
+       typedef const charT*    const_iterator;
+
+private:
+       struct dynamic_info
+       {
+               allocator_type  m_allocator;
+                int    m_ref_count = 1;
+               size_type       m_capacity = 0;
+               size_type       m_size = 0;
+               typename allocator_type::pointer m_data = 0;
+               dynamic_info(const allocator_type& alloc):
+                       m_allocator(alloc)
+               {
+               }
+               dynamic_info(const dynamic_info& other):
+                       m_allocator(other.m_allocator),
+                       m_ref_count(1),
+                       m_capacity(other.m_capacity),
+                       m_size(other.m_size)
+               {
+                       m_data = m_allocator.allocate(m_capacity);
+                       for( size_type i = 0; i < m_size; i ++ )
+                               m_data[i] = other.m_data[i];
+               }
+       };
+
+       allocator_type  m_allocator;
+       dynamic_info    *m_content;
+
+public:
+       basic_string(const allocator_type& alloc = allocator_type()):
+               m_allocator(alloc),
+               m_content(0)
+       {
+       }
+       basic_string(const basic_string& str) throw():
+               basic_string(allocator_type())
+       {
+               *this = str;
+       }
+       #if _CXX11_AVAIL
+       basic_string(basic_string&& str):
+               m_allocator(str.m_allocator),
+               m_content(str.m_content)
+       {
+               str.m_content = 0;
+               ::_sys::debug("basic_string(move) %p %s", m_content, c_str());
+       }
+       #endif
+       basic_string(const basic_string& str, const allocator_type& alloc):
+               basic_string(str, 0, str.length(), alloc)
+       {
+       }
+       basic_string(const basic_string& str, size_type pos, size_type len = npos, const allocator_type& alloc = allocator_type()):
+               basic_string(alloc)
+       {
+               if( pos < str.length() )
+               {
+                       if( len > str.length() - pos )
+                               len = str.length() - pos;
+                       reserve(len);
+                       for( size_type i = 0; i < len; i ++ )
+                               m_content->m_data[i] = str.m_content->m_data[pos+i];
+                       m_content->m_size = len;
+               }
+       }
+       basic_string(const charT *s, const allocator_type& alloc = allocator_type()):
+               basic_string(s, traits::length(s), alloc)
+       {
+       }
+       basic_string(const charT *s, size_type n, const allocator_type& alloc = allocator_type()):
+               basic_string(alloc)
+       {
+               if( n > 0 )
+               {
+                       reserve(n);
+                       for( size_type i = 0; i < n; i ++ )
+                               m_content->m_data[i] = s[i];
+                       m_content->m_data[n] = 0;
+                       m_content->m_size = n;
+               }
+       }
+       basic_string(size_type n, charT c, const allocator_type& alloc = allocator_type()):
+               basic_string(alloc)
+       {
+               if( n > 0 )
+               {
+                       reserve(n);
+                       for( size_type i = 0; i < n; i ++ )
+                               m_content->m_data[i] = c;
+                       m_content->m_data[n] = 0;
+                       m_content->m_size = n;
+               }
+       }
+       #if __cplusplus < 199711L
+       basic_string(basic_string&& str) noexcept:
+               basic_string(allocator_type())
+       {
+       }
+       basic_string(basic_string&& str, const allocator_type& alloc) noexcept:
+               basic_string(alloc)
+       {
+               m_content = str.m_content;
+               str.m_content = 0;
+       }
+       #endif
+       ~basic_string()
+       {
+               release_content();
+       }
+       basic_string& operator=(const basic_string& str) throw() {
+               return assign(str);
+       }
+       basic_string& operator=(const charT* s) {
+               return assign(s);
+       }
+       basic_string& operator=(charT c) {
+               return assign(c);
+       }
+       
+       // iterators
+       
+       // capacity
+       size_type size() const {
+               return m_content ? m_content->m_size : 0;
+       }
+       size_type length() const {
+               return size();
+       }
+       size_type max_size() const {
+               return -1;
+       }
+       void resize(size_type size, charT c = 0) {
+               reserve(size);
+               if( m_content->m_size < size ) {
+                       for( size_type ofs = m_content->m_size; ofs < size; ofs ++ )
+                               m_content->m_data[ofs] = c;
+                       m_content->m_data[size] = 0;
+               }
+               m_content->m_size = size;
+               m_content->m_data[size] = 0;
+       }
+       size_type capacity() const {
+               return m_content ? m_content->m_capacity : 0;
+       }
+       void reserve(size_type size) {
+               own_content();
+               size = (size+1 + 31) & ~31;
+               if( size > m_content->m_capacity ) {
+                       auto new_area = m_allocator.allocate(size);
+                       for( size_type i = 0; i < m_content->m_size; i ++ )
+                               new_area[i] = m_content->m_data[i];
+                       m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
+                       m_content->m_data = new_area;
+                       m_content->m_capacity = size;
+               }
+       }
+       void clear() {
+               own_content();
+               m_content->m_size = 0;
+       }
+       bool empty() const {
+               return length() == 0;
+       }
+       #if _CXX11_AVAIL
+       void shrink_to_fit();
+       #endif
+       
+       // Access
+       reference operator[] (size_type pos) {
+               own_content();
+               return m_content->m_data[pos];
+       }
+       const_reference operator[] (size_type pos) const {
+               return (m_content ? m_content->m_data[pos] : *(const charT*)0);
+       }
+       reference at(size_type pos) {
+               own_content();
+               if(pos >= m_content->m_size)
+                       _throw_out_of_range("basic_string - at");
+               return m_content->m_data[pos];
+       }
+       const_reference at(size_type pos) const {
+               if(!m_content || pos >= m_content.m_size)
+                       _throw_out_of_range("basic_string - at");
+               return m_content->m_data[pos];
+       }
+       #if _CXX11_AVAIL
+       reference back() {
+               own_content();
+               return m_content->m_data[m_content->m_size];
+       }
+       const_reference back() const {
+               return m_content->m_data[m_content->m_size];
+       }
+       reference front() {
+               own_content();
+               return m_content->m_data[0];
+       }
+       const_reference front() const {
+               return m_content->m_data[0];
+       }
+       #endif
+       
+       // Modifiers
+       basic_string& operator +=(const basic_string& str) {
+               return append(str);
+       }
+       basic_string& operator +=(const charT* s) {
+               return append(s);
+       }
+       basic_string& operator +=(charT c) {
+               push_back(c);
+               return *this;
+       }
+       basic_string& append(const basic_string& str) {
+               return append(str, 0, npos);
+       }
+       basic_string& append(const basic_string& str, size_type subpos, size_type sublen) {
+               if(subpos >= str.size())
+                       _throw_out_of_range("basic_string - assign source");
+               if( sublen > str.size() - subpos )
+                       sublen = str.size() - subpos;
+               append( str.data() + subpos, sublen );
+               return *this;
+       }
+       basic_string& append(const charT* s) {
+               return append(s, traits::length(s));
+       }
+       basic_string& append(const charT* s, size_type n) {
+               reserve(size() + n);
+               for( size_type i = 0; i < n; i ++ )
+                       m_content->m_data[size() + i] = s[i];
+               m_content->m_data[size()+n] = '\0';
+               m_content->m_size += n;
+               return *this;
+       }
+       basic_string& append(size_type n, charT c) {
+               reserve(size() + n);
+               for( size_type i = 0; i < n; i ++ )
+                       m_content->m_data[size() + i] = c;
+               m_content->m_data[size()+n] = '\0';
+               m_content->m_size += n;
+               return *this;
+       }
+       void push_back(charT c) {
+               append(1, c);
+       }
+       basic_string& assign(const basic_string& str) throw() {
+               // Special case, triggers copy-on-write.
+               release_content();
+               m_content = str.m_content;
+               m_content->m_ref_count ++;
+               return *this;
+       }
+       basic_string& assign(const basic_string& str, size_type subpos, size_type sublen) {
+               if(subpos >= str.size())
+                       _throw_out_of_range("basic_string - assign source");
+               if( sublen > str.size() - subpos )
+                       sublen = str.size() - subpos;
+               
+               return assign(str.data() + subpos, sublen);
+       }
+       basic_string& assign(const charT* s) {
+               return assign(s, traits::length(s));
+       }
+       basic_string& assign(const charT* s, size_type n) {
+               release_content();
+               reserve(n);
+               for( size_type i = 0; i < n; i ++ )
+                       m_content->m_data[i] = s[i];
+               m_content->m_data[n] = '\0';
+               m_content->m_size = n;
+               return *this;
+       }
+       basic_string& assign(size_type n, charT c) {
+               release_content();
+               reserve(n);
+               for( size_type i = 0; i < n; i ++ )
+                       m_content->m_data[i] = c;
+               m_content->m_data[n] = '\0';
+               m_content->m_size = n;
+               return *this;
+       }
+       
+       basic_string& insert(size_type pos, const basic_string& str);
+       basic_string& insert(size_type pos, const basic_string& str, size_type subpos, size_type sublen);
+       basic_string& insert(size_type pos, const charT& s);
+       basic_string& insert(size_type pos, const charT& s, size_type n);
+       basic_string& insert(size_type pos, size_type n, charT c);
+       iterator insert(const_iterator p, size_type n, charT c);
+       iterator insert(const_iterator p, charT c);
+       template <class InputIterator>
+       iterator insert(iterator p, InputIterator first, InputIterator last);
+       #if _CXX11_AVAIL
+       basic_string& insert(const_iterator p, initializer_list<charT> il);
+       #endif
+       
+       basic_string& erase(size_type pos = 0, size_type len = npos);
+       iterator erase(const_iterator p);
+       iterator erase(const_iterator first, const_iterator last);
+       
+       basic_string& replace(size_type pos, size_type len, const basic_string& str);
+       basic_string& replace(const_iterator i1, const_reference i2, const basic_string& str);
+       basic_string& replace(size_type pos, size_type len, const basic_string& str, size_type subpos, size_type sublen);
+       basic_string& replace(size_type pos, size_type len, const charT *s);
+       basic_string& replace(const_iterator i1, const_reference i2, const charT* s);
+       basic_string& replace(size_type pos, size_type len, const charT *s, size_type n);
+       basic_string& replace(const_iterator i1, const_reference i2, const charT* s, size_type n);
+       basic_string& replace(size_type pos, size_type len, size_type n, charT c);
+       basic_string& replace(const_iterator i1, const_reference i2, size_type n, charT c);
+       template <class InputIterator>
+       basic_string& replace(const_iterator i1, const_reference i2, InputIterator first, InputIterator last);
+       basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<charT> il);
+       
+       void swap(basic_string& str)
+       {
+               auto tmp = m_content;
+               m_content = str.m_content;
+               str.m_content = tmp;
+       }
+       
+       #if _CXX11_AVAIL
+       void pop_back();
+       #endif
+       
+       // String operations
+       const charT *c_str() const noexcept
+       {
+               // TODO: this is const, but also might need to do processing
+               if(m_content) {
+                       _libcxx_assert(m_content->m_data[m_content->m_size] == '\0');
+               }
+               return (m_content ? m_content->m_data : "");
+       }
+       const charT *data() const
+       {
+               return (m_content ? m_content->m_data : NULL);
+       }
+       allocator_type get_allocator() const noexcept
+       {
+               return m_allocator;
+       }
+       size_type copy(charT* s, size_type len, size_type pos = 0) const;
+       
+       size_type find(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find(const charT* s, size_type pos = 0) const;
+       size_type find(const charT* s, size_type pos, size_type n) const;
+       size_type find(charT c, size_type pos = 0) const noexcept;
+       
+       size_type rfind(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type rfind(const charT* s, size_type pos = 0) const;
+       size_type rfind(const charT* s, size_type pos, size_type n) const;
+       size_type rfind(charT c, size_type pos = 0) const noexcept;
+       
+       size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find_first_of(const charT* s, size_type pos = 0) const;
+       size_type find_first_of(const charT* s, size_type pos, size_type n) const;
+       size_type find_first_of(charT c, size_type pos = 0) const noexcept;
+       
+       size_type find_last_of(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find_last_of(const charT* s, size_type pos = 0) const;
+       size_type find_last_of(const charT* s, size_type pos, size_type n) const;
+       size_type find_last_of(charT c, size_type pos = 0) const noexcept;
+
+       size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find_first_not_of(const charT* s, size_type pos = 0) const;
+       size_type find_first_not_of(const charT* s, size_type pos, size_type n) const;
+       size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
+
+       size_type find_last_not_of(const basic_string& str, size_type pos = 0) const noexcept;
+       size_type find_last_not_of(const charT* s, size_type pos = 0) const;
+       size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
+       size_type find_last_not_of(charT c, size_type pos = 0) const noexcept;
+
+       basic_string substr(size_type pos = 0, size_type len = npos) const;
+       
+       int compare(const basic_string& str) const noexcept {
+               return compare(0, size(), str.data(), str.size());
+       }
+       int compare(size_type pos, size_type len, const basic_string& str) const {
+               _libcxx_assert(pos <= size());
+               _libcxx_assert(len <= size());
+               _libcxx_assert(pos+len <= size());
+               return compare(pos, len, str.data(), str.size());
+       }
+       int compare(size_type pos, size_type len, const basic_string& str, size_type subpos, size_type sublen) const {
+               // TODO: check
+               _libcxx_assert(subpos <= str.size());
+               _libcxx_assert(sublen <= str.size());
+               _libcxx_assert(subpos+sublen <= str.size());
+               return compare(pos, len, str.data()+subpos, sublen);
+       }
+       int compare(const charT* s) const {
+               return compare(0, npos, s, traits::length(s));
+       }
+       int compare(size_type pos, size_type len, const charT* s) const {
+               return compare(pos, len, s, traits::length(s));
+       }
+       int compare(size_type pos, size_type len, const charT* s, size_type n) const {
+               if( n <= len ) {
+                       int rv = traits::compare(data()+pos, s, n);
+                       if( rv == 0 && n < len ) {
+                               rv = -1;
+                       }
+                       return rv;
+               }
+               else {
+                       int rv = traits::compare(data()+pos, s, len);
+                       if(rv == 0) {
+                               rv = 1;
+                       }
+                       return rv;
+               }
+       }
+       
+       static const size_type npos = -1;
+private:
+       void own_content() {
+               if(!m_content)
+               {
+                       m_content = new dynamic_info(m_allocator);
+               }
+               else if( m_content->m_ref_count > 1 )
+               {
+                       dynamic_info *new_cont = new dynamic_info(*m_content);
+                       m_content->m_ref_count --;
+                       m_content = new_cont;
+               }
+               else
+               {
+                       // already owned
+               }
+       }
+       void release_content() {
+               if( m_content )
+               {
+                       m_content->m_ref_count --;
+                       if( m_content->m_ref_count == 0 ) {
+                               m_allocator.deallocate(m_content->m_data, m_content->m_capacity);
+                               delete m_content;
+                       }
+                       m_content = NULL;
+               }
+       }
+};
+
+typedef basic_string<char>     string;
+
+#define _libcxx_str    basic_string<charT,traits,Alloc>
+
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const basic_string<charT,traits,Alloc>& rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(lhs.size() + rhs.size());
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT* rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(lhs.size() + traits::length(rhs));
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const charT* lhs, const basic_string<charT,traits,Alloc>& rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(traits::length(lhs) + rhs.size());
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const basic_string<charT,traits,Alloc>& lhs, const charT rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(lhs.size() + 1);
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+template <class charT, class traits, class Alloc>
+basic_string<charT,traits,Alloc> operator+(const charT lhs, const basic_string<charT,traits,Alloc>& rhs)
+{
+       basic_string<charT,traits,Alloc>        ret;
+       ret.reserve(1 + rhs.size());
+       ret += lhs;
+       ret += rhs;
+       return ret;
+}
+
+// Three overloads each
+// name: Actual operator, opp: reversed operator
+#define _libcxx_string_def_cmp(name, opp) \
+       template <class charT, class traits, class Alloc> \
+       bool operator name(const _libcxx_str& lhs, const _libcxx_str& rhs) { return lhs.compare(rhs) name 0; } \
+       template <class charT, class traits, class Alloc> \
+       bool operator name(const charT* lhs, const _libcxx_str& rhs) { return rhs.compare(lhs) opp 0; } \
+       template <class charT, class traits, class Alloc> \
+       bool operator name(const _libcxx_str& lhs, const charT* rhs) { return lhs.compare(rhs) name 0; }
+
+_libcxx_string_def_cmp(<, >)
+_libcxx_string_def_cmp(<=, >=)
+_libcxx_string_def_cmp(==, ==)
+_libcxx_string_def_cmp(>=, <=)
+_libcxx_string_def_cmp(>, <)
+};
+
+#endif
+
+// vim: ft=cpp
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/system_error b/Usermode/Libraries/libc++.so_src/include_exp/system_error
new file mode 100644 (file)
index 0000000..496970e
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * system_error (header)
+ * - C++11's system_error exception
+ */
+#ifndef _LIBCXX_SYSTEM_ERROR_
+#define _LIBCXX_SYSTEM_ERROR_
+
+#include "_libcxx_helpers.h"
+
+#if !_CXX11_AVAIL
+# error "This header requires C++11 support enabled"
+#endif
+
+#include <exception>
+#include <string>
+
+namespace std {
+
+class error_category;
+class error_condition;
+class error_code;
+
+static bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept;
+static bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept;
+static bool operator< (const error_condition& lhs, const error_condition& rhs) noexcept;
+static bool operator==(const error_condition& lhs, const error_code& rhs) noexcept;
+static bool operator==(const error_code& lhs, const error_condition& rhs) noexcept;
+static bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept;
+static bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept;
+
+extern const error_category&   generic_category() noexcept;
+extern const error_category&   system_category() noexcept;
+
+class error_condition
+{
+        int    m_val;
+       const error_category*   m_cat;
+public:
+       error_condition() noexcept:
+               error_condition(0, ::std::generic_category())
+       {
+       }
+       error_condition(int val, const error_category& cat) noexcept:
+               m_val(val),
+               m_cat(&cat)
+       {
+       }
+       //template <class ErrorConditionEnum> error_condition(ErrorConditionEnum e) noexcept;
+       //template <class ErrorConditionEnum> error_condition& operator=(ErrorConditionEnum e) noexcept;
+       void assign(int val, const error_category& cat) noexcept {
+               m_val = val;
+               m_cat = &cat;
+       }
+       void clear() noexcept {
+               assign(0, ::std::generic_category());
+       }
+       int value() const noexcept {
+               return m_val;
+       }
+       const error_category& category() const noexcept {
+               return *m_cat;
+       }
+       string message() const;
+       explicit operator bool() const noexcept {
+               return m_val != 0;
+       }
+};
+
+class error_category
+{
+public:
+       error_category() {
+       }
+       error_category(const error_category&) = delete; // disallow copying
+       virtual ~error_category() noexcept {
+       }
+       bool operator==(const error_category& rhs) const noexcept {
+               return this == &rhs;
+       }
+       bool operator!=(const error_category& rhs) const noexcept {
+               return !(*this == rhs);
+       }
+       bool operator<(const error_category& rhs) const noexcept {
+               return this < &rhs;
+       }
+       virtual const char* name() const noexcept = 0;
+       virtual error_condition default_error_condition(int val) const noexcept {
+               return error_condition(val, *this);
+       }
+       virtual bool equivalent(int valcode, const ::std::error_condition& cond) const noexcept {
+               return default_error_condition(valcode) == cond;
+       }
+       virtual bool equivalent(const error_code& code, int valcond) const noexcept;    // in system_error.cc
+       virtual ::std::string message(int val) const = 0;
+};
+
+class error_code
+{
+       int     m_ev;
+       const ::std::error_category*    m_ecat;
+public:
+       error_code() noexcept:
+               error_code(0, ::std::generic_category())
+       {
+       }
+       error_code(int ev, const ::std::error_category& ecat) noexcept:
+               m_ev(ev),
+               m_ecat(&ecat)
+       {
+       }
+       //template <class ErrorCodeEnum>
+       //error_code(ErrorCodeEnum e) noexcept;
+       void assign(int val, const error_category& ecat) noexcept {
+               m_ev = val;
+               m_ecat = &ecat;
+       }
+       //template <class ErrorCodeEnum>
+       //error_code& operator= (ErrorCodeEnum e) noexcept;
+       void clear() noexcept {
+               m_ev = 0;
+               m_ecat = 0;
+       }
+       int value() const noexcept {
+               return m_ev;
+       }
+       const error_category& category() const noexcept {
+               return *m_ecat;
+       }
+       error_condition default_error_condition() const noexcept {
+               return category().default_error_condition(value());
+       }
+       ::std::string message() const {
+               return category().message(value());
+       }
+       operator bool() const noexcept {
+               return m_ev != 0;
+       }
+};
+
+class system_error:
+       public ::std::exception
+{
+       const error_code        m_error_code;
+       ::std::string   m_what_str;
+public:
+       system_error(::std::error_code ec);
+       system_error(::std::error_code ec, const ::std::string& what_arg);
+       system_error(::std::error_code ec, const char* what_arg);
+       system_error(int ev, const ::std::error_category& ecat);
+       system_error(int ev, const ::std::error_category& ecat, const ::std::string& what_arg);
+       system_error(int ev, const ::std::error_category& ecat, const char* what_arg);
+       ~system_error() noexcept;
+       
+       const char* what() const noexcept;
+};
+
+static inline bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept {
+       return lhs.category() == rhs.category() && lhs.value() == rhs.value();
+}
+static inline bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept {
+       return !(lhs == rhs);
+}
+static inline bool operator< (const error_condition& lhs, const error_condition& rhs) noexcept {
+       return lhs.category() < rhs.category() || lhs.value() < rhs.value();
+}
+static inline bool operator==(const error_condition& lhs, const error_code& rhs) noexcept {
+       return lhs.category().equivalent(rhs, lhs.value()) || rhs.category().equivalent(rhs.value(), lhs);
+}
+static inline bool operator==(const error_code& lhs, const error_condition& rhs) noexcept {
+       return lhs.category().equivalent(lhs.value(),rhs) || rhs.category().equivalent(lhs,rhs.value());
+}
+static inline bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept {
+       return !(lhs == rhs);
+}
+static inline bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept {
+       return !(lhs == rhs);
+}
+
+
+
+};     // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/type_traits b/Usermode/Libraries/libc++.so_src/include_exp/type_traits
new file mode 100644 (file)
index 0000000..62103ac
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * type_traits (header)
+ * - C++11 type traits
+ */
+#ifndef _LIBCXX_TYPE_TRAITS_
+#define _LIBCXX_TYPE_TRAITS_
+
+#include "_libcxx_helpers.h"
+
+#if !_CXX11_AVAIL
+# error "This header requires C++11 support enabled"
+#endif
+
+template <class T> struct remove_reference     { typedef T     type; };
+template <class T> struct remove_reference<T&> { typedef T     type; };
+template <class T> struct remove_reference<T&&>        { typedef T     type; };
+
+#endif
+
+// vim: ft=cpp
+
index c02d388..c8b037c 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _LIBCXX__TYPEINFO_
 #define _LIBCXX__TYPEINFO_
 
+#include <cstddef>
+
 namespace std {
 
 // Type information class
@@ -19,9 +21,16 @@ public:
        bool operator!=(const type_info &) const;
        bool before(const type_info &) const;
        const char* name() const;
+       
+       // acess
+       bool __is_child(const type_info &, size_t&) const;
 private:
        type_info (const type_info& rhs);
        type_info& operator= (const type_info& rhs);
+
+       // acess
+       bool is_class() const;
+       bool is_subclass() const;
        
        // CXX ABI
        const char *__type_name;
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/utility b/Usermode/Libraries/libc++.so_src/include_exp/utility
new file mode 100644 (file)
index 0000000..b3e40c5
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * string (header)
+ * - C++'s String type
+ */
+#ifndef _LIBCXX_UTILITY_
+#define _LIBCXX_UTILITY_
+
+#include "_libcxx_helpers.h"
+#include "type_traits"
+
+namespace std {
+
+template <class T1, class T2>
+class pair
+{
+public:
+       typedef T1      first_type;
+       typedef T2      second_type;
+       
+       first_type      first;
+       second_type     second;
+       
+       pair()
+       {
+       }
+       template <class U, class V>
+       pair(const pair<U,V>& pr):
+               first (pr.first),
+               second(pr.second)
+       {
+       }
+       pair(const first_type& a, const second_type& b):
+               first (a),
+               second(b)
+       {
+       }
+       pair(const pair& pr):
+               first(pr.first),
+               second(pr.second)
+       {
+       }
+       pair(pair&& pr):
+               first(pr.first), second(pr.second)
+       {
+       }
+       // operator = is implicit
+       pair& operator=(const pair& x) {
+               first  = x.first;
+               second = x.second;
+               return *this;
+       }
+};
+
+template <class T1, class T2>  
+bool operator== (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs) {
+       return lhs.first == rhs.first && lhs.second == rhs.second;
+}
+template <class T1, class T2>  
+bool operator!= (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs) {
+       return !(lhs == rhs);
+}
+
+#if _CXX11_AVAIL
+template <class T>
+T&& forward(typename remove_reference<T>::type& arg) noexcept {
+       return static_cast<decltype(arg)&&>(arg);
+}
+template <class T>
+T&& forward(typename remove_reference<T>::type&& arg) noexcept {
+       return static_cast<decltype(arg)&&>(arg);
+}
+
+template <class T>
+typename remove_reference<T>::type&& move( T&& t) noexcept {
+       return static_cast<typename remove_reference<T>::type&&>(t);
+}
+//template <class T>
+//constexpr typename ::std::remove_reference<T>::type&& move( T&& t) noexcept {
+//     return static_cast<typename ::std::remove_reference<T>::type&&>(t);
+//}
+#endif
+
+};     // namespace std
+
+#endif
+
+// vim: ft=cpp
+
diff --git a/Usermode/Libraries/libc++.so_src/include_exp/vector b/Usermode/Libraries/libc++.so_src/include_exp/vector
new file mode 100644 (file)
index 0000000..ab42c9c
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * vector (header)
+ * - C++'s vector (dynamic array) type
+ */
+#ifndef _LIBCXX_VECTOR_
+#define _LIBCXX_VECTOR_
+
+#include <allocator>
+#include <stdexcept>
+#include <initializer_list>
+
+extern "C" void _SysDebug(const char *, ...);
+
+namespace std {
+
+namespace _bits {
+template <class VectorType, class T>
+class vector_iterator//:
+       //public random_acess_iterator_tag
+{
+       friend VectorType;
+       
+       typedef typename VectorType::size_type  size_type;
+       typedef typename VectorType::difference_type    difference_type;
+       
+       T*      m_array;
+       size_type       m_pos;
+       size_type       m_max;
+public:
+       vector_iterator():
+               vector_iterator(0,0,0)
+       {
+       }
+       vector_iterator(const vector_iterator& x):
+               vector_iterator()
+       {
+               *this = x;
+       }
+       vector_iterator(T* array, size_type start, size_type max):
+               m_array(array),
+               m_pos(start),
+               m_max(max)
+       {
+       }
+       vector_iterator& operator=(const vector_iterator& x)
+       {
+               m_array = x.m_array;
+               m_pos = x.m_pos;
+               m_max = x.m_max;
+               return *this;
+       }
+       bool operator==(const vector_iterator& other) const {
+               return m_pos == other.m_pos;
+       }
+       bool operator!=(const vector_iterator& other) const {
+               return !(*this == other);
+       }
+       T& operator*() const {
+               return m_array[m_pos];
+       }
+       T& operator->() const {
+               return m_array[m_pos];
+       }
+       T& operator[](difference_type n) {
+               return *(*this + n);
+       }
+       vector_iterator& operator++() {
+               if(m_pos < m_max) {
+                       m_pos ++;
+               }
+               return *this;
+       }
+       const vector_iterator operator++(int) {
+               vector_iterator ret(*this);
+               ++*this;
+               return ret;
+       }
+       vector_iterator& operator--() {
+               if(m_pos > 0) {
+                       m_pos --;
+               }
+               return *this;
+       }
+       const vector_iterator operator--(int) {
+               vector_iterator ret(*this);
+               --*this;
+               return ret;
+       }
+       vector_iterator& operator+=(difference_type n) {
+               if( n < 0 )
+                       return (*this -= -n);
+               if( n > 0 )
+                       m_pos = (m_pos + n < m_max ? m_pos + n : m_max); 
+               return *this;
+       }
+       vector_iterator& operator-=(difference_type n) {
+               if( n < 0 )
+                       return (*this += -n);
+               if( n > 0 )
+                       m_pos = (m_pos >= n ? m_pos - n : 0);
+               return *this;
+       }
+       const difference_type operator-(const vector_iterator& it2) const {
+               //_libcxx_assert(m_array == it2.m_array);
+               return m_pos - it2.m_pos;
+       }
+       bool operator<(const vector_iterator& o) const { return m_pos < o.m_pos; }
+       bool operator>(const vector_iterator& o) const { return m_pos > o.m_pos; }
+       bool operator<=(const vector_iterator& o) const { return m_pos <= o.m_pos; }
+       bool operator>=(const vector_iterator& o) const { return m_pos >= o.m_pos; }
+};
+#define vector_iterator_tpl class VectorType, class T
+#define vector_iterator        vector_iterator<VectorType, T>
+template <vector_iterator_tpl>
+const vector_iterator operator+(const vector_iterator& it, typename VectorType::difference_type n) {
+       return vector_iterator(it) += n;
+}
+template <vector_iterator_tpl>
+const vector_iterator operator+(typename VectorType::difference_type n, const vector_iterator& it) {
+       return vector_iterator(it) += n;
+}
+template <vector_iterator_tpl>
+const vector_iterator operator-(const vector_iterator& it, typename VectorType::difference_type n) {
+       return vector_iterator(it) -= n;
+}
+#undef vector_iterator_tpl
+#undef vector_iterator
+
+}
+
+template <class T, class Alloc = allocator<T> >
+class vector
+{
+public:
+       typedef T       value_type;
+       typedef Alloc   allocator_type;
+       typedef typename allocator_type::reference      reference;
+       typedef typename allocator_type::const_reference        const_reference;
+       typedef typename allocator_type::pointer        pointer;
+       typedef typename allocator_type::const_pointer  const_pointer;
+       typedef int     difference_type;
+       typedef size_t  size_type;
+       typedef ::std::_bits::vector_iterator<vector,T> iterator;
+       typedef ::std::_bits::vector_iterator<vector,const T>   const_iterator;
+
+private:
+       allocator_type  m_alloc;
+       size_type       m_size;
+       size_type       m_capacity;
+       value_type*     m_data;
+
+public:        
+       vector(const allocator_type& alloc = allocator_type()):
+               m_alloc(alloc),
+               m_size(0),
+               m_capacity(0),
+               m_data(0)
+       {
+       }
+       vector(size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type()):
+               vector(alloc)
+       {
+               resize(n, val);
+       }
+       template <class InputIterator>
+       vector(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()):
+               vector(alloc)
+       {
+               insert(begin(), first, last);
+       }
+       vector(const vector& x):
+               vector(x.m_alloc)
+       {
+               *this = x;
+       }
+       #if _CXX11_AVAIL
+       vector(vector&& x):
+               m_alloc(x.m_alloc),
+               m_size(x.m_size),
+               m_capacity(x.m_capacity),
+               m_data(x.m_data)
+       {
+               x.m_data = nullptr;
+               x.m_capacity = 0;
+               x.m_size = 0;
+       }
+       vector(vector&& x, const allocator_type& alloc):
+               m_alloc(alloc),
+               m_size(x.m_size),
+               m_capacity(x.m_capacity),
+               m_data(x.m_data)
+       {
+               x.m_data = nullptr;
+               x.m_capacity = 0;
+               x.m_size = 0;
+       }
+       vector(std::initializer_list<value_type> il, const allocator_type& alloc = allocator_type()):
+               vector(alloc)
+       {
+               reserve(il.size());
+               insert(begin(), il.begin(), il.end());
+       }
+       #endif
+       vector& operator=(const vector& x)
+       {
+               clear();
+               m_alloc.deallocate(m_data, m_capacity);
+               m_capacity = 0;
+               m_data = nullptr;
+               
+               reserve(x.size());
+               for( size_type i = 0; i < x.size(); i ++ )
+                       push_back( x[i] );
+               
+               return *this;
+       }
+       
+       ~vector()
+       {
+               clear();
+               m_alloc.deallocate(m_data, m_capacity);
+               m_capacity = 0;
+               m_data = nullptr;
+       }
+       
+       // Iterators
+       iterator       begin()       { return iterator_to(0); }
+       const_iterator begin() const { return iterator_to(0); }
+       iterator       end()       { return iterator_to(m_size); }
+       const_iterator end() const { return iterator_to(m_size); }
+       
+       // Capacity
+       size_type size() const {
+               return m_size;
+       }
+       size_type max_size() const {
+               return -1 / sizeof(value_type);
+       }
+       void resize(size_type new_cap, value_type val = value_type()) {
+               reserve(new_cap);
+               if( new_cap > m_size )
+               {
+                       for( size_type i = m_size; i < new_cap; i ++ ) {
+                               m_alloc.construct( &m_data[i], val );
+                       }
+               }
+               else
+               {
+                       for( size_type i = new_cap; i < m_size; i ++ )
+                               m_alloc.destroy( &m_data[i] );
+               }
+               m_size = new_cap;
+       }
+       size_type capacity() const {
+               return m_capacity;
+       }
+       bool empty() const {
+               return m_size == 0;
+       }
+       void reserve(size_type n) {
+               if( n > max_size() )
+                       throw ::std::length_error("::std::vector::reserve");
+               if( n > m_capacity )
+               {
+                       size_type size = (n + 0x1F) & ~0x1F;
+                       auto new_area = m_alloc.allocate(size);
+                       for( size_type i = 0; i < m_size; i ++ )
+                               new_area[i] = m_data[i];
+                       m_alloc.deallocate(m_data, m_capacity);
+                       m_data = new_area;
+                       m_capacity = size;
+                       //::_SysDebug("::std::vector::resize - m_capacity=%i for n=%i", m_capacity, n);
+               }
+       }
+       void shrink_to_fit() {
+       }
+       
+       // Element access
+       reference operator[] (size_type n) {
+               return m_data[n];
+       }
+       const_reference operator[] (size_type n) const {
+               return m_data[n];
+       }
+       reference at(size_type n) {
+               if(n > size())
+                       _throw_out_of_range("::std::vector - at");
+               return m_data[n];
+       }
+       const_reference at(size_type n) const {
+               if(n > size())
+                       _throw_out_of_range("::std::vector - at");
+               return m_data[n];
+       }
+       reference front() {
+               return m_data[0];
+       }
+       const_reference front() const {
+               return m_data[0];
+       }
+       reference back() {
+               return m_data[size()-1];
+       }
+       const_reference back() const {
+               return m_data[size()-1];
+       }
+       pointer data() noexcept {
+               return m_data;
+       }
+       const_pointer data() const noexcept {
+               return m_data;
+       }
+       
+       // Modifiers
+       void assign(size_type n, const value_type& val) {
+               clear();
+               resize(n, val);
+       }
+       void push_back(const value_type& val) {
+               resize(size()+1, val);
+       }
+       void pop_back() {
+               if( !empty() ) {
+                       resize(size()-1);
+               }
+       }
+       iterator insert(iterator position, const value_type& val) {
+               insert(position, 1, val);
+               return iterator_to(position.m_pos);
+       }
+       void insert(iterator position, size_type n, const value_type& val) {
+               reserve(m_size + n);
+               if( position != end() ) {
+                       ::_sys::debug("TODO: vector::insert within vector (%i!=%i)",
+                               position-begin(), end()-begin());
+                       ::_sys::abort();
+               }
+               size_type       pos = m_size;
+               while( n -- )
+               {
+                       //::_sys::debug("vector::insert - %x at %i", val, pos);
+                       m_alloc.construct( &m_data[pos], val );
+                       pos ++;
+                       m_size ++;
+               }
+       }
+       template <class InputIterator>
+       void insert(iterator position, InputIterator first, InputIterator last) {
+               InputIterator   it = first;
+               size_type       len = 0;
+               while(it != last) {
+                       ++ it;
+                       len ++;
+               }
+               reserve(m_size + len);
+               
+               it = first;
+               while(it != last)
+               {
+                       //::_sys::debug("vector::insert - to %i, from %p:%i",
+                       //      position.m_pos, it.m_array, it.m_pos);
+                       position = insert(position, *it) + 1;
+                       ++it;
+               }
+       }
+       iterator erase(iterator position);
+       iterator erase(iterator first, iterator last);
+       //void swap(vector& x) {
+       //      ::std::swap(m_size, x.m_size);
+       //      ::std::swap(m_capacity, x.m_capacity);
+       //      ::std::swap(m_data, x.m_data);
+       //}
+       void clear() {
+               for( size_type i = 0; i < m_size; i ++ ) {
+                       m_alloc.destroy( &m_data[i] );
+               }
+               m_size = 0;
+       }
+private:
+       iterator iterator_to(size_type index) {
+               _libcxx_assert(index <= m_size);
+               return iterator(m_data, index, m_size);
+       }
+       const_iterator iterator_to(size_type index) const {
+               _libcxx_assert(index <= m_size);
+               return const_iterator(m_data, index, m_size);
+       }
+};
+
+};     // namespace std
+
+#endif
+// vim: ft=cpp
+
index ed0a2eb..2ce7a51 100644 (file)
@@ -6,9 +6,13 @@
  * - Miscelanious functions
  */
 #include <string.h>
+#include <acess/sys.h>
+#include <exception>
 
 extern "C" int SoMain()
 {
+       //extern void _init();
+       //_init();
        // nope
        return 0;
 }
@@ -16,11 +20,8 @@ extern "C" int SoMain()
 extern "C" void __cxa_pure_virtual()
 {
        // dunno
-}
-
-extern "C" void __gxx_personality_v0()
-{
-       // TODO: Handle __gxx_personality_v0 somehow
+       ::_SysDebug("__cxa_pure_virtual by %p", __builtin_return_address(0));
+       ::std::terminate();
 }
 
 
diff --git a/Usermode/Libraries/libc++.so_src/mutex.cc b/Usermode/Libraries/libc++.so_src/mutex.cc
new file mode 100644 (file)
index 0000000..5ff27df
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * mutex.cc
+ * - ::std::mutex and helpers
+ */
+#include <mutex>
+#include <system_error>
+#include <cerrno>
+
+// === CODE ===
+::std::mutex::~mutex()
+{
+       
+}
+
+void ::std::mutex::lock()
+{
+       if( m_flag )
+       {
+               _sys::debug("TODO: userland mutexes");
+               throw ::std::system_error(ENOTIMPL, ::std::system_category());
+       }
+       m_flag = true;
+}
+
+bool ::std::mutex::try_lock()
+{
+       bool rv = m_flag;
+       m_flag = true;
+       return !rv;
+}
+
+void ::std::mutex::unlock()
+{
+       m_flag = false;
+}
+
index 1d09fbc..f1ebc45 100644 (file)
@@ -7,25 +7,51 @@
  */
 #include <stddef.h>
 #include <stdlib.h>
+#include <acess/sys.h>
+#include <new>
+
+// === IMPORTS ===
+extern "C" bool        _libc_free(void *mem);  // from libc.so, actual free.
 
 // === CODE ===
 void *operator new( size_t size )
 {
+       //_SysDebug("libc++ - operator new(%i)", size);
        return malloc( size );
 }
 
 void *operator new[]( size_t size )
 {
+       //_SysDebug("libc++ - operator new[](%i)", size);
        return malloc( size );
 }
 
 void operator delete(void *ptr)
 {
-       free(ptr);
+       if( !_libc_free(ptr) ) {
+               _SysDebug("delete of invalid by %p", __builtin_return_address(0));
+               throw ::std::bad_alloc();
+       }
 }
 
 void operator delete[](void *ptr)
 {
-       free(ptr);
+       if( !_libc_free(ptr) ) {
+               _SysDebug("delete[] of invalid by %p", __builtin_return_address(0));
+               throw ::std::bad_alloc();
+       }
+}
+
+
+::std::bad_alloc::bad_alloc() noexcept
+{
+}
+::std::bad_alloc::~bad_alloc() noexcept
+{
+}
+
+const char *::std::bad_alloc::what() const noexcept
+{
+       return "allocation failure";
 }
 
diff --git a/Usermode/Libraries/libc++.so_src/string.cc b/Usermode/Libraries/libc++.so_src/string.cc
new file mode 100644 (file)
index 0000000..f063e34
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * exceptions.cc
+ * - ::std::exception and friends
+ */
+#include <string>
+#include <stdexcept>
+
+void ::std::_throw_out_of_range(const char *message)
+{
+       throw ::std::out_of_range( ::std::string(message) );
+}
+
diff --git a/Usermode/Libraries/libc++.so_src/system_error.cc b/Usermode/Libraries/libc++.so_src/system_error.cc
new file mode 100644 (file)
index 0000000..9a9fb4d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Acess2 C++ Library
+ * - By John Hodge (thePowersGang)
+ *
+ * system_error.cc
+ * - ::std::system_error and other helpers
+ */
+#include <system_error>
+#include <cerrno>
+
+namespace std {
+
+system_error::system_error(::std::error_code ec):
+       m_error_code(ec),
+       m_what_str( (::std::string)ec.category().name() + ":" + ec.message())
+{
+       ::_sys::debug("system_error(%s:%s)", ec.category().name(), ec.message().c_str());
+}
+system_error::system_error(::std::error_code ec, const ::std::string& what_arg):
+       system_error(ec)
+{
+       m_what_str += " - ";
+       m_what_str += what_arg;
+}
+system_error::system_error(::std::error_code ec, const char* what_arg):
+       system_error(ec)
+{
+       m_what_str += " - ";
+       m_what_str += what_arg;
+}
+system_error::system_error(int ev, const ::std::error_category& ecat):
+       system_error( ::std::error_code(ev, ecat) )
+{
+}
+system_error::system_error(int ev, const ::std::error_category& ecat, const ::std::string& what_arg):
+       system_error(ev, ecat)
+{
+       m_what_str += " - ";
+       m_what_str += what_arg;
+}
+system_error::system_error(int ev, const ::std::error_category& ecat, const char* what_arg):
+       system_error(ev, ecat)
+{
+       m_what_str += " - ";
+       m_what_str += what_arg;
+}
+
+system_error::~system_error() noexcept
+{
+}
+
+const char* system_error::what() const noexcept
+{
+       return m_what_str.c_str();
+}
+
+
+bool error_category::equivalent(const error_code& code, int valcond) const noexcept {
+       return *this == code.category() && code.value() == valcond;
+}
+
+
+class class_generic_category:
+       public error_category
+{
+public:
+       class_generic_category() {
+       }
+       ~class_generic_category() noexcept {
+       }
+       const char *name() const noexcept {
+               return "generic";
+       }
+       ::std::string message(int val) const {
+               return ::std::string( ::strerror(val) );
+       }
+} g_generic_category;
+
+const ::std::error_category& generic_category() noexcept
+{
+       return g_generic_category;
+}
+
+
+class class_system_category:
+       public error_category
+{
+public:
+       class_system_category() {
+       }
+       ~class_system_category() noexcept {
+       }
+       const char *name() const noexcept {
+               return "system";
+       }
+       ::std::string message(int val) const {
+               return ::std::string( ::strerror(val) );
+       }
+} g_system_category;
+
+const ::std::error_category& system_category() noexcept
+{
+       return g_system_category;
+}
+
+};     // namespace std
+
index b0a9b3e..99bfedc 100644 (file)
@@ -6,6 +6,9 @@
  * - typeid and dynamic_cast
  */
 #include <typeinfo>
+#include <cxxabi.h>
+#include <acess/sys.h>
+#include <cstdlib>
 
 namespace std {
 
@@ -16,16 +19,19 @@ type_info::~type_info()
 
 bool type_info::operator==(const type_info& other) const
 {
+       //_SysDebug("type_info::operator== - '%s' == '%s'", this->__type_name, other.__type_name);
        return this->__type_name == other.__type_name;
 }
 
 bool type_info::operator!=(const type_info& other) const
 {
+       //_SysDebug("type_info::operator!= - '%s' != '%s'", this->__type_name, other.__type_name);
        return this->__type_name != other.__type_name;
 }
 
 bool type_info::before(const type_info& other) const
 {
+       //_SysDebug("type_info::before - '%s' < '%s'", this->__type_name, other.__type_name);
        return this->__type_name < other.__type_name;
 }
 
@@ -41,10 +47,76 @@ type_info::type_info(const type_info& rhs):
 }
 type_info& type_info::operator=(const type_info& rhs)
 {
+       _SysDebug("type_info::operator=, was %s now %s", __type_name, rhs.__type_name);
        __type_name = rhs.__type_name;
        return *this;
 }
 
+bool type_info::is_class() const
+{
+       if( typeid(*this) == typeid(::__cxxabiv1::__class_type_info) )
+               return true;
+       if( is_subclass() )
+               return true;
+       return false;
+}
 
-};     // namespace std
+bool type_info::is_subclass() const
+{
+       if( typeid(*this) == typeid(::__cxxabiv1::__si_class_type_info) )
+               return true;
+       if( typeid(*this) == typeid(::__cxxabiv1::__vmi_class_type_info) )
+               return true;
+       return false;
+}
+
+// Acess-defined
+bool type_info::__is_child(const type_info &poss_child, size_t &offset) const
+{
+       _SysDebug("typeids = this:%s , poss_child:%s", typeid(*this).name(), typeid(poss_child).name());
+
+       // Check #1: Child is same type
+       if( poss_child == *this ) {
+               offset = 0;
+               return true;
+       }
+       
+       // Check #2: This type must be a class
+       if( !this->is_class() ) {
+               return false;
+       }
+       // Check #3: Child class must be a subclass
+       if( !poss_child.is_subclass() ) {
+               return false;
+       }
+       
+       if( typeid(poss_child) == typeid(::__cxxabiv1::__si_class_type_info) ) {
+               auto &si_poss_child = reinterpret_cast<const ::__cxxabiv1::__si_class_type_info&>(poss_child);
+               // Single inheritance
+               _SysDebug("type_info::__is_child - Single inheritance");
+               return __is_child( *si_poss_child.__base_type, offset );
+       }
+       else if( typeid(poss_child) == typeid(::__cxxabiv1::__vmi_class_type_info) ) {
+               // Multiple inheritance
+               _SysDebug("TODO: type_info::__is_child - Multiple inheritance");
+               abort();
+               for(;;);
+       }
+       else {
+               // Oops!
+               _SysDebug("ERROR: type_info::__is_child - Reported subclass type, but not a subclass %s",
+                       typeid(poss_child).name()
+                       );
+               abort();
+               for(;;);
+       }
+}
 
+
+// NOTE: Not defined by the C++ ABI, but is similar to one defined by GCC (__cxa_type_match
+//bool __acess_type_match(std::typeinfo& possibly_derived, const std::typeinfo& base_type)
+//{
+//     return false;
+//}
+
+};     // namespace std
diff --git a/Usermode/Libraries/libc++_extras.so_src/Makefile b/Usermode/Libraries/libc++_extras.so_src/Makefile
new file mode 100644 (file)
index 0000000..f129b61
--- /dev/null
@@ -0,0 +1,19 @@
+# Acess2 Basic C Library
+# Makefile
+
+-include ../Makefile.cfg
+
+CPPFLAGS += 
+CXXFLAGS += -Wall -Werror -Wextra -std=c++11
+CFLAGS   += -Wall -Werror -Wextra
+ASFLAGS  +=
+LDFLAGS  += 
+LIBS     += -lc++
+
+include ../Makefile.tpl
+
+%.native: %.cpp
+       $(NCXX) $< -o $@ -Wall -std=c++11 -I include_exp/
+
+TEST_cprintf.native: include_exp/cxxextras_printf
+
diff --git a/Usermode/Libraries/libc++_extras.so_src/TEST_cprintf.cpp b/Usermode/Libraries/libc++_extras.so_src/TEST_cprintf.cpp
new file mode 100644 (file)
index 0000000..b77b004
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ */
+#include <cxxextras_printf>
+#include <cstdio>
+#include <stdexcept>
+
+void my_puts(const char *str, size_t len)
+{
+       fwrite(str, 1, len, stdout);
+}
+
+#define ASSERT_EXCEPTION(expr, Exception) do{bool _ok=false; try { expr; } catch(const Exception& e){_ok=true;}if(!_ok)throw ::std::runtime_error("Didn't throw "#Exception);}while(0)
+
+int main()
+{
+       printf("Success\n");
+       cprintf(my_puts, "%s %i %+#-010x\n", "hello_world", 1337, 0x1234565);
+       
+       //printf("Too Few\n");
+       //ASSERT_EXCEPTION( ::cxxextras::cprintf(my_puts, "%s %i %+#-010x\n"), ::cxxextras::cprintf_toofewargs );
+       //printf("Too Many\n");
+       //ASSERT_EXCEPTION( ::cxxextras::cprintf(my_puts, "%s\n", "tst", 12345), ::cxxextras::cprintf_toomanyargs );
+       //
+       //printf("Bad Format\n");
+       //ASSERT_EXCEPTION( ::cxxextras::cprintf(my_puts, "%-\n"), ::cxxextras::cprintf_badformat );
+       
+       return 0;
+}
+
diff --git a/Usermode/Libraries/libc++_extras.so_src/include_exp/cxxextras_printf b/Usermode/Libraries/libc++_extras.so_src/include_exp/cxxextras_printf
new file mode 100644 (file)
index 0000000..7d05e21
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ */
+#ifndef _LIBCXXEXTRAS_PRINTF_
+#define _LIBCXXEXTRAS_PRINTF_
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstdio>
+#include <functional>
+
+namespace cxxextras {
+
+class cprintf_toomanyargs:
+       public ::std::exception
+{
+};
+class cprintf_toofewargs:
+       public ::std::exception
+{
+};
+class cprintf_badformat:
+       public ::std::exception
+{
+       const char *m_reason;
+public:
+       cprintf_badformat(const char *reason):
+               m_reason(reason)
+       {
+       }
+       const char* what() const noexcept override {
+               return m_reason;
+       }
+};
+
+namespace _bits {
+
+enum e_cprintf_type
+{
+       TYPE_AUTO,
+       TYPE_BOOLEAN,
+       TYPE_BINARY,
+       TYPE_OCT,
+       TYPE_INT,
+       TYPE_INTU,
+       TYPE_INTS,
+       TYPE_HEXLC,
+       TYPE_HEXUC,
+       TYPE_STRING,
+};
+
+struct PrintfFlags
+{
+       unsigned int width;
+       unsigned int precision;
+       unsigned int flags;
+       
+       struct Left {};
+       constexpr PrintfFlags(PrintfFlags x, Left  _): width(x.width), precision(x.precision), flags(x.flags | 1) {}
+       struct Sign {};
+       constexpr PrintfFlags(PrintfFlags x, Sign  _): width(x.width), precision(x.precision), flags(x.flags | 2) {}
+       struct Space {};
+       constexpr PrintfFlags(PrintfFlags x, Space _): width(x.width), precision(x.precision), flags(x.flags | 4) {}
+       struct Alt {};
+       constexpr PrintfFlags(PrintfFlags x, Alt   _): width(x.width), precision(x.precision), flags(x.flags | 8) {}
+       struct Zero {};
+       constexpr PrintfFlags(PrintfFlags x, Zero  _): width(x.width), precision(x.precision), flags(x.flags | 16) {}
+       
+       struct ArgWidth {};
+       constexpr PrintfFlags(PrintfFlags x, ArgWidth _, unsigned int v): width(v), precision(x.precision), flags(x.flags) {}
+       struct ArgPrec {};
+       constexpr PrintfFlags(PrintfFlags x, ArgPrec  _, unsigned int v): width(x.width), precision(v), flags(x.flags) {}
+       
+       struct FAuto {};
+       constexpr PrintfFlags(PrintfFlags x, FAuto   _): width(x.width), precision(x.precision), flags(x.flags | 0x000) {}
+       struct FString {};
+       constexpr PrintfFlags(PrintfFlags x, FString _): width(x.width), precision(x.precision), flags(x.flags | 0x100) {}
+       struct FBool {};
+       constexpr PrintfFlags(PrintfFlags x, FBool   _): width(x.width), precision(x.precision), flags(x.flags | 0x200) {}
+       struct FBinary {};
+       constexpr PrintfFlags(PrintfFlags x, FBinary _): width(x.width), precision(x.precision), flags(x.flags | 0x300) {}
+       struct FOct {};
+       constexpr PrintfFlags(PrintfFlags x, FOct   _): width(x.width), precision(x.precision), flags(x.flags | 0x400) {}
+       struct FUDec {};
+       constexpr PrintfFlags(PrintfFlags x, FUDec  _): width(x.width), precision(x.precision), flags(x.flags | 0x500) {}
+       struct FSDec {};
+       constexpr PrintfFlags(PrintfFlags x, FSDec  _): width(x.width), precision(x.precision), flags(x.flags | 0x600) {}
+       struct FHexL {};
+       constexpr PrintfFlags(PrintfFlags x, FHexL  _): width(x.width), precision(x.precision), flags(x.flags | 0x700) {}
+       struct FHexU {};
+       constexpr PrintfFlags(PrintfFlags x, FHexU  _): width(x.width), precision(x.precision), flags(x.flags | 0x800) {}
+       
+       constexpr PrintfFlags():
+               width(0), precision(0), flags(0)
+       {
+       }
+};
+struct s_cprintf_fmt
+{
+       bool isValid = false;
+       unsigned int precision = 0;
+       unsigned int minLength = 0;
+       bool    padLeft = false;
+       bool    showSign = false;
+       bool    showSpace = false;
+       bool    altFormat = false;
+       bool    padZero = false;
+       enum e_cprintf_type     type;
+};
+;
+
+constexpr bool isdigit_s(const char ch) {
+       return '0' <= ch && ch <= '9';
+}
+constexpr unsigned todigit(const char ch) {
+       return ch - '0';
+}
+       
+
+};     // namespace _bits
+
+typedef ::std::function<void(const char*,size_t)>      cprintf_cb;
+template <typename Arg> size_t cprintf_val(cprintf_cb puts, const _bits::PrintfFlags &fmt, Arg arg);
+template <typename Arg> constexpr bool cprintf_val_chk(const _bits::PrintfFlags fmt, Arg arg);
+
+constexpr bool cprintf_val_chk(const _bits::PrintfFlags fmt, const char* arg) {
+       return true;
+}
+size_t cprintf_val(cprintf_cb puts, const _bits::PrintfFlags& fmt, const char* arg) {
+       unsigned int len;
+       for(len = 0; arg[len]; len ++)
+               ;
+       puts(arg, len);
+       return len;
+}
+constexpr bool cprintf_val_chk(const _bits::PrintfFlags& fmt, int arg) {
+       return true;
+}
+size_t cprintf_val(cprintf_cb puts, const _bits::PrintfFlags& fmt, int arg) {
+       size_t len = ::std::snprintf(nullptr, 0, "%i", arg);
+       char buf[len+1];
+       ::std::snprintf(buf, len+1, "%i", arg);
+       puts(buf, len);
+       return len;
+}
+constexpr bool cprintf_val_chk(const _bits::PrintfFlags& fmt, unsigned int arg) {
+       return true;
+}
+size_t cprintf_val(cprintf_cb puts, const _bits::PrintfFlags& fmt, unsigned int arg) {
+       size_t len = ::std::snprintf(nullptr, 0, "%u", arg);
+       char buf[len+1];
+       ::std::snprintf(buf, len+1, "%u", arg);
+       puts(buf, len);
+       return len;
+}
+
+namespace _bits
+{
+namespace _printf
+{
+       template <unsigned N>
+       class _str
+       {
+               const char      m_buf[N];
+               unsigned m_ofs;
+       public:
+               constexpr _str(const char buf[N]):
+                       m_buf(buf),
+                       m_ofs(0)
+               {
+               }
+               constexpr _str(const char buf[N], unsigned ofs):
+                       m_buf(buf),
+                       m_ofs(ofs)
+               {
+               }
+               constexpr _str<N> operator+(const unsigned o) {
+                       return _str(m_buf, m_ofs+o);
+               }
+               constexpr char operator*() {
+                       return m_buf[m_ofs];
+               }
+       };
+       
+       template <typename... Args>
+       constexpr bool val(const char* fmt, Args... args);
+       
+       template <typename Fmt>
+       constexpr bool val_fmt_done(const char * fmt, PrintfFlags item, Fmt fmtcode)
+       {
+               return false ? false : throw "Too few arguments";
+       }
+       template <typename Fmt, typename Arg, typename... Args>
+       constexpr bool val_fmt_done(const char* fmt, PrintfFlags item, Fmt fmtcode, Arg arg, Args... args)
+       {
+               return cprintf_val_chk(item, arg) && val(fmt+1, args...);
+       }
+       // --- Format code
+       template <typename ...Args>
+       constexpr bool val_fmt_fmt(const char * fmt, PrintfFlags item, Args... args)
+       {
+               return *fmt == '\0' ? throw "ERROR: NUL byte in format specifier"
+                    : *fmt == '?' ? val_fmt_done(fmt, item, PrintfFlags::FAuto(),  args...)
+                    : *fmt == 's' ? val_fmt_done(fmt, item, PrintfFlags::FString(),args...)
+                    : *fmt == 'B' ? val_fmt_done(fmt, item, PrintfFlags::FBool(),  args...)
+                    : *fmt == 'b' ? val_fmt_done(fmt, item, PrintfFlags::FBinary(),args...)
+                    : *fmt == 'o' ? val_fmt_done(fmt, item, PrintfFlags::FOct(),   args...)
+                    : *fmt == 'i' ? val_fmt_done(fmt, item, PrintfFlags::FSDec(),  args...)
+                    : *fmt == 'u' ? val_fmt_done(fmt, item, PrintfFlags::FUDec(),  args...)
+                    : *fmt == 'x' ? val_fmt_done(fmt, item, PrintfFlags::FHexL(),  args...)
+                    : *fmt == 'X' ? val_fmt_done(fmt, item, PrintfFlags::FHexU(),  args...)
+                    : throw cprintf_badformat("Unknown character in format string");
+       }
+       // --- Size modifier (not implemented, not needed?)
+       template <typename ...Args>
+       constexpr bool val_fmt_size(const char * fmt, PrintfFlags item, Args... args)
+       {
+               // TODO: Size characters?
+               return val_fmt_fmt(fmt, item, args...);
+       }
+       // --- Precision
+       template <typename ...Args>
+       constexpr bool val_fmt_prec_val(const char * fmt, unsigned int value, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? val_fmt_prec_val(fmt+1, value*10+_bits::todigit(*fmt), item, args...)
+                    : val_fmt_size(fmt, PrintfFlags(item, PrintfFlags::ArgPrec(), value), args...);
+       }
+       template <typename ...Args>
+       constexpr bool val_fmt_prec_arg(const char *fmt, PrintfFlags item, unsigned int size, Args... args)
+       {
+               return val_fmt_prec_opt(fmt, PrintfFlags(item, PrintfFlags::ArgPrec(), size), args...);
+       }
+       template <typename Arg, typename ...Args>
+       constexpr bool val_fmt_prec_arg(const char *fmt, PrintfFlags item, Arg size, Args... args)
+       {
+               //static_assert(false, "Invalid type for precision modifier, must be 'unsigned int'");
+               return false ? false : throw "Invalid type for precision modifier, must be 'unsigned int'";
+       }
+       constexpr bool val_fmt_prec_arg(const char *fmt, PrintfFlags item)
+       {
+               //static_assert(false, "Too few arguments when getting precision modifier");
+               return false ? false : throw "Too few arguments when getting precision modifier";
+       }
+       template <typename ...Args>
+       constexpr bool val_fmt_prec(const char * fmt, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? val_fmt_prec_val(fmt+1, _bits::todigit(*fmt), item, args...)
+                    : *fmt == '*' ? val_fmt_prec_arg(fmt+1, item, args...)
+                    : val_fmt_size(fmt, item, args...);
+       }
+       template <typename ...Args>
+       constexpr bool val_fmt_prec_opt(const char * fmt, PrintfFlags item, Args... args)
+       {
+               return *fmt == '.' ? val_fmt_prec(fmt+1, item, args...)
+                    : val_fmt_size(fmt, item, args...);
+       }
+       // --- Field Width ---  
+       template <typename ...Args>
+       constexpr bool val_fmt_width_val(const char* fmt, unsigned int size, PrintfFlags item, Args... args)
+       {
+               return  _bits::isdigit_s(*fmt) ? val_fmt_width_val(fmt+1, size*10+_bits::todigit(*fmt), item, args...)
+                     : val_fmt_prec_opt(fmt, PrintfFlags(item, PrintfFlags::ArgWidth(), size), args...);
+       }
+       template <typename ...Args>
+       constexpr bool val_fmt_width_arg(const char *fmt, PrintfFlags item, unsigned int size, Args... args)
+       {
+               return val_fmt_prec_opt(fmt, PrintfFlags(item, PrintfFlags::ArgWidth(), size), args...);
+       }
+       template <typename Arg, typename ...Args>
+       constexpr bool val_fmt_width_arg(const char *fmt, PrintfFlags item, Arg size, Args... args)
+       {
+               //static_assert(false, "Invalid type for width modifier, must be 'unsigned int'");
+               return false ? false : throw "Invalid type for width modifier, must be 'unsigned int'";
+       }
+       constexpr bool val_fmt_width_arg(const char *fmt, PrintfFlags item)
+       {
+               //static_assert(false, "Too few arguments when reading width for width modifier");
+               return false ? false : throw "Too few arguments when reading width for width modifier";
+       }
+       template <typename ...Args>
+       constexpr bool val_fmt_width(const char * fmt, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? val_fmt_width_val(fmt+1, _bits::todigit(*fmt), item, args...)
+                    : *fmt == '*' ? val_fmt_width_arg(fmt+1, item, args...)
+                    : val_fmt_prec_opt(fmt, item, args...);
+       }
+       // --- Flags
+       template <typename ...Args>
+       constexpr bool val_fmt_flags(const char * fmt, PrintfFlags item, Args... args)
+       {
+               return
+                 *fmt == '-' ? val_fmt_flags(fmt+1, PrintfFlags(item, PrintfFlags::Left()) , args...)
+               : *fmt == '+' ? val_fmt_flags(fmt+1, PrintfFlags(item, PrintfFlags::Sign()) , args...)
+               : *fmt == ' ' ? val_fmt_flags(fmt+1, PrintfFlags(item, PrintfFlags::Space()), args...)
+               : *fmt == '#' ? val_fmt_flags(fmt+1, PrintfFlags(item, PrintfFlags::Alt())  , args...)
+               : *fmt == '0' ? val_fmt_flags(fmt+1, PrintfFlags(item, PrintfFlags::Zero()) , args...)
+               : val_fmt_width(fmt, item, args...);
+       }
+       // --- Literal '%'
+       template <typename ...Args>
+       constexpr bool val_fmt_start(const char* fmt, Args... args)
+       {
+               return *fmt == '%' ? val(fmt+1, args...) : val_fmt_flags(fmt, PrintfFlags(), args...);
+       }
+       template <typename... Args>
+       constexpr bool val(const char* fmt, Args... args)
+       {
+               return *fmt == '\0' ? true
+                    : *fmt == '%' ? val_fmt_start(fmt+1, args...)
+                    : val(fmt+1, args...);
+       }
+       
+       size_t run(cprintf_cb puts, const char *fmt);
+       template <typename... Args> size_t run(cprintf_cb puts, const char * fmt, Args... args);
+
+       // --- Print formatted value
+       template <typename Fmt>
+       constexpr size_t run_fmt_done(cprintf_cb puts, const char * fmt, PrintfFlags item, Fmt fmtcode)
+       {
+               throw cprintf_toofewargs();
+       }
+       template <typename Fmt, typename Arg, typename... Args>
+       size_t run_fmt_done(cprintf_cb puts, const char * fmt, PrintfFlags item, Fmt fmtcode, Arg val,  Args... args)
+       {
+               if( !puts )
+                       return run(puts, fmt+1, args...);
+               else
+                       return ::cxxextras::cprintf_val(puts, PrintfFlags(item, fmtcode), val) + run(puts, fmt+1, args...);
+       }
+       // --- Format code
+       template <typename ...Args>
+       size_t run_fmt_fmt(cprintf_cb puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return *fmt == '\0' ? throw "ERROR: NUL byte in format specifier"
+                    : *fmt == '?' ? run_fmt_done(puts, fmt, item, PrintfFlags::FAuto(),  args...)
+                    : *fmt == 's' ? run_fmt_done(puts, fmt, item, PrintfFlags::FString(),args...)
+                    : *fmt == 'B' ? run_fmt_done(puts, fmt, item, PrintfFlags::FBool(),  args...)
+                    : *fmt == 'b' ? run_fmt_done(puts, fmt, item, PrintfFlags::FBinary(),args...)
+                    : *fmt == 'o' ? run_fmt_done(puts, fmt, item, PrintfFlags::FOct(),   args...)
+                    : *fmt == 'i' ? run_fmt_done(puts, fmt, item, PrintfFlags::FSDec(),  args...)
+                    : *fmt == 'u' ? run_fmt_done(puts, fmt, item, PrintfFlags::FUDec(),  args...)
+                    : *fmt == 'x' ? run_fmt_done(puts, fmt, item, PrintfFlags::FHexL(),  args...)
+                    : *fmt == 'X' ? run_fmt_done(puts, fmt, item, PrintfFlags::FHexU(),  args...)
+                    : throw cprintf_badformat("Unknown character in format string");
+       }
+       // --- Size modifier (not implemented, not needed?)
+       template <typename ...Args>
+       size_t run_fmt_size(cprintf_cb puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               // TODO: Size characters?
+               return run_fmt_fmt(puts, fmt, item, args...);
+       }
+       // --- Precision
+       template <typename ...Args>
+       size_t run_fmt_prec_val(cprintf_cb puts, const char * fmt, unsigned int val, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? run_fmt_prec_val(puts, fmt+1, val*10+_bits::todigit(*fmt), item, args...)
+                    : run_fmt_size(puts, fmt, PrintfFlags(item, PrintfFlags::ArgPrec(), val), args...);
+       }
+       template <typename ...Args>
+       size_t run_fmt_prec_arg(cprintf_cb puts, const char *fmt, PrintfFlags item, unsigned int size, Args... args)
+       {
+               return run_fmt_prec_opt(puts, fmt, PrintfFlags(item, PrintfFlags::ArgPrec(), size), args...);
+       }
+       template <typename Arg, typename ...Args>
+       size_t run_fmt_prec_arg(cprintf_cb puts, const char *fmt, PrintfFlags item, Arg size, Args... args)
+       {
+               throw cprintf_badformat("Invalid type for printf precision modifier");
+       }
+       size_t run_fmt_prec_arg(cprintf_cb puts, const char *fmt, PrintfFlags item)
+       {
+               throw cprintf_toofewargs();
+       }
+       template <typename ...Args>
+       size_t run_fmt_prec(cprintf_cb puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? run_fmt_prec_val(puts, fmt+1, _bits::todigit(*fmt), item, args...)
+                    : *fmt == '*' ? run_fmt_prec_arg(puts, fmt+1, item, args...)
+                    : run_fmt_size(puts, fmt, item, args...);
+       }
+       template <typename ...Args>
+       size_t run_fmt_prec_opt(cprintf_cb puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return *fmt == '.' ? run_fmt_prec(puts, fmt+1, item, args...)
+                    : run_fmt_size(puts, fmt, item, args...);
+       }
+       // --- Field Width ---  
+       template <typename ...Args>
+       size_t run_fmt_width_val(cprintf_cb puts, const char* fmt, unsigned int val, PrintfFlags item, Args... args)
+       {
+               return  _bits::isdigit_s(*fmt) ? run_fmt_width_val(puts, fmt+1, val*10+_bits::todigit(*fmt), item, args...)
+                     : run_fmt_prec_opt(puts, fmt, PrintfFlags(item, PrintfFlags::ArgWidth(), val), args...);
+       }
+       template <typename ...Args>
+       size_t run_fmt_width_arg(cprintf_cb puts, const char *fmt, PrintfFlags item, unsigned int size, Args... args)
+       {
+               return run_fmt_prec_opt(puts, fmt, PrintfFlags(item, PrintfFlags::ArgWidth(), size), args...);
+       }
+       template <typename Arg, typename ...Args>
+       size_t run_fmt_width_arg(cprintf_cb puts, const char *fmt, PrintfFlags item, Arg size, Args... args)
+       {
+               throw cprintf_badformat("Invalid type for printf width modifier");
+       }
+       size_t run_fmt_width_arg(cprintf_cb puts, const char *fmt, PrintfFlags item)
+       {
+               throw cprintf_toofewargs();
+       }
+       template <typename ...Args>
+       size_t run_fmt_width(cprintf_cb puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? run_fmt_width_val(puts, fmt+1, _bits::todigit(*fmt), item, args...)
+                    : *fmt == '*' ? run_fmt_width_arg(puts, fmt+1, item, args...)
+                    : run_fmt_prec_opt(puts, fmt, item, args...);
+       }
+       // --- Flags
+       template <typename ...Args>
+       size_t run_fmt_flags(cprintf_cb puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return
+                 *fmt == '-' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Left()) , args...)
+               : *fmt == '+' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Sign()) , args...)
+               : *fmt == ' ' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Space()), args...)
+               : *fmt == '#' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Alt())  , args...)
+               : *fmt == '0' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Zero()) , args...)
+               : run_fmt_width(puts, fmt, item, args...);
+       }
+       // --- Literal '%'
+       template <typename ...Args>
+       size_t run_fmt_start(cprintf_cb puts, const char * fmt, Args... args)
+       {
+               return *fmt == '%'
+                       ? (puts("%", 1), 1 + run(puts, fmt+1, args...))
+                       : run_fmt_flags(puts, fmt, PrintfFlags(), args...);
+       }
+       // --- Root
+       template <typename... Args>
+       size_t run(cprintf_cb puts, const char * fmt, Args... args)
+       {
+               int ofs;
+               for( ofs = 0; fmt[ofs] != '\0' && fmt[ofs] != '%'; ofs ++ )
+                       ;
+               if( fmt[ofs] != '%' )
+                       throw cprintf_toomanyargs();
+               if(ofs > 0 && puts) puts(fmt, ofs);
+               return ofs + run_fmt_start(puts, fmt+ofs+1, args...);
+       }
+       size_t run(cprintf_cb puts, const char *fmt)
+       {
+               int ofs;
+               for( ofs = 0; fmt[ofs] != '\0' && fmt[ofs] != '%'; ofs ++ )
+                       ;
+               if(ofs > 0 && puts) puts(fmt, ofs);
+               return ofs + (fmt[ofs] == '%' ? run_fmt_start(puts, fmt+ofs+1) : 0);
+       }
+
+}
+
+};     // namespace _bits
+
+#define cprintf(puts, fmt, ...)        static_assert(::cxxextras::_bits::_printf::val(fmt, __VA_ARGS__),"");::cxxextras::_bits::_printf::run(puts, fmt, __VA_ARGS__)
+
+//template <typename ... Args>
+//size_t cprintf(cprintf_cb puts, const char *fmt, Args... args)
+//{
+//     _bits::_printf::run(nullptr, fmt, args...);
+//     return _bits::_printf::run(puts, fmt, args...);
+//}
+
+};
+
+#endif
+
+// vim: ft=cpp
+
index c615b6e..64749b3 100644 (file)
@@ -4,9 +4,11 @@
 -include ../Makefile.cfg\r
 \r
 CPPFLAGS += \r
-CFLAGS   += -Wall -Werror -Wextra\r
+CFLAGS   += -nostdlib -Wall -Werror -Wextra\r
 ASFLAGS  +=\r
-LDFLAGS  += -Map map.txt\r
+LDFLAGS  += -nostdlib\r
+PRELINK  := $(CRTI) $(CRTBEGINS) $(CRT0S)\r
+LIBS     += $(LIBGCC_PATH) $(CRTENDS) $(CRTN)\r
 \r
 INCFILES := stdio.h stdlib.h\r
 \r
@@ -19,7 +21,7 @@ OBJ += arch/$(ARCHDIR).ao
 DEPFILES := $(OBJ:%.o=%.d)\r
 BIN = libc.so\r
 ifeq ($(ARCHDIR),native)\r
- OBJ := $(filter-out heap.o,$(OBJ))\r
+ OBJ := $(filter-out heap.o,$(OBJ)) heap_native.o\r
  #LDFLAGS += -l c\r
  BIN = libc_acess.so\r
 endif\r
@@ -27,8 +29,8 @@ endif
 include ../Makefile.tpl\r
 \r
 EXP_%.txt: TEST_%.native\r
-       ./$< > $@\r
-       rm $<\r
+       @./$< > $@\r
+       @rm $<\r
 EXP_strtoi.txt:\r
        echo -n "" > $@\r
 \r
diff --git a/Usermode/Libraries/libc.so_src/TEST_string.c b/Usermode/Libraries/libc.so_src/TEST_string.c
new file mode 100644 (file)
index 0000000..4ecca30
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ */
+#include <stdio.h>
+#include <string.h>
+
+#define ASSERT(cnd)    printf("ASSERT: "#cnd" == %s\n", ((cnd) ? "pass" : "FAIL"))
+
+int main()
+{
+       ASSERT(strcmp("hello", "world") < 0);
+       ASSERT(strcmp("hello", "hello") == 0);
+       ASSERT(strcmp("wello", "hello") > 0);
+       ASSERT(strcmp("\xff", "\1") > 0);
+       ASSERT(strcmp("\1", "\xff") < 0);
+       ASSERT(strcmp("Hello", "hello") < 0);
+       
+       ASSERT(strncmp("hello world", "hello", 5) == 0);
+       
+       ASSERT(strcasecmp("hello", "world") < 0);
+       ASSERT(strcasecmp("hello", "hello") == 0);
+       ASSERT(strcasecmp("wello", "hello") > 0);
+       ASSERT(strcasecmp("\xff", "\1") > 0);
+       ASSERT(strcasecmp("\1", "\xff") < 0);
+       ASSERT(strcasecmp("Hello", "hello") == 0);
+       ASSERT(strcasecmp("Hello", "Hello") == 0);
+       ASSERT(strcasecmp("hellO", "Hello") == 0);
+       
+       char buf[13];
+       memset(buf, 127, sizeof(buf));
+       ASSERT(buf[0] == 127);  ASSERT(buf[4] == 127);
+       strncpy(buf, "hello", 4);
+       ASSERT(buf[3] == 'l');  ASSERT(buf[4] == 127);
+       strncpy(buf, "hello", 8);
+       ASSERT(buf[4] == 'o');  ASSERT(buf[5] == '\0'); ASSERT(buf[7] == '\0'); ASSERT(buf[8] == 127);
+       
+       memset(buf, 0, 13);
+       ASSERT(buf[0] == 0);    ASSERT(buf[12] == 0);
+       
+       ASSERT(memchr("\xffhello", 'x', 6) == NULL);
+       
+       const char *teststr_foo = "foo";
+       ASSERT(strchr(teststr_foo, 'f') == teststr_foo+0);
+       ASSERT(strchr(teststr_foo, 'o') == teststr_foo+1);
+       ASSERT(strchr(teststr_foo, '\0') == teststr_foo+3);
+       ASSERT(strchr(teststr_foo, 'X') == NULL);
+       ASSERT(strrchr(teststr_foo, 'f') == teststr_foo+0);
+       ASSERT(strrchr(teststr_foo, 'o') == teststr_foo+2);
+       ASSERT(strrchr(teststr_foo, '\0') == teststr_foo+3);
+       ASSERT(strrchr(teststr_foo, 'X') == NULL);
+}
+
index 6d89224..e065808 100644 (file)
@@ -7,15 +7,71 @@
  */
 #include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>    // strerror
 
-#define TST(t, class, base, val, exp, fmt) do {\
-       t ret = strto##class(#val, NULL, base); \
+#define STR_(v)        #v
+#define STR(v) STR_(v)
+#define TST(t, class, base, val, exp, fmt, ofs, exp_errno) do {\
+       const char *in = val;\
+       char *end;\
+       errno = 0;\
+       t ret = strto##class(in, &end, base); \
        if( ret != exp ) \
-               printf("FAIL strto"#class"('"#val"') != "#val" (act 0x"fmt")\n", ret);\
+               fprintf(stderr, "FAIL strto"#class"('%s') != "#exp" (act "fmt")\n", in, ret);\
+       if( end != in+ofs ) \
+               fprintf(stderr, "FAIL strto"#class"('%s') returned wrong end: %p (+%zi) instead of %p (+%zi)\n",\
+                       in,end,end-in,in+ofs,(size_t)ofs);\
+       if( exp_errno != errno ) \
+               fprintf(stderr, "FAIL strto"#class"('%s') returned wrong errno, exp '%s', got '%s'\n",\
+                       in, strerror(exp_errno), strerror(errno));\
 }while(0)
 
+#define PRIMEBUF(fmt, val)     buf_len = snprintf(buf, sizeof(buf), fmt, val)
+
 int main(int argc, char *argv[])
 {
-       TST(unsigned long, ul, 0, 0x10ec, 0x10ec, "%lx");
-       TST(unsigned long long, ull, 0, 0xffeed10ec, 0xffeed10ec, "%llx");
+       char buf[64];
+       size_t  buf_len;
+       
+       // Success cases
+       TST(unsigned long, ul, 0, "0x10ec", 0x10ec, "%lx", 2+4, 0);
+       TST(unsigned long long, ull, 0, "0xffeed10ec", 0xffeed10ec, "%llx", 2+9, 0);
+       TST(unsigned long long, ull, 0, "01234567", 01234567, "%llo", 8, 0);
+       TST(unsigned long long, ull, 0, "1234567", 1234567, "%lld", 7, 0);
+       TST(long long, ll, 0, "-1", -1, "%lld", 2, 0);  // -1
+       TST(long long, ll, 0, "100113", 100113, "%lld", strlen(in), 0);
+       TST(long long, ll, 0, "0x101", 0x101, "0x%llx", strlen(in), 0);
+       
+       // Invalid strings
+       TST(unsigned long long, ull, 0, "0x",  0, "%llx", 1, 0);        // Single 0
+       TST(unsigned long long, ull, 0, "0xg", 0, "%llx", 1, 0);        // Single 0
+       TST(unsigned long long, ull, 0, "-a", 0, "%llx", 0, 0); // Nothing
+       TST(long long, ll, 0, "-a", 0, "%lld", 0, 0);   // Nothing
+       TST(long long, ll, 0, "-1aaatg", -1, "%lld", 2, 0);     // -1 (with traling junk)
+       TST(long long, ll, 0, "-+1aaatg", 0, "%lld", 0, 0);     // Nothing
+       TST(long long, ll, 0, "-  1", 0, "%lld", 0, 0); // Nothing
+       TST(long long, ll, 0, "01278  1", 0127, "%lld", 4, 0);  // 0127 with junk
+       
+       // Range edges
+       PRIMEBUF("0x%llx", ULLONG_MAX);
+       TST(unsigned long long, ull, 0, buf, ULLONG_MAX, "0x%llx", buf_len, 0);
+       PRIMEBUF("%llu", ULLONG_MAX);
+       TST(unsigned long long, ull, 0, buf, ULLONG_MAX, "%llu", buf_len, 0);
+       PRIMEBUF("-%llu", (long long)LONG_MAX);
+       TST(long, l, 0, buf, -LONG_MAX, "%ld", buf_len, 0);
+       
+       // Out of range
+       // - When the range limit is hit, valid characters should still be consumed (just not used)
+       TST(unsigned long long, ull, 0, "0x10000FFFF0000FFFF", ULLONG_MAX, "%llx", strlen(in), ERANGE);
+       TST(unsigned long, ul, 0, "0x10000FFFF0000FFFF", ULONG_MAX, "%lx", strlen(in), ERANGE);
+       TST(long, l, 0, "0x10000FFFF0000FFFF", LONG_MAX, "%ld", strlen(in), ERANGE);
+       TST(long, l, 0, "-0x10000FFFF0000FFFF", LONG_MIN, "%ld", strlen(in), ERANGE);
+       if( LONG_MIN < -LONG_MAX )
+       {
+               // Ensure that if -LONG_MIN is greater than LONG_MAX, that converting it leaves a range error
+               PRIMEBUF("%ld", LONG_MIN);
+               TST(long, l, 0, buf+1, LONG_MAX, "%ld", buf_len-1, ERANGE);
+       }
 }
index d5a5e97..18a199c 100644 (file)
@@ -22,23 +22,40 @@ int isalnum(int ch) {
        return isalpha(ch) || isdigit(ch);
 }
 
-int toupper(int ch) {
-       if('a'<=ch && ch <='z')
-               return ch - 'a' + 'A';
-       return ch;
+int isxdigit(int ch) {
+       if('0'<=ch&&ch<='9')    return 1;
+       if('a'<=ch&&ch<='f')    return 1;
+       if('F'<=ch&&ch<='F')    return 1;
+       return 0;
 }
-int tolower(int ch) {
-       if('A'<=ch && ch <='Z')
-               return ch - 'A' + 'a';
-       return ch;
+
+int isupper(int ch) {
+       if('A'<=ch && ch <='Z') return 1;
+       return 0;
+}
+
+int islower(int ch) {
+       if('a'<=ch && ch <='z') return 1;
+       return 0;
+}
+
+int ispunct(int ch) {
+       if( isprint(ch) && !isspace(ch) && !isalnum(ch) )
+               return 1;
+       return 0;
 }
 
 int isprint(int ch ) {
-       if( ch < ' ' )  return 0;
-       if( ch > 'z' )  return 0;
+       if( ' ' <= ch && ch <= 'z' )    return 1;
        return 1;
 }
 
+int isgraph(int ch) {
+       // Anything but space
+       if( ' ' < ch && ch <= 'z' )     return 1;
+       return 0;
+}
+
 int isspace(int ch) {
        if(ch == ' ')   return 1;
        if(ch == '\t')  return 1;
@@ -47,12 +64,17 @@ int isspace(int ch) {
        return 0;
 }
 
-int isxdigit(int ch) {
-       if('0'<=ch&&ch<='9')    return 1;
-       if('a'<=ch&&ch<='f')    return 1;
-       if('F'<=ch&&ch<='F')    return 1;
-       return 0;
+int toupper(int ch) {
+       if('a'<=ch && ch <='z')
+               return ch - 'a' + 'A';
+       return ch;
 }
+int tolower(int ch) {
+       if('A'<=ch && ch <='Z')
+               return ch - 'A' + 'a';
+       return ch;
+}
+
 
 // C99
 int isblank(int ch) {
index 6f95457..295183c 100644 (file)
@@ -21,13 +21,16 @@ EXPORT char *strerror(int errnum)
        switch((enum libc_eErrorNumbers)errnum)
        {
        case EOK:       return "Success";
+       case ERANGE:    return "Value out of range";
+       case EDOM:      return "Value out of domain";
+       case EILSEQ:    return "Illegal character sequence";
+
        case ENOSYS:    return "Invalid instruction/syscall";
        case EINVAL:    return "Bad argument(s)";
        case EBADF:     return "Invalid file";
        case ENOMEM:    return "No free memory";
        case EACCES:    return "Not permitted";
        case EBUSY:     return "Resource is busy";
-       case ERANGE:    return "Value out of range";
        case ENOTFOUND: return "Item not found";
        case EROFS:     return "Read only filesystem";
        case ENOTIMPL:  return "Not implimented";
@@ -46,8 +49,15 @@ EXPORT char *strerror(int errnum)
        case ENOTTY:    return "Not a TTY";
        case EAGAIN:    return "Try again";
        case EFBIG:     return "File too big";
+       case E2BIG:     return "Value too big";
        case EALREADY:  return "Operation was no-op";
+       case ENOSPC:    return "No space left on the device";
+
        case EAFNOSUPPORT:      return "Address family not supported";
+       case EADDRINUSE:        return "Address already in use";
+       case ETIMEDOUT: return "Operation timed out";
+       case EOPNOTSUPP:        return "Operation not supported on socket";
+
        case EINTERNAL: return "Internal error";
        }
        _SysDebug("strerror: errnum=%i unk", errnum);
index d6d9a40..71e3d6d 100644 (file)
@@ -8,6 +8,8 @@
 #include <acess/sys.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
+#include <assert.h>\r
+#include <stdbool.h>\r
 #include "lib.h"\r
 \r
 #if 0\r
@@ -71,6 +73,7 @@ static const heap_head        _heap_zero_allocation;
 EXPORT void    *malloc(size_t bytes);\r
 void   *_malloc(size_t bytes, void *owner);\r
 EXPORT void    *calloc(size_t bytes, size_t count);\r
+bool   _libc_free(void *mem);\r
 EXPORT void    free(void *mem);\r
 EXPORT void    *realloc(void *mem, size_t bytes);\r
 EXPORT void    *sbrk(int increment);\r
@@ -221,26 +224,31 @@ EXPORT void *calloc(size_t __nmemb, size_t __size)
  \param mem    Pointer - Memory to free\r
 */\r
 EXPORT void free(void *mem)\r
+{\r
+       if( !_libc_free(mem) ) {\r
+               Heap_Validate(1);\r
+               exit(0);\r
+       }\r
+}\r
+\r
+// Exported for libc++\r
+EXPORT bool _libc_free(void *mem)\r
 {\r
        heap_head       *head = (heap_head*)mem - 1;\r
 \r
        // Free of NULL or the zero allocation does nothing\r
        if(!mem || mem == _heap_zero_allocation.data)\r
-               return ;\r
+               return true;\r
        \r
        // Sanity check the head address\r
        if(head->magic != MAGIC) {\r
                if( head->magic != MAGIC_FREE ) {\r
-                       _SysDebug("Double free of %p", mem);\r
-                       Heap_Validate(1);\r
-                       exit(0);\r
+                       _SysDebug("Double free of %p by %p", mem, __builtin_return_address(0));\r
                }\r
                else {\r
-                       _SysDebug("Free of invalid pointer %p", mem);\r
-                       Heap_Validate(1);\r
-                       exit(0);\r
+                       _SysDebug("Free of invalid pointer %p by ", mem, __builtin_return_address(0));\r
                }\r
-               return;\r
+               return false;\r
        }\r
        \r
        head->magic = MAGIC_FREE;\r
@@ -265,8 +273,9 @@ EXPORT void free(void *mem)
                heap_foot *prevFoot = PREV_FOOT(head);\r
                if( prevFoot->magic != MAGIC )\r
                {\r
+                       _SysDebug("Heap corruption, previous foot magic invalid");\r
                        Heap_Validate(1);\r
-                       exit(1);\r
+                       return false;\r
                }\r
                \r
                heap_head *prevHead = prevFoot->header;\r
@@ -281,6 +290,8 @@ EXPORT void free(void *mem)
                        prevFoot->header = NULL;\r
                }\r
        }\r
+       \r
+       return true;\r
 }\r
 \r
 /**\r
@@ -308,7 +319,8 @@ EXPORT void *realloc(void *oldPos, size_t bytes)
        \r
        // Check for free space after the block\r
        heap_head *nexthead = NEXT_HEAD(head);\r
-       if( nexthead && nexthead->magic == MAGIC_FREE && head->size + nexthead->size >= reqd_size )\r
+       assert( nexthead <= _heap_end );\r
+       if( nexthead != _heap_end && nexthead->magic == MAGIC_FREE && head->size + nexthead->size >= reqd_size )\r
        {\r
                // Split next block\r
                if( head->size + nexthead->size > reqd_size )\r
@@ -337,12 +349,12 @@ EXPORT void *realloc(void *oldPos, size_t bytes)
        void *ret = _malloc(bytes, __builtin_return_address(0));\r
        if(ret == NULL)\r
                return NULL;\r
+       heap_head *newhead = (heap_head*)ret - 1;\r
        \r
-       //Copy Old Data\r
+       // Copy Old Data\r
+       assert( head->size < newhead->size );\r
        size_t copy_size = head->size-sizeof(heap_head)-sizeof(heap_foot);\r
-       if( copy_size > bytes )\r
-               copy_size = bytes;\r
-       memcpy(ret, oldPos, bytes);\r
+       memcpy(ret, oldPos, copy_size);\r
        free(oldPos);\r
        \r
        //Return\r
diff --git a/Usermode/Libraries/libc.so_src/heap_native.c b/Usermode/Libraries/libc.so_src/heap_native.c
new file mode 100644 (file)
index 0000000..0f4d9b3
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+#include <stdbool.h>
+
+bool _libc_free(void *addr)
+{
+       free(addr);
+       return true;
+}
index 75e4ce8..69067e8 100644 (file)
@@ -14,21 +14,27 @@ extern "C" {
 
 extern int isalpha(int ch);
 extern int isdigit(int ch);
-
 extern int isalnum(int ch);
+extern int isxdigit(int ch);
 
-extern int toupper(int ch);
-extern int tolower(int ch);
+extern int islower(int ch);
+extern int isupper(int ch);
+extern int ispunct(int ch);
 
 extern int isprint(int ch);
+extern int isgraph(int ch);
 
 extern int isspace(int ch);
 
-extern int isxdigit(int ch);
+extern int iscntrl(int ch);
 
 // C99
 extern int isblank(int ch);
 
+// Conversions
+extern int toupper(int ch);
+extern int tolower(int ch);
+
 #ifdef __cplusplus
 }
 #endif
index f943654..d7b1053 100755 (executable)
@@ -1,13 +1,16 @@
 
 enum libc_eErrorNumbers {
        EOK,
+       EDOM,   // (C99) Value out of domain
+       EILSEQ, // (C99) Illegal multi-byte sequence
+       ERANGE, // (C99) Value out of range
+       
        ENOSYS, // Invalid Instruction
        EINVAL, // Invalid Paramater
        EBADF,  // Bad FD
        ENOMEM, // No free memory
        EACCES, // Not permitted
        EBUSY,  // Resource is busy
-       ERANGE, // Value out of range
        ENOTFOUND,      // Item not found
        EROFS,  // Read only
        ENOTIMPL,       // Not implemented
@@ -27,11 +30,16 @@ enum libc_eErrorNumbers {
 
        EAGAIN, // Try again
        EALREADY,       // Operation was a NOP
+       ENOSPC, // (POSIX) No space left on device
        
        EFBIG,  // File too large
+       E2BIG,  // Argument list too large
 
        // psockets
        EAFNOSUPPORT,   
+       EADDRINUSE,     // (POSIX.1) Specified addres is already in use
+       ETIMEDOUT,
+       EOPNOTSUPP,     // (POSIX.1) Operation not supported on socket
        
        EINTERNAL       // Internal Error
 };
index 0200aa6..05e6707 100644 (file)
 #define _INTTYPES_H_
 
 #include <stdint.h>
+#include <limits.h>
 
-#define PRId64 "lld"
-#define PRIdLEAST64    "lld"
-#define PRIdFAST64     "lld"
+#if INT64_MAX == LONG_MAX
+# define _PRI64        "l"
+#else
+# define _PRI64        "ll"
+#endif
+
+#define PRId64 _PRI64"d"
+#define PRIdLEAST64    _PRI64"d"
+#define PRIdFAST64     _PRI64"d"
 #define PRIdMAX
 #define PRIdPTR
-#define PRIi64 "lli"
+#define PRIi64 _PRI64"i"
 #define PRIiLEAST64
 #define PRIiFAST64
 #define PRIiMAX
 #define PRIiPTR
 
-#define PRIx64 "llx"
+#define PRIx64 _PRI64"i"
 
 #endif
index ed1fce5..b2cb857 100644 (file)
@@ -94,7 +94,7 @@ extern FILE   *open_memstream(char **bufferptr, size_t *lengthptr);
 extern FILE    *fdopen(int fd, const char *modes);
 extern FILE    *tmpfile(void);
 extern int     fclose(FILE *fp);
-extern void    fflush(FILE *fp);
+extern int     fflush(FILE *fp);
 extern off_t   ftell(FILE *fp);
 extern off_t   ftello(FILE *fp);
 extern int     fseek(FILE *fp, long int amt, int whence);
index 07fc81f..fa923ee 100644 (file)
@@ -112,6 +112,8 @@ extern int  rand_p(unsigned int *seedp);
 # define SEEK_END      (-1)\r
 #endif\r
 \r
+#define MB_CUR_MAX     5       // (C99) Max number of bytes in a single multibyte character (UTF8=5)\r
+\r
 #ifdef __cplusplus\r
 }\r
 #endif\r
index 7ef1bc7..028ed27 100644 (file)
@@ -29,6 +29,7 @@ extern char   *strrchr(const char *str, int character);
 extern char    *strstr(const char *str1, const char *str2);
 extern size_t  strcspn(const char *haystack, const char *reject);
 extern size_t  strspn(const char *haystack, const char *accept);
+extern char    *strpbrk(const char *haystack, const char *accept);
 
 extern char    *strtok(char *str, const char *delim);
 extern char    *strtok_r(char *str, const char *delim, char **saveptr);
index 5e32fc8..532f09b 100644 (file)
@@ -41,6 +41,7 @@ int raise(int signal)
 void abort(void)
 {
        // raise(SIGABRT);
+       _SysDebug("abort() - %p", __builtin_return_address(0));
        _exit(-1);
 }
 
index 1bb90cd..55fd521 100644 (file)
@@ -14,6 +14,9 @@
 \r
 #define DEBUG_BUILD    0\r
 \r
+#define LOG_WARN(f,...)        _SysDebug("WARN: %s: "f, __func__ ,## __VA_ARGS__)\r
+#define LOG_NOTICE(f,...)      _SysDebug("NOTE: %s: "f, __func__ ,## __VA_ARGS__)\r
+\r
 // === CONSTANTS ===\r
 #define        _stdin  0\r
 #define        _stdout 1\r
@@ -27,9 +30,9 @@ struct sFILE  *get_file_struct();
 \r
 // === GLOBALS ===\r
 struct sFILE   _iob[STDIO_MAX_STREAMS];        // IO Buffer\r
-struct sFILE   *stdin; // Standard Input\r
-struct sFILE   *stdout;        // Standard Output\r
-struct sFILE   *stderr;        // Standard Error\r
+struct sFILE   *stdin = &_iob[0];      // Standard Input\r
+struct sFILE   *stdout = &_iob[1];     // Standard Output\r
+struct sFILE   *stderr = &_iob[2];     // Standard Error\r
 ///\note Initialised in SoMain\r
 static const int STDIN_BUFSIZ = 512;\r
 static const int STDOUT_BUFSIZ = 512;\r
@@ -38,19 +41,16 @@ static const int STDOUT_BUFSIZ = 512;
 void _stdio_init(void)\r
 {\r
        // Init FileIO Pointers\r
-       stdin = &_iob[0];\r
        stdin->FD = 0;\r
        stdin->Flags = FILE_FLAG_ALLOC|FILE_FLAG_MODE_READ|FILE_FLAG_LINEBUFFERED|FILE_FLAG_OURBUFFER;\r
        stdin->Buffer = malloc(STDIN_BUFSIZ);\r
        stdin->BufferSpace = STDIN_BUFSIZ;\r
 \r
-       stdout = &_iob[1];\r
        stdout->FD = 1;\r
        stdout->Flags = FILE_FLAG_ALLOC|FILE_FLAG_MODE_WRITE|FILE_FLAG_LINEBUFFERED|FILE_FLAG_OURBUFFER;\r
        stdout->Buffer = malloc(STDOUT_BUFSIZ);\r
        stdout->BufferSpace = STDOUT_BUFSIZ;\r
        \r
-       stderr = &_iob[2];\r
        stderr->FD = 2;\r
        stderr->Flags = FILE_FLAG_ALLOC|FILE_FLAG_MODE_WRITE;\r
 }\r
@@ -374,22 +374,23 @@ int _fflush_int(FILE *fp)
        return ret;\r
 }\r
 \r
-EXPORT void fflush(FILE *fp)\r
+EXPORT int fflush(FILE *fp)\r
 {\r
        if( !fp || fp->FD == FD_NOTOPEN )\r
-               return ;\r
+               return EBADF;\r
        \r
        // Nothing to do for memory files\r
        if( fp->FD == FD_MEMFILE )\r
-               return ;\r
+               return 0;\r
        // Memory streams, update pointers\r
        if( fp->FD == FD_MEMSTREAM ) {\r
                *fp->BufPtr = fp->Buffer;\r
                *fp->LenPtr = fp->BufferPos;\r
-               return ;\r
+               return 0;\r
        }\r
        \r
        _fflush_int(fp);\r
+       return 0;\r
 }\r
 \r
 EXPORT void clearerr(FILE *fp)\r
@@ -681,19 +682,28 @@ EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
 {\r
        size_t  ret;\r
        \r
-       if(!fp || fp->FD == -1)\r
+       if(!fp || fp->FD == -1) {\r
+               LOG_WARN("bad fp %p", fp);\r
                return -1;\r
+       }\r
        if( size == 0 || num == 0 )\r
                return 0;\r
        \r
        if( _GetFileMode(fp) != FILE_FLAG_MODE_READ ) {\r
                errno = 0;\r
+               LOG_WARN("not open for read");\r
+               if( fp == stdin ) {\r
+                       LOG_WARN("BUGCHECK FAIL: stdin was not open for read");\r
+                       exit(129);\r
+               }\r
                return -1;\r
        }\r
 \r
        // Don't read if EOF is set\r
-       if( fp->Flags & FILE_FLAG_EOF )\r
+       if( fp->Flags & FILE_FLAG_EOF ) {\r
+               LOG_NOTICE("EOF");\r
                return 0;\r
+       }\r
 \r
        \r
        if( fp->FD == FD_MEMFILE ) {\r
@@ -701,6 +711,7 @@ EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
        }\r
        else if( fp->FD == FD_MEMSTREAM ) {\r
                //return _fread_memstream(ptr, size, num, fp);\r
+               LOG_WARN("Reading from a mem stream");\r
                errno = EBADF;\r
                return 0;\r
        }\r
@@ -744,6 +755,8 @@ EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
                                extra, size, num\r
                                );\r
                }\r
+               LOG_NOTICE("Incomplete read %i/%i bytes (object size %i)",\r
+                       ret, bytes, size);\r
        }\r
        \r
        return ret / size;\r
@@ -782,13 +795,12 @@ EXPORT char *fgets(char *s, int size, FILE *fp)
  */\r
 EXPORT int fputc(int c, FILE *fp)\r
 {\r
-       char    ch = c;\r
+       unsigned char   ch = c;\r
        return fwrite(&ch, 1, 1, fp);\r
 }\r
 \r
 EXPORT int putchar(int c)\r
 {\r
-       c &= 0xFF;\r
        return fputc(c, stdout);\r
 }\r
 \r
@@ -798,7 +810,7 @@ EXPORT int putchar(int c)
  */\r
 EXPORT int fgetc(FILE *fp)\r
 {\r
-       char    ret = 0;\r
+       unsigned char   ret = 0;\r
        if( fread(&ret, 1, 1, fp) != 1 )\r
                return -1;\r
        return ret;\r
@@ -812,7 +824,6 @@ EXPORT int getchar(void)
 \r
 EXPORT int puts(const char *str)\r
 {\r
-       \r
        if(!str)        return 0;\r
         int    len = strlen(str);\r
        \r
index aa79ec9..d61d51d 100644 (file)
@@ -2,7 +2,7 @@
  * AcessOS Basic C Library
  * string.c
  */
-#include <acess/sys.h>
+//#include <acess/sys.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <ctype.h>
  * \fn EXPORT int strcmp(const char *s1, const char *s2)
  * \brief Compare two strings
  */
-EXPORT int strcmp(const char *s1, const char *s2)
+EXPORT int strcmp(const char *_s1, const char *_s2)
 {
-       while(*s1 && *s1 == *s2) {
-               s1++; s2++;
-       }
-       return (int)*s1 - (int)*s2;
+       return strncmp(_s1, _s2, SIZE_MAX);
 }
 
 /**
- * \fn EXPORT int strncmp(const char *s1, const char *s2)
- * \brief Compare two strings
+ * \fn EXPORT int strncmp(const char *s1, const char *s2, size_t n)
+ * \brief Compare two strings, stopping after n characters
  */
-EXPORT int strncmp(const char *s1, const char *s2, size_t n)
+EXPORT int strncmp(const char *_s1, const char *_s2, size_t n)
 {
+       const unsigned char*    s1 = (const unsigned char*)_s1;
+       const unsigned char*    s2 = (const unsigned char*)_s2;
        while(n && *s1 && *s1 == *s2)
        {
                s1++; s2++;
@@ -38,23 +37,31 @@ EXPORT int strncmp(const char *s1, const char *s2, size_t n)
                return (int)*s1 - (int)*s2;
 }
 
-EXPORT int strcasecmp(const char *s1, const char *s2)
+EXPORT int strcasecmp(const char *_s1, const char *_s2)
 {
-        int    rv;
-       while( (rv = toupper(*s1) - toupper(*s2)) == 0 && *s1 != '\0' && *s2 != '\0' ) {
-               s1++; s2++;
-       }
-       return rv;
+       return strncasecmp(_s1, _s2, SIZE_MAX);
 }
 
-EXPORT int strncasecmp(const char *s1, const char *s2, size_t n)
+EXPORT int strncasecmp(const char *_s1, const char *_s2, size_t n)
 {
-        int    rv = 0;
-       if( n == 0 )    return 0;
-       while(n -- && (rv = toupper(*s1) - toupper(*s2)) == 0 && *s1 != '\0' && *s2 != '\0') {
-               s1++; s2++;
+       const unsigned char*    s1 = (const unsigned char*)_s1;
+       const unsigned char*    s2 = (const unsigned char*)_s2;
+       while( n-- && *s1 && *s2 )
+       {
+               if( *s1 != *s2 )
+               {
+                       int rv;
+                       rv = toupper(*s1) - toupper(*s2);
+                       if(rv != 0)
+                               return rv;
+                       rv = tolower(*s1) - tolower(*s2);
+                       if(rv != 0)
+                               return rv;
+               }
+               s1 ++;
+               s2 ++;
        }
-       return rv;
+       return 0;
 }
 
 /**
@@ -80,8 +87,13 @@ EXPORT char *strcpy(char *dst, const char *src)
 EXPORT char *strncpy(char *dst, const char *src, size_t num)
 {
        char *to = dst;
-       while(*src && num--)    *to++ = *src++;
-       *to = '\0';
+       while(num --)
+       {
+               if(*src)
+                       *to++ = *src++;
+               else
+                       *to++ = '\0';
+       }
        return dst;
 }
 
@@ -118,9 +130,10 @@ EXPORT char *strncat(char *dst, const char *src, size_t n)
  */
 EXPORT size_t strlen(const char *str)
 {
-       size_t  retval;
-       for(retval = 0; *str != '\0'; str++, retval++);
-       return retval;
+       size_t  len = 0;
+       while(str[len] != '\0')
+               len ++;
+       return len;
 }
 
 /**
@@ -130,8 +143,9 @@ EXPORT size_t strlen(const char *str)
  */
 EXPORT size_t strnlen(const char *str, size_t maxlen)
 {
-       size_t  len;
-       for( len = 0; maxlen -- && *str; str ++, len ++ );
+       size_t  len = 0;
+       while( len < maxlen && str[len] != '\0' )
+               len ++;
        return len;
 }
 
@@ -171,11 +185,12 @@ EXPORT char *strndup(const char *str, size_t maxlen)
  * \fn EXPORT char *strchr(char *str, int character)
  * \brief Locate a character in a string
  */
-EXPORT char *strchr(const char *str, int character)
+EXPORT char *strchr(const char *_str, int character)
 {
+       const unsigned char* str = (const unsigned char*)_str;
        for(;*str;str++)
        {
-               if(*str == character)
+               if( *str == character )
                        return (char*)str;
        }
        return NULL;
@@ -185,11 +200,10 @@ EXPORT char *strchr(const char *str, int character)
  * \fn EXPORT char *strrchr(char *str, int character)
  * \brief Locate the last occurance of a character in a string
  */
-EXPORT char *strrchr(const char *str, int character)
+EXPORT char *strrchr(const char *_str, int character)
 {
-        int    i;
-       i = strlen(str)-1;
-       while(i--)
+       const unsigned char* str = (const unsigned char*)_str;
+       for( size_t i = strlen(_str); i--; )
        {
                if(str[i] == character)
                        return (void*)&str[i];
@@ -277,6 +291,8 @@ EXPORT void *memcpy(void *__dest, const void *__src, size_t count)
        return __dest;
 }
 
+// TODO: memccpy (POSIX defined)
+
 /**
  * \fn EXPORT void *memmove(void *dest, const void *src, size_t count)
  * \brief Copy data in memory, avoiding overlap problems
@@ -316,7 +332,7 @@ EXPORT int memcmp(const void *mem1, const void *mem2, size_t count)
        while(count--)
        {
                if( *p1 != *p2 )
-                       return *p1 - *p2;
+                       return (int)*p1 - (int)*p2;
                p1 ++;
                p2 ++;
        }
@@ -332,11 +348,12 @@ EXPORT int memcmp(const void *mem1, const void *mem2, size_t count)
  */
 EXPORT void *memchr(const void *ptr, int value, size_t num)
 {
+       const unsigned char* buf = ptr;
        while(num--)
        {
-               if( *(const unsigned char*)ptr == (unsigned char)value )
-                       return (void*)ptr;
-               ptr ++;
+               if( *buf == (unsigned char)value )
+                       return (void*)buf;
+               buf ++;
        }
        return NULL;
 }
@@ -344,12 +361,13 @@ EXPORT void *memchr(const void *ptr, int value, size_t num)
 EXPORT size_t strcspn(const char *haystack, const char *reject)
 {
        size_t  ret = 0;
-        int    i;
        while( *haystack )
        {
-               for( i = 0; reject[i] && reject[i] == *haystack; i ++ );
-
-               if( reject[i] ) return ret;
+               for( int i = 0; reject[i]; i ++ )
+               {
+                       if( reject[i] == *haystack )
+                               return ret;
+               }
                ret ++;
        }
        return ret;
@@ -358,17 +376,32 @@ EXPORT size_t strcspn(const char *haystack, const char *reject)
 EXPORT size_t strspn(const char *haystack, const char *accept)
 {
        size_t  ret = 0;
-        int    i;
        while( *haystack )
        {
-               for( i = 0; accept[i] && accept[i] == *haystack; i ++ );
-
-               if( !accept[i] )        return ret;
+               for( int i = 0; accept[i]; i ++ )
+               {
+                       if( accept[i] != *haystack )
+                               return ret;
+               }
                ret ++;
        }
        return ret;
 }
 
+EXPORT char *strpbrk(const char *haystack, const char *accept)
+{
+       while( *haystack )
+       {
+               for( int i = 0; accept[i]; i ++ )
+               {
+                       if( accept[i] == *haystack )
+                               return (char*)haystack;
+               }
+               haystack ++;
+       }
+       return NULL;
+}
+
 char *strtok(char *str, const char *delim)
 {
        static char *__saveptr;
index de7f725..84bf000 100644 (file)
@@ -12,7 +12,7 @@
 
 unsigned long long strtoull(const char *str, char **end, int base)
 {
-       long long       ret = 0;
+       unsigned long long      ret = 0;
        
        if( !str || base < 0 || base > 36 || base == 1 ) {
                if(end)
@@ -27,7 +27,7 @@ unsigned long long strtoull(const char *str, char **end, int base)
        
        // Handle base detection for hex
        if( base == 0 || base == 16 ) {
-               if( *str == '0' && str[1] == 'x' ) {
+               if( *str == '0' && (str[1] == 'x' || str[1] == 'X') && isxdigit(str[2]) ) {
                        str += 2;
                        base = 16;
                }
@@ -43,6 +43,10 @@ unsigned long long strtoull(const char *str, char **end, int base)
        if( base == 0 )
                base = 10;
 
+       // Value before getting within 1 digit of ULLONG_MAX
+       // - Used to avoid overflow in more accurate check
+       unsigned long long      max_before_ullong_max = ULLONG_MAX / base;
+       unsigned int    space_above = ULLONG_MAX - max_before_ullong_max * base;
        while( *str )
        {
                 int    next = -1;
@@ -58,8 +62,31 @@ unsigned long long strtoull(const char *str, char **end, int base)
                        if( 'a' <= *str && *str <= 'a'+base-10-1 )
                                next = *str - 'a' + 10;
                }
+               //_SysDebug("strtoull - ret=0x%llx,next=%i,str='%s'", ret, next, str);
                if( next < 0 )
                        break;
+               
+               // If we're already out of range, keep eating
+               if( ret == ULLONG_MAX ) {
+                       errno = ERANGE;
+                       str ++;
+                       // Keep eating until first unrecognised character
+                       continue;
+               }
+       
+               // Rough then accurate check against max value
+               if( ret >= max_before_ullong_max )
+               {
+                       //_SysDebug("strtoull - 0x%llx>0x%llx", ret, max_before_ullong_max);
+                       if( (ret - max_before_ullong_max) * base + next > space_above ) {
+                               //_SysDebug("strtoull - %u*%u+%u (%u) > %u",
+                               //      (unsigned int)(ret - max_before_ullong_max), base, next, space_above);
+                               ret = ULLONG_MAX;
+                               errno = ERANGE;
+                               str ++;
+                               continue;
+                       }
+               }
                ret *= base;
                ret += next;
                str ++;
@@ -85,7 +112,6 @@ unsigned long strtoul(const char *ptr, char **end, int base)
 long long strtoll(const char *str, char **end, int base)
 {
         int    neg = 0;
-       unsigned long long      ret;
 
        if( !str ) {
                errno = EINVAL;
@@ -96,17 +122,37 @@ long long strtoll(const char *str, char **end, int base)
                str++;
        
        // Check for negative (or positive) sign
-       if(*str == '-' || *str == '+') {
+       if(*str == '-' || *str == '+')
+       {
+               //_SysDebug("strtoll - str[0:1] = '%.2s'", str);
+               if( !isdigit(str[1]) ) {
+                       // Non-digit, invalid string
+                       if(end) *end = (char*)str;
+                       return 0;
+               }
                neg = (*str == '-');
                str++;
        }
 
-       ret = strtoull(str, end, base); 
+       unsigned long long ret = strtoull(str, end, base);      
+       //_SysDebug("strtoll - neg=%i,ret=%llu", neg, ret);
 
-       if( neg )
+       if( neg ) {
+               // Abuses unsigned integer overflow
+               if( ret + LLONG_MIN < ret ) {
+                       errno = ERANGE;
+                       return LLONG_MIN;
+               }
                return -ret;
+       }
        else
+       {
+               if( ret > LLONG_MAX ) {
+                       errno = ERANGE;
+                       return LLONG_MAX;
+               }
                return ret;
+       }
 }
 
 long strtol(const char *str, char **end, int base)
index a1c67ff..922943e 100644 (file)
@@ -45,21 +45,8 @@ tCPUID       gCPU_Features;
  */\r
 int SoMain(UNUSED(uintptr_t, BaseAddress), UNUSED(int, argc), UNUSED(char **, argv), char **envp)\r
 {\r
-       // Init for env.c\r
        environ = envp;\r
 \r
-       #if 0   \r
-       {\r
-                int    i = 0;\r
-               char    **tmp;\r
-               _SysDebug("envp = %p", envp);\r
-               for(tmp = envp; *tmp; tmp++,i++)\r
-               {\r
-                       _SysDebug("envp[%i] = '%s'", i, *tmp);\r
-               }\r
-       }\r
-       #endif\r
-\r
        _stdio_init();  \r
        \r
        #if USE_CPUID\r
@@ -76,7 +63,7 @@ int SoMain(UNUSED(uintptr_t, BaseAddress), UNUSED(int, argc), UNUSED(char **, ar
        // Set Error handler\r
        _SysSetFaultHandler(ErrorHandler);\r
        \r
-       return 1;\r
+       return 0;\r
 }\r
 \r
 int ErrorHandler(int Fault)\r
index 185af88..611ae9b 100644 (file)
@@ -145,11 +145,18 @@ size_t strftime(char*restrict s, size_t maxsize, const char*restrict format, con
                if( *format == 0 )
                        break;
                format ++;
+               
+               // If EOS is hit on a '%', break early
+               if( *format == 0 )
+                       break;
                switch(*format++)
                {
-               case 0: format--;       break;
-               case '%':       ofs += _puts(s, maxsize, ofs, format-1, 1);     break;
-               case 'd':       // The day of the month as a decimal number (range 01 to 31).
+               // Literal '%', 
+               case '%':
+                       ofs += _puts(s, maxsize, ofs, format-1, 1);
+                       break;
+               // The day of the month as a decimal number (range 01 to 31).
+               case 'd':
                        {
                        char tmp[2] = {'0','0'};
                        tmp[0] += (timeptr->tm_mday / 10) % 10;
@@ -157,6 +164,24 @@ size_t strftime(char*restrict s, size_t maxsize, const char*restrict format, con
                        ofs += _puts(s, maxsize, ofs, tmp, 2);
                        }
                        break;
+               // Two-digit 24 hour
+               case 'H':
+                       {
+                       char tmp[2] = {'0','0'};
+                       tmp[0] += (timeptr->tm_hour / 10) % 10;
+                       tmp[1] +=  timeptr->tm_hour % 10;
+                       ofs += _puts(s, maxsize, ofs, tmp, 2);
+                       }
+                       break;
+               // Two-digit minutes
+               case 'M':
+                       {
+                       char tmp[2] = {'0','0'};
+                       tmp[0] += (timeptr->tm_min / 10) % 10;
+                       tmp[1] +=  timeptr->tm_min % 10;
+                       ofs += _puts(s, maxsize, ofs, tmp, 2);
+                       }
+                       break;
                default:
                        _SysDebug("TODO: strftime('...%%%c...')", format[-1]);
                        break;
index 6fed585..00eb13f 100644 (file)
@@ -114,7 +114,7 @@ int64_t get_days_since_y2k(int64_t ts, int *h, int *m, int *s)
        ts -= n_leap;
        #endif
        
-       int64_t days = ts / 24*60*60;
+       int64_t days = ts / (24*60*60);
        int64_t seconds = ts % (24*60*60);
        *s = (is_ls ? 60 : seconds % 60);
        *m = (seconds/60 % 24);
diff --git a/Usermode/Libraries/libiconv.so_src/Makefile b/Usermode/Libraries/libiconv.so_src/Makefile
new file mode 100644 (file)
index 0000000..50f257a
--- /dev/null
@@ -0,0 +1,15 @@
+# Acess 2 "libiconv"
+#
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS   += -Wall
+LDFLAGS  += -lc -soname libiconv.so
+
+OBJ = iconv.o
+BIN = libiconv.so
+
+include ../Makefile.tpl
+
+
diff --git a/Usermode/Libraries/libiconv.so_src/iconv.c b/Usermode/Libraries/libiconv.so_src/iconv.c
new file mode 100644 (file)
index 0000000..d339555
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ */
+#include <iconv.h>
+#include <acess/sys.h>
+
+// === CODE ===
+int SoMain(void)
+{
+       return 0;
+}
+
+iconv_t iconv_open(const char *to, const char *from)
+{
+       return NULL;
+}
+
+size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
+{
+       _SysDebug("WTF are you using iconv for?");
+       return 0;
+}
+
+int iconv_close(iconv_t cd)
+{
+       return 0;
+}
+
diff --git a/Usermode/Libraries/libiconv.so_src/include_exp/iconv.h b/Usermode/Libraries/libiconv.so_src/include_exp/iconv.h
new file mode 100644 (file)
index 0000000..817abee
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Acess2 libiconv
+ * - By John Hodge (thePowersGang)
+ *
+ * iconv.h
+ * - External header
+ */
+#ifndef _ICONV_H_
+#define _ICONV_H_
+
+#include <stddef.h>
+
+typedef void   *iconv_t;
+
+extern iconv_t iconv_open(const char *to, const char *from);
+extern size_t  iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
+extern int     iconv_close(iconv_t cd);
+
+#endif
+
diff --git a/Usermode/Libraries/libintl.so_src/Makefile b/Usermode/Libraries/libintl.so_src/Makefile
new file mode 100644 (file)
index 0000000..398ffc4
--- /dev/null
@@ -0,0 +1,16 @@
+# Acess 2 "libintl"
+#
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS   += -Wall
+LDFLAGS  += -lc
+
+OBJ = main.o gettext.o
+BIN = libintl.so
+
+include ../Makefile.tpl
+
+
+
diff --git a/Usermode/Libraries/libintl.so_src/gettext.c b/Usermode/Libraries/libintl.so_src/gettext.c
new file mode 100644 (file)
index 0000000..3b10d41
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ */
+#include <stddef.h>
+#include <libintl.h>
+
+// === CODE ===
+char *gettext(const char *msg)
+{
+       return dcgettext(NULL, msg, 0);
+}
+char *dgettext(const char *domain, const char *msg)
+{
+       return dcgettext(domain, msg, 0);
+}
+char *dcgettext(const char *domain, const char *msg, int category)
+{
+       return (char*)msg;
+}
+
+char *ngettext(const char *msg, const char *msgp, unsigned long int n)
+{
+       return dcngettext(NULL, msg, msgp, n, 0);
+}
+char *dngettext(const char *domain, const char *msg, const char *msgp, unsigned long int n)
+{
+       return dcngettext(domain, msg, msgp, n, 0);
+}
+char *dcngettext(const char *domain, const char *msg, const char *msgp, unsigned long int n, int category)
+{
+       if( n == 1 )
+               return (char*)msg;
+       else
+               return (char*)msgp;
+}
+
diff --git a/Usermode/Libraries/libintl.so_src/include_exp/libintl.h b/Usermode/Libraries/libintl.so_src/include_exp/libintl.h
new file mode 100644 (file)
index 0000000..54c0993
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ */
+#ifndef _LIBINTL_H_
+#define _LIBINTL_H_
+
+extern char    *gettext(const char *msg);
+extern char    *dgettext(const char *domain, const char *msg);
+extern char    *dcgettext(const char *domain, const char *msg, int category);
+extern char    *ngettext(const char *msg, const char *msgp, unsigned long int n);
+extern char    *dngettext(const char *domain, const char *msg, const char *msgp, unsigned long int n);
+extern char    *dcngettext(const char *domain, const char *msg, const char *msgp, unsigned long int n, int category);
+
+#endif
diff --git a/Usermode/Libraries/libintl.so_src/main.c b/Usermode/Libraries/libintl.so_src/main.c
new file mode 100644 (file)
index 0000000..30dead7
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ */
+
+int SoMain(void)
+{
+       return 0;
+}
index d6d988f..a860012 100644 (file)
 extern "C" {
 #endif
 
+typedef float  float_t;
+typedef double double_t;
+
+
+#define INFINITY       (*(float*)((uint32_t[]){0x78000000}))
+#define NAN    (*(float*)((uint32_t[]){0x78000001}))
+
 extern double  pow(double x, double y);
 extern double  exp(double x);
 extern double  log(double val);
index 29abaaa..10d5b96 100644 (file)
@@ -7,6 +7,9 @@ CFLAGS   += -Wall
 LDFLAGS  += -lc -soname libnet.so
 
 OBJ = main.o address.o socket.o
+OBJ += hostnames.o dns.o
 BIN = libnet.so
 
+UTESTS = dns
+
 include ../Makefile.tpl
diff --git a/Usermode/Libraries/libnet.so_src/TEST_dns.c b/Usermode/Libraries/libnet.so_src/TEST_dns.c
new file mode 100644 (file)
index 0000000..26b36bf
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ */
+#include "include/dns.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+
+extern int DNS_int_ParseResponse(const void* packet, size_t return_len, void *info, handle_record_t* handle_record_t);
+
+// Complex response from "Q ssh.ucc.asn.au A IN"
+const uint8_t test_packet_1[] = {
+       0xac, 0x00, 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x03, 0x73, 0x73, 0x68, 0x03, 0x75, 0x63, 0x63, 0x03, 0x61, 0x73, 0x6e, 0x02, 0x61, 0x75, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x77, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x78, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x79, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x61, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x7a, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x62, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x75, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x76, 0xc0, 0x18, 0xc0, 0x2c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x25, 0xd1, 0xc0, 0x05, 0xc0, 0x3c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x25, 0xd1, 0xc2, 0x05, 0xc0, 0x4c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x25, 0xd1, 0xc4, 0x05, 0xc0, 0x5c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x3a, 0x41, 0xfe, 0x49, 0xc0, 0x6c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x25, 0xd1, 0xc6, 0x05, 0xc0, 0x7c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x3a, 0x41, 0xfd, 0x49, 0xc0, 0x8c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0xd3, 0x1d, 0x85, 0x20, 0xc0, 0x9c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0xca, 0x0c, 0x1f, 0x8d, 
+       };
+
+#define TEST_REL_INT(exp, rel, have) do { \
+       int a = (exp);\
+       int b = (have);\
+       if( !(a rel b) ) { \
+               fprintf(stderr, "TEST_REL_INT("#exp" "#rel" "#exp") FAILED l=%i r=%i", \
+                       a, b); \
+               return 1; \
+       } \
+} while(0)
+       
+int test_response_parse_1_cb(void *info, const char *name, enum eTypes type, enum eClass class, unsigned int ttl, size_t rdlength, const void *rdata)
+{
+       int* stagep = info;
+       switch( *stagep )
+       {
+       case 0:
+               TEST_REL_INT(0, ==, strcmp(name, "au."));
+               break;
+       }
+       (*stagep) += 1;
+       return 0;
+}
+int test_response_parse_1(void)
+{
+       int stage = 0;
+       TEST_REL_INT(0, ==, DNS_int_ParseResponse(test_packet_1, sizeof(test_packet_1), &stage, test_response_parse_1_cb) );
+       return 0;
+}
+
+int main(void)
+{
+        int rv = 0;
+       // - Name Encode
+       // - Name Decode
+       // - Response parsing
+       rv |= test_response_parse_1();
+       return rv;
+}
index 66a28b1..d103e64 100644 (file)
@@ -7,7 +7,8 @@
  */
 #include <net.h>
 #include <stdint.h>
-#include <stdio.h>
+#include <stdio.h>     // sprintf
+#include <stdlib.h>
 #define DEBUG  0
 
 static inline uint32_t htonl(uint32_t v)
@@ -37,43 +38,50 @@ static inline uint16_t htons(uint16_t v)
  */
 static int Net_ParseIPv4Addr(const char *String, uint8_t *Addr)
 {
-        int    i = 0;
         int    j;
-        int    val;
+       const char *pos = String;
        
-       for( j = 0; String[i] && j < 4; j ++ )
+       for( j = 0; *pos && j < 4; j ++ )
        {
-               val = 0;
-               for( ; String[i] && String[i] != '.'; i++ )
-               {
-                       if('0' > String[i] || String[i] > '9') {
-                               #if DEBUG
-                               printf("0<c<9 expected, '%c' found\n", String[i]);
-                               #endif
-                               return 0;
-                       }
-                       val = val*10 + String[i] - '0';
+               char    *end;
+               unsigned long val = strtoul(pos, &end, 10);
+               if( *end && *end != '.' ) {
+                       #if DEBUG
+                       _SysDebug("%s: Unexpected character, '%c' found", __func__, *end);
+                       #endif
+                       return 0;
+               }
+               if( *pos == '.' ) {
+                       #if DEBUG
+                       _SysDebug("%s: Two dots in a row", __func__);
+                       #endif
+                       return 0;
                }
                if(val > 255) {
                        #if DEBUG
-                       printf("val > 255 (%i)\n", val);
+                       _SysDebug("%s: val > 255 (%i)", __func__, val);
                        #endif
                        return 0;
                }
+               #if DEBUG
+               _SysDebug("%s: Comp '%.*s' = %lu", __func__, end - pos, pos, val);
+               #endif
                Addr[j] = val;
                
-               if(String[i] == '.')
-                       i ++;
+               pos = end;
+               
+               if(*pos == '.')
+                       pos ++;
        }
        if( j != 4 ) {
                #if DEBUG
-               printf("4 parts expected, %i found\n", j);
+               _SysDebug("%s: 4 parts expected, %i found", __func__, j);
                #endif
                return 0;
        }
-       if(String[i] != '\0') {
+       if(*pos != '\0') {
                #if DEBUG
-               printf("EOS != '\\0', '%c'\n", String[i]);
+               _SysDebug("%s: EOS != '\\0', '%c'", __func__, *pos);
                #endif
                return 0;
        }
diff --git a/Usermode/Libraries/libnet.so_src/dns.c b/Usermode/Libraries/libnet.so_src/dns.c
new file mode 100644 (file)
index 0000000..3bb9c35
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * Acess2 Networking Toolkit
+ * By John Hodge (thePowersGang)
+ * 
+ * dns.c
+ * - Hostname<->Address resolution
+ */
+#include <stddef.h>    // size_t / NULL
+#include <stdint.h>    // uint*_t
+#include <string.h>    // memcpy, strchr
+#include <assert.h>
+#include <acess/sys.h> // for _SysSelect
+#include <acess/fd_set.h>      // FD_SET
+#include <net.h>
+#include "include/dns.h"
+
+// === PROTOTYPES ===
+//int DNS_Query(int ServerAType, const void *ServerAddr, const char *name, enum eTypes type, enum eClass class, handle_record_t* handle_record, void *info);
+int DNS_int_ParseResponse(const void* packet, size_t return_len, void *info, handle_record_t* handle_record_t);
+size_t DNS_EncodeName(void *buf, const char *dotted_name);
+int DNS_DecodeName(char dotted_name[256], const void *buf, size_t ofs, size_t space);
+int DNS_int_ParseRR(const void *buf, size_t ofs, size_t space, char* name_p, enum eTypes* type_p, enum eClass* class_p, uint32_t* ttl_p, size_t* rdlength_p);
+
+static uint16_t        get16(const void *buf);
+static uint32_t        get32(const void *buf);
+static size_t put16(void *buf, uint16_t val);
+
+
+// === CODE ===
+int DNS_Query(int ServerAType, const void *ServerAddr, const char *name, enum eTypes type, enum eClass class, handle_record_t* handle_record, void *info)
+{
+       int namelen = DNS_EncodeName(NULL, name);
+       assert(namelen < 256);
+       size_t  pos = 0;
+       char    packet[ 512 ];
+       assert( (6*2) + (namelen + 2*2) < 512 );
+       // - Header
+       pos += put16(packet + pos, 0xAC00);     // Identifier (arbitary)
+       pos += put16(packet + pos, (0 << 0) | (0 << 1) | (1 << 8) );    // Op : Query, Standard, Recursion
+       pos += put16(packet + pos, 1);  // QDCount
+       pos += put16(packet + pos, 0);  // ANCount
+       pos += put16(packet + pos, 0);  // NSCount
+       pos += put16(packet + pos, 0);  // ARCount
+       // - Question
+       pos += DNS_EncodeName(packet + pos, name);
+       pos += put16(packet + pos, type);       // QType
+       pos += put16(packet + pos, class);      // QClass
+       
+       assert(pos <= sizeof(packet));
+       
+       // Send and wait for reply
+       // - Lock
+       //  > TODO: Lock DNS queries
+       // - Send
+       int sock = Net_OpenSocket_UDP(ServerAType, ServerAddr, 53, 0);
+       if( sock < 0 ) {
+               // Connection failed
+               _SysDebug("DNS_Query - UDP open failed");
+               // TODO: Correctly report this failure with a useful error code
+               return 1;
+       }
+       int rv = Net_UDP_SendTo(sock, 53, ServerAType, ServerAddr, pos, packet);
+       if( rv != pos ) {
+               _SysDebug("DNS_Query - Write failed");
+               // TODO: Error reporting
+               _SysClose(sock);
+               return 1;
+       }
+       // - Wait
+       {
+                int    nfd = sock + 1;
+               fd_set  fds;
+               FD_ZERO(&fds);
+               FD_SET(sock, &fds);
+               int64_t timeout = 2000; // Give it two seconds, should be long enough
+               rv = _SysSelect(nfd, &fds, NULL, NULL, &timeout, 0);
+               if( rv == 0 ) {
+                       // Timeout with no reply, give up
+                       _SysDebug("DNS_Query - Timeout");
+                       _SysClose(sock);
+                       return 1;
+               }
+               if( rv < 0 ) {
+                       // Oops, select failed
+                       _SysDebug("DNS_Query - Select failure");
+                       _SysClose(sock);
+                       return 1;
+               }
+       }
+       int return_len = Net_UDP_RecvFrom(sock, NULL, NULL, NULL, sizeof(packet), packet);
+       if( return_len <= 0 ) {
+               // TODO: Error reporting
+               _SysDebug("DNS_Query - Read failure");
+               _SysClose(sock);
+               return 1;
+       }
+       _SysClose(sock);
+       // - Release
+       //  > TODO: Lock DNS queries
+       
+       // For each response in the answer (and additional) sections, call the passed callback
+       return DNS_int_ParseResponse(packet, return_len, info, handle_record);
+}
+
+int DNS_int_ParseResponse(const void* buf, size_t return_len, void *info, handle_record_t* handle_record)
+{
+       const uint8_t* packet = buf;
+       char    rr_name[256];
+       unsigned int id = get16(packet + 0);
+       if( id != 0xAC00 ) {
+               _SysDebug("DNS_Query - Packet ID mismatch");
+               return 2;
+       }
+       unsigned int flags = get16(packet + 2);
+       unsigned int qd_count = get16(packet + 4);
+       unsigned int an_count = get16(packet + 6);
+       unsigned int ns_count = get16(packet + 8);
+       unsigned int ar_count = get16(packet + 10);
+       size_t pos = 6*2;
+       // TODO: Can I safely assert / fail if qd_count is non-zero?
+       // - Questions, ignored
+       for( unsigned int i = 0; i < qd_count; i ++ ) {
+               int rv = DNS_DecodeName(rr_name, packet, pos, return_len);
+               if( rv < 0 ) {
+                       _SysDebug("DNS_Query - Parse error in QD");
+                       return 1;
+               }
+               pos += rv + 2*2;
+       }
+       // - Answers, pass on to handler
+       for( unsigned int i = 0; i < an_count; i ++ )
+       {
+               enum eTypes     type;
+               enum eClass     class;
+               uint32_t        ttl;
+               size_t  rdlength;
+               int rv = DNS_int_ParseRR(packet, pos, return_len, rr_name, &type, &class, &ttl, &rdlength);
+               if( rv < 0 ) {
+                       _SysDebug("DNS_Query - Parse error in AN");
+                       return 1;
+               }
+               pos += rv;
+               
+               handle_record(info, rr_name, type, class, ttl, rdlength, packet + pos - rdlength);
+       }
+       // Authority Records (should all be NS records)
+       for( unsigned int i = 0; i < ns_count; i ++ )
+       {
+               size_t  rdlength;
+               int rv = DNS_int_ParseRR(packet, pos, return_len, rr_name, NULL, NULL, NULL, &rdlength);
+               if( rv < 0 ) {
+                       _SysDebug("DNS_Query - Parse error in NS");
+                       return 1;
+               }
+               pos += rv;
+       }
+       // - Additional records, pass to handler
+       for( unsigned int i = 0; i < ar_count; i ++ )
+       {
+               enum eTypes     type;
+               enum eClass     class;
+               uint32_t        ttl;
+               size_t  rdlength;
+               int rv = DNS_int_ParseRR(packet, pos, return_len, rr_name, &type, &class, &ttl, &rdlength);
+               if( rv < 0 ) {
+                       _SysDebug("DNS_Query - Parse error in AR");
+                       return 1;
+               }
+               pos += rv;
+               
+               handle_record(info, rr_name, type, class, ttl, rdlength, packet + pos - rdlength);
+       }
+       
+       return 0;
+}
+
+/// Encode a dotted name as a DNS name
+size_t DNS_EncodeName(void *buf, const char *dotted_name)
+{
+       size_t  ret = 0;
+       const char *str = dotted_name;
+       uint8_t *buf8 = buf;
+       while( *str )
+       {
+               const char *next = strchr(str, '.');
+               size_t seg_len = (next ? next - str : strlen(str));
+               if( seg_len > 63 ) {
+                       // Oops, too long (truncate)
+                       seg_len = 63;
+               }
+               if( seg_len == 0 && next != NULL ) {
+                       // '..' encountered, invalid (skip)
+                       str = next+1;
+                       continue ;
+               }
+               
+               if( buf8 )
+               {
+                       buf8[ret] = seg_len;
+                       memcpy(buf8+ret+1, str, seg_len);
+               }
+               ret += 1 + seg_len;
+               
+               if( next == NULL ) {
+                       // No trailing '.', assume it's there? Yes, need to be NUL terminated
+                       if(buf8)        buf8[ret] = 0;
+                       ret ++;
+                       break;
+               }
+               else {
+                       str = next + 1;
+               }
+       }
+       return ret;
+}
+
+// Decode a name (including trailing . for root)
+int DNS_DecodeName(char dotted_name[256], const void *buf, size_t ofs, size_t space)
+{
+       int consumed = 0;
+       int out_pos = 0;
+       const uint8_t *buf8 = (const uint8_t*)buf + ofs;
+       for( ;; )
+       {
+               if( ofs + consumed + 1 > space ) {
+                       _SysDebug("DNS_DecodeName - Len byte OOR space=%i", space);
+                       return -1;
+               }
+               uint8_t seg_len = *buf8;
+               buf8 ++;
+               consumed ++;
+               // Done
+               if( seg_len == 0 )
+                       break;
+               if( (seg_len & 0xC0) == 0xC0 )
+               {
+                       // Backreference, the rest of the name is a backref
+                       char tmp[256];
+                       int ref_ofs = get16(buf8 - 1) & 0x3FFF;
+                       consumed += 1, buf8 += 1;       // Only one, previous inc still applies
+                       _SysDebug("DNS_DecodeName - Nested at %i", ref_ofs);
+                       if( DNS_DecodeName(tmp, buf, ref_ofs, space) < 0 )
+                               return -1;
+                       memcpy(dotted_name+out_pos, tmp, strlen(tmp));
+                       out_pos += strlen(tmp);
+                       break;
+               }
+               // Protocol violation (segment too long)
+               if( seg_len >= 64 ) {
+                       _SysDebug("DNS_DecodeName - Seg too long %i", seg_len);
+                       return -1;
+               }
+               // Protocol violation (overflowed end of buffer)
+               if( ofs + consumed + seg_len > space ) {
+                       _SysDebug("DNS_DecodeName - Seg OOR %i+%i>%i", consumed, seg_len, space);
+                       return -1;
+               }
+               // Protocol violation (name was too long)
+               if( out_pos + seg_len + 1 > 255 ) {
+                       _SysDebug("DNS_DecodeName - Dotted name too long %i+%i+1 > %i",
+                               out_pos, seg_len, 255);
+                       return -1;
+               }
+               
+               _SysDebug("DNS_DecodeName : Seg %i '%.*s'", seg_len, seg_len, buf8);
+               
+               // Read segment
+               memcpy(dotted_name + out_pos, buf8, seg_len);
+               buf8 += seg_len;
+               consumed += seg_len;
+               out_pos += seg_len;
+               
+               // Place '.'
+               dotted_name[out_pos] = '.';
+               out_pos ++;
+       }
+       dotted_name[out_pos] = '\0';
+       _SysDebug("DNS_DecodeName - '%s', consumed = %i", dotted_name, consumed);
+       return consumed;
+}
+
+// Parse a Resource Record
+int DNS_int_ParseRR(const void *buf, size_t ofs, size_t space, char* name_p, enum eTypes* type_p, enum eClass* class_p, uint32_t* ttl_p, size_t* rdlength_p)
+{
+       const uint8_t   *buf8 = buf;
+       size_t  consumed = 0;
+       
+       // 1. Name
+       int rv = DNS_DecodeName(name_p, buf, ofs, space);
+       if(rv < 0)      return -1;
+       
+       ofs += rv, consumed += rv;
+       
+       if( type_p )
+               *type_p = get16(buf8 + ofs);
+       ofs += 2, consumed += 2;
+       
+       if( class_p )
+               *class_p = get16(buf8 + ofs);
+       ofs += 2, consumed += 2;
+       
+       if( ttl_p )
+               *ttl_p = get32(buf + ofs);
+       ofs += 4, consumed += 4;
+       
+       size_t rdlength = get16(buf + ofs);
+       if( rdlength_p )
+               *rdlength_p = rdlength;
+       ofs += 2, consumed += 2;
+       
+       _SysDebug("DNS_int_ParseRR - name='%s', rdlength=%i", name_p, rdlength);
+       
+       return consumed + rdlength;
+}
+
+static uint16_t get16(const void *buf) {
+       const uint8_t* buf8 = buf;
+       uint16_t rv = 0;
+       rv |= (uint16_t)buf8[0] << 8;
+       rv |= (uint16_t)buf8[1] << 0;
+       return rv;
+}
+static uint32_t get32(const void *buf) {
+       const uint8_t* buf8 = buf;
+       uint32_t rv = 0;
+       rv |= (uint32_t)buf8[0] << 24;
+       rv |= (uint32_t)buf8[1] << 16;
+       rv |= (uint32_t)buf8[2] << 8;
+       rv |= (uint32_t)buf8[3] << 0;
+       return rv;
+}
+static size_t put16(void *buf, uint16_t val) {
+       uint8_t* buf8 = buf;
+       buf8[0] = val >> 8;
+       buf8[1] = val & 0xFF;
+       return 2;
+}
+
diff --git a/Usermode/Libraries/libnet.so_src/hostnames.c b/Usermode/Libraries/libnet.so_src/hostnames.c
new file mode 100644 (file)
index 0000000..c3c9626
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Acess2 Networking Toolkit
+ * By John Hodge (thePowersGang)
+ * 
+ * dns.c
+ * - Hostname<->Address resolution
+ */
+#include <net.h>
+#include "include/dns.h"
+#include <string.h>
+#include <stdlib.h>    // malloc (for loading config)
+#include <stdbool.h>
+#include <acess/sys.h> // _SysDebug
+
+// === TYPES ===
+struct sDNSServer
+{
+        int    AddrType;
+       char    AddrData[16];
+};
+
+struct sHostEntry
+{
+        int    AddrType;
+       char    AddrData[16];
+       char    *Names[];
+};
+
+struct sLookupAnyInfo
+{
+        int    expected_type;
+       void    *dest_ptr;
+       bool    have_result;
+};
+struct sDNSCallbackInfo
+{
+       void    *cb_info;
+       tNet_LookupAddrs_Callback       *callback;
+       enum eTypes     desired_type;
+       enum eClass     desired_class;
+       bool    got_value;
+};
+
+// === PROTOTYPES ===
+ int   int_lookupany_callback(void *info_v, int AddrType, const void *Addr);
+void   int_DNS_callback(void *info, const char *name, enum eTypes type, enum eClass class, unsigned int ttl, size_t rdlength, const void *rdata);
+
+// === GLOBALS ===
+ int   giNumDNSServers;
+struct sDNSServer      *gaDNSServers;
+ int   giNumHostEntries;
+struct sHostEntry      *gaHostEntries;
+
+// === CODE ===
+int Net_Lookup_AnyAddr(const char *Name, int AddrType, void *Addr)
+{
+       struct sLookupAnyInfo   cb_info = {
+               .expected_type = AddrType,
+               .dest_ptr = Addr,
+               .have_result = false,
+               };
+       return Net_Lookup_Addrs(Name, &cb_info, int_lookupany_callback);
+}
+int int_lookupany_callback(void *info_v, int AddrType, const void *Addr)
+{
+       struct sLookupAnyInfo   *info = info_v;
+       if( AddrType == info->expected_type && info->have_result == false )
+       {
+               memcpy(info->dest_ptr, Addr, Net_GetAddressSize(AddrType));
+               
+               info->have_result = true;
+               return 1;
+       }
+       return 0;
+}
+
+int Net_Lookup_Addrs(const char *Name, void *cb_info, tNet_LookupAddrs_Callback *callback)
+{
+       _SysDebug("Net_Lookup_Addrs(Name='%s')", Name);
+       // 1. Load (if not loaded) the DNS config from "/Acess/Conf/dns"
+       // - "* <ip> <ip>" for DNS server(s)
+       // - "127.0.0.1 localhost localhost.localdomain"
+       if( !gaDNSServers )
+       {
+               giNumDNSServers = 1;
+               gaDNSServers = malloc( 1 * sizeof(gaDNSServers[0]) );
+               gaDNSServers[0].AddrType = Net_ParseAddress("192.168.1.1", gaDNSServers[0].AddrData);
+       }
+       
+       // 2. Check the hosts list
+       for( int i = 0; i < giNumHostEntries; i ++ )
+       {
+               const struct sHostEntry* he = &gaHostEntries[i];
+               for( const char * const *namep = (const char**)he->Names; *namep; namep ++ )
+               {
+                       if( strcasecmp(Name, *namep) == 0 )
+                       {
+                               if( callback(cb_info, he->AddrType, he->AddrData) != 0 )
+                                       return 0;
+                       }
+               }
+       }
+       // 3. Contact DNS server specified in config
+       for( int i = 0; i < giNumDNSServers; i ++ )
+       {
+               const struct sDNSServer *s = &gaDNSServers[i];
+               struct sDNSCallbackInfo info = {
+                       .cb_info = cb_info,
+                       .callback = callback,
+                       .desired_type = TYPE_A,
+                       .desired_class = CLASS_IN,
+                       .got_value = false,
+                       };
+               if( ! DNS_Query(s->AddrType, s->AddrData, Name, info.desired_type, info.desired_class, int_DNS_callback, &info) )
+               {
+                       if( info.got_value )
+                       {
+                               return 0;
+                       }
+                       else
+                       {
+                               // NXDomain, I guess
+                               return 1;
+                       }
+               }
+       }
+       return 1;
+}
+
+void int_DNS_callback(void *info_v, const char *name, enum eTypes type, enum eClass class, unsigned int ttl, size_t rdlength, const void *rdata)
+{
+       struct sDNSCallbackInfo *info = info_v;
+       _SysDebug("int_DNS_callback(name='%s', type=%i, class=%i)", name, type, class);
+       
+       // Check type matches (if pattern was provided)
+       if( info->desired_type != QTYPE_STAR && type != info->desired_type )
+               return ;
+       if( info->desired_class != QCLASS_STAR && class != info->desired_class )
+               return ;
+       
+       switch( type )
+       {
+       case TYPE_A:
+               if( rdlength != 4 )
+                       return ;
+               info->callback( info->cb_info, 4, rdata );
+               break;
+       //case TYPE_AAAA:
+       //      if( rdlength != 16 )
+       //              return ;
+       //      info->callback( info->cb_info, 6, rdata );
+       //      break;
+       default:
+               // Ignore anything not A/AAAA
+               break;
+       }
+       info->got_value = true;
+}
+
+int Net_Lookup_Name(int AddrType, const void *Addr, char *Dest[256])
+{
+       return 1;
+}
+
diff --git a/Usermode/Libraries/libnet.so_src/include/dns.h b/Usermode/Libraries/libnet.so_src/include/dns.h
new file mode 100644 (file)
index 0000000..dc7a58b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Acess2 Networking Toolkit
+ * By John Hodge (thePowersGang)
+ * 
+ * dns.h
+ * - DNS Protocol Interface
+ */
+#ifndef _DNS_H_
+#define _DNS_H_
+
+#include <stddef.h>
+
+enum eTypes
+{
+       TYPE_A = 1,
+       TYPE_NS = 2,
+       TYPE_CNAME = 5,
+       TYPE_SOA = 6,
+       TYPE_NULL = 10,
+       TYPE_PTR = 12,
+       TYPE_HINFO = 13,
+       TYPE_MX = 15,
+       TYPE_TXT = 16,
+       QTYPE_STAR = 255,
+};
+
+enum eClass
+{
+       CLASS_IN = 1,
+       CLASS_CH = 3,   // "Chaos"
+       QCLASS_STAR = 255,
+};
+
+/**
+ * \brief Handler for a DNS record obtained by DNS_Query
+ * \param info Value passed as the last argument to DNS_Query
+ * \param name NUL-terminated name associated with the returned record
+ * \param type Record type (may not be equal to requested)
+ * \param class        Record class (may not be equal to requested)
+ * \param rdlength     Length of data pointed to by 'rdata'
+ * \param rdata        Record data
+ */
+typedef void   handle_record_t(void *info, const char *name, enum eTypes type, enum eClass class, unsigned int ttl, size_t rdlength, const void *rdata);
+
+int DNS_Query(int ServerAType, const void *ServerAddr, const char *name, enum eTypes type, enum eClass class, handle_record_t* handle_record, void *info);
+
+#endif
+
index 5fe4ba1..3d33da0 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef __LIBNET_H_
 #define __LIBNET_H_
 
+#include <stddef.h>
+
 enum {
        NET_ADDRTYPE_NULL = 0,
        NET_ADDRTYPE_IPV4 = 4,
@@ -53,8 +55,43 @@ extern char  *Net_GetInterface(int AddrType, void *Addr);
  * Opens a file using /Devices/ip/routes/@<AddrType>:<Addr>/<SocketName>
  * 
  */
-extern int     Net_OpenSocket(int AddrType, void *Addr, const char *SocketName);
+extern int     Net_OpenSocket(int AddrType, const void *Addr, const char *SocketName);
+
+extern int     Net_OpenSocket_TCPC(int AddrType, const void *Addr, int Port);
+
+extern int     Net_OpenSocket_UDP(int AddrType, const void *Addr, int RAddr, int LAddr);
+extern int Net_UDP_SendTo  (int FD, int Port, int AddrType, const void *Addr, size_t Length, const void *Data);
+extern int Net_UDP_RecvFrom(int FD, int* Port, int* AddrType, void *Addr, size_t Length, void *Data);
 
-extern int     Net_OpenSocket_TCPC(int AddrType, void *Addr, int Port);
+
+/**
+ * \name Hostnames
+ * \brief Handling of hostname resolution
+ * \{
+ */
+
+/**
+ * \brief Returns an address for the specified hostname
+ * \note Picks randomly if multiple addresses are present
+ */
+extern int     Net_Lookup_AnyAddr(const char *Name, int AddrType, void *Addr);
+
+/**
+ * \brief Callback for Net_Lookup_Addrs, returns non-zero when lookup should terminate
+ */
+typedef int tNet_LookupAddrs_Callback(void *info, int AddrType, const void *Addr);
+
+/**
+ * \brief Enumerate addresses for a host, calling the provided function for each
+ */
+extern int     Net_Lookup_Addrs(const char *Name, void *info, tNet_LookupAddrs_Callback* callback);
+
+/**
+ */
+extern int     Net_Lookup_Name(int AddrType, const void *Addr, char *Dest[256]);
+
+/**
+ * \}
+ */
 
 #endif
index 85f7e54..825dc6f 100644 (file)
@@ -8,17 +8,28 @@
 #include <net.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <string.h>    // memcpy
 #include <acess/sys.h>
 
-int Net_OpenSocket(int AddrType, void *Addr, const char *Filename)
+enum {
+       UDP_IOCTL_GETSETLPORT = 4,
+       UDP_IOCTL_GETSETRPORT,
+       UDP_IOCTL_GETSETRMASK,
+       UDP_IOCTL_SETRADDR,
+       UDP_IOCTL_SENDTO,
+       UDP_IOCTL_RECVFROM,
+};
+
+int Net_OpenSocket(int AddrType, const void *Addr, const char *Filename)
 {
         int    addrLen = Net_GetAddressSize(AddrType);
-        int    i;
-       uint8_t *addrBuffer = Addr;
        char    hexAddr[addrLen*2+1];
        
-       for( i = 0; i < addrLen; i ++ )
-               sprintf(hexAddr+i*2, "%02x", addrBuffer[i]);
+       {
+               const uint8_t   *addrBuffer = Addr;
+               for( unsigned int i = 0; i < addrLen; i ++ )
+                       sprintf(hexAddr+i*2, "%02x", addrBuffer[i]);
+       }
        
        if(Filename)
        {
@@ -37,14 +48,82 @@ int Net_OpenSocket(int AddrType, void *Addr, const char *Filename)
        }
 }
 
-int Net_OpenSocket_TCPC(int AddrType, void *Addr, int Port)
+int Net_OpenSocket_TCPC(int AddrType, const void *Addr, int Port)
 {
        int fd = Net_OpenSocket(AddrType, Addr, "tcpc");
        if( fd == -1 )  return -1;
        
-       _SysIOCtl(fd, 5, &Port);        // Remote Port
-        _SysIOCtl(fd, 6, Addr);        // Remote address
-       _SysIOCtl(fd, 7, NULL); // connect
+       if( _SysIOCtl(fd, 5, &Port) < 0 )       // Remote Port
+               goto err;
+       if( _SysIOCtl(fd, 6, (void*)Addr) < 0 ) // Remote address (kernel shouldn't modify)
+               goto err;
+       if( _SysIOCtl(fd, 7, NULL) < 0) // connect
+               goto err;
+       return fd;
+err:
+       _SysClose(fd);
+       return -1;
+}
+
+int Net_OpenSocket_UDP(int AddrType, const void *Addr, int RPort, int LPort)
+{
+       int fd = Net_OpenSocket(AddrType, Addr, "udp");
+       if( fd == -1 )  return -1;
+       
+       if( _SysIOCtl(fd, UDP_IOCTL_GETSETLPORT, &LPort) < 0 )
+               goto err;
+       if( _SysIOCtl(fd, UDP_IOCTL_GETSETRPORT, &RPort) < 0 )
+               goto err;
+       int maskbits = Net_GetAddressSize(AddrType) * 8;
+       if( _SysIOCtl(fd, UDP_IOCTL_GETSETRMASK, &maskbits) < 0 )
+               goto err;
+       if( _SysIOCtl(fd, UDP_IOCTL_SETRADDR, (void*)Addr) < 0 )        // Remote address (kernel shouldn't modify)
+               goto err;
        return fd;
+err:
+       _SysClose(fd);
+       return -1;
+}
+
+int Net_UDP_SendTo(int FD, int Port, int AddrType, const void *Addr, size_t Length, const void *Data)
+{
+       struct {
+               uint16_t port;
+               uint16_t addr_type;
+               char    addr[16];
+       } ep;
+       ep.port = Port;
+       ep.addr_type = AddrType;
+       memcpy(ep.addr, Addr, Net_GetAddressSize(AddrType));
+       struct {
+               const void *ep;
+               const void *buf;
+               uint16_t len;
+       } info = { .ep = &ep, .buf = Data, .len = Length };
+       
+       return _SysIOCtl(FD, UDP_IOCTL_SENDTO, &info);
+}
+
+int Net_UDP_RecvFrom(int FD, int* Port, int* AddrType, void *Addr, size_t Length, void *Data)
+{
+       struct {
+               uint16_t port;
+               uint16_t addr_type;
+               char    addr[16];
+       } ep;
+       struct {
+               void *ep;
+               void *buf;
+               uint16_t len;
+       } info = { .ep = &ep, .buf = Data, .len = Length };
+       
+       int rv = _SysIOCtl(FD, UDP_IOCTL_RECVFROM, &info);
+       if( rv > 0 )
+       {
+               if(Port)        *Port = ep.port;
+               if(AddrType)    *AddrType = ep.addr_type;
+               if(Addr)        memcpy(Addr, ep.addr, Net_GetAddressSize(ep.addr_type));
+       }
+       return rv;
 }
 
index dcbf8f5..eb2fd2f 100644 (file)
@@ -6,12 +6,14 @@
 CPPFLAGS += \r
 CFLAGS   += -Wextra\r
 ASFLAGS  +=\r
-LDFLAGS  += -soname libposix.so -Map map.txt -lc\r
+LDFLAGS  += -nostdlib\r
+PRELINK  += $(CRTI) $(CRTBEGINS) $(CRT0S)\r
+LIBS     += -lc $(CRTENDS) $(CRTN)\r
 \r
 OBJ  = main.o unistd.o dirent.o stat.o utmpx.o termios.o\r
 OBJ += pwd.o syslog.o sys_time.o sys_ioctl.o sys_resource.o\r
 OBJ += fcntl.o clocks.o sys_wait.o unistd_crypt.o\r
-OBJ += grp.o pty.o mktemp.o utime.o\r
+OBJ += grp.o pty.o mktemp.o utime.o getopt.o\r
 DEPFILES := $(OBJ:%.o=%.d)\r
 BIN = libposix.so\r
 \r
diff --git a/Usermode/Libraries/libposix.so_src/getopt.c b/Usermode/Libraries/libposix.so_src/getopt.c
new file mode 100644 (file)
index 0000000..ab6186b
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Acess2 POSIX Emulation Layer
+ * - By John Hodge (thePowersGang)
+ *
+ * getopt.c
+ * - getopt() command line parsing code
+ */
+#include <getopt.h>
+
+// === GLOBALS ===
+char*  optarg;
+ int   opterr;
+ int   optind;
+ int   optopt;
+
+// === CODE ===
+int getopt(int argc, char * const argv[], const char *optstring)
+{
+       return -1;
+}
+
diff --git a/Usermode/Libraries/libposix.so_src/include_exp/endian.h b/Usermode/Libraries/libposix.so_src/include_exp/endian.h
new file mode 100644 (file)
index 0000000..a70ec0d
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ */
+#ifndef _LIBPOSIX_ENDIAN_H_
+#define _LIBPOSIX_ENDIAN_H_
+
+#define __LITTLE_ENDIAN        0
+#define __BIG_ENDIAN   0
+#define __BYTE_ORDER   __LITTLE_ENDIAN
+
+#endif
+
diff --git a/Usermode/Libraries/libposix.so_src/include_exp/getopt.h b/Usermode/Libraries/libposix.so_src/include_exp/getopt.h
new file mode 100644 (file)
index 0000000..b6db119
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Acess2 POSIX Emulation Layer
+ * - By John Hodge (thePowersGang)
+ *
+ * getopt.h
+ * - getopt() command line parsing code
+ */
+#ifndef _LIBPOSIX_GETOPT_H_
+#define _LIBPOSIX_GETOPT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char*   optarg;
+extern int     opterr;
+extern int     optind;
+extern int     optopt;
+
+extern int     getopt(int argc, char * const argv[], const char *optstring);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/Usermode/Libraries/libposix.so_src/include_exp/glob.h b/Usermode/Libraries/libposix.so_src/include_exp/glob.h
new file mode 100644 (file)
index 0000000..ff96b8e
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Acess2 POSIX Emulation Library
+ * - By John Hodge (thePowersGang)
+ *
+ * glob.h
+ * - Globbing code
+ */
+#ifndef _LIBPOSIX__GLOB_H_
+#define _LIBPOSIX__GLOB_H_
+
+
+
+#endif
diff --git a/Usermode/Libraries/libposix.so_src/include_exp/regex.h b/Usermode/Libraries/libposix.so_src/include_exp/regex.h
new file mode 100644 (file)
index 0000000..ebbe6b6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Acess2 POSIX Emulation Library
+ * - By John Hodge (thePowersGang)
+ *
+ * regex.h
+ * - POSIX regular expression support
+ */
+#ifndef _LIBPOSIX_REGEX_H_
+#define _LIBPOSIX_REGEX_H_
+
+typedef struct {
+       void *unused;
+} regex_t;
+
+typedef size_t regoff_t;
+
+typedef struct {
+       regoff_t rm_so;
+       regoff_t rm_eo;
+} regmatch_t;
+
+extern int regcomp(regex_t *preg, const char *regex, int cflags);
+extern int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+extern size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
+extern void regfree(regex_t *preg);
+
+enum {
+       REG_BADBR = 1,
+       REG_BADPAT,
+       REG_BADRPT,
+};
+
+#define REG_EXTENDED   0x1
+#define REG_ICASE      0x2
+#define REG_NOSUB      0x4
+#define REG_NEWLINE    0x8
+
+
+#endif
+
+
diff --git a/Usermode/Libraries/libposix.so_src/include_exp/strings.h b/Usermode/Libraries/libposix.so_src/include_exp/strings.h
new file mode 100644 (file)
index 0000000..9c4114d
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Acess2 POSIX Emulation Library
+ * - By John Hodge (thePowersGang)
+ *
+ * strings.h
+ * - BSD's verison of string.h
+ */
+#ifndef _LIBPOSIX_STRINGS_H_
+#define _LIBPOSIX_STRINGS_H_
+
+
+
+#endif
+
index 6519b3b..10c4779 100644 (file)
@@ -71,6 +71,10 @@ extern int   chmod(const char *path, mode_t mode);
 
 extern int     unlink(const char *pathname);
 
+#define F_OK   00
+#define R_OK   04
+#define W_OK   02
+#define X_OK   01
 extern int     access(const char *pathname, int mode);
 
 extern pid_t   setsid(void);
@@ -93,6 +97,7 @@ extern unsigned int   alarm(unsigned int seconds);
 extern char    *crypt(const char *key, const char *salt);
 
 // - pty.c
+extern int     isatty(int fd);
 extern char    *ttyname(int fd);
 extern int     ttyname_r(int fd, char *buf, size_t buflen);
 
index 863b925..2cc5f2a 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <unistd.h>    // mktemp
 #include <stdlib.h>    // mkstemp
+#include <stdio.h>
 #include <string.h>    // str*
 #include <errno.h>
 
@@ -25,7 +26,7 @@ int mkstemp(char *template)
        
        for( int i = 0; i < 1000000; i ++ )
        {
-               sprintf(template+tpl_len-6, "%06d", i);
+               snprintf(template+tpl_len-6, 6+1, "%06d", i);
                int fd = open(template, O_EXCL|O_CREAT, 0600);
                if(fd == -1)    continue ;
        
index 3af7bcb..dca2963 100644 (file)
@@ -292,3 +292,21 @@ int ttyname_r(int fd, char *buf, size_t buflen)
 
        return ENOTIMPL;
 }
+
+int isatty(int fd)
+{
+       if( fd < 0 ) {
+               errno = EBADF;
+               return 0;
+       }
+       
+        int    type = _SysIOCtl(fd, DRV_IOCTL_TYPE, NULL);
+       if( type == -1 )
+               return 0;
+       if( type != DRV_TYPE_TERMINAL ) {
+               errno = ENOTTY;
+               // NOTE: Pre POSIX 2001, EINVAL was returned
+               return 0;
+       }
+       return 1;
+}
index 0ad326e..65f7380 100644 (file)
@@ -4,7 +4,8 @@ include ../Makefile.cfg
 
 CPPFLAGS +=
 CFLAGS   += -Wall
-LDFLAGS  += -lc -soname libpsocket.so -lnet
+LDFLAGS  += -lc -soname libpsocket.so
+LIBS     += -lnet
 
 OBJ = main.o getaddrinfo.o socket.o pton.o byteordering.o
 BIN = libpsocket.so
index 5c21c06..e1a0e42 100644 (file)
 #include <stdlib.h>    // strtol
 #include <acess/sys.h>
 
+// === TYPES ===
+struct sLookupInfo {
+       struct addrinfo **ret_p;
+};
+
+// === PROTOTYPES ===
+struct addrinfo *int_new_addrinfo(int af, const void *addrdata);
+int int_getaddinfo_lookupcb(void *info, int addr_type, const void *addr);
+
+// === GLOBALS ===
 static const struct {
        const char *Name;
         int    SockType;
@@ -52,28 +62,20 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
        {
                // 1. Check if the node is an IP address
                {
-                        int    type;
                        char    addrdata[16];
-                       type = Net_ParseAddress(node, addrdata);
+                       int type = Net_ParseAddress(node, addrdata);
                        switch(type)
                        {
-                       case 0:
+                       case NET_ADDRTYPE_NULL:
                                break;
-                       case 4: // IPv4
-                               ret = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
-                               ret->ai_family = AF_INET;
-                               ret->ai_socktype = 0;
-                               ret->ai_protocol = 0;
-                               ret->ai_addrlen = sizeof(struct in_addr);
-                               ret->ai_addr = (void*)( ret + 1 );
-                               ret->ai_canonname = 0;
-                               ret->ai_next = 0;
-                               ((struct sockaddr_in*)ret->ai_addr)->sin_family = AF_INET;
-                               ((struct sockaddr_in*)ret->ai_addr)->sin_port = 0;
-                               memcpy( &((struct sockaddr_in*)ret->ai_addr)->sin_addr, addrdata, 4 );
+                       case NET_ADDRTYPE_IPV4:
+                               ret = int_new_addrinfo(AF_INET, addrdata);
+                               break;
+                       case NET_ADDRTYPE_IPV6:
+                               ret = int_new_addrinfo(AF_INET6, addrdata);
                                break;
                        default:
-                               _SysDebug("getaddrinfo: Unknown address family %i", type);
+                               _SysDebug("getaddrinfo: Unknown address type %i", type);
                                return 1;
                        }
                }
@@ -82,15 +84,19 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
                // - No luck with above, and hints->ai_flags doesn't have AI_NUMERICHOST set
                if( !ret && !(hints->ai_flags & AI_NUMERICHOST) )
                {
-                       _SysDebug("getaddrinfo: TODO DNS Lookups");
-                       // TODO: DNS Lookups
-                       // ? /Acess/Conf/Nameservers
-                       // ? /Acess/Conf/Hosts
-                       //count = Net_LookupDNS(node, service, NULL);
-                       //
+                       // Just does a basic A record lookup
+                       // TODO: Support SRV records
+                       // TODO: Ensure that CNAMEs are handled correctly
+                       struct sLookupInfo info = {
+                               .ret_p = &ret,
+                               };
+                       if( Net_Lookup_Addrs(node, &info, int_getaddinfo_lookupcb) ) {
+                               // Lookup failed, quick return
+                               return EAI_NONAME;
+                       }
                }
                
-               // 3. No Match, chuck sad
+               // 3. No Match, return sad
                if( !ret )
                {
                        return EAI_NONAME;
@@ -182,9 +188,81 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
        return 0;
 }
 
+/**
+ * \brief Allocate a new zeroed addrinfo for the specified address
+ */
+struct addrinfo *int_new_addrinfo(int af, const void *addrdata)
+{
+       size_t  addrlen = 0;
+       switch(af)
+       {
+       case AF_INET:
+               addrlen = sizeof(struct sockaddr_in);
+               break;
+       case AF_INET6:
+               addrlen = sizeof(struct sockaddr_in6);
+               break;
+       default:
+               _SysDebug("int_new_addrinfo: ERROR - Unknown AF %i", af);
+               return NULL;
+       }
+       struct addrinfo* ret = malloc(sizeof(struct addrinfo) + addrlen);
+       ret->ai_family = af;
+       ret->ai_socktype = 0;
+       ret->ai_protocol = 0;
+       ret->ai_addrlen = addrlen;
+       ret->ai_addr = (void*)( ret + 1 );
+       ret->ai_canonname = 0;
+       ret->ai_next = 0;
+       switch(af)
+       {
+       case AF_INET:
+               ((struct sockaddr_in*)ret->ai_addr)->sin_family = AF_INET;
+               ((struct sockaddr_in*)ret->ai_addr)->sin_port = 0;
+               memcpy( &((struct sockaddr_in*)ret->ai_addr)->sin_addr, addrdata, 4 );
+               break;
+       case AF_INET6:
+               ((struct sockaddr_in6*)ret->ai_addr)->sin6_family = AF_INET6;
+               ((struct sockaddr_in6*)ret->ai_addr)->sin6_port = 0;
+               memcpy( &((struct sockaddr_in6*)ret->ai_addr)->sin6_addr, addrdata, 16 );
+               break;
+       default:
+               _SysDebug("int_new_addrinfo: BUGCHECK - Unhandled AF %i", af);
+               return NULL;
+       }
+       return ret;
+}
+
+// Callback for getaddrinfo's call to Net_Lookup_Addrs
+int int_getaddinfo_lookupcb(void *info_v, int addr_type, const void *addr)
+{
+       struct sLookupInfo *info = info_v;
+       struct addrinfo *ent;
+       switch( addr_type )
+       {
+       case NET_ADDRTYPE_IPV4:
+               ent = int_new_addrinfo(AF_INET, addr);
+               break;
+       case NET_ADDRTYPE_IPV6:
+               ent = int_new_addrinfo(AF_INET6, addr);
+               break;
+       default:
+               // Huh... unknown address type, just ignore it
+               return 0;
+       }
+       ent->ai_next = *info->ret_p;
+       *info->ret_p = ent;
+       return 0;
+}
+
 void freeaddrinfo(struct addrinfo *res)
 {
-       
+       while( res )
+       {
+               struct addrinfo *next = res->ai_next;
+               free(res);
+               res = next;
+       }
 }
 
 int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
diff --git a/Usermode/Libraries/libpthread.so_src/Makefile b/Usermode/Libraries/libpthread.so_src/Makefile
new file mode 100644 (file)
index 0000000..0870c0c
--- /dev/null
@@ -0,0 +1,12 @@
+# Acess 2 - POSIX Threads
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS   += -Wall
+LDFLAGS  += -lc -soname libpthread.so
+
+OBJ = main.o thread.o
+BIN = libpthread.so
+
+include ../Makefile.tpl
diff --git a/Usermode/Libraries/libpthread.so_src/include_exp/pthread.h b/Usermode/Libraries/libpthread.so_src/include_exp/pthread.h
new file mode 100644 (file)
index 0000000..376fb0e
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Acess2 libpthread
+ * - By John Hodge (thePowersGang)
+ *
+ * pthread.h
+ * - Core POSIX threads header
+ */
+#ifndef _LIBPTHREAT_PTHREAD_H_
+#define _LIBPTHREAT_PTHREAD_H_
+
+// XXX: Hack - libgcc doesn't seem to be auto-detecting the presence of this header
+#include "sched.h"
+
+//! \name pthread core
+//! \{
+typedef struct pthread_attr_s  pthread_attr_t;
+
+struct pthread_s
+{
+       void*   retval;
+       unsigned int    kernel_handle;
+};
+typedef struct pthread_s       pthread_t;
+
+extern int     pthread_create(pthread_t *threadptr, const pthread_attr_t * attrs, void* (*fcn)(void*), void* arg);
+extern int     pthread_detach(pthread_t thread);
+extern int     pthread_join(pthread_t thread, void **retvalptr);
+extern int     pthread_cancel(pthread_t thread);
+extern int     pthread_equal(pthread_t t1, pthread_t t2);
+extern pthread_t       pthread_self(void);
+extern void    pthread_exit(void* retval);
+//! }
+
+
+//! \name pthread_once
+//! \{
+struct pthread_once_s
+{
+       int     flag;
+};
+#define PTHREAD_ONCE_INIT      ((struct pthread_once_s){.flag=0})
+typedef struct pthread_once_s  pthread_once_t;
+extern int pthread_once(pthread_once_t *once_contol, void (*init_routine)(void));
+//! \}
+
+//! \name pthread mutexes
+//! \{
+#define PTHREAD_MUTEX_NORMAL   0
+#define PTHREAD_MUTEX_RECURSIVE        1
+struct pthread_mutexattr_s
+{
+       int     type;
+};
+typedef struct pthread_mutexattr_s     pthread_mutexattr_t;
+extern int pthread_mutexattr_init(pthread_mutexattr_t *attrs);
+extern int pthread_mutexattr_settype(pthread_mutexattr_t *attrs, int type);
+extern int pthread_mutexattr_destroy(pthread_mutexattr_t *attrs);
+
+struct pthread_mutex_s
+{
+       void*   futex;
+};
+#define PTHREAD_MUTEX_INITIALIZER      ((struct pthread_mutex_s){0})
+typedef struct pthread_mutex_s pthread_mutex_t;
+extern int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t *attrs);
+extern int pthread_mutex_lock(pthread_mutex_t *lock);
+extern int pthread_mutex_trylock(pthread_mutex_t *lock);
+extern int pthread_mutex_unlock(pthread_mutex_t *lock);
+extern int pthread_mutex_destroy(pthread_mutex_t *lock);
+//! \}
+
+//! \name pthread TLS keys
+//! \{
+//typedef struct pthread_key_s pthread_key_t;
+typedef unsigned int   pthread_key_t;
+extern int pthread_key_create(pthread_key_t *keyptr, void (*fcn)(void*));
+extern int pthread_key_delete(pthread_key_t key);
+extern int pthread_setspecific(pthread_key_t key, const void* data);
+extern void* pthread_getspecific(pthread_key_t key);
+//! \}
+
+//! \name pthread condvars
+//! \{
+typedef struct pthread_cond_s  pthread_cond_t;
+typedef struct pthread_condattr_s      pthread_condattr_t;
+extern int pthread_cond_init(pthread_cond_t *condptr, const pthread_condattr_t* attrs);
+extern int pthread_cond_wait(pthread_cond_t *condptr, pthread_mutex_t *mutex);
+extern int pthread_cond_timedwait(pthread_cond_t *condptr, pthread_mutex_t *mutex, const struct timespec *timeout);
+extern int pthread_cond_signal(pthread_cond_t *condptr);
+extern int pthread_cond_broadcast(pthread_cond_t *condptr);
+extern int pthread_cond_destroy(pthread_cond_t *condptr);
+//! \}
+
+#endif
+
diff --git a/Usermode/Libraries/libpthread.so_src/include_exp/sched.h b/Usermode/Libraries/libpthread.so_src/include_exp/sched.h
new file mode 100644 (file)
index 0000000..8366ba2
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Acess2 libpthread
+ * - By John Hodge (thePowersGang)
+ *
+ * sched.h
+ * - Execution Scheduling (POSIX Realtime Extensions)
+ */
+#ifndef _LIBPTHREAT_SCHED_H_
+#define _LIBPTHREAT_SCHED_H_
+
+// *grumble* libgcc wants a yield
+extern int     sched_yield(void);
+
+#endif
+
diff --git a/Usermode/Libraries/libpthread.so_src/main.c b/Usermode/Libraries/libpthread.so_src/main.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Usermode/Libraries/libpthread.so_src/thread.c b/Usermode/Libraries/libpthread.so_src/thread.c
new file mode 100644 (file)
index 0000000..4b5f51f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Acess2 libpthread
+ * - By John Hodge (thePowersGang)
+ *
+ * thread.c
+ * - Thread management for pthreads
+ */
+#include <pthread.h>
+#include <assert.h>
+
+int pthread_create(pthread_t *threadptr, const pthread_attr_t * attrs, void* (*fcn)(void*), void* arg)
+{
+       assert(!"TODO: pthread_create");
+       return 0;
+}
+int pthread_detach(pthread_t thread)
+{
+       assert(!"TODO: pthread_detach");
+       return 0;
+}
+int pthread_join(pthread_t thread, void **retvalptr)
+{
+       assert(!"TODO: pthread_join");
+       return 0;
+}
+int pthread_cancel(pthread_t thread)
+{
+       assert(!"TODO: pthread_cancel");
+       return 0;
+}
+int pthread_equal(pthread_t t1, pthread_t t2)
+{
+       assert(!"TODO: pthread_equal");
+       return 0;
+}
+pthread_t pthread_self(void)
+{
+       assert(!"TODO: pthread_self");
+       return (pthread_t){0};
+}
+void pthread_exit(void* retval)
+{
+       assert(!"TODO: pthread_create");
+}
diff --git a/Usermode/Libraries/libresolv.so_src/Makefile b/Usermode/Libraries/libresolv.so_src/Makefile
new file mode 100644 (file)
index 0000000..21eb942
--- /dev/null
@@ -0,0 +1,16 @@
+# Acess2 BSD "resolv" library
+# Makefile
+
+-include ../Makefile.cfg
+
+CPPFLAGS += 
+CFLAGS   += -Wextra
+ASFLAGS  +=
+LDFLAGS  += 
+LIBS     += -lnet -lpsocket
+
+OBJ  = resolv.o
+BIN = libresolv.so
+
+include ../Makefile.tpl
+
diff --git a/Usermode/Libraries/libresolv.so_src/include_exp/arpa/nameser.h b/Usermode/Libraries/libresolv.so_src/include_exp/arpa/nameser.h
new file mode 100644 (file)
index 0000000..5f2532b
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Acess2 POSIX Sockets Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * arpa/nameser.h
+ * - BSD name resolution (TODO: move to libresolv)
+ *
+ * NOTE: I have no fucking idea who/what defines this header, it's wanted by glib
+ */
+#ifndef _LIBPSOCKET__ARPA_NAMESER_H_
+#define _LIBPSOCKET__ARPA_NAMESER_H_
+
+#define C_IN   0x1
+
+#endif
+
diff --git a/Usermode/Libraries/libresolv.so_src/include_exp/resolv.h b/Usermode/Libraries/libresolv.so_src/include_exp/resolv.h
new file mode 100644 (file)
index 0000000..66d9657
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ */
+#ifndef _LIBRESOLV__RESOLV_H_
+#define _LIBRESOLV__RESOLV_H_
+
+extern int res_init(void);
+
+extern int res_query(const char *dname, int class, int type, unsigned char *answer, int anslen);
+
+extern int res_search(const char *dname, int class, int type, unsigned char *answer, int anslen);
+
+extern int res_querydomain(const char *name, const char *domain, int class, int type, unsigned char *answer, int anslen);
+
+extern int res_mkquery(int op, const char *dname, int class, int type, char *data, int datalen, struct rrec *newrr, char *buf, int buflen);
+
+extern int res_send(const char *msg, int msglen, char *answer, int anslen);
+
+
+#endif
+
diff --git a/Usermode/Libraries/libresolv.so_src/resolv.c b/Usermode/Libraries/libresolv.so_src/resolv.c
new file mode 100644 (file)
index 0000000..e8d121b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ */
+
+int res_init(void)
+{
+       return 1;
+}
+
+int res_query(const char *dname, int class, int type, unsigned char *answer, int anslen)
+{
+       return 1;
+}
+
+int res_search(const char *dname, int class, int type, unsigned char *answer, int anslen)
+{
+       return 1;
+}
+
+int res_querydomain(const char *name, const char *domain, int class, int type, unsigned char *answer, int anslen)
+{
+       return 1;
+}
+
+int res_mkquery(int op, const char *dname, int class, int type, char *data, int datalen, struct rrec *newrr, char *buf, int buflen)
+{
+       return 1;
+}
+
+int res_send(const char *msg, int msglen, char *answer, int anslen)
+{
+       return 1;
+}
+
index ef0eb56..6c7e3e4 100644 (file)
 
 #include <stdint.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * \breif Read a single codepoint from  a UTF-8 stream
  * \return Number of bytes read
@@ -27,5 +31,102 @@ extern int  WriteUTF8(char *buf, uint32_t Val);
 
 static inline int      Unicode_IsPrinting(uint32_t Codepoint) { return 1; }
 
+#ifdef __cplusplus
+}      // extern "C"
+#endif
+
+#ifdef __cplusplus
+#include <iterator>
+
+namespace libunicode {
+
+class utf8iterator:
+       public ::std::iterator< ::std::forward_iterator_tag, uint32_t >
+{
+       const char*     m_curpos;
+       uint32_t        m_curval;
+public:
+       utf8iterator():
+               m_curpos(0)
+       {
+       }
+       utf8iterator(const char *pos):
+               m_curpos(pos)
+       {
+               (*this)++;
+       }
+       utf8iterator(const utf8iterator& other) {
+               m_curpos = other.m_curpos;
+               m_curval = other.m_curval;
+       }
+       utf8iterator& operator=(const utf8iterator& other) {
+               m_curpos = other.m_curpos;
+               m_curval = other.m_curval;
+               return *this;
+       }
+       
+       bool operator== (const utf8iterator& other) {
+               return other.m_curpos == m_curpos;
+       }
+       bool operator!= (const utf8iterator& other) {
+               return other.m_curpos != m_curpos;
+       }
+       utf8iterator& operator++() {
+               m_curpos += ::ReadUTF8(m_curpos, &m_curval);
+               return *this;
+       }
+       utf8iterator operator++(int) {
+               utf8iterator    rv(*this);
+               m_curpos += ::ReadUTF8(m_curpos, &m_curval);
+               return rv;
+       }
+       uint32_t operator*() const {
+               return m_curval;
+       }
+       uint32_t operator->() const {
+               return m_curval;
+       }
+};
+
+class utf8string
+{
+       const char* m_data;
+       size_t  m_len;
+       
+       size_t _strlen(const char*s) {
+               size_t  l = 0;
+               while(*s)       l ++;
+               return l;
+       }
+public:
+       utf8string(const char* c_str):
+               m_data(c_str),
+               m_len(_strlen(c_str))
+       {
+       }
+       utf8string(const char* c_str, size_t len):
+               m_data(c_str),
+               m_len(len)
+       {
+       }
+       utf8string(const ::std::string& str):
+               m_data(str.c_str()),
+               m_len(str.size())
+       {
+       }
+       
+       utf8iterator begin() const {
+               return utf8iterator(m_data);
+       }
+       utf8iterator end() const {
+               return utf8iterator(m_data + m_len);
+       }
+};
+
+
+};
+
+#endif
+
 #endif
 
index 519b0fd..2f6fa8f 100644 (file)
@@ -5,3 +5,14 @@ CPPFLAGS += -I$(ACESSUSERDIR)/include/ -DARCHDIR_is_$(ARCHDIR)
 CPPFLAGS += -I $(ACESSDIR)/Externals/Output/$(ARCHDIR)/include
 CFLAGS += -std=gnu99 -g
 LDFLAGS += -L $(ACESSDIR)/Externals/Output/$(ARCHDIR)/lib
+LDFLAGS += -L $(OUTPUTDIR)Libs
+
+CRTI := $(OUTPUTDIR)Libs/crti.o
+CRTBEGIN := $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o 2>/dev/null)
+CRTBEGINS := $(shell $(CC) $(CFLAGS) -print-file-name=crtbeginS.o 2>/dev/null)
+CRT0 := $(OUTPUTDIR)Libs/crt0.o
+CRT0S := $(OUTPUTDIR)Libs/crt0S.o
+CRTEND := $(shell $(CC) $(CFLAGS) -print-file-name=crtend.o 2>/dev/null)
+CRTENDS := $(shell $(CC) $(CFLAGS) -print-file-name=crtendS.o 2>/dev/null)
+CRTN := $(OUTPUTDIR)Libs/crtn.o
+LIBGCC_PATH = $(shell $(CC) -print-libgcc-file-name 2>/dev/null)

UCC git Repository :: git.ucc.asn.au