summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes36
-rw-r--r--Libc_version2
-rw-r--r--Makefile34
-rw-r--r--README21
-rw-r--r--as/Makefile3
-rw-r--r--as/as86_encap.sh4
-rw-r--r--as/as86_to_data1
-rw-r--r--as/pops.c4
-rw-r--r--as/typeconv.c4
-rw-r--r--bcc/Makefile7
-rw-r--r--bcc/bcc.c16
-rw-r--r--bootblocks/Makefile41
-rw-r--r--bootblocks/bzimage.c2
-rw-r--r--bootblocks/dosfs.c6
-rw-r--r--bootblocks/elf_info.c189
-rw-r--r--bootblocks/elf_info.h282
-rw-r--r--bootblocks/i86_funcs.h21
-rw-r--r--bootblocks/li86.s46
-rw-r--r--bootblocks/makeboot.c43
-rw-r--r--bootblocks/minix.c349
-rw-r--r--bootblocks/minix.h103
-rw-r--r--bootblocks/monitor.c11
-rw-r--r--bootblocks/noboot.s32
-rw-r--r--bootblocks/readfs.h17
-rw-r--r--bootblocks/standalone.c309
-rw-r--r--bootblocks/sysboot.s29
-rw-r--r--bootblocks/tarboot.s12
-rw-r--r--copt/Makefile4
-rw-r--r--dis88/Makefile5
-rw-r--r--elksemu/Makefile2
-rw-r--r--elksemu/elks.h1
-rw-r--r--elksemu/minix.c6
-rw-r--r--ifdef.c9
-rw-r--r--ld/Makefile6
-rw-r--r--ld/io.c7
-rw-r--r--ld/objchop.c87
-rw-r--r--ld/typeconv.c4
-rw-r--r--ld/x86_aout.h2
-rw-r--r--libc/Config.dflt17
-rw-r--r--libc/Config_sh14
-rw-r--r--libc/Makefile5
-rw-r--r--libc/gtermcap/Config1
-rw-r--r--libc/misc/cputype.c18
-rw-r--r--libc/stdio1/BUGS15
-rw-r--r--libc/stdio1/Config3
-rw-r--r--libc/stdio1/NOTICE17
-rw-r--r--libc/stdio1/README8
-rw-r--r--libc/stdio1/TODO33
-rw-r--r--libc/stdio1/__ffillbuf.c55
-rw-r--r--libc/stdio1/__stdio_init.c66
-rw-r--r--libc/stdio1/fclose.c41
-rw-r--r--libc/stdio1/fcntl.h72
-rw-r--r--libc/stdio1/fflush.c36
-rw-r--r--libc/stdio1/fgetc.c39
-rw-r--r--libc/stdio1/fgets.c50
-rw-r--r--libc/stdio1/fopen.c80
-rw-r--r--libc/stdio1/fputc.c53
-rw-r--r--libc/stdio1/fputs.c32
-rw-r--r--libc/stdio1/idealgetline.c67
-rw-r--r--libc/stdio1/makefile36
-rw-r--r--libc/stdio1/old_printf.c230
-rw-r--r--libc/stdio1/printf.c649
-rw-r--r--libc/stdio1/puts.c26
-rw-r--r--libc/stdio1/scanf.c151
-rw-r--r--libc/stdio1/stdio.h135
-rwxr-xr-xlibc/stdio1/test.sh12
-rw-r--r--libc/syscall/syscall.dat.chad55
-rw-r--r--libc/syscall/syscall.dat.code70
-rw-r--r--libc/syscall/syscall.dat.rdb142
-rw-r--r--makefile.in57
-rw-r--r--tests/README3
-rw-r--r--tests/hd.c81
72 files changed, 3501 insertions, 625 deletions
diff --git a/Changes b/Changes
index 59f13ca..6a195a9 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,39 @@
+For version 0.13.0.
+
+> Added '-g' to gcc options, make sure install has '-s' to strip symbols.
+
+> Grrrr, missing files in bootblocks directory, I didn't have them all.
+ OK, as part of the dist script I'll have to do a 'make other' ...
+ Some other bits there too ...
+
+> Minor alteration to opening files in ld to fix problem when share.exe
+ loaded under dos.
+
+> Added Config.dflt for default libc configuration flags. I can now
+ re-introduce Joel's standard I/O functions ... but they haven't
+ been updated in a while ...
+
+> Addition to minix.c to use allow BB to determine the track size by
+ trial and error (not intuit from superblock) to allow mis-sized
+ filesystems on a floppy. Also add some error retries to the floppy
+ version.
+
+> Can now do 'use16 8086' in assembler instead of 'use16 86' also
+ 'use16 80386'
+
+> Add 'make install-ln', this installs _symbolic_links_ to the dev
+ directory in the normal directories. This means you don't have
+ to do a make install after re-compiling. But it also means the
+ 'install' is dependent on the dev dirs.
+
+> Add ability to use overrides on the comand line of the initial make,
+ and have them saved, for CC, CFLAGS, LDFLAGS, PREFIX, BINDIR and LIBDIR.
+ Includes minor alteration to bcc.c and as86_encap.
+
+> Added in 'objchop' as an option in the ld directory.
+
+> Removed too eager 'typeconv.c' warning.
+
For version 0.12.0.
> Notice the change in the version numbers, as long as I'm releasing the
diff --git a/Libc_version b/Libc_version
index ac454c6..e01e0dd 100644
--- a/Libc_version
+++ b/Libc_version
@@ -1 +1 @@
-0.12.0
+0.12.4
diff --git a/Makefile b/Makefile
index c04c366..fdeaa2c 100644
--- a/Makefile
+++ b/Makefile
@@ -2,9 +2,15 @@
# This file is part of the Linux-8086 Development environment and is
# distributed under the GNU General Public License.
-TARGETS=bcc unproto copt as86 ld86 \
+TARGETS=clean bcc unproto copt as86 ld86 \
install install-all install-lib install-lib2 install-other \
- clean tests alt-libs library config other
+ install-ln install-man \
+ tests alt-libs library config other
+
+PREFIX= /usr/bcc
+BINDIR= /usr/bin
+LIBDIR= $(PREFIX)/lib/bcc
+CFLAGS= -O
# Some makes take the last of a list as the default ...
all: make.fil
@@ -17,15 +23,23 @@ $(TARGETS): phony
phony:
realclean:
- [ ! -f make.fil ] || $(MAKE) -f make.fil TOPDIR=`pwd` $@
- rm -f make.fil ifdef ifdef.o
+ -[ ! -f make.fil ] || $(MAKE) -f make.fil TOPDIR=`pwd` $@
+ -rm -f make.fil ifdef ifdef.o
make.fil: ifdef makefile.in
./ifdef -MU makefile.in >tmp.mak
- mv -f tmp.mak make.fil
+ sed -e "s:%PREFIX%:$(PREFIX):" \
+ -e "s:%BINDIR%:$(BINDIR):" \
+ -e "s:%LIBDIR%:$(LIBDIR):" \
+ -e "s:%CC%:$(CC):" \
+ -e "s:%CFLAGS%:$(CFLAGS):" \
+ -e "s:%LDFLAGS%:$(LDFLAGS):" \
+ < tmp.mak > make.tmp
+ mv -f make.tmp make.fil
+ @rm -f tmp.mak
ifdef: ifdef.o
- $(CC) -o ifdef ifdef.o
+ $(CC) $(LDFLAGS) -o ifdef ifdef.o
ifdef.o: ifdef.c
$(CC) $(CFLAGS) $(IFDEFFLAGS) -c ifdef.c
@@ -34,14 +48,13 @@ Uninstall: phony
@echo 'Are you really sure... have you checked this... ^C to interrupt'
@read line
rm -rf /usr/bcc
- rm -f /usr/bin/bcc /usr/bin/as86_encap /usr/bin/dis88
- rm -f /usr/bin/as86 /usr/bin/ld86
+ rm -f $(BINDIR)/bcc $(BINDIR)/as86_encap $(BINDIR)/dis86
+ rm -f $(BINDIR)/as86 $(BINDIR)/ld86
rm -f /lib/elksemu
rm -f /usr/lib/liberror.txt
rm -f /usr/man/man1/elks.1* /usr/man/man1/elksemu.1*
- rm -f /usr/man/man1/dis88.1* /usr/man/man1/bcc.1*
+ rm -f /usr/man/man1/dis86.1* /usr/man/man1/bcc.1*
rm -f /usr/man/man1/as86.1* /usr/man/man1/ld86.1*
- rm -f /usr/man/man1/dis88.1*
distribution:
@rm -f /tmp/linux-86 || true
@@ -62,6 +75,7 @@ distribution:
rm libc-$$VER ;\
$(MAKE) -C /tmp/linux-86 install \
ARFLAGS=q DIST=/tmp/linux-86-dist || exit 1 ;\
+ $(MAKE) -C /tmp/linux-86 other ;\
tar cf /tmp/Dist/Dev86bin-$$VER.tar -C /tmp/linux-86-dist . ;\
rm -f /tmp/Dist/Dev86clb-$$VER.zip Bcc ;\
ln -s /tmp/linux-86 Bcc ;\
diff --git a/README b/README
index acc38b4..a639b4b 100644
--- a/README
+++ b/README
@@ -1,11 +1,6 @@
This is a development environment for ELKS-86 and standalone 8086 code.
-The only hand configuration is to choose one of libc/syscall/syscall.dat.*
-to be used as libc/syscall/syscall.dat The '*.chad' one matches the *.50
-elks kernel but you're best to pickup the one in the kernel you're compiling
-for.
-
-All you then need to do then is 'make' from the top directory and the main
+All you need to do is 'make' from the top directory and the main
parts of the package will be made. These can be tested by use the 'ncc'
program from the newly created bin subdirectory.
@@ -15,12 +10,17 @@ Use 'make Uninstall' to remove everything (Beware with this though!)
Some other bits can be built by 'make other' and installed with
'make install-other'.
+If you don't want it to install some bits in /usr/bin you can override
+the bindir on the first make ie: 'make BINDIR=/usr/local/bin' this
+is remembered until 'make.fil' is rebuilt.
+
The manual pages in the man subdirectory are a start as some pages matched
to these programs, there are also some hints for using as86 well.
The tests and bootblocks directories give some example code.
The bcc command defaults to using /usr/bcc/include and /usr/bcc/lib the
libraries _and_ include files are copied to these locations by install.
+This can be changed by overriding 'PREFIX=...' on the initial make.
All the versions of the library are built by make; 'normal', 'fast', 'MSDOS',
'standalone' and Linux-i386.
@@ -43,7 +43,8 @@ $ make install-all
The as86 and ld86 with this are _different_ from the ones needed for the
linux-i386 kernel but can replace them, the kernel-i386 ones _will_ _not_
-work correctly here!
+work correctly here! BUT when this as86 is used for the kernel it will
+complain about every i386 instruction encountered; don't worry, its ok.
I _strongly_ suggest you install the kernel patch or load the module in
the elksemu directory in your Linux-i386 kernel, it makes things _much_
@@ -55,9 +56,9 @@ This software is for the most part under GPL style copyright, the libc and
libbsd are covered by the 'weaker' library versions of this document.
(See the COPYING files in this and the libc directories for details)
-The copyrights of other parts are documented in the relevent files. Some
-parts are explicitly PD others like the unproto code have copyrights that
-allow free distribution but are otherwise more vague.
+The copyrights of other parts are documented in the relevent files.
+Some parts are explicitly PD others like the unproto and dis88 code have
+copyrights that allow free distribution but are otherwise more vague.
--
Rob. (Robert de Bath <robert@mayday.cix.co.uk>)
diff --git a/as/Makefile b/as/Makefile
index 04a0d98..647d977 100644
--- a/as/Makefile
+++ b/as/Makefile
@@ -15,7 +15,8 @@ as86: $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o as86
as86_encap: as86_encap.sh
- sed "s:%%LIBDIR%%:$(LIBDIR):" < as86_encap.sh > tmp
+ sed -e "s:%%LIBDIR%%:$(LIBDIR):" -e "s:%%BINDIR%%:$(BINDIR):" \
+ < as86_encap.sh > tmp
@mv -f tmp as86_encap
chmod +x as86_encap
diff --git a/as/as86_encap.sh b/as/as86_encap.sh
index 5dea514..e5cf9e7 100644
--- a/as/as86_encap.sh
+++ b/as/as86_encap.sh
@@ -19,9 +19,11 @@
trap "rm -f _$$.* ; exit 99" 1 2 3 15
LIBDIR='%%LIBDIR%%' # Set by make install
+BINDIR='%%BINDIR%%' # Set by make install
# If the one set by install fails then try a couple of others.
[ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`"
+[ -x "$LIBDIR/as86" ] || LIBDIR="$BINDIR"
[ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`/../lib"
[ -x "$LIBDIR/as86" ] || LIBDIR=/usr/bin
@@ -81,7 +83,7 @@ $LIBDIR/as86 "$@" "$IFILE" -b _$$.bin -s _$$.sym || RV=$?
if(NF == 0) next;
printf " ";
for(i=2;i<=NF;i++) {
- if( $i >= 32 && $i <= 127 && $i != 39 && $i != 92 )
+ if( $i >= 32 && $i < 127 && $i != 39 && $i != 92 )
printf("\047%c\047,", $i);
else
printf("%3d,", $i);
diff --git a/as/as86_to_data b/as/as86_to_data
index ded1f0e..d53e500 100644
--- a/as/as86_to_data
+++ b/as/as86_to_data
@@ -22,6 +22,7 @@
trap "rm -f _$$.* ; exit 99" 1 2 3 15
LIBDIR='%%LIBDIR%%' # Set by make install
+[ -d "$LIBDIR" ] || LIBDIR='%%BINDIR%%'
[ -d "$LIBDIR" ] || LIBDIR=/usr/bin
IFILE="$1"
diff --git a/as/pops.c b/as/pops.c
index a2670c8..e239892 100644
--- a/as/pops.c
+++ b/as/pops.c
@@ -1006,7 +1006,9 @@ PUBLIC void puse16()
absexpres();
if (lastexp.data & UNDBIT)
return;
- if( lastexp.offset > 15 )
+ if( lastexp.offset > 8000 )
+ setcpu((int) lastexp.offset / 100 % 10);
+ else if( lastexp.offset > 15 )
setcpu((int) lastexp.offset / 100);
else
setcpu((int) lastexp.offset);
diff --git a/as/typeconv.c b/as/typeconv.c
index 6cc4a20..708d92b 100644
--- a/as/typeconv.c
+++ b/as/typeconv.c
@@ -156,6 +156,8 @@ unsigned count;
{
switch (count)
{
+ case 0:
+ return 0;
case 1:
return buf[0] & 0xFF;
case 2:
@@ -174,6 +176,8 @@ unsigned count;
{
switch (count)
{
+ case 0:
+ return 0;
case 1:
return buf[0] & 0xFF;
case 2:
diff --git a/bcc/Makefile b/bcc/Makefile
index 8812c38..2bffe68 100644
--- a/bcc/Makefile
+++ b/bcc/Makefile
@@ -9,7 +9,7 @@ CFLAGS =-O
LDFLAGS =-s
BINDIR =/usr/bin
LIBDIR =/usr/lib/bcc
-BCCDEFS =-DLOCALPREFIX=$(PREFIX) -DDEFARCH=0
+BCCDEFS =-DLOCALPREFIX=$(PREFIX) -DBINDIR=$(BINDIR) -DDEFARCH=0
OBJS = bcc-cc1.o codefrag.o debug.o declare.o express.o exptree.o floatop.o \
function.o gencode.o genloads.o glogcode.o hardop.o input.o label.o \
@@ -37,7 +37,7 @@ ccc: bcc.c
$(CC) $(ANSI) $(CFLAGS) -DCCC $(BCCDEFS) $(LDFLAGS) bcc.c -o $@
bcc-cc1: $(OBJS)
- $(CC) $(LDFLAGS) $(OBJS) -o bcc-cc1
+ $(CC) $(BCCARCH) $(LDFLAGS) $(OBJS) -o bcc-cc1
clean realclean:
rm -f bcc bcc-cc1 ncc bcc09 ccc bcc.o $(OBJS)
@@ -48,3 +48,6 @@ $(OBJS): bcc.h align.h const.h types.h \
input.h label.h os.h output.h \
parse.h proto.h reg.h sc.h scan.h \
sizes.h table.h type.h
+
+.c.o:
+ $(CC) $(BCCARCH) $(CFLAGS) -c $<
diff --git a/bcc/bcc.c b/bcc/bcc.c
index 4dc16b1..146312a 100644
--- a/bcc/bcc.c
+++ b/bcc/bcc.c
@@ -22,7 +22,7 @@
#define PUBLIC
#define TRUE 1
-#ifdef __STDC__
+#if __STDC__ == 1
#define P(x) x
#define HASHIT(x) #x
#define QUOT(x) HASHIT(x)
@@ -45,7 +45,7 @@
#define EXESUF
#endif
-#if defined(__minix) || defined(_AIX)
+#if defined(__minix) || defined(_AIX) || defined(__BCC__)
#define realpath(x,y) 0
#endif
@@ -76,7 +76,11 @@
#define STANDARD_CRT0_0_PREFIX "~/lib/bcc/i86/"
#define STANDARD_CRT0_3_PREFIX "~/lib/bcc/i386/"
#define STANDARD_EXEC_PREFIX "~/lib/bcc/"
+#ifdef BINDIR
+#define STANDARD_EXEC_PREFIX_2 QUOT(BINDIR) "/"
+#else
#define STANDARD_EXEC_PREFIX_2 "/usr/bin/"
+#endif
#define DEFAULT_INCLUDE "-I~/include"
#define DEFAULT_LIBDIR0 "-L~/lib/bcc/i86/"
#define DEFAULT_LIBDIR3 "-L~/lib/bcc/i386/"
@@ -1094,9 +1098,15 @@ int mode;
}
ppath = expand_tilde(stralloc2(prefix->name, path), 1);
if (verbosity > 2)
- writesn(ppath);
+ writes(ppath);
if (access(ppath, mode) == 0)
+ {
+ if (verbosity > 2)
+ writesn(" - found.");
return ppath;
+ }
+ if (verbosity > 2)
+ writesn(" - nope.");
free(ppath);
}
return path;
diff --git a/bootblocks/Makefile b/bootblocks/Makefile
index 707179f..7569500 100644
--- a/bootblocks/Makefile
+++ b/bootblocks/Makefile
@@ -7,26 +7,34 @@ CC=$(BCC)
CFLAGS=-ansi -Ms -H0x10000 -s
ASFLAGS=-0
# LST=-l $*.lst
+# CLST=-A-l -A$*.lst
default: makeboot makeboot.com monitor.out
all: default tgz bin
CSRC=minix.c
-SSRC=tarboot.s skip.s com_bcc.s tich.s sysboot.s bootlist.s mbr.s msdos.s
+SSRC=sysboot.s \
+ tarboot.s skip.s com_bcc.s tich.s \
+ bootlist.s mbr.s msdos.s noboot.s
encap: $(SSRC:s=v) $(CSRC:c=v) minixhd.v
bin: $(SSRC:s=bin) $(CSRC:c=bin) minixhd.bin
MOBJ=monitor.o i86_funcs.o relocate.o help.o bzimage.o dosfs.o nofs.o
MSRC=monitor.c i86_funcs.c relocate.c help.c bzimage.c dosfs.c nofs.c
+MINC=i86_funcs.h readfs.h
+
+EXTRAS=minix.h elf_info.c elf_info.h standalone.c li86.s
install:
monitor.out: $(MOBJ)
$(CC) $(CFLAGS) $(MOBJ) -o monitor.out
-monitor: $(MSRC)
+$(MOBJ): $(MINC) version.h
+
+monitor: $(MSRC) $(MINC)
@rm -f $(MOBJ)
make 'CFLAGS=-ansi' monitor.out
mv monitor.out monitor
@@ -38,35 +46,42 @@ minix.s: minix.c
minixhd.s: minix.c
$(BCC) -Mc -DHARDDISK -S minix.c -o minixhd.s
-makeboot: makeboot.c sysboot.v skip.v msdos.v tarboot.v
+makeboot: makeboot.c sysboot.v noboot.v skip.v msdos.v tarboot.v
$(HOSTCC) $(HOSTCCFLAGS) -o makeboot makeboot.c
-makeboot.com: makeboot.c sysboot.v skip.v msdos.v tarboot.v
+makeboot.com: makeboot.c sysboot.v noboot.v skip.v msdos.v tarboot.v
$(BCC) -Md -o makeboot.com makeboot.c
+version.h:
+ head -1 ../Libc_version | \
+ sed 's/\(.*\)/#define VERSION "\1"/' > version.h
+
clean realclean:
rm -f monitor makeboot bootblocks.tar.gz
- rm -f minix.s *.com *.o *.bin *.out *.lst *.sym *.v
+ rm -f minix.s minixhd.s version.h
+ rm -f *.com *.o *.bin *.out *.lst *.sym *.v *.tmp
tgz: minix.bin monitor.out makeboot.com makeboot
tar cfV bootblocks.tar ENIAC monitor.out \
README Makefile \
- $(MSRC) makeboot.c \
- $(CSRC) $(SSRC) \
- makeboot.com minix.bin
+ $(MSRC) \
+ $(MINC) \
+ makeboot.c $(CSRC) \
+ $(SSRC) \
+ makeboot.com minix.bin \
+ $(EXTRAS)
makeboot tar bootblocks.tar
gzip -f9 bootblocks.tar
distribution:
- tar czf /tmp/bootblocks.tar.gz README Makefile \
- $(MSRC) makeboot.c \
- $(CSRC) $(SSRC)
+ tar czf /tmp/bootblocks.tar.gz \
+ README Makefile $(MSRC) $(MINC) makeboot.c $(CSRC) $(SSRC) $(EXTRAS)
.SUFFIXES: .bin .v
.s.bin:
- $(BCC) -c $*.s -A-u- -A-b -A/tmp/$*.bin -A-s -A$*.sym -A-l -A$*.lst
- -@mv /tmp/$*.bin $*.bin
+ $(BCC) -c $*.s -A-u- -A-b -A$*.tmp -A-s -A$*.sym $(CLST)
+ mv $*.tmp $*.bin
-@rm $*.o
.s.v:
diff --git a/bootblocks/bzimage.c b/bootblocks/bzimage.c
index 8d38753..2e7c835 100644
--- a/bootblocks/bzimage.c
+++ b/bootblocks/bzimage.c
@@ -227,6 +227,8 @@ static unsigned int last_address = 0;
for(i=0; i<512; i++)
__poke_es(i, buffer[i]);
}
+ else
+ printf("In EMU can't write to 0x%x\n", address);
return 0;
}
#endif
diff --git a/bootblocks/dosfs.c b/bootblocks/dosfs.c
index 9dba0af..b9a2c04 100644
--- a/bootblocks/dosfs.c
+++ b/bootblocks/dosfs.c
@@ -298,14 +298,12 @@ static int pend_s, pend_h, pend_c, pend_len = 0;
pend_h != phy_h ||
pend_c != phy_c )
{
-/*
-printf("phy_read(%d,%d,%d,%d,%d,%d);\n",
- drive, pend_c, pend_h, pend_s+1, pend_len, buf_start);
-*/
if( buf_start ) do
{
rv = phy_read(drive, pend_c, pend_h, pend_s+1, pend_len, buf_start);
tries--;
+ if( rv ) printf("Error in phy_read(%d,%d,%d,%d,%d,%d);\n",
+ drive, pend_c, pend_h, pend_s+1, pend_len, buf_start);
}
while(rv && tries > 0);
diff --git a/bootblocks/elf_info.c b/bootblocks/elf_info.c
new file mode 100644
index 0000000..86fa392
--- /dev/null
+++ b/bootblocks/elf_info.c
@@ -0,0 +1,189 @@
+
+#include <stdio.h>
+#include "elf_info.h"
+
+Elf32_Ehdr elf_head;
+Elf32_Phdr *elf_prog;
+
+#ifdef TEST
+FILE *ifd;
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ ifd = fopen(argv[1], "r");
+ if (ifd == 0)
+ exit(1);
+
+ read_elfprog();
+ write_ram("", -1L, 0);
+
+ fclose(ifd);
+}
+
+read_file(buf, offset, len)
+void *buf;
+long offset;
+int len;
+{
+ fseek(ifd, offset, 0);
+ return fread(buf, 1, len, ifd);
+}
+
+write_ram(buf, linear, len)
+char *buf;
+long linear;
+int len;
+{
+static long llen = 0;
+static long lastlin= -1;
+
+ if( llen > 0 && lastlin + llen != linear )
+ {
+ printf("for %8ld bytes\n", llen);
+ lastlin= -1;
+ }
+ if( lastlin == -1 )
+ {
+ lastlin = linear;
+ llen = 0;
+
+ if( linear != -1 )
+ printf("Write %08lx ", linear);
+ }
+ llen += len;
+ return len;
+}
+
+error(str)
+char *str;
+{
+ printf("Error: %s\n", str);
+ return -1;
+}
+#endif
+
+info_elf()
+{
+ int i;
+
+ printf("ELF-386 executable, entry = 0x%08lx\n", elf_head.e_entry);
+ printf("\t\toffset paddr vaddr filesz memsz align\n");
+ for (i = 0; i < elf_head.e_phnum; i++)
+ {
+ printf(" %d: ", i);
+ switch ((int) elf_prog[i].p_type)
+ {
+ case PT_NULL:
+ printf("PT_NULL");
+ break;
+ case PT_LOAD:
+ printf("PT_LOAD");
+ break;
+ case PT_DYNAMIC:
+ printf("PT_DYNAMIC");
+ break;
+ case PT_INTERP:
+ printf("PT_INTERP");
+ break;
+ case PT_NOTE:
+ printf("PT_NOTE");
+ break;
+ case PT_SHLIB:
+ printf("PT_SHLIB");
+ break;
+ case PT_PHDR:
+ printf("PT_PHDR");
+ break;
+ default:
+ printf("PT_(%d)", elf_prog[i].p_type);
+ break;
+ }
+ printf("\t%08lx %08lx %08lx %08lx %08lx %08lx",
+ elf_prog[i].p_offset,
+ elf_prog[i].p_paddr,
+ elf_prog[i].p_vaddr,
+ elf_prog[i].p_filesz,
+ elf_prog[i].p_memsz,
+ elf_prog[i].p_align
+ );
+ printf("\n");
+ }
+}
+
+read_elfprog()
+{
+ static unsigned char elf_ok[] =
+ {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS32, ELFDATA2LSB, EV_CURRENT};
+
+ int i;
+ char page_buf[4096];
+
+ if (read_file(&elf_head, 0L, sizeof(elf_head)) != sizeof(elf_head))
+ return error("Can't read ELF header");
+
+ if (memcmp(elf_head.e_ident, elf_ok, 7) != 0 ||
+ elf_head.e_type != ET_EXEC ||
+ elf_head.e_machine != EM_386 ||
+ elf_head.e_phnum <= 0 ||
+ elf_head.e_phentsize != sizeof(Elf32_Phdr)
+ )
+ return error("Not a 386 executable ELF program");
+
+ elf_prog = malloc(i = sizeof(Elf32_Phdr) * elf_head.e_phnum);
+ if (elf_prog == 0)
+ return error("Out of memory");
+
+ if (read_file(elf_prog, elf_head.e_phoff, i) != i)
+ return error("Can't read ELF program header");
+
+ info_elf();
+
+ for (i = 0; i < elf_head.e_phnum; i++)
+ {
+ long from, to, length, copied;
+ int chunk;
+
+ switch ((int) elf_prog[i].p_type)
+ {
+ case PT_NULL:
+ case PT_NOTE:
+ continue;
+ default:
+ return error("ELF: Unusable program segment (Must be static)");
+ case PT_LOAD:
+ break;
+ }
+ from=elf_prog[i].p_offset;
+ to=elf_prog[i].p_vaddr;
+ length=elf_prog[i].p_filesz;
+
+ for(copied=0; copied<length; )
+ {
+ if(length>copied+sizeof(page_buf)) chunk=sizeof(page_buf);
+ else chunk=length-copied;
+
+ if( (chunk=read_file(page_buf, from, chunk)) <= 0 )
+ return error("ELF Cannot read executable");
+ if( write_ram(page_buf, to, chunk) < 0 )
+ return error("Memory save failed");
+ copied+=chunk; from+=chunk; to+=chunk;
+ }
+ length=elf_prog[i].p_memsz;
+ if( length > copied )
+ {
+ write_ram("", -1L, 0);
+ memset(page_buf, '\0', sizeof(page_buf));
+ for(; copied<length; )
+ {
+ if(length>copied+sizeof(page_buf)) chunk=sizeof(page_buf);
+ else chunk=length-copied;
+
+ if( write_ram(page_buf, to, chunk) < 0 )
+ return error("Memory zap failed");
+ copied+=chunk; to+=chunk;
+ }
+ }
+ }
+}
diff --git a/bootblocks/elf_info.h b/bootblocks/elf_info.h
new file mode 100644
index 0000000..a011d97
--- /dev/null
+++ b/bootblocks/elf_info.h
@@ -0,0 +1,282 @@
+
+/* ELF layout information */
+
+/* NOTE: I'm copying the file format information here because the _format_
+ * is standard, but the Linux header files are not and may depend on
+ * headers not available when compiling Linux-86 code.
+ */
+
+#ifndef _LINUX_ELF_H
+#define _LINUX_ELF_H
+
+typedef unsigned long Elf32_Addr;
+typedef unsigned short Elf32_Half;
+typedef unsigned long Elf32_Off;
+typedef long Elf32_Sword;
+typedef unsigned long Elf32_Word;
+
+/* These constants are for the segment types stored in the image headers */
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+#define PT_LOPROC 0x70000000L
+#define PT_HIPROC 0x7fffffffL
+
+/* These constants define the different elf file types */
+#define ET_NONE 0
+#define ET_REL 1
+#define ET_EXEC 2
+#define ET_DYN 3
+#define ET_CORE 4
+#define ET_LOPROC 5
+#define ET_HIPROC 6
+
+/* These constants define the various ELF target machines */
+#define EM_NONE 0
+#define EM_M32 1
+#define EM_SPARC 2
+#define EM_386 3
+#define EM_68K 4
+#define EM_88K 5
+#define EM_486 6 /* Perhaps disused */
+#define EM_860 7
+
+/* This is the info that is needed to parse the dynamic section of the file */
+#define DT_NULL 0
+#define DT_NEEDED 1
+#define DT_PLTRELSZ 2
+#define DT_PLTGOT 3
+#define DT_HASH 4
+#define DT_STRTAB 5
+#define DT_SYMTAB 6
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_STRSZ 10
+#define DT_SYMENT 11
+#define DT_INIT 12
+#define DT_FINI 13
+#define DT_SONAME 14
+#define DT_RPATH 15
+#define DT_SYMBOLIC 16
+#define DT_REL 17
+#define DT_RELSZ 18
+#define DT_RELENT 19
+#define DT_PLTREL 20
+#define DT_DEBUG 21
+#define DT_TEXTREL 22
+#define DT_JMPREL 23
+#define DT_LOPROC 0x70000000L
+#define DT_HIPROC 0x7fffffffL
+
+/* This info is needed when parsing the symbol table */
+#define STB_LOCAL 0
+#define STB_GLOBAL 1
+#define STB_WEAK 2
+
+#define STT_NOTYPE 0
+#define STT_OBJECT 1
+#define STT_FUNC 2
+#define STT_SECTION 3
+#define STT_FILE 4
+
+#define ELF32_ST_BIND(x) ((x) >> 4)
+#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
+
+/* Symbolic values for the entries in the auxiliary table
+ put on the initial stack */
+#define AT_NULL 0 /* end of vector */
+#define AT_IGNORE 1 /* entry should be ignored */
+#define AT_EXECFD 2 /* file descriptor of program */
+#define AT_PHDR 3 /* program headers for program */
+#define AT_PHENT 4 /* size of program header entry */
+#define AT_PHNUM 5 /* number of program headers */
+#define AT_PAGESZ 6 /* system page size */
+#define AT_BASE 7 /* base address of interpreter */
+#define AT_FLAGS 8 /* flags */
+#define AT_ENTRY 9 /* entry point of program */
+#define AT_NOTELF 10 /* program is not ELF */
+#define AT_UID 11 /* real uid */
+#define AT_EUID 12 /* effective uid */
+#define AT_GID 13 /* real gid */
+#define AT_EGID 14 /* effective gid */
+
+
+typedef struct dynamic{
+ Elf32_Sword d_tag;
+ union{
+ Elf32_Sword d_val;
+ Elf32_Addr d_ptr;
+ } d_un;
+} Elf32_Dyn;
+
+extern Elf32_Dyn _DYNAMIC [];
+
+/* The following are used with relocations */
+#define ELF32_R_SYM(x) ((x) >> 8)
+#define ELF32_R_TYPE(x) ((x) & 0xff)
+
+#define R_386_NONE 0
+#define R_386_32 1
+#define R_386_PC32 2
+#define R_386_GOT32 3
+#define R_386_PLT32 4
+#define R_386_COPY 5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF 9
+#define R_386_GOTPC 10
+#define R_386_NUM 11
+
+typedef struct elf32_rel {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+} Elf32_Rel;
+
+typedef struct elf32_rela{
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+typedef struct elf32_sym{
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf32_Half st_shndx;
+} Elf32_Sym;
+
+
+#define EI_NIDENT 16
+
+typedef struct elfhdr{
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry; /* Entry point */
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+/* These constants define the permissions on sections in the program
+ header, p_flags. */
+#define PF_R 0x4
+#define PF_W 0x2
+#define PF_X 0x1
+
+typedef struct elf_phdr{
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+/* sh_type */
+#define SHT_NULL 0
+#define SHT_PROGBITS 1
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_RELA 4
+#define SHT_HASH 5
+#define SHT_DYNAMIC 6
+#define SHT_NOTE 7
+#define SHT_NOBITS 8
+#define SHT_REL 9
+#define SHT_SHLIB 10
+#define SHT_DYNSYM 11
+#define SHT_NUM 12
+#define SHT_LOPROC 0x70000000L
+#define SHT_HIPROC 0x7fffffffL
+#define SHT_LOUSER 0x80000000L
+#define SHT_HIUSER 0xffffffffL
+
+/* sh_flags */
+#define SHF_WRITE 0x1
+#define SHF_ALLOC 0x2
+#define SHF_EXECINSTR 0x4
+#define SHF_MASKPROC 0xf0000000L
+
+/* special section indexes */
+#define SHN_UNDEF 0
+#define SHN_LORESERVE 0xff00L
+#define SHN_LOPROC 0xff00L
+#define SHN_HIPROC 0xff1fL
+#define SHN_ABS 0xfff1L
+#define SHN_COMMON 0xfff2L
+#define SHN_HIRESERVE 0xffffL
+
+typedef struct {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+#define EI_MAG0 0 /* e_ident[] indexes */
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+#define EI_PAD 7
+
+#define ELFMAG0 0x7f /* EI_MAG */
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define ELFCLASSNONE 0 /* EI_CLASS */
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define ELFCLASSNUM 3
+
+#define ELFDATANONE 0 /* e_ident[EI_DATA] */
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#define EV_NONE 0 /* e_version, EI_VERSION */
+#define EV_CURRENT 1
+#define EV_NUM 2
+
+/* Notes used in ET_CORE */
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_PRPSINFO 3
+#define NT_TASKSTRUCT 4
+
+/* Note header in a PT_NOTE section */
+typedef struct elf_note {
+ Elf32_Word n_namesz; /* Name size */
+ Elf32_Word n_descsz; /* Content size */
+ Elf32_Word n_type; /* Content type */
+} Elf32_Nhdr;
+
+#endif /* _LINUX_ELF_H */
diff --git a/bootblocks/i86_funcs.h b/bootblocks/i86_funcs.h
new file mode 100644
index 0000000..9eb1b05
--- /dev/null
+++ b/bootblocks/i86_funcs.h
@@ -0,0 +1,21 @@
+/*
+ * These are bios and hardware functions for the 8086 IBM PC
+ */
+
+extern int x86; /* CPU major number (0-3) */
+extern char *x86_name; /* and it's name */
+extern int x86_emu; /* Is this a PC emulator ? */
+extern int x86_a20_closed; /* Is the A20 gate closed ? */
+extern int x86_test; /* In test mode */
+extern int x86_fpu;
+
+extern unsigned boot_mem_top; /* Top of RAM below 1M */
+extern long main_mem_top; /* Top of RAM above 1M */
+
+int a20_closed();
+void open_a20();
+void bios_open_a20();
+void cpu_check();
+void mem_check();
+int ext_put();
+int ext_get();
diff --git a/bootblocks/li86.s b/bootblocks/li86.s
new file mode 100644
index 0000000..0c391ff
--- /dev/null
+++ b/bootblocks/li86.s
@@ -0,0 +1,46 @@
+!----------------------------------------------------------------------------
+!
+! This is a skeleton for creating an impure Linux-8086 executable without
+! using the linker. The .text and .data areas are correctly positioned.
+!
+! This file needs to be compiled using the 3 pass mode (-j)
+!
+!----------------------------------------------------------------------------
+.text
+org -32
+.word 0x0301 ! Magic
+.word 0x0410 ! Btype
+.long 0x20 ! header length
+.long _etext ! a_text
+.long _edata-_etext ! a_data
+.long 0 ! a_bss
+.long 0 ! a_entry
+.long STACK_SIZE ! a_total
+.long 0 ! a_syms
+.data
+.blkb _etext
+.even
+.text
+!----------------------------------------------------------------------------
+
+STACK_SIZE = 0x10000
+
+.data
+var:
+.word $1234
+
+.text
+ int $20
+ mov ax,var
+ mov bx,_edata
+ push ax
+ ret
+
+!----------------------------------------------------------------------------
+! This trailer must be at the end of the file.
+.text
+_etext:
+.data
+_edata:
+END
+
diff --git a/bootblocks/makeboot.c b/bootblocks/makeboot.c
index 0f07735..4a036a6 100644
--- a/bootblocks/makeboot.c
+++ b/bootblocks/makeboot.c
@@ -4,17 +4,18 @@
#include <time.h>
#include "sysboot.v"
+#include "noboot.v"
#include "msdos.v"
#include "skip.v"
#include "tarboot.v"
char buffer[1024];
-#define FS_NONE 0
-#define FS_ADOS 1
-#define FS_DOS 2
-#define FS_TAR 3
-#define FS_STAT 4
+#define FS_NONE 0 /* Bootsector is complete */
+#define FS_ADOS 1 /* Bootsector needs 'normal' DOS FS */
+#define FS_DOS 2 /* Bootsector needs any DOS FS */
+#define FS_TAR 3 /* Bootsector needs GNU-tar volume label */
+#define FS_STAT 4 /* DOS bootsector is checked */
struct bblist {
char * name;
@@ -24,7 +25,7 @@ struct bblist {
} bblocks[] = {
{ "tar", tarboot_data, FS_TAR, "Bootable GNU tar volume lable" },
{ "dosfs", msdos_data, FS_ADOS, "Boots file BOOTFILE.SYS from dosfs" },
- { "none", sysboot_data, FS_DOS, "No OS bookblock, just message" },
+ { "none", noboot_data, FS_DOS, "No OS bookblock, just message" },
{ "skip", skip_data, FS_DOS, "Bypasses floppy boot with message" },
{ "stat", 0, FS_STAT, "Display dosfs superblock" },
{ "copy", 0, FS_STAT, "Copy boot block to makeboot.sav" },
@@ -41,6 +42,8 @@ int disk_sect = 63; /* These are initilised to the maximums */
int disk_head = 256; /* Set to the correct values when an MSDOS disk is */
int disk_trck = 256; /* successfully identified */
+int force = 0;
+
main(argc, argv)
int argc;
char ** argv;
@@ -51,6 +54,10 @@ char ** argv;
progname = argv[0];
+ if( argc == 4 && strcmp(argv[1], "-f") == 0 )
+ {
+ argv++; argc--; force++;
+ }
if( argc != 3 ) Usage();
if( (i=strlen(argv[1])) < 2 ) Usage();
@@ -355,12 +362,12 @@ not_zapped:
if( csum != osum )
{
fprintf(stderr, "TAR file checksum failed, this isn't a tar file.\n");
- exit(9);
+ if(!force) exit(9);
}
if( buff_tar.linkflag != 'V' )
{
fprintf(stderr, "Tar file doesn't start with a volume label\n");
- exit(8);
+ if(!force) exit(8);
}
strcpy(vbuf, boot_tar.name); strcat(vbuf, " Volume 1");
@@ -568,24 +575,26 @@ check_msdos()
{
disk_sect = dosflds[DOS_SPT].value;
disk_head = dosflds[DOS_HEADS].value;
- disk_trck = dosflds[DOS_MAXSECT].value/disk_head/disk_sect;
+ if( disk_sect > 0 && disk_head > 0 )
+ disk_trck = dosflds[DOS_MAXSECT].value/disk_head/disk_sect;
return;
}
- exit(2);
+ if(!force) exit(2);
}
check_simpledos()
{
- int numclust;
+ int numclust = 0xFFFF;
char * err = 0;
check_msdos();
/* Work out how many real clusters there are */
- numclust = ( dosflds[DOS_MAXSECT].value
- - dosflds[DOS_RESV].value
- - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value
- - ((dosflds[DOS_NROOT].value+15)/16)
- ) / dosflds[DOS_MAXSECT].value + 2;
+ if( dosflds[DOS_MAXSECT].value + 2 > 2 )
+ numclust = ( dosflds[DOS_MAXSECT].value
+ - dosflds[DOS_RESV].value
+ - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value
+ - ((dosflds[DOS_NROOT].value+15)/16)
+ ) / dosflds[DOS_MAXSECT].value + 2;
if( dosflds[DOS_NFAT].value > 2 )
err = "Too many fat copies on disk";
@@ -607,7 +616,7 @@ check_simpledos()
fprintf(stderr, "ERROR: %s\n\n", err);
print_super(buffer);
- exit(2);
+ if(!force) exit(2);
}
/**************************************************************************/
diff --git a/bootblocks/minix.c b/bootblocks/minix.c
index 8242707..cfcfb38 100644
--- a/bootblocks/minix.c
+++ b/bootblocks/minix.c
@@ -7,6 +7,7 @@
*/
#include <a.out.h>
+#include "minix.h"
#undef DOTS /* define to have dots printed */
#define zone_shift 0 /* for any < 32M (non-zero not supported yet) */
@@ -16,10 +17,20 @@
#define BOOTSEG (0x07c0)
#define LOADSEG (0x1000)
+#define TRY_FLOPPY
+
#ifdef HARDDISK
#define get_now()
#endif
+#ifdef zone_shift
+#if zone_shift == 0
+#define load_zone load_block
+#endif
+#else
+static short zone_shift;
+#endif
+
#asm
! BOOTSEG = 0x07c0
! LOADSEG = 0x1000 ! This must be sector aligned
@@ -57,11 +68,13 @@ org dos_sysid
mov sp,ax
#ifndef HARDDISK
+loopy:
mov ax,#$0204 ! Read 4 sectors, code + superblock.
mov bx,#start ! Where this _should_ be
mov cx,#$0001 ! From sector 1
xor dx,dx ! Of the floppy drive head zero
int $13
+ jc loopy
#else
mov cx,#$100 ! Move 256 words
@@ -88,117 +101,7 @@ org dos_sysid
#endasm
/****************************************************************************/
-/* Super block table. The root file system and every mounted file system
- * has an entry here. The entry holds information about the sizes of the bit
- * maps and inodes. The s_ninodes field gives the number of inodes available
- * for files and directories, including the root directory. Inode 0 is
- * on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be
- * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
- * for files and directories. The disk layout is:
- *
- * Item # blocks
- * boot block 1
- * super block 1
- * inode map s_imap_blocks
- * zone map s_zmap_blocks
- * inodes (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK
- * unused whatever is needed to fill out the current zone
- * data zones (s_nzones - s_firstdatazone) << s_log_zone_size
- *
- * A super_block slot is free if s_dev == NO_DEV.
- */
-
-#define BLOCK_SIZE 1024 /* # bytes in a disk block */
-
-/* Flag bits for i_mode in the inode. */
-#define I_TYPE 0170000 /* this field gives inode type */
-#define I_REGULAR 0100000 /* regular file, not dir or special */
-#define I_BLOCK_SPECIAL 0060000 /* block special file */
-#define I_DIRECTORY 0040000 /* file is a directory */
-#define I_CHAR_SPECIAL 0020000 /* character special file */
-#define I_SET_UID_BIT 0004000 /* set effective uid on exec */
-#define I_SET_GID_BIT 0002000 /* set effective gid on exec */
-#define ALL_MODES 0006777 /* all bits for user, group and others */
-#define RWX_MODES 0000777 /* mode bits for RWX only */
-#define R_BIT 0000004 /* Rwx protection bit */
-#define W_BIT 0000002 /* rWx protection bit */
-#define X_BIT 0000001 /* rwX protection bit */
-#define I_NOT_ALLOC 0000000 /* this inode is free */
-
-/* Type definitions */
-typedef unsigned short unshort; /* must be 16-bit unsigned */
-typedef unshort block_nr; /* block number */
-typedef unshort inode_nr; /* inode number */
-typedef unshort zone_nr; /* zone number */
-typedef unshort bit_nr; /* if inode_nr & zone_nr both unshort,
- then also unshort, else long */
-
-typedef unshort sect_nr;
-
-typedef long zone_type; /* zone size */
-typedef unshort mask_bits; /* mode bits */
-typedef unshort dev_nr; /* major | minor device number */
-typedef char links; /* number of links to an inode */
-typedef long real_time; /* real time in seconds since Jan 1, 1970 */
-typedef long file_pos; /* position in, or length of, a file */
-typedef short uid; /* user id */
-typedef char gid; /* group id */
-
-/* Tables sizes */
-#define NR_ZONE_NUMS 9 /* # zone numbers in an inode */
-#define NAME_SIZE 14 /* # bytes in a directory component */
-
-/* Miscellaneous constants */
-#define SUPER_MAGIC 0x137F /* magic number contained in super-block */
-
-#define BOOT_BLOCK (block_nr)0 /* block number of boot block */
-#define SUPER_BLOCK (block_nr)1 /* block number of super block */
-#define ROOT_INODE (inode_nr)1 /* inode number for root directory */
-
-/* Derived sizes */
-#define NR_DZONE_NUM (NR_ZONE_NUMS-2) /* # zones in inode */
-#define INODES_PER_BLOCK (BLOCK_SIZE/sizeof(d_inode)) /* # inodes/disk blk */
-#define NR_INDIRECTS (BLOCK_SIZE/sizeof(zone_nr)) /* # zones/indir blk */
-#define INTS_PER_BLOCK (BLOCK_SIZE/sizeof(int)) /* # integers/blk */
-
-struct super_block {
- inode_nr s_ninodes; /* # usable inodes on the minor device */
- zone_nr s_nzones; /* total device size, including bit maps etc */
- unshort s_imap_blocks; /* # of blocks used by inode bit map */
- unshort s_zmap_blocks; /* # of blocks used by zone bit map */
- zone_nr s_firstdatazone; /* number of first data zone */
- short s_log_zone_size; /* log2 of blocks/zone */
- file_pos s_max_size; /* maximum file size on this device */
- short s_magic; /* magic number to recognize super-blocks */
-
-} ;
-
-/* Type definitions local to the File System. */
-typedef struct { /* directory entry */
- inode_nr d_inum; /* inode number */
- char d_name[NAME_SIZE]; /* character string */
-} dir_struct;
-
-/* Declaration of the disk inode used in rw_inode(). */
-typedef struct { /* disk inode. Memory inode is in "inotab.h" */
- mask_bits i_mode; /* file type, protection, etc. */
- uid i_uid; /* user id of the file's owner */
- file_pos i_size; /* current file size in bytes */
- real_time i_modtime; /* when was file data last changed */
- gid i_gid; /* group number */
- links i_nlinks; /* how many links to this file */
- zone_nr i_zone[NR_ZONE_NUMS]; /* block nums for direct, ind, and dbl ind */
-} d_inode;
-
-/****************************************************************************/
-
-#ifdef zone_shift
-#if zone_shift == 0
-#define load_zone load_block
-#endif
-#else
-static short zone_shift;
-#endif
+/* /* */
/* The name of the file and inode to start */
extern char bootfile[];
@@ -222,8 +125,10 @@ extern unsigned ldaddr;
extern dir_struct * dirptr;
extern unsigned flength;
+#ifndef HARDDISK
/* The 'shape' of the floppy - intuit from superblock */
extern unsigned n_sectors;
+#endif
/*
* #define b_super (*(struct super_block *) 1024)
@@ -237,16 +142,19 @@ extern zone_nr b_zone[NR_INDIRECTS];
extern dir_struct directory[];
/****************************************************************************/
+/* /* */
#asm
! A few variables we need to know the positions of for patching, so export
! them and as86_encaps will make some variables.
.text
-export _inode ! Inode to search
+export inode ! Inode to search
+inode:
_inode: .word 1 ! ROOT_INODE
-export _bootfile ! File to boot, make this whatever you like,
-_bootfile: ! 'boot' is good too.
+export bootfile ! File to boot, make this whatever you like,
+bootfile: ! 'boot' is good too.
+_bootfile:
.ascii "linux"
.byte 0,0,0,0,0,0,0,0,0
@@ -266,6 +174,9 @@ code:
#endasm
+/************************************/
+/* Hard disk device driver */
+/************************************/
#ifdef HARDDISK
#asm
@@ -319,7 +230,7 @@ real_block:
!
! Load AL sectors from linear sector DX:CX into location ES:BX
-! Linear sector zero is a [bootpart]
+! Linear sector zero is at [bootpart]
! This loads one sector at a time, but that's OK cause even in the _very_
! worst case it'll take no more that 5 seconds to load a 16 bit executable.
!
@@ -384,10 +295,20 @@ onesect:
pop bx ! ES:BX for int 1302
pop es
+ mov di,#5 ! Lots of retries for a hd
+retry:
mov ax,#$0201
int $13
- jc _nogood
+ jnc got_hd_sect
+
+ xor ax,ax ! Reset between each try.
+ int $13
+ dec di
+ jnz retry
+ jmp _nogood
+
+got_hd_sect:
pop dx
pop cx
pop si
@@ -402,62 +323,9 @@ onesect:
#endasm
#else
-#asm
-_set_bpb:
-bios_tabl=dosfs_stat ! Temp space.
-bios_disk=dosfs_stat+4 !
-
-#ifndef __CALLER_SAVES__
- push si
- push di
-#endif
-
- mov di,#bios_disk
- mov bx,#0x78
-! 0:bx is parameter table address
-
- push ds
- push di
-
- mov si,[bx]
- mov ax,[bx+2]
- mov [bios_tabl],si
- mov [bios_tabl+2],ax
- push ax
-
- pop ds
-! ds:si is source
-
-! copy 12 bytes
- mov cl,#6
- cld
- rep
- movsw
-
- pop di
- pop ds
- mov ax,[_n_sectors]
- movb 4[di],al ! patch sector count
-
- mov [bx],di
- mov 2[bx],es
-
-#ifndef __CALLER_SAVES__
- pop si
- pop di
-#endif
- ret
-
-_unset_bpb:
-! 0:0x78 is parameter table address
-
- mov ax,[bios_tabl]
- mov [0x78],ax
- mov ax,[bios_tabl+2]
- mov [0x78+2],ax
- ret
-
-#endasm
+/************************************/
+/* Floppy disk device driver */
+/************************************/
static
load_block(address, blkno)
@@ -505,6 +373,8 @@ static
get_now()
{
#asm
+ mov si,#5
+retry_get:
xor dx,dx
mov cx,[_firstsect]
shr ch,#1
@@ -515,8 +385,13 @@ get_now()
test ax,ax
jz no_load
mov ah,#2
+ int $13 ! Try fetch
+ jnc no_load
+ xor ax,ax ! Bad, retry.
int $13
- jc nogood
+ dec si
+ jnz retry_get
+ jmp nogood
no_load:
xor ax,ax
mov [_loadcount],ax
@@ -548,7 +423,47 @@ zero_block(address)
#endasm
}
-#endif /* !HARDDISK */
+#ifdef TRY_FLOPPY
+#asm
+!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+!
+! These are the number of sectors per track that will be scanned for.
+! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on
+! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies.
+
+disksizes: .byte 36,21,18,15,9
+
+! It seems that there is no BIOS call to get the number of sectors. Guess
+! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
+! 15 if sector 15 can be read. Otherwise guess 9.
+
+_probe_sectors:
+ mov si,#disksizes ! table of sizes to try
+
+probe_loop:
+ lodsb
+ cbw ! extend to word
+ mov _n_sectors, ax
+ cmp al,#9
+ je got_sectors ! if all else fails, try 9
+ xchg ax, cx ! cx = track and sector
+ xor dx, dx ! drive 0, head 0
+ mov bx,#probe_buf ! address after setup (es = cs)
+ mov ax,#0x0201 ! service 2, 1 sector
+ int 0x13
+ jc probe_loop ! try next value
+got_sectors:
+
+ ret
+#endasm
+#else
+probe_sectors()
+{
+ n_sectors = b_super.s_nzones / 80;
+ if( n_sectors < 5 ) n_sectors = b_super.s_nzones / 40;
+}
+#endif
+#endif
#ifdef DOTS
static
@@ -566,10 +481,10 @@ bios_putc(c)
}
#endif
+#if defined(HARDDISK) && !defined(SKIPBOOT)
static
nogood()
{
-#ifdef HARDDISK
#asm
mov si,#fail_fs
min_nextc:
@@ -589,7 +504,13 @@ min_eos: ! Wait for a key then reboot
fail_fs:
.asciz "Inital boot failed, press return to reboot\r\n"
#endasm
+}
+
#else
+
+static
+nogood()
+{
/* This didn't work, chain the boot sector of the HD */
#asm
push cs
@@ -603,8 +524,8 @@ hcode:
jc hcode ! Keep trying forever!
jmpi BOOTADDR,0
#endasm
-#endif
}
+#endif
/****************************************************************************/
#asm
@@ -616,6 +537,8 @@ end_of_part1:
#endasm
/****************************************************************************/
+/* Part two, code to load directories then a file into memory from the device
+ */
static
loadprog()
@@ -624,10 +547,9 @@ loadprog()
bios_putc('+');
#endif
if( b_super.s_magic != SUPER_MAGIC ) nogood();
- n_sectors = b_super.s_nzones / 80;
- if( n_sectors < 5 ) n_sectors = b_super.s_nzones / 40;
-
#ifndef HARDDISK
+ probe_sectors();
+
set_bpb();
#endif
@@ -723,20 +645,80 @@ register char * p = dirptr->d_name;
#endif
}
+#ifndef HARDDISK
+#asm
+_set_bpb:
+bios_tabl=dosfs_stat ! Temp space.
+bios_disk=dosfs_stat+4 !
+
+#ifndef __CALLER_SAVES__
+ push si
+ push di
+#endif
+
+ mov di,#bios_disk
+ mov bx,#0x78
+! 0:bx is parameter table address
+
+ push ds
+ push di
+
+ mov si,[bx]
+ mov ax,[bx+2]
+ mov [bios_tabl],si
+ mov [bios_tabl+2],ax
+ push ax
+
+ pop ds
+! ds:si is source
+
+! copy 12 bytes
+ mov cl,#6
+ cld
+ rep
+ movsw
+
+ pop di
+ pop ds
+ mov ax,[_n_sectors]
+ movb 4[di],al ! patch sector count
+
+ mov [bx],di
+ mov 2[bx],es
+
+#ifndef __CALLER_SAVES__
+ pop si
+ pop di
+#endif
+ ret
+
+_unset_bpb:
+! 0:0x78 is parameter table address
+
+ mov ax,[bios_tabl]
+ mov [0x78],ax
+ mov ax,[bios_tabl+2]
+ mov [0x78+2],ax
+ ret
+
+#endasm
+#endif
+
static
runprog()
{
-/* This did work, run the loaded executable */
+/* It all worked, run the loaded executable */
#asm
#ifdef HARDDISK
mov dx,[bootpart+2]
xchg dh,dl ! DX => hard drive
push [bootpart] ! CX => partition offset
+ xor si,si
#else
xor dx,dx ! DX=0 => floppy drive
push dx ! CX=0 => partition offset = 0
-#endif
mov si,[_n_sectors] ! Save for monitor.out
+#endif
mov bx,#LOADSEG
mov ds,bx ! DS = loadaddress
@@ -787,7 +769,9 @@ islu:
libend:
vars:
+#ifndef HARDDISK
_n_sectors: .word 0
+#endif
_next_zone: .word 0
_end_zone: .word 0
_indirect: .word 0
@@ -798,7 +782,7 @@ varend:
end_of_prog:
if *>start+0x400
- fail
+ fail! Part 2 too large!
endif
.blkb 0x3FF+start-*
@@ -807,6 +791,7 @@ end_of_prog:
_b_super: .blkb 1024
_b_inode: .blkb 1024
_b_zone: .blkb 1024
+probe_buf:
_directory: .blkb 32768
#endasm
diff --git a/bootblocks/minix.h b/bootblocks/minix.h
new file mode 100644
index 0000000..984a6bc
--- /dev/null
+++ b/bootblocks/minix.h
@@ -0,0 +1,103 @@
+/****************************************************************************/
+/* Super block table. The root file system and every mounted file system
+ * has an entry here. The entry holds information about the sizes of the bit
+ * maps and inodes. The s_ninodes field gives the number of inodes available
+ * for files and directories, including the root directory. Inode 0 is
+ * on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be
+ * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
+ * for files and directories. The disk layout is:
+ *
+ * Item # blocks
+ * boot block 1
+ * super block 1
+ * inode map s_imap_blocks
+ * zone map s_zmap_blocks
+ * inodes (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK
+ * unused whatever is needed to fill out the current zone
+ * data zones (s_nzones - s_firstdatazone) << s_log_zone_size
+ *
+ * A super_block slot is free if s_dev == NO_DEV.
+ */
+
+#define BLOCK_SIZE 1024 /* # bytes in a disk block */
+
+/* Flag bits for i_mode in the inode. */
+#define I_TYPE 0170000 /* this field gives inode type */
+#define I_REGULAR 0100000 /* regular file, not dir or special */
+#define I_BLOCK_SPECIAL 0060000 /* block special file */
+#define I_DIRECTORY 0040000 /* file is a directory */
+#define I_CHAR_SPECIAL 0020000 /* character special file */
+#define I_SET_UID_BIT 0004000 /* set effective uid on exec */
+#define I_SET_GID_BIT 0002000 /* set effective gid on exec */
+#define ALL_MODES 0006777 /* all bits for user, group and others */
+#define RWX_MODES 0000777 /* mode bits for RWX only */
+#define R_BIT 0000004 /* Rwx protection bit */
+#define W_BIT 0000002 /* rWx protection bit */
+#define X_BIT 0000001 /* rwX protection bit */
+#define I_NOT_ALLOC 0000000 /* this inode is free */
+
+/* Type definitions */
+typedef unsigned short unshort; /* must be 16-bit unsigned */
+typedef unshort block_nr; /* block number */
+typedef unshort inode_nr; /* inode number */
+typedef unshort zone_nr; /* zone number */
+typedef unshort bit_nr; /* if inode_nr & zone_nr both unshort,
+ then also unshort, else long */
+
+typedef unshort sect_nr;
+
+typedef long zone_type; /* zone size */
+typedef unshort mask_bits; /* mode bits */
+typedef unshort dev_nr; /* major | minor device number */
+typedef char links; /* number of links to an inode */
+typedef long real_time; /* real time in seconds since Jan 1, 1970 */
+typedef long file_pos; /* position in, or length of, a file */
+typedef short uid; /* user id */
+typedef char gid; /* group id */
+
+/* Tables sizes */
+#define NR_ZONE_NUMS 9 /* # zone numbers in an inode */
+#define NAME_SIZE 14 /* # bytes in a directory component */
+
+/* Miscellaneous constants */
+#define SUPER_MAGIC 0x137F /* magic number contained in super-block */
+
+#define BOOT_BLOCK (block_nr)0 /* block number of boot block */
+#define SUPER_BLOCK (block_nr)1 /* block number of super block */
+#define ROOT_INODE (inode_nr)1 /* inode number for root directory */
+
+/* Derived sizes */
+#define NR_DZONE_NUM (NR_ZONE_NUMS-2) /* # zones in inode */
+#define INODES_PER_BLOCK (BLOCK_SIZE/sizeof(d_inode)) /* # inodes/disk blk */
+#define NR_INDIRECTS (BLOCK_SIZE/sizeof(zone_nr)) /* # zones/indir blk */
+#define INTS_PER_BLOCK (BLOCK_SIZE/sizeof(int)) /* # integers/blk */
+
+struct super_block {
+ inode_nr s_ninodes; /* # usable inodes on the minor device */
+ zone_nr s_nzones; /* total device size, including bit maps etc */
+ unshort s_imap_blocks; /* # of blocks used by inode bit map */
+ unshort s_zmap_blocks; /* # of blocks used by zone bit map */
+ zone_nr s_firstdatazone; /* number of first data zone */
+ short s_log_zone_size; /* log2 of blocks/zone */
+ file_pos s_max_size; /* maximum file size on this device */
+ short s_magic; /* magic number to recognize super-blocks */
+
+} ;
+
+/* Type definitions local to the File System. */
+typedef struct { /* directory entry */
+ inode_nr d_inum; /* inode number */
+ char d_name[NAME_SIZE]; /* character string */
+} dir_struct;
+
+/* Declaration of the disk inode used in rw_inode(). */
+typedef struct { /* disk inode. Memory inode is in "inotab.h" */
+ mask_bits i_mode; /* file type, protection, etc. */
+ uid i_uid; /* user id of the file's owner */
+ file_pos i_size; /* current file size in bytes */
+ real_time i_modtime; /* when was file data last changed */
+ gid i_gid; /* group number */
+ links i_nlinks; /* how many links to this file */
+ zone_nr i_zone[NR_ZONE_NUMS]; /* block nums for direct, ind, and dbl ind */
+} d_inode;
+
diff --git a/bootblocks/monitor.c b/bootblocks/monitor.c
index dbf2d64..5c78aaf 100644
--- a/bootblocks/monitor.c
+++ b/bootblocks/monitor.c
@@ -1,12 +1,11 @@
-#define VERSION "0.1.1-ALPHA"
-
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <dos.h>
#include "i86_funcs.h"
#include "readfs.h"
+#include "version.h"
#ifdef __STANDALONE__
#define NOT_VT52COLOUR
@@ -60,7 +59,7 @@ static char minibuf[2] = " ";
if( x86 > 2 && !x86_emu ) /* Check some basics */
cmd_bzimage((void*)0);
else
- printf("System is not a 386+ in real mode, load aborted.\nUse 'bzimage' command toattempt load.\n");
+ printf("System is not an 80386 compatible in real mode, load aborted.\nUse 'bzimage' command to attempt load.\n");
}
for (;;)
@@ -135,7 +134,11 @@ void init_prog()
#ifdef VT52COLOUR
printf("\033E\033Rg\033Sa\033J");
#endif
- printf("Linux x86 boot monitor Version %s\n", VERSION);
+#ifdef VERSION
+ printf("Linux x86 boot monitor, Version %s.\n", VERSION);
+#else
+ printf("Linux x86 boot monitor.\n");
+#endif
cpu_check();
mem_check();
diff --git a/bootblocks/noboot.s b/bootblocks/noboot.s
new file mode 100644
index 0000000..7ab9f4e
--- /dev/null
+++ b/bootblocks/noboot.s
@@ -0,0 +1,32 @@
+
+org $7c00
+
+include sysboot.s
+
+org dos_sysid
+ .ascii "PANIC" ! System ID
+
+org codestart
+ xor ax,ax
+ mov ds,ax
+ mov ss,ax
+ mov sp,ax
+ jmpi code,#0
+
+no_os:
+ .asciz "PANIC! NO OS Found!\r\n"
+
+code: ! SI = pointer to error message
+ mov si,#no_os
+nextc:
+ lodsb
+ cmp al,#0
+ jz eos
+ mov bx,#7
+ mov ah,#$E ! Can't use $13 cause that's AT+ only!
+ int $10
+ jmp nextc
+eos: ! Wait for a key then reboot
+ xor ax,ax
+ int $16
+ jmpi $0,$FFFF ! Wam! Try or die!
diff --git a/bootblocks/readfs.h b/bootblocks/readfs.h
new file mode 100644
index 0000000..aa6b87c
--- /dev/null
+++ b/bootblocks/readfs.h
@@ -0,0 +1,17 @@
+
+/* Functions for reading from one file at a time in the root directory
+ * of a raw filesystem.
+ */
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+int open_file P((char * fname));
+int rewind_file P((void));
+int close_file P((void));
+long file_length P((void));
+int read_block P((char * buffer));
+
diff --git a/bootblocks/standalone.c b/bootblocks/standalone.c
new file mode 100644
index 0000000..57634d4
--- /dev/null
+++ b/bootblocks/standalone.c
@@ -0,0 +1,309 @@
+
+#include <errno.h>
+#asm
+entry _int_80 ! Tell ld86 we really do need this file.
+ ! then call the init stuff before main.
+
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word _pre_main ! 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
+
+void int_80();
+
+static void pre_main()
+{
+ /* Set the int 0x80 pointer to here */
+ __set_es(0);
+ __doke_es(0x80*4+0, int_80);
+ __doke_es(0x80*4+2, __get_cs());
+ bios_coninit();
+}
+
+void int_80()
+{
+#asm
+SYS_EXIT=1
+SYS_FORK=2
+SYS_READ=3
+SYS_WRITE=4
+SYS_OPEN=5
+SYS_CLOSE=6
+SYS_CHDIR=12
+SYS_LSEEK=19
+ENOSYS=38
+
+ push es
+ push si
+ push di
+ push dx
+ push cx
+ push bx
+ cmp ax,#SYS_READ
+ jne L1
+ call _func_read
+ jmp L0
+L1:
+ cmp ax,#SYS_WRITE
+ jne L2
+ call _func_write
+ jmp L0
+L2:
+ cmp ax,#SYS_LSEEK
+ jne L3
+ call _func_lseek
+ jmp L0
+L3:
+ cmp ax,#SYS_EXIT
+ jne L4
+ call _func_exit
+ jmp L0
+L4:
+ mov ax,#-ENOSYS
+L0:
+ pop bx
+ pop cx
+ pop dx
+ pop di
+ pop si
+ pop es
+ iret
+#endasm
+}
+
+func_lseek() { return -38; }
+
+func_write(bx,cx,dx,di,si,es)
+int bx,dx;
+char * cx;
+{
+ register int v, c;
+ if(bx == 1 || bx == 2)
+ {
+ for(v=dx; v>0; v--)
+ {
+ c= *cx++;
+ if( c == '\n') bios_putc('\r');
+ bios_putc(c);
+ }
+ return dx;
+ }
+ return -EBADF;
+}
+
+func_read(bx,cx,dx,di,si,es)
+int bx,dx;
+char * cx;
+{
+ if(bx == 0) return read_line(cx, dx);
+ return -EBADF;
+}
+
+read_line(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');
+ }
+}
+
+#define CTRL(x) ((x)&0x1F)
+static int last_attr = 0x07;
+static int con_mode;
+static int con_size = 0x184F;
+static int con_colour = 0;
+
+bios_coninit()
+{
+#asm
+ mov ax,#$0F00
+ int $10
+ mov _con_mode,ax
+#endasm
+ if( (con_mode &0xFF) > 39 ) con_size = (con_size&0xFF00) + (con_mode&0xFF);
+ if( (con_mode&0xFF00) != 0x700)
+ con_colour = 1;
+}
+
+bios_putc(c)
+int c;
+{
+static char tbuf[3];
+static int tcnt=0;
+ if(tcnt)
+ {
+ tbuf[tcnt++] = c;
+ if( tcnt < 3 && (tbuf[0] != CTRL(']') || tbuf[1] < '`' || tbuf[1] > 'p'))
+ return;
+ if( tbuf[0] == CTRL('P') )
+ {
+ if( tbuf[1] >= 32 && tbuf[1] <= 56
+ && tbuf[2] >= 32 && tbuf[2] <= 111 )
+ asm_cpos((tbuf[1]-32), (tbuf[2]-32));
+ }
+ else
+ {
+ if( tbuf[1] >= '`' )
+ last_attr = ( (tbuf[1]&0xF) | (last_attr&0xF0));
+ else
+ last_attr = ( (tbuf[2]&0xF) | ((tbuf[1]&0xF)<<4));
+
+ if( !con_colour )
+ last_attr = (last_attr&0x88) + ((last_attr&7)?0x07:0x70);
+ }
+ tcnt=0;
+ return;
+ }
+ if( c & 0xE0 ) { asm_colour(last_attr) ; asm_putc(c); }
+ else switch(c)
+ {
+ case CTRL('L'):
+ asm_cpos(0,0);
+ asm_cls();
+ break;
+ case CTRL('P'):
+ case CTRL(']'):
+ tbuf[tcnt++] = c;
+ break;
+ default:
+ asm_putc(c);
+ break;
+ }
+ return;
+}
+
+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_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_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 dx,_con_size
+ 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
+}
+
+bios_getc()
+{
+#asm
+ xor ax,ax
+ int $16
+#endasm
+}
+
+static void be_safe()
+{
+#asm
+ iret
+#endasm
+}
+
+func_exit(bx,cx,dx,di,si,es) /* AKA reboot! */
+{
+ __set_es(0);
+ __doke_es(0xE6*4+2,__get_cs());
+ __doke_es(0xE6*4+0,be_safe);
+#asm
+ mov ax,#$FFFF
+ int $E6 ! Try to exit DOSEMU
+ mov ax,#$0040 ! If we get here we're not in dosemu.
+ mov es,ax
+ seg es
+ mov [$72],#$1234 ! Warm reboot.
+ jmpi $0000,$FFFF
+#endasm
+}
diff --git a/bootblocks/sysboot.s b/bootblocks/sysboot.s
index 3bc7c57..ee62e69 100644
--- a/bootblocks/sysboot.s
+++ b/bootblocks/sysboot.s
@@ -46,36 +46,11 @@ dos4_label: .blkb 11 ! Disk Label (DOS 4+)
dos4_fattype: .blkb 8 ! FAT type
!
-! This is where the code will be overlaid, the default is an 'oops'
+! This is where the code will be overlaid, the default is a hang
.blkb sysboot_start+0x3E-*
public codestart
codestart:
- xor ax,ax
- mov ds,ax
- mov es,ax
- mov ss,ax
- mov sp,ax
- jmpi sys_code+$7C00-sysboot_start,#0
-
-sys_code: ! SI now has pointer to error message
- mov si,#sys_no_os+$7C00-sysboot_start
-sys_nextc:
- lodsb
- cmp al,#0
- jz sys_eos
- mov bx,#7
- mov ah,#$E ! Can't use $13 cause that's AT+ only!
- int $10
- jmp sys_nextc
-sys_eos: ! Wait for a key then reboot
- xor ax,ax
- int $16
- !int $19 ! This should be OK as we haven't touched anything.
- jmpi $0,$FFFF ! Wam! Try or die!
-
-sys_no_os:
- .asciz "PANIC! NO OS Found!\r\n"
-
+ j codestart
! Partition table
public partition_1
diff --git a/bootblocks/tarboot.s b/bootblocks/tarboot.s
index 0fb85d3..be68ecd 100644
--- a/bootblocks/tarboot.s
+++ b/bootblocks/tarboot.s
@@ -137,7 +137,11 @@ blk_uid: .blkb 8
blk_gid: .blkb 8
blk_size: .blkb 12
blk_mtime: .asciz "6141567743 "
-blk_chksum: .asciz " 131141"
+if DEBUG
+blk_chksum: .asciz " 142273"
+else
+blk_chksum: .asciz " 127270"
+endif
blk_link: .byte 'V
! Sneaks here, overlay zero init vars on tar data.
@@ -476,14 +480,16 @@ endif
!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-if DEBUG = 0
- locn(510)
! This isn't a hard disk boot sector so don't give it an HD magic
+! locn(510)
! .word 0xAA55
+if DEBUG = 0
+locn(510)
.word 0
endif
! From here down is where we load stuff.
+locn(512)
blk_load: ! Address of block load
tar_name: .blkb 100
diff --git a/copt/Makefile b/copt/Makefile
index 9f273a3..7a7d653 100644
--- a/copt/Makefile
+++ b/copt/Makefile
@@ -1,6 +1,8 @@
copt: copt.c
- $(CC) $(CFLAGS) -o copt copt.c
+ $(CC) $(ANSI) $(CFLAGS) $(LDFLAGS) -o copt copt.c
realclean clean:
rm -f *.o copt
+
+
diff --git a/dis88/Makefile b/dis88/Makefile
index 9e82095..520becc 100644
--- a/dis88/Makefile
+++ b/dis88/Makefile
@@ -27,6 +27,7 @@
#CC=bcc
CFLAGS=-O
LDFLAGS=
+BINDIR=/usr/bin
OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o
@@ -36,8 +37,8 @@ dis88: $(OBJ)
$(CC) $(LDFLAGS) -o dis88 $(OBJ)
install: dis88
- install -m 755 -s dis88 $(DIST)/usr/bin/dis88
- install -m 644 dis88.1 $(DIST)/usr/man/man1/dis88.1
+ install -m 755 -s dis88 $(DIST)$(BINDIR)/dis86
+ install -m 644 dis88.1 $(DIST)/usr/man/man1/dis86.1
$(OBJ): dis.h a.out.h
diff --git a/elksemu/Makefile b/elksemu/Makefile
index 2de8673..df7b08a 100644
--- a/elksemu/Makefile
+++ b/elksemu/Makefile
@@ -42,7 +42,7 @@ module: binfmt_elks.o
# HOW to compile the module...
-# This matches my compile (2.0.0); yours may be different.
+# This matches my compile (2.0.x); yours may be different.
MODCFLAGS=-D__KERNEL__ -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \
-fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE -DMODVERSIONS \
-include /usr/include/linux/modversions.h
diff --git a/elksemu/elks.h b/elksemu/elks.h
index 6d52470..5da93a1 100644
--- a/elksemu/elks.h
+++ b/elksemu/elks.h
@@ -94,3 +94,4 @@ extern volatile struct vm86_struct elks_cpu;
void db_printf(const char *, ...);
int elks_syscall(void);
+void minix_syscall(void);
diff --git a/elksemu/minix.c b/elksemu/minix.c
index 0c0ad67..86a966f 100644
--- a/elksemu/minix.c
+++ b/elksemu/minix.c
@@ -1,9 +1,3 @@
-
-/*
- * System calls are mostly pretty easy as the emulator is tightly bound to
- * the minix task.
- */
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/ifdef.c b/ifdef.c
index 0837864..adb7cae 100644
--- a/ifdef.c
+++ b/ifdef.c
@@ -167,6 +167,7 @@ char * fname;
}
}
fclose(fd);
+ if( iflevel != 0 ) fatal("Not enough endif's");
}
void
@@ -322,6 +323,14 @@ manifest_constant()
#ifdef GNUMAKE
save_name("GNUMAKE", 'D');
#endif
+ if( sizeof(int) < 4 )
+ save_name("__SMALL_INTS__", 'D');
+ if( sizeof(char *) <= 2 )
+ save_name("__SMALL_MEMORY__", 'D');
+ if( sizeof(long) == 4 )
+ save_name("__LONG_32_BIT__", 'D');
+ if( sizeof(int) == 8 )
+ save_name("__LONG_64_BIT__", 'D');
/* MSDOS */
#ifdef MSDOS
diff --git a/ld/Makefile b/ld/Makefile
index 2e30d96..9e1f124 100644
--- a/ld/Makefile
+++ b/ld/Makefile
@@ -1,7 +1,7 @@
LIBDIR =/usr/bin
CFLAGS =-O
-LDFLAGS =-s
+LDFLAGS =
# May need some of these if the auto-sense fails.
# -DV7_A_OUT # a.out.h is like V7
@@ -18,7 +18,7 @@ DEFS =-DREL_OUTPUT -DBUGCOMPAT
OBJS= dumps.o io.o ld.o readobj.o table.o typeconv.o linksyms.o \
writex86.o writebin.o writerel.o
-all: ld86
+all: ld86 objchop
ld86: $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o $@
@@ -28,7 +28,7 @@ install: ld86
install -m 755 ld86 $(LIBDIR)
clean realclean:
- rm -f $(OBJS) ld86
+ rm -f *.o ld86 objchop
$(OBJS): align.h ar.h bindef.h byteord.h config.h const.h globvar.h obj.h \
syshead.h type.h x86_aout.h
diff --git a/ld/io.c b/ld/io.c
index 39fc6a0..a21ecd3 100644
--- a/ld/io.c
+++ b/ld/io.c
@@ -121,8 +121,10 @@ int level;
PUBLIC void executable()
{
+#ifndef MSDOS
if (errcount == 0)
chmod(outputname, outputperms);
+#endif
}
PUBLIC void flusherr()
@@ -179,15 +181,18 @@ char *filename;
outputname = filename;
#ifdef O_BINARY
- if ((outfd = open(filename, O_BINARY|O_RDWR|O_CREAT|O_TRUNC, CREAT_PERMS)) == ERR)
+ if ((outfd = open(filename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, CREAT_PERMS)) == ERR)
#else
if ((outfd = creat(filename, CREAT_PERMS)) == ERR)
#endif
outputerror("cannot open");
+#ifndef MSDOS
+ /* Can't do this on MSDOS; it upsets share.exe */
oldmask = umask(0); umask(oldmask);
outputperms = ((CREAT_PERMS | EXEC_PERMS) & ~oldmask);
chmod(filename, outputperms & ~EXEC_PERMS);
+#endif
#ifdef REL_OUTPUT
drelbufptr = drelbuf;
diff --git a/ld/objchop.c b/ld/objchop.c
new file mode 100644
index 0000000..c5a81e4
--- /dev/null
+++ b/ld/objchop.c
@@ -0,0 +1,87 @@
+
+#include <stdio.h>
+#include "x86_aout.h"
+
+#ifndef __OUT_OK
+
+main()
+{
+ fprintf(stderr, "Compile error: struct exec invalid\n");
+ exit(1);
+}
+
+#else
+
+FILE * ifd;
+struct exec header;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ FILE * ofd;
+ if( argc != 5 ) fatal("Usage: objchop a.out text.bin data.bin sizes.asm");
+
+ ifd = fopen(argv[1], "r");
+ if( ifd == 0 ) fatal("Cannot open input file");
+
+ if( fread(&header, A_MINHDR, 1, ifd) != 1 )
+ fatal("Incomplete executable header");
+
+ if( BADMAG(header) )
+ fatal("Input file has bad magic number");
+
+ if( fseek(ifd, A_TEXTPOS(header), 0) < 0 )
+ fatal("Cannot seek to start of text");
+
+ write_file(argv[2], header.a_text);
+
+ if( fseek(ifd, A_DATAPOS(header), 0) < 0 )
+ fatal("Cannot seek to start of data");
+
+ write_file(argv[3], header.a_data);
+
+ ofd = fopen(argv[4], "w");
+ if( ofd == 0 ) fatal("Cannot open output file");
+
+ fprintf(ofd, "TEXT_SIZE=%ld\nDATA_SIZE=%ld\nBSS_SIZE=%ld\nALLOC_SIZE=%ld\n",
+ header.a_text, header.a_data, header.a_bss, header.a_total);
+
+ fclose(ofd);
+
+ exit(0);
+}
+
+write_file(fname, bsize)
+char * fname;
+long bsize;
+{
+ char buffer[1024];
+ int ssize;
+ FILE * ofd;
+
+ ofd = fopen(fname, "w");
+ if( ofd == 0 ) fatal("Cannout open output file");
+
+ while(bsize>0)
+ {
+ if( bsize > sizeof(buffer) ) ssize = sizeof(buffer);
+ else ssize = bsize;
+
+ if( (ssize=fread(buffer, 1, ssize, ifd)) <= 0 )
+ fatal("Error reading segment from executable");
+ if( fwrite(buffer, 1, ssize, ofd) != ssize )
+ fatal("Error writing output file");
+ bsize -= ssize;
+ }
+ fclose(ofd);
+}
+
+fatal(str)
+char * str;
+{
+ fprintf(stderr, "objchop: %s\n", str);
+ exit(2);
+}
+
+#endif
diff --git a/ld/typeconv.c b/ld/typeconv.c
index 6cc4a20..708d92b 100644
--- a/ld/typeconv.c
+++ b/ld/typeconv.c
@@ -156,6 +156,8 @@ unsigned count;
{
switch (count)
{
+ case 0:
+ return 0;
case 1:
return buf[0] & 0xFF;
case 2:
@@ -174,6 +176,8 @@ unsigned count;
{
switch (count)
{
+ case 0:
+ return 0;
case 1:
return buf[0] & 0xFF;
case 2:
diff --git a/ld/x86_aout.h b/ld/x86_aout.h
index af2c537..777f281 100644
--- a/ld/x86_aout.h
+++ b/ld/x86_aout.h
@@ -9,7 +9,7 @@
#define __AOUT_H
/* If the host isn't an x86 all bets are off, use chars. */
-#if defined(i386) || defined(__BCC__)
+#if defined(i386) || defined(__BCC__) || defined(MSDOS)
typedef long Long;
#define __OUT_OK 1
#else
diff --git a/libc/Config.dflt b/libc/Config.dflt
new file mode 100644
index 0000000..b2a79b0
--- /dev/null
+++ b/libc/Config.dflt
@@ -0,0 +1,17 @@
+bcc:+:
+bios:+:
+error:+:
+getent:+:
+gtermcap:+:
+i386fp:+:
+i386sys:+:
+kinclude:+:
+malloc1:+:
+misc:+:
+msdos:+:
+regexp:+:
+stdio2:+:
+string:+:
+syscall:+:
+termios:+:
+time:+:
diff --git a/libc/Config_sh b/libc/Config_sh
index 4beff3e..0b65992 100644
--- a/libc/Config_sh
+++ b/libc/Config_sh
@@ -6,14 +6,16 @@
main()
{
rm -f .config.tmp
- ALLON=no
+ ALLON=yes
- if [ -f .config.lst ]
+ if [ "$ALLON" = yes -a -f .config.lst ]
then grep '^[^:]*:+:' .config.lst > .config.tmp
- if [ ! -s .config.tmp ]
- then ALLON=yes
- fi
- else ALLON=yes
+ [ -s .config.tmp ] && ALLON=no
+ fi
+
+ if [ "$ALLON" = yes -a -f Config.dflt ]
+ then grep '^[^:]*:+:' Config.dflt > .config.tmp
+ [ -s .config.tmp ] && ALLON=no
fi
egrep -v '^#|^$' /dev/null */[Cc]onfig | \
diff --git a/libc/Makefile b/libc/Makefile
index 593eaab..436c3c6 100644
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -11,7 +11,7 @@ endif
VERMAJOR=0
VERMINOR=12
-VERPATCH=0
+VERPATCH=4
VER=$(VERMAJOR).$(VERMINOR).$(VERPATCH)
CC=bcc
@@ -44,7 +44,8 @@ crt0.o: crt0.c Makefile
$(CC) -c $(CFLAGS) -D__LIBC_VER__='"$(VER)"' -o $@ crt0.c
crtX.o:
- @echo "You need to define the 'PLATFORM=...' variable"
+ @echo "You need to define the 'PLATFORM=...' variable,"
+ @echo "Preferably by doing make from `dirname \`pwd\``"
@exit 1
############################################################################
diff --git a/libc/gtermcap/Config b/libc/gtermcap/Config
new file mode 100644
index 0000000..659749e
--- /dev/null
+++ b/libc/gtermcap/Config
@@ -0,0 +1 @@
+gtermcap:GNU termcap routines
diff --git a/libc/misc/cputype.c b/libc/misc/cputype.c
index 8417514..d9c3e01 100644
--- a/libc/misc/cputype.c
+++ b/libc/misc/cputype.c
@@ -1,4 +1,8 @@
-/*
+/* Copyright (C) 1989,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the terms of the GNU Library General Public License.
+ **********************************************************************
+ *
* This does a determination of the cpu type that is actually being used.
* It can determine the CPU on anything upto and including a 386 accuratly
* whatever mode the CPU is in (This is 16 bit code)
@@ -12,18 +16,6 @@
* $ cputype # Call cputype(0) and interpret
* $ cputype + # Call cputype(1) get a SIGILL (or perhaps interpret)
*
- * NOTE: This code is COPYRIGHT and not under the GNU Lib copyright, this
- * may be distributed freely as source or as a standalone binary
- * compiled from this unmodified source.
- *
- * You may use the cputype() function in your own personal code.
- * You may distribute a binary version of code containing the
- * cputype() function if either you distribute this source with
- * the binary version or distribute a clear reference to a freely
- * available copy of this source code and the source code to the
- * rest of your package with the binary version of the package.
- *
- * (C) Copyright R de Bath 1989-1996
*/
#ifdef STANDALONE
diff --git a/libc/stdio1/BUGS b/libc/stdio1/BUGS
new file mode 100644
index 0000000..0e8e0db
--- /dev/null
+++ b/libc/stdio1/BUGS
@@ -0,0 +1,15 @@
+Error checking is known to be wanting. However the author just wants to
+get it working right now.
+
+fread() and fwrite() are not supported. open(), read(), write(), and close()
+work very well for binary data.
+
+fopen() is the only way to open a file. None of the temp stuff is supported,
+and frepon() is unsupported.
+
+GNU extensions are unsupported.
+
+Some printf specifications may not work. Read the code for details of what
+IS supported.
+
+Other than that, this should be a perfectly normal stdio lib when it's finished.
diff --git a/libc/stdio1/Config b/libc/stdio1/Config
new file mode 100644
index 0000000..3b3b35f
--- /dev/null
+++ b/libc/stdio1/Config
@@ -0,0 +1,3 @@
+
+
+stdio: Joel's stdio package altered by Nat
diff --git a/libc/stdio1/NOTICE b/libc/stdio1/NOTICE
new file mode 100644
index 0000000..25ca5b6
--- /dev/null
+++ b/libc/stdio1/NOTICE
@@ -0,0 +1,17 @@
+/*
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
diff --git a/libc/stdio1/README b/libc/stdio1/README
new file mode 100644
index 0000000..ead7846
--- /dev/null
+++ b/libc/stdio1/README
@@ -0,0 +1,8 @@
+I found that it was helpful to have the extern stuff actually defined in
+one file as not external...
+
+Still trying to find the other problems
+
+Whether it is desireable to list stdio.h as a dependency is debateable
+
+-Joel
diff --git a/libc/stdio1/TODO b/libc/stdio1/TODO
new file mode 100644
index 0000000..481f6d9
--- /dev/null
+++ b/libc/stdio1/TODO
@@ -0,0 +1,33 @@
+Sun Jan 21 18:16:03 EST 1996 -- Nat Friedman
+============================================
+I've made a load of changes to this code, but there's still a lot to be done.
+- scanf, fscanf
+
+
+
+
+input, file positioning, eof, declarations of functions, printf
+
+look for unsigned char references
+
+specifically
+fix printf and figure out what's going on in there.
+write idealgetline, scanf, other stuff
+then deal with above stuff...
+
+
+LATEST LIST:
+printf, fprintf
+scanf, fscanf
+feof
+seek support
+error handling (not too hard since system calls only in a few places)
+atexit stuff (close files; will need to add a linked list of files)
+setvbuf if desired
+check that fopen() and stdio_init() fill in ALL the fields
+testing!
+
+rm NOTICE
+
+
+
diff --git a/libc/stdio1/__ffillbuf.c b/libc/stdio1/__ffillbuf.c
new file mode 100644
index 0000000..e705cbf
--- /dev/null
+++ b/libc/stdio1/__ffillbuf.c
@@ -0,0 +1,55 @@
+/* simplified linux __ffillbuf.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <unistd.h>
+#include "stdio.h"
+
+/* this function makes the mistake of assuming the buffer really DOES
+need to be filled. */
+
+/* RDB:
+ * Added simple processing for EOF and errors
+ * As this is _only_ called from getc() the memory footprint is smaller
+ * if it pretends to be getc in the complex case.
+ */
+
+int
+__ffillbuf(stream)
+FILE *stream;
+{
+ int stat;
+
+ if( stream->fd < 0 || ferror(stream) ) return EOF;
+
+ stat = read(stream->fd, (char *) stream->bufstart, stream->bufend - stream->bufstart);
+ if( stat > 0 )
+ stream->bufread = stream->bufstart + stat;
+ else if( stat == 0 )
+ {
+ stream->fc_eof = 1;
+ return EOF;
+ }
+ else
+ {
+ stream->fc_err = 1;
+ return EOF;
+ }
+
+ stream->bufpos = stream->bufstart;
+
+ return getc(stream);
+}
diff --git a/libc/stdio1/__stdio_init.c b/libc/stdio1/__stdio_init.c
new file mode 100644
index 0000000..b49bb28
--- /dev/null
+++ b/libc/stdio1/__stdio_init.c
@@ -0,0 +1,66 @@
+/* simplified linux __stdio_init.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "stdio.h"
+
+/*
+ OK, Complete hackup here, I've removed the need for the init function.
+ Not also I've make the types into 'unsigned char' this is so it doesn't
+ return EOF when it really means '\377'
+ */
+
+static unsigned char __stdinbuf[BUFSIZ], __stdoutbuf[BUFSIZ], __stderrbuf[80];
+
+static FILE __the_stdin = {
+ 0,
+ __stdinbuf,
+ __stdinbuf,
+ __stdinbuf,
+ __stdinbuf+sizeof(__stdinbuf),
+ _IOLBF,
+ _MODE_READ,
+ 0, 0,
+ 0, 0, 1
+};
+
+static FILE __the_stdout = {
+ 1,
+ __stdoutbuf,
+ __stdoutbuf,
+ __stdoutbuf,
+ __stdoutbuf+sizeof(__stdoutbuf),
+ _IOLBF,
+ _MODE_WRITE,
+ 0, 0,
+ 0, 0, 1
+};
+
+static FILE __the_stderr = {
+ 2,
+ __stderrbuf,
+ __stderrbuf,
+ __stderrbuf,
+ __stderrbuf+sizeof(__stderrbuf),
+ _IOLBF,
+ _MODE_WRITE,
+ 0, 0,
+ 0, 0, 1
+};
+
+FILE *stdin = &__the_stdin,
+ *stdout = &__the_stdout,
+ *stderr = &__the_stderr;
diff --git a/libc/stdio1/fclose.c b/libc/stdio1/fclose.c
new file mode 100644
index 0000000..7ec233e
--- /dev/null
+++ b/libc/stdio1/fclose.c
@@ -0,0 +1,41 @@
+/* simplified linux fclose.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <unistd.h>
+#include "stdio.h"
+
+int fclose (stream)
+FILE *stream;
+{
+ /* only allow fclose() on what was fopen()ed. */
+ /*
+ This isn't right, there's nothing wrong with fclosing stdin
+ but the next fopen/open will be given fd 0 and so become stdin
+ Of course you do have to be a little careful :-)
+ RDB
+ */
+
+ if ((stream == stdin) || (stream == stdout) || (stream == stderr)) return EOF;
+
+ if (fflush(stream)) return EOF;
+
+ if (close(stream->fd)) return EOF;
+
+ free(stream->bufstart);
+ free(stream);
+ return 0;
+}
diff --git a/libc/stdio1/fcntl.h b/libc/stdio1/fcntl.h
new file mode 100644
index 0000000..69fdb90
--- /dev/null
+++ b/libc/stdio1/fcntl.h
@@ -0,0 +1,72 @@
+#ifndef __FCNTL_H
+#define __FCNTL_H
+
+/*
+ * Definitions taken from the i386 Linux kernel.
+ */
+
+/* open/fcntl */
+
+#define O_ACCMODE 0003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100 /* not fcntl */
+#define O_EXCL 0200 /* not fcntl */
+#define O_NOCTTY 0400 /* not fcntl */
+#define O_TRUNC 01000 /* not fcntl */
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_NDELAY O_NONBLOCK
+#if 0
+#define O_SYNC 010000 /* Not supported */
+#define FASYNC 020000 /* Not supported */
+#endif
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get f_flags */
+#define F_SETFD 2 /* set f_flags */
+#define F_GETFL 3 /* more flags (cloexec) */
+#define F_SETFL 4
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#ifdef __KERNEL__
+#define F_POSIX 1
+#define F_FLOCK 2
+#endif /* __KERNEL__ */
+
+#if 0
+struct flock {
+ short l_type;
+ short l_whence;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+};
+#endif
+
+#endif
diff --git a/libc/stdio1/fflush.c b/libc/stdio1/fflush.c
new file mode 100644
index 0000000..c9cdac7
--- /dev/null
+++ b/libc/stdio1/fflush.c
@@ -0,0 +1,36 @@
+/* simplified linux fflush.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <unistd.h>
+#include "stdio.h"
+
+int fflush(stream)
+FILE *stream;
+{
+ if (stream == 0) return 0;
+ if ((stream->file_mode == _MODE_WRITE)
+ ||(stream->file_mode == (_MODE_WRITE & _MODE_RDWR))){
+ write(stream->fd, (char *) stream->bufstart,
+ stream->bufpos - stream->bufstart);
+ stream->bufpos = stream->bufstart;
+ }
+ return 0;
+}
+/* TODO: return EOF or 0; support NULL stream */
+/* The only place an error can come from is the write; you're not checking RDB
+ */
diff --git a/libc/stdio1/fgetc.c b/libc/stdio1/fgetc.c
new file mode 100644
index 0000000..2c41062
--- /dev/null
+++ b/libc/stdio1/fgetc.c
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "stdio.h"
+
+/*
+ * Make this not dependent on getc() then we can:
+ #define getc(fp) fgetc(fp)
+ * if memory is _really_ tight.
+ */
+
+int fgetc(stream)
+FILE *stream;
+{
+ if( stream->ungetted )
+ {
+ stream->ungetted = 0;
+ return stream->ungetchar;
+ }
+ if( stream->bufpos == stream->bufread )
+ return __ffillbuf(stream);
+ else
+ return *stream->bufpos++;
+}
diff --git a/libc/stdio1/fgets.c b/libc/stdio1/fgets.c
new file mode 100644
index 0000000..c085970
--- /dev/null
+++ b/libc/stdio1/fgets.c
@@ -0,0 +1,50 @@
+/* fgets.c for limited linux stdio
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "stdio.h"
+
+/*
+ RDB BZZZT! This should only read upto and including any newline!
+*/
+
+char *fgets(s, count, f)
+char *s;
+size_t count;
+FILE *f;
+{
+ char *ret;
+ register size_t i;
+ register int ch;
+
+ ret = s;
+ for(i=count; i>0; i--)
+ {
+ ch = getc(f);
+ if( ch == EOF )
+ {
+ if(s==ret) return 0;
+ break;
+ }
+ *s++ = (char) ch;
+ if( ch == '\n' ) break;
+ }
+ *s = 0;
+
+ if( ferror(f) ) return 0;
+ return ret;
+}
diff --git a/libc/stdio1/fopen.c b/libc/stdio1/fopen.c
new file mode 100644
index 0000000..1265ff5
--- /dev/null
+++ b/libc/stdio1/fopen.c
@@ -0,0 +1,80 @@
+/* simplified linux fopen.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "stdio.h"
+#include <malloc.h>
+
+FILE * fopen(name, openmode)
+char *name;
+char *openmode;
+{
+ FILE *new;
+ int openplus=0;
+ char basemode;
+
+ basemode = openmode[0];
+ while (openmode[0] != 0){
+ switch(openmode[0]){
+ case '+': openplus=1; break;
+ }
+ openmode++;
+ }
+
+ new = malloc(sizeof(new));
+ if( new == 0 ) return 0;
+ new->bufread = new->bufpos = new->bufstart = malloc(BUFSIZ);
+ if( new->bufstart == 0 ) { free(new) ; return 0; }
+
+ new->bufend = new->bufstart + BUFSIZ;
+ new->buffer_mode = _IOFBF;
+ new->iotrans = 0;
+ new->fd = -1;
+ if (openplus){
+ new->file_mode = _MODE_RDWR;
+ switch (basemode){
+ case 'a':
+ new->fd = open(name, O_RDWR | O_APPEND | O_CREAT);
+ break;
+ case 'r':
+ new->fd = open(name, O_RDWR);
+ break;
+ case 'w':
+ new->fd = open(name, O_RDWR | O_TRUNC | O_CREAT);
+ break;
+ }
+ } else switch (basemode){
+ case 'a':
+ new->fd = open(name, O_WRONLY | O_APPEND | O_CREAT);
+ new->file_mode = _MODE_WRITE;
+ break;
+ case 'r':
+ new->fd = open(name, O_RDONLY);
+ new->file_mode = _MODE_READ;
+ break;
+ case 'w':
+ new->fd = open(name, O_WRONLY | O_TRUNC | O_CREAT);
+ new->file_mode = _MODE_WRITE;
+ break;
+ }
+ if( new->fd < 0 )
+ {
+ free(new->bufstart);
+ free(new);
+ return 0;
+ }
+ return new;
+}
diff --git a/libc/stdio1/fputc.c b/libc/stdio1/fputc.c
new file mode 100644
index 0000000..939a721
--- /dev/null
+++ b/libc/stdio1/fputc.c
@@ -0,0 +1,53 @@
+/* simplified linux fputc.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "stdio.h"
+
+/*
+ * Make this not dependent on putc() then we can:
+ #define putc(c, fp) fputc(c, fp)
+ * if memory is _really_ tight.
+ */
+
+#undef putc
+#define putc(c, stream) \
+ (((stream)->bufpos[0] = (c)), \
+ ((stream)->bufpos++), \
+ ((((stream)->bufpos == (stream)->bufend) \
+ ||((stream)->buffer_mode == _IONBF) \
+ ||(((stream)->buffer_mode == _IOLBF) \
+ && ((stream)->bufpos != (stream)->bufstart) \
+ && ((stream)->bufpos[-1] == '\n'))) \
+ ? fflush(stream):0))
+
+#define new_putc(c, stream) \
+ ((unsigned char)( \
+ ((stream)->bufpos>=(stream)->bufread) ? fputc((c), (stream)) \
+ : *(stream)->bufpos++ = (c) \
+ ))
+
+int
+fputc(int c, FILE * stream)
+{
+#ifdef __MSDOS__
+ if( c == '\n' && stream->iotrans ) fputc('\r', stream);
+#endif
+ return putc(c, stream);
+}
+
+
+
diff --git a/libc/stdio1/fputs.c b/libc/stdio1/fputs.c
new file mode 100644
index 0000000..41e2998
--- /dev/null
+++ b/libc/stdio1/fputs.c
@@ -0,0 +1,32 @@
+/* simplified linux fputs.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <unistd.h>
+#include <string.h>
+#include "stdio.h"
+
+int
+fputs(__const char * string, FILE * stream)
+{
+ if (stream->buffer_mode != _IONBF){
+ while (string[0] != 0){
+ putc(string[0], stream);
+ string++;
+ }
+ } else write(stream->fd, string, strlen(string));
+ return 0;
+}
diff --git a/libc/stdio1/idealgetline.c b/libc/stdio1/idealgetline.c
new file mode 100644
index 0000000..7eacc9e
--- /dev/null
+++ b/libc/stdio1/idealgetline.c
@@ -0,0 +1,67 @@
+/* idealgetline.c -- my idea of an ideal getline function for stdio
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* I actually intend to use this in 32 bit programs, unlike the other stuff
+ in this lib. IMHO GNU getline is broken. It is too hard to use.
+
+ Just pass this function a FILE * and it will retrieve a line for you using
+ getc(). It will realloc() exactly the amount of memory needed, and will
+ generate error messages for non-ascii characters on stderr.
+
+ This may not be your ideal. It probably generates far too many errors.
+ It doesn't work well for those who don't use English (but since
+ Linux-less-than-32 libc and kernels are each being produced by one
+ person in the US and one in the UK, this isn't a problem). It probably
+ is not what you (or I) want for interactive input.
+
+ You're welcome to modify this routine to meet your needs. However, if
+ you change the semantics significantly, please change the name.
+
+ (Maybe I should have put my own name on it so there will be no confusion
+ about who thought it was ideal). */
+
+#include <stdio.h>
+#include <malloc.h>
+
+char *idealgetline(f)
+FILE *f;
+{
+ char c;
+ char *ret;
+ int size = 0, bufsize = 256;
+
+ ret = malloc(256);
+ c = getc(f);
+ while ((c != EOF) && (c != '\n')){
+ if ((c >= ' ') && (c <= 126)){
+ ret[size] = c;
+ size++;
+ if (size == bufsize){
+ bufsize += 256;
+ ret = realloc(ret, bufsize);
+ }
+ } else {
+ fprintf(stderr, "Unexpected character 0x%x encountered in input", c);
+ free(ret);
+ return 0;
+ }
+ }
+ ret[size] = '\0';
+ size++;
+ return realloc(ret, size);
+}
diff --git a/libc/stdio1/makefile b/libc/stdio1/makefile
new file mode 100644
index 0000000..d8058b0
--- /dev/null
+++ b/libc/stdio1/makefile
@@ -0,0 +1,36 @@
+TOP=..
+include $(TOP)/Make.defs
+OBJ = __ffillbuf.o __stdio_init.o fflush.o fgetc.o fgets.o \
+ fputc.o fputs.o puts.o printf.o fopen.o fclose.o scanf.o
+
+#missing functions from above: printf etc, scanf etc, idealgetline
+#seek
+
+#fopen.c, fclose.c removed because of malloc() use
+
+CFLAGS+=$(WALL)
+
+ifeq ($(PLATFORM),i86-ELKS)
+CFLAGS=$(CCFLAGS) $(DEFS) -ansi
+endif
+
+all: $(OBJ)
+
+libc.a: $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+$(OBJ): stdio.h
+
+test: test.o $(OBJ)
+ $(CC) -o test test.o $(OBJ)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ $< -c
+
+clean:
+ rm -f *.o test libc.a
+
+transfer:
+ -@rm -f ../include/stdio.h
+ cp -p stdio.h ../include/.
diff --git a/libc/stdio1/old_printf.c b/libc/stdio1/old_printf.c
new file mode 100644
index 0000000..81d62ac
--- /dev/null
+++ b/libc/stdio1/old_printf.c
@@ -0,0 +1,230 @@
+/* fprintf.c for limited Linux libc
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* Thanks Alan for writing the hard routine for me :-)
+ * Alan said that this works "most of the time". Something tells me I'm making
+ * it even worse! */
+/* The basic idea here is to make fprintf the core routine. printf obviously
+ can just call fprintf with stdout followed by all of its arguments.
+ sprintf() works using the fake file &the_sprintf. It's marked as fully
+ buffered, so that it will only write(2) when &the_sprintf->bufpos ==
+ &the_sprintf->bufend, which I doubt will happen since &the_sprintf->bufend
+ = 0. The trick is that sprintf must set &the_sprintf->bufstart =
+ &the_sprintf->bufpos = its first argument. Not as orthagonal (is that
+ the right word?) as glibc's facilities for non-files, but this isn't a
+ library for people who have unlimited RAM budgets. (not like the libc
+ I use on linux/i586 enjoys an unlimited RAM budget either; I only have
+ 8 MB
+
+ I'm not sure what the "correct" way to pass the variable arguments
+ from one function to the next is. Rather than pass the arguments
+ themselves, I'm passing a pointer to them. However, the following
+ explaination from Alan is probably a polite way of saying it will not
+ work on a 386 anyway.
+ Joel Weber
+
+ [ I've migrated all of this code over to the ELKS stdarg that I wrote.
+ The accepted way to do it is for the wrapper function to accept a
+ variable number of arguments, use stdarg to make an argument pointer,
+ and then pass the argument pointer on to the core function, as I've
+ done here. This should definitely work on a 386, as the arguments
+ are still passed in the stack, and stack order is maintained. -Nat ]
+ */
+
+/*
+ * This is NOT stunningly portable, but works
+ * for pretty dumb non ANSI compilers and is
+ * tight. Adjust the sizes to taste.
+ *
+ * Illegal format strings will break it. Only the
+ * following simple subset is supported
+ *
+ * %x - hex
+ * %d - decimal
+ * %s - string
+ * %c - char
+ *
+ * And the h/l length specifiers for %d/%x
+ *
+ * Alan Cox.
+ */
+
+#include <stdarg.h>
+#include "stdio.h"
+
+/* 17 to make sure that there's room for the trailing newline.
+ I'm not really sure if this is ideal... */
+static char nstring[17]="0123456789ABCDEF";
+
+static unsigned char *
+__numout(long i, int base)
+{
+ static unsigned char out[16];
+ int n;
+ int flg = 0;
+ unsigned long val;
+
+ if (i<0 && base==10)
+ {
+ flg = 1;
+ i = -i;
+ }
+ val = i;
+
+ for (n = 0; n < 15; n++)
+ out[n] = ' ';
+ out[15] = '\0';
+ n = 14;
+ do{
+ out[n] = nstring[val % base];
+ n--;
+ val /= base;
+ }
+ while(val);
+ if(flg) out[n--] = '-';
+ return &out[n+1];
+}
+
+static int
+internal_fprintf(FILE * stream, __const char * fmt, va_list ap)
+{
+ register int c;
+ int count = 0;
+ int type, base;
+
+ while(c=*fmt++)
+ {
+ if(c!='%')
+ {
+ putc(c, stream);
+ count++;
+ }
+ else
+ {
+ type=1;
+ do { c=*fmt++; } while( c=='.' || (c>='0' && c<='9'));
+ if( c == 0 ) break;
+ if(c=='h')
+ {
+ c=*fmt++;
+ type = 0;
+ }
+ else if(c=='l')
+ {
+ c=*fmt++;
+ type = 2;
+ }
+
+ switch(c)
+ {
+ case 'x':
+ case 'o':
+ case 'd':
+ if (c=='x') base=16;
+ if (c=='o') base=8;
+ if (c=='d') base=10;
+ {
+ long val=0;
+ switch(type)
+ {
+ case 0:
+ val=va_arg(ap, short);
+ break;
+ case 1:
+ val=va_arg(ap, int);
+ break;
+ case 2:
+ val=va_arg(ap, long);
+ break;
+ }
+ fputs((__const char *)__numout(val,base),stream);
+ }
+ break;
+ case 's':
+ {
+ char *cp;
+ cp=va_arg(ap, char *);
+ while(*cp)
+ putc(*cp++, stream);
+ break;
+ }
+ case 'c':
+ putc(va_arg(ap, int), stream);
+ break;
+ default:
+ putc(c, stream);
+ }
+ }
+ }
+ return count;
+}
+
+
+int
+fprintf(FILE * stream, __const char * fmt, ...)
+{
+ va_list ap;
+ int retval;
+ va_start(ap, fmt);
+ retval=internal_fprintf(stream, fmt, ap);
+ va_end(ap);
+ return(retval);
+}
+
+int
+printf(__const char * fmt, ...)
+{
+ va_list ap;
+ int retval;
+ va_start(ap, fmt);
+ retval=internal_fprintf(stdout, fmt, ap);
+ va_end(ap);
+ return(retval);
+}
+
+/* This is a strange way of doing sprintf, but it should work */
+int sprintf(char * s, __const char * fmt, ...)
+{
+ static FILE the_sprintf = {
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ _IOFBF,
+ _MODE_WRITE,
+ 0, 0,
+ 0, 0};
+ va_list ap;
+ int retval;
+
+ va_start(ap, fmt);
+ the_sprintf.bufstart = the_sprintf.bufpos = (unsigned char *) s;
+ the_sprintf.fc_err = 0;
+
+ retval = internal_fprintf(&the_sprintf, fmt, ap);
+ /* null-terminate the string */
+ putc('\0', &the_sprintf);
+
+ va_end(ap);
+ return retval;
+}
+
+
+
+
+
diff --git a/libc/stdio1/printf.c b/libc/stdio1/printf.c
new file mode 100644
index 0000000..f2a39bd
--- /dev/null
+++ b/libc/stdio1/printf.c
@@ -0,0 +1,649 @@
+/* fprintf.c for limited Linux libc
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* Thanks Alan for writing the hard routine for me :-)
+ * Alan said that this works "most of the time". Something tells me I'm making
+ * it even worse! */
+/* The basic idea here is to make fprintf the core routine. printf obviously
+ can just call fprintf with stdout followed by all of its arguments.
+ sprintf() works using the fake file &the_sprintf. It's marked as fully
+ buffered, so that it will only write(2) when &the_sprintf->bufpos ==
+ &the_sprintf->bufend, which I doubt will happen since &the_sprintf->bufend
+ = 0. The trick is that sprintf must set &the_sprintf->bufstart =
+ &the_sprintf->bufpos = its first argument. Not as orthagonal (is that
+ the right word?) as glibc's facilities for non-files, but this isn't a
+ library for people who have unlimited RAM budgets. (not like the libc
+ I use on linux/i586 enjoys an unlimited RAM budget either; I only have
+ 8 MB
+
+ I'm not sure what the "correct" way to pass the variable arguments
+ from one function to the next is. Rather than pass the arguments
+ themselves, I'm passing a pointer to them. However, the following
+ explaination from Alan is probably a polite way of saying it will not
+ work on a 386 anyway.
+ Joel Weber
+
+ [ I've migrated all of this code over to the ELKS stdarg that I wrote.
+ The accepted way to do it is for the wrapper function to accept a
+ variable number of arguments, use stdarg to make an argument pointer,
+ and then pass the argument pointer on to the core function, as I've
+ done here. This should definitely work on a 386, as the arguments
+ are still passed in the stack, and stack order is maintained. -Nat ]
+ */
+
+/*
+ * This is NOT stunningly portable, but works
+ * for pretty dumb non ANSI compilers and is
+ * tight. Adjust the sizes to taste.
+ *
+ * Illegal format strings will break it. Only the
+ * following simple subset is supported
+ *
+ * %x - hex
+ * %d - decimal
+ * %s - string
+ * %c - char
+ *
+ * And the h/l length specifiers for %d/%x
+ *
+ * Alan Cox.
+ */
+
+#include <stdarg.h>
+#include "stdio.h"
+
+/* 17 to make sure that there's room for the trailing newline.
+ I'm not really sure if this is ideal... */
+static char nstring[17]="0123456789ABCDEF";
+
+static unsigned char *
+__numout(long i, int base)
+{
+ static unsigned char out[16];
+ int n;
+ int flg = 0;
+ unsigned long val;
+
+ if (i<0 && base==10)
+ {
+ flg = 1;
+ i = -i;
+ }
+ val = i;
+
+ for (n = 0; n < 15; n++)
+ out[n] = ' ';
+ out[15] = '\0';
+ n = 14;
+ do{
+ out[n] = nstring[val % base];
+ n--;
+ val /= base;
+ }
+ while(val);
+ if(flg) out[n--] = '-';
+ return &out[n+1];
+}
+
+int
+fprintf(FILE * stream, __const char * fmt, ...)
+{
+ va_list ap;
+ int retval;
+ va_start(ap, fmt);
+ retval=internal_fprintf(stream, fmt, ap);
+ va_end(ap);
+ return(retval);
+}
+
+int
+printf(__const char * fmt, ...)
+{
+ va_list ap;
+ int retval;
+ va_start(ap, fmt);
+ retval=internal_fprintf(stdout, fmt, ap);
+ va_end(ap);
+ return(retval);
+}
+
+/* This is a strange way of doing sprintf, but it should work */
+int sprintf(char * s, __const char * fmt, ...)
+{
+ static FILE the_sprintf = {
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ _IOFBF,
+ _MODE_WRITE,
+ 0, 0,
+ 0, 0};
+ va_list ap;
+ int retval;
+
+ va_start(ap, fmt);
+ the_sprintf.bufstart = the_sprintf.bufpos = (unsigned char *) s;
+ the_sprintf.fc_err = 0;
+
+ retval = internal_fprintf(&the_sprintf, fmt, ap);
+ /* null-terminate the string */
+ putc('\0', &the_sprintf);
+
+ va_end(ap);
+ return retval;
+}
+
+
+
+
+
+/*
+ * printf.c - This is the more complete fprintf() replacement for libc8086
+ * Copyright (C) 1996 Steven Huang <sthuang@hns.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+/*
+ * This decides if the little test main program gets included
+ */
+#undef TEST
+/*
+ * This decides if printf() should act like standard. When undefined,
+ * - prints out "(err)" if a bad format is encountered
+ * - supports the %b (binary) format
+ */
+#define STANDARD
+
+/*
+ * Shut bcc up about 'const', which doesn't seem to be handled right
+ * by unproto.
+ */
+#ifdef __BCC__
+#define const
+#endif
+
+#define BUF_SIZE 128
+#define OUTC(c) { putc(c, stream); n++; }
+#define max(a, b) ((a > b) ? a : b)
+/*
+ * if you change the ff, you need to change the order of characters in
+ * the string 'flagstr' defined in _printf()
+ */
+#define FLAG_PADZERO (1<<0)
+#define FLAG_LEFTJUST (1<<1)
+#define FLAG_SIGNED (1<<2)
+#define FLAG_ALT (1<<3)
+#define FLAG_SPACE (1<<4)
+
+static char *utoa(unsigned int val, char *buf, int radix)
+/*
+ * Converts an integer to a variable-radix string representation
+ *
+ * Note:
+ * Does not perform sanity checking for 'radix'
+ * Assumes 'buf' has memory allocated to it
+ */
+{
+ int divisor;
+ char *p = buf;
+ const char *digitstr = "0123456789abcdef";
+
+ for (divisor = 1; val / divisor >= radix; divisor *= radix);
+ do {
+ *p++ = digitstr[val / divisor];
+ val %= divisor;
+ divisor /= radix;
+ } while (divisor >= 1);
+ *p = '\0';
+ return(buf);
+}
+
+static
+internal_fprintf(FILE * stream, const char * fmt, char *args)
+
+/* static int _printf(FILE *stream, const char *fmt, char *args) */
+/*
+ * The one that does all the work.
+ * This is a fairly complete implementation of printf(), supporting
+ * everything EXCEPT:
+ * - floating point (eEDOUfg formats)
+ * - pointers (realizes them but doesn't understand how to print them)
+ * - short and long (h/l) modifiers (dunno what to do about them)
+ * It's even slightly faster than gcc's printf() on Linux. Can't beat
+ * HP-UX's printf() though ;)
+ *
+ * Supports:
+ * d, signed integer
+ * i
+ * o unsigned octal integer
+ * u unsigned integer
+ * x unsigned hex lowercase a-f
+ * X unsigned hex uppercase A-F
+ * c character
+ * s string (character pointer)
+ * p void pointer (ignores it)
+ * % % character
+ * n number of characters output so far
+ *
+ * Special feature: (no really, it's not a bug =) )
+ * b prints an integer in binary form (i think this might come
+ * in handy *somewhere*)
+ *
+ * # alternate format for octal (leading 0) and hex (0x/0X)
+ * 0 leading zeroes for d, i, o, u, x, and X
+ * - left justify, overrides '0'
+ * ' ' (space) force a blank in front of positive numbers
+ * + force a sign in front of any number
+ *
+ * width.precision, including support for '*' (reads value from
+ * the parameter list (MUST BE INT))
+ *
+ * h, short/long modifiers, recognized but ignored.
+ * l
+ *
+ * Warning:
+ * The way varargs is implemented in libc is evil. Don't think
+ * there's a better way, but misaligned or wrong parameters
+ * passed to printf() can break a lot of things. I've tried my
+ * best to handle errors in the format string, though.
+ *
+ * Each %something field cannot exceed 'BUF_SIZE' characters,
+ * which I set to 128 right now. %s fields are not subject to
+ * this limit.
+ *
+ * Note:
+ * The semicolon -looks- missing in a few places but that's
+ * because of the macro def of 'OUTC'. did it that way to
+ * save a few lines of source ;)
+ *
+ * Expects a 'char *' as varargs parameter, unlike libc8086's
+ * printf(), which takes a 'int *' then casts it to a 'char *'.
+ * Either has to change, but it should be trivial.
+ *
+ * This function aborts whenever it scans an illegal format, unlike
+ * gcc's libc which prints out the illegal format as if it's -not-
+ * a format string. The 'STANDARD' preprocessor flag controls if
+ * if just aborts (when defined) or prints out "(err)" (when undefined).
+ */
+{
+ /*
+ * the "0-+# " and "dcs..." strings are listed in my idea of their
+ * frequency of use, with the most popular in front. not terribly
+ * important but strchr() might have an easier time that way.
+ * if you change the ordering of 'flagstr', make sure you update
+ * the #define FLAG_* stuff on top of this file too.
+ */
+ char c, *s, *f;
+ const char *flagstr = "0-+# ",
+#ifdef STANDARD
+ *typestr = "dcsixXuop";
+#else
+ *typestr = "dcsixXuopb";
+#endif
+ int n = 0, flags, width, actwidth, prec, bad = 0, neg, i;
+ static char buf[BUF_SIZE];
+
+ for (c = *fmt++; c && !bad;) {
+ if (c != '%') { /* just copy */
+ OUTC(c);
+ c = *fmt++;
+ }
+ else {
+ c = *fmt++; /* chew the % sign */
+ flags = width = prec = 0;
+ /*
+ * Parse the "0-+# " flags
+ */
+ while ((f = strchr(flagstr, c)) != NULL) {
+ flags |= 1 << (f - flagstr);
+ c = *fmt++;
+ }
+ /*
+ * The '*' parameter says fetch width value from varargs
+ */
+ if (c == '*') {
+ width = *(int *) args;
+ args += sizeof(int);
+ if (width < 0) {
+ width = abs(width);
+ flags |= FLAG_LEFTJUST; /* set '-' flag */
+ }
+ c = *fmt++;
+ }
+ else
+ /*
+ * scan and convert the width parameter
+ */
+ if (isdigit(c))
+ while (isdigit(c)) {
+ width *= 10;
+ width += c - '0';
+ c = *fmt++;
+ }
+ /*
+ * a '.' means there may be a precision parameter
+ */
+ if (c == '.') {
+ c = *fmt++;
+ /*
+ * fetch precision value from varargs
+ */
+ if (c == '*') {
+ prec = *(int *) args;
+ if (prec < 0)
+ prec = 0;
+ args += sizeof(int);
+ c = *fmt++;
+ }
+ else
+ /*
+ * scan and convert precision field
+ */
+ if (isdigit(c))
+ while (isdigit(c)) {
+ prec *= 10;
+ prec += c - '0';
+ c = *fmt++;
+ }
+ }
+ /*
+ * short and long modifiers. ignored for the moment
+ */
+ if (c == 'h') {
+ c = *fmt++;
+ }
+ else
+ if (c == 'l') {
+ c = *fmt++;
+ }
+ /*
+ * check if it's a valid type "dioux..."
+ */
+ if (strchr(typestr, c) != NULL) {
+ neg = 0;
+ switch (c) {
+ case 'd':
+ case 'i': {
+ int val = *(int *) args;
+ args += sizeof(int);
+ neg = (val < 0);
+ val = abs(val);
+ actwidth = strlen(utoa(val, buf, 10)); }
+ /*
+ * if negative or '+'/' ' flags set
+ */
+ if (neg || (flags & FLAG_SIGNED) || (flags & FLAG_SPACE))
+ actwidth++;
+ break;
+ case 'u': {
+ unsigned int uval = *(unsigned int *) args;
+ args += sizeof(unsigned int);
+ actwidth = strlen(utoa(uval, buf, 10)); }
+ /*
+ * if '+'/' ' flags set
+ */
+ if ((flags & FLAG_SIGNED) || (flags & FLAG_SPACE))
+ actwidth++;
+ break;
+ case 'x':
+ case 'X': {
+ int val = *(int *) args;
+ args += sizeof(int);
+ actwidth = strlen(utoa(val, buf, 16)); }
+ if (flags & FLAG_ALT)
+ actwidth += 2;
+ break;
+ case 'o': {
+ int val = *(int *) args;
+ args += sizeof(int);
+ actwidth = strlen(utoa(val, buf, 8)); }
+ if (flags & FLAG_ALT)
+ actwidth++;
+ break;
+ case 's':
+ s = *(char **) args;
+ args += sizeof(char *);
+ actwidth = strlen(s);
+ break;
+ case 'c':
+ buf[0] = *(char *) args;
+ buf[1] = '\0';
+ args += sizeof(char);
+ actwidth = 1;
+ break;
+ /*
+ * dunno how to handle pointers - what's the format of
+ * linux86 pointers?! right now just prints "(ptr)"
+ */
+ case 'p':
+ strcpy(buf, "(ptr)");
+ args += sizeof(void *);
+ actwidth = strlen(buf);
+ s = buf; /* pretend we're a string */
+ c = 's';
+ break;
+#ifndef STANDARD
+ case 'b': {
+ int val = *(int *) args;
+ args += sizeof(int);
+ actwidth = strlen(utoa(val, buf, 2)); }
+ break;
+#endif
+ }
+ /*
+ * strings behave differently to the width.precision
+ * parameters, so handle separately. besides, we avoid
+ * an extra 'memcpy' to 'buf'
+ */
+ if (c == 's') {
+ if (prec == 0)
+ prec = actwidth;
+ width = max(width, prec);
+ /*
+ * pad to the left if not left justified
+ */
+ if (!(flags & FLAG_LEFTJUST)) {
+ for (i = width; i > prec; i--)
+ OUTC(' ');
+ }
+ /*
+ * print out entire string if no precision specified, otherwise
+ * that's our upper limit
+ */
+ if (prec == 0)
+ for (; *s; s++)
+ OUTC(*s) /* no semicolon here */
+ else
+ for (i = 0; i < prec; i++)
+ OUTC(s[i]);
+ }
+ else {
+ /*
+ * precision is as wide as width if it's not specified and
+ * the leading zero '0' flag is set, and left-justify is
+ * -not- set. c standard says left justify overrides the
+ * leading 0.
+ */
+ if (prec == 0 && (flags & FLAG_PADZERO) && !(flags & FLAG_LEFTJUST))
+ prec = width;
+ /*
+ * expand width.precision to fit the actual width. printf
+ * width specifies the -minimum-, and aside from the
+ * precision of %s fields, there's no way to specify maximum
+ */
+ prec = max(prec, actwidth);
+ width = max(width, prec);
+ /*
+ * pad to the left if we're not left justified
+ */
+ if (!(flags & FLAG_LEFTJUST)) {
+ for (i = width; i > prec; i--)
+ OUTC(' ');
+ }
+ /*
+ * check if we might need to print the sign
+ */
+ if (strchr("diu", c) != NULL) {
+ if (neg) /* print if negative */
+ OUTC('-') /* yes, no ';' here =) */
+ else
+ if (flags & FLAG_SIGNED) /* or '+' specified */
+ OUTC('+') /* nor here */
+ else
+ if (flags & FLAG_SPACE) /* or ' ' specified */
+ OUTC(' ') /* nor here */
+ }
+ /*
+ * the alternate '#' flag is set. doesn't affect all though
+ */
+ if (flags & FLAG_ALT) {
+ switch (c) {
+ case 'o':
+ OUTC('0'); /* leading zero for octals */
+ break;
+ case 'x':
+ case 'X': /* prints 0x or 0X */
+ OUTC('0');
+ OUTC(c);
+ break;
+ }
+ }
+ /*
+ * fill the precision field with either spaces or zeroes,
+ * depending if we're printing numbers
+ */
+ if (strchr("diuxXo", c) != NULL)
+ for (i = prec; i > actwidth; i--)
+ OUTC('0')
+ else
+ for (i = prec; i > actwidth; i--)
+ OUTC(' ');
+ /*
+ * print the field, except for 'X', which we convert to caps
+ */
+ if (c != 'X')
+ for (f = buf; *f; f++)
+ OUTC(*f) /* none here either */
+ else
+ for (f = buf; *f; f++)
+ OUTC(toupper(*f));
+ }
+ /*
+ * if we're left justified, we now need to pad spaces to the
+ * right so that width will be correct
+ */
+ if (flags & FLAG_LEFTJUST)
+ for (i = width; i > prec; i--)
+ OUTC(' ');
+ }
+ else {
+ /*
+ * miscellaneous %thingies
+ */
+ switch (c) {
+ case '%': /* %% -> % */
+ OUTC('%');
+ break;
+ case 'n': /* %n writes current output count */
+ *(*(int **) args) = n;
+ args += sizeof(int *);
+ break;
+ default: /* oops, got a bad %thingy */
+ bad = 1;
+ }
+ }
+ c = *fmt++;
+ }
+ }
+#ifndef STANDARD
+ /*
+ * dunno what the standard wants if the format string is badly
+ * formed, so i print (err) if the debug flag is set
+ */
+ if (bad) {
+ OUTC('(');
+ OUTC('e');
+ OUTC('r');
+ OUTC('r');
+ OUTC(')');
+ }
+#endif
+ return(n);
+}
+
+#ifdef TEST
+
+#include <time.h>
+
+int main()
+{
+ static unsigned char xbuf[128], *x;
+ char *fmt = "%s, %s %d, %.*d:%.*d\n";
+ int rv1, rv2, i, dt1, dt2;
+ clock_t t1, t2;
+
+ x = xbuf;
+ *(char **) x = "Sun";
+ x += sizeof(char *);
+ *(char **) x = "Feb";
+ x += sizeof(char *);
+ *(int *) x = 18;
+ x += sizeof(int);
+ *(int *) x = 2;
+ x += sizeof(int);
+ *(int *) x = 10;
+ x += sizeof(int);
+ *(int *) x = 2;
+ x += sizeof(int);
+ *(int *) x = 56;
+ x += sizeof(int);
+ t1 = clock();
+ for (i = 0; i < 1000; i++)
+ rv1 = _printf(stdout, fmt, xbuf);
+ t2 = clock();
+ dt1 = t2 - t1;
+
+ t1 = clock();
+ for (i = 0; i < 1000; i++)
+ rv2 = printf(fmt, "Sun", "Feb", 18, 2, 10, 2, 56);
+ t2 = clock();
+ dt2 = t2 - t1;
+
+ printf("\nrv1: %d, rv2: %d, dt1: %d, dt2: %d\n", rv1, rv2, dt1, dt2);
+ return(0);
+}
+
+#endif
diff --git a/libc/stdio1/puts.c b/libc/stdio1/puts.c
new file mode 100644
index 0000000..d9bb8d0
--- /dev/null
+++ b/libc/stdio1/puts.c
@@ -0,0 +1,26 @@
+/* simplified linux puts.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "stdio.h"
+
+int puts (string)
+char *string;
+{
+ fputs(string, stdout);
+ putc('\n', stdout);
+ return 0;
+}
diff --git a/libc/stdio1/scanf.c b/libc/stdio1/scanf.c
new file mode 100644
index 0000000..81900a1
--- /dev/null
+++ b/libc/stdio1/scanf.c
@@ -0,0 +1,151 @@
+/* scanf.c for limited Linux libc
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* This scanf code was derived from my printf code, which in turn was
+ * derived from Alan Cox's printk. It was tested by [no one so far...]
+ */
+
+/* Disclaimer: I haven't even THOUGHT about testing this. If you do decide
+ * to be brave and test it, and it doesn't work, you have the following
+ * options:
+ * o Send me mail telling me it doesn't work, which I will ignore
+ * since I already knew that.
+ * o Fix it yourself
+ * o isolate the problem and send it to the list, and maybe
+ * I'll fix it
+ */
+
+/* BTW, the above comment may be destroyed once this has been tested. It's
+ * not nessisary for my great great grandchildren to see it when they
+ * take Ancient Linux History...
+ */
+
+/* Incidentally, if it doesn't work, it may well be because I never bothered
+ * to learn how to use scanf()...I briefly tried it for the usaco qualification
+ * round, but had some wierd problems...ask me after mid February...BTW the
+ * problems had nothing to do with scanf(); it was still broken (hopelessly)
+ * when I went to getchar().
+ */
+
+/* Note, too that the current version probably assumes some things with
+ * variable argument handling that it shouldn't. Don't expect this to
+ * work on a 386 in 32 bit mode, don't expect this to work on a Z80,
+ * or anything other than an 8086. In fact, don't expect it to even
+ * work on an 8086 ;-)
+ */
+
+/* One of these days the headers will work painlessly... */
+/* #include <linuxmt/types.h> */
+/* #include <linuxmt/fcntl.h> */
+#include "stdio.h"
+
+/* note that we assume base == 10... */
+static int numin(int *num, int base, FILE *stream, int c)
+{
+ if ((c < '0') || (c > '9')) return 0;
+ *num = 0;
+ while ((c >= '0') && (c <= '9')) {
+ *num = *num * base + c - '0';
+ c = getc(stream);
+ }
+ ungetc(c, stream);
+}
+
+/* currently, the h/l specifications are ignored */
+static int internal_scanf(stream,fmt,a1)
+FILE *stream;
+char *fmt;
+int *a1;
+{
+ unsigned char *p=(char *)a1;
+ char c;
+ int inc;
+ int count = 0;
+
+ while(c=*fmt++)
+ {
+ do {
+ inc = getc(stream);
+ } while ((inc == ' ') || (inc == '\t') || (inc == '\n'));
+
+ if ((c == '\n') || (c == '\t') || (c == ' '))
+ ;
+ else if (c!='%') {
+ if (c != inc) {
+ ungetc(inc, stream);
+ return count;
+ }
+ } else {
+ int len=2;
+ c=*fmt++;
+ if(c=='h') c=*fmt++;
+ else if(c=='l') c=*fmt++;
+
+ switch(c)
+ {
+ case 'x':
+ if (numin(p, 16, stream, inc)) count++;
+ else return count;
+ p+=2;
+ break;
+ case 'd':
+ if (numin(p, 10, stream, inc)) count++;
+ else return count;
+ p+=2;
+ break;
+ case 's':
+ {
+ char *cp=*((char **)p);
+ p+=sizeof(char *);
+ while(*cp)
+ putc(cp++, stream);
+ while ((inc != ' ') && (inc != '\t')
+ && (inc != '\n') && (inc != EOF)) {
+ *cp++ = inc;
+ inc = getc(stream);
+ }
+ ungetc(inc, stream);
+ break;
+ }
+ case 'c':
+ *p++ = inc;
+ p++;
+ break;
+ default:
+ putc('?', stream);
+ }
+ }
+ }
+ return count;
+}
+
+
+int fscanf(stream,fmt,a1)
+FILE *stream;
+char *fmt;
+int a1;
+{
+ return internal_fscanf(stream,fmt,&a1);
+}
+
+int scanf(fmt,a1)
+char *fmt;
+int a1;
+{
+ return internal_fscanf(stdout,fmt,&a1);
+}
diff --git a/libc/stdio1/stdio.h b/libc/stdio1/stdio.h
new file mode 100644
index 0000000..4bd1989
--- /dev/null
+++ b/libc/stdio1/stdio.h
@@ -0,0 +1,135 @@
+/* simplified linux stdio.h
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <malloc.h>
+
+#ifndef __STDIO_H
+#define __STDIO_H
+
+/* when you add or change fields here, be sure to change the initialization
+ * in stdio_init and fopen */
+struct __stdio_file {
+ int fd; /* the file descriptor associated with the stream */
+ unsigned char *bufstart; /* the start of the buffer */
+ unsigned char *bufpos; /* the next byte to write to or read from */
+ unsigned char *bufread; /* the end of data returned by last read() */
+ unsigned char *bufend; /* the end of the buffer; ie the byte after the last
+ malloc()ed byte */
+ int buffer_mode;
+#define _IONBF 0xB111 /* no buffering */
+#define _IOLBF 0xB112 /* line buffering */
+#define _IOFBF 0xB113 /* full buffering */
+ int file_mode;
+#define _MODE_READ 0xB121
+#define _MODE_WRITE 0xB122
+#define _MODE_RDWR 0xB124 /* used when a file is readwrite and is ord with
+ what's in the buffer now */
+ unsigned char ungetted, ungetchar;
+ /* ungetted = 1 if there's data unread; else 0
+ ungetchar contains the character */
+ int fc_eof:1;
+ int fc_err:1; /* eof and error conditions */
+ int iotrans:1; /* Translate \n -> \r\n on MSDOS */
+};
+
+#define EOF (-1)
+
+typedef struct __stdio_file FILE;
+
+#define BUFSIZ 256
+
+extern FILE *stdin, *stdout, *stderr, *__stdsprintf;
+
+/* The following macros are used for all access to the buffers. If you
+ * know the file is unbuffered, however, you may write to it directly, as
+ * fputs.c does. However, be aware that sprintf assumes that by setting
+ * bufend to 0, no file writing will occur. Also, since NO streams use
+ * unbuffered mode by default and the function to change this behavior is
+ * not implemented yet, I'm considering disallowing raw access at the cost
+ * of having each byte of a string written individually. However, that
+ * IS what you're asking for with non-buffered mode.
+ *
+ * RDB: It's considered very bad form to use the raw read() & write()
+ * calls on the same files you use the stdio functions.
+ */
+#ifdef __MSDOS__
+#define putc(c, fp) fputc(c, fp)
+#define getc(fp) fgetc(fp)
+#else
+#define putc(c, stream) \
+ (((stream)->bufpos[0] = (c)), \
+ ((stream)->bufpos++), \
+ ((((stream)->bufpos == (stream)->bufend) \
+ ||((stream)->buffer_mode == _IONBF) \
+ ||(((stream)->buffer_mode == _IOLBF) \
+ && ((stream)->bufpos != (stream)->bufstart) \
+ && ((stream)->bufpos[-1] == '\n'))) \
+ ? fflush(stream):0))
+
+#define getc(stream) \
+ ((stream)->ungetted ? (((stream)->ungetted = 0), ((stream)->ungetchar)) : \
+ (((stream)->bufpos == (stream)->bufread)?__ffillbuf(stream): \
+ (*(stream)->bufpos++)))
+
+#endif
+
+#define putchar(c) putc((c), stdout)
+#define getchar() getc(stdin)
+#define ungetc(c, stream) (((stream)->ungetted = 1), ((stream)->ungetchar = c))
+
+#define ferror(fp) ((fp)->fc_err)
+#define feof(fp) ((fp)->fc_eof)
+
+#define fileno(fp) ((fp)->fd)
+/* declare functions; not like it makes much difference without ANSI */
+/* RDB: The return values _are_ important, especially if we ever use
+ 8086 'large' model
+ */
+
+#ifndef __P
+#define __P(x) ()
+#endif
+
+int setvbuf __P((FILE*, char*, int, size_t));
+int __ffillbuf __P((FILE*));
+void __stdio_init __P((void));
+int fclose __P((FILE*));
+int fflush __P((FILE*));
+int fgetc __P((FILE*));
+char *fgets __P((char*, size_t, FILE*));
+FILE *fopen __P((char*, char*));
+
+int fputc __P((int, FILE*));
+int fputs __P((__const char*, FILE*));
+char *idealgetline __P((FILE*));
+int puts __P((char*));
+
+int printf __P ((__const char *, ...));
+int fprintf __P ((FILE *, __const char *, ...));
+int sprintf __P ((char *, __const char *, ...));
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#endif /* __STDIO_H */
+/* TODO: add scanf, fscanf */
diff --git a/libc/stdio1/test.sh b/libc/stdio1/test.sh
new file mode 100755
index 0000000..9d872dc
--- /dev/null
+++ b/libc/stdio1/test.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+echo 'rm -f *.o test *.a'
+rm -f *.o test *.a
+echo 'make'
+make
+echo 'ar r libnat.a *.o'
+ar r libnat.a *.o
+echo 'ranlib libnat.a'
+ranlib libnat.a
+echo 'gcc test.c -I- -I../include -fno-builtin -o test.o -L./ -lnat'
+gcc test.c -I- -I../include -fno-builtin -o test.o -L./ -lnat
diff --git a/libc/syscall/syscall.dat.chad b/libc/syscall/syscall.dat.chad
deleted file mode 100644
index a6e8b06..0000000
--- a/libc/syscall/syscall.dat.chad
+++ /dev/null
@@ -1,55 +0,0 @@
-exit 1 1 * c exit does stdio, _exit in crt0
-fork 2 0
-read 3 3
-write 4 3
-open 5 3
-close 6 1
-wait 7 0 . THIS one is different
-creat 8 0 . THIS one is different
-link 9 2
-unlink 10 1
-exec 11 3 * minix style exec
-chdir 12 1
-time 13 0 . THIS one is different
-mknod 14 3
-chmod 15 2
-chown 16 3
-brk 17 1 * This is only to tell the system
-stat 18 2
-lseek 19 3 * nb 2nd arg is an io ptr to long not a long.
-getpid 20 1 * this gets both pid & ppid
-mount 21 5
-umount 22 1
-setuid 23 1
-getuid 24 1 * this gets both uid and euid
-stime 25 2 - this must not exist - even as a libc.
-ptrace 26 4
-alarm 27 2
-fstat 28 2
-pause 29 0
-utime 30 2
-access 33 2
-nice 34 1 .
-sleep 35 0 . THIS one is different
-sync 36 0
-kill 37 2
-rename 38 2
-mkdir 39 2
-rmdir 40 1
-dup 41 1 - using nasty fcntl function
-pipe 42 1
-times 43 2 * 2nd arg is pointer for long ret val.
-profil 44 0
-setgid 46 1
-getgid 47 1 * this gets both gid and egid
-signal 48 2 * have put the despatch table in user space.
-getinfo 49 1 - possible? gets pid,ppid,uid,euid etc
-fcntl 50 3
-acct 51 1 -
-phys 52 0 . THIS one is different
-lock 53 0 . THIS one is different
-ioctl 54 3 . make this and fcntl the same ?
-reboot 55 3 . the magic number is 0xfee1,0xdead,...
-mpx 56 0 . THIS one is different
-dup2 57 0 . THIS one is different
-umask 60 1
diff --git a/libc/syscall/syscall.dat.code b/libc/syscall/syscall.dat.code
deleted file mode 100644
index a91ca86..0000000
--- a/libc/syscall/syscall.dat.code
+++ /dev/null
@@ -1,70 +0,0 @@
-(
-tr '[A-Z]' '[a-z]' < syscall.dat.rdb
-echo %%%
-cat <<!
-exit 1 0
-fork 2 0
-read 3 0
-write 4 0
-open 5 0
-close 6 0
-wait 7 0
-creat 8 0
-link 9 0
-unlink 10 0
-exec 11 0
-chdir 12 0
-time 13 0
-mknod 14 0
-chmod 15 0
-chown 16 0
-brk 17 0
-stat 18 0
-lseek 19 0
-getpid 20 0
-mount 21 0
-umount 22 0
-setuid 23 0
-getuid 24 0
-stime 25 0
-ptrace 26 0
-alarm 27 0
-fstat 28 0
-pause 29 0
-utime 30 0
-access 33 0
-nice 34 0
-sleep 35 0
-sync 36 0
-kill 37 0
-rename 38 0
-mkdir 39 0
-rmdir 40 0
-dup 41 0
-pipe 42 0
-times 43 0
-profil 44 0
-setgid 46 0
-getgid 47 0
-signal 48 0
-getinfo 49 0
-fcntl 50 0
-acct 51 0
-phys 52 0
-lock 53 0
-ioctl 54 0
-reboot 55 0
-mpx 56 0
-dup2 57 0
-umask 60 0
-!
-) | awk '/%%%/{ flg++; OFS="\t"; next;}
-flg==0 { save4[$1] = $4; save3[$1] = $3;
- for(i=5; i<=NF; i++) saverest[$1] = saverest[$1] " " $i;
-}
-flg==1 {
- if( $1 in save3 )
- print $1, $2, save3[$1]+0, save4[$1] " " saverest[$1] ;
- else
- print $1, $2, "0", ". THIS one is different";
- }'
diff --git a/libc/syscall/syscall.dat.rdb b/libc/syscall/syscall.dat.rdb
deleted file mode 100644
index de5ed9b..0000000
--- a/libc/syscall/syscall.dat.rdb
+++ /dev/null
@@ -1,142 +0,0 @@
-#
-# Name No Args Flag, comment
-#
-# . = Ok, with comment
-# * = Needs libc code (Prefix __)
-# - = Obsolete/not required
-#
-# WARNING!
-# This file is used to generate includes for ELKSemu too.
-# This file is continually changing, when you upgrade you _MUST_ ensure
-# that ELKSemu is of a matching build!
-#
-# Calls that use one fd
-READ 3 3
-WRITE 4 3
-CLOSE 6 1
-LSEEK 19 3 * NB 2nd arg is an IO ptr to long not a long.
-FSTAT 28 2
-IOCTL 54 3 . Make this and fcntl the same ?
-FCNTL 55 3
-FTRUNCATE 93 3
-FCHMOD 94 2
-FCHOWN 95 3
-FSYNC 118 1
-FCHDIR 133 1
-LLSEEK 140 3 * 2nd arg is ptr to two longs
-READV 145 3
-WRITEV 146 3
-FLOCK 143 2 - Use fcntl
-DUP 41 1 - Using nasty fcntl function
-
-#
-SETUP 0 X
-EXIT 1 1 * C exit does stdio, _exit in crt0
-FORK 2 0
-OPEN 5 3
-WAIT4 7 4
-VFORK 8 0 . Needed for 8086
-GETINFO 49 1 - Possible? Gets pid,ppid,uid,euid etc
-LINK 9 2
-UNLINK 10 1
-EXEC 11 3 * Minix style exec
-CHDIR 12 1
-GETTIMEOFDAY 13 2 . time() exists only in libc
-MKNOD 14 3
-CHMOD 15 2
-CHOWN 16 3
-BRK 17 1 * This is only to tell the system
-STAT 18 2
-GETPID 20 1 * This gets both pid & ppid
-MOUNT 21 5
-UMOUNT 22 1
-SETUID 23 1
-GETUID 24 1 * This gets both uid and euid
-SETTIMEOFDAY 25 2 . STIME should _NOT_ exist even as a libc.
-STIME 25 2 - This must NOT exist - even as a libc.
-PTRACE 26 4
-ALARM 27 2
-PAUSE 29 0
-UTIME 30 2
-ACCESS 33 2
-NICE 34 1 .
-FTIME 35 1 - Use gettimeofday
-SYNC 36 0
-KILL 37 2
-RENAME 38 2
-MKDIR 39 2
-RMDIR 40 1
-PIPE 42 1
-TIMES 43 2 * 2nd arg is pointer for long ret val.
-SETGID 46 1
-GETGID 47 1 * This gets both gid and egid
-SIGNAL 48 2 * Have put the despatch table in user space.
-ACCT 51 1 -
-SETPGID 57 2
-ULIMIT 58 2
-UMASK 60 1
-CHROOT 61 1
-USTAT 62 2
-GETPGRP 65 0 - use getpgid(0)
-SETSID 66 0
-SIGACTION 67 X
-SGETMASK 68 X
-SSETMASK 69 X
-SETREUID 70 2
-SETREGID 71 2
-SIGSUSPEND 72 X
-SIGPENDING 73 X
-SETHOSTNAME 74 2
-SETRLIMIT 75 2
-GETRLIMIT 76 2
-GETRUSAGE 77 2
-GETGROUPS 80 2
-SETGROUPS 81 2
-SYMLINK 83 2
-LSTAT 84 2
-READLINK 85 3
-SWAPON 87 X
-REBOOT 88 3 . The magic number is 0xfee1,0xdead,...
-MUNMAP 91 X
-TRUNCATE 92 3
-GETPRIORITY 96 2
-SETPRIORITY 97 3
-PROFIL 98 X
-STATFS 99 2
-FSTATFS 100 2
-SOCKETCALL 102 X
-SYSLOG 103 X
-SETITIMER 104 3
-GETITIMER 105 2
-UNAME 109 1
-VHANGUP 111 0
-SWAPOFF 115 X
-SYSINFO 116 X - Use /proc
-IPC 117 5 * This is for all SYSV IPC
-SIGRETURN 119 X
-SETDOMAINNAME 121 X
-ADJTIMEX 124 X
-MPROTECT 125 X
-SIGPROCMASK 126 X
-QUOTACTL 131 X
-GETPGID 132 1
-SYSFS 135 X
-PERSONALITY 136 X
-SETFSUID 138 1
-SETFSGID 139 1
-GETDENTS 141 X
-SELECT 142 5 *
-MSYNC 144 X
-GETSID 147 X
-FDATASYNC 148 X
-SYSCTL 149 X
-MUNLOCK 151 X
-MUNLOCKALL 153 X
-SCHED_SETPARAM 154 X
-SCHED_GETPARAM 155 X
-SCHED_SETSCHEDULER 156 X
-SCHED_GETSCHEDULER 157 X
-SCHED_YIELD 158 X
-SCHED_GET_PRIORITY_MAX 159 X
-SCHED_GET_PRIORITY_MIN 160 X
-SCHED_RR_GET_INTERVAL 161 X
diff --git a/makefile.in b/makefile.in
index 423b154..efc168b 100644
--- a/makefile.in
+++ b/makefile.in
@@ -13,10 +13,11 @@
# Defaults, generic C
ARFLAGS =r
-CFLAGS =-O
-LDFLAGS =-s
+CC =%CC%
+CFLAGS =%CFLAGS%
+LDFLAGS =
MAKEARG =CC='$(CC)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' PREFIX=$(PREFIX) \
- LIBDIR='$(LIBDIR)' BINDIR='$(BINDIR)'
+ LIBDIR='$(LIBDIR)' BINDIR='$(BINDIR)' ANSI='$(ANSI)'
MAKEC=$(MAKE) -C
MAKEX=
@@ -32,11 +33,10 @@ WALL =-Wstrict-prototypes
CC =gcc $(GCCFLAG)
#ifdef __i386__
-CFLAGS =-Wall $(WALL) -O2 -m486 -fno-strength-reduce
+CFLAGS =-Wall $(WALL) -O2 -m486 -fno-strength-reduce -g
#else
-CFLAGS =-Wall $(WALL) -O2 -fno-strength-reduce
-#endf
-LDFLAGS =-s
+CFLAGS =-Wall $(WALL) -O2 -fno-strength-reduce -g
+#endif
#endif
#ifndef GNUMAKE
@@ -52,19 +52,21 @@ CFLAGS=-O -m -w -DPOSIX_HEADERS_MISSING -DVERY_SMALL_MEMORY
#endif
#ifdef __BCC__
-CC =bcc
+ANSI =-ansi
#ifdef __AS386_32__
CFLAGS =-3
LDFLAGS =-3 -s -N
#else
CFLAGS =-0
LDFLAGS =-0 -s -H10000
+BCCARCH =-Mf
#endif
#endif
# Alter these if for some reason you don't want this done as root.
INDAT=-o root -g root -m 644
-INEXE=-o root -g root -m 755
+INEXE=-o root -g root -m 755 -s
+INSCR=-o root -g root -m 755
all: check_config bcc unproto copt as86 ld86 library alt-libs elksemu
@@ -76,10 +78,10 @@ install-all: install install-other
LIBARGS= CC=ncc CCFLAGS= ARFLAGS=$(ARFLAGS)
-# Season to taste
-PREFIX= /usr/bcc
-BINDIR= /usr/bin
-LIBDIR= $(PREFIX)/lib/bcc
+# Season in the top makefile
+PREFIX= %PREFIX%
+BINDIR= %BINDIR%
+LIBDIR= %LIBDIR%
DISTBIN= $(DIST)$(BINDIR)
DISTLIB= $(DIST)$(LIBDIR)
@@ -100,8 +102,8 @@ bindir: $(MAKEX)
phony:
bcc: bindir
- $(MAKEC) bcc $(MAKEARG) bcc ncc bcc-cc1
- cp -p bcc/bcc bin/bcc
+ $(MAKEC) bcc $(MAKEARG) BCCARCH=$(BCCARCH) bcc ncc bcc-cc1
+ cp -p bcc/bcc bin/Bcc
cp -p bcc/ncc bin/ncc
cp -p bcc/bcc-cc1 lib/bcc-cc1
@@ -124,13 +126,25 @@ ld86: bindir
cp -p ld/ld86 bin/ld86
elksemu: bindir
- $(MAKEC) elksemu $(MAKEARG) elksemu
+ $(MAKEC) elksemu \
+ CC='$(CC)' PREFIX=$(PREFIX) LIBDIR='$(LIBDIR)' BINDIR='$(BINDIR)' \
+ elksemu
cp -p elksemu/elksemu bin/elksemu
+install-ln: bcc unproto copt as86 ld86 elksemu
+ install -d $(DISTBIN)
+ ln -fs `pwd`/bin/ncc $(DISTBIN)/bcc
+ ln -fs `pwd`/bin/as86_encap $(DISTBIN)/as86_encap
+ ln -fs `pwd`/bin/as86 $(DISTBIN)/as86
+ ln -fs `pwd`/bin/ld86 $(DISTBIN)/ld86
+ ln -fs `pwd`/bin/elksemu $(DIST)/lib/elksemu
+ install -d $(DIST)/usr/lib
+ install $(INDAT) libc/error/liberror.txt $(DIST)/usr/lib/liberror.txt
+
install-bcc: bcc unproto copt as86 ld86
install -d $(DISTBIN) $(DISTLIB) $(DISTLIB)/i86
- install $(INEXE) bin/bcc $(DISTBIN)/bcc
- install $(INEXE) bin/as86_encap $(DISTBIN)/as86_encap
+ install $(INEXE) bin/Bcc $(DISTBIN)/bcc
+ install $(INSCR) bin/as86_encap $(DISTBIN)/as86_encap
install $(INEXE) bin/as86 $(DISTBIN)/as86
install $(INEXE) bin/ld86 $(DISTBIN)/ld86
install $(INEXE) lib/bcc-cc1 $(DISTLIB)/bcc-cc1
@@ -140,6 +154,7 @@ install-bcc: bcc unproto copt as86 ld86
@test ! -f $(DISTLIB)/as86 || rm -f $(DISTLIB)/as86
@test ! -f $(DISTLIB)/ld86 || rm -f $(DISTLIB)/ld86
+# NB: This doesn't install as a suid root, that's ok though.
install-emu: elksemu
install -d $(DIST)/lib
install $(INEXE) bin/elksemu $(DIST)/lib/elksemu
@@ -173,6 +188,7 @@ lib/lib1-done:
$(MAKE) -f make.fil alt-libs
library: bindir
+ test -f bin/ncc
$(MAKEC) libc $(LIBARGS) PLATFORM=i86-ELKS
cp -p libc/crt0.o libc/libc.a lib/.
@touch lib/lib0-done
@@ -181,22 +197,27 @@ alt-libs: lib-bsd lib-fast lib-stand lib-dos lib-386
@touch lib/lib1-done
lib-bsd: bindir
+ test -f bin/ncc
$(MAKEC) libbsd $(LIBARGS)
cp -p libbsd/libbsd.a lib/libbsd.a
lib-fast: bindir
+ test -f bin/ncc
$(MAKEC) libc $(LIBARGS) PLATFORM=i86-FAST
cp -p libc/libc_f.a lib/libc_f.a
lib-stand: bindir
+ test -f bin/ncc
$(MAKEC) libc $(LIBARGS) PLATFORM=i86-BIOS
cp -p libc/libc_s.a lib/libc_s.a
lib-dos: bindir
+ test -f bin/ncc
$(MAKEC) libc $(LIBARGS) PLATFORM=i86-DOS
cp -p libc/libdos.a lib/libdos.a
lib-386: bindir
+ test -f bin/ncc
$(MAKEC) libc $(LIBARGS) PLATFORM=i386-BCC
cp -p libc/crt3.o lib/i386/crt0.o
cp -p libc/libc3.a lib/i386/libc.a
diff --git a/tests/README b/tests/README
index 1f9bcfd..996660f 100644
--- a/tests/README
+++ b/tests/README
@@ -18,7 +18,4 @@ wc.c Word,line and character counts.
grab.c Grabs _all_ available memory (3GB+ on Linux-i386) then frees
rand.c Generates random numbers and pipes them to 'hd'
-BTW: i386 OMAGIC files can be converted to deformed ELFs with this:
- $ objcopy -O elf32-i386 sync
-
-Robert
diff --git a/tests/hd.c b/tests/hd.c
index 341185f..3df7761 100644
--- a/tests/hd.c
+++ b/tests/hd.c
@@ -9,6 +9,10 @@ long offset = 0;
FILE *fd;
+FILE * ofd = stdout;
+char * outfile = 0;
+int reverse = 0;
+
main(argc, argv)
int argc;
char **argv;
@@ -21,25 +25,52 @@ char **argv;
if (aflag && argv[ar][0] == '-')
switch (argv[ar][1])
{
- case 'r':
- return reverse_hd(argc, argv);
- case 'o':
+ case 'r': /* Reverse */
+ reverse = 1;
+ break;
+ case 's': /* Skip */
offset = strtol(argv[ar] + 2, (void *) 0, 0);
break;
case '-':
aflag = 0;
break;
+ case 'o': /* Output */
+ if( argv[ar][2] ) outfile = argv[ar]+2;
+ else
+ {
+ if( ++ar >= argc ) Usage();
+ outfile = argv[ar];
+ }
+ break;
default:
Usage();
}
else
{
+ if( outfile )
+ {
+ if( ofd != stdout ) fclose(ofd);
+#ifdef MSDOS
+ if( reverse )
+ ofd = fopen(outfile, "wb");
+ else
+#endif
+ ofd = fopen(outfile, "w");
+ if( ofd == 0 )
+ {
+ fprintf(stderr, "Cannot open file '%s'\n", outfile);
+ exit(9);
+ }
+ }
fd = fopen(argv[ar], "rb");
if (fd == 0)
fprintf(stderr, "Cannot open file '%s'\n", argv[ar]);
else
{
- do_fd();
+ if( reverse )
+ do_rev_fd();
+ else
+ do_fd();
fclose(fd);
}
done = 1;
@@ -51,14 +82,19 @@ char **argv;
#else
{
fd = stdin;
- do_fd();
+ if( reverse )
+ do_rev_fd();
+ else
+ do_fd();
}
#endif
+
+ exit(0);
}
Usage()
{
- fprintf(stderr, "Usage: hd [-r]|[[-oOffset] file]\n");
+ fprintf(stderr, "Usage: hd [-o Outfile][-r]|[[-sSkip_bytes] file]\n");
exit(1);
}
@@ -109,28 +145,28 @@ int eofflag;
{
if (lastaddr + 16 == address)
{
- printf("*\n");
- fflush(stdout);
+ fprintf(ofd, "*\n");
+ fflush(ofd);
}
return;
}
}
lastaddr = address;
- printf("%06lx:", address);
+ fprintf(ofd, "%06lx:", address);
for (j = 0; j < 16; j++)
{
if (j == 8)
- putchar(' ');
+ fputc(' ', ofd);
if (num[j] >= 0)
- printf(" %02x", num[j]);
+ fprintf(ofd, " %02x", num[j]);
else
- printf(" ");
+ fprintf(ofd, " ");
lastnum[j] = num[j];
num[j] = -1;
}
- printf(" %.16s\n", chr);
+ fprintf(ofd, " %.16s\n", chr);
}
@@ -139,13 +175,12 @@ int eofflag;
* file
*/
-/* -- 0 1 2 3 4 5 6 7 8 9 a b c d e f */
-static char *datafmt = "%x: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n";
-reverse_hd()
+do_rev_fd()
{
char str[160];
char * ptr;
- int c[16], d[16], x, i, nxtaddr, addr;
+ int c[16], i, nxtaddr, addr;
+ int zap_last = 1;
for (i = 0; i < 16; i++)
c[i] = 0;
@@ -153,30 +188,32 @@ reverse_hd()
for (nxtaddr = 0;;)
{
- if (gets(str) == NULL)
+ if (fgets(str, sizeof(str), fd) == NULL)
break;
str[57] = 0;
ptr = str;
+ if( *ptr == '*' ) zap_last = 0;
if( !isxdigit(*ptr) ) continue;
addr = strtol(ptr, &ptr, 16);
if( *ptr == ':' ) ptr++;
if (nxtaddr == 0)
nxtaddr = addr;
+ if( zap_last ) memset(c, 0, sizeof(c));
+ else zap_last = 1;
while (nxtaddr < addr)
{
- nxtaddr += 16;
- for (i = 0; i < 16; i++)
- putchar(c[i]);
+ for (i = 0; nxtaddr < addr && i < 16; i++, nxtaddr++)
+ fputc(c[i], ofd);
}
for (i = 0; i < 16 && *ptr; i++)
{
char * ptr2;
c[i] = strtol(ptr, &ptr2, 16);
if( ptr == ptr2 ) break;
- putchar(c[i]);
+ fputc(c[i], ofd);
ptr = ptr2;
}
nxtaddr += 16;