summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-11-03 22:33:35 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:33:35 +0200
commitc218c617b5be443b7968308506969ad2b726d73c (patch)
tree0051f396af56133d24fcf2ab757fabc78c1a09bf /libc
parent0936b9aeab611665645a4e6bafaded7ca76dd189 (diff)
parent0d2fbe9b1bd284ce2cad55be17e8f2c896031a25 (diff)
downloaddev86-c218c617b5be443b7968308506969ad2b726d73c.tar.gz
Import Dev86src-0.0.8.tar.gzv0.0.8
Diffstat (limited to 'libc')
-rw-r--r--libc/Config_sh8
-rw-r--r--libc/Make.defs66
-rw-r--r--libc/Makefile73
-rw-r--r--libc/Pre_main21
-rw-r--r--libc/README26
-rw-r--r--libc/bcc/Makefile16
-rw-r--r--libc/bcc/bcc_i386.c149
-rw-r--r--libc/bcc/heap.c88
-rw-r--r--libc/bcc/ldiv.c3
-rw-r--r--libc/bios/Config1
-rw-r--r--libc/bios/Makefile30
-rw-r--r--libc/bios/README10
-rw-r--r--libc/bios/bios.c205
-rw-r--r--libc/bios/bios_vid.c465
-rw-r--r--libc/crt0.c9
-rw-r--r--libc/crt0.obin125 -> 0 bytes
-rw-r--r--libc/error/Makefile2
-rw-r--r--libc/error/sys_errlist.c1
-rw-r--r--libc/grp/Makefile13
-rw-r--r--libc/gtermcap/Makefile2
-rw-r--r--libc/i386fp/Config1
-rw-r--r--libc/i386fp/Makefile58
-rw-r--r--libc/i386fp/bccfp.tex0
-rw-r--r--libc/i386fp/changes30
-rw-r--r--libc/i386fp/fabs.x17
-rw-r--r--libc/i386fp/fadd.x485
-rw-r--r--libc/i386fp/fcomp.x89
-rw-r--r--libc/i386fp/fdiv.x312
-rw-r--r--libc/i386fp/fmul.x150
-rw-r--r--libc/i386fp/fpbsr.x25
-rw-r--r--libc/i386fp/fperr.c44
-rw-r--r--libc/i386fp/fperr.h8
-rw-r--r--libc/i386fp/fperror.x126
-rw-r--r--libc/i386fp/fplib.h43
-rw-r--r--libc/i386fp/fptoi.x117
-rw-r--r--libc/i386fp/fpulld.x20
-rw-r--r--libc/i386fp/fpullf.x101
-rw-r--r--libc/i386fp/fpushd.x60
-rw-r--r--libc/i386fp/fpushf.x74
-rw-r--r--libc/i386fp/fpushi.x126
-rw-r--r--libc/i386fp/frexp.x66
-rw-r--r--libc/i386fp/ftst.x28
-rw-r--r--libc/i386fp/ldexp.x74
-rw-r--r--libc/i386fp/modf.c14
-rw-r--r--libc/i386fp/test.c118
-rw-r--r--libc/include/ctype.h25
-rw-r--r--libc/include/dos.h2
-rw-r--r--libc/include/limits.h26
-rw-r--r--libc/include/math.h0
-rw-r--r--libc/include/stddef.h4
-rw-r--r--libc/include/stdio.h4
-rw-r--r--libc/include/sys/mman.h0
-rw-r--r--libc/include/sys/stat.h33
-rw-r--r--libc/include/sys/vm86.h125
-rw-r--r--libc/include/sys/x3
-rw-r--r--libc/kinclude/Makefile4
-rw-r--r--libc/kinclude/arch/types.h8
-rw-r--r--libc/kinclude/linuxmt/stat.h2
-rw-r--r--libc/kinclude/linuxmt/types.h2
-rw-r--r--libc/libc.abin82366 -> 0 bytes
-rw-r--r--libc/malloc1/malloc.c44
-rw-r--r--libc/malloc2/malloc.c1
-rw-r--r--libc/misc/Makefile14
-rw-r--r--libc/misc/aliases.c17
-rw-r--r--libc/misc/cputype.c2
-rw-r--r--libc/misc/setenv.c97
-rw-r--r--libc/msdos/Makefile4
-rw-r--r--libc/msdos/msdos.c37
-rw-r--r--libc/msdos/time.c63
-rw-r--r--libc/pwd/Makefile8
-rw-r--r--libc/stdio2/Makefile6
-rw-r--r--libc/stdio2/printf.c35
-rw-r--r--libc/stdio2/stdio.c73
-rw-r--r--libc/stdio2/stdio.h4
-rw-r--r--libc/string/string.c2
-rw-r--r--libc/syscall/Makefile53
-rw-r--r--libc/syscall/dirent.c22
-rw-r--r--libc/syscall/mksys386154
-rw-r--r--libc/syscall/sys386.dat155
-rw-r--r--libc/syscall/syslib0.c264
-rw-r--r--libc/syscall/syslib3.c109
-rw-r--r--libc/syscall/syslibc.c241
-rw-r--r--libc/termios/Makefile8
-rw-r--r--libc/tests/README3
-rw-r--r--libc/tests/env.c1
-rw-r--r--libc/tests/ft.c70
-rw-r--r--[-rwxr-xr-x]libc/tests/grab.c5
-rw-r--r--[-rwxr-xr-x]libc/tests/ls.c0
-rw-r--r--libc/time/README3
-rw-r--r--libc/time/asc_conv.c19
-rw-r--r--libc/time/asctime.c2
-rw-r--r--libc/time/ctime.c34
-rw-r--r--libc/time/gmtime.c4
-rw-r--r--libc/time/localtime.c4
-rw-r--r--libc/time/tm_conv.c74
-rw-r--r--libc/utmp/Makefile2
96 files changed, 4738 insertions, 508 deletions
diff --git a/libc/Config_sh b/libc/Config_sh
index e27acaa..6c93784 100644
--- a/libc/Config_sh
+++ b/libc/Config_sh
@@ -30,6 +30,10 @@ main()
CHANGED=0
RUNNING=1
+ [ "$DIST" != "" ] && {
+ RUNNING=0
+ echo 'Using default configuration'
+ }
while [ $RUNNING = 1 ]
do
display
@@ -51,9 +55,9 @@ main()
fi
done
- if [ "$CHANGED" = 1 ]
+ if [ "$CHANGED" = 1 -a \( -f libc.a -o -f crt0.o \) ]
then echo '
- You should now run a "make realclean" to clean out the libc.a
+ You should now run a "make clean" to clean out the libc.a
'
exit 1
fi
diff --git a/libc/Make.defs b/libc/Make.defs
index 6744899..ff571d7 100644
--- a/libc/Make.defs
+++ b/libc/Make.defs
@@ -10,49 +10,72 @@
# Define enviroment var for others.
ifeq ($(PLATFORM),)
-PLATFORM=i86-ELKS
-#PLATFORM=i86-FAST
-#PLATFORM=i86-DOS
-#PLATFORM=i386-Linux
+# PLATFORM=i86-ELKS
+# PLATFORM=i86-FAST PLATFORM=i86-DOS PLATFORM=i386-BCC PLATFORM=i386-Linux
+
+PLATFORM=$(shell if [ -f $(TOP)/.config.otype ] ; \
+ then cat $(TOP)/.config.otype ; \
+ else echo i86-ELKS ; fi)
+export PLATFORM
endif
VERMAJOR=0
VERMINOR=0
-VERPATCH=7
+VERPATCH=8
VER=$(VERMAJOR).$(VERMINOR).$(VERPATCH)
-LIBDEFS=-D__LIBC__
+LIBDEFS='-D__LIBC__="$(VER)"'
LIBC=libc.a
-ifneq ($(PLATFORM),i386-Linux)
+##############################################################################
# Normal standard 8086 code
ifeq ($(PLATFORM),i86-ELKS)
ARCH=
+LIB_CPU=i86
+LIB_OS=ELKS
endif
# 8086 elks code With "Caller saves" and "First arg in AX"
ifeq ($(PLATFORM),i86-FAST)
ARCH=-Mf
LIBC=libc_f.a
+LIB_CPU=i86
+LIB_OS=ELKS
+endif
+
+# Standalone executable
+ifeq ($(PLATFORM),i86-BIOS)
+ARCH=-Ms
+LIBC=libc_s.a
+LIB_CPU=i86
+LIB_OS=BIOS
endif
# MSDOS COM file (msdos libs don't support "First arg in AX")
ifeq ($(PLATFORM),i86-DOS)
ARCH=-Md
LIBC=libdos.a
+LIB_CPU=i86
+LIB_OS=DOS
endif
+##############################################################################
+
# BCC 386.
ifeq ($(PLATFORM),i386-BCC)
-ARCH=-3
-endif
+ARCH=-3 -N
+LIB_CPU=i386
+LIB_OS=ELKS
CC=bcc $(ARCH)
-CCFLAGS=-I -I$(TOP)/include # -O
-LKFLAGS=-L -L$(TOP)/ -s
+CCFLAGS=-I -I$(TOP)/include
+LKFLAGS=-L -L$(TOP)/
+endif
-else # ifeq ($(PLATFORM),i386-Linux)
+ifeq ($(PLATFORM),i386-Linux)
+LIB_CPU=g386
+LIB_OS=ELKS
CC=gcc $(ARCH)
# ARCH=-b i486-linuxaout
@@ -61,8 +84,25 @@ CCFLAGS=-O6 -fomit-frame-pointer -I- -I$(TOP)/include -I. -fno-builtin
WALL= -ansi -pedantic -Wwrite-strings -Wpointer-arith -Wcast-qual \
-Wcast-align -Wtraditional -Wstrict-prototypes -Wmissing-prototypes \
-Wnested-externs -Winline -Wshadow
+endif
-endif # ifeq ($(PLATFORM),i386-Linux)
+############################################################################
+
+ifeq ($(LIB_CPU),i86)
+CC=bcc $(ARCH)
+CCFLAGS=-I -I$(TOP)/include # -O
+LKFLAGS=-L -L$(TOP)/ -s
+endif
+
+ifeq ($(LIB_CPU),)
+LIB_CPU=Unknown
+LIB_OS=Unknown
+LIBC=libc_X.a
+CCFLAGS=-I$(TOP)/include
+LKFLAGS=
+endif
CFLAGS=$(CCFLAGS) $(LIBDEFS)
LDFLAGS=$(LKFLAGS)
+
+.PRECIOUS: $(LIBC)
diff --git a/libc/Makefile b/libc/Makefile
index a88ffb2..d533320 100644
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -12,51 +12,86 @@ TARGETS=$(OBJ) $(LIBC)
TXT=Makefile Make.defs README KERNEL COPYING Contributors MAGIC \
New_subdir Pre_main Config_sh
-all: .config.lst $(TARGETS)
+all: .config.dir .config.otype $(TARGETS)
-install: all
+install: all install_incl
install -d $(BCCHOME)
+ install -d $(LIBDIR)/$(LIB_CPU)
+ install -m 644 crt0.o $(LIBDIR)/$(LIB_CPU)
+ install -m 644 $(LIBC) $(LIBDIR)/$(LIB_CPU)
+ -install -d $(DIST)/usr/lib
+ -install -m 644 error/liberror.txt $(DIST)/usr/lib/liberror.txt
+
+# I've changed this so it'll be easier to make a binary dist.
+old_install_incl:
rm -rf $(BCCHOME)/include
ln -s $(TOPDIR)/libc/include $(BCCHOME)/include
- install -d $(LIBDIR)/i86
- install -m 644 crt0.o $(LIBDIR)/i86
- install -m 644 $(LIBC) $(LIBDIR)/i86
- -install -m 644 error/liberror.txt /usr/lib
+
+install_incl:
+ rm -rf $(BCCHOME)/include
+ cp -pr include $(BCCHOME)/include
+ if [ -f kinclude/Used ] ; \
+ then cp -pr kinclude/arch $(BCCHOME)/include/arch ; \
+ else rm -rf $(BCCHOME)/include/linuxmt ; \
+ ln -s $(ELKSSRC)/include/linuxmt $(BCCHOME)/include ; \
+ fi
+ -chown -R root:root $(BCCHOME)/include 2>/dev/null
+ -chmod -R u=rwX,og=rX $(BCCHOME)/include
tests: dummy
- make -C tests
+ $(MAKE) -C tests
dummy:
-$(LIBC): .config.dir transfer
+$(LIBC): transfer .config.dir
@for i in `cat .config.dir` ; do \
- echo make -C $$i libc.a ; make -C $$i libc.a || exit 1 ; \
+ echo $(MAKE) -C $$i libc.a ; $(MAKE) -C $$i libc.a || exit 1 ; \
done
-realclean: dummy
- rm -f $(OBJ) $(LIBC) .config.dir
- @for i in */Makefile ; do \
- grep -q '^clean:' $$i && make -C `dirname $$i` clean ; \
+transfer: .config.dir
+ @echo Checking for transfers
+ @for i in `cat .config.dir`; do \
+ grep -q '^transfer' $$i/Makefile && $(MAKE) -s -C $$i $@ ; \
done ; echo -n
+ @[ -f kinclude/Used ] || \
+ { rm -f include/linuxmt ; \
+ ln -s $(ELKSSRC)/include/linuxmt include ; }
-clean: .config.dir
+realclean: noconfig clean dellib
+
+clean:
+ rm -f $(OBJ) $(LIBC)
@for i in */Makefile ; do \
- make -C `dirname $$i` $@ || exit 1 ; \
+ $(MAKE) -C `dirname $$i` $@ || exit 1 ; \
done
+dellib:
+ rm -f libc*.a libdos.a
+
+##############################################################################
+
.config.lst: Makefile Make.defs Config_sh
sh Config_sh
config:
sh Config_sh
+noconfig:
+ rm -f .config.dir .config.lst .config.otype
+
.config.dir: .config.lst
@grep '^[^:]*:+:' < .config.lst | sed 's/:.*//' > .config.dir
+.config.otype: dummy
+ @[ -f .config.otype ] || echo $(PLATFORM) > .config.otype
+ @[ "$(PLATFORM)" = "`cat .config.otype `" ] || $(MAKE) -$(MAKEFLAGS) clean
+ @rm -f .config.otype
+ @echo $(PLATFORM) > .config.otype
+
dist: clean
-rm -f include/linuxmt
tar cf temp.tar \
- $(TXT) $(TARGETS) $(SRC) include \
+ $(TXT) $(SRC) include \
`for i in */Makefile */Config; do dirname $$i; done | sort -u`
rm -rf libc-$(VER)
mkdir libc-$(VER) ; cd libc-$(VER) ; tar xf ../temp.tar
@@ -66,9 +101,3 @@ dist: clean
dist_ver: dist
mv libc-8086-$(VER).tar.gz ..
echo $(VER) > ../Libc_version
-
-transfer: dummy
- @echo Checking for transfers
- @for i in `cat .config.dir`; do \
- grep -q '^transfer' $$i/Makefile && make -C $$i $@ ; \
- done ; echo -n
diff --git a/libc/Pre_main b/libc/Pre_main
index e3793f1..0b3bec2 100644
--- a/libc/Pre_main
+++ b/libc/Pre_main
@@ -5,12 +5,13 @@ exit() function.
The exit processing uses the standard 'atexit' and 'on_exit' functions
see the normal man pages.
-Execution of code before main is Linux-8086 specific; the method
-is similar to this:
+Execution of code before main is Linux-8086 (actually BCC) specific; the
+method works like this:
/**********************/
-int global_var_that_needs_init;
+long global_var_that_needs_init;
+#ifdef __AS386_16__
#asm
loc 1 ! Make sure the pointer is in the correct segment
auto_func: ! Label for bcc -M to work.
@@ -18,10 +19,20 @@ auto_func: ! Label for bcc -M to work.
.word no_op ! Space filler cause segs are padded to 4 bytes.
.text ! So the function after is also in the correct seg.
#endasm
+#endif
+
+#ifdef __AS386_32__
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .long _init_vars ! Pointer to the autorun function
+ .text ! So the function after is also in the correct seg.
+#endasm
+#endif
static void init_vars()
{
- global_var_that_needs_init = getuid();
+ time(&global_var_that_needs_init);
}
/**********************/
@@ -33,7 +44,7 @@ not be executed.
Also do note that the init functions are called in essentially random order
(It's actually the order that they appear in the executable) so you must be
-careful not to call any routines tht have their own autostart from inside
+careful not to call any routines that have their own autostart from inside
your autostart. Nevertheless you should try to ensure that your routines
will fail gracefully if they are called before the initilisation routine.
diff --git a/libc/README b/libc/README
index feb6e4a..0b65f99 100644
--- a/libc/README
+++ b/libc/README
@@ -1,31 +1,37 @@
-The lib can be compiled five different ways for Linux-8086 standard,
-Linux-8086 with 'First arg in AX', MS-DOS, BCC-386 or for GNU-386. At
-the moment the 386 versions are missing some _very_ important bits.
-This can be done by running.
+The lib can be compiled six different ways for Linux-8086 standard,
+Linux-8086 with 'First arg in AX', Linx-8086 standalone, MS-DOS, BCC-386
+or for GNU-386. At the moment the 386 GNU version will NOT work, the
+BCC-386 is just barely working.
+
+This can be done by running one of.
make PLATFORM=i86-FAST clean all
make PLATFORM=i86-DOS clean all
-an so on.
+ make PLATFORM=i86-BIOS clean all
+ make PLATFORM=i386-BCC clean all
SYSTEM CALLS
The system call table (syscalls/syscall.dat) is constantly changing, using
skewed versions is _very_ likely to give you segfaults and strange behaviour.
For this lib you should use the same version of elksemu.
The system call table will only be frozen when the linux-86 kernel is
-running and reasonably stable.
+running and reasonably stable. The 386 version is using a distinct list
+that matches the Linux-i386 syscall list.
THE COMPILER
You should use the versions of bcc, unproto, as86, ld86 and elksemu that
are in this version of the combined development environment. Some other
versions will work but often they'll just appear to work or not work at
all. The standard bcc-cc1 won't pickup the right header files, the
-standard ld86 won't generate COM files and looks in the wrong place for
-crt0.o and libc.a.
+standard ld86 won't generate COM files or 386-Linux files and looks in
+the wrong place for crt0.o and libc.a.
Main Subdirectories.
bcc Lots of BCC helper functions
+bios Minimal 'system' calls for standalone executables.
error The C error functions.
grp Routines for /etc/group, from Nat
+i386fp BCC's floating point routines for 386 code.
include Some include files, some new others Glib or Glib hacked.
kinclude Kernel include files, here for now.
malloc1 My malloc routines
@@ -34,12 +40,12 @@ misc Various larger functions
msdos This is the equlivent of the syscall directory for msdos.
pwd Routines for /etc/passwd, from Nat
regexp Standard regular expression parser
-stdio1 Joel's standard I/O functions - as yet rather incomplete
stdio2 My standard I/O
string The functions for string.h
-syscall All the system call functions, and a few tied lib ones.
+syscall All the system call functions, and some tied lib ones.
termios Termimal mode control.
utmp /etc/utmp updating
+time Unix time related functions.
tests Various C programs used to test the lib.
Directory structure:
diff --git a/libc/bcc/Makefile b/libc/bcc/Makefile
index 4f52133..991b50e 100644
--- a/libc/bcc/Makefile
+++ b/libc/bcc/Makefile
@@ -4,10 +4,20 @@
TOP=..
include $(TOP)/Make.defs
+CFLAGS=$(CCFLAGS)
# Support for integer arithmetic
+ifeq ($(LIB_CPU),i86)
IOBJ=__idiv.o __idivu.o __imod.o __imodu.o __imul.o __isl.o __isr.o __isru.o
ISRC=bcc_int.c
+endif
+
+# Support for integer arithmetic when compiling for the i386
+ifeq ($(LIB_CPU),i386)
+ISRC=bcc_i386.c
+IOBJ=__idiv.o __idivu.o __imod.o __imodu.o __imul.o __isl.o __isr.o __isru.o \
+ __divsi3.o
+endif
# Support for long arithmetic on little-endian (normal) longs
LSRC=bcc_long.c
@@ -30,7 +40,13 @@ PSRC=bcc_io.c
POBJ=__inport.o __inportb.o __outport.o __outportb.o __peekb.o __peekw.o \
__pokeb.o __pokew.o
+ifeq ($(LIB_CPU),i86)
OBJ=__ldivmod.o $(IOBJ) $(LOBJ) $(AOBJ)
+endif
+ifeq ($(LIB_CPU),i386)
+OBJ=$(IOBJ) $(AOBJ)
+endif
+
OLDOBJ=$(ROBJ) $(POBJ)
all: $(OBJ)
diff --git a/libc/bcc/bcc_i386.c b/libc/bcc/bcc_i386.c
new file mode 100644
index 0000000..d994628
--- /dev/null
+++ b/libc/bcc/bcc_i386.c
@@ -0,0 +1,149 @@
+/************************************************************************/
+/* This file contains the BCC compiler helper functions */
+/* Support for 386 integer arithmetic
+ * __divsi3.o __idiv.o __idivu.o __imod.o __imodu.o __imul.o
+ * __isl.o __isr.o __isru.o
+ */
+
+#ifdef __AS386_32__
+#asm
+ .text ! This is common to all.
+ .align 4
+#endasm
+
+#ifdef L___divsi3
+#asm
+! divsi3.s
+ .globl ___divsi3
+ ___divsi3:
+ push edx
+ mov eax,[esp+4+4]
+ cdq
+ idiv [esp+4+4+4]
+ pop edx
+ ret
+
+ .globl ___udivsi3
+ .text
+ .align 4
+
+ ___udivsi3:
+ push edx
+ mov eax,[esp+4+4]
+ sub edx,edx
+ div [esp+4+4+4]
+ pop edx
+ ret
+#endasm
+#endif
+
+#ifdef L___idiv
+#asm
+! idiv.s
+! idiv_ doesn`t preserve edx (returns remainder in it)
+
+ .globl idiv_
+idiv_:
+ cdq
+ idiv ebx
+ ret
+#endasm
+#endif
+
+#ifdef L___idivu
+#asm
+! idivu.s
+! idiv_u doesn`t preserve edx (returns remainder in it)
+
+ .globl idiv_u
+idiv_u:
+ xor edx,edx
+ div ebx
+ ret
+#endasm
+#endif
+
+#ifdef L___imod
+#asm
+! imod.s
+! imod doesn`t preserve edx (returns quotient in it)
+
+ .globl imod
+imod:
+ cdq
+ idiv ebx
+ mov eax,edx ! instruction queue full so xchg slower
+ ret
+#endasm
+#endif
+
+#ifdef L___imodu
+#asm
+! imodu.s
+! imodu doesn`t preserve edx (returns quotient in it)
+
+ .globl imodu
+imodu:
+ xor edx,edx
+ div ebx
+ mov eax,edx ! instruction queue full so xchg slower
+ ret
+#endasm
+#endif
+
+#ifdef L___imul
+#asm
+! imul.s
+! imul_, imul_u don`t preserve edx
+
+ .globl imul_
+ .globl imul_u
+imul_:
+imul_u:
+ imul ebx
+ ret
+#endasm
+#endif
+
+#ifdef L___isl
+#asm
+! isl.s
+! isl, islu don`t preserve cl
+
+ .globl isl
+ .globl islu
+isl:
+islu:
+ mov cl,bl
+ shl eax,cl
+ ret
+#endasm
+#endif
+
+#ifdef L___isr
+#asm
+! isr.s
+! isr doesn`t preserve cl
+
+ .globl isr
+isr:
+ mov cl,bl
+ sar eax,cl
+ ret
+#endasm
+#endif
+
+#ifdef L___isru
+#asm
+! isru.s
+! isru doesn`t preserve cl
+
+ .globl isru
+isru:
+ mov cl,bl
+ shr eax,cl
+ ret
+#endasm
+#endif
+
+#endif
diff --git a/libc/bcc/heap.c b/libc/bcc/heap.c
index af4e898..6a6ce2c 100644
--- a/libc/bcc/heap.c
+++ b/libc/bcc/heap.c
@@ -3,6 +3,8 @@
* under the GNU Library General Public License.
*/
+#include <errno.h>
+
/****************************************************************************/
#ifdef L_errno
@@ -11,8 +13,9 @@ int errno = 0; /* libc error value */
/****************************************************************************/
-#ifdef L___brk_addr
#ifdef __AS386_16__
+
+#ifdef L___brk_addr
#asm
.data
export brk_addr
@@ -20,14 +23,12 @@ brk_addr: .word __end ! This holds the current return for sbrk(0)
.text
#endasm
#endif
-#endif
/****************************************************************************/
#ifdef L_sbrk
-#ifdef __AS386_16__
int sbrk(brk_off)
-unsigned int brk_off;
+int brk_off;
{
#asm
mov bx,sp
@@ -36,14 +37,14 @@ unsigned int brk_off;
#endif
test ax,ax
jnz has_change
- mov ax,[brk_addr] ! Simple one; read current - can`t fail.
+ mov ax,[brk_addr] ! Simple one, read current - can`t fail.
jmp eof
has_change:
js go_down
add ax,[brk_addr] ! Goin up!
jc Enomem
- sub bx,#64 ! Safety space
+ sub bx,#512 ! Safety space 512 bytes
cmp bx,ax ! Too close ?
jb Enomem
@@ -71,22 +72,20 @@ eof:
#endasm
}
#endif
-#endif
/****************************************************************************/
#ifdef L_brk
-#ifdef __AS386_16__
int
brk(new_brk)
-void * new_brk;
+char * new_brk;
{
#asm
mov bx,sp
#if !__FIRST_ARG_IN_AX__
mov ax,[bx+2] ! Fetch the requested value
#endif
- sub bx,#64 ! Safety space
+ sub bx,#512 ! Safety space 512 bytes
cmp bx,ax ! Too close ?
jb Enomem
cmp ax,#__end
@@ -111,6 +110,75 @@ brk_ok:
#endasm
}
#endif
+
#endif
/****************************************************************************/
+
+#ifdef __AS386_32__
+extern char * __brk_addr;
+extern char * __brk();
+
+#ifdef L___brk_addr
+char * __brk_addr = 0; /* This holds the current return for sbrk(0) */
+
+char *
+__brk(val)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov ebx,eax
+#else
+ mov ebx,[esp+4]
+#endif
+ mov eax,#45
+ int $80
+#endasm
+}
+
+__brk_addr_init()
+{
+ if( __brk_addr == 0 && (__brk_addr = __brk(0)) == 0 )
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+#ifdef L_sbrk
+char *
+sbrk(brk_off)
+int brk_off;
+{
+ char * new_brk;
+ if( __brk_addr_init() ) return (char*)-1;
+ if( brk_off == 0 ) return __brk_addr;
+
+ new_brk = __brk_addr + brk_off;
+ __brk_addr = __brk(new_brk);
+ if( __brk_addr != new_brk )
+ {
+ errno = ENOMEM;
+ return (char*)-1;
+ }
+ return __brk_addr - brk_off;
+}
+#endif
+
+#ifdef L_brk
+int
+brk(new_brk)
+char * new_brk;
+{
+ if( __brk_addr_init() ) return -1;
+
+ __brk_addr = __brk(new_brk);
+ if( __brk_addr == new_brk ) return 0;
+ errno = ENOMEM;
+ return -1;
+}
+#endif
+
+#endif
diff --git a/libc/bcc/ldiv.c b/libc/bcc/ldiv.c
index 6bfef0a..aab0701 100644
--- a/libc/bcc/ldiv.c
+++ b/libc/bcc/ldiv.c
@@ -1,3 +1,5 @@
+
+#ifdef __AS386_16__
#asm
.text
export _ldiv
@@ -24,4 +26,5 @@ _ldiv:
.data
.bss
#endasm
+#endif
diff --git a/libc/bios/Config b/libc/bios/Config
new file mode 100644
index 0000000..e7f1971
--- /dev/null
+++ b/libc/bios/Config
@@ -0,0 +1 @@
+bios: Minimal syscalls for BIOS level
diff --git a/libc/bios/Makefile b/libc/bios/Makefile
new file mode 100644
index 0000000..934ec07
--- /dev/null
+++ b/libc/bios/Makefile
@@ -0,0 +1,30 @@
+# Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+ifeq ($(LIB_OS),BIOS)
+ASRC=bios.c
+AOBJ=bios_start.o bios_isatty.o \
+ bios_open.o bios_read.o bios_write.o bios_lseek.o bios_close.o
+
+BSRC=bios_vid.c
+BOBJ=bios_putc.o bios_getc.o bios_rdline.o
+endif
+
+all: $(AOBJ) $(BOBJ)
+
+libc.a: $(AOBJ) $(BOBJ)
+ ar r ../$(LIBC) $(AOBJ) $(BOBJ)
+ @touch libc.a
+
+clean:
+ rm -f *.o libc.a
+
+$(AOBJ): $(ASRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ASRC)
+
+$(BOBJ): $(BSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(BSRC)
diff --git a/libc/bios/README b/libc/bios/README
new file mode 100644
index 0000000..cc883e1
--- /dev/null
+++ b/libc/bios/README
@@ -0,0 +1,10 @@
+Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+This file is part of the Linux-8086 C library and is distributed
+under the GNU Library General Public License.
+
+This is a very simple set of functions for standalone executables.
+
+There is a choice as to which console type you want to use, I think
+the VT52 clone is best.
+
+-Robert
diff --git a/libc/bios/bios.c b/libc/bios/bios.c
new file mode 100644
index 0000000..18e2448
--- /dev/null
+++ b/libc/bios/bios.c
@@ -0,0 +1,205 @@
+/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#if !__FIRST_ARG_IN_AX__
+#ifdef __AS386_16__
+#ifdef __STANDALONE__
+
+#include <dos.h>
+#include <fcntl.h>
+#include <errno.h>
+int errno;
+
+#ifdef L_bios_start
+char ** environ = { 0 };
+
+void (*__cleanup)() = 0;
+
+#asm
+ .data
+export ___argr
+___argr:
+ .word 0,0,0,0,0,0,0 ! A struct REGS
+defarg:
+ .word boot_str, 0
+boot_str:
+ .asciz "boot"
+
+ .text
+export ___cstartup ! Crt0 startup
+___cstartup:
+ mov ___argr+0,ax
+ mov ___argr+2,bx
+ mov ___argr+4,cx
+ mov ___argr+6,dx
+ mov ___argr+8,si
+ mov ___argr+10,di
+
+zap_bss: ! Clear the BSS
+ mov ax,ds
+ mov es,ax ! ES now data seg
+ mov di,#__edata
+ mov cx,#__end
+ sub cx,di
+ xor ax,ax
+ cld
+ rep
+ stosb
+
+ push [_environ]
+ mov ax,#defarg ! Don`t define __mkargv, standalone programs don`t
+ push ax ! get any arguments.
+ mov ax,#1
+ push ax
+
+ mov si,#auto_start ! Pointer to first autostart function
+auto_run:
+ mov bx,[si]
+ test bx,bx
+ jz no_entry
+ call bx ! Call the function
+no_entry:
+ inc si ! SI at next
+ inc si
+ jmp auto_run ! And round for the next.
+
+call_exit: ! Last item called by above.
+ pop bx ! Be tidy.
+ push ax ! At the end the last called was main() push it`s
+ call _exit ! return val and call exit();
+bad_exit:
+ jmp bad_exit ! Exit returned !!
+
+ loc 2
+ .word _main ! Segment 2 is the trailing pointers, main and the
+ .word call_exit ! routine to call exit.
+data_start:
+
+ .text
+export _exit
+_exit: ! exit(rv) function
+ mov bx,sp
+ push [bx+2] ! Copy the `rv` for the exit fuctions.
+ mov bx,[___cleanup] ! Call exit, normally this is `__do_exit`
+ test bx,bx
+ je no_clean ! But it`s default is null
+ call bx
+no_clean:
+ inc sp
+ inc sp
+
+export __exit
+__exit:
+ xor ax,ax
+ mov es,ax
+ mov ax,cs
+ seg es
+ mov [$E6*4+2],ax
+ mov ax,#reti_ins
+ seg es
+ mov [$E6*4],ax
+ mov ax,#$FFFF
+ int $E6 ! Try to exit DOSEMU
+ ! If we get here we`re not in dosemu.
+ seg es
+ mov [$472],#$1234 ! Warm reboot.
+ jmpi $0000,$FFFF
+reti_ins:
+ reti
+
+#endasm
+
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_write
+write(fd,buf,len)
+int fd,len;
+char * buf;
+{
+ register int v, c;
+ if(fd == 1 || fd == 2)
+ {
+ for(v=len; v>0; v--)
+ {
+ c= *buf++;
+ if( c == '\n') bios_putc('\r');
+ bios_putc(c);
+ }
+ return len;
+ }
+ errno = EBADF;
+ return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_read
+read(fd,buf,len)
+int fd,len;
+char * buf;
+{
+ if(fd == 0) return bios_rdline(buf, len);
+ errno = EBADF;
+ return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_lseek
+long
+lseek(fd, offt, whence)
+int fd, whence;
+long offt;
+{
+ if( fd >= 0 && fd <= 2 ) errno = ESPIPE;
+ else errno = EBADF;
+ return -1L;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_open
+open(name, flags, mode)
+char * name;
+int flags, mode;
+{
+ errno = ENOENT;
+ return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_close
+close(fd)
+int fd;
+{
+ if( fd >= 0 && fd <= 2 ) errno = ENOSYS;
+ else errno = EBADF;
+ return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_isatty
+isatty(fd)
+int fd;
+{
+ if( fd >= 0 && fd <= 2 ) return 1;
+ return 0;
+}
+#endif
+
+/****************************************************************************/
+
+#endif
+#endif
+#endif
diff --git a/libc/bios/bios_vid.c b/libc/bios/bios_vid.c
new file mode 100644
index 0000000..0d891a0
--- /dev/null
+++ b/libc/bios/bios_vid.c
@@ -0,0 +1,465 @@
+/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/* Various possible console types */
+#define VT52_CON /* IMO the best, no clear to EOS/EOL yet */
+#define XANSI_CON /* Largest but still not complete */
+#define XDUMB_CON /* Can't do much */
+#define XSPEC_CON /* Incomplete, best for slow links */
+
+#if !__FIRST_ARG_IN_AX__
+#ifdef __AS386_16__
+#ifdef __STANDALONE__
+
+#include <dos.h>
+#include <errno.h>
+int errno;
+
+#ifdef L_bios_putc
+#define CTRL(x) ((x)&0x1F)
+static int last_attr = 0x07;
+static int con_mode;
+static unsigned char con_height = 24, con_width = 79;
+
+static int con_colour = 0;
+static unsigned char con_row, con_col;
+
+#ifdef VT52_CON
+bios_putc(c)
+int c;
+{
+static int ctrl = 0;
+ int new_attr;
+ if( con_mode==0 ) asm_coninit();
+
+ switch( ctrl )
+ {
+ case 1:
+ ctrl=0;
+ switch(c)
+ {
+ case 'A': if( con_row ) con_row--; asm_cpos(con_row, con_col); break;
+ case 'B': if( con_row != con_height ) con_row++;
+ asm_cpos(con_row, con_col); break;
+ case 'C': if( con_col != con_height ) con_col++;
+ asm_cpos(con_row, con_col); break;
+ case 'D': if( con_col ) con_col--; asm_cpos(con_row, con_col); break;
+ case 'E': last_attr = 0x07; asm_cls();
+ case 'H': asm_cpos(0,0); break;
+ case 'J': asm_cls(); break;
+ case 'K': break;
+ case 'R': ctrl = 2; break; /* Foreground */
+ case 'S': ctrl = 3; break; /* Background */
+ case 'Y': ctrl = 4; break; /* ttypos */
+ }
+ break;
+ case 2: ctrl=0; new_attr = (last_attr & 0xF0) + (c&0xF);
+ if(0) {
+ case 3: ctrl=0; new_attr = (last_attr & 0x0F) + (c<<4);
+ }
+ switch(c)
+ {
+ case '_': if( !con_colour ) last_attr = (last_attr&0x88) + 1;
+ break;
+ case '!': last_attr = (last_attr&0x88) + 0x70; break;
+ case ' ': last_attr = 0x07; break;
+ case '+': last_attr |= 0x08; break;
+ case '*': last_attr |= 0x80; break;
+
+ default: if( con_colour )
+ last_attr = new_attr;
+ }
+ break;
+ case 4: ctrl=5; con_col = c-' '; break;
+ case 5: ctrl=0; con_row = c-' '; asm_cpos(con_row, con_col); break;
+ break;
+
+ default:
+ if( c & 0xE0 )
+ { asm_colour(last_attr) ; asm_putc(c); }
+ else switch(c)
+ {
+ default:
+ asm_putc(c);
+ break;
+ case CTRL('L'):
+ asm_cpos(0,0);
+ asm_cls();
+ break;
+ case CTRL('['):
+ ctrl = 1;
+ asm_gpos();
+ break;
+ }
+ break;
+ }
+}
+#endif
+
+#ifdef ANSI_CON
+#define MAX_ARGS 8
+static int colconv[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+static int vidcnt = 0;
+static int ansi_2 = 0;
+static int ansi_argc = 0;
+static int ansi_argv[MAX_ARGS];
+
+bios_putc(c)
+int c;
+{
+ if( con_mode==0 ) asm_coninit();
+
+ if( vidcnt == 0 || c < ' ' || c > '~' )
+ {
+ switch(c & 0xFF)
+ {
+ default:
+ asm_colour(last_attr);
+ asm_putc(c);
+ break;
+ case CTRL('L'):
+ asm_cpos(0,0);
+ asm_cls();
+ break;
+ case CTRL('['):
+ vidcnt=1;
+ break;
+ }
+ return;
+ }
+
+ /* ... ansi/vt100 interpretation, this collects _all_ ansi control strings */
+ switch(vidcnt)
+ {
+ case 1: for(ansi_argc=0; ansi_argc<MAX_ARGS; ansi_argc++)
+ ansi_argv[ansi_argc] = 0;
+ ansi_2 = 0;
+ ansi_argc = 0;
+ vidcnt++;
+
+ if( c != '[' )
+ {
+ do_ansi(c + 0x1B00, ansi_argc, ansi_argv);
+ vidcnt = 0;
+ }
+ break;
+
+ case 2: if( c == ';' )
+ {
+ if( ansi_argc < MAX_ARGS )
+ ansi_argc++;
+ }
+ else if( c >= '0' && c <= '9' )
+ ansi_argv[ansi_argc] = ansi_argv[ansi_argc] * 10 + c - '0';
+ else if( c >= '@' )
+ {
+ do_ansi(c+ansi_2, ++ansi_argc, ansi_argv);
+ vidcnt = 0;
+ }
+ else
+ ansi_2 = (c<<8);
+ break;
+
+ default: vidcnt = 0; /* This definitly won't happen ... definitly ... */
+ }
+}
+
+do_ansi(ctrl, argc, argv)
+int ctrl, argc, *argv;
+{
+ switch(ctrl)
+ {
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ asm_gpos();
+ if( argv[0] < 1 ) argv[0] = 1;
+ switch(ctrl)
+ {
+ case 'A': if( argv[0]>con_row ) con_row=0; else con_row-=argv[0]; break;
+ case 'B': if( argv[0]+con_row>con_height )
+ con_row = con_height;
+ else
+ con_row += argv[0];
+ break;
+ case 'C': if( argv[0]+con_col>con_width )
+ con_col = con_width;
+ else
+ con_col += argv[0];
+ break;
+ case 'D': if( argv[0]>con_col ) con_col=0; else con_col-=argv[0]; break;
+ }
+ asm_cpos(con_row, con_col);
+ break;
+
+ case 'H':
+ if( --argv[0] < 0 ) argv[0] = 0;
+ if( --argv[1] < 0 ) argv[1] = 0;
+ asm_cpos(argv[0],argv[1]);
+ break;
+ case 'J': if( argv[0] == 2 ) asm_cls();
+ break;
+ case 'm':
+ {
+ int ar;
+ for(ar=0; ar<argc; ar++) switch(argv[ar])
+ {
+ case 0: last_attr = 0x07; break;
+ case 1: last_attr |= 0x08; break;
+ case 5: last_attr |= 0x80; break;
+ case 7: last_attr = 0x70; break;
+ case 30: case 31: case 32: case 33:
+ case 34: case 35: case 36: case 37:
+ if( con_colour )
+ last_attr = ((last_attr&0xF8)|(colconv[argv[ar]-30]));
+ break;
+ case 40: case 41: case 42: case 43:
+ case 44: case 45: case 46: case 47:
+ if( con_colour )
+ last_attr = ((last_attr&0x8F)|((colconv[argv[ar]-40])<<4));
+ break;
+ default: break;
+ }
+ }
+ }
+}
+#endif
+
+#ifdef SPEC_CON
+static char vidbuf[3];
+static int vidcnt=0;
+
+bios_putc(c)
+int c;
+{
+ if( con_mode==0 ) asm_coninit();
+ if( vidcnt == 0 )
+ {
+ if( c & 0xE0 )
+ { asm_colour(last_attr) ; asm_putc(c); }
+ else switch(c)
+ {
+ default:
+ asm_putc(c);
+ break;
+ case CTRL('L'):
+ asm_cpos(0,0);
+ asm_cls();
+ break;
+ case CTRL('P'):
+ case CTRL(']'):
+ vidbuf[vidcnt++] = c;
+ break;
+ }
+ }
+ else
+ {
+ vidbuf[vidcnt++] = c;
+ if( vidcnt < 3 &&
+ (vidbuf[0] != CTRL(']') || vidbuf[1] < '`' || vidbuf[1] > 'p'))
+ return;
+
+ if( vidbuf[0] == CTRL('P') )
+ {
+ if( vidbuf[1] >= 32 && vidbuf[1] <= 56
+ && vidbuf[2] >= 32 && vidbuf[2] <= 111 )
+ asm_cpos((vidbuf[1]-32), (vidbuf[2]-32));
+ }
+ else
+ {
+ if( vidbuf[1] >= '`' )
+ last_attr = ( (vidbuf[1]&0xF) | (last_attr&0xF0));
+ else
+ last_attr = ( (vidbuf[2]&0xF) | ((vidbuf[1]&0xF)<<4));
+
+ if( !con_colour )
+ last_attr = (last_attr&0x88) + ((last_attr&7)?0x07:0x70);
+ }
+ vidcnt=0;
+ }
+}
+#endif
+
+#ifdef DUMB_CON
+bios_putc(c)
+int c;
+{
+ if( con_mode==0 ) asm_coninit();
+ if( c & 0xE0 ) asm_putc(c);
+ else switch(c)
+ {
+ default:
+ asm_putc(c);
+ break;
+ case CTRL('L'):
+ asm_cls();
+ case CTRL('^'):
+ asm_cpos(0,0);
+ break;
+ }
+}
+#endif
+
+static asm_coninit()
+{
+#asm
+ mov ax,#$0F00
+ int $10
+ mov _con_mode,ax
+#endasm
+ if( (con_mode &0xFF) > 39 ) con_width = (con_mode>>8);
+ if( (con_mode&0xFF) != 0x7)
+ con_colour = 1;
+}
+
+static asm_putc(c)
+{
+#asm
+#if !__FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov ax,[bx+2]
+#endif
+ mov ah,#$0E
+ mov bx,#7
+ int $10
+#endasm
+}
+
+static asm_cls()
+{
+#asm
+ push bp ! Bug in some old BIOS`s
+ !mov ax,#$0500
+ !int $10
+ mov ax,#$0600
+ mov bh,_last_attr
+ mov cx,#$0000
+ mov dl,_con_width
+ mov dh,_con_height
+ int $10
+ pop bp
+#endasm
+}
+
+static asm_cpos(r,c)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov dh,al
+ mov ax,[bx+2]
+ mov dl,al
+#else
+ mov bx,sp
+ mov ax,[bx+2]
+ mov dh,al
+ mov ax,[bx+4]
+ mov dl,al
+#endif
+ mov ah,#$02
+ mov bx,#7
+ int $10
+#endasm
+}
+
+#ifndef DUMB_CON
+static asm_colour(c)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx+2]
+#endif
+ mov ah,#$08
+ int $10
+ mov ah,#$09
+ mov cx,#1
+ int $10
+#endasm
+}
+
+static asm_gpos()
+{
+#asm
+ mov ah,#$03
+ mov bx,#7
+ int $10
+ mov [_con_row],dh
+ mov [_con_col],dl
+ mov ax,cx
+#endasm
+}
+#endif
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_rdline
+bios_rdline(buf, len)
+char * buf;
+int len;
+{
+ int ch;
+ int pos=0;
+
+ if( len == 1 )
+ {
+ buf[0]=((ch=bios_getc())&0xFF?ch&0xFF:((ch>>8)&0xFF|0x80));
+ return 1;
+ }
+
+ for(ch=0;;)
+ {
+ if(ch != '\003')
+ {
+ ch = bios_getc();
+ if( pos == 0 && (ch&0xFF) == 0 )
+ {
+ buf[0] = ((ch>>8)|0x80);
+ return 1;
+ }
+ ch &= 0x7F;
+ }
+ if( ch == '\r' )
+ {
+ bios_putc('\r'); bios_putc('\n');
+ buf[pos++] = '\n';
+ return pos;
+ }
+ if( ch >= ' ' && ch != 0x7F && pos < len-1)
+ bios_putc(buf[pos++] = ch);
+ else if( (ch == '\003' || ch == '\b') && pos > 0 )
+ {
+ bios_putc('\b'); bios_putc(' '); bios_putc('\b');
+ pos--;
+ }
+ else if( ch == '\003' )
+ return 0;
+ else
+ bios_putc('\007');
+ }
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_getc
+bios_getc()
+{
+#asm
+ xor ax,ax
+ int $16
+#endasm
+}
+#endif
+
+/****************************************************************************/
+
+#endif
+#endif
+#endif
diff --git a/libc/crt0.c b/libc/crt0.c
index 71ca6bc..b21b525 100644
--- a/libc/crt0.c
+++ b/libc/crt0.c
@@ -20,15 +20,20 @@ entry startup ! Crt0 startup
startup:
br ___cstartup
export no_op
-no_op: ! Generic no operation call (the byte was free :-) )
+no_op: ! Generic no operation call
ret
+ .ascii __LIBC__ ! Version id.
+
loc 1 ! Segment 1 is where the pointers to the autostart
-ZP_safety: ! functions are stored.
+ ! functions are stored.
+#if !__AS386_32__
+ZP_safety:
.word 0 ! But first some zeros to avoid null pointer writes.
.word 0
.word 0
.word 0
+#endif
export auto_start
auto_start:
diff --git a/libc/crt0.o b/libc/crt0.o
deleted file mode 100644
index e43705b..0000000
--- a/libc/crt0.o
+++ /dev/null
Binary files differ
diff --git a/libc/error/Makefile b/libc/error/Makefile
index bcc9287..dc9b98e 100644
--- a/libc/error/Makefile
+++ b/libc/error/Makefile
@@ -5,7 +5,9 @@
TOP=..
include $(TOP)/Make.defs
+ifeq ($(LIB_OS),ELKS)
OBJ=error.o sys_errlist.o perror.o sys_siglist.o __assert.o
+endif
all: $(OBJ)
diff --git a/libc/error/sys_errlist.c b/libc/error/sys_errlist.c
index 1d9e65b..79a40bf 100644
--- a/libc/error/sys_errlist.c
+++ b/libc/error/sys_errlist.c
@@ -23,7 +23,6 @@ int sys_nerr = NR_ERRORS;
loc 1 ! Make sure the pointer is in the correct segment
auto_func: ! Label for bcc -M to work.
.word _init_vars ! Pointer to the autorun function
- .word no_op ! Space filler cause segs are padded to 4 bytes.
.text ! So the function after is also in the correct seg.
#endasm
diff --git a/libc/grp/Makefile b/libc/grp/Makefile
index e8cb13a..f5d42a0 100644
--- a/libc/grp/Makefile
+++ b/libc/grp/Makefile
@@ -5,15 +5,20 @@
TOP=..
include $(TOP)/Make.defs
-ifeq ($(PLATFORM),i386-Linux)
+ifeq ($(LIB_CPU),g386)
CFLAGS+=$(WALL)
-else # ifeq ($(PLATFORM),i86-ELKS)
+else
CFLAGS=$(CCFLAGS) $(LIBDEFS) -ansi
endif
GSRC=__getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c initgroups.c \
config-grp.h
+
+ifeq ($(LIB_OS),ELKS)
GOBJ=__getgrent.o grent.o getgrnam.o getgrgid.o fgetgrent.o initgroups.o
+else
+GOBJ=
+endif
all: $(GOBJ)
@@ -35,7 +40,3 @@ libgrp.a: $(GOBJ)
clean:
rm -f *.o libc.a libgrp.a
-
-
-
-
diff --git a/libc/gtermcap/Makefile b/libc/gtermcap/Makefile
index fe4e8ae..62a966d 100644
--- a/libc/gtermcap/Makefile
+++ b/libc/gtermcap/Makefile
@@ -5,7 +5,9 @@
TOP=..
include $(TOP)/Make.defs
+ifeq ($(LIB_OS),ELKS)
OBJ=termcap.o tparam.o
+endif
all: $(OBJ)
diff --git a/libc/i386fp/Config b/libc/i386fp/Config
new file mode 100644
index 0000000..dac69f0
--- /dev/null
+++ b/libc/i386fp/Config
@@ -0,0 +1 @@
+386fp: Bcc 386 floating point
diff --git a/libc/i386fp/Makefile b/libc/i386fp/Makefile
new file mode 100644
index 0000000..88158f7
--- /dev/null
+++ b/libc/i386fp/Makefile
@@ -0,0 +1,58 @@
+# Makefile for bcc 386 software floating point library
+
+TOP=..
+include $(TOP)/Make.defs
+
+.SUFFIXES: .x # .x files are .s files that need C-preprocessing
+.x.o:
+ cp $< tmp.c
+ $(CC) $(CFLAGS) -P tmp.c | $(AS) - -n $* -o $@
+
+# $(ASCPP) $(ASCPPFLAGS) $< >tmp
+# $(AS) tmp -n $* -l tmp.lst -o $@
+
+AS =as86 -3
+ASCPP =/lib/cpp
+ASCPPFLAGS =-P -traditional
+
+FPDIST =Makefile $(FPSRC) test.c bccfp.tex
+FPSRC =fadd.x fcomp.x fdiv.x fmul.x fbsr.x \
+ fperr.c fperror.x fptoi.x fpushd.x fpulld.x \
+ fpushi.x fpushf.x fpullf.x frexp.x ftst.x \
+ gcclib.x \
+ fabs.x ldexp.x modf.c \
+ fperr.h fplib.h
+FPOBJ =fadd.o fcomp.o fdiv.o fmul.o fpbsr.o \
+ fperr.o fperror.o fptoi.o fpushd.o fpulld.o \
+ fpushi.o fpushf.o fpullf.o frexp.o ftst.o \
+ fabs.o ldexp.o modf.o
+JUNK =tmp tmp.c tmp.lst
+LIB =.
+
+test: test.c $(LIB)/libfp.a
+ $(CC) -o $@ test.c $(LIB)/libfp.a -lm
+
+$(FPOBJ): fplib.h
+fperr.c fperror.x: fperr.h
+
+$(LIB)/libfp.a: $(FPOBJ)
+ ar rc $(LIB)/libfp.a $(FPOBJ)
+ rm -f $(JUNK)
+
+ifeq ($(LIB_CPU),i386)
+libc.a: $(FPOBJ)
+ rm -f $(JUNK)
+ ar rc ../libc.a $(FPOBJ)
+else
+libc.a:
+endif
+
+dist: $(FPDIST)
+ /bin/tar cvf - $(FPDIST) | /bin/compress -b 13 >bccfp.tar.Z
+ uue bccfp.tar.Z
+
+clean:
+ rm -f $(FPOBJ) $(JUNK) test
+ rm -f $(LIB)/libfp.a bccfp.tar.Z bccfp.uue
+
+realclean: clean
diff --git a/libc/i386fp/bccfp.tex b/libc/i386fp/bccfp.tex
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libc/i386fp/bccfp.tex
diff --git a/libc/i386fp/changes b/libc/i386fp/changes
new file mode 100644
index 0000000..2cc632a
--- /dev/null
+++ b/libc/i386fp/changes
@@ -0,0 +1,30 @@
+fcomp:
+Fixes for negative 0 (perhaps this shouldn't be generated, like denormals
+and infinities (these would cause even more trouble) but Fsub routine or
+something generated one).
+
+frexp.x:
+Deleted 3rd arg (used to return value when bcc wasn't doing it right).
+
+Fixed frexp(value = 0) and ldexp(value = 0) returning nonzero.
+
+Most files:
+Changed comment symbol to '!' for new assembler (not the native ';' in
+case this is ported to ACK someday).
+
+Avoided using ebp and unnecessary register saves.
+
+Changed assembler style to make it a bit more portable or like I do it
+(no '$' for hex, 8[esp] instead of [esp+8], use only .define and not export
+or .globl, use '#' (could use nothing) instead of '*' for immediate).
+The partly-supported 8(ebp) and .globl would be still more portable.
+
+Changed terminology 'mantissa' to 'fraction'.
+
+Round to even. Required for 'paranioa' not to find any defects.
+
+Used preprocessor.
+
+Parametrized most of the magic numbers. Phew!
+
+Supported denormals. Now 'paranioa' doesn't find any flaws.
diff --git a/libc/i386fp/fabs.x b/libc/i386fp/fabs.x
new file mode 100644
index 0000000..fe81676
--- /dev/null
+++ b/libc/i386fp/fabs.x
@@ -0,0 +1,17 @@
+! bcc 386 floating point routines (version 2) -- _fabs
+! author: Bruce Evans
+
+#include "fplib.h"
+
+! double fabs(double value);
+! returns the absolute value of a number
+! this works for all NaNs, like the 80*87 fabs, but perhaps we should check
+! for exceptions that can happen when an 80*87 register is loaded
+
+ .globl _fabs
+ .align ALIGNMENT
+_fabs:
+ mov eax,PC_SIZE+D_LOW[esp]
+ mov edx,PC_SIZE+D_HIGH[esp]
+ and edx,~D_SIGN_MASK
+ ret
diff --git a/libc/i386fp/fadd.x b/libc/i386fp/fadd.x
new file mode 100644
index 0000000..d1e60b1
--- /dev/null
+++ b/libc/i386fp/fadd.x
@@ -0,0 +1,485 @@
+! bcc 386 floating point routines (version 2)
+! -- Fadd, Faddd, Faddf, Fsub, Fsubd, Fsubf, normalize2
+! author: Bruce Evans
+
+#include "fplib.h"
+
+#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE)
+
+ .extern Fpushf
+ .extern fpdenormal
+ .extern fpoverflow
+ .extern fpunderflow
+
+ .globl Fadd
+ .align ALIGNMENT
+Fadd:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
+ mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
+ call addition
+ mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret #D_SIZE
+
+ .globl Faddd
+ .align ALIGNMENT
+Faddd:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ecx,D_HIGH[ebx]
+ mov ebx,D_LOW[ebx]
+ call addition
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .globl Faddf
+ .align ALIGNMENT
+Faddf:
+ push ebp
+ push edi
+ push esi
+ call Fpushf
+ pop ebx ! yl
+ pop ecx ! yu
+ mov eax,FRAME_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
+ call addition
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .globl Fsub
+ .align ALIGNMENT
+Fsub:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
+ mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
+ xor ecx,#D_SIGN_MASK ! complement sign
+ call addition
+ mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret #D_SIZE
+
+ .globl Fsubd
+ .align ALIGNMENT
+Fsubd:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ecx,D_HIGH[ebx]
+ mov ebx,D_LOW[ebx]
+ xor ecx,#D_SIGN_MASK ! complement sign
+ call addition
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .globl Fsubf
+ .align ALIGNMENT
+Fsubf:
+ push ebp
+ push edi
+ push esi
+ call Fpushf
+ pop ebx ! yl
+ pop ecx ! yu
+ mov eax,FRAME_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
+ xor ecx,#D_SIGN_MASK ! complement sign
+ call addition
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .align ALIGNMENT
+exp_y_0:
+
+! Check for x denormal, to split off special case where both are denormal,
+! so the norm bit (or 1 higher) is known to be set for addition, so addition
+! can be done faster
+
+ test esi,#D_EXP_MASK
+ jnz x_normal_exp_y_0
+ test esi,esi ! test top bits of x fraction
+ jnz both_denorm ! denormal iff nonzero fraction with zero exp
+ test eax,eax ! test rest of fraction
+ jz return_edx_eax ! everything 0 (XXX - do signs matter?)
+both_denorm:
+ call fpdenormal
+ test ebp,#D_SIGN_MASK
+ jnz denorm_subtract
+
+! Add denormal x to denormal or zero y
+
+#if D_NORM_BIT != D_EXP_SHIFT
+#include "error, carry into norm bit does not go into exponent"
+#endif
+
+ add eax,ebx
+ adc esi,edi
+ or edx,esi
+ ret
+
+denorm_subtract:
+ sub eax,ebx
+ sbb esi,edi
+ or edx,esi
+ ret
+
+ .align ALIGNMENT
+x_normal_exp_y_0:
+ test edi,edi ! this is like the check for x denormal
+ jnz y_denorm
+ test ebx,ebx
+ jz return_edx_eax ! y = 0
+y_denorm:
+ call fpdenormal
+ or ecx,#1 << D_EXP_SHIFT ! normalize y by setting exponent to 1
+ jmp got_y
+
+ .align ALIGNMENT
+return_edx_eax:
+ ret
+
+ .align ALIGNMENT
+add_bigshift:
+ cmp ecx,#D_FRAC_BIT+2
+ jae return_edx_eax ! x dominates y
+ sub ecx,#REG_BIT
+ shrd ebp,ebx,cl
+ shrd ebx,edi,cl
+ shr edi,cl
+ add eax,edi
+ adc esi,#0
+ xchg ebp,ebx
+ br normalize
+
+ .align ALIGNMENT
+addition:
+ mov esi,edx ! this mainly for consistent naming
+ and esi,#D_EXP_MASK | D_FRAC_MASK ! discard sign so comparison is simple
+ mov edi,ecx ! free cl for shifts
+ and edi,#D_EXP_MASK | D_FRAC_MASK
+ cmp esi,edi
+ ja xbigger
+ jb swap
+ cmp eax,ebx
+ jae xbigger
+swap:
+ xchg edx,ecx
+ xchg eax,ebx
+ xchg esi,edi
+xbigger:
+
+! edx holds sign of result from here on
+! and exponent of result before the normalization step
+
+ mov ebp,edx ! prepare difference of signs
+ xor ebp,ecx
+
+ and ecx,#D_EXP_MASK ! extract exp_y and check for y 0 or denormal
+ beq exp_y_0 ! otherwise x is not 0 or denormal either
+ and edi,#D_FRAC_MASK ! extract fraction
+ or edi,#D_NORM_MASK ! normalize
+got_y:
+ and esi,#D_FRAC_MASK ! extract fraction
+ or esi,#D_NORM_MASK ! normalize
+
+ sub ecx,edx ! carries from non-exp bits in edx killed later
+ neg ecx
+ and ecx,#D_EXP_MASK
+ shr ecx,#D_EXP_SHIFT ! difference of exponents
+
+got_x_and_y:
+ and ebp,#D_SIGN_MASK ! see if signs are same
+ bne subtract ! else roundoff reg ebp has been cleared
+
+ cmp cl,#REG_BIT
+ bhis add_bigshift
+ shrd ebp,ebx,cl
+ shrd ebx,edi,cl
+ shr edi,cl
+ add eax,ebx
+ adc esi,edi
+
+! result edx(D_SIGN_MASK | D_EXP_MASK bits):esi:eax:ebp but needs normalization
+
+ mov edi,edx
+ and edi,#D_EXP_MASK
+ test esi,#D_NORM_MASK << 1
+ jnz add_loverflow
+
+add_round:
+ cmp ebp,#1 << (REG_BIT-1) ! test roundoff register
+ jb add_done ! no rounding
+ jz tie
+add_roundup:
+ add eax,#1
+ adc esi,#0
+ test esi,#D_NORM_MASK << 1
+ jnz pre_add_loverflow ! rounding may cause overflow!
+add_done:
+ mov ecx,edx ! duplicated code from 'done'
+ and edx,#D_SIGN_MASK
+ or edx,edi
+ and esi,#D_FRAC_MASK
+ or edx,esi
+ ret
+
+ .align ALIGNMENT
+tie:
+ test al,#1 ! tie case, round to even
+ jz add_done ! even, no rounding
+ jmp add_roundup
+
+ .align ALIGNMENT
+pre_add_loverflow:
+ sub ebp,ebp ! clear rounding register
+ ! probably avoiding tests for more rounding
+add_loverflow:
+ shrd ebp,eax,#1
+ jnc over_set_sticky_bit
+ or ebp,#1
+over_set_sticky_bit:
+ shrd eax,esi,#1
+ shr esi,#1
+ add edi,1 << D_EXP_SHIFT
+ cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT
+ jl add_round
+overflow:
+ call fpoverflow
+ mov eax,ecx ! XXX - wrong reg
+ ret
+
+! result edx(D_SIGN_MASK | D_EXP_MASK bits):
+! esi((D_NORM_MASK << 1) | D_NORM_MASK | D_FRAC_MASK bits):eax:ebp:ebx
+! but needs normalization
+
+ .align ALIGNMENT
+normalize:
+ mov edi,edx
+ and edi,#D_EXP_MASK
+ test esi,#D_NORM_MASK << 1
+ bne loverflow
+
+! result edx(D_SIGN_MASK bit):edi(D_EXP_MASK bits):
+! esi(D_NORM_MASK | D_FRAC_MASK bits):eax:ebp:ebx
+! but needs normalization
+
+ .globl normalize2
+normalize2:
+ test esi,#D_NORM_MASK ! already-normalized is very common
+ jz normalize3
+round:
+ cmp ebp,#1 << (REG_BIT-1) ! test roundoff register
+ jb done ! no rounding
+ jz near_tie
+roundup:
+ add eax,#1
+ adc esi,#0
+ test esi,#D_NORM_MASK << 1
+ bne pre_loverflow ! rounding may cause overflow!
+done:
+cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT
+jae overflow
+ and edx,#D_SIGN_MASK ! extract sign of largest and result
+ or edx,edi ! include exponent with sign
+ and esi,#D_FRAC_MASK ! discard norm bit
+ or edx,esi ! include fraction with sign and exponent
+ ret
+
+ .align ALIGNMENT
+near_tie:
+ test ebx,ebx
+ jnz roundup
+ test al,#1 ! tie case, round to even
+ jz done ! even, no rounding
+ jmp roundup
+
+ .align ALIGNMENT
+not_in_8_below:
+ shld ecx,esi,#REG_BIT-D_NORM_BIT+16 ! in 9 to 16 below?
+ jz not_in_16_below ! must be way below (17-20 for usual D_NORM_BIT)
+ mov cl,bsr_table[ecx] ! bsr(esi) - (D_NORM_BIT-16)
+ neg ecx ! (D_NORM_BIT-16) - bsr(esi)
+ add ecx,#16
+ jmp got_shift
+
+ .align ALIGNMENT
+not_in_16_below:
+ mov cl,bsr_table[esi] ! bsr(esi) directly
+ neg ecx ! -bsr(esi)
+ add ecx,#D_NORM_BIT ! D_NORM_BIT - bsr(esi)
+ jmp got_shift
+
+ .align ALIGNMENT
+normalize3:
+ test esi,esi
+ jz shift32
+
+! Find first nonzero bit in esi
+! Don't use bsr, it is very slow (const + 3 * bit_found)
+! We know that there is some nonzero bit, and the norm bit and above are clear
+
+ sub ecx,ecx ! prepare unsigned extension of cl
+ shld ecx,esi,#REG_BIT-D_NORM_BIT+8 ! any bits in 8 below norm bit?
+ jz not_in_8_below
+ mov cl,bsr_table[ecx] ! bsr(esi) - (D_NORM_BIT-8)
+ neg ecx ! (D_NORM_BIT-8) - bsr(esi)
+ add ecx,#8 ! D_NORM_BIT - bsr(esi)
+got_shift:
+ shld esi,eax,cl
+ shld eax,ebp,cl
+ shld ebp,ebx,cl
+ shl ebx,cl
+ shl ecx,D_EXP_SHIFT
+ sub edi,ecx
+ bhi round ! XXX - can rounding change the exponent to > 0?
+ ! not bgt since edi may be 0x80000000
+ neg edi
+ shr edi,#D_EXP_SHIFT
+ inc edi
+ br fpunderflow
+
+ .align ALIGNMENT
+pre_loverflow:
+ sub ebp,ebp ! clear rounding registers
+ sub ebx,ebx ! probably avoiding tests for more rounding
+
+loverflow:
+ shr esi,#1 ! carry bit stayed in the reg
+ rcr eax,#1
+ rcr ebp,#1
+ rcr ebx,#1
+ add edi,1 << D_EXP_SHIFT
+ cmp edi,#D_EXP_INFINITE << D_EXP_SHIFT
+ blt round
+ call fpoverflow
+ mov eax,ecx ! XXX - wrong reg
+ ret
+
+ .align ALIGNMENT
+shift32:
+ test eax,eax
+ jz shift64
+ mov esi,eax
+ mov eax,ebp
+ mov ebp,ebx
+ sub ebx,ebx
+ sub edi,#REG_BIT << D_EXP_SHIFT
+shiftxx:
+ test esi,#~(D_NORM_MASK | D_FRAC_MASK)
+ jz over_adjust ! else too big already
+ shrd ebx,ebp,#D_BIT-D_FRAC_BIT
+ shrd ebp,eax,#D_BIT-D_FRAC_BIT
+ shrd eax,esi,#D_BIT-D_FRAC_BIT
+ shr esi,#D_BIT-D_FRAC_BIT
+ add edi,#(D_BIT-D_FRAC_BIT) << D_EXP_SHIFT
+over_adjust:
+ test edi,edi
+ bgt normalize2
+ neg edi
+ shr edi,#D_EXP_SHIFT
+ inc edi
+ br fpunderflow
+
+ .align ALIGNMENT
+shift64:
+ test ebp,ebp
+ jz shift96
+ mov esi,ebp
+ mov eax,ebx
+ sub ebp,ebp
+ mov ebx,ebp
+ sub edi,#(2*REG_BIT) << D_EXP_SHIFT
+ jmp shiftxx
+
+ .align ALIGNMENT
+shift96:
+ test ebx,ebx ! XXX - this test is probably unnecessary
+ ! since the shift must be small unless we
+ ! are subtracting 2 almost-equal numbers,
+ ! and then the bits beyond 64 will mostly
+ ! be 0
+ jz return_esi_eax ! all zero
+ mov esi,ebx
+ sub ebx,ebx
+ sub edi,#(3*REG_BIT) << D_EXP_SHIFT
+ jmp shiftxx
+
+ .align ALIGNMENT
+return_esi_eax:
+ mov edx,esi
+ ret
+
+ .align ALIGNMENT
+subtract:
+ sub ebp,ebp ! set up roundoff register
+ cmp ecx,#REG_BIT
+ jae subtract_bigshift
+ shrd ebp,ebx,cl
+ shrd ebx,edi,cl
+ shr edi,cl
+ neg ebp ! begin subtraction esi:eax:0 - edi:ebx:ebp
+ sbb eax,ebx
+ sbb esi,edi
+ sub ebx,ebx
+ mov edi,edx
+ and edi,#D_EXP_MASK
+ br normalize2
+
+ .align ALIGNMENT
+subtract_bigshift:
+ cmp ecx,#D_FRAC_BIT+2
+ bhis return_edx_eax ! x dominates y
+ sub ecx,#REG_BIT
+ shrd ebp,ebx,cl
+ shrd ebx,edi,cl
+ shr edi,cl
+ not ebp ! begin subtraction esi:eax:0:0 - 0:edi:ebx:ebp
+ not ebx
+ add ebp,#1
+ adc ebx,#0
+ cmc
+ sbb eax,edi
+ sbb esi,#0
+ xchg ebp,ebx
+ mov edi,edx
+ and edi,#D_EXP_MASK
+ br normalize2
+
+ .data
+ .extern bsr_table
diff --git a/libc/i386fp/fcomp.x b/libc/i386fp/fcomp.x
new file mode 100644
index 0000000..71148ab
--- /dev/null
+++ b/libc/i386fp/fcomp.x
@@ -0,0 +1,89 @@
+! bcc 386 floating point routines (version 2) -- Fcomp, Fcompd, Fcompf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern Fpushf
+
+! Pop 2 doubles from stack and compare them, return result in flags so
+! normal signed branches work (unlike 80x87 which returns the result in
+! the zero and carry flags).
+
+ .globl Fcomp
+ .align ALIGNMENT
+Fcomp:
+ pop ecx ! get return address
+ pop eax ! xl
+ pop edx ! xu
+ push ecx ! put back ret address - pop 2nd double later
+
+! All this popping is bad on 486's since plain mov takes 1+ cycle and pop
+! takes 4 cycles. But this code is designed for 386's where popping is
+! nominally the same speed and saves code space and so maybe instruction
+! fetch time as well as the instruction to adjust the stack (ret #n takes
+! no longer than plain ret but inhibits gotos).
+
+ mov ebx,PC_SIZE+D_LOW[esp] ! yl
+ mov ecx,PC_SIZE+D_HIGH[esp] ! yu
+ jmp compare
+
+! Pop double from stack and compare with double at [ebx]
+
+ .globl Fcompd
+ .align ALIGNMENT
+Fcompd:
+ mov eax,PC_SIZE+D_LOW[esp] ! xl
+ mov edx,PC_SIZE+D_HIGH[esp] ! xu
+ mov ecx,D_HIGH[ebx] ! yu
+ mov ebx,D_LOW[ebx] ! yl
+
+compare:
+ test edx,#D_SIGN_MASK ! is x >= 0?
+ jz cmp0 ! yes; just compare x and y
+ test ecx,#D_SIGN_MASK ! no; but is y >= 0?
+ jz cmp0 ! yes; just compare x and y
+
+ xchg edx,ecx ! x, y < 0, so ...
+ xchg eax,ebx ! ... swap x and y ...
+ xor edx,#D_SIGN_MASK ! ... and toggle signs
+ xor ecx,#D_SIGN_MASK
+
+cmp0:
+ cmp edx,ecx ! compare upper dwords
+ jnz checkneg0 ! if upper dwords differ, job is almost done
+ mov edx,eax ! upper dwords equal, so ...
+ mov ecx,ebx ! ... must make unsigned comparison of lower dwords
+ shr edx,#1 ! shift past sign
+ shr ecx,#1
+ cmp edx,ecx ! compare top 31 bits of lower dwords
+ jnz return ! if these differ, job is done
+ and eax,#1 ! compare lowest bits
+ and ebx,#1
+ cmp eax,ebx
+
+return:
+ ret #D_SIZE ! return, popping 1 double from stack
+
+checkneg0:
+ test edx,#D_EXP_MASK | D_FRAC_MASK ! check to catch unusual case ...
+ jnz recheck
+ test eax,eax
+ jnz recheck
+ test ecx,#D_EXP_MASK | D_FRAC_MASK
+ jnz recheck
+ test ebx,ebx
+ jz return ! ... both are (+-) zero, return 'z'
+
+recheck:
+ cmp edx,ecx ! the upper words were really different
+ ret #D_SIZE
+
+ .globl Fcompf
+ .align ALIGNMENT
+Fcompf:
+ call Fpushf
+ pop ebx ! yl
+ pop ecx ! yu
+ mov eax,PC_SIZE+D_LOW[esp] ! xl
+ mov edx,PC_SIZE+D_HIGH[esp] ! xu
+ jmp compare
diff --git a/libc/i386fp/fdiv.x b/libc/i386fp/fdiv.x
new file mode 100644
index 0000000..4a5cf74
--- /dev/null
+++ b/libc/i386fp/fdiv.x
@@ -0,0 +1,312 @@
+#define EF_SIZE 4
+
+! bcc 386 floating point routines (version 2) -- Fdiv, Fdivd, Fdivf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE)
+
+ .extern Fpushf
+ .extern fpdivzero
+ .extern fpoverflow
+ .extern fpunderflow
+
+! double Fdiv(double x, double y) returns x / y
+
+! pop 2 doubles from stack, divide first by second, and push quotient on stack
+
+! we denote upper and lower dwords of x and y (or their fractions)
+! by (xu,xl), (yu,yl)
+
+ .globl Fdivf
+ .align ALIGNMENT
+Fdivf:
+ sub esp,#D_SIZE ! make space for dummy double on stack
+ push ebp
+ push edi ! save some regs
+ push esi
+ mov eax,FRAME_SIZE-PC_SIZE+D_SIZE[esp] ! move return address ...
+ mov FRAME_SIZE-PC_SIZE[esp],eax ! ... to usual spot
+ call Fpushf
+ pop esi ! yl
+ pop edi ! yu
+ mov eax,FRAME_SIZE+D_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! xu
+ jmp division
+
+ .globl Fdiv
+ .align ALIGNMENT
+Fdiv:
+ push ebp
+ push edi ! save some regs
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
+ mov esi,FRAME_SIZE+D_SIZE+D_LOW[esp] ! yl
+ mov edi,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! yu
+ jmp division
+
+ .align ALIGNMENT
+exp_y_0:
+ mov ebx,edi
+ or ebx,esi
+ beq zerodivide
+ mov ebx,#1
+fix_y:
+ test edi,edi ! XXX - sloow
+ js y_unpacked
+ shld edi,esi,#1
+ shl esi,#1
+ dec bx
+ jmp fix_y
+
+ .align ALIGNMENT
+exp_x_0:
+ mov ecx,edx
+ or ecx,eax
+ beq retz
+ mov ecx,#1 ! change exponent from 0 to 1
+fix_x:
+ test edx,#1 << (REG_BIT-1-2) ! XXX - sloow
+ jnz x_unpacked
+ shld edx,eax,#1
+ shl eax,#1
+ dec cx
+ jmp fix_x
+
+! Fdivd pops double from stack, divides it by double at [ebx],
+! and pushes quotient back on stack
+
+ .globl Fdivd
+ .align ALIGNMENT
+Fdivd:
+ sub esp,#D_SIZE ! make space for dummy double on stack
+ push ebp
+ push edi ! save some regs
+ push esi
+ mov eax,FRAME_SIZE-PC_SIZE+D_SIZE[esp] ! move return address ...
+ mov FRAME_SIZE-PC_SIZE[esp],eax ! ... to usual spot
+ mov eax,FRAME_SIZE+D_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_SIZE+D_HIGH[esp] ! xu
+ mov esi,D_LOW[ebx] ! yl
+ mov edi,D_HIGH[ebx] ! yu
+
+division:
+
+! The full calculations are
+
+! (xu,xl,0) = yu * (zu,zl) + (0,r,0) (normal 96/32 -> 64 bit division)
+! yl * zu = yu * q1 + r1 (32*32 -> 64 bit mul and 64/32 -> 32 bit div)
+
+! so
+
+! (xu,xl,0,0) = (yu,yl) * (zu,zl-q1) + (0,0,r-r1,yl*(q1-zl))
+
+! where the calculations zl-q1, r-r1 and yl*(q1-zl) are more complicated
+! than the notation suggests. They may be negative and the one with the
+! multiplication may not fit in 32 bits and in both cases the overflow
+! has to be moved into higher bit positions.
+
+! See Knuth for why (zu,zl-q1) is the correct 64-bit quotient to within
+! 1 bit either way (assuming the normalization x < 2 * y).
+
+! We only need to calculate the remainder (0,0,r-r1,yl*(q1-zl)) to resolve
+! tie cases. It tells whether the approximate quotient is too high or too
+! low.
+
+#define NTEMPS 5
+
+ sub esp,#NTEMPS*GENREG_SIZE ! space to remember values for rounding of tie case
+
+! Offsets from esp for these values (offsets using FRAME_SIZE are invalid
+! while these temps are active)
+r = 0
+q1 = 4
+r1 = 8
+yl = 12
+zl = 16
+
+! Step 1: unpack and normalize x to fraction in edx:eax (left shifted as
+! far as possible less 2 so that x < y, and later z < y); unpack and normalize
+! y to a fraction in edi:esi (left shifted as far as possible), put difference
+! of signs (= sign of quotient) in ecx(D_SIGN_MASK) and difference of exponents
+! (= exponent of quotient before normalization) in cx.
+
+ mov ebp,edx ! xu
+ xor ebp,edi ! xu ^ yu
+ and ebp,#D_SIGN_MASK ! sign of result is difference of signs
+
+! Unpack y first to trap 0 / 0
+
+ mov ebx,edi ! remember yu for exponent of y
+ shld edi,esi,#D_BIT-D_FRAC_BIT ! extract fraction of y ...
+ shl esi,#D_BIT-D_FRAC_BIT
+ and ebx,#D_EXP_MASK ! exponent of y
+ jz exp_y_0
+ shr ebx,#D_EXP_SHIFT ! in ebx (actually in bx, with high bits 0)
+ or edi,#D_NORM_MASK << (D_BIT-D_FRAC_BIT) ! normalize
+y_unpacked:
+
+! Unpack x
+
+ mov ecx,edx ! remember xu for exponent of x
+ shld edx,eax,#D_BIT-D_FRAC_BIT-2 ! extract fraction of x ...
+ shl eax,#D_BIT-D_FRAC_BIT-2
+ and edx,#(D_NORM_MASK << (D_BIT-D_FRAC_BIT-2+1))-1
+ ! XXX - above may be shifted 1 extra unnecessarily
+ and ecx,#D_EXP_MASK ! exponent of x
+ jz exp_x_0
+ shr ecx,#D_EXP_SHIFT ! in ecx (actually in cx, with high bits 0)
+ or edx,#D_NORM_MASK << (D_BIT-D_FRAC_BIT-2) ! normalize
+x_unpacked:
+
+ sub cx,bx ! not ecx,ebx because we want to use high bit for sign
+ add cx,#D_EXP_BIAS ! adjust exponent of quotient
+
+ or ecx,ebp ! include sign with exponent
+
+! Step 2: quotient of fractions -> (edx,eax)
+
+! 2a: (xu,xl,0) div yu = (zu,zl) -> (ebx,esi)
+
+ div eax,edi ! (xu,xl) div yu = zu in eax; remainder (rem) in edx
+ mov ebx,eax ! save zu in ebx
+ sub eax,eax ! clear eax: (edx,eax) = (rem,0)
+ div eax,edi ! (rem,0) div yu = zl in eax
+ mov r[esp],edx
+ mov zl[esp],eax
+ xchg eax,esi ! store zl in esi; save yl in eax
+ mov yl[esp],eax
+
+! 2b: (yl * zu) div yu -> (0,eax)
+
+ mul eax,ebx ! yl * zu -> (edx,eax)
+ div eax,edi ! (yl * zu) div yu in eax
+ mov q1[esp],eax
+ mov r1[esp],edx
+
+! 2c: (xu,xl) / (yu,yl) = (zu,zl) - (yl * zu) div yu -> (edx,eax)
+
+ mov edx,ebx ! zu
+ xchg eax,esi ! eax <- zl; esi <- (yl * zu) div yu
+ sub eax,esi
+ sbb edx,#0
+
+! Step 3: normalise quotient
+
+ test edx,#1 << (REG_BIT-2) ! is fraction too small? (can only be by 1 bit)
+ jnz div4
+ shld edx,eax,#1 ! yes; multiply fraction ...
+ shl eax,#1 ! ... by 2 ...
+ dec cx ! ... and decrement exponent
+
+! Step 4: shift and round
+
+div4:
+ mov ebx,eax ! save for rounding
+ shrd eax,edx,#D_BIT-D_FRAC_BIT-1 ! shift fraction of result ...
+ shr edx,#D_BIT-D_FRAC_BIT-1 ! ... to proper position
+ and ebx,#(1 << (D_BIT-D_FRAC_BIT-1))-1 ! look at bits shifted out
+ cmp ebx,#D_NORM_MASK >> (D_BIT-D_FRAC_BIT) ! compare with middle value
+ jb div5 ! below middle, don't round up
+ ja roundup ! above middle, round up
+
+! The low bits don't contain enough information to resolve the tie case,
+! because the quotient itself is only an approximation.
+! Calculate the exact remainder.
+! This case is not very common, so don't worry much about speed.
+! Unfortunately we had to save extra in all cases to prepare for it.
+
+ push edx
+ push eax
+
+ sub esi,esi ! the calculation requires 33 bits - carry to here
+ mov eax,2*GENREG_SIZE+q1[esp]
+ sub eax,2*GENREG_SIZE+zl[esp]
+ pushfd
+ mul dword EF_SIZE+2*GENREG_SIZE+yl[esp]
+ popfd
+ jnc foo
+ sub edx,2*GENREG_SIZE+yl[esp]
+ sbb esi,#0
+foo:
+ add edx,2*GENREG_SIZE+r[esp]
+ adc esi,#0
+ sub edx,2*GENREG_SIZE+r1[esp]
+ sbb esi,#0
+ mov ebx,eax
+ mov edi,edx
+
+ pop eax
+ pop edx
+
+! Can finally decide rounding of tie case
+
+ js div5 ! remainder < 0 from looking at top 64 bits
+ jnz roundup ! remainder > 0 from looking at top 64 bits
+ or edi,ebx ! test bottom 64 bits
+ jnz roundup ! remainder > 0
+
+ test al,#1 ! at last we know it is the tie case, check parity bit
+ jz div5 ! already even, otherwise round up to make even
+
+roundup:
+ add eax,#1 ! add rounding bit
+ adc edx,#0
+ test edx,#D_NORM_MASK << 1 ! has fraction overflowed (very unlikely)
+ jz div5
+! Why were the shifts commented out?
+ shrd eax,edx,#1 ! yes, divide fraction ...
+ shr edx,#1 ! ... by 2 ...
+ inc cx ! ... and increment exponent
+
+! Step 5: put it all together
+
+div5:
+ mov ebx,ecx ! extract sign
+ and ebx,D_SIGN_MASK
+ cmp cx,#D_EXP_INFINITE ! is exponent too big?
+ jge overflow
+ test cx,cx
+ jle underflow
+ shl ecx,#D_EXP_SHIFT
+
+ and edx,#D_FRAC_MASK ! remove norm bit
+ or edx,ecx ! include exponent ...
+ or edx,ebx ! ... and sign
+
+return:
+ add esp,#NTEMPS*GENREG_SIZE ! reclaim temp space
+ mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax ! "push" lower dword of product ...
+ mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx ! ... and upper dword
+ pop esi ! restore registers
+ pop edi
+ pop ebp
+ ret #D_SIZE
+
+retz:
+ sub edx,edx ! clear upper dword
+ sub eax,eax ! ... and lower dword
+ jmp return
+
+overflow:
+ mov edx,ecx ! put sign in usual reg
+ call fpoverflow
+ mov eax,ecx ! XXX - wrong reg
+ jmp return
+
+underflow:
+ mov esi,edx ! put upper part of fraction in usual reg
+ mov edx,ecx ! sign
+ movsx edi,cx ! put shift in usual reg
+ neg edi
+ inc edi
+ call fpunderflow
+ jmp return
+
+zerodivide:
+ mov edx,ebp ! sign
+ call fpdivzero
+ mov eax,ecx ! XXX - wrong reg
+ jmp return
diff --git a/libc/i386fp/fmul.x b/libc/i386fp/fmul.x
new file mode 100644
index 0000000..aa62b5c
--- /dev/null
+++ b/libc/i386fp/fmul.x
@@ -0,0 +1,150 @@
+! bcc 386 floating point routines (version 2) -- Fmul, Fmuld, Fmulf
+! author: Bruce Evans
+
+#include "fplib.h"
+
+#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE)
+
+ .extern Fpushf
+ .extern fpoverflow
+ .extern fpunderflow
+ .extern normalize2
+
+ .globl Fmul
+ .align ALIGNMENT
+Fmul:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
+ mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
+ call multiplication
+ mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret #D_SIZE
+
+ .globl Fmuld
+ .align ALIGNMENT
+Fmuld:
+ push ebp
+ push edi
+ push esi
+ mov eax,FRAME_SIZE+D_LOW[esp]
+ mov edx,FRAME_SIZE+D_HIGH[esp]
+ mov ecx,D_HIGH[ebx]
+ mov ebx,D_LOW[ebx]
+ call multiplication
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .globl Fmulf
+ .align ALIGNMENT
+Fmulf:
+ push ebp
+ push edi
+ push esi
+ call Fpushf
+ pop ebx ! yl
+ pop ecx ! xu
+ mov eax,FRAME_SIZE+D_LOW[esp] ! xl
+ mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
+ call multiplication
+ mov FRAME_SIZE+D_LOW[esp],eax
+ mov FRAME_SIZE+D_HIGH[esp],edx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+
+ .align ALIGNMENT
+exp_x_0:
+ mov edx,#1 << D_EXP_SHIFT ! change exponent from 0 to 1
+ jmp x_unpacked ! XXX - check for denormal?
+
+ .align ALIGNMENT
+exp_y_0:
+ mov ecx,#1 << D_EXP_SHIFT
+ jmp y_unpacked
+
+ .align ALIGNMENT
+multiplication:
+ mov ebp,edx ! xu
+ xor ebp,ecx ! xu ^ yu
+ and ebp,#D_SIGN_MASK ! sign of result is difference of signs
+
+ mov esi,edx ! free edx for multiplications
+ and esi,#D_FRAC_MASK ! discard sign and exponent
+ and edx,#D_EXP_MASK ! exponent(x)
+ jz exp_x_0
+ or esi,#D_NORM_MASK ! normalize
+x_unpacked:
+
+ mov edi,ecx ! this mainly for consistent naming
+ and edi,#D_FRAC_MASK
+ and ecx,#D_EXP_MASK ! exponent(y)
+ jz exp_y_0
+ or edi,#D_NORM_MASK
+y_unpacked:
+
+ add ecx,edx ! add exponents
+
+! exponent is in ecx, sign in ebp, operands in esi:eax and edi:ebx, edx is free
+! product to go in esi:eax:ebp:ebx
+! terminology: x * y = (xu,xl) * (yu,yl)
+! = (xu * yu,0,0) + (0,xu * yl + xl * yu,0) + (0,0,xl * yl)
+
+ push ecx
+ push ebp
+ mov ecx,eax
+ mul ebx ! xl * yl
+ mov ebp,edx ! (xl * yl).u in ebp
+ xchg ebx,eax ! (xl * yl).l in ebx (final), yl in eax
+ mul esi ! xu * yl
+ push eax ! (xu * yl).l on stack
+ push edx ! (xu * yl).u on stack
+ mov eax,esi ! xu
+ mul edi ! xu * yu
+ mov esi,edx ! (xu * yu).u in esi (final except carries)
+ xchg ecx,eax ! (xu * yu).l in ecx, xl in eax
+ mul edi ! xl * yu
+
+ add ebp,eax ! (xl * yl).u + (xl * yu).l
+ pop eax ! (xu * yl).u
+ adc eax,edx ! (xu * yl).u + (xl * yu).u
+ adc esi,#0
+ pop edx ! (xu * yl).l
+ add ebp,edx ! ((xl * yl).u + (xl * yu).l) + (xu * yl).l
+ adc eax,ecx ! ((xu * yl).u + (xl * yu).u) + (xu * yu).l
+ adc esi,#0
+ pop edx ! sign
+ pop edi ! exponent
+ sub edi,#(D_EXP_BIAS+1-(D_EXP_BIT+2)) << D_EXP_SHIFT ! adjust
+! cmp edi,#(D_EXP_INFINITE-1+(D_EXP_BIT+2)) << D_EXP_SHIFT
+! jae outofbounds ! 0 will be caught as underflow by normalize2
+cmp edi,#(2*D_EXP_INFINITE-(D_EXP_BIAS+1)+(D_EXP_BIT+2)) << D_EXP_SHIFT
+ja underflow
+ br normalize2
+
+ .align ALIGNMENT
+overflow:
+ mov edx,ebp ! put sign in usual reg
+ call fpoverflow
+ mov eax,ecx ! XXX - wrong reg
+ ret
+
+ .align ALIGNMENT
+underflow:
+ mov edx,ebp ! put sign in usual reg
+ neg edi
+ shr edi,#D_EXP_SHIFT
+ inc edi
+ br fpunderflow
diff --git a/libc/i386fp/fpbsr.x b/libc/i386fp/fpbsr.x
new file mode 100644
index 0000000..8ff38d7
--- /dev/null
+++ b/libc/i386fp/fpbsr.x
@@ -0,0 +1,25 @@
+! bcc 386 floating point routines (version 2) -- bsr_table
+! author: Bruce Evans
+
+#include "fplib.h"
+
+ .globl bsr_table
+ .data
+ .align ALIGNMENT
+bsr_table: ! table to replace bsr on range 0-255
+.byte -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
+.byte 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+.byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+.byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+.byte 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+.byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
diff --git a/libc/i386fp/fperr.c b/libc/i386fp/fperr.c
new file mode 100644
index 0000000..fa1633e
--- /dev/null
+++ b/libc/i386fp/fperr.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <signal.h>
+
+#include "fperr.h"
+
+void fperr(errno)
+int errno;
+{
+
+#if defined(DEBUG) || 0
+ switch(errno) {
+
+ case EFDENORMAL:
+ fputs("\nDenormal - ", stderr);
+ break;
+
+ case EFINFINITY:
+ fputs("\nInfinity - ", stderr);
+ break;
+
+ case EFNAN:
+ fputs("\nNaN - ", stderr);
+ break;
+
+ case EFOVERFLOW:
+ fputs("\nOverflow - ", stderr);
+ break;
+
+ case EFUNDERFLOW:
+ fputs("\nUnderflow - ", stderr);
+ break;
+
+ case EFDIVZERO:
+ fputs("\nZero divide - ", stderr);
+ break;
+
+ default:
+ fprintf(stderr, "\nUnknown error 0x%x - ", errno);
+ }
+ fflush(stderr);
+#endif
+
+ kill(getpid(), SIGFPE);
+}
diff --git a/libc/i386fp/fperr.h b/libc/i386fp/fperr.h
new file mode 100644
index 0000000..f2a2a7d
--- /dev/null
+++ b/libc/i386fp/fperr.h
@@ -0,0 +1,8 @@
+/* fperr.h */
+
+#define EFDENORMAL 1
+#define EFINFINITY 2
+#define EFNAN 3
+#define EFOVERFLOW 4
+#define EFUNDERFLOW 5
+#define EFDIVZERO 6
diff --git a/libc/i386fp/fperror.x b/libc/i386fp/fperror.x
new file mode 100644
index 0000000..04f3f74
--- /dev/null
+++ b/libc/i386fp/fperror.x
@@ -0,0 +1,126 @@
+! bcc 386 floating point routines (version 2)
+! --- fpdenormal, fperror, fpinfinity, fpNaN, fpoverflow, fpunderflow,fpdivzero
+! author: Bruce Evans
+
+#include "fperr.h"
+#include "fplib.h"
+
+ .extern _fperr
+
+! Cause a denormal-operand exception
+! Preserves all general registers if signal handler returns
+
+ .globl fpdenormal
+ .align ALIGNMENT
+fpdenormal:
+#if 0
+ push eax
+ mov eax,#EFDENORMAL
+ call fperror
+ pop eax
+#endif
+ ret
+
+! Cause an exception with error code eax, preserving all genregs except eax
+
+ .globl fperror
+ .align ALIGNMENT
+fperror:
+ push ebp ! set up usual frame ...
+ mov ebp,esp ! ... for debugging
+ push edx ! save default
+ push ecx
+ push eax ! error code is arg to C routine
+ call _fperr
+ add esp,#GENREG_SIZE
+ pop ecx ! restore default
+ pop edx
+ pop ebp
+ ret
+
+ .align ALIGNMENT
+fphuge:
+ mov ecx,#D_HUGE_LOW ! prepare number +-HUGEVAL
+ or edx,#D_HUGE_HIGH ! ... in case signal handler returns
+ jmp fperror
+
+! Cause an infinite-operand exception
+! Return +-HUGEVAL in edx:ecx with sign from edx
+
+ .globl fpinfinity
+ .align ALIGNMENT
+fpinfinity:
+ mov eax,#EFINFINITY
+ jmp fphuge ! almost right
+
+! Cause an NaN-operand exception
+! Return +-HUGEVAL in edx:ecx with sign from edx
+
+ .globl fpNaN
+ .align ALIGNMENT
+fpNaN:
+ mov eax,#EFNAN ! there are different types of NaNs but...
+ jmp fphuge ! WRONG
+
+! Cause an overflow exception
+! Return +-HUGEVAL in edx:ecx with sign from edx
+
+ .globl fpoverflow
+ .align ALIGNMENT
+fpoverflow:
+ mov eax,#EFOVERFLOW
+ jmp fphuge ! almost right
+
+! Cause an underflow exception (actually assume it is masked for now)
+! Return denormal or 0.0 in edx:ecx
+! XXX - this should cause a denormal exception or none for the denormal case
+! Args: sign in edx, fraction in esi:eax, right shift in edi
+! Returns: denormalized number in edx:eax
+
+ .globl fpunderflow
+ .align ALIGNMENT
+fpunderflow:
+#if 0
+ mov eax,#EFUNDERFLOW
+ jmp fperror
+#endif
+ cmp edi,#REG_BIT
+ jb denormalize1
+ mov eax,esi
+ sub esi,esi
+ sub edi,#REG_BIT
+ cmp edi,#REG_BIT
+ jb denormalize1
+denormalize_underflow:
+#if 0
+ mov eax,#EFUNDERFLOW
+ jmp fperror
+#endif
+ sub eax,eax
+ mov edx,eax
+ ret
+
+ .align ALIGNMENT
+denormalize1:
+ mov ecx,edi
+ shrd eax,esi,cl
+ shr esi,cl
+ mov ecx,esi
+ or ecx,eax
+ jz denormalize_underflow
+ and edx,#D_SIGN_MASK
+ or edx,esi
+ ret
+
+! Cause an fp division by zero exception
+! Return +-HUGEVAL in edx:ecx with sign from edx
+
+ .globl fpdivzero
+ .align ALIGNMENT
+fpdivzero:
+ mov eax,#EFDIVZERO
+ test edx,#D_EXP_MASK
+ jnz fphuge ! almost right
+ sub ecx,ecx
+ mov edx,ecx
+ jmp fperror
diff --git a/libc/i386fp/fplib.h b/libc/i386fp/fplib.h
new file mode 100644
index 0000000..f110717
--- /dev/null
+++ b/libc/i386fp/fplib.h
@@ -0,0 +1,43 @@
+#define ALIGNMENT 4
+#define CHAR_BIT 8
+#define D_BIT (D_SIZE * CHAR_BIT)
+#define D_EXP_BIAS ((1 << (D_EXP_BIT - 1)) - 1)
+#define D_EXP_BIT 11
+#define D_EXP_INFINITE ((1 << D_EXP_BIT) - 1)
+#define D_EXP_MASK (((1 << D_EXP_BIT) - 1) << D_EXP_SHIFT)
+#define D_EXP_SHIFT (REG_BIT - (1 + D_EXP_BIT))
+#define D_FRAC_BIT 53
+#define D_FRAC_MASK (D_NORM_MASK - 1)
+#define D_HIGH 4
+#define D_HUGE_HIGH (D_EXP_MASK - 1)
+#define D_HUGE_LOW 0xFFFFFFFF
+#define D_LOW 0
+#define D_NORM_BIT (D_FRAC_BIT - 1 - REG_BIT)
+#define D_NORM_MASK (1 << D_NORM_BIT)
+#define D_SIGN_BIT 63
+#define D_SIGN_MASK (1 << (D_SIGN_BIT - REG_BIT))
+#define D_SIZE 8
+#define F_BIT (F_SIZE * CHAR_BIT)
+#define F_EXP_BIAS ((1 << (F_EXP_BIT - 1)) - 1)
+#define F_EXP_BIT 8
+#define F_EXP_INFINITE ((1 << F_EXP_BIT) - 1)
+#define F_EXP_MASK (((1 << F_EXP_BIT) - 1) << F_EXP_SHIFT)
+#define F_EXP_SHIFT (REG_BIT - (1 + F_EXP_BIT))
+#define F_FRAC_BIT 24
+#define F_FRAC_MASK (F_NORM_MASK - 1)
+#define F_HIGH 0
+#define F_HUGE_HIGH (F_EXP_MASK - 1)
+#define F_NORM_BIT (F_FRAC_BIT - 1)
+#define F_NORM_MASK (1 << F_NORM_BIT)
+#define F_SIGN_BIT 31
+#define F_SIGN_MASK (1 << F_SIGN_BIT)
+#define F_SIZE 4
+#define FREE_D_SIGN_BIT_TEST (D_SIGN_BIT % REG_BIT == REG_BIT - 1)
+#define GENREG_SIZE 4
+#define INT_BIT 32
+#define INT_MAX 0x7FFFFFFF
+#define INT_MIN (-0x7FFFFFFF - 1)
+#define PC_SIZE 4
+#define REG_BIT 32
+#define SHORT_BIT 16
+#define UINT_MAX 0xFFFFFFFF
diff --git a/libc/i386fp/fptoi.x b/libc/i386fp/fptoi.x
new file mode 100644
index 0000000..30de729
--- /dev/null
+++ b/libc/i386fp/fptoi.x
@@ -0,0 +1,117 @@
+! bcc 386 floating point routines (version 2)
+! -- dtoi, dtol, dtoui, dtoul, ftoi, ftol (todo: ftoui, ftoul)
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpoverflow
+ .extern Fpushf
+
+! Convert double x at [ebx] to int and return in eax
+
+ .globl dtoi
+ .globl dtol
+ .align ALIGNMENT
+dtoi:
+dtol:
+ mov eax,D_HIGH[ebx]
+ mov ecx,eax
+ and ecx,#D_EXP_MASK ! extract exponent
+ jz retz ! if 0 return 0
+ test eax,#D_SIGN_MASK
+ jnz negative
+ call into_dtoui
+ cmp eax,#INT_MAX
+ ja overflow_int_max
+ ret
+
+ .align ALIGNMENT
+negative:
+ and eax,#~D_SIGN_MASK
+ call into_dtoui
+ cmp eax,#INT_MIN
+ ja overflow_int_min
+ neg eax
+ ret
+
+ .align ALIGNMENT
+overflow_int_max:
+ call fpoverflow
+ mov eax,#INT_MAX
+ ret
+
+ .align ALIGNMENT
+overflow_int_min:
+ js return ! actually INT_MIN is OK
+ call fpoverflow
+ mov eax,#INT_MIN
+return:
+ ret
+
+ .align ALIGNMENT
+retz:
+ sub eax,eax ! clear return value
+ ret
+
+! Convert double x at [ebx] to unsigned and return in eax
+
+ .globl dtoui
+ .globl dtoul
+ .align ALIGNMENT
+dtoui:
+dtoul:
+ mov eax,D_HIGH[ebx]
+ mov ecx,eax
+ and ecx,#D_EXP_MASK ! extract exponent
+ jz retz ! if 0 return 0
+ test eax,#D_SIGN_MASK
+ jnz overflow_0
+into_dtoui:
+ mov edx,D_LOW[ebx]
+
+ and eax,#D_FRAC_MASK ! extract fraction
+ or eax,#D_NORM_MASK ! restore normalization bit
+
+ shr ecx,#D_EXP_SHIFT ! convert exponent to number
+ sub ecx,#D_EXP_BIAS+D_NORM_BIT ! adjust radix point
+ jl dtoui_rightshift ! should we shift left or right?
+ cmp ecx,#D_BIT-D_FRAC_BIT ! can shift left by at most this
+ ja overflow_uint_max ! if more, overflow
+ shld eax,edx,cl
+ ret
+
+ .align ALIGNMENT
+dtoui_rightshift:
+ neg ecx ! make shift count > 0
+ cmp ecx,#REG_BIT ! big shifts would be taken mod REG_BIT ...
+ jae retz ! ... no good
+ shr eax,cl ! otherwise it is faster to do the shift ...
+ ret ! ... then to jump for the slightly smaller
+ ! ... shift counts that shift out all bits
+
+ .align ALIGNMENT
+overflow_0:
+ call fpoverflow
+ sub eax,eax
+ ret
+
+ .align ALIGNMENT
+overflow_uint_max:
+ call fpoverflow
+ mov eax,#UINT_MAX
+ ret
+
+! ftoi is like dtoi except ebx points to a float instead of a double.
+! This is a quickly-written slowish version that does not take advantage
+! of the float being smaller.
+
+ .globl ftoi
+ .globl ftol
+ .align ALIGNMENT
+ftoi:
+ftol:
+ call Fpushf
+ mov ebx,esp
+ call dtoi
+ add esp,#D_SIZE
+ ret
diff --git a/libc/i386fp/fpulld.x b/libc/i386fp/fpulld.x
new file mode 100644
index 0000000..928a846
--- /dev/null
+++ b/libc/i386fp/fpulld.x
@@ -0,0 +1,20 @@
+! bcc 386 floating point routines (version 2) -- Fpulld
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+! Pop double from stack and store at address [ebx]
+
+ .globl Fpulld
+ .align ALIGNMENT
+Fpulld:
+ pop ecx
+ pop dword D_LOW[ebx]
+ pop dword D_HIGH[ebx]
+ jmp ecx ! return
+
+! This popping method is much slower on 486's because popping to memory
+! takes 5+ while moving twice takes 2 and the return address doesn't
+! have to be moved. However, popping is a little faster on a non-cached
+! 386/20 with static column RAM although the memory access pattern is
+! better for a double-width move than for popping. What about a cached 386?
diff --git a/libc/i386fp/fpullf.x b/libc/i386fp/fpullf.x
new file mode 100644
index 0000000..417ef92
--- /dev/null
+++ b/libc/i386fp/fpullf.x
@@ -0,0 +1,101 @@
+! bcc 386 floating point routines (version 2) -- Fpullf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpoverflow
+ .extern fpunderflow
+
+! pop double from stack, convert to float and store at address [ebx]
+
+ .globl Fpullf
+ .align ALIGNMENT
+Fpullf:
+
+! Step 1: load and shift left
+
+ mov eax,PC_SIZE+D_LOW[esp] ! lower dword
+ mov edx,PC_SIZE+D_HIGH[esp] ! upper dword
+ mov ecx,edx ! copy upper dword into ecx ...
+ and ecx,#D_SIGN_MASK ! ... and extract sign
+ and edx,#D_EXP_MASK | D_FRAC_MASK ! extract exponent and fraction
+ sub edx,#(D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT ! adjust exponent bias
+ jz underflow
+ cmp edx,#F_EXP_INFINITE << D_EXP_SHIFT ! check if exponent lies in reduced range
+ jae outofbounds
+ shld edx,eax,#D_EXP_BIT-F_EXP_BIT ! shift exponent and fraction
+
+! Step 2: round
+
+ test eax,#1 << (REG_BIT-1-(D_EXP_BIT-F_EXP_BIT)) ! test upper rounding bit
+ jz step3 ! below middle, don't round up
+ test eax,#(1 << (REG_BIT-1-(D_EXP_BIT-F_EXP_BIT)))-1 ! test other rounding bits
+ jnz roundup ! above middle, round up
+ test dl,#1 ! in middle, check parity bit
+ jz step3 ! already even, otherwise round up to make even
+
+roundup:
+ inc edx ! carry 1
+ test edx,#F_FRAC_MASK ! is fraction now 0? (carry into F_EXPMASK)
+ jnz step3 ! no -- carry complete
+ cmp edx,#(F_EXP_INFINITE << F_EXP_SHIFT) & ~F_NORM_MASK ! yes (very unlikely): check for overflow
+ ! XXX - I think these tests say 0x7e7fffff overflows
+ jae overflow
+
+! Step 3: put it all together
+
+step3:
+ or edx,ecx ! include sign
+ mov F_HIGH[ebx],edx ! store the result in [ebx]
+ ret #D_SIZE ! return and release double from stack
+
+ .align ALIGNMENT
+outofbounds:
+ jns overflow ! have just compared exponent with the max
+underflow:
+! call fpunderflow ! XXX
+ push ecx ! save sign
+ mov ecx,edx
+ and ecx,#~D_FRAC_MASK ! assume fraction is below exp
+ cmp ecx,#-((D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT) ! was exp = 0?
+ jz exp_x_0
+ shr ecx,#D_EXP_SHIFT
+ neg ecx
+ and edx,#D_FRAC_MASK
+ or edx,#D_NORM_MASK
+ shld edx,eax,#D_EXP_BIT-F_EXP_BIT-1
+ shl eax,#D_EXP_BIT-F_EXP_BIT-1
+ push ebx ! save to use for rounding
+ sub ebx,ebx
+ shrd ebx,eax,cl
+ shrd eax,edx,cl
+ shr edx,cl
+ cmp eax,#1 << (REG_BIT-1)
+ jb over_denorm_roundup
+ ja denorm_roundup
+ test dl,#1
+ jz over_denorm_roundup
+denorm_roundup:
+#if F_NORM_BIT != F_EXP_SHIFT
+#include "carry into norm bit doesn't go into low exp bit"
+#endif
+ inc edx
+over_denorm_roundup:
+ pop ebx
+ pop ecx
+ or edx,ecx
+ mov F_HIGH[ebx],edx
+ ret #D_SIZE
+
+ .align ALIGNMENT
+exp_x_0: ! XXX check for denormals - they underflow
+ pop ecx
+ mov dword F_HIGH[ebx],#0
+ ret #D_SIZE
+
+ .align ALIGNMENT
+overflow:
+ mov edx,ebx ! put sign in usual reg
+ call fpoverflow
+ mov F_HIGH[ebx],dword #F_HUGE_HIGH ! XXX - should use infinity
+ ret #D_SIZE ! ... if fpoverflow does
diff --git a/libc/i386fp/fpushd.x b/libc/i386fp/fpushd.x
new file mode 100644
index 0000000..68caab0
--- /dev/null
+++ b/libc/i386fp/fpushd.x
@@ -0,0 +1,60 @@
+! bcc 386 floating point routines (version 2) -- dtof, Fpushd, Fneg, Fnegd
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern Fpullf
+
+! dtof converts the double at [ebx] to a float and pushes the float onto
+! the stack (D_SIZE bytes are allocated for the float although only the bottom
+! F_SIZE are used).
+! This is a quickly-written slowish version.
+
+ .globl dtof
+ .align ALIGNMENT
+dtof:
+ pop eax
+ sub esp,#D_SIZE ! build result here
+ push eax ! put back return address
+ call Fpushd
+ lea ebx,D_SIZE+PC_SIZE[esp]
+ call Fpullf
+ ret
+
+! Push double at address [ebx] onto stack
+
+ .globl Fpushd
+ .align ALIGNMENT
+Fpushd:
+ pop ecx
+ push dword D_HIGH[ebx]
+ push dword D_LOW[ebx]
+ jmp ecx ! return
+
+! Push double at address [ebx] onto stack, negating it on the way.
+
+! Don't worry about generating -0 because other routines have to allow for
+! it anyway.
+
+! Perhaps this and Fneg should check for denormals and illegal operands
+! (I think only signalling NaNs are illegal).
+! fchs doesn't check, but fld does.
+! Our Fpushd is not quite like fld because no conversions are involved.
+
+ .globl Fnegd
+ .align ALIGNMENT
+Fnegd:
+ pop ecx
+ mov eax,D_HIGH[ebx]
+ xor eax,#D_SIGN_MASK ! toggle sign
+ push eax
+ push dword D_LOW[ebx]
+ jmp ecx ! return
+
+! Negate double on stack
+
+ .globl Fneg
+ .align ALIGNMENT
+Fneg:
+ xorb PC_SIZE+D_SIZE-1[esp],D_SIGN_MASK >> (REG_BIT-CHAR_BIT) ! toggle sign
+ ret
diff --git a/libc/i386fp/fpushf.x b/libc/i386fp/fpushf.x
new file mode 100644
index 0000000..7cb2f8d
--- /dev/null
+++ b/libc/i386fp/fpushf.x
@@ -0,0 +1,74 @@
+! bcc 386 floating point routines (version 2) -- Fpushf, Fnegf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpdenormal
+
+! Load float at [ebx], convert to double and push on stack
+
+ .globl Fpushf
+ .align ALIGNMENT
+Fpushf:
+ mov edx,F_HIGH[ebx]
+into_Fpushf:
+ test edx,#F_EXP_MASK ! is exponent 0?
+ jz exp_x_0
+
+ mov ecx,edx ! extract sign
+ and ecx,#F_SIGN_MASK
+
+ and edx,#F_EXP_MASK | F_FRAC_MASK ! extract exponent and fraction
+ sub eax,eax ! clear lower dword
+ shrd eax,edx,#D_EXP_BIT-F_EXP_BIT ! shift exponent and fraction to new position
+ shr edx,#D_EXP_BIT-F_EXP_BIT
+
+ add edx,#(D_EXP_BIAS-F_EXP_BIAS) << D_EXP_SHIFT ! adjust exponent bias
+ or edx,ecx ! include sign
+
+ pop ecx
+ push edx ! upper dword
+ push eax ! lower dword
+ jmp ecx ! return
+
+ .align ALIGNMENT
+exp_x_0:
+ mov eax,edx
+ and eax,#F_FRAC_MASK
+ jnz x_denorm
+ pop ecx
+ push eax ! upper dword = 0
+ push eax ! lower dword = 0
+ jmp ecx ! return
+
+ .align ALIGNMENT
+x_denorm:
+ call fpdenormal
+ bsr ecx,eax ! zzzz
+ neg ecx
+ add ecx,#F_NORM_BIT
+ shl eax,cl
+ and eax,#F_FRAC_MASK
+ neg ecx
+ add ecx,#D_EXP_BIAS-F_EXP_BIAS+1
+ shl ecx,#D_EXP_SHIFT
+ and edx,#F_SIGN_MASK ! assumed same as D_SIGN_MASK
+ or edx,ecx
+ sub ecx,ecx
+ shrd ecx,eax,#D_EXP_BIT-F_EXP_BIT
+ shr eax,#D_EXP_BIT-F_EXP_BIT
+ or edx,eax
+
+ pop eax
+ push edx ! upper dword
+ push ecx ! lower dword
+ jmp eax ! return
+
+! Fnegf: as Fpushf, but negate double before pushing onto stack
+
+ .globl Fnegf
+ .align ALIGNMENT
+Fnegf:
+ mov edx,F_HIGH[ebx]
+ xor edx,#F_SIGN_MASK ! toggle sign
+ jmp into_Fpushf ! join Fpushf
diff --git a/libc/i386fp/fpushi.x b/libc/i386fp/fpushi.x
new file mode 100644
index 0000000..b19aae2
--- /dev/null
+++ b/libc/i386fp/fpushi.x
@@ -0,0 +1,126 @@
+! bcc 386 floating point routines (version 2)
+! -- Fpushi, Fpushl, Fpushs, Fpushc, Fpushuc, Fpushui, Fpushul, Fpushus
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+! Convert the short in ax to double and push on stack
+
+ .globl Fpushs
+ .align ALIGNMENT
+Fpushs:
+ cwde
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the int or long in eax to double and push on stack
+
+ .globl Fpushi
+ .globl Fpushl
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushi:
+Fpushl:
+ test eax,eax
+ jz return_eax ! got 0 in eax
+ mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent
+ jns normalize ! sign and fraction bits already set up
+ mov ebx,#D_SIGN_MASK | ((D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT) ! adjust sign
+ neg eax ! adjust fraction
+ jmp normalize
+
+ .align ALIGNMENT
+ret1:
+ mov eax,#D_EXP_BIAS << D_EXP_SHIFT
+ add eax,#0 ! fast 3-byte instruction to align
+
+! .align ALIGNMENT ! don't do this until it pads with nop's
+return_eax:
+ pop ecx
+ push eax ! upper dword
+ push dword #0 ! lower dword = 0
+ jmp ecx ! return
+
+! Convert the (unsigned) char in al to double and push on stack
+
+ .globl Fpushc
+ .globl Fpushuc
+ .align ALIGNMENT
+Fpushc:
+Fpushuc:
+ and eax,#(1 << CHAR_BIT)-1
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the unsigned short in ax to double and push on stack
+
+ .globl Fpushus
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushus:
+ and eax,#(1 << SHORT_BIT)-1
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the unsigned int or long in eax to double and push on stack
+
+ .globl Fpushui
+ .globl Fpushul
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushui:
+Fpushul:
+ cmp eax,#1 ! this tests for both 0 and 1
+ jb return_eax ! got 0 in eax
+ jz ret1
+ mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent
+
+! .align ALIGNMENT ! don't do this until it pads with nop's
+normalize:
+ sub edx,edx ! clear lower dword of result
+
+! Find first nonzero bit
+! Don't use bsr, it is slow (const + 3n on 386, const + n on 486)
+
+ sub ecx,ecx ! prepare unsigned extension of cl
+ test eax,#~D_FRAC_MASK
+ jnz large
+ test eax,#0xFF << (D_NORM_BIT-8)
+ jnz middle
+ shl eax,#8
+ sub ebx,#8 << D_EXP_SHIFT
+ test eax,#0xFF << (D_NORM_BIT-8)
+ jnz middle
+ shl eax,#8
+ sub ebx,#8 << D_EXP_SHIFT
+middle:
+ shld ecx,eax,#D_NORM_BIT
+ mov cl,bsr_table[ecx]
+ add ecx,#REG_BIT-D_NORM_BIT-D_NORM_BIT
+ neg ecx
+ shl eax,cl
+ shl ecx,#D_EXP_SHIFT
+ sub ebx,ecx
+return:
+ and eax,#D_FRAC_MASK ! remove normalization bit
+ or eax,ebx ! include exponent (and sign) to fraction
+ pop ecx
+ push eax ! upper dword
+ push edx ! lower dword
+ jmp ecx ! return
+
+ .align ALIGNMENT
+large:
+ shld ecx,eax,#REG_BIT-(D_NORM_BIT+8)
+ jnz huge
+ shld ecx,eax,#REG_BIT-D_NORM_BIT
+ mov cl,bsr_table[ecx]
+got_shift_right:
+ shrd edx,eax,cl
+ shr eax,cl
+ shl ecx,#D_EXP_SHIFT
+ add ebx,ecx
+ jmp return
+
+ .align ALIGNMENT
+huge:
+ mov cl,bsr_table[ecx]
+ add cl,#8
+ jmp got_shift_right
+
+ .data
+ .extern bsr_table
diff --git a/libc/i386fp/frexp.x b/libc/i386fp/frexp.x
new file mode 100644
index 0000000..318fc34
--- /dev/null
+++ b/libc/i386fp/frexp.x
@@ -0,0 +1,66 @@
+! bcc 386 floating point routines (version 2) -- _frexp
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpdenormal
+
+! void frexp(double value, int *exponent);
+! splits a double into exponent and fraction (where 0.5 <= fraction < 1.0)
+
+ .globl _frexp
+ .align ALIGNMENT
+_frexp:
+push ebx
+#undef PC_SIZE
+#define PC_SIZE 8
+ mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x
+ mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x
+ mov edx,PC_SIZE+D_SIZE[esp] ! exponent pointer
+ mov ecx,ebx ! extract exponent here
+ and ecx,#D_EXP_MASK
+ jz exp_x_0
+
+ shr ecx,#D_EXP_SHIFT ! exponent + bias
+got_x:
+ sub ecx,#D_EXP_BIAS-1 ! D_EXP_BIAS is for 1.x form, we want 0.1x form
+ mov [edx],ecx ! return exponent
+ and ebx,#D_SIGN_MASK | D_FRAC_MASK ! extract sign and fraction
+ or ebx,#(D_EXP_BIAS-1) << D_EXP_SHIFT ! set new exponent for 0.1x
+mov edx,ebx
+pop ebx
+ ret
+
+ .align ALIGNMENT
+exp_x_0:
+ test ebx,#D_FRAC_MASK
+ jnz xu_denorm
+ test eax,eax
+ jnz xl_denorm
+ mov [edx],ecx ! return zero exponent
+ mov ebx,ecx ! guard against -0 (may not be necessary)
+mov edx,ebx
+pop ebx
+ ret
+
+ .align ALIGNMENT
+xl_denorm:
+ call fpdenormal
+ bsr ecx,eax ! zzzz
+ neg ecx
+ add ecx,#REG_BIT-1
+ shl eax,cl
+ shld ebx,eax,#D_NORM_BIT+1
+ shl eax,#D_NORM_BIT+1
+ sub ecx,#D_NORM_BIT+1
+ jmp got_x
+
+ .align ALIGNMENT
+xu_denorm:
+ call fpdenormal
+ bsr ecx,ebx
+ neg ecx
+ add ecx,#D_NORM_BIT
+ shld ebx,eax,cl
+ shl eax,cl
+ jmp got_x
diff --git a/libc/i386fp/ftst.x b/libc/i386fp/ftst.x
new file mode 100644
index 0000000..2a92ef1
--- /dev/null
+++ b/libc/i386fp/ftst.x
@@ -0,0 +1,28 @@
+! bcc 386 floating point routines (version 2) -- Ftst, Ftstd, Ftstf
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+#if 0 /* bcc doesn't generate Ftst (but it might in future) */
+ .globl Ftst
+#endif
+ .align ALIGNMENT
+Ftst:
+ cmp dword PC_SIZE+D_HIGH[esp],#0 ! need only test upper dword of x
+ ret #D_SIZE
+
+! Compare double at address [ebx] with 0
+
+ .globl Ftstd
+ .align ALIGNMENT
+Ftstd:
+ cmp dword D_HIGH[ebx],#0 ! need only test upper dword of x
+ ret
+
+! Compare float at address [ebx] with 0
+
+ .globl Ftstf
+ .align ALIGNMENT
+Ftstf:
+ cmp dword F_HIGH[ebx],#0
+ ret
diff --git a/libc/i386fp/ldexp.x b/libc/i386fp/ldexp.x
new file mode 100644
index 0000000..bc9dd03
--- /dev/null
+++ b/libc/i386fp/ldexp.x
@@ -0,0 +1,74 @@
+! bcc 386 floating point routines (version 2) -- _ldexp
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpoverflow
+ .extern fpunderflow
+
+! void ldexp(double value, int exponent);
+! returns value * (2 ** exponent)
+
+ .globl _ldexp
+ .align ALIGNMENT
+_ldexp:
+push ebx
+#undef PC_SIZE
+#define PC_SIZE 8
+ mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x
+ mov ecx,PC_SIZE+D_SIZE[esp] ! exponent arg
+ mov eax,ebx ! extract exponent (of x) here
+ and eax,#D_EXP_MASK
+! jz exp_y_0 ! may need check for preposterous exponent arg too
+
+ shr eax,#D_EXP_SHIFT ! shift to low bits just for testing
+ jz underflow ! denormal?
+ add eax,ecx ! test-add the exponents
+ jz underflow ! XXX probably need to fiddle norm bit
+ cmp eax,#D_EXP_INFINITE ! check if still within range
+ jae outofbounds ! the unsigned compare catches all overflow cases
+ ! because the exponent of x is non-negative
+
+ shl ecx,#D_EXP_SHIFT ! shift exponent arg bits into final position ...
+ add ebx,ecx ! ... safe to add it to exponent of x now
+ mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x
+mov edx,ebx
+pop ebx
+ ret
+
+
+ .align ALIGNMENT
+outofbounds:
+ test ecx,ecx ! overflow or underflow?
+ jns overflow
+underflow:
+ mov edx,ebx ! put sign in usual reg
+ push edi
+ push esi
+ mov edi,eax ! put exponent in usual reg
+ mov eax,2*GENREG_SIZE+PC_SIZE+D_LOW[esp]
+ ! put lower dword of x in usual reg
+ mov esi,ebx ! put upper dword of x in usual reg
+ and esi,#D_EXP_MASK | D_FRAC_MASK
+ test esi,#D_EXP_MASK
+ jz foo
+ and esi,#D_FRAC_MASK
+ or esi,#D_NORM_MASK
+foo:
+ neg edi
+! inc edi ! XXX ?
+ call fpunderflow
+ pop esi
+ pop edi
+ mov ebx,edx ! XXX = wrong reg
+pop ebx
+ ret
+
+ .align ALIGNMENT
+overflow:
+ mov edx,ebx ! put sign in usual reg
+ call fpoverflow
+ mov eax,ecx ! XXX = wrong reg
+ mov ebx,edx ! XXX = wrong reg
+pop ebx
+ ret
diff --git a/libc/i386fp/modf.c b/libc/i386fp/modf.c
new file mode 100644
index 0000000..3232543
--- /dev/null
+++ b/libc/i386fp/modf.c
@@ -0,0 +1,14 @@
+#include <math.h>
+
+/* Slooow version. */
+
+double modf(x, pint)
+double x;
+double *pint;
+{
+ if (x >= 0)
+ *pint = floor(x);
+ else
+ *pint = ceil(x);
+ return x - *pint;
+}
diff --git a/libc/i386fp/test.c b/libc/i386fp/test.c
new file mode 100644
index 0000000..bd92581
--- /dev/null
+++ b/libc/i386fp/test.c
@@ -0,0 +1,118 @@
+#include <sys/times.h>
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+
+#define CONVTYPE int
+#define MAX (MIN + NITER - 1)
+#define MIN INT_MIN
+
+#define NITER 1000000
+
+double one = 1;
+double two = 2;
+double big = 1e99;
+
+double d;
+double d1;
+float f;
+
+int main()
+{
+ CONVTYPE cti;
+ CONVTYPE cto;
+ clock_t delta;
+ struct tms finish;
+ int i;
+ struct tms start;
+
+#if 0
+ times(&start);
+ for (cti = MIN; cti <= MAX; ++cti)
+ {
+ d = cti;
+ cto = d;
+ if (cti != cto)
+ printf("%08x %08x\n", cti, cto);
+ if (cti % 10000000 == 0)
+ {
+ printf("%8x ok ", cti);
+ fflush(stdout);
+ }
+ }
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for %d i -> d and d -> i conversions was %g s (%d t)\n",
+ MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta);
+#endif
+
+ times(&start);
+ for (cti = MIN; cti <= MAX; ++cti)
+ d = cti;
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for %d i -> d conversions was %g s (%d t)\n",
+ MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta);
+
+ times(&start);
+ for (cti = MIN; cti <= MAX; ++cti)
+ {
+ d = cti;
+ cto = d;
+ }
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime - delta;
+ printf("Time for %d d -> i conversions was %g s (%d t)\n",
+ MAX - MIN + 1, delta / (double) CLOCKS_PER_SEC, delta);
+
+ d = 0;
+ times(&start);
+ for (i = 0; i < NITER; ++i)
+ d = d + 1;
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for adding %d 1.0's to 0.0 was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, d);
+
+ d = 0;
+ times(&start);
+ for (; d < NITER;)
+ d = d + 1;
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for adding %d 1.0's to 0.0 (d index) was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, d);
+
+ times(&start);
+ for (i = 1; i <= NITER; ++i)
+ {
+ d1 = i;
+ d = d1 * d1;
+ }
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for %d mults was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, d);
+
+ times(&start);
+ for (i = 1; i <= NITER; ++i)
+ {
+ d1 = i;
+ d = 1 / d1;
+ }
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for %d divs was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, d);
+
+ f = 0;
+ times(&start);
+ for (i = 0; i < NITER; ++i)
+ f = f + 1;
+ times(&finish);
+ delta = finish.tms_utime - start.tms_utime;
+ printf("Time for adding %d 1.0f's to 0.0f was %g s (%d t), result = %g\n",
+ NITER, delta / (double) CLOCKS_PER_SEC, delta, f);
+
+ return 0;
+}
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index 038659f..3e94272 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -21,17 +21,18 @@ extern unsigned char _ctype[];
#define _tolower(c) ((c)^0x20)
#define toascii(c) ((c)&0x7F)
-#define isalnum(c) (_ctype[(int) c]&(__CT_u|__CT_l|__CT_d))
-#define isalpha(c) (_ctype[(int) c]&(__CT_u|__CT_l))
-#define isascii(c) !((c)&~0x7F)
-#define iscntrl(c) (_ctype[(int) c]&__CT_c)
-#define isdigit(c) (_ctype[(int) c]&__CT_d)
-#define isgraph(c) !(_ctype[(int) c]&(__CT_c|__CT_s))
-#define islower(c) (_ctype[(int) c]&__CT_l)
-#define isprint(c) !(_ctype[(int) c]&__CT_c)
-#define ispunct(c) (_ctype[(int) c]&__CT_p)
-#define isspace(c) (_ctype[(int) c]&__CT_s)
-#define isupper(c) (_ctype[(int) c]&__CT_u)
-#define isxdigit(c) (_ctype[(int) c]&__CT_x)
+/* Note the '!!' is a cast to 'bool' and even BCC deletes it in an if() */
+#define isalnum(c) (!!(_ctype[(int) c]&(__CT_u|__CT_l|__CT_d)))
+#define isalpha(c) (!!(_ctype[(int) c]&(__CT_u|__CT_l)))
+#define isascii(c) (!((c)&~0x7F))
+#define iscntrl(c) (!!(_ctype[(int) c]&__CT_c))
+#define isdigit(c) (!!(_ctype[(int) c]&__CT_d))
+#define isgraph(c) (!(_ctype[(int) c]&(__CT_c|__CT_s)))
+#define islower(c) (!!(_ctype[(int) c]&__CT_l))
+#define isprint(c) (!(_ctype[(int) c]&__CT_c))
+#define ispunct(c) (!!(_ctype[(int) c]&__CT_p))
+#define isspace(c) (!!(_ctype[(int) c]&__CT_s))
+#define isupper(c) (!!(_ctype[(int) c]&__CT_u))
+#define isxdigit(c) (!!(_ctype[(int) c]&__CT_x))
#endif /* __CTYPE_H */
diff --git a/libc/include/dos.h b/libc/include/dos.h
index 28575b4..1e2b11e 100644
--- a/libc/include/dos.h
+++ b/libc/include/dos.h
@@ -14,6 +14,7 @@ struct SREGS
unsigned int es, cs, ss, ds;
};
+#ifdef __MSDOS__
extern unsigned int __envseg;
extern unsigned int __psp;
char * __fconv __P((char * fname));
@@ -21,6 +22,7 @@ char * __fconv __P((char * fname));
unsigned int __segalloc __P((unsigned int paracount));
void __setvect __P((int i, long j));
long __getvect __P((int vecno));
+#endif
unsigned int __get_ds __P((void));
unsigned int __get_es __P((void));
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 579287e..520c1c4 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -26,7 +26,31 @@
#ifndef RAND_MAX
#define RAND_MAX INT_MAX
#endif
-#else
+#endif
+
+#if __AS386_32__
+#define MB_LEN_MAX 1 /* Longest multi-byte character */
+#define CHAR_MAX 127 /* maximum char value */
+#define CHAR_MIN (-127) /* mimimum char value */
+#define SCHAR_MAX 127 /* maximum signed char value */
+#define SCHAR_MIN (-127) /* minimum signed char value */
+#define CHAR_BIT 8 /* number of bits in a char */
+#define SHRT_MAX 32767 /* maximum (signed) short value */
+#define SHRT_MIN (-32767) /* minimum (signed) short value */
+#define INT_MAX 2147483647 /* maximum (signed) int value */
+#define INT_MIN (-2147483647) /* minimum (signed) int value */
+#define LONG_MAX 2147483647 /* maximum (signed) long value */
+#define LONG_MIN (-2147483647) /* minimum (signed) long value */
+#define UCHAR_MAX 255 /* maximum unsigned char value */
+#define USHRT_MAX 0xffff /* maximum unsigned short value */
+#define UINT_MAX 0xffffffff /* maximum unsigned int value */
+#define ULONG_MAX 0xffffffff /* maximum unsigned long value */
+#ifndef RAND_MAX
+#define RAND_MAX INT_MAX
+#endif
+#endif
+
+#ifndef CHAR_MAX
#error "Limits.h not implemented"
#endif
diff --git a/libc/include/math.h b/libc/include/math.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libc/include/math.h
diff --git a/libc/include/stddef.h b/libc/include/stddef.h
index f21f683..ce3cf2b 100644
--- a/libc/include/stddef.h
+++ b/libc/include/stddef.h
@@ -9,7 +9,9 @@
#undef __need_ptrdiff_t
#undef __need_NULL
-#if __AS386_16__ /* Only for 8086 */
+/* Fact is these are _normal_ */
+#if 1 /* __BCC__ */ /* Only for Bcc 8086/80386 */
+
#ifndef __STDDEF_H
#define __STDDEF_H
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index ba70b1d..98ca38a 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -61,7 +61,11 @@ struct __stdio_file {
typedef struct __stdio_file FILE;
+#ifdef __AS386_16__
#define BUFSIZ (256)
+#else
+#define BUFSIZ (2048)
+#endif
extern FILE stdin[1];
extern FILE stdout[1];
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libc/include/sys/mman.h
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index b8c5ee0..d21f986 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -5,6 +5,38 @@
#include <sys/types.h>
#include <features.h>
+#ifdef __AS386_32__
+/* This is for Linux-386, ho hum, I wish BCC could compile the proper one */
+#define mknod __dv32_mknod
+#define stat __dv32_stat
+#define lstat __dv32_lstat
+#define fstat __dv32_fstat
+
+struct stat {
+ dev_t st_dev;
+ unsigned short __pad1;
+ ino_t st_ino;
+ umode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ unsigned short __pad2;
+ off_t st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ time_t st_atime;
+ unsigned long __unused1;
+ time_t st_mtime;
+ unsigned long __unused2;
+ time_t st_ctime;
+ unsigned long __unused3;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+#else
+
struct stat
{
dev_t st_dev;
@@ -19,6 +51,7 @@ struct stat
time_t st_mtime;
time_t st_ctime;
};
+#endif
int stat __P((__const char * __path, struct stat * __statbuf));
int lstat __P((__const char * __path, struct stat * __statbuf));
diff --git a/libc/include/sys/vm86.h b/libc/include/sys/vm86.h
new file mode 100644
index 0000000..851814e
--- /dev/null
+++ b/libc/include/sys/vm86.h
@@ -0,0 +1,125 @@
+#if !__AS386_16__
+
+#ifndef _SYS_VM86_H
+#define _SYS_VM86_H
+
+#include <features.h>
+#ifndef _LINUX_VM86_H
+#define _LINUX_VM86_H
+
+/*
+ * I'm guessing at the VIF/VIP flag usage, but hope that this is how
+ * the Pentium uses them. Linux will return from vm86 mode when both
+ * VIF and VIP is set.
+ *
+ * On a Pentium, we could probably optimize the virtual flags directly
+ * in the eflags register instead of doing it "by hand" in vflags...
+ *
+ * Linus
+ */
+
+#define TF_MASK 0x00000100
+#define IF_MASK 0x00000200
+#define IOPL_MASK 0x00003000
+#define NT_MASK 0x00004000
+#define VM_MASK 0x00020000
+#define AC_MASK 0x00040000
+#define VIF_MASK 0x00080000 /* virtual interrupt flag */
+#define VIP_MASK 0x00100000 /* virtual interrupt pending */
+#define ID_MASK 0x00200000
+
+#define BIOSSEG 0x0f000
+
+#define CPU_086 0
+#define CPU_186 1
+#define CPU_286 2
+#define CPU_386 3
+#define CPU_486 4
+#define CPU_586 5
+
+/*
+ * Return values for the 'vm86()' system call
+ */
+#define VM86_TYPE(retval) ((retval) & 0xff)
+#define VM86_ARG(retval) ((retval) >> 8)
+
+#define VM86_SIGNAL 0 /* return due to signal */
+#define VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */
+#define VM86_INTx 2 /* int3/int x instruction (ARG = x) */
+#define VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */
+
+/*
+ * This is the stack-layout when we have done a "SAVE_ALL" from vm86
+ * mode - the main change is that the old segment descriptors aren't
+ * useful any more and are forced to be zero by the kernel (and the
+ * hardware when a trap occurs), and the real segment descriptors are
+ * at the end of the structure. Look at ptrace.h to see the "normal"
+ * setup.
+ */
+
+struct vm86_regs {
+/*
+ * normal regs, with special meaning for the segment descriptors..
+ */
+ long ebx;
+ long ecx;
+ long edx;
+ long esi;
+ long edi;
+ long ebp;
+ long eax;
+ long __null_ds;
+ long __null_es;
+ long __null_fs;
+ long __null_gs;
+ long orig_eax;
+ long eip;
+ unsigned short cs, __csh;
+ long eflags;
+ long esp;
+ unsigned short ss, __ssh;
+/*
+ * these are specific to v86 mode:
+ */
+ unsigned short es, __esh;
+ unsigned short ds, __dsh;
+ unsigned short fs, __fsh;
+ unsigned short gs, __gsh;
+};
+
+struct revectored_struct {
+ unsigned long __map[8]; /* 256 bits */
+};
+
+struct vm86_struct {
+ struct vm86_regs regs;
+ unsigned long flags;
+ unsigned long screen_bitmap;
+ unsigned long cpu_type;
+ struct revectored_struct int_revectored;
+ struct revectored_struct int21_revectored;
+};
+
+/*
+ * flags masks
+ */
+#define VM86_SCREEN_BITMAP 0x0001
+
+#ifdef __KERNEL__
+
+void handle_vm86_fault(struct vm86_regs *, long);
+void handle_vm86_debug(struct vm86_regs *, long);
+
+#endif
+
+#endif
+
+__BEGIN_DECLS
+
+extern vm86(struct vm86_struct * __info);
+
+__END_DECLS
+
+#endif /*_SYS_VM86_H */
+
+#endif
diff --git a/libc/include/sys/x b/libc/include/sys/x
deleted file mode 100644
index edb5794..0000000
--- a/libc/include/sys/x
+++ /dev/null
@@ -1,3 +0,0 @@
-#define S_IREAD S_IRUSR /* read permission, owner */
-#define S_IWRITE S_IWUSR /* write permission, owner */
-#define S_IEXEC S_IXUSR /* execute/search permission, owner */
diff --git a/libc/kinclude/Makefile b/libc/kinclude/Makefile
index 83d05ed..8982f57 100644
--- a/libc/kinclude/Makefile
+++ b/libc/kinclude/Makefile
@@ -14,10 +14,14 @@ libc.a:
transfer:
-@rm -f ../include/linuxmt
ln -s ../kinclude/linuxmt ../include
+ @touch Used
# This is for use once linuxmt's syscall interface really gets working.
+# beware the arch directory must be removed when you do this.
real_transfer:
-@rm -f ../include/linuxmt
cd ../include ; ln -s ../../linuxmt/include/linuxmt .
clean:
+ -@rm -f ../include/linuxmt
+ -@rm -f Used
diff --git a/libc/kinclude/arch/types.h b/libc/kinclude/arch/types.h
index b77ad8e..00afeed 100644
--- a/libc/kinclude/arch/types.h
+++ b/libc/kinclude/arch/types.h
@@ -10,10 +10,10 @@ typedef unsigned char * __pu8;
typedef char __s8;
typedef char * __ps8;
-typedef unsigned int __u16;
-typedef unsigned int * __pu16;
-typedef int __s16;
-typedef int * __ps16;
+typedef unsigned short __u16;
+typedef unsigned short * __pu16;
+typedef short __s16;
+typedef short * __ps16;
typedef unsigned long __u32;
typedef unsigned long * __pu32;
diff --git a/libc/kinclude/linuxmt/stat.h b/libc/kinclude/linuxmt/stat.h
index 48256a5..9fbd191 100644
--- a/libc/kinclude/linuxmt/stat.h
+++ b/libc/kinclude/linuxmt/stat.h
@@ -27,7 +27,9 @@
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#ifdef __LINUXMT_NETWORK__
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
#define S_IRWXU 00700
#define S_IRUSR 00400
diff --git a/libc/kinclude/linuxmt/types.h b/libc/kinclude/linuxmt/types.h
index 1450d25..8e5236a 100644
--- a/libc/kinclude/linuxmt/types.h
+++ b/libc/kinclude/linuxmt/types.h
@@ -24,7 +24,7 @@ typedef __u32 loff_t;
typedef __u32 speed_t;
typedef __u16 dev_t;
-typedef __u16 ino_t;
+typedef __uint ino_t;
typedef __u32 tcflag_t;
typedef __u8 cc_t;
diff --git a/libc/libc.a b/libc/libc.a
deleted file mode 100644
index be7499f..0000000
--- a/libc/libc.a
+++ /dev/null
Binary files differ
diff --git a/libc/malloc1/malloc.c b/libc/malloc1/malloc.c
index 91912f7..86ffd42 100644
--- a/libc/malloc1/malloc.c
+++ b/libc/malloc1/malloc.c
@@ -106,7 +106,7 @@ size_t size;
if (size == 0)
return 0; /* No allocation required. */
- hp = (mem *) (*__alloca_alloc) (sizeof(mem) + size);
+ hp = (mem *) (*__alloca_alloc) (sizeof(mem)*2 + size);
if (hp == 0)
return hp;
@@ -135,8 +135,8 @@ void *ptr;
top = (mem *) sbrk(0);
if (chk + m_size(chk) == top)
{
- noise("FREE sbrk", chk);
- sbrk(-m_size(chk) * sizeof(mem));
+ noise("FREE brk", chk);
+ brk(top-m_size(chk));
/*
* Adding this code allow free to release blocks in any order; they
* can still only be allocated from the top of the heap tho.
@@ -215,9 +215,11 @@ size_t size;
* circular list of all the free blocks in memory
*/
+#define Static static
+
static mem *chunk_list = 0;
-static void insert_chunk();
-static mem *search_chunk();
+Static void __insert_chunk();
+Static mem *__search_chunk();
void *
malloc(size)
@@ -248,7 +250,7 @@ size_t size;
__alloca_alloc = malloc; /* We'll be messing with the heap now TVM */
#ifdef LAZY_FREE
- ptr = search_chunk(sz);
+ ptr = __search_chunk(sz);
if (ptr == 0)
{
#endif
@@ -268,11 +270,10 @@ size_t size;
return ptr + 1;
}
- insert_chunk(ptr);
+ __insert_chunk(ptr);
}
ptr = m_next(chunk_list);
- if (m_size(ptr) < (MAX_INT/sizeof(mem))
- && ptr + m_size(ptr) == (void *) sbrk(0))
+ if (ptr + m_size(ptr) == (void *) sbrk(0))
{
/* Time to free for real */
m_next(chunk_list) = m_next(ptr);
@@ -281,11 +282,11 @@ size_t size;
free(ptr + 1);
}
#ifdef LAZY_FREE
- ptr = search_chunk(sz);
+ ptr = __search_chunk(sz);
#endif
}
#ifndef LAZY_FREE
- ptr = search_chunk(sz);
+ ptr = __search_chunk(sz);
#endif
if (ptr == 0)
{
@@ -294,17 +295,22 @@ size_t size;
alloc = sizeof(mem) * (MCHUNK * ((sz + MCHUNK - 1) / MCHUNK) - 1);
ptr = __mini_malloc(alloc);
if (ptr)
- insert_chunk(ptr - 1);
+ __insert_chunk(ptr - 1);
else /* Oooo, near end of RAM */
{
- for(alloc/=2; alloc>256; )
+ unsigned int needed = alloc;
+ for(alloc/=2; alloc>256 && needed; )
{
ptr = __mini_malloc(alloc);
- if (ptr) insert_chunk(ptr - 1);
+ if (ptr)
+ {
+ if( alloc > needed ) needed = 0; else needed -= alloc;
+ __insert_chunk(ptr - 1);
+ }
else alloc/=2;
}
}
- ptr = search_chunk(sz);
+ ptr = __search_chunk(sz);
if (ptr == 0)
#endif
{
@@ -336,8 +342,8 @@ size_t size;
* the chain of memory chunks
*/
-static void
-insert_chunk(mem_chunk)
+Static void
+__insert_chunk(mem_chunk)
mem *mem_chunk;
{
register mem *p1, *p2;
@@ -438,8 +444,8 @@ mem *mem_chunk;
* chunk returned. If none is found NULL is returned.
*/
-static mem *
-search_chunk(mem_size)
+Static mem *
+__search_chunk(mem_size)
unsigned int mem_size;
{
register mem *p1, *p2;
diff --git a/libc/malloc2/malloc.c b/libc/malloc2/malloc.c
index 143d324..2e1cc04 100644
--- a/libc/malloc2/malloc.c
+++ b/libc/malloc2/malloc.c
@@ -47,7 +47,6 @@ extern int __STACKSIZE;
loc 1 ! Make sure the pointer is in the correct segment
auto_func: ! Label for bcc -M to work.
.word _malloc_init ! Pointer to the autorun function
- .word no_op ! Space filler cause segs are padded to 4 bytes.
.text ! So the function after is also in the correct seg.
#endasm
#endif
diff --git a/libc/misc/Makefile b/libc/misc/Makefile
index 01092bb..3db73a7 100644
--- a/libc/misc/Makefile
+++ b/libc/misc/Makefile
@@ -15,17 +15,17 @@ GOBJ=atoi.o atol.o ltoa.o ltostr.o \
ctype.o qsort.o bsearch.o rand.o lsearch.o getopt.o \
itoa.o cputype.o strtol.o crypt.o
-UOBJ=getenv.o putenv.o popen.o system.o
+UOBJ=getenv.o putenv.o popen.o system.o setenv.o
-ifeq ($(PLATFORM),i86-DOS)
-OBJ=$(MOBJ) $(EOBJ) $(GOBJ)
-else
+ifeq ($(LIB_OS),ELKS)
OBJ=$(MOBJ) $(EOBJ) $(GOBJ) $(UOBJ)
+else
+OBJ=$(MOBJ) $(EOBJ) $(GOBJ)
endif
# No ELKS strtod() until BCC does 16 bit FP...
-ifeq ($(PLATFORM),i386-Linux)
+ifneq ($(LIB_CPU),i86)
OBJ+=strtod.o
endif
@@ -45,14 +45,14 @@ $(EOBJ): $(ESRC)
$(CC) $(CFLAGS) -c -DL_$* -o $@ $(ESRC)
crypt.o: crypt.c
-ifeq ($(PLATFORM),i386-Linux)
+ifeq ($(LIB_CPU),g386)
$(CC) $(CFLAGS) $< -c -o $@ $(WALL)
else
$(CC) $(CFLAGS) $< -c -o $@ -ansi
endif
strto%.o: strto%.c
-ifeq ($(PLATFORM),i386-Linux)
+ifeq ($(LIB_CPU),g386)
$(CC) $(CFLAGS) $< -c -o $@ $(WALL)
else
$(CC) $(CFLAGS) $< -c -o $@ -ansi
diff --git a/libc/misc/aliases.c b/libc/misc/aliases.c
index 466cb74..d23ea65 100644
--- a/libc/misc/aliases.c
+++ b/libc/misc/aliases.c
@@ -27,8 +27,9 @@ int signo;
#undef bcopy
void
bcopy(src, dest, len)
-void * src, *dest;
-unsigned int len;
+__const void * src;
+void *dest;
+int len;
{
(void) memcpy(dest, src, len);
}
@@ -39,7 +40,7 @@ unsigned int len;
void
bzero(dest, len)
void *dest;
-unsigned int len;
+int len;
{
(void) memset(dest, '\0', len);
}
@@ -49,8 +50,8 @@ unsigned int len;
#undef bcmp
int
bcmp(dest, src, len)
-void * src, *dest;
-unsigned int len;
+__const void * src, *dest;
+int len;
{
return memcmp(dest, src, len);
}
@@ -60,7 +61,7 @@ unsigned int len;
#undef index
char *
index(src, chr)
-char *src;
+__const char *src;
int chr;
{
return strchr(src, chr);
@@ -71,7 +72,7 @@ int chr;
#undef rindex
char *
rindex(src, chr)
-char *src;
+__const char *src;
int chr;
{
return strrchr(src, chr);
@@ -83,7 +84,7 @@ int chr;
int
remove(src)
-char *src;
+__const char *src;
{
extern int errno;
int er = errno;
diff --git a/libc/misc/cputype.c b/libc/misc/cputype.c
index 7dd7088..8417514 100644
--- a/libc/misc/cputype.c
+++ b/libc/misc/cputype.c
@@ -327,7 +327,7 @@ int6:
mov sp, bp
jmp fail386
-; This was the old way, didn't always work tho.
+; This was the old way, didn`t always work tho.
; push bp
; mov bp, sp
; push ax
diff --git a/libc/misc/setenv.c b/libc/misc/setenv.c
new file mode 100644
index 0000000..10b32d2
--- /dev/null
+++ b/libc/misc/setenv.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 1992, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+extern char ** environ;
+
+int
+setenv(name, value, replace)
+__const char *name;
+__const char *value;
+int replace;
+{
+ register char **ep;
+ register size_t size;
+ __const size_t namelen = strlen (name);
+ __const size_t vallen = strlen (value);
+ int result = 0;
+
+ size = 0;
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!memcmp (*ep, name, namelen) && (*ep)[namelen] == '=')
+ break;
+ else
+ ++size;
+
+ if (*ep == NULL)
+ {
+ static char **last_environ = NULL;
+ char **new_environ = (char **) malloc((size + 2) * sizeof(char *));
+ if (new_environ == NULL)
+ {
+ result = -1;
+ goto do_return;
+ }
+ (void) memcpy((void*) new_environ, (void*) environ, size * sizeof(char *));
+
+ new_environ[size] = malloc (namelen + 1 + vallen + 1);
+ if (new_environ[size] == NULL)
+ {
+ free (new_environ);
+ errno = ENOMEM;
+ result = -1;
+ goto do_return;
+ }
+ memcpy (new_environ[size], name, namelen);
+ new_environ[size][namelen] = '=';
+ memcpy (&new_environ[size][namelen + 1], value, vallen + 1);
+
+ new_environ[size + 1] = NULL;
+
+ if (last_environ != NULL)
+ free ((void*) last_environ);
+ last_environ = new_environ;
+ environ = new_environ;
+ }
+ else if (replace)
+ {
+ size_t len = strlen (*ep);
+ if (len < namelen + 1 + vallen)
+ {
+ char *new = malloc (namelen + 1 + vallen + 1);
+ if (new == NULL)
+ {
+ result = -1;
+ goto do_return;
+ }
+ *ep = new;
+ }
+ memcpy (*ep, name, namelen);
+ (*ep)[namelen] = '=';
+ memcpy (&(*ep)[namelen + 1], value, vallen + 1);
+ }
+
+do_return:
+ return result;
+}
+
+void
+unsetenv(name)
+__const char *name;
+{
+ register char **ep;
+ register char **dp;
+ __const size_t namelen = strlen (name);
+
+ for (dp = ep = environ; *ep != NULL; ++ep)
+ if (memcmp (*ep, name, namelen) || (*ep)[namelen] != '=')
+ {
+ *dp = *ep;
+ ++dp;
+ }
+ *dp = NULL;
+}
diff --git a/libc/msdos/Makefile b/libc/msdos/Makefile
index cdafaa3..59f38b9 100644
--- a/libc/msdos/Makefile
+++ b/libc/msdos/Makefile
@@ -15,11 +15,13 @@ BSRC=i86.c
BOBJ= __seg_regs.o __peek_es.o __poke_es.o __deek_es.o __doke_es.o \
__strchr_es.o
-ifeq ($(PLATFORM),i86-DOS)
+ifeq ($(LIB_CPU),i86)
+ifeq ($(LIB_OS),DOS)
OBJ=$(AOBJ) $(BOBJ)
else
OBJ=$(BOBJ)
endif
+endif
all: $(OBJ)
diff --git a/libc/msdos/msdos.c b/libc/msdos/msdos.c
index ddb49d9..390e904 100644
--- a/libc/msdos/msdos.c
+++ b/libc/msdos/msdos.c
@@ -14,11 +14,8 @@ int errno;
#ifdef L_dos_start
-static char * argdef[2] = { "C" };
-char ** __argv =argdef;
-char ** environ =argdef+1;
-
-int __argc =1;
+static char * defarg[2] = { "C" };
+static char ** def_environ =defarg+1;
void (*__cleanup)() = 0;
#asm
@@ -109,14 +106,19 @@ zap_bss: ! Clear the BSS
rep
stosb
- call ___mkargv ! Fetch the arguments and enviroment
- push [_environ]
- push [___argv]
- push [___argc]
+ push [_def_environ] ! Defaults for when nothing is used.
+ mov ax,#_defarg
+ push ax
+ mov ax,#1
+ push ax
mov si,#auto_start ! Pointer to first autostart function
auto_run:
- call [si] ! Call the function
+ mov bx,[si]
+ test bx,bx
+ jz no_entry
+ call bx ! Call the function
+no_entry:
inc si ! SI at next
inc si
jmp auto_run ! And round for the next.
@@ -163,11 +165,18 @@ sys_call0:
#ifdef L___mkargv
-extern char ** environ;
-extern char ** __argv;
-extern int __argc;
+#ifdef __AS386_16__
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word ___mkargv ! Pointer to the autorun function
+ .text ! So the function after is also in the correct seg.
+#endasm
+#endif
-__mkargv()
+__mkargv(__argc, __argv)
+int __argc;
+char ** __argv;
{
int length, i, argc=1, s=0;
char *ptr, *p;
diff --git a/libc/msdos/time.c b/libc/msdos/time.c
new file mode 100644
index 0000000..0a66da8
--- /dev/null
+++ b/libc/msdos/time.c
@@ -0,0 +1,63 @@
+
+#include <time.h>
+
+static int mdays[13] = { 0,31,31+28,31+28+31,31+28+31+30,
+ 31+28+31+30+31,31+28+31+30+31+30,31+28+31+30+31+30+31,
+ 31+28+31+30+31+30+31+31,31+28+31+30+31+30+31+31+30,
+ 31+28+31+30+31+30+31+31+30+31,31+28+31+30+31+30+31+31+30+31+30,
+ 365 };
+
+#define SECSPERHOUR (60*60)
+#define SECSPERDAY (SECSPERHOUR*24L)
+
+/****************************************
+ * Return the number of seconds that have elapsed since the start
+ * of 1970.
+ * Input:
+ * timer pointer to where to store result (or NULL)
+ * Output:
+ * *timer = result (unless timer == NULL)
+ * Returns:
+ * time
+ */
+
+static long get_time(ah)
+{
+#asm
+#if !__FIST_ARG_IN_AX__
+ mov bx,sp
+ mov ax,[bx+2]
+#endif
+ mov ah,al
+ int $21
+ mov ax,dx
+ mov dx,cx
+#endasm
+}
+
+time_t time(timer)
+time_t *timer;
+{
+ unsigned day,month,year;
+ long rv;
+ time_t t;
+
+ rv = get_time(0x2C);
+ rv >>= 8; t = (rv & 0xFF);
+ rv >>= 8; t += (rv & 0xFF)*60;
+ rv >>= 8; t += (rv & 0xFF)*3600;
+
+ rv = get_time(0x2A);
+ day = (rv & 0xFF);
+ rv >>= 8; month = (rv & 0xFF) -1;
+ rv >>= 8; year = (rv & 0xFFFF) - 1970;
+
+ if (month <= 1 || year & 3) /* if before Feb or not a leap year */
+ day--; /* don't add day for leap year */
+ day += mdays[month]; /* day in year */
+ day += (year + 3) >> 2; /* add a day for each leap year */
+ t += ((year * 365L) + day) * SECSPERDAY;
+ if (timer)
+ *timer = t;
+ return t;
+}
diff --git a/libc/pwd/Makefile b/libc/pwd/Makefile
index a31ac02..eb4b844 100644
--- a/libc/pwd/Makefile
+++ b/libc/pwd/Makefile
@@ -5,14 +5,18 @@
TOP=..
include $(TOP)/Make.defs
-ifeq ($(PLATFORM),i386-Linux)
+ifeq ($(PLATFORM),i386-ELKS)
CFLAGS+=$(WALL)
-else # ifeq ($(PLATFORM),i86-ELKS)
+else
CFLAGS=$(CCFLAGS) $(LIBDEFS) -ansi
endif
PSRC=__getpwent.c pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c fgetpwent.c
+ifeq ($(LIB_OS),ELKS)
POBJ=__getpwent.o pwent.o getpwnam.o getpwuid.o putpwent.o getpw.o fgetpwent.o
+else
+POBJ=
+endif
all: $(POBJ)
diff --git a/libc/stdio2/Makefile b/libc/stdio2/Makefile
index ef96567..f77df3a 100644
--- a/libc/stdio2/Makefile
+++ b/libc/stdio2/Makefile
@@ -2,6 +2,10 @@
TOP=..
include $(TOP)/Make.defs
+ifneq ($(LIB_CPU),i86)
+CFLAGS=$(CCFLAGS) $(LIBDEFS) -DFLOATS
+endif
+
ASRC=stdio.c
AOBJ=_stdio_init.o fputc.o fgetc.o fflush.o fgets.o gets.o fputs.o \
puts.o fread.o fwrite.o fopen.o fclose.o fseek.o rewind.o ftell.o \
@@ -28,6 +32,8 @@ transfer:
clean:
rm -f *.o libc.a
+$(OBJ): stdio.h
+
$(AOBJ): $(ASRC)
$(CC) $(CFLAGS) -c -DL_$* -o $@ $(ASRC)
diff --git a/libc/stdio2/printf.c b/libc/stdio2/printf.c
index 0d107a4..5a5744d 100644
--- a/libc/stdio2/printf.c
+++ b/libc/stdio2/printf.c
@@ -115,6 +115,11 @@ static FILE string[1] =
#endif
#ifdef L_vfprintf
+
+#ifdef FLOATS
+int (*__fp_print)() = 0;
+#endif
+
static int
prtfld(op, buf, ljustf, sign, pad, width, preci, buffer_mode)
register FILE *op;
@@ -197,9 +202,6 @@ register va_list ap;
register char *ptmp;
char tmp[64], *ltostr(), *ultostr();
int buffer_mode;
-#if FLOATS
- double fx;
-#endif
/* This speeds things up a bit for unbuffered */
buffer_mode = (op->mode&__MODE_BUF);
@@ -314,18 +316,6 @@ register va_list ap;
hash=1;
goto fmtnxt;
-#if FLOATS
- case 'e': /* float */
- case 'f':
- case 'g':
- case 'E':
- case 'G':
- fx = va_arg(ap, double);
- fp_print(fx, *fmt, preci, ptmp);
- preci = -1;
- goto printit;
-#endif
-
case 'c': /* Character */
ptmp[0] = va_arg(ap, int);
ptmp[1] = '\0';
@@ -341,6 +331,21 @@ register va_list ap;
sign, pad, width, preci, buffer_mode);
break;
+#if FLOATS
+ case 'e': /* float */
+ case 'f':
+ case 'g':
+ case 'E':
+ case 'G':
+ if ( __fp_print )
+ {
+ (*__fp_print)(&va_arg(ap, double), *fmt, preci, ptmp);
+ preci = -1;
+ goto printit;
+ }
+ /* FALLTHROUGH if no floating printf available */
+#endif
+
default: /* unknown character */
goto charout;
}
diff --git a/libc/stdio2/stdio.c b/libc/stdio2/stdio.c
index fa10644..bab246b 100644
--- a/libc/stdio2/stdio.c
+++ b/libc/stdio2/stdio.c
@@ -15,21 +15,29 @@
extern FILE *__IO_list; /* For fflush at exit */
-#ifndef __AS386_16__
-#define Inline_init __io_init_vars()
-#else
+#ifdef __AS386_16__
+#define Inline_init
+#endif
+
+#ifdef __AS386_32__
#define Inline_init
#endif
+#ifndef Inline_init
+#define Inline_init __io_init_vars()
+#endif
+
#ifdef L__stdio_init
+#define buferr (stderr->unbuf) /* Stderr is unbuffered */
+
FILE *__IO_list = 0; /* For fflush at exit */
static char bufin[BUFSIZ];
static char bufout[BUFSIZ];
+#ifndef buferr
static char buferr[BUFSIZ];
-
-/* #define buferr (stderr->unbuf) /* Stderr is unbuffered */
+#endif
FILE stdin[1] =
{
@@ -51,20 +59,32 @@ FILE stderr[1] =
/* Call the stdio initiliser; it's main job it to call atexit */
-#ifndef __AS386_16__
-#define STATIC
-#else
+#ifdef __AS386_16__
#define STATIC static
#asm
loc 1 ! Make sure the pointer is in the correct segment
auto_func: ! Label for bcc -M to work.
.word ___io_init_vars ! Pointer to the autorun function
- .word no_op ! Space filler cause segs are padded to 4 bytes.
.text ! So the function after is also in the correct seg.
#endasm
#endif
+#ifdef __AS386_32__
+#define STATIC static
+
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .long ___io_init_vars ! Pointer to the autorun function
+ .text ! So the function after is also in the correct seg.
+#endasm
+#endif
+
+#ifndef STATIC
+#define STATIC
+#endif
+
STATIC int
__stdio_close_all()
{
@@ -85,9 +105,11 @@ STATIC void
__io_init_vars()
{
#ifndef __AS386_16__
+#ifndef __AS386_32__
static int first_time = 1;
if( !first_time ) return ; first_time = 1;
#endif
+#endif
if (isatty(1))
stdout->mode |= _IOLBF;
atexit(__stdio_close_all);
@@ -483,10 +505,32 @@ long offset;
int ref;
{
/* Use fflush to sync the pointers */
- /*
- * TODO: if __MODE_READING and no ungetc ever done can just move
- * pointer
- */
+
+#if 0
+ /* if __MODE_READING and no ungetc ever done can just move pointer */
+ /* This needs testing! */
+
+ if ( (fp->mode &(__MODE_READING | __MODE_UNGOT)) == __MODE_READING &&
+ ( ref == SEEK_SET || ref == SEEK_CUR )
+ {
+ long fpos = lseek(fp->fd, 0L, SEEK_CUR);
+ if( fpos == -1 ) return EOF;
+
+ if( ref == SEEK_CUR )
+ {
+ ref = SEEK_SET;
+ offset = fpos + offset + fp->bufpos - fp->bufread;
+ }
+ if( ref == SEEK_SET )
+ {
+ if ( offset < fpos && offset >= fpos + fp->bufstart - fp->bufread )
+ {
+ fp->bufpos = offset - fpos + fp->bufread;
+ return 0;
+ }
+ }
+ }
+#endif
if (fflush(fp) == EOF)
return EOF;
@@ -756,6 +800,9 @@ FILE *fp;
if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ)
return EOF;
+ /* Can't do fast fseeks */
+ fp->mode |= __MODE_UNGOT;
+
if( fp->bufpos > fp->bufstart )
return *--fp->bufpos = (unsigned char) c;
else if( fp->bufread == fp->bufstart )
diff --git a/libc/stdio2/stdio.h b/libc/stdio2/stdio.h
index ba70b1d..98ca38a 100644
--- a/libc/stdio2/stdio.h
+++ b/libc/stdio2/stdio.h
@@ -61,7 +61,11 @@ struct __stdio_file {
typedef struct __stdio_file FILE;
+#ifdef __AS386_16__
#define BUFSIZ (256)
+#else
+#define BUFSIZ (2048)
+#endif
extern FILE stdin[1];
extern FILE stdout[1];
diff --git a/libc/string/string.c b/libc/string/string.c
index 50b7145..3e6d2e4 100644
--- a/libc/string/string.c
+++ b/libc/string/string.c
@@ -343,7 +343,7 @@ char * s;
register char * p;
len = strlen(s)+1;
- p = (char *) malloc(s);
+ p = (char *) malloc(len);
if(p) memcpy(p, s, len); /* Faster than strcpy */
return p;
}
diff --git a/libc/syscall/Makefile b/libc/syscall/Makefile
index fd2f1bc..06728da 100644
--- a/libc/syscall/Makefile
+++ b/libc/syscall/Makefile
@@ -6,34 +6,52 @@ TOP=..
include $(TOP)/Make.defs
LSRC=syslibc.c
-LOBJ=__cstartup.o time.o lseek.o getpid.o getppid.o \
- getuid.o geteuid.o getgid.o getegid.o \
- dup2.o dup.o abort.o wait.o waitpid.o sleep.o \
- killpg.o setpgrp.o getpgrp.o times.o usleep.o
+LOBJ=time.o abort.o wait.o waitpid.o killpg.o setpgrp.o sleep.o \
+ usleep.o
+
+LSRC3=syslib3.c
+LOBJ3=__cstart3.o
+
+LSRC0=syslib0.c
+LOBJ0=__cstartup.o lseek.o getpid.o getppid.o getuid.o geteuid.o getgid.o \
+ getegid.o dup2.o dup.o getpgrp.o times.o
ESRC=execve.c
-EOBJ=execve.o execl.o execv.o execle.o
+E2OBJ=execl.o execv.o execle.o
+EOBJ=execve.o $(E2OBJ)
DSRC=dirent.c
DOBJ=opendir.o closedir.o readdir.o
-ifeq ($(PLATFORM),i86-DOS)
-OBJ=setjmp.o
-else
-OBJ=$(LOBJ) $(DOBJ) $(EOBJ) signal.o setjmp.o execve.o
+ifeq ($(LIB_CPU)-$(LIB_OS),i86-ELKS)
+SYSCALLS=sh mksyscall
+OBJ=$(LOBJ0) $(LOBJ) $(DOBJ) $(EOBJ) signal.o setjmp.o
+DEP=mksyscall syscall.dat
endif
-all: mksyscall syscall.dat $(OBJ)
- sh mksyscall
+ifeq ($(LIB_CPU)-$(LIB_OS),i386-ELKS)
+SYSCALLS=sh mksys386
+OBJ=setjmp.o $(LOBJ3) $(LOBJ) $(E2OBJ) $(DOBJ)
+DEP=mksys386 sys386.dat
+endif
-clean:
- rm -f *.o libc.a syscall.c syscall.mak call_tab.v defn_tab.v
+ifeq ($(SYSCALLS),)
+SYSCALLS=true
+OBJ=setjmp.o
+DEP=
+endif
+
+all: $(DEP) $(OBJ)
+ $(SYSCALLS)
-libc.a: mksyscall syscall.dat $(OBJ)
- sh mksyscall libc.a
+libc.a: $(DEP) $(OBJ)
+ $(SYSCALLS) libc.a
ar r ../$(LIBC) $(OBJ)
@touch libc.a
+clean:
+ rm -f *.o libc.a syscall.c syscall.mak call_tab.v defn_tab.v
+
$(LOBJ): $(LSRC)
$(CC) $(CFLAGS) -c -DL_$* -o $@ $(LSRC)
@@ -43,3 +61,8 @@ $(DOBJ): $(DSRC)
$(EOBJ): $(ESRC)
$(CC) $(CFLAGS) -c -DL_$* -o $@ $(ESRC)
+$(LOBJ0): $(LSRC0)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(LSRC0)
+
+$(LOBJ3): $(LSRC3)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(LSRC3)
diff --git a/libc/syscall/dirent.c b/libc/syscall/dirent.c
index bbb3c13..8f7574c 100644
--- a/libc/syscall/dirent.c
+++ b/libc/syscall/dirent.c
@@ -60,6 +60,7 @@ DIR *dirp;
}
#endif
+#ifdef __AS386_16__
#ifdef L_readdir
/*
* This currently assumes we see a v. simple diectory structure, it's
@@ -82,3 +83,24 @@ DIR *dirp;
return dirp->dd_buf;
}
#endif
+#else
+
+/* This is for 386 linux */
+
+#ifdef L_readdir
+struct dirent *
+readdir(dirp)
+DIR *dirp;
+{
+ int cc;
+
+ cc = __readdir(dirp->dd_fd, dirp->dd_buf, 1);
+ if (cc <= 0)
+ return 0;
+ if (cc>1) dirp->dd_buf->d_name[cc] = 0;
+
+ return dirp->dd_buf;
+}
+#endif
+
+#endif
diff --git a/libc/syscall/mksys386 b/libc/syscall/mksys386
new file mode 100644
index 0000000..be7b2d5
--- /dev/null
+++ b/libc/syscall/mksys386
@@ -0,0 +1,154 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+#
+# This script generates the 'simple' system calls for the 386
+#
+# Each call is put into it's own object file, if the semantics of the
+# call are not correct UNIX then the 4th field in the dat file has a
+# marker and the function is generated with a __ prefix.
+#
+#
+# Different levels of squeeze
+# 0 = each is complete
+# 1 = Short codes calling common function
+
+rm -f syscall.c syscall.mak call_tab.v defn_tab.v
+
+tr '[A-Z]' '[a-z]' < sys386.dat | \
+awk 'BEGIN{
+ print "# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>" > "syscall.mak";
+ print "# This file is part of the Linux-8086 C library and is distributed" > "syscall.mak";
+ print "# under the GNU Library General Public License." > "syscall.mak";
+ print "# " > "syscall.mak";
+ print "# This file is automatically generated\n" > "syscall.mak"
+
+ print "/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>";
+ print " * This file is part of the Linux-8086 C library and is distributed";
+ print " * under the GNU Library General Public License.";
+ print " * ";
+ print " * This file is automatically generated */\n"
+ obj="OBJ=";
+
+ print "/* Standard start */\n\n"
+ printf("#ifndef __MSDOS__\n");
+ printf("#ifdef __AS386_32__\n");
+ printf("#asm\n");
+ printf(" .text\n");
+ printf(" .align 4\n");
+ printf("#endasm\n\n");
+
+ COMPACT=0;
+}
+/^[ ]*#/ { next; }
+/^[ ]*$/ { next; }
+{
+ if( $2 > max_call ) max_call = $2;
+
+ if( $3 == "x" || $3 == "" ) next;
+ else if( $4 == "-" ) next;
+ else if( $4 == "*" ) funcname="__" $1;
+ else funcname=$1;
+
+ shortname=substr(funcname,1,12);
+
+ if( length(obj) > 60 )
+ {
+ printf("%s\t\\\n", obj) > "syscall.mak";
+ obj=" ";
+ }
+ obj=obj shortname ".o ";
+
+ printf "/* CALL %s */\n\n", $0;
+
+ printf("#ifdef L_%s\n", shortname);
+ printf("#asm\n");
+ printf("export _%s\n", funcname);
+ printf("_%s:\n", funcname);
+
+ # Inline assembler max to 5 args (20 bytes)
+ if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 ))
+ {
+ if( $3 == 0 )
+ {
+ printf(" mov eax,#%d\n", $2);
+ }
+ else
+ {
+ printf("#if __FIRST_ARG_IN_AX__\n");
+ printf(" mov edx,#%d\n", $2);
+ printf("#else\n");
+ printf(" mov eax,#%d\n", $2);
+ printf("#endif\n");
+ }
+ printf(" br sys_call%d\n", $3);
+ }
+ else
+ {
+ if( $3 >= 1 ) printf("#if __FIRST_ARG_IN_AX__\n");
+ if( $3 >= 5 ) printf(" push edi\n");
+ if( $3 >= 4 ) printf(" push esi\n");
+ if( $3 >= 5 ) printf(" mov edi,[esp+16]\n");
+ if( $3 >= 4 ) printf(" mov esi,[esp+12]\n");
+ if( $3 >= 3 ) printf(" mov edx,[esp+8]\n");
+ if( $3 >= 2 ) printf(" mov ecx,[esp+4]\n");
+ if( $3 >= 1 ) printf(" mov ebx,eax\n");
+ if( $3 >= 1 ) printf("#else\n");
+ if( $3 >= 5 ) printf(" push edi\n");
+ if( $3 >= 4 ) printf(" push esi\n");
+ if( $3 >= 5 ) printf(" mov edi,[esp+20]\n");
+ if( $3 >= 4 ) printf(" mov esi,[esp+16]\n");
+ if( $3 >= 3 ) printf(" mov edx,[esp+12]\n");
+ if( $3 >= 2 ) printf(" mov ecx,[esp+8]\n");
+ if( $3 >= 1 ) printf(" mov ebx,[esp+4]\n");
+ if( $3 >= 1 ) printf("#endif\n");
+ printf(" mov eax,#%d\n", $2);
+ printf(" int $80\n");
+
+ if( $3 >= 4 ) printf(" pop esi\n");
+ if( $3 >= 5 ) printf(" pop edi\n");
+
+ printf(" test eax,eax\n");
+ printf(" jl syscall_err\n");
+ printf(" ret\n");
+ printf("syscall_err:\n");
+ printf(" neg eax\n");
+ printf(" mov [_errno],eax\n");
+ printf(" mov eax,#-1\n");
+ printf(" ret\n");
+ }
+ printf("#endasm\n");
+ printf("#endif\n\n");
+}
+END{
+
+ printf("#endif /* __AS386_32__ */\n\n");
+ printf("#endif /* __MSDOS__ */\n\n");
+ printf("%s\n", obj) > "syscall.mak";
+ printf "\n" > "syscall.mak";
+
+}' > syscall.c
+
+cat >> syscall.mak <<\!
+
+TOP=..
+include $(TOP)/Make.defs
+
+all: $(OBJ)
+
+libc.a: $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+$(OBJ): sys386.dat mksys386
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ syscall.c
+!
+
+rv=$?
+if [ "$rv" != 0 ]
+then exit $rv
+fi
+
+export MAKELEVEL
+MAKELEVEL=0
+exec make -f syscall.mak $1
diff --git a/libc/syscall/sys386.dat b/libc/syscall/sys386.dat
new file mode 100644
index 0000000..da9ad6c
--- /dev/null
+++ b/libc/syscall/sys386.dat
@@ -0,0 +1,155 @@
+
+#
+# Name No Args Flag, comment
+#
+# . = Ok, with comment
+# * = Needs libc code (Prefix __)
+# - = Obsolete/not required
+#
+# Name N C
+setup 0 X
+exit 1 1 *
+fork 2 0
+vfork 2 0 . Fake alias of fork
+read 3 3
+write 4 3
+open 5 3
+close 6 1
+waitpid 7 3
+creat 8 2
+link 9 2
+unlink 10 1
+execve 11 3
+chdir 12 1
+time 13 1
+dv32_mknod 14 3 * Has correct args for 32bit dev_t
+chmod 15 2
+chown 16 3
+break 17 X - This is done in a special function
+oldstat 18 X -
+lseek 19 3
+getpid 20 0
+mount 21 5
+umount 22 1
+setuid 23 1
+getuid 24 0
+stime 25 1
+ptrace 26 4
+alarm 27 1
+oldfstat 28 X -
+pause 29 0
+utime 30 2
+stty 31 X -
+gtty 32 X -
+access 33 2
+nice 34 1
+ftime 35 1
+sync 36 0
+kill 37 2
+rename 38 2
+mkdir 39 2
+rmdir 40 1
+dup 41 1
+pipe 42 1
+times 43 1
+prof 44 X -
+brk 45 1 - need to save brk_addr & -ve is valid return.
+setgid 46 1
+getgid 47 0
+signal 48 2
+geteuid 49 0
+getegid 50 0
+acct 51 1
+phys 52 X -
+lock 53 X -
+ioctl 54 3
+fcntl 55 3
+mpx 56 X -
+setpgid 57 2
+ulimit 58 2
+oldolduname 59 X -
+umask 60 1
+chroot 61 1
+dv32_ustat 62 2 * Has correct args for 32bit dev_t
+dup2 63 2
+getppid 64 0
+getpgrp 65 0
+setsid 66 0
+sigaction 67 3
+siggetmask 68 0
+sigsetmask 69 1
+setreuid 70 2
+setregid 71 2
+sigsuspend 72 1
+sigpending 73 1
+sethostname 74 2
+setrlimit 75 2
+getrlimit 76 2
+getrusage 77 2
+gettimeofday 78 2
+settimeofday 79 2
+getgroups 80 2
+setgroups 81 2
+select 82 1 * select's arg is &arg1
+symlink 83 2
+oldlstat 84 X -
+readlink 85 3
+uselib 86 1
+swapon 87 2
+reboot 88 3
+readdir 89 3 * Takes the fd not a ddptr
+mmap 90 1 * Is a pointer to a buffer with the 6 args.
+munmap 91 2
+truncate 92 2
+ftruncate 93 2
+fchmod 94 2
+fchown 95 2
+getpriority 96 2
+setpriority 97 3
+profil 98 X - glibc has userspace
+statfs 99 2
+fstatfs 100 2
+ioperm 101 3
+socketcall 102 2 * This is a lib internal for socket stuff
+klog 103 X
+setitimer 104 3
+getitimer 105 2
+dv32_stat 106 2 * Has correct args for 32 bit dev_t
+dv32_lstat 107 2 * Has correct args for 32 bit dev_t
+dv32_fstat 108 2 * Has correct args for 32 bit dev_t
+olduname 109 X -
+iopl 110 1
+vhangup 111 0
+idle 112 0 - System internal
+vm86 113 1
+wait4 114 4
+swapoff 115 1
+sysinfo 116 1
+ipc 117 5 * SYSV ipc entry point
+fsync 118 1
+sigreturn 119 1 * Signal internal
+clone 120 2
+setdomainname 121 2
+uname 122 1
+modify_ldt 123 X
+adjtimex 124 1
+mprotect 125 3
+sigprocmask 126 3
+create_module 127 X - Module handling, NO WAY!
+init_module 128 X
+delete_module 129 X
+get_kernel_syms 130 X
+quotactl 131 X
+getpgid 132 1
+fchdir 133 1
+bdflush 134 2
+sysfs 135 3
+personality 136 1 * Linux specific.
+afs_syscall 137 X
+setfsuid 138 1
+setfsgid 139 1
+_llseek 140 X
+getdents 141 3 * New style readdir ?
+_newselect 142 X
+flock 143 2
+syscall_flock 143 X
diff --git a/libc/syscall/syslib0.c b/libc/syscall/syslib0.c
new file mode 100644
index 0000000..98f59e6
--- /dev/null
+++ b/libc/syscall/syslib0.c
@@ -0,0 +1,264 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/times.h>
+
+/* MSDOS has it's own versions */
+#ifndef __MSDOS__
+#ifdef __AS386_16__
+
+/********************** Function __cstartup *******************************/
+
+#ifdef L___cstartup
+
+void (*__cleanup)() = 0;
+char ** environ;
+
+#asm
+ loc 2
+call_main:
+ .word _main ! Segment 2 is the trailing pointers, main and the
+ .word call_exit ! routine to call exit.
+#if __FIRST_ARG_IN_AX__
+ .data
+saved_arg1:
+ .word 0
+#endif
+#if __CALLER_SAVES__
+ .data
+loopy_safe:
+ .word 0
+#endif
+ .text
+
+export ___cstartup
+___cstartup: ! Crt0 startup
+ pop cx ! Argc
+ mov bx,sp ! Calculate ptrs to argv and envp
+ mov ax,cx
+ inc ax
+ shl ax,#1
+ add ax,bx
+
+export ___mkargv
+___mkargv: ! BCC tells the linker to init argc,argv with this.
+
+ push ax ! Push Envp
+ mov [_environ],ax ! And save
+ push bx ! Push argv
+#if __FIRST_ARG_IN_AX__
+ mov [saved_arg1],cx
+#else
+ push cx ! Push argc
+#endif
+
+ mov si,#auto_start ! Pointer to first autostart function
+auto_run:
+#if __FIRST_ARG_IN_AX__
+ mov ax,[saved_arg1]
+#endif
+#if __CALLER_SAVES__
+ mov [loopy_safe],si
+#endif
+ mov bx,[si]
+ test bx,bx
+ jz no_entry
+ call bx ! Call the function
+no_entry:
+#if __CALLER_SAVES__
+ mov si,[loopy_safe]
+#endif
+ inc si ! SI at next
+ inc si
+ jmp auto_run ! And round for the next.
+
+call_exit: ! Last item called by above.
+ pop bx ! Be tidy.
+#if !__FIRST_ARG_IN_AX__
+ push ax ! At the end the last called was main() push it`s
+#endif
+ call _exit ! return val and call exit();
+bad_exit:
+ jmp bad_exit ! Exit returned !!
+
+export _exit
+export __exit
+_exit: ! exit(rv) function
+#if __FIRST_ARG_IN_AX__
+ mov [saved_arg1],ax
+#else
+ mov bx,sp
+ push [bx+2] ! Copy the `rv` for the exit fuctions.
+#endif
+ mov bx,[___cleanup] ! Call exit, normally this is `__do_exit`
+ test bx,bx
+ je no_clean ! But it`s default is null
+ call bx
+no_clean:
+#if __FIRST_ARG_IN_AX__
+ mov ax,[saved_arg1]
+#else
+ inc sp
+ inc sp
+#endif
+__exit: ! _exit(rv)
+ br ___exit ! This is just an alias for __exit();
+
+#endasm
+
+#endif
+
+/********************** Function lseek ************************************/
+
+#ifdef L_lseek
+off_t lseek(fd, posn, where)
+int fd;
+off_t posn;
+int where;
+{
+ if( __lseek(fd, &posn, where) < 0 ) return -1;
+ else return posn;
+}
+#endif
+
+/********************** Function getpid ************************************/
+
+#ifdef L_getpid
+int getpid()
+{
+ int ppid;
+ return __getpid(&ppid);
+}
+#endif
+
+/********************** Function getppid ************************************/
+
+#ifdef L_getppid
+int getppid()
+{
+ int ppid;
+ __getpid(&ppid);
+ return ppid;
+}
+#endif
+
+/********************** Function getuid ************************************/
+
+#ifdef L_getuid
+int getuid()
+{
+ int euid;
+ return __getuid(&euid);
+}
+#endif
+
+/********************** Function geteuid ************************************/
+
+#ifdef L_geteuid
+int geteuid()
+{
+ int euid;
+ __getuid(&euid);
+ return euid;
+}
+#endif
+
+/********************** Function getgid ************************************/
+
+#ifdef L_getgid
+int getgid()
+{
+ int egid;
+ return __getgid(&egid);
+}
+#endif
+
+/********************** Function getegid ************************************/
+
+#ifdef L_getegid
+int getegid()
+{
+ int egid;
+ __getgid(&egid);
+ return egid;
+}
+#endif
+
+/********************** Function dup2 ************************************/
+
+#ifdef L_dup2
+
+#include <fcntl.h>
+
+int dup2(ifd, ofd)
+int ifd;
+{
+ return fcntl(ifd, F_DUPFD, ofd);
+}
+#endif
+
+/********************** Function dup ************************************/
+
+#ifdef L_dup
+#include <sys/param.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* This is horribly complicated, there _must_ be a better way! */
+
+int
+dup(fd)
+int fd;
+{
+ int nfd;
+ extern int errno;
+ int oerr = errno;
+
+ errno = 0;
+ for(nfd=0; nfd<NR_OPEN; nfd++)
+ {
+ if( fcntl(nfd, F_GETFD) < 0 )
+ break;
+ }
+ if( nfd == NR_OPEN ) { errno = EMFILE ; return -1; }
+ errno = oerr;
+ if( fcntl(fd, F_DUPFD, nfd) < 0 )
+ {
+ if( errno == EINVAL ) errno = EMFILE;
+ return -1;
+ }
+ return nfd;
+}
+#endif
+
+/********************** Function getpgrp ************************************/
+
+#ifdef L_getpgrp
+int
+getpgrp()
+{
+ return getpgid(0);
+}
+#endif
+
+/********************** Function times ************************************/
+
+#ifdef L_times
+clock_t times(buf)
+struct tms* buf;
+{
+ long rv;
+ __times(buf, &rv);
+ return rv;
+}
+#endif
+
+/********************** THE END ********************************************/
+
+#endif /* __AS386_16__ */
+#endif /* __MSDOS__ */
diff --git a/libc/syscall/syslib3.c b/libc/syscall/syslib3.c
new file mode 100644
index 0000000..c4df1fc
--- /dev/null
+++ b/libc/syscall/syslib3.c
@@ -0,0 +1,109 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/times.h>
+
+/* MSDOS has it's own versions */
+#ifndef __MSDOS__
+#ifdef __AS386_32__
+
+/********************** Function __cstartup *******************************/
+
+#ifdef L___cstart3
+
+void (*__cleanup)() = 0;
+char ** environ;
+
+#asm
+ loc 2
+call_main:
+ .long _main ! Segment 2 is the trailing pointers, main and the
+ .long call_exit ! routine to call exit.
+#if __FIRST_ARG_IN_AX__
+ .data
+saved_arg1:
+ .long 0
+#endif
+#if __CALLER_SAVES__
+ .data
+loopy_safe:
+ .long 0
+#endif
+ .text
+
+export ___mkargv
+___mkargv: ! BCC Tells linker to init argv ... none needed.
+
+export ___cstartup
+___cstartup: ! Crt0 startup (Linux style)
+ mov eax,[esp]
+ test eax,eax
+ jz call_exit ! If argc == 0 this is being called by ldd, exit.
+ mov eax,[esp+8]
+ mov [_environ],eax
+#if __FIRST_ARG_IN_AX__
+ pop [saved_arg1] ! Argc will go into eax
+#endif
+
+ mov esi,#auto_start ! Pointer to first autostart function
+auto_run:
+#if __FIRST_ARG_IN_AX__
+ mov eax,[saved_arg1]
+#endif
+#if __CALLER_SAVES__
+ mov [loopy_safe],esi
+#endif
+ mov ebx,[esi]
+ test ebx,ebx
+ jz no_func
+ call ebx ! Call the function
+no_func:
+#if __CALLER_SAVES__
+ mov esi,[loopy_safe]
+#endif
+ add esi,#4 ! SI at next
+ jmp auto_run ! And round for the next.
+
+call_exit: ! Last item called by above.
+ pop ebx ! Be tidy.
+#if !__FIRST_ARG_IN_AX__
+ push eax ! At the end the last called was main() push it`s
+#endif
+ call _exit ! return val and call exit();
+bad_exit:
+ jmp bad_exit ! Exit returned !!
+
+export _exit
+export __exit
+_exit: ! exit(rv) function
+#if __FIRST_ARG_IN_AX__
+ mov [saved_arg1],eax
+#else
+ push [esp+4] ! Copy the `rv` for the exit fuctions.
+#endif
+ mov ebx,[___cleanup] ! Call exit, normally this is `__do_exit`
+ test ebx,ebx
+ je no_clean ! But it`s default is null
+ call ebx
+no_clean:
+#if __FIRST_ARG_IN_AX__
+ mov eax,[saved_arg1]
+#else
+ add esp,#4
+#endif
+__exit: ! _exit(rv)
+ br ___exit ! This is just an alias for __exit();
+
+#endasm
+#endif
+
+/********************** Function ? ************************************/
+
+/*---*/
+#endif
+#endif
diff --git a/libc/syscall/syslibc.c b/libc/syscall/syslibc.c
index e6d58eb..68f5a0b 100644
--- a/libc/syscall/syslibc.c
+++ b/libc/syscall/syslibc.c
@@ -6,104 +6,9 @@
#include <sys/types.h>
#include <errno.h>
#include <time.h>
-#include <sys/times.h>
/* MSDOS has it's own versions */
#ifndef __MSDOS__
-#ifdef __AS386_16__
-
-/********************** Function __cstartup *******************************/
-
-#ifdef L___cstartup
-
-void (*__cleanup)() = 0;
-char ** environ;
-
-#asm
- loc 2
-call_main:
- .word _main ! Segment 2 is the trailing pointers, main and the
- .word call_exit ! routine to call exit.
-#if __FIRST_ARG_IN_AX__
- .data
-saved_arg1:
- .word 0
-#endif
-#if __CALLER_SAVES__
- .data
-loopy_safe:
- .word 0
-#endif
- .text
-
-export ___cstartup
-___cstartup: ! Crt0 startup
- pop cx ! Argc
- mov bx,sp ! Calculate ptrs to argv and envp
- mov ax,cx
- inc ax
- shl ax,#1
- add ax,bx
- push ax ! Push Envp
- mov [_environ],ax ! And save
- push bx ! Push argv
-#if __FIRST_ARG_IN_AX__
- mov [saved_arg1],cx
-#else
- push cx ! Push argc
-#endif
-
- mov si,#auto_start ! Pointer to first autostart function
-auto_run:
-#if __FIRST_ARG_IN_AX__
- mov ax,[saved_arg1]
-#endif
-#if __CALLER_SAVES__
- mov [loopy_safe],si
-#endif
- call [si] ! Call the function
-#if __CALLER_SAVES__
- mov si,[loopy_safe]
-#endif
- inc si ! SI at next
- inc si
- jmp auto_run ! And round for the next.
-
-call_exit: ! Last item called by above.
- pop bx ! Be tidy.
-#if !__FIRST_ARG_IN_AX__
- push ax ! At the end the last called was main() push it`s
-#endif
- call _exit ! return val and call exit();
-bad_exit:
- jmp bad_exit ! Exit returned !!
-
-export _exit
-export __exit
-_exit: ! exit(rv) function
-#if __FIRST_ARG_IN_AX__
- mov [saved_arg1],ax
-#else
- mov bx,sp
- push [bx+2] ! Copy the `rv` for the exit fuctions.
-#endif
- mov bx,[___cleanup] ! Call exit, normally this is `__do_exit`
- test bx,bx
- je no_clean ! But it`s default is null
- call bx
-no_clean:
-#if __FIRST_ARG_IN_AX__
- mov ax,[saved_arg1]
-#else
- inc sp
- inc sp
-#endif
-__exit: ! _exit(rv)
- br ___exit ! This is just an alias for __exit();
-
-#endasm
-
-#endif
/********************** Function time ************************************/
@@ -118,141 +23,6 @@ time_t *where;
}
#endif
-/********************** Function times ************************************/
-
-#ifdef L_times
-clock_t times(buf)
-struct tms* buf;
-{
- long rv;
- __times(buf, &rv);
- return rv;
-}
-#endif
-
-/********************** Function lseek ************************************/
-
-#ifdef L_lseek
-off_t lseek(fd, posn, where)
-int fd;
-off_t posn;
-int where;
-{
- if( __lseek(fd, &posn, where) < 0 ) return -1;
- else return posn;
-}
-#endif
-
-/********************** Function getpid ************************************/
-
-#ifdef L_getpid
-int getpid()
-{
- int ppid;
- return __getpid(&ppid);
-}
-#endif
-
-/********************** Function getppid ************************************/
-
-#ifdef L_getppid
-int getppid()
-{
- int ppid;
- __getpid(&ppid);
- return ppid;
-}
-#endif
-
-/********************** Function getuid ************************************/
-
-#ifdef L_getuid
-int getuid()
-{
- int euid;
- return __getuid(&euid);
-}
-#endif
-
-/********************** Function geteuid ************************************/
-
-#ifdef L_geteuid
-int geteuid()
-{
- int euid;
- __getuid(&euid);
- return euid;
-}
-#endif
-
-/********************** Function getgid ************************************/
-
-#ifdef L_getgid
-int getgid()
-{
- int egid;
- return __getgid(&egid);
-}
-#endif
-
-/********************** Function getegid ************************************/
-
-#ifdef L_getegid
-int getegid()
-{
- int egid;
- __getgid(&egid);
- return egid;
-}
-#endif
-
-/********************** Function dup2 ************************************/
-
-#ifdef L_dup2
-
-#include <fcntl.h>
-
-int dup2(ifd, ofd)
-int ifd;
-{
- return fcntl(ifd, F_DUPFD, ofd);
-}
-#endif
-
-/********************** Function dup ************************************/
-
-#ifdef L_dup
-#include <sys/param.h>
-#include <fcntl.h>
-#include <errno.h>
-
-/* This is horribly complicated, there _must_ be a better way! */
-
-int
-dup(fd)
-int fd;
-{
- int nfd;
- extern int errno;
- int oerr = errno;
-
- errno = 0;
- for(nfd=0; nfd<NR_OPEN; nfd++)
- {
- if( fcntl(nfd, F_GETFD) < 0 )
- break;
- }
- if( nfd == NR_OPEN ) { errno = EMFILE ; return -1; }
- errno = oerr;
- if( fcntl(fd, F_DUPFD, nfd) < 0 )
- {
- if( errno == EINVAL ) errno = EMFILE;
- return -1;
- }
- return nfd;
-}
-#endif
-
/********************** Function abort ************************************/
#ifdef L_abort
@@ -310,16 +80,6 @@ int sig;
}
#endif
-/********************** Function getpgrp ************************************/
-
-#ifdef L_getpgrp
-int
-getpgrp()
-{
- return getpgid(0);
-}
-#endif
-
/********************** Function setpgrp ************************************/
#ifdef L_setpgrp
@@ -392,5 +152,4 @@ unsigned long useconds;
/********************** THE END ********************************************/
-#endif /* __AS386_16__ */
#endif /* __MSDOS__ */
diff --git a/libc/termios/Makefile b/libc/termios/Makefile
index c978638..7903bc2 100644
--- a/libc/termios/Makefile
+++ b/libc/termios/Makefile
@@ -10,17 +10,17 @@ TOBJ=tcsetattr.o tcgetattr.o tcdrain.o tcflow.o tcflush.o tcsendbreak.o \
tcsetpgrp.o tcgetpgrp.o isatty.o \
cfgetospeed.o cfgetispeed.o cfsetospeed.o cfsetispeed.o cfmakeraw.o
+ifeq ($(LIB_OS),ELKS)
OBJ=$(TOBJ) ttyname.o
+else
+OBJ=
+endif
all: $(OBJ)
-ifeq ($(PLATFORM),i86-DOS)
-libc.a:
-else
libc.a: $(OBJ)
ar r ../$(LIBC) $(OBJ)
@touch libc.a
-endif
clean:
rm -f *.o libc.a
diff --git a/libc/tests/README b/libc/tests/README
index 642e636..4d308c7 100644
--- a/libc/tests/README
+++ b/libc/tests/README
@@ -16,4 +16,7 @@ size.c Size of executables and object files.
sync.c :-)
wc.c Word count.
+BTW: i386 OMAGIC files can be converted to deformed ELFs with this:
+ $ ld -N -Ttext 0 --defsym _start=0 sync -o sync1 -s
+
-Robert
diff --git a/libc/tests/env.c b/libc/tests/env.c
index baeb8e9..c904969 100644
--- a/libc/tests/env.c
+++ b/libc/tests/env.c
@@ -71,7 +71,6 @@ int global_var_that_needs_init = 0x201;
loc 1 ! Make sure the pointer is in the correct segment
auto_func: ! Label for bcc -M to work.
.word _init_vars ! Pointer to the autorun function
- .word no_op ! Space filler cause segs are padded to 4 bytes.
.text ! So the function after is also in the correct seg.
#endasm
diff --git a/libc/tests/ft.c b/libc/tests/ft.c
index 6456d0b..1bdc737 100644
--- a/libc/tests/ft.c
+++ b/libc/tests/ft.c
@@ -24,11 +24,6 @@
#include <pwd.h>
#include <grp.h>
-#ifdef __BCC__X
-#undef S_IFLNK
-#undef S_IFSOCK
-#endif
-
#ifdef S_IFSOCK
#include <sys/socket.h>
#endif
@@ -37,7 +32,7 @@
#endif
/* Ansi prototypes */
-#ifdef __STDC__
+#ifdef __STTDC__
#define PR(x) x
#else
#define PR(x) ()
@@ -66,12 +61,8 @@ int copy_file PR((char * source, char * dest));
void Usage PR((void));
int cmd_mkdir PR((char * dirname));
int cmd_mknod PR((void));
-int warn_func PR((int enumber, char * estr, char * eobj));
-int error_func PR((int enumber, char * estr, char * eobj));
-
-#define warning(x,y,z) ( Line_no = __LINE__, warn_func(x,y,z))
-#define error(x,y,z) ( Line_no = __LINE__, error_func(x,y,z))
-int Line_no = -1;
+int warning PR((int enumber, char * estr, char * eobj));
+int error PR((int enumber, char * estr, char * eobj));
#define DO_BDIR 0x0010 /* Do Dir before contents */
#define DO_ADIR 0x0020 /* Do Dir after contents */
@@ -109,7 +100,7 @@ struct {
{ "chgrp", CMD_CHGRP, 1, "vfR" },
{ "chmod", CMD_CHMOD, 1, "vfR" },
{ "chown", CMD_CHOWN, 1, "vfR" },
- { "cp", CMD_CP, -1, "vifRrpsd" },
+ { "cp", CMD_CP, -1, "vifRrpsda" },
{ "extar", CMD_EXTAR, 1, "" },
{ "install", CMD_INSTALL, -1, "cdso:g:m:" },
{ "ln", CMD_LN, -1, "vifs" },
@@ -215,6 +206,8 @@ int argc; char ** argv;
case 's': flg_symlink++;
if( cmd_tok == CMD_LN) cmd_tok |= OK_DIR+OK_NO_SOURCE;
break;
+ case 'a': flg_recurse++; flg_preserve++; flg_noderef++;
+ break;
}
if(*p == '-') break;
p++;
@@ -393,7 +386,7 @@ char * dname; char * fname;
buf = alloca(strlen(dname) + strlen(fname) + 4);
if( buf == 0 )
{
- error(errno, "Can't allocate memory for path beyond", dname);
+ error(errno, "Can't allocate memory for path beyond ", dname);
return ;
}
strcpy(buf, dname);
@@ -454,16 +447,15 @@ char * dname;
if( flg_recurse )
{
dfd = opendir(dname);
-
if( dfd == 0 && errno == EACCES && flg_force )
{
old_mode = (cur_file_stat.st_mode & 07777);
if( chmod(dname, (0700|old_mode)) )
- return error(errno, "Can't unlock", dname);
+ return error(errno, "", dname);
dfd = opendir(dname);
}
- if( dfd == 0 ) return error(errno, "Can't open", dname);
+ if( dfd == 0 ) return error(errno, "", dname);
while((ent=readdir(dfd)))
{
@@ -504,12 +496,12 @@ int when; char * fname;
case CMD_MV: rv = cmd_mv(fname); break;
case CMD_RM: rv = cmd_rm(fname); break;
- case CMD_EXTAR: error(ENOSYS, "", ""); exit(1);
+ case CMD_EXTAR: error(EINVAL, "", "No code."); exit(1);
case CMD_LN+OK_DIR+OK_NO_SOURCE:
case CMD_LN: rv = cmd_ln(fname); break;
- case CMD_INSTALL: error(EINVAL, "", "Bad program"); exit(1);
+ case CMD_INSTALL: error(EINVAL, "", ""); exit(1);
case CMD_MKDIR: rv = cmd_mkdir(fname); break;
case CMD_MKFIFO: rv = cmd_mkfifo(fname); break;
@@ -547,7 +539,7 @@ char * prefix; char * ustring;
{
if(!strisdigit(userstr) )
{
- error(EINVAL, "Unknown user", userstr);
+ error(EINVAL, "Unknown user ", userstr);
exit(1);
}
set_user = atoi(userstr);
@@ -568,7 +560,7 @@ char * prefix; char * ustring;
{
if(!strisdigit(groupstr) )
{
- error(EINVAL, "Unknown group", groupstr);
+ error(EINVAL, "Unknown group ", groupstr);
exit(1);
}
set_group = atoi(groupstr);
@@ -654,7 +646,7 @@ static mtab[] = {0, 0111, 0222, 0333, 0444, 0555, 0666, 0777 };
if(!done_change)
{
ch_error:
- error(EINVAL, "Invalid mode string", str);
+ error(EINVAL, "Invalid mode string ", str);
exit(1);
}
return mode;
@@ -760,7 +752,7 @@ char * fname;
if( set_mode >= 0 ) mode=set_mode;
rv = mknod(fname, S_IFIFO|mode, 0);
if(rv<0)
- warning(errno, "Cannot create fifo", fname);
+ warning(errno, "Cannot create fifo ", fname);
return rv;
}
@@ -783,10 +775,10 @@ char * fname;
if( fd>=0 ) rv = bind(fd, adr, len);
if( fd>=0 ) close(fd);
if(set_mode >= 0 && chmod(fname, set_mode&07777) < 0 )
- warning(errno, "Chmod", fname);
+ warning(errno, "Chmod ", fname);
if(rv<0)
- warning(errno, "Cannot create socket", fname);
+ warning(errno, "Cannot create socket ", fname);
return rv;
}
#endif
@@ -879,7 +871,7 @@ char * fname;
return error(errno, "", fname);
if( S_ISDIR(cur_file_stat.st_mode) )
- return error(EISDIR, "Can't rename across devices", fname);
+ return error(EISDIR, "Can't rename across devices ", fname);
if( copy_file(fname, destfile) != 0 ) return -1;
copy_modes(destfile);
@@ -934,7 +926,7 @@ char * fname;
if( dest_stat.st_ino == cur_file_stat.st_ino
&& dest_stat.st_dev == cur_file_stat.st_dev )
{
- warning(EPERM, "Can't copy file to itself", fname);
+ warning(EPERM, "Can't copy file to itself ", fname);
return -1;
}
}
@@ -946,12 +938,12 @@ char * fname;
{
if( S_ISDIR(dest_stat.st_mode) ) return 0;
if( unlink(destfile) < 0 )
- return error(errno, "Can't delete", destfile);
+ return error(errno, "Can't delete ", destfile);
}
return cmd_mkdir(destfile);
}
else if( S_ISDIR(dest_stat.st_mode) )
- return error(EPERM, "Can't copy non-directory to directory", destfile);
+ return error(EPERM, "Can't copy non-directory to directory ", destfile);
else if( S_ISREG(cur_file_stat.st_mode) )
{
/* Copy_ok - do we want to force a real file */;
@@ -960,7 +952,7 @@ char * fname;
}
else if( flg_recurse ) /* Don't copy other things while recursing */
{
- return error(EPERM, "Can't copy", fname);
+ return error(EPERM, "Can't copy ", fname);
}
if( copy_file(fname, destfile) != 0 ) return -1;
@@ -996,7 +988,7 @@ char * file;
if (chown (file, user, group)
&& (errno != EPERM || geteuid() == 0 || (flg_preserve==0 && flg_force==0)))
- error (errno, "Can't change perms for", file);
+ error (errno, "Can't change perms for ", file);
mode = cur_file_stat.st_mode;
if(set_mode>=0) mode=set_mode;
@@ -1046,7 +1038,7 @@ char * source; char * dest;
if(dfd<0)
{
close(sfd);
- return error(errno, "Cannot create", source);
+ return error(errno, "Cannot create ", source);
}
}
@@ -1164,13 +1156,13 @@ char * dirname;
if( set_user > 0 || set_group > 0 )
{
if( chown(dirname, set_user, set_group) < 0)
- warning(errno, "Cannot change directory owner", dirname);
+ warning(errno, "Cannot change directory owner ", dirname);
else if( chmod (dirname, mode & 07777) )
warning(errno, "", dirname);
}
}
- if(retv<0) error(errno, "Cannot create directory", dirname);
+ if(retv<0) error(errno, "Cannot create directory ", dirname);
return retv;
}
@@ -1199,19 +1191,19 @@ cmd_mknod()
}
int
-warn_func(enumber, estr, eobj)
+warning(enumber, estr, eobj)
int enumber; char * estr; char * eobj;
{
if(flg_verbose)
- return error_func(enumber, estr, eobj);
+ return error(enumber, estr, eobj);
return 0;
}
int
-error_func(enumber, estr, eobj)
+error(enumber, estr, eobj)
int enumber; char * estr; char * eobj;
{
- fprintf(stderr, "%s%s(%d): ", prog_name[0]=='-'?"ft":"", prog_name, Line_no);
- fprintf(stderr, "%s%s%s: %s\n", estr, (*estr?" ":""), eobj, strerror(enumber));
+ fprintf(stderr, "%s%s: ", prog_name[0]=='-'?"ft":"", prog_name);
+ fprintf(stderr, "%s%s: %s\n", estr, eobj, strerror(enumber));
return -1;
}
diff --git a/libc/tests/grab.c b/libc/tests/grab.c
index bd62a0f..b65fa28 100755..100644
--- a/libc/tests/grab.c
+++ b/libc/tests/grab.c
@@ -19,7 +19,7 @@ char ** argv;
struct s * ptr2;
struct s * ptr3;
int i,sz;
- long total = 0;
+ unsigned long total = 0;
for(i=0, sz=256 ; i<32; i++, sz = ((sz << 1) | (sz & V)) & M)
{
@@ -39,7 +39,7 @@ char ** argv;
ptr3->n = 0;
}
}
- for(sz>>=1; sz>255; )
+ for(sz>>=1; sz>3; )
{
ptr2 = (struct s *) malloc(sz-sizeof(int));
if(ptr2==0) { sz >>=1; continue; }
@@ -77,4 +77,5 @@ char ** argv;
printf("%2d(%8u)..%08lx..%ld\n",i++,sz,(long)ptr2,(long)ptr2);
}
while(ptr2 && i < 100);
+ exit(0);
}
diff --git a/libc/tests/ls.c b/libc/tests/ls.c
index 8cae4d0..8cae4d0 100755..100644
--- a/libc/tests/ls.c
+++ b/libc/tests/ls.c
diff --git a/libc/time/README b/libc/time/README
index 0d50401..da4f4e6 100644
--- a/libc/time/README
+++ b/libc/time/README
@@ -2,6 +2,7 @@ Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
This file is part of the Linux-8086 C library and is distributed
under the GNU Library General Public License.
-There's currently nothing special about time.
+There are two ways of converting the time_t to a struct tm, I'm not
+quite sure which is better.
-Robert
diff --git a/libc/time/asc_conv.c b/libc/time/asc_conv.c
index 0ba48f1..78cbcdd 100644
--- a/libc/time/asc_conv.c
+++ b/libc/time/asc_conv.c
@@ -5,7 +5,9 @@
* Internal ascii conversion routine, avoid use of printf, it's a bit big!
*/
-static hit(buf, val)
+
+static void
+hit(buf, val)
char * buf;
int val;
{
@@ -14,20 +16,21 @@ int val;
void
__asctime(buffer, ptm)
-char * buffer;
+register char * buffer;
struct tm * ptm;
{
-static days[] = "SunMonTueWedThuFriSat";
-static mons[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+static char days[] = "SunMonTueWedThuFriSat";
+static char mons[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
int year;
/* 012345678901234567890123456 */
strcpy(buffer, "Err Err .. ..:..:.. ....\n");
- if( ptm->tm_wday >= 0 && ptm->tm_wday <= 6 )
- memcpy(buffer, days+3*ptm->tm_wday, 3);
+ if( (ptm->tm_wday >= 0) && (ptm->tm_wday <= 6) )
+ memcpy(buffer, days+3*(ptm->tm_wday), 3);
+
+ if( (ptm->tm_mon >= 0) && (ptm->tm_mon <= 11) )
+ memcpy(buffer+4, mons+3*(ptm->tm_mon), 3);
- if( ptm->tm_mon >= 1 && ptm->tm_mon <= 12 )
- memcpy(buffer+4, mons+3*ptm->tm_mon-3, 3);
hit(buffer+ 8, ptm->tm_mday/10);
hit(buffer+ 9, ptm->tm_mday );
diff --git a/libc/time/asctime.c b/libc/time/asctime.c
index b66cd37..ea13bf8 100644
--- a/libc/time/asctime.c
+++ b/libc/time/asctime.c
@@ -5,7 +5,7 @@ extern void __asctime();
char *
asctime(timeptr)
-struct tm * timeptr;
+__const struct tm * timeptr;
{
static char timebuf[26];
diff --git a/libc/time/ctime.c b/libc/time/ctime.c
index bc7283d..2f42cd3 100644
--- a/libc/time/ctime.c
+++ b/libc/time/ctime.c
@@ -2,25 +2,25 @@
#include <time.h>
extern void __tm_conv();
-extern void __asc_conv();
+extern void __asctime();
char *
ctime(timep)
-time_t * timep;
+__const time_t * timep;
{
-static char cbuf[26];
- struct tm tmb;
- struct timezone tz;
- time_t offt;
-
- gettimeofday((void*)0, &tz);
-
- offt = -tz.tz_minuteswest*60L;
-
- /* tmb.tm_isdst = ? */
- __tm_conv(&tmb, &timep, offt);
-
- __asc_conv(cbuf, &tmb);
-
- return cbuf;
+ static char cbuf[26];
+ struct tm tmb;
+ struct timezone tz;
+ time_t offt;
+
+ gettimeofday((void*)0, &tz);
+
+ offt = -tz.tz_minuteswest*60L;
+
+ /* tmb.tm_isdst = ? */
+ __tm_conv(&tmb, timep, offt);
+
+ __asctime(cbuf, &tmb);
+
+ return cbuf;
}
diff --git a/libc/time/gmtime.c b/libc/time/gmtime.c
index 29907d0..aa0a246 100644
--- a/libc/time/gmtime.c
+++ b/libc/time/gmtime.c
@@ -5,11 +5,11 @@ extern void __tm_conv();
struct tm *
gmtime(timep)
-time_t * timep;
+__const time_t * timep;
{
static struct tm tmb;
- __tm_conv(&tmb, &timep, 0L);
+ __tm_conv(&tmb, timep, 0L);
return &tmb;
}
diff --git a/libc/time/localtime.c b/libc/time/localtime.c
index b0b729c..9d9b46d 100644
--- a/libc/time/localtime.c
+++ b/libc/time/localtime.c
@@ -5,7 +5,7 @@ extern void __tm_conv();
struct tm *
localtime(timep)
-time_t * timep;
+__const time_t * timep;
{
static struct tm tmb;
struct timezone tz;
@@ -16,7 +16,7 @@ time_t * timep;
offt = -tz.tz_minuteswest*60L;
/* tmb.tm_isdst = ? */
- __tm_conv(&tmb, &timep, offt);
+ __tm_conv(&tmb, timep, offt);
return &tmb;
}
diff --git a/libc/time/tm_conv.c b/libc/time/tm_conv.c
index 96f4735..ffd524c 100644
--- a/libc/time/tm_conv.c
+++ b/libc/time/tm_conv.c
@@ -1,4 +1,5 @@
+#if 0
#include <time.h>
/* This is a translation from ALGOL in Collected Algorithms of CACM. */
@@ -62,3 +63,76 @@ static int moffset[] =
if (m > 1 && ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0)))
tmbuf->tm_yday++;
}
+
+#else
+
+/* This is adapted from glibc */
+/* Copyright (C) 1991, 1993 Free Software Foundation, Inc */
+
+#define SECS_PER_HOUR 3600L
+#define SECS_PER_DAY 86400L
+
+#include <time.h>
+
+static const unsigned short int __mon_lengths[2][12] =
+ {
+ /* Normal years. */
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ /* Leap years. */
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+ };
+
+
+void
+__tm_conv(tmbuf, t, offset)
+struct tm *tmbuf;
+time_t *t;
+time_t offset;
+{
+ long days, rem;
+ register int y;
+ register unsigned short int *ip;
+
+ days = *t / SECS_PER_DAY;
+ rem = *t % SECS_PER_DAY;
+ rem += offset;
+ while (rem < 0)
+ {
+ rem += SECS_PER_DAY;
+ --days;
+ }
+ while (rem >= SECS_PER_DAY)
+ {
+ rem -= SECS_PER_DAY;
+ ++days;
+ }
+ tmbuf->tm_hour = rem / SECS_PER_HOUR;
+ rem %= SECS_PER_HOUR;
+ tmbuf->tm_min = rem / 60;
+ tmbuf->tm_sec = rem % 60;
+ /* January 1, 1970 was a Thursday. */
+ tmbuf->tm_wday = (4 + days) % 7;
+ if (tmbuf->tm_wday < 0)
+ tmbuf->tm_wday += 7;
+ y = 1970;
+ while (days >= (rem = __isleap(y) ? 366 : 365))
+ {
+ ++y;
+ days -= rem;
+ }
+ while (days < 0)
+ {
+ --y;
+ days += __isleap(y) ? 366 : 365;
+ }
+ tmbuf->tm_year = y - 1900;
+ tmbuf->tm_yday = days;
+ ip = __mon_lengths[__isleap(y)];
+ for (y = 0; days >= ip[y]; ++y)
+ days -= ip[y];
+ tmbuf->tm_mon = y;
+ tmbuf->tm_mday = days + 1;
+ tmbuf->tm_isdst = -1;
+}
+
+#endif
diff --git a/libc/utmp/Makefile b/libc/utmp/Makefile
index cbb16a8..2c88bd2 100644
--- a/libc/utmp/Makefile
+++ b/libc/utmp/Makefile
@@ -5,7 +5,9 @@
TOP=..
include $(TOP)/Make.defs
+ifeq ($(LIB_OS),ELKS)
OBJ=utent.o
+endif
all: $(OBJ)