Very first cut at a klibc-derived C library for com32
authorhpa <hpa>
Wed, 10 Nov 2004 22:31:50 +0000 (22:31 +0000)
committerhpa <hpa>
Wed, 10 Nov 2004 22:31:50 +0000 (22:31 +0000)
117 files changed:
com32/Makefile [new file with mode: 0644]
com32/include/bitsize/limits.h [new file with mode: 0644]
com32/include/bitsize/stddef.h [new file with mode: 0644]
com32/include/bitsize/stdint.h [new file with mode: 0644]
com32/include/bitsize/stdintconst.h [new file with mode: 0644]
com32/include/bitsize/stdintlimits.h [new file with mode: 0644]
com32/include/com32.h
com32/include/ctype.h [new file with mode: 0644]
com32/include/errno.h [new file with mode: 0644]
com32/include/inttypes.h [new file with mode: 0644]
com32/include/klibc/compiler.h [new file with mode: 0644]
com32/include/klibc/extern.h [new file with mode: 0644]
com32/include/klibc/sysconfig.h [new file with mode: 0644]
com32/include/limits.h [new file with mode: 0644]
com32/include/malloc.h [new file with mode: 0644]
com32/include/minmax.h [new file with mode: 0644]
com32/include/stdarg.h [new file with mode: 0644]
com32/include/stddef.h [new file with mode: 0644]
com32/include/stdio.h [new file with mode: 0644]
com32/include/stdlib.h [new file with mode: 0644]
com32/include/string.h [new file with mode: 0644]
com32/include/sys/cpu.h [new file with mode: 0644]
com32/include/sys/io.h [new file with mode: 0644]
com32/include/sys/pci.h [new file with mode: 0644]
com32/include/sys/types.h [new file with mode: 0644]
com32/lib/MCONFIG [new file with mode: 0644]
com32/lib/Makefile [new file with mode: 0644]
com32/lib/abort.c [new file with mode: 0644]
com32/lib/atexit.c [new file with mode: 0644]
com32/lib/atexit.h [new file with mode: 0644]
com32/lib/atoi.c [new file with mode: 0644]
com32/lib/atol.c [new file with mode: 0644]
com32/lib/atoll.c [new file with mode: 0644]
com32/lib/atox.c [new file with mode: 0644]
com32/lib/calloc.c [new file with mode: 0644]
com32/lib/creat.c [new file with mode: 0644]
com32/lib/ctypes.c [new file with mode: 0644]
com32/lib/errno.c [new file with mode: 0644]
com32/lib/exit.c [new file with mode: 0644]
com32/lib/fgetc.c [new file with mode: 0644]
com32/lib/fgets.c [new file with mode: 0644]
com32/lib/fopen.c [new file with mode: 0644]
com32/lib/fprintf.c [new file with mode: 0644]
com32/lib/fputc.c [new file with mode: 0644]
com32/lib/fputs.c [new file with mode: 0644]
com32/lib/fread.c [new file with mode: 0644]
com32/lib/fread2.c [new file with mode: 0644]
com32/lib/free.c [new file with mode: 0644]
com32/lib/fwrite.c [new file with mode: 0644]
com32/lib/fwrite2.c [new file with mode: 0644]
com32/lib/getopt.c [new file with mode: 0644]
com32/lib/init.h [new file with mode: 0644]
com32/lib/lrand48.c [new file with mode: 0644]
com32/lib/malloc.c [new file with mode: 0644]
com32/lib/memccpy.c [new file with mode: 0644]
com32/lib/memchr.c [new file with mode: 0644]
com32/lib/memcmp.c [new file with mode: 0644]
com32/lib/memcpy.c [new file with mode: 0644]
com32/lib/memmem.c [new file with mode: 0644]
com32/lib/memmove.c [new file with mode: 0644]
com32/lib/memset.c [new file with mode: 0644]
com32/lib/memswap.c [new file with mode: 0644]
com32/lib/onexit.c [new file with mode: 0644]
com32/lib/perror.c [new file with mode: 0644]
com32/lib/printf.c [new file with mode: 0644]
com32/lib/puts.c [new file with mode: 0644]
com32/lib/qsort.c [new file with mode: 0644]
com32/lib/realloc.c [new file with mode: 0644]
com32/lib/seed48.c [new file with mode: 0644]
com32/lib/setjmp.S [new file with mode: 0644]
com32/lib/snprintf.c [new file with mode: 0644]
com32/lib/sprintf.c [new file with mode: 0644]
com32/lib/srand48.c [new file with mode: 0644]
com32/lib/sscanf.c [new file with mode: 0644]
com32/lib/stack.c [new file with mode: 0644]
com32/lib/strcasecmp.c [new file with mode: 0644]
com32/lib/strcat.c [new file with mode: 0644]
com32/lib/strchr.c [new file with mode: 0644]
com32/lib/strcmp.c [new file with mode: 0644]
com32/lib/strcpy.c [new file with mode: 0644]
com32/lib/strdup.c [new file with mode: 0644]
com32/lib/strerror.c [new file with mode: 0644]
com32/lib/strlen.c [new file with mode: 0644]
com32/lib/strncasecmp.c [new file with mode: 0644]
com32/lib/strncat.c [new file with mode: 0644]
com32/lib/strncmp.c [new file with mode: 0644]
com32/lib/strncpy.c [new file with mode: 0644]
com32/lib/strndup.c [new file with mode: 0644]
com32/lib/strntoimax.c [new file with mode: 0644]
com32/lib/strntoumax.c [new file with mode: 0644]
com32/lib/strrchr.c [new file with mode: 0644]
com32/lib/strsep.c [new file with mode: 0644]
com32/lib/strspn.c [new file with mode: 0644]
com32/lib/strstr.c [new file with mode: 0644]
com32/lib/strtoimax.c [new file with mode: 0644]
com32/lib/strtok.c [new file with mode: 0644]
com32/lib/strtol.c [new file with mode: 0644]
com32/lib/strtoll.c [new file with mode: 0644]
com32/lib/strtoul.c [new file with mode: 0644]
com32/lib/strtoull.c [new file with mode: 0644]
com32/lib/strtoumax.c [new file with mode: 0644]
com32/lib/strtox.c [new file with mode: 0644]
com32/lib/sys/close.c [new file with mode: 0644]
com32/lib/sys/entry.S [new file with mode: 0644]
com32/lib/sys/exit.S [new file with mode: 0644]
com32/lib/sys/file.h [new file with mode: 0644]
com32/lib/sys/fileinfo.c [new file with mode: 0644]
com32/lib/sys/open.c [new file with mode: 0644]
com32/lib/sys/read.c [new file with mode: 0644]
com32/lib/sys/write.c [new file with mode: 0644]
com32/lib/vfprintf.c [new file with mode: 0644]
com32/lib/vprintf.c [new file with mode: 0644]
com32/lib/vsnprintf.c [new file with mode: 0644]
com32/lib/vsprintf.c [new file with mode: 0644]
com32/lib/vsscanf.c [new file with mode: 0644]
com32/modules/Makefile [new file with mode: 0644]
com32/modules/hello.c [new file with mode: 0644]

diff --git a/com32/Makefile b/com32/Makefile
new file mode 100644 (file)
index 0000000..66b1001
--- /dev/null
@@ -0,0 +1,4 @@
+SUBDIRS = lib modules
+
+all tidy clean spotless:
+       for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
diff --git a/com32/include/bitsize/limits.h b/com32/include/bitsize/limits.h
new file mode 100644 (file)
index 0000000..f90e524
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * bits32/limits.h
+ */
+
+#ifndef _BITSIZE_LIMITS_H
+#define _BITSIZE_LIMITS_H
+
+#define LONG_BIT       32
+
+#define LONG_MIN       (-2147483647L-1)
+#define LONG_MAX       2147483647L
+#define ULONG_MAX      4294967295UL
+
+#endif /* _BITSIZE_LIMITS_H */
diff --git a/com32/include/bitsize/stddef.h b/com32/include/bitsize/stddef.h
new file mode 100644 (file)
index 0000000..c486041
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * bits32/stddef.h
+ */
+
+#ifndef _BITSIZE_STDDEF_H
+#define _BITSIZE_STDDEF_H
+
+#define _SIZE_T
+#if defined(__s390__) || defined(__hppa__) || defined(__cris__)
+typedef unsigned long size_t;
+#else
+typedef unsigned int size_t;
+#endif
+
+#define _PTRDIFF_T
+typedef signed int   ptrdiff_t;
+
+#endif /* _BITSIZE_STDDEF_H */
diff --git a/com32/include/bitsize/stdint.h b/com32/include/bitsize/stdint.h
new file mode 100644 (file)
index 0000000..40b4649
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * bits32/stdint.h
+ */
+
+#ifndef _BITSIZE_STDINT_H
+#define _BITSIZE_STDINT_H
+
+typedef signed char            int8_t;
+typedef short int              int16_t;
+typedef int                    int32_t;
+typedef long long int          int64_t;
+
+typedef unsigned char          uint8_t;
+typedef unsigned short int     uint16_t;
+typedef unsigned int           uint32_t;
+typedef unsigned long long int uint64_t;
+
+typedef int                    int_fast16_t;
+typedef int                    int_fast32_t;
+
+typedef unsigned int           uint_fast16_t;
+typedef unsigned int           uint_fast32_t;
+
+typedef int                    intptr_t;
+typedef unsigned int           uintptr_t;
+
+#define __INT64_C(c)   c ## LL
+#define __UINT64_C(c)  c ## ULL
+
+#define __PRI64_RANK   "ll"
+#define __PRIFAST_RANK ""
+#define __PRIPTR_RANK  ""
+
+#endif /* _BITSIZE_STDINT_H */
diff --git a/com32/include/bitsize/stdintconst.h b/com32/include/bitsize/stdintconst.h
new file mode 100644 (file)
index 0000000..8157dd0
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * bits32/stdintconst.h
+ */
+
+#ifndef _BITSIZE_STDINTCONST_H
+#define _BITSIZE_STDINTCONST_H
+
+#define INT_FAST16_C(c)         INT32_C(c)
+#define INT_FAST32_C(c)  INT32_C(c)
+
+#define UINT_FAST16_C(c) UINT32_C(c)
+#define UINT_FAST32_C(c) UINT32_C(c)
+
+#define INTPTR_C(c)     INT32_C(c)
+#define UINTPTR_C(c)    UINT32_C(c)
+#define PTRDIFF_C(c)     INT32_C(c)
+
+#endif /* _BITSIZE_STDINTCONST_H */
diff --git a/com32/include/bitsize/stdintlimits.h b/com32/include/bitsize/stdintlimits.h
new file mode 100644 (file)
index 0000000..b44fe01
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * bits32/stdintlimits.h
+ */
+
+#ifndef _BITSIZE_STDINTLIMITS_H
+#define _BITSIZE_STDINTLIMITS_H
+
+#define INT_FAST16_MIN INT32_MIN
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST16_MAX INT32_MAX
+#define INT_FAST32_MAX INT32_MAX
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INTPTR_MIN     INT32_MIN
+#define INTPTR_MAX     INT32_MAX
+#define UINTPTR_MAX    UINT32_MAX
+
+#define PTRDIFF_MIN    INT32_MIN
+#define PTRDIFF_MAX    INT32_MAX
+
+#endif /* _BITSIZE_STDINTLIMITS_H */
index 2462607..4548519 100644 (file)
@@ -20,7 +20,8 @@
  *
  * The syscall interface is:
  *
- * __syscall(<interrupt #>, <source regs>, <return regs>)
+ * __intcall(interrupt_#, source_regs, return_regs)
+ * __farcall(seg, offs, source_regs, return_regs)
  */
 typedef union {
   uint32_t l;
@@ -75,6 +76,22 @@ extern struct com32_sys_args {
 } __com32;
 
 /*
+ * System call macros
+ */
+static inline void
+__intcall(uint8_t __i, const com32sys_t *__sr, com32sys_t *__dr)
+{
+  __com32.cs_intcall(__i, __sr, __dr);
+}
+
+static inline void
+__farcall(uint16_t __es, uint16_t __eo,
+         const com32sys_t *__sr, com32sys_t *__dr)
+{
+  __com32.cs_farcall((__es << 16) + __eo, __sr, __dr);
+}
+
+/*
  * These functions convert between linear pointers in the range
  * 0..0xFFFFF and real-mode style SEG:OFFS pointers.  Note that a
  * 32-bit linear pointer is not compatible with a SEG:OFFS pointer
@@ -82,18 +99,18 @@ extern struct com32_sys_args {
  */
 static inline uint16_t SEG(void *__p)
 {
-  return (uint16_t)(((uint32_t)__p) >> 4);
+  return (uint16_t)(((uintptr_t)__p) >> 4);
 }
 
 static inline uint16_t OFFS(void *__p)
 {
   /* The double cast here is to shut up gcc */
-  return (uint16_t)(uint32_t)__p & 0x000F;
+  return (uint16_t)(uintptr_t)__p & 0x000F;
 }
 
 static inline void *MK_PTR(uint16_t __seg, uint16_t __offs)
 {
-  return (void *)( ((uint32_t)__seg << 4) + (uint32_t)__offs );
+  return (void *)((__seg << 4) + __offs);
 }
 
 #endif /* _COM32_H */
diff --git a/com32/include/ctype.h b/com32/include/ctype.h
new file mode 100644 (file)
index 0000000..daa6a8e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * ctype.h
+ *
+ * This assumes ISO 8859-1, being a reasonable superset of ASCII.
+ */
+
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+#ifndef __CTYPE_NO_INLINE
+# define __ctype_inline extern __inline__
+#else
+# define __ctype_inline
+#endif
+
+/*
+ * This relies on the following definitions:
+ *
+ * cntrl = !print
+ * alpha = upper|lower
+ * graph = punct|alpha|digit
+ * blank = '\t' || ' ' (per POSIX requirement)
+ */
+enum {
+  __ctype_upper  = (1 << 0),
+  __ctype_lower  = (1 << 1),
+  __ctype_digit  = (1 << 2),
+  __ctype_xdigit = (1 << 3),
+  __ctype_space  = (1 << 4),
+  __ctype_print  = (1 << 5),
+  __ctype_punct  = (1 << 6),
+  __ctype_cntrl  = (1 << 7),
+};
+
+extern const unsigned char __ctypes[];
+
+__ctype_inline int isalnum(int __c)
+{
+  return __ctypes[__c+1] &
+    (__ctype_upper|__ctype_lower|__ctype_digit);
+}
+
+__ctype_inline int isalpha(int __c)
+{
+  return __ctypes[__c+1] &
+    (__ctype_upper|__ctype_lower);
+}
+
+__ctype_inline int isascii(int __c)
+{
+  return !(__c & ~0x7f);
+}
+
+__ctype_inline int isblank(int __c)
+{
+  return (__c == '\t') || (__c == ' ');
+}
+
+__ctype_inline int iscntrl(int __c)
+{
+  return __ctypes[__c+1] & __ctype_cntrl;
+}
+
+__ctype_inline int isdigit(int __c)
+{
+  return ((unsigned)__c - '0') <= 9;
+}
+
+__ctype_inline int isgraph(int __c)
+{
+  return __ctypes[__c+1] &
+    (__ctype_upper|__ctype_lower|__ctype_digit|__ctype_punct);
+}
+
+__ctype_inline int islower(int __c)
+{
+  return __ctypes[__c+1] & __ctype_lower;
+}
+
+__ctype_inline int isprint(int __c)
+{
+  return __ctypes[__c+1] & __ctype_print;
+}
+
+__ctype_inline int ispunct(int __c)
+{
+  return __ctypes[__c+1] & __ctype_punct;
+}
+
+__ctype_inline int isspace(int __c)
+{
+  return __ctypes[__c+1] & __ctype_space;
+}
+
+__ctype_inline int isupper(int __c)
+{
+  return __ctypes[__c+1] & __ctype_upper;
+}
+
+__ctype_inline int isxdigit(int __c)
+{
+  return __ctypes[__c+1] & __ctype_xdigit;
+}
+
+/* Note: this is decimal, not hex, to avoid accidental promotion to unsigned */
+#define _toupper(__c) ((__c) & ~32)
+#define _tolower(__c) ((__c) | 32)
+
+__ctype_inline int toupper(int __c)
+{
+  return islower(__c) ? _toupper(__c) : __c;
+}
+
+__ctype_inline int tolower(int __c)
+{
+  return isupper(__c) ? _tolower(__c) : __c;
+}
+
+#endif /* _CTYPE_H */
diff --git a/com32/include/errno.h b/com32/include/errno.h
new file mode 100644 (file)
index 0000000..d32f33f
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+extern int errno;
+
+#define        EPERM            1      /* Operation not permitted */
+#define        ENOENT           2      /* No such file or directory */
+#define        ESRCH            3      /* No such process */
+#define        EINTR            4      /* Interrupted system call */
+#define        EIO              5      /* I/O error */
+#define        ENXIO            6      /* No such device or address */
+#define        E2BIG            7      /* Arg list too long */
+#define        ENOEXEC          8      /* Exec format error */
+#define        EBADF            9      /* Bad file number */
+#define        ECHILD          10      /* No child processes */
+#define        EAGAIN          11      /* Try again */
+#define        ENOMEM          12      /* Out of memory */
+#define        EACCES          13      /* Permission denied */
+#define        EFAULT          14      /* Bad address */
+#define        ENOTBLK         15      /* Block device required */
+#define        EBUSY           16      /* Device or resource busy */
+#define        EEXIST          17      /* File exists */
+#define        EXDEV           18      /* Cross-device link */
+#define        ENODEV          19      /* No such device */
+#define        ENOTDIR         20      /* Not a directory */
+#define        EISDIR          21      /* Is a directory */
+#define        EINVAL          22      /* Invalid argument */
+#define        ENFILE          23      /* File table overflow */
+#define        EMFILE          24      /* Too many open files */
+#define        ENOTTY          25      /* Not a typewriter */
+#define        ETXTBSY         26      /* Text file busy */
+#define        EFBIG           27      /* File too large */
+#define        ENOSPC          28      /* No space left on device */
+#define        ESPIPE          29      /* Illegal seek */
+#define        EROFS           30      /* Read-only file system */
+#define        EMLINK          31      /* Too many links */
+#define        EPIPE           32      /* Broken pipe */
+#define        EDOM            33      /* Math argument out of domain of func */
+#define        ERANGE          34      /* Math result not representable */
+#define        EDEADLK         35      /* Resource deadlock would occur */
+#define        ENAMETOOLONG    36      /* File name too long */
+#define        ENOLCK          37      /* No record locks available */
+#define        ENOSYS          38      /* Function not implemented */
+#define        ENOTEMPTY       39      /* Directory not empty */
+#define        ELOOP           40      /* Too many symbolic links encountered */
+#define        EWOULDBLOCK     EAGAIN  /* Operation would block */
+#define        ENOMSG          42      /* No message of desired type */
+#define        EIDRM           43      /* Identifier removed */
+#define        ECHRNG          44      /* Channel number out of range */
+#define        EL2NSYNC        45      /* Level 2 not synchronized */
+#define        EL3HLT          46      /* Level 3 halted */
+#define        EL3RST          47      /* Level 3 reset */
+#define        ELNRNG          48      /* Link number out of range */
+#define        EUNATCH         49      /* Protocol driver not attached */
+#define        ENOCSI          50      /* No CSI structure available */
+#define        EL2HLT          51      /* Level 2 halted */
+#define        EBADE           52      /* Invalid exchange */
+#define        EBADR           53      /* Invalid request descriptor */
+#define        EXFULL          54      /* Exchange full */
+#define        ENOANO          55      /* No anode */
+#define        EBADRQC         56      /* Invalid request code */
+#define        EBADSLT         57      /* Invalid slot */
+
+#define        EDEADLOCK       EDEADLK
+
+#define        EBFONT          59      /* Bad font file format */
+#define        ENOSTR          60      /* Device not a stream */
+#define        ENODATA         61      /* No data available */
+#define        ETIME           62      /* Timer expired */
+#define        ENOSR           63      /* Out of streams resources */
+#define        ENONET          64      /* Machine is not on the network */
+#define        ENOPKG          65      /* Package not installed */
+#define        EREMOTE         66      /* Object is remote */
+#define        ENOLINK         67      /* Link has been severed */
+#define        EADV            68      /* Advertise error */
+#define        ESRMNT          69      /* Srmount error */
+#define        ECOMM           70      /* Communication error on send */
+#define        EPROTO          71      /* Protocol error */
+#define        EMULTIHOP       72      /* Multihop attempted */
+#define        EDOTDOT         73      /* RFS specific error */
+#define        EBADMSG         74      /* Not a data message */
+#define        EOVERFLOW       75      /* Value too large for defined data type */
+#define        ENOTUNIQ        76      /* Name not unique on network */
+#define        EBADFD          77      /* File descriptor in bad state */
+#define        EREMCHG         78      /* Remote address changed */
+#define        ELIBACC         79      /* Can not access a needed shared library */
+#define        ELIBBAD         80      /* Accessing a corrupted shared library */
+#define        ELIBSCN         81      /* .lib section in a.out corrupted */
+#define        ELIBMAX         82      /* Attempting to link in too many shared libraries */
+#define        ELIBEXEC        83      /* Cannot exec a shared library directly */
+#define        EILSEQ          84      /* Illegal byte sequence */
+#define        ERESTART        85      /* Interrupted system call should be restarted */
+#define        ESTRPIPE        86      /* Streams pipe error */
+#define        EUSERS          87      /* Too many users */
+#define        ENOTSOCK        88      /* Socket operation on non-socket */
+#define        EDESTADDRREQ    89      /* Destination address required */
+#define        EMSGSIZE        90      /* Message too long */
+#define        EPROTOTYPE      91      /* Protocol wrong type for socket */
+#define        ENOPROTOOPT     92      /* Protocol not available */
+#define        EPROTONOSUPPORT 93      /* Protocol not supported */
+#define        ESOCKTNOSUPPORT 94      /* Socket type not supported */
+#define        EOPNOTSUPP      95      /* Operation not supported on transport endpoint */
+#define        EPFNOSUPPORT    96      /* Protocol family not supported */
+#define        EAFNOSUPPORT    97      /* Address family not supported by protocol */
+#define        EADDRINUSE      98      /* Address already in use */
+#define        EADDRNOTAVAIL   99      /* Cannot assign requested address */
+#define        ENETDOWN        100     /* Network is down */
+#define        ENETUNREACH     101     /* Network is unreachable */
+#define        ENETRESET       102     /* Network dropped connection because of reset */
+#define        ECONNABORTED    103     /* Software caused connection abort */
+#define        ECONNRESET      104     /* Connection reset by peer */
+#define        ENOBUFS         105     /* No buffer space available */
+#define        EISCONN         106     /* Transport endpoint is already connected */
+#define        ENOTCONN        107     /* Transport endpoint is not connected */
+#define        ESHUTDOWN       108     /* Cannot send after transport endpoint shutdown */
+#define        ETOOMANYREFS    109     /* Too many references: cannot splice */
+#define        ETIMEDOUT       110     /* Connection timed out */
+#define        ECONNREFUSED    111     /* Connection refused */
+#define        EHOSTDOWN       112     /* Host is down */
+#define        EHOSTUNREACH    113     /* No route to host */
+#define        EALREADY        114     /* Operation already in progress */
+#define        EINPROGRESS     115     /* Operation now in progress */
+#define        ESTALE          116     /* Stale NFS file handle */
+#define        EUCLEAN         117     /* Structure needs cleaning */
+#define        ENOTNAM         118     /* Not a XENIX named type file */
+#define        ENAVAIL         119     /* No XENIX semaphores available */
+#define        EISNAM          120     /* Is a named type file */
+#define        EREMOTEIO       121     /* Remote I/O error */
+#define        EDQUOT          122     /* Quota exceeded */
+
+#define        ENOMEDIUM       123     /* No medium found */
+#define        EMEDIUMTYPE     124     /* Wrong medium type */
+
+#endif /* _ERRNO_H */
+
diff --git a/com32/include/inttypes.h b/com32/include/inttypes.h
new file mode 100644 (file)
index 0000000..e00fa63
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * inttypes.h
+ */
+
+#ifndef _INTTYPES_H
+#define _INTTYPES_H
+
+#include <klibc/extern.h>
+#include <stdint.h>
+#include <stddef.h>
+
+static __inline__ intmax_t imaxabs(intmax_t __n)
+{
+  return (__n < (intmax_t)0) ? -__n : __n;
+}
+
+__extern intmax_t strtoimax(const char *, char **, int);
+__extern uintmax_t strtoumax(const char *, char **, int);
+
+/* extensions */
+__extern intmax_t strntoimax(const char *, char **, int, size_t);
+__extern uintmax_t strntoumax(const char *, char **, int, size_t);
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
+
+#define PRId8  "d"
+#define PRId16 "d"
+#define PRId32 "d"
+#define PRId64 __PRI64_RANK "d"
+
+#define PRIdLEAST8     "d"
+#define PRIdLEAST16    "d"
+#define PRIdLEAST32    "d"
+#define PRIdLEAST64    __PRI64_RANK "d"
+
+#define PRIdFAST8      "d"
+#define PRIdFAST16     __PRIFAST_RANK "d"
+#define PRIdFAST32     __PRIFAST_RANK "d"
+#define PRIdFAST64     __PRI64_RANK "d"
+
+#define PRIdMAX         __PRI64_RANK "d"
+#define PRIdPTR  __PRIPTR_RANK "d"
+
+#define PRIi8  "i"
+#define PRIi16 "i"
+#define PRIi32 "i"
+#define PRIi64 __PRI64_RANK "i"
+
+#define PRIiLEAST8     "i"
+#define PRIiLEAST16    "i"
+#define PRIiLEAST32    "i"
+#define PRIiLEAST64    __PRI64_RANK "i"
+
+#define PRIiFAST8      "i"
+#define PRIiFAST16     __PRIFAST_RANK "i"
+#define PRIiFAST32     __PRIFAST_RANK "i"
+#define PRIiFAST64     __PRI64_RANK "i"
+
+#define PRIiMAX         __PRI64_RANK "i"
+#define PRIiPTR  __PRIPTR_RANK "i"
+
+#define PRIo8  "o"
+#define PRIo16 "o"
+#define PRIo32 "o"
+#define PRIo64 __PRI64_RANK "o"
+
+#define PRIoLEAST8     "o"
+#define PRIoLEAST16    "o"
+#define PRIoLEAST32    "o"
+#define PRIoLEAST64    __PRI64_RANK "o"
+
+#define PRIoFAST8      "o"
+#define PRIoFAST16     __PRIFAST_RANK "o"
+#define PRIoFAST32     __PRIFAST_RANK "o"
+#define PRIoFAST64     __PRI64_RANK "o"
+
+#define PRIoMAX         __PRI64_RANK "o"
+#define PRIoPTR  __PRIPTR_RANK "o"
+
+#define PRIu8  "u"
+#define PRIu16 "u"
+#define PRIu32 "u"
+#define PRIu64 __PRI64_RANK "u"
+
+#define PRIuLEAST8     "u"
+#define PRIuLEAST16    "u"
+#define PRIuLEAST32    "u"
+#define PRIuLEAST64    __PRI64_RANK "u"
+
+#define PRIuFAST8      "u"
+#define PRIuFAST16     __PRIFAST_RANK "u"
+#define PRIuFAST32     __PRIFAST_RANK "u"
+#define PRIuFAST64     __PRI64_RANK "u"
+
+#define PRIuMAX         __PRI64_RANK "u"
+#define PRIuPTR  __PRIPTR_RANK "u"
+
+#define PRIx8  "x"
+#define PRIx16 "x"
+#define PRIx32 "x"
+#define PRIx64 __PRI64_RANK "x"
+
+#define PRIxLEAST8     "x"
+#define PRIxLEAST16    "x"
+#define PRIxLEAST32    "x"
+#define PRIxLEAST64    __PRI64_RANK "x"
+
+#define PRIxFAST8      "x"
+#define PRIxFAST16     __PRIFAST_RANK "x"
+#define PRIxFAST32     __PRIFAST_RANK "x"
+#define PRIxFAST64     __PRI64_RANK "x"
+
+#define PRIxMAX         __PRI64_RANK "x"
+#define PRIxPTR  __PRIPTR_RANK "x"
+
+#define PRIX8  "X"
+#define PRIX16 "X"
+#define PRIX32 "X"
+#define PRIX64 __PRI64_RANK "X"
+
+#define PRIXLEAST8     "X"
+#define PRIXLEAST16    "X"
+#define PRIXLEAST32    "X"
+#define PRIXLEAST64    __PRI64_RANK "X"
+
+#define PRIXFAST8      "X"
+#define PRIXFAST16     __PRIFAST_RANK "X"
+#define PRIXFAST32     __PRIFAST_RANK "X"
+#define PRIXFAST64     __PRI64_RANK "X"
+
+#define PRIXMAX         __PRI64_RANK "X"
+#define PRIXPTR  __PRIPTR_RANK "X"
+
+#define SCNd8  "hhd"
+#define SCNd16 "hd"
+#define SCNd32 "d"
+#define SCNd64 __PRI64_RANK "d"
+
+#define SCNdLEAST8     "hhd"
+#define SCNdLEAST16    "hd"
+#define SCNdLEAST32    "d"
+#define SCNdLEAST64    __PRI64_RANK "d"
+
+#define SCNdFAST8      "hhd"
+#define SCNdFAST16     __PRIFAST_RANK "d"
+#define SCNdFAST32     __PRIFAST_RANK "d"
+#define SCNdFAST64     __PRI64_RANK "d"
+
+#define SCNdMAX         __PRI64_RANK "d"
+#define SCNdPTR  __PRIPTR_RANK "d"
+
+#define SCNi8  "hhi"
+#define SCNi16 "hi"
+#define SCNi32 "i"
+#define SCNi64 __PRI64_RANK "i"
+
+#define SCNiLEAST8     "hhi"
+#define SCNiLEAST16    "hi"
+#define SCNiLEAST32    "i"
+#define SCNiLEAST64    __PRI64_RANK "i"
+
+#define SCNiFAST8      "hhi"
+#define SCNiFAST16     __PRIFAST_RANK "i"
+#define SCNiFAST32     __PRIFAST_RANK "i"
+#define SCNiFAST64     __PRI64_RANK "i"
+
+#define SCNiMAX         __PRI64_RANK "i"
+#define SCNiPTR  __PRIPTR_RANK "i"
+
+#define SCNo8  "hho"
+#define SCNo16 "ho"
+#define SCNo32 "o"
+#define SCNo64 __PRI64_RANK "o"
+
+#define SCNoLEAST8     "hho"
+#define SCNoLEAST16    "ho"
+#define SCNoLEAST32    "o"
+#define SCNoLEAST64    __PRI64_RANK "o"
+
+#define SCNoFAST8      "hho"
+#define SCNoFAST16     __PRIFAST_RANK "o"
+#define SCNoFAST32     __PRIFAST_RANK "o"
+#define SCNoFAST64     __PRI64_RANK "o"
+
+#define SCNoMAX         __PRI64_RANK "o"
+#define SCNoPTR  __PRIPTR_RANK "o"
+
+#define SCNu8  "hhu"
+#define SCNu16 "hu"
+#define SCNu32 "u"
+#define SCNu64 __PRI64_RANK "u"
+
+#define SCNuLEAST8     "hhu"
+#define SCNuLEAST16    "hu"
+#define SCNuLEAST32    "u"
+#define SCNuLEAST64    __PRI64_RANK "u"
+
+#define SCNuFAST8      "hhu"
+#define SCNuFAST16     __PRIFAST_RANK "u"
+#define SCNuFAST32     __PRIFAST_RANK "u"
+#define SCNuFAST64     __PRI64_RANK "u"
+
+#define SCNuMAX         __PRI64_RANK "u"
+#define SCNuPTR  __PRIPTR_RANK "u"
+
+#define SCNx8  "hhx"
+#define SCNx16 "hx"
+#define SCNx32 "x"
+#define SCNx64 __PRI64_RANK "x"
+
+#define SCNxLEAST8     "hhx"
+#define SCNxLEAST16    "hx"
+#define SCNxLEAST32    "x"
+#define SCNxLEAST64    __PRI64_RANK "x"
+
+#define SCNxFAST8      "hhx"
+#define SCNxFAST16     __PRIFAST_RANK "x"
+#define SCNxFAST32     __PRIFAST_RANK "x"
+#define SCNxFAST64     __PRI64_RANK "x"
+
+#define SCNxMAX         __PRI64_RANK "x"
+#define SCNxPTR  __PRIPTR_RANK "x"
+
+#endif
+
+#endif /* _INTTYPES_H */
diff --git a/com32/include/klibc/compiler.h b/com32/include/klibc/compiler.h
new file mode 100644 (file)
index 0000000..f806506
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * klibc/compiler.h
+ *
+ * Various compiler features
+ */
+
+#ifndef _KLIBC_COMPILER_H
+#define _KLIBC_COMPILER_H
+
+#define __user
+
+/* Specific calling conventions */
+/* __cdecl is used when we want varadic and non-varadic functions to have
+   the same binary calling convention. */
+#ifdef __i386__
+# ifdef __GNUC__
+#  define __cdecl __attribute__((cdecl,regparm(0)))
+# else
+  /* Most other C compilers have __cdecl as a keyword */
+# endif
+#else
+# define __cdecl               /* Meaningless on non-i386 */
+#endif
+
+/* How to declare a function that *must* be inlined */
+#ifdef __GNUC__
+# if __GNUC_MAJOR__ >= 3
+#  define __must_inline static __inline__ __attribute__((always_inline))
+# else
+#  define __must_inline extern __inline__
+# endif
+#else
+# define __must_inline inline  /* Just hope this works... */
+#endif
+
+/* How to declare a function that does not return */
+#ifdef __GNUC__
+# define __noreturn void __attribute__((noreturn))
+#else
+# define __noreturn void
+#endif
+
+/* "const" function:
+
+     Many functions do not examine any values except their arguments,
+     and have no effects except the return value.  Basically this is
+     just slightly more strict class than the `pure' attribute above,
+     since function is not allowed to read global memory.
+
+     Note that a function that has pointer arguments and examines the
+     data pointed to must _not_ be declared `const'.  Likewise, a
+     function that calls a non-`const' function usually must not be
+     `const'.  It does not make sense for a `const' function to return
+     `void'.
+*/
+#ifdef __GNUC__
+# define __constfunc __attribute__((const))
+#else
+# define __constfunc
+#endif
+#undef __attribute_const__
+#define __attribute_const__ __constfunc
+
+/* "pure" function:
+
+     Many functions have no effects except the return value and their
+     return value depends only on the parameters and/or global
+     variables.  Such a function can be subject to common subexpression
+     elimination and loop optimization just as an arithmetic operator
+     would be.  These functions should be declared with the attribute
+     `pure'.
+*/
+#ifdef __GNUC__
+# define __purefunc __attribute__((pure))
+#else
+# define __purefunc
+#endif
+#undef __attribute_pure__
+#define __attribute_pure__ __purefunc
+
+/* Format attribute */
+#ifdef __GNUC__
+# define __formatfunc(t,f,a) __attribute__((format(t,f,a)))
+#else
+# define __formatfunc(t,f,a)
+#endif
+
+/* malloc() function (returns unaliased pointer) */
+#if defined(__GNUC__) && (__GNUC_MAJOR__ >= 3)
+# define __mallocfunc __attribute__((malloc))
+#else
+# define __mallocfunc
+#endif
+
+/* likely/unlikely */
+#if defined(__GNUC__) && (__GNUC_MAJOR__ > 2 || (__GNUC_MAJOR__ == 2 && __GNUC_MINOR__ >= 95))
+# define __likely(x)   __builtin_expect((x), 1)
+# define __unlikely(x) __builtin_expect((x), 0)
+#else
+# define __likely(x)   (x)
+# define __unlikely(x) (x)
+#endif
+
+/* Possibly unused function */
+#ifdef __GNUC__
+# define __unusedfunc  __attribute__((unused))
+#else
+# define __unusedfunc
+#endif
+
+/* Constructors and destructors */
+#define __constructor  __attribute__((constructor))
+#define __destructor   __attribute__((destructor))
+
+#endif
diff --git a/com32/include/klibc/extern.h b/com32/include/klibc/extern.h
new file mode 100644 (file)
index 0000000..f9c3467
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * klibc/extern.h
+ */
+
+#ifndef _KLIBC_EXTERN_H
+#define _KLIBC_EXTERN_H
+
+#ifdef __cplusplus
+#define __extern extern "C"
+#else
+#define __extern extern
+#endif
+
+#endif /* _KLIBC_EXTERN_H */
diff --git a/com32/include/klibc/sysconfig.h b/com32/include/klibc/sysconfig.h
new file mode 100644 (file)
index 0000000..efaaaf5
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * klibc/sysconfig.h
+ *
+ * Allows for definitions of some things which may be system-dependent
+ */
+
+#ifndef _KLIBC_SYSCONFIG_H
+#define _KLIBC_SYSCONFIG_H
+
+/*
+ * Define this to obtain memory using sbrk() instead
+ * of mmap().  This should make it friendlier on
+ * non-MMU architectures.  This should become a
+ * per-architecture configurable.
+ */
+#define MALLOC_USING_SBRK
+
+/*
+ * This is the minimum chunk size we will ask the kernel for using
+ * malloc(); this should be a multiple of the page size on all
+ * architectures.
+ */
+#define MALLOC_CHUNK_SIZE      4096
+#define MALLOC_CHUNK_MASK       (MALLOC_CHUNK_SIZE-1)
+
+/*
+ * This is the minimum alignment for the memory returned by sbrk().
+ * It must be a power of 2.  If MALLOC_USING_SBRK is defined it should
+ * be no smaller than the size of struct arena_header in malloc.h (4
+ * pointers.)
+ */
+#define SBRK_ALIGNMENT         32
+
+#endif /* _KLIBC_SYSCONFIG_H */
diff --git a/com32/include/limits.h b/com32/include/limits.h
new file mode 100644 (file)
index 0000000..64ef974
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * limits.h
+ */
+
+#ifndef _LIMITS_H
+#define _LIMITS_H
+
+#define CHAR_BIT       8
+#define SHRT_BIT       16
+#define INT_BIT                32
+#define LONGLONG_BIT   64
+
+#define SCHAR_MIN      (-128)
+#define SCHAR_MAX      127
+#define UCHAR_MAX      255
+
+#ifdef __CHAR_UNSIGNED__
+# define CHAR_MIN 0
+# define CHAR_MAX UCHAR_MAX
+#else
+# define CHAR_MIN SCHAR_MIN
+# define CHAR_MAX SCHAR_MAX
+#endif
+
+#define SHRT_MIN       (-32768)
+#define SHRT_MAX       32767
+#define USHRT_MAX      65535
+
+#define INT_MIN                (-2147483647-1)
+#define INT_MAX                2147483647
+#define UINT_MAX       4294967295U
+
+#define LONGLONG_MIN   (-9223372036854775807LL-1)
+#define LONGLONG_MAX   9223372036854775807LL
+#define ULONGLONG_MAX  18446744073709551615ULL
+
+#include <bitsize/limits.h>
+
+#endif /* _LIMITS_H */
diff --git a/com32/include/malloc.h b/com32/include/malloc.h
new file mode 100644 (file)
index 0000000..57b7652
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * malloc.h
+ *
+ * Internals for the memory allocator
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/*
+ * This is the minimum chunk size we will ask the kernel for; this should
+ * be a multiple of the page size on all architectures.
+ */
+#define MALLOC_CHUNK_SIZE      65536
+#define MALLOC_CHUNK_MASK       (MALLOC_CHUNK_SIZE-1)
+
+/*
+ * This structure should be a power of two.  This becomes the
+ * alignment unit.
+ */
+struct free_arena_header;
+
+struct arena_header {
+  size_t type;
+  size_t size;                 /* Also gives the location of the next entry */
+  struct free_arena_header *next, *prev;
+};
+
+#ifdef DEBUG_MALLOC
+#define ARENA_TYPE_USED 0x64e69c70
+#define ARENA_TYPE_FREE 0x012d610a
+#define ARENA_TYPE_HEAD 0x971676b5
+#define ARENA_TYPE_DEAD 0xeeeeeeee
+#else
+#define ARENA_TYPE_USED 0
+#define ARENA_TYPE_FREE 1
+#define ARENA_TYPE_HEAD 2
+#endif
+
+#define ARENA_SIZE_MASK (~(sizeof(struct arena_header)-1))
+
+#define ARENA_ALIGN_UP(p)      ((char *)(((uintptr_t)(p) + ARENA_SIZE_MASK) & ARENA_SIZE_MASK))
+#define ARENA_ALIGN_DOWN(p)    ((char *)((uintptr_t)(p) & ARENA_SIZE_MASK))
+
+/*
+ * This structure should be no more than twice the size of the
+ * previous structure.
+ */
+struct free_arena_header {
+  struct arena_header a;
+  struct free_arena_header *next_free, *prev_free;
+};
+
+extern struct free_arena_header __malloc_head;
diff --git a/com32/include/minmax.h b/com32/include/minmax.h
new file mode 100644 (file)
index 0000000..319db16
--- /dev/null
@@ -0,0 +1,44 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2004 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef _MINMAX_H
+#define _MINMAX_H
+
+/*
+ * minmax.h: Type-independent safe min/max macros
+ */
+
+#define min(x,y) ({ __typeof(x) xx = (x); \
+                    __typeof(y) yy = (y); \
+                    xx < yy ? xx : yy; })
+#define max(x,y) ({ __typeof(x) xx = (x); \
+                    __typeof(y) yy = (y); \
+                    xx > yy ? xx : yy; })
+
+#endif /* _MINMAX_H */
+
diff --git a/com32/include/stdarg.h b/com32/include/stdarg.h
new file mode 100644 (file)
index 0000000..cc324b8
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * stdarg.h
+ *
+ * This is just a wrapper for the gcc one, but defines va_copy()
+ * even if gcc doesn't.
+ */
+
+/* Note: the _STDARG_H macro belongs to the gcc header... */
+#include_next <stdarg.h>
+
+/* Older gcc considers this an extension, so it's double underbar only */
+#ifndef va_copy
+#define va_copy(d,s) __va_copy(d,s)
+#endif
diff --git a/com32/include/stddef.h b/com32/include/stddef.h
new file mode 100644 (file)
index 0000000..125d235
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * stddef.h
+ */
+
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+#ifndef __KLIBC__
+# define __KLIBC__ 1
+#endif
+
+#include <bitsize/stddef.h>
+
+#undef NULL
+#ifdef __cplusplus
+# define NULL 0
+#else
+# define NULL ((void *)0)
+#endif
+
+#undef offsetof
+#define offsetof(t,m) ((size_t)&((t *)0)->m)
+
+#endif /* _STDDEF_H */
diff --git a/com32/include/stdio.h b/com32/include/stdio.h
new file mode 100644 (file)
index 0000000..e40a3af
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * stdio.h
+ */
+
+#ifndef _STDIO_H
+#define _STDIO_H
+
+#include <klibc/extern.h>
+#include <stdarg.h>
+#include <stddef.h>
+
+/* This structure doesn't really exist, but it gives us something
+   to define FILE * with */
+struct _IO_file;
+typedef struct _IO_file FILE;
+
+#ifndef EOF
+# define EOF (-1)
+#endif
+
+#ifndef BUFSIZ
+# define BUFSIZ 4096
+#endif
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+/*
+ * Convert between a FILE * and a file descriptor.  We don't actually
+ * have any in-memory data, so we just abuse the pointer itself to
+ * hold the data.  Note, however, that for file descriptors, -1 is
+ * error and 0 is a valid value; for FILE *, NULL (0) is error and
+ * non-NULL are valid.
+ */
+static __inline__ int fileno(FILE *__f)
+{
+  /* This should really be intptr_t, but size_t should be the same size */
+  return (int)(size_t)__f - 1;
+}
+
+/* This is a macro so it can be used as initializer */
+#define __create_file(__fd) ((FILE *)(size_t)((__fd) + 1))
+
+#define stdin  __create_file(0)
+#define stdout __create_file(1)
+#define stderr __create_file(2)
+
+__extern FILE *fopen(const char *, const char *);
+
+static __inline__ FILE *fdopen(int __fd, const char *__m)
+{
+  (void)__m; return __create_file(__fd);
+}
+static __inline__ int fclose(FILE *__f)
+{
+  extern int close(int);
+  return close(fileno(__f));
+}
+
+__extern int fputs(const char *, FILE *);
+__extern int puts(const char *);
+__extern int fputc(int, FILE *);
+#define putc(c,f)  fputc((c),(f))
+#define putchar(c) fputc((c),stdout)
+
+__extern int    fgetc(FILE *);
+__extern char * fgets(char *, int, FILE *);
+#define getc(f) fgetc(f)
+
+__extern size_t _fread(void *, size_t, FILE *);
+__extern size_t _fwrite(const void *, size_t, FILE *);
+
+#ifndef __NO_FREAD_FWRITE_INLINES
+extern __inline__ size_t
+fread(void *__p, size_t __s, size_t __n, FILE *__f)
+{
+  return _fread(__p, __s*__n, __f)/__s;
+}
+
+extern __inline__ size_t
+fwrite(void *__p, size_t __s, size_t __n, FILE *__f)
+{
+  return _fwrite(__p, __s*__n, __f)/__s;
+}
+#endif
+
+__extern int printf(const char *, ...);
+__extern int vprintf(const char *, va_list);
+__extern int fprintf(FILE *, const char *, ...);
+__extern int vfprintf(FILE *, const char *, va_list);
+__extern int sprintf(char *, const char *, ...);
+__extern int vsprintf(char *, const char *, va_list);
+__extern int snprintf(char *, size_t n, const char *, ...);
+__extern int vsnprintf(char *, size_t n, const char *, va_list);
+
+/* No buffering, so no flushing needed */
+extern __inline__ int
+fflush(FILE *__f)
+{
+  (void)__f;
+  return 0;
+}
+
+__extern int sscanf(const char *, const char *, ...);
+__extern int vsscanf(const char *, const char *, va_list);
+
+__extern void perror(const char *);
+
+__extern int rename(const char *, const char *);
+
+#endif /* _STDIO_H */
diff --git a/com32/include/stdlib.h b/com32/include/stdlib.h
new file mode 100644 (file)
index 0000000..be4e76e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * stdlib.h
+ */
+
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+#include <klibc/extern.h>
+#include <klibc/compiler.h>
+#include <stddef.h>
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+
+static __inline__ __noreturn _Exit(int __n) {
+  __extern __noreturn _exit(int);
+  _exit(__n);
+  for(;;);                     /* Some gcc versions are stupid */
+}
+__extern __noreturn abort(void);
+static __inline__ int abs(int __n) {
+  return (__n < 0) ? -__n : __n;
+}
+__extern int atexit(void (*)(void));
+__extern int on_exit(void (*)(int, void *), void *);
+__extern int atoi(const char *);
+__extern long atol(const char *);
+__extern long long atoll(const char *);
+__extern __noreturn exit(int);
+__extern void free(void *);
+static __inline__ long labs(long __n) {
+  return (__n < 0L) ? -__n : __n;
+}
+
+static __inline__ long long llabs(long long __n) {
+  return (__n < 0LL) ? -__n : __n;
+}
+
+__extern __mallocfunc void *malloc(size_t);
+__extern __mallocfunc void *calloc(size_t, size_t);
+__extern __mallocfunc void *realloc(void *, size_t);
+__extern long strtol(const char *, char **, int);
+__extern long long strtoll(const char *, char **, int);
+__extern unsigned long strtoul(const char *, char **, int);
+__extern unsigned long long strtoull(const char *, char **, int);
+
+__extern char *getenv(const char *);
+__extern int putenv(const char *);
+__extern int setenv(const char *, const char *, int);
+__extern int unsetenv(const char *);
+
+__extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
+
+
+__extern long jrand48(unsigned short *);
+__extern long mrand48(void);
+__extern long nrand48(unsigned short *);
+__extern long lrand48(void);
+__extern unsigned short *seed48(const unsigned short *);
+__extern void srand48(long);
+
+#define RAND_MAX 0x7fffffff
+static __inline__ int rand(void) {
+  return (int)lrand48();
+}
+static __inline__ void srand(unsigned int __s) {
+  srand48(__s);
+}
+static __inline__ long random(void)
+{
+  return lrand48();
+}
+static __inline__ void srandom(unsigned int __s)
+{
+  srand48(__s);
+}
+
+/* Basic PTY functions.  These only work if devpts is mounted! */
+
+__extern int unlockpt(int);
+__extern char *ptsname(int);
+__extern int getpt(void);
+
+static __inline__ int grantpt(int __fd)
+{
+  (void)__fd;
+  return 0;                    /* devpts does this all for us! */
+}
+
+#endif /* _STDLIB_H */
diff --git a/com32/include/string.h b/com32/include/string.h
new file mode 100644 (file)
index 0000000..3bbb217
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * string.h
+ */
+
+#ifndef _STRING_H
+#define _STRING_H
+
+#include <klibc/extern.h>
+#include <stddef.h>
+
+__extern void *memccpy(void *, const void *, int, size_t);
+__extern void *memchr(const void *, int, size_t);
+__extern int memcmp(const void *, const void *, size_t);
+__extern void *memcpy(void *, const void *, size_t);
+__extern void *memmove(void *, const void *, size_t);
+__extern void *memset(void *, int, size_t);
+__extern void *memmem(const void *, size_t, const void *, size_t);
+__extern void memswap(void *, void *, size_t);
+__extern int strcasecmp(const char *, const char *);
+__extern int strncasecmp(const char *, const char *, size_t);
+__extern char *strcat(char *, const char *);
+__extern char *strchr(const char *, int);
+__extern int strcmp(const char *, const char *);
+__extern char *strcpy(char *, const char *);
+__extern size_t strcspn(const char *, const char *);
+__extern char *strdup(const char *);
+__extern char *strndup(const char *, size_t);
+__extern char *strerror(int);
+__extern size_t strlen(const char *);
+__extern size_t strnlen(const char *, size_t);
+__extern char *strncat(char *, const char *, size_t);
+__extern size_t strlcat(char *, const char *, size_t);
+__extern int strncmp(const char *, const char *, size_t);
+__extern char *strncpy(char *, const char *, size_t);
+__extern size_t strlcpy(char *, const char *, size_t);
+__extern char *strpbrk(const char *, const char *);
+__extern char *strrchr(const char *, int);
+__extern char *strsep(char **, const char *);
+__extern size_t strspn(const char *, const char *);
+__extern char *strstr(const char *, const char *);
+__extern char *strtok(char *, const char *);
+
+#endif /* _STRING_H */
diff --git a/com32/include/sys/cpu.h b/com32/include/sys/cpu.h
new file mode 100644 (file)
index 0000000..1af2db7
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _CPU_H
+#define _CPU_H
+
+#include <inttypes.h>
+
+static inline uint64_t rdtsc(void)
+{
+  uint64_t v;
+  asm volatile("rdtsc" : "=A" (v));
+  return v;
+}
+
+static inline uint32_t rdtscl(void)
+{
+  uint32_t v;
+  asm volatile("rdtsc" : "=a" (v) : : "edx");
+  return v;
+}
+
+static inline uint32_t cpuid_eax(uint32_t level)
+{
+  uint32_t v;
+
+  asm("cpuid" : "=a" (v) : "a" (level) : "ebx", "ecx", "edx");
+  return v;
+}
+static inline uint32_t cpuid_ebx(uint32_t level)
+{
+  uint32_t v;
+
+  asm("cpuid" : "=b" (v),  "+a" (level) : : "ecx", "edx");
+  return v;
+}
+static inline uint32_t cpuid_ecx(uint32_t level)
+{
+  uint32_t v;
+
+  asm("cpuid" : "=c" (v), "+a" (level) : : "ebx", "edx");
+  return v;
+}
+static inline uint32_t cpuid_edx(uint32_t level)
+{
+  uint32_t v;
+
+  asm("cpuid" : "=d" (v), "+a" (level) : : "ebx", "ecx");
+  return v;
+}
+
+static inline uint64_t rdmsr(uint32_t msr)
+{
+  uint64_t v;
+  
+  asm volatile("rdmsr" : "=A" (v) : "c" (msr));
+  return v;
+}
+static inline void wrmsr(uint64_t v, uint32_t msr)
+{
+  asm volatile("wrmsr" : : "A" (v), "c" (msr));
+}
+
+static inline void cpu_relax(void)
+{
+  asm volatile("rep ; nop");
+}
+
+/* These are local cli/sti; not SMP-safe!!! */
+
+static inline void cli(void)
+{
+  asm volatile("cli");
+}
+
+static inline void sti(void)
+{
+  asm volatile("sti");
+}
+
+#endif
diff --git a/com32/include/sys/io.h b/com32/include/sys/io.h
new file mode 100644 (file)
index 0000000..460f230
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _SYS_IO_H
+#define _SYS_IO_H
+
+#include <inttypes.h>
+
+static inline uint8_t inb(uint16_t p)
+{
+  uint8_t v;
+  asm volatile("inb %1,%0" : "=a" (v) : "Nd" (p));
+  return v;
+}
+
+static inline uint16_t inw(uint16_t p)
+{
+  uint16_t v;
+  asm volatile("inw %1,%0" : "=a" (v) : "Nd" (p));
+  return v;
+}
+
+static inline uint32_t inl(uint16_t p)
+{
+  uint32_t v;
+  asm volatile("inl %1,%0" : "=a" (v) : "Nd" (p));
+  return v;
+}
+
+static inline void outb(uint8_t v, uint16_t p)
+{
+  asm volatile("outb %0,%1" : : "a" (v), "Nd" (p));
+}
+
+static inline void outw(uint16_t v, uint16_t p)
+{
+  asm volatile("outw %0,%1" : : "a" (v), "Nd" (p));
+}
+
+static inline void outl(uint32_t v, uint16_t p)
+{
+  asm volatile("outl %0,%1" : : "a" (v), "Nd" (p));
+}
+
+#endif /* _SYS_IO_H */
diff --git a/com32/include/sys/pci.h b/com32/include/sys/pci.h
new file mode 100644 (file)
index 0000000..9a01cc4
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _SYS_PCI_H
+#define _SYS_PCI_H
+
+#include <inttypes.h>
+#include <sys/io.h>
+
+typedef uint32_t pciaddr_t;
+
+static inline pciaddr_t pci_mkaddr(uint32_t bus, uint32_t dev,
+                                  uint32_t func, uint32_t reg)
+{
+  return 0x80000000 | ((bus & 0xff) << 16) | ((dev & 0x1f) << 11) |
+    ((func & 0x07) << 8) | (reg & 0xff);
+}
+
+uint8_t pci_read8(pciaddr_t a);
+uint16_t pci_read16(pciaddr_t a);
+uint32_t pci_read32(pciaddr_t a);
+void pci_write8(uint8_t v, pciaddr_t a);
+void pci_write16(uint16_t v, pciaddr_t a);
+void pci_write32(uint32_t v, pciaddr_t a);
+
+#endif /* _SYS_PCI_H */
diff --git a/com32/include/sys/types.h b/com32/include/sys/types.h
new file mode 100644 (file)
index 0000000..d7e9cba
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * sys/types.h
+ */
+
+#ifndef _SYS_TYPES_H
+#define _SYS_TYPES_H
+
+#include <klibc/compiler.h>
+#include <stddef.h>
+#include <stdint.h>
+
+typedef ptrdiff_t      ssize_t;
+typedef int            mode_t;
+typedef int64_t                off_t;
+
+#endif
diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG
new file mode 100644 (file)
index 0000000..0613664
--- /dev/null
@@ -0,0 +1,57 @@
+CC     = gcc
+LD     = ld
+INCLUDE        = -I.
+AR     = ar
+RANLIB = ranlib
+NM     = nm
+PERL   = perl
+STRIP  = strip --strip-all -R .comment -R .note
+OBJCOPY        = objcopy
+
+REQFLAGS  = -m32 -I. -I./sys -I../include
+OPTFLAGS  = -Os -march=i386 -falign-functions=0 -falign-jumps=0 -falign-labels=0
+WARNFLAGS = -W -Wall -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline
+
+CFLAGS  = -Wp,-MT,$@,-MD,$(dir $@).$(notdir $@).d $(OPTFLAGS) \
+         $(REQFLAGS) $(WARNFLAGS)
+LDFLAGS        = -m elf32_i386
+
+.SUFFIXES: .c .o .a .so .lo .i .S .s .ls .ss .lss
+
+% : %.c # Cancel default rule
+
+% : %.S
+
+.c.o:
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+.c.i:
+       $(CC) $(CFLAGS) -E -o $@ $<
+
+.c.s:
+       $(CC) $(CFLAGS) -S -o $@ $<
+
+.S.o:
+       $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
+
+.S.s:
+       $(CC) $(CFLAGS) -D__ASSEMBLY__ -E -o $@ $<
+
+.S.lo:
+       $(CC) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -c -o $@ $<
+
+.S.ls:
+       $(CC) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -E -o $@ $<
+
+.s.o:
+       $(CC) $(CFLAGS) -x assembler -c -o $@ $<
+
+.ls.lo:
+       $(CC) $(CFLAGS) $(SOFLAGS) -x assembler -c -o $@ $<
+
+.c.lo:
+       $(CC) $(CFLAGS) $(SOFLAGS) -c -o $@ $<
+
+.c.ls:
+       $(CC) $(CFLAGS) $(SOFLAGS) -S -o $@ $<
+
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
new file mode 100644 (file)
index 0000000..6b5ab01
--- /dev/null
@@ -0,0 +1,102 @@
+# Include configuration rules
+include MCONFIG
+
+LIBOBJS = \
+       abort.o \
+       atexit.o \
+       atoi.o \
+       atol.o \
+       atoll.o \
+       calloc.o \
+       creat.o \
+       ctypes.o \
+       errno.o \
+       fgetc.o \
+       fgets.o \
+       fopen.o \
+       fprintf.o \
+       fputc.o \
+       fputs.o \
+       fread2.o \
+       fread.o \
+       free.o \
+       fwrite2.o \
+       fwrite.o \
+       getopt.o \
+       lrand48.o \
+       malloc.o \
+       memccpy.o \
+       memchr.o \
+       memcmp.o \
+       memcpy.o \
+       memmem.o \
+       memmove.o \
+       memset.o \
+       memswap.o \
+       onexit.o \
+       perror.o \
+       printf.o \
+       puts.o \
+       qsort.o \
+       realloc.o \
+       seed48.o \
+       snprintf.o \
+       sprintf.o \
+       srand48.o \
+       sscanf.o \
+       stack.o \
+       strcasecmp.o \
+       strcat.o \
+       strchr.o \
+       strcmp.o \
+       strcpy.o \
+       strdup.o \
+       strerror.o \
+       strlen.o \
+       strncasecmp.o \
+       strncat.o \
+       strncmp.o \
+       strncpy.o \
+       strndup.o \
+       strntoimax.o \
+       strntoumax.o \
+       strrchr.o \
+       strsep.o \
+       strspn.o \
+       strstr.o \
+       strtoimax.o \
+       strtok.o \
+       strtol.o \
+       strtoll.o \
+       strtoul.o \
+       strtoull.o \
+       strtoumax.o \
+       vfprintf.o \
+       vprintf.o \
+       vsnprintf.o \
+       vsprintf.o \
+       vsscanf.o \
+       sys/entry.o sys/exit.o \
+       sys/open.o \
+       sys/fileinfo.o \
+       sys/close.o \
+       sys/read.o \
+       sys/write.o
+
+all: libcom32.a
+
+libcom32.a : $(LIBOBJS)
+       rm -f $@
+       $(AR) cq $@ $^
+       $(RANLIB) $@
+
+tidy:
+       rm -f *.o .*.d */*.o */.*.d
+
+clean: tidy
+       rm -f *.a
+
+spotless: clean
+       rm -f *~ \#* */*~ */\#*
+
+-include .*.d
diff --git a/com32/lib/abort.c b/com32/lib/abort.c
new file mode 100644 (file)
index 0000000..9280d98
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * abort.c
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+void abort(void)
+{
+  sigset_t set;
+
+  sigemptyset(&set);
+  sigaddset(&set, SIGABRT);
+  sigprocmask(SIG_UNBLOCK, &set, NULL);
+  raise(SIGABRT);
+  _exit(255);                  /* raise() should have killed us */
+}
+  
diff --git a/com32/lib/atexit.c b/com32/lib/atexit.c
new file mode 100644 (file)
index 0000000..078dd8b
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * atexit.c
+ */
+
+#include <stdlib.h>
+
+int atexit(void (*fctn)(void))
+{
+  return on_exit((void (*)(int, void *))fctn, NULL);
+}
diff --git a/com32/lib/atexit.h b/com32/lib/atexit.h
new file mode 100644 (file)
index 0000000..792141d
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * atexit.h
+ *
+ * atexit()/on_exit() internal definitions
+ */
+
+#ifndef ATEXIT_H
+#define ATEXIT_H
+
+struct atexit {
+  void (*fctn)(int, void *);
+  void *arg;                   /* on_exit() parameter */
+  struct atexit *next;
+};
+
+#endif /* ATEXIT_H */
+
diff --git a/com32/lib/atoi.c b/com32/lib/atoi.c
new file mode 100644 (file)
index 0000000..a6ec0bf
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE int
+#define NAME atoi
+#include "atox.c"
diff --git a/com32/lib/atol.c b/com32/lib/atol.c
new file mode 100644 (file)
index 0000000..e65484e
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE long
+#define NAME atol
+#include "atox.c"
diff --git a/com32/lib/atoll.c b/com32/lib/atoll.c
new file mode 100644 (file)
index 0000000..25df79e
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE long long
+#define NAME atoll
+#include "atox.c"
diff --git a/com32/lib/atox.c b/com32/lib/atox.c
new file mode 100644 (file)
index 0000000..56f8d93
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * atox.c
+ *
+ * atoi(), atol(), atoll()
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+TYPE NAME (const char *nptr)
+{
+  return (TYPE) strntoumax(nptr, (char **)NULL, 10, ~(size_t)0);
+}
diff --git a/com32/lib/calloc.c b/com32/lib/calloc.c
new file mode 100644 (file)
index 0000000..228a1b7
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * calloc.c
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+/* FIXME: This should look for multiplication overflow */
+
+void *calloc(size_t nmemb, size_t size)
+{
+  void *ptr;
+
+  size *= nmemb;
+  ptr = malloc(size);
+  if ( ptr )
+    memset(ptr, 0, size);
+
+  return ptr;
+}
+
diff --git a/com32/lib/creat.c b/com32/lib/creat.c
new file mode 100644 (file)
index 0000000..9bd2217
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * creat.c
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int creat(const char *pathname, mode_t mode)
+{
+  return open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode);
+}
diff --git a/com32/lib/ctypes.c b/com32/lib/ctypes.c
new file mode 100644 (file)
index 0000000..acfa05a
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * ctypes.c
+ *
+ * This is the array that defines <ctype.h> classes.
+ * This assumes ISO 8859-1.
+ */
+
+#include <ctype.h>
+
+const unsigned char __ctypes[257] = {
+  0,                           /* EOF */
+
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl|__ctype_space, /* BS */
+  __ctype_cntrl|__ctype_space, /* TAB */
+  __ctype_cntrl|__ctype_space, /* LF */
+  __ctype_cntrl|__ctype_space, /* VT */
+  __ctype_cntrl|__ctype_space, /* FF */
+  __ctype_cntrl|__ctype_space, /* CR */
+  __ctype_cntrl,               /* control character */
+
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  __ctype_cntrl,               /* control character */
+  
+  __ctype_print|__ctype_space, /* space */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_digit|__ctype_xdigit, /* digit */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_upper|__ctype_xdigit, /* A-F */
+  __ctype_print|__ctype_upper|__ctype_xdigit, /* A-F */
+  __ctype_print|__ctype_upper|__ctype_xdigit, /* A-F */
+  __ctype_print|__ctype_upper|__ctype_xdigit, /* A-F */
+  __ctype_print|__ctype_upper|__ctype_xdigit, /* A-F */
+  __ctype_print|__ctype_upper|__ctype_xdigit, /* A-F */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_upper, /* G-Z */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_lower|__ctype_xdigit, /* a-f */
+  __ctype_print|__ctype_lower|__ctype_xdigit, /* a-f */
+  __ctype_print|__ctype_lower|__ctype_xdigit, /* a-f */
+  __ctype_print|__ctype_lower|__ctype_xdigit, /* a-f */
+  __ctype_print|__ctype_lower|__ctype_xdigit, /* a-f */
+  __ctype_print|__ctype_lower|__ctype_xdigit, /* a-f */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_lower, /* g-z */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_cntrl,                               /* control character */
+
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+  __ctype_cntrl,                               /* control character */
+
+  __ctype_print|__ctype_space, /* NBSP */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_punct, /* punctuation */
+
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_upper, /* upper accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_punct, /* punctuation */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+  __ctype_print|__ctype_lower, /* lower accented */
+};
diff --git a/com32/lib/errno.c b/com32/lib/errno.c
new file mode 100644 (file)
index 0000000..f280e30
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * errno.c
+ *
+ */
+#include <errno.h>
+
+int errno;
diff --git a/com32/lib/exit.c b/com32/lib/exit.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/com32/lib/fgetc.c b/com32/lib/fgetc.c
new file mode 100644 (file)
index 0000000..83eee16
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * fgetc.c
+ *
+ * Extremely slow fgetc implementation, using _fread().  If people
+ * actually need character-oriented input to be fast, we may actually
+ * have to implement buffering.  Sigh.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+int fgetc(FILE *f)
+{
+  unsigned char ch;
+
+  return (_fread(&ch, 1, f) == 1) ? (int)ch : EOF;
+}
+
diff --git a/com32/lib/fgets.c b/com32/lib/fgets.c
new file mode 100644 (file)
index 0000000..88a145a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * fgets.c
+ *
+ * This will be very slow due to the implementation of getc(),
+ * but we can't afford to drain characters we don't need from
+ * the input.
+ */
+
+#include <stdio.h>
+
+char *fgets(char *s, int n, FILE *f)
+{
+  int ch;
+  char *p = s;
+
+  while ( n > 1 ) {
+    ch = getc(f);
+    if ( ch == EOF ) {
+      *p = '\0';
+      return NULL;
+    }
+    *p++ = ch;
+    if ( ch == '\n' )
+      break;
+  }
+  if ( n )
+    *p = '\0';
+  
+  return s;
+}
+
+
+    
diff --git a/com32/lib/fopen.c b/com32/lib/fopen.c
new file mode 100644 (file)
index 0000000..5c84184
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * fopen.c
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* This depends on O_RDONLY == 0, O_WRONLY == 1, O_RDWR == 2 */
+
+
+FILE *fopen(const char *file, const char *mode)
+{
+  int flags = O_RDONLY;
+  int plus = 0;
+  int fd;
+
+  while ( *mode ) {
+    switch ( *mode ) {
+    case 'r':
+      flags = O_RDONLY;
+      break;
+    case 'w':
+      flags = O_WRONLY|O_CREAT|O_TRUNC;
+      break;
+    case 'a':
+      flags = O_WRONLY|O_CREAT|O_APPEND;
+      break;
+    case '+':
+      plus = 1;
+      break;
+    }
+    mode++;
+  }
+
+  if ( plus ) {
+    flags = (flags & ~(O_RDONLY|O_WRONLY)) | O_RDWR;
+  }
+
+  fd = open(file, flags, 0666);
+
+  if ( fd < 0 )
+    return NULL;
+  else
+    return fdopen(fd, mode);
+}
diff --git a/com32/lib/fprintf.c b/com32/lib/fprintf.c
new file mode 100644 (file)
index 0000000..df3823e
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * fprintf.c
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#define BUFFER_SIZE    16384
+
+int fprintf(FILE *file, const char *format, ...)
+{
+  va_list ap;
+  int rv;
+
+  va_start(ap, format);
+  rv = vfprintf(file, format, ap);
+  va_end(ap);
+  return rv;
+}
diff --git a/com32/lib/fputc.c b/com32/lib/fputc.c
new file mode 100644 (file)
index 0000000..61aff16
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * fputc.c
+ *
+ * gcc "printf decompilation" expects this to exist...
+ */
+
+#include <stdio.h>
+
+int fputc(int c, FILE *f)
+{
+  unsigned char ch = c;
+
+  return _fwrite(&ch, 1, f) == 1 ? ch : EOF;
+}
diff --git a/com32/lib/fputs.c b/com32/lib/fputs.c
new file mode 100644 (file)
index 0000000..4b68f96
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * fputs.c
+ *
+ * This isn't quite fputs() in the stdio sense, since we don't
+ * have stdio, but it takes a file descriptor argument instead
+ * of the FILE *.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+int fputs(const char *s, FILE *file)
+{
+  return _fwrite(s, strlen(s), file);
+}
diff --git a/com32/lib/fread.c b/com32/lib/fread.c
new file mode 100644 (file)
index 0000000..8f7dba9
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * fread.c
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+
+size_t _fread(void *buf, size_t count, FILE *f)
+{
+  size_t bytes = 0;
+  ssize_t rv;
+  char *p = buf;
+
+  while ( count ) {
+    rv = read(fileno(f), p, count);
+    if ( rv == -1 ) {
+      if ( errno == EINTR )
+       continue;
+      else
+       break;
+    } else if ( rv == 0 ) {
+      break;
+    }
+
+    p += rv;
+    bytes += rv;
+    count -= rv;
+  }
+
+  return bytes;
+}
+
+    
+      
diff --git a/com32/lib/fread2.c b/com32/lib/fread2.c
new file mode 100644 (file)
index 0000000..9e5ac81
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * fread2.c
+ *
+ * The actual fread() function as a non-inline
+ */
+
+#define __NO_FREAD_FWRITE_INLINES
+#include <stdio.h>
+
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *f)
+{
+  return _fread(ptr, size*nmemb, f)/size;
+}
diff --git a/com32/lib/free.c b/com32/lib/free.c
new file mode 100644 (file)
index 0000000..aa17080
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * free.c
+ *
+ * Very simple linked-list based malloc()/free().
+ */
+
+#include <stdlib.h>
+#include "malloc.h"
+
+static struct free_arena_header *
+__free_block(struct free_arena_header *ah)
+{
+  struct free_arena_header *pah, *nah;
+
+  pah = ah->a.prev;
+  nah = ah->a.next;
+  if ( pah->a.type == ARENA_TYPE_FREE &&
+       (char *)pah+pah->a.size == (char *)ah ) {
+    /* Coalesce into the previous block */
+    pah->a.size += ah->a.size;
+    pah->a.next = nah;
+    nah->a.prev = pah;
+
+#ifdef DEBUG_MALLOC
+    ah->a.type = ARENA_TYPE_DEAD;
+#endif
+
+    ah = pah;
+    pah = ah->a.prev;
+  } else {
+    /* Need to add this block to the free chain */
+    ah->a.type = ARENA_TYPE_FREE;
+
+    ah->next_free = __malloc_head.next_free;
+    ah->prev_free = &__malloc_head;
+    __malloc_head.next_free = ah;
+    ah->next_free->prev_free = ah;
+  }
+
+  /* In either of the previous cases, we might be able to merge
+     with the subsequent block... */
+  if ( nah->a.type == ARENA_TYPE_FREE &&
+       (char *)ah+ah->a.size == (char *)nah ) {
+    ah->a.size += nah->a.size;
+
+    /* Remove the old block from the chains */
+    nah->next_free->prev_free = nah->prev_free;
+    nah->prev_free->next_free = nah->next_free;
+    ah->a.next = nah->a.next;
+    nah->a.next->a.prev = ah;
+
+#ifdef DEBUG_MALLOC
+    nah->a.type = ARENA_TYPE_DEAD;
+#endif
+  }
+
+  /* Return the block that contains the called block */
+  return ah;
+}
+
+void free(void *ptr)
+{
+  struct free_arena_header *ah;
+
+  if ( !ptr )
+    return;
+
+  ah = (struct free_arena_header *)
+    ((struct arena_header *)ptr - 1);
+
+#ifdef DEBUG_MALLOC
+  assert( ah->a.type == ARENA_TYPE_USED );
+#endif
+
+  __free_block(ah);
+
+  /* Here we could insert code to return memory to the system. */
+}
diff --git a/com32/lib/fwrite.c b/com32/lib/fwrite.c
new file mode 100644 (file)
index 0000000..0a73188
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * fwrite.c
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+
+size_t _fwrite(const void *buf, size_t count, FILE *f)
+{
+  size_t bytes = 0;
+  ssize_t rv;
+  const char *p = buf;
+
+  while ( count ) {
+    rv = write(fileno(f), p, count);
+    if ( rv == -1 ) {
+      if ( errno == EINTR )
+       continue;
+      else
+       break;
+    } else if ( rv == 0 ) {
+      break;
+    }
+
+    p += rv;
+    bytes += rv;
+    count -= rv;
+  }
+
+  return bytes;
+}
+
+    
+      
diff --git a/com32/lib/fwrite2.c b/com32/lib/fwrite2.c
new file mode 100644 (file)
index 0000000..82ec832
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * fwrite2.c
+ *
+ * The actual fwrite() function as a non-inline
+ */
+
+#define __NO_FREAD_FWRITE_INLINES
+#include <stdio.h>
+
+size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *f)
+{
+  return _fwrite(ptr, size*nmemb, f)/size;
+}
diff --git a/com32/lib/getopt.c b/com32/lib/getopt.c
new file mode 100644 (file)
index 0000000..5a992dc
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * getopt.c
+ *
+ * Simple POSIX getopt(), no GNU extensions...
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+char *optarg;
+int optind = 1;
+int opterr, optopt;
+static const char *__optptr;
+
+int getopt(int argc, char * const *argv, const char *optstring)
+{
+  const char *carg = argv[optind];
+  const char *osptr;
+  int opt;
+
+  /* We don't actually need argc */
+  (void)argc;
+
+  /* First, eliminate all non-option cases */
+  
+  if ( !carg || carg[0] != '-' || !carg[1] ) {
+    return -1;
+  }
+
+  if ( carg[1] == '-' && !carg[2] ) {
+    optind++;
+    return -1;
+  }
+
+  if ( (uintptr_t)(__optptr-carg) > (uintptr_t)strlen(carg) )
+    __optptr = carg+1; /* Someone frobbed optind, change to new opt. */
+
+  opt = *__optptr++;
+
+  if ( opt != ':' && (osptr = strchr(optstring, opt)) ) {
+    if ( osptr[1] == ':' ) {
+      if ( *__optptr ) {
+       /* Argument-taking option with attached argument */
+       optarg = (char *)__optptr;
+       optind++;
+      } else {
+       /* Argument-taking option with non-attached argument */
+       if ( argv[optind+1] ) {
+         optarg = (char *)argv[optind+1];
+         optind += 2;
+       } else {
+         /* Missing argument */
+         return (optstring[0] == ':') ? ':' : '?';
+       }
+      }
+      return opt;
+    } else {
+      /* Non-argument-taking option */
+      /* __optptr will remember the exact position to resume at */
+      if ( ! *__optptr )
+       optind++;
+      return opt;
+    }
+  } else {
+    /* Unknown option */
+    optopt = opt;
+    if ( ! *__optptr )
+      optind++;
+    return '?';
+  }
+}
+
+       
diff --git a/com32/lib/init.h b/com32/lib/init.h
new file mode 100644 (file)
index 0000000..2d98342
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * init.h
+ *
+ * Magic to set up initializers
+ */
+
+#ifndef _INIT_H
+#define _INIT_H 1
+
+#include <inttypes.h>
+
+#define COM32_INIT(x) static const void * const  __COM32_INIT \
+       __attribute__((section(".init_array"),unused)) = (const void * const)&x
+
+#endif /* _INIT_H */
diff --git a/com32/lib/lrand48.c b/com32/lib/lrand48.c
new file mode 100644 (file)
index 0000000..4d05de2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * lrand48.c
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+unsigned short __rand48_seed[3];
+
+long jrand48(unsigned short xsubi[3])
+{
+  uint64_t x;
+
+  /* The xsubi[] array is littleendian by spec */
+  x = (uint64_t)xsubi[0] +
+    ((uint64_t)xsubi[1] << 16) +
+    ((uint64_t)xsubi[2] << 32);
+
+  x = (0x5deece66dULL * x) + 0xb;
+  
+  xsubi[0] = (unsigned short)x;
+  xsubi[1] = (unsigned short)(x >> 16);
+  xsubi[2] = (unsigned short)(x >> 32);
+
+  return (long)(int32_t)(x >> 16);
+}
+
+long mrand48(void)
+{
+  return jrand48(__rand48_seed);
+}
+
+long nrand48(unsigned short xsubi[3])
+{
+  return (long)((uint32_t)jrand48(xsubi) >> 1);
+}
+
+long lrand48(void)
+{
+  return (long)((uint32_t)(mrand48() >> 1));
+}
+
diff --git a/com32/lib/malloc.c b/com32/lib/malloc.c
new file mode 100644 (file)
index 0000000..4efd89c
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * malloc.c
+ *
+ * Very simple linked-list based malloc()/free().
+ */
+
+#include <stdlib.h>
+#include "init.h"
+#include "malloc.h"
+
+struct free_arena_header __malloc_head =
+{
+  {
+    ARENA_TYPE_HEAD,
+    0,
+    &__malloc_head,
+    &__malloc_head,
+  },
+  &__malloc_head,
+  &__malloc_head
+};
+
+/* This is extern so it can be overridden by the user application */
+extern size_t __stack_size;
+
+static inline size_t sp(void)
+{
+  size_t sp;
+  asm volatile("movl %%esp,%0" : "=rm" (sp));
+  return sp;
+}
+
+static void __constructor init_memory_arena(void)
+{
+  extern char _end[];          /* Symbol created by the linker */
+  struct free_arena_header *fp;
+  size_t start, total_space;
+
+  start = (size_t)ARENA_ALIGN_UP(_end);
+  total_space = sp() - start;
+
+  if ( __stack_size == 0 || __stack_size > total_space >> 1 )
+    __stack_size = total_space >> 1; /* Half for the stack, half for the heap... */
+  
+  if ( total_space < __stack_size + 4*sizeof(struct arena_header) )
+    __stack_size = total_space - 4*sizeof(struct arena_header);
+
+  fp = (struct free_arena_header *)start;
+  fp->a.type = ARENA_TYPE_FREE;
+  fp->a.size = total_space - __stack_size;
+  
+  /* Insert into chains */
+  fp->a.next = fp->a.prev = &__malloc_head;
+  fp->next_free = fp->prev_free = &__malloc_head;
+  __malloc_head.a.next = __malloc_head.a.prev = fp;
+  __malloc_head.next_free = __malloc_head.prev_free = fp;
+}
+
+static void *__malloc_from_block(struct free_arena_header *fp, size_t size)
+{
+  size_t fsize;
+  struct free_arena_header *nfp, *na;
+
+  fsize = fp->a.size;
+  
+  /* We need the 2* to account for the larger requirements of a free block */
+  if ( fsize >= size+2*sizeof(struct arena_header) ) {
+    /* Bigger block than required -- split block */
+    nfp = (struct free_arena_header *)((char *)fp + size);
+    na = fp->a.next;
+
+    nfp->a.type = ARENA_TYPE_FREE;
+    nfp->a.size = fsize-size;
+    fp->a.type  = ARENA_TYPE_USED;
+    fp->a.size  = size;
+
+    /* Insert into all-block chain */
+    nfp->a.prev = fp;
+    nfp->a.next = na;
+    na->a.prev = nfp;
+    fp->a.next = nfp;
+    
+    /* Replace current block on free chain */
+    nfp->next_free = fp->next_free;
+    nfp->prev_free = fp->prev_free;
+    fp->next_free->prev_free = nfp;
+    fp->prev_free->next_free = nfp;
+  } else {
+    /* Allocate the whole block */
+    fp->a.type = ARENA_TYPE_USED;
+
+    /* Remove from free chain */
+    fp->next_free->prev_free = fp->prev_free;
+    fp->prev_free->next_free = fp->next_free;
+  }
+  
+  return (void *)(&fp->a + 1);
+}
+
+void *malloc(size_t size)
+{
+  struct free_arena_header *fp;
+
+  if ( size == 0 )
+    return NULL;
+
+  /* Add the obligatory arena header, and round up */
+  size = (size+2*sizeof(struct arena_header)-1) & ARENA_SIZE_MASK;
+
+  for ( fp = __malloc_head.next_free ; fp->a.type != ARENA_TYPE_HEAD ;
+       fp = fp->next_free ) {
+    if ( fp->a.size >= size ) {
+      /* Found fit -- allocate out of this block */
+      return __malloc_from_block(fp, size);
+    }
+  }
+
+  /* Nothing found... need to request a block from the kernel */
+  return NULL;                 /* No kernel to get stuff from */
+}
diff --git a/com32/lib/memccpy.c b/com32/lib/memccpy.c
new file mode 100644 (file)
index 0000000..22f68de
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * memccpy.c
+ *
+ * memccpy()
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+void *memccpy(void *dst, const void *src, int c, size_t n)
+{
+  char *q = dst;
+  const char *p = src;
+  char ch;
+
+  while ( n-- ) {
+    *q++ = ch = *p++;
+    if ( ch == (char)c )
+      return q;
+  }
+
+  return NULL;                 /* No instance of "c" found */
+}
diff --git a/com32/lib/memchr.c b/com32/lib/memchr.c
new file mode 100644 (file)
index 0000000..c5c5fa2
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * memchr.c
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+void *memchr(const void *s, int c, size_t n)
+{
+  const unsigned char *sp = s;
+
+  while ( n-- ) {
+    if ( *sp == (unsigned char)c )
+      return (void *)sp;
+  }
+
+  return NULL;
+}
diff --git a/com32/lib/memcmp.c b/com32/lib/memcmp.c
new file mode 100644 (file)
index 0000000..f6bc172
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * memcmp.c
+ */
+
+#include <string.h>
+
+int memcmp(const void *s1, const void *s2, size_t n)
+{
+  const unsigned char *c1 = s1, *c2 = s2;
+  int d = 0;
+
+  while ( n-- ) {
+    d = (int)*c1++ - (int)*c2++;
+    if ( d )
+      break;
+  }
+
+  return d;
+}
diff --git a/com32/lib/memcpy.c b/com32/lib/memcpy.c
new file mode 100644 (file)
index 0000000..b9171c3
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * memcpy.c
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+void *memcpy(void *dst, const void *src, size_t n)
+{
+  const char *p = src;
+  char *q = dst;
+#if defined(__i386__)
+  size_t nl = n >> 2;
+  asm volatile("cld ; rep ; movsl ; movl %3,%0 ; rep ; movsb"
+              : "+c" (nl), "+S" (p), "+D" (q)
+              : "r" (n & 3));
+#elif defined(__x86_64__)
+  size_t nq = n >> 3;
+  asm volatile("cld ; rep ; movsq ; movl %3,%%ecx ; rep ; movsb"
+              : "+c" (nq), "+S" (p), "+D" (q)
+              : "r" ((uint32_t)(n & 7)));
+#else
+  while ( n-- ) {
+    *q++ = *p++;
+  }
+#endif
+
+  return dst;
+}
diff --git a/com32/lib/memmem.c b/com32/lib/memmem.c
new file mode 100644 (file)
index 0000000..0f59938
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * memmem.c
+ *
+ * Find a byte string inside a longer byte string
+ *
+ * This uses the "Not So Naive" algorithm, a very simple but
+ * usually effective algorithm, see:
+ *
+ * http://www-igm.univ-mlv.fr/~lecroq/string/
+ */
+
+#include <string.h>
+
+void *memmem(const void *haystack, size_t n, const void *needle, size_t m)
+{
+  const unsigned char *y = (const unsigned char *)haystack;
+  const unsigned char *x = (const unsigned char *)needle;
+
+  size_t j, k, l;
+
+  if ( m > n )
+    return NULL;
+
+  if ( x[0] == x[1] ) {
+    k = 2;
+    l = 1;
+  } else {
+    k = 1;
+    l = 2;
+  }
+
+  j = 0;
+  while ( j <= n-m ) {
+    if (x[1] != y[j+1]) {
+      j += k;
+    } else {
+      if ( !memcmp(x+2, y+j+2, m-2) && x[0] == y[j] )
+       return (void *)&y[j];
+      j += l;
+    }
+  }
+
+  return NULL;
+}
diff --git a/com32/lib/memmove.c b/com32/lib/memmove.c
new file mode 100644 (file)
index 0000000..c1f042a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * memmove.c
+ */
+
+#include <string.h>
+
+void *memmove(void *dst, const void *src, size_t n)
+{
+  const char *p = src;
+  char *q = dst;
+#if defined(__i386__) || defined(__x86_64__)
+  if ( q < p ) {
+    asm volatile("cld ; rep ; movsb" : "+c" (n), "+S" (p), "+D" (q));
+  } else {
+    p += (n-1);
+    q += (n-1);
+    asm volatile("std ; rep ; movsb" : "+c" (n), "+S" (p), "+D" (q));
+  }
+#else
+  if ( q < p ) {
+    while ( n-- ) {
+      *q++ = *p++;
+    }
+  } else {
+    p += n;
+    q += n;
+    while ( n-- ) {
+      *--q = *--p;
+    }
+  }
+#endif
+
+  return dst;
+}
diff --git a/com32/lib/memset.c b/com32/lib/memset.c
new file mode 100644 (file)
index 0000000..522cc59
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * memset.c
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+void *memset(void *dst, int c, size_t n)
+{
+  char *q = dst;
+
+#if defined(__i386__)
+  size_t nl = n >> 2;
+  asm volatile("cld ; rep ; stosl ; movl %3,%0 ; rep ; stosb"
+              : "+c" (nl), "+D" (q)
+              : "a" ((unsigned char)c * 0x01010101U), "r" (n & 3));
+#elif defined(__x86_64__)
+  size_t nq = n >> 3;
+  asm volatile("cld ; rep ; stosq ; movl %3,%%ecx ; rep ; stosb"
+              : "+c" (nq), "+D" (q)
+              : "a" ((unsigned char)c * 0x0101010101010101U),
+              "r" ((uint32_t)n & 7));
+#else
+  while ( n-- ) {
+    *q++ = c;
+  }
+#endif
+
+  return dst;
+}
diff --git a/com32/lib/memswap.c b/com32/lib/memswap.c
new file mode 100644 (file)
index 0000000..10440e3
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * memswap()
+ *
+ * Swaps the contents of two nonoverlapping memory areas.
+ * This really could be done faster...
+ */
+
+#include <string.h>
+
+void memswap(void *m1, void *m2, size_t n)
+{
+  char *p = m1;
+  char *q = m2;
+  char tmp;
+
+  while ( n-- ) {
+    tmp = *p;
+    *p = *q;
+    *q = tmp;
+    
+    p++; q++;
+  }
+}
diff --git a/com32/lib/onexit.c b/com32/lib/onexit.c
new file mode 100644 (file)
index 0000000..70a9c01
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * onexit.c
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "atexit.h"
+
+extern __noreturn (*__exit_handler)(int);
+static struct atexit *__atexit_list;
+
+static __noreturn on_exit_exit(int rv)
+{
+  struct atexit *ap;
+  
+  for ( ap = __atexit_list ; ap ; ap = ap->next ) {
+    ap->fctn(rv, ap->arg);     /* This assumes extra args are harmless */
+  }
+  
+  _exit(rv);
+}
+
+int on_exit(void (*fctn)(int, void *), void *arg)
+{
+  struct atexit *as = malloc(sizeof(struct atexit));
+
+  if ( !as )
+    return -1;
+
+  as->fctn = fctn;
+  as->arg  = arg;
+
+  as->next = __atexit_list;
+  __atexit_list = as;
+
+  __exit_handler = on_exit_exit;
+
+  return 0;
+}
diff --git a/com32/lib/perror.c b/com32/lib/perror.c
new file mode 100644 (file)
index 0000000..45585cd
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * perror.c
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+void perror(const char *s)
+{
+  fprintf(stderr, "%s: error %d\n", s, errno);
+}
diff --git a/com32/lib/printf.c b/com32/lib/printf.c
new file mode 100644 (file)
index 0000000..3423759
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * printf.c
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#define BUFFER_SIZE    16384
+
+int printf(const char *format, ...)
+{
+  va_list ap;
+  int rv;
+
+  va_start(ap, format);
+  rv = vfprintf(stdout, format, ap);
+  va_end(ap);
+  return rv;
+}
diff --git a/com32/lib/puts.c b/com32/lib/puts.c
new file mode 100644 (file)
index 0000000..ecebf27
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * puts.c
+ */
+
+#include <stdio.h>
+
+int puts(const char *s)
+{
+  if ( fputs(s, stdout) < 0 )
+    return -1;
+
+  return _fwrite("\n", 1, stdout);
+}
diff --git a/com32/lib/qsort.c b/com32/lib/qsort.c
new file mode 100644 (file)
index 0000000..e2197ea
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * qsort.c
+ *
+ * This is actually combsort.  It's an O(n log n) algorithm with
+ * simplicity/small code size being its main virtue.
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+static inline size_t newgap(size_t gap)
+{
+  gap = (gap*10)/13;
+  if ( gap == 9 || gap == 10 )
+    gap = 11;
+
+  if ( gap < 1 )
+    gap = 1;
+  return gap;
+}
+
+void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
+{
+  size_t gap = nmemb;
+  size_t i, j;
+  void *p1, *p2;
+  int swapped;
+
+  do {
+    gap = newgap(gap);
+    swapped = 0;
+    
+    for ( i = 0, p1 = base ; i < nmemb-gap ; i++, (char *)p1 += size ) {
+      j = i+gap;
+      if ( compar(p1, p2 = (char *)base+j*size) > 0 ) {
+       memswap(p1, p2, size);
+       swapped = 1;
+      }
+    }
+  } while ( gap > 1 || swapped );
+}
+
diff --git a/com32/lib/realloc.c b/com32/lib/realloc.c
new file mode 100644 (file)
index 0000000..577c200
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * realloc.c
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "malloc.h"
+
+/* FIXME: This is cheesy, it should be fixed later */
+
+void *realloc(void *ptr, size_t size)
+{
+  struct free_arena_header *ah;
+  void *newptr;
+  size_t oldsize;
+
+  if ( !ptr )
+    return malloc(size);
+
+  if ( size == 0 ) {
+    free(ptr);
+    return NULL;
+  }
+
+  /* Add the obligatory arena header, and round up */
+  size = (size+2*sizeof(struct arena_header)-1) & ARENA_SIZE_MASK;
+
+  ah = (struct free_arena_header *)
+    ((struct arena_header *)ptr - 1);
+
+  if ( ah->a.size >= size && size >= (ah->a.size >> 2) ) {
+    /* This field is a good size already. */
+    return ptr;
+  } else {
+    /* Make me a new block.  This is kind of bogus; we should
+       be checking the adjacent blocks to see if we can do an
+       in-place adjustment... fix that later. */
+    
+    oldsize = ah->a.size - sizeof(struct arena_header);
+
+    newptr = malloc(size);
+    memcpy(newptr, ptr, (size < oldsize) ? size : oldsize);
+    free(ptr);
+
+    return newptr;
+  }
+}
+  
diff --git a/com32/lib/seed48.c b/com32/lib/seed48.c
new file mode 100644 (file)
index 0000000..f8353c8
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * seed48.c
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+extern unsigned short __rand48_seed[3];
+
+unsigned short *seed48(const unsigned short xsubi[3])
+{
+  static unsigned short oldseed[3];
+  memcpy(oldseed, __rand48_seed, sizeof __rand48_seed);
+  memcpy(__rand48_seed, xsubi, sizeof __rand48_seed);
+  
+  return oldseed;
+}
+
diff --git a/com32/lib/setjmp.S b/com32/lib/setjmp.S
new file mode 100644 (file)
index 0000000..bea900c
--- /dev/null
@@ -0,0 +1,58 @@
+#
+# arch/i386/setjmp.S
+#
+# setjmp/longjmp for the i386 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+#      %ebx
+#      %esp
+#      %ebp
+#      %esi
+#      %edi
+#      <return address>
+#
+
+       .text
+       .align 4
+       .globl setjmp
+       .type setjmp, @function
+setjmp:
+#ifdef REGPARM
+       movl %eax,%edx
+#else
+       movl 4(%esp),%edx
+#endif 
+       popl %ecx                       # Return address, and adjust the stack
+       xorl %eax,%eax                  # Return value
+       movl %ebx,(%edx)
+       movl %esp,4(%edx)               # Post-return %esp!
+       pushl %ecx                      # Make the call/return stack happy
+       movl %ebp,8(%edx)
+       movl %esi,12(%edx)
+       movl %edi,16(%edx)
+       movl %ecx,20(%edx)              # Return address
+       ret
+
+       .size setjmp,.-setjmp
+
+       .text
+       .align 4
+       .globl longjmp
+       .type longjmp, @function
+longjmp:
+#ifdef REGPARM
+       xchgl %eax,%edx
+#else
+       movl 4(%esp),%edx               # jmp_ptr address
+       movl 8(%esp),%eax               # Return value
+#endif
+       movl (%edx),%ebx
+       movl 4(%edx),%esp
+       movl 8(%edx),%ebp
+       movl 12(%edx),%esi
+       movl 16(%edx),%edi
+       jmp *20(%edx)
+
+       .size longjmp,.-longjmp
diff --git a/com32/lib/snprintf.c b/com32/lib/snprintf.c
new file mode 100644 (file)
index 0000000..c642851
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * snprintf.c
+ */
+
+#include <stdio.h>
+
+int snprintf(char *buffer, size_t n, const char *format, ...)
+{
+  va_list ap;
+  int rv;
+
+  va_start(ap, format);
+  rv = vsnprintf(buffer, n, format, ap);
+  va_end(ap);
+  return rv;
+}
diff --git a/com32/lib/sprintf.c b/com32/lib/sprintf.c
new file mode 100644 (file)
index 0000000..31f28af
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * sprintf.c
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+int sprintf(char *buffer, const char *format, ...)
+{
+  va_list ap;
+  int rv;
+
+  va_start(ap, format);
+  rv = vsnprintf(buffer, ~(size_t)0, format, ap);
+  va_end(ap);
+
+  return rv;
+}
diff --git a/com32/lib/srand48.c b/com32/lib/srand48.c
new file mode 100644 (file)
index 0000000..a3df16d
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * srand48.c
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+extern unsigned short __rand48_seed[3];
+
+
+void srand48(long seedval)
+{
+  __rand48_seed[0] = 0x330e;
+  __rand48_seed[1] = (unsigned short)seedval;
+  __rand48_seed[2] = (unsigned short)((uint32_t)seedval >> 16);
+}
diff --git a/com32/lib/sscanf.c b/com32/lib/sscanf.c
new file mode 100644 (file)
index 0000000..81aab9e
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * sscanf()
+ */
+
+#include <stdio.h>
+
+int sscanf(const char *str, const char *format, ...)
+{
+  va_list ap;
+  int rv;
+
+  va_start(ap, format);
+  rv = vsscanf(str, format, ap);
+  va_end(ap);
+
+  return rv;
+}
diff --git a/com32/lib/stack.c b/com32/lib/stack.c
new file mode 100644 (file)
index 0000000..e778e8e
--- /dev/null
@@ -0,0 +1,4 @@
+#include <stdlib.h>
+
+/* Default stack size 8 MB */
+size_t stack_size = 8 << 20;
diff --git a/com32/lib/strcasecmp.c b/com32/lib/strcasecmp.c
new file mode 100644 (file)
index 0000000..12aef40
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * strcasecmp.c
+ */
+
+#include <string.h>
+#include <ctype.h>
+
+int strcasecmp(const char *s1, const char *s2)
+{
+  const unsigned char *c1 = s1, *c2 = s2;
+  unsigned char ch;
+  int d = 0;
+
+  while ( 1 ) {
+    /* toupper() expects an unsigned char (implicitly cast to int)
+       as input, and returns an int, which is exactly what we want. */
+    d = toupper(ch = *c1++) - toupper(*c2++);
+    if ( d || !ch )
+      break;
+  }
+
+  return d;
+}
diff --git a/com32/lib/strcat.c b/com32/lib/strcat.c
new file mode 100644 (file)
index 0000000..a5f9477
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * strcat.c
+ */
+
+#include <string.h>
+
+char *strcat(char *dst, const char *src)
+{
+  strcpy(strchr(dst, '\0'), src);
+  return dst;
+}
diff --git a/com32/lib/strchr.c b/com32/lib/strchr.c
new file mode 100644 (file)
index 0000000..192f836
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * strchr.c
+ */
+
+#include <string.h>
+
+char *strchr(const char *s, int c)
+{
+  while ( *s != (char)c ) {
+    if ( ! *s )
+      return NULL;
+    s++;
+  }
+
+  return (char *)s;
+}
diff --git a/com32/lib/strcmp.c b/com32/lib/strcmp.c
new file mode 100644 (file)
index 0000000..f44774f
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * strcmp.c
+ */
+
+#include <string.h>
+
+int strcmp(const char *s1, const char *s2)
+{
+  const unsigned char *c1 = s1, *c2 = s2;
+  unsigned char ch;
+  int d = 0;
+
+  while ( 1 ) {
+    d = (int)(ch = *c1++) - (int)*c2++;
+    if ( d || !ch )
+      break;
+  }
+
+  return d;
+}
diff --git a/com32/lib/strcpy.c b/com32/lib/strcpy.c
new file mode 100644 (file)
index 0000000..8372eba
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * strcpy.c
+ *
+ * strcpy()
+ */
+
+#include <string.h>
+
+char *strcpy(char *dst, const char *src)
+{
+  char *q = dst;
+  const char *p = src;
+  char ch;
+
+  do {
+    *q++ = ch = *p++;
+  } while ( ch );
+
+  return dst;
+}
diff --git a/com32/lib/strdup.c b/com32/lib/strdup.c
new file mode 100644 (file)
index 0000000..eb170c2
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * strdup.c
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+char *strdup(const char *s)
+{
+  int l = strlen(s)+1;
+  char *d = malloc(l);
+
+  if ( d )
+    memcpy(d, s, l);
+
+  return d;
+}
diff --git a/com32/lib/strerror.c b/com32/lib/strerror.c
new file mode 100644 (file)
index 0000000..6270555
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * strerror.c
+ */
+
+#include <string.h>
+
+char *strerror(int errnum)
+{
+  static char message[32] = "error "; /* enough for error 2^63-1 */
+
+  char numbuf[32];
+  char *p;
+
+  p = numbuf+sizeof numbuf;
+  *--p = '\0';
+
+  do {
+    *--p = (errnum % 10) + '0';
+    errnum /= 10;
+  } while ( errnum );
+
+  return (char *)memcpy(message+6, p, (numbuf+sizeof numbuf)-p);
+}
+
diff --git a/com32/lib/strlen.c b/com32/lib/strlen.c
new file mode 100644 (file)
index 0000000..4d773f9
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * strlen()
+ */
+
+#include <string.h>
+
+size_t strlen(const char *s)
+{
+  const char *ss = s;
+  while ( *ss )
+    ss++;
+  return ss-s;
+}
+
diff --git a/com32/lib/strncasecmp.c b/com32/lib/strncasecmp.c
new file mode 100644 (file)
index 0000000..3309d1a
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * strncasecmp.c
+ */
+
+#include <string.h>
+#include <ctype.h>
+
+int strncasecmp(const char *s1, const char *s2, size_t n)
+{
+  const unsigned char *c1 = s1, *c2 = s2;
+  unsigned char ch;
+  int d = 0;
+
+  while ( n-- ) {
+    /* toupper() expects an unsigned char (implicitly cast to int)
+       as input, and returns an int, which is exactly what we want. */
+    d = toupper(ch = *c1++) - toupper(*c2++);
+    if ( d || !ch )
+      break;
+  }
+
+  return d;
+}
diff --git a/com32/lib/strncat.c b/com32/lib/strncat.c
new file mode 100644 (file)
index 0000000..99d9575
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * strncat.c
+ */
+
+#include <string.h>
+
+char *strncat(char *dst, const char *src, size_t n)
+{
+  strncpy(strchr(dst, '\0'), src, n);
+  return dst;
+}
diff --git a/com32/lib/strncmp.c b/com32/lib/strncmp.c
new file mode 100644 (file)
index 0000000..4dbde13
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * strncmp.c
+ */
+
+#include <string.h>
+
+int strncmp(const char *s1, const char *s2, size_t n)
+{
+  const unsigned char *c1 = s1, *c2 = s2;
+  unsigned char ch;
+  int d = 0;
+
+  while ( n-- ) {
+    d = (int)(ch = *c1++) - (int)*c2++;
+    if ( d || !ch )
+      break;
+  }
+
+  return d;
+}
diff --git a/com32/lib/strncpy.c b/com32/lib/strncpy.c
new file mode 100644 (file)
index 0000000..a8fe45f
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * strncpy.c
+ *
+ * strncpy()
+ */
+
+#include <string.h>
+
+char *strncpy(char *dst, const char *src, size_t n)
+{
+  char *q = dst;
+  const char *p = src;
+  char ch;
+
+  while ( n-- ) {
+    *q++ = ch = *p++;
+    if ( !ch )
+      break;
+  }
+
+  return dst;
+}
diff --git a/com32/lib/strndup.c b/com32/lib/strndup.c
new file mode 100644 (file)
index 0000000..1b44e6f
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * strndup.c
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+char *strndup(const char *s, size_t n)
+{
+       int l = n > strlen(s) ? strlen(s)+1 : n+1;
+       char *d = malloc(l);
+
+       if (d)
+               memcpy(d, s, l);
+       d[n] = '\0';
+       return d;
+}
diff --git a/com32/lib/strntoimax.c b/com32/lib/strntoimax.c
new file mode 100644 (file)
index 0000000..f53a266
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * strntoimax.c
+ *
+ * strntoimax()
+ */
+
+#include <stddef.h>
+#include <inttypes.h>
+
+intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n)
+{
+  return (intmax_t) strntoumax(nptr, endptr, base, n);
+}
diff --git a/com32/lib/strntoumax.c b/com32/lib/strntoumax.c
new file mode 100644 (file)
index 0000000..4e30637
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * strntoumax.c
+ *
+ * The strntoumax() function and associated
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ctype.h>
+
+static inline int digitval(int ch)
+{
+  if ( ch >= '0' && ch <= '9' ) {
+    return ch-'0';
+  } else if ( ch >= 'A' && ch <= 'Z' ) {
+    return ch-'A'+10;
+  } else if ( ch >= 'a' && ch <= 'z' ) {
+    return ch-'a'+10;
+  } else {
+    return -1;
+  }
+}
+
+uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n)
+{
+  int minus = 0;
+  uintmax_t v = 0;
+  int d;
+
+  while ( n && isspace((unsigned char)*nptr) ) {
+    nptr++;
+    n--;
+  }
+
+  /* Single optional + or - */
+  if ( n && *nptr == '-' ) {
+    minus = 1;
+    nptr++;
+    n--;
+  } else if ( n && *nptr == '+' ) {
+    nptr++;
+  }
+
+  if ( base == 0 ) {
+    if ( n >= 2 && nptr[0] == '0' &&
+        (nptr[1] == 'x' || nptr[1] == 'X') ) {
+      n -= 2;
+      nptr += 2;
+      base = 16;
+    } else if ( n >= 1 && nptr[0] == '0' ) {
+      n--;
+      nptr++;
+      base = 8;
+    } else {
+      base = 10;
+    }
+  } else if ( base == 16 ) {
+    if ( n >= 2 && nptr[0] == '0' &&
+        (nptr[1] == 'x' || nptr[1] == 'X') ) {
+      n -= 2;
+      nptr += 2;
+    }
+  }
+
+  while ( n && (d = digitval(*nptr)) >= 0 && d < base ) {
+    v = v*base + d;
+    n--;
+    nptr++;
+  }
+
+  if ( endptr )
+    *endptr = (char *)nptr;
+
+  return minus ? -v : v;
+}
diff --git a/com32/lib/strrchr.c b/com32/lib/strrchr.c
new file mode 100644 (file)
index 0000000..3b42464
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * strrchr.c
+ */
+
+#include <string.h>
+
+char *strrchr(const char *s, int c)
+{
+  const char *found = NULL;
+  
+  while ( *s ) {
+    if ( *s == (char) c )
+      found = s;
+    s++;
+  }
+
+  return (char *)found;
+}
diff --git a/com32/lib/strsep.c b/com32/lib/strsep.c
new file mode 100644 (file)
index 0000000..58a7a07
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * strsep.c
+ */
+
+#include <string.h>
+
+char *strsep(char **stringp, const char *delim)
+{
+  char *s = *stringp;
+  char *e;
+
+  if ( !s )
+    return NULL;
+
+  e = strpbrk(s, delim);
+  if (e)
+    *e++ = '\0';
+
+  *stringp = e;
+  return s;
+}
diff --git a/com32/lib/strspn.c b/com32/lib/strspn.c
new file mode 100644 (file)
index 0000000..856a964
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * strspn, strcspn
+ */
+
+#include <string.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <limits.h>
+
+#ifndef LONG_BIT
+#define LONG_BIT (CHAR_BIT*sizeof(long))
+#endif
+
+static inline void
+set_bit(unsigned long *bitmap, unsigned int bit)
+{
+  bitmap[bit/LONG_BIT] |= 1UL << (bit%LONG_BIT);
+}
+
+static inline int
+test_bit(unsigned long *bitmap, unsigned int bit)
+{
+  return (int)(bitmap[bit/LONG_BIT] >> (bit%LONG_BIT)) & 1;
+}
+
+static size_t
+strxspn(const char *s, const char *map, int parity)
+{
+  unsigned long matchmap[((1 << CHAR_BIT)+LONG_BIT-1)/LONG_BIT];
+  size_t n = 0;
+
+  /* Create bitmap */
+  memset(matchmap, 0, sizeof matchmap);
+  while ( *map )
+    set_bit(matchmap, (unsigned char) *map++);
+
+  /* Make sure the null character never matches */
+  if ( parity )
+    set_bit(matchmap, 0);
+
+  /* Calculate span length */
+  while ( test_bit(matchmap, (unsigned char) *s++)^parity )
+    n++;
+
+  return n;
+}
+
+size_t
+strspn(const char *s, const char *accept)
+{
+  return strxspn(s, accept, 0);
+}
+
+size_t
+strcspn(const char *s, const char *reject)
+{
+  return strxspn(s, reject, 1);
+}
+
+char *
+strpbrk(const char *s, const char *accept)
+{
+  const char *ss = s+strxspn(s, accept, 1);
+  
+  return *ss ? (char *)ss : NULL;
+}
+
diff --git a/com32/lib/strstr.c b/com32/lib/strstr.c
new file mode 100644 (file)
index 0000000..10222df
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * strstr.c
+ */
+
+#include <string.h>
+
+char *strstr(const char *haystack, const char *needle)
+{
+  return (char *)memmem(haystack, strlen(haystack), needle, strlen(needle));
+}
diff --git a/com32/lib/strtoimax.c b/com32/lib/strtoimax.c
new file mode 100644 (file)
index 0000000..0cdd088
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE intmax_t
+#define NAME strtoimax
+#include "strtox.c"
diff --git a/com32/lib/strtok.c b/com32/lib/strtok.c
new file mode 100644 (file)
index 0000000..6e84f1d
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * strtok.c
+ */
+
+#include <string.h>
+
+char *strtok(char *s, const char *delim)
+{
+  static char *holder;
+
+  if ( s )
+    holder = s;
+
+  return strsep(&holder, delim);
+}
+
diff --git a/com32/lib/strtol.c b/com32/lib/strtol.c
new file mode 100644 (file)
index 0000000..9efc8b9
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE signed long
+#define NAME strtol
+#include "strtox.c"
diff --git a/com32/lib/strtoll.c b/com32/lib/strtoll.c
new file mode 100644 (file)
index 0000000..a9428c7
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE signed long long
+#define NAME strtoll
+#include "strtox.c"
diff --git a/com32/lib/strtoul.c b/com32/lib/strtoul.c
new file mode 100644 (file)
index 0000000..3189aaa
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE unsigned long
+#define NAME strtoul
+#include "strtox.c"
diff --git a/com32/lib/strtoull.c b/com32/lib/strtoull.c
new file mode 100644 (file)
index 0000000..83c14e9
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE unsigned long long
+#define NAME strtoull
+#include "strtox.c"
diff --git a/com32/lib/strtoumax.c b/com32/lib/strtoumax.c
new file mode 100644 (file)
index 0000000..a379710
--- /dev/null
@@ -0,0 +1,3 @@
+#define TYPE uintmax_t
+#define NAME strtoumax
+#include "strtox.c"
diff --git a/com32/lib/strtox.c b/com32/lib/strtox.c
new file mode 100644 (file)
index 0000000..7c228b6
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * strtox.c
+ *
+ * strto...() functions, by macro definition
+ */
+
+#include <stddef.h>
+#include <inttypes.h>
+
+TYPE NAME (const char *nptr, char **endptr, int base)
+{
+  return (TYPE) strntoumax(nptr, endptr, base, ~(size_t)0);
+}
diff --git a/com32/lib/sys/close.c b/com32/lib/sys/close.c
new file mode 100644 (file)
index 0000000..b81d77e
--- /dev/null
@@ -0,0 +1,57 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2004 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * close.c
+ */
+
+#include <errno.h>
+#include <com32.h>
+#include <string.h>
+#include "file.h"
+
+int close(int fd)
+{
+  com32sys_t regs;
+  struct file_info *fp = &__file_info[fd];
+
+  if ( fd >= NFILES || fp->blocklg2 == 0 ) {
+    errno = EBADF;
+    return -1;
+  }
+
+  if ( fp->filedes ) {
+    memset(&regs, 0, sizeof regs);
+    regs.eax.w[0] = 0x0008;    /* Close file */
+    regs.esi.w[0] = fp->filedes;
+
+    __com32.cs_intcall(0x22, &regs, NULL);
+  }
+
+  return 0;
+}
diff --git a/com32/lib/sys/entry.S b/com32/lib/sys/entry.S
new file mode 100644 (file)
index 0000000..4019452
--- /dev/null
@@ -0,0 +1,83 @@
+#ident "$Id$"
+# -----------------------------------------------------------------------
+#   
+#   Copyright 2003-2004 H. Peter Anvin - All Rights Reserved
+#
+#   Permission is hereby granted, free of charge, to any person
+#   obtaining a copy of this software and associated documentation
+#   files (the "Software"), to deal in the Software without
+#   restriction, including without limitation the rights to use,
+#   copy, modify, merge, publish, distribute, sublicense, and/or
+#   sell copies of the Software, and to permit persons to whom
+#   the Software is furnished to do so, subject to the following
+#   conditions:
+#   
+#   The above copyright notice and this permission notice shall
+#   be included in all copies or substantial portions of the Software.
+#   
+#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+#   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+#   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+#   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+#   OTHER DEALINGS IN THE SOFTWARE.
+#
+# -----------------------------------------------------------------------
+
+# COM32 start up code - must be linked first in the binary
+
+       
+               .section ".init","ax"
+               .globl _start
+               .type _start, @function
+_start:
+               # This first instruction acts as COM32 magic number
+               movl $0x21cd4cff,%eax
+
+               # Upwards string operations
+               cld
+
+               # Zero the .bss segment
+               xorl %eax,%eax
+               movl $__bss_start,%edi          # Symbol provided by linker
+               movl $_end+3,%ecx               # Symbol provided by linker
+               subl %edi,%ecx
+               shrl $2,%ecx
+               rep ; stosl
+
+               # Copy COM32 invocation parameters
+               leal 4(%esp),%esi               # Argument list
+               movl $__com32,%edi
+               movl $6,%ecx
+               movl %esp,-4(%edi)              # Save the initial stack ptr
+               cmpl (%esi),%ecx
+               jbe 1f
+               movl (%esi),%ecx
+1:             rep ; movsl
+
+               # Look for library initialization functions
+               movl $__ctors_start, %esi
+2:
+               cmpl $__ctors_end, %esi
+               jae 3f
+               call *(%esi)
+               addl $4,%esi
+               jmp 2b
+
+#
+# Run program.  Note that we dont actually pass argc, argv to main...
+#
+3:
+               call main
+               pushl %eax
+               call *(__exit_handler)
+               hlt
+               .size _start, .-_start
+                       
+               .bss
+               .globl __entry_esp
+__entry_esp:   .space 4
+               .globl __com32
+__com32:       .space 4*6
diff --git a/com32/lib/sys/exit.S b/com32/lib/sys/exit.S
new file mode 100644 (file)
index 0000000..76c8b5d
--- /dev/null
@@ -0,0 +1,27 @@
+# $Id$
+#
+# Implementation of _exit() for com32 based on c32entry.S
+#
+       .text
+       .globl _exit
+       .type _exit, @function
+_exit:
+       # Run any destructors
+       movl $__dtors_start, %esi
+2:
+       cmpl $__dtors_end, %esi
+       jae 1f
+       call *(%esi)
+       addl $4,%esi
+       jmp 2b
+       
+1:
+       movl 4(%esp),%eax               # Exit code in %eax = return value
+       movl (__entry_esp),%esp         # Return stack pointer to entry value
+       ret                             # Return to termination address
+       .size _exit, .-_exit
+
+       .data
+__exit_handler:
+       .globl __exit_handler
+       .long _exit
diff --git a/com32/lib/sys/file.h b/com32/lib/sys/file.h
new file mode 100644 (file)
index 0000000..6a56f58
--- /dev/null
@@ -0,0 +1,69 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * file.h
+ *
+ * Internal implementation of file I/O for COM32
+ */
+
+#ifndef _COM32_SYS_FILE_H
+#define _COM32_SYS_FILE_H
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+/* Ordinary file */
+
+#define NFILES 32              /* Number of files to support */
+#define MAXBLOCK 16384         /* Defined by ABI */
+
+struct file_info {
+  int blocklg2;                        /* Blocksize log 2 */
+  size_t offset;               /* Current file offset */
+  size_t length;               /* Total file length */
+  uint16_t filedes;            /* File descriptor */
+  uint16_t _filler;            /* Unused */
+  size_t nbytes;               /* Number of bytes available in buffer */
+  char *datap;                 /* Current data pointer */
+  char buf[MAXBLOCK];
+};
+
+extern struct file_info __file_info[NFILES];
+
+/* Special device (tty et al) */
+
+#define __DEV_MAGIC    0x504af4e7
+struct dev_info {
+  uint32_t dev_magic;          /* Magic number */
+  ssize_t (*read)(int, void *, size_t);
+  ssize_t (*write)(int, const void *, size_t);
+};
+
+#endif /* _COM32_SYS_FILE_H */
diff --git a/com32/lib/sys/fileinfo.c b/com32/lib/sys/fileinfo.c
new file mode 100644 (file)
index 0000000..a1fc7c9
--- /dev/null
@@ -0,0 +1,3 @@
+#include "file.h"
+
+struct file_info __file_info[NFILES];
diff --git a/com32/lib/sys/open.c b/com32/lib/sys/open.c
new file mode 100644 (file)
index 0000000..3f84e5f
--- /dev/null
@@ -0,0 +1,79 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <errno.h>
+#include <com32.h>
+#include <string.h>
+#include "file.h"
+
+int open(const char *pathname, int flags, mode_t mode)
+{
+  com32sys_t regs;
+  int fd;
+  struct file_info *fp;
+  
+  if ( flags ) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  for ( fd = 0, fp = __file_info ; fd < NFILES ; fd++, fp++ )
+    if ( fp->blocklg2 == 0 )
+      break;
+
+  if ( fd >= NFILES ) {
+    errno = EMFILE;
+    return -1;
+  }
+
+  strlcpy(__com32.cs_bounce, pathname, __com32.cs_bounce_size);
+
+  regs.eax.w[0] = 0x0006;
+  regs.esi.w[0] = OFFS(__com32.cs_bounce);
+  regs.es = SEG(__com32.cs_bounce);
+
+  __com32.cs_intcall(0x22, &regs, &regs);
+  
+  if ( (regs.eflags.l & EFLAGS_CF) || regs.esi.w[0] == 0 ) {
+    errno = ENOENT;
+    return -1;
+  }
+
+  {
+    uint16_t blklg2;
+    asm("bsrw %1,%0" : "=r" (blklg2) : "rm" (regs.ecx.w[0]));
+    fp->blocklg2 = blklg2;
+  }
+  fp->length    = regs.eax.l;
+  fp->filedes   = regs.esi.w[0];
+  fp->offset    = 0;
+  fp->nbytes    = 0;
+  fp->datap     = fp->buf;
+
+  return fd;
+} 
diff --git a/com32/lib/sys/read.c b/com32/lib/sys/read.c
new file mode 100644 (file)
index 0000000..1c16ce4
--- /dev/null
@@ -0,0 +1,92 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2004 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * read.c
+ *
+ * Reading from a file
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <com32.h>
+#include <minmax.h>
+#include "file.h"
+
+ssize_t read(int fd, void *buf, size_t count)
+{
+  com32sys_t ireg, oreg;
+  struct file_info *fp = &__file_info[fd];
+  char *bufp = buf;
+  size_t n = 0;
+  size_t ncopy;
+
+  if ( fd >= NFILES || fp->blocklg2 == 0 ) {
+    errno = EBADF;
+    return -1;
+  }
+
+  memset(&ireg, 0, sizeof ireg);
+  ireg.eax.w[0] = 0x0007;      /* Read file */
+  ireg.esi.w[0] = OFFS(__com32.cs_bounce);
+  ireg.es = SEG(__com32.cs_bounce);
+
+  while ( count ) {
+    if ( fp->nbytes == 0 ) {
+      if ( fp->offset >= fp->length || !fp->filedes )
+       return n;               /* As good as it gets... */
+
+      ireg.esi.w[0] = fp->filedes;
+      ireg.ecx.w[0] = MAXBLOCK >> fp->blocklg2;
+      
+      __intcall(0x22, &ireg, &oreg);
+
+      if ( oreg.eflags.l & EFLAGS_CF ) {
+       errno = EIO;
+       return -1;
+      }
+
+      fp->filedes = ireg.esi.w[0];
+      fp->nbytes = min(fp->length-fp->offset, (unsigned)MAXBLOCK);
+      fp->datap = fp->buf;
+      memcpy(fp->buf, __com32.cs_bounce, fp->nbytes);
+    }
+
+    ncopy = min(count, fp->nbytes);
+    memcpy(bufp, fp->datap, ncopy);
+
+    n += ncopy;
+    bufp += ncopy;
+    count -= ncopy;
+    fp->datap += ncopy;
+    fp->offset += ncopy;
+    fp->nbytes -= ncopy;
+  }
+
+  return n;
+}
diff --git a/com32/lib/sys/write.c b/com32/lib/sys/write.c
new file mode 100644 (file)
index 0000000..b908f36
--- /dev/null
@@ -0,0 +1,58 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2004 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * write.c
+ *
+ * Writing to the console
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <com32.h>
+#include <minmax.h>
+#include "file.h"
+
+ssize_t write(int fd, void *buf, size_t count)
+{
+  com32sys_t ireg;
+  struct file_info *fp = &__file_info[fd];
+  char *bufp = buf;
+  size_t n = 0;
+
+  memset(&ireg, 0, sizeof ireg); 
+  ireg.eax.b[1] = 0x02;
+
+  while ( count-- ) {
+    ireg.edx.b[0] = *bufp++;
+    __intcall(0x21, &ireg, NULL);
+    n++;
+  }
+
+  return n;
+}
diff --git a/com32/lib/vfprintf.c b/com32/lib/vfprintf.c
new file mode 100644 (file)
index 0000000..39cf983
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * vfprintf.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#define BUFFER_SIZE    32768
+
+int vfprintf(FILE *file, const char *format, va_list ap)
+{
+  int rv;
+  char buffer[BUFFER_SIZE];
+
+  rv = vsnprintf(buffer, BUFFER_SIZE, format, ap);
+
+  if ( rv < 0 )
+    return rv;
+
+  if ( rv > BUFFER_SIZE-1 )
+    rv = BUFFER_SIZE-1;
+
+  return _fwrite(buffer, rv, file);
+}
diff --git a/com32/lib/vprintf.c b/com32/lib/vprintf.c
new file mode 100644 (file)
index 0000000..7d60665
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * vprintf.c
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+int vprintf(const char *format, va_list ap)
+{
+  return vfprintf(stdout, format, ap);
+}
diff --git a/com32/lib/vsnprintf.c b/com32/lib/vsnprintf.c
new file mode 100644 (file)
index 0000000..5cb9331
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+ * vsnprintf.c
+ *
+ * vsnprintf(), from which the rest of the printf()
+ * family is built
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+enum flags {
+  FL_ZERO   = 0x01,            /* Zero modifier */
+  FL_MINUS  = 0x02,            /* Minus modifier */
+  FL_PLUS   = 0x04,            /* Plus modifier */
+  FL_TICK   = 0x08,            /* ' modifier */
+  FL_SPACE  = 0x10,            /* Space modifier */
+  FL_HASH   = 0x20,            /* # modifier */
+  FL_SIGNED = 0x40,            /* Number is signed */
+  FL_UPPER  = 0x80             /* Upper case digits */
+};
+
+/* These may have to be adjusted on certain implementations */
+enum ranks {
+  rank_char    = -2,
+  rank_short   = -1,
+  rank_int     = 0,
+  rank_long    = 1,
+  rank_longlong        = 2
+};
+
+#define MIN_RANK       rank_char
+#define MAX_RANK       rank_longlong
+
+#define INTMAX_RANK    rank_longlong
+#define SIZE_T_RANK    rank_long
+#define PTRDIFF_T_RANK rank_long
+
+#define EMIT(x) ({ if (o<n){*q++ = (x);} o++; })
+
+static size_t
+format_int(char *q, size_t n, uintmax_t val, enum flags flags,
+          int base, int width, int prec)
+{
+  char *qq;
+  size_t o = 0, oo;
+  static const char lcdigits[] = "0123456789abcdef";
+  static const char ucdigits[] = "0123456789ABCDEF";
+  const char *digits;
+  uintmax_t tmpval;
+  int minus = 0;
+  int ndigits = 0, nchars;
+  int tickskip, b4tick;
+
+  /* Select type of digits */
+  digits = (flags & FL_UPPER) ? ucdigits : lcdigits;
+
+  /* If signed, separate out the minus */
+  if ( flags & FL_SIGNED && (intmax_t)val < 0 ) {
+    minus = 1;
+    val = (uintmax_t)(-(intmax_t)val);
+  }
+
+  /* Count the number of digits needed.  This returns zero for 0. */
+  tmpval = val;
+  while ( tmpval ) {
+    tmpval /= base;
+    ndigits++;
+  }
+
+  /* Adjust ndigits for size of output */
+
+  if ( flags & FL_HASH && base == 8 ) {
+    if ( prec < ndigits+1 )
+      prec = ndigits+1;
+  }
+
+  if ( ndigits < prec ) {
+    ndigits = prec;            /* Mandatory number padding */
+  } else if ( val == 0 ) {
+    ndigits = 1;               /* Zero still requires space */
+  }
+
+  /* For ', figure out what the skip should be */
+  if ( flags & FL_TICK ) {
+    tickskip = (base == 16) ? 4 : 3;
+  } else {
+    tickskip = ndigits;                /* No tick marks */
+  }
+
+  /* Tick marks aren't digits, but generated by the number converter */
+  ndigits += (ndigits-1)/tickskip;
+
+  /* Now compute the number of nondigits */
+  nchars = ndigits;
+
+  if ( minus || (flags & (FL_PLUS|FL_SPACE)) )
+    nchars++;                  /* Need space for sign */
+  if ( (flags & FL_HASH) && base == 16 ) {
+    nchars += 2;               /* Add 0x for hex */
+  }
+
+  /* Emit early space padding */
+  if ( !(flags & (FL_MINUS|FL_ZERO)) && width > nchars ) {
+    while ( width > nchars ) {
+      EMIT(' ');
+      width--;
+    }
+  }
+
+  /* Emit nondigits */
+  if ( minus )
+    EMIT('-');
+  else if ( flags & FL_PLUS )
+    EMIT('+');
+  else if ( flags & FL_SPACE )
+    EMIT(' ');
+
+  if ( (flags & FL_HASH) && base == 16 ) {
+    EMIT('0');
+    EMIT((flags & FL_UPPER) ? 'X' : 'x');
+  }
+
+  /* Emit zero padding */
+  if ( (flags & (FL_MINUS|FL_ZERO)) == FL_ZERO && width > ndigits ) {
+    while ( width > nchars ) {
+      EMIT('0');
+      width--;
+    }
+  }
+
+  /* Generate the number.  This is done from right to left. */
+  q += ndigits;                        /* Advance the pointer to end of number */
+  o += ndigits;
+  qq = q; oo = o;              /* Temporary values */
+
+  b4tick = tickskip;
+  while ( ndigits > 0 ) {
+    if ( !b4tick-- ) {
+      qq--; oo--; ndigits--;
+      if ( oo < n ) *qq = '_';
+      b4tick = tickskip-1;
+    }
+    qq--; oo--; ndigits--;
+    if ( oo < n ) *qq = digits[val%base];
+    val /= base;
+  }
+
+  /* Emit late space padding */
+  while ( (flags & FL_MINUS) && width > nchars ) {
+    EMIT(' ');
+    width--;
+  }
+
+  return o;
+}
+
+
+int vsnprintf(char *buffer, size_t n, const char *format, va_list ap)
+{
+  const char *p = format;
+  char ch;
+  char *q = buffer;
+  size_t o = 0;                        /* Number of characters output */
+  uintmax_t val = 0;
+  int rank = rank_int;         /* Default rank */
+  int width = 0;
+  int prec  = -1;
+  int base;
+  size_t sz;
+  enum flags flags = 0;
+  enum {
+    st_normal,                 /* Ground state */
+    st_flags,                  /* Special flags */
+    st_width,                  /* Field width */
+    st_prec,                   /* Field precision */
+    st_modifiers               /* Length or conversion modifiers */
+  } state = st_normal;
+  const char *sarg;            /* %s string argument */
+  char carg;                   /* %c char argument */
+  int slen;                    /* String length */
+
+  while ( (ch = *p++) ) {
+    switch ( state ) {
+    case st_normal:
+      if ( ch == '%' ) {
+       state = st_flags;
+       flags = 0; rank = rank_int; width = 0; prec = -1;
+      } else {
+       EMIT(ch);
+      }
+      break;
+
+    case st_flags:
+      switch ( ch ) {
+      case '-':
+       flags |= FL_MINUS;
+       break;
+      case '+':
+       flags |= FL_PLUS;
+       break;
+      case '\'':
+       flags |= FL_TICK;
+       break;
+      case ' ':
+       flags |= FL_SPACE;
+       break;
+      case '#':
+       flags |= FL_HASH;
+       break;
+      case '0':
+       flags |= FL_ZERO;
+       break;
+      default:
+       state = st_width;
+       p--;                    /* Process this character again */
+       break;
+      }
+      break;
+
+    case st_width:
+      if ( ch >= '0' && ch <= '9' ) {
+       width = width*10+(ch-'0');
+      } else if ( ch == '*' ) {
+       width = va_arg(ap, int);
+       if ( width < 0 ) {
+         width = -width;
+         flags |= FL_MINUS;
+       }
+      } else if ( ch == '.' ) {
+       prec = 0;               /* Precision given */
+       state = st_prec;
+      } else {
+       state = st_modifiers;
+       p--;                    /* Process this character again */
+      }
+      break;
+
+    case st_prec:
+      if ( ch >= '0' && ch <= '9' ) {
+       prec = prec*10+(ch-'0');
+      } else if ( ch == '*' ) {
+       prec = va_arg(ap, int);
+       if ( prec < 0 )
+         prec = -1;
+      } else {
+       state = st_modifiers;
+       p--;                    /* Process this character again */
+      }
+      break;
+
+    case st_modifiers:
+      switch ( ch ) {
+       /* Length modifiers - nonterminal sequences */
+      case 'h':
+       rank--;                 /* Shorter rank */
+       break;
+      case 'l':
+       rank++;                 /* Longer rank */
+       break;
+      case 'j':
+       rank = INTMAX_RANK;
+       break;
+      case 'z':
+       rank = SIZE_T_RANK;
+       break;
+      case 't':
+       rank = PTRDIFF_T_RANK;
+       break;
+      case 'L':
+      case 'q':
+       rank += 2;
+       break;
+      default:
+       /* Output modifiers - terminal sequences */
+       state = st_normal;      /* Next state will be normal */
+       if ( rank < MIN_RANK )  /* Canonicalize rank */
+         rank = MIN_RANK;
+       else if ( rank > MAX_RANK )
+         rank = MAX_RANK;
+
+       switch ( ch ) {
+       case 'P':               /* Upper case pointer */
+         flags |= FL_UPPER;
+         /* fall through */
+       case 'p':               /* Pointer */
+         base = 16;
+         prec = (CHAR_BIT*sizeof(void *)+3)/4;
+         flags |= FL_HASH;
+         val = (uintmax_t)(uintptr_t)va_arg(ap, void *);
+         goto is_integer;
+
+       case 'd':               /* Signed decimal output */
+       case 'i':
+         base = 10;
+         flags |= FL_SIGNED;
+         switch (rank) {
+         case rank_char:
+           /* Yes, all these casts are needed... */
+           val = (uintmax_t)(intmax_t)(signed char)va_arg(ap, signed int);
+           break;
+         case rank_short:
+           val = (uintmax_t)(intmax_t)(signed short)va_arg(ap, signed int);
+           break;
+         case rank_int:
+           val = (uintmax_t)(intmax_t)va_arg(ap, signed int);
+           break;
+         case rank_long:
+           val = (uintmax_t)(intmax_t)va_arg(ap, signed long);
+           break;
+         case rank_longlong:
+           val = (uintmax_t)(intmax_t)va_arg(ap, signed long long);
+           break;
+         }
+         goto is_integer;
+       case 'o':               /* Octal */
+         base = 8;
+         goto is_unsigned;
+       case 'u':               /* Unsigned decimal */
+         base = 10;
+         goto is_unsigned;
+       case 'X':               /* Upper case hexadecimal */
+         flags |= FL_UPPER;
+         /* fall through */
+       case 'x':               /* Hexadecimal */
+         base = 16;
+         goto is_unsigned;
+
+       is_unsigned:
+         switch (rank) {
+         case rank_char:
+           val = (uintmax_t)(unsigned char)va_arg(ap, unsigned int);
+           break;
+         case rank_short:
+           val = (uintmax_t)(unsigned short)va_arg(ap, unsigned int);
+           break;
+         case rank_int:
+           val = (uintmax_t)va_arg(ap, unsigned int);
+           break;
+         case rank_long:
+           val = (uintmax_t)va_arg(ap, unsigned long);
+           break;
+         case rank_longlong:
+           val = (uintmax_t)va_arg(ap, unsigned long long);
+           break;
+         }
+         /* fall through */
+
+       is_integer:
+         sz = format_int(q, (o<n) ? n-o : 0, val, flags, base, width, prec);
+         q += sz; o += sz;
+         break;
+
+       case 'c':               /* Character */
+         carg = (char)va_arg(ap, int);
+         sarg = &carg;
+         slen = 1;
+         goto is_string;
+       case 's':               /* String */
+         sarg = va_arg(ap, const char *);
+         sarg = sarg ? sarg : "(null)";
+         slen = strlen(sarg);
+         goto is_string;
+
+       is_string:
+         {
+           char sch;
+           int i;
+           
+           if ( prec != -1 && slen > prec )
+             slen = prec;
+           
+           if ( width > slen && !(flags & FL_MINUS) ) {
+             char pad = (flags & FL_ZERO) ? '0' : ' ';
+             while ( width > slen ) {
+               EMIT(pad);
+               width--;
+             }
+           }
+           for ( i = slen ; i ; i-- ) {
+             sch = *sarg++;
+             EMIT(sch);
+           }
+           if ( width > slen && (flags & FL_MINUS) ) {
+             while ( width > slen ) {
+               EMIT(' ');
+               width--;
+             }
+           }
+         }
+         break;
+
+       case 'n':               /* Output the number of characters written */
+         {
+           switch (rank) {
+           case rank_char:
+             *va_arg(ap, signed char *) = o;
+             break;
+           case rank_short:
+             *va_arg(ap, signed short *) = o;
+             break;
+           case rank_int:
+             *va_arg(ap, signed int *) = o;
+             break;
+           case rank_long:
+             *va_arg(ap, signed long *) = o;
+             break;
+           case rank_longlong:
+             *va_arg(ap, signed long long *) = o;
+             break;
+           }
+         }
+         break;
+         
+       default:                /* Anything else, including % */
+         EMIT(ch);
+         break;
+       }
+      }
+    }
+  }
+
+  /* Null-terminate the string */
+  if ( o<n )
+    *q = '\0';                 /* No overflow */
+  else if ( n>0 )
+    buffer[n-1] = '\0';                /* Overflow - terminate at end of buffer */
+
+  return o;
+}
diff --git a/com32/lib/vsprintf.c b/com32/lib/vsprintf.c
new file mode 100644 (file)
index 0000000..4a6100e
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * vsprintf.c
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+int vsprintf(char *buffer, const char *format, va_list ap)
+{
+  return vsnprintf(buffer, ~(size_t)0, format, ap);
+}
diff --git a/com32/lib/vsscanf.c b/com32/lib/vsscanf.c
new file mode 100644 (file)
index 0000000..12a82b2
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * vsscanf.c
+ *
+ * vsscanf(), from which the rest of the scanf()
+ * family is built
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+#ifndef LONG_BIT
+#define LONG_BIT (CHAR_BIT*sizeof(long))
+#endif
+
+enum flags {
+  FL_SPLAT  = 0x01,            /* Drop the value, do not assign */
+  FL_INV    = 0x02,            /* Character-set with inverse */
+  FL_WIDTH  = 0x04,            /* Field width specified */
+  FL_MINUS  = 0x08,            /* Negative number */
+};
+
+enum ranks {
+  rank_char    = -2,
+  rank_short   = -1,
+  rank_int     = 0,
+  rank_long    = 1,
+  rank_longlong        = 2,
+  rank_ptr      = INT_MAX      /* Special value used for pointers */
+};
+
+#define MIN_RANK       rank_char
+#define MAX_RANK       rank_longlong
+
+#define INTMAX_RANK    rank_longlong
+#define SIZE_T_RANK    rank_long
+#define PTRDIFF_T_RANK rank_long
+
+enum bail {
+  bail_none = 0,               /* No error condition */
+  bail_eof,                    /* Hit EOF */
+  bail_err                     /* Conversion mismatch */
+};
+
+static inline const char *
+skipspace(const char *p)
+{
+  while ( isspace((unsigned char)*p) ) p++;
+  return p;
+}
+
+#undef set_bit
+static inline void
+set_bit(unsigned long *bitmap, unsigned int bit)
+{
+  bitmap[bit/LONG_BIT] |= 1UL << (bit%LONG_BIT);
+}
+
+#undef test_bit
+static inline int
+test_bit(unsigned long *bitmap, unsigned int bit)
+{
+  return (int)(bitmap[bit/LONG_BIT] >> (bit%LONG_BIT)) & 1;
+}
+
+int vsscanf(const char *buffer, const char *format, va_list ap)
+{
+  const char *p = format;
+  char ch;
+  const char *q = buffer;
+  const char *qq;
+  uintmax_t val = 0;
+  int rank = rank_int;         /* Default rank */
+  unsigned int width = UINT_MAX;
+  int base;
+  enum flags flags = 0;
+  enum {
+    st_normal,                 /* Ground state */
+    st_flags,                  /* Special flags */
+    st_width,                  /* Field width */
+    st_modifiers,              /* Length or conversion modifiers */
+    st_match_init,             /* Initial state of %[ sequence */
+    st_match,                  /* Main state of %[ sequence */
+    st_match_range,            /* After - in a %[ sequence */
+  } state = st_normal;
+  char *sarg = NULL;           /* %s %c or %[ string argument */
+  enum bail bail = bail_none;
+  int sign;
+  int converted = 0;           /* Successful conversions */
+  unsigned long matchmap[((1 << CHAR_BIT)+(LONG_BIT-1))/LONG_BIT];
+  int matchinv = 0;            /* Is match map inverted? */
+  unsigned char range_start = 0;
+
+  while ( (ch = *p++) && !bail ) {
+    switch ( state ) {
+    case st_normal:
+      if ( ch == '%' ) {
+       state = st_flags;
+       flags = 0; rank = rank_int; width = UINT_MAX;
+      } else if ( isspace((unsigned char)ch) ) {
+       q = skipspace(q);
+      } else {
+       if ( *q == ch )
+         q++;
+       else
+         bail = bail_err;      /* Match failure */
+      }
+      break;
+
+    case st_flags:
+      switch ( ch ) {
+      case '*':
+       flags |= FL_SPLAT;
+       break;
+      case '0' ... '9':
+       width = (ch-'0');
+       state = st_width;
+       flags |= FL_WIDTH;
+       break;
+      default:
+       state = st_modifiers;
+       p--;                    /* Process this character again */
+       break;
+      }
+      break;
+
+    case st_width:
+      if ( ch >= '0' && ch <= '9' ) {
+       width = width*10+(ch-'0');
+      } else {
+       state = st_modifiers;
+       p--;                    /* Process this character again */
+      }
+      break;
+
+    case st_modifiers:
+      switch ( ch ) {
+       /* Length modifiers - nonterminal sequences */
+      case 'h':
+       rank--;                 /* Shorter rank */
+       break;
+      case 'l':
+       rank++;                 /* Longer rank */
+       break;
+      case 'j':
+       rank = INTMAX_RANK;
+       break;
+      case 'z':
+       rank = SIZE_T_RANK;
+       break;
+      case 't':
+       rank = PTRDIFF_T_RANK;
+       break;
+      case 'L':
+      case 'q':
+       rank = rank_longlong;   /* long double/long long */
+       break;
+
+      default:
+       /* Output modifiers - terminal sequences */
+       state = st_normal;      /* Next state will be normal */
+       if ( rank < MIN_RANK )  /* Canonicalize rank */
+         rank = MIN_RANK;
+       else if ( rank > MAX_RANK )
+         rank = MAX_RANK;
+
+       switch ( ch ) {
+       case 'P':               /* Upper case pointer */
+       case 'p':               /* Pointer */
+#if 0  /* Enable this to allow null pointers by name */
+         q = skipspace(q);
+         if ( !isdigit((unsigned char)*q) ) {
+           static const char * const nullnames[] =
+           { "null", "nul", "nil", "(null)", "(nul)", "(nil)", 0 };
+           const char * const *np;
+
+           /* Check to see if it's a null pointer by name */
+           for ( np = nullnames ; *np ; np++ ) {
+             if ( !strncasecmp(q, *np, strlen(*np)) ) {
+               val = (uintmax_t)((void *)NULL);
+               goto set_integer;
+             }
+           }
+           /* Failure */
+           bail = bail_err;
+           break;
+         }
+         /* else */
+#endif
+         rank = rank_ptr;
+         base = 0; sign = 0;
+         goto scan_int;
+
+       case 'i':               /* Base-independent integer */
+         base = 0; sign = 1;
+         goto scan_int;
+
+       case 'd':               /* Decimal integer */
+         base = 10; sign = 1;
+         goto scan_int;
+
+       case 'o':               /* Octal integer */
+         base = 8; sign = 0;
+         goto scan_int;
+
+       case 'u':               /* Unsigned decimal integer */
+         base = 10; sign = 0;
+         goto scan_int;
+         
+       case 'x':               /* Hexadecimal integer */
+       case 'X':
+         base = 16; sign = 0;
+         goto scan_int;
+
+       case 'n':               /* Number of characters consumed */
+         val = (q-buffer);
+         goto set_integer;
+
+       scan_int:
+         q = skipspace(q);
+         if ( !*q ) {
+           bail = bail_eof;
+           break;
+         }
+         val = strntoumax(q, (char **)&qq, base, width);
+         if ( qq == q ) {
+           bail = bail_err;
+           break;
+         }
+         q = qq;
+         converted++;
+         /* fall through */
+
+       set_integer:
+         if ( !(flags & FL_SPLAT) ) {
+           switch(rank) {
+           case rank_char:
+             *va_arg(ap, unsigned char *) = (unsigned char)val;
+             break;
+           case rank_short:
+             *va_arg(ap, unsigned short *) = (unsigned short)val;
+             break;
+           case rank_int:
+             *va_arg(ap, unsigned int *) = (unsigned int)val;
+             break;
+           case rank_long:
+             *va_arg(ap, unsigned long *) = (unsigned long)val;
+             break;
+           case rank_longlong:
+             *va_arg(ap, unsigned long long *) = (unsigned long long)val;
+             break;
+           case rank_ptr:
+             *va_arg(ap, void **) = (void *)(uintptr_t)val;
+             break;
+           }
+         }
+         break;
+         
+       case 'c':               /* Character */
+          width = (flags & FL_WIDTH) ? width : 1; /* Default width == 1 */
+          sarg = va_arg(ap, char *);
+          while ( width-- ) {
+            if ( !*q ) {
+              bail = bail_eof;
+              break;
+            }
+            *sarg++ = *q++;
+          }
+          if ( !bail )
+            converted++;
+          break;
+
+        case 's':               /* String */
+         {
+           char *sp;
+           sp = sarg = va_arg(ap, char *);
+           while ( width-- && *q && !isspace((unsigned char)*q) ) {
+             *sp++ = *q++;
+           }
+           if ( sarg != sp ) {
+             *sp = '\0';       /* Terminate output */
+             converted++;
+           } else {
+             bail = bail_eof;
+           }
+         }
+         break;
+         
+       case '[':               /* Character range */
+         sarg = va_arg(ap, char *);
+         state = st_match_init;
+         matchinv = 0;
+         memset(matchmap, 0, sizeof matchmap);
+         break;
+
+       case '%':               /* %% sequence */
+         if ( *q == '%' )
+           q++;
+         else
+           bail = bail_err;
+         break;
+
+       default:                /* Anything else */
+         bail = bail_err;      /* Unknown sequence */
+         break;
+       }
+      }
+      break;
+    
+    case st_match_init:                /* Initial state for %[ match */
+      if ( ch == '^' && !(flags & FL_INV) ) {
+       matchinv = 1;
+      } else {
+       set_bit(matchmap, (unsigned char)ch);
+       state = st_match;
+      }
+      break;
+      
+    case st_match:             /* Main state for %[ match */
+      if ( ch == ']' ) {
+       goto match_run;
+      } else if ( ch == '-' ) {
+       range_start = (unsigned char)ch;
+       state = st_match_range;
+      } else {
+       set_bit(matchmap, (unsigned char)ch);
+      }
+      break;
+      
+    case st_match_range:               /* %[ match after - */
+      if ( ch == ']' ) {
+       set_bit(matchmap, (unsigned char)'-'); /* - was last character */
+       goto match_run;
+      } else {
+       int i;
+       for ( i = range_start ; i < (unsigned char)ch ; i++ )
+         set_bit(matchmap, i);
+       state = st_match;
+      }
+      break;
+
+    match_run:                 /* Match expression finished */
+      qq = q;
+      while ( width && *q && test_bit(matchmap, (unsigned char)*q)^matchinv ) {
+       *sarg++ = *q++;
+      }
+      if ( q != qq ) {
+       *sarg = '\0';
+       converted++;
+      } else {
+       bail = *q ? bail_err : bail_eof;
+      }
+      break;
+    }
+  }
+
+  if ( bail == bail_eof && !converted )
+    converted = -1;            /* Return EOF (-1) */
+
+  return converted;
+}
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
new file mode 100644 (file)
index 0000000..a47e0a2
--- /dev/null
@@ -0,0 +1,61 @@
+#ident "$Id$"
+## -----------------------------------------------------------------------
+##   
+##   Copyright 2001-2004 H. Peter Anvin - All Rights Reserved
+##
+##   This program is free software; you can redistribute it and/or modify
+##   it under the terms of the GNU General Public License as published by
+##   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+##   USA; either version 2 of the License, or (at your option) any later
+##   version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+##
+## samples for syslinux users
+##
+
+gcc_ok   = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
+                  then echo $(1); else echo $(2); fi)
+
+M32     := $(call gcc_ok,-m32,)
+
+CC         = gcc $(M32)
+LD         = ld -m elf_i386
+AR        = ar
+NASM      = nasm
+RANLIB    = ranlib
+CFLAGS     = -W -Wall -march=i386 -Os -fomit-frame-pointer -I../com32/include
+SFLAGS     = -march=i386
+LDFLAGS    = -s -T ../lib/com32.ld
+OBJCOPY    = objcopy
+PPMTOLSS16 =   ../ppmtolss16
+LIB       = ../lib/libcom32.a
+
+.SUFFIXES: .lss .c .o .elf .c32
+
+all: hello.c32
+
+.PRECIOUS: %.o
+%.o: %.S
+       $(CC) $(SFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.o
+%.o: %.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.elf
+%.elf: %.o $(LIB)
+       $(LD) $(LDFLAGS) -o $@ $^
+
+%.c32: %.elf
+       $(OBJCOPY) -O binary $< $@
+
+tidy:
+       rm -f *.o *.a *.lst *.elf
+
+clean: tidy
+       rm -f *.lss *.o *.c32 *.com
+
+spotless: clean
+       rm -f *~ \#*
diff --git a/com32/modules/hello.c b/com32/modules/hello.c
new file mode 100644 (file)
index 0000000..bcb018d
--- /dev/null
@@ -0,0 +1,27 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2002 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Bostom MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * hello.c
+ *
+ * Hello, World! using libcom32
+ */
+
+#include <stdio.h>
+
+int main(void)
+{
+  printf("Hello, World!\n");
+
+  return 0;
+}