Merge branch 'master' of git://git.ucc.asn.au/tpg/acess2
authorJohn Hodge <[email protected]>
Tue, 22 Jan 2013 09:26:02 +0000 (17:26 +0800)
committerJohn Hodge <[email protected]>
Tue, 22 Jan 2013 09:26:02 +0000 (17:26 +0800)
90 files changed:
.travis.yml
AcessNative/acesskernel_src/Makefile
AcessNative/acesskernel_src/helpers.c
AcessNative/acesskernel_src/include/arch.h
AcessNative/acesskernel_src/include/heap.h
AcessNative/acesskernel_src/include/threads_int.h
AcessNative/acesskernel_src/nativefs.c
AcessNative/acesskernel_src/syscalls.c
AcessNative/acesskernel_src/threads.c
AcessNative/acesskernel_src/video.c
AcessNative/ld-acess_src/Makefile
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/main.c
AcessNative/ld-acess_src/memory.c
AcessNative/ld-acess_src/request.c
AcessNative/ld-acess_src/syscalls.c
AcessNative/syscalls.h
AcessNative/syscalls_list.h [new file with mode: 0644]
KernelLand/Kernel/arch/x86/acpica.c
KernelLand/Kernel/arch/x86/vm8086.c
KernelLand/Kernel/arch/x86_64/pci.c [changed from symlink to file mode: 0644]
KernelLand/Kernel/debug.c
KernelLand/Kernel/drv/fifo.c
KernelLand/Kernel/drv/proc.c
KernelLand/Kernel/drv/vterm.c
KernelLand/Kernel/drv/vterm.h
KernelLand/Kernel/drv/vterm_termbuf.c
KernelLand/Kernel/drv/vterm_vt100.c
KernelLand/Kernel/include/events.h
KernelLand/Kernel/include/threads_int.h
KernelLand/Kernel/include/vfs_ext.h
KernelLand/Kernel/logging.c
KernelLand/Kernel/messages.c
KernelLand/Kernel/syscalls.c
KernelLand/Kernel/system.c
KernelLand/Kernel/threads.c
KernelLand/Kernel/vfs/handle.c
KernelLand/Kernel/vfs/select.c
KernelLand/Modules/Display/BochsGA/bochsvbe.c
KernelLand/Modules/Display/RPi/main.c [new file with mode: 0644]
KernelLand/Modules/Filesystems/InitRD/Makefile
KernelLand/Modules/Filesystems/InitRD/files.lst
KernelLand/Modules/IPStack/udp.c
KernelLand/Modules/Network/VIARhineII/rhine2.c
KernelLand/Modules/Storage/FDDv2/main.c
Makefile
Notes/3D.txt [new file with mode: 0644]
Tools/GCCProxy/gccproxy.sh
Usermode/Applications/axwin3_src/Interface/main.c
Usermode/Applications/axwin3_src/WM/Makefile
Usermode/Applications/axwin3_src/WM/include/utf8.h [deleted file]
Usermode/Applications/axwin3_src/WM/ipc.c
Usermode/Applications/axwin3_src/WM/main.c
Usermode/Applications/axwin3_src/WM/renderers/framebuffer.c
Usermode/Applications/axwin3_src/WM/renderers/richtext.c
Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c
Usermode/Applications/axwin3_src/WM/utf-8.c [deleted file]
Usermode/Applications/axwin3_src/WM/video.c
Usermode/Applications/axwin3_src/WM/wm.c
Usermode/Applications/axwin3_src/WM/wm_render_text.c
Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c
Usermode/Applications/dhcpclient_src/main.c
Usermode/Applications/gui_shell_src/Makefile
Usermode/Applications/gui_shell_src/display.c [new file with mode: 0644]
Usermode/Applications/gui_shell_src/include/display.h
Usermode/Applications/gui_shell_src/main.c
Usermode/Applications/gui_shell_src/vt100.c
Usermode/Applications/init_src/common.h [new file with mode: 0644]
Usermode/Applications/init_src/main.c
Usermode/Applications/irc_src/main.c
Usermode/Applications/telnetd_src/main.c
Usermode/Filesystem/Conf/inittab [new file with mode: 0644]
Usermode/Filesystem/Makefile
Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h
Usermode/Libraries/ld-acess.so_src/include_exp/acess/fd_set.h
Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h
Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/keysyms.h [changed from symlink to file mode: 0644]
Usermode/Libraries/libc.so_src/Makefile
Usermode/Libraries/libc.so_src/scanf.c
Usermode/Libraries/libc.so_src/select.c [deleted file]
Usermode/Libraries/libc.so_src/stdio.c
Usermode/Libraries/libposix.so_src/include_exp/sys/types.h
Usermode/Libraries/libunicode.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libunicode.so_src/include_exp/unicode.h [new file with mode: 0644]
Usermode/Libraries/libunicode.so_src/main.c [new file with mode: 0644]
Usermode/Libraries/libunicode.so_src/utf-8.c [new file with mode: 0644]

index 336c3d1..6154547 100644 (file)
@@ -4,6 +4,6 @@ before_install:
  - sudo apt-get update -qq
  - sudo apt-get install -qq nasm
 env:
- - ARCH=host HOST_ARCH=x86
+ - ARCH=host HOST_ARCH=x86 USE_ACPICA=0
  - ARCH=host HOST_ARCH=x86_64 CC="$CC -m64"
 script: "make all"
index b4b7c11..d17e3bb 100644 (file)
@@ -13,7 +13,8 @@ endif
 \r
 KERNEL_SRC = ../../KernelLand/Kernel/\r
 \r
-KERNEL_OBJ := logging.o adt.o lib.o libc.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\r
+#KERNEL_OBJ += libc.o\r
 KERNEL_OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/io.o vfs/dir.o\r
 KERNEL_OBJ += vfs/nodecache.o vfs/mount.o vfs/memfile.o vfs/select.o\r
 KERNEL_OBJ += vfs/fs/root.o vfs/fs/devfs.o\r
@@ -36,7 +37,8 @@ DEPFILES := $(DEPFILES:%=%.dep)
 \r
 KCPPFLAGS = -I include/ -I $(KERNEL_SRC)include/\r
 CFLAGS += -Wall -g -std=gnu99\r
-LDFLAGS += -lSDL -lSDLmain -g -Wl,--defsym,__buildnum=$(BUILD_NUM)\r
+CPPFLAGS += $(shell sdl-config --cflags) -I /usr/include/\r
+LDFLAGS += $(shell sdl-config --libs) -g -Wl,--defsym,__buildnum=$(BUILD_NUM)\r
 \r
 ifeq ($(PLATFORM),win)\r
        BIN := ../AcessKernel.exe\r
@@ -69,7 +71,7 @@ $(OBJ): obj-$(PLATFORM)/%.o: %.c
 $(K_OBJ): $(KERNEL_SRC)obj-native-$(PLATFORM)/%.o: $(KERNEL_SRC)%.c\r
        @mkdir -p $(dir $@)\r
        @echo [CC] -o $@\r
-       $(CC) -ffreestanding -c $< -o $@ $(CFLAGS) $(KCPPFLAGS) $(CPPFLAGS)\r
+       @$(CC) -ffreestanding -c $< -o $@ $(CFLAGS) $(KCPPFLAGS) $(CPPFLAGS)\r
        @$(CC) -ffreestanding -M $(KCPPFLAGS) $(CPPFLAGS) -MT $@ -o [email protected] $<\r
 \r
 \r
@@ -81,12 +83,13 @@ $(N_OBJ): obj-$(PLATFORM)/%.o: %.c
 \r
 $(BUILDINFO_SRC): $(filter-out $(BUILDINFO_OBJ), $(OBJ)) Makefile\r
        @echo "" > $@\r
-       $(eval _GITHASH=$(shell (git log -n 1 | head -n 1 | awk '{print $$2}') || echo UNK))\r
-       $(eval _GITCHANGED=$(shell (git status --porcelain | grep -c '^ M ') || echo UNK))\r
+       $(eval _GITHASH=$(shell (git log -n 1 | head -n 1 | awk '{print $$2}') 2>/dev/null || echo UNK))\r
+       $(eval _GITCHANGED=$(shell (git status --porcelain | grep -c '^ M ') 2>/dev/null || echo UNK))\r
+       $(eval _HOSTNAME=$(shell hostname --fqdn 2>/dev/null || hostname || echo UNK))\r
        @echo "const char gsKernelVersion[] = \"$(ACESS_VERSION)\";" >> $@\r
        @echo "const char gsGitHash[] = \"$(_GITHASH)\";" >> $@\r
-       @echo "const char gsBuildInfo[] = \"Acess2 v$(KERNEL_VERSION) $(ARCH)-$(PLATFORM)\\\\r\\\\n\"" >> $@\r
-       @echo "                           \"Build $(shell hostname --fqdn):$(BUILD_NUM) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@\r
+       @echo "const char gsBuildInfo[] = \"AcessNative $(ACESS_VERSION) $(ARCH)-$(PLATFORM)\\\\r\\\\n\"" >> $@\r
+       @echo "                           \"Build $(_HOSTNAME):$(BUILD_NUM) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@\r
        @echo "const int giBuildNumber = $(BUILD_NUM);" >> $@\r
 $(BUILDINFO_OBJ): $(BUILDINFO_SRC)\r
        @echo [CC] -o $@\r
index 3cf273e..6396d16 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <sys/time.h>
+#include <string.h>
 
 #if 0
 void LogF(const char *Fmt, ...)
@@ -67,10 +68,14 @@ void KernelPanic_PutChar(char ch)
 void Debug_PutCharDebug(char ch)
 {
        printf("%c", ch);
+       if( ch == '\n' )
+               fflush(stdout);
 }
 void Debug_PutStringDebug(const char *String)
 {
        printf("%s", String);
+       if( strchr(String, '\n') )
+               fflush(stdout);
 }
 
 void *Heap_Allocate(const char *File, int Line, int ByteCount)
@@ -93,6 +98,11 @@ void Heap_Deallocate(void *Ptr)
        free(Ptr);
 }
 
+char *Heap_StringDup(const char *File, int Line, const char *Str)
+{
+       return strdup(Str);
+}
+
 void Heap_Dump(void)
 {
 }
@@ -130,3 +140,59 @@ void IPStack_SendDebugText(const char *str)
        // nop
 }
 
+int strpos(const char *str, char ch)
+{
+       const char *retptr = strchr(str, ch);
+       int rv = retptr ? retptr - str : -1;
+       return rv;
+}
+
+int CheckString(const char *string)
+{
+       if( (intptr_t)string < 0x1000 )
+               return 0;
+       return 1;
+}
+
+int CheckMem(const void *buf, size_t len)
+{
+       if( (intptr_t)buf < 0x1000 )
+               return 0;
+       return 1;
+}
+
+void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
+{
+       static const char cUCDIGITS[] = "0123456789ABCDEF";
+       char    tmpBuf[64+1];
+        int    pos=0, i;
+       Uint64  rem;
+
+       // Sanity check
+       if(!buf)        return;
+       
+       // Sanity Check
+       if(base > 16 || base < 2) {
+               buf[0] = 0;
+               return;
+       }
+       
+       // Convert 
+       while(num > base-1) {
+               rem = num % base;
+               num = num / base;       // Shift `num` and get remainder
+               tmpBuf[pos] = cUCDIGITS[ rem ];
+               pos++;
+       }
+       tmpBuf[pos++] = cUCDIGITS[ num ];               // Last digit of `num`
+       
+       // Put in reverse
+       i = 0;
+       minLength -= pos;
+       while(minLength-- > 0)
+               buf[i++] = pad;
+       while(pos-- > 0)
+               buf[i++] = tmpBuf[pos]; // Reverse the order of characters
+       buf[i] = 0;
+}
+
index 1307e0c..e99948c 100644 (file)
@@ -29,7 +29,6 @@ typedef intptr_t      tPAddr;
 typedef        int     BOOL;
 
 #include <stddef.h>
-#undef NULL
 #undef offsetof
 
 struct sShortSpinlock
index 287250c..8bf7d8e 100644 (file)
@@ -11,6 +11,7 @@ extern void   *Heap_Reallocate(const char *File, int Line, void *Ptr, size_t Bytes
 extern void    Heap_Deallocate(void *Ptr);
 extern int     Heap_IsHeapAddr(void *Ptr);
 extern void    Heap_Validate(void);
+extern char    *Heap_StringDup(const char *File, int Line, const char *Str);
 
 #define malloc(size)   Heap_Allocate(_MODULE_NAME_"/"__FILE__, __LINE__, (size))
 #define calloc(num,size)       Heap_AllocateZero(_MODULE_NAME_"/"__FILE__, __LINE__, (num)*(size))
@@ -18,6 +19,6 @@ extern void   Heap_Validate(void);
 #define        free(ptr)       Heap_Deallocate((ptr))
 #define IsHeap(ptr)    Heap_IsHeapAddr((ptr))
 
-#define strdup(Str)    _strdup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str))
+#define strdup(Str)    Heap_StringDup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str))
 
 #endif
index 1294a5f..8061f1e 100644 (file)
@@ -50,7 +50,7 @@ struct sThread
 
        tProcess        *Process;       
 
-       Uint32  Events, WaitMask;
+       Uint32  EventState, WaitMask;
        void    *EventSem;      // Should be SDL_sem, but I don't want SDL in this header
 
        // Message queue
index 0e791b8..cca9e7d 100644 (file)
@@ -5,11 +5,13 @@
  * nativefs.c\r
  * - Host filesystem access\r
  */\r
-#define DEBUG  0\r
+#define DEBUG  1\r
 #define off_t  _acess_off_t\r
+#define sprintf _acess_sprintf\r
 #include <acess.h>     // Acess\r
 #include <vfs.h>       // Acess\r
 #undef off_t\r
+#undef sprintf\r
 #include <dirent.h>    // Posix\r
 #include <sys/stat.h>  // Posix\r
 #include <stdio.h>     // Posix\r
@@ -203,8 +205,9 @@ size_t NativeFS_Read(tVFS_Node *Node, _acess_off_t Offset, size_t Length, void *
                LEAVE('i', 0);\r
                return 0;\r
        }\r
-       LEAVE('-');\r
-       return fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode );\r
+       size_t ret = fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode );\r
+       LEAVE('x', ret);\r
+       return ret;\r
 }\r
 \r
 size_t NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer)\r
index d14a1d9..4458846 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Syscall Distribution
  */
-#define DEBUG  0
+#define DEBUG  1
 #include <acess.h>
 #include <threads.h>
 #include <events.h>
@@ -30,7 +30,7 @@ typedef int   (*tSyscallHandler)(Uint *Errno, const char *Format, void *Args, int
        a3 = *(_t3*)Args;Args+=sizeof(_t3);\
        a4 = *(_t4*)Args;Args+=sizeof(_t4);\
        a5 = *(_t5*)Args;Args+=sizeof(_t5);\
-       LOG("SYSCALL5 '%s' %p %p %p %p %p %p", Fmt, (intptr_t)a0,(intptr_t)a1,(intptr_t)a2,(intptr_t)a3,(intptr_t)a4,(intptr_t)a5);\
+       LOG("SYSCALL6 '%s' %p %p %p %p %p %p", Fmt, (intptr_t)a0,(intptr_t)a1,(intptr_t)a2,(intptr_t)a3,(intptr_t)a4,(intptr_t)a5);\
        _call\
 }
 #define SYSCALL5(_name, _fmtstr, _t0, _t1, _t2, _t3, _t4, _call) int _name(Uint*Errno,const char*Fmt,void*Args,int*Sizes){\
@@ -89,7 +89,7 @@ typedef int   (*tSyscallHandler)(Uint *Errno, const char *Format, void *Args, int
 }
 
 // === CODE ===
-int Syscall_Null(Uint*Errno, const char *Format, void *Args, int *Sizes)
+int Syscall_Null(Uint *Errno, const char *Format, void *Args, int *Sizes)
 {
        return 0;
 }
@@ -100,7 +100,9 @@ SYSCALL1(Syscall_Exit, "i", int,
 );
 
 SYSCALL2(Syscall_Open, "si", const char *, int,
-       return VFS_Open(a0, a1|VFS_OPENFLAG_USER);
+       int rv = VFS_Open(a0, a1|VFS_OPENFLAG_USER);
+       if(rv == -1)    *Errno = errno;
+       return rv;
 );
 SYSCALL1(Syscall_Close, "i", int,
        VFS_Close(a0);
@@ -111,12 +113,18 @@ SYSCALL3(Syscall_Read, "iid", int, int, void *,
                Log_Warning("Syscalls", "Read - %i < %i", Sizes[2], a1);
                return -1;
        }
-       return VFS_Read(a0, a1, a2);
+       size_t rv = VFS_Read(a0, a1, a2);
+       if(rv == -1)    *Errno = errno;
+       return rv;
 );
 SYSCALL3(Syscall_Write, "iid", int, int, const void *,
-       if( Sizes[2] < a1 )
+       if( Sizes[2] < a1 ) {
+               *Errno = EINVAL;
                return -1;
-       return VFS_Write(a0, a1, a2);
+       }
+       size_t rv = VFS_Write(a0, a1, a2);
+       if(rv == -1)    *Errno = errno;
+       return rv;
 );
 SYSCALL3(Syscall_Seek, "iIi", int, int64_t, int,
        return VFS_Seek(a0, a1, a2);
@@ -129,7 +137,7 @@ SYSCALL3(Syscall_IOCtl, "iid", int, int, void *,
 );
 SYSCALL3(Syscall_FInfo, "idi", int, void *, int,
        if( Sizes[1] < sizeof(tFInfo)+a2*sizeof(tVFS_ACL)) {
-               LOG("offsetof(size) = %i", offsetof(tFInfo, size));
+               //LOG("offsetof(size) = %i", offsetof(tFInfo, size));
                LOG("Bad size %i < %i", Sizes[1], sizeof(tFInfo)+a2*sizeof(tVFS_ACL));
                *Errno = -EINVAL;
                return -1;
@@ -273,12 +281,15 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
         int    argListLen = 0;
         int    i, retVal;
        tRequestHeader  *ret;
-        int    retValueCount = 1;
-        int    retDataLen = sizeof(Uint64);
+        int    retValueCount;
+        int    retDataLen;
        void    *returnData[Request->NParams];
         int    argSizes[Request->NParams];
        Uint    ret_errno = 0;
        
+       // Clear errno (Acess verson) at the start of the request
+       errno = 0;
+       
        // Sanity check
        if( Request->CallID >= ciNumSyscalls ) {
                Log_Notice("Syscalls", "Unknown syscall number %i", Request->CallID);
@@ -289,7 +300,11 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
                Log_Notice("Syscalls", "Unimplemented syscall %i", Request->CallID);
                return NULL;
        }
-       
+
+       // Init return count/size
+       retValueCount = 2;
+       retDataLen = sizeof(Uint64) + sizeof(Uint32);   
+
        // Get size of argument list
        for( i = 0; i < Request->NParams; i ++ )
        {
@@ -310,12 +325,19 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
                case ARG_TYPE_DATA:
                        formatString[i] = 'd';
                        argListLen += sizeof(void*);
+                       // Prepare the return values
+                       if( Request->Params[i].Flags & ARG_FLAG_RETURN )
+                       {
+                               retDataLen += Request->Params[i].Length;
+                               retValueCount ++;
+                       }
                        break;
                case ARG_TYPE_STRING:
                        formatString[i] = 's';
                        argListLen += sizeof(char*);
                        break;
                default:
+                       Log_Error("Syscalls", "Unknown param type %i", Request->Params[i].Type);
                        return NULL;    // ERROR!
                }
        }
@@ -356,13 +378,6 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
                        // Data gets special handling, because only it can be returned to the user
                        // (ARG_TYPE_DATA is a pointer)
                        case ARG_TYPE_DATA:
-                               // Prepare the return values
-                               if( Request->Params[i].Flags & ARG_FLAG_RETURN )
-                               {
-                                       retDataLen += Request->Params[i].Length;
-                                       retValueCount ++;
-                               }
-                               
                                // Check for non-resident data
                                if( Request->Params[i].Length == 0 )
                                {
@@ -392,9 +407,17 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
                        }
                }
                
+               // --- Perform request
                retVal = caSyscalls[Request->CallID](&ret_errno, formatString, argListData, argSizes);
        }
        
+       // ---------- Return
+       
+       if( ret_errno == 0 && errno != 0 ) {
+               ret_errno = errno;
+               LOG("errno = %i", errno);
+       }
+       
        // Allocate the return
        size_t  msglen = sizeof(tRequestHeader) + retValueCount * sizeof(tRequestValue) + retDataLen;
        ret = malloc(msglen);
@@ -411,9 +434,18 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
        *(Uint64*)inData = retVal;
        inData += sizeof(Uint64);
        
+       // Static Uint32 errno value
+       ret->Params[1].Type = ARG_TYPE_INT32;
+       ret->Params[1].Flags = 0;
+       ret->Params[1].Length = sizeof(Uint32);
+       *(Uint32*)inData = ret_errno;
+       inData += sizeof(Uint32);
+
+       LOG("Ret: %llx, errno=%i", retVal, ret_errno);  
+
        //Log_Debug("Syscalls", "Return 0x%llx", retVal);
        
-       retValueCount = 1;
+       retValueCount = 2;
        for( i = 0; i < Request->NParams; i ++ )
        {
                if( Request->Params[i].Type != ARG_TYPE_DATA )  continue;
@@ -434,9 +466,7 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
                retValueCount ++;
        }
        
-       *ReturnLength = sizeof(tRequestHeader)
-               + retValueCount * sizeof(tRequestValue)
-               + retDataLen;
+       *ReturnLength = ret->MessageLength;
        
        return ret;
 }
index 661d584..7296a58 100644 (file)
@@ -339,7 +339,7 @@ Uint32 Threads_WaitEvents(Uint32 Mask)
        //Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);      
 
        gpCurrentThread->WaitMask = Mask;
-       if( !(gpCurrentThread->Events & Mask) )
+       if( !(gpCurrentThread->EventState & Mask) )
        {
                if( Threads_Glue_SemWait(gpCurrentThread->EventSem, INT_MAX) == -1 ) {
                        Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
@@ -347,8 +347,8 @@ Uint32 Threads_WaitEvents(Uint32 Mask)
                }
                //Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
        }
-       rv = gpCurrentThread->Events & Mask;
-       gpCurrentThread->Events &= ~Mask;
+       rv = gpCurrentThread->EventState & Mask;
+       gpCurrentThread->EventState &= ~Mask;
        gpCurrentThread->WaitMask = -1;
 
        //Log_Debug("Threads", "- rv = %x", rv);
@@ -358,7 +358,7 @@ Uint32 Threads_WaitEvents(Uint32 Mask)
 
 void Threads_PostEvent(tThread *Thread, Uint32 Events)
 {
-       Thread->Events |= Events;
+       Thread->EventState |= Events;
 //     Log_Debug("Threads", "Trigger event %x (->Events = %p) on %p", Events, Thread->Events, Thread);
 
        if( Events == 0 || Thread->WaitMask & Events ) {
@@ -369,6 +369,6 @@ void Threads_PostEvent(tThread *Thread, Uint32 Events)
 
 void Threads_ClearEvent(Uint32 EventMask)
 {
-       gpCurrentThread->Events &= ~EventMask;
+       gpCurrentThread->EventState &= ~EventMask;
 }
 
index da18f48..3cce484 100644 (file)
@@ -14,8 +14,8 @@
 
 // === PROTOTYPES ===
  int   Video_Install(char **Arguments);
-Uint64 Video_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
-Uint64 Video_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer);
+size_t Video_Read(tVFS_Node *Node, Uint64 Offset, size_t Length, void *Buffer);
+size_t Video_Write(tVFS_Node *Node, Uint64 Offset, size_t Length, const void *Buffer);
  int   Video_IOCtl(tVFS_Node *Node, int ID, void *Data);
 // --- 2D Acceleration Functions --
 void   Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
@@ -55,7 +55,7 @@ int Video_Install(char **Arguments)
 /**
  * \brief Read from framebuffer (unimplemented)
  */
-Uint64 Video_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+size_t Video_Read(tVFS_Node *Node, Uint64 Offset, size_t Length, void *Buffer)
 {
        return 0;
 }
@@ -63,7 +63,7 @@ Uint64 Video_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
 /**
  * \brief Write to the framebuffer
  */
-Uint64 Video_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer)
+size_t Video_Write(tVFS_Node *Node, Uint64 Offset, size_t Length, const void *Buffer)
 {
         int    i;
        ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
index bbaef1d..78e0785 100644 (file)
@@ -11,7 +11,8 @@ OBJ := $(addprefix obj-$(PLATFORM)/,$(OBJ))
 
 ifeq ($(PLATFORM),win)
        BIN := ../ld-acess.exe
-       LDFLAGS += -lws2_32
+       LINKADDR := 0x70000000
+       LDFLAGS += -lws2_32 -Wl,--image-base,$(LINKADDR)
 endif
 ifeq ($(PLATFORM),lin)
        BIN := ../ld-acess
index d04ac6d..59be829 100644 (file)
@@ -65,9 +65,9 @@ char *Binary_LocateLibrary(const char *Name)
                strcat(tmp, "/");
                strcat(tmp, Name);
                
-               fd = acess_open(tmp, 4);        // OPENFLAG_EXEC
+               fd = acess__SysOpen(tmp, 4);    // OPENFLAG_EXEC
                if(fd != -1) {
-                       acess_close(fd);
+                       acess__SysClose(fd);
                        return strdup(tmp);
                }
        }               
@@ -84,9 +84,9 @@ char *Binary_LocateLibrary(const char *Name)
                printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
                #endif
 
-               fd = acess_open(tmp, 4);        // OPENFLAG_EXEC
+               fd = acess__SysOpen(tmp, 4);    // OPENFLAG_EXEC
                if(fd != -1) {
-                       acess_close(fd);
+                       acess__SysClose(fd);
                        return strdup(tmp);
                }
        }               
@@ -156,22 +156,22 @@ void *Binary_Load(const char *Filename, uintptr_t *EntryPoint)
                }
        }
 
-       fd = acess_open(Filename, 2|1); // Execute and Read
+       fd = acess__SysOpen(Filename, 2|1);     // Execute and Read
        if( fd == -1 ) {
                // TODO: Handle libary directories
                perror("Opening binary");
                return NULL;
        }
 
-       acess_read(fd, &dword, 4);
-       acess_seek(fd, 0, ACESS_SEEK_SET);
+       acess__SysRead(fd, &dword, 4);
+       acess__SysSeek(fd, 0, ACESS_SEEK_SET);
        
        if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
                fmt = &gElf_FormatDef;
        }
        else {
                fprintf(stderr, "Unknown executable format (0x%08x)\n", dword);
-               acess_close(fd);
+               acess__SysClose(fd);
                return NULL;
        }
        
@@ -179,7 +179,7 @@ void *Binary_Load(const char *Filename, uintptr_t *EntryPoint)
        printf("fmt->Load(0x%x)...\n", fd);
        #endif
        ret = fmt->Load(fd);
-       acess_close(fd);
+       acess__SysClose(fd);
        #if DEBUG
        printf("fmt->Load(0x%x): %p\n", fd, ret);
        #endif
index 63db861..9f67e9c 100644 (file)
@@ -31,11 +31,12 @@ static inline void AddLoaded(const char *Path, void *Base)
        Binary_SetReadyToUse(Base);
 }
 
-static inline int SysSetMemFlags(uintptr_t Addr, unsigned int flags, unsigned int mask)
+static inline int _SysSetMemFlags(uintptr_t Addr, unsigned int flags, unsigned int mask)
 {
        return 0;
 }
 
+
 extern int     AllocateMemory(uintptr_t VirtAddr, size_t ByteCount);
 extern uintptr_t       FindFreeRange(size_t ByteCount, int MaxBits);
 
index d661622..19a8c13 100644 (file)
@@ -42,7 +42,7 @@ void *Elf_Load(int FD)
        Elf64_Ehdr      hdr;\r
        \r
        // Read ELF Header\r
-       acess_read(FD, &hdr, sizeof(hdr));\r
+       acess__SysRead(FD, &hdr, sizeof(hdr));\r
        \r
        // Check the file type\r
        if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {\r
@@ -89,8 +89,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
                return NULL;\r
        }\r
        LOG("hdr.phoff = 0x%08x\n", hdr->phoff);\r
-       acess_seek(FD, hdr->phoff, ACESS_SEEK_SET);\r
-       acess_read(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);\r
+       acess__SysSeek(FD, hdr->phoff, ACESS_SEEK_SET);\r
+       acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);\r
        \r
        // Count Pages\r
        iPageCount = 0;\r
@@ -146,8 +146,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
                        char *tmp;\r
                        //if(ret->Interpreter)  continue;\r
                        tmp = malloc(phtab[i].FileSize);\r
-                       acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
-                       acess_read(FD, tmp, phtab[i].FileSize);\r
+                       acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
+                       acess__SysRead(FD, tmp, phtab[i].FileSize);\r
                        //ret->Interpreter = Binary_RegInterp(tmp);\r
                        LOG("Interpreter '%s'\n", tmp);\r
                        free(tmp);\r
@@ -168,8 +168,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr)
                        return NULL;\r
                }\r
                \r
-               acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
-               acess_read(FD, PTRMK(void, addr), phtab[i].FileSize);\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
        }\r
        \r
@@ -211,8 +211,8 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr)
                return NULL;\r
        }\r
        LOG("hdr.phoff = 0x%08llx\n", (long long)hdr->e_phoff);\r
-       acess_seek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
-       acess_read(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);\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
@@ -270,8 +270,8 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr)
                        //if(ret->Interpreter)  continue;\r
                        tmp = malloc(phtab[i].p_filesz+1);\r
                        tmp[ phtab[i].p_filesz ] = 0;\r
-                       acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
-                       acess_read(FD, tmp, 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
@@ -295,8 +295,8 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr)
                        return NULL;\r
                }\r
                \r
-               acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
-               acess_read(FD, PTRMK(void, addr), phtab[i].p_filesz);\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
index 07662a5..dcfc526 100644 (file)
@@ -11,7 +11,8 @@
 #include <stdarg.h>
 #include <stddef.h>
 
-#define DEBUG(v...)    do{}while(0)//Debug(v)
+#define DEBUG(v...)    Debug(v)
+//#define DEBUG(v...)  do{}while(0)//Debug(v)
 #define PAGE_SIZE      4096
 
 typedef struct sFILE   FILE;
@@ -41,12 +42,12 @@ char        *gsExecutablePath = "./ld-acess";
 
 // === CODE ===
 // --- VFS Calls
-int acess_chdir(const char *Path)
+int acess__SysChdir(const char *Path)
 {
        return _Syscall(SYS_CHDIR, ">s", Path);
 }
 
-int acess_open(const char *Path, int Flags)
+int acess__SysOpen(const char *Path, int Flags)
 {
        if( strncmp(Path, "$$$$", 4) == 0 )
        {
@@ -56,7 +57,8 @@ int acess_open(const char *Path, int Flags)
        return _Syscall(SYS_OPEN, ">s >i", Path, Flags);
 }
 
-void acess_close(int FD) {
+void acess__SysClose(int FD)
+{
        if(FD & NATIVE_FILE_MASK) {
                return native_close(FD & (NATIVE_FILE_MASK-1));
        }
@@ -64,12 +66,12 @@ void acess_close(int FD) {
        _Syscall(SYS_CLOSE, ">i", FD);
 }
 
-int acess_reopen(int FD, const char *Path, int Flags) {
+int acess__SysReopen(int FD, const char *Path, int Flags) {
        DEBUG("reopen(0x%x, \"%s\", 0x%x)", FD, Path, Flags);
        return _Syscall(SYS_REOPEN, ">i >s >i", FD, Path, Flags);
 }
 
-size_t acess_read(int FD, void *Dest, size_t Bytes) {
+size_t acess__SysRead(int FD, void *Dest, size_t Bytes) {
        if(FD & NATIVE_FILE_MASK)
                return native_read(FD & (NATIVE_FILE_MASK-1), Dest, Bytes);
 //     if( FD > 2 )
@@ -77,7 +79,7 @@ size_t acess_read(int FD, void *Dest, size_t Bytes) {
        return _Syscall(SYS_READ, ">i >i <d", FD, Bytes, Bytes, Dest);
 }
 
-size_t acess_write(int FD, const void *Src, size_t Bytes) {
+size_t acess__SysWrite(int FD, const void *Src, size_t Bytes) {
        if(FD & NATIVE_FILE_MASK)
                return native_write(FD & (NATIVE_FILE_MASK-1), Src, Bytes);
 //     if( FD > 2 )
@@ -85,7 +87,8 @@ size_t acess_write(int FD, const void *Src, size_t Bytes) {
        return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src);
 }
 
-int acess_seek(int FD, int64_t Ofs, int Dir) {
+int acess__SysSeek(int FD, int64_t Ofs, int Dir)
+{
        if(FD & NATIVE_FILE_MASK) {
                return native_seek(FD & (NATIVE_FILE_MASK-1), Ofs, Dir);
        }
@@ -93,14 +96,15 @@ int acess_seek(int FD, int64_t Ofs, int Dir) {
        return _Syscall(SYS_SEEK, ">i >I >i", FD, Ofs, Dir);
 }
 
-uint64_t acess_tell(int FD) {
+uint64_t acess__SysTell(int FD)
+{
        if(FD & NATIVE_FILE_MASK)
                return native_tell( FD & (NATIVE_FILE_MASK-1) );
        DEBUG("tell(0x%x)", FD);
        return _Syscall(SYS_TELL, ">i", FD);
 }
 
-int acess_ioctl(int fd, int id, void *data) {
+int acess__SysIOCtl(int fd, int id, void *data) {
         int    len;
        DEBUG("ioctl(%i, %i, %p)", fd, id, data);
        // NOTE: The length here is hacky and could break
@@ -110,7 +114,7 @@ int acess_ioctl(int fd, int id, void *data) {
                len = PAGE_SIZE - ((uintptr_t)data % PAGE_SIZE);
        return _Syscall(SYS_IOCTL, ">i >i ?d", fd, id, len, data);
 }
-int acess_finfo(int fd, t_sysFInfo *info, int maxacls) {
+int acess__SysFInfo(int fd, t_sysFInfo *info, int maxacls) {
 //     DEBUG("offsetof(size, t_sysFInfo) = %i", offsetof(t_sysFInfo, size));
        DEBUG("finfo(%i, %p, %i)", fd, info, maxacls);
        return _Syscall(SYS_FINFO, ">i <d >i",
@@ -120,12 +124,12 @@ int acess_finfo(int fd, t_sysFInfo *info, int maxacls) {
                );
 }
 
-int acess_SysReadDir(int fd, char *dest) {
+int acess__SysReadDir(int fd, char *dest) {
        DEBUG("SysReadDir(%i, %p)", fd, dest);
        return _Syscall(SYS_READDIR, ">i <d", fd, 256, dest);
 }
 
-int acess__SysSelect(int nfds, fd_set *read, fd_set *write, fd_set *error, time_t *timeout, uint32_t events)
+int acess__SysSelect(int nfds, fd_set *read, fd_set *write, fd_set *error, int64_t *timeout, uint32_t events)
 {
        DEBUG("_SysSelect(%i, %p, %p, %p, %p, 0x%x)", nfds, read, write, error, timeout, events);
        return _Syscall(SYS_SELECT, ">i ?d ?d ?d >d >i", nfds,
@@ -137,12 +141,6 @@ int acess__SysSelect(int nfds, fd_set *read, fd_set *write, fd_set *error, time_
                );
 }
 
-int acess_select(int nfds, fd_set *read, fd_set *write, fd_set *error, time_t *timeout)
-{
-       return acess__SysSelect(nfds, read, write, error, timeout, 0);
-}
-
-
 int acess__SysOpenChild(int fd, char *name, int flags) {
        DEBUG("_SysOpenChild(0x%x, '%s', 0x%x)", fd, name, flags);
        return _Syscall(SYS_OPENCHILD, ">i >s >i", fd, name, flags);
@@ -166,7 +164,7 @@ int acess__SysSetFaultHandler(int (*Handler)(int)) {
 }
 
 // --- Memory Management ---
-uint64_t acess__SysAllocate(uint vaddr)
+uint64_t acess__SysAllocate(uintptr_t vaddr)
 {
        if( AllocateMemory(vaddr, 0x1000) == -1 )       // Allocate a page
                return 0;
@@ -175,7 +173,7 @@ uint64_t acess__SysAllocate(uint vaddr)
 }
 
 // --- Process Management ---
-int acess_clone(int flags, void *stack)
+int acess__SysClone(int flags, void *stack)
 {
        #ifdef __WIN32__
        Warning("Win32 does not support anything like fork(2), cannot emulate");
@@ -211,7 +209,7 @@ int acess_clone(int flags, void *stack)
        #endif
 }
 
-int acess_execve(char *path, char **argv, const char **envp)
+int acess__SysExecVE(char *path, char **argv, const char **envp)
 {
         int    i, argc;
        
@@ -288,13 +286,13 @@ int acess__SysSpawn(const char *binary, const char **argv, const char **envp, in
        return kernel_tid;
 }
 
-void acess_sleep(void)
-{
-       DEBUG("%s()", __func__);
-       _Syscall(SYS_SLEEP, "");
-}
+//void acess_sleep(void)
+//{
+//     DEBUG("%s()", __func__);
+//     _Syscall(SYS_SLEEP, "");
+//}
 
-int acess_waittid(int TID, int *ExitStatus)
+int acess__SysWaitTID(int TID, int *ExitStatus)
 {
        DEBUG("%s(%i, %p)", __func__, TID, ExitStatus);
        return _Syscall(SYS_WAITTID, ">i <d", TID, sizeof(int), &ExitStatus);
@@ -307,13 +305,13 @@ int acess_getpid(void) { return _Syscall(SYS_GETPID, ""); }
 int acess_getuid(void) { return _Syscall(SYS_GETUID, ""); }
 int acess_getgid(void) { return _Syscall(SYS_GETGID, ""); }
 
-int acess_SysSendMessage(int DestTID, int Length, void *Data)
+int acess__SysSendMessage(int DestTID, int Length, void *Data)
 {
        DEBUG("%s(%i, 0x%x, %p)", __func__, DestTID, Length, Data);
        return _Syscall(SYS_SENDMSG, ">i >d", DestTID, Length, Data);
 }
 
-int acess_SysGetMessage(int *SourceTID, int BufLen, void *Data)
+int acess__SysGetMessage(int *SourceTID, int BufLen, void *Data)
 {
        DEBUG("%s(%p, %p)", __func__, SourceTID, Data);
        return _Syscall(SYS_GETMSG, "<d <d",
@@ -349,45 +347,51 @@ void acess__exit(int Status)
        exit(Status);
 }
 
+uint32_t acess__SysSetMemFlags(uintptr_t vaddr, uint32_t flags, uint32_t mask)
+{
+       // TODO: Impliment acess__SysSetMemFlags?
+       return 0;
+}
+
 
 // === Symbol List ===
 #define DEFSYM(name)   {#name, &acess_##name}
 const tSym     caBuiltinSymbols[] = {
        DEFSYM(_exit),
        
-       DEFSYM(chdir),
-       DEFSYM(open),
-       DEFSYM(close),
-       DEFSYM(reopen),
-       DEFSYM(read),
-       DEFSYM(write),
-       DEFSYM(seek),
-       DEFSYM(tell),
-       DEFSYM(ioctl),
-       DEFSYM(finfo),
-       DEFSYM(SysReadDir),
-       DEFSYM(select),
+       DEFSYM(_SysChdir),
+       DEFSYM(_SysOpen),
        DEFSYM(_SysOpenChild),
+       DEFSYM(_SysReopen),
+       DEFSYM(_SysClose),
+       DEFSYM(_SysRead),
+       DEFSYM(_SysWrite),
+       DEFSYM(_SysSeek),
+       DEFSYM(_SysTell),
+       DEFSYM(_SysIOCtl),
+       DEFSYM(_SysFInfo),
+       DEFSYM(_SysReadDir),
        DEFSYM(_SysGetACL),
        DEFSYM(_SysMount),
        DEFSYM(_SysSelect),
        
-       DEFSYM(clone),
-       DEFSYM(execve),
+       DEFSYM(_SysClone),
+       DEFSYM(_SysExecVE),
        DEFSYM(_SysSpawn),
-       DEFSYM(sleep),
+//     DEFSYM(sleep),
        
-       DEFSYM(waittid),
+       DEFSYM(_SysWaitTID),
        DEFSYM(gettid),
        DEFSYM(setuid),
        DEFSYM(setgid),
        DEFSYM(getuid),
        DEFSYM(getgid),
 
-       DEFSYM(SysSendMessage),
-       DEFSYM(SysGetMessage),
+       DEFSYM(_SysSendMessage),
+       DEFSYM(_SysGetMessage),
        
        DEFSYM(_SysAllocate),
+       DEFSYM(_SysSetMemFlags),
        DEFSYM(_SysDebug),
        DEFSYM(_SysSetFaultHandler),
        DEFSYM(_SysWaitEvent),
index dc319ac..e9a4b3b 100644 (file)
@@ -13,6 +13,8 @@
 // Syscall request (used by acess_*)
 extern uint64_t        _Syscall(int SyscallID, const char *ArgTypes, ...);
 
+extern int     acess__errno;
+
 extern int     native_open(const char *Path, int Flags);
 extern void    native_close(int FD);
 extern size_t  native_read(int FD, void *Dest, size_t Bytes);
@@ -24,10 +26,10 @@ extern int  native_execve(const char *filename, const char *const argv[], const c
 extern int     native_spawn(const char *filename, const char *const argv[], const char *const envp[]);
 
 // Syscalls used by the linker
-extern int     acess_open(const char *Path, int Flags);
-extern void    acess_close(int FD);
-extern size_t  acess_read(int FD, void *Dest, size_t Bytes);
-extern int     acess_seek(int FD, int64_t Offset, int Dir);
+extern int     acess__SysOpen(const char *Path, int Flags);
+extern void    acess__SysClose(int FD);
+extern size_t  acess__SysRead(int FD, void *Dest, size_t Bytes);
+extern int     acess__SysSeek(int FD, int64_t Offset, int Dir);
 
 // Symbol type
 typedef struct {
index e4acbf0..a03e963 100644 (file)
@@ -53,7 +53,7 @@ int main(int argc, char *argv[], char **envp)
                }
                
                if(strcmp(argv[i], "--open") == 0) {
-                       if( acess_open(argv[++i], 6) == -1 ) {  // Read/Write
+                       if( acess__SysOpen(argv[++i], 6) == -1 ) {      // Read/Write
                                fprintf(stderr, "Unable to open '%s'\n", argv[i]);
                                exit(1);
                        }
@@ -85,7 +85,10 @@ int main(int argc, char *argv[], char **envp)
 
        base = Binary_Load(appPath, (uintptr_t*)&appMain);
        printf("[DEBUG %i] base = %p\n", giSyscall_ClientID, base);
-       if( !base )     return 127;
+       if( !base )     {
+               *((char*)NULL) = 0;
+               return 127;
+       }
        
        printf("==============================\n");
        printf("[DEBUG %i] %i ", giSyscall_ClientID, appArgc);
index 3f0091d..c8166af 100644 (file)
@@ -21,9 +21,26 @@ int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount)
        size_t  size = (VirtAddr & 0xFFF) + ByteCount;
        void    *tmp;
        #if __WIN32__
-       tmp = VirtualAlloc((void*)base, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+       do
+       {
+               MEMORY_BASIC_INFORMATION        info;
+               VirtualQuery( (void*)base, &info, sizeof(info) );
+               if( info.State != MEM_FREE ) {
+                       printf("ERROR: Unable to allocate memory %p+0x%x, already allocated\n",
+                               (void*)base, size);
+                       base += 0x1000;
+                       if( size < 0x1000 )
+                               return 0;
+                       size -= 0x1000;
+               }
+               else
+                       break;
+       } while( size >= 0x1000 );
+       tmp = VirtualAlloc((void*)base, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if( tmp == NULL ) {
-               printf("ERROR: Unable to allocate memory (0x%x)\n", (int)GetLastError());
+               printf("ERROR: Unable to allocate memory %p+%x (0x%x)\n",
+                       (void*)base, size,
+                       (int)GetLastError());
                return -1;
        }
        #else
index 5bcf8cd..2fa481a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  */
-#define DEBUG  0
+#define DEBUG  1
 
 
 #if DEBUG
@@ -51,6 +51,7 @@ void Request_Preinit(void)
        memset((void *)&gSyscall_ServerAddr, '\0', sizeof(struct sockaddr_in));
        gSyscall_ServerAddr.sin_family = AF_INET;
        gSyscall_ServerAddr.sin_port = htons(SERVER_PORT);
+       gSyscall_ServerAddr.sin_addr.s_addr = htonl(0x7F000001);
 }
 
 int _InitSyscalls(void)
@@ -80,20 +81,13 @@ int _InitSyscalls(void)
                exit(0);
        }
        
-       #if 0
-       // Set client address
-       memset((void *)&client, '\0', sizeof(struct sockaddr_in));
-       client.sin_family = AF_INET;
-       client.sin_port = htons(0);
-       client.sin_addr.s_addr = htonl(0x7F000001);
-       #endif
-       
        #if USE_TCP
        if( connect(gSocket, (struct sockaddr *)&gSyscall_ServerAddr, sizeof(struct sockaddr_in)) < 0 )
        {
                fprintf(stderr, "[ERROR -] Cannot connect to server (localhost:%i)\n", SERVER_PORT);
                perror("_InitSyscalls");
                #if __WIN32__
+               fprintf(stderr, "[ERROR -] - WSAGetLastError said %i", WSAGetLastError());
                closesocket(gSocket);
                WSACleanup();
                #else
@@ -104,6 +98,11 @@ int _InitSyscalls(void)
        #endif
        
        #if 0
+       // Set client address
+       memset((void *)&client, '\0', sizeof(struct sockaddr_in));
+       client.sin_family = AF_INET;
+       client.sin_port = htons(0);
+       client.sin_addr.s_addr = htonl(0x7F000001);
        // Bind
        if( bind(gSocket, (struct sockaddr *)&client, sizeof(struct sockaddr_in)) == -1 )
        {
@@ -309,7 +308,11 @@ int ReadData(void *Dest, int MaxLength, int Timeout)
        }
        if( ret == 0 ) {
                fprintf(stderr, "[ERROR %i] Connection closed.\n", giSyscall_ClientID);
+               #if __WIN32__
+               closesocket(gSocket);
+               #else
                close(gSocket);
+               #endif
                exit(0);
        }
        
index 26f6c44..c649f28 100644 (file)
@@ -9,7 +9,9 @@
 #include <string.h>
 #include <stddef.h>
 #include <unistd.h>
-#include <spawn.h>     // posix_spawn
+#ifndef __WIN32__
+# include <spawn.h>    // posix_spawn
+#endif
 #include "request.h"
 
 #if SYSCALL_TRACE
 #define DEBUG(...)     do{}while(0)
 #endif
 
+#define assert(cnd) do{ \
+       if( !(cnd) ) { \
+               fprintf(stderr, "%s:%i - assert failed - " #cnd, __FILE__, __LINE__);\
+               exit(-1); \
+       } \
+}while(0)
+
 #define        MAX_FPS 16
 
 // === Types ===
@@ -161,7 +170,7 @@ uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
 {
        va_list args;
         int    paramCount, dataLength;
-        int    retCount = 1, retLength = sizeof(uint64_t);
+        int    retCount = 2, retLength = sizeof(uint64_t) + sizeof(uint32_t);
        void    **retPtrs;      // Pointers to return buffers
        const char      *str;
        tRequestHeader  *req;
@@ -234,38 +243,33 @@ uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
        }
        va_end(args);
        
-       // Send syscall request
+       // --- Send syscall request
        if( SendRequest(req, dataLength, retLength) < 0 ) {
                fprintf(stderr, "syscalls.c: SendRequest failed (SyscallID = %i)\n", SyscallID);
                exit(127);
        }
        
-       // Parse return value
-       dataPtr = &req->Params[req->NParams];
-       retValue = 0;
-       if( req->NParams >= 1 )
-       {
-               switch(req->Params[0].Type)
-               {
-               case ARG_TYPE_INT64:
-                       retValue = *(uint64_t*)dataPtr;
-                       dataPtr += req->Params[0].Length;
-                       break;
-               case ARG_TYPE_INT32:
-                       retValue = *(uint32_t*)dataPtr;
-                       dataPtr += req->Params[0].Length;
-                       break;
-               }       
-       }
+       Debug("req->NParams = %i", req->NParams);
+       assert(req->NParams >= 2);
+       // return
+       assert(req->Params[0].Type == ARG_TYPE_INT64);
+       assert(req->Params[0].Length == sizeof(uint64_t));
+       retValue = *(uint64_t*)dataPtr;
+       dataPtr += sizeof(uint64_t);
+       // errno
+       assert(req->Params[1].Type == ARG_TYPE_INT32);
+       assert(req->Params[1].Length == sizeof(uint32_t));
+       acess__errno = *(uint32_t*)dataPtr;
+       dataPtr += sizeof(uint32_t);
        
        // Write changes to buffers
-       if( req->NParams - 1 != retCount ) {
+       if( req->NParams - 2 != retCount ) {
                fprintf(stderr, "syscalls.c: Return count inbalance (%i - 1 != exp %i) [Call %i]\n",
                        req->NParams, retCount, SyscallID);
                exit(127);
        }
        retCount = 0;
-       for( i = 1; i < req->NParams; i ++ )
+       for( i = 2; i < req->NParams; i ++ )
        {
                #if 0
                 int     j;
@@ -274,6 +278,7 @@ uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
                        printf(" %02x", ((uint8_t*)dataPtr)[j]);
                printf("\n");
                #endif
+               assert( req->Params[i].Type == ARG_TYPE_DATA );
                memcpy( retPtrs[retCount++], dataPtr, req->Params[i].Length );
                dataPtr += req->Params[i].Length;
        }
@@ -341,7 +346,11 @@ int native_spawn(const char *filename, const char *const argv[], const char *con
 {
        int rv;
        
+       #if __WIN32__
+       rv = _spawnve(_P_NOWAIT, filename, argv, envp);
+       #else
        rv = posix_spawn(NULL, filename, NULL, NULL, (void*)argv, (void*)envp);
+       #endif
        
        return rv;
 }
index 21a9cb5..b9661bc 100644 (file)
@@ -35,84 +35,20 @@ typedef struct sRequestHeader {
        tRequestValue   Params[];
 }      tRequestHeader;
 
-enum eSyscalls {
-       SYS_NULL,
-       
-       SYS_EXIT,
-       
-       SYS_OPEN,
-       SYS_CLOSE,
-       SYS_READ,
-       SYS_WRITE,
-       SYS_SEEK,
-       SYS_TELL,
-       SYS_IOCTL,
-       SYS_FINFO,
-       SYS_READDIR,
-       SYS_OPENCHILD,
-       SYS_GETACL,
-       SYS_MOUNT,
-       SYS_REOPEN,
-       SYS_CHDIR,
-       
-       SYS_WAITTID,
-       SYS_SETUID,
-       SYS_SETGID,
-
-       SYS_GETTID,
-       SYS_GETPID,
-       SYS_GETUID,
-       SYS_GETGID,
 
-       // IPC
-       SYS_SLEEP,
-       SYS_AN_FORK,
-       SYS_AN_SPAWN,
-       SYS_SENDMSG,
-       SYS_GETMSG,
-       SYS_SELECT,
-       SYS_WAITEVENT,
-       
+enum eSyscalls {
+       #define _(n) n
+       #include "syscalls_list.h"
+       #undef _
        N_SYSCALLS
 };
 
 #ifndef DONT_INCLUDE_SYSCALL_NAMES
 static const char * casSYSCALL_NAMES[] = {
-       "SYS_NULL",
-       
-       "SYS_EXIT",
-       
-       "SYS_OPEN",
-       "SYS_CLOSE",
-       "SYS_READ",
-       "SYS_WRITE",
-       "SYS_SEEK",
-       "SYS_TELL",
-       "SYS_IOCTL",
-       "SYS_FINFO",
-       "SYS_READDIR",
-       "SYS_OPENCHILD",
-       "SYS_GETACL",
-       "SYS_MOUNT",
-       "SYS_REOPEN",
-       "SYS_CHDIR",
-       
-       "SYS_WAITTID",
-       "SYS_SETUID",
-       "SYS_SETGID",
-       
-       "SYS_GETTID",
-       "SYS_GETPID",
-       "SYS_GETUID",
-       "SYS_GETGID",
-       
-       // IPC
-       "SYS_SLEEP",
-       "SYS_AN_FORK",
-       "SYS_SENDMSG",
-       "SYS_GETMSG",
-       "SYS_SELECT",
-       "SYS_WAITEVENT"
+       #define _(n) #n
+       #include "syscalls_list.h"
+       #undef _
+       "-"
 };
 #endif
 
diff --git a/AcessNative/syscalls_list.h b/AcessNative/syscalls_list.h
new file mode 100644 (file)
index 0000000..9ab9098
--- /dev/null
@@ -0,0 +1,37 @@
+_(SYS_NULL),
+
+_(SYS_EXIT),
+
+_(SYS_OPEN),
+_(SYS_CLOSE),
+_(SYS_READ),
+_(SYS_WRITE),
+_(SYS_SEEK),
+_(SYS_TELL),
+_(SYS_IOCTL),
+_(SYS_FINFO),
+_(SYS_READDIR),
+_(SYS_OPENCHILD),
+_(SYS_GETACL),
+_(SYS_MOUNT),
+_(SYS_REOPEN),
+_(SYS_CHDIR),
+
+_(SYS_WAITTID),
+_(SYS_SETUID),
+_(SYS_SETGID),
+
+_(SYS_GETTID),
+_(SYS_GETPID),
+_(SYS_GETUID),
+_(SYS_GETGID),
+
+// IPC
+_(SYS_SLEEP),
+_(SYS_AN_FORK),
+_(SYS_AN_SPAWN),
+_(SYS_SENDMSG),
+_(SYS_GETMSG),
+_(SYS_SELECT),
+_(SYS_WAITEVENT),
+
index 43a1854..57d7fe8 100644 (file)
@@ -5,7 +5,7 @@
  * acpica.c
  * - ACPICA Interface
  */
-#define ACPI_DEBUG_OUTPUT      1
+#define ACPI_DEBUG_OUTPUT      0
 #define DEBUG  0
 #define _AcpiModuleName "Shim"
 #define _COMPONENT     "Acess"
index 397ec14..77b0d1a 100644 (file)
@@ -77,7 +77,7 @@ int VM8086_Install(char **Arguments)
        
        // Create BIOS Call process
        pid = Proc_Clone(CLONE_VM);
-       Log_Debug("VM8086", "pid = %i", pid);
+       //Log_Debug("VM8086", "pid = %i", pid);
        if(pid == -1)
        {
                Log_Error("VM8086", "Unable to clone kernel into VM8086 worker");
@@ -89,7 +89,7 @@ int VM8086_Install(char **Arguments)
                Uint16  * volatile rmstack;     // Real Mode Stack
                 int    i;
 
-               Log_Debug("VM8086", "Initialising worker");     
+               //Log_Debug("VM8086", "Initialising worker");   
        
                // Set Image Name
                Threads_SetName("VM8086");
deleted file mode 120000 (symlink)
index cac29a8fa6fbcd0adfc2a30bf6858dd0c59b373c..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1 +0,0 @@
-../x86/pci.c
\ No newline at end of file
new file mode 100644 (file)
index 0000000000000000000000000000000000000000..a85e06c3f8bfa48169053ff1434eb5afe2afe85e
--- /dev/null
@@ -0,0 +1 @@
+#include "../x86/pci.c"
index cb11f5f..1cea00c 100644 (file)
@@ -150,7 +150,7 @@ void Debug(const char *Fmt, ...)
        va_list args;
        
        #if LOCK_DEBUG_OUTPUT
-       SHORTLOCK(&glDebug_Lock);
+       if(!CPU_HAS_LOCK(&glDebug_Lock)) SHORTLOCK(&glDebug_Lock);
        #endif
 
        Debug_Puts(0, "Debug: ");
@@ -228,7 +228,8 @@ void Panic(const char *Fmt, ...)
        va_list args;
        
        #if LOCK_DEBUG_OUTPUT
-       SHORTLOCK(&glDebug_Lock);
+       if( !CPU_HAS_LOCK(&glDebug_Lock) )
+               SHORTLOCK(&glDebug_Lock);
        #endif
        // And never SHORTREL
        
index 2adaec7..1e6fcdb 100644 (file)
@@ -1,5 +1,9 @@
-/* AcessOS
- * FIFO Pipe Driver
+/* 
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * drv/fifo.c
+ * - FIFO Pipe Driver
  */
 #define DEBUG  0
 #include <acess.h>
@@ -126,9 +130,8 @@ tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
        if(Filename[0] == '\0') return NULL;
        
        // Anon Pipe
-       if(Filename[0] == 'a' && Filename[1] == 'n'
-       && Filename[2] == 'o' && Filename[3] == 'n'
-       && Filename[4] == '\0') {
+       if( strcmp(Filename, "anon") == 0 )
+       {
                tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
                return &tmp->Node;
        }
@@ -277,6 +280,7 @@ size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
                
                // Mark some flags
                if( pipe->ReadPos == pipe->WritePos ) {
+                       LOG("%i == %i, marking none to read", pipe->ReadPos, pipe->WritePos);
                        VFS_MarkAvaliable(Node, 0);
                }
                VFS_MarkFull(Node, 0);  // Buffer can't still be full
@@ -312,9 +316,12 @@ size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
        while(remaining)
        {
                // Wait for buffer to empty
-               if(pipe->Flags & PF_BLOCKING) {
-                       if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize )
+               if(pipe->Flags & PF_BLOCKING)
+               {
+                       if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize ) {
+                               LOG("Blocking write on FIFO");
                                VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
+                       }
 
                        len = remaining;
                        if( pipe->ReadPos > pipe->WritePos )
@@ -346,11 +353,14 @@ size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
                if(len > pipe->BufSize - pipe->WritePos)
                {
                        int ofs = pipe->BufSize - pipe->WritePos;
+                       LOG("pipe->Buffer = %p, pipe->WritePos = %i, ofs=%i, len=%i",
+                               pipe->Buffer, pipe->WritePos, ofs, len);
                        memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
-                       memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
+                       memcpy(&pipe->Buffer[0], (Uint8*)Buffer + ofs, len-ofs);
                }
                else
                {
+                       LOG("pipe->Buffer = %p, pipe->WritePos = %i", pipe->Buffer, pipe->WritePos);
                        memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
                }
                
@@ -360,6 +370,7 @@ size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
                
                // Mark some flags
                if( pipe->ReadPos == pipe->WritePos ) {
+                       LOG("Buffer is full");
                        VFS_MarkFull(Node, 1);  // Buffer full
                }
                VFS_MarkAvaliable(Node, 1);
@@ -384,11 +395,13 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
        tPipe   *ret;
         int    namelen = strlen(Name) + 1;
         int    allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
-       
+
+       ENTER("iSize sName", Size, Name);       
+
        ret = calloc(1, allocsize);
-       if(!ret)        return NULL;
+       if(!ret)        LEAVE_RET('n', NULL);
        
-       // Clear Return
+       // Set default flags
        ret->Flags = PF_BLOCKING;
        
        // Allocate Buffer
@@ -417,6 +430,8 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
                = ret->Node.MTime
                = ret->Node.ATime = now();
        ret->Node.Type = &gFIFO_PipeNodeType;
+
+       LEAVE('p', ret);
        
        return ret;
 }
index 9c7d909..930616a 100644 (file)
@@ -150,6 +150,10 @@ int SysFS_RegisterFile(const char *Path, const char *Data, int Length)
                if( !child )
                {
                        child = calloc( 1, sizeof(tSysFS_Ent)+tmp+1 );
+                       if( !child ) {
+                               Log_Error("SysFS", "calloc(%i) failure", sizeof(tSysFS_Ent)+tmp+1);
+                               return -1;
+                       }
                        child->Next = NULL;
                        memcpy(child->Name, &Path[start], tmp);
                        child->Name[tmp] = '\0';
@@ -174,7 +178,8 @@ int SysFS_RegisterFile(const char *Path, const char *Data, int Length)
                                ent->Node.Size ++;
                        else
                                gSysFS_DriverInfo.RootNode.Size ++;
-                       Log_Log("SysFS", "Added directory '%s'", child->Name);
+                       Log_Log("SysFS", "Added directory '%.*s'", tmp, &Path[start]);
+                       Log_Log("SysFS", "Added directory '%.*s'", tmp, child->Name);
                }
                
                ent = child;
index fc6dea2..3ff1a53 100644 (file)
@@ -114,11 +114,11 @@ int VT_Install(char **Arguments)
                        
                        if( strcmp(opt, "Video") == 0 ) {
                                if( !gsVT_OutputDevice )
-                                       gsVT_OutputDevice = strdup(val);
+                                       gsVT_OutputDevice = val;
                        }
                        else if( strcmp(opt, "Input") == 0 ) {
                                if( !gsVT_InputDevice )
-                                       gsVT_InputDevice = strdup(val);
+                                       gsVT_InputDevice = val;
                        }
                        else if( strcmp(opt, "Width") == 0 ) {
                                giVT_RealWidth = atoi( val );
@@ -129,6 +129,9 @@ int VT_Install(char **Arguments)
                        else if( strcmp(opt, "Scrollback") == 0 ) {
                                giVT_Scrollback = atoi( val );
                        }
+                       else {
+                               Log_Notice("VTerm", "Unknown option '%s'", opt);
+                       }
                }
        }
        
@@ -448,8 +451,8 @@ size_t VT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer
                // - Sanity Checking
                size = term->Width*term->Height*4;
                if( Offset > size ) {
-                       Log_Notice("VTerm", "VT_Write: Offset (0x%llx) > FBSize (0x%x)",
-                               Offset, size);
+                       Log_Notice("VTerm", "VT_Write: %i Offset (0x%llx) > FBSize (0x%x)",
+                               (int)Node->Inode, Offset, size);
                        return 0;
                }
                if( Offset + Length > size ) {
index 55eea0e..abd786c 100644 (file)
@@ -112,7 +112,7 @@ extern void VT_InitInput(void);
 extern void    VT_KBCallBack(Uint32 Codepoint);
 // --- VT100 Emulation ---
 extern void    VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int argc, int *args);
-extern int     VT_int_ParseEscape(tVTerm *Term, const char *Buffer);
+extern int     VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes);
 // --- Terminal Buffer ---
 extern void    VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count);
 extern void    VT_int_PutChar(tVTerm *Term, Uint32 Ch);
index 7c29656..525f1a4 100644 (file)
  */
 void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count)
 {
-       Uint32  val;
         int    i;
        
        // Iterate
        for( i = 0; i < Count; i++ )
        {
                // Handle escape sequences
-               if( Buffer[i] == 0x1B )
+               if( Buffer[i] == 0x1B && Count - i > 1 )
                {
-                       i ++;
-                       i += VT_int_ParseEscape(Term, (const char*)&Buffer[i]) - 1;
-                       continue;
+                       int ret = VT_int_ParseEscape(Term, (const char*)&Buffer[i+1], Count-(i+1));
+                       if( ret > 0 )
+                       {
+                               i += ret;
+                               continue;
+                       }
                }
                
                // Fast check for non UTF-8
                if( Buffer[i] < 128 )   // Plain ASCII
                        VT_int_PutChar(Term, Buffer[i]);
                else {  // UTF-8
+                       Uint32  val;
                        i += ReadUTF8(&Buffer[i], &val) - 1;
                        VT_int_PutChar(Term, val);
                }
index fb152a3..d86ee0f 100644 (file)
@@ -211,30 +211,39 @@ void VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int argc, int
  * \fn int VT_int_ParseEscape(tVTerm *Term, const char *Buffer)
  * \brief Parses a VT100 Escape code
  */
-int VT_int_ParseEscape(tVTerm *Term, const char *Buffer)
+int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes)
 {
        char    c;
-        int    argc = 0, j = 1;
+        int    argc = 0, j = 0;
         int    args[6] = {0,0,0,0};
         int    bQuestionMark = 0;
-       
-       switch(Buffer[0])
+
+       if( Bytes == j )        return j;
+       c = Buffer[j++];
+
+       switch(c)
        {
        //Large Code
        case '[':
                // Get Arguments
+               if(Bytes == j)  return j;
                c = Buffer[j++];
                if(c == '?') {
                        bQuestionMark = 1;
+                       if(Bytes == j)  return j;
                        c = Buffer[j++];
                }
                if( '0' <= c && c <= '9' )
                {
                        do {
-                               if(c == ';')    c = Buffer[j++];
+                               if(c == ';') {
+                                       if(Bytes == j)  return j;
+                                       c = Buffer[j++];
+                               }
                                while('0' <= c && c <= '9') {
                                        args[argc] *= 10;
                                        args[argc] += c-'0';
+                                       if(Bytes == j)  return j;
                                        c = Buffer[j++];
                                }
                                argc ++;
@@ -242,51 +251,64 @@ int VT_int_ParseEscape(tVTerm *Term, const char *Buffer)
                }
                
                // Get Command
-               if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
+               if( !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') )
                {
-                       if( bQuestionMark )
+                       // Error
+                       return j;
+               }
+               
+               if( bQuestionMark )
+               {
+                       switch(c)
                        {
-                               switch(c)
+                       // DEC Private Mode Set
+                       case 'h':
+                               if(argc != 1)   break;
+                               switch(args[0])
                                {
-                               // DEC Private Mode Set
-                               case 'h':
-                                       if(argc != 1)   break;
-                                       switch(args[0])
-                                       {
-                                       case 25:
-                                               Term->Flags &= ~VT_FLAG_HIDECSR;
-                                               break;
-                                       case 1047:
-                                               VT_int_ToggleAltBuffer(Term, 1);
-                                               break;
-                                       }
+                               case 25:
+                                       Term->Flags &= ~VT_FLAG_HIDECSR;
+                                       break;
+                               case 1047:
+                                       VT_int_ToggleAltBuffer(Term, 1);
                                        break;
-                               case 'l':
-                                       if(argc != 1)   break;
-                                       switch(args[0])
-                                       {
-                                       case 25:
-                                               Term->Flags |= VT_FLAG_HIDECSR;
-                                               break;
-                                       case 1047:
-                                               VT_int_ToggleAltBuffer(Term, 0);
-                                               break;
-                                       }
+                               }
+                               break;
+                       case 'l':
+                               if(argc != 1)   break;
+                               switch(args[0])
+                               {
+                               case 25:
+                                       Term->Flags |= VT_FLAG_HIDECSR;
                                        break;
-                               default:
-                                       Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c);
+                               case 1047:
+                                       VT_int_ToggleAltBuffer(Term, 0);
                                        break;
                                }
+                               break;
+                       default:
+                               Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c);
+                               break;
                        }
-                       else
-                       {
-                               VT_int_ParseEscape_StandardLarge(Term, c, argc, args);
-                       }
+               }
+               else
+               {
+                       VT_int_ParseEscape_StandardLarge(Term, c, argc, args);
                }
                break;
-               
+       case '\0':
+               // Ignore \0
+               break;
        default:
-               Log_Notice("VTerm", "TODO: Handle short escape codes");
+               //Log_Notice("VTerm", "TODO: Handle short escape codes");
+               {
+                       static volatile int tmp = 0;
+                       if(tmp == 0) {
+                               tmp = 1;
+                               Debug("VTerm: Unknown short 0x%x", c);
+                               tmp = 0;
+                       }
+               }
                break;
        }
        
index dc9d654..17143e8 100644 (file)
@@ -25,6 +25,8 @@
 //! General purpose event for short waits
 //! e.g. waiting for an IRQ in a Read() call
 #define THREAD_EVENT_SHORTWAIT 0x00000010
+//! Fired when a child process quits
+#define THREAD_EVENT_DEADCHILD 0x00000020
 
 #define THREAD_EVENT_USER1     0x10000000
 #define THREAD_EVENT_USER2     0x20000000
index 578fdcf..4845264 100644 (file)
@@ -71,7 +71,10 @@ struct sThread
        struct sProcess *Process;       //!< Thread Group / Process
        struct sThread  *Parent;        //!< Parent Thread
        char    *ThreadName;    //!< Name of thread
-       
+
+       struct sThread  *LastDeadChild; //!< Last child to die (will have the \a DeadChildren lock)
+       tMutex  DeadChildLock;  //!< Lock to prevent clobbering of \a LastDeadChild, acquired by child, released by parent
+
        // --- arch/proc.c's responsibility
        //! Kernel Stack Base
        tVAddr  KernelStack;
index 44c70f8..a130ac6 100644 (file)
@@ -143,6 +143,10 @@ typedef struct sFInfo
        tVFS_ACL        acls[]; //!< ACL buffer (size is passed in the \a MaxACLs argument to VFS_FInfo)
 } PACKED tFInfo;
 
+// --- fd_set --
+#include "../../../Usermode/Libraries/ld-acess.so_src/include_exp/acess/fd_set.h"
+
+#if 0
 /**
  * \brief fd_set for select()
  */
@@ -170,6 +174,7 @@ typedef struct
  * \param fdsetp       Set to modify
  */
 #define FD_ISSET(fd, fdsetp) ((fdsetp)->flags[(fd)/16]&(1<<((fd)%16)))
+#endif
 
 // === FUNCTIONS ===
 /**
index aab25a1..5149e02 100644 (file)
@@ -93,7 +93,7 @@ void Log_AddEvent(const char *Ident, int Level, const char *Format, va_list Args
        if( Level >= NUM_LOG_LEVELS )   return;
 
        va_copy(args_tmp, Args);
-       len = vsnprintf(NULL, 256, Format, args_tmp);
+       len = vsnprintf(NULL, 0, Format, args_tmp);
        
        #if USE_RING_BUFFER || !CACHE_MESSAGES
        {
index 8237423..b9d7a6f 100644 (file)
@@ -88,10 +88,11 @@ int Proc_GetMessage(Uint *Source, Uint BufSize, void *Buffer)
        void    *tmp;
        tThread *cur = Proc_GetCurThread();
 
-       ENTER("pSource pBuffer", Source, Buffer);
+       ENTER("pSource xBufSize pBuffer", Source, BufSize, Buffer);
        
        // Check if queue has any items
        if(!cur->Messages) {
+               LOG("empty queue");
                LEAVE('i', 0);
                return 0;
        }
index 1f2f798..635f69a 100644 (file)
@@ -29,8 +29,8 @@
 #define CHECK_STR_ARRAY(arr)   do {\
         int    i;\
        char    **tmp = (char**)arr; \
-       CHECK_NUM_NONULL( tmp, sizeof(char**) ); \
-       for(i=0;tmp[i];i++) { \
+       CHECK_NUM_NULLOK( tmp, sizeof(char**) ); \
+       for(i=0;tmp&&tmp[i];i++) { \
                CHECK_STR_NONULL( tmp[i] ); \
                CHECK_NUM_NONULL( &tmp[i+1], sizeof(char*) ); \
        }\
@@ -172,7 +172,8 @@ void SyscallHandler(tSyscallRegs *Regs)
                CHECK_STR_NONULL((const char*)Regs->Arg1);
                CHECK_STR_ARRAY((const char**)Regs->Arg2);
                CHECK_STR_ARRAY((const char**)Regs->Arg3);
-               CHECK_NUM_NULLOK((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
+               if( Regs->Arg4 > 0 )
+                       CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
                ret = Proc_SysSpawn(
                        (const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3,
                        Regs->Arg4, (int*)Regs->Arg5
index 9224db5..7938723 100644 (file)
@@ -48,6 +48,8 @@ void System_Init(char *CommandLine)
        if(Proc_Clone(CLONE_VM|CLONE_NOUSER) == 0)
        {
                const char      *args[] = {gsInitBinary, 0};
+               VFS_Open("/Devices/VTerm/0", VFS_OPENFLAG_READ|VFS_OPENFLAG_USER);      // 0: stdin
+               VFS_Open("/Devices/VTerm/0", VFS_OPENFLAG_WRITE|VFS_OPENFLAG_USER);     // 1: stdout
                Proc_Execve(gsInitBinary, args, &args[1], 0);
                Log_KernelPanic("System", "Unable to spawn init '%s'", gsInitBinary);
        }
index 92a7a57..a86eba0 100644 (file)
@@ -11,6 +11,7 @@
 #include <hal_proc.h>
 #include <semaphore.h>
 #include <vfs_threads.h>       // VFS Handle maintainence
+#include <events.h>
 
 // Configuration
 #define DEBUG_TRACE_TICKETS    0       // Trace ticket counts
@@ -442,9 +443,30 @@ tThread *Threads_CloneThreadZero(void)
 tTID Threads_WaitTID(int TID, int *Status)
 {      
        // Any Child
-       if(TID == -1) {
-               Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
-               return -1;
+       if(TID == -1)
+       {
+               Uint32 ev = Threads_WaitEvents(THREAD_EVENT_DEADCHILD);
+               tTID    ret = -1;
+               if( ev & THREAD_EVENT_DEADCHILD )
+               {
+                       // A child died, get the TID
+                       tThread *us = Proc_GetCurThread();
+                       ASSERT(us->LastDeadChild);
+                       ret = us->LastDeadChild->TID;
+                       // - Mark as dead (as opposed to undead)
+                       ASSERT(us->LastDeadChild->Status == THREAD_STAT_ZOMBIE);
+                       us->LastDeadChild->Status = THREAD_STAT_DEAD;
+                       // - Set return status
+                       if(Status)
+                               *Status = us->LastDeadChild->RetStatus;
+                       us->LastDeadChild = NULL;
+                       Mutex_Release(&us->DeadChildLock);
+               }
+               else
+               {
+                       Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
+               }
+               return ret;
        }
        
        // Any peer/child thread
@@ -460,33 +482,14 @@ tTID Threads_WaitTID(int TID, int *Status)
        }
        
        // Specific Thread
-       if(TID > 0) {
-               tThread *t = Threads_GetThread(TID);
+       if(TID > 0)
+       {
                tTID    ret;
-               
-               // Wait for the thread to die!
-               // TODO: Handle child also being suspended if wanted
-               while(t->Status != THREAD_STAT_ZOMBIE) {
-                       Threads_Sleep();
-                       Log_Debug("Threads", "%i waiting for %i, t->Status = %i",
-                               Threads_GetTID(), t->TID, t->Status);
-               }
-               
-               // Set return status
-               ret = t->TID;
-               switch(t->Status)
+               // NOTE: Race condition - Other child dies, desired child dies, first death is 'lost'
+               while( (ret = Threads_WaitTID(-1, Status)) != TID )
                {
-               case THREAD_STAT_ZOMBIE:
-                       // Kill the thread
-                       t->Status = THREAD_STAT_DEAD;
-                       // TODO: Child return value?
-                       if(Status)      *Status = t->RetStatus;
-                       // add to delete queue
-                       Threads_Delete( t );
-                       break;
-               default:
-                       if(Status)      *Status = -1;
-                       break;
+                       if( ret == -1 )
+                               break;
                }
                return ret;
        }
@@ -685,8 +688,10 @@ void Threads_Kill(tThread *Thread, int Status)
 
        Thread->Status = THREAD_STAT_ZOMBIE;
        SHORTREL( &glThreadListLock );
-       // TODO: Send something like SIGCHLD
-       Threads_Wake( Thread->Parent );
+       // TODO: It's possible that we could be timer-preempted here, should disable that... somehow
+       Mutex_Acquire( &Thread->Parent->DeadChildLock );        // released by parent
+       Thread->Parent->LastDeadChild = Thread;
+       Threads_PostEvent( Thread->Parent, THREAD_EVENT_DEADCHILD );
        
        Log("Thread %i went *hurk* (%i)", Thread->TID, Status);
        
index 1f3e379..cb4fae1 100644 (file)
@@ -196,7 +196,14 @@ void *VFS_SaveHandles(int NumFDs, int *FDs)
                tVFS_Handle     *h;
                if( FDs == NULL )
                        h = &gaUserHandles[i];
-               else {
+               else if( FDs[i] == -1 )
+               {
+                       Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (-1), ignorning", i);
+                       memset(&ret[i], 0, sizeof(tVFS_Handle));
+                       continue ;
+               }
+               else
+               {
                        h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1));
                        if(!h) {
                                Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i",
index 412cb1a..8bd0deb 100644 (file)
@@ -129,8 +129,8 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set
        tThread *thisthread = Proc_GetCurThread();
         int    ret;
        
-       ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout bIsKernel",
-               MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, IsKernel);
+       ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout xExtraEvents bIsKernel",
+               MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, ExtraEvents, IsKernel);
        
        // Notes: The idea is to make sure we only enter wait (Threads_WaitEvents)
        // if we are going to be woken up (either by an event at a later time,
@@ -140,6 +140,8 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set
        // or the semaphore is incremeneted (or both, but never none)
        
        // Register with nodes
+       if( ReadHandles )
+               LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
        ret  = VFS_int_Select_Register(thisthread, MaxHandle, ReadHandles, 0, IsKernel);
        ret += VFS_int_Select_Register(thisthread, MaxHandle, WriteHandles, 1, IsKernel);
        ret += VFS_int_Select_Register(thisthread, MaxHandle, ErrHandles, 2, IsKernel);
@@ -149,9 +151,11 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set
        // If there were events waiting, de-register and return
        if( ret > 0 )
        {
+               LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
                ret  = VFS_int_Select_Deregister(thisthread, MaxHandle, ReadHandles, 0, IsKernel);
                ret += VFS_int_Select_Deregister(thisthread, MaxHandle, WriteHandles, 1, IsKernel);
                ret += VFS_int_Select_Deregister(thisthread, MaxHandle, ErrHandles, 2, IsKernel);
+               LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
                LEAVE('i', ret);
                return ret;
        }
@@ -306,8 +310,10 @@ int VFS_int_Select_Register(tThread *Thread, int MaxHandle, fd_set *Handles, int
                }
                
                // Check for the flag
-               if( !!*flag == !!wantedFlagValue )
+               if( !!*flag == !!wantedFlagValue ) {
+                       LOG(" %i == want %i", !!*flag, !!wantedFlagValue);
                        numFlagged ++;
+               }
        }
        
        LEAVE('i', numFlagged);
@@ -348,8 +354,6 @@ int VFS_int_Select_Deregister(tThread *Thread, int MaxHandle, fd_set *Handles, i
                        continue;
                }
        
-               // Get the type of the listen
-       
                // Get the type of the listen
                if( VFS_int_Select_GetType(Type, handle->Node, &list, &flag, &wantedFlagValue, NULL) ) {
                        LEAVE('i', 0);
@@ -362,6 +366,8 @@ int VFS_int_Select_Deregister(tThread *Thread, int MaxHandle, fd_set *Handles, i
                // Check for the flag
                if( !!*flag == !!wantedFlagValue ) {
                        numFlagged ++;
+                       LOG(" %i == want %i", !!*flag, !!wantedFlagValue);
+                       FD_SET(i, Handles);
                }
                else {
                        FD_CLR(i, Handles);
index 5988ee7..50e76d3 100644 (file)
@@ -82,6 +82,7 @@ Uint  *gBGA_Framebuffer;
 const tBGA_Mode        *gpBGA_CurrentMode;\r
 const tBGA_Mode        gBGA_Modes[] = {\r
        {640,480,32, 640*480*4},\r
+       {800,480,32, 800*480*4},        // Nice mode for VM testing\r
        {800,600,32, 800*600*4},\r
        {1024,768,32, 1024*768*4}\r
 };\r
diff --git a/KernelLand/Modules/Display/RPi/main.c b/KernelLand/Modules/Display/RPi/main.c
new file mode 100644 (file)
index 0000000..a0df903
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * Acess2 Raspberry Pi (BCM2835)
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Driver core
+ *
+ * http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/screen01.html
+ */
+#define DEBUG  0
+#define VERSION        ((0<<8)|1)
+#include <acess.h>
+#include <errno.h>
+#include <modules.h>
+#include <vfs.h>
+#include <fs_devfs.h>
+#include <drv_pci.h>
+#include <api_drv_video.h>
+
+// === PROTOCOLS ===
+ int   RPiVid_Install(const char **Arguments);
+// - GPU Communication
+ int   RPiVid_int_MBoxCheck(Uint8 Box);
+Uint32 RPiVid_int_MBoxRecv(Uint8 Box);
+void   RPiVid_int_MBoxSend(Uint8 Box, Uint32 Message);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, RPiVid, RPiVid_Install, NULL, NULL);
+
+// === CODE ===
+int RPiVid_Install(const char **Arguments)
+{
+       return 0;
+}
+
+
+// --- GPU Comms ---
+int RPiVid_int_MBoxCheck(Uint8 Box)
+{
+       return 0;
+}
+
+Uint32 RPiVid_int_MBoxRecv(Uint8 Box)
+{
+       Uint32  val;
+       do {
+               while( gRPiVid_Mbox->Status & (1 << 30) )
+                       ;
+               val = gRPiVid_Mbox->Read;
+       } while( (val & 0xF) != Box );
+       
+       return 0;
+}
+
+void RPiVid_int_MBoxSend(Uint8 Box, Uint32 Message)
+{
+       while( gRPiVid_Mbox.Status & (1 << 31) )
+               ;
+       gRPiVid_Mbox.Write = (Message << 4) | (Box & 0xF);
+}
+
index 5aa0e65..5758f99 100644 (file)
@@ -13,4 +13,8 @@ LDFLAGS += @files.$(ARCH).c.ldopts
 files.$(ARCH).c: GenerateInitRD.php files.lst
        ARCH=$(ARCH) ACESSDIR=$(ACESSDIR) php GenerateInitRD.php files.lst $@ [email protected] [email protected]
 
+# Override default install method, because the floppy is small :)
+install:
+       true
+
 -include files.$(ARCH).c.dep
index ccbbe0c..5b17070 100644 (file)
@@ -13,6 +13,7 @@ Dir "Bin" {
        File "ping" "__BIN__/Bin/ping"
        File "telnet" "__BIN__/Bin/telnet"
        File "irc" "__BIN__/Bin/irc"
+       File "bomb" "__BIN__/Bin/bomb"
        File "dhcpc" "__BIN__/SBin/dhcpc"
 }
 Dir "Libs" {
@@ -26,9 +27,10 @@ Dir "Libs" {
        File "libaxwin3.so" "__BIN__/Libs/libaxwin3.so"
        File "libposix.so" "__BIN__/Libs/libposix.so"
        File "libpsocket.so" "__BIN__/Libs/libpsocket.so"
+       File "libunicode.so" "__BIN__/Libs/libunicode.so"
 }
 Dir "Conf" {
-       File "BootConf.cfg" "__FS__/Conf/BootConf.cfg"
+       File "inittab" "__FS__/Conf/inittab"
 }
 Dir "Apps" {
        Dir "AxWin" {
@@ -36,6 +38,7 @@ Dir "Apps" {
                        File "AxWinWM" "__BIN__/Apps/AxWin/3.0/AxWinWM"
                        File "AxWinUI" "__BIN__/Apps/AxWin/3.0/AxWinUI"
                        File "ate" "__BIN__/Apps/AxWin/3.0/ate"
+                       File "terminal" "__BIN__/Apps/AxWin/3.0/terminal"
                        File "AcessLogoSmall.sif" "__SRC__/Usermode/Applications/axwin3_src/AcessLogoSmall.sif"
                }
        }
index 1d80569..ae3806b 100644 (file)
@@ -268,7 +268,7 @@ size_t UDP_Channel_Write(tVFS_Node *Node, off_t Offset, size_t Length, const voi
 
        UDP_SendPacketTo(chan, ep->AddrType, &ep->Addr, ep->Port, data, (size_t)Length - ofs);
        
-       return 0;
+       return Length;
 }
 
 /**
index f9f4d25..9bdbafb 100644 (file)
@@ -80,11 +80,9 @@ int Rhine2_Install(char **Options)
 {
         int    id = -1;
         int    i = 0;
-//     Uint16  base;
        tCard   *card;
        
        giRhine2_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID);
-       Log_Debug("Rhine2", "giRhine2_CardCount = %i", giRhine2_CardCount);
        if( giRhine2_CardCount == 0 )   return MODULE_ERR_NOTNEEDED;
        
        gaRhine2_Cards = calloc( giRhine2_CardCount, sizeof(tCard) );
index f6290d9..90cff7f 100644 (file)
@@ -115,7 +115,7 @@ int FDD_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
 {
        if(Pos < 0 || Pos > MAX_DISKS )
                return -ENOENT;
-       if(gaFDD_Disks[Pos].bValid)
+       if(!gaFDD_Disks[Pos].bValid)
                return 1;
        
        Dest[0] = '0' + Pos;
index 32f1ffb..c2ef59f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -12,12 +12,12 @@ SUBMAKE = $(MAKE) --no-print-directory
 
 USRLIBS := crt0.o acess.ld ld-acess.so libc.so libposix.so
 USRLIBS += libreadline.so libnet.so liburi.so libpsocket.so
-USRLIBS += libimage_sif.so
+USRLIBS += libimage_sif.so libunicode.so
 
 USRAPPS := init login CLIShell cat ls mount
 USRAPPS += bomb lspci
 USRAPPS += ip dhcpclient ping telnet irc wget telnetd
-USRAPPS += axwin3 gui_ate
+USRAPPS += axwin3 gui_ate gui_shell
 
 ALL_DYNMODS = $(addprefix all-,$(DYNMODS))
 ALL_MODULES := $(addprefix all-,$(MODULES))
diff --git a/Notes/3D.txt b/Notes/3D.txt
new file mode 100644 (file)
index 0000000..a530e3c
--- /dev/null
@@ -0,0 +1,8 @@
+GL control channel:
+  App -> GUI -> VTerm -> Driver
+- App creates 3D window
+- GUI passes X,Y WxH to VTerm (and can issue resize notices upwards)
+- VTerm passes to driver (and can disable display of local regions when VT switch)
+
+Allocates command ring buffer for libgl
+
index a3183d3..477c476 100755 (executable)
@@ -55,6 +55,16 @@ while [[ $# -gt 0 ]]; do
        -l*|-L*)
                _libs=$_libs" $1"
                ;;
+       -v|--version|-V)
+               _verarg=$_verarg" $1"
+               ;;
+       --inv=ld)
+               _actas=ld
+               ;;
+       -print-prog-name=ld)
+               echo $0 --inv=ld
+               exit 0
+               ;;
        *)
                _miscargs=$_miscargs" $1"
                ;;
@@ -63,7 +73,7 @@ while [[ $# -gt 0 ]]; do
 done
 
 run() {
-#      echo --- $*
+       #echo --- $*
        $*
        return $?
 }
@@ -75,6 +85,11 @@ rm $cfgfile
 
 #echo "_compile = $_compile, _preproc = $_preproc"
 
+if [[ "x$_actas" == "xld" ]]; then
+       run $_LD $LDFLAGS $_ldflags $_outfile $_miscargs $LIBGCC_PATH $_libs
+       exit $?
+fi
+
 if [[ $_preproc -eq 1 ]]; then
        run $_CC -E $CFLAGS $_cflags $_miscargs $_outfile
 elif [[ $_makedep -eq 1 ]]; then
@@ -84,8 +99,10 @@ elif [[ $_compile -eq 1 ]]; then
 elif echo " $_miscargs" | grep '\.c' >/dev/null; then
        tmpout=`mktemp acess_gccproxy.XXXXXXXXXX.o --tmpdir`
        run $_CC $CFLAGS $_cflags $_miscargs -c -o $tmpout
-       run $_LD $LDFLAGS $_ldflags $_libs $tmpout $_outfile -lgcc $_libs
+       run $_LD $LDFLAGS $_ldflags $_libs $tmpout $_outfile $LIBGCC_PATH $_libs
+       _rv=$?
        rm $tmpout
+       exit $_rv
 else
        run $_LD$_ldflags $_miscargs $_outfile $LDFLAGS  $_libs
 fi
index e8b5834..a098614 100644 (file)
@@ -111,14 +111,16 @@ void create_sidebar(void)
 
 void mainmenu_app_textedit(void *unused)
 {
-       const char      *args[] = {"ate",NULL};
 //     _SysDebug("TODO: Launch text editor");
+       const char      *args[] = {"ate",NULL};
        _SysSpawn("/Acess/Apps/AxWin/3.0/ate", args, (const char **)gEnvion, 0, NULL, NULL);
 }
 
 void mainmenu_app_terminal(void *unused)
 {
-       _SysDebug("TODO: Launch terminal emulator");
+       _SysDebug("Launch terminal emulator");
+       const char      *args[] = {"terminal",NULL};
+       _SysSpawn("/Acess/Apps/AxWin/3.0/terminal", args, (const char **)gEnvion, 0, NULL, NULL);
 }
 
 void mainmenu_run_dialog(void *unused)
index 1d67450..1112ffe 100644 (file)
@@ -7,7 +7,7 @@ CFLAGS += -std=gnu99
 
 DIR := Apps/AxWin/3.0
 BIN := AxWinWM
-OBJ := main.o input.o video.o ipc.o image.o utf-8.o
+OBJ := main.o input.o video.o ipc.o image.o
 OBJ += wm.o wm_input.o wm_render.o wm_render_text.o wm_hotkeys.o
 OBJ += decorator.o
 OBJ += renderers/framebuffer.o
@@ -23,7 +23,7 @@ OBJ += renderers/widget/textinput.o
 OBJ += renderers/widget/spacer.o
 OBJ += renderers/widget/subwin.o
 
-LDFLAGS += -limage_sif -luri -lnet
+LDFLAGS += -limage_sif -luri -lnet -lunicode
 
 -include ../../Makefile.tpl
 
diff --git a/Usermode/Applications/axwin3_src/WM/include/utf8.h b/Usermode/Applications/axwin3_src/WM/include/utf8.h
deleted file mode 100644 (file)
index 3ecaeb0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Acess2 GUI (AxWin) Version 3
- * - By John Hodge (thePowersGang)
- *
- * utf8.h
- * - UTF-8 Parsing header
- */
-#ifndef _UTF8_H_
-#define _UTF8_H_
-
-#include <stdint.h>
-
-extern int     ReadUTF8(const char *Input, uint32_t *Val);
-extern int     ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val);
-extern int     WriteUTF8(char *buf, uint32_t Val);
-
-#endif
-
index 5b600ee..7874335 100644 (file)
@@ -461,8 +461,8 @@ int IPC_Msg_FocusWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
        ASSERT(Msg->ID == IPCMSG_FOCUSWINDOW);
        
        // Don't allow the focus to be changed unless the client has the focus
-       if(!gpWM_FocusedWindow) return 1;
-       if(gpWM_FocusedWindow->Client != Client)        return 1;
+//     if(!gpWM_FocusedWindow) return 1;
+//     if(gpWM_FocusedWindow->Client != Client)        return 1;
 
        win = IPC_int_GetWindow(Client, Msg->Window);
        if(!win)        return 1;
index 7d2d391..9db1c15 100644 (file)
@@ -66,10 +66,12 @@ int main(int argc, char *argv[])
        Renderer_RichText_Init();
        WM_Initialise();
 
-       // TODO: Config
+       // TODO: Move these to config
        uint32_t        keys[4];
        keys[0] = KEYSYM_LEFTGUI;       keys[1] = KEYSYM_r;
        WM_Hotkey_Register(2, keys, "Interface>Run");
+       keys[0] = KEYSYM_LEFTGUI;       keys[1] = KEYSYM_t;
+       WM_Hotkey_Register(2, keys, "Interface>Terminal");
        
        // Spawn interface root
        {
@@ -83,7 +85,7 @@ int main(int argc, char *argv[])
                sprintf(server_info, "AXWIN3_SERVER=%i", server_tid);
                // TODO: Does the client need FDs?
                 int    rv = _SysSpawn(csInterfaceApp, argv, envp, 0, NULL, NULL);
-               if( rv ) {
+               if( rv < 0 ) {
                        _SysDebug("_SysSpawn chucked a sad, rv=%i, errno=%i", rv, _errno);
                }
        }
index fc838cb..68a3f8c 100644 (file)
@@ -16,7 +16,6 @@ typedef struct
 {
        short   W, H;
        void    *Data;
-       char    _data[];
 } tFBBuffer;
 typedef struct
 {
@@ -162,7 +161,7 @@ int _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data)
        buf = malloc(sizeof(tFBBuffer) + msg->W * msg->H * 4);
        buf->W = msg->W;
        buf->H = msg->H;
-       buf->Data = buf->_data;
+       buf->Data = buf + 1;
        
        info->Buffers[msg->Buffer] = buf;
        
index 28be1ae..c62dd7f 100644 (file)
@@ -224,6 +224,27 @@ void Renderer_RichText_Redraw(tWindow *Window)
                Window->W, (info->DispLines-i)*info->LineHeight,
                info->DefaultBG
                );
+
+       // HACK!
+       info->DispCols = Window->W / 8; 
+
+       // TODO: Text cursor
+       _SysDebug("Cursor at %i,%i", info->CursorCol, info->CursorRow);
+       _SysDebug(" Range [%i+%i],[%i+%i]", info->FirstVisRow, info->DispLines, info->FirstVisCol, info->DispCols);
+       if( info->CursorRow >= info->FirstVisRow && info->CursorRow < info->FirstVisRow + info->DispLines )
+       {
+               if( info->CursorCol >= info->FirstVisCol && info->CursorCol < info->FirstVisCol + info->DispCols )
+               {
+                       // TODO: Kill hardcoded 8 with cached text distance
+                       WM_Render_FillRect(Window,
+                               (info->CursorCol - info->FirstVisCol) * 8,
+                               (info->CursorRow - info->FirstVisRow) * info->LineHeight,
+                               1,
+                               info->LineHeight,
+                               info->DefaultFG
+                               );
+               }
+       }
 }
 
 int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data)
@@ -241,6 +262,10 @@ int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void
        case _ATTR_DEFFG:
                info->DefaultFG = msg->Value;
                break;
+       case _ATTR_CURSORPOS:
+               info->CursorRow = msg->Value >> 12;
+               info->CursorCol = msg->Value & 0xFFF;
+               break;
        case _ATTR_SCROLL:
                // TODO: Set scroll flag
                break;
@@ -298,7 +323,9 @@ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const voi
        }
        line->ByteLength = Len - sizeof(*msg);
        memcpy(line->Data, msg->LineData, Len - sizeof(*msg));
-       
+
+       WM_Invalidate( Window );
+
        return  0;
 }
 
@@ -312,6 +339,10 @@ int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const voi
                if(Len < sizeof(*msg))  return -1;
                info->DispLines = msg->H / info->LineHeight;
                return 1; }
+       case WNDMSG_KEYDOWN:
+       case WNDMSG_KEYUP:
+       case WNDMSG_KEYFIRE:
+               return 1;
        }
        return 0;
 }
index 6d34a8e..fc7e107 100644 (file)
@@ -10,7 +10,7 @@
 #include <common.h>
 #include "./common.h"
 #include "./colours.h"
-#include <utf8.h>
+#include <unicode.h>
 #include <string.h>
 
 // TODO: Include a proper keysym header
diff --git a/Usermode/Applications/axwin3_src/WM/utf-8.c b/Usermode/Applications/axwin3_src/WM/utf-8.c
deleted file mode 100644 (file)
index 93e0318..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Acess2 GUI (AxWin) Version 3
- * - By John Hodge (thePowersGang)
- *
- * utf-8.c
- * - UTF-8 Parsing code
- */
-#include <stdint.h>
-#include <utf8.h>
-
-/**
- * \brief Read a UTF-8 character from a string
- * \param Input        Source UTF-8 encoded string
- * \param Val  Destination for read codepoint
- * \return Number of bytes read/used
- */
-int ReadUTF8(const char *Input, uint32_t *Val)
-{
-       const uint8_t   *str = (const uint8_t *)Input;
-       *Val = 0xFFFD;  // Assume invalid character
-       
-       // ASCII
-       if( !(*str & 0x80) ) {
-               *Val = *str;
-               return 1;
-       }
-       
-       // Middle of a sequence
-       if( (*str & 0xC0) == 0x80 ) {
-               return 1;
-       }
-       
-       // Two Byte
-       if( (*str & 0xE0) == 0xC0 ) {
-               *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F);  // Lower 6 Bits
-               return 2;
-       }
-       
-       // Three Byte
-       if( (*str & 0xF0) == 0xE0 ) {
-               *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F);  // Lower 6 Bits
-               return 3;
-       }
-       
-       // Four Byte
-       if( (*str & 0xF8) == 0xF0 ) {
-               *Val = (*str & 0x07) << 18;     // Upper 3 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
-               str ++;
-               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
-               *Val |= (*str & 0x3F);  // Lower 6 Bits
-               return 4;
-       }
-       
-       // UTF-8 Doesn't support more than four bytes
-       return 4;
-}
-
-/**
- * \brief Get the UTF-8 character before the 
- * \
- */
-int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val)
-{
-        int    len = 0;
-       
-       // Scan backwards for the beginning of the character
-       while( Offset > 0 && (Base[Offset--] & 0xC0) == 0x80 )
-               len ++;
-       // Invalid string (no beginning)
-       if(Offset == 0 && (Base[Offset] & 0xC0) == 0x80 )
-               return len;
-       
-       len ++; // First character
-       if( ReadUTF8(Base+Offset, Val) != len ) {
-               *Val = 0xFFFD;
-       }
-       return len;
-}
-
-/**
- * \brief Write a UTF-8 character sequence to a string
- * \param buf  Destination buffer (must have at least 4 bytes available)
- * \param Val  Unicode codepoint to write
- * \return Number of bytes written
- * \note Does not NULL terminate the string in \a buf
- */
-int WriteUTF8(char *buf, uint32_t Val)
-{
-       uint8_t *str = (void*)buf;
-       
-       // ASCII
-       if( Val < 128 ) {
-               if(str) {
-                       *str = Val;
-               }
-               return 1;
-       }
-       
-       // Two Byte
-       if( Val < 0x8000 ) {
-               if(str) {
-                       *str = 0xC0 | (Val >> 6);
-                       str ++;
-                       *str = 0x80 | (Val & 0x3F);
-               }
-               return 2;
-       }
-       
-       // Three Byte
-       if( Val < 0x10000 ) {
-               if(str) {
-                       *str = 0xE0 | (Val >> 12);
-                       str ++;
-                       *str = 0x80 | ((Val >> 6) & 0x3F);
-                       str ++;
-                       *str = 0x80 | (Val & 0x3F);
-               }
-               return 3;
-       }
-       
-       // Four Byte
-       if( Val < 0x110000 ) {
-               if(str) {
-                       *str = 0xF0 | (Val >> 18);
-                       str ++;
-                       *str = 0x80 | ((Val >> 12) & 0x3F);
-                       str ++;
-                       *str = 0x80 | ((Val >> 6) & 0x3F);
-                       str ++;
-                       *str = 0x80 | (Val & 0x3F);
-               }
-               return 4;
-       }
-       
-       // UTF-8 Doesn't support more than four bytes
-       return 0;
-}
-
index 60f2155..1b9ffab 100644 (file)
@@ -87,7 +87,7 @@ void Video_Update(void)
 
        _SysDebug("Video_Update - Updating lines %i to %i (0x%x+0x%x px)",
                giVideo_FirstDirtyLine, giVideo_LastDirtyLine, ofs, size);
-       _SysSeek(giTerminalFD, ofs*4, 1);
+       _SysSeek(giTerminalFD, ofs*4, SEEK_SET);
        _SysDebug("Video_Update - Sending FD %i %p 0x%x", giTerminalFD, gpScreenBuffer+ofs, size*4);
        _SysWrite(giTerminalFD, gpScreenBuffer+ofs, size*4);
        _SysDebug("Video_Update - Done");
index f9592db..8886af1 100644 (file)
@@ -173,6 +173,8 @@ void WM_FocusWindow(tWindow *Destination)
 {
        struct sWndMsg_Bool     _msg;
        
+       _SysDebug("WM_FocusWindow(%p)", Destination);
+
        if( gpWM_FocusedWindow == Destination )
                return ;
        if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
index 6ad72be..8258531 100644 (file)
@@ -8,7 +8,7 @@
 #include <common.h>
 #include <wm_internals.h>
 #include <stdlib.h>
-#include <utf8.h>
+#include <unicode.h>
 #include <limits.h>    // INT_MAX
 
 // === TYPES ===
index fd1cf39..9fed544 100644 (file)
@@ -10,6 +10,7 @@
 #include "include/internal.h"
 #include <richtext_messages.h>
 #include <string.h>
+#include <wm_messages.h>
 //#include <alloca.h>
 
 // === TYPES ===
@@ -23,6 +24,16 @@ typedef struct sRichText_Window
 // === CODE ===
 int AxWin3_RichText_MessageHandler(tHWND Window, int MessageID, int Size, void *Data)
 {
+       tRichText_Window        *info = AxWin3_int_GetDataPtr(Window);
+       struct sWndMsg_KeyAction        *keyaction = Data;
+       _SysDebug("MessageID = %i", MessageID);
+       switch(MessageID)
+       {
+       case WNDMSG_KEYFIRE:
+               if(Size < sizeof(*keyaction))   return -1;
+               info->KeyCallback(Window, 2, keyaction->KeySym, keyaction->UCS32);
+               return 1;
+       }
        return 0;
 }
 
index b9b2814..73e85d8 100644 (file)
@@ -528,7 +528,7 @@ void SetAddress(tInterface *Iface, void *Addr, void *Mask, void *Router)
        _SysIOCtl(Iface->IfaceFD, 6, Addr);
        _SysIOCtl(Iface->IfaceFD, 7, &mask_bits);
 
-       if( Router );
+       if( Router )
        {
                uint8_t *addr = Router;
                _SysDebug("Router %i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
index 7ccfff4..a38f135 100644 (file)
@@ -2,9 +2,9 @@
 
 -include ../Makefile.cfg
 
-LDFLAGS += -laxwin3
+LDFLAGS += -laxwin3 -lunicode
 
-OBJ = main.o
+OBJ = main.o vt100.o display.o
 BIN = terminal
 DIR := Apps/AxWin/3.0
 
diff --git a/Usermode/Applications/gui_shell_src/display.c b/Usermode/Applications/gui_shell_src/display.c
new file mode 100644 (file)
index 0000000..1665e44
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * display.c
+ * - Abstract display manipulation methods
+ */
+#include "include/display.h"
+#include <acess/sys.h> // _SysDebug
+#include <stdlib.h>    // exit
+#include <string.h>
+#include <unicode.h>
+#include <stdio.h>
+#include <axwin3/axwin.h>
+#include <axwin3/richtext.h>
+
+#define UNIMPLIMENTED()        do{_SysDebug("UNIMPLIMENTED %s", __func__); exit(-1);}while(0)
+
+// === EXTERN ==
+extern tHWND   gMainWindow;
+
+// === GLOBALS ===
+ int   giDisplayCols;
+ int   giDisplayLines;
+ int   giDisplayTotalLines;
+ int   giDisplayBufSize;
+ int   giCurrentLine;
+ int   giCurrentLinePos;       // byte offset, not column
+ int   giCurrentCol;
+ int   giFirstDispLine;        // First displayed line
+ int   giFirstLine;    // Ring buffer start
+char   **gasDisplayLines;
+ int   *gaiDisplayLineSizes;
+char   *gabDisplayLinesDirty;
+
+// === CODE ===
+void Display_Init(int Cols, int Lines, int ExtraScrollbackLines)
+{
+       giDisplayCols = Cols;
+       giDisplayLines = Lines;
+       giDisplayTotalLines = Lines + ExtraScrollbackLines;
+       gasDisplayLines = calloc( sizeof(char*), (Lines + ExtraScrollbackLines) );
+       gaiDisplayLineSizes = calloc( sizeof(int), (Lines + ExtraScrollbackLines) );
+       gabDisplayLinesDirty = calloc( sizeof(char), (Lines + ExtraScrollbackLines) );
+       
+       AxWin3_RichText_SetLineCount(gMainWindow, Lines+ExtraScrollbackLines);
+       AxWin3_RichText_SetCursorType(gMainWindow, 1);  // TODO: enum
+}
+
+void Display_int_PushString(int Length, const char *Text)
+{
+       _SysDebug("Line %i += %i '%*C'", giCurrentLine, Length, Length, Text);
+       if( !gasDisplayLines[giCurrentLine] || giCurrentLinePos + Length >= gaiDisplayLineSizes[giCurrentLine] )
+       {
+                int    reqsize = giCurrentLinePos + Length;
+               gaiDisplayLineSizes[giCurrentLine] = (reqsize + 32-1) & ~(32-1);
+               void *tmp = realloc(gasDisplayLines[giCurrentLine], gaiDisplayLineSizes[giCurrentLine]);
+               if( !tmp )      perror("Display_AddText - realloc");
+               gasDisplayLines[giCurrentLine] = tmp;
+       }
+
+       memcpy(gasDisplayLines[giCurrentLine]+giCurrentLinePos, Text, Length);
+       gabDisplayLinesDirty[giCurrentLine] = 1;
+       gasDisplayLines[giCurrentLine][giCurrentLinePos+Length] = 0;
+       giCurrentLinePos += Length;
+       
+}
+
+void Display_AddText(int Length, const char *UTF8Text)
+{
+       _SysDebug("%i '%.*s'", Length, Length, UTF8Text);
+       // Copy as many characters (not bytes, have to trim off the last char) as we can to the current line
+       // - then roll over to the next line
+       while( Length > 0 )
+       {
+                int    space = giDisplayCols - giCurrentCol;
+                int    bytes = 0;
+               while( space && bytes < Length )
+               {
+                       uint32_t        cp;
+                       bytes += ReadUTF8(UTF8Text+bytes, &cp);
+                       if( Unicode_IsPrinting(cp) ) {
+                               space --;
+                               giCurrentCol ++;
+                       }
+               }
+       
+               Display_int_PushString(bytes, UTF8Text);
+
+               UTF8Text += bytes;
+               _SysDebug("Length(%i) -= bytes(%i)", Length, bytes);
+               Length -= bytes;
+               if( Length != 0 )
+               {
+                       // Next line
+                       giCurrentLinePos = 0;
+                       giCurrentCol = 0;
+                       giCurrentLine ++;
+               }
+       }
+}
+
+void Display_Newline(int bCarriageReturn)
+{
+       Display_Flush();
+
+       // Going down!
+       giCurrentLine ++;
+       if( giCurrentLine == giDisplayLines )
+               giCurrentLine = 0;
+       if( giCurrentLine == giFirstLine )
+       {
+               giFirstLine ++;
+               if(giFirstLine == giDisplayLines)
+                       giFirstLine = 0;
+       }
+       
+       if( bCarriageReturn ) {
+               giCurrentLinePos = 0;
+               giCurrentCol = 0;
+       }
+       else {
+               giCurrentLinePos = 0;
+                int    i = giCurrentCol;
+               if( !gasDisplayLines[giCurrentLine] )
+               {
+                       giCurrentCol = 0;
+                       while(i--)
+                               Display_AddText(1, " ");
+               }
+               else
+               {
+                       while( i -- )
+                       {
+                               uint32_t        cp;
+                               giCurrentLinePos += ReadUTF8(gasDisplayLines[giCurrentLine]+giCurrentLinePos, &cp);
+                               if( !Unicode_IsPrinting(cp) )
+                                       i ++;
+                       }
+               }
+       }
+}
+
+void Display_SetCursor(int Row, int Col)
+{
+       UNIMPLIMENTED();
+}
+
+void Display_MoveCursor(int RelRow, int RelCol)
+{
+       if( RelRow < 0 )
+       {
+               for( ; RelRow < 0; RelRow ++ )
+               {
+                       uint32_t        cp;
+                       int delta = ReadUTF8Rev(gasDisplayLines[giCurrentLine], giCurrentLinePos, &cp);
+                       if( !Unicode_IsPrinting(cp) )
+                               RelRow --;
+                       else
+                               giCurrentCol --;
+                       giCurrentLinePos -= delta;
+               }
+       }
+       else
+       {
+               UNIMPLIMENTED();
+       }
+}
+
+void Display_ClearLine(int Dir)        // 0: All, 1: Forward, -1: Reverse
+{
+       if( Dir == 0 )
+       {
+               // Completely clear line
+               if( gasDisplayLines[giCurrentLine] )
+                       free(gasDisplayLines[giCurrentLine]);
+               gasDisplayLines[giCurrentLine] = NULL;
+               gabDisplayLinesDirty[giCurrentLine] = 1;
+       }
+       else if( Dir == 1 )
+       {
+               // Forward clear (truncate)
+       }
+       else if( Dir == -1 )
+       {
+               // Reverse clear (replace with spaces)
+       }
+       else
+       {
+               // BUGCHECK
+       }
+}
+
+void Display_ClearLines(int Dir)       // 0: All, 1: Forward, -1: Reverse
+{
+       if( Dir == 0 )
+       {
+               // Push giDisplayLines worth of empty lines
+               // Move cursor back up by giDisplayLines
+       }
+       else if( Dir == 1 )
+       {
+               // Push (giDisplayLines - (giCurrentLine-giFirstDispLine)) and reverse
+       }
+       else if( Dir == -1 )
+       {
+               // Reverse clear (replace with spaces)
+       }
+       else
+       {
+               // BUGCHECK
+       }
+}
+
+void Display_SetForeground(uint32_t RGB)
+{
+       char    buf[7+1];
+       sprintf(buf, "\1%06x", RGB&0xFFFFFF);
+       Display_int_PushString(7, buf);
+}
+
+void Display_SetBackground(uint32_t RGB)
+{
+       char    buf[7+1];
+       sprintf(buf, "\2%06x", RGB&0xFFFFFF);
+       Display_int_PushString(7, buf);
+}
+
+void Display_Flush(void)
+{
+        int    i;
+       for( i = 0; i < giDisplayCols; i ++ )
+       {
+                int    line = (giFirstLine + i) % giDisplayTotalLines;
+               if( !gabDisplayLinesDirty[line] )
+                       continue;
+               _SysDebug("Line %i+%i '%s'", giFirstLine, i, gasDisplayLines[line]);
+               AxWin3_RichText_SendLine(gMainWindow, giFirstLine + i, gasDisplayLines[line] );
+               gabDisplayLinesDirty[line] = 0;
+       }
+       
+       // force redraw?
+       AxWin3_RichText_SetCursorPos(gMainWindow, giCurrentLine, giCurrentCol);
+}
+
+void Display_ShowAltBuffer(int AltBufEnabled)
+{
+       UNIMPLIMENTED();
+}
+
index 80bc69c..4feaf35 100644 (file)
@@ -3,11 +3,15 @@
  * - By John Hodge (thePowersGang)
  *
  * display.h
- * - RichText Termianl Translation
+ * - RichText terminal translation
  */
 #ifndef _DISPLAY_H_
 #define _DISPLAY_H_
 
+#include <stdint.h>
+
+extern void    Display_Init(int Cols, int Lines, int ExtraScrollbackLines);
+
 extern void    Display_AddText(int Length, const char *UTF8Text);
 extern void    Display_Newline(int bCarriageReturn);
 extern void    Display_SetCursor(int Row, int Col);
@@ -16,6 +20,16 @@ extern void  Display_ClearLine(int Dir);     // 0: All, 1: Forward, -1: Reverse
 extern void    Display_ClearLines(int Dir);    // 0: All, 1: Forward, -1: Reverse
 extern void    Display_SetForeground(uint32_t RGB);
 extern void    Display_SetBackground(uint32_t RGB);
+/**
+ * \brief Ensure that recent updates are flushed to the server
+ * \note Called at the end of an "input" buffer
+ */
+extern void    Display_Flush(void);
+
+/**
+ * \brief Switch the display to the alternate buffer (no scrollback)
+ */
+extern void    Display_ShowAltBuffer(int AltBufEnabled);
 
 #endif
 
index c7aac85..4b82d0e 100644 (file)
@@ -8,14 +8,19 @@
 #include <axwin3/axwin.h>
 #include <axwin3/menu.h>
 #include <axwin3/richtext.h>
+#include <axwin3/keysyms.h>
 #include <stdio.h>
+#include <acess/sys.h>
 #include "include/display.h"
 #include "include/vt100.h"
+#include <string.h>
+#include <unicode.h>
 
 // === PROTOTYPES ===
  int   main(int argc, char *argv[], const char **envp);
  int   Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
  int   Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
+void   Term_HandleOutput(int Len, const char *Buf);
 
 // === GLOBALS ===
 tHWND  gMainWindow;
@@ -52,22 +57,30 @@ int main(int argc, char *argv[], const char **envp)
        // <testing>
        AxWin3_RichText_SetLineCount(gMainWindow, 3);
        AxWin3_RichText_SendLine(gMainWindow, 0, "First line!");
-       AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \x01""ff0000A red");
+       AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \1ff0000A red");
        // </testing>
 
-       AxWin3_ResizeWindow(gMainWindow, 600, 400);
-       AxWin3_MoveWindow(gMainWindow, 50, 50);
+       Display_Init(80, 25, 100);
+       AxWin3_ResizeWindow(gMainWindow, 80*8, 25*16);
+       AxWin3_MoveWindow(gMainWindow, 20, 50);
        AxWin3_ShowWindow(gMainWindow, 1);
        AxWin3_FocusWindow(gMainWindow);
 
        // Spawn shell
-       giChildStdout = open("/Devices/FIFO/anon", O_RDWR);
-       giChildStdin = open("/Devices/FIFO/anon", O_RDWR);
+       giChildStdin = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
+       giChildStdout = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
+       if( giChildStdout == -1 || giChildStdin == -1 ) {
+               perror("Oh, fsck");
+               _SysDebug("out,in = %i,%i", giChildStdout, giChildStdin);
+               return -1;
+       }
 
        {
                 int    fds[] = {giChildStdin, giChildStdout, giChildStdout};
                const char      *argv[] = {"CLIShell", NULL};
-               _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+               int pid = _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+               if( pid < 0 )
+                       _SysDebug("ERROR: Shell spawn failed");
        }
 
        // Main loop
@@ -81,9 +94,10 @@ int main(int argc, char *argv[], const char **envp)
                
                if( FD_ISSET(giChildStdout, &fds) )
                {
+                       _SysDebug("Activity on child stdout");
                        // Read and update screen
                        char    buf[32];
-                       int len = read(giChildStdout, buf, sizeof(buf));
+                       int len = _SysRead(giChildStdout, buf, sizeof(buf));
                        if( len <= 0 )  break;
                        
                        Term_HandleOutput(len, buf);
@@ -101,35 +115,51 @@ int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translat
        #define _bitset(var,bit,set) do{if(set)var|=1<<(bit);else var&=1<<(bit);}while(0)
        switch(KeySym)
        {
-       case KEY_LCTRL:
-               _bitset(ctrl_state, 0, bPress);
+       case KEYSYM_LEFTCTRL:
+               _bitset(ctrl_state, 0, bPress!=0);
                return 0;
-       case KEY_RCTRL:
-               _bitset(ctrl_state, 0, bPress);
+       case KEYSYM_RIGHTCTRL:
+               _bitset(ctrl_state, 1, bPress!=0);
                return 0;
        }
        #undef _bitset
 
        // Handle shortcuts
        // - Ctrl-A -- Ctrl-Z
-       if( ctrl_state && KeySym >= KEY_a && KeySym <= KEY_z )
+       if( ctrl_state && KeySym >= KEYSYM_a && KeySym <= KEYSYM_z )
        {
-               Translated = KeySym - KEY_a + 1;
+               Translated = KeySym - KEYSYM_a + 1;
        }
 
-       if( Translated )
+       // == 2 :: FIRE
+       if( bPress == 2 )
        {
-               // Encode and send
+               if( Translated )
+               {
+                       char    buf[6];
+                        int    len;
+                       
+                       // Encode and send
+                       len = WriteUTF8(buf, Translated);
+                       
+                       _SysDebug("Keystroke translated to '%.*s'", len, buf);
+                       _SysWrite(giChildStdin, buf, len);
+                       
+                       return 0;
+               }
                
-               return 0;
-       }
-       
-       // No translation, look for escape sequences to send
-       switch(KeySym)
-       {
-       case KEY_LEFTARROW:
-       //      str = "\x1b[D";
-               break;
+               // No translation, look for escape sequences to send
+               const char *str = NULL;
+               switch(KeySym)
+               {
+               case KEYSYM_LEFTARROW:
+                       str = "\x1b[D";
+                       break;
+               }
+               if( str )
+               {
+                       _SysWrite(giChildStdin, str, strlen(str));
+               }
        }
        return 0;
 }
@@ -153,8 +183,10 @@ void Term_HandleOutput(int Len, const char *Buf)
                        Display_AddText(-esc_len, Buf + ofs);
                        esc_len = -esc_len;
                }
-               Len -= esc_len;
                ofs += esc_len;
+               _SysDebug("Len = %i, ofs = %i", Len, ofs);
        }
+       
+       Display_Flush();
 }
 
index 51c8016..2a87ca4 100644 (file)
@@ -2,42 +2,86 @@
  * Acess GUI Terminal
  * - By John Hodge (thePowersGang)
  *
- * main.c
- * - Core
+ * vt100.c
+ * - VT100/xterm Emulation
  */
 #include <string.h>
+#include <limits.h>
 #include "include/vt100.h"
 #include "include/display.h"
+#include <ctype.h>     // isalpha
+#include <acess/sys.h> // _SysDebug
+
+const uint32_t caVT100Colours[] = {
+       // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray
+       // Same again, but bright
+       0x000000, 0x770000, 0x007700, 0x777700, 0x000077, 0x770077, 0x007777, 0xAAAAAAA,
+       0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFFF
+};
+
+ int   Term_HandleVT100_Long(int Len, const char *Buf);
+
+static inline int min(int a, int b)
+{
+       return a < b ? a : b;
+}
 
 int Term_HandleVT100(int Len, const char *Buf)
 {
-       const int       max_length = 16;
-       static char     inc_buf[max_length]
+       #define MAX_VT100_ESCAPE_LEN    16
+       static char     inc_buf[MAX_VT100_ESCAPE_LEN];
        static int      inc_len = 0;
 
        if( inc_len > 0 || *Buf == '\x1b' )
        {
-               memcpy(inc_buf + inc_len, Buf, min(max_length - inc_len, Len));
                // Handle VT100 (like) escape sequence
-               
-               inc_len = 0;
-               return 1;
+                int    new_bytes = min(MAX_VT100_ESCAPE_LEN - inc_len, Len);
+                int    ret = 0, old_inc_len = inc_len;
+               memcpy(inc_buf + inc_len, Buf, new_bytes);
+
+               inc_len += new_bytes;
+
+               if( inc_len <= 1 )
+                       return 1;       // Skip 1 character (the '\x1b')
+
+               switch(inc_buf[1])
+               {
+               case '[':       // Multibyte, funtime starts    
+                       ret = Term_HandleVT100_Long(inc_len-2, inc_buf+2);
+                       if( ret > 0 ) {
+                               ret += 2;
+                       }
+                       break;
+               default:
+                       ret = 2;
+                       break;
+               }       
+
+               if( ret != 0 ) {
+                       inc_len = 0;
+                       ret -= old_inc_len;     // counter cached bytes
+               }
+               return ret;
        }
 
        switch( *Buf )
        {
        case '\b':
                // TODO: Backspace
+               Display_MoveCursor(-1, 0);
+               Display_AddText(1, " ");
+               Display_MoveCursor(-1, 0);
                return 1;
        case '\t':
-               // TODO: tab
+               // TODO: tab (get current cursor pos, space until multiple of 8)
                return 1;
        case '\n':
                Display_Newline(1);
                return 1;
        case '\r':
                // TODO: Carriage return
-               return ;
+               Display_MoveCursor(INT_MIN, 0);
+               return 1;
        }
 
         int    ret = 0;
@@ -52,3 +96,100 @@ int Term_HandleVT100(int Len, const char *Buf)
        }
        return -ret;
 }
+
+int Term_HandleVT100_Long(int Len, const char *Buffer)
+{
+       char    c;
+        int    argc = 0, j = 0;
+        int    args[6] = {0,0,0,0,0,0};
+        int    bQuestionMark = 0;
+       
+       // Get Arguments
+       if(j == Len)    return 0;
+       c = Buffer[j++];
+       if(c == '?') {
+               bQuestionMark = 1;
+               if(j == Len)    return 0;
+               c = Buffer[j++];
+       }
+       if( '0' <= c && c <= '9' )
+       {
+               do {
+                       if(c == ';') {
+                               if(j == Len)    return 0;
+                               c = Buffer[j++];
+                       }
+                       while('0' <= c && c <= '9') {
+                               args[argc] *= 10;
+                               args[argc] += c-'0';
+                               if(j == Len)    return 0;
+                               c = Buffer[j++];
+                       }
+                       argc ++;
+               } while(c == ';');
+       }
+       
+       // Get Command
+       if( !isalpha(c) ) {
+               // Bother.
+               _SysDebug("Unexpected char 0x%x in VT100 escape code", c);
+               return 1;
+       }
+
+       if( bQuestionMark )
+       {
+               // Special commands
+               switch( c )
+               {
+               default:
+                       _SysDebug("Unknown VT100 extended escape char 0x%x", c);
+                       break;
+               }
+       }
+       else
+       {
+               // Standard commands
+               switch( c )
+               {
+               case 'J':
+                       if( argc == 0 )
+                               Display_ClearLine(0);
+                       else if( args[0] == 2 )
+                               Display_ClearLines(0);  // Entire screen!
+                       else
+                               _SysDebug("TODO: VT100 %i J", args[0]);
+                       break;
+               case 'm':
+                       if( argc == 0 )
+                       {
+                               // Reset
+                       }
+                       else
+                       {
+                               int i;
+                               for( i = 0; i < argc; i ++ )
+                               {
+                                       if( args[i] < 8 )
+                                       {
+                                               // Flags?
+                                       }
+                                       else if( 30 <= args[i] && args[i] <= 37 )
+                                       {
+                                               // TODO: Bold/bright
+                                               Display_SetForeground( caVT100Colours[ args[i]-30 ] );
+                                       } 
+                                       else if( 40 <= args[i] && args[i] <= 47 )
+                                       {
+                                               // TODO: Bold/bright
+                                               Display_SetBackground( caVT100Colours[ args[i]-30 ] );
+                                       } 
+                               }
+                       }
+                       break;
+               default:
+                       _SysDebug("Unknown VT100 escape char 0x%x", c);
+                       break;
+               }
+       }
+       return j;
+}
diff --git a/Usermode/Applications/init_src/common.h b/Usermode/Applications/init_src/common.h
new file mode 100644 (file)
index 0000000..406fe6f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Acess2 Userland init(8)
+ * - Userland root process
+ * 
+ * common.h
+ * - Common type definitions
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+typedef struct sInitProgram    tInitProgram;
+
+struct sKTerm
+{
+        int    ID;
+};
+
+struct sSTerm
+{
+       uint32_t        FormatBits;
+       unsigned int    BaudRate;
+       char    Path[];
+};
+
+struct sDaemon
+{
+       char    *StdoutPath;    // heap
+       char    *StderrPath;    // heap
+};
+
+union uProgTypes
+{
+       struct sKTerm   KTerm;
+       struct sSTerm   STerm;
+       struct sDaemon  Daemon;
+};
+
+enum eProgType
+{
+       PT_KTERM,
+       PT_STERM,
+       PT_DAEMON
+};
+
+struct sInitProgram
+{
+       tInitProgram    *Next;
+       enum eProgType  Type;
+        int    CurrentPID;
+       char    **Command;
+       union uProgTypes        TypeInfo;
+};
+
+#endif
+
index 51b9194..a3d737d 100644 (file)
@@ -4,16 +4,37 @@
 #include <acess/sys.h>
 #include <stdlib.h>
 #include <stdio.h>
-//#include "common.h"
+#include <string.h>
+#include "common.h"
+#include <ctype.h>
 
 // === CONSTANTS ===
-#define NUM_TERMS      4
-#define        DEFAULT_TERMINAL        "/Devices/VTerm/0"
 #define DEFAULT_SHELL  "/Acess/SBin/login"
+#define INITTAB_FILE   "/Acess/Conf/inittab"
 
 #define ARRAY_SIZE(x)  ((sizeof(x))/(sizeof((x)[0])))
 
 // === PROTOTYPES ===
+ int   ProcessInittab(const char *Path);
+char   *ReadQuotedString(FILE *FP);
+char   **ReadCommand(FILE *FP);
+void   FreeCommand(char **Command);
+
+tInitProgram   *AllocateProgram(char **Command, enum eProgType Type, size_t ExtraSpace);
+void   RespawnProgam(tInitProgram *Program);
+
+ int   AddKTerminal(int TerminalSpec, char **Command);
+ int   AddSerialTerminal(const char *DevPathSegment, const char *ModeStr, char **Command);
+ int   AddDaemon(char *StdoutPath, char *StderrPath, char **Command);
+
+ int   SpawnCommand(int c_stdin, int c_stdout, int c_stderr, char **ArgV);
+ int   SpawnKTerm(tInitProgram *Program);
+ int   SpawnSTerm(tInitProgram *Program);
+ int   SpawnDaemon(tInitProgram *Program);
+
+// === GLOBALS ===
+const char     *gsInittabPath = INITTAB_FILE;
+tInitProgram   *gpInitPrograms;
 
 // === CODE ===
 /**
  */
 int main(int argc, char *argv[])
 {
-        int    tid;
-        int    i;
-       char    termpath[sizeof(DEFAULT_TERMINAL)] = DEFAULT_TERMINAL;
-       char    *child_argv[2] = {DEFAULT_SHELL, 0};
+       // Parse commandline args
+       // TODO: cmdline
+
+       // TODO: Behave differently if not invoked as first process?
+
+       // Begin init process
+       if( ProcessInittab(gsInittabPath) != 0 )
+       {
+               // No inittab file found, default to:
+               _SysDebug("inittab '%s' is invalid, falling back to one VT", gsInittabPath);
+               
+               #if 0
+               for( ;; )
+               {
+                       int pid = SpawnCommand(0, 1, 1, (char *[]){DEFAULT_SHELL, NULL});
+                       // TODO: Detect errors
+                       _SysWaitTID(pid, NULL);
+               }
+               #else
+               return 41;
+               #endif
+       }
+
+       // TODO: Implement message watching
+       for(;;)
+       {
+                int    pid, status;
+               pid = _SysWaitTID(-1, &status);
+               _SysDebug("PID %i died, looking for respawn entry", pid);
+       }
        
-       // - Parse init script
+       return 42;
+}
+
+char *ReadQuotedString(FILE *FP)
+{
+       char    ch;
+       
+       while( isblank(ch = fgetc(FP)) )
+               ;
+
+       if( ch == '\n' ) {
+               return NULL;
+       }
+
+       char    *retstr = NULL;
+        int    mode = 0;
+        int    pos = 0, space = 0;
+       for( ; !feof(FP); ch = fgetc(FP) )
+       {
+                int    skip;
+               skip = 1;
+               if( mode & 4 ) {
+                       // Add escaped/special character
+                       skip = 0;
+                       mode &= 3;
+               }
+               else if( mode == 0 )
+               {
+                       if( isspace(ch) ) {
+                               fseek(FP, -1, SEEK_CUR);
+                               break;
+                       }
+                       else if( ch == '\\' )
+                               mode |= 4;
+                       else if( ch == '"' )
+                               mode = 1;
+                       else if( ch == '\'')
+                               mode = 2;
+                       else {
+                               // Add character
+                               skip = 0;
+                       }
+               }
+               // Double-quoted string
+               else if( mode == 1 )
+               {
+                       if( ch == '"' )
+                               mode = 0;
+                       else if( ch == '\\' )
+                               mode |= 4;
+                       else {
+                               // Add character
+                               skip = 0;
+                       }
+               }
+               // Single-quoted string
+               else if( mode == 2 )
+               {
+                       if( ch == '\'' )
+                               mode = 0;
+                       else if( ch == '\\' )
+                               mode |= 4;
+                       else {
+                               // Add character
+                               skip = 0;
+                       }
+               }
        
-       // - Start virtual terminals
-       for( i = 0; i < NUM_TERMS; i++ )
-       {               
-               tid = _SysClone(CLONE_VM, 0);
-               if(tid == 0)
+               if( !skip )
                {
-                       termpath[sizeof(DEFAULT_TERMINAL)-2] = '0' + i;
+                       if( pos == space ) {
+                               space += 32;
+                               void *tmp = realloc(retstr, space+1);
+                               if( !tmp ) {
+                                       _SysDebug("ReadQuotedString - realloc(%i) failure", space+1);
+                                       free(retstr);
+                                       return NULL;
+                               }
+                               retstr = tmp;
+                       }
+                       retstr[pos++] = ch;
+               }
+       }
+       retstr[pos] = '\0';
+       return retstr;
+}
+
+char **ReadCommand(FILE *FP)
+{
+       const int       space = 8;
+        int    pos = 0;
+       char    **ret = malloc(space*sizeof(char*));
+       char    *arg;
+       do {
+               arg = ReadQuotedString(FP);
+               if(arg == NULL)
+                       break;
+               if( pos == space - 1 ) {
+                       _SysDebug("Too many arguments %i", pos);
+                       ret[pos] = NULL;
+                       FreeCommand(ret);
+                       return NULL;
+               }
+               ret[pos++] = arg;
+       } while(arg != NULL);
+       ret[pos] = NULL;
+       return ret;
+}
+
+void FreeCommand(char **Command)
+{
+       int pos = 0;
+       while( Command[pos] )
+       {
+               free(Command[pos]);
+               pos ++;
+       }
+       free(Command);
+}
+
+int ProcessInittab(const char *Path)
+{
+       FILE    *fp = fopen(Path, "r");
+
+       if( !fp )
+               return 1;       
+
+       while(!feof(fp))
+       {
+               char cmdbuf[64+1];
+               
+                int    rv;
+               if( (rv = fscanf(fp, "%64s%*[ \t]", &cmdbuf)) != 1 ) {
+                       _SysDebug("fscanf rv %i != exp 1", rv);
+                       break;
+               }
+               
+               // Clear comments
+               if( cmdbuf[0] == '#' ) {
+                       while( !feof(fp) && fgetc(fp) != '\n' )
+                               ;
+                       continue ;
+               }
+               if( cmdbuf[0] == '\0' ) {
+                       char    ch = fgetc(fp);
+                       if( ch != '\n' && ch != -1 ) {
+                               fclose(fp);
+                               _SysDebug("Unexpected char 0x%x, expecting EOL", ch);
+                               return 2;       // Unexpected character?
+                       }
+                       continue ;
+               }
+
+               // Check commands
+               if( strcmp(cmdbuf, "ktty") == 0 ) {
+                       // ktty <ID> <command...>
+                       // - Spins off a console on the specified kernel TTY
+                        int    id = 0;
+                       if( fscanf(fp, "%d ", &id) != 1 ) {
+                               _SysDebug("init[ktty] - TTY ID read failed");
+                               goto lineError;
+                       }
+                       char    **command = ReadCommand(fp);
+                       if( !command ) {
+                               _SysDebug("init[ktty] - Command read failure");
+                               goto lineError;
+                       }
+                       AddKTerminal(id, command);
+                       free(command);
+               }
+               else if(strcmp(cmdbuf, "stty") == 0 ) {
+                       // stty <devpath> [78][NOE][012][bB]<baud> <command...>
+                       char    path_seg[32+1];
+                       char    modespec[4+6+1];
+                       if( fscanf(fp, "%32s %6s ", &path_seg, &modespec) != 2 ) {
+                               goto lineError;
+                       }
+                       char **command = ReadCommand(fp);
+                       if( !command )
+                               goto lineError;
+                       AddSerialTerminal(path_seg, modespec, command);
+               }
+               else if(strcmp(cmdbuf, "daemon") == 0 ) {
+                       // daemon <stdout> <stderr> <command...>
+                       // - Runs a daemon (respawning) that logs to the specified files
+                       // - Will append a header whenever the daemon starts
+                       char    *stdout_path = ReadQuotedString(fp);
+                       char    *stderr_path = ReadQuotedString(fp);
+                       char    **command = ReadCommand(fp);
                        
-                       _SysOpen(termpath, OPENFLAG_READ);      // Stdin
-                       _SysOpen(termpath, OPENFLAG_WRITE);     // Stdout
-                       _SysOpen(termpath, OPENFLAG_WRITE);     // Stderr
-                       _SysExecVE(DEFAULT_SHELL, child_argv, NULL);
-                       for(;;) ;
+                       AddDaemon(stdout_path, stderr_path, command);
+               }
+               else if(strcmp(cmdbuf, "exec") == 0 ) {
+                       // exec <command...>
+                       // - Runs a command and waits for it to complete before continuing
+                       // - NOTE: No other commands will respawn while this is running
+                       char **command = ReadCommand(fp);
+                       if(!command)
+                               goto lineError;
+
+                       int handles[] = {0, 1, 2};
+                       int pid = _SysSpawn(command[0], (const char **)command, NULL, 3, handles, NULL);
+                       int retstatus;
+                       _SysWaitTID(pid, &retstatus);
+                       _SysDebug("Command '%s' returned %i", command[0], retstatus);
+
+                       FreeCommand(command);
+               }
+               else {
+                       // Unknown command.
+                       _SysDebug("Unknown command '%s'", cmdbuf);
+                       goto lineError;
                }
+               fscanf(fp, " ");
+               continue;
+       lineError:
+               _SysDebug("label lineError: goto'd");
+               while( !feof(fp) && fgetc(fp) != '\n' )
+                       ;
+               continue ;
        }
+
+       fclose(fp);
+       return 0;
+}
+
+tInitProgram *AllocateProgram(char **Command, enum eProgType Type, size_t ExtraSpace)
+{
+       tInitProgram    *ret;
        
-       // TODO: Implement message watching
-       for(;;)
-               _SysWaitEvent(THREAD_EVENT_IPCMSG);
+       ret = malloc( sizeof(tInitProgram) - sizeof(union uProgTypes) + ExtraSpace );
+       ret->Next = NULL;
+       ret->CurrentPID = 0;
+       ret->Type = Type;
+       ret->Command = Command;
        
-       return 42;
+       // Append
+       ret->Next = gpInitPrograms;
+       gpInitPrograms = ret;
+       
+       return ret;
+}
+
+void RespawnProgam(tInitProgram *Program)
+{
+        int    rv = 0;
+       switch(Program->Type)
+       {
+       case PT_KTERM:  rv = SpawnKTerm(Program);       break;
+       case PT_STERM:  rv = SpawnSTerm(Program);       break;
+       case PT_DAEMON: rv = SpawnDaemon(Program);      break;
+       default:
+               _SysDebug("BUGCHECK - Program Type %i unknown", Program->Type);
+               break;
+       }
+       if( !rv ) {
+               _SysDebug("Respawn failure!");
+               // TODO: Remove from list?
+       }
+}
+
+int AddKTerminal(int TerminalID, char **Command)
+{
+       // TODO: Smarter validation
+       if( TerminalID < 0 || TerminalID > 7 )
+               return -1;
+       
+       tInitProgram    *ent = AllocateProgram(Command, PT_KTERM, sizeof(struct sKTerm));
+       ent->TypeInfo.KTerm.ID = TerminalID;
+
+       RespawnProgam(ent);
+       return 0;
+}
+
+int AddSerialTerminal(const char *DevPathSegment, const char *ModeStr, char **Command)
+{
+       char    dbit, parity, sbit;
+        int    baud;
+
+       // Parse mode string
+       if( sscanf(ModeStr, "%1[78]%1[NOE]%1[012]%*1[bB]%d", &dbit, &parity, &sbit, &baud) != 5 ) {
+               // Oops?
+               return -1;
+       }
+       
+       // Validate baud rate / build mode word
+       // TODO: Does baud rate need validation?
+       uint32_t        modeword = 0;
+       modeword |= (dbit == '7' ? 1 : 0) << 0;
+       modeword |= (parity == 'O' ? 1 : (parity == 'E' ? 2 : 0)) << 1;
+       modeword |= (sbit - '0') << 3;
+       
+       // Create info
+       const char DEVPREFIX[] = "/Devices/";
+       int pathlen = sizeof(DEVPREFIX) + strlen(DevPathSegment);
+       tInitProgram    *ent = AllocateProgram(Command, PT_STERM, sizeof(struct sSTerm)+pathlen);
+       ent->TypeInfo.STerm.FormatBits = modeword;
+       ent->TypeInfo.STerm.BaudRate = baud;
+       strcpy(ent->TypeInfo.STerm.Path, DEVPREFIX);
+       strcat(ent->TypeInfo.STerm.Path, DevPathSegment);
+
+       RespawnProgam(ent);
+       return 0;
+}
+
+int AddDaemon(char *StdoutPath, char *StderrPath, char **Command)
+{
+       tInitProgram    *ent = AllocateProgram(Command, PT_DAEMON, sizeof(struct sDaemon));
+       ent->TypeInfo.Daemon.StdoutPath = StdoutPath;
+       ent->TypeInfo.Daemon.StderrPath = StderrPath;
+       
+       RespawnProgam(ent);
+       return 0;
+}
+
+int SpawnCommand(int c_stdin, int c_stdout, int c_stderr, char **ArgV)
+{
+        int    handles[] = {c_stdin, c_stdout, c_stderr};
+
+       int rv = _SysSpawn(ArgV[0], (const char **)ArgV, NULL, 3, handles, NULL);
+
+       _SysClose(c_stdin);
+       if( c_stdout != c_stdin )
+               _SysClose(c_stdout);
+       if( c_stderr != c_stdin && c_stderr != c_stdout )
+               _SysClose(c_stderr);
+
+       return rv;
+}
+
+int SpawnKTerm(tInitProgram *Program)
+{
+       const char fmt[] = "/Devices/VTerm/%i";
+       char    path[sizeof(fmt)];
+       
+       snprintf(path, sizeof(path), fmt, Program->TypeInfo.KTerm.ID);
+       
+        int    in = _SysOpen(path, OPENFLAG_READ);
+        int    out = _SysOpen(path, OPENFLAG_WRITE);
+       
+       return SpawnCommand(in, out, out, Program->Command);
+}
+
+int SpawnSTerm(tInitProgram *Program)
+{
+        int    in = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_READ);
+        int    out = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_WRITE);
+
+       #if 0
+       if( _SysIOCtl(in, 0, NULL) != DRV_TYPE_SERIAL )
+       {
+               // Oops?
+               return -2;
+       }
+       _SysIOCtl(in, SERIAL_IOCTL_GETSETBAUD, &Program->TypeInfo.STerm.BaudRate);
+       _SysIOCtl(in, SERIAL_IOCTL_GETSETFORMAT, &Program->TypeInfo.STerm.FormatBits);
+       #endif
+
+       return SpawnCommand(in, out, out, Program->Command);
+}
+
+int SpawnDaemon(tInitProgram *Program)
+{
+        int    in = _SysOpen("/Devices/null", OPENFLAG_READ);
+        int    out = _SysOpen(Program->TypeInfo.Daemon.StdoutPath, OPENFLAG_WRITE);
+        int    err = _SysOpen(Program->TypeInfo.Daemon.StderrPath, OPENFLAG_WRITE);
+       
+       if( in == -1 || out == -1 || err == -1 ) {
+               _SysClose(in);
+               _SysClose(out);
+               _SysClose(err);
+               return -2;
+       }
+       
+       return SpawnCommand(in, out, err, Program->Command);
 }
 
index 9e5a075..16eee39 100644 (file)
@@ -78,7 +78,7 @@ char  *gsNickname = "acess";
 tServer        *gpServers;\r
 tWindow        gWindow_Status = {\r
        NULL, NULL, NULL,       // No next, empty list, no server\r
-       0, ""   // No activity, empty name (rendered as status)\r
+       0, {""} // No activity, empty name (rendered as status)\r
 };\r
 tWindow        *gpWindows = &gWindow_Status;\r
 tWindow        *gpCurrentWindow = &gWindow_Status;\r
index a4f5e0d..bf6de99 100644 (file)
@@ -55,17 +55,17 @@ int main(int argc, char *argv[])
        return 0;
 }
 
+static void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
+{
+       FD_SET(fd, set);
+       if(*maxfd < fd) *maxfd = fd;
+}
+
 void EventLoop(void)
 {
        fd_set  fds;
         int    maxfd;
 
-       void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
-       {
-               FD_SET(fd, set);
-               if(*maxfd < fd) *maxfd = fd;
-       }
-
        for( ;; )
        {
                FD_ZERO(&fds);
diff --git a/Usermode/Filesystem/Conf/inittab b/Usermode/Filesystem/Conf/inittab
new file mode 100644 (file)
index 0000000..a64bfc0
--- /dev/null
@@ -0,0 +1,8 @@
+exec /Acess/Bin/dhcpc
+
+ktty 0 /Acess/SBin/login
+ktty 1 /Acess/SBin/login
+stty serial/0 /Acess/SBin/login
+
+
+#vim: ft=text
index 7eb0694..a49d887 100644 (file)
@@ -5,7 +5,7 @@
 
 DIRS  = Bin SBin Libs Modules Apps
 DIRS += Conf Conf/Auth
-FILES = Conf/BootConf.cfg
+FILES = Conf/inittab
 # Conf/Auth/Users Conf/Auth/Passwords Conf/Auth/Groups
 
 #DIRS  := $(addprefix $(DISTROOT)/,$(DIRS))
index 2c85b14..351c841 100644 (file)
@@ -100,9 +100,23 @@ _errno:    .long   0       @ Placed in .text, to allow use of relative addressing
 // Override the clone syscall
 #define _exit  _exit_raw
 #define _clone _clone_raw
+#define _SysSeek       _SysSeek_borken
 #include "syscalls.s.h"
 #undef _exit
 #undef _clone
+#undef _SysSeek 
+
+// NOTE: _SysSeek needs special handling for alignment
+.globl _SysSeek
+_SysSeek:
+       push {lr}
+       mov r1,r2
+       mov r2,r3
+       ldr r3, [sp,#4]
+       svc #SYS_SEEK
+       ldr r3, =_errno
+       str r2, [r3]
+       pop {pc}
 
 .globl _clone
 _clone:
@@ -120,6 +134,7 @@ _clone_ret:
        pop {r4}
        mov pc, lr
 
+
 .globl _exit
 _exit:
        svc #0
index 0793901..b2367d1 100644 (file)
@@ -21,9 +21,29 @@ typedef struct
 }      fd_set;
 
 
-extern void    FD_ZERO(fd_set *fdsetp);
-extern void    FD_CLR(int fd, fd_set *fdsetp);
-extern void    FD_SET(int fd, fd_set *fdsetp);
-extern int     FD_ISSET(int fd, fd_set *fdsetp);
+static inline void     FD_ZERO(fd_set *fdsetp)
+{
+       int i = FD_SETSIZE/16;
+       while( i-- )
+               fdsetp->flags[i] = 0;
+}
+static inline  void    FD_CLR(int fd, fd_set *fdsetp)
+{
+       if(fd < 0 || fd > FD_SETSIZE)   return;
+       fd_set_ent_t    mask = 1 << (fd % 16);
+       fdsetp->flags[fd/16] &= ~mask;
+}
+static inline  void    FD_SET(int fd, fd_set *fdsetp)
+{
+       if(fd < 0 || fd > FD_SETSIZE)   return;
+       fd_set_ent_t    mask = 1 << (fd % 16);
+       fdsetp->flags[fd/16] |= mask;
+}
+static inline  int     FD_ISSET(int fd, fd_set *fdsetp)
+{
+       if(fd < 0 || fd > FD_SETSIZE)   return 0;
+       fd_set_ent_t    mask = 1 << (fd % 16);
+       return !!( fdsetp->flags[fd/16] & mask );
+}
 
 #endif
index c798702..d9d3173 100644 (file)
@@ -33,6 +33,8 @@
 #define GETMSG_IGNORE  ((void*)-1)
 #define FILEFLAG_DIRECTORY     0x10
 #define FILEFLAG_SYMLINK       0x20
+#define CLONE_VM       0x10
+
 
 // === TYPES ===
 
deleted file mode 120000 (symlink)
index 93c2064e2025798423a9f9137e6bfcaa906b7c6c..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../KernelLand/Kernel/include/keysyms.h
\ No newline at end of file
new file mode 100644 (file)
index 0000000000000000000000000000000000000000..6517a405d99074c4a03154aa0964549feb0af69d
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../../../KernelLand/Kernel/include/keysyms.h"
index 31adb5c..c29e0e5 100644 (file)
@@ -10,7 +10,7 @@ LDFLAGS  += -soname libc.so -Map map.txt
 \r
 INCFILES := stdio.h stdlib.h\r
 \r
-OBJ  = stub.o heap.o stdlib.o env.o stdio.o string.o select.o rand.o\r
+OBJ  = stub.o heap.o stdlib.o env.o stdio.o string.o rand.o\r
 OBJ += perror.o scanf.o signals.o strtoi.o strtof.o\r
 OBJ += arch/$(ARCHDIR).ao\r
 # signals.o\r
index 6a1d584..3d45ed1 100644 (file)
@@ -152,6 +152,8 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char
                // int  offset = -1;
                enum e_vcscanf_sizes    size = _VCSCANF_UNDEF;
                enum e_vcscanf_types    valtype;
+                int    fail = 0;
+                int    nnewch;
 
                const char      *set_start;
                 int    set_len;                
@@ -161,6 +163,7 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char
                {
                        while( (ich = __getc(h)) && isspace(ich) )
                                nch ++;
+                       if(ich) __rewind(h);
                        continue ;
                }
                
@@ -262,22 +265,30 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char
                {
                // Decimal integer
                case 'd':
-                       nch += _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
+                       nnewch = _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
+                       if(nnewch==0)   fail=1;
+                       nch += nnewch;
                        valtype = _VCSCANF_INT;
                        break;
                // variable-base integer
                case 'i':
-                       nch += _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
+                       nnewch = _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
+                       if(nnewch==0)   fail=1;
+                       nch += nnewch;
                        valtype = _VCSCANF_INT;
                        break;
                // Octal integer
                case 'o':
-                       nch += _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
+                       nnewch = _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
+                       if(nnewch==0)   fail=1;
+                       nch += nnewch;
                        valtype = _VCSCANF_INT;
                        break;
                // Hexadecimal integer
                case 'x': case 'X':
-                       nch += _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
+                       nnewch = _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
+                       if(nnewch==0)   fail=1;
+                       nch += nnewch;
                        valtype = _VCSCANF_INT;
                        break;
                // strtod format float
@@ -304,13 +315,14 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char
                                maxlen = -1;
 
                        ich = 0;
-                       while( maxlen -- && (ich = __getc(h)) && !isblank(ich) )
+                       while( maxlen -- && (ich = __getc(h)) && !isspace(ich) )
                        {
                                if(ptr._char)   *ptr._char++ = ich;
                                nch ++;
                        }
                        if( maxlen >= 0 && ich )
                                __rewind(h);
+                       if(ptr._char)   *ptr._char++ = 0;
                        valtype = _VCSCANF_NOTYPE;
                        break;
                // match a set of characters
@@ -329,6 +341,8 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char
                                fch = *format++;
                        } while( fch && fch != ']' );
 
+                       if( maxlen == 0 )
+                               maxlen = -1;
                        ich = 0;
                        while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) )
                        {
@@ -337,6 +351,7 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char
                        }
                        if( maxlen >= 0 && ich )
                                __rewind(h);
+                       if(ptr._char)   *ptr._char++ = 0;
                        valtype = _VCSCANF_NOTYPE;
                        break;
                case 'p': // read back printf("%p")
@@ -354,7 +369,10 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char
                        valtype = _VCSCANF_NOTYPE;
                        break;
                }
-               
+
+               if(fail)
+                       break;          
+
                switch(valtype)
                {
                case _VCSCANF_NOTYPE:
@@ -406,7 +424,8 @@ int vsscanf(const char *str, const char *format, va_list ap)
 
 int _vfscanf_getc(void *h)
 {
-       return fgetc(h);        // TODO: Handle -1 -> 0
+       int ch = fgetc(h);
+       return ch == -1 ? 0 : ch;
 }
 void _vfscanf_rewind(void *h)
 {
diff --git a/Usermode/Libraries/libc.so_src/select.c b/Usermode/Libraries/libc.so_src/select.c
deleted file mode 100644 (file)
index c42848c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Acess2 C Library
- * - By John Hodge (thePowersGang)
- *
- * select.c
- */
-
-//#include <sys/select.h>
-#include <sys/types.h>
-
-void FD_ZERO(fd_set *fdsetp)
-{
-       int i = FD_SETSIZE/16;
-       while( i-- )
-               fdsetp->flags[i]=0;
-}
-
-void FD_CLR(int fd, fd_set *fdsetp)
-{
-       if(fd < 0 || fd > FD_SETSIZE)   return;
-       fdsetp->flags[fd/16] &= (fd_set_ent_t) ((~1 << (fd%16))) & 0xFFFF;
-}
-
-void FD_SET(int fd, fd_set *fdsetp)
-{
-       if(fd < 0 || fd > FD_SETSIZE)   return;
-       fdsetp->flags[fd/16] |= (fd_set_ent_t) (1 << (fd%16));
-}
-
-int FD_ISSET(int fd, fd_set *fdsetp)
-{
-       if(fd < 0 || fd > FD_SETSIZE)   return 0;
-       return !!( fdsetp->flags[fd/16] & (1<<(fd%16)) );
-}
-
index 840e24d..39d37a4 100644 (file)
@@ -348,6 +348,12 @@ EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)
        }\r
        else {\r
                ret = _SysRead(fp->FD, ptr, size*num);\r
+               if( ret == (size_t)-1)\r
+                       return -1;\r
+               if( ret == 0 && size*num > 0 ) {\r
+                       fp->Flags |= FILE_FLAG_EOF;\r
+                       return 0;\r
+               }\r
                ret /= size;\r
        }\r
                \r
@@ -403,7 +409,7 @@ EXPORT int putchar(int c)
 EXPORT int fgetc(FILE *fp)\r
 {\r
        char    ret = 0;\r
-       if( fread(&ret, 1, 1, fp) == (size_t)-1 )\r
+       if( fread(&ret, 1, 1, fp) != 1 )\r
                return -1;\r
        return ret;\r
 }\r
@@ -452,7 +458,7 @@ EXPORT int vsprintf(char * __s, const char *__format, va_list __args)
        return vsnprintf(__s, 0x7FFFFFFF, __format, __args);\r
 }\r
 \r
-//sprintfv\r
+\r
 /**\r
  * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)\r
  * \brief Prints a formatted string to a buffer\r
@@ -470,11 +476,11 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg
        uint64_t        arg;\r
         int    bLongLong, bPadLeft;\r
 \r
-       void _addchar(char ch)\r
-       {\r
-               if(buf && pos < __maxlen)       buf[pos] = ch;\r
-               pos ++;\r
-       }\r
+       #define _addchar(ch) do { \\r
+               if(buf && pos < __maxlen)       buf[pos] = (ch); \\r
+               else (void)(ch); \\r
+               pos ++; \\r
+       } while(0)\r
 \r
        tmp[32] = '\0';\r
        \r
@@ -637,6 +643,7 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg
        }\r
        _addchar('\0');\r
        pos --;\r
+       #undef _addchar\r
        \r
        //_SysDebug("vsnprintf: buf = '%s'", buf);\r
        \r
@@ -708,7 +715,7 @@ EXPORT int printf(const char *format, ...)
        va_end(args);\r
        \r
        // Send to stdout\r
-       _SysWrite(_stdout, buf, size+1);\r
+       _SysWrite(_stdout, buf, size);\r
        \r
        // Free buffer\r
        free(buf);\r
index db78b5a..9b7aac0 100644 (file)
@@ -13,8 +13,6 @@ typedef unsigned int  u_int;
 typedef struct stat    t_fstat;
 
 
-#define CLONE_VM       0x10
-
 typedef unsigned int   id_t;
 typedef unsigned long  pid_t;
 typedef unsigned long  tid_t;
diff --git a/Usermode/Libraries/libunicode.so_src/Makefile b/Usermode/Libraries/libunicode.so_src/Makefile
new file mode 100644 (file)
index 0000000..d515f3d
--- /dev/null
@@ -0,0 +1,14 @@
+# Acess 2 "libunicode"
+#
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS   += -Wall
+LDFLAGS  += -lc -soname libunicode.so
+
+OBJ = main.o utf-8.o
+BIN = libunicode.so
+
+include ../Makefile.tpl
+
diff --git a/Usermode/Libraries/libunicode.so_src/include_exp/unicode.h b/Usermode/Libraries/libunicode.so_src/include_exp/unicode.h
new file mode 100644 (file)
index 0000000..ef0eb56
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Acess2 "libunicode" UTF Parser
+ * - By John Hodge (thePowersGang)
+ *
+ * unicode.h
+ * - Main header
+ */
+#ifndef _LIBUNICODE__UNICODE_H_
+#define _LIBUNICODE__UNICODE_H_
+
+#include <stdint.h>
+
+/**
+ * \breif Read a single codepoint from  a UTF-8 stream
+ * \return Number of bytes read
+ */
+extern int     ReadUTF8(const char *Input, uint32_t *Val);
+/**
+ * \brief Read backwards in the stream
+ */
+extern int     ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val);
+/**
+ * \breif Write a single codepoint to a UTF-8 stream
+ */
+extern int     WriteUTF8(char *buf, uint32_t Val);
+
+
+static inline int      Unicode_IsPrinting(uint32_t Codepoint) { return 1; }
+
+#endif
+
diff --git a/Usermode/Libraries/libunicode.so_src/main.c b/Usermode/Libraries/libunicode.so_src/main.c
new file mode 100644 (file)
index 0000000..e39dc9b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Acess2 "libunicode"
+ * - By John Hoge
+ *
+ * main.c
+ * - Stub main
+ */
+
+int SoMain(void)
+{
+       return 0;
+}
diff --git a/Usermode/Libraries/libunicode.so_src/utf-8.c b/Usermode/Libraries/libunicode.so_src/utf-8.c
new file mode 100644 (file)
index 0000000..3aa9d1a
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Acess2 "libunicode" UTF Parser
+ * - By John Hodge (thePowersGang)
+ *
+ * utf-8.c
+ * - UTF-8 Parsing code
+ */
+#include <stdint.h>
+#include <unicode.h>
+
+/**
+ * \brief Read a UTF-8 character from a string
+ * \param Input        Source UTF-8 encoded string
+ * \param Val  Destination for read codepoint
+ * \return Number of bytes read/used
+ */
+int ReadUTF8(const char *Input, uint32_t *Val)
+{
+       const uint8_t   *str = (const uint8_t *)Input;
+       *Val = 0xFFFD;  // Assume invalid character
+       
+       // ASCII
+       if( !(*str & 0x80) ) {
+               *Val = *str;
+               return 1;
+       }
+       
+       // Middle of a sequence
+       if( (*str & 0xC0) == 0x80 ) {
+               return 1;
+       }
+       
+       // Two Byte
+       if( (*str & 0xE0) == 0xC0 ) {
+               *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
+               str ++;
+               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
+               *Val |= (*str & 0x3F);  // Lower 6 Bits
+               return 2;
+       }
+       
+       // Three Byte
+       if( (*str & 0xF0) == 0xE0 ) {
+               *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
+               str ++;
+               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
+               *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
+               str ++;
+               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
+               *Val |= (*str & 0x3F);  // Lower 6 Bits
+               return 3;
+       }
+       
+       // Four Byte
+       if( (*str & 0xF8) == 0xF0 ) {
+               *Val = (*str & 0x07) << 18;     // Upper 3 Bits
+               str ++;
+               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
+               *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
+               str ++;
+               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
+               *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
+               str ++;
+               if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
+               *Val |= (*str & 0x3F);  // Lower 6 Bits
+               return 4;
+       }
+       
+       // UTF-8 Doesn't support more than four bytes
+       return 4;
+}
+
+/**
+ * \brief Get the UTF-8 character before the 
+ * \
+ */
+int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val)
+{
+        int    len = 0;
+       
+       // Scan backwards for the beginning of the character
+       while( Offset > 0 && (Base[Offset--] & 0xC0) == 0x80 )
+               len ++;
+       // Invalid string (no beginning)
+       if(Offset == 0 && (Base[Offset] & 0xC0) == 0x80 )
+               return len;
+       
+       len ++; // First character
+       if( ReadUTF8(Base+Offset, Val) != len ) {
+               *Val = 0xFFFD;
+       }
+       return len;
+}
+
+/**
+ * \brief Write a UTF-8 character sequence to a string
+ * \param buf  Destination buffer (must have at least 4 bytes available)
+ * \param Val  Unicode codepoint to write
+ * \return Number of bytes written
+ * \note Does not NULL terminate the string in \a buf
+ */
+int WriteUTF8(char *buf, uint32_t Val)
+{
+       uint8_t *str = (void*)buf;
+       
+       // ASCII
+       if( Val < 128 ) {
+               if(str) {
+                       *str = Val;
+               }
+               return 1;
+       }
+       
+       // Two Byte
+       if( Val < 0x8000 ) {
+               if(str) {
+                       *str = 0xC0 | (Val >> 6);
+                       str ++;
+                       *str = 0x80 | (Val & 0x3F);
+               }
+               return 2;
+       }
+       
+       // Three Byte
+       if( Val < 0x10000 ) {
+               if(str) {
+                       *str = 0xE0 | (Val >> 12);
+                       str ++;
+                       *str = 0x80 | ((Val >> 6) & 0x3F);
+                       str ++;
+                       *str = 0x80 | (Val & 0x3F);
+               }
+               return 3;
+       }
+       
+       // Four Byte
+       if( Val < 0x110000 ) {
+               if(str) {
+                       *str = 0xF0 | (Val >> 18);
+                       str ++;
+                       *str = 0x80 | ((Val >> 12) & 0x3F);
+                       str ++;
+                       *str = 0x80 | ((Val >> 6) & 0x3F);
+                       str ++;
+                       *str = 0x80 | (Val & 0x3F);
+               }
+               return 4;
+       }
+       
+       // UTF-8 Doesn't support more than four bytes
+       return 0;
+}
+

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