diff options
Diffstat (limited to 'sys/boot')
76 files changed, 851 insertions, 12826 deletions
diff --git a/sys/boot/Makefile b/sys/boot/Makefile index cd271859639f..1de594169211 100644 --- a/sys/boot/Makefile +++ b/sys/boot/Makefile @@ -1,7 +1,4 @@ -# Build the add-in FORTH interpreter -SUBDIR+= ficl - -# Pick the machine-dependant subdir based on the target architecture. -SUBDIR+= ${MACHINE_ARCH} +# Pick the subdir based on the target architecture. +SUBDIR= ${MACHINE_ARCH} .include <bsd.subdir.mk> diff --git a/sys/boot/alpha/Makefile.inc b/sys/boot/alpha/Makefile.inc index abb4f65cbc89..bbbea75f1efe 100644 --- a/sys/boot/alpha/Makefile.inc +++ b/sys/boot/alpha/Makefile.inc @@ -1,8 +1,10 @@ # Options used when building app-specific libalpha components -PRIMARY_LOAD_ADDRESS= 0x20000000 # "Region 1 start" -SECONDARY_LOAD_ADDRESS= 0x2000c000 # "Region 1 start" + 48k -HEAP_LIMIT= 0x20040000 # "Region 1 start" + 256k +PRIMARY_LOAD_ADDRESS= 20000000 # "Region 1 start" +SECONDARY_LOAD_ADDRESS= 2000c000 # "Region 1 start" + 48k +HEAP_LIMIT= 20040000 # "Region 1 start" + 256k DPADD+= ${DESTDIR}/${LIBDIR}/libstand.a LIBSTANDDIR= ${.CURDIR}/../../../../lib/libstand LIBSTAND= -lstand LIBALPHA= ${.OBJDIR}/../libalpha/libalpha.a + +BINDIR= /usr/mdec diff --git a/sys/boot/alpha/boot1/Makefile b/sys/boot/alpha/boot1/Makefile index bfbcb7a88114..e163c03345a4 100644 --- a/sys/boot/alpha/boot1/Makefile +++ b/sys/boot/alpha/boot1/Makefile @@ -12,10 +12,9 @@ CFLAGS+= -mno-fp-regs CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR} CFLAGS+= -I${LIBSTANDDIR} CFLAGS+= -I${.CURDIR}/.. -CFLAGS+= -DSECONDARY_LOAD_ADDRESS=${SECONDARY_LOAD_ADDRESS} -DMINIMAL +CFLAGS+= -DSECONDARY_LOAD_ADDRESS=0x${SECONDARY_LOAD_ADDRESS} -DMINIMAL NOMAN=1 STRIP= -BINDIR?= /boot BOOT_RELOC = ${PRIMARY_LOAD_ADDRESS} @@ -23,6 +22,10 @@ CLEANFILES+= ${PROG}.sym ${PROG}.nosym ${PROG}.list all: ${PROG} +afterinstall: + ln -sf boot1 /usr/mdec/daboot + ln -sf boot1 /usr/mdec/fdboot + ${PROG}.nosym: ${PROG}.sym cp ${PROG}.sym ${PROG}.nosym strip ${PROG}.nosym @@ -33,9 +36,10 @@ ${PROG}: ${PROG}.nosym .include <bsd.prog.mk> start.o: ${.CURDIR}/../libalpha/start.S - ${CC} -c ${CFLAGS} $< + ${CC} -c -DPRIMARY_BOOTBLOCK $< ${PROG}.sym: ${OBJS} ${LIBKERN} ${LD} -M -Ttext ${BOOT_RELOC} -N -e start -o ${PROG}.sym ${OBJS} \ ${LIBSTAND} ${LIBALPHA} ${LIBSTAND} > ${.OBJDIR}/${PROG}.list size ${PROG}.sym + diff --git a/sys/boot/alpha/boot1/boot1.c b/sys/boot/alpha/boot1/boot1.c index 9eac7ec64c71..a3fbfc2bf397 100644 --- a/sys/boot/alpha/boot1/boot1.c +++ b/sys/boot/alpha/boot1/boot1.c @@ -1,5 +1,5 @@ /* - * $Id: boot1.c,v 1.2 1998/09/26 10:51:36 dfr Exp $ + * $Id: boot1.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $ * From $NetBSD: bootxx.c,v 1.4 1997/09/06 14:08:29 drochner Exp $ */ @@ -181,7 +181,7 @@ main() init_prom_calls(); - loadfile("/boot/loader", loadaddr); + loadfile("/boot/boot2", loadaddr); entry = (void (*)())loadaddr; (*entry)(); diff --git a/sys/boot/alpha/boot2/Makefile b/sys/boot/alpha/boot2/Makefile index 956944d255c8..dfc8e58121eb 100644 --- a/sys/boot/alpha/boot2/Makefile +++ b/sys/boot/alpha/boot2/Makefile @@ -1,6 +1,6 @@ # $NetBSD: Makefile,v 1.12 1998/02/19 14:18:36 drochner Exp $ -BASE= loader +BASE= boot2 PROG= ${BASE} NOMAN= NEWVERSWHAT= "SRM disk boot" @@ -16,9 +16,6 @@ SRCS+= main.c conf.c CFLAGS+= -mno-fp-regs CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR} CFLAGS+= -I${.CURDIR}/../../.. -I. -CFLAGS+= -DLOADER -CFLAGS+= -DPRIMARY_LOAD_ADDRESS=${PRIMARY_LOAD_ADDRESS} \ - -DSECONDARY_LOAD_ADDRESS=${SECONDARY_LOAD_ADDRESS} CLEANFILES+= vers.c vers.o gensetdefs.o gensetdefs setdef0.o setdef1.o \ setdefs.h start.o @@ -30,7 +27,6 @@ CFLAGS+= -I${LIBSTANDDIR} CFLAGS+= -I${.CURDIR}/.. CRT= start.o STRIP= -BINDIR?= /boot all: ${BASE} @@ -38,7 +34,7 @@ vers.o: ${.CURDIR}/newvers.sh ${.CURDIR}/Makefile sh ${.CURDIR}/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} ${CC} -c vers.c -${BASE}: ${BASE}.sym ${BASE}.help +${BASE}: ${BASE}.sym objcopy -O binary ${BASE}.sym ${BASE} ${BASE}.sym: ${OBJS} ${LIBSTAND} ${LIBALPHA} ${CRT} vers.o setdef0.o setdef1.o @@ -46,21 +42,9 @@ ${BASE}.sym: ${OBJS} ${LIBSTAND} ${LIBALPHA} ${CRT} vers.o setdef0.o setdef1.o ${CRT} setdef0.o ${OBJS} setdef1.o \ vers.o ${LIBSTAND} ${LIBALPHA} ${LIBSTAND} >${.OBJDIR}/${BASE}.list -${BASE}.help: help.common help.alpha - cat ${.ALLSRC} | awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET} - -beforeinstall: -.if exists(${.OBJDIR}/loader.help) - ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ - ${.OBJDIR}/${BASE}.help ${DESTDIR}/boot -.else - ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ - ${.CURDIR}/${BASE}.help ${DESTDIR}/boot -.endif - # Other fragments still to be brought in from ../Makfile.booters? start.o: ${.CURDIR}/../libalpha/start.S - ${CC} -c ${CFLAGS} $< + ${CC} -c $< setdef0.o: setdefs.h diff --git a/sys/boot/alpha/boot2/help.alpha b/sys/boot/alpha/boot2/help.alpha deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/sys/boot/alpha/boot2/help.alpha +++ /dev/null diff --git a/sys/boot/alpha/boot2/newvers.sh b/sys/boot/alpha/boot2/newvers.sh index 978c16489867..88cc010175bb 100644 --- a/sys/boot/alpha/boot2/newvers.sh +++ b/sys/boot/alpha/boot2/newvers.sh @@ -35,7 +35,6 @@ # # @(#)newvers.sh 8.1 (Berkeley) 4/20/94 -LC_TIME=C; export LC_TIME u=${USER-root} h=`hostname` t=`date` r=`head -n 6 $1 | tail -n 1 | awk -F: ' { print $1 } '` diff --git a/sys/boot/alpha/common/main.c b/sys/boot/alpha/common/main.c index 41400240b26e..365e5c4cd98c 100644 --- a/sys/boot/alpha/common/main.c +++ b/sys/boot/alpha/common/main.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: main.c,v 1.8 1998/10/31 17:12:32 dfr Exp $ + * $Id: main.c,v 1.4 1998/09/03 02:10:02 msmith Exp $ */ @@ -63,50 +63,6 @@ memsize() return total; } -static void -extend_heap() -{ - struct rpb *hwrpb = (struct rpb *)HWRPB_ADDR; - struct mddt *mddtp; - struct mddt_cluster *memc; - int i; - unsigned long total = 0; - unsigned long startpfn; - vm_offset_t startva; - vm_offset_t startpte; - - /* - * Find the last usable memory cluster and add some of its pages - * to our address space. The 256k allowed by the firmware isn't quite - * adequate for our needs. - */ - mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off); - for (i = mddtp->mddt_cluster_cnt - 1; i >= 0; i--) { - memc = &mddtp->mddt_clusters[i]; - if (!(memc->mddt_usage & (MDDT_NONVOLATILE | MDDT_PALCODE))) - break; - } - - /* - * We want to extend the heap from 256k to 512k. With 8k pages - * (assumed), we need 32 pages. We take pages from the end of the - * last usable memory region, taking care to avoid the memory used - * by the kernel's message buffer. We allow 4 pages for the - * message buffer. - */ - startpfn = memc->mddt_pfn + memc->mddt_pg_cnt - 4 - 32; - startva = 0x20040000; - startpte = 0x40000000 - + (((startva >> 23) & 0x3ff) << PAGE_SHIFT) - + (((startva >> 13) & 0x3ff) << 3); - - for (i = 0; i < 32; i++) { - u_int64_t pte; - pte = ((startpfn + i) << 32) | 0x1101; - *(u_int64_t *) (startpte + 8 * i) = pte; - } -} - void main(void) { @@ -114,27 +70,18 @@ main(void) char bootfile[128]; /* - * Initialise the heap as early as possible. Once this is done, - * alloc() is usable. The stack is buried inside us, so this is - * safe. + * Initialise the heap as early as possible. Once this is done, alloc() is usable. + * The stack is buried inside us, so this is safe */ - extend_heap(); - setheap((void *)end, (void *)0x20080000); + setheap((void *)end, (void *)0x20040000); -#ifdef LOADER - /* - * If this is the two stage disk loader, add the memory used by - * the first stage to the heap. - */ - free_region((void *)PRIMARY_LOAD_ADDRESS, - (void *)SECONDARY_LOAD_ADDRESS); -#endif /* - * XXX Chicken-and-egg problem; we want to have console output - * early, but some console attributes may depend on reading from - * eg. the boot device, which we can't do yet. We can use - * printf() etc. once this is done. + * XXX Chicken-and-egg problem; we want to have console output early, but some + * console attributes may depend on reading from eg. the boot device, which we + * can't do yet. + * + * We can use printf() etc. once this is done. */ cons_probe(); @@ -142,11 +89,6 @@ main(void) OSFpal(); /* - * Initialise the block cache - */ - bcache_init(32, 512); /* 16k XXX tune this */ - - /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) diff --git a/sys/boot/alpha/libalpha/Makefile b/sys/boot/alpha/libalpha/Makefile index 4928647b7548..a82febf2e2a3 100644 --- a/sys/boot/alpha/libalpha/Makefile +++ b/sys/boot/alpha/libalpha/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.5 1998/10/14 09:53:25 peter Exp $ +# $Id: Makefile,v 1.4 1998/09/26 10:51:37 dfr Exp $ LIB= alpha NOPIC= true @@ -14,7 +14,7 @@ CFLAGS+= -DDEBUG CFLAGS+= -I${.CURDIR}/../../common -mno-fp-regs \ -I${.CURDIR}/../../.. -I. -#CFLAGS+= -DDISK_DEBUG +CFLAGS+= -DDISK_DEBUG #CPPFLAGS+= -DNO_DISKLABEL #CPPFLAGS+= -DSAVE_MEMORY diff --git a/sys/boot/alpha/libalpha/srmdisk.c b/sys/boot/alpha/libalpha/srmdisk.c index 6b7d17b8e76d..f7427bdb493f 100644 --- a/sys/boot/alpha/libalpha/srmdisk.c +++ b/sys/boot/alpha/libalpha/srmdisk.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: srmdisk.c,v 1.3 1998/11/02 23:28:10 msmith Exp $ + * $Id$ */ /* @@ -46,7 +46,6 @@ #include <machine/stdarg.h> #include <machine/prom.h> -#include "bootstrap.h" #include "libalpha.h" #define SRMDISK_SECSIZE 512 @@ -62,16 +61,18 @@ static int bd_init(void); static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize); -static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize); static int bd_open(struct open_file *f, void *vdev); static int bd_close(struct open_file *f); -static void bd_print(int verbose); struct open_disk { int od_fd; int od_unit; /* our unit number */ int od_boff; /* block offset from beginning of SRM disk */ int od_flags; +#define BD_MODEMASK 0x3 +#define BD_MODEINT13 0x0 +#define BD_MODEEDD1 0x1 +#define BD_MODEEDD3 0x2 #define BD_FLOPPY (1<<2) u_char od_buf[BUFSIZE]; /* transfer buffer (do we want/need this?) */ }; @@ -83,8 +84,7 @@ struct devsw srmdisk = { bd_strategy, bd_open, bd_close, - noioctl, - bd_print + noioctl }; /* @@ -120,23 +120,6 @@ bd_init(void) } /* - * Print information about disks - */ -static void -bd_print(int verbose) -{ - int i; - char line[80]; - - for (i = 0; i < nbdinfo; i++) { - sprintf(line, " disk%d: SRM drive %s", i, bdinfo[i].bd_name); - pager_output(line); - /* XXX more detail? */ - pager_output("\n"); - } -} - -/* * Attempt to open the disk described by (dev) for use by (f). * * Note that the philosophy here is "give them exactly what @@ -324,17 +307,7 @@ bd_close(struct open_file *f) } static int -bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize) -{ - struct bcache_devdata bcd; - - bcd.dv_strategy = bd_realstrategy; - bcd.dv_devdata = devdata; - return(bcache_strategy(&bcd, rw, dblk, size, buf, rsize)); -} - -static int -bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize) +bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize) { prom_return_t ret; struct open_disk *od = (struct open_disk *)devdata; diff --git a/sys/boot/alpha/libalpha/start.S b/sys/boot/alpha/libalpha/start.S index 39c3e48952c6..53063aba11ee 100644 --- a/sys/boot/alpha/libalpha/start.S +++ b/sys/boot/alpha/libalpha/start.S @@ -1,5 +1,5 @@ /* - * $Id: start.S,v 1.1.1.1 1998/08/21 03:17:42 msmith Exp $ + * $Id$ * From: $NetBSD: start.S,v 1.4 1998/03/28 00:54:15 cgd Exp $ */ @@ -51,15 +51,16 @@ NESTED(start, 1, ENTRY_FRAME, ra, 0, 0) Lstartgp: LDGP(pv) +#ifndef PRIMARY_BOOTBLOCK + lda sp,start /* start stack below text */ + lda sp,-ENTRY_FRAME(sp) +#endif + lda a0,_edata lda a1,_end subq a1,a0,a1 CALL(bzero) -#if defined(NETBOOT) || defined(LOADER) - lda sp,stack + 8192 - ENTRY_FRAME -#endif - CALL(main) /* transfer to C */ XLEAF(_rtt, 0) @@ -82,7 +83,3 @@ LEAF(cpu_number, 0) call_pal PAL_VMS_mfpr_whami RET END(cpu_number) - -#if defined(NETBOOT) || defined(LOADER) -BSS(stack, 8192) -#endif diff --git a/sys/boot/alpha/netboot/Makefile b/sys/boot/alpha/netboot/Makefile index 927522c4b638..bb4a77ea046d 100644 --- a/sys/boot/alpha/netboot/Makefile +++ b/sys/boot/alpha/netboot/Makefile @@ -16,7 +16,8 @@ SRCS+= main.c conf.c dev_net.c CFLAGS+= -mno-fp-regs CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR} CFLAGS+= -I${.OBJDIR} -CFLAGS+= -DNETBOOT +# Verbose ls causes extra heap usage +CFLAGS+= -DVERBOSE_LS CLEANFILES+= vers.c vers.o gensetdefs.o gensetdefs setdef0.o setdef1.o \ setdefs.h start.o @@ -28,7 +29,6 @@ CFLAGS+= -I${LIBSTANDDIR} CFLAGS+= -I${.CURDIR}/.. CRT= start.o STRIP= -BINDIR?= /boot all: ${BASE} @@ -49,7 +49,7 @@ ${BASE}.sym: ${OBJS} ${LIBSTAND} ${LIBALPHA} ${CRT} vers.o setdef0.o setdef1.o vers.o ${LIBSTAND} ${LIBALPHA} ${LIBSTAND} >${.OBJDIR}/${BASE}.list start.o: ${.CURDIR}/../libalpha/start.S - ${CC} -c ${CFLAGS} $< + ${CC} -c -DPRIMARY_BOOTBLOCK $< setdef0.o: setdefs.h diff --git a/sys/boot/common/Makefile.inc b/sys/boot/common/Makefile.inc index c29494ba6aef..805b0094eaa2 100644 --- a/sys/boot/common/Makefile.inc +++ b/sys/boot/common/Makefile.inc @@ -1,8 +1,7 @@ -# $Id: Makefile.inc,v 1.7 1998/11/02 23:28:10 msmith Exp $ +# $Id: Makefile.inc,v 1.5 1998/09/14 18:27:04 msmith Exp $ -SRCS+= bcache.c boot.c commands.c console.c devopen.c interp.c -SRCS+= interp_backslash.c interp_parse.c load_aout.c load_elf.c ls.c misc.c -SRCS+= module.c panic.c +SRCS+= boot.c commands.c console.c devopen.c interp.c interp_backslash.c +SRCS+= interp_parse.c load_aout.c load_elf.c ls.c misc.c module.c panic.c # Machine-independant ISA PnP .if HAVE_ISABUS @@ -11,8 +10,3 @@ SRCS+= isapnp.c .if HAVE_PNP SRCS+= pnp.c .endif - -# Forth interpreter -.if BOOT_FORTH -SRCS+= interp_forth.c -.endif diff --git a/sys/boot/common/bcache.c b/sys/boot/common/bcache.c deleted file mode 100644 index fc12f578f9fa..000000000000 --- a/sys/boot/common/bcache.c +++ /dev/null @@ -1,262 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: bcache.c,v 1.3 1998/11/04 00:29:01 msmith Exp $ - */ - -/* - * Simple LRU block cache - */ - -#include <stand.h> -#include <string.h> -#include <bitstring.h> - -#include "bootstrap.h" - -/* #define BCACHE_DEBUG */ - -#ifdef BCACHE_DEBUG -#define BCACHE_TIMEOUT 10 -# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __FUNCTION__ , ## args) -#else -#define BCACHE_TIMEOUT 2 -# define DEBUG(fmt, args...) -#endif - - -struct bcachectl -{ - daddr_t bc_blkno; - time_t bc_stamp; - int bc_count; -}; - -static struct bcachectl *bcache_ctl; -static caddr_t bcache_data; -static bitstr_t *bcache_miss; -static int bcache_nblks; -static int bcache_blksize; -static int bcache_hits, bcache_misses, bcache_ops, bcache_bypasses; -static int bcache_bcount; - -static void bcache_insert(caddr_t buf, daddr_t blkno); -static int bcache_lookup(caddr_t buf, daddr_t blkno); - -/* - * Initialise the cache for (nblks) of (bsize). - */ -int -bcache_init(int nblks, size_t bsize) -{ - int i; - - /* discard any old contents */ - if (bcache_data != NULL) { - free(bcache_data); - bcache_data = NULL; - free(bcache_ctl); - } - - /* Allocate control structures */ - bcache_nblks = nblks; - bcache_blksize = bsize; - bcache_data = malloc(bcache_nblks * bcache_blksize); - bcache_ctl = (struct bcachectl *)malloc(bcache_nblks * sizeof(struct bcachectl)); - bcache_miss = bit_alloc((bcache_nblks + 1) / 2); - if ((bcache_data == NULL) || (bcache_ctl == NULL) || (bcache_miss == NULL)) { - if (bcache_miss) - free(bcache_miss); - if (bcache_ctl) - free(bcache_ctl); - if (bcache_data) - free(bcache_data); - bcache_data = NULL; - return(ENOMEM); - } - - /* Invalidate the cache */ - for (i = 0; i < bcache_nblks; i++) { - bcache_ctl[i].bc_count = -1; - bcache_ctl[i].bc_blkno = -1; - } - - return(0); -} - -/* - * Handle a transfer request; fill in parts of the request that can - * be satisfied by the cache, use the supplied strategy routine to do - * device I/O and then use the I/O results to populate the cache. - * - * Requests larger than 1/2 the cache size will be bypassed and go - * directly to the disk. XXX tune this. - */ -int -bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf, size_t *rsize) -{ - struct bcache_devdata *dd = (struct bcache_devdata *)devdata; - int nblk, p_size; - daddr_t p_blk; - caddr_t p_buf; - int i, j, result; - - bcache_ops++; - - /* bypass large requests, or when the cache is inactive */ - if ((bcache_data == NULL) || ((size * 2 / bcache_blksize) > bcache_nblks)) { - DEBUG("bypass %d from %d", size / bcache_blksize, blk); - bcache_bypasses++; - return(dd->dv_strategy(dd->dv_devdata, rw, blk, size, buf, rsize)); - } - - nblk = size / bcache_blksize; - result = 0; - - /* Satisfy any cache hits up front */ - for (i = 0; i < nblk; i++) { - if (bcache_lookup(buf + (bcache_blksize * i), blk + i)) { - bit_set(bcache_miss, i); /* cache miss */ - bcache_misses++; - } else { - bit_clear(bcache_miss, i); /* cache hit */ - bcache_hits++; - } - } - - /* Go back and fill in any misses XXX optimise */ - p_blk = -1; - p_buf = NULL; - p_size = 0; - for (i = 0; i < nblk; i++) { - if (bit_test(bcache_miss, i)) { - /* miss, add to pending transfer */ - if (p_blk == -1) { - p_blk = blk + i; - p_buf = buf + (bcache_blksize * i); - p_size = 1; - } else { - p_size++; - } - } else if (p_blk != -1) { - /* hit, complete pending transfer */ - result = dd->dv_strategy(dd->dv_devdata, rw, p_blk, p_size * bcache_blksize, p_buf, NULL); - if (result != 0) - goto done; - for (j = 0; j < p_size; j++) - bcache_insert(p_buf + (j * bcache_blksize), p_blk + j); - p_blk = -1; - } - } - if (p_blk != -1) { - /* pending transfer left */ - result = dd->dv_strategy(dd->dv_devdata, rw, p_blk, p_size * bcache_blksize, p_buf, NULL); - if (result != 0) - goto done; - for (j = 0; j < p_size; j++) - bcache_insert(p_buf + (j * bcache_blksize), p_blk + j); - } - - done: - if ((result == 0) && (rsize != NULL)) - *rsize = size; - return(result); -} - - -/* - * Insert a block into the cache. Retire the oldest block to do so, if required. - * - * XXX the LRU algorithm will fail after 2^31 blocks have been transferred. - */ -static void -bcache_insert(caddr_t buf, daddr_t blkno) -{ - time_t now; - int i, cand, ocount; - - time(&now); - cand = 0; /* assume the first block */ - ocount = bcache_ctl[0].bc_count; - - /* find the oldest block */ - for (i = 1; i < bcache_nblks; i++) { - if (bcache_ctl[i].bc_blkno == blkno) { - /* reuse old entry */ - cand = i; - break; - } - if (bcache_ctl[i].bc_count < ocount) { - ocount = bcache_ctl[i].bc_count; - cand = i; - } - } - - DEBUG("insert blk %d -> %d @ %d # %d", blkno, cand, now, bcache_bcount); - bcopy(buf, bcache_data + (bcache_blksize * cand), bcache_blksize); - bcache_ctl[cand].bc_blkno = blkno; - bcache_ctl[cand].bc_stamp = now; - bcache_ctl[cand].bc_count = bcache_bcount++; -} - -/* - * Look for a block in the cache. Blocks more than BCACHE_TIMEOUT seconds old - * may be stale (removable media) and thus are discarded. Copy the block out - * if successful and return zero, or return nonzero on failure. - */ -static int -bcache_lookup(caddr_t buf, daddr_t blkno) -{ - time_t now; - int i; - - time(&now); - - for (i = 0; i < bcache_nblks; i++) - /* cache hit? */ - if ((bcache_ctl[i].bc_blkno == blkno) && ((bcache_ctl[i].bc_stamp + BCACHE_TIMEOUT) >= now)) { - bcopy(bcache_data + (bcache_blksize * i), buf, bcache_blksize); - DEBUG("hit blk %d <- %d (now %d then %d)", blkno, i, now, bcache_ctl[i].bc_stamp); - return(0); - } - return(ENOENT); -} - -COMMAND_SET(bcachestat, "bcachestat", "get disk block cache stats", command_bcache); - -static int -command_bcache(int argc, char *argv[]) -{ - int i; - - for (i = 0; i < bcache_nblks; i++) { - printf("%08x %04x %04x|", bcache_ctl[i].bc_blkno, bcache_ctl[i].bc_stamp & 0xffff, bcache_ctl[i].bc_count & 0xffff); - if (((i + 1) % 4) == 0) - printf("\n"); - } - printf("\n%d ops %d bypasses %d hits %d misses\n", bcache_ops, bcache_bypasses, bcache_hits, bcache_misses); - return(CMD_OK); -} - diff --git a/sys/boot/common/boot.c b/sys/boot/common/boot.c index 2de8603e881e..608c9d02a921 100644 --- a/sys/boot/common/boot.c +++ b/sys/boot/common/boot.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: boot.c,v 1.9 1998/10/31 17:12:32 dfr Exp $ + * $Id: boot.c,v 1.6 1998/10/11 10:10:41 peter Exp $ */ /* @@ -38,7 +38,7 @@ static char *getbootfile(int try); /* List of kernel names to try (may be overwritten by boot.config) XXX should move from here? */ -static char *default_bootfiles = "kernel;kernel.old"; +static char *default_bootfiles = "kernel,kernel.old"; static int autoboot_tried; @@ -203,13 +203,11 @@ autoboot(int delay, char *prompt) break; } if (ntime != otime) { - printf("\rBooting [%s] in %d seconds... ", getbootfile(0), (int)(when - ntime)); + printf("\rBooting [%s] in %d seconds...", getbootfile(0), (int)(when - ntime)); otime = ntime; cr = 1; } } - if (yes) - printf("\rBooting [%s]... ", getbootfile(0)); if (cr) putchar('\n'); if (yes) { @@ -243,11 +241,11 @@ getbootfile(int try) spec = default_bootfiles; while ((try > 0) && (spec != NULL)) { - spec = strchr(spec, ';'); + spec = strchr(spec, ','); try--; } if (spec != NULL) { - if ((ep = strchr(spec, ';')) != NULL) { + if ((ep = strchr(spec, ',')) != NULL) { len = ep - spec; } else { len = strlen(spec); diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index ed450d91602e..84f6d4809764 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -23,11 +23,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bootstrap.h,v 1.17 1999/01/15 00:31:45 abial Exp $ + * $Id: bootstrap.h,v 1.12 1998/10/09 07:09:22 msmith Exp $ */ #include <sys/types.h> -#include <sys/queue.h> /* XXX debugging */ extern struct console vidconsole; @@ -56,7 +55,7 @@ extern char command_errbuf[]; /* XXX blah, length */ /* interp.c */ extern void interact(void); -extern int source(char *filename); +extern void source(char *filename); /* interp_parse.c */ extern int parse(int *argc, char ***argv, char *str); @@ -72,15 +71,6 @@ extern size_t strlenout(vm_offset_t str); extern char *strdupout(vm_offset_t str); /* - * Disk block cache - */ -struct bcache_devdata -{ - int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size, void *buf, size_t *rsize); - void *dv_devdata; -}; - -/* * Modular console support. */ struct console @@ -104,44 +94,33 @@ extern void cons_probe(void); /* * Plug-and-play enumerator/configurator interface. */ -struct pnphandler +struct pnpident { - char *pp_name; /* handler/bus name */ - void (* pp_enumerate)(void); /* enumerate PnP devices, add to chain */ + char *id_ident; /* ASCII identifier, actual format varies with bus/handler */ + struct pnpident *id_next; /* the next identifier */ }; -struct pnpident +struct pnphandler; +struct pnpinfo { - char *id_ident; /* ASCII identifier, actual format varies with bus/handler */ - STAILQ_ENTRY(pnpident) id_link; + struct pnpident *pi_ident; /* list of identifiers */ + int pi_revision; /* optional revision (or -1) if not supported */ + char *pi_module; /* module/args nominated to handle device */ + int pi_argc; /* module arguments */ + char **pi_argv; + struct pnphandler *pi_handler; /* handler which detected this device */ + struct pnpinfo *pi_next; }; -struct pnpinfo +struct pnphandler { - char *pi_desc; /* ASCII description, optional */ - int pi_revision; /* optional revision (or -1) if not supported */ - char *pi_module; /* module/args nominated to handle device */ - int pi_argc; /* module arguments */ - char **pi_argv; - struct pnphandler *pi_handler; /* handler which detected this device */ - STAILQ_HEAD(,pnpident) pi_ident; /* list of identifiers */ - STAILQ_ENTRY(pnpinfo) pi_link; + char *pp_name; /* handler/bus name */ + void (* pp_enumerate)(struct pnpinfo **); /* add detected devices to chain */ }; extern struct pnphandler *pnphandlers[]; /* provided by MD code */ extern void pnp_addident(struct pnpinfo *pi, char *ident); -extern struct pnpinfo *pnp_allocinfo(void); -extern void pnp_freeinfo(struct pnpinfo *pi); -extern void pnp_addinfo(struct pnpinfo *pi); -extern char *pnp_eisaformat(u_int8_t *data); - -/* - * < 0 - No ISA in system - * == 0 - Maybe ISA, search for read data port - * > 0 - ISA in system, value is read data port address - */ -extern int isapnp_readport; /* * Module metadata header. @@ -201,53 +180,58 @@ extern vm_offset_t aout_findsym(char *name, struct loaded_module *mp); extern int elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result); -#ifndef NEW_LINKER_SET -#include <sys/linker_set.h> - -/* XXX just for conversion's sake, until we move to the new linker set code */ - -#define SET_FOREACH(pvar, set) \ - for (pvar = set.ls_items; \ - pvar < set.ls_items + set.ls_length; \ - pvar++) - -#else /* NEW_LINKER_SET */ +#if defined(__ELF__) /* - * Private macros, not to be used outside this header file. + * Alpha GAS needs an align before the section change. It seems to assume + * that after the .previous, it is aligned, so the following .align 3 is + * ignored. Since the previous instructions often contain strings, this is + * a problem. */ -#define __MAKE_SET(set, sym) \ - static void *__CONCAT(__setentry,__LINE__) \ - __attribute__((__section__("set_" #set),__unused__)) = &sym -#define __SET_BEGIN(set) \ - ({ extern void *__CONCAT(__start_set_,set); \ - &__CONCAT(__start_set_,set); }) -#define __SET_END(set) \ - ({ extern void *__CONCAT(__stop_set_,set); \ - &__CONCAT(__stop_set_,set); }) -/* - * Public macros. - */ +#ifdef __alpha__ +#define MAKE_SET(set, sym) \ + static void const * const __set_##set##_sym_##sym = &sym; \ + __asm(".align 3"); \ + __asm(".section .set." #set ",\"aw\""); \ + __asm(".quad " #sym); \ + __asm(".previous") +#else +#define MAKE_SET(set, sym) \ + static void const * const __set_##set##_sym_##sym = &sym; \ + __asm(".section .set." #set ",\"aw\""); \ + __asm(".long " #sym); \ + __asm(".previous") +#endif +#define TEXT_SET(set, sym) MAKE_SET(set, sym) +#define DATA_SET(set, sym) MAKE_SET(set, sym) +#define BSS_SET(set, sym) MAKE_SET(set, sym) +#define ABS_SET(set, sym) MAKE_SET(set, sym) -/* Add an entry to a set. */ -#define TEXT_SET(set, sym) __MAKE_SET(set, sym) -#define DATA_SET(set, sym) __MAKE_SET(set, sym) -#define BSS_SET(set, sym) __MAKE_SET(set, sym) -#define ABS_SET(set, sym) __MAKE_SET(set, sym) +#else /* - * Iterate over all the elements of a set. - * - * Sets always contain addresses of things, and "pvar" points to words - * containing those addresses. Thus is must be declared as "type **pvar", - * and the address of each set item is obtained inside the loop by "*pvar". + * Linker set support, directly from <sys/kernel.h> + * + * NB: the constants defined below must match those defined in + * ld/ld.h. Since their calculation requires arithmetic, we + * can't name them symbolically (e.g., 23 is N_SETT | N_EXT). */ -#define SET_FOREACH(pvar, set) \ - for (pvar = (__typeof__(pvar))__SET_BEGIN(set); \ - pvar < (__typeof__(pvar))__SET_END(set); pvar++) +#define MAKE_SET(set, sym, type) \ + static void const * const __set_##set##_sym_##sym = &sym; \ + __asm(".stabs \"_" #set "\", " #type ", 0, 0, _" #sym) +#define TEXT_SET(set, sym) MAKE_SET(set, sym, 23) +#define DATA_SET(set, sym) MAKE_SET(set, sym, 25) +#define BSS_SET(set, sym) MAKE_SET(set, sym, 27) +#define ABS_SET(set, sym) MAKE_SET(set, sym, 21) + #endif +struct linker_set { + int ls_length; + const void *ls_items[1]; /* really ls_length of them, trailing NULL */ +}; + /* * Support for commands */ diff --git a/sys/boot/common/commands.c b/sys/boot/common/commands.c index fe0eb54d7707..77cc43ca0e71 100644 --- a/sys/boot/common/commands.c +++ b/sys/boot/common/commands.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: commands.c,v 1.8 1999/01/09 02:34:48 msmith Exp $ + * $Id: commands.c,v 1.4 1998/10/07 02:38:26 msmith Exp $ */ #include <stand.h> @@ -34,181 +34,35 @@ char *command_errmsg; char command_errbuf[256]; /* XXX should have procedural interface for setting, size limit? */ - - -/* - * Help is read from a formatted text file. - * - * Entries in the file are formatted as - -# Ttopic [Ssubtopic] Ddescription -help -text -here -# - - * - * Note that for code simplicity's sake, the above format must be followed - * exactly. - * - * Subtopic entries must immediately follow the topic (this is used to - * produce the listing of subtopics). - * - * If no argument(s) are supplied by the user, the help for 'help' is displayed. - */ -COMMAND_SET(help, "help", "detailed help", command_help); - -static int -help_getnext(int fd, char **topic, char **subtopic, char **desc) -{ - char line[81], *cp, *ep; - - for (;;) { - if (fgetstr(line, 80, fd) < 0) - return(0); - - if ((strlen(line) < 3) || (line[0] != '#') || (line[1] != ' ')) - continue; - - *topic = *subtopic = *desc = NULL; - cp = line + 2; - while((cp != NULL) && (*cp != 0)) { - ep = strchr(cp, ' '); - if ((*cp == 'T') && (*topic == NULL)) { - if (ep != NULL) - *ep++ = 0; - *topic = strdup(cp + 1); - } else if ((*cp == 'S') && (*subtopic == NULL)) { - if (ep != NULL) - *ep++ = 0; - *subtopic = strdup(cp + 1); - } else if (*cp == 'D') { - *desc = strdup(cp + 1); - ep = NULL; - } - cp = ep; - } - if (*topic == NULL) { - if (*subtopic != NULL) - free(*subtopic); - if (*desc != NULL) - free(*desc); - continue; - } - return(1); - } -} - -static void -help_emitsummary(char *topic, char *subtopic, char *desc) -{ - int i; - pager_output(" "); - pager_output(topic); - i = strlen(topic); - if (subtopic != NULL) { - pager_output(" "); - pager_output(subtopic); - i += strlen(subtopic) + 1; - } - if (desc != NULL) { - do { - pager_output(" "); - } while (i++ < 30); - pager_output(desc); - } - pager_output("\n"); -} +COMMAND_SET(help, "help", "detailed help", command_help); - static int -command_help(int argc, char *argv[]) +command_help(int argc, char *argv[]) { - char buf[81]; /* XXX buffer size? */ - int hfd, matched, doindex; - char *topic, *subtopic, *t, *s, *d; + char helppath[80]; /* XXX buffer size? */ /* page the help text from our load path */ - sprintf(buf, "%s/boot/loader.help", getenv("loaddev")); - if ((hfd = open(buf, O_RDONLY)) < 0) { + sprintf(helppath, "%s/boot/boot.help", getenv("loaddev")); + printf("%s\n", helppath); + if (pager_file(helppath) == -1) printf("Verbose help not available, use '?' to list commands\n"); - return(CMD_OK); - } - - /* pick up request from arguments */ - topic = subtopic = NULL; - switch(argc) { - case 3: - subtopic = strdup(argv[2]); - case 2: - topic = strdup(argv[1]); - break; - case 1: - topic = strdup("help"); - break; - default: - command_errmsg = "usage is 'help <topic> [<subtopic>]"; - return(CMD_ERROR); - } - - /* magic "index" keyword */ - doindex = !strcmp(topic, "index"); - matched = doindex; - - /* Scan the helpfile looking for help matching the request */ - pager_open(); - while(help_getnext(hfd, &t, &s, &d)) { - - if (doindex) { /* dink around formatting */ - help_emitsummary(t, s, d); - - } else if (strcmp(topic, t)) { - /* topic mismatch */ - if(matched) /* nothing more on this topic, stop scanning */ - break; - - } else { - /* topic matched */ - matched = 1; - if (((subtopic == NULL) && (s == NULL)) || - ((subtopic != NULL) && (s != NULL) && !strcmp(subtopic, s))) { - /* exact match, print text */ - while((fgetstr(buf, 80, hfd) >= 0) && (buf[0] != '#')) { - pager_output(buf); - pager_output("\n"); - } - } else if ((subtopic == NULL) && (s != NULL)) { - /* topic match, list subtopics */ - help_emitsummary(t, s, d); - } - } - free(t); - free(s); - free(d); - } - pager_close(); - close(hfd); - if (!matched) { - sprintf(command_errbuf, "no help available for '%s'", topic); - return(CMD_ERROR); - } return(CMD_OK); } - COMMAND_SET(commandlist, "?", "list commands", command_commandlist); static int command_commandlist(int argc, char *argv[]) { struct bootblk_command **cmdp; + int i; printf("Available commands:\n"); - SET_FOREACH(cmdp, Xcommand_set) { - if (((*cmdp)->c_name != NULL) && ((*cmdp)->c_desc != NULL)) - printf(" %-15s %s\n", (*cmdp)->c_name, (*cmdp)->c_desc); - } + cmdp = (struct bootblk_command **)Xcommand_set.ls_items; + for (i = 0; i < Xcommand_set.ls_length; i++) + if ((cmdp[i]->c_name != NULL) && (cmdp[i]->c_desc != NULL)) + printf(" %-15s %s\n", cmdp[i]->c_name, cmdp[i]->c_desc); return(CMD_OK); } @@ -299,7 +153,6 @@ command_echo(int argc, char *argv[]) nl = 0; optind = 1; - optreset = 1; while ((ch = getopt(argc, argv, "n")) != -1) { switch(ch) { case 'n': @@ -344,7 +197,6 @@ command_read(int argc, char *argv[]) timeout = -1; prompt = NULL; optind = 1; - optreset = 1; while ((c = getopt(argc, argv, "p:t:")) != -1) { switch(c) { @@ -382,47 +234,3 @@ command_read(int argc, char *argv[]) setenv(name, buf, 1); return(CMD_OK); } - -/* - * List all disk-like devices - */ -COMMAND_SET(lsdev, "lsdev", "list all devices", command_lsdev); - -static int -command_lsdev(int argc, char *argv[]) -{ - int verbose, ch, i; - char line[80]; - - verbose = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "v")) != -1) { - switch(ch) { - case 'v': - verbose = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); - } - } - argv += (optind); - argc -= (optind); - - pager_open(); - for (i = 0; devsw[i] != NULL; i++) { - if (devsw[i]->dv_print != NULL){ - sprintf(line, "%s @ %p\n", devsw[i]->dv_name, devsw[i]->dv_print); - pager_output(line); - devsw[i]->dv_print(verbose); - } else { - sprintf(line, "%s: (unknown)\n", devsw[i]->dv_name); - pager_output(line); - } - } - pager_close(); - return(CMD_OK); -} - diff --git a/sys/boot/common/console.c b/sys/boot/common/console.c index 8c4377f2bcd4..b9534d304030 100644 --- a/sys/boot/common/console.c +++ b/sys/boot/common/console.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: console.c,v 1.3 1998/10/11 10:19:11 peter Exp $ + * $Id: console.c,v 1.2 1998/09/26 01:29:13 msmith Exp $ */ #include <stand.h> @@ -150,12 +150,8 @@ cons_set(struct env_var *ev, int flags, void *value) { int cons, active; - if ((value == NULL) || ((active = cons_find(value)) == -1)) { - if (value != NULL) - printf("no such console '%s'\n", (char *)value); - printf("Available consoles:\n"); - for (cons = 0; consoles[cons] != NULL; cons++) - printf(" %s\n", consoles[cons]->c_name); + if ((active = cons_find(value)) == -1) { + printf("no such console '%s'\n", (char *)value); return(CMD_ERROR); } diff --git a/sys/boot/common/help.common b/sys/boot/common/help.common deleted file mode 100644 index e467b1ca7092..000000000000 --- a/sys/boot/common/help.common +++ /dev/null @@ -1,262 +0,0 @@ -################################################################################ -# Thelp DDisplay command help - - help [topic [subtopic]] - ? - - The help command displays help on commands and their usage. - - In command help, a term enclosed with <...> indicates a value as - described by the term. A term enclosed with [...] is optional, - and may not be required by all forms of the command. - - Some commands may not be availalble. Use the '?' command to list - most available commands. - -################################################################################ -# Tautoboot DBoot after a delay - - autoboot [<delay> [<prompt>]] - - Displays <prompt> or a default prompt, and counts down <delay> seconds - before attempting to boot. If <delay> is not specified, the default - value is 10. - -################################################################################ -# Tboot DBoot immediately - - boot [-<arg> ...] [<kernelname>] - - Boot the system. If arguments are specified, they are added to the - arguments for the kernel. If <kernelname> is specified, and a kernel - has not already been loaded, it will be booted instead of the default - kernel. - -################################################################################ -# Techo DEcho arguments - - echo [-n] [<message>] - - Emits <message>, with no trailing newline if -n is specified. This is - most useful in conjunction with scripts and the '@' line prefix. - - Variables are substituted by prefixing them with $, eg. - - echo Current device is $currdev - - will print the current device. - -################################################################################ -# Tload DLoad a kernel or module - - load [-t <type>] <filename> - - Loads the module contained in <filename> into memory. If no other - modules are loaded, <filename> must be a kernel or the command will - fail. - - If -t is specified, the module is loaded as raw data of <type>, for - later use by the kernel or other modules. <type> may be any string. - -################################################################################ -# Tls DList files - - ls [-l] [<path>] - - Displays a listing of files in the directory <path>, or the root - directory of the current device if <path> is not specified. - - The -l argument displays file sizes as well; the process of obtaining - file sizes on some media may be very slow. - -################################################################################ -# Tlsdev DList devices - - lsdev [-v] - - List all of the devices from which it may be possible to load modules. - If -v is specified, print more details. - -################################################################################ -# Tlsmod DList modules - - lsmod [-v] - - List loaded modules. If [-v] is specified, print more details. - -################################################################################ -# Tpnpscan DScan for PnP devices - - pnpscan [-v] - - Scan for Plug-and-Play devices. This command is normally automatically - run as part of the boot process, in order to dynamically load modules - required for system operation. - - If the -v argument is specified, details on the devices found will - be printed. - -################################################################################ -# Tset DSet a variable - - set <variable name> - set <variable name>=<value> - - The set command is used to set variables. - -################################################################################ -# Tset Sautoboot_delay DSet the default autoboot delay - - set autoboot_delay=<value> - - Sets the default delay for the autoboot command to <value> seconds. - -################################################################################ -# Tset Sbootfile DSet the default boot file set - - set bootfile=<filename>[,<filename>...] - - The default search path for bootable kernels is /kernel,/kernel.old. - It may be overridden by setting the bootfile variable to a - semicolon-separated list of paths, which will be searched for in turn. - -################################################################################ -# Tset Sboot_askname DPrompt for root device - - set boot_askname - - Instructs the kernel to prompt the user for the name of the root device - when the kernel is booted. - -################################################################################ -# Tset Sboot_ddb DDrop to the kernel debugger (DDB) - - set boot_ddb - - Instructs the kernel to start in the DDB debugger, rather than - proceeding to initialise when booted. - -################################################################################ -# Tset Sboot_gdb DSelect gdb-remote mode - - set boot_gdb - - Selects gdb-remote mode for the kernel debugger by default. - -################################################################################ -# Tset Sboot_single DStart system in single-user mode - - set boot_single - - Prevents the kernel from initiating a multi-user startup, single-user - mode will be entered when the kernel has finished device probes. - -################################################################################ -# Tset Sboot_verbose DVerbose boot messages - - set boot_verbose - - Setting this variable causes extra debugging information to be printed - by the kernel during the boot phase. - -################################################################################ -# Tset Sconsole DSet the current console - - set console[=<value>] - - Sets the current console. If <value> is omitted, a list of valid - consoles will be displayed. - -################################################################################ -# Tset Scurrdev DSet the current device - - set currdev=<device> - - Selects the default device. Syntax for devices is odd. - -################################################################################ -# Tset Smodule_path DSet the module search path - - set module_path=<path>[,<path>...] - - Sets the list of directories which will be searched in for modules - named in a load command or implicitly required by a dependancy. - -################################################################################ -# Tset Sprompt DSet the command prompt - - set prompt=<value> - - The command prompt is displayed when the loader is waiting for input. - Variable substitution is performed on the prompt. The default - prompt can be set with: - - set prompt=\$currdev> - -################################################################################ -# Tset Srootdev DSet the root filesystem - - set rootdev=<path> - - By default the value of $currdev is used to set the root filesystem - when the kernel is booted. This can be overridden by setting - $rootdev explicitly. - -################################################################################ -# Tshow DShow the values of variables - - show [<variable>] - - Displays the value of <variable>, or all variables if not specified. - Multiple paths can be separated with a semicolon. - - See the set command for a list of some variables. - -################################################################################ -# Tsource DRead commands from a script file - - source <filename> - - The entire contents of <filename> are read into memory before executing - commands, so it is safe to source a file from removable media. - - A number of modifiers may be prefixed to commands within a script file - to alter their behaviour: - - @ Suppresses the printing of the command when executed. - - - Prevents the script from terminating if the command returns - an error. - -################################################################################ -# Tread DRead input from the terminal - - read [-t <value>] [-p <prompt>] [<variable name>] - - The read command reads a line of input from the terminal. If the - -t argument is specified, it will return nothing if no input has been - received after <value> seconds. (Any keypress will cancel the - timeout). - - If -p is specified, <prompt> is printed before reading input. No - newline is emitted after the prompt. - - If a variable name is supplied, the variable is set to the value read, - less any terminating newline. - -################################################################################ -# Tunload DRemove all modules from memory - - unload - - This command removes any kernel and all loaded modules from memory. - -################################################################################ -# Tunset DUnset a variable - - unset <variable name> - - If allowed, the named variable's value is discarded and the variable - is removed. - -################################################################################ diff --git a/sys/boot/common/interp.c b/sys/boot/common/interp.c index 22d2199beebc..d24ed6e3182a 100644 --- a/sys/boot/common/interp.c +++ b/sys/boot/common/interp.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: interp.c,v 1.11 1999/01/13 21:59:58 abial Exp $ + * $Id: interp.c,v 1.5 1998/10/07 02:38:26 msmith Exp $ */ /* * Simple commandline interpreter, toplevel and misc. @@ -35,15 +35,6 @@ #include <string.h> #include "bootstrap.h" -#ifdef BOOT_FORTH -#include "ficl.h" -#define RETURN(x) stackPushINT32(bf_vm->pStack,!x); return(x) - -extern FICL_VM *bf_vm; -#else -#define RETURN(x) return(x) -#endif - #define MAXARGS 20 /* maximum number of arguments allowed */ static void prompt(void); @@ -51,10 +42,10 @@ static void prompt(void); /* * Perform the command */ -int +static int perform(int argc, char *argv[]) { - int result; + int i, result; struct bootblk_command **cmdp; bootblk_cmd_t *cmd; @@ -67,17 +58,17 @@ perform(int argc, char *argv[]) cmd = NULL; result = CMD_ERROR; - /* search the command set for the command */ - SET_FOREACH(cmdp, Xcommand_set) { - if (((*cmdp)->c_name != NULL) && !strcmp(argv[0], (*cmdp)->c_name)) - cmd = (*cmdp)->c_fn; + cmdp = (struct bootblk_command **)Xcommand_set.ls_items; + for (i = 0; i < Xcommand_set.ls_length; i++) { + if ((cmdp[i]->c_name != NULL) && !strcmp(argv[0], cmdp[i]->c_name)) + cmd = cmdp[i]->c_fn; } if (cmd != NULL) { result = (cmd)(argc, argv); } else { command_errmsg = "unknown command"; } - RETURN(result); + return(result); } /* @@ -87,20 +78,13 @@ void interact(void) { char input[256]; /* big enough? */ -#ifndef BOOT_FORTH int argc; char **argv; -#endif - -#ifdef BOOT_FORTH - bf_init(); -#endif /* * Read our default configuration */ - if(source("/boot/loader.rc")!=CMD_OK) - source("/boot/boot.conf"); + source("/boot/boot.conf"); printf("\n"); /* * Before interacting, we might want to autoboot. @@ -118,9 +102,6 @@ interact(void) input[0] = '\0'; prompt(); ngets(input, sizeof(input)); -#ifdef BOOT_FORTH - bf_run(input); -#else if (!parse(&argc, &argv, input)) { if (perform(argc, argv)) printf("%s: %s\n", argv[0], command_errmsg); @@ -128,7 +109,6 @@ interact(void) } else { printf("parse error\n"); } -#endif } } @@ -147,12 +127,10 @@ static int command_source(int argc, char *argv[]) { int i; - int res; - res=CMD_OK; - for (i = 1; (i < argc) && (res == CMD_OK); i++) - res=source(argv[i]); - return(res); + for (i = 1; i < argc; i++) + source(argv[i]); + return(CMD_OK); } struct sourceline @@ -165,18 +143,18 @@ struct sourceline struct sourceline *next; }; -int +void source(char *filename) { struct sourceline *script, *se, *sp; char input[256]; /* big enough? */ - int argc,res; + int argc; char **argv, *cp; int fd, flags, line; if (((fd = open(filename, O_RDONLY)) == -1)) { - sprintf(command_errbuf,"can't open '%s': %s\n", filename, strerror(errno)); - return(CMD_ERROR); + printf("can't open '%s': %s\n", filename, strerror(errno)); + return; } /* @@ -223,7 +201,6 @@ source(char *filename) * Execute the script */ argv = NULL; - res = CMD_OK; for (sp = script; sp != NULL; sp = sp->next) { /* print if not being quiet */ @@ -237,16 +214,13 @@ source(char *filename) if ((argc > 0) && (perform(argc, argv) != 0)) { /* normal command */ printf("%s: %s\n", argv[0], command_errmsg); - if (!(sp->flags & SL_IGNOREERR)) { - res=CMD_ERROR; + if (!(sp->flags & SL_IGNOREERR)) break; - } } free(argv); argv = NULL; } else { printf("%s line %d: parse error\n", filename, sp->line); - res=CMD_ERROR; break; } } @@ -257,7 +231,6 @@ source(char *filename) script = script->next; free(se); } - return(res); } /* diff --git a/sys/boot/common/interp_backslash.c b/sys/boot/common/interp_backslash.c index 6de118ec63fc..8807fdaa9645 100644 --- a/sys/boot/common/interp_backslash.c +++ b/sys/boot/common/interp_backslash.c @@ -11,7 +11,7 @@ * Jordan K. Hubbard * 29 August 1998 * - * $Id: interp_backslash.c,v 1.2 1998/09/03 06:14:41 jkh Exp $ + * $Id: interp_backslash.c,v 1.1 1998/09/01 00:41:24 msmith Exp $ * * Routine for doing backslash elimination. */ @@ -52,10 +52,9 @@ backslash(char *str) str++; break; - /* preserve backslashed quotes, dollar signs */ + /* preserve backslashed quotes */ case '\'': case '"': - case '$': new_str[i++] = '\\'; new_str[i++] = *str++; break; diff --git a/sys/boot/common/interp_forth.c b/sys/boot/common/interp_forth.c deleted file mode 100644 index 68e09340b0ad..000000000000 --- a/sys/boot/common/interp_forth.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: interp_forth.c,v 1.8 1998/12/22 11:41:51 abial Exp $ - */ - -#include <string.h> -#include <stand.h> -#include "bootstrap.h" -#include "ficl.h" - -/* #define BFORTH_DEBUG */ - -#ifdef BFORTH_DEBUG -# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __FUNCTION__ , ## args) -#else -# define DEBUG(fmt, args...) -#endif - -/* - * BootForth Interface to Ficl Forth interpreter. - */ - -FICL_VM *bf_vm; - -/* - * Shim for taking commands from BF and passing them out to 'standard' - * argv/argc command functions. - */ -static void -bf_command(FICL_VM *vm) -{ - char *name, *line, *tail, *cp; - int len; - struct bootblk_command **cmdp; - bootblk_cmd_t *cmd; - int argc, result; - char **argv; - - /* Get the name of the current word */ - name = vm->runningWord->name; - - /* Find our command structure */ - cmd = NULL; - SET_FOREACH(cmdp, Xcommand_set) { - if (((*cmdp)->c_name != NULL) && !strcmp(name, (*cmdp)->c_name)) - cmd = (*cmdp)->c_fn; - } - if (cmd == NULL) - panic("callout for unknown command '%s'", name); - - /* Get remainder of invocation */ - tail = vmGetInBuf(vm); - for (cp = tail, len = 0; *cp != 0 && *cp != '\n'; cp++, len++) - ; - - line = malloc(strlen(name) + len + 2); - strcpy(line, name); - if (len > 0) { - strcat(line, " "); - strncat(line, tail, len); - vmUpdateTib(vm, tail + len); - } - DEBUG("cmd '%s'", line); - - command_errmsg = command_errbuf; - command_errbuf[0] = 0; - if (!parse(&argc, &argv, line)) { - result = (cmd)(argc, argv); - free(argv); - if(result != 0) { - vmTextOut(vm,argv[0],0); - vmTextOut(vm,": ",0); - vmTextOut(vm,command_errmsg,1); - } - } else { - vmTextOut(vm, "parse error\n", 1); - result=1; - } - free(line); - stackPushINT32(vm->pStack,!result); -} - -/* - * Initialise the Forth interpreter, create all our commands as words. - */ -void -bf_init(void) -{ - struct bootblk_command **cmdp; - int fd; - - ficlInitSystem(4000); /* Default dictionary ~4000 cells */ - bf_vm = ficlNewVM(); - - /* make all commands appear as Forth words */ - SET_FOREACH(cmdp, Xcommand_set) - ficlBuild((*cmdp)->c_name, bf_command, FW_DEFAULT); - - /* try to load and run init file if present */ - if ((fd = open("/boot/boot.4th", O_RDONLY)) != -1) { - (void)ficlExecFD(bf_vm, fd); - close(fd); - } -} - -/* - * Feed a line of user input to the Forth interpreter - */ -void -bf_run(char *line) -{ - int result; - - result = ficlExec(bf_vm, line); - DEBUG("ficlExec '%s' = %d", line, result); - - if (result == VM_USEREXIT) - panic("interpreter exit"); -} diff --git a/sys/boot/common/interp_parse.c b/sys/boot/common/interp_parse.c index 865c8cbc0501..ef235632bd66 100644 --- a/sys/boot/common/interp_parse.c +++ b/sys/boot/common/interp_parse.c @@ -11,7 +11,7 @@ * Jordan K. Hubbard * 29 August 1998 * - * $Id: interp_parse.c,v 1.5 1999/01/10 05:08:12 msmith Exp $ + * $Id: interp_parse.c,v 1.3 1998/09/04 02:43:26 msmith Exp $ * * The meat of the simple parser. */ @@ -100,11 +100,7 @@ parse(int *argc, char ***argv, char *str) while (*p) { switch (state) { case STR: - if ((*p == '\\') && p[1]) { - p++; - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } else if (isquote(*p)) { + if (isquote(*p)) { quote = quote ? 0 : *p; ++p; } diff --git a/sys/boot/common/isapnp.c b/sys/boot/common/isapnp.c index 865e8f683e15..cc28da6c954f 100644 --- a/sys/boot/common/isapnp.c +++ b/sys/boot/common/isapnp.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: isapnp.c,v 1.3 1998/10/21 20:07:04 msmith Exp $ + * $Id: isapnp.c,v 1.1 1998/09/18 00:24:25 msmith Exp $ */ /* @@ -43,17 +43,17 @@ static void isapnp_write(int d, u_char r); static u_char isapnp_read(int d); static void isapnp_send_Initiation_LFSR(); static int isapnp_get_serial(u_int8_t *p); -static int isapnp_isolation_protocol(void); -static void isapnp_enumerate(void); +static int isapnp_isolation_protocol(struct pnpinfo **pnplist); +static void isapnp_enumerate(struct pnpinfo **pnplist); /* PnP read data port */ -int isapnp_readport = 0; +static int pnp_rd_port; #define _PNP_ID_LEN 9 struct pnphandler isapnphandler = { - "ISA bus", + "isapnp", isapnp_enumerate }; @@ -68,7 +68,7 @@ static u_char isapnp_read(int d) { outb (_PNP_ADDRESS, d); - return (inb(isapnp_readport)); + return (inb(3 | (pnp_rd_port <<2))); } /* @@ -104,11 +104,11 @@ isapnp_get_serial(u_int8_t *data) bzero(data, _PNP_ID_LEN); outb(_PNP_ADDRESS, SERIAL_ISOLATION); for (i = 0; i < 72; i++) { - bit = inb(isapnp_readport) == 0x55; + bit = inb((pnp_rd_port << 2) | 0x3) == 0x55; delay(250); /* Delay 250 usec */ /* Can't Short Circuit the next evaluation, so 'and' is last */ - bit = (inb(isapnp_readport) == 0xaa) && bit; + bit = (inb((pnp_rd_port << 2) | 0x3) == 0xaa) && bit; delay(250); /* Delay 250 usec */ valid = valid || bit; @@ -126,112 +126,87 @@ isapnp_get_serial(u_int8_t *data) } /* - * Fills the buffer with resource info from the device. - * Returns nonzero if the device fails to report + * Format a pnp id as a string in standard ISA PnP format, AAAIIRR + * where 'AAA' is the EISA ID, II is the product ID and RR the revision ID. */ -static int -isapnp_get_resource_info(u_int8_t *buffer, int len) +static char * +isapnp_format(u_int8_t *data) { - int i, j; - u_char temp; - - for (i = 0; i < len; i++) { - outb(_PNP_ADDRESS, STATUS); - for (j = 0; j < 100; j++) { - if ((inb(isapnp_readport)) & 0x1) - break; - delay(1); - } - if (j == 100) { - printf("PnP device failed to report resource data\n"); - return(1); - } - outb(_PNP_ADDRESS, RESOURCE_DATA); - temp = inb(isapnp_readport); - if (buffer != NULL) - buffer[i] = temp; - } - return(0); + static char idbuf[8]; + const char hextoascii[] = "0123456789abcdef"; + + idbuf[0] = '@' + ((data[0] & 0x7c) >> 2); + idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5)); + idbuf[2] = '@' + (data[1] & 0x1f); + idbuf[3] = hextoascii[(data[2] >> 4)]; + idbuf[4] = hextoascii[(data[2] & 0xf)]; + idbuf[5] = hextoascii[(data[3] >> 4)]; + idbuf[6] = hextoascii[(data[3] & 0xf)]; + idbuf[7] = 0; } /* - * Scan Resource Data for useful information. - * - * We scan the resource data for compatible device IDs and - * identifier strings; we only take the first identifier string - * and assume it's for the card as a whole. - * - * Returns 0 if the scan completed OK, nonzero on error. + * Try to read a compatible device ID from the current device, return + * 1 if we found one. */ +#define READ_RSC(c) {while ((isapnp_read(STATUS) & 1) == 0); (c) = isapnp_read(RESOURCE_DATA);} static int -isapnp_scan_resdata(struct pnpinfo *pi) +isapnp_getid(u_int8_t *data) { - u_char tag, resinfo[8]; - int large_len, limit; - char *str; - - limit = 1000; - while ((limit-- > 0) && !isapnp_get_resource_info(&tag, 1)) { - if (PNP_RES_TYPE(tag) == 0) { - /* Small resource */ - switch (PNP_SRES_NUM(tag)) { - - case COMP_DEVICE_ID: - /* Got a compatible device id resource */ - if (isapnp_get_resource_info(resinfo, PNP_SRES_LEN(tag))) - return(1); - pnp_addident(pi, pnp_eisaformat(resinfo)); - - case END_TAG: - return(0); - break; - - default: - /* Skip this resource */ - if (isapnp_get_resource_info(NULL, PNP_SRES_LEN(tag))) - return(1); - break; - } - } else { - /* Large resource */ - if (isapnp_get_resource_info(resinfo, 2)) + int discard, pos, len; + u_int8_t c, t; + + discard = 0; + len = 0; + pos = 0; + + for (;;) { + READ_RSC(c); + /* skipping junk? */ + if (discard > 0) { + discard--; + continue; + } + /* copying data? */ + if (len > 0) { + data[pos++] = c; + /* got all data? */ + if (pos >= len) return(1); - - large_len = resinfo[1]; - large_len = (large_len << 8) + resinfo[0]; - - switch(PNP_LRES_NUM(tag)) { - - case ID_STRING_ANSI: - str = malloc(large_len + 1); - if (isapnp_get_resource_info(str, large_len)) { - free(str); - return(1); - } - str[large_len] = 0; - if (pi->pi_desc == NULL) { - pi->pi_desc = str; - } else { - free(str); - } - break; - - default: - /* Large resource, skip it */ - if (isapnp_get_resource_info(NULL, large_len)) - return(1); - } } + /* resource type */ + if (c & 0x80) { /* large resource, throw it away */ + if (c == 0xff) + return(0); /* end of resources */ + READ_RSC(c); + discard = c; + READ_RSC(c); + discard += ((int)c << 8); + continue; + } + /* small resource */ + t = (c >> 3) & 0xf; + if (t == 0xf) + return(0); /* end of resources */ + if ((t == LOG_DEVICE_ID) || (t == COMP_DEVICE_ID)) { + len = c & 7; + pos = 0; + continue; + } + discard = c & 7; /* unwanted small resource */ } - return(1); + } + /* - * Run the isolation protocol. Upon exiting, all cards are aware that - * they should use isapnp_readport as the READ_DATA port. + * Run the isolation protocol. Use pnp_rd_port as the READ_DATA port + * value (caller should try multiple READ_DATA locations before giving + * up). Upon exiting, all cards are aware that they should use + * pnp_rd_port as the READ_DATA port. */ static int -isapnp_isolation_protocol(void) +isapnp_isolation_protocol(struct pnpinfo **pilist) { int csn; struct pnpinfo *pi; @@ -246,32 +221,30 @@ isapnp_isolation_protocol(void) for (csn = 1; ; csn++) { /* Wake up cards without a CSN (ie. all of them) */ isapnp_write(WAKE, 0); - isapnp_write(SET_RD_DATA, (isapnp_readport >> 2)); + isapnp_write(SET_RD_DATA, pnp_rd_port); outb(_PNP_ADDRESS, SERIAL_ISOLATION); delay(1000); /* Delay 1 msec */ if (isapnp_get_serial(cardid)) { isapnp_write(SET_CSN, csn); - pi = pnp_allocinfo(); + pi = malloc(sizeof(struct pnpinfo)); + pi->pi_next = *pilist; + *pilist = pi; ndevs++; - pnp_addident(pi, pnp_eisaformat(cardid)); /* scan the card obtaining all the identifiers it holds */ - if (isapnp_scan_resdata(pi)) { - pnp_freeinfo(pi); /* error getting data, ignore */ - } else { - pnp_addinfo(pi); + while (isapnp_getid(cardid)) { + printf(" %s\n", isapnp_format(cardid)); + pnp_addident(pi, isapnp_format(cardid)); } - } else { + } else break; - } } /* Move all cards to wait-for-key state */ - while (--csn > 0) { + while (csn >= 0) { isapnp_send_Initiation_LFSR(); isapnp_write(WAKE, csn); isapnp_write(CONFIG_CONTROL, 0x02); delay(1000); /* XXX is it really necessary ? */ - csn--; } return(ndevs); } @@ -280,40 +253,17 @@ isapnp_isolation_protocol(void) * Locate ISA-PnP devices and populate the supplied list. */ static void -isapnp_enumerate(void) +isapnp_enumerate(struct pnpinfo **pnplist) { - int pnp_rd_port; - - /* Check for I/O port access */ - if ((archsw.arch_isainb == NULL) || (archsw.arch_isaoutb == NULL)) - return; - - /* - * Validate a possibly-suggested read port value. If the autoscan failed - * last time, this will return us to autoscan mode again. - */ - if ((isapnp_readport > 0) && - (((isapnp_readport < 0x203) || - (isapnp_readport > 0x3ff) || - (isapnp_readport & 0x3) != 0x3))) - /* invalid, go look for ourselves */ - isapnp_readport = 0; - - if (isapnp_readport < 0) { - /* someone is telling us there is no ISA in the system */ - return; - - } else if (isapnp_readport > 0) { - /* Someone has told us where the port is/should be, or we found one last time */ - isapnp_isolation_protocol(); - - } else { - /* No clues, look for it ourselves */ - for (pnp_rd_port = 0x80; pnp_rd_port < 0xff; pnp_rd_port += 0x10) { - /* Look for something, quit when we find it */ - isapnp_readport = (pnp_rd_port << 2) | 0x3; - if (isapnp_isolation_protocol() > 0) - break; - } + int devs; + + for (pnp_rd_port = 0x80; pnp_rd_port < 0xff; pnp_rd_port += 0x10) { + + /* Look for something, quit when we find it */ + if ((devs = isapnp_isolation_protocol(pnplist)) > 0) + break; } + printf("Found %d ISA PnP devices\n", devs); } + + diff --git a/sys/boot/common/isapnp.h b/sys/boot/common/isapnp.h index 0b3b9ec88527..6c072824867e 100644 --- a/sys/boot/common/isapnp.h +++ b/sys/boot/common/isapnp.h @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: isapnp.h,v 1.1 1998/09/18 00:24:25 msmith Exp $ + * $Id: pnp.h,v 1.6 1998/01/10 07:41:43 kato Exp $ */ #ifndef _I386_ISA_PNP_H_ @@ -210,12 +210,6 @@ /*** 32-bit memory accesses are at 0x76 ***/ -/* Macros to parse Resource IDs */ -#define PNP_RES_TYPE(a) (a >> 7) -#define PNP_SRES_NUM(a) (a >> 3) -#define PNP_SRES_LEN(a) (a & 0x07) -#define PNP_LRES_NUM(a) (a & 0x7f) - /* Small Resource Item names */ #define PNP_VERSION 0x1 #define LOG_DEVICE_ID 0x2 diff --git a/sys/boot/common/load_aout.c b/sys/boot/common/load_aout.c index 6d33ad49f367..3a5d34d15a6b 100644 --- a/sys/boot/common/load_aout.c +++ b/sys/boot/common/load_aout.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: load_aout.c,v 1.10 1998/10/12 09:05:12 peter Exp $ + * $Id: load_aout.c,v 1.9 1998/10/09 23:15:39 peter Exp $ */ #include <sys/param.h> @@ -223,34 +223,30 @@ aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct ex /* symbol table size */ ssym = addr; - if(ehdr->a_syms!=NULL) { - archsw.arch_copyin(&ehdr->a_syms, addr, sizeof(ehdr->a_syms)); - addr += sizeof(ehdr->a_syms); + archsw.arch_copyin(&ehdr->a_syms, addr, sizeof(ehdr->a_syms)); + addr += sizeof(ehdr->a_syms); - /* symbol table */ - printf("symbols=[0x%x+0x%lx", sizeof(ehdr->a_syms), ehdr->a_syms); - if (archsw.arch_readin(fd, addr, ehdr->a_syms) != ehdr->a_syms) - return(0); - addr += ehdr->a_syms; - - /* string table */ - read(fd, &ss, sizeof(ss)); - archsw.arch_copyin(&ss, addr, sizeof(ss)); - addr += sizeof(ss); - ss -= sizeof(ss); - printf("+0x%x+0x%x]", sizeof(ss), ss); - if (archsw.arch_readin(fd, addr, ss) != ss) - return(0); - addr += ss; - - mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym); - mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym); - } else { - printf("symbols=[none]"); - } - printf("\n"); + /* symbol table */ + printf("symbols=[0x%x+0x%lx", sizeof(ehdr->a_syms), ehdr->a_syms); + if (archsw.arch_readin(fd, addr, ehdr->a_syms) != ehdr->a_syms) + return(0); + addr += ehdr->a_syms; + + /* string table */ + read(fd, &ss, sizeof(ss)); + archsw.arch_copyin(&ss, addr, sizeof(ss)); + addr += sizeof(ss); + ss -= sizeof(ss); + printf("+0x%x+0x%x]", sizeof(ss), ss); + if (archsw.arch_readin(fd, addr, ss) != ss) + return(0); + printf(" \n"); + addr += ss; esym = addr; + mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym); + mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym); + return(addr - loadaddr); } diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index ff1f50638ac8..b2b38c7800b6 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: load_elf.c,v 1.9 1998/10/17 03:06:38 peter Exp $ + * $Id: load_elf.c,v 1.7 1998/10/15 21:56:47 dfr Exp $ */ #include <sys/param.h> @@ -40,7 +40,7 @@ #include "bootstrap.h" -static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, int kernel, caddr_t firstpage, int firstlen); +static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, Elf_Phdr *phdr, int kernel); char *elf_kerneltype = "elf kernel"; char *elf_moduletype = "elf module"; @@ -54,15 +54,15 @@ int elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) { struct loaded_module *mp, *kmp; - Elf_Ehdr *ehdr; + Elf_Ehdr ehdr; + Elf_Phdr *phdr; int fd; int err, kernel; u_int pad; char *s; - caddr_t firstpage; - int firstlen; mp = NULL; + phdr = NULL; /* * Open the image, read and validate the ELF header @@ -71,26 +71,21 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) return(EFTYPE); if ((fd = open(filename, O_RDONLY)) == -1) return(errno); - firstpage = malloc(PAGE_SIZE); - if (firstpage == NULL) - return(ENOMEM); - firstlen = read(fd, firstpage, PAGE_SIZE); - if (firstlen <= sizeof(ehdr)) { + if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) { err = EFTYPE; /* could be EIO, but may be small file */ goto oerr; } - ehdr = (Elf_Ehdr *)firstpage; /* Is it ELF? */ - if (!IS_ELF(*ehdr)) { + if (!IS_ELF(ehdr)) { err = EFTYPE; goto oerr; } - if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ - ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || - ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */ - ehdr->e_version != EV_CURRENT || - ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */ + if (ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ + ehdr.e_ident[EI_DATA] != ELF_TARG_DATA || + ehdr.e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */ + ehdr.e_version != EV_CURRENT || + ehdr.e_machine != ELF_TARG_MACH) { /* Machine ? */ err = EFTYPE; goto oerr; } @@ -100,7 +95,7 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) * Check to see what sort of module we are. */ kmp = mod_findmodule(NULL, NULL); - if (ehdr->e_type == ET_DYN) { + if (ehdr.e_type == ET_DYN) { /* Looks like a kld module */ if (kmp == NULL) { printf("elf_loadmodule: can't load module before kernel\n"); @@ -121,7 +116,7 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) pad = PAGE_SIZE - pad; dest += pad; } - } else if (ehdr->e_type == ET_EXEC) { + } else if (ehdr.e_type == ET_EXEC) { /* Looks like a kernel */ if (kmp != NULL) { printf("elf_loadmodule: kernel already loaded\n"); @@ -131,7 +126,7 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) /* * Calculate destination address based on kernel entrypoint */ - dest = (vm_offset_t) ehdr->e_entry; + dest = (vm_offset_t) ehdr.e_entry; if (dest == 0) { printf("elf_loadmodule: not a kernel (maybe static binary?)\n"); err = EPERM; @@ -169,12 +164,36 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) printf("%s ", filename); #endif - mp->m_size = elf_loadimage(mp, fd, dest, ehdr, kernel, firstpage, firstlen); + phdr = malloc(ehdr.e_phnum * sizeof(*phdr)); + if (phdr == NULL) { + err = ENOMEM; + goto out; + } + + if (lseek(fd, ehdr.e_phoff, SEEK_SET) == -1) { + printf("elf_loadexec: lseek for phdr failed\n"); + goto ioerr; + } + if (read(fd, phdr, ehdr.e_phnum * sizeof(*phdr)) != + ehdr.e_phnum * sizeof(*phdr)) { + printf("elf_loadmodule: cannot read program header\n"); + goto ioerr; + } + if (lseek(fd, 0, SEEK_SET) == -1) { + close(fd); + if ((fd = open(filename, O_RDONLY)) == -1) { + printf("elf_loadmodule: cannot reset file position\n"); + mod_discard(mp); + return errno; + } + } + + mp->m_size = elf_loadimage(mp, fd, dest, &ehdr, phdr, kernel); if (mp->m_size == 0 || mp->m_addr == 0) goto ioerr; /* save exec header as metadata */ - mod_addmetadata(mp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr); + mod_addmetadata(mp, MODINFOMD_ELFHDR, sizeof(ehdr), &ehdr); /* Load OK, return module pointer */ *result = (struct loaded_module *)mp; @@ -186,8 +205,8 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) oerr: mod_discard(mp); out: - if (firstpage) - free(firstpage); + if (phdr) + free(phdr); close(fd); return(err); } @@ -198,10 +217,9 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) */ static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, - Elf_Ehdr *ehdr, int kernel, caddr_t firstpage, int firstlen) + Elf_Ehdr *ehdr, Elf_Phdr *phdr, int kernel) { int i, j; - Elf_Phdr *phdr; Elf_Shdr *shdr; int ret; vm_offset_t firstaddr; @@ -221,7 +239,6 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, int symstrindex; int symtabindex; long size; - int fpcopy; dp = NULL; shdr = NULL; @@ -235,12 +252,6 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, #endif } - if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > firstlen) { - printf("elf_loadimage: program header not within first page\n"); - goto out; - } - phdr = (Elf_Phdr *)(firstpage + ehdr->e_phoff); - for (i = 0; i < ehdr->e_phnum; i++) { /* We want to load PT_LOAD segments only.. */ if (phdr[i].p_type != PT_LOAD) @@ -261,22 +272,15 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, printf(" "); } #endif - fpcopy = 0; - if (firstlen > phdr[i].p_offset) { - fpcopy = firstlen - phdr[i].p_offset; - archsw.arch_copyin(firstpage + phdr[i].p_offset, - phdr[i].p_vaddr + off, fpcopy); + + if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) { + printf("\nelf_loadexec: cannot seek\n"); + goto out; } - if (phdr[i].p_filesz > fpcopy) { - if (lseek(fd, phdr[i].p_offset + fpcopy, SEEK_SET) == -1) { - printf("\nelf_loadexec: cannot seek\n"); - goto out; - } - if (archsw.arch_readin(fd, phdr[i].p_vaddr + off + fpcopy, - phdr[i].p_filesz - fpcopy) != phdr[i].p_filesz - fpcopy) { - printf("\nelf_loadexec: archsw.readin failed\n"); - goto out; - } + if (archsw.arch_readin(fd, phdr[i].p_vaddr + off, phdr[i].p_filesz) != + phdr[i].p_filesz) { + printf("\nelf_loadexec: archsw.readin failed\n"); + goto out; } /* clear space from oversized segments; eg: bss */ if (phdr[i].p_filesz < phdr[i].p_memsz) { @@ -323,11 +327,11 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, if (shdr == NULL) goto nosyms; if (lseek(fd, ehdr->e_shoff, SEEK_SET) == -1) { - printf("\nelf_loadimage: cannot lseek() to section headers"); + printf("\nelf_loadimage: cannot lseek() to section headers\n"); goto nosyms; } if (read(fd, shdr, chunk) != chunk) { - printf("\nelf_loadimage: read section headers failed"); + printf("\nelf_loadimage: read section headers failed\n"); goto nosyms; } symtabindex = -1; @@ -382,7 +386,7 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, lastaddr += sizeof(long); #ifdef ELF_VERBOSE - printf("\n%s: 0x%lx@0x%lx -> 0x%lx-0x%lx", secname, + printf("%s: 0x%lx@0x%lx -> 0x%lx-0x%lx\n", secname, shdr[i].sh_size, shdr[i].sh_offset, lastaddr, lastaddr + shdr[i].sh_size); #else @@ -392,14 +396,14 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, #endif if (lseek(fd, shdr[i].sh_offset, SEEK_SET) == -1) { - printf("\nelf_loadimage: could not seek for symbols - skipped!"); + printf("\nelf_loadimage: could not seek for symbols - skipped!\n"); lastaddr = ssym; ssym = 0; goto nosyms; } if (archsw.arch_readin(fd, lastaddr, shdr[i].sh_size) != shdr[i].sh_size) { - printf("\nelf_loadimage: could not read symbols - skipped!"); + printf("\nelf_loadimage: could not read symbols - skipped!\n"); lastaddr = ssym; ssym = 0; goto nosyms; @@ -414,14 +418,13 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, } esym = lastaddr; #ifndef ELF_VERBOSE - printf("]"); + printf("]\n"); #endif mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym); mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym); nosyms: - printf("\n"); ret = lastaddr - firstaddr; mp->m_addr = firstaddr; diff --git a/sys/boot/common/ls.c b/sys/boot/common/ls.c index 73f805700bf8..493482a7b300 100644 --- a/sys/boot/common/ls.c +++ b/sys/boot/common/ls.c @@ -1,5 +1,5 @@ /* - * $Id: ls.c,v 1.6 1998/10/11 10:28:51 peter Exp $ + * $Id: ls.c,v 1.5 1998/10/09 07:09:22 msmith Exp $ * From: $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $ */ @@ -70,7 +70,6 @@ command_ls(int argc, char *argv[]) fd = -1; verbose = 0; optind = 1; - optreset = 1; while ((ch = getopt(argc, argv, "l")) != -1) { switch(ch) { case 'l': diff --git a/sys/boot/common/merge_help.awk b/sys/boot/common/merge_help.awk deleted file mode 100644 index 1376c53aee3c..000000000000 --- a/sys/boot/common/merge_help.awk +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/awk -f -# -# $Id: mergehelp.awk,v 1.3 1999/01/13 20:06:52 jabley Exp $ -# -# Merge two boot loader help files for FreeBSD 3.0 -# Joe Abley <jabley@patho.gen.nz> - -BEGIN \ -{ - state = 0; - first = 0; - ind = 0; -} - -# beginning of first command -/^###/ && (state == 0) \ -{ - state = 1; - next; -} - -# entry header -/^# T[[:graph:]]+ (S[[:graph:]]+ )*D[[:graph:]][[:print:]]*$/ && (state == 1) \ -{ - match($0, " T[[:graph:]]+"); - T = substr($0, RSTART + 2, RLENGTH - 2); - match($0, " S[[:graph:]]+"); - S = (RLENGTH == -1) ? "" : substr($0, RSTART + 2, RLENGTH - 2); - match($0, " D[[:graph:]][[:print:]]*$"); - D = substr($0, RSTART + 2); - - # find a suitable place to store this one... - ind++; - if (ind == 1) - { - first = ind; - help[ind, "T"] = T; - help[ind, "S"] = S; - help[ind, "link"] = -1; - } else { - i = first; j = -1; - while (help[i, "T"] help[i, "S"] < T S) - { - j = i; - i = help[i, "link"]; - if (i == -1) break; - } - - if (i == -1) - { - help[j, "link"] = ind; - help[ind, "link"] = -1; - } else { - help[ind, "link"] = i; - if (j == -1) - first = ind; - else - help[j, "link"] = ind; - } - } - help[ind, "T"] = T; - help[ind, "S"] = S; - help[ind, "D"] = D; - - # set our state - state = 2; - help[ind, "text"] = 0; - next; -} - -# end of last command, beginning of next one -/^###/ && (state == 2) \ -{ - state = 1; -} - -(state == 2) \ -{ - sub("[[:blank:]]+$", ""); - if (help[ind, "text"] == 0 && $0 ~ /^[[:blank:]]*$/) next; - help[ind, "text", help[ind, "text"]] = $0; - help[ind, "text"]++; - next; -} - -# show them what we have (it's already sorted in help[]) -END \ -{ - node = first; - while (node != -1) - { - printf "################################################################################\n"; - printf "# T%s ", help[node, "T"]; - if (help[node, "S"] != "") printf "S%s ", help[node, "S"]; - printf "D%s\n\n", help[node, "D"]; - for (i = 0; i < help[node, "text"]; i++) - printf "%s\n", help[node, "text", i]; - node = help[node, "link"]; - } - printf "################################################################################\n"; -} diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index 141a8ed32f66..5b0d547af069 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: module.c,v 1.6 1998/10/09 23:12:34 peter Exp $ + * $Id: module.c,v 1.5 1998/09/26 10:51:38 dfr Exp $ */ /* @@ -72,7 +72,6 @@ command_load(int argc, char *argv[]) dofile = 0; optind = 1; - optreset = 1; typestr = NULL; while ((ch = getopt(argc, argv, "t:")) != -1) { switch(ch) { @@ -134,7 +133,6 @@ command_lsmod(int argc, char *argv[]) verbose = 0; optind = 1; - optreset = 1; while ((ch = getopt(argc, argv, "v")) != -1) { switch(ch) { case 'v': diff --git a/sys/boot/common/pnp.c b/sys/boot/common/pnp.c index 74853154ffe7..4a8ee48d5bd4 100644 --- a/sys/boot/common/pnp.c +++ b/sys/boot/common/pnp.c @@ -13,10 +13,9 @@ #include <string.h> #include <bootstrap.h> -STAILQ_HEAD(,pnpinfo) pnp_devices; -static int pnp_devices_initted = 0; +static struct pnpinfo *pnp_devices = NULL; -static void pnp_discard(void); +static void pnp_discard(struct pnpinfo **list); static int pnp_readconf(char *path); static int pnp_scankernel(void); @@ -29,56 +28,15 @@ COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan); int pnp_scan(int argc, char *argv[]) { - struct pnpinfo *pi; int hdlr; - int verbose; - int ch; - - if (pnp_devices_initted == 0) { - STAILQ_INIT(&pnp_devices); - pnp_devices_initted = 1; - } - - verbose = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "v")) != -1) { - switch(ch) { - case 'v': - verbose = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); - } - } /* forget anything we think we knew */ - pnp_discard(); - - if (verbose) - pager_open(); + pnp_discard(&pnp_devices); /* iterate over all of the handlers */ for (hdlr = 0; pnphandlers[hdlr] != NULL; hdlr++) { - if (verbose) { - pager_output("Probing "); - pager_output(pnphandlers[hdlr]->pp_name); - pager_output("...\n"); - } - pnphandlers[hdlr]->pp_enumerate(); - } - if (verbose) { - for (pi = pnp_devices.stqh_first; pi != NULL; pi = pi->pi_link.stqe_next) { - pager_output(pi->pi_ident.stqh_first->id_ident); /* first ident should be canonical */ - if (pi->pi_desc != NULL) { - pager_output(" : "); - pager_output(pi->pi_desc); - } - pager_output("\n"); - } - pager_close(); + printf("Probing bus '%s'...\n", pnphandlers[hdlr]->pp_name); + pnphandlers[hdlr]->pp_enumerate(&pnp_devices); } return(CMD_OK); } @@ -93,7 +51,7 @@ pnp_reload(char *fname) char *modfname; /* find anything? */ - if (pnp_devices.stqh_first != NULL) { + if (pnp_devices != NULL) { /* check for kernel, assign modules handled by static drivers there */ if (pnp_scankernel()) { @@ -112,13 +70,13 @@ pnp_reload(char *fname) } /* try to load any modules that have been nominated */ - for (pi = pnp_devices.stqh_first; pi != NULL; pi = pi->pi_link.stqe_next) { + for (pi = pnp_devices; pi != NULL; pi = pi->pi_next) { /* Already loaded? */ if ((pi->pi_module != NULL) && (mod_findmodule(pi->pi_module, NULL) == NULL)) { - modfname = malloc(strlen(pi->pi_module) + 4); + modfname = malloc(strlen(pi->pi_module + 3)); sprintf(modfname, "%s.ko", pi->pi_module); /* XXX implicit knowledge of KLD module filenames */ if (mod_load(pi->pi_module, pi->pi_argc, pi->pi_argv)) - printf("Could not load module '%s' for device '%s'\n", modfname, pi->pi_ident.stqh_first->id_ident); + printf("Could not load module '%s' for device '%s'\n", modfname, pi->pi_ident->id_ident); free(modfname); } } @@ -130,14 +88,24 @@ pnp_reload(char *fname) * Throw away anything we think we know about PnP devices on (list) */ static void -pnp_discard(void) +pnp_discard(struct pnpinfo **list) { struct pnpinfo *pi; - - while (pnp_devices.stqh_first != NULL) { - pi = pnp_devices.stqh_first; - STAILQ_REMOVE_HEAD(&pnp_devices, pi_link); - pnp_freeinfo(pi); + struct pnpident *id; + + while (*list != NULL) { + pi = *list; + *list = (*list)->pi_next; + while (pi->pi_ident) { + id = pi->pi_ident; + pi->pi_ident = pi->pi_ident->id_next; + free(id); + } + if (pi->pi_module) + free(pi->pi_module); + if (pi->pi_argv) + free(pi->pi_argv); + free(pi); } } @@ -258,14 +226,14 @@ pnp_readconf(char *path) * assigned. * XXX no revision parse/test here yet. */ - for (pi = pnp_devices.stqh_first; pi != NULL; pi = pi->pi_link.stqe_next) { + for (pi = pnp_devices; pi != NULL; pi = pi->pi_next) { /* no driver assigned, bus matches OK */ if ((pi->pi_module == NULL) && !strcmp(pi->pi_handler->pp_name, currbus)) { /* scan idents, take first match */ - for (id = pi->pi_ident.stqh_first; id != NULL; id = id->id_link.stqe_next) + for (id = pi->pi_ident; id != NULL; id = id->id_next) if (!strcmp(id->id_ident, ident)) break; @@ -299,82 +267,19 @@ pnp_scankernel(void) void pnp_addident(struct pnpinfo *pi, char *ident) { - struct pnpident *id; - - for (id = pi->pi_ident.stqh_first; id != NULL; id = id->id_link.stqe_next) - if (!strcmp(id->id_ident, ident)) - return; /* already have this one */ - - id = malloc(sizeof(struct pnpident)); - id->id_ident = strdup(ident); - STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link); -} - -/* - * Allocate a new pnpinfo struct - */ -struct pnpinfo * -pnp_allocinfo(void) -{ - struct pnpinfo *pi; + struct pnpident *id, **idp; - pi = malloc(sizeof(struct pnpinfo)); - bzero(pi, sizeof(struct pnpinfo)); - STAILQ_INIT(&pi->pi_ident); - return(pi); -} - -/* - * Release storage held by a pnpinfo struct - */ -void -pnp_freeinfo(struct pnpinfo *pi) -{ - struct pnpident *id; - - while (pi->pi_ident.stqh_first != NULL) { - id = pi->pi_ident.stqh_first; - STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link); - free(id->id_ident); - free(id); + if (pi->pi_ident == NULL) { + idp = &(pi->pi_ident); + } else { + for (id = pi->pi_ident; id->id_next != NULL; id = id->id_next) + if (!strcmp(id->id_ident, ident)) + return; /* already have this one */ + ; + idp = &(id->id_next); } - if (pi->pi_desc) - free(pi->pi_desc); - if (pi->pi_module) - free(pi->pi_module); - if (pi->pi_argv) - free(pi->pi_argv); - free(pi); -} - -/* - * Add a new pnpinfo struct to the list. - */ -void -pnp_addinfo(struct pnpinfo *pi) -{ - STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link); -} - - -/* - * Format an EISA id as a string in standard ISA PnP format, AAAIIRR - * where 'AAA' is the EISA vendor ID, II is the product ID and RR the revision ID. - */ -char * -pnp_eisaformat(u_int8_t *data) -{ - static char idbuf[8]; - const char hextoascii[] = "0123456789abcdef"; - - idbuf[0] = '@' + ((data[0] & 0x7c) >> 2); - idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5)); - idbuf[2] = '@' + (data[1] & 0x1f); - idbuf[3] = hextoascii[(data[2] >> 4)]; - idbuf[4] = hextoascii[(data[2] & 0xf)]; - idbuf[5] = hextoascii[(data[3] >> 4)]; - idbuf[6] = hextoascii[(data[3] & 0xf)]; - idbuf[7] = 0; - return(idbuf); + *idp = malloc(sizeof(struct pnpident)); + (*idp)->id_next = NULL; + (*idp)->id_ident = strdup(ident); } diff --git a/sys/boot/common/pnpdata b/sys/boot/common/pnpdata deleted file mode 100644 index 62d35a819386..000000000000 --- a/sys/boot/common/pnpdata +++ /dev/null @@ -1,183 +0,0 @@ -# -# $Id$ -# -# This file contains the system default Plug-and-Play data. It is -# derived from a number of sources, including: -# -# - The Microsoft "Windows Generic Device IDs" document -# - -[pci] -###################################################################### -# PCI devices. -# -# Required attributes: -# -# ident= PCI identifier in the form 0xDDDDVVVV where -# 'VVVV' is the 4-digit hex form of the vendor ID and -# 'DDDD' is the 4-digit hex form of the device ID. -# or -# -# vendor= 0xVVVV where 'VVVV' is above -# name= Vendor name - -vendor=0x8086 name=Intel - - -[isa] -###################################################################### -# ISA PnP devices -# -# Required attributes: -# -# ident= ISA PnP identifier in the form AAAIIRR where -# 'AAA' is the EISA vendor ID, 'II' is the device ID -# and 'RR' is the revision ID. -# or -# -# vendor= AAA to register just a vendor name. -# name= Vendor name -# -# Optional attributes: -# -# module= Support module identifier. -# -# args= Arguments to pass to the support module. -# - -vendor=CSC name=Crystal Semiconductor -vendor=CTL name=Creative Labs -vendor=PNP name=Generic - -# From "Windows Generic Device IDs" -# -# --Parallel Devices-- -ident=PNP0400 module=lpt # Standard LPT printer port -ident=PNP0401 module=lpt # ECP printer port - -# --Serial Devices-- -ident=PNP0500 module=sio # Standard PC COM port -ident=PNP0501 module=sio # 16550A-compatible COM port -ident=PNP0502 module=sio # Multiport serial device (non-intelligent 16550) - -# --Disk Controllers-- -ident=PNP0600 module=wd # Generic ESDI/IDE/ATA compatible hard disk controller -ident=PNP0603 module=wd # Generic IDE supporting Microsoft Device Bay Specification -ident=PNP0700 module=fd # PC standard floppy disk controller -ident=PNP0701 module=fd # Standard floppy controller supporting MS Device Bay Spec - -# --Peripheral Buses-- -ident=PNP0A00 module=isa # ISA Bus -ident=PNP0A01 module=eisa # EISA Bus -ident=PNP0A03 module=pci # PCI Bus -ident=PNP0A04 module=isa # VESA/VL Bus - -# -- Real Time Clock, BIOS, System board devices-- -ident=PNP0C04 module=npx # Math Coprocessor -ident=PNP0C05 module=apm # APM BIOS (Version independent) - -# --PCMCIA Controller Chipsets-- -ident=PNP0E00 module=pcic # Intel 82365-Compatible PCMCIA Controller -ident=PNP0E01 module=pcic # Cirrus Logic CL-PD6720 PCMCIA Controller -ident=PNP0E02 module=pcic # VLSI VL82C146 PCMCIA Controller -ident=PNP0E03 module=pcic # Intel 82365-compatible CardBus controller - -# --Network Adapters-- -ident=PNP8001 module=ed # Novell/Anthem NE3200 -ident=PNP8004 # Compaq NE3200 -ident=PNP80d3 module=ed # Novell/Anthem NE1000 -ident=PNP80d4 module=ed # Novell/Anthem NE2000 -ident=PNP80d5 module=ed # NE1000 Compatible -ident=PNP80d6 module=ed # NE2000 Compatible -ident=PNP80d8 module=lnc # Novell/Anthem NE2100 -ident=PNP80e9 module=le # DEC (DE200) EtherWorks Turbo -ident=PNP80eb module=le # DEC (DE201) EtherWorks Turbo/TP -ident=PNP80ec module=le # DEC (DE202) EtherWorks Turbo/TP_BNC -ident=PNP80f1 module=eg # 3Com EtherLink Plus -ident=PNP80f3 module=ed # 3Com EtherLink II or IITP (8 or 16-bit) -ident=PNP80f6 module=ed # 3Com EtherLink 16 -ident=PNP80f7 module=ep # 3Com EtherLink III -ident=PNP80f8 module=ep # 3Com Generic Etherlink Plug and Play Device -ident=PNP8123 module=ed # SMC StarCard PLUS (WD/8003S) -ident=PNP8124 module=ed # SMC StarCard PLUS With On Board Hub (WD/8003SH) -ident=PNP8125 module=ed # SMC EtherCard PLUS (WD/8003E) -ident=PNP8126 module=ed # SMC EtherCard PLUS With Boot ROM Socket (WD/8003EBT) -ident=PNP8127 module=ed # SMC EtherCard PLUS With Boot ROM Socket (WD/8003EB) -ident=PNP8128 module=ed # SMC EtherCard PLUS TP (WD/8003WT) -ident=PNP812a module=ed # SMC EtherCard PLUS 16 With Boot ROM Socket (WD/8013EBT) -ident=PNP812d module=ie # Intel EtherExpress 16 or 16TP -ident=PNP8137 module=ed # Artisoft AE-1 -ident=PNP8138 module=ed # Artisoft AE-2 or AE-3 -ident=PNP8158 module=ed # HP PC LAN Adapter/16 TP Plus (HP27247B) -ident=PNP8159 module=ed # HP PC LAN Adapter/16 TL Plus (HP27252) -ident=PNP81c3 module=ed # SMC EtherCard PLUS Elite (WD/8003EP) -ident=PNP81c4 module=ed # SMC EtherCard PLUS 10T (WD/8003W) -ident=PNP81c5 module=ed # SMC EtherCard PLUS Elite 16 (WD/8013EP) -ident=PNP81c6 module=ed # SMC EtherCard PLUS Elite 16T (WD/8013W) -ident=PNP81c7 module=ed # SMC EtherCard PLUS Elite 16 Combo (WD/8013EW or 8013EWC) -ident=PNP81c8 module=ed # SMC EtherElite Ultra 16 -ident=PNP820a module=ed # Zenith Data Systems NE2000-Compatible -ident=PNP8231 module=lnc # Advanced Micro Devices AM2100/AM1500T -ident=PNP828C module=lnc # AMD PCNet Family cards -ident=PNP828D module=lnc # AMD PCNet32 (VL version) -ident=PNP8323 module=ed # SMC EtherCard (All Types except 8013/A) -ident=PNP8390 module=ed # Generic network adapter - -# --SCSI, Proprietary CD Adapters-- -ident=PNPA003 module=matcd # Panasonic proprietary CD-ROM adapter (SBPro/SB16) -ident=PNPA02B module=scd # Sony proprietary CD-ROM controller -ident=PNPA030 module=mcd # Mitsumi LU-005 Single Speed CD-ROM controller + drive -ident=PNPA031 module=mcd # Mitsumi FX-001 Single Speed CD-ROM controller + drive -ident=PNPA032 module=mcd # Mitsumi FX-001 Double Speed CD-ROM controller + drive - -# --Sound/Video-capture, multimedia-- -ident=PNPB000 module=pcm # Sound Blaster 1.5 sound device -ident=PNPB001 module=pcm # Sound Blaster 2.0 sound device -ident=PNPB002 module=pcm # Sound Blaster Pro sound device -ident=PNPB003 module=pcm # Sound Blaster 16 sound device -ident=PNPB007 module=pcm # Microsoft Windows Sound System-compatible sound device -ident=PNPB009 module=pcm # Plug and Play Microsoft Windows Sound System Device -ident=PNPB020 module=pcm # Yamaha OPL3-compatible FM synthesizer device -ident=PNPB02F module=joy # Joystick/Game port - -# --Compatibility with early device ID list-- -ident=PNP0802 module=pcm # Microsoft Sound System compatible device (obsolete, use PNPB0xx instead) - -# --Modems-- -ident=PNPC000 module=sio # Compaq 14400 Modem (TBD) -ident=PNPC001 module=sio # Compaq 2400/9600 Modem (TBD) - -# Vendor supplied IDs. - -# --Parallel Devices-- - -# --Serial Devices-- - -# --Disk Controllers-- - -# --Peripheral Buses-- - -# --Real Time Clock, BIOS, System board devices-- - -# --PCMCIA Controller Chipsets-- - -# --Network Adapters-- -ident=CSC6040 module=cs # Crystal Semiconductor CS8920 - -# --SCSI, Proprietary CD Adapters-- - -# --Sound/Video-capture, multimedia-- - -# --Modems-- - - - -[com] -###################################################################### -# COM PnP devices -# - -[lpt] -###################################################################### -# LPT PnP devices -# diff --git a/sys/boot/ficl/Makefile b/sys/boot/ficl/Makefile deleted file mode 100644 index 260254e316a1..000000000000 --- a/sys/boot/ficl/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# $Id: Makefile,v 1.6 1998/11/05 08:39:42 jkh Exp $ -# -LIB= ficl -NOPROFILE= yes -INTERNALLIB= yes -INTERNALSTATICLIB= yes -BASE_SRCS= dict.c ficl.c math64.c stack.c sysdep.c vm.c words.c -SRCS= ${BASE_SRCS} softcore.c -CLEANFILES= softcore.c testmain - -# Standard softwords -SOFTWORDS= softcore.fr jhlocal.fr marker.fr -# Optional OO extension softwords -#SOFTWORDS+= oo.fr classes.fr - -.PATH: ${.CURDIR}/softwords -CFLAGS+= -I${.CURDIR} - -softcore.c: ${SOFTWORDS} softcore.awk - (cd ${.CURDIR}/softwords; cat ${SOFTWORDS} | awk -f softcore.awk) > ${.TARGET} - -.include <bsd.lib.mk> - -testmain: ${.CURDIR}/testmain.c ${SRCS} - @for i in ${BASE_SRCS}; do echo $${i}... ; \ - ${CC} -c ${CFLAGS} -DTESTMAIN ${.CURDIR}/$${i}; done - @echo softdep.c... - @${CC} -c ${CFLAGS} -D_TESTMAIN softcore.c - cc -o ${.TARGET} ${.CURDIR}/testmain.c ${OBJS} - diff --git a/sys/boot/ficl/dict.c b/sys/boot/ficl/dict.c deleted file mode 100644 index 640a2fddc1ad..000000000000 --- a/sys/boot/ficl/dict.c +++ /dev/null @@ -1,779 +0,0 @@ -/******************************************************************* -** d i c t . c -** Forth Inspired Command Language - dictionary methods -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 19 July 1997 -** -*******************************************************************/ -/* -** This file implements the dictionary -- FICL's model of -** memory management. All FICL words are stored in the -** dictionary. A word is a named chunk of data with its -** associated code. FICL treats all words the same, even -** precompiled ones, so your words become first-class -** extensions of the language. You can even define new -** control structures. -** -** 29 jun 1998 (sadler) added variable sized hash table support -*/ - -#ifdef TESTMAIN -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#else -#include <stand.h> -#endif -#include <string.h> -#include "ficl.h" - -static char *dictCopyName(FICL_DICT *pDict, STRINGINFO si); - -/************************************************************************** - d i c t A b o r t D e f i n i t i o n -** Abort a definition in process: reclaim its memory and unlink it -** from the dictionary list. Assumes that there is a smudged -** definition in process...otherwise does nothing. -** NOTE: this function is not smart enough to unlink a word that -** has been successfully defined (ie linked into a hash). It -** only works for defs in process. If the def has been unsmudged, -** nothing happens. -**************************************************************************/ -void dictAbortDefinition(FICL_DICT *pDict) -{ - FICL_WORD *pFW; - ficlLockDictionary(TRUE); - pFW = pDict->smudge; - - if (pFW->flags & FW_SMUDGE) - pDict->here = (CELL *)pFW->name; - - ficlLockDictionary(FALSE); - return; -} - - -/************************************************************************** - a l i g n P t r -** Aligns the given pointer to FICL_ALIGN address units. -** Returns the aligned pointer value. -**************************************************************************/ -void *alignPtr(void *ptr) -{ -#if FICL_ALIGN > 0 - char *cp; - CELL c; - cp = (char *)ptr + FICL_ALIGN_ADD; - c.p = (void *)cp; - c.u = c.u & (~FICL_ALIGN_ADD); - ptr = (CELL *)c.p; -#endif - return ptr; -} - - -/************************************************************************** - d i c t A l i g n -** Align the dictionary's free space pointer -**************************************************************************/ -void dictAlign(FICL_DICT *pDict) -{ - pDict->here = alignPtr(pDict->here); -} - - -/************************************************************************** - d i c t A l l o t -** Allocate or remove n chars of dictionary space, with -** checks for underrun and overrun -**************************************************************************/ -int dictAllot(FICL_DICT *pDict, int n) -{ - char *cp = (char *)pDict->here; -#if FICL_ROBUST - if (n > 0) - { - if ((unsigned)n <= dictCellsAvail(pDict) * sizeof (CELL)) - cp += n; - else - return 1; /* dict is full */ - } - else - { - n = -n; - if ((unsigned)n <= dictCellsUsed(pDict) * sizeof (CELL)) - cp -= n; - else /* prevent underflow */ - cp -= dictCellsUsed(pDict) * sizeof (CELL); - } -#else - cp += n; -#endif - pDict->here = PTRtoCELL cp; - return 0; -} - - -/************************************************************************** - d i c t A l l o t C e l l s -** Reserve space for the requested number of cells in the -** dictionary. If nCells < 0 , removes space from the dictionary. -**************************************************************************/ -int dictAllotCells(FICL_DICT *pDict, int nCells) -{ -#if FICL_ROBUST - if (nCells > 0) - { - if (nCells <= dictCellsAvail(pDict)) - pDict->here += nCells; - else - return 1; /* dict is full */ - } - else - { - nCells = -nCells; - if (nCells <= dictCellsUsed(pDict)) - pDict->here -= nCells; - else /* prevent underflow */ - pDict->here -= dictCellsUsed(pDict); - } -#else - pDict->here += nCells; -#endif - return 0; -} - - -/************************************************************************** - d i c t A p p e n d C e l l -** Append the specified cell to the dictionary -**************************************************************************/ -void dictAppendCell(FICL_DICT *pDict, CELL c) -{ - *pDict->here++ = c; - return; -} - - -/************************************************************************** - d i c t A p p e n d C h a r -** Append the specified char to the dictionary -**************************************************************************/ -void dictAppendChar(FICL_DICT *pDict, char c) -{ - char *cp = (char *)pDict->here; - *cp++ = c; - pDict->here = PTRtoCELL cp; - return; -} - - -/************************************************************************** - d i c t A p p e n d W o r d -** Create a new word in the dictionary with the specified -** name, code, and flags. Name must be NULL-terminated. -**************************************************************************/ -FICL_WORD *dictAppendWord(FICL_DICT *pDict, - char *name, - FICL_CODE pCode, - UNS8 flags) -{ - STRINGINFO si; - SI_SETLEN(si, strlen(name)); - SI_SETPTR(si, name); - return dictAppendWord2(pDict, si, pCode, flags); -} - - -/************************************************************************** - d i c t A p p e n d W o r d 2 -** Create a new word in the dictionary with the specified -** STRINGINFO, code, and flags. Does not require a NULL-terminated -** name. -**************************************************************************/ -FICL_WORD *dictAppendWord2(FICL_DICT *pDict, - STRINGINFO si, - FICL_CODE pCode, - UNS8 flags) -{ - FICL_COUNT len = (FICL_COUNT)SI_COUNT(si); - char *name = SI_PTR(si); - char *pName; - FICL_WORD *pFW; - - ficlLockDictionary(TRUE); - - /* - ** NOTE: dictCopyName advances "here" as a side-effect. - ** It must execute before pFW is initialized. - */ - pName = dictCopyName(pDict, si); - pFW = (FICL_WORD *)pDict->here; - pDict->smudge = pFW; - pFW->hash = hashHashCode(si); - pFW->code = pCode; - pFW->flags = (UNS8)(flags | FW_SMUDGE); - pFW->nName = (char)len; - pFW->name = pName; - /* - ** Point "here" to first cell of new word's param area... - */ - pDict->here = pFW->param; - - if (!(flags & FW_SMUDGE)) - dictUnsmudge(pDict); - - ficlLockDictionary(FALSE); - return pFW; -} - - -/************************************************************************** - d i c t A p p e n d U N S 3 2 -** Append the specified UNS32 to the dictionary -**************************************************************************/ -void dictAppendUNS32(FICL_DICT *pDict, UNS32 u) -{ - *pDict->here++ = LVALUEtoCELL(u); - return; -} - - -/************************************************************************** - d i c t C e l l s A v a i l -** Returns the number of empty cells left in the dictionary -**************************************************************************/ -int dictCellsAvail(FICL_DICT *pDict) -{ - return pDict->size - dictCellsUsed(pDict); -} - - -/************************************************************************** - d i c t C e l l s U s e d -** Returns the number of cells consumed in the dicionary -**************************************************************************/ -int dictCellsUsed(FICL_DICT *pDict) -{ - return pDict->here - pDict->dict; -} - - -/************************************************************************** - d i c t C h e c k -** Checks the dictionary for corruption and throws appropriate -** errors -**************************************************************************/ -void dictCheck(FICL_DICT *pDict, FICL_VM *pVM, int nCells) -{ - if ((nCells >= 0) && (dictCellsAvail(pDict) < nCells)) - { - vmThrowErr(pVM, "Error: dictionary full"); - } - - if ((nCells <= 0) && (dictCellsUsed(pDict) < -nCells)) - { - vmThrowErr(pVM, "Error: dictionary underflow"); - } - - if (pDict->nLists > FICL_DEFAULT_VOCS) - { - dictResetSearchOrder(pDict); - vmThrowErr(pVM, "Error: search order overflow"); - } - else if (pDict->nLists < 0) - { - dictResetSearchOrder(pDict); - vmThrowErr(pVM, "Error: search order underflow"); - } - - return; -} - - -/************************************************************************** - d i c t C o p y N a m e -** Copy up to nFICLNAME characters of the name specified by si into -** the dictionary starting at "here", then NULL-terminate the name, -** point "here" to the next available byte, and return the address of -** the beginning of the name. Used by dictAppendWord. -** N O T E S : -** 1. "here" is guaranteed to be aligned after this operation. -** 2. If the string has zero length, align and return "here" -**************************************************************************/ -static char *dictCopyName(FICL_DICT *pDict, STRINGINFO si) -{ - char *oldCP = (char *)pDict->here; - char *cp = oldCP; - char *name = SI_PTR(si); - int i = SI_COUNT(si); - - if (i == 0) - { - dictAlign(pDict); - return (char *)pDict->here; - } - - if (i > nFICLNAME) - i = nFICLNAME; - - for (; i > 0; --i) - { - *cp++ = *name++; - } - - *cp++ = '\0'; - - pDict->here = PTRtoCELL cp; - dictAlign(pDict); - return oldCP; -} - - -/************************************************************************** - d i c t C r e a t e -** Create and initialize a dictionary with the specified number -** of cells capacity, and no hashing (hash size == 1). -**************************************************************************/ -FICL_DICT *dictCreate(unsigned nCells) -{ - return dictCreateHashed(nCells, 1); -} - - -FICL_DICT *dictCreateHashed(unsigned nCells, unsigned nHash) -{ - FICL_DICT *pDict; - size_t nAlloc; - - nAlloc = sizeof (FICL_DICT) + nCells * sizeof (CELL) - + sizeof (FICL_HASH) + (nHash - 1) * sizeof (FICL_WORD *); - - pDict = ficlMalloc(nAlloc); - assert(pDict); - pDict->size = nCells; - dictEmpty(pDict, nHash); - return pDict; -} - - -/************************************************************************** - d i c t D e l e t e -** Free all memory allocated for the given dictionary -**************************************************************************/ -void dictDelete(FICL_DICT *pDict) -{ - assert(pDict); - ficlFree(pDict); - return; -} - - -/************************************************************************** - d i c t E m p t y -** Empty the dictionary, reset its hash table, and reset its search order. -** Clears and (re-)creates the main hash table (pForthWords) with the -** size specified by nHash. -**************************************************************************/ -void dictEmpty(FICL_DICT *pDict, unsigned nHash) -{ - FICL_HASH *pHash; - - pDict->here = pDict->dict; - - dictAlign(pDict); - pHash = (FICL_HASH *)pDict->here; - dictAllot(pDict, - sizeof (FICL_HASH) + (nHash - 1) * sizeof (FICL_WORD *)); - - pHash->size = nHash; - hashReset(pHash); - - pDict->pForthWords = pHash; - pDict->smudge = NULL; - dictResetSearchOrder(pDict); - return; -} - - -/************************************************************************** - d i c t H a s h S u m m a r y -** Calculate a figure of merit for the dictionary hash table based -** on the average search depth for all the words in the dictionary, -** assuming uniform distribution of target keys. The figure of merit -** is the ratio of the total search depth for all keys in the table -** versus a theoretical optimum that would be achieved if the keys -** were distributed into the table as evenly as possible. -** The figure would be worse if the hash table used an open -** addressing scheme (i.e. collisions resolved by searching the -** table for an empty slot) for a given size table. -**************************************************************************/ -void dictHashSummary(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - FICL_HASH *pFHash; - FICL_WORD **pHash; - unsigned size; - FICL_WORD *pFW; - unsigned i; - int nMax = 0; - int nWords = 0; - int nFilled; - double avg = 0.0; - double best; - int nAvg, nRem, nDepth; - - dictCheck(dp, pVM, 0); - - pFHash = dp->pSearch[dp->nLists - 1]; - pHash = pFHash->table; - size = pFHash->size; - nFilled = size; - - for (i = 0; i < size; i++) - { - int n = 0; - pFW = pHash[i]; - - while (pFW) - { - ++n; - ++nWords; - pFW = pFW->link; - } - - avg += (double)(n * (n+1)) / 2.0; - - if (n > nMax) - nMax = n; - if (n == 0) - --nFilled; - } - - /* Calc actual avg search depth for this hash */ - avg = avg / nWords; - - /* Calc best possible performance with this size hash */ - nAvg = nWords / size; - nRem = nWords % size; - nDepth = size * (nAvg * (nAvg+1))/2 + (nAvg+1)*nRem; - best = (double)nDepth/nWords; - - sprintf(pVM->pad, - "%d bins, %2.0f%% filled, Depth: Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%", - size, - (double)nFilled * 100.0 / size, nMax, - avg, - best, - 100.0 * best / avg); - - ficlTextOut(pVM, pVM->pad, 1); - - return; -} - - -/************************************************************************** - d i c t I n c l u d e s -** Returns TRUE iff the given pointer is within the address range of -** the dictionary. -**************************************************************************/ -int dictIncludes(FICL_DICT *pDict, void *p) -{ - return ((p >= (void *) &pDict->dict) - && (p < (void *)(&pDict->dict + pDict->size)) - ); -} - - -/************************************************************************** - d i c t L o o k u p -** Find the FICL_WORD that matches the given name and length. -** If found, returns the word's address. Otherwise returns NULL. -** Uses the search order list to search multiple wordlists. -**************************************************************************/ -FICL_WORD *dictLookup(FICL_DICT *pDict, STRINGINFO si) -{ - FICL_WORD *pFW = NULL; - FICL_HASH *pHash; - int i; - UNS16 hashCode = hashHashCode(si); - - assert(pDict); - - ficlLockDictionary(1); - - for (i = (int)pDict->nLists - 1; (i >= 0) && (!pFW); --i) - { - pHash = pDict->pSearch[i]; - pFW = hashLookup(pHash, si, hashCode); - } - - ficlLockDictionary(0); - return pFW; -} - - -/************************************************************************** - d i c t L o o k u p L o c -** Same as dictLookup, but looks in system locals dictionary first... -** Assumes locals dictionary has only one wordlist... -**************************************************************************/ -#if FICL_WANT_LOCALS -FICL_WORD *dictLookupLoc(FICL_DICT *pDict, STRINGINFO si) -{ - FICL_WORD *pFW = NULL; - FICL_HASH *pHash = ficlGetLoc()->pForthWords; - int i; - UNS16 hashCode = hashHashCode(si); - - assert(pHash); - assert(pDict); - - ficlLockDictionary(1); - /* - ** check the locals dict first... - */ - pFW = hashLookup(pHash, si, hashCode); - - /* - ** If no joy, (!pFW) --------------------------v - ** iterate over the search list in the main dict - */ - for (i = (int)pDict->nLists - 1; (i >= 0) && (!pFW); --i) - { - pHash = pDict->pSearch[i]; - pFW = hashLookup(pHash, si, hashCode); - } - - ficlLockDictionary(0); - return pFW; -} -#endif - - -/************************************************************************** - d i c t R e s e t S e a r c h O r d e r -** Initialize the dictionary search order list to sane state -**************************************************************************/ -void dictResetSearchOrder(FICL_DICT *pDict) -{ - assert(pDict); - pDict->pCompile = pDict->pForthWords; - pDict->nLists = 1; - pDict->pSearch[0] = pDict->pForthWords; - return; -} - - -/************************************************************************** - d i c t S e t F l a g s -** Changes the flags field of the most recently defined word: -** Set all bits that are ones in the set parameter, clear all bits -** that are ones in the clr parameter. Clear wins in case the same bit -** is set in both parameters. -**************************************************************************/ -void dictSetFlags(FICL_DICT *pDict, UNS8 set, UNS8 clr) -{ - assert(pDict->smudge); - pDict->smudge->flags |= set; - pDict->smudge->flags &= ~clr; - return; -} - - -/************************************************************************** - d i c t S e t I m m e d i a t e -** Set the most recently defined word as IMMEDIATE -**************************************************************************/ -void dictSetImmediate(FICL_DICT *pDict) -{ - assert(pDict->smudge); - pDict->smudge->flags |= FW_IMMEDIATE; - return; -} - - -/************************************************************************** - d i c t U n s m u d g e -** Completes the definition of a word by linking it -** into the main list -**************************************************************************/ -void dictUnsmudge(FICL_DICT *pDict) -{ - FICL_WORD *pFW = pDict->smudge; - FICL_HASH *pHash = pDict->pCompile; - - assert(pHash); - assert(pFW); - /* - ** :noname words never get linked into the list... - */ - if (pFW->nName > 0) - hashInsertWord(pHash, pFW); - pFW->flags &= ~(FW_SMUDGE); - return; -} - - -/************************************************************************** - d i c t W h e r e -** Returns the value of the HERE pointer -- the address -** of the next free cell in the dictionary -**************************************************************************/ -CELL *dictWhere(FICL_DICT *pDict) -{ - return pDict->here; -} - - -/************************************************************************** - h a s h F o r g e t -** Unlink all words in the hash that have addresses greater than or -** equal to the address supplied. Implementation factor for FORGET -** and MARKER. -**************************************************************************/ -void hashForget(FICL_HASH *pHash, void *where) -{ - FICL_WORD *pWord; - unsigned i; - - assert(pHash); - assert(where); - - for (i = 0; i < pHash->size; i++) - { - pWord = pHash->table[i]; - - while ((void *)pWord >= where) - { - pWord = pWord->link; - } - - pHash->table[i] = pWord; - } - - return; -} - - -/************************************************************************** - h a s h H a s h C o d e -** -** Generate a 16 bit hashcode from a character string using a rolling -** shift and add stolen from PJ Weinberger of Bell Labs fame. Case folds -** the name before hashing it... -** N O T E : If string has zero length, returns zero. -**************************************************************************/ -UNS16 hashHashCode(STRINGINFO si) -{ - /* hashPJW */ - UNS8 *cp; - UNS16 code = (UNS16)si.count; - UNS16 shift = 0; - - if (si.count == 0) - return 0; - - for (cp = (UNS8 *)si.cp; *cp && si.count; cp++, si.count--) - { - code = (UNS16)((code << 4) + tolower(*cp)); - shift = (UNS16)(code & 0xf000); - if (shift) - { - code ^= (UNS16)(shift >> 8); - code ^= (UNS16)shift; - } - } - - return (UNS16)code; -} - - -/************************************************************************** - h a s h I n s e r t W o r d -** Put a word into the hash table using the word's hashcode as -** an index (modulo the table size). -**************************************************************************/ -void hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW) -{ - FICL_WORD **pList; - - assert(pHash); - assert(pFW); - - if (pHash->size == 1) - { - pList = pHash->table; - } - else - { - pList = pHash->table + (pFW->hash % pHash->size); - } - - pFW->link = *pList; - *pList = pFW; - return; -} - - -/************************************************************************** - h a s h L o o k u p -** Find a name in the hash table given the hashcode and text of the name. -** Returns the address of the corresponding FICL_WORD if found, -** otherwise NULL. -** Note: outer loop on link field supports inheritance in wordlists. -** It's not part of ANS Forth - ficl only. hashReset creates wordlists -** with NULL link fields. -**************************************************************************/ -FICL_WORD *hashLookup(FICL_HASH *pHash, STRINGINFO si, UNS16 hashCode) -{ - FICL_COUNT nCmp = (FICL_COUNT)si.count; - FICL_WORD *pFW; - UNS16 hashIdx; - - if (nCmp > nFICLNAME) - nCmp = nFICLNAME; - - for (; pHash != NULL; pHash = pHash->link) - { - if (pHash->size > 1) - hashIdx = (UNS16)(hashCode % pHash->size); - else /* avoid the modulo op for single threaded lists */ - hashIdx = 0; - - for (pFW = pHash->table[hashIdx]; pFW; pFW = pFW->link) - { - if ( (pFW->nName == si.count) - && (!strincmp(si.cp, pFW->name, nCmp)) ) - return pFW; -#if FICL_ROBUST - assert(pFW != pFW->link); -#endif - } - } - - return NULL; -} - - -/************************************************************************** - h a s h R e s e t -** Initialize a FICL_HASH to empty state. -**************************************************************************/ -void hashReset(FICL_HASH *pHash) -{ - unsigned i; - - assert(pHash); - - for (i = 0; i < pHash->size; i++) - { - pHash->table[i] = NULL; - } - - pHash->link = NULL; - return; -} - - diff --git a/sys/boot/ficl/ficl.c b/sys/boot/ficl/ficl.c deleted file mode 100644 index 3b5885f06e2b..000000000000 --- a/sys/boot/ficl/ficl.c +++ /dev/null @@ -1,432 +0,0 @@ -/******************************************************************* -** f i c l . c -** Forth Inspired Command Language - external interface -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 19 July 1997 -** -*******************************************************************/ -/* -** This is an ANS Forth interpreter written in C. -** Ficl uses Forth syntax for its commands, but turns the Forth -** model on its head in other respects. -** Ficl provides facilities for interoperating -** with programs written in C: C functions can be exported to Ficl, -** and Ficl commands can be executed via a C calling interface. The -** interpreter is re-entrant, so it can be used in multiple instances -** in a multitasking system. Unlike Forth, Ficl's outer interpreter -** expects a text block as input, and returns to the caller after each -** text block, so the data pump is somewhere in external code. This -** is more like TCL than Forth. -** -** Code is written in ANSI C for portability. -*/ - -#ifdef TESTMAIN -#include <stdlib.h> -#else -#include <stand.h> -#endif -#include <string.h> -#include "ficl.h" - - -/* -** Local prototypes -*/ - - -/* -** System statics -** The system builds a global dictionary during its start -** sequence. This is shared by all interpreter instances. -** Therefore only one instance can update the dictionary -** at a time. The system imports a locking function that -** you can override in order to control update access to -** the dictionary. The function is stubbed out by default, -** but you can insert one: #define FICL_MULTITHREAD 1 -** and supply your own version of ficlLockDictionary. -*/ -static FICL_DICT *dp = NULL; -static FICL_DICT *envp = NULL; -#if FICL_WANT_LOCALS -static FICL_DICT *localp = NULL; -#endif -static FICL_VM *vmList = NULL; - -static int defaultStack = FICL_DEFAULT_STACK; -static int defaultDict = FICL_DEFAULT_DICT; - - -/************************************************************************** - f i c l I n i t S y s t e m -** Binds a global dictionary to the interpreter system. -** You specify the address and size of the allocated area. -** After that, ficl manages it. -** First step is to set up the static pointers to the area. -** Then write the "precompiled" portion of the dictionary in. -** The dictionary needs to be at least large enough to hold the -** precompiled part. Try 1K cells minimum. Use "words" to find -** out how much of the dictionary is used at any time. -**************************************************************************/ -void ficlInitSystem(int nDictCells) -{ - if (dp) - dictDelete(dp); - - if (envp) - dictDelete(envp); - -#if FICL_WANT_LOCALS - if (localp) - dictDelete(localp); -#endif - - if (nDictCells <= 0) - nDictCells = defaultDict; - - dp = dictCreateHashed((unsigned)nDictCells, HASHSIZE); - envp = dictCreate( (unsigned)FICL_DEFAULT_ENV); -#if FICL_WANT_LOCALS - /* - ** The locals dictionary is only searched while compiling, - ** but this is where speed is most important. On the other - ** hand, the dictionary gets emptied after each use of locals - ** The need to balance search speed with the cost of the empty - ** operation led me to select a single-threaded list... - */ - localp = dictCreate( (unsigned)FICL_MAX_LOCALS * CELLS_PER_WORD); -#endif - - ficlCompileCore(dp); - - return; -} - - -/************************************************************************** - f i c l N e w V M -** Create a new virtual machine and link it into the system list -** of VMs for later cleanup by ficlTermSystem. If this is the first -** VM to be created, use it to compile the words in softcore.c -**************************************************************************/ -FICL_VM *ficlNewVM(void) -{ - FICL_VM *pVM = vmCreate(NULL, defaultStack, defaultStack); - pVM->link = vmList; - - /* - ** Borrow the first vm to build the soft words in softcore.c - */ - if (vmList == NULL) - ficlCompileSoftCore(pVM); - - vmList = pVM; - return pVM; -} - - -/************************************************************************** - f i c l B u i l d -** Builds a word into the dictionary. -** Preconditions: system must be initialized, and there must -** be enough space for the new word's header! Operation is -** controlled by ficlLockDictionary, so any initialization -** required by your version of the function (if you overrode -** it) must be complete at this point. -** Parameters: -** name -- duh, the name of the word -** code -- code to execute when the word is invoked - must take a single param -** pointer to a FICL_VM -** flags -- 0 or more of F_IMMEDIATE, F_COMPILE, use bitwise OR! -** -**************************************************************************/ -int ficlBuild(char *name, FICL_CODE code, char flags) -{ - int err = ficlLockDictionary(TRUE); - if (err) return err; - - dictAppendWord(dp, name, code, flags); - - ficlLockDictionary(FALSE); - return 0; -} - - -/************************************************************************** - f i c l E x e c -** Evaluates a block of input text in the context of the -** specified interpreter. Emits any requested output to the -** interpreter's output function. -** -** Contains the "inner interpreter" code in a tight loop -** -** Returns one of the VM_XXXX codes defined in ficl.h: -** VM_OUTOFTEXT is the normal exit condition -** VM_ERREXIT means that the interp encountered a syntax error -** and the vm has been reset to recover (some or all -** of the text block got ignored -** VM_USEREXIT means that the user executed the "bye" command -** to shut down the interpreter. This would be a good -** time to delete the vm, etc -- or you can ignore this -** signal. -**************************************************************************/ -int ficlExec(FICL_VM *pVM, char *pText) -{ - int except; - FICL_WORD *tempFW; - jmp_buf vmState; - jmp_buf *oldState; - TIB saveTib; - - assert(pVM); - - vmPushTib(pVM, pText, &saveTib); - - /* - ** Save and restore VM's jmp_buf to enable nested calls to ficlExec - */ - oldState = pVM->pState; - pVM->pState = &vmState; /* This has to come before the setjmp! */ - except = setjmp(vmState); - - switch (except) - { - case 0: - if (pVM->fRestart) - { - pVM->fRestart = 0; - pVM->runningWord->code(pVM); - } - - /* - ** the mysterious inner interpreter... - ** vmThrow gets you out of this loop with a longjmp() - */ - for (;;) - { - tempFW = *pVM->ip++; - /* - ** inline code for - ** vmExecute(pVM, tempFW); - */ - pVM->runningWord = tempFW; - tempFW->code(pVM); - } - - break; - - case VM_RESTART: - pVM->fRestart = 1; - except = VM_OUTOFTEXT; - break; - - case VM_OUTOFTEXT: -#ifdef TESTMAIN - if ((pVM->state != COMPILE) && (pVM->sourceID.i == 0)) - ficlTextOut(pVM, FICL_PROMPT, 0); -#endif - break; - - case VM_USEREXIT: - break; - - case VM_QUIT: - if (pVM->state == COMPILE) - dictAbortDefinition(dp); - vmQuit(pVM); - break; - - case VM_ERREXIT: - default: /* user defined exit code?? */ - if (pVM->state == COMPILE) - { - dictAbortDefinition(dp); -#if FICL_WANT_LOCALS - dictEmpty(localp, localp->pForthWords->size); -#endif - } - dictResetSearchOrder(dp); - vmReset(pVM); - break; - } - - pVM->pState = oldState; - vmPopTib(pVM, &saveTib); - return (except); -} - -/************************************************************************** - f i c l E x e c F D -** reads in text from file fd and passes it to ficlExec() - * returns VM_OUTOFTEXT on success or the ficlExec() error code on - * failure. - */ -#define nLINEBUF 256 -int ficlExecFD(FICL_VM *pVM, int fd) -{ - char cp[nLINEBUF]; - int i, nLine = 0, rval = VM_OUTOFTEXT; - char ch; - CELL id; - - id = pVM->sourceID; - pVM->sourceID.i = fd; - - /* feed each line to ficlExec */ - while (1) { - int status, i; - - i = 0; - while ((status = read(fd, &ch, 1)) > 0 && ch != '\n') - cp[i++] = ch; - nLine++; - if (!i) { - if (status < 1) - break; - continue; - } - cp[i] = '\0'; - if ((rval = ficlExec(pVM, cp)) >= VM_ERREXIT) - { - pVM->sourceID = id; - vmThrowErr(pVM, "ficlExecFD: Error at line %d", nLine); - break; - } - } - /* - ** Pass an empty line with SOURCE-ID == 0 to flush - ** any pending REFILLs (as required by FILE wordset) - */ - pVM->sourceID.i = -1; - ficlExec(pVM, ""); - - pVM->sourceID = id; - return rval; -} - -/************************************************************************** - f i c l L o o k u p -** Look in the system dictionary for a match to the given name. If -** found, return the address of the corresponding FICL_WORD. Otherwise -** return NULL. -**************************************************************************/ -FICL_WORD *ficlLookup(char *name) -{ - STRINGINFO si; - SI_PSZ(si, name); - return dictLookup(dp, si); -} - - -/************************************************************************** - f i c l G e t D i c t -** Returns the address of the system dictionary -**************************************************************************/ -FICL_DICT *ficlGetDict(void) -{ - return dp; -} - - -/************************************************************************** - f i c l G e t E n v -** Returns the address of the system environment space -**************************************************************************/ -FICL_DICT *ficlGetEnv(void) -{ - return envp; -} - - -/************************************************************************** - f i c l S e t E n v -** Create an environment variable with a one-CELL payload. ficlSetEnvD -** makes one with a two-CELL payload. -**************************************************************************/ -void ficlSetEnv(char *name, UNS32 value) -{ - STRINGINFO si; - FICL_WORD *pFW; - - SI_PSZ(si, name); - pFW = dictLookup(envp, si); - - if (pFW == NULL) - { - dictAppendWord(envp, name, constantParen, FW_DEFAULT); - dictAppendCell(envp, LVALUEtoCELL(value)); - } - else - { - pFW->param[0] = LVALUEtoCELL(value); - } - - return; -} - -void ficlSetEnvD(char *name, UNS32 hi, UNS32 lo) -{ - FICL_WORD *pFW; - STRINGINFO si; - SI_PSZ(si, name); - pFW = dictLookup(envp, si); - - if (pFW == NULL) - { - dictAppendWord(envp, name, twoConstParen, FW_DEFAULT); - dictAppendCell(envp, LVALUEtoCELL(lo)); - dictAppendCell(envp, LVALUEtoCELL(hi)); - } - else - { - pFW->param[0] = LVALUEtoCELL(lo); - pFW->param[1] = LVALUEtoCELL(hi); - } - - return; -} - - -/************************************************************************** - f i c l G e t L o c -** Returns the address of the system locals dictionary. This dict is -** only used during compilation, and is shared by all VMs. -**************************************************************************/ -#if FICL_WANT_LOCALS -FICL_DICT *ficlGetLoc(void) -{ - return localp; -} -#endif - - -/************************************************************************** - f i c l T e r m S y s t e m -** Tear the system down by deleting the dictionaries and all VMs. -** This saves you from having to keep track of all that stuff. -**************************************************************************/ -void ficlTermSystem(void) -{ - if (dp) - dictDelete(dp); - dp = NULL; - - if (envp) - dictDelete(envp); - envp = NULL; - -#if FICL_WANT_LOCALS - if (localp) - dictDelete(localp); - localp = NULL; -#endif - - while (vmList != NULL) - { - FICL_VM *pVM = vmList; - vmList = vmList->link; - vmDelete(pVM); - } - - return; -} diff --git a/sys/boot/ficl/ficl.h b/sys/boot/ficl/ficl.h deleted file mode 100644 index 3fcb32efbb81..000000000000 --- a/sys/boot/ficl/ficl.h +++ /dev/null @@ -1,773 +0,0 @@ -/******************************************************************* -** f i c l . h -** Forth Inspired Command Language -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 19 July 1997 -** -*******************************************************************/ -/* -** N O T I C E -- DISCLAIMER OF WARRANTY -** -** Ficl is freeware. Use it in any way that you like, with -** the understanding that the code is supported on a "best effort" -** basis only. -** -** Any third party may reproduce, distribute, or modify the ficl -** software code or any derivative works thereof without any -** compensation or license, provided that the author information -** and this disclaimer text are retained in the source code files. -** The ficl software code is provided on an "as is" basis without -** warranty of any kind, including, without limitation, the implied -** warranties of merchantability and fitness for a particular purpose -** and their equivalents under the laws of any jurisdiction. -** -** I am interested in hearing from anyone who uses ficl. If you have -** a problem, a success story, a defect, an enhancement request, or -** if you would like to contribute to the ficl release (yay!), please -** send me email at the address above. -*/ - -#if !defined (__FICL_H__) -#define __FICL_H__ -/* -** Ficl (Forth-inspired command language) is an ANS Forth -** interpreter written in C. Unlike traditional Forths, this -** interpreter is designed to be embedded into other systems -** as a command/macro/development prototype language. -** -** Where Forths usually view themselves as the center of the system -** and expect the rest of the system to be coded in Forth, Ficl -** acts as a component of the system. It is easy to export -** code written in C or ASM to Ficl in the style of TCL, or to invoke -** Ficl code from a compiled module. This allows you to do incremental -** development in a way that combines the best features of threaded -** languages (rapid development, quick code/test/debug cycle, -** reasonably fast) with the best features of C (everyone knows it, -** easier to support large blocks of code, efficient, type checking). -** -** Ficl provides facilities for interoperating -** with programs written in C: C functions can be exported to Ficl, -** and Ficl commands can be executed via a C calling interface. The -** interpreter is re-entrant, so it can be used in multiple instances -** in a multitasking system. Unlike Forth, Ficl's outer interpreter -** expects a text block as input, and returns to the caller after each -** text block, so the "data pump" is somewhere in external code. This -** is more like TCL than Forth, which usually expcets to be at the center -** of the system, requesting input at its convenience. Each Ficl virtual -** machine can be bound to a different I/O channel, and is independent -** of all others in in the same address space except that all virtual -** machines share a common dictionary (a sort or open symbol table that -** defines all of the elements of the language). -** -** Code is written in ANSI C for portability. -** -** Summary of Ficl features and constraints: -** - Standard: Implements the ANSI Forth CORE word set and part -** of the CORE EXT word-set, SEARCH and SEARCH EXT, TOOLS and -** TOOLS EXT, LOCAL and LOCAL ext and various extras. -** - Extensible: you can export code written in Forth, C, -** or asm in a straightforward way. Ficl provides open -** facilities for extending the language in an application -** specific way. You can even add new control structures! -** - Ficl and C can interact in two ways: Ficl can encapsulate -** C code, or C code can invoke Ficl code. -** - Thread-safe, re-entrant: The shared system dictionary -** uses a locking mechanism that you can either supply -** or stub out to provide exclusive access. Each Ficl -** virtual machine has an otherwise complete state, and -** each can be bound to a separate I/O channel (or none at all). -** - Simple encapsulation into existing systems: a basic implementation -** requires three function calls (see the example program in testmain.c). -** - ROMable: Ficl is designed to work in RAM-based and ROM code / RAM data -** environments. It does require somewhat more memory than a pure -** ROM implementation because it builds its system dictionary in -** RAM at startup time. -** - Written an ANSI C to be as simple as I can make it to understand, -** support, debug, and port. Compiles without complaint at /Az /W4 -** (require ANSI C, max warnings) under Microsoft VC++ 5. -** - Does full 32 bit math (but you need to implement -** two mixed precision math primitives (see sysdep.c)) -** - Indirect threaded interpreter is not the fastest kind of -** Forth there is (see pForth 68K for a really fast subroutine -** threaded interpreter), but it's the cleanest match to a -** pure C implementation. -** -** P O R T I N G F i c l -** -** To install Ficl on your target system, you need an ANSI C compiler -** and its runtime library. Inspect the system dependent macros and -** functions in sysdep.h and sysdep.c and edit them to suit your -** system. For example, INT16 is a short on some compilers and an -** int on others. Check the default CELL alignment controlled by -** FICL_ALIGN. If necessary, add new definitions of ficlMalloc, ficlFree, -** ficlLockDictionary, and ficlTextOut to work with your operating system. -** Finally, use testmain.c as a guide to installing the Ficl system and -** one or more virtual machines into your code. You do not need to include -** testmain.c in your build. -** -** T o D o L i s t -** -** 1. Unimplemented system dependent CORE word: key -** 2. Kludged CORE word: ACCEPT -** 3. Dictionary locking is full of holes - only one vm at a time -** can alter the dict. -** 4. Ficl uses the pad in CORE words - this violates the standard, -** but it's cleaner for a multithreaded system. I'll have to make a -** second pad for reference by the word PAD to fix this. -** -** F o r M o r e I n f o r m a t i o n -** -** Web home of ficl -** http://www.taygeta.com/forth/compilers -** Check this website for Forth literature (including the ANSI standard) -** http://www.taygeta.com/forthlit.html -** and here for software and more links -** http://www.taygeta.com/forth.html -** -** Obvious Performance enhancement opportunities -** Compile speed -** - work on interpret speed -** - turn off locals (FICL_WANT_LOCALS) -** Interpret speed -** - Change inner interpreter (and everything else) -** so that a definition is a list of pointers to functions -** and inline data rather than pointers to words. This gets -** rid of vm->runningWord and a level of indirection in the -** inner loop. I'll look at it for ficl 3.0 -** - Make the main hash table a bigger prime (HASHSIZE) -** - FORGET about twiddling the hash function - my experience is -** that that is a waste of time. -** - eliminate the need to pass the pVM parameter on the stack -** by dedicating a register to it. Most words need access to the -** vm, but the parameter passing overhead can be reduced. One way -** requires that the host OS have a task switch callout. Create -** a global variable for the running VM and refer to it in words -** that need VM access. Alternative: use thread local storage. -** For single threaded implementations, you can just use a global. -** The first two solutions create portability problems, so I -** haven't considered doing them. Another possibility is to -** declare the pVm parameter to be "register", and hope the compiler -** pays attention. -** -*/ - -/* -** Revision History: -** 27 Aug 1998 (sadler) testing and corrections for LOCALS, LOCALS EXT, -** SEARCH / SEARCH EXT, TOOLS / TOOLS EXT. -** Added .X to display in hex, PARSE and PARSE-WORD to supplement WORD, -** EMPTY to clear stack. -** -** 29 jun 1998 (sadler) added variable sized hash table support -** and ANS Forth optional SEARCH & SEARCH EXT word set. -** 26 May 1998 (sadler) -** FICL_PROMPT macro -** 14 April 1998 (sadler) V1.04 -** Ficlwin: Windows version, Skip Carter's Linux port -** 5 March 1998 (sadler) V1.03 -** Bug fixes -- passes John Ryan's ANS test suite "core.fr" -** -** 24 February 1998 (sadler) V1.02 -** -Fixed bugs in <# # #> -** -Changed FICL_WORD so that storage for the name characters -** can be allocated from the dictionary as needed rather than -** reserving 32 bytes in each word whether needed or not - -** this saved 50% of the dictionary storage requirement. -** -Added words in testmain for Win32 functions system,chdir,cwd, -** also added a word that loads and evaluates a file. -** -** December 1997 (sadler) -** -Added VM_RESTART exception handling in ficlExec -- this lets words -** that require additional text to succeed (like :, create, variable...) -** recover gracefully from an empty input buffer rather than emitting -** an error message. Definitions can span multiple input blocks with -** no restrictions. -** -Changed #include order so that <assert.h> is included in sysdep.h, -** and sysdep is included in all other files. This lets you define -** NDEBUG in sysdep.h to disable assertions if you want to. -** -Make PC specific system dependent code conditional on _M_IX86 -** defined so that ports can coexist in sysdep.h/sysdep.c -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sysdep.h" -#include <limits.h> /* UCHAR_MAX */ - -/* -** Forward declarations... read on. -*/ -struct ficl_word; -struct vm; -struct ficl_dict; - -/* -** the Good Stuff starts here... -*/ -#define FICL_VER "2.02" -#ifndef FICL_PROMPT -# define FICL_PROMPT "ok> " -#endif - -/* -** ANS Forth requires false to be zero, and true to be the ones -** complement of false... that unifies logical and bitwise operations -** nicely. -*/ -#define FICL_TRUE (0xffffffffL) -#define FICL_FALSE (0) -#define FICL_BOOL(x) ((x) ? FICL_TRUE : FICL_FALSE) - - -/* -** A CELL is the main storage type. It must be large enough -** to contain a pointer or a scalar. Let's be picky and make -** a 32 bit cell explicitly... -*/ -typedef union _cell -{ - INT32 i; - UNS32 u; - void *p; -} CELL; - -/* -** LVALUEtoCELL does a little pointer trickery to cast any 32 bit -** lvalue (informal definition: an expression whose result has an -** address) to CELL. Remember that constants and casts are NOT -** themselves lvalues! -*/ -#define LVALUEtoCELL(v) (*(CELL *)&v) - -/* -** PTRtoCELL is a cast through void * intended to satisfy the -** most outrageously pedantic compiler... (I won't mention -** its name) -*/ -#define PTRtoCELL (CELL *)(void *) -#define PTRtoSTRING (FICL_STRING *)(void *) - -/* -** Strings in FICL are stored in Pascal style - with a count -** preceding the text. We'll also NULL-terminate them so that -** they work with the usual C lib string functions. (Belt & -** suspenders? You decide.) -** STRINGINFO hides the implementation with a couple of -** macros for use in internal routines. -*/ - -typedef unsigned char FICL_COUNT; -#define FICL_STRING_MAX UCHAR_MAX -typedef struct _ficl_string -{ - FICL_COUNT count; - char text[1]; -} FICL_STRING; - -typedef struct -{ - UNS32 count; - char *cp; -} STRINGINFO; - -#define SI_COUNT(si) (si.count) -#define SI_PTR(si) (si.cp) -#define SI_SETLEN(si, len) (si.count = (UNS32)(len)) -#define SI_SETPTR(si, ptr) (si.cp = (char *)(ptr)) -/* -** Init a STRINGINFO from a pointer to NULL-terminated string -*/ -#define SI_PSZ(si, psz) \ - {si.cp = psz; si.count = (FICL_COUNT)strlen(psz);} -/* -** Init a STRINGINFO from a pointer to FICL_STRING -*/ -#define SI_PFS(si, pfs) \ - {si.cp = pfs->text; si.count = pfs->count;} - -/* -** Ficl uses a this little structure to hold the address of -** the block of text it's working on and an index to the next -** unconsumed character in the string. Traditionally, this is -** done by a Text Input Buffer, so I've called this struct TIB. -*/ -typedef struct -{ - INT32 index; - char *cp; -} TIB; - - -/* -** Stacks get heavy use in Ficl and Forth... -** Each virtual machine implements two of them: -** one holds parameters (data), and the other holds return -** addresses and control flow information for the virtual -** machine. (Note: C's automatic stack is implicitly used, -** but not modeled because it doesn't need to be...) -** Here's an abstract type for a stack -*/ -typedef struct _ficlStack -{ - UNS32 nCells; /* size of the stack */ - CELL *pFrame; /* link reg for stack frame */ - CELL *sp; /* stack pointer */ - CELL base[1]; /* Bottom of the stack */ -} FICL_STACK; - -/* -** Stack methods... many map closely to required Forth words. -*/ -FICL_STACK *stackCreate(unsigned nCells); -void stackDelete(FICL_STACK *pStack); -int stackDepth (FICL_STACK *pStack); -void stackDrop (FICL_STACK *pStack, int n); -CELL stackFetch (FICL_STACK *pStack, int n); -CELL stackGetTop(FICL_STACK *pStack); -void stackLink (FICL_STACK *pStack, int nCells); -void stackPick (FICL_STACK *pStack, int n); -CELL stackPop (FICL_STACK *pStack); -void *stackPopPtr (FICL_STACK *pStack); -UNS32 stackPopUNS32 (FICL_STACK *pStack); -INT32 stackPopINT32 (FICL_STACK *pStack); -void stackPush (FICL_STACK *pStack, CELL c); -void stackPushPtr (FICL_STACK *pStack, void *ptr); -void stackPushUNS32(FICL_STACK *pStack, UNS32 u); -void stackPushINT32(FICL_STACK *pStack, INT32 i); -void stackReset (FICL_STACK *pStack); -void stackRoll (FICL_STACK *pStack, int n); -void stackSetTop(FICL_STACK *pStack, CELL c); -void stackStore (FICL_STACK *pStack, int n, CELL c); -void stackUnlink(FICL_STACK *pStack); - -/* -** The virtual machine (VM) contains the state for one interpreter. -** Defined operations include: -** Create & initialize -** Delete -** Execute a block of text -** Parse a word out of the input stream -** Call return, and branch -** Text output -** Throw an exception -*/ - -typedef struct ficl_word ** IPTYPE; /* the VM's instruction pointer */ - -/* -** Each VM has a placeholder for an output function - -** this makes it possible to have each VM do I/O -** through a different device. If you specify no -** OUTFUNC, it defaults to ficlTextOut. -*/ -typedef void (*OUTFUNC)(struct vm *pVM, char *text, int fNewline); - -/* -** Each VM operates in one of two non-error states: interpreting -** or compiling. When interpreting, words are simply executed. -** When compiling, most words in the input stream have their -** addresses inserted into the word under construction. Some words -** (known as IMMEDIATE) are executed in the compile state, too. -*/ -/* values of STATE */ -#define INTERPRET 0 -#define COMPILE 1 - -/* -** The pad is a small scratch area for text manipulation. ANS Forth -** requires it to hold at least 84 characters. -*/ -#if !defined nPAD -#define nPAD 256 -#endif - -/* -** ANS Forth requires that a word's name contain {1..31} characters. -*/ -#if !defined nFICLNAME -#define nFICLNAME 31 -#endif - -/* -** OK - now we can really define the VM... -*/ -typedef struct vm -{ - struct vm *link; /* Ficl keeps a VM list for simple teardown */ - jmp_buf *pState; /* crude exception mechanism... */ - OUTFUNC textOut; /* Output callback - see sysdep.c */ - void * pExtend; /* vm extension pointer */ - short fRestart; /* Set TRUE to restart runningWord */ - IPTYPE ip; /* instruction pointer */ - struct ficl_word - *runningWord;/* address of currently running word (often just *(ip-1) ) */ - UNS32 state; /* compiling or interpreting */ - UNS32 base; /* number conversion base */ - FICL_STACK *pStack; /* param stack */ - FICL_STACK *rStack; /* return stack */ - CELL sourceID; /* -1 if string, 0 if normal input */ - TIB tib; /* address of incoming text string */ -#if FICL_WANT_USER - CELL user[FICL_USER_CELLS]; -#endif - char pad[nPAD]; /* the scratch area (see above) */ -} FICL_VM; - -/* -** A FICL_CODE points to a function that gets called to help execute -** a word in the dictionary. It always gets passed a pointer to the -** running virtual machine, and from there it can get the address -** of the parameter area of the word it's supposed to operate on. -** For precompiled words, the code is all there is. For user defined -** words, the code assumes that the word's parameter area is a list -** of pointers to the code fields of other words to execute, and -** may also contain inline data. The first parameter is always -** a pointer to a code field. -*/ -typedef void (*FICL_CODE)(FICL_VM *pVm); - -/* -** Ficl models memory as a contiguous space divided into -** words in a linked list called the dictionary. -** A FICL_WORD starts each entry in the list. -** Version 1.02: space for the name characters is allotted from -** the dictionary ahead of the word struct - this saves about half -** the storage on average with very little runtime cost. -*/ -typedef struct ficl_word -{ - struct ficl_word *link; /* Previous word in the dictionary */ - UNS16 hash; - UNS8 flags; /* Immediate, Smudge, Compile-only */ - FICL_COUNT nName; /* Number of chars in word name */ - char *name; /* First nFICLNAME chars of word name */ - FICL_CODE code; /* Native code to execute the word */ - CELL param[1]; /* First data cell of the word */ -} FICL_WORD; - -/* -** Worst-case size of a word header: nFICLNAME chars in name -*/ -#define CELLS_PER_WORD \ - ( (sizeof (FICL_WORD) + nFICLNAME + sizeof (CELL)) \ - / (sizeof (CELL)) ) - -int wordIsImmediate(FICL_WORD *pFW); -int wordIsCompileOnly(FICL_WORD *pFW); - -/* flag values for word header */ -#define FW_IMMEDIATE 1 /* execute me even if compiling */ -#define FW_COMPILE 2 /* error if executed when not compiling */ -#define FW_SMUDGE 4 /* definition in progress - hide me */ -#define FW_CLASS 8 /* Word defines a class */ - -#define FW_COMPIMMED (FW_IMMEDIATE | FW_COMPILE) -#define FW_DEFAULT 0 - - -/* -** Exit codes for vmThrow -*/ -#define VM_OUTOFTEXT 1 /* hungry - normal exit */ -#define VM_RESTART 2 /* word needs more text to suxcceed - re-run it */ -#define VM_USEREXIT 3 /* user wants to quit */ -#define VM_ERREXIT 4 /* interp found an error */ -#define VM_QUIT 5 /* like errexit, but leave pStack & base alone */ - - -void vmBranchRelative(FICL_VM *pVM, int offset); -FICL_VM * vmCreate (FICL_VM *pVM, unsigned nPStack, unsigned nRStack); -void vmDelete (FICL_VM *pVM); -void vmExecute(FICL_VM *pVM, FICL_WORD *pWord); -char * vmGetString(FICL_VM *pVM, FICL_STRING *spDest, char delimiter); -STRINGINFO vmGetWord(FICL_VM *pVM); -STRINGINFO vmGetWord0(FICL_VM *pVM); -int vmGetWordToPad(FICL_VM *pVM); -STRINGINFO vmParseString(FICL_VM *pVM, char delimiter); -void vmPopIP (FICL_VM *pVM); -void vmPushIP (FICL_VM *pVM, IPTYPE newIP); -void vmQuit (FICL_VM *pVM); -void vmReset (FICL_VM *pVM); -void vmSetTextOut(FICL_VM *pVM, OUTFUNC textOut); -void vmTextOut(FICL_VM *pVM, char *text, int fNewline); -void vmThrow (FICL_VM *pVM, int except); -void vmThrowErr(FICL_VM *pVM, char *fmt, ...); - -/* -** vmCheckStack needs a vm pointer because it might have to say -** something if it finds a problem. Parms popCells and pushCells -** correspond to the number of parameters on the left and right of -** a word's stack effect comment. -*/ -void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells); - -/* -** TIB access routines... -** ANS forth seems to require the input buffer to be represented -** as a pointer to the start of the buffer, and an index to the -** next character to read. -** PushTib points the VM to a new input string and optionally -** returns a copy of the current state -** PopTib restores the TIB state given a saved TIB from PushTib -** GetInBuf returns a pointer to the next unused char of the TIB -*/ -void vmPushTib(FICL_VM *pVM, char *text, TIB *pSaveTib); -void vmPopTib(FICL_VM *pVM, TIB *pTib); -#define vmGetInBuf(pVM) ((pVM)->tib.cp + (pVM)->tib.index) -#define vmSetTibIndex(pVM, i) (pVM)->tib.index = i -#define vmUpdateTib(pVM, str) (pVM)->tib.index = (str) - (pVM)->tib.cp - -/* -** Generally useful string manipulators omitted by ANSI C... -** ltoa complements strtol -*/ -#if defined(_WIN32) && !FICL_MAIN -/* #SHEESH -** Why do Microsoft Meatballs insist on contaminating -** my namespace with their string functions??? -*/ -#pragma warning(disable: 4273) -#endif - -char *ltoa( INT32 value, char *string, int radix ); -char *ultoa(UNS32 value, char *string, int radix ); -char digit_to_char(int value); -char *strrev( char *string ); -char *skipSpace(char *cp); -char *caseFold(char *cp); -int strincmp(char *cp1, char *cp2, FICL_COUNT count); - -#if defined(_WIN32) && !FICL_MAIN -#pragma warning(default: 4273) -#endif - -/* -** Ficl hash table - variable size. -** assert(size > 0) -** If size is 1, the table degenerates into a linked list. -** A WORDLIST (see the search order word set in DPANS) is -** just a pointer to a FICL_HASH in this implementation. -*/ -#if !defined HASHSIZE /* Default size of hash table. For best */ -#define HASHSIZE 127 /* performance, use a prime number! */ -#endif - -typedef struct ficl_hash -{ - struct ficl_hash *link; /* eventual inheritance support */ - unsigned size; - FICL_WORD *table[1]; -} FICL_HASH; - -void hashForget(FICL_HASH *pHash, void *where); -UNS16 hashHashCode(STRINGINFO si); -void hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW); -FICL_WORD *hashLookup(struct ficl_hash *pHash, - STRINGINFO si, - UNS16 hashCode); -void hashReset(FICL_HASH *pHash); - -/* -** A Dictionary is a linked list of FICL_WORDs. It is also Ficl's -** memory model. Description of fields: -** -** here -- points to the next free byte in the dictionary. This -** pointer is forced to be CELL-aligned before a definition is added. -** Do not assume any specific alignment otherwise - Use dictAlign(). -** -** smudge -- pointer to word currently being defined (or last defined word) -** If the definition completes successfully, the word will be -** linked into the hash table. If unsuccessful, dictUnsmudge -** uses this pointer to restore the previous state of the dictionary. -** Smudge prevents unintentional recursion as a side-effect: the -** dictionary search algo examines only completed definitions, so a -** word cannot invoke itself by name. See the ficl word "recurse". -** NOTE: smudge always points to the last word defined. IMMEDIATE -** makes use of this fact. Smudge is initially NULL. -** -** pForthWords -- pointer to the default wordlist (FICL_HASH). -** This is the initial compilation list, and contains all -** ficl's precompiled words. -** -** pCompile -- compilation wordlist - initially equal to pForthWords -** pSearch -- array of pointers to wordlists. Managed as a stack. -** Highest index is the first list in the search order. -** nLists -- number of lists in pSearch. nLists-1 is the highest -** filled slot in pSearch, and points to the first wordlist -** in the search order -** size -- number of cells in the dictionary (total) -** dict -- start of data area. Must be at the end of the struct. -*/ -typedef struct ficl_dict -{ - CELL *here; - FICL_WORD *smudge; - FICL_HASH *pForthWords; - FICL_HASH *pCompile; - FICL_HASH *pSearch[FICL_DEFAULT_VOCS]; - int nLists; - unsigned size; /* Number of cells in dict (total)*/ - CELL dict[1]; /* Base of dictionary memory */ -} FICL_DICT; - -void *alignPtr(void *ptr); -void dictAbortDefinition(FICL_DICT *pDict); -void dictAlign(FICL_DICT *pDict); -int dictAllot(FICL_DICT *pDict, int n); -int dictAllotCells(FICL_DICT *pDict, int nCells); -void dictAppendCell(FICL_DICT *pDict, CELL c); -void dictAppendChar(FICL_DICT *pDict, char c); -FICL_WORD *dictAppendWord(FICL_DICT *pDict, - char *name, - FICL_CODE pCode, - UNS8 flags); -FICL_WORD *dictAppendWord2(FICL_DICT *pDict, - STRINGINFO si, - FICL_CODE pCode, - UNS8 flags); -void dictAppendUNS32(FICL_DICT *pDict, UNS32 u); -int dictCellsAvail(FICL_DICT *pDict); -int dictCellsUsed (FICL_DICT *pDict); -void dictCheck(FICL_DICT *pDict, FICL_VM *pVM, int nCells); -FICL_DICT *dictCreate(unsigned nCELLS); -FICL_DICT *dictCreateHashed(unsigned nCells, unsigned nHash); -void dictDelete(FICL_DICT *pDict); -void dictEmpty(FICL_DICT *pDict, unsigned nHash); -void dictHashSummary(FICL_VM *pVM); -int dictIncludes(FICL_DICT *pDict, void *p); -FICL_WORD *dictLookup(FICL_DICT *pDict, STRINGINFO si); -#if FICL_WANT_LOCALS -FICL_WORD *dictLookupLoc(FICL_DICT *pDict, STRINGINFO si); -#endif -void dictResetSearchOrder(FICL_DICT *pDict); -void dictSetFlags(FICL_DICT *pDict, UNS8 set, UNS8 clr); -void dictSetImmediate(FICL_DICT *pDict); -void dictUnsmudge(FICL_DICT *pDict); -CELL *dictWhere(FICL_DICT *pDict); - - -/* -** External interface to FICL... -*/ -/* -** f i c l I n i t S y s t e m -** Binds a global dictionary to the interpreter system and initializes -** the dict to contain the ANSI CORE wordset. -** You specify the address and size of the allocated area. -** After that, ficl manages it. -** First step is to set up the static pointers to the area. -** Then write the "precompiled" portion of the dictionary in. -** The dictionary needs to be at least large enough to hold the -** precompiled part. Try 1K cells minimum. Use "words" to find -** out how much of the dictionary is used at any time. -*/ -void ficlInitSystem(int nDictCells); - -/* -** f i c l T e r m S y s t e m -** Deletes the system dictionary and all virtual machines that -** were created with ficlNewVM (see below). Call this function to -** reclaim all memory used by the dictionary and VMs. -*/ -void ficlTermSystem(void); - -/* -** f i c l E x e c -** Evaluates a block of input text in the context of the -** specified interpreter. Emits any requested output to the -** interpreter's output function -** Execution returns when the text block has been executed, -** or an error occurs. -** Returns one of the VM_XXXX codes defined in ficl.h: -** VM_OUTOFTEXT is the normal exit condition -** VM_ERREXIT means that the interp encountered a syntax error -** and the vm has been reset to recover (some or all -** of the text block got ignored -** VM_USEREXIT means that the user executed the "bye" command -** to shut down the interpreter. This would be a good -** time to delete the vm, etc -- or you can ignore this -** signal. -** Preconditions: successful execution of ficlInitSystem, -** Successful creation and init of the VM by ficlNewVM (or equiv) -*/ -int ficlExec(FICL_VM *pVM, char *pText); - -/* -** ficlExecFD(FICL_VM *pVM, int fd); - * Evaluates text from file passed in via fd. - * Execution returns when all of file has been executed or an - * error occurs. - */ -int ficlExecFD(FICL_VM *pVM, int fd); - -/* -** Create a new VM from the heap, and link it into the system VM list. -** Initializes the VM and binds default sized stacks to it. Returns the -** address of the VM, or NULL if an error occurs. -** Precondition: successful execution of ficlInitSystem -*/ -FICL_VM *ficlNewVM(void); - -/* -** Returns the address of the most recently defined word in the system -** dictionary with the given name, or NULL if no match. -** Precondition: successful execution of ficlInitSystem -*/ -FICL_WORD *ficlLookup(char *name); - -/* -** f i c l G e t D i c t -** Utility function - returns the address of the system dictionary. -** Precondition: successful execution of ficlInitSystem -*/ -FICL_DICT *ficlGetDict(void); -FICL_DICT *ficlGetEnv(void); -void ficlSetEnv(char *name, UNS32 value); -void ficlSetEnvD(char *name, UNS32 hi, UNS32 lo); -#if FICL_WANT_LOCALS -FICL_DICT *ficlGetLoc(void); -#endif -/* -** f i c l B u i l d -** Builds a word into the system default dictionary in a thread-safe way. -** Preconditions: system must be initialized, and there must -** be enough space for the new word's header! Operation is -** controlled by ficlLockDictionary, so any initialization -** required by your version of the function (if you "overrode" -** it) must be complete at this point. -** Parameters: -** name -- the name of the word to be built -** code -- code to execute when the word is invoked - must take a single param -** pointer to a FICL_VM -** flags -- 0 or more of FW_IMMEDIATE, FW_COMPILE, use bitwise OR! -** Most words can use FW_DEFAULT. -** nAllot - number of extra cells to allocate in the parameter area (usually zero) -*/ -int ficlBuild(char *name, FICL_CODE code, char flags); - -/* -** f i c l C o m p i l e C o r e -** Builds the ANS CORE wordset into the dictionary - called by -** ficlInitSystem - no need to waste dict space by doing it again. -*/ -void ficlCompileCore(FICL_DICT *dp); -void ficlCompileSoftCore(FICL_VM *pVM); - -/* -** from words.c... -*/ -void constantParen(FICL_VM *pVM); -void twoConstParen(FICL_VM *pVM); - -#if defined(__i386__) && !defined(TESTMAIN) -extern void ficlOutb(FICL_VM *pVM); -extern void ficlInb(FICL_VM *pVM); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __FICL_H__ */ diff --git a/sys/boot/ficl/math64.c b/sys/boot/ficl/math64.c deleted file mode 100644 index e83000a8b4a2..000000000000 --- a/sys/boot/ficl/math64.c +++ /dev/null @@ -1,296 +0,0 @@ -/******************************************************************* -** m a t h 6 4 . c -** Forth Inspired Command Language - 64 bit math support routines -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 25 January 1998 -** -*******************************************************************/ - -#include "ficl.h" -#include "math64.h" - - -/************************************************************************** - m 6 4 A b s -** Returns the absolute value of an INT64 -**************************************************************************/ -INT64 m64Abs(INT64 x) -{ - if (m64IsNegative(x)) - x = m64Negate(x); - - return x; -} - - -/************************************************************************** - m 6 4 F l o o r e d D i v I -** -** FROM THE FORTH ANS... -** Floored division is integer division in which the remainder carries -** the sign of the divisor or is zero, and the quotient is rounded to -** its arithmetic floor. Symmetric division is integer division in which -** the remainder carries the sign of the dividend or is zero and the -** quotient is the mathematical quotient rounded towards zero or -** truncated. Examples of each are shown in tables 3.3 and 3.4. -** -** Table 3.3 - Floored Division Example -** Dividend Divisor Remainder Quotient -** -------- ------- --------- -------- -** 10 7 3 1 -** -10 7 4 -2 -** 10 -7 -4 -2 -** -10 -7 -3 1 -** -** -** Table 3.4 - Symmetric Division Example -** Dividend Divisor Remainder Quotient -** -------- ------- --------- -------- -** 10 7 3 1 -** -10 7 -3 -1 -** 10 -7 3 -1 -** -10 -7 -3 1 -**************************************************************************/ -INTQR m64FlooredDivI(INT64 num, INT32 den) -{ - INTQR qr; - UNSQR uqr; - int signRem = 1; - int signQuot = 1; - - if (m64IsNegative(num)) - { - num = m64Negate(num); - signQuot = -signQuot; - } - - if (den < 0) - { - den = -den; - signRem = -signRem; - signQuot = -signQuot; - } - - uqr = ficlLongDiv(m64CastIU(num), (UNS32)den); - qr = m64CastQRUI(uqr); - if (signQuot < 0) - { - qr.quot = -qr.quot; - if (qr.rem != 0) - { - qr.quot--; - qr.rem = den - qr.rem; - } - } - - if (signRem < 0) - qr.rem = -qr.rem; - - return qr; -} - - -/************************************************************************** - m 6 4 I s N e g a t i v e -** Returns TRUE if the specified INT64 has its sign bit set. -**************************************************************************/ -int m64IsNegative(INT64 x) -{ - return (x.hi < 0); -} - - -/************************************************************************** - m 6 4 M a c -** Mixed precision multiply and accumulate primitive for number building. -** Multiplies UNS64 u by UNS32 mul and adds UNS32 add. Mul is typically -** the numeric base, and add represents a digit to be appended to the -** growing number. -** Returns the result of the operation -**************************************************************************/ -UNS64 m64Mac(UNS64 u, UNS32 mul, UNS32 add) -{ - UNS64 resultLo = ficlLongMul(u.lo, mul); - UNS64 resultHi = ficlLongMul(u.hi, mul); - resultLo.hi += resultHi.lo; - resultHi.lo = resultLo.lo + add; - - if (resultHi.lo < resultLo.lo) - resultLo.hi++; - - resultLo.lo = resultHi.lo; - - return resultLo; -} - - -/************************************************************************** - m 6 4 M u l I -** Multiplies a pair of INT32s and returns an INT64 result. -**************************************************************************/ -INT64 m64MulI(INT32 x, INT32 y) -{ - UNS64 prod; - int sign = 1; - - if (x < 0) - { - sign = -sign; - x = -x; - } - - if (y < 0) - { - sign = -sign; - y = -y; - } - - prod = ficlLongMul(x, y); - if (sign > 0) - return m64CastUI(prod); - else - return m64Negate(m64CastUI(prod)); -} - - -/************************************************************************** - m 6 4 N e g a t e -** Negates an INT64 by complementing and incrementing. -**************************************************************************/ -INT64 m64Negate(INT64 x) -{ - x.hi = ~x.hi; - x.lo = ~x.lo; - x.lo ++; - if (x.lo == 0) - x.hi++; - - return x; -} - - -/************************************************************************** - m 6 4 P u s h -** Push an INT64 onto the specified stack in the order required -** by ANS Forth (most significant cell on top) -** These should probably be macros... -**************************************************************************/ -void i64Push(FICL_STACK *pStack, INT64 i64) -{ - stackPushINT32(pStack, i64.lo); - stackPushINT32(pStack, i64.hi); - return; -} - -void u64Push(FICL_STACK *pStack, UNS64 u64) -{ - stackPushINT32(pStack, u64.lo); - stackPushINT32(pStack, u64.hi); - return; -} - - -/************************************************************************** - m 6 4 P o p -** Pops an INT64 off the stack in the order required by ANS Forth -** (most significant cell on top) -** These should probably be macros... -**************************************************************************/ -INT64 i64Pop(FICL_STACK *pStack) -{ - INT64 ret; - ret.hi = stackPopINT32(pStack); - ret.lo = stackPopINT32(pStack); - return ret; -} - -UNS64 u64Pop(FICL_STACK *pStack) -{ - UNS64 ret; - ret.hi = stackPopINT32(pStack); - ret.lo = stackPopINT32(pStack); - return ret; -} - - -/************************************************************************** - m 6 4 S y m m e t r i c D i v -** Divide an INT64 by an INT32 and return an INT32 quotient and an INT32 -** remainder. The absolute values of quotient and remainder are not -** affected by the signs of the numerator and denominator (the operation -** is symmetric on the number line) -**************************************************************************/ -INTQR m64SymmetricDivI(INT64 num, INT32 den) -{ - INTQR qr; - UNSQR uqr; - int signRem = 1; - int signQuot = 1; - - if (m64IsNegative(num)) - { - num = m64Negate(num); - signRem = -signRem; - signQuot = -signQuot; - } - - if (den < 0) - { - den = -den; - signQuot = -signQuot; - } - - uqr = ficlLongDiv(m64CastIU(num), (UNS32)den); - qr = m64CastQRUI(uqr); - if (signRem < 0) - qr.rem = -qr.rem; - - if (signQuot < 0) - qr.quot = -qr.quot; - - return qr; -} - - -/************************************************************************** - m 6 4 U M o d -** Divides an UNS64 by base (an UNS16) and returns an UNS16 remainder. -** Writes the quotient back to the original UNS64 as a side effect. -** This operation is typically used to convert an UNS64 to a text string -** in any base. See words.c:numberSignS, for example. -** Mechanics: performs 4 ficlLongDivs, each of which produces 16 bits -** of the quotient. C does not provide a way to divide an UNS32 by an -** UNS16 and get an UNS32 quotient (ldiv is closest, but it's signed, -** unfortunately), so I've used ficlLongDiv. -**************************************************************************/ -UNS16 m64UMod(UNS64 *pUD, UNS16 base) -{ - UNS64 ud; - UNSQR qr; - UNS64 result; - - result.hi = result.lo = 0; - - ud.hi = 0; - ud.lo = pUD->hi >> 16; - qr = ficlLongDiv(ud, (UNS32)base); - result.hi = qr.quot << 16; - - ud.lo = (qr.rem << 16) | (pUD->hi & 0x0000ffff); - qr = ficlLongDiv(ud, (UNS32)base); - result.hi |= qr.quot & 0x0000ffff; - - ud.lo = (qr.rem << 16) | (pUD->lo >> 16); - qr = ficlLongDiv(ud, (UNS32)base); - result.lo = qr.quot << 16; - - ud.lo = (qr.rem << 16) | (pUD->lo & 0x0000ffff); - qr = ficlLongDiv(ud, (UNS32)base); - result.lo |= qr.quot & 0x0000ffff; - - *pUD = result; - - return (UNS16)(qr.rem); -} - - diff --git a/sys/boot/ficl/math64.h b/sys/boot/ficl/math64.h deleted file mode 100644 index 2b7df37006bd..000000000000 --- a/sys/boot/ficl/math64.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************* -** m a t h 6 4 . h -** Forth Inspired Command Language - 64 bit math support routines -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 25 January 1998 -** -*******************************************************************/ -/* -** N O T I C E -- DISCLAIMER OF WARRANTY -** -** Ficl is freeware. Use it in any way that you like, with -** the understanding that the code is not supported. -** -** Any third party may reproduce, distribute, or modify the ficl -** software code or any derivative works thereof without any -** compensation or license, provided that the author information -** and this disclaimer text are retained in the source code files. -** The ficl software code is provided on an "as is" basis without -** warranty of any kind, including, without limitation, the implied -** warranties of merchantability and fitness for a particular purpose -** and their equivalents under the laws of any jurisdiction. -** -** I am interested in hearing from anyone who uses ficl. If you have -** a problem, a success story, a defect, an enhancement request, or -** if you would like to contribute to the ficl release (yay!), please -** send me email at the address above. -*/ - -#if !defined (__MATH64_H__) -#define __MATH64_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -INT64 m64Abs(INT64 x); -int m64IsNegative(INT64 x); -UNS64 m64Mac(UNS64 u, UNS32 mul, UNS32 add); -INT64 m64MulI(INT32 x, INT32 y); -INT64 m64Negate(INT64 x); -INTQR m64FlooredDivI(INT64 num, INT32 den); -void i64Push(FICL_STACK *pStack, INT64 i64); -INT64 i64Pop(FICL_STACK *pStack); -void u64Push(FICL_STACK *pStack, UNS64 u64); -UNS64 u64Pop(FICL_STACK *pStack); -INTQR m64SymmetricDivI(INT64 num, INT32 den); -UNS16 m64UMod(UNS64 *pUD, UNS16 base); - -#define i64Extend(i64) (i64).hi = ((i64).lo < 0) ? -1L : 0 -#define m64CastIU(i64) (*(UNS64 *)(&(i64))) -#define m64CastUI(u64) (*(INT64 *)(&(u64))) -#define m64CastQRIU(iqr) (*(UNSQR *)(&(iqr))) -#define m64CastQRUI(uqr) (*(INTQR *)(&(uqr))) - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/sys/boot/ficl/softwords/classes.fr b/sys/boot/ficl/softwords/classes.fr deleted file mode 100644 index 75dc35ae0da2..000000000000 --- a/sys/boot/ficl/softwords/classes.fr +++ /dev/null @@ -1,140 +0,0 @@ -\ ** ficl/softwords/classes.fr -\ ** F I C L 2 . 0 C L A S S E S -\ john sadler 1 sep 98 -\ Needs oop.fr - -.( loading ficl utility classes ) cr -also oop definitions - -\ REF subclass holds a pointer to an object. It's -\ mainly for aggregation to help in making data structures. -\ -object subclass c-ref - cell: .class - cell: .instance - - : get ( inst class -- refinst refclass ) - drop 2@ ; - : set ( refinst refclass inst class -- ) - drop 2! ; -end-class - -object subclass c-byte - char: .payload - - : get drop c@ ; - : set drop c! ; -end-class - -object subclass c-2byte - 2 chars: .payload - - : get drop w@ ; - : set drop w! ; -end-class - -object subclass c-4byte - cell: .payload - - : get drop @ ; - : set drop ! ; -end-class - - -\ ** C - P T R -\ Base class for pointers to scalars (not objects). -\ Note: use c-ref to make references to objects. C-ptr -\ subclasses refer to untyped quantities of various sizes. - -\ Derived classes must specify the size of the thing -\ they point to, and supply get and set methods. - -\ All derived classes must define the @size method: -\ @size ( inst class -- addr-units ) -\ Returns the size in address units of the thing the pointer -\ refers to. -object subclass c-ptr - c-4byte obj: .addr - - \ get the value of the pointer - : get-ptr ( inst class -- addr ) - c-ptr => .addr - c-4byte => get - ; - - \ set the pointer to address supplied - : set-ptr ( addr inst class -- ) - c-ptr => .addr - c-4byte => set - ; - - \ increment the pointer in place - : inc-ptr ( inst class -- ) - 2dup 2dup ( i c i c i c ) - c-ptr => get-ptr -rot ( i c addr i c ) - --> @size + -rot ( addr' i c ) - c-ptr => set-ptr - ; - - \ decrement the pointer in place - : dec-ptr ( inst class -- ) - 2dup 2dup ( i c i c i c ) - c-ptr => get-ptr -rot ( i c addr i c ) - --> @size - -rot ( addr' i c ) - c-ptr => set-ptr - ; - - \ index the pointer in place - : index-ptr ( index inst class -- ) - locals| class inst index | - inst class c-ptr => get-ptr ( addr ) - inst class --> @size index * + ( addr' ) - inst class c-ptr => set-ptr - ; - -end-class - - -\ ** C - C E L L P T R -\ Models a pointer to cell (a 32 bit scalar). -c-ptr subclass c-cellPtr - : @size 2drop 4 ; - \ fetch and store through the pointer - : get ( inst class -- cell ) - c-ptr => get-ptr @ - ; - : set ( value inst class -- ) - c-ptr => get-ptr ! - ; -end-class - - -\ ** C - 2 B Y T E P T R -\ Models a pointer to a 16 bit scalar -c-ptr subclass c-2bytePtr - : @size 2drop 2 ; - \ fetch and store through the pointer - : get ( inst class -- value ) - c-ptr => get-ptr w@ - ; - : set ( value inst class -- ) - c-ptr => get-ptr w! - ; -end-class - - -\ ** C - B Y T E P T R -\ Models a pointer to an 8 bit scalar -c-ptr subclass c-bytePtr - : @size 2drop 1 ; - \ fetch and store through the pointer - : get ( inst class -- value ) - c-ptr => get-ptr c@ - ; - : set ( value inst class -- ) - c-ptr => get-ptr c! - ; -end-class - - -previous definitions diff --git a/sys/boot/ficl/softwords/jhlocal.fr b/sys/boot/ficl/softwords/jhlocal.fr deleted file mode 100644 index 034ada519711..000000000000 --- a/sys/boot/ficl/softwords/jhlocal.fr +++ /dev/null @@ -1,77 +0,0 @@ -\ #if FICL_WANT_LOCALS -\ ** ficl/softwords/jhlocal.fr -\ ** stack comment style local syntax... -\ { a b c | cleared -- d e } -\ variables before the "|" are initialized in reverse order -\ from the stack. Those after the "|" are zero initialized. -\ Anything between "--" and "}" is treated as comment -\ Uses locals... -\ locstate: 0 = looking for | or -- or }} -\ 1 = found | -\ 2 = found -- -hide -0 constant zero - -: ?-- ( c-addr u -- c-addr u flag ) - 2dup s" --" compare 0= ; -: ?} ( c-addr u -- c-addr u flag ) - 2dup s" }" compare 0= ; -: ?| ( c-addr u -- c-addr u flag ) - 2dup s" |" compare 0= ; - -: ?delim ( c-addr u -- state | c-addr u 0 ) - ?| if - 2drop 1 - else - ?-- if - 2drop 2 - else - ?} if 2drop 3 else 0 endif - endif - endif -; - -set-current - -: { - 0 dup locals| locstate | - - \ stack locals until we hit a delimiter - begin - parse-word \ ( nLocals c-addr u ) - ?delim dup to locstate - 0= while - rot 1+ \ ( c-addr u ... c-addr u nLocals ) - repeat - - \ now unstack the locals - 0 do (local) loop \ ( ) - - \ zero locals until -- or } - locstate 1 = if - begin - parse-word - ?delim dup to locstate - 0= while - postpone zero (local) - repeat - endif - - 0 0 (local) - - \ toss words until } - locstate 2 = if - begin - parse-word - ?delim dup to locstate - 0= while - 2drop - repeat - endif - - locstate 3 <> abort" syntax error in { } local line" -; immediate compile-only - -previous -\ #endif - diff --git a/sys/boot/ficl/softwords/marker.fr b/sys/boot/ficl/softwords/marker.fr deleted file mode 100644 index c80c2cf3f2ce..000000000000 --- a/sys/boot/ficl/softwords/marker.fr +++ /dev/null @@ -1,25 +0,0 @@ -\ ** ficl/softwords/marker.fr -\ ** Ficl implementation of CORE EXT MARKER -\ John Sadler, 4 Oct 98 -\ Requires ficl 2.02 FORGET-WID !! - -: marker ( "name" -- ) - create - get-current , - get-order dup , - 0 ?do , loop - does> - 0 set-order \ clear search order - dup body> >name drop - here - allot \ reset HERE to my xt-addr - dup @ ( pfa current-wid ) - dup set-current forget-wid ( pfa ) - cell+ dup @ swap ( count count-addr ) - over cells + swap ( last-wid-addr count ) - 0 ?do - dup @ dup ( wid-addr wid wid ) - >search forget-wid ( wid-addr ) - cell- - loop - drop -; diff --git a/sys/boot/ficl/softwords/oo.fr b/sys/boot/ficl/softwords/oo.fr deleted file mode 100644 index cd16c77b28b0..000000000000 --- a/sys/boot/ficl/softwords/oo.fr +++ /dev/null @@ -1,464 +0,0 @@ -\ ** ficl/softwords/oo.fr -\ ** F I C L O - O E X T E N S I O N S -\ ** john sadler aug 1998 - -.( loading ficl O-O extensions ) cr -7 ficl-vocabulary oop -also oop definitions - -\ Design goals: -\ 0. Traditional OOP: late binding by default for safety. -\ Early binding if you ask for it. -\ 1. Single inheritance -\ 2. Object aggregation (has-a relationship) -\ 3. Support objects in the dictionary and as proxies for -\ existing structures (by reference): -\ *** A ficl object can wrap a C struct *** -\ 4. Separate name-spaces for methods - methods are -\ only visible in the context of a class / object -\ 5. Methods can be overridden, and subclasses can add methods. -\ No limit on number of methods. - -\ General info: -\ Classes are objects, too: all classes are instances of METACLASS -\ All classes are derived (by convention) from OBJECT. This -\ base class provides a default initializer and superclass -\ access method - -\ A ficl object binds instance storage (payload) to a class. -\ object ( -- instance class ) -\ All objects push their payload address and class address when -\ executed. All objects have this footprint: -\ cell 0: first payload cell - -\ A ficl class consists of a parent class pointer, a wordlist -\ ID for the methods of the class, and a size for the payload -\ of objects created by the class. A class is an object. -\ The NEW method creates and initializes an instance of a class. -\ Classes have this footprint: -\ cell 0: parent class address -\ cell 1: wordlist ID -\ cell 2: size of instance's payload - -\ Methods expect an object couple ( instance class ) -\ on the stack. -\ Overridden methods must maintain the same stack signature as -\ their predecessors. Ficl has no way of enforcing this, though. - -user current-class -0 current-class ! - -\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ -\ ** L A T E B I N D I N G -\ Compile the method name, and code to find and -\ execute it at run-time... -\ parse-method compiles the method name so that it pushes -\ the string base address and count at run-time. -\ -: parse-method \ name run: ( -- c-addr u ) - parse-word - postpone sliteral -; compile-only - -: lookup-method ( class c-addr u -- class xt ) - 2dup - local u - local c-addr - end-locals - 2 pick cell+ @ ( -- class c-addr u wid ) - search-wordlist ( -- class 0 | xt 1 | xt -1 ) - 0= if - c-addr u type ." not found in " - body> >name type - cr abort - endif -; - -: exec-method ( instance class c-addr u -- <method-signature> ) - lookup-method execute -; - -: find-method-xt \ name ( class -- class xt ) - parse-word lookup-method -; - - -\ Method lookup operator takes a class-addr and instance-addr -\ and executes the method from the class's wordlist if -\ interpreting. If compiling, bind late. -\ -: --> ( instance class -- ??? ) - state @ 0= if - find-method-xt execute - else - parse-method postpone exec-method - endif -; immediate - - -\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ -\ ** E A R L Y B I N D I N G -\ Early binding operator compiles code to execute a method -\ given its class at compile time. Classes are immediate, -\ so they leave their cell-pair on the stack when compiling. -\ Example: -\ : get-wid metaclass => .wid @ ; -\ Usage -\ my-class get-wid ( -- wid-of-my-class ) -\ -: => \ c:( class meta -- ) run: ( -- ??? ) invokes compiled method - drop find-method-xt compile, drop -; immediate compile-only - - -\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ -\ ** I N S T A N C E V A R I A B L E S -\ Instance variables (IV) are represented by words in the class's -\ private wordlist. Each IV word contains the offset -\ of the IV it represents, and runs code to add that offset -\ to the base address of an instance when executed. -\ The metaclass SUB method, defined below, leaves the address -\ of the new class's offset field and its initial size on the -\ stack for these words to update. When a class definition is -\ complete, END-CLASS saves the final size in the class's size -\ field, and restores the search order and compile wordlist to -\ prior state. Note that these words are hidden in their own -\ wordlist to prevent accidental use outside a SUB END-CLASS pair. -\ -wordlist -dup constant instance-vars -dup >search ficl-set-current -: do-instance-var - does> ( instance class addr[offset] -- addr[field] ) - nip @ + -; - -: addr-units: ( offset size "name" -- offset' ) - create over , + - do-instance-var -; - -: chars: \ ( offset nCells "name" -- offset' ) Create n char member. - chars addr-units: ; - -: char: \ ( offset nCells "name" -- offset' ) Create 1 char member. - 1 chars: ; - -: cells: ( offset nCells "name" -- offset' ) - cells >r aligned r> addr-units: -; - -: cell: ( offset nCells "name" -- offset' ) - 1 cells: ; - -\ Aggregate an object into the class... -\ Needs the class of the instance to create -\ Example: object obj: m_obj -\ -: do-aggregate - does> ( instance class pfa -- a-instance a-class ) - 2@ ( inst class a-class a-offset ) - 2swap drop ( a-class a-offset inst ) - + swap ( a-inst a-class ) -; - -: obj: ( offset class meta "name" -- offset' ) - locals| meta class offset | - create offset , class , - class meta --> get-size offset + - do-aggregate -; - -\ Aggregate an array of objects into a class -\ Usage example: -\ 3 my-class array: my-array -\ Makes an instance variable array of 3 instances of my-class -\ named my-array. -\ -: array: ( offset n class meta "name" -- offset' ) - locals| meta class nobjs offset | - create offset , class , - class meta --> get-size nobjs * offset + - do-aggregate -; - -\ Aggregate a pointer to an object: REF is a member variable -\ whose class is set at compile time. This is useful for wrapping -\ data structures in C, where there is only a pointer and the type -\ it refers to is known. If you want polymorphism, see c_ref -\ in classes.fr. REF is only useful for pre-initialized structures, -\ since there's no supported way to set one. -: ref: ( offset class meta "name" -- offset' ) - locals| meta class offset | - create offset , class , - offset cell+ - does> ( inst class pfa -- ptr-inst ptr-class ) - 2@ ( inst class ptr-class ptr-offset ) - 2swap drop + @ swap -; - -\ END-CLASS terminates construction of a class by storing -\ the size of its instance variables in the class's size field -\ ( -- old-wid addr[size] 0 ) -\ -: end-class ( old-wid addr[size] size -- ) - swap ! set-current - search> drop \ pop struct builder wordlist -; - -set-current previous -\ E N D I N S T A N C E V A R I A B L E S - - -\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ -\ D O - D O - I N S T A N C E -\ Makes a class method that contains the code for an -\ instance of the class. This word gets compiled into -\ the wordlist of every class by the SUB method. -\ PRECONDITION: current-class contains the class address -\ -: do-do-instance ( -- ) - s" : .do-instance does> [ current-class @ ] literal ;" - evaluate -; - -\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ -\ ** M E T A C L A S S -\ Every class is an instance of metaclass. This lets -\ classes have methods that are different from those -\ of their instances. -\ Classes are IMMEDIATE to make early binding simpler -\ See above... -\ -:noname - wordlist - create immediate - 0 , \ NULL parent class - dup , \ wid - 3 cells , \ instance size - ficl-set-current - does> dup -; execute metaclass - -metaclass drop current-class ! -do-do-instance - -\ -\ C L A S S M E T H O D S -\ -instance-vars >search - -create .super ( class metaclass -- parent-class ) - 0 cells , do-instance-var - -create .wid ( class metaclass -- wid ) \ return wid of class - 1 cells , do-instance-var - -create .size ( class metaclass -- size ) \ return class's payload size - 2 cells , do-instance-var - -previous - -: get-size metaclass => .size @ ; -: get-wid metaclass => .wid @ ; -: get-super metaclass => .super @ ; - -\ create an uninitialized instance of a class, leaving -\ the address of the new instance and its class -\ -: instance ( class metaclass "name" -- instance class ) - locals| meta parent | - create - here parent --> .do-instance \ ( inst class ) - parent meta metaclass => get-size - allot \ allocate payload space -; - -\ create an uninitialized array -: array ( n class metaclass "name" -- n instance class ) - locals| meta parent nobj | - create nobj - here parent --> .do-instance \ ( nobj inst class ) - parent meta metaclass => get-size - nobj * allot \ allocate payload space -; - -\ create an initialized instance -\ -: new \ ( class metaclass "name" -- ) - metaclass => instance --> init -; - -\ create an initialized array of instances -: new-array ( n class metaclass "name" -- ) - metaclass => array - --> array-init -; - -\ create a proxy object with initialized payload address given -: ref ( instance-addr class metaclass "name" -- ) - drop create , , - does> 2@ -; - -\ create a subclass -: sub ( class metaclass "name" -- old-wid addr[size] size ) - wordlist - locals| wid meta parent | - parent meta metaclass => get-wid - wid wid-set-super - create immediate - here current-class ! \ prep for do-do-instance - parent , \ save parent class - wid , \ save wid - here parent meta --> get-size dup , ( addr[size] size ) - metaclass => .do-instance - wid ficl-set-current -rot - do-do-instance - instance-vars >search \ push struct builder wordlist -; - -\ OFFSET-OF returns the offset of an instance variable -\ from the instance base address. If the next token is not -\ the name of in instance variable method, you get garbage -\ results -- there is no way at present to check for this error. -: offset-of ( class metaclass "name" -- offset ) - drop find-method-xt nip >body @ ; - -\ ID returns the string name cell-pair of its class -: id ( class metaclass -- c-addr u ) - drop body> >name ; - -\ list methods of the class -: methods \ ( class meta -- ) - locals| meta class | - begin - class body> >name type ." methods:" cr - class meta --> get-wid >search words cr previous - class meta metaclass => get-super - dup to class - 0= until cr -; - -\ list class's ancestors -: pedigree ( class meta -- ) - locals| meta class | - begin - class body> >name type space - class meta metaclass => get-super - dup to class - 0= until cr -; - -\ decompile a method -: see ( class meta -- ) - metaclass => get-wid >search see previous ; - -set-current -\ E N D M E T A C L A S S - -\ META is a nickname for the address of METACLASS... -metaclass drop -constant meta - -\ SUBCLASS is a nickname for a class's SUB method... -\ Subclass compilation ends when you invoke end-class -\ This method is late bound for safety... -: subclass --> sub ; - - -\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ -\ ** O B J E C T -\ Root of all classes -:noname - wordlist - create immediate - 0 , \ NULL parent class - dup , \ wid - 0 , \ instance size - ficl-set-current - does> meta -; execute object - -object drop current-class ! -do-do-instance - -\ O B J E C T M E T H O D S -\ Convert instance cell-pair to class cell-pair -\ Useful for binding class methods from an instance -: class ( instance class -- class metaclass ) - nip meta ; - -\ default INIT method zero fills an instance -: init ( instance class -- ) - meta - metaclass => get-size ( inst size ) - erase ; - -\ Apply INIT to an array of NOBJ objects... -\ -: array-init ( nobj inst class -- ) - 0 dup locals| &init &next class inst | - \ - \ bind methods outside the loop to save time - \ - class s" init" lookup-method to &init - s" next" lookup-method to &next - drop - 0 ?do - inst class 2dup - &init execute - &next execute drop to inst - loop -; - -\ Instance aliases for common class methods -\ Upcast to parent class -: super ( instance class -- instance parent-class ) - meta metaclass => get-super ; - -: pedigree ( instance class -- ) - object => class - metaclass => pedigree ; - -: size ( instance class -- sizeof-instance ) - object => class - metaclass => get-size ; - -: methods ( instance class -- ) - object => class - metaclass => methods ; - -\ Array indexing methods... -\ Usage examples: -\ 10 object-array --> index -\ obj --> next -\ -: index ( n instance class -- instance[n] class ) - locals| class inst | - inst class - object => class - metaclass => get-size * ( n*size ) - inst + class ; - -: next ( instance[n] class -- instance[n+1] class ) - locals| class inst | - inst class - object => class - metaclass => get-size - inst + - class ; - -: prev ( instance[n] class -- instance[n-1] class ) - locals| class inst | - inst class - object => class - metaclass => get-size - inst swap - - class ; - -set-current -\ E N D O B J E C T - - -previous definitions diff --git a/sys/boot/ficl/softwords/softcore.awk b/sys/boot/ficl/softwords/softcore.awk deleted file mode 100644 index b182b9950897..000000000000 --- a/sys/boot/ficl/softwords/softcore.awk +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/awk -f -# Convert forth source files to a giant C string -# Joe Abley <jabley@patho.gen.nz>, 12 January 1999 - -BEGIN \ -{ - printf "/***************************************************************\n"; - printf "** s o f t c o r e . c\n"; - printf "** Forth Inspired Command Language -\n"; - printf "** Words from CORE set written in FICL\n"; - printf "** Author: John Sadler (john_sadler@alum.mit.edu)\n"; - printf "** Created: 27 December 1997\n"; - printf "** Last update: %s\n", strftime(); - printf "***************************************************************/\n"; - printf "\n/*\n"; - printf "** This file contains definitions that are compiled into the\n"; - printf "** system dictionary by the first virtual machine to be created.\n"; - printf "** Created automagically by ficl/softwords/softcore.awk\n"; - printf "*/\n"; - printf "\n#include \"ficl.h\"\n"; - printf "\nstatic char softWords[] =\n"; - - commenting = 0; -} - -# some general early substitutions -{ - gsub("\t", " "); # replace each tab with 4 spaces - gsub("\"", "\\\""); # escape quotes - gsub("\\\\[[:space:]]+$", ""); # toss empty comments -} - -# strip out empty lines -/^ *$/ \ -{ - next; -} - -# emit / ** lines as multi-line C comments -/^\\[[:space:]]\*\*/ && (commenting == 0) \ -{ - sub("^\\\\[[:space:]]", ""); - printf "/*\n%s\n", $0; - commenting = 1; - next; -} - -/^\\[[:space:]]\*\*/ \ -{ - sub("^\\\\[[:space:]]", ""); - printf "%s\n", $0; - next; -} - -# function to close a comment, used later -function end_comments() -{ - commenting = 0; - printf "*/\n"; -} - -# pass commented preprocessor directives -/^\\[[:space:]]#/ \ -{ - if (commenting) end_comments(); - sub("^\\\\[[:space:]]", ""); - printf "%s\n", $0; - next; -} - -# toss all other full-line comments -/^\\/ \ -{ - if (commenting) end_comments(); - next; -} - -# emit all other lines as quoted string fragments -{ - if (commenting) end_comments(); - - sub("\\\\[[:space:]]+.*$", ""); # lop off trailing \ comments - sub("[[:space:]]+$", ""); # remove trailing spaces - printf " \"%s \\n\"\n", $0; - next; -} - -END \ -{ - if (commenting) end_comments(); - printf " \"quit \";\n"; - printf "\n\nvoid ficlCompileSoftCore(FICL_VM *pVM)\n"; - printf "{\n"; - printf " assert(ficlExec(pVM, softWords) != VM_ERREXIT);\n"; - printf "}\n"; -} diff --git a/sys/boot/ficl/softwords/softcore.fr b/sys/boot/ficl/softwords/softcore.fr deleted file mode 100644 index bcc2696b6efd..000000000000 --- a/sys/boot/ficl/softwords/softcore.fr +++ /dev/null @@ -1,125 +0,0 @@ -\ ** ficl/softwords/softcore.fr -\ ** FICL soft extensions -\ ** John Sadler (john_sadler@alum.mit.edu) -\ ** September, 1998 - -\ ** Ficl USER variables -\ ** See words.c for primitive def'n of USER -\ #if FICL_WANT_USER - -variable nUser 0 nUser ! -: user \ name ( -- ) - nUser dup @ user 1 swap +! ; - -\ #endif - -\ ** ficl extras -\ EMPTY cleans the parameter stack -: empty ( xn..x1 -- ) depth 0 ?do drop loop ; -\ CELL- undoes CELL+ -: cell- ( addr -- addr ) [ 1 cells ] literal - ; -: -rot ( a b c -- c a b ) 2 -roll ; - -\ ** CORE -: abs ( x -- x ) - dup 0< if negate endif ; -decimal 32 constant bl - -: space ( -- ) bl emit ; - -: spaces ( n -- ) 0 ?do space loop ; - -: abort" - postpone if - postpone ." - postpone cr - postpone abort - postpone endif -; immediate - - -\ ** CORE EXT -0 constant false --1 constant true -: <> = invert ; -: 0<> 0= invert ; -: compile, , ; -: erase ( addr u -- ) 0 fill ; -: nip ( y x -- x ) swap drop ; -: tuck ( y x -- x y x) swap over ; - -\ ** LOCAL EXT word set -\ #if FICL_WANT_LOCALS -: locals| ( name...name | -- ) - begin - bl word count - dup 0= abort" where's the delimiter??" - over c@ - [char] | - over 1- or - while - (local) - repeat 2drop 0 0 (local) -; immediate - -: local ( name -- ) bl word count (local) ; immediate - -: end-locals ( -- ) 0 0 (local) ; immediate - -\ #endif - -\ ** TOOLS word set... -: ? ( addr -- ) @ . ; -: dump ( addr u -- ) - 0 ?do - dup c@ . 1+ - i 7 and 7 = if cr endif - loop drop -; - -\ ** SEARCH+EXT words and ficl helpers -\ -: wordlist ( -- ) - 1 ficl-wordlist ; - -\ DO_VOCABULARY handles the DOES> part of a VOCABULARY -\ When executed, new voc replaces top of search stack -: do-vocabulary ( -- ) - does> @ search> drop >search ; - -: vocabulary ( name -- ) - wordlist create , do-vocabulary ; - -: ficl-vocabulary ( nBuckets name -- ) - ficl-wordlist create , do-vocabulary ; - -\ ALSO dups the search stack... -: also ( -- ) - search> dup >search >search ; - -\ FORTH drops the top of the search stack and pushes FORTH-WORDLIST -: forth ( -- ) - search> drop - forth-wordlist >search ; - -\ ONLY sets the search order to a default state -: only ( -- ) - -1 set-order ; - -\ ORDER displays the compile wid and the search order list -: order ( -- ) - ." Search: " - get-order 0 ?do x. loop cr - ." Compile: " get-current x. cr ; - -\ PREVIOUS drops the search order stack -: previous ( -- ) search> drop ; - -\ FICL-SET-CURRENT sets the compile wordlist and pushes the previous value -: ficl-set-current ( wid -- old-wid ) - get-current swap set-current ; - -wordlist constant hidden -: hide hidden dup >search ficl-set-current ; - -\ ** E N D S O F T C O R E . F R - diff --git a/sys/boot/ficl/stack.c b/sys/boot/ficl/stack.c deleted file mode 100644 index aee9f8f5ff56..000000000000 --- a/sys/boot/ficl/stack.c +++ /dev/null @@ -1,305 +0,0 @@ -/******************************************************************* -** s t a c k . c -** Forth Inspired Command Language -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 16 Oct 1997 -** -*******************************************************************/ - -#ifdef TESTMAIN -#include <stdlib.h> -#else -#include <stand.h> -#endif -#include "ficl.h" - -#define STKDEPTH(s) ((s)->sp - (s)->base) - -/* -** N O T E: Stack convention: -** -** sp points to the first available cell -** push: store value at sp, increment sp -** pop: decrement sp, fetch value at sp -** Stack grows from low to high memory -*/ - -/******************************************************************* - v m C h e c k S t a c k -** Check the parameter stack for underflow or overflow. -** nCells controls the type of check: if nCells is zero, -** the function checks the stack state for underflow and overflow. -** If nCells > 0, checks to see that the stack has room to push -** that many cells. If less than zero, checks to see that the -** stack has room to pop that many cells. If any test fails, -** the function throws (via vmThrow) a VM_ERREXIT exception. -*******************************************************************/ -void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells) -{ - FICL_STACK *pStack = pVM->pStack; - int nFree = pStack->base + pStack->nCells - pStack->sp; - - if (popCells > STKDEPTH(pStack)) - { - vmThrowErr(pVM, "Error: stack underflow"); - } - - if (nFree < pushCells - popCells) - { - vmThrowErr(pVM, "Error: stack overflow"); - } - - return; -} - -/******************************************************************* - s t a c k C r e a t e -** -*******************************************************************/ - -FICL_STACK *stackCreate(unsigned nCells) -{ - size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL); - FICL_STACK *pStack = ficlMalloc(size); - -#if FICL_ROBUST - assert (nCells != 0); - assert (pStack != NULL); -#endif - - pStack->nCells = nCells; - pStack->sp = pStack->base; - pStack->pFrame = NULL; - return pStack; -} - - -/******************************************************************* - s t a c k D e l e t e -** -*******************************************************************/ - -void stackDelete(FICL_STACK *pStack) -{ - if (pStack) - ficlFree(pStack); - return; -} - - -/******************************************************************* - s t a c k D e p t h -** -*******************************************************************/ - -int stackDepth(FICL_STACK *pStack) -{ - return STKDEPTH(pStack); -} - -/******************************************************************* - s t a c k D r o p -** -*******************************************************************/ - -void stackDrop(FICL_STACK *pStack, int n) -{ -#if FICL_ROBUST - assert(n > 0); -#endif - pStack->sp -= n; - return; -} - - -/******************************************************************* - s t a c k F e t c h -** -*******************************************************************/ - -CELL stackFetch(FICL_STACK *pStack, int n) -{ - return pStack->sp[-n-1]; -} - -void stackStore(FICL_STACK *pStack, int n, CELL c) -{ - pStack->sp[-n-1] = c; - return; -} - - -/******************************************************************* - s t a c k G e t T o p -** -*******************************************************************/ - -CELL stackGetTop(FICL_STACK *pStack) -{ - return pStack->sp[-1]; -} - - -/******************************************************************* - s t a c k L i n k -** Link a frame using the stack's frame pointer. Allot space for -** nCells cells in the frame -** 1) Push pFrame -** 2) pFrame = sp -** 3) sp += nCells -*******************************************************************/ - -void stackLink(FICL_STACK *pStack, int nCells) -{ - stackPushPtr(pStack, pStack->pFrame); - pStack->pFrame = pStack->sp; - pStack->sp += nCells; - return; -} - - -/******************************************************************* - s t a c k U n l i n k -** Unink a stack frame previously created by stackLink -** 1) sp = pFrame -** 2) pFrame = pop() -*******************************************************************/ - -void stackUnlink(FICL_STACK *pStack) -{ - pStack->sp = pStack->pFrame; - pStack->pFrame = stackPopPtr(pStack); - return; -} - - -/******************************************************************* - s t a c k P i c k -** -*******************************************************************/ - -void stackPick(FICL_STACK *pStack, int n) -{ - stackPush(pStack, stackFetch(pStack, n)); - return; -} - - -/******************************************************************* - s t a c k P o p -** -*******************************************************************/ - -CELL stackPop(FICL_STACK *pStack) -{ - return *--pStack->sp; -} - -void *stackPopPtr(FICL_STACK *pStack) -{ - return (*--pStack->sp).p; -} - -UNS32 stackPopUNS32(FICL_STACK *pStack) -{ - return (*--pStack->sp).u; -} - -INT32 stackPopINT32(FICL_STACK *pStack) -{ - return (*--pStack->sp).i; -} - - -/******************************************************************* - s t a c k P u s h -** -*******************************************************************/ - -void stackPush(FICL_STACK *pStack, CELL c) -{ - *pStack->sp++ = c; -} - -void stackPushPtr(FICL_STACK *pStack, void *ptr) -{ - *pStack->sp++ = LVALUEtoCELL(ptr); -} - -void stackPushUNS32(FICL_STACK *pStack, UNS32 u) -{ - *pStack->sp++ = LVALUEtoCELL(u); -} - -void stackPushINT32(FICL_STACK *pStack, INT32 i) -{ - *pStack->sp++ = LVALUEtoCELL(i); -} - -/******************************************************************* - s t a c k R e s e t -** -*******************************************************************/ - -void stackReset(FICL_STACK *pStack) -{ - pStack->sp = pStack->base; - return; -} - - -/******************************************************************* - s t a c k R o l l -** Roll nth stack entry to the top (counting from zero), if n is -** >= 0. Drop other entries as needed to fill the hole. -** If n < 0, roll top-of-stack to nth entry, pushing others -** upward as needed to fill the hole. -*******************************************************************/ - -void stackRoll(FICL_STACK *pStack, int n) -{ - CELL c; - CELL *pCell; - - if (n == 0) - return; - else if (n > 0) - { - pCell = pStack->sp - n - 1; - c = *pCell; - - for (;n > 0; --n, pCell++) - { - *pCell = pCell[1]; - } - - *pCell = c; - } - else - { - pCell = pStack->sp - 1; - c = *pCell; - - for (; n < 0; ++n, pCell--) - { - *pCell = pCell[-1]; - } - - *pCell = c; - } - return; -} - - -/******************************************************************* - s t a c k S e t T o p -** -*******************************************************************/ - -void stackSetTop(FICL_STACK *pStack, CELL c) -{ - pStack->sp[-1] = c; - return; -} - - diff --git a/sys/boot/ficl/sysdep.c b/sys/boot/ficl/sysdep.c deleted file mode 100644 index 84a704dabdd8..000000000000 --- a/sys/boot/ficl/sysdep.c +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************* -** s y s d e p . c -** Forth Inspired Command Language -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 16 Oct 1997 -** Implementations of FICL external interface functions... -** -*******************************************************************/ - -#ifdef TESTMAIN -#include <stdio.h> -#include <stdlib.h> -#else -#include <stand.h> -#ifdef __i386__ -#include <machine/cpufunc.h> -#endif -#endif -#include "ficl.h" - -/* -******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith -*/ - -UNS64 ficlLongMul(UNS32 x, UNS32 y) -{ - UNS64 q; - u_int64_t qx; - - qx = (u_int64_t)x * (u_int64_t) y; - - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); - - return q; -} - -UNSQR ficlLongDiv(UNS64 q, UNS32 y) -{ - UNSQR result; - u_int64_t qx, qh; - - qh = q.hi; - qx = (qh << 32) | q.lo; - - result.quot = qx / y; - result.rem = qx % y; - - return result; -} - -void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) -{ - IGNORE(pVM); - - while(*msg != 0) - putchar(*(msg++)); - if (fNewline) - putchar('\n'); - - return; -} - -void *ficlMalloc (size_t size) -{ - return malloc(size); -} - -void ficlFree (void *p) -{ - free(p); -} - -#ifdef __i386__ -/* - * outb ( port# c -- ) - * Store a byte to I/O port number port# - */ -void -ficlOutb(FICL_VM *pVM) -{ - u_char c; - u_int32_t port; - - port=stackPopUNS32(pVM->pStack); - c=(u_char)stackPopINT32(pVM->pStack); - outb(port,c); -} - -/* - * inb ( port# -- c ) - * Fetch a byte from I/O port number port# - */ -void -ficlInb(FICL_VM *pVM) -{ - u_char c; - u_int32_t port; - - port=stackPopUNS32(pVM->pStack); - c=inb(port); - stackPushINT32(pVM->pStack,c); -} -#endif - -/* -** Stub function for dictionary access control - does nothing -** by default, user can redefine to guarantee exclusive dict -** access to a single thread for updates. All dict update code -** is guaranteed to be bracketed as follows: -** ficlLockDictionary(TRUE); -** <code that updates dictionary> -** ficlLockDictionary(FALSE); -** -** Returns zero if successful, nonzero if unable to acquire lock -** befor timeout (optional - could also block forever) -*/ -#if FICL_MULTITHREAD -int ficlLockDictionary(short fLock) -{ - IGNORE(fLock); - return 0; -} -#endif /* FICL_MULTITHREAD */ - - diff --git a/sys/boot/ficl/sysdep.h b/sys/boot/ficl/sysdep.h deleted file mode 100644 index 4095701cad2a..000000000000 --- a/sys/boot/ficl/sysdep.h +++ /dev/null @@ -1,251 +0,0 @@ -/******************************************************************* - s y s d e p . h -** Forth Inspired Command Language -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 16 Oct 1997 -** Ficl system dependent types and prototypes... -** -** Note: Ficl also depends on the use of "assert" when -** FICL_ROBUST is enabled. This may require some consideration -** in firmware systems since assert often -** assumes stderr/stdout. -** -*******************************************************************/ -/* -** N O T I C E -- DISCLAIMER OF WARRANTY -** -** Ficl is freeware. Use it in any way that you like, with -** the understanding that the code is not supported. -** -** Any third party may reproduce, distribute, or modify the ficl -** software code or any derivative works thereof without any -** compensation or license, provided that the author information -** and this disclaimer text are retained in the source code files. -** The ficl software code is provided on an "as is" basis without -** warranty of any kind, including, without limitation, the implied -** warranties of merchantability and fitness for a particular purpose -** and their equivalents under the laws of any jurisdiction. -** -** I am interested in hearing from anyone who uses ficl. If you have -** a problem, a success story, a defect, an enhancement request, or -** if you would like to contribute to the ficl release (yay!), please -** send me email at the address above. -*/ - -#if !defined (__SYSDEP_H__) -#define __SYSDEP_H__ - -#include <sys/types.h> - -#include <stddef.h> /* size_t, NULL */ -#include <setjmp.h> - -#include <assert.h> - -#if !defined IGNORE /* Macro to silence unused param warnings */ -#define IGNORE(x) &x -#endif - - -/* -** TRUE and FALSE for C boolean operations, and -** portable 32 bit types for CELLs -** -*/ -#if !defined TRUE -#define TRUE 1 -#endif -#if !defined FALSE -#define FALSE 0 -#endif - - -#if !defined INT32 -#define INT32 int32_t -#endif - -#if !defined UNS32 -#define UNS32 u_int32_t -#endif - -#if !defined UNS16 -#define UNS16 u_int16_t -#endif - -#if !defined UNS8 -#define UNS8 u_int8_t -#endif - -#if !defined NULL -#define NULL ((void *)0) -#endif - -typedef struct -{ - UNS32 hi; - UNS32 lo; -} UNS64; - -typedef struct -{ - UNS32 quot; - UNS32 rem; -} UNSQR; - -typedef struct -{ - INT32 hi; - INT32 lo; -} INT64; - -typedef struct -{ - INT32 quot; - INT32 rem; -} INTQR; - - -/* -** Build controls -** FICL_MULTITHREAD enables dictionary mutual exclusion -** wia the ficlLockDictionary system dependent function. -*/ -#if !defined FICL_MULTITHREAD -#define FICL_MULTITHREAD 0 -#endif - -/* -** FICL_ROBUST enables bounds checking of stacks and the dictionary. -** This will detect stack over and underflows and dictionary overflows. -** Any exceptional condition will result in an assertion failure. -** (As generated by the ANSI assert macro) -** FICL_ROBUST == 1 --> stack checking in the outer interpreter -** FICL_ROBUST == 2 also enables checking in many primitives -*/ - -#if !defined FICL_ROBUST -#define FICL_ROBUST 2 -#endif - -/* -** FICL_DEFAULT_STACK Specifies the default size (in CELLs) of -** a new virtual machine's stacks, unless overridden at -** create time. -*/ -#if !defined FICL_DEFAULT_STACK -#define FICL_DEFAULT_STACK 128 -#endif - -/* -** FICL_DEFAULT_DICT specifies the number of CELLs to allocate -** for the system dictionary by default. The value -** can be overridden at startup time as well. -** FICL_DEFAULT_ENV specifies the number of cells to allot -** for the environment-query dictionary. -*/ -#if !defined FICL_DEFAULT_DICT -#define FICL_DEFAULT_DICT 12288 -#endif - -#if !defined FICL_DEFAULT_ENV -#define FICL_DEFAULT_ENV 260 -#endif - -/* -** FICL_DEFAULT_VOCS specifies the maximum number of wordlists in -** the dictionary search order. See Forth DPANS sec 16.3.3 -** (file://dpans16.htm#16.3.3) -*/ -#if !defined FICL_DEFAULT_VOCS -#define FICL_DEFAULT_VOCS 16 -#endif - -/* -** User variables: per-instance variables bound to the VM. -** Kinda like thread-local storage. Could be implemented in a -** VM private dictionary, but I've chosen the lower overhead -** approach of an array of CELLs instead. -*/ -#if !defined FICL_WANT_USER -#define FICL_WANT_USER 1 -#endif - -#if !defined FICL_USER_CELLS -#define FICL_USER_CELLS 16 -#endif - -/* -** FICL_WANT_LOCALS controls the creation of the LOCALS wordset and -** a private dictionary for local variable compilation. -*/ -#if !defined FICL_WANT_LOCALS -#define FICL_WANT_LOCALS 1 -#endif - -/* Max number of local variables per definition */ -#if !defined FICL_MAX_LOCALS -#define FICL_MAX_LOCALS 16 -#endif - -/* -** FICL_ALIGN is the power of two to which the dictionary -** pointer address must be aligned. This value is usually -** either 1 or 2, depending on the memory architecture -** of the target system; 2 is safe on any 16 or 32 bit -** machine. -*/ -#if !defined FICL_ALIGN -#define FICL_ALIGN 2 -#define FICL_ALIGN_ADD ((1 << FICL_ALIGN) - 1) -#endif - -/* -** System dependent routines -- -** edit the implementations in sysdep.c to be compatible -** with your runtime environment... -** ficlTextOut sends a NULL terminated string to the -** default output device - used for system error messages -** ficlMalloc and ficlFree have the same semantics as malloc and free -** in standard C -** ficlLongMul multiplies two UNS32s and returns a 64 bit unsigned -** product -** ficlLongDiv divides an UNS64 by an UNS32 and returns UNS32 quotient -** and remainder -*/ -struct vm; -void ficlTextOut(struct vm *pVM, char *msg, int fNewline); -void *ficlMalloc (size_t size); -void ficlFree (void *p); - -/* -** Stub function for dictionary access control - does nothing -** by default, user can redefine to guarantee exclusive dict -** access to a single thread for updates. All dict update code -** must be bracketed as follows: -** ficlLockDictionary(TRUE); -** <code that updates dictionary> -** ficlLockDictionary(FALSE); -** -** Returns zero if successful, nonzero if unable to acquire lock -** before timeout (optional - could also block forever) -** -** NOTE: this function must be implemented with lock counting -** semantics: nested calls must behave properly. -*/ -#if FICL_MULTITHREAD -int ficlLockDictionary(short fLock); -#else -#define ficlLockDictionary(x) 0 /* ignore */ -#endif - -/* -** 64 bit integer math support routines: multiply two UNS32s -** to get a 64 bit prodict, & divide the product by an UNS32 -** to get an UNS32 quotient and remainder. Much easier in asm -** on a 32 bit CPU than in C, which usually doesn't support -** the double length result (but it should). -*/ -UNS64 ficlLongMul(UNS32 x, UNS32 y); -UNSQR ficlLongDiv(UNS64 q, UNS32 y); - -#endif /*__SYSDEP_H__*/ diff --git a/sys/boot/ficl/testmain.c b/sys/boot/ficl/testmain.c deleted file mode 100644 index f7cdc4440a83..000000000000 --- a/sys/boot/ficl/testmain.c +++ /dev/null @@ -1,275 +0,0 @@ -/* -** stub main for testing FICL -** -*/ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "ficl.h" - -/* -** Ficl interface to getcwd -** Prints the current working directory using the VM's -** textOut method... -*/ -static void ficlGetCWD(FICL_VM *pVM) -{ - char *cp; - - cp = getcwd(NULL, 80); - vmTextOut(pVM, cp, 1); - free(cp); - return; -} - -/* -** Ficl interface to chdir -** Gets a newline (or NULL) delimited string from the input -** and feeds it to chdir() -** Example: -** cd c:\tmp -*/ -static void ficlChDir(FICL_VM *pVM) -{ - FICL_STRING *pFS = (FICL_STRING *)pVM->pad; - vmGetString(pVM, pFS, '\n'); - if (pFS->count > 0) - { - int err = chdir(pFS->text); - if (err) - { - vmTextOut(pVM, "Error: path not found", 1); - vmThrow(pVM, VM_QUIT); - } - } - else - { - vmTextOut(pVM, "Warning (chdir): nothing happened", 1); - } - return; -} - -/* -** Ficl interface to system (ANSI) -** Gets a newline (or NULL) delimited string from the input -** and feeds it to system() -** Example: -** system del *.* -** \ ouch! -*/ -static void ficlSystem(FICL_VM *pVM) -{ - FICL_STRING *pFS = (FICL_STRING *)pVM->pad; - - vmGetString(pVM, pFS, '\n'); - if (pFS->count > 0) - { - int err = system(pFS->text); - if (err) - { - sprintf(pVM->pad, "System call returned %d", err); - vmTextOut(pVM, pVM->pad, 1); - vmThrow(pVM, VM_QUIT); - } - } - else - { - vmTextOut(pVM, "Warning (system): nothing happened", 1); - } - return; -} - -/* -** Ficl add-in to load a text file and execute it... -** Cheesy, but illustrative. -** Line oriented... filename is newline (or NULL) delimited. -** Example: -** load test.ficl -*/ -#define nLINEBUF 256 -static void ficlLoad(FICL_VM *pVM) -{ - char cp[nLINEBUF]; - char filename[nLINEBUF]; - FICL_STRING *pFilename = (FICL_STRING *)filename; - int nLine = 0; - FILE *fp; - int result; - CELL id; - struct stat buf; - - - vmGetString(pVM, pFilename, '\n'); - - if (pFilename->count <= 0) - { - vmTextOut(pVM, "Warning (load): nothing happened", 1); - return; - } - - /* - ** get the file's size and make sure it exists - */ - result = stat( pFilename->text, &buf ); - - if (result != 0) - { - vmTextOut(pVM, "Unable to stat file: ", 0); - vmTextOut(pVM, pFilename->text, 1); - vmThrow(pVM, VM_QUIT); - } - - fp = fopen(pFilename->text, "r"); - if (!fp) - { - vmTextOut(pVM, "Unable to open file ", 0); - vmTextOut(pVM, pFilename->text, 1); - vmThrow(pVM, VM_QUIT); - } - - id = pVM->sourceID; - pVM->sourceID.p = (void *)fp; - - /* feed each line to ficlExec */ - while (fgets(cp, nLINEBUF, fp)) - { - int len = strlen(cp) - 1; - - nLine++; - if (len <= 0) - continue; - - if (cp[len] == '\n') - cp[len] = '\0'; - - result = ficlExec(pVM, cp); - if (result >= VM_ERREXIT) - { - pVM->sourceID = id; - fclose(fp); - vmThrowErr(pVM, "Error loading file <%s> line %d", pFilename->text, nLine); - break; - } - } - /* - ** Pass an empty line with SOURCE-ID == 0 to flush - ** any pending REFILLs (as required by FILE wordset) - */ - pVM->sourceID.i = -1; - ficlExec(pVM, ""); - - pVM->sourceID = id; - fclose(fp); - - return; -} - -/* -** Dump a tab delimited file that summarizes the contents of the -** dictionary hash table by hashcode... -*/ -static void spewHash(FICL_VM *pVM) -{ - FICL_HASH *pHash = ficlGetDict()->pForthWords; - FICL_WORD *pFW; - FILE *pOut; - unsigned i; - unsigned nHash = pHash->size; - - if (!vmGetWordToPad(pVM)) - vmThrow(pVM, VM_OUTOFTEXT); - - pOut = fopen(pVM->pad, "w"); - if (!pOut) - { - vmTextOut(pVM, "unable to open file", 1); - return; - } - - for (i=0; i < nHash; i++) - { - int n = 0; - - pFW = pHash->table[i]; - while (pFW) - { - n++; - pFW = pFW->link; - } - - fprintf(pOut, "%d\t%d", i, n); - - pFW = pHash->table[i]; - while (pFW) - { - fprintf(pOut, "\t%s", pFW->name); - pFW = pFW->link; - } - - fprintf(pOut, "\n"); - } - - fclose(pOut); - return; -} - -static void ficlBreak(FICL_VM *pVM) -{ - pVM->state = pVM->state; - return; -} - -void buildTestInterface(void) -{ - ficlBuild("break", ficlBreak, FW_DEFAULT); - ficlBuild("cd", ficlChDir, FW_DEFAULT); - ficlBuild("load", ficlLoad, FW_DEFAULT); - ficlBuild("pwd", ficlGetCWD, FW_DEFAULT); - ficlBuild("system", ficlSystem, FW_DEFAULT); - ficlBuild("spewhash", spewHash, FW_DEFAULT); - - return; -} - - -int main(int argc, char **argv) -{ - char in[256]; - FICL_VM *pVM; - - ficlInitSystem(10000); - buildTestInterface(); - pVM = ficlNewVM(); - - ficlExec(pVM, ".ver .( " __DATE__ " ) cr quit"); - - /* - ** load file from cmd line... - */ - if (argc > 1) - { - sprintf(in, ".( loading %s ) cr load %s\n cr", argv[1], argv[1]); - ficlExec(pVM, in); - } - - for (;;) - { - int ret; - if (fgets(in, sizeof(in) - 1, stdin) == NULL) - break; - ret = ficlExec(pVM, in); - if (ret == VM_USEREXIT) - { - ficlTermSystem(); - break; - } - } - - return 0; -} - diff --git a/sys/boot/ficl/vm.c b/sys/boot/ficl/vm.c deleted file mode 100644 index 6852c62bd663..000000000000 --- a/sys/boot/ficl/vm.c +++ /dev/null @@ -1,565 +0,0 @@ -/*******************************************************************
-** v m . c -** Forth Inspired Command Language - virtual machine methods -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 19 July 1997 -** -*******************************************************************/ -/* -** This file implements the virtual machine of FICL. Each virtual -** machine retains the state of an interpreter. A virtual machine -** owns a pair of stacks for parameters and return addresses, as -** well as a pile of state variables and the two dedicated registers -** of the interp. -*/ - -#ifdef TESTMAIN -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#else -#include <stand.h> -#endif -#include <stdarg.h> -#include <string.h> -#include "ficl.h" - -static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - -/************************************************************************** - v m B r a n c h R e l a t i v e -** -**************************************************************************/ -void vmBranchRelative(FICL_VM *pVM, int offset) -{ - pVM->ip += offset; - return; -} - - -/************************************************************************** - v m C r e a t e -** -**************************************************************************/ -FICL_VM *vmCreate(FICL_VM *pVM, unsigned nPStack, unsigned nRStack) -{ - if (pVM == NULL) - { - pVM = (FICL_VM *)ficlMalloc(sizeof (FICL_VM)); - pVM->pStack = NULL; - pVM->rStack = NULL; - pVM->link = NULL; - } - assert (pVM); - - if (pVM->pStack) - stackDelete(pVM->pStack); - pVM->pStack = stackCreate(nPStack); - - if (pVM->rStack) - stackDelete(pVM->rStack); - pVM->rStack = stackCreate(nRStack); - - pVM->textOut = ficlTextOut; - - vmReset(pVM); - return pVM; -} - - -/************************************************************************** - v m D e l e t e -** -**************************************************************************/ -void vmDelete (FICL_VM *pVM) -{ - if (pVM) - { - ficlFree(pVM->pStack); - ficlFree(pVM->rStack); - ficlFree(pVM); - } - - return; -} - - -/************************************************************************** - v m E x e c u t e -** -**************************************************************************/ -void vmExecute(FICL_VM *pVM, FICL_WORD *pWord) -{ - pVM->runningWord = pWord; - pWord->code(pVM); - return; -} - - -/************************************************************************** - v m G e t S t r i n g -** Parses a string out of the VM input buffer and copies up to the first -** FICL_STRING_MAX characters to the supplied destination buffer, a -** FICL_STRING. The destination string is NULL terminated. -** -** Returns the address of the first unused character in the dest buffer. -**************************************************************************/ -char *vmGetString(FICL_VM *pVM, FICL_STRING *spDest, char delimiter) -{ - STRINGINFO si = vmParseString(pVM, delimiter); - - if (SI_COUNT(si) > FICL_STRING_MAX) - { - SI_SETLEN(si, FICL_STRING_MAX); - } - - strncpy(spDest->text, SI_PTR(si), SI_COUNT(si)); - spDest->text[SI_COUNT(si)] = '\0'; - spDest->count = (FICL_COUNT)SI_COUNT(si); - - return spDest->text + SI_COUNT(si) + 1; -} - - -/************************************************************************** - v m G e t W o r d -** vmGetWord calls vmGetWord0 repeatedly until it gets a string with -** non-zero length. -**************************************************************************/ -STRINGINFO vmGetWord(FICL_VM *pVM) -{ - STRINGINFO si = vmGetWord0(pVM); - - if (SI_COUNT(si) == 0) - { - vmThrow(pVM, VM_RESTART); - } - - return si; -} - - -/************************************************************************** - v m G e t W o r d 0 -** Skip leading whitespace and parse a space delimited word from the tib. -** Returns the start address and length of the word. Updates the tib -** to reflect characters consumed, including the trailing delimiter. -** If there's nothing of interest in the tib, returns zero. This function -** does not use vmParseString because it uses isspace() rather than a -** single delimiter character. -**************************************************************************/ -STRINGINFO vmGetWord0(FICL_VM *pVM) -{ - char *pSrc = vmGetInBuf(pVM); - STRINGINFO si; - UNS32 count = 0; - char ch; - - pSrc = skipSpace(pSrc); - SI_SETPTR(si, pSrc); - - for (ch = *pSrc; ch != '\0' && !isspace(ch); ch = *++pSrc) - { - count++; - } - - SI_SETLEN(si, count); - - if (isspace(ch)) /* skip one trailing delimiter */ - pSrc++; - - vmUpdateTib(pVM, pSrc); - - return si; -} - - -/************************************************************************** - v m G e t W o r d T o P a d -** Does vmGetWord0 and copies the result to the pad as a NULL terminated -** string. Returns the length of the string. If the string is too long -** to fit in the pad, it is truncated. -**************************************************************************/ -int vmGetWordToPad(FICL_VM *pVM) -{ - STRINGINFO si; - char *cp = (char *)pVM->pad; - si = vmGetWord0(pVM); - - if (SI_COUNT(si) > nPAD) - SI_SETLEN(si, nPAD); - - strncpy(cp, SI_PTR(si), SI_COUNT(si)); - cp[SI_COUNT(si)] = '\0'; - return (int)(SI_COUNT(si)); -} - - -/************************************************************************** - v m P a r s e S t r i n g -** Parses a string out of the input buffer using the delimiter -** specified. Skips leading delimiters, marks the start of the string, -** and counts characters to the next delimiter it encounters. It then -** updates the vm input buffer to consume all these chars, including the -** trailing delimiter. -** Returns the address and length of the parsed string, not including the -** trailing delimiter. -**************************************************************************/ -STRINGINFO vmParseString(FICL_VM *pVM, char delim) -{ - STRINGINFO si; - char *pSrc = vmGetInBuf(pVM); - char ch; - - while (*pSrc == delim) /* skip lead delimiters */ - pSrc++; - - SI_SETPTR(si, pSrc); /* mark start of text */ - - for (ch = *pSrc; (ch != delim) - && (ch != '\0') - && (ch != '\r') - && (ch != '\n'); ch = *++pSrc) - { - ; /* find next delimiter or end of line */ - } - - /* set length of result */ - SI_SETLEN(si, pSrc - SI_PTR(si)); - - if (*pSrc == delim) /* gobble trailing delimiter */ - pSrc++; - - vmUpdateTib(pVM, pSrc); - return si; -} - - -/************************************************************************** - v m P o p I P -** -**************************************************************************/ -void vmPopIP(FICL_VM *pVM) -{ - pVM->ip = (IPTYPE)(stackPopPtr(pVM->rStack)); - return; -} - - -/************************************************************************** - v m P u s h I P -** -**************************************************************************/ -void vmPushIP(FICL_VM *pVM, IPTYPE newIP) -{ - stackPushPtr(pVM->rStack, (void *)pVM->ip); - pVM->ip = newIP; - return; -} - - -/************************************************************************** - v m P u s h T i b -** Binds the specified input string to the VM and clears >IN (the index) -**************************************************************************/ -void vmPushTib(FICL_VM *pVM, char *text, TIB *pSaveTib) -{ - if (pSaveTib) - { - *pSaveTib = pVM->tib; - } - - pVM->tib.cp = text; - pVM->tib.index = 0; -} - - -void vmPopTib(FICL_VM *pVM, TIB *pTib) -{ - if (pTib) - { - pVM->tib = *pTib; - } - return; -} - - -/************************************************************************** - v m Q u i t -** -**************************************************************************/ -void vmQuit(FICL_VM *pVM) -{ - static FICL_WORD *pInterp = NULL; - if (!pInterp) - pInterp = ficlLookup("interpret"); - assert(pInterp); - - stackReset(pVM->rStack); - pVM->fRestart = 0; - pVM->ip = &pInterp; - pVM->runningWord = pInterp; - pVM->state = INTERPRET; - pVM->tib.cp = NULL; - pVM->tib.index = 0; - pVM->pad[0] = '\0'; - pVM->sourceID.i = 0; - return; -} - - -/************************************************************************** - v m R e s e t -** -**************************************************************************/ -void vmReset(FICL_VM *pVM) -{ - vmQuit(pVM); - stackReset(pVM->pStack); - pVM->base = 10; - return; -} - - -/************************************************************************** - v m S e t T e x t O u t -** Binds the specified output callback to the vm. If you pass NULL, -** binds the default output function (ficlTextOut) -**************************************************************************/ -void vmSetTextOut(FICL_VM *pVM, OUTFUNC textOut) -{ - if (textOut) - pVM->textOut = textOut; - else - pVM->textOut = ficlTextOut; - - return; -} - - -/************************************************************************** - v m T e x t O u t -** Feeds text to the vm's output callback -**************************************************************************/ -void vmTextOut(FICL_VM *pVM, char *text, int fNewline) -{ - assert(pVM); - assert(pVM->textOut); - (pVM->textOut)(pVM, text, fNewline); - - return; -} - - -/************************************************************************** - v m T h r o w -** -**************************************************************************/ -void vmThrow(FICL_VM *pVM, int except) -{ - longjmp(*(pVM->pState), except); -} - - -void vmThrowErr(FICL_VM *pVM, char *fmt, ...) -{ - va_list va; - va_start(va, fmt); - vsprintf(pVM->pad, fmt, va); - vmTextOut(pVM, pVM->pad, 1); - va_end(va); - longjmp(*(pVM->pState), VM_ERREXIT); -} - - -/************************************************************************** - w o r d I s I m m e d i a t e -** -**************************************************************************/ -int wordIsImmediate(FICL_WORD *pFW) -{ - return ((pFW != NULL) && (pFW->flags & FW_IMMEDIATE)); -} - - -/************************************************************************** - w o r d I s C o m p i l e O n l y -** -**************************************************************************/ -int wordIsCompileOnly(FICL_WORD *pFW) -{ - return ((pFW != NULL) && (pFW->flags & FW_COMPILE)); -} - - -/************************************************************************** - s t r r e v -** -**************************************************************************/ -char *strrev( char *string ) -{ /* reverse a string in-place */ - int i = strlen(string); - char *p1 = string; /* first char of string */ - char *p2 = string + i - 1; /* last non-NULL char of string */ - char c; - - if (i > 1) - { - while (p1 < p2) - { - c = *p2; - *p2 = *p1; - *p1 = c; - p1++; p2--; - } - } - - return string; -} - - -/************************************************************************** - d i g i t _ t o _ c h a r -** -**************************************************************************/ -char digit_to_char(int value) -{ - return digits[value]; -} - - -/************************************************************************** - l t o a -** -**************************************************************************/ -char *ltoa( INT32 value, char *string, int radix ) -{ /* convert long to string, any base */ - char *cp = string; - int sign = ((radix == 10) && (value < 0)); - UNSQR result; - UNS64 v; - - assert(radix > 1); - assert(radix < 37); - assert(string); - - if (sign) - value = -value; - - if (value == 0) - *cp++ = '0'; - else - { - v.hi = 0; - v.lo = (UNS32)value; - while (v.lo) - { - result = ficlLongDiv(v, (UNS32)radix); - *cp++ = digits[result.rem]; - v.lo = result.quot; - } - } - - if (sign) - *cp++ = '-'; - - *cp++ = '\0'; - - return strrev(string); -} - - -/************************************************************************** - u l t o a -** -**************************************************************************/ -char *ultoa(UNS32 value, char *string, int radix ) -{ /* convert long to string, any base */ - char *cp = string; - UNS64 ud; - UNSQR result; - - assert(radix > 1); - assert(radix < 37); - assert(string); - - if (value == 0) - *cp++ = '0'; - else - { - ud.hi = 0; - ud.lo = value; - result.quot = value; - - while (ud.lo) - { - result = ficlLongDiv(ud, (UNS32)radix); - ud.lo = result.quot; - *cp++ = digits[result.rem]; - } - } - - *cp++ = '\0'; - - return strrev(string); -} - - -/************************************************************************** - c a s e F o l d -** Case folds a NULL terminated string in place. All characters -** get converted to lower case. -**************************************************************************/ -char *caseFold(char *cp) -{ - char *oldCp = cp; - - while (*cp) - { - if (isupper(*cp)) - *cp = (char)tolower(*cp); - cp++; - } - - return oldCp; -} - - -/************************************************************************** - s t r i n c m p -** -**************************************************************************/ -int strincmp(char *cp1, char *cp2, FICL_COUNT count) -{ - int i = 0; - char c1, c2; - - for (c1 = *cp1, c2 = *cp2; - ((i == 0) && count && c1 && c2); - c1 = *++cp1, c2 = *++cp2, count--) - { - i = tolower(c1) - tolower(c2); - } - - return i; -} - - - -/************************************************************************** - s k i p S p a c e -** Given a string pointer, returns a pointer to the first non-space -** char of the string, or to the NULL terminator if no such char found. -**************************************************************************/ -char *skipSpace(char *cp) -{ - assert(cp); - - while (isspace(*cp)) - cp++; - - return cp; -} - - diff --git a/sys/boot/ficl/words.c b/sys/boot/ficl/words.c deleted file mode 100644 index c76c169a83d3..000000000000 --- a/sys/boot/ficl/words.c +++ /dev/null @@ -1,4544 +0,0 @@ -/******************************************************************* -** w o r d s . c -** Forth Inspired Command Language -** ANS Forth CORE word-set written in C -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 19 July 1997 -** -*******************************************************************/ - -#ifdef TESTMAIN -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <fcntl.h> -#else -#include <stand.h> -#endif -#include <string.h> -#include "ficl.h" -#include "math64.h" - -static void colonParen(FICL_VM *pVM); -static void literalIm(FICL_VM *pVM); -static void interpWord(FICL_VM *pVM, STRINGINFO si); - -/* -** Control structure building words use these -** strings' addresses as markers on the stack to -** check for structure completion. -*/ -static char doTag[] = "do"; -static char ifTag[] = "if"; -static char colonTag[] = "colon"; -static char leaveTag[] = "leave"; -static char beginTag[] = "begin"; -static char whileTag[] = "while"; - -/* -** Pointers to various words in the dictionary -** -- initialized by ficlCompileCore, below -- -** for use by compiling words. Colon definitions -** in ficl are lists of pointers to words. A bit -** simple-minded... -*/ -static FICL_WORD *pBranchParen = NULL; -static FICL_WORD *pComma = NULL; -static FICL_WORD *pDoParen = NULL; -static FICL_WORD *pDoesParen = NULL; -static FICL_WORD *pExitParen = NULL; -static FICL_WORD *pIfParen = NULL; -static FICL_WORD *pInterpret = NULL; -static FICL_WORD *pLitParen = NULL; -static FICL_WORD *pLoopParen = NULL; -static FICL_WORD *pPLoopParen = NULL; -static FICL_WORD *pQDoParen = NULL; -static FICL_WORD *pSemiParen = NULL; -static FICL_WORD *pStore = NULL; -static FICL_WORD *pStringLit = NULL; -static FICL_WORD *pType = NULL; - -#if FICL_WANT_LOCALS -static FICL_WORD *pGetLocalParen= NULL; -static FICL_WORD *pGetLocal0 = NULL; -static FICL_WORD *pGetLocal1 = NULL; -static FICL_WORD *pToLocalParen = NULL; -static FICL_WORD *pToLocal0 = NULL; -static FICL_WORD *pToLocal1 = NULL; -static FICL_WORD *pLinkParen = NULL; -static FICL_WORD *pUnLinkParen = NULL; -static int nLocals = 0; -#endif - - -/* -** C O N T R O L S T R U C T U R E B U I L D E R S -** -** Push current dict location for later branch resolution. -** The location may be either a branch target or a patch address... -*/ -static void markBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag) -{ - stackPushPtr(pVM->pStack, dp->here); - stackPushPtr(pVM->pStack, tag); - return; -} - -static void markControlTag(FICL_VM *pVM, char *tag) -{ - stackPushPtr(pVM->pStack, tag); - return; -} - -static void matchControlTag(FICL_VM *pVM, char *tag) -{ - char *cp = (char *)stackPopPtr(pVM->pStack); - if ( strcmp(cp, tag) ) - { - vmTextOut(pVM, "Warning -- unmatched control word: ", 0); - vmTextOut(pVM, tag, 1); - } - - return; -} - -/* -** Expect a branch target address on the param stack, -** compile a literal offset from the current dict location -** to the target address -*/ -static void resolveBackBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag) -{ - long offset; - CELL *patchAddr; - - matchControlTag(pVM, tag); - - patchAddr = (CELL *)stackPopPtr(pVM->pStack); - offset = patchAddr - dp->here; - dictAppendCell(dp, LVALUEtoCELL(offset)); - - return; -} - - -/* -** Expect a branch patch address on the param stack, -** compile a literal offset from the patch location -** to the current dict location -*/ -static void resolveForwardBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag) -{ - long offset; - CELL *patchAddr; - - matchControlTag(pVM, tag); - - patchAddr = (CELL *)stackPopPtr(pVM->pStack); - offset = dp->here - patchAddr; - *patchAddr = LVALUEtoCELL(offset); - - return; -} - -/* -** Match the tag to the top of the stack. If success, -** sopy "here" address into the cell whose address is next -** on the stack. Used by do..leave..loop. -*/ -static void resolveAbsBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag) -{ - CELL *patchAddr; - char *cp; - - cp = stackPopPtr(pVM->pStack); - if (strcmp(cp, tag)) - { - vmTextOut(pVM, "Warning -- Unmatched control word: ", 0); - vmTextOut(pVM, tag, 1); - } - - patchAddr = (CELL *)stackPopPtr(pVM->pStack); - *patchAddr = LVALUEtoCELL(dp->here); - - return; -} - - -/************************************************************************** - i s N u m b e r -** Attempts to convert the NULL terminated string in the VM's pad to -** a number using the VM's current base. If successful, pushes the number -** onto the param stack and returns TRUE. Otherwise, returns FALSE. -**************************************************************************/ - -static int isNumber(FICL_VM *pVM, STRINGINFO si) -{ - INT32 accum = 0; - char isNeg = FALSE; - unsigned base = pVM->base; - char *cp = SI_PTR(si); - FICL_COUNT count= (FICL_COUNT)SI_COUNT(si); - unsigned ch; - unsigned digit; - - if (*cp == '-') - { - cp++; - count--; - isNeg = TRUE; - } - else if ((cp[0] == '0') && (cp[1] == 'x')) - { /* detect 0xNNNN format for hex numbers */ - cp += 2; - count -= 2; - base = 16; - } - - if (count == 0) - return FALSE; - - while (count-- && ((ch = *cp++) != '\0')) - { - if (ch < '0') - return FALSE; - - digit = ch - '0'; - - if (digit > 9) - digit = tolower(ch) - 'a' + 10; - /* - ** Note: following test also catches chars between 9 and a - ** because 'digit' is unsigned! - */ - if (digit >= base) - return FALSE; - - accum = accum * base + digit; - } - - if (isNeg) - accum = -accum; - - stackPushINT32(pVM->pStack, accum); - - return TRUE; -} - - -/************************************************************************** - a d d & f r i e n d s -** -**************************************************************************/ - -static void add(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - i = stackPopINT32(pVM->pStack); - i += stackGetTop(pVM->pStack).i; - stackSetTop(pVM->pStack, LVALUEtoCELL(i)); - return; -} - -static void sub(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - i = stackPopINT32(pVM->pStack); - i = stackGetTop(pVM->pStack).i - i; - stackSetTop(pVM->pStack, LVALUEtoCELL(i)); - return; -} - -static void mul(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - i = stackPopINT32(pVM->pStack); - i *= stackGetTop(pVM->pStack).i; - stackSetTop(pVM->pStack, LVALUEtoCELL(i)); - return; -} - -static void negate(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - i = -stackPopINT32(pVM->pStack); - stackPushINT32(pVM->pStack, i); - return; -} - -static void ficlDiv(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - i = stackPopINT32(pVM->pStack); - i = stackGetTop(pVM->pStack).i / i; - stackSetTop(pVM->pStack, LVALUEtoCELL(i)); - return; -} - -/* -** slash-mod CORE ( n1 n2 -- n3 n4 ) -** Divide n1 by n2, giving the single-cell remainder n3 and the single-cell -** quotient n4. An ambiguous condition exists if n2 is zero. If n1 and n2 -** differ in sign, the implementation-defined result returned will be the -** same as that returned by either the phrase -** >R S>D R> FM/MOD or the phrase >R S>D R> SM/REM . -** NOTE: Ficl complies with the second phrase (symmetric division) -*/ -static void slashMod(FICL_VM *pVM) -{ - INT64 n1; - INT32 n2; - INTQR qr; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 2); -#endif - n2 = stackPopINT32(pVM->pStack); - n1.lo = stackPopINT32(pVM->pStack); - i64Extend(n1); - - qr = m64SymmetricDivI(n1, n2); - stackPushINT32(pVM->pStack, qr.rem); - stackPushINT32(pVM->pStack, qr.quot); - return; -} - -static void onePlus(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - i = stackGetTop(pVM->pStack).i; - i += 1; - stackSetTop(pVM->pStack, LVALUEtoCELL(i)); - return; -} - -static void oneMinus(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - i = stackGetTop(pVM->pStack).i; - i -= 1; - stackSetTop(pVM->pStack, LVALUEtoCELL(i)); - return; -} - -static void twoMul(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - i = stackGetTop(pVM->pStack).i; - i *= 2; - stackSetTop(pVM->pStack, LVALUEtoCELL(i)); - return; -} - -static void twoDiv(FICL_VM *pVM) -{ - INT32 i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - i = stackGetTop(pVM->pStack).i; - i >>= 1; - stackSetTop(pVM->pStack, LVALUEtoCELL(i)); - return; -} - -static void mulDiv(FICL_VM *pVM) -{ - INT32 x, y, z; - INT64 prod; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 3, 1); -#endif - z = stackPopINT32(pVM->pStack); - y = stackPopINT32(pVM->pStack); - x = stackPopINT32(pVM->pStack); - - prod = m64MulI(x,y); - x = m64SymmetricDivI(prod, z).quot; - - stackPushINT32(pVM->pStack, x); - return; -} - - -static void mulDivRem(FICL_VM *pVM) -{ - INT32 x, y, z; - INT64 prod; - INTQR qr; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 3, 2); -#endif - z = stackPopINT32(pVM->pStack); - y = stackPopINT32(pVM->pStack); - x = stackPopINT32(pVM->pStack); - - prod = m64MulI(x,y); - qr = m64SymmetricDivI(prod, z); - - stackPushINT32(pVM->pStack, qr.rem); - stackPushINT32(pVM->pStack, qr.quot); - return; -} - - -/************************************************************************** - b y e -** TOOLS -** Signal the system to shut down - this causes ficlExec to return -** VM_USEREXIT. The rest is up to you. -**************************************************************************/ - -static void bye(FICL_VM *pVM) -{ - vmThrow(pVM, VM_USEREXIT); - return; -} - - -/************************************************************************** - c o l o n d e f i n i t i o n s -** Code to begin compiling a colon definition -** This function sets the state to COMPILE, then creates a -** new word whose name is the next word in the input stream -** and whose code is colonParen. -**************************************************************************/ - -static void colon(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - STRINGINFO si = vmGetWord(pVM); - - pVM->state = COMPILE; - markControlTag(pVM, colonTag); - dictAppendWord2(dp, si, colonParen, FW_DEFAULT | FW_SMUDGE); -#if FICL_WANT_LOCALS - nLocals = 0; -#endif - return; -} - - -/************************************************************************** - c o l o n P a r e n -** This is the code that executes a colon definition. It assumes that the -** virtual machine is running a "next" loop (See the vm.c -** for its implementation of member function vmExecute()). The colon -** code simply copies the address of the first word in the list of words -** to interpret into IP after saving its old value. When we return to the -** "next" loop, the virtual machine will call the code for each word in -** turn. -** -**************************************************************************/ - -static void colonParen(FICL_VM *pVM) -{ - IPTYPE tempIP = (IPTYPE) (pVM->runningWord->param); - vmPushIP(pVM, tempIP); - - return; -} - - -/************************************************************************** - s e m i c o l o n C o I m -** -** IMMEDIATE code for ";". This function sets the state to INTERPRET and -** terminates a word under compilation by appending code for "(;)" to -** the definition. TO DO: checks for leftover branch target tags on the -** return stack and complains if any are found. -**************************************************************************/ -static void semiParen(FICL_VM *pVM) -{ - vmPopIP(pVM); - return; -} - - -static void semicolonCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pSemiParen); - matchControlTag(pVM, colonTag); - -#if FICL_WANT_LOCALS - assert(pUnLinkParen); - if (nLocals > 0) - { - FICL_DICT *pLoc = ficlGetLoc(); - dictEmpty(pLoc, pLoc->pForthWords->size); - dictAppendCell(dp, LVALUEtoCELL(pUnLinkParen)); - } - nLocals = 0; -#endif - - dictAppendCell(dp, LVALUEtoCELL(pSemiParen)); - pVM->state = INTERPRET; - dictUnsmudge(dp); - return; -} - - -/************************************************************************** - e x i t -** CORE -** This function simply pops the previous instruction -** pointer and returns to the "next" loop. Used for exiting from within -** a definition. Note that exitParen is identical to semiParen - they -** are in two different functions so that "see" can correctly identify -** the end of a colon definition, even if it uses "exit". -**************************************************************************/ -static void exitParen(FICL_VM *pVM) -{ - vmPopIP(pVM); - return; -} - -static void exitCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - assert(pExitParen); - IGNORE(pVM); - -#if FICL_WANT_LOCALS - if (nLocals > 0) - { - dictAppendCell(dp, LVALUEtoCELL(pUnLinkParen)); - } -#endif - dictAppendCell(dp, LVALUEtoCELL(pExitParen)); - return; -} - - -/************************************************************************** - c o n s t a n t P a r e n -** This is the run-time code for "constant". It simply returns the -** contents of its word's first data cell. -** -**************************************************************************/ - -void constantParen(FICL_VM *pVM) -{ - FICL_WORD *pFW = pVM->runningWord; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif - stackPush(pVM->pStack, pFW->param[0]); - return; -} - -void twoConstParen(FICL_VM *pVM) -{ - FICL_WORD *pFW = pVM->runningWord; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 2); -#endif - stackPush(pVM->pStack, pFW->param[0]); /* lo */ - stackPush(pVM->pStack, pFW->param[1]); /* hi */ - return; -} - - -/************************************************************************** - c o n s t a n t -** IMMEDIATE -** Compiles a constant into the dictionary. Constants return their -** value when invoked. Expects a value on top of the parm stack. -**************************************************************************/ - -static void constant(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - STRINGINFO si = vmGetWord(pVM); - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - dictAppendWord2(dp, si, constantParen, FW_DEFAULT); - dictAppendCell(dp, stackPop(pVM->pStack)); - return; -} - - -static void twoConstant(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - STRINGINFO si = vmGetWord(pVM); - CELL c; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - c = stackPop(pVM->pStack); - dictAppendWord2(dp, si, twoConstParen, FW_DEFAULT); - dictAppendCell(dp, stackPop(pVM->pStack)); - dictAppendCell(dp, c); - return; -} - - -/************************************************************************** - d i s p l a y C e l l -** Drop and print the contents of the cell at the top of the param -** stack -**************************************************************************/ - -static void displayCell(FICL_VM *pVM) -{ - CELL c; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - c = stackPop(pVM->pStack); - ltoa((c).i, pVM->pad, pVM->base); - strcat(pVM->pad, " "); - vmTextOut(pVM, pVM->pad, 0); - return; -} - -static void displayCellNoPad(FICL_VM *pVM) -{ - CELL c; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - c = stackPop(pVM->pStack); - ltoa((c).i, pVM->pad, pVM->base); - vmTextOut(pVM, pVM->pad, 0); - return; -} - -static void uDot(FICL_VM *pVM) -{ - UNS32 u; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - u = stackPopUNS32(pVM->pStack); - ultoa(u, pVM->pad, pVM->base); - strcat(pVM->pad, " "); - vmTextOut(pVM, pVM->pad, 0); - return; -} - - -static void hexDot(FICL_VM *pVM) -{ - UNS32 u; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - u = stackPopUNS32(pVM->pStack); - ultoa(u, pVM->pad, 16); - strcat(pVM->pad, " "); - vmTextOut(pVM, pVM->pad, 0); - return; -} - - -/************************************************************************** - d i s p l a y S t a c k -** Display the parameter stack (code for ".s") -**************************************************************************/ - -static void displayStack(FICL_VM *pVM) -{ - int d = stackDepth(pVM->pStack); - int i; - CELL *pCell; - - vmCheckStack(pVM, 0, 0); - - if (d == 0) - vmTextOut(pVM, "(Stack Empty)", 1); - else - { - pCell = pVM->pStack->sp; - for (i = 0; i < d; i++) - { - vmTextOut(pVM, ltoa((*--pCell).i, pVM->pad, pVM->base), 1); - } - } -} - - -/************************************************************************** - d u p & f r i e n d s -** -**************************************************************************/ - -static void depth(FICL_VM *pVM) -{ - int i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif - i = stackDepth(pVM->pStack); - stackPushINT32(pVM->pStack, i); - return; -} - - -static void drop(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - stackDrop(pVM->pStack, 1); - return; -} - - -static void twoDrop(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - stackDrop(pVM->pStack, 2); - return; -} - - -static void dup(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 2); -#endif - stackPick(pVM->pStack, 0); - return; -} - - -static void twoDup(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 4); -#endif - stackPick(pVM->pStack, 1); - stackPick(pVM->pStack, 1); - return; -} - - -static void over(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 3); -#endif - stackPick(pVM->pStack, 1); - return; -} - -static void twoOver(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 4, 6); -#endif - stackPick(pVM->pStack, 3); - stackPick(pVM->pStack, 3); - return; -} - - -static void pick(FICL_VM *pVM) -{ - CELL c = stackPop(pVM->pStack); -#if FICL_ROBUST > 1 - vmCheckStack(pVM, c.i+1, c.i+2); -#endif - stackPick(pVM->pStack, c.i); - return; -} - - -static void questionDup(FICL_VM *pVM) -{ - CELL c; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 2); -#endif - c = stackGetTop(pVM->pStack); - - if (c.i != 0) - stackPick(pVM->pStack, 0); - - return; -} - - -static void roll(FICL_VM *pVM) -{ - int i = stackPop(pVM->pStack).i; - i = (i > 0) ? i : 0; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, i+1, i+1); -#endif - stackRoll(pVM->pStack, i); - return; -} - - -static void minusRoll(FICL_VM *pVM) -{ - int i = stackPop(pVM->pStack).i; - i = (i > 0) ? i : 0; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, i+1, i+1); -#endif - stackRoll(pVM->pStack, -i); - return; -} - - -static void rot(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 3, 3); -#endif - stackRoll(pVM->pStack, 2); - return; -} - - -static void swap(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 2); -#endif - stackRoll(pVM->pStack, 1); - return; -} - - -static void twoSwap(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 4, 4); -#endif - stackRoll(pVM->pStack, 3); - stackRoll(pVM->pStack, 3); - return; -} - - -/************************************************************************** - e m i t & f r i e n d s -** -**************************************************************************/ - -static void emit(FICL_VM *pVM) -{ - char *cp = pVM->pad; - int i; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - i = stackPopINT32(pVM->pStack); - cp[0] = (char)i; - cp[1] = '\0'; - vmTextOut(pVM, cp, 0); - return; -} - - -static void cr(FICL_VM *pVM) -{ - vmTextOut(pVM, "", 1); - return; -} - - -static void commentLine(FICL_VM *pVM) -{ - char *cp = vmGetInBuf(pVM); - char ch = *cp; - - while ((ch != '\0') && (ch != '\r') && (ch != '\n')) - { - ch = *++cp; - } - - /* - ** Cope with DOS or UNIX-style EOLs - - ** Check for /r, /n, /r/n, or /n/r end-of-line sequences, - ** and point cp to next char. If EOL is \0, we're done. - */ - if (ch != '\0') - { - cp++; - - if ( (ch != *cp) - && ((*cp == '\r') || (*cp == '\n')) ) - cp++; - } - - vmUpdateTib(pVM, cp); - return; -} - - -/* -** paren CORE -** Compilation: Perform the execution semantics given below. -** Execution: ( "ccc<paren>" -- ) -** Parse ccc delimited by ) (right parenthesis). ( is an immediate word. -** The number of characters in ccc may be zero to the number of characters -** in the parse area. -** -*/ -static void commentHang(FICL_VM *pVM) -{ - vmParseString(pVM, ')'); - return; -} - - -/************************************************************************** - F E T C H & S T O R E -** -**************************************************************************/ - -static void fetch(FICL_VM *pVM) -{ - CELL *pCell; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - pCell = (CELL *)stackPopPtr(pVM->pStack); - stackPush(pVM->pStack, *pCell); - return; -} - -/* -** two-fetch CORE ( a-addr -- x1 x2 ) -** Fetch the cell pair x1 x2 stored at a-addr. x2 is stored at a-addr and -** x1 at the next consecutive cell. It is equivalent to the sequence -** DUP CELL+ @ SWAP @ . -*/ -static void twoFetch(FICL_VM *pVM) -{ - CELL *pCell; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 2); -#endif - pCell = (CELL *)stackPopPtr(pVM->pStack); - stackPush(pVM->pStack, *pCell++); - stackPush(pVM->pStack, *pCell); - swap(pVM); - return; -} - -/* -** store CORE ( x a-addr -- ) -** Store x at a-addr. -*/ -static void store(FICL_VM *pVM) -{ - CELL *pCell; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - pCell = (CELL *)stackPopPtr(pVM->pStack); - *pCell = stackPop(pVM->pStack); -} - -/* -** two-store CORE ( x1 x2 a-addr -- ) -** Store the cell pair x1 x2 at a-addr, with x2 at a-addr and x1 at the -** next consecutive cell. It is equivalent to the sequence -** SWAP OVER ! CELL+ ! . -*/ -static void twoStore(FICL_VM *pVM) -{ - CELL *pCell; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 3, 0); -#endif - pCell = (CELL *)stackPopPtr(pVM->pStack); - *pCell++ = stackPop(pVM->pStack); - *pCell = stackPop(pVM->pStack); -} - -static void plusStore(FICL_VM *pVM) -{ - CELL *pCell; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - pCell = (CELL *)stackPopPtr(pVM->pStack); - pCell->i += stackPop(pVM->pStack).i; -} - - -static void wFetch(FICL_VM *pVM) -{ - UNS16 *pw; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - pw = (UNS16 *)stackPopPtr(pVM->pStack); - stackPushUNS32(pVM->pStack, (UNS32)*pw); - return; -} - -static void wStore(FICL_VM *pVM) -{ - UNS16 *pw; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - pw = (UNS16 *)stackPopPtr(pVM->pStack); - *pw = (UNS16)(stackPop(pVM->pStack).u); -} - -static void cFetch(FICL_VM *pVM) -{ - UNS8 *pc; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - pc = (UNS8 *)stackPopPtr(pVM->pStack); - stackPushUNS32(pVM->pStack, (UNS32)*pc); - return; -} - -static void cStore(FICL_VM *pVM) -{ - UNS8 *pc; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - pc = (UNS8 *)stackPopPtr(pVM->pStack); - *pc = (UNS8)(stackPop(pVM->pStack).u); -} - - -/************************************************************************** - i f C o I m -** IMMEDIATE -** Compiles code for a conditional branch into the dictionary -** and pushes the branch patch address on the stack for later -** patching by ELSE or THEN/ENDIF. -**************************************************************************/ - -static void ifCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pIfParen); - - dictAppendCell(dp, LVALUEtoCELL(pIfParen)); - markBranch(dp, pVM, ifTag); - dictAppendUNS32(dp, 1); - return; -} - - -/************************************************************************** - i f P a r e n -** Runtime code to do "if" or "until": pop a flag from the stack, -** fall through if true, branch if false. Probably ought to be -** called (not?branch) since it does "branch if false". -**************************************************************************/ - -static void ifParen(FICL_VM *pVM) -{ - UNS32 flag; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - flag = stackPopUNS32(pVM->pStack); - - if (flag) - { /* fall through */ - vmBranchRelative(pVM, 1); - } - else - { /* take branch (to else/endif/begin) */ - vmBranchRelative(pVM, (int)(*pVM->ip)); - } - - return; -} - - -/************************************************************************** - e l s e C o I m -** -** IMMEDIATE -- compiles an "else"... -** 1) Compile a branch and a patch address; the address gets patched -** by "endif" to point past the "else" code. -** 2) Pop the the "if" patch address -** 3) Patch the "if" branch to point to the current compile address. -** 4) Push the "else" patch address. ("endif" patches this to jump past -** the "else" code. -**************************************************************************/ - -static void elseCoIm(FICL_VM *pVM) -{ - CELL *patchAddr; - int offset; - FICL_DICT *dp = ficlGetDict(); - - assert(pBranchParen); - /* (1) compile branch runtime */ - dictAppendCell(dp, LVALUEtoCELL(pBranchParen)); - matchControlTag(pVM, ifTag); - patchAddr = - (CELL *)stackPopPtr(pVM->pStack); /* (2) pop "if" patch addr */ - markBranch(dp, pVM, ifTag); /* (4) push "else" patch addr */ - dictAppendUNS32(dp, 1); /* (1) compile patch placeholder */ - offset = dp->here - patchAddr; - *patchAddr = LVALUEtoCELL(offset); /* (3) Patch "if" */ - - return; -} - - -/************************************************************************** - b r a n c h P a r e n -** -** Runtime for "(branch)" -- expects a literal offset in the next -** compilation address, and branches to that location. -**************************************************************************/ - -static void branchParen(FICL_VM *pVM) -{ - vmBranchRelative(pVM, *(int *)(pVM->ip)); - return; -} - - -/************************************************************************** - e n d i f C o I m -** -**************************************************************************/ - -static void endifCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - resolveForwardBranch(dp, pVM, ifTag); - return; -} - - -/************************************************************************** - i n t e r p r e t -** This is the "user interface" of a Forth. It does the following: -** while there are words in the VM's Text Input Buffer -** Copy next word into the pad (vmGetWord) -** Attempt to find the word in the dictionary (dictLookup) -** If successful, execute the word. -** Otherwise, attempt to convert the word to a number (isNumber) -** If successful, push the number onto the parameter stack. -** Otherwise, print an error message and exit loop... -** End Loop -** -** From the standard, section 3.4 -** Text interpretation (see 6.1.1360 EVALUATE and 6.1.2050 QUIT) shall -** repeat the following steps until either the parse area is empty or an -** ambiguous condition exists: -** a) Skip leading spaces and parse a name (see 3.4.1); -**************************************************************************/ - -static void interpret(FICL_VM *pVM) -{ - STRINGINFO si = vmGetWord0(pVM); - assert(pVM); - - vmBranchRelative(pVM, -1); - - /* - // Get next word...if out of text, we're done. - */ - if (si.count == 0) - { - vmThrow(pVM, VM_OUTOFTEXT); - } - - interpWord(pVM, si); - - - return; /* back to inner interpreter */ -} - -/************************************************************************** -** From the standard, section 3.4 -** b) Search the dictionary name space (see 3.4.2). If a definition name -** matching the string is found: -** 1.if interpreting, perform the interpretation semantics of the definition -** (see 3.4.3.2), and continue at a); -** 2.if compiling, perform the compilation semantics of the definition -** (see 3.4.3.3), and continue at a). -** -** c) If a definition name matching the string is not found, attempt to -** convert the string to a number (see 3.4.1.3). If successful: -** 1.if interpreting, place the number on the data stack, and continue at a); -** 2.if compiling, compile code that when executed will place the number on -** the stack (see 6.1.1780 LITERAL), and continue at a); -** -** d) If unsuccessful, an ambiguous condition exists (see 3.4.4). -**************************************************************************/ -static void interpWord(FICL_VM *pVM, STRINGINFO si) -{ - FICL_DICT *dp = ficlGetDict(); - FICL_WORD *tempFW; - -#if FICL_ROBUST - dictCheck(dp, pVM, 0); - vmCheckStack(pVM, 0, 0); -#endif - -#if FICL_WANT_LOCALS - if (nLocals > 0) - { - tempFW = dictLookupLoc(dp, si); - } - else -#endif - tempFW = dictLookup(dp, si); - - if (pVM->state == INTERPRET) - { - if (tempFW != NULL) - { - if (wordIsCompileOnly(tempFW)) - { - vmThrowErr(pVM, "Error: Compile only!"); - } - - vmExecute(pVM, tempFW); - } - - else if (!isNumber(pVM, si)) - { - int i = SI_COUNT(si); - vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si)); - } - } - - else /* (pVM->state == COMPILE) */ - { - if (tempFW != NULL) - { - if (wordIsImmediate(tempFW)) - { - vmExecute(pVM, tempFW); - } - else - { - dictAppendCell(dp, LVALUEtoCELL(tempFW)); - } - } - else if (isNumber(pVM, si)) - { - literalIm(pVM); - } - else - { - int i = SI_COUNT(si); - vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si)); - } - } - - return; -} - - -/************************************************************************** - l i t e r a l P a r e n -** -** This is the runtime for (literal). It assumes that it is part of a colon -** definition, and that the next CELL contains a value to be pushed on the -** parameter stack at runtime. This code is compiled by "literal". -** -**************************************************************************/ - -static void literalParen(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif - stackPushINT32(pVM->pStack, *(INT32 *)(pVM->ip)); - vmBranchRelative(pVM, 1); - return; -} - - -/************************************************************************** - l i t e r a l I m -** -** IMMEDIATE code for "literal". This function gets a value from the stack -** and compiles it into the dictionary preceded by the code for "(literal)". -** IMMEDIATE -**************************************************************************/ - -static void literalIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - assert(pLitParen); - - dictAppendCell(dp, LVALUEtoCELL(pLitParen)); - dictAppendCell(dp, stackPop(pVM->pStack)); - - return; -} - - -/************************************************************************** - l i s t W o r d s -** -**************************************************************************/ -#define nCOLWIDTH 8 -static void listWords(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - FICL_HASH *pHash = dp->pSearch[dp->nLists - 1]; - FICL_WORD *wp; - int nChars = 0; - int len; - int y = 0; - unsigned i; - int nWords = 0; - char *cp; - char *pPad = pVM->pad; - - for (i = 0; i < pHash->size; i++) - { - for (wp = pHash->table[i]; wp != NULL; wp = wp->link, nWords++) - { - if (wp->nName == 0) /* ignore :noname defs */ - continue; - - cp = wp->name; - nChars += sprintf(pPad + nChars, "%s", cp); - - if (nChars > 70) - { - pPad[nChars] = '\0'; - nChars = 0; - y++; - if(y>23) { - y=0; - vmTextOut(pVM, "--- Press Enter to continue ---",0); - getchar(); - vmTextOut(pVM,"\r",0); - } - vmTextOut(pVM, pPad, 1); - } - else - { - len = nCOLWIDTH - nChars % nCOLWIDTH; - while (len-- > 0) - pPad[nChars++] = ' '; - } - - if (nChars > 70) - { - pPad[nChars] = '\0'; - nChars = 0; - y++; - if(y>23) { - y=0; - vmTextOut(pVM, "--- Press Enter to continue ---",0); - getchar(); - vmTextOut(pVM,"\r",0); - } - vmTextOut(pVM, pPad, 1); - } - } - } - - if (nChars > 0) - { - pPad[nChars] = '\0'; - nChars = 0; - vmTextOut(pVM, pPad, 1); - } - - sprintf(pVM->pad, "Dictionary: %d words, %ld cells used of %lu total", - nWords, dp->here - dp->dict, dp->size); - vmTextOut(pVM, pVM->pad, 1); - return; -} - - -static void listEnv(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetEnv(); - FICL_HASH *pHash = dp->pForthWords; - FICL_WORD *wp; - unsigned i; - int nWords = 0; - - for (i = 0; i < pHash->size; i++) - { - for (wp = pHash->table[i]; wp != NULL; wp = wp->link, nWords++) - { - vmTextOut(pVM, wp->name, 1); - } - } - - sprintf(pVM->pad, "Environment: %d words, %ld cells used of %lu total", - nWords, dp->here - dp->dict, dp->size); - vmTextOut(pVM, pVM->pad, 1); - return; -} - - -/************************************************************************** - l o g i c a n d c o m p a r i s o n s -** -**************************************************************************/ - -static void zeroEquals(FICL_VM *pVM) -{ - CELL c; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - c.i = FICL_BOOL(stackPopINT32(pVM->pStack) == 0); - stackPush(pVM->pStack, c); - return; -} - -static void zeroLess(FICL_VM *pVM) -{ - CELL c; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - c.i = FICL_BOOL(stackPopINT32(pVM->pStack) < 0); - stackPush(pVM->pStack, c); - return; -} - -static void zeroGreater(FICL_VM *pVM) -{ - CELL c; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - c.i = FICL_BOOL(stackPopINT32(pVM->pStack) > 0); - stackPush(pVM->pStack, c); - return; -} - -static void isEqual(FICL_VM *pVM) -{ - CELL x, y; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - x = stackPop(pVM->pStack); - y = stackPop(pVM->pStack); - stackPushINT32(pVM->pStack, FICL_BOOL(x.i == y.i)); - return; -} - -static void isLess(FICL_VM *pVM) -{ - CELL x, y; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - y = stackPop(pVM->pStack); - x = stackPop(pVM->pStack); - stackPushINT32(pVM->pStack, FICL_BOOL(x.i < y.i)); - return; -} - -static void uIsLess(FICL_VM *pVM) -{ - UNS32 u1, u2; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - u2 = stackPopUNS32(pVM->pStack); - u1 = stackPopUNS32(pVM->pStack); - stackPushINT32(pVM->pStack, FICL_BOOL(u1 < u2)); - return; -} - -static void isGreater(FICL_VM *pVM) -{ - CELL x, y; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - y = stackPop(pVM->pStack); - x = stackPop(pVM->pStack); - stackPushINT32(pVM->pStack, FICL_BOOL(x.i > y.i)); - return; -} - -static void bitwiseAnd(FICL_VM *pVM) -{ - CELL x, y; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - x = stackPop(pVM->pStack); - y = stackPop(pVM->pStack); - stackPushINT32(pVM->pStack, x.i & y.i); - return; -} - -static void bitwiseOr(FICL_VM *pVM) -{ - CELL x, y; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - x = stackPop(pVM->pStack); - y = stackPop(pVM->pStack); - stackPushINT32(pVM->pStack, x.i | y.i); - return; -} - -static void bitwiseXor(FICL_VM *pVM) -{ - CELL x, y; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - x = stackPop(pVM->pStack); - y = stackPop(pVM->pStack); - stackPushINT32(pVM->pStack, x.i ^ y.i); - return; -} - -static void bitwiseNot(FICL_VM *pVM) -{ - CELL x; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - x = stackPop(pVM->pStack); - stackPushINT32(pVM->pStack, ~x.i); - return; -} - - -/************************************************************************** - D o / L o o p -** do -- IMMEDIATE COMPILE ONLY -** Compiles code to initialize a loop: compile (do), -** allot space to hold the "leave" address, push a branch -** target address for the loop. -** (do) -- runtime for "do" -** pops index and limit from the p stack and moves them -** to the r stack, then skips to the loop body. -** loop -- IMMEDIATE COMPILE ONLY -** +loop -** Compiles code for the test part of a loop: -** compile (loop), resolve forward branch from "do", and -** copy "here" address to the "leave" address allotted by "do" -** i,j,k -- COMPILE ONLY -** Runtime: Push loop indices on param stack (i is innermost loop...) -** Note: each loop has three values on the return stack: -** ( R: leave limit index ) -** "leave" is the absolute address of the next cell after the loop -** limit and index are the loop control variables. -** leave -- COMPILE ONLY -** Runtime: pop the loop control variables, then pop the -** "leave" address and jump (absolute) there. -**************************************************************************/ - -static void doCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pDoParen); - - dictAppendCell(dp, LVALUEtoCELL(pDoParen)); - /* - ** Allot space for a pointer to the end - ** of the loop - "leave" uses this... - */ - markBranch(dp, pVM, leaveTag); - dictAppendUNS32(dp, 0); - /* - ** Mark location of head of loop... - */ - markBranch(dp, pVM, doTag); - - return; -} - - -static void doParen(FICL_VM *pVM) -{ - CELL index, limit; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - index = stackPop(pVM->pStack); - limit = stackPop(pVM->pStack); - - /* copy "leave" target addr to stack */ - stackPushPtr(pVM->rStack, *(pVM->ip++)); - stackPush(pVM->rStack, limit); - stackPush(pVM->rStack, index); - - return; -} - - -static void qDoCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pQDoParen); - - dictAppendCell(dp, LVALUEtoCELL(pQDoParen)); - /* - ** Allot space for a pointer to the end - ** of the loop - "leave" uses this... - */ - markBranch(dp, pVM, leaveTag); - dictAppendUNS32(dp, 0); - /* - ** Mark location of head of loop... - */ - markBranch(dp, pVM, doTag); - - return; -} - - -static void qDoParen(FICL_VM *pVM) -{ - CELL index, limit; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - index = stackPop(pVM->pStack); - limit = stackPop(pVM->pStack); - - /* copy "leave" target addr to stack */ - stackPushPtr(pVM->rStack, *(pVM->ip++)); - - if (limit.u == index.u) - { - vmPopIP(pVM); - } - else - { - stackPush(pVM->rStack, limit); - stackPush(pVM->rStack, index); - } - - return; -} - - -/* -** Runtime code to break out of a do..loop construct -** Drop the loop control variables; the branch address -** past "loop" is next on the return stack. -*/ -static void leaveCo(FICL_VM *pVM) -{ - /* almost unloop */ - stackDrop(pVM->rStack, 2); - /* exit */ - vmPopIP(pVM); - return; -} - - -static void unloopCo(FICL_VM *pVM) -{ - stackDrop(pVM->rStack, 3); - return; -} - - -static void loopCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pLoopParen); - - dictAppendCell(dp, LVALUEtoCELL(pLoopParen)); - resolveBackBranch(dp, pVM, doTag); - resolveAbsBranch(dp, pVM, leaveTag); - return; -} - - -static void plusLoopCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pPLoopParen); - - dictAppendCell(dp, LVALUEtoCELL(pPLoopParen)); - resolveBackBranch(dp, pVM, doTag); - resolveAbsBranch(dp, pVM, leaveTag); - return; -} - - -static void loopParen(FICL_VM *pVM) -{ - INT32 index = stackGetTop(pVM->rStack).i; - INT32 limit = stackFetch(pVM->rStack, 1).i; - - index++; - - if (index >= limit) - { - stackDrop(pVM->rStack, 3); /* nuke the loop indices & "leave" addr */ - vmBranchRelative(pVM, 1); /* fall through the loop */ - } - else - { /* update index, branch to loop head */ - stackSetTop(pVM->rStack, LVALUEtoCELL(index)); - vmBranchRelative(pVM, *(int *)(pVM->ip)); - } - - return; -} - - -static void plusLoopParen(FICL_VM *pVM) -{ - INT32 index = stackGetTop(pVM->rStack).i; - INT32 limit = stackFetch(pVM->rStack, 1).i; - INT32 increment = stackPop(pVM->pStack).i; - int flag; - - index += increment; - - if (increment < 0) - flag = (index < limit); - else - flag = (index >= limit); - - if (flag) - { - stackDrop(pVM->rStack, 3); /* nuke the loop indices & "leave" addr */ - vmBranchRelative(pVM, 1); /* fall through the loop */ - } - else - { /* update index, branch to loop head */ - stackSetTop(pVM->rStack, LVALUEtoCELL(index)); - vmBranchRelative(pVM, *(int *)(pVM->ip)); - } - - return; -} - - -static void loopICo(FICL_VM *pVM) -{ - CELL index = stackGetTop(pVM->rStack); - stackPush(pVM->pStack, index); - - return; -} - - -static void loopJCo(FICL_VM *pVM) -{ - CELL index = stackFetch(pVM->rStack, 3); - stackPush(pVM->pStack, index); - - return; -} - - -static void loopKCo(FICL_VM *pVM) -{ - CELL index = stackFetch(pVM->rStack, 6); - stackPush(pVM->pStack, index); - - return; -} - - -/************************************************************************** - r e t u r n s t a c k -** -**************************************************************************/ - -static void toRStack(FICL_VM *pVM) -{ - stackPush(pVM->rStack, stackPop(pVM->pStack)); - return; -} - -static void fromRStack(FICL_VM *pVM) -{ - stackPush(pVM->pStack, stackPop(pVM->rStack)); - return; -} - -static void fetchRStack(FICL_VM *pVM) -{ - stackPush(pVM->pStack, stackGetTop(pVM->rStack)); - return; -} - - -/************************************************************************** - v a r i a b l e -** -**************************************************************************/ - -static void variableParen(FICL_VM *pVM) -{ - FICL_WORD *fw = pVM->runningWord; - stackPushPtr(pVM->pStack, fw->param); - return; -} - - -static void variable(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - STRINGINFO si = vmGetWord(pVM); - - dictAppendWord2(dp, si, variableParen, FW_DEFAULT); - dictAllotCells(dp, 1); - return; -} - - - -/************************************************************************** - b a s e & f r i e n d s -** -**************************************************************************/ - -static void base(FICL_VM *pVM) -{ - CELL *pBase = (CELL *)(&pVM->base); - stackPush(pVM->pStack, LVALUEtoCELL(pBase)); - return; -} - - -static void decimal(FICL_VM *pVM) -{ - pVM->base = 10; - return; -} - - -static void hex(FICL_VM *pVM) -{ - pVM->base = 16; - return; -} - - -/************************************************************************** - a l l o t & f r i e n d s -** -**************************************************************************/ - -static void allot(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - INT32 i = stackPopINT32(pVM->pStack); -#if FICL_ROBUST - dictCheck(dp, pVM, i); -#endif - dictAllot(dp, i); - return; -} - - -static void here(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - stackPushPtr(pVM->pStack, dp->here); - return; -} - - -static void comma(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - CELL c = stackPop(pVM->pStack); - dictAppendCell(dp, c); - return; -} - - -static void cComma(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - char c = (char)stackPopINT32(pVM->pStack); - dictAppendChar(dp, c); - return; -} - - -static void cells(FICL_VM *pVM) -{ - INT32 i = stackPopINT32(pVM->pStack); - stackPushINT32(pVM->pStack, i * (INT32)sizeof (CELL)); - return; -} - - -static void cellPlus(FICL_VM *pVM) -{ - char *cp = stackPopPtr(pVM->pStack); - stackPushPtr(pVM->pStack, cp + sizeof (CELL)); - return; -} - - -/************************************************************************** - t i c k -** tick CORE ( "<spaces>name" -- xt ) -** Skip leading space delimiters. Parse name delimited by a space. Find -** name and return xt, the execution token for name. An ambiguous condition -** exists if name is not found. -**************************************************************************/ -static void tick(FICL_VM *pVM) -{ - FICL_WORD *pFW = NULL; - STRINGINFO si = vmGetWord(pVM); - - pFW = dictLookup(ficlGetDict(), si); - if (!pFW) - { - int i = SI_COUNT(si); - vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si)); - } - stackPushPtr(pVM->pStack, pFW); - return; -} - - -static void bracketTickCoIm(FICL_VM *pVM) -{ - tick(pVM); - literalIm(pVM); - - return; -} - - -/************************************************************************** - p o s t p o n e -** Lookup the next word in the input stream and compile code to -** insert it into definitions created by the resulting word -** (defers compilation, even of immediate words) -**************************************************************************/ - -static void postponeCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - FICL_WORD *pFW; - assert(pComma); - - tick(pVM); - pFW = stackGetTop(pVM->pStack).p; - if (wordIsImmediate(pFW)) - { - dictAppendCell(dp, stackPop(pVM->pStack)); - } - else - { - literalIm(pVM); - dictAppendCell(dp, LVALUEtoCELL(pComma)); - } - - return; -} - - - -/************************************************************************** - e x e c u t e -** Pop an execution token (pointer to a word) off the stack and -** run it -**************************************************************************/ - -static void execute(FICL_VM *pVM) -{ - FICL_WORD *pFW; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - - pFW = stackPopPtr(pVM->pStack); - vmExecute(pVM, pFW); - - return; -} - - -/************************************************************************** - i m m e d i a t e -** Make the most recently compiled word IMMEDIATE -- it executes even -** in compile state (most often used for control compiling words -** such as IF, THEN, etc) -**************************************************************************/ - -static void immediate(FICL_VM *pVM) -{ - IGNORE(pVM); - dictSetImmediate(ficlGetDict()); - return; -} - - -static void compileOnly(FICL_VM *pVM) -{ - IGNORE(pVM); - dictSetFlags(ficlGetDict(), FW_COMPILE, 0); - return; -} - - -/************************************************************************** - d o t Q u o t e -** IMMEDIATE word that compiles a string literal for later display -** Compile stringLit, then copy the bytes of the string from the TIB -** to the dictionary. Backpatch the count byte and align the dictionary. -** -** stringlit: Fetch the count from the dictionary, then push the address -** and count on the stack. Finally, update ip to point to the first -** aligned address after the string text. -**************************************************************************/ - -static void stringLit(FICL_VM *pVM) -{ - FICL_STRING *sp = (FICL_STRING *)(pVM->ip); - FICL_COUNT count = sp->count; - char *cp = sp->text; - stackPushPtr(pVM->pStack, cp); - stackPushUNS32(pVM->pStack, count); - cp += count + 1; - cp = alignPtr(cp); - pVM->ip = (IPTYPE)(void *)cp; - return; -} - -static void dotQuoteCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - dictAppendCell(dp, LVALUEtoCELL(pStringLit)); - dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"'); - dictAlign(dp); - dictAppendCell(dp, LVALUEtoCELL(pType)); - return; -} - - -static void dotParen(FICL_VM *pVM) -{ - char *pSrc = vmGetInBuf(pVM); - char *pDest = pVM->pad; - char ch; - - pSrc = skipSpace(pSrc); - - for (ch = *pSrc; (ch != '\0') && (ch != ')'); ch = *++pSrc) - *pDest++ = ch; - - *pDest = '\0'; - if (ch == ')') - pSrc++; - - vmTextOut(pVM, pVM->pad, 0); - vmUpdateTib(pVM, pSrc); - - return; -} - - -/************************************************************************** - s l i t e r a l -** STRING -** Interpretation: Interpretation semantics for this word are undefined. -** Compilation: ( c-addr1 u -- ) -** Append the run-time semantics given below to the current definition. -** Run-time: ( -- c-addr2 u ) -** Return c-addr2 u describing a string consisting of the characters -** specified by c-addr1 u during compilation. A program shall not alter -** the returned string. -**************************************************************************/ -static void sLiteralCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - char *cp, *cpDest; - UNS32 u; - u = stackPopUNS32(pVM->pStack); - cp = stackPopPtr(pVM->pStack); - - dictAppendCell(dp, LVALUEtoCELL(pStringLit)); - cpDest = (char *) dp->here; - *cpDest++ = (char) u; - - for (; u > 0; --u) - { - *cpDest++ = *cp++; - } - - *cpDest++ = 0; - dp->here = PTRtoCELL alignPtr(cpDest); - return; -} - - -/************************************************************************** - s t a t e -** Return the address of the VM's state member (must be sized the -** same as a CELL for this reason) -**************************************************************************/ -static void state(FICL_VM *pVM) -{ - stackPushPtr(pVM->pStack, &pVM->state); - return; -} - - -/************************************************************************** - c r e a t e . . . d o e s > -** Make a new word in the dictionary with the run-time effect of -** a variable (push my address), but with extra space allotted -** for use by does> . -**************************************************************************/ - -static void createParen(FICL_VM *pVM) -{ - CELL *pCell = pVM->runningWord->param; - stackPushPtr(pVM->pStack, pCell+1); - return; -} - - -static void create(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - STRINGINFO si = vmGetWord(pVM); - - dictAppendWord2(dp, si, createParen, FW_DEFAULT); - dictAllotCells(dp, 1); - return; -} - - -static void doDoes(FICL_VM *pVM) -{ - CELL *pCell = pVM->runningWord->param; - IPTYPE tempIP = (IPTYPE)((*pCell).p); - stackPushPtr(pVM->pStack, pCell+1); - vmPushIP(pVM, tempIP); - return; -} - - -static void doesParen(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - dp->smudge->code = doDoes; - dp->smudge->param[0] = LVALUEtoCELL(pVM->ip); - vmPopIP(pVM); - return; -} - - -static void doesCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); -#if FICL_WANT_LOCALS - assert(pUnLinkParen); - if (nLocals > 0) - { - FICL_DICT *pLoc = ficlGetLoc(); - dictEmpty(pLoc, pLoc->pForthWords->size); - dictAppendCell(dp, LVALUEtoCELL(pUnLinkParen)); - } - - nLocals = 0; -#endif - IGNORE(pVM); - - dictAppendCell(dp, LVALUEtoCELL(pDoesParen)); - return; -} - - -/************************************************************************** - t o b o d y -** to-body CORE ( xt -- a-addr ) -** a-addr is the data-field address corresponding to xt. An ambiguous -** condition exists if xt is not for a word defined via CREATE. -**************************************************************************/ -static void toBody(FICL_VM *pVM) -{ - FICL_WORD *pFW = stackPopPtr(pVM->pStack); - stackPushPtr(pVM->pStack, pFW->param + 1); - return; -} - - -/* -** from-body ficl ( a-addr -- xt ) -** Reverse effect of >body -*/ -static void fromBody(FICL_VM *pVM) -{ - char *ptr = (char *) stackPopPtr(pVM->pStack) - sizeof (FICL_WORD); - stackPushPtr(pVM->pStack, ptr); - return; -} - - -/* -** >name ficl ( xt -- c-addr u ) -** Push the address and length of a word's name given its address -** xt. -*/ -static void toName(FICL_VM *pVM) -{ - FICL_WORD *pFW = stackPopPtr(pVM->pStack); - stackPushPtr(pVM->pStack, pFW->name); - stackPushUNS32(pVM->pStack, pFW->nName); - return; -} - - -/************************************************************************** - l b r a c k e t e t c -** -**************************************************************************/ - -static void lbracketCoIm(FICL_VM *pVM) -{ - pVM->state = INTERPRET; - return; -} - - -static void rbracket(FICL_VM *pVM) -{ - pVM->state = COMPILE; - return; -} - - -/************************************************************************** - p i c t u r e d n u m e r i c w o r d s -** -** less-number-sign CORE ( -- ) -** Initialize the pictured numeric output conversion process. -** (clear the pad) -**************************************************************************/ -static void lessNumberSign(FICL_VM *pVM) -{ - FICL_STRING *sp = PTRtoSTRING pVM->pad; - sp->count = 0; - return; -} - -/* -** number-sign CORE ( ud1 -- ud2 ) -** Divide ud1 by the number in BASE giving the quotient ud2 and the remainder -** n. (n is the least-significant digit of ud1.) Convert n to external form -** and add the resulting character to the beginning of the pictured numeric -** output string. An ambiguous condition exists if # executes outside of a -** <# #> delimited number conversion. -*/ -static void numberSign(FICL_VM *pVM) -{ - FICL_STRING *sp = PTRtoSTRING pVM->pad; - UNS64 u; - UNS16 rem; - - u = u64Pop(pVM->pStack); - rem = m64UMod(&u, (UNS16)(pVM->base)); - sp->text[sp->count++] = digit_to_char(rem); - u64Push(pVM->pStack, u); - return; -} - -/* -** number-sign-greater CORE ( xd -- c-addr u ) -** Drop xd. Make the pictured numeric output string available as a character -** string. c-addr and u specify the resulting character string. A program -** may replace characters within the string. -*/ -static void numberSignGreater(FICL_VM *pVM) -{ - FICL_STRING *sp = PTRtoSTRING pVM->pad; - sp->text[sp->count] = '\0'; - strrev(sp->text); - stackDrop(pVM->pStack, 2); - stackPushPtr(pVM->pStack, sp->text); - stackPushUNS32(pVM->pStack, sp->count); - return; -} - -/* -** number-sign-s CORE ( ud1 -- ud2 ) -** Convert one digit of ud1 according to the rule for #. Continue conversion -** until the quotient is zero. ud2 is zero. An ambiguous condition exists if -** #S executes outside of a <# #> delimited number conversion. -** TO DO: presently does not use ud1 hi cell - use it! -*/ -static void numberSignS(FICL_VM *pVM) -{ - FICL_STRING *sp = PTRtoSTRING pVM->pad; - UNS64 u; - UNS16 rem; - - u = u64Pop(pVM->pStack); - - do - { - rem = m64UMod(&u, (UNS16)(pVM->base)); - sp->text[sp->count++] = digit_to_char(rem); - } - while (u.hi || u.lo); - - u64Push(pVM->pStack, u); - return; -} - -/* -** HOLD CORE ( char -- ) -** Add char to the beginning of the pictured numeric output string. An ambiguous -** condition exists if HOLD executes outside of a <# #> delimited number conversion. -*/ -static void hold(FICL_VM *pVM) -{ - FICL_STRING *sp = PTRtoSTRING pVM->pad; - int i = stackPopINT32(pVM->pStack); - sp->text[sp->count++] = (char) i; - return; -} - -/* -** SIGN CORE ( n -- ) -** If n is negative, add a minus sign to the beginning of the pictured -** numeric output string. An ambiguous condition exists if SIGN -** executes outside of a <# #> delimited number conversion. -*/ -static void sign(FICL_VM *pVM) -{ - FICL_STRING *sp = PTRtoSTRING pVM->pad; - int i = stackPopINT32(pVM->pStack); - if (i < 0) - sp->text[sp->count++] = '-'; - return; -} - - -/************************************************************************** - t o N u m b e r -** to-number CORE ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 ) -** ud2 is the unsigned result of converting the characters within the -** string specified by c-addr1 u1 into digits, using the number in BASE, -** and adding each into ud1 after multiplying ud1 by the number in BASE. -** Conversion continues left-to-right until a character that is not -** convertible, including any + or -, is encountered or the string is -** entirely converted. c-addr2 is the location of the first unconverted -** character or the first character past the end of the string if the string -** was entirely converted. u2 is the number of unconverted characters in the -** string. An ambiguous condition exists if ud2 overflows during the -** conversion. -** TO DO: presently does not use ud1 hi cell - use it! -**************************************************************************/ -static void toNumber(FICL_VM *pVM) -{ - UNS32 count = stackPopUNS32(pVM->pStack); - char *cp = (char *)stackPopPtr(pVM->pStack); - UNS64 accum; - UNS32 base = pVM->base; - UNS32 ch; - UNS32 digit; - - accum = u64Pop(pVM->pStack); - - for (ch = *cp; count > 0; ch = *++cp, count--) - { - if (ch < '0') - break; - - digit = ch - '0'; - - if (digit > 9) - digit = tolower(ch) - 'a' + 10; - /* - ** Note: following test also catches chars between 9 and a - ** because 'digit' is unsigned! - */ - if (digit >= base) - break; - - accum = m64Mac(accum, base, digit); - } - - u64Push(pVM->pStack, accum); - stackPushPtr (pVM->pStack, cp); - stackPushUNS32(pVM->pStack, count); - - return; -} - - - -/************************************************************************** - q u i t & a b o r t -** quit CORE ( -- ) ( R: i*x -- ) -** Empty the return stack, store zero in SOURCE-ID if it is present, make -** the user input device the input source, and enter interpretation state. -** Do not display a message. Repeat the following: -** -** Accept a line from the input source into the input buffer, set >IN to -** zero, and interpret. -** Display the implementation-defined system prompt if in -** interpretation state, all processing has been completed, and no -** ambiguous condition exists. -**************************************************************************/ - -static void quit(FICL_VM *pVM) -{ - vmThrow(pVM, VM_QUIT); - return; -} - - -static void ficlAbort(FICL_VM *pVM) -{ - vmThrow(pVM, VM_ERREXIT); - return; -} - - -/************************************************************************** - a c c e p t -** accept CORE ( c-addr +n1 -- +n2 ) -** Receive a string of at most +n1 characters. An ambiguous condition -** exists if +n1 is zero or greater than 32,767. Display graphic characters -** as they are received. A program that depends on the presence or absence -** of non-graphic characters in the string has an environmental dependency. -** The editing functions, if any, that the system performs in order to -** construct the string are implementation-defined. -** -** (Although the standard text doesn't say so, I assume that the intent -** of 'accept' is to store the string at the address specified on -** the stack.) -** Implementation: if there's more text in the TIB, use it. Otherwise -** throw out for more text. Copy characters up to the max count into the -** address given, and return the number of actual characters copied. -**************************************************************************/ -static void accept(FICL_VM *pVM) -{ - UNS32 count, len; - char *cp; - char *pBuf = vmGetInBuf(pVM); - - len = strlen(pBuf); - if (len == 0) - vmThrow(pVM, VM_RESTART); - /* OK - now we have something in the text buffer - use it */ - count = stackPopUNS32(pVM->pStack); - cp = stackPopPtr(pVM->pStack); - - strncpy(cp, vmGetInBuf(pVM), count); - len = (count < len) ? count : len; - pBuf += len; - vmUpdateTib(pVM, pBuf); - stackPushUNS32(pVM->pStack, len); - - return; -} - - -/************************************************************************** - a l i g n -** 6.1.0705 ALIGN CORE ( -- ) -** If the data-space pointer is not aligned, reserve enough space to -** align it. -**************************************************************************/ -static void align(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - IGNORE(pVM); - dictAlign(dp); - return; -} - - -/************************************************************************** - a l i g n e d -** -**************************************************************************/ -static void aligned(FICL_VM *pVM) -{ - void *addr = stackPopPtr(pVM->pStack); - stackPushPtr(pVM->pStack, alignPtr(addr)); - return; -} - - -/************************************************************************** - b e g i n & f r i e n d s -** Indefinite loop control structures -** A.6.1.0760 BEGIN -** Typical use: -** : X ... BEGIN ... test UNTIL ; -** or -** : X ... BEGIN ... test WHILE ... REPEAT ; -**************************************************************************/ -static void beginCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - markBranch(dp, pVM, beginTag); - return; -} - -static void untilCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pIfParen); - - dictAppendCell(dp, LVALUEtoCELL(pIfParen)); - resolveBackBranch(dp, pVM, beginTag); - return; -} - -static void whileCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pIfParen); - - dictAppendCell(dp, LVALUEtoCELL(pIfParen)); - markBranch(dp, pVM, whileTag); - twoSwap(pVM); - dictAppendUNS32(dp, 1); - return; -} - -static void repeatCoIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - assert(pBranchParen); - dictAppendCell(dp, LVALUEtoCELL(pBranchParen)); - - /* expect "begin" branch marker */ - resolveBackBranch(dp, pVM, beginTag); - /* expect "while" branch marker */ - resolveForwardBranch(dp, pVM, whileTag); - return; -} - - -/************************************************************************** - c h a r & f r i e n d s -** 6.1.0895 CHAR CORE ( "<spaces>name" -- char ) -** Skip leading space delimiters. Parse name delimited by a space. -** Put the value of its first character onto the stack. -** -** bracket-char CORE -** Interpretation: Interpretation semantics for this word are undefined. -** Compilation: ( "<spaces>name" -- ) -** Skip leading space delimiters. Parse name delimited by a space. -** Append the run-time semantics given below to the current definition. -** Run-time: ( -- char ) -** Place char, the value of the first character of name, on the stack. -**************************************************************************/ -static void ficlChar(FICL_VM *pVM) -{ - STRINGINFO si = vmGetWord(pVM); - stackPushUNS32(pVM->pStack, (UNS32)(si.cp[0])); - - return; -} - -static void charCoIm(FICL_VM *pVM) -{ - ficlChar(pVM); - literalIm(pVM); - return; -} - -/************************************************************************** - c h a r P l u s -** char-plus CORE ( c-addr1 -- c-addr2 ) -** Add the size in address units of a character to c-addr1, giving c-addr2. -**************************************************************************/ -static void charPlus(FICL_VM *pVM) -{ - char *cp = stackPopPtr(pVM->pStack); - stackPushPtr(pVM->pStack, cp + 1); - return; -} - -/************************************************************************** - c h a r s -** chars CORE ( n1 -- n2 ) -** n2 is the size in address units of n1 characters. -** For most processors, this function can be a no-op. To guarantee -** portability, we'll multiply by sizeof (char). -**************************************************************************/ -#if defined (_M_IX86) -#pragma warning(disable: 4127) -#endif -static void ficlChars(FICL_VM *pVM) -{ - if (sizeof (char) > 1) - { - INT32 i = stackPopINT32(pVM->pStack); - stackPushINT32(pVM->pStack, i * sizeof (char)); - } - /* otherwise no-op! */ - return; -} -#if defined (_M_IX86) -#pragma warning(default: 4127) -#endif - - -/************************************************************************** - c o u n t -** COUNT CORE ( c-addr1 -- c-addr2 u ) -** Return the character string specification for the counted string stored -** at c-addr1. c-addr2 is the address of the first character after c-addr1. -** u is the contents of the character at c-addr1, which is the length in -** characters of the string at c-addr2. -**************************************************************************/ -static void count(FICL_VM *pVM) -{ - FICL_STRING *sp = stackPopPtr(pVM->pStack); - stackPushPtr(pVM->pStack, sp->text); - stackPushUNS32(pVM->pStack, sp->count); - return; -} - -/************************************************************************** - e n v i r o n m e n t ? -** environment-query CORE ( c-addr u -- false | i*x true ) -** c-addr is the address of a character string and u is the string's -** character count. u may have a value in the range from zero to an -** implementation-defined maximum which shall not be less than 31. The -** character string should contain a keyword from 3.2.6 Environmental -** queries or the optional word sets to be checked for correspondence -** with an attribute of the present environment. If the system treats the -** attribute as unknown, the returned flag is false; otherwise, the flag -** is true and the i*x returned is of the type specified in the table for -** the attribute queried. -**************************************************************************/ -static void environmentQ(FICL_VM *pVM) -{ - FICL_DICT *envp = ficlGetEnv(); - FICL_COUNT len = (FICL_COUNT)stackPopUNS32(pVM->pStack); - char *cp = stackPopPtr(pVM->pStack); - FICL_WORD *pFW; - STRINGINFO si; - - SI_PSZ(si, cp); - pFW = dictLookup(envp, si); - - if (pFW != NULL) - { - vmExecute(pVM, pFW); - stackPushINT32(pVM->pStack, FICL_TRUE); - } - else - { - stackPushINT32(pVM->pStack, FICL_FALSE); - } - - return; -} - -/************************************************************************** - e v a l u a t e -** EVALUATE CORE ( i*x c-addr u -- j*x ) -** Save the current input source specification. Store minus-one (-1) in -** SOURCE-ID if it is present. Make the string described by c-addr and u -** both the input source and input buffer, set >IN to zero, and interpret. -** When the parse area is empty, restore the prior input source -** specification. Other stack effects are due to the words EVALUATEd. -** -** DEFICIENCY: this version does not handle errors or restarts. -**************************************************************************/ -static void evaluate(FICL_VM *pVM) -{ - UNS32 count = stackPopUNS32(pVM->pStack); - char *cp = stackPopPtr(pVM->pStack); - CELL id; - - IGNORE(count); - id = pVM->sourceID; - pVM->sourceID.i = -1; - vmPushIP(pVM, &pInterpret); - ficlExec(pVM, cp); - vmPopIP(pVM); - pVM->sourceID = id; - return; -} - - -/************************************************************************** - s t r i n g q u o t e -** Intrpreting: get string delimited by a quote from the input stream, -** copy to a scratch area, and put its count and address on the stack. -** Compiling: compile code to push the address and count of a string -** literal, compile the string from the input stream, and align the dict -** pointer. -**************************************************************************/ -static void stringQuoteIm(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - if (pVM->state == INTERPRET) - { - FICL_STRING *sp = (FICL_STRING *) dp->here; - vmGetString(pVM, sp, '\"'); - stackPushPtr(pVM->pStack, sp->text); - stackPushUNS32(pVM->pStack, sp->count); - } - else /* COMPILE state */ - { - dictAppendCell(dp, LVALUEtoCELL(pStringLit)); - dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"'); - dictAlign(dp); - } - - return; -} - -/************************************************************************** - t y p e -** Pop count and char address from stack and print the designated string. -**************************************************************************/ -static void type(FICL_VM *pVM) -{ - UNS32 count = stackPopUNS32(pVM->pStack); - char *cp = stackPopPtr(pVM->pStack); - - /* - ** Since we don't have an output primitive for a counted string - ** (oops), make sure the string is null terminated. If not, copy - ** and terminate it. - */ - /* XXX Uses free space on top of dictionary. Is it guaranteed - * XXX to always fit? (abial) - */ - if (cp[count] != '\0') - { - char *pDest = (char *)ficlGetDict()->here; - if (cp != pDest) - strncpy(pDest, cp, count); - - pDest[count] = '\0'; - cp = pDest; - } - - vmTextOut(pVM, cp, 0); - return; -} - -/************************************************************************** - w o r d -** word CORE ( char "<chars>ccc<char>" -- c-addr ) -** Skip leading delimiters. Parse characters ccc delimited by char. An -** ambiguous condition exists if the length of the parsed string is greater -** than the implementation-defined length of a counted string. -** -** c-addr is the address of a transient region containing the parsed word -** as a counted string. If the parse area was empty or contained no -** characters other than the delimiter, the resulting string has a zero -** length. A space, not included in the length, follows the string. A -** program may replace characters within the string. -** NOTE! Ficl also NULL-terminates the dest string. -**************************************************************************/ -static void ficlWord(FICL_VM *pVM) -{ - FICL_STRING *sp = (FICL_STRING *)pVM->pad; - char delim = (char)stackPopINT32(pVM->pStack); - STRINGINFO si; - - si = vmParseString(pVM, delim); - - if (SI_COUNT(si) > nPAD-1) - SI_SETLEN(si, nPAD-1); - - sp->count = (FICL_COUNT)SI_COUNT(si); - strncpy(sp->text, SI_PTR(si), SI_COUNT(si)); - strcat(sp->text, " "); - - stackPushPtr(pVM->pStack, sp); - return; -} - - -/************************************************************************** - p a r s e - w o r d -** ficl PARSE-WORD ( <spaces>name -- c-addr u ) -** Skip leading spaces and parse name delimited by a space. c-addr is the -** address within the input buffer and u is the length of the selected -** string. If the parse area is empty, the resulting string has a zero length. -**************************************************************************/ -static void parseNoCopy(FICL_VM *pVM) -{ - STRINGINFO si = vmGetWord0(pVM); - stackPushPtr(pVM->pStack, SI_PTR(si)); - stackPushUNS32(pVM->pStack, SI_COUNT(si)); - return; -} - - -/************************************************************************** - p a r s e -** CORE EXT ( char "ccc<char>" -- c-addr u ) -** Parse ccc delimited by the delimiter char. -** c-addr is the address (within the input buffer) and u is the length of -** the parsed string. If the parse area was empty, the resulting string has -** a zero length. -** NOTE! PARSE differs from WORD: it does not skip leading delimiters. -**************************************************************************/ -static void parse(FICL_VM *pVM) -{ - char *pSrc = vmGetInBuf(pVM); - char *cp; - UNS32 count; - char delim = (char)stackPopINT32(pVM->pStack); - - cp = pSrc; /* mark start of text */ - - while ((*pSrc != delim) && (*pSrc != '\0')) - pSrc++; /* find next delimiter or end */ - - count = pSrc - cp; /* set length of result */ - - if (*pSrc == delim) /* gobble trailing delimiter */ - pSrc++; - - vmUpdateTib(pVM, pSrc); - stackPushPtr(pVM->pStack, cp); - stackPushUNS32(pVM->pStack, count); - return; -} - - -/************************************************************************** - f i l l -** CORE ( c-addr u char -- ) -** If u is greater than zero, store char in each of u consecutive -** characters of memory beginning at c-addr. -**************************************************************************/ -static void fill(FICL_VM *pVM) -{ - char ch = (char)stackPopINT32(pVM->pStack); - UNS32 u = stackPopUNS32(pVM->pStack); - char *cp = (char *)stackPopPtr(pVM->pStack); - - while (u > 0) - { - *cp++ = ch; - u--; - } - - return; -} - - -/************************************************************************** - f i n d -** FIND CORE ( c-addr -- c-addr 0 | xt 1 | xt -1 ) -** Find the definition named in the counted string at c-addr. If the -** definition is not found, return c-addr and zero. If the definition is -** found, return its execution token xt. If the definition is immediate, -** also return one (1), otherwise also return minus-one (-1). For a given -** string, the values returned by FIND while compiling may differ from -** those returned while not compiling. -**************************************************************************/ -static void find(FICL_VM *pVM) -{ - FICL_STRING *sp = stackPopPtr(pVM->pStack); - FICL_WORD *pFW; - STRINGINFO si; - - SI_PFS(si, sp); - pFW = dictLookup(ficlGetDict(), si); - if (pFW) - { - stackPushPtr(pVM->pStack, pFW); - stackPushINT32(pVM->pStack, (wordIsImmediate(pFW) ? 1 : -1)); - } - else - { - stackPushPtr(pVM->pStack, sp); - stackPushUNS32(pVM->pStack, 0); - } - return; -} - - -/************************************************************************** - f m S l a s h M o d -** f-m-slash-mod CORE ( d1 n1 -- n2 n3 ) -** Divide d1 by n1, giving the floored quotient n3 and the remainder n2. -** Input and output stack arguments are signed. An ambiguous condition -** exists if n1 is zero or if the quotient lies outside the range of a -** single-cell signed integer. -**************************************************************************/ -static void fmSlashMod(FICL_VM *pVM) -{ - INT64 d1; - INT32 n1; - INTQR qr; - - n1 = stackPopINT32(pVM->pStack); - d1 = i64Pop(pVM->pStack); - qr = m64FlooredDivI(d1, n1); - stackPushINT32(pVM->pStack, qr.rem); - stackPushINT32(pVM->pStack, qr.quot); - return; -} - - -/************************************************************************** - s m S l a s h R e m -** s-m-slash-rem CORE ( d1 n1 -- n2 n3 ) -** Divide d1 by n1, giving the symmetric quotient n3 and the remainder n2. -** Input and output stack arguments are signed. An ambiguous condition -** exists if n1 is zero or if the quotient lies outside the range of a -** single-cell signed integer. -**************************************************************************/ -static void smSlashRem(FICL_VM *pVM) -{ - INT64 d1; - INT32 n1; - INTQR qr; - - n1 = stackPopINT32(pVM->pStack); - d1 = i64Pop(pVM->pStack); - qr = m64SymmetricDivI(d1, n1); - stackPushINT32(pVM->pStack, qr.rem); - stackPushINT32(pVM->pStack, qr.quot); - return; -} - - -static void ficlMod(FICL_VM *pVM) -{ - INT64 d1; - INT32 n1; - INTQR qr; - - n1 = stackPopINT32(pVM->pStack); - d1.lo = stackPopINT32(pVM->pStack); - i64Extend(d1); - qr = m64SymmetricDivI(d1, n1); - stackPushINT32(pVM->pStack, qr.rem); - return; -} - - -/************************************************************************** - u m S l a s h M o d -** u-m-slash-mod CORE ( ud u1 -- u2 u3 ) -** Divide ud by u1, giving the quotient u3 and the remainder u2. -** All values and arithmetic are unsigned. An ambiguous condition -** exists if u1 is zero or if the quotient lies outside the range of a -** single-cell unsigned integer. -*************************************************************************/ -static void umSlashMod(FICL_VM *pVM) -{ - UNS64 ud; - UNS32 u1; - UNSQR qr; - - u1 = stackPopUNS32(pVM->pStack); - ud = u64Pop(pVM->pStack); - qr = ficlLongDiv(ud, u1); - stackPushUNS32(pVM->pStack, qr.rem); - stackPushUNS32(pVM->pStack, qr.quot); - return; -} - - -/************************************************************************** - l s h i f t -** l-shift CORE ( x1 u -- x2 ) -** Perform a logical left shift of u bit-places on x1, giving x2. -** Put zeroes into the least significant bits vacated by the shift. -** An ambiguous condition exists if u is greater than or equal to the -** number of bits in a cell. -** -** r-shift CORE ( x1 u -- x2 ) -** Perform a logical right shift of u bit-places on x1, giving x2. -** Put zeroes into the most significant bits vacated by the shift. An -** ambiguous condition exists if u is greater than or equal to the -** number of bits in a cell. -**************************************************************************/ -static void lshift(FICL_VM *pVM) -{ - UNS32 nBits = stackPopUNS32(pVM->pStack); - UNS32 x1 = stackPopUNS32(pVM->pStack); - - stackPushUNS32(pVM->pStack, x1 << nBits); - return; -} - - -static void rshift(FICL_VM *pVM) -{ - UNS32 nBits = stackPopUNS32(pVM->pStack); - UNS32 x1 = stackPopUNS32(pVM->pStack); - - stackPushUNS32(pVM->pStack, x1 >> nBits); - return; -} - - -/************************************************************************** - m S t a r -** m-star CORE ( n1 n2 -- d ) -** d is the signed product of n1 times n2. -**************************************************************************/ -static void mStar(FICL_VM *pVM) -{ - INT32 n2 = stackPopINT32(pVM->pStack); - INT32 n1 = stackPopINT32(pVM->pStack); - INT64 d; - - d = m64MulI(n1, n2); - i64Push(pVM->pStack, d); - return; -} - - -static void umStar(FICL_VM *pVM) -{ - UNS32 u2 = stackPopUNS32(pVM->pStack); - UNS32 u1 = stackPopUNS32(pVM->pStack); - UNS64 ud; - - ud = ficlLongMul(u1, u2); - u64Push(pVM->pStack, ud); - return; -} - - -/************************************************************************** - m a x & m i n -** -**************************************************************************/ -static void ficlMax(FICL_VM *pVM) -{ - INT32 n2 = stackPopINT32(pVM->pStack); - INT32 n1 = stackPopINT32(pVM->pStack); - - stackPushINT32(pVM->pStack, (n1 > n2) ? n1 : n2); - return; -} - -static void ficlMin(FICL_VM *pVM) -{ - INT32 n2 = stackPopINT32(pVM->pStack); - INT32 n1 = stackPopINT32(pVM->pStack); - - stackPushINT32(pVM->pStack, (n1 < n2) ? n1 : n2); - return; -} - - -/************************************************************************** - m o v e -** CORE ( addr1 addr2 u -- ) -** If u is greater than zero, copy the contents of u consecutive address -** units at addr1 to the u consecutive address units at addr2. After MOVE -** completes, the u consecutive address units at addr2 contain exactly -** what the u consecutive address units at addr1 contained before the move. -** NOTE! This implementation assumes that a char is the same size as -** an address unit. -**************************************************************************/ -static void move(FICL_VM *pVM) -{ - UNS32 u = stackPopUNS32(pVM->pStack); - char *addr2 = stackPopPtr(pVM->pStack); - char *addr1 = stackPopPtr(pVM->pStack); - - if (u == 0) - return; - /* - ** Do the copy carefully, so as to be - ** correct even if the two ranges overlap - */ - if (addr1 >= addr2) - { - for (; u > 0; u--) - *addr2++ = *addr1++; - } - else - { - addr2 += u-1; - addr1 += u-1; - for (; u > 0; u--) - *addr2-- = *addr1--; - } - - return; -} - - -/************************************************************************** - r e c u r s e -** -**************************************************************************/ -static void recurseCoIm(FICL_VM *pVM) -{ - FICL_DICT *pDict = ficlGetDict(); - - IGNORE(pVM); - dictAppendCell(pDict, LVALUEtoCELL(pDict->smudge)); - return; -} - - -/************************************************************************** - s t o d -** s-to-d CORE ( n -- d ) -** Convert the number n to the double-cell number d with the same -** numerical value. -**************************************************************************/ -static void sToD(FICL_VM *pVM) -{ - INT32 s = stackPopINT32(pVM->pStack); - - /* sign extend to 64 bits.. */ - stackPushINT32(pVM->pStack, s); - stackPushINT32(pVM->pStack, (s < 0) ? -1 : 0); - return; -} - - -/************************************************************************** - s o u r c e -** CORE ( -- c-addr u ) -** c-addr is the address of, and u is the number of characters in, the -** input buffer. -**************************************************************************/ -static void source(FICL_VM *pVM) -{ - stackPushPtr(pVM->pStack, pVM->tib.cp); - stackPushINT32(pVM->pStack, strlen(pVM->tib.cp)); - return; -} - - -/************************************************************************** - v e r s i o n -** non-standard... -**************************************************************************/ -static void ficlVersion(FICL_VM *pVM) -{ - vmTextOut(pVM, "ficl Version " FICL_VER, 1); - return; -} - - -/************************************************************************** - t o I n -** to-in CORE -**************************************************************************/ -static void toIn(FICL_VM *pVM) -{ - stackPushPtr(pVM->pStack, &pVM->tib.index); - return; -} - - -/************************************************************************** - d e f i n i t i o n s -** SEARCH ( -- ) -** Make the compilation word list the same as the first word list in the -** search order. Specifies that the names of subsequent definitions will -** be placed in the compilation word list. Subsequent changes in the search -** order will not affect the compilation word list. -**************************************************************************/ -static void definitions(FICL_VM *pVM) -{ - FICL_DICT *pDict = ficlGetDict(); - - assert(pDict); - if (pDict->nLists < 1) - { - vmThrowErr(pVM, "DEFINITIONS error - empty search order"); - } - - pDict->pCompile = pDict->pSearch[pDict->nLists-1]; - return; -} - - -/************************************************************************** - f o r t h - w o r d l i s t -** SEARCH ( -- wid ) -** Return wid, the identifier of the word list that includes all standard -** words provided by the implementation. This word list is initially the -** compilation word list and is part of the initial search order. -**************************************************************************/ -static void forthWordlist(FICL_VM *pVM) -{ - FICL_HASH *pHash = ficlGetDict()->pForthWords; - stackPushPtr(pVM->pStack, pHash); - return; -} - - -/************************************************************************** - g e t - c u r r e n t -** SEARCH ( -- wid ) -** Return wid, the identifier of the compilation word list. -**************************************************************************/ -static void getCurrent(FICL_VM *pVM) -{ - ficlLockDictionary(TRUE); - stackPushPtr(pVM->pStack, ficlGetDict()->pCompile); - ficlLockDictionary(FALSE); - return; -} - - -/************************************************************************** - g e t - o r d e r -** SEARCH ( -- widn ... wid1 n ) -** Returns the number of word lists n in the search order and the word list -** identifiers widn ... wid1 identifying these word lists. wid1 identifies -** the word list that is searched first, and widn the word list that is -** searched last. The search order is unaffected. -**************************************************************************/ -static void getOrder(FICL_VM *pVM) -{ - FICL_DICT *pDict = ficlGetDict(); - int nLists = pDict->nLists; - int i; - - ficlLockDictionary(TRUE); - for (i = 0; i < nLists; i++) - { - stackPushPtr(pVM->pStack, pDict->pSearch[i]); - } - - stackPushUNS32(pVM->pStack, nLists); - ficlLockDictionary(FALSE); - return; -} - - -/************************************************************************** - s e a r c h - w o r d l i s t -** SEARCH ( c-addr u wid -- 0 | xt 1 | xt -1 ) -** Find the definition identified by the string c-addr u in the word list -** identified by wid. If the definition is not found, return zero. If the -** definition is found, return its execution token xt and one (1) if the -** definition is immediate, minus-one (-1) otherwise. -**************************************************************************/ -static void searchWordlist(FICL_VM *pVM) -{ - STRINGINFO si; - UNS16 hashCode; - FICL_WORD *pFW; - FICL_HASH *pHash = stackPopPtr(pVM->pStack); - - si.count = (FICL_COUNT)stackPopUNS32(pVM->pStack); - si.cp = stackPopPtr(pVM->pStack); - hashCode = hashHashCode(si); - - ficlLockDictionary(TRUE); - pFW = hashLookup(pHash, si, hashCode); - ficlLockDictionary(FALSE); - - if (pFW) - { - stackPushPtr(pVM->pStack, pFW); - stackPushINT32(pVM->pStack, (wordIsImmediate(pFW) ? 1 : -1)); - } - else - { - stackPushUNS32(pVM->pStack, 0); - } - - return; -} - - -/************************************************************************** - s e t - c u r r e n t -** SEARCH ( wid -- ) -** Set the compilation word list to the word list identified by wid. -**************************************************************************/ -static void setCurrent(FICL_VM *pVM) -{ - FICL_HASH *pHash = stackPopPtr(pVM->pStack); - FICL_DICT *pDict = ficlGetDict(); - ficlLockDictionary(TRUE); - pDict->pCompile = pHash; - ficlLockDictionary(FALSE); - return; -} - - -/************************************************************************** - s e t - o r d e r -** SEARCH ( widn ... wid1 n -- ) -** Set the search order to the word lists identified by widn ... wid1. -** Subsequently, word list wid1 will be searched first, and word list -** widn searched last. If n is zero, empty the search order. If n is minus -** one, set the search order to the implementation-defined minimum -** search order. The minimum search order shall include the words -** FORTH-WORDLIST and SET-ORDER. A system shall allow n to -** be at least eight. -**************************************************************************/ -static void setOrder(FICL_VM *pVM) -{ - int i; - int nLists = stackPopINT32(pVM->pStack); - FICL_DICT *dp = ficlGetDict(); - - if (nLists > FICL_DEFAULT_VOCS) - { - vmThrowErr(pVM, "set-order error: list would be too large"); - } - - ficlLockDictionary(TRUE); - - if (nLists >= 0) - { - dp->nLists = nLists; - for (i = nLists-1; i >= 0; --i) - { - dp->pSearch[i] = stackPopPtr(pVM->pStack); - } - } - else - { - dictResetSearchOrder(dp); - } - - ficlLockDictionary(FALSE); - return; -} - - -/************************************************************************** - w o r d l i s t -** SEARCH ( -- wid ) -** Create a new empty word list, returning its word list identifier wid. -** The new word list may be returned from a pool of preallocated word -** lists or may be dynamically allocated in data space. A system shall -** allow the creation of at least 8 new word lists in addition to any -** provided as part of the system. -** Notes: -** 1. ficl creates a new single-list hash in the dictionary and returns -** its address. -** 2. ficl-wordlist takes an arg off the stack indicating the number of -** hash entries in the wordlist. Ficl 2.02 and later define WORDLIST as -** : wordlist 1 ficl-wordlist ; -**************************************************************************/ -static void wordlist(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - FICL_HASH *pHash; - UNS32 nBuckets; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - nBuckets = stackPopUNS32(pVM->pStack); - - dictAlign(dp); - pHash = (FICL_HASH *)dp->here; - dictAllot(dp, sizeof (FICL_HASH) - + (nBuckets-1) * sizeof (FICL_WORD *)); - - pHash->size = nBuckets; - hashReset(pHash); - - stackPushPtr(pVM->pStack, pHash); - return; -} - - -/************************************************************************** - S E A R C H > -** ficl ( -- wid ) -** Pop wid off the search order. Error if the search order is empty -**************************************************************************/ -static void searchPop(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - int nLists; - - ficlLockDictionary(TRUE); - nLists = dp->nLists; - if (nLists == 0) - { - vmThrowErr(pVM, "search> error: empty search order"); - } - stackPushPtr(pVM->pStack, dp->pSearch[--dp->nLists]); - ficlLockDictionary(FALSE); - return; -} - - -/************************************************************************** - > S E A R C H -** ficl ( wid -- ) -** Push wid onto the search order. Error if the search order is full. -**************************************************************************/ -static void searchPush(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - - ficlLockDictionary(TRUE); - if (dp->nLists > FICL_DEFAULT_VOCS) - { - vmThrowErr(pVM, ">search error: search order overflow"); - } - dp->pSearch[dp->nLists++] = stackPopPtr(pVM->pStack); - ficlLockDictionary(FALSE); - return; -} - - -/************************************************************************** - c o l o n N o N a m e -** CORE EXT ( C: -- colon-sys ) ( S: -- xt ) -** Create an unnamed colon definition and push its address. -** Change state to compile. -**************************************************************************/ -static void colonNoName(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - FICL_WORD *pFW; - STRINGINFO si; - - SI_SETLEN(si, 0); - SI_SETPTR(si, NULL); - - pVM->state = COMPILE; - pFW = dictAppendWord2(dp, si, colonParen, FW_DEFAULT | FW_SMUDGE); - stackPushPtr(pVM->pStack, pFW); - markControlTag(pVM, colonTag); - return; -} - - -/************************************************************************** - u s e r V a r i a b l e -** user ( u -- ) "<spaces>name" -** Get a name from the input stream and create a user variable -** with the name and the index supplied. The run-time effect -** of a user variable is to push the address of the indexed cell -** in the running vm's user array. -** -** User variables are vm local cells. Each vm has an array of -** FICL_USER_CELLS of them when FICL_WANT_USER is nonzero. -** Ficl's user facility is implemented with two primitives, -** "user" and "(user)", a variable ("nUser") (in softcore.c) that -** holds the index of the next free user cell, and a redefinition -** (also in softcore) of "user" that defines a user word and increments -** nUser. -**************************************************************************/ -#if FICL_WANT_USER -static void userParen(FICL_VM *pVM) -{ - INT32 i = pVM->runningWord->param[0].i; - stackPushPtr(pVM->pStack, &pVM->user[i]); - return; -} - - -static void userVariable(FICL_VM *pVM) -{ - FICL_DICT *dp = ficlGetDict(); - STRINGINFO si = vmGetWord(pVM); - CELL c; - - c = stackPop(pVM->pStack); - if (c.i >= FICL_USER_CELLS) - { - vmThrowErr(pVM, "Error - out of user space"); - } - - dictAppendWord2(dp, si, userParen, FW_DEFAULT); - dictAppendCell(dp, c); - return; -} -#endif - - -/************************************************************************** - t o V a l u e -** CORE EXT -** Interpretation: ( x "<spaces>name" -- ) -** Skip leading spaces and parse name delimited by a space. Store x in -** name. An ambiguous condition exists if name was not defined by VALUE. -** NOTE: In ficl, VALUE is an alias of CONSTANT -**************************************************************************/ -static void toValue(FICL_VM *pVM) -{ - STRINGINFO si = vmGetWord(pVM); - FICL_DICT *dp = ficlGetDict(); - FICL_WORD *pFW; - -#if FICL_WANT_LOCALS - FICL_DICT *pLoc = ficlGetLoc(); - if ((nLocals > 0) && (pVM->state == COMPILE)) - { - pFW = dictLookup(pLoc, si); - if (pFW) - { - dictAppendCell(dp, LVALUEtoCELL(pToLocalParen)); - dictAppendCell(dp, LVALUEtoCELL(pFW->param[0])); - return; - } - } -#endif - - assert(pStore); - - pFW = dictLookup(dp, si); - if (!pFW) - { - int i = SI_COUNT(si); - vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si)); - } - - if (pVM->state == INTERPRET) - pFW->param[0] = stackPop(pVM->pStack); - else /* compile code to store to word's param */ - { - stackPushPtr(pVM->pStack, &pFW->param[0]); - literalIm(pVM); - dictAppendCell(dp, LVALUEtoCELL(pStore)); - } - return; -} - - -#if FICL_WANT_LOCALS -/************************************************************************** - l i n k P a r e n -** ( -- ) -** Link a frame on the return stack, reserving nCells of space for -** locals - the value of nCells is the next cell in the instruction -** stream. -**************************************************************************/ -static void linkParen(FICL_VM *pVM) -{ - INT32 nLink = *(INT32 *)(pVM->ip); - vmBranchRelative(pVM, 1); - stackLink(pVM->rStack, nLink); - return; -} - - -static void unlinkParen(FICL_VM *pVM) -{ - stackUnlink(pVM->rStack); - return; -} - - -/************************************************************************** - d o L o c a l I m -** Immediate - cfa of a local while compiling - when executed, compiles -** code to fetch the value of a local given the local's index in the -** word's pfa -**************************************************************************/ -static void getLocalParen(FICL_VM *pVM) -{ - INT32 nLocal = *(INT32 *)(pVM->ip++); - stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]); - return; -} - - -static void toLocalParen(FICL_VM *pVM) -{ - INT32 nLocal = *(INT32 *)(pVM->ip++); - pVM->rStack->pFrame[nLocal] = stackPop(pVM->pStack); - return; -} - - -static void getLocal0(FICL_VM *pVM) -{ - stackPush(pVM->pStack, pVM->rStack->pFrame[0]); - return; -} - - -static void toLocal0(FICL_VM *pVM) -{ - pVM->rStack->pFrame[0] = stackPop(pVM->pStack); - return; -} - - -static void getLocal1(FICL_VM *pVM) -{ - stackPush(pVM->pStack, pVM->rStack->pFrame[1]); - return; -} - - -static void toLocal1(FICL_VM *pVM) -{ - pVM->rStack->pFrame[1] = stackPop(pVM->pStack); - return; -} - - -/* -** Each local is recorded in a private locals dictionary as a -** word that does doLocalIm at runtime. DoLocalIm compiles code -** into the client definition to fetch the value of the -** corresponding local variable from the return stack. -** The private dictionary gets initialized at the end of each block -** that uses locals (in ; and does> for example). -*/ -static void doLocalIm(FICL_VM *pVM) -{ - FICL_DICT *pDict = ficlGetDict(); - int nLocal = pVM->runningWord->param[0].i; - - if (pVM->state == INTERPRET) - { - stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]); - } - else - { - - if (nLocal == 0) - { - dictAppendCell(pDict, LVALUEtoCELL(pGetLocal0)); - } - else if (nLocal == 1) - { - dictAppendCell(pDict, LVALUEtoCELL(pGetLocal1)); - } - else - { - dictAppendCell(pDict, LVALUEtoCELL(pGetLocalParen)); - dictAppendCell(pDict, LVALUEtoCELL(nLocal)); - } - } - return; -} - - -/************************************************************************** - l o c a l P a r e n -** paren-local-paren LOCAL -** Interpretation: Interpretation semantics for this word are undefined. -** Execution: ( c-addr u -- ) -** When executed during compilation, (LOCAL) passes a message to the -** system that has one of two meanings. If u is non-zero, -** the message identifies a new local whose definition name is given by -** the string of characters identified by c-addr u. If u is zero, -** the message is last local and c-addr has no significance. -** -** The result of executing (LOCAL) during compilation of a definition is -** to create a set of named local identifiers, each of which is -** a definition name, that only have execution semantics within the scope -** of that definition's source. -** -** local Execution: ( -- x ) -** -** Push the local's value, x, onto the stack. The local's value is -** initialized as described in 13.3.3 Processing locals and may be -** changed by preceding the local's name with TO. An ambiguous condition -** exists when local is executed while in interpretation state. -**************************************************************************/ -static void localParen(FICL_VM *pVM) -{ - static CELL *pMark = NULL; - FICL_DICT *pDict = ficlGetDict(); - STRINGINFO si; - SI_SETLEN(si, stackPopUNS32(pVM->pStack)); - SI_SETPTR(si, (char *)stackPopPtr(pVM->pStack)); - - if (SI_COUNT(si) > 0) - { /* add a local to the dict and update nLocals */ - FICL_DICT *pLoc = ficlGetLoc(); - if (nLocals >= FICL_MAX_LOCALS) - { - vmThrowErr(pVM, "Error: out of local space"); - } - - dictAppendWord2(pLoc, si, doLocalIm, FW_COMPIMMED); - dictAppendCell(pLoc, LVALUEtoCELL(nLocals)); - - if (nLocals == 0) - { /* compile code to create a local stack frame */ - dictAppendCell(pDict, LVALUEtoCELL(pLinkParen)); - /* save location in dictionary for #locals */ - pMark = pDict->here; - dictAppendCell(pDict, LVALUEtoCELL(nLocals)); - /* compile code to initialize first local */ - dictAppendCell(pDict, LVALUEtoCELL(pToLocal0)); - } - else if (nLocals == 1) - { - dictAppendCell(pDict, LVALUEtoCELL(pToLocal1)); - } - else - { - dictAppendCell(pDict, LVALUEtoCELL(pToLocalParen)); - dictAppendCell(pDict, LVALUEtoCELL(nLocals)); - } - - nLocals++; - } - else if (nLocals > 0) - { /* write nLocals to (link) param area in dictionary */ - *(INT32 *)pMark = nLocals; - } - - return; -} - - -#endif -/************************************************************************** - setParentWid -** FICL -** setparentwid ( parent-wid wid -- ) -** Set WID's link field to the parent-wid. search-wordlist will -** iterate through all the links when finding words in the child wid. -**************************************************************************/ -static void setParentWid(FICL_VM *pVM) -{ - FICL_HASH *parent, *child; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - child = (FICL_HASH *)stackPopPtr(pVM->pStack); - parent = (FICL_HASH *)stackPopPtr(pVM->pStack); - - child->link = parent; - return; -} - - -/************************************************************************** - s e e -** TOOLS ( "<spaces>name" -- ) -** Display a human-readable representation of the named word's definition. -** The source of the representation (object-code decompilation, source -** block, etc.) and the particular form of the display is implementation -** defined. -** NOTE: these funcs come late in the file because they reference all -** of the word-builder funcs without declaring them again. Call me lazy. -**************************************************************************/ -/* -** isAFiclWord -** Vet a candidate pointer carefully to make sure -** it's not some chunk o' inline data... -** It has to have a name, and it has to look -** like it's in the dictionary address range. -** NOTE: this excludes :noname words! -*/ -static int isAFiclWord(FICL_WORD *pFW) -{ - void *pv = (void *)pFW; - FICL_DICT *pd = ficlGetDict(); - - if (!dictIncludes(pd, pFW)) - return 0; - - if (!dictIncludes(pd, pFW->name)) - return 0; - - return ((pFW->nName > 0) && (pFW->name[pFW->nName] == '\0')); -} - -/* -** seeColon (for proctologists only) -** Walks a colon definition, decompiling -** on the fly. Knows about primitive control structures. -*/ -static void seeColon(FICL_VM *pVM, CELL *pc) -{ - for (; pc->p != pSemiParen; pc++) - { - FICL_WORD *pFW = (FICL_WORD *)(pc->p); - - if (isAFiclWord(pFW)) - { - if (pFW->code == literalParen) - { - CELL v = *++pc; - if (isAFiclWord(v.p)) - { - FICL_WORD *pLit = (FICL_WORD *)v.p; - sprintf(pVM->pad, " literal %.*s (%#lx)", - pLit->nName, pLit->name, v.u); - } - else - sprintf(pVM->pad, " literal %ld (%#lx)", v.i, v.u); - } - else if (pFW->code == stringLit) - { - FICL_STRING *sp = (FICL_STRING *)(void *)++pc; - pc = (CELL *)alignPtr(sp->text + sp->count + 1) - 1; - sprintf(pVM->pad, " s\" %.*s\"", sp->count, sp->text); - } - else if (pFW->code == ifParen) - { - CELL c = *++pc; - if (c.i > 0) - sprintf(pVM->pad, " if / while (branch rel %ld)", c.i); - else - sprintf(pVM->pad, " until (branch rel %ld)", c.i); - } - else if (pFW->code == branchParen) - { - CELL c = *++pc; - if (c.i > 0) - sprintf(pVM->pad, " else (branch rel %ld)", c.i); - else - sprintf(pVM->pad, " repeat (branch rel %ld)", c.i); - } - else if (pFW->code == qDoParen) - { - CELL c = *++pc; - sprintf(pVM->pad, " ?do (leave abs %#lx)", c.u); - } - else if (pFW->code == doParen) - { - CELL c = *++pc; - sprintf(pVM->pad, " do (leave abs %#lx)", c.u); - } - else if (pFW->code == loopParen) - { - CELL c = *++pc; - sprintf(pVM->pad, " loop (branch rel %#ld)", c.i); - } - else if (pFW->code == plusLoopParen) - { - CELL c = *++pc; - sprintf(pVM->pad, " +loop (branch rel %#ld)", c.i); - } - else /* default: print word's name */ - { - sprintf(pVM->pad, " %.*s", pFW->nName, pFW->name); - } - - vmTextOut(pVM, pVM->pad, 1); - } - else /* probably not a word - punt and print value */ - { - sprintf(pVM->pad, " %ld (%#lx)", pc->i, pc->u); - vmTextOut(pVM, pVM->pad, 1); - } - } - - vmTextOut(pVM, ";", 1); -} - -/* -** Here's the outer part of the decompiler. It's -** just a big nested conditional that checks the -** CFA of the word to decompile for each kind of -** known word-builder code, and tries to do -** something appropriate. If the CFA is not recognized, -** just indicate that it is a primitive. -*/ -static void see(FICL_VM *pVM) -{ - FICL_DICT *pd = ficlGetDict(); - FICL_WORD *pFW; - - tick(pVM); - pFW = (FICL_WORD *)stackPopPtr(pVM->pStack); - - if (pFW->code == colonParen) - { - sprintf(pVM->pad, ": %.*s", pFW->nName, pFW->name); - vmTextOut(pVM, pVM->pad, 1); - seeColon(pVM, pFW->param); - } - else if (pFW->code == doDoes) - { - vmTextOut(pVM, "does>", 1); - seeColon(pVM, (CELL *)pFW->param->p); - } - else if (pFW->code == createParen) - { - vmTextOut(pVM, "create", 1); - } - else if (pFW->code == variableParen) - { - sprintf(pVM->pad, "variable = %ld (%#lx)", - pFW->param->i, pFW->param->u); - vmTextOut(pVM, pVM->pad, 1); - } - else if (pFW->code == userParen) - { - sprintf(pVM->pad, "user variable %ld (%#lx)", - pFW->param->i, pFW->param->u); - vmTextOut(pVM, pVM->pad, 1); - } - else if (pFW->code == constantParen) - { - sprintf(pVM->pad, "constant = %ld (%#lx)", - pFW->param->i, pFW->param->u); - vmTextOut(pVM, pVM->pad, 1); - } - else - { - vmTextOut(pVM, "primitive", 1); - } - - if (pFW->flags & FW_IMMEDIATE) - { - vmTextOut(pVM, "immediate", 1); - } - - return; -} - - -/************************************************************************** - c o m p a r e -** STRING ( c-addr1 u1 c-addr2 u2 -- n ) -** Compare the string specified by c-addr1 u1 to the string specified by -** c-addr2 u2. The strings are compared, beginning at the given addresses, -** character by character, up to the length of the shorter string or until a -** difference is found. If the two strings are identical, n is zero. If the two -** strings are identical up to the length of the shorter string, n is minus-one -** (-1) if u1 is less than u2 and one (1) otherwise. If the two strings are not -** identical up to the length of the shorter string, n is minus-one (-1) if the -** first non-matching character in the string specified by c-addr1 u1 has a -** lesser numeric value than the corresponding character in the string specified -** by c-addr2 u2 and one (1) otherwise. -**************************************************************************/ -static void compareString(FICL_VM *pVM) -{ - char *cp1, *cp2; - UNS32 u1, u2, uMin; - int n = 0; - - vmCheckStack(pVM, 4, 1); - u2 = stackPopUNS32(pVM->pStack); - cp2 = (char *)stackPopPtr(pVM->pStack); - u1 = stackPopUNS32(pVM->pStack); - cp1 = (char *)stackPopPtr(pVM->pStack); - - uMin = (u1 < u2)? u1 : u2; - for ( ; (uMin > 0) && (n == 0); uMin--) - { - n = (int)(*cp1++ - *cp2++); - } - - if (n == 0) - n = (int)(u1 - u2); - - if (n < 0) - n = -1; - else if (n > 0) - n = 1; - - stackPushINT32(pVM->pStack, n); - return; -} - - -/************************************************************************** - r e f i l l -** CORE EXT ( -- flag ) -** Attempt to fill the input buffer from the input source, returning a true -** flag if successful. -** When the input source is the user input device, attempt to receive input -** into the terminal input buffer. If successful, make the result the input -** buffer, set >IN to zero, and return true. Receipt of a line containing no -** characters is considered successful. If there is no input available from -** the current input source, return false. -** When the input source is a string from EVALUATE, return false and -** perform no other action. -**************************************************************************/ -static void refill(FICL_VM *pVM) -{ - INT32 ret = (pVM->sourceID.i == -1) ? FICL_FALSE : FICL_TRUE; - stackPushINT32(pVM->pStack, ret); - if (ret) - vmThrow(pVM, VM_OUTOFTEXT); - return; -} - - -/************************************************************************** - f o r g e t -** TOOLS EXT ( "<spaces>name" -- ) -** Skip leading space delimiters. Parse name delimited by a space. -** Find name, then delete name from the dictionary along with all -** words added to the dictionary after name. An ambiguous -** condition exists if name cannot be found. -** -** If the Search-Order word set is present, FORGET searches the -** compilation word list. An ambiguous condition exists if the -** compilation word list is deleted. -**************************************************************************/ -static void forgetWid(FICL_VM *pVM) -{ - FICL_DICT *pDict = ficlGetDict(); - FICL_HASH *pHash; - - pHash = (FICL_HASH *)stackPopPtr(pVM->pStack); - hashForget(pHash, pDict->here); - - return; -} - - -static void forget(FICL_VM *pVM) -{ - void *where; - FICL_DICT *pDict = ficlGetDict(); - FICL_HASH *pHash = pDict->pCompile; - - tick(pVM); - where = ((FICL_WORD *)stackPopPtr(pVM->pStack))->name; - hashForget(pHash, where); - pDict->here = PTRtoCELL where; - - return; -} - -/************************* freebsd added I/O words **************************/ - -/* fopen - open a file and return new fd on stack. - * - * fopen ( count ptr -- fd ) - */ -static void pfopen(FICL_VM *pVM) -{ - int fd; - char *p; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 1); -#endif - (void)stackPopINT32(pVM->pStack); /* don't need count value */ - p = stackPopPtr(pVM->pStack); - fd = open(p, O_RDONLY); - stackPushINT32(pVM->pStack, fd); - return; -} - -/* fclose - close a file who's fd is on stack. - * - * fclose ( fd -- ) - */ -static void pfclose(FICL_VM *pVM) -{ - int fd; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - fd = stackPopINT32(pVM->pStack); /* get fd */ - if (fd != -1) - close(fd); - return; -} - -/* fread - read file contents - * - * fread ( fd buf nbytes -- nread ) - */ -static void pfread(FICL_VM *pVM) -{ - int fd, len; - char *buf; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 3, 1); -#endif - len = stackPopINT32(pVM->pStack); /* get number of bytes to read */ - buf = stackPopPtr(pVM->pStack); /* get buffer */ - fd = stackPopINT32(pVM->pStack); /* get fd */ - if (len > 0 && buf && fd != -1) - stackPushINT32(pVM->pStack, read(fd, buf, len)); - else - stackPushINT32(pVM->pStack, -1); - return; -} - -/* fload - interpret file contents - * - * fload ( fd -- ) - */ -static void pfload(FICL_VM *pVM) -{ - int fd; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); -#endif - fd = stackPopINT32(pVM->pStack); /* get fd */ - if (fd != -1) - ficlExecFD(pVM, fd); - return; -} - -/* key - get a character from stdin - * - * key ( -- char ) - */ -static void key(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif - stackPushINT32(pVM->pStack, getchar()); - return; -} - -/* key? - check for a character from stdin (FACILITY) - * - * key? ( -- flag ) - */ -static void keyQuestion(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif -#ifdef TESTMAIN - /* XXX Since we don't fiddle with termios, let it always succeed... */ - stackPushINT32(pVM->pStack, FICL_TRUE); -#else - /* But here do the right thing. */ - stackPushINT32(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE); -#endif - return; -} - -/* seconds - gives number of seconds since beginning of time - * - * beginning of time is defined as: - * - * BTX - number of seconds since midnight - * FreeBSD - number of seconds since Jan 1 1970 - * - * seconds ( -- u ) - */ -static void pseconds(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM,0,1); -#endif - stackPushUNS32(pVM->pStack, (u_int32_t) time(NULL)); - return; -} - -/* ms - wait at least that many milliseconds (FACILITY) - * - * ms ( u -- ) - * - */ -static void ms(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM,1,0); -#endif -#ifdef TESTMAIN - usleep(stackPopUNS32(pVM->pStack)*1000); -#else - delay(stackPopUNS32(pVM->pStack)*1000); -#endif - return; -} - -/* fkey - get a character from a file - * - * fkey ( file -- char ) - */ -static void fkey(FICL_VM *pVM) -{ - int i, fd; - char ch; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - fd = stackPopINT32(pVM->pStack); - i = read(fd, &ch, 1); - stackPushINT32(pVM->pStack, i > 0 ? ch : -1); - return; -} - - -/************************************************************************** - f i c l C o m p i l e C o r e -** Builds the primitive wordset and the environment-query namespace. -**************************************************************************/ - -void ficlCompileCore(FICL_DICT *dp) -{ - assert (dp); - - /* - ** CORE word set - ** see softcore.c for definitions of: abs bl space spaces abort" - */ - pStore = - dictAppendWord(dp, "!", store, FW_DEFAULT); - dictAppendWord(dp, "#", numberSign, FW_DEFAULT); - dictAppendWord(dp, "#>", numberSignGreater,FW_DEFAULT); - dictAppendWord(dp, "#s", numberSignS, FW_DEFAULT); - dictAppendWord(dp, "\'", tick, FW_DEFAULT); - dictAppendWord(dp, "(", commentHang, FW_IMMEDIATE); - dictAppendWord(dp, "*", mul, FW_DEFAULT); - dictAppendWord(dp, "*/", mulDiv, FW_DEFAULT); - dictAppendWord(dp, "*/mod", mulDivRem, FW_DEFAULT); - dictAppendWord(dp, "+", add, FW_DEFAULT); - dictAppendWord(dp, "+!", plusStore, FW_DEFAULT); - dictAppendWord(dp, "+loop", plusLoopCoIm, FW_COMPIMMED); - pComma = - dictAppendWord(dp, ",", comma, FW_DEFAULT); - dictAppendWord(dp, "-", sub, FW_DEFAULT); - dictAppendWord(dp, ".", displayCell, FW_DEFAULT); - dictAppendWord(dp, ".#", displayCellNoPad, FW_DEFAULT); - dictAppendWord(dp, ".\"", dotQuoteCoIm, FW_COMPIMMED); - dictAppendWord(dp, "/", ficlDiv, FW_DEFAULT); - dictAppendWord(dp, "/mod", slashMod, FW_DEFAULT); - dictAppendWord(dp, "0<", zeroLess, FW_DEFAULT); - dictAppendWord(dp, "0=", zeroEquals, FW_DEFAULT); - dictAppendWord(dp, "0>", zeroGreater, FW_DEFAULT); - dictAppendWord(dp, "1+", onePlus, FW_DEFAULT); - dictAppendWord(dp, "1-", oneMinus, FW_DEFAULT); - dictAppendWord(dp, "2!", twoStore, FW_DEFAULT); - dictAppendWord(dp, "2*", twoMul, FW_DEFAULT); - dictAppendWord(dp, "2/", twoDiv, FW_DEFAULT); - dictAppendWord(dp, "2@", twoFetch, FW_DEFAULT); - dictAppendWord(dp, "2drop", twoDrop, FW_DEFAULT); - dictAppendWord(dp, "2dup", twoDup, FW_DEFAULT); - dictAppendWord(dp, "2over", twoOver, FW_DEFAULT); - dictAppendWord(dp, "2swap", twoSwap, FW_DEFAULT); - dictAppendWord(dp, ":", colon, FW_DEFAULT); - dictAppendWord(dp, ";", semicolonCoIm, FW_COMPIMMED); - dictAppendWord(dp, "<", isLess, FW_DEFAULT); - dictAppendWord(dp, "<#", lessNumberSign, FW_DEFAULT); - dictAppendWord(dp, "=", isEqual, FW_DEFAULT); - dictAppendWord(dp, ">", isGreater, FW_DEFAULT); - dictAppendWord(dp, ">body", toBody, FW_DEFAULT); - dictAppendWord(dp, ">in", toIn, FW_DEFAULT); - dictAppendWord(dp, ">number", toNumber, FW_DEFAULT); - dictAppendWord(dp, ">r", toRStack, FW_DEFAULT); - dictAppendWord(dp, "?dup", questionDup, FW_DEFAULT); - dictAppendWord(dp, "@", fetch, FW_DEFAULT); - dictAppendWord(dp, "abort", ficlAbort, FW_DEFAULT); - dictAppendWord(dp, "accept", accept, FW_DEFAULT); - dictAppendWord(dp, "align", align, FW_DEFAULT); - dictAppendWord(dp, "aligned", aligned, FW_DEFAULT); - dictAppendWord(dp, "allot", allot, FW_DEFAULT); - dictAppendWord(dp, "and", bitwiseAnd, FW_DEFAULT); - dictAppendWord(dp, "base", base, FW_DEFAULT); - dictAppendWord(dp, "begin", beginCoIm, FW_COMPIMMED); - dictAppendWord(dp, "c!", cStore, FW_DEFAULT); - dictAppendWord(dp, "c,", cComma, FW_DEFAULT); - dictAppendWord(dp, "c@", cFetch, FW_DEFAULT); - dictAppendWord(dp, "cell+", cellPlus, FW_DEFAULT); - dictAppendWord(dp, "cells", cells, FW_DEFAULT); - dictAppendWord(dp, "char", ficlChar, FW_DEFAULT); - dictAppendWord(dp, "char+", charPlus, FW_DEFAULT); - dictAppendWord(dp, "chars", ficlChars, FW_DEFAULT); - dictAppendWord(dp, "constant", constant, FW_DEFAULT); - dictAppendWord(dp, "count", count, FW_DEFAULT); - dictAppendWord(dp, "cr", cr, FW_DEFAULT); - dictAppendWord(dp, "create", create, FW_DEFAULT); - dictAppendWord(dp, "decimal", decimal, FW_DEFAULT); - dictAppendWord(dp, "depth", depth, FW_DEFAULT); - dictAppendWord(dp, "do", doCoIm, FW_COMPIMMED); - dictAppendWord(dp, "does>", doesCoIm, FW_COMPIMMED); - dictAppendWord(dp, "drop", drop, FW_DEFAULT); - dictAppendWord(dp, "dup", dup, FW_DEFAULT); - dictAppendWord(dp, "else", elseCoIm, FW_COMPIMMED); - dictAppendWord(dp, "emit", emit, FW_DEFAULT); - dictAppendWord(dp, "environment?", environmentQ,FW_DEFAULT); - dictAppendWord(dp, "evaluate", evaluate, FW_DEFAULT); - dictAppendWord(dp, "execute", execute, FW_DEFAULT); - dictAppendWord(dp, "exit", exitCoIm, FW_COMPIMMED); - dictAppendWord(dp, "fill", fill, FW_DEFAULT); - dictAppendWord(dp, "find", find, FW_DEFAULT); - dictAppendWord(dp, "fm/mod", fmSlashMod, FW_DEFAULT); - dictAppendWord(dp, "here", here, FW_DEFAULT); - dictAppendWord(dp, "hex", hex, FW_DEFAULT); - dictAppendWord(dp, "hold", hold, FW_DEFAULT); - dictAppendWord(dp, "i", loopICo, FW_COMPILE); - dictAppendWord(dp, "if", ifCoIm, FW_COMPIMMED); - dictAppendWord(dp, "immediate", immediate, FW_DEFAULT); - dictAppendWord(dp, "invert", bitwiseNot, FW_DEFAULT); - dictAppendWord(dp, "j", loopJCo, FW_COMPILE); - dictAppendWord(dp, "k", loopKCo, FW_COMPILE); - dictAppendWord(dp, "leave", leaveCo, FW_COMPILE); - dictAppendWord(dp, "literal", literalIm, FW_IMMEDIATE); - dictAppendWord(dp, "loop", loopCoIm, FW_COMPIMMED); - dictAppendWord(dp, "lshift", lshift, FW_DEFAULT); - dictAppendWord(dp, "m*", mStar, FW_DEFAULT); - dictAppendWord(dp, "max", ficlMax, FW_DEFAULT); - dictAppendWord(dp, "min", ficlMin, FW_DEFAULT); - dictAppendWord(dp, "mod", ficlMod, FW_DEFAULT); - dictAppendWord(dp, "move", move, FW_DEFAULT); - dictAppendWord(dp, "negate", negate, FW_DEFAULT); - dictAppendWord(dp, "or", bitwiseOr, FW_DEFAULT); - dictAppendWord(dp, "over", over, FW_DEFAULT); - dictAppendWord(dp, "postpone", postponeCoIm, FW_COMPIMMED); - dictAppendWord(dp, "quit", quit, FW_DEFAULT); - dictAppendWord(dp, "r>", fromRStack, FW_DEFAULT); - dictAppendWord(dp, "r@", fetchRStack, FW_DEFAULT); - dictAppendWord(dp, "recurse", recurseCoIm, FW_COMPIMMED); - dictAppendWord(dp, "repeat", repeatCoIm, FW_COMPIMMED); - dictAppendWord(dp, "rot", rot, FW_DEFAULT); - dictAppendWord(dp, "rshift", rshift, FW_DEFAULT); - dictAppendWord(dp, "s\"", stringQuoteIm, FW_IMMEDIATE); - dictAppendWord(dp, "s>d", sToD, FW_DEFAULT); - dictAppendWord(dp, "sign", sign, FW_DEFAULT); - dictAppendWord(dp, "sm/rem", smSlashRem, FW_DEFAULT); - dictAppendWord(dp, "source", source, FW_DEFAULT); - dictAppendWord(dp, "state", state, FW_DEFAULT); - dictAppendWord(dp, "swap", swap, FW_DEFAULT); - dictAppendWord(dp, "then", endifCoIm, FW_COMPIMMED); - pType = - dictAppendWord(dp, "type", type, FW_DEFAULT); - dictAppendWord(dp, "u.", uDot, FW_DEFAULT); - dictAppendWord(dp, "u<", uIsLess, FW_DEFAULT); - dictAppendWord(dp, "um*", umStar, FW_DEFAULT); - dictAppendWord(dp, "um/mod", umSlashMod, FW_DEFAULT); - dictAppendWord(dp, "unloop", unloopCo, FW_COMPILE); - dictAppendWord(dp, "until", untilCoIm, FW_COMPIMMED); - dictAppendWord(dp, "variable", variable, FW_DEFAULT); - dictAppendWord(dp, "while", whileCoIm, FW_COMPIMMED); - dictAppendWord(dp, "word", ficlWord, FW_DEFAULT); - dictAppendWord(dp, "xor", bitwiseXor, FW_DEFAULT); - dictAppendWord(dp, "[", lbracketCoIm, FW_COMPIMMED); - dictAppendWord(dp, "[\']", bracketTickCoIm,FW_COMPIMMED); - dictAppendWord(dp, "[char]", charCoIm, FW_COMPIMMED); - dictAppendWord(dp, "]", rbracket, FW_DEFAULT); - /* - ** CORE EXT word set... - ** see softcore.c for other definitions - */ - dictAppendWord(dp, ".(", dotParen, FW_DEFAULT); - dictAppendWord(dp, ":noname", colonNoName, FW_DEFAULT); - dictAppendWord(dp, "?do", qDoCoIm, FW_COMPIMMED); - dictAppendWord(dp, "parse", parse, FW_DEFAULT); - dictAppendWord(dp, "pick", pick, FW_DEFAULT); - dictAppendWord(dp, "roll", roll, FW_DEFAULT); - dictAppendWord(dp, "refill", refill, FW_DEFAULT); - dictAppendWord(dp, "to", toValue, FW_IMMEDIATE); - dictAppendWord(dp, "value", constant, FW_DEFAULT); - dictAppendWord(dp, "\\", commentLine, FW_IMMEDIATE); - - /* FreeBSD extension words */ - dictAppendWord(dp, "fopen", pfopen, FW_DEFAULT); - dictAppendWord(dp, "fclose", pfclose, FW_DEFAULT); - dictAppendWord(dp, "fread", pfread, FW_DEFAULT); - dictAppendWord(dp, "fload", pfload, FW_DEFAULT); - dictAppendWord(dp, "fkey", fkey, FW_DEFAULT); - dictAppendWord(dp, "key", key, FW_DEFAULT); - dictAppendWord(dp, "key?", keyQuestion, FW_DEFAULT); - dictAppendWord(dp, "ms", ms, FW_DEFAULT); - dictAppendWord(dp, "seconds", pseconds, FW_DEFAULT); -#ifdef __i386__ -#ifndef TESTMAIN - dictAppendWord(dp, "outb", ficlOutb, FW_DEFAULT); - dictAppendWord(dp, "inb", ficlInb, FW_DEFAULT); -#endif - ficlSetEnv("arch-i386", FICL_TRUE); -#else - ficlSetEnv("arch-i386", FICL_FALSE); -#endif - - /* - ** Set CORE environment query values - */ - ficlSetEnv("/counted-string", FICL_STRING_MAX); - ficlSetEnv("/hold", nPAD); - ficlSetEnv("/pad", nPAD); - ficlSetEnv("address-unit-bits", 8); - ficlSetEnv("core", FICL_TRUE); - ficlSetEnv("core-ext", FICL_FALSE); - ficlSetEnv("floored", FICL_FALSE); - ficlSetEnv("max-char", UCHAR_MAX); - ficlSetEnvD("max-d", 0x7fffffff, 0xffffffff ); - ficlSetEnv("max-n", 0x7fffffff); - ficlSetEnv("max-u", 0xffffffff); - ficlSetEnvD("max-ud", 0xffffffff, 0xffffffff); - ficlSetEnv("return-stack-cells",FICL_DEFAULT_STACK); - ficlSetEnv("stack-cells", FICL_DEFAULT_STACK); - - /* - ** LOCAL and LOCAL EXT - ** see softcore.c for implementation of locals| - */ -#if FICL_WANT_LOCALS - pLinkParen = - dictAppendWord(dp, "(link)", linkParen, FW_COMPILE); - pUnLinkParen = - dictAppendWord(dp, "(unlink)", unlinkParen, FW_COMPILE); - dictAppendWord(dp, "doLocal", doLocalIm, FW_COMPIMMED); - pGetLocalParen = - dictAppendWord(dp, "(@local)", getLocalParen, FW_COMPILE); - pToLocalParen = - dictAppendWord(dp, "(toLocal)", toLocalParen, FW_COMPILE); - pGetLocal0 = - dictAppendWord(dp, "(@local0)", getLocal0, FW_COMPILE); - pToLocal0 = - dictAppendWord(dp, "(toLocal0)",toLocal0, FW_COMPILE); - pGetLocal1 = - dictAppendWord(dp, "(@local1)", getLocal1, FW_COMPILE); - pToLocal1 = - dictAppendWord(dp, "(toLocal1)",toLocal1, FW_COMPILE); - dictAppendWord(dp, "(local)", localParen, FW_COMPILE); - - ficlSetEnv("locals", FICL_TRUE); - ficlSetEnv("locals-ext", FICL_TRUE); - ficlSetEnv("#locals", FICL_MAX_LOCALS); -#endif - - /* - ** optional SEARCH-ORDER word set - */ - dictAppendWord(dp, ">search", searchPush, FW_DEFAULT); - dictAppendWord(dp, "search>", searchPop, FW_DEFAULT); - dictAppendWord(dp, "definitions", - definitions, FW_DEFAULT); - dictAppendWord(dp, "forth-wordlist", - forthWordlist, FW_DEFAULT); - dictAppendWord(dp, "get-current", - getCurrent, FW_DEFAULT); - dictAppendWord(dp, "get-order", getOrder, FW_DEFAULT); - dictAppendWord(dp, "search-wordlist", - searchWordlist, FW_DEFAULT); - dictAppendWord(dp, "set-current", - setCurrent, FW_DEFAULT); - dictAppendWord(dp, "set-order", setOrder, FW_DEFAULT); - dictAppendWord(dp, "ficl-wordlist", wordlist, FW_DEFAULT); - - /* - ** Set SEARCH environment query values - */ - ficlSetEnv("search-order", FICL_TRUE); - ficlSetEnv("search-order-ext", FICL_TRUE); - ficlSetEnv("wordlists", FICL_DEFAULT_VOCS); - - /* - ** TOOLS and TOOLS EXT - */ - dictAppendWord(dp, ".s", displayStack, FW_DEFAULT); - dictAppendWord(dp, "bye", bye, FW_DEFAULT); - dictAppendWord(dp, "forget", forget, FW_DEFAULT); - dictAppendWord(dp, "see", see, FW_DEFAULT); - dictAppendWord(dp, "words", listWords, FW_DEFAULT); - - /* - ** Set TOOLS environment query values - */ - ficlSetEnv("tools", FICL_TRUE); - ficlSetEnv("tools-ext", FICL_FALSE); - - /* - ** Ficl extras - */ - dictAppendWord(dp, ".env", listEnv, FW_DEFAULT); - dictAppendWord(dp, ".hash", dictHashSummary,FW_DEFAULT); - dictAppendWord(dp, ".ver", ficlVersion, FW_DEFAULT); - dictAppendWord(dp, "-roll", minusRoll, FW_DEFAULT); - dictAppendWord(dp, "2constant", twoConstant, FW_IMMEDIATE); /* DOUBLE */ - dictAppendWord(dp, ">name", toName, FW_DEFAULT); - dictAppendWord(dp, "body>", fromBody, FW_DEFAULT); - dictAppendWord(dp, "compare", compareString, FW_DEFAULT); /* STRING */ - dictAppendWord(dp, "compile-only", - compileOnly, FW_DEFAULT); - dictAppendWord(dp, "endif", endifCoIm, FW_COMPIMMED); - dictAppendWord(dp, "forget-wid",forgetWid, FW_DEFAULT); - dictAppendWord(dp, "parse-word",parseNoCopy, FW_DEFAULT); - dictAppendWord(dp, "sliteral", sLiteralCoIm, FW_COMPIMMED); /* STRING */ - dictAppendWord(dp, "wid-set-super", - setParentWid, FW_DEFAULT); - dictAppendWord(dp, "w@", wFetch, FW_DEFAULT); - dictAppendWord(dp, "w!", wStore, FW_DEFAULT); - dictAppendWord(dp, "x.", hexDot, FW_DEFAULT); -#if FICL_WANT_USER - dictAppendWord(dp, "(user)", userParen, FW_DEFAULT); - dictAppendWord(dp, "user", userVariable, FW_DEFAULT); -#endif - /* - ** internal support words - */ - pExitParen = - dictAppendWord(dp, "(exit)", exitParen, FW_COMPILE); - pSemiParen = - dictAppendWord(dp, "(;)", semiParen, FW_COMPILE); - pLitParen = - dictAppendWord(dp, "(literal)", literalParen, FW_COMPILE); - pStringLit = - dictAppendWord(dp, "(.\")", stringLit, FW_COMPILE); - pIfParen = - dictAppendWord(dp, "(if)", ifParen, FW_COMPILE); - pBranchParen = - dictAppendWord(dp, "(branch)", branchParen, FW_COMPILE); - pDoParen = - dictAppendWord(dp, "(do)", doParen, FW_COMPILE); - pDoesParen = - dictAppendWord(dp, "(does>)", doesParen, FW_COMPILE); - pQDoParen = - dictAppendWord(dp, "(?do)", qDoParen, FW_COMPILE); - pLoopParen = - dictAppendWord(dp, "(loop)", loopParen, FW_COMPILE); - pPLoopParen = - dictAppendWord(dp, "(+loop)", plusLoopParen, FW_COMPILE); - pInterpret = - dictAppendWord(dp, "interpret", interpret, FW_DEFAULT); - dictAppendWord(dp, "(variable)",variableParen, FW_COMPILE); - dictAppendWord(dp, "(constant)",constantParen, FW_COMPILE); - - return; -} - diff --git a/sys/boot/i386/boot0/Makefile b/sys/boot/i386/boot0/Makefile index 4e890da32565..d6c407a0cc47 100644 --- a/sys/boot/i386/boot0/Makefile +++ b/sys/boot/i386/boot0/Makefile @@ -1,16 +1,12 @@ -# $Id: Makefile,v 1.5 1998/10/17 14:20:25 rnordier Exp $ +# $Id: Makefile,v 1.3 1998/10/09 17:19:51 rnordier Exp $ PROG= boot0 NOMAN= STRIP= BINDIR?= /boot -BINMODE= 444 M4?= m4 -B0FLAGS=0x0 -B0TICKS=0xb6 - ORG= 0x600 boot0: boot0.o @@ -23,8 +19,8 @@ boot0: boot0.o .endif boot0.o: boot0.m4 boot0.s - (cd ${.CURDIR}; ${M4} -DFLAGS=${B0FLAGS} -DTICKS=${B0TICKS} \ - boot0.m4 boot0.s) | ${AS} ${AFLAGS} -o ${.TARGET} + (cd ${.CURDIR}; ${M4} boot0.m4 boot0.s) | \ + ${AS} ${AFLAGS} -o ${.TARGET} CLEANFILES+= boot0.out boot0.o diff --git a/sys/boot/i386/boot0/boot0.m4 b/sys/boot/i386/boot0/boot0.m4 index f0912a888243..c0a38b76911e 100644 --- a/sys/boot/i386/boot0/boot0.m4 +++ b/sys/boot/i386/boot0/boot0.m4 @@ -13,7 +13,7 @@ # purpose. # -# $Id: boot0.m4,v 1.2 1998/10/19 19:13:53 rnordier Exp $ +# $Id:$ define(_al,0x0)dnl define(_cl,0x1)dnl @@ -52,22 +52,25 @@ define(_bx_,0x7)dnl define(o16,`.byte 0x66')dnl define(addwia,`.byte 0x5; .word $1')dnl -define(btwr1,`.word 0xa30f; .byte 0x40 | ($1 << 0x3) | $3; .byte $2')dnl -define(btswr1,`.word 0xab0f; .byte 0x40 | ($1 << 0x3) | $3; .byte $2')dnl -define(cmpbmr,`.byte 0x3a; .byte 0x6 | ($2 << 0x3); .word $1')dnl -define(cmpw1r,`.byte 0x3b; .byte 0x40 | ($3 << 0x3) | $2; .byte $1')dnl +define(btwrm,`.byte 0xf; .byte 0xa3; .byte 0x6 | ($1 << 0x3); .word $2')dnl +define(btswrm,`.byte 0xf; .byte 0xab; .byte 0x6 | ($1 << 0x3); .word $2')dnl +define(cmpwmr,`.byte 0x3b; .byte ($2 << 0x3) | 0x6; .word $1')dnl define(cmpwi2,`.byte 0x81; .byte 0xb8 | $3; .word $2; .word $1')dnl -define(addwir,`.byte 0x83; .byte 0xc0 | $2; .byte $1')dnl +define(cmpwir,`.byte 0x81; .byte 0xf8 | $2; .word $1')dnl define(movbr0,`.byte 0x88; .byte ($1 << 0x3) | $2')dnl +define(movbrm,`.byte 0x88; .byte 0x6 | ($1 << 0x3); .word $2')dnl define(movbr1,`.byte 0x88; .byte 0x40 | ($1 << 0x3) | $3; .byte $2')dnl define(movwr1,`.byte 0x89; .byte 0x40 | ($1 << 0x3) | $3; .byte $2')dnl define(movb0r,`.byte 0x8a; .byte ($2 << 0x3) | $1')dnl +define(movbmr,`.byte 0x8a; .byte 0x6 | ($2 << 0x3); .word $1')dnl define(movb1r,`.byte 0x8a; .byte 0x40 | ($3 << 0x3) | $2; .byte $1')dnl define(movw1r,`.byte 0x8b; .byte 0x40 | ($3 << 0x3) | $2; .byte $1')dnl define(movws1,`.byte 0x8c; .byte 0x40 | ($1 << 0x3) | $3; .byte $2')dnl +define(leaw1r,`.byte 0x8d; .byte 0x40 | ($3 << 0x3) | $2; .byte $1')dnl +define(movbma,`.byte 0xa0; .word $1')dnl +define(movbam,`.byte 0xa2; .word $1')dnl define(movwir,`.byte 0xb8 | $2; .word $1')dnl define(movbi0,`.byte 0xc6; .byte $2; .byte $1')dnl define(callwi,`.byte 0xe8; .word $1 - . - 0x2')dnl define(jmpnwi,`.byte 0xe9; .word $1 - . - 0x2')dnl -define(tstbi1,`.byte 0xf6; .byte 0x40 | $3; .byte $2; .byte $1')dnl define(incb1,`.byte 0xfe; .byte 0x40 | $2; .byte $1')dnl diff --git a/sys/boot/i386/boot0/boot0.s b/sys/boot/i386/boot0/boot0.s index 08a8d6be21b2..ae7fa5db8893 100644 --- a/sys/boot/i386/boot0/boot0.s +++ b/sys/boot/i386/boot0/boot0.s @@ -13,36 +13,19 @@ # purpose. # -# $Id: boot0.s,v 1.5 1998/11/29 14:09:00 rnordier Exp $ +# $Id: boot0.s,v 1.2 1998/10/09 17:19:51 rnordier Exp $ # A 512-byte boot manager. - .set NHRDRV,0x475 # Number of hard drives - .set ORIGIN,0x600 # Execution address - .set DSKPKT,0x800 # Disk packet - .set FAKE,0x810 # Partition entry .set LOAD,0x7c00 # Load address - + .set ORIGIN,0x600 # Relocation address .set PRT_OFF,0x1be # Partition table - - .set TBL0SZ,0x3 # Table 0 size - .set TBL1SZ,0xa # Table 1 size - - .set MAGIC,0xaa55 # Magic: bootable - - .set KEY_ENTER,0x1c # Enter key scan code - .set KEY_F1,0x3b # F1 key scan code - - .set _NXTDRV,-0x47 # Drive number - .set _OPT,-0x46 # Default option - .set _FLAGS,-0x45 # Flags - .set _TICKS,-0x44 # Timeout ticks - .set _FAKE,0x10 # Fake partition entry - .set _MNUOPT,0x1c # Menu options + .set FAKE,0x810 # Partition entry + .set MNUOPT,0x81c # Menu options .globl start # Entry point -start: cld # String ops inc +start: cld # String ops inc xorl %eax,%eax # Zero movl %eax,%es # Address movl %eax,%ds # data @@ -53,185 +36,183 @@ start: cld # String ops inc movwir(0x100,_cx) # Word count rep # Relocate movsl # code - movl %edi,%ebp # Address variables movb $0x10,%cl # Words to clear rep # Zero stosl # them incb1(-0xe,_di_) # Sector number jmpnwi(main-LOAD+ORIGIN) # To relocated code -main: movbr1(_dl,_FAKE,_bp_) # Save drive number +main: movbrm(_dl,FAKE) # Save drive number callwi(putn) # To new line movwir(partbl,_bx) # Partition table xorl %edx,%edx # Item -main.1: movbr0(_dh,_bx_) # Mark inactive +main.1: movbr0(_dh,_bx_) # Mark inactive movb1r(0x4,_bx_,_al) # Load type - movwir(tables,_di) # Lookup tables - movb $TBL0SZ,%cl # Entries + movwir(table0,_di) # Exclusion table + movb $0x3,%cl # Entries repne # Exclude scasb # partition? je main.3 # Yes - movb $TBL1SZ,%cl # Entries + movb $0xa,%cl # Entries repne # Known scasb # type? jne main.2 # No - addwir(TBL1SZ,_di) # Adjust -main.2: movb0r(_di_,_cl) # Partition - addl %ecx,%edi # description - callwi(putx) # Display it -main.3: addwir(0x10,_bx) # Next entry + leaw1r(0xa,_di_,_di) # Name table +main.2: movwir(item,_si) # Display start + callwi(putkey) # of menu item + movl %edi,%esi # Set pointer + lodsb # to + cwde # partition + add %eax,%esi # description + callwi(puts) # Display it + btswrm(_dx,MNUOPT) # Flag option enabled +main.3: addb $0x10,%bl # Next entry incl %edx # Next item cmpb $0x4,%dl # Done? jb main.1 # No - movb1r(_FAKE,_bp_,_al) # Drive number - subb $0x80-0x1,%al # Does next - cmpbmr(NHRDRV,_al) # drive exist? - jb main.4 # Yes - decb %al # Already drive 0? - jz main.5 # Yes - xorb %al,%al # Drive 0 -main.4: addb $'0'|0x80,%al # Save - movbr1(_al,_NXTDRV,_bp_) # it - movwir(drive,_di) # Display - callwi(putx) # item -main.5: movwir(prompt,_si) # Display + movwir(prompt,_si) # Display callwi(putstr) # prompt - movb1r(_OPT,_bp_,_dl) # Display + movbmr(opt,_dl) # Display decl %esi # default callwi(putkey) # key xorb %ah,%ah # BIOS: Get int $0x1a # system time - movl %edx,%edi # Save ticks -main.6: movb $0x1,%ah # BIOS: Check + movl %edx,%edi # Save +main.4: movb $0x1,%ah # BIOS: Check int $0x16 # for keypress - jnz main.9 # Have one + jnz main.6 # Have one xorb %ah,%ah # BIOS: Get int $0x1a # system time subl %edi,%edx # Elapsed time - cmpw1r(_TICKS,_bp_,_dx) # Timeout? - jb main.6 # No -main.7: movb1r(_OPT,_bp_,_al) # Load default - jmp main.10 # Join common code -main.8: movb $0x7,%al # Signal + cmpwmr(ticks,_dx) # Timeout? + jb main.4 # No + jmp main.7 # Join common code +main.5: movb $0x7,%al # Signal callwi(putchr) # error -main.9: xorb %ah,%ah # BIOS: Get +main.6: xorb %ah,%ah # BIOS: Get int $0x16 # keypress movb %ah,%al # Scan code - cmpb $KEY_ENTER,%al # Enter pressed? - je main.7 # No - subb $KEY_F1,%al # Less F1 scan code - cmpb $0x4,%al # F1..F5? - ja main.8 # No -main.10: cwtl # Option - btwr1(_ax,_MNUOPT,_bp_) # enabled? - jnc main.8 # No + cmpb $0x1c,%al # Enter pressed? + jne main.8 # No +main.7: movbma(opt) # Load + jmp main.9 # default +main.8: subb $0x3b,%al # Less F1 scan code + jb main.5 # Not a function key +main.9: cmpb $0x4,%al # F1..F5? + ja main.5 # No movwir(FAKE,_si) # Partition entry - movb1r(_NXTDRV,_bp_,_dl) # Next drive - subb $'0',%dl # number - cmpb $0x4,%al # F5 pressed? - je main.11 # Yes - movb0r(_si_,_dl) # Drive number - movbr1(_al,_OPT,_bp_) # Save option + movb0r(_si_,_dl) # Load drive number + jne main.10 # If not F5 + xorb $0x1,%dl # Toggle drive + jmp main.11 # number +main.10: cwtl # Option + btwrm(_ax,MNUOPT) # enabled? + jnc main.5 # No + movbam(opt) # Save option shlb $0x4,%al # Point to addwia(partbl) # partition - xchgl %esi,%eax # entry - tstbi1(0x40,_FLAGS,_bp_) # No updates? - jnz main.11 # Yes + xchgl %esi,%eax # entry movbi0(0x80,_si_) # Flag active pushl %esi # Save - xchgl %esi,%eax # Fake partition entry + movl %eax,%esi # Fake partition entry movwir(start,_bx) # Data to write movwir(0x301,_ax) # Write sector callwi(intx13) # to disk popl %esi # Restore + jc main.5 # If error main.11: movwir(LOAD,_bx) # Address for read movwir(0x201,_ax) # Read sector callwi(intx13) # from disk - jc main.8 # If error - cmpwi2(MAGIC,0x1fe,_bx_) # Bootable? - jne main.8 # No + jc main.5 # If error + cmpwi2(0xaa55,0x1fe,_bx_) # Bootable? + jne main.5 # No movwir(crlf,_si) # Leave some callwi(puts) # space jmp *%ebx # Invoke bootstrap # Display routines -putkey: movb $'F',%al # Display +putkey: movb $'F',%al # Display callwi(putchr) # 'F' movb $'1',%al # Prepare addb %dl,%al # digit jmp putstr.1 # Display the rest -putx: btswr1(_dx,_MNUOPT,_bp_) # Enable menu option - movwir(item,_si) # Display - callwi(putkey) # key - movl %edi,%esi # Display the rest - puts: callwi(putstr) # Display string putn: movwir(crlf,_si) # To next line -putstr: lodsb # Get byte - testb $0x80,%al # End of string? +putstr: lodsb # Get byte + testb $0x80,%al # End of string? jnz putstr.2 # Yes putstr.1: callwi(putchr) # Display char jmp putstr # Continue -putstr.2: andb $~0x80,%al # Clear MSB +putstr.2: andb $~0x80,%al # Clear MSB -putchr: pushl %ebx # Save - movwir(0x7,_bx) # Page:attribute +putchr: pushl %ebx # Save + movwir(0x7,_bx) # Page:attribute movb $0xe,%ah # BIOS: Display int $0x10 # character popl %ebx # Restore ret # To caller -# Disk I/O routine +# Disk I/O -intx13: cli # Disable interrupts - movb1r(0x1,_si_,_dh) # Load head +intx13: movb1r(0x1,_si_,_dh) # Load head movw1r(0x2,_si_,_cx) # Load cylinder:sector o16 # Load movw1r(0x8,_si_,_di) # offset - movwir(DSKPKT,_si) # Packet pointer + pushl %ecx # Save + pushl %ebx # caller's + movwir(0x55aa,_bx) # Magic + pushl %eax # Save + movb $0x41,%ah # BIOS: EDD extensions + int $0x13 # present? + popl %eax # Restore + jc intx13.1 # No + cmpwir(0xaa55,_bx) # Magic? + jne intx13.1 # No + testb $0x1,%cl # Use packet? + jz intx13.1 # No + orb $0x40,%ah # Use EDD +intx13.1: popl %ebx # Restore + popl %ecx # caller's + testb $0x40,%ah # Use EDD? + jz intx13.2 # No + movwir(break,_si) # Packet pointer movbi0(0x10,_si_) # Packet size movbr1(_al,0x2,_si_) # Block count movwr1(_bx,0x4,_si_) # Transfer movws1(_es,0x6,_si_) # buffer o16 # LBA movwr1(_di,0x8,_si_) # address - sti # Enable interrupts - tstbi1(0x80,_FLAGS,_bp_) # Use packet interface? - jz intx13.1 # No - orb $0x40,%ah # Use disk packet - decl %eax # Verify off -intx13.1: int $0x13 # BIOS: Disk I/O + xorb %al,%al # Verify off +intx13.2: int $0x13 # BIOS: Disk I/O ret # To caller # Menu strings -item: .ascii " "; .byte ' '|0x80 +crlf: .ascii "\r"; .byte '\n'|0x80 +item: .ascii " "; .byte ' '|0x80 prompt: .ascii "\nDefault:"; .byte ' '|0x80 -crlf: .ascii "\r"; .byte '\n'|0x80 # Partition type tables -tables: - .byte 0x0, 0x5, 0xf - - .byte 0x1, 0x4, 0x6, 0xb, 0xc, 0xe, 0x63, 0x83 +table0: .byte 0x0, 0x5, 0xf +table1: .byte 0x1, 0x4, 0x6, 0xb, 0xc, 0xe, 0x63, 0x83 .byte 0xa5, 0xa6 - .byte os_misc-. # Unknown - .byte os_dos-. # DOS - .byte os_dos-. # DOS - .byte os_dos-. # DOS - .byte os_dos-. # Windows - .byte os_dos-. # Windows - .byte os_dos-. # Windows - .byte os_unix-. # UNIX - .byte os_linux-. # Linux - .byte os_freebsd-. # FreeBSD - .byte os_bsd-. # OpenBSD + .byte os_misc-.-1 # Unknown + .byte os_dos-.-1 # DOS + .byte os_dos-.-1 # DOS + .byte os_dos-.-1 # DOS + .byte os_dos-.-1 # Windows + .byte os_dos-.-1 # Windows + .byte os_dos-.-1 # Windows + .byte os_unix-.-1 # UNIX + .byte os_linux-.-1 # Linux + .byte os_freebsd-.-1 # FreeBSD + .byte os_bsd-.-1 # OpenBSD os_misc: .ascii "?"; .byte '?'|0x80 os_dos: .ascii "DO"; .byte 'S'|0x80 @@ -240,13 +221,12 @@ os_linux: .ascii "Linu"; .byte 'x'|0x80 os_freebsd: .ascii "Free" os_bsd: .ascii "BS"; .byte 'D'|0x80 - .org PRT_OFF-0xb,0x90 + .org PRT_OFF-0x3,0x90 + +opt: .byte 0x1 # Option +ticks: .word 0xb6 # Delay -drive: .ascii "Drive " -nxtdrv: .byte 0x0 # Next drive number -opt: .byte 0x0 # Option -flags: .byte FLAGS # Flags -ticks: .word TICKS # Delay +partbl: .fill 0x40,0x1,0x0 # Partition table + .word 0xaa55 # Magic number -partbl: .fill 0x40,0x1,0x0 # Partition table - .word MAGIC # Magic number +break: # Uninitialized data diff --git a/sys/boot/i386/boot2/Makefile b/sys/boot/i386/boot2/Makefile index 2b581ec521cd..e36df60f2a9b 100644 --- a/sys/boot/i386/boot2/Makefile +++ b/sys/boot/i386/boot2/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.10 1998/11/08 15:36:34 rnordier Exp $ +# $Id: Makefile,v 1.6 1998/10/15 20:04:21 rnordier Exp $ PROG= boot2 NOMAN= @@ -11,10 +11,6 @@ CLEANFILES+= boot1 boot1.out boot1.o \ M4?= m4 -BOOT_COMCONSOLE_PORT?= 0x3f8 -BOOT_COMCONSOLE_SPEED?= 9600 -B2SIOFMT?= 0x3 - .if exists(${.OBJDIR}/../btx) BTX= ${.OBJDIR}/../btx .else @@ -62,10 +58,7 @@ boot2.out: boot2.o sio.o ${BTX}/lib/crt0.o boot2.o sio.o sio.o: sio.s - (cd ${.CURDIR}; ${M4} -DSIOPRT=${BOOT_COMCONSOLE_PORT} \ - -DSIOFMT=${B2SIOFMT} \ - -DSIOSPD=${BOOT_COMCONSOLE_SPEED} sio.s) | \ - ${AS} ${AFLAGS} -o ${.TARGET} + ${AS} ${AFLAGS} -o ${.TARGET} ${.IMPSRC} install: ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ diff --git a/sys/boot/i386/boot2/boot1.m4 b/sys/boot/i386/boot2/boot1.m4 index 06bdc9789331..fc221a1854c1 100644 --- a/sys/boot/i386/boot2/boot1.m4 +++ b/sys/boot/i386/boot2/boot1.m4 @@ -13,7 +13,7 @@ # purpose. # -# $Id: boot1.m4,v 1.2 1998/11/05 20:52:25 rnordier Exp $ +# $Id:$ define(_al,0x0)dnl define(_cl,0x1)dnl @@ -60,5 +60,3 @@ define(movbi1,`.byte 0xc6; .byte 0x40 | $3; .byte $2; .byte $1')dnl define(callwi,`.byte 0xe8; .word $1 - . - 0x2')dnl define(jmpnwi,`.byte 0xe9; .word $1 - . - 0x2')dnl define(tstbi0,`.byte 0xf6; .byte $2; .byte $1')dnl -define(tstbim,`.byte 0xf6; .byte 0x6; .word $2; .byte $1')dnl -define(incw1,`.byte 0xff; .byte 0x40 | $2; .byte $1')dnl diff --git a/sys/boot/i386/boot2/boot1.s b/sys/boot/i386/boot2/boot1.s index 3161b748b8e9..8b408cebeff4 100644 --- a/sys/boot/i386/boot2/boot1.s +++ b/sys/boot/i386/boot2/boot1.s @@ -13,10 +13,11 @@ # purpose. # -# $Id: boot1.s,v 1.7 1999/01/10 13:29:51 peter Exp $ +# $Id: boot1.s,v 1.1.1.1 1998/10/12 21:16:26 rnordier Exp $ - .set MEM_REL,0x700 # Relocation address - .set MEM_ARG,0x900 # Arguments + .set MEM_REL,0x600 # Relocation address + .set MEM_ARG,0x800 # Arguments + .set MEM_PKT,0x810 # Disk packet .set MEM_ORG,0x7c00 # Origin .set MEM_BUF,0x8c00 # Load area .set MEM_BTX,0x9000 # BTX start @@ -37,58 +38,59 @@ start: jmp main # Start recognizably .org 0x4,0x90 -# External read from disk - -xread: pushl %ecx # Set - pushl %eax # LBA - pushl %es # Set transfer - pushl %ebx # buffer - pushl %edx # Set count:drive +xread: pushl %cs # Address + popl %ds # data +xread.1: movwir(MEM_PKT,_si) # Packet + movbr1(_al,0x2,_si_) # Blocks to read + o16 # Transfer + movwr1(_bx,0x4,_si_) # buffer + o16 # LBA + movwr1(_cx,0x8,_si_) # address callwi(read) # Read from disk - popl %edx # Pop all - popl %ebx # registers - popl %es # pushed, but - popl %ecx # preserve - popl %ecx # AX - lret # To far caller - -# Bootstrap + lret # To caller main: cld # String ops inc - xorl %ecx,%ecx # Zero - movl %cx,%es # Address - movl %cx,%ds # data - movl %cx,%ss # Set up + xorl %eax,%eax # Zero + movl %ax,%es # Address + movl %ax,%ds # data + movl %ax,%ss # Set up movwir(start,_sp) # stack movl %esp,%esi # Source movwir(MEM_REL,_di) # Destination - incb %ch # Word count + movwir(0x100,_cx) # Word count rep # Copy movsl # code - movwir(part4,_si) # Partition + movb $0x10,%cl # Words to clear + rep # Zero + stosl # them + movbi1(0x10,-0x10,_di_) # Set packet size cmpb $0x80,%dl # Hard drive? jb main.4 # No - movb $0x1,%dh # Block count - callwi(nread) # Read MBR - movwir(0x1,_cx) # Two passes + movwir(part4,_si) # Read master + movb $0x1,%al # boot + callwi(nread) # record + xorl %eax,%eax # Pass number main.1: movwir(MEM_BUF+PRT_OFF,_si) # Partition table movb $0x1,%dh # Partition main.2: cmpbi1(PRT_BSD,0x4,_si_) # Our partition type? jne main.3 # No - jecxz main.5 # If second pass tstbi0(0x80,_si_) # Active? jnz main.5 # Yes + testb %al,%al # Second pass? + jnz main.5 # Yes main.3: addl $0x10,%esi # Next entry incb %dh # Partition - cmpb $0x1+PRT_NUM,%dh # In table? - jb main.2 # Yes - decl %ecx # Do two - jecxz main.1 # passes + cmpb $0x1+PRT_NUM,%dh # Done? + jb main.2 # No + incl %eax # Pass + cmpb $0x2,%al # Done? + jb main.1 # No movwir(msg_part,_si) # Message jmp error # Error main.4: xorl %edx,%edx # Partition:drive + movwir(part4,_si) # Partition pointer main.5: movwrm(_dx,MEM_ARG) # Save args - movb $0x10,%dh # Sector count + movb $0x10,%al # Sector count callwi(nread) # Read disk movwir(MEM_BTX,_bx) # BTX movw1r(0xa,_bx_,_si) # Point past @@ -107,34 +109,33 @@ main.5: movwrm(_dx,MEM_ARG) # Save args # Enable A20 -seta20: cli # Disable interrupts -seta20.1: inb $0x64,%al # Get status +seta20: inb $0x64,%al # Get status testb $0x2,%al # Busy? - jnz seta20.1 # Yes + jnz seta20 # Yes movb $0xd1,%al # Command: Write outb %al,$0x64 # output port -seta20.2: inb $0x64,%al # Get status +seta20.1: inb $0x64,%al # Get status testb $0x2,%al # Busy? - jnz seta20.2 # Yes + jnz seta20.1 # Yes movb $0xdf,%al # Enable outb %al,$0x60 # A20 - sti # Enable interrupts ret # To caller -# Local read from disk +# Read from disk -nread: movwir(MEM_BUF,_bx) # Transfer buffer - movw1r(0x8,_si_,_ax) # Get - movw1r(0xa,_si_,_cx) # LBA +nread: xorw %bx,%bx # Transfer + movb $MEM_BUF>>0x8,%bh # buffer + o16 # LBA + movw1r(0x8,_si_,_cx) # address pushl %cs # Read from - callwi(xread) # disk + callwi(xread.1) # disk jnc return # If success movwir(msg_read,_si) # Message # Error exit error: callwi(putstr) # Display message - movwir(prompt,_si) # Display + movwir(msg_boot,_si) # Display callwi(putstr) # prompt xorb %ah,%ah # BIOS: Get int $0x16 # keypress @@ -149,24 +150,40 @@ putstr: lodsb # Get char testb %al,%al # End of string? jne putstr.0 # No -ereturn: movb $0x1,%ah # Invalid - stc # argument -return: ret # To caller +return: ret # Generic return # Read from disk -read: movl %esp,%ebp # Address stack frame +read: testb %dh,%dh # Try for extensions? + jz read.3 # No + movwir(0x55aa,_bx) # Magic pushl %edx # Save + movb $0x41,%ah # BIOS: Check + int $0x13 # extensions present + popl %edx # Restore + jc read.3 # If error + cmpwir(0xaa55,_bx) # Magic? + jne read.3 # No + testb $0x1,%cl # Packet interface? + jz read.3 # No + movb $0x42,%ah # BIOS: Extended + int $0x13 # read + ret # To caller + +read.1: movb $0x1,%ah # Invalid + stc # parameter +read.2: ret # To caller + +read.3: pushl %edx # Save movb $0x8,%ah # BIOS: Get drive int $0x13 # parameters movb %dh,%ch # Max head number popl %edx # Restore - jc return # If error + jc read.2 # If error andb $0x3f,%cl # Sectors per track - jz ereturn # If zero - cli # Disable interrupts + jz read.1 # If zero o16 # Get - movw1r(0x8,_bp_,_ax) # LBA + movw1r(0x8,_si_,_ax) # LBA pushl %edx # Save movzbw %cl,%bx # Divide by xorw %dx,%dx # sectors @@ -174,14 +191,13 @@ read: movl %esp,%ebp # Address stack frame movb %ch,%bl # Max head number movb %dl,%ch # Sector number incl %ebx # Divide by - xorb %dl,%dl # number - divw %bx,%ax # of heads + xorb %dl,%dl # number of + divw %bx,%ax # heads movb %dl,%bh # Head number popl %edx # Restore o16 # Cylinder number cmpl $0x3ff,%eax # supportable? - sti # Enable interrupts - ja ereturn # No + ja read.1 # No xchgb %al,%ah # Set up cylinder rorb $0x2,%al # number orb %ch,%al # Merge @@ -189,39 +205,37 @@ read: movl %esp,%ebp # Address stack frame xchgl %eax,%ecx # number movb %bh,%dh # Head number subb %ah,%al # Sectors this track - movb1r(0x3,_bp_,_ah) # Blocks to read + movb1r(0x2,_si_,_ah) # Blocks to read cmpb %ah,%al # To read - jb read.1 # this + jb read.4 # this movb %ah,%al # track -read.1: movwir(0x5,_di) # Try count -read.2: lesw1r(0x4,_bp_,_bx) # Transfer buffer +read.4: movwir(0x5,_bp) # Try count +read.5: lesw1r(0x4,_si_,_bx) # Transfer buffer pushl %eax # Save - movb $0x2,%ah # BIOS: Read - int $0x13 # from disk + movb $0x2,%ah # BIOS: Conventional + int $0x13 # read popl %ebx # Restore - jnc read.3 # If success - decl %edi # Retry? - jz read.5 # No + jnc read.6 # If success + decl %ebp # Retry? + jz read.7 # No xorb %ah,%ah # BIOS: Reset int $0x13 # disk system - xchgl %ebx,%eax # Block count - jmp read.2 # Continue -read.3: movzbl %bl,%eax # Sectors read - addwr1(_ax,0x8,_bp_) # Adjust - jnc read.4 # LBA, - incw1(0xa,_bp_) # transfer -read.4: shlb %bl # buffer - addbr1(_bl,0x5,_bp_) # pointer, - subbr1(_al,0x3,_bp_) # block count - ja read # If not done -read.5: ret # To caller + movl %ebx,%eax # Block count + jmp read.5 # Continue +read.6: movzbw %bl,%ax # Sectors read + o16 # Adjust + addwr1(_ax,0x8,_si_) # LBA, + shlb %bl # buffer + addbr1(_bl,0x5,_si_) # pointer, + subbr1(_al,0x2,_si_) # block count + ja read.3 # If not done +read.7: ret # To caller # Messages -msg_read: .asciz "Read" -msg_part: .asciz "Boot" - -prompt: .asciz " error\r\n" +msg_read: .asciz "Read error" +msg_part: .asciz "No bootable partition" +msg_boot: .asciz "\r\nHit return to reboot: " .org PRT_OFF,0x90 diff --git a/sys/boot/i386/boot2/boot2.c b/sys/boot/i386/boot2/boot2.c index fa6058bcccb7..bf9ed8c61f54 100644 --- a/sys/boot/i386/boot2/boot2.c +++ b/sys/boot/i386/boot2/boot2.c @@ -14,7 +14,7 @@ */ /* - * $Id: boot2.c,v 1.17 1999/01/10 13:29:52 peter Exp $ + * $Id: boot2.c,v 1.6 1998/10/13 23:43:38 rnordier Exp $ */ #include <sys/param.h> @@ -53,9 +53,11 @@ #define PATH_CONFIG "/boot.config" #define PATH_BOOT3 "/boot/loader" #define PATH_KERNEL "/kernel" +#define PATH_HELP "boot.help" -#define ARGS 0x900 +#define ARGS 0x800 #define NOPT 11 +#define XOPT 2 #define BSIZEMAX 8192 #define NDEV 5 #define MEM_BASE 0x12 @@ -102,6 +104,7 @@ static struct dsk { } dsk; static char cmd[512]; static char kname[1024]; +static char help[2048]; static uint32_t opts; static struct bootinfo bootinfo; static int ls; @@ -136,7 +139,7 @@ static int getc(int); int main(void) { - int autoboot, i; + int autoboot, helpon, i; v86.ctl = V86_FLAGS; dsk.drive = *(uint8_t *)PTOV(ARGS); @@ -151,14 +154,11 @@ main(void) for (i = 0; i < N_BIOS_GEOM; i++) bootinfo.bi_bios_geom[i] = drvinfo(i); autoboot = 2; + helpon = 1; readfile(PATH_CONFIG, cmd, sizeof(cmd)); - if (*cmd) { - printf("%s: %s", PATH_CONFIG, cmd); - if (parse(cmd)) - autoboot = 0; - *cmd = 0; - } - if (autoboot && !*kname) { + if (parse(cmd)) + autoboot = 0; + else if (!*kname) { if (autoboot == 2) { memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); if (!keyhit(0x37)) { @@ -169,21 +169,21 @@ main(void) if (autoboot == 1) memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); } + readfile(PATH_HELP, help, sizeof(help)); for (;;) { printf(" \n>> FreeBSD/i386 BOOT\n" "Default: %u:%s(%u,%c)%s\n" + "%s" "boot: ", dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, - 'a' + dsk.part, kname); + 'a' + dsk.part, kname, helpon ? help : ""); if (ioctrl & 0x2) sio_flush(); if (!autoboot || keyhit(0x5a)) getstr(cmd, sizeof(cmd)); - else - putchar('\n'); - autoboot = 0; + autoboot = helpon = 0; if (parse(cmd)) - putchar('\a'); + helpon = 1; else load(kname); } @@ -226,16 +226,22 @@ load(const char *fname) if (fmt == 0) { addr = hdr.ex.a_entry & 0xffffff; p = PTOV(addr); + printf("%s=0x%x ", "text", (unsigned)hdr.ex.a_text); fs_off = PAGE_SIZE; if (xfsread(ino, p, hdr.ex.a_text)) return; p += roundup2(hdr.ex.a_text, PAGE_SIZE); + printf("%s=0x%x ", "data", (unsigned)hdr.ex.a_data); if (xfsread(ino, p, hdr.ex.a_data)) return; - p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE); + p += hdr.ex.a_data; + printf("%s=0x%x ", "bss", (unsigned)hdr.ex.a_bss); + p += roundup2(hdr.ex.a_bss, PAGE_SIZE); bootinfo.bi_symtab = VTOP(p); memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); p += sizeof(hdr.ex.a_syms); + printf("symbols=["); + printf("+0x%x", (unsigned)hdr.ex.a_syms); if (hdr.ex.a_syms) { if (xfsread(ino, p, hdr.ex.a_syms)) return; @@ -245,6 +251,7 @@ load(const char *fname) x = *(uint32_t *)p; p += sizeof(int); x -= sizeof(int); + printf("+0x%x", x); if (xfsread(ino, p, x)) return; p += x; @@ -259,12 +266,15 @@ load(const char *fname) } for (i = 0; i < 2; i++) { p = PTOV(ep[i].p_paddr & 0xffffff); + printf("%s=0x%x ", !i ? "text" : "data", ep[i].p_filesz); fs_off = ep[i].p_offset; if (xfsread(ino, p, ep[i].p_filesz)) return; } + printf("%s=0x%x ", "bss", ep[1].p_memsz - ep[1].p_filesz); p += roundup2(ep[1].p_memsz, PAGE_SIZE); bootinfo.bi_symtab = VTOP(p); + printf("symbols=["); if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { fs_off = hdr.eh.e_shoff + sizeof(es[0]) * (hdr.eh.e_shstrndx + 1); @@ -273,6 +283,7 @@ load(const char *fname) for (i = 0; i < 2; i++) { memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size)); p += sizeof(es[i].sh_size); + printf("+0x%x", es[i].sh_size); fs_off = es[i].sh_offset; if (xfsread(ino, p, es[i].sh_size)) return; @@ -282,6 +293,7 @@ load(const char *fname) addr = hdr.eh.e_entry & 0xffffff; } bootinfo.bi_esymtab = VTOP(p); + printf("]\nentry=0x%x\n", addr); bootinfo.bi_kernelname = VTOP(fname); __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), MAKEBOOTDEV(dsk.type, 0, dsk.slice, dsk.unit, dsk.part), @@ -305,14 +317,16 @@ parse(char *arg) for (i = 0; c != optstr[i]; i++) if (i == NOPT - 1) return -1; - opts ^= 1 << flags[i]; + if (i < XOPT) + opts ^= 1 << flags[i]; + else + opts |= 1 << flags[i]; } if (opts & 1 << RBX_PROBEKBD) { i = *(uint8_t *)PTOV(0x496) & 0x10; printf("Keyboard: %s\n", i ? "yes" : "no"); if (!i) opts |= 1 << RBX_DUAL | 1 << RBX_SERIAL; - opts &= ~(1 << RBX_PROBEKBD); } ioctrl = opts & 1 << RBX_DUAL ? 0x3 : opts & 1 << RBX_SERIAL ? 0x2 : 0x1; @@ -469,7 +483,7 @@ fsread(ino_t inode, void *buf, size_t nbyte) return -1; } fsblks = fs.fs_bsize >> DEV_BSHIFT; - dsk.meta++; + dsk.meta = 1; } if (!inode) return 0; @@ -630,15 +644,9 @@ getstr(char *str, int size) s = str; do { switch (c = getchar()) { - case 0: - break; case '\b': - if (s > str) { + if (s > str) s--; - putchar(c); - putchar(' '); - } else - c = 0; break; case '\n': *s = 0; @@ -647,8 +655,7 @@ getstr(char *str, int size) if (s - str < size - 1) *s++ = c; } - if (c) - putchar(c); + putchar(c); } while (c != '\n'); } @@ -731,12 +738,11 @@ drvread(void *buf, unsigned lba, unsigned nblk) printf("%c\b", c = c << 8 | c >> 24); v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; - v86.addr = 0x704; /* call to xread in boot1 */ - v86.es = VTOPSEG(buf); - v86.eax = lba; - v86.ebx = VTOPOFF(buf); - v86.ecx = lba >> 16; - v86.edx = nblk << 8 | dsk.drive; + v86.addr = 0x604; + v86.eax = nblk; + v86.ebx = VTOPSEG(buf) << 16 | VTOPOFF(buf); + v86.ecx = lba; + v86.edx = 0x100 | dsk.drive; v86int(); v86.ctl = V86_FLAGS; if (V86_CY(v86.efl)) { diff --git a/sys/boot/i386/boot2/sio.s b/sys/boot/i386/boot2/sio.s index 92237b852b72..985ac04ef469 100644 --- a/sys/boot/i386/boot2/sio.s +++ b/sys/boot/i386/boot2/sio.s @@ -13,11 +13,11 @@ # purpose. # -# $Id: sio.s,v 1.2 1998/10/20 20:20:48 rnordier Exp $ +# $Id:$ - .set SIO_PRT,SIOPRT # Base port - .set SIO_FMT,SIOFMT # 8N1 - .set SIO_DIV,(115200/SIOSPD) # 115200 / SPD + .set SIO_PRT,0x3f8 # Base port + .set SIO_FMT,0x3 # 8N1 + .set SIO_DIV,0xc # 115200 / 9600 .globl sio_init .globl sio_flush diff --git a/sys/boot/i386/btx/btx/btx.s b/sys/boot/i386/btx/btx/btx.s index 92842626d00f..d94fa2c11a27 100644 --- a/sys/boot/i386/btx/btx/btx.s +++ b/sys/boot/i386/btx/btx/btx.s @@ -13,7 +13,7 @@ # purpose. # -# $Id: btx.s,v 1.7 1998/11/01 13:52:52 rnordier Exp $ +# $Id: btx.s,v 1.5 1998/10/03 18:05:12 rnordier Exp $ # # Memory layout. @@ -340,7 +340,7 @@ intx00: pushb $0x0 # Int 0x0: #DE intx10: pushb $0x10 # Int 0x10: #MF jmp ex_noc # Floating-point error # -# Handle #GP exception. +# # ex_v86: testb $0x2,0x12(%esp,1) # V86 mode? jz except # No @@ -459,7 +459,7 @@ v86mon.1: lodsb # Get opcode v86mon.2: cmpb $0xf4,%al # HLT? jne v86mon.3 # No cmpl $inthlt+0x1,%esi # Is inthlt? - jne v86mon.6 # No (ignore) + jne v86mon.4 # No jmp intrtn # Return to user mode v86mon.3: cmpb $0xfa,%al # CLI? je v86cli # Yes @@ -479,13 +479,13 @@ v86mon.3: cmpb $0xfa,%al # CLI? cmpb $0xcf,%al # IRET/IRETD? je v86iret # Yes popl %ebx # Restore - popa # Restore +v86mon.4: popa # Restore jmp except # Handle exception -v86mon.4: movl %edx,0x30(%ebp) # Save V86 flags -v86mon.5: popl %edx # V86 SS adjustment +v86mon.5: movl %edx,0x30(%ebp) # Save V86 flags +v86mon.6: popl %edx # V86 SS adjustment subl %edx,%ebx # Save V86 movl %ebx,0x34(%ebp) # SP -v86mon.6: subl %edi,%esi # From linear +v86mon.7: subl %edi,%esi # From linear movl %esi,0x28(%ebp) # Save V86 IP popa # Restore leal 0x8(%esp,1),%esp # Discard int no, error @@ -494,12 +494,12 @@ v86mon.6: subl %edi,%esi # From linear # Emulate CLI. # v86cli: andb $~0x2,0x31(%ebp) # Clear IF - jmp v86mon.6 # Finish up + jmp v86mon.7 # Finish up # # Emulate STI. # v86sti: orb $0x2,0x31(%ebp) # Set IF - jmp v86mon.6 # Finish up + jmp v86mon.7 # Finish up # # Emulate PUSHF/PUSHFD. # @@ -508,7 +508,7 @@ v86pushf: subl %ecx,%ebx # Adjust SP je v86pushf.1 # Yes o16 # 16-bit v86pushf.1: movl %edx,(%ebx) # Save flags - jmp v86mon.5 # Finish up + jmp v86mon.6 # Finish up # # Emulate IRET/IRETD. # @@ -529,7 +529,7 @@ v86popf.1: movl (%ebx),%eax # Load flags andl $V86_FLG,%eax # Merge andl $~V86_FLG,%edx # the orl %eax,%edx # flags - jmp v86mon.4 # Finish up + jmp v86mon.5 # Finish up # # Emulate INT imm8. # @@ -546,7 +546,7 @@ v86intn: lodsb # Get int no movl %edi,0x2c(%ebp) # Save CS xorl %edi,%edi # No ESI adjustment andb $~0x3,%dh # Clear IF and TF - jmp v86mon.4 # Finish up + jmp v86mon.5 # Finish up # # Hardware interrupt jump table. # @@ -693,12 +693,12 @@ intusr.4: shrl $0x4,%eax # Gives segment xchgl %eax,%ebp # Get int no/address testb $0x1,%dl # Address? jnz intusr.5 # Yes - shll $0x2,%eax # Scale + shll $0x2,%eax # XXX Scale movl (%eax),%eax # Load int vector -intusr.5: movl %eax,%ecx # Save +intusr.5: movl %eax,%ecx # XXX Save shrl $0x10,%eax # Gives segment stosl # Set CS - movw %cx,%ax # Restore + movw %cx,%ax # XXX Restore stosl # Set EIP leal 0x10(%esp,1),%esp # Discard seg regs popa # Restore @@ -755,7 +755,7 @@ dump.1: testb $DMP_X32,%ch # Dump long? dump.2: testb $DMP_MEM,%ch # Dump memory? jz dump.8 # No pushl %ds # Save - testb $0x2,0x52(%ebx) # V86 mode? + testb $0x2,0x52(%ebx) # XXX V86 mode? jnz dump.3 # Yes verrl 0x4(%esi) # Readable selector? jnz dump.3 # No diff --git a/sys/boot/i386/btx/btxldr/Makefile b/sys/boot/i386/btx/btxldr/Makefile index 32cb4adb0b8e..9df9681867ec 100644 --- a/sys/boot/i386/btx/btxldr/Makefile +++ b/sys/boot/i386/btx/btxldr/Makefile @@ -1,7 +1,6 @@ -# $Id: Makefile,v 1.5 1998/10/13 18:29:18 rnordier Exp $ +# $Id: Makefile,v 1.4 1998/09/25 17:14:15 peter Exp $ ORG=0x100000 -AFLAGS+= --assembler-with-cpp all: btxldr @@ -15,7 +14,7 @@ btxldr: btxldr.o .endif btxldr.o: btxldr.s - ${CC} ${AFLAGS} -c -o ${.TARGET} ${.CURDIR}/btxldr.s + ${AS} ${AFLAGS} -o ${.TARGET} ${.CURDIR}/btxldr.s CLEANFILES+= btxldr btxldr.out btxldr.o diff --git a/sys/boot/i386/btx/btxldr/btxldr.s b/sys/boot/i386/btx/btxldr/btxldr.s index a3172e3e3cb5..7a6bd50b1a15 100644 --- a/sys/boot/i386/btx/btxldr/btxldr.s +++ b/sys/boot/i386/btx/btxldr/btxldr.s @@ -13,7 +13,7 @@ # purpose. # -# $Id: btxldr.s,v 1.3 1998/10/06 07:15:35 rnordier Exp $ +# $Id: btxldr.s,v 1.2 1998/10/06 06:13:36 msmith Exp $ # # Prototype BTX loader program, written in a couple of hours. The @@ -70,24 +70,24 @@ start: cld # String ops inc shll $0xa,%eax # in bytes movl %eax,%ebp # Base of user stack movl $m_mem,%esi # Display - call dhexout # amount of - call dputstr # base memory + call hexout # amount of + call putstr # base memory lgdt gdtdesc # Load new GDT # # Relocate caller's arguments. # movl $m_esp,%esi # Display movl %esp,%eax # caller's - call dhexout # stack - call dputstr # pointer + call hexout # stack + call putstr # pointer movl $m_args,%esi # Format string leal 0x4(%esp,1),%ebx # First argument movl $0x6,%ecx # Count start.1: movl (%ebx),%eax # Get argument and addl $0x4,%ebx # bump pointer - call dhexout # Display it + call hexout # Display it loop start.1 # Till done - call dputstr # End message + call putstr # End message movl $0x48,%ecx # Allocate space subl %ecx,%ebp # for bootinfo movl 0x18(%esp,1),%esi # Source @@ -97,8 +97,8 @@ start.1: movl (%ebx),%eax # Get argument and movl %ebp,0x18(%esp,1) # Update pointer movl $m_rel_bi,%esi # Display movl %ebp,%eax # bootinfo - call dhexout # relocation - call dputstr # message + call hexout # relocation + call putstr # message movl $0x18,%ecx # Allocate space subl %ecx,%ebp # for arguments leal 0x4(%esp,1),%esi # Source @@ -107,8 +107,8 @@ start.1: movl (%ebx),%eax # Get argument and movsb # them movl $m_rel_args,%esi # Display movl %ebp,%eax # argument - call dhexout # relocation - call dputstr # message + call hexout # relocation + call putstr # message # # Set up BTX kernel. # @@ -145,16 +145,16 @@ start.1: movl (%ebx),%eax # Get argument and movl %esi,%ebx # Keep place movl $m_rel_btx,%esi # Restore popl %eax # parameters - call dhexout # and + call hexout # and popl %ebp # display movl %ebp,%eax # the - call dhexout # relocation - call dputstr # message + call hexout # relocation + call putstr # message addl $PAG_SIZ,%ebp # Display movl $m_base,%esi # the movl %ebp,%eax # user - call dhexout # base - call dputstr # address + call hexout # base + call putstr # address # # Set up ELF-format client program. # @@ -164,7 +164,7 @@ start.1: movl (%ebx),%eax # Get argument and call putstr # message start.2: jmp start.2 # Hang start.3: movl $m_elf,%esi # Display ELF - call dputstr # message + call putstr # message movl $m_segs,%esi # Format string movl $0x2,%edi # Segment count movl 0x1c(%ebx),%edx # Get e_phoff @@ -173,14 +173,14 @@ start.3: movl $m_elf,%esi # Display ELF start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD? jne start.6 # No movl 0x4(%edx),%eax # Display - call dhexout # p_offset + call hexout # p_offset movl 0x8(%edx),%eax # Display - call dhexout # p_vaddr + call hexout # p_vaddr movl 0x10(%edx),%eax # Display - call dhexout # p_filesz + call hexout # p_filesz movl 0x14(%edx),%eax # Display - call dhexout # p_memsz - call dputstr # End message + call hexout # p_memsz + call putstr # End message pushl %esi # Save pushl %edi # working pushl %ecx # registers @@ -205,7 +205,7 @@ start.5: popl %ecx # Restore start.6: addl $0x20,%edx # To next entry loop start.4 # Till done start.7: movl $m_done,%esi # Display done - call dputstr # message + call putstr # message movl $start.8,%esi # Real mode stub movl $MEM_STUB,%edi # Destination movl $SIZ_STUB,%ecx # Size @@ -229,10 +229,6 @@ start.9: # # Output message [ESI] followed by EAX in hex. # -dhexout: -#ifndef BTXLDR_VERBOSE - ret -#endif hexout: pushl %eax # Save call putstr # Display message popl %eax # Restore @@ -258,12 +254,6 @@ hexout.2: decl %esi # Adjust for inc # # Output zero-terminated string [ESI] to the console. # -dputstr: -#ifndef BTXLDR_VERBOSE - ret -#else - jmp putstr -#endif putstr.0: call putchr # Output char putstr: lodsb # Load char testb %al,%al # End of string? @@ -272,10 +262,6 @@ putstr: lodsb # Load char # # Output character AL to the console. # -dputchr: -#ifndef BTXLDR_VERBOSE - ret -#endif putchr: pusha # Save xorl %ecx,%ecx # Zero for loops movb $SCR_MAT,%ah # Mode/attribute @@ -351,10 +337,7 @@ gdtdesc: .word gdt.1-gdt-1 # Limit # # Messages. # -m_logo: .asciz "\nBTX loader 0.01 " -m_vers: .asciz "BTX version is \0\n" -e_fmt: .asciz "Error: Client format not supported\n" -#ifdef BTXLDR_VERBOSE +m_logo: .asciz "\nBTX loader 0.01\n" m_mem: .asciz "Starting in protected mode (base mem=\0)\n" m_esp: .asciz "Arguments passed (esp=\0):\n" m_args: .asciz"<howto=" @@ -365,8 +348,10 @@ m_args: .asciz"<howto=" .asciz" bootinfo=\0>\n" m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n" m_rel_args: .asciz "Relocated arguments (size=18) to \0\n" +m_vers: .asciz "BTX version is \0\n" m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n" m_base: .asciz "Client base address is \0\n" +e_fmt: .asciz "Error: Client format not supported\n" m_elf: .asciz "Client format is ELF\n" m_segs: .asciz "text segment: offset=" .asciz " vaddr=" @@ -377,7 +362,6 @@ m_segs: .asciz "text segment: offset=" .asciz " filesz=" .asciz " memsz=\0\n" m_done: .asciz "Loading complete\n" -#endif # # Uninitialized data area. # diff --git a/sys/boot/i386/btx/lib/btxv86.s b/sys/boot/i386/btx/lib/btxv86.s index 46709a39540c..b67e873510e5 100644 --- a/sys/boot/i386/btx/lib/btxv86.s +++ b/sys/boot/i386/btx/lib/btxv86.s @@ -13,7 +13,7 @@ # purpose. # -# $Id: btxv86.s,v 1.1 1998/09/14 10:37:00 rnordier Exp $ +# $Id:$ # # BTX V86 interface. @@ -48,13 +48,11 @@ # # V86 interface function. # -__v86int: popl __v86ret # Save return address - pushl $__v86 # Push pointer +__v86int: pushl $__v86 # Push pointer call __v86_swap # Load V86 registers int $INT_V86 # To BTX call __v86_swap # Load user registers addl $0x4,%esp # Discard pointer - pushl __v86ret # Restore return address ret # To user # # Swap V86 and user registers. @@ -82,4 +80,3 @@ __v86_swap: xchgl %ebp,0x4(%esp,1) # Swap pointer, EBP # V86 interface structure. # .comm __v86,SIZ_V86 - .comm __v86ret,4 diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile index 2cfd2e345956..ec22662921de 100644 --- a/sys/boot/i386/libi386/Makefile +++ b/sys/boot/i386/libi386/Makefile @@ -1,39 +1,26 @@ -# $Id: Makefile,v 1.12 1998/12/22 11:51:25 abial Exp $ +# $Id: Makefile,v 1.7 1998/09/30 22:36:45 peter Exp $ # -LIB= i386 +LIB= i386 NOPIC= NOPROFILE= -INTERNALLIB= true +INTERNALLIB= true INTERNALSTATICLIB= true -SRCS= aout_freebsd.c biosdisk.c biosmem.c biospnp.c biospci.c \ - bootinfo.c comconsole.c devicename.c elf_freebsd.c gatea20.c \ - i386_copy.c i386_module.c time.c vidconsole.c +SRCS= aout_freebsd.c biosdisk.c biosmem.c bootinfo.c comconsole.c \ + devicename.c elf_freebsd.c gatea20.c i386_copy.c i386_module.c time.c vidconsole.c CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../btx/lib \ -I${.CURDIR}/../../.. -I. -BOOT_COMCONSOLE_PORT?= 0x3f8 -CFLAGS+= -DCOMPORT=${BOOT_COMCONSOLE_PORT} - -BOOT_COMCONSOLE_SPEED?= 9600 -CFLAGS+= -DCOMSPEED=${BOOT_COMCONSOLE_SPEED} - # Make the disk code more talkative #CFLAGS+= -DDISK_DEBUG -# Include simple terminal emulation (cons25-compatible) -CFLAGS+= -DTERM_EMU - -# If it's not there, don't consider it a target -.if exists(${.CURDIR}/../../../i386/include) -beforedepend ${OBJS}: machine machine: ln -sf ${.CURDIR}/../../../i386/include machine -.endif - CLEANFILES+= machine .include <bsd.lib.mk> + +beforedepend ${OBJS}: machine diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c index 8b102aefbd5d..1337a92ac0d9 100644 --- a/sys/boot/i386/libi386/biosdisk.c +++ b/sys/boot/i386/libi386/biosdisk.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: biosdisk.c,v 1.19 1999/01/09 02:36:19 msmith Exp $ + * $Id: biosdisk.c,v 1.13 1998/10/11 10:01:55 peter Exp $ */ /* @@ -101,14 +101,10 @@ static int bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest); static int bd_int13probe(struct bdinfo *bd); -static void bd_printslice(struct open_disk *od, int offset, char *prefix); - static int bd_init(void); static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize); -static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize); static int bd_open(struct open_file *f, ...); static int bd_close(struct open_file *f); -static void bd_print(int verbose); struct devsw biosdisk = { "disk", @@ -117,8 +113,7 @@ struct devsw biosdisk = { bd_strategy, bd_open, bd_close, - noioctl, - bd_print + noioctl }; static int bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev); @@ -174,6 +169,7 @@ bd_init(void) /* XXX we need "disk aliases" to make this simpler */ printf("BIOS drive %c: is disk%d\n", (unit < 0x80) ? ('A' + unit) : ('C' + unit - 0x80), nbdinfo); + bdinfo[nbdinfo].bd_unit = unit; nbdinfo++; } } @@ -204,91 +200,6 @@ bd_int13probe(struct bdinfo *bd) } /* - * Print information about disks - */ -static void -bd_print(int verbose) -{ - int i, j; - char line[80]; - struct i386_devdesc dev; - struct open_disk *od; - struct dos_partition *dptr; - - for (i = 0; i < nbdinfo; i++) { - sprintf(line, " disk%d: BIOS drive %c:\n", i, - (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit) : ('C' + bdinfo[i].bd_unit - 0x80)); - pager_output(line); - - /* try to open the whole disk */ - dev.d_kind.biosdisk.unit = i; - dev.d_kind.biosdisk.slice = -1; - dev.d_kind.biosdisk.partition = -1; - - if (!bd_opendisk(&od, &dev)) { - - /* Do we have a partition table? */ - if (od->od_flags & BD_PARTTABOK) { - dptr = &od->od_parttab[0]; - - /* Check for a "truly dedicated" disk */ - if ((dptr[3].dp_typ == DOSPTYP_386BSD) && - (dptr[3].dp_start == 0) && - (dptr[3].dp_size == 50000)) { - sprintf(line, " disk%d", i); - bd_printslice(od, 0, line); - } else { - for (j = 0; j < NDOSPART; j++) { - switch(dptr[j].dp_typ) { - case DOSPTYP_386BSD: - sprintf(line, " disk%ds%d", i, j + 1); - bd_printslice(od, dptr[j].dp_start, line); - break; - default: - } - } - - } - } - bd_closedisk(od); - } - } -} - -static void -bd_printslice(struct open_disk *od, int offset, char *prefix) -{ - char line[80]; - u_char buf[BIOSDISK_SECSIZE]; - struct disklabel *lp; - int i; - - /* read disklabel */ - if (bd_read(od, offset + LABELSECTOR, 1, buf)) - return; - lp =(struct disklabel *)(&buf[0]); - if (lp->d_magic != DISKMAGIC) { - sprintf(line, "%s: bad disklabel\n"); - pager_output(line); - return; - } - - /* Print partitions */ - for (i = 0; i < lp->d_npartitions; i++) { - if ((lp->d_partitions[i].p_fstype == FS_BSDFFS) || (lp->d_partitions[i].p_fstype == FS_SWAP) || - ((lp->d_partitions[i].p_fstype == FS_UNUSED) && - (od->od_flags & BD_FLOPPY) && (i == 0))) { /* Floppies often have bogus fstype, print 'a' */ - sprintf(line, " %s%c: %s %.6dMB (%d - %d)\n", prefix, 'a' + i, - (lp->d_partitions[i].p_fstype == FS_SWAP) ? "swap" : "FFS", - lp->d_partitions[i].p_size / 2048, /* 512-byte sector assumption */ - lp->d_partitions[i].p_offset, lp->d_partitions[i].p_offset + lp->d_partitions[i].p_size); - pager_output(line); - } - } -} - - -/* * Attempt to open the disk described by (dev) for use by (f). * * Note that the philosophy here is "give them exactly what @@ -391,14 +302,8 @@ bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev) dptr = &od->od_parttab[0]; od->od_flags |= BD_PARTTABOK; - /* Is this a request for the whole disk? */ - if (dev->d_kind.biosdisk.slice == -1) { - sector == 0; - goto unsliced; - } - /* Try to auto-detect the best slice; this should always give a slice number */ - if (dev->d_kind.biosdisk.slice == 0) + if (dev->d_kind.biosdisk.slice < 1) dev->d_kind.biosdisk.slice = bd_bestslice(dptr); switch (dev->d_kind.biosdisk.slice) { @@ -406,7 +311,6 @@ bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev) error = ENOENT; goto out; case 0: - sector = 0; goto unsliced; default: break; @@ -570,16 +474,6 @@ bd_closedisk(struct open_disk *od) static int bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize) { - struct bcache_devdata bcd; - - bcd.dv_strategy = bd_realstrategy; - bcd.dv_devdata = devdata; - return(bcache_strategy(&bcd, rw, dblk, size, buf, rsize)); -} - -static int -bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize) -{ struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data); int blks; #ifdef BD_SUPPORT_FRAGS @@ -747,10 +641,7 @@ bd_getgeom(struct open_disk *od) } /* - * Return a suitable dev_t value for (dev). - * - * In the case where it looks like (dev) is a SCSI disk, we allow the number of - * IDE disks to be specified in $num_ide_disks. There should be a Better Way. + * Return a suitable dev_t value for (dev) */ int bd_getdev(struct i386_devdesc *dev) @@ -759,8 +650,6 @@ bd_getdev(struct i386_devdesc *dev) int biosdev; int major; int rootdev; - char *nip, *cp; - int unitofs = 0; biosdev = bd_unit2bios(dev->d_kind.biosdisk.unit); DEBUG("unit %d BIOS device %d", dev->d_kind.biosdisk.unit, biosdev); @@ -783,13 +672,6 @@ bd_getdev(struct i386_devdesc *dev) if ((od->od_flags & BD_LABELOK) && (od->od_disklabel.d_type == DTYPE_SCSI)) { /* label OK, disk labelled as SCSI */ major = DAMAJOR; - /* check for unit number correction hint */ - if ((nip = getenv("num_ide_disks")) != NULL) { - unitofs = strtol(nip, &cp, 0); - /* check for parse error */ - if ((cp == nip) || (*cp != 0)) - unitofs = 0; - } } else { /* assume an IDE disk */ major = WDMAJOR; @@ -798,7 +680,7 @@ bd_getdev(struct i386_devdesc *dev) rootdev = MAKEBOOTDEV(major, (dev->d_kind.biosdisk.slice + 1) >> 4, /* XXX slices may be wrong here */ (dev->d_kind.biosdisk.slice + 1) & 0xf, - (biosdev & 0x7f) - unitofs, /* allow for #wd compenstation in da case */ + biosdev & 0x7f, /* XXX allow/compute shift for da when wd present */ dev->d_kind.biosdisk.partition); DEBUG("dev is 0x%x\n", rootdev); return(rootdev); diff --git a/sys/boot/i386/libi386/biospci.c b/sys/boot/i386/libi386/biospci.c deleted file mode 100644 index 92f4fd28c297..000000000000 --- a/sys/boot/i386/libi386/biospci.c +++ /dev/null @@ -1,294 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - */ - -/* - * PnP enumerator using the PCI BIOS. - */ - -#include <stand.h> -#include <string.h> -#include <machine/stdarg.h> -#include <bootstrap.h> -#include <isapnp.h> -#include <btxv86.h> - -/* - * Stupid PCI BIOS interface doesn't let you simply enumerate everything - * that's there, instead you have to ask it if it has something. - * - * So we have to scan by class code, subclass code and sometimes programming - * interface. - */ - -struct pci_progif -{ - int pi_code; - char *pi_name; -}; - -static struct pci_progif progif_null[] = { - {0x0, NULL}, - {-1, NULL} -}; - -static struct pci_progif progif_display[] = { - {0x0, "VGA"}, - {0x1, "8514"}, - {-1, NULL} -}; - -static struct pci_progif progif_ide[] = { - {0x00, NULL}, - {0x01, NULL}, - {0x02, NULL}, - {0x03, NULL}, - {0x04, NULL}, - {0x05, NULL}, - {0x06, NULL}, - {0x07, NULL}, - {0x08, NULL}, - {0x09, NULL}, - {0x0a, NULL}, - {0x0b, NULL}, - {0x0c, NULL}, - {0x0d, NULL}, - {0x0e, NULL}, - {0x0f, NULL}, - {0x80, NULL}, - {0x81, NULL}, - {0x82, NULL}, - {0x83, NULL}, - {0x84, NULL}, - {0x85, NULL}, - {0x86, NULL}, - {0x87, NULL}, - {0x88, NULL}, - {0x89, NULL}, - {0x8a, NULL}, - {0x8b, NULL}, - {0x8c, NULL}, - {0x8d, NULL}, - {0x8e, NULL}, - {0x8f, NULL}, - {-1, NULL} -}; - -static struct pci_progif progif_serial[] = { - {0x0, "8250"}, - {0x1, "16450"}, - {0x2, "16550"}, - {-1, NULL} -}; - -static struct pci_progif progif_parallel[] = { - {0x0, "Standard"}, - {0x1, "Bidirectional"}, - {0x2, "ECP"}, - {-1, NULL} -}; - - -struct pci_subclass -{ - int ps_subclass; - char *ps_name; - struct pci_progif *ps_progif; /* if set, use for programming interface value(s) */ -}; - -static struct pci_subclass subclass_old[] = { - {0x0, "Old non-VGA", progif_null}, - {0x1, "Old VGA", progif_null}, - {-1, NULL, NULL} -}; - -static struct pci_subclass subclass_mass[] = { - {0x0, "SCSI", progif_null}, - {0x1, "IDE", progif_ide}, - {0x2, "Floppy disk", progif_null}, - {0x3, "IPI", progif_null}, - {0x4, "RAID", progif_null}, - {0x80, "mass storage", progif_null}, - {-1, NULL, NULL} -}; - -static struct pci_subclass subclass_net[] = { - {0x0, "Ethernet", progif_null}, - {0x1, "Token ring", progif_null}, - {0x2, "FDDI", progif_null}, - {0x3, "ATM", progif_null}, - {0x80, "network", progif_null}, - {-1, NULL, NULL} -}; - -static struct pci_subclass subclass_display[] = { - {0x0, NULL, progif_display}, - {0x1, "XGA", progif_null}, - {0x80, "other", progif_null}, - {-1, NULL, NULL} -}; - -static struct pci_subclass subclass_comms[] = { - {0x0, "serial", progif_serial}, - {0x1, "parallel", progif_parallel}, - {0x80, "communications", progif_null}, - {-1, NULL, NULL} -}; - -static struct pci_subclass subclass_serial[] = { - {0x0, "Firewire", progif_null}, - {0x1, "ACCESS.bus", progif_null}, - {0x2, "SSA", progif_null}, - {0x3, "USB", progif_null}, - {0x4, "Fibrechannel", progif_null}, - {-1, NULL, NULL} -}; - -static struct pci_class -{ - int pc_class; - char *pc_name; - struct pci_subclass *pc_subclass; -} pci_classes[] = { - {0x0, "device", subclass_old}, - {0x1, "controller", subclass_mass}, - {0x2, "controller", subclass_net}, - {0x3, "display", subclass_display}, - {0x7, "controller", subclass_comms}, - {0xc, "controller", subclass_serial}, - {-1, NULL, NULL} -}; - - -static void biospci_enumerate(void); -static void biospci_addinfo(int devid, struct pci_class *pc, struct pci_subclass *psc, struct pci_progif *ppi); - -static int biospci_version; -static int biospci_hwcap; - -struct pnphandler biospcihandler = -{ - "PCI BIOS", - biospci_enumerate -}; - -static void -biospci_enumerate(void) -{ - int index, locator, devid; - struct pci_class *pc; - struct pci_subclass *psc; - struct pci_progif *ppi; - - /* Find the PCI BIOS */ - v86.ctl = V86_FLAGS; - v86.addr = 0x1a; - v86.eax = 0xb101; - v86.edi = 0x0; - v86int(); - - /* Check for OK response */ - if ((v86.efl & 1) || ((v86.eax & 0xff00) != 0) || (v86.edx != 0x20494350)) - return; - - biospci_version = v86.ebx & 0xffff; - biospci_hwcap = v86.eax & 0xff; -#if 0 - printf("PCI BIOS %d.%d%s%s\n", - bcd2bin((biospci_version >> 8) & 0xf), bcd2bin(biospci_version & 0xf), - (biospci_hwcap & 1) ? " config1" : "", (biospci_hwcap & 2) ? " config2" : ""); -#endif - /* Iterate over known classes */ - for (pc = pci_classes; pc->pc_class >= 0; pc++) { - /* Iterate over subclasses */ - for (psc = pc->pc_subclass; psc->ps_subclass >= 0; psc++) { - /* Iterate over programming interfaces */ - for (ppi = psc->ps_progif; ppi->pi_code >= 0; ppi++) { - - /* Scan for matches */ - for (index = 0; ; index++) { - - /* Look for a match */ - v86.ctl = V86_FLAGS; - v86.addr = 0x1a; - v86.eax = 0xb103; - v86.ecx = (pc->pc_class << 16) + (psc->ps_subclass << 8) + ppi->pi_code; - v86.esi = index; - v86int(); - /* error/end of matches */ - if ((v86.efl & 1) || (v86.eax & 0xff00)) - break; - - /* Got something */ - locator = v86.ebx; - - /* Read the device identifier from the nominated device */ - v86.ctl = V86_FLAGS; - v86.addr = 0x1a; - v86.eax = 0xb10a; - v86.ebx = locator; - v86.edi = 0x0; - v86int(); - /* error */ - if ((v86.efl & 1) || (v86.eax & 0xff00)) - break; - - /* We have the device ID, create a PnP object and save everything */ - devid = v86.ecx; - biospci_addinfo(devid, pc, psc, ppi); - } - } - } - } -} - -static void -biospci_addinfo(int devid, struct pci_class *pc, struct pci_subclass *psc, struct pci_progif *ppi) -{ - struct pnpinfo *pi; - char desc[80]; - - - /* build the description */ - desc[0] = 0; - if (ppi->pi_name != NULL) { - strcat(desc, ppi->pi_name); - strcat(desc, " "); - } - if (psc->ps_name != NULL) { - strcat(desc, psc->ps_name); - strcat(desc, " "); - } - if (pc->pc_name != NULL) - strcat(desc, pc->pc_name); - - pi = pnp_allocinfo(); - pi->pi_desc = strdup(desc); - sprintf(desc,"0x%08x", devid); - pnp_addident(pi, desc); - pnp_addinfo(pi); -} diff --git a/sys/boot/i386/libi386/biospnp.c b/sys/boot/i386/libi386/biospnp.c deleted file mode 100644 index a6064ba27462..000000000000 --- a/sys/boot/i386/libi386/biospnp.c +++ /dev/null @@ -1,289 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: biospnp.c,v 1.2 1998/10/23 22:29:08 msmith Exp $ - */ - -/* - * PnP BIOS enumerator. - */ - -#include <stand.h> -#include <string.h> -#include <machine/stdarg.h> -#include <bootstrap.h> -#include <isapnp.h> -#include <btxv86.h> - - -static int biospnp_init(void); -static void biospnp_enumerate(void); - -struct pnphandler biospnphandler = -{ - "PnP BIOS", - biospnp_enumerate -}; - -struct pnp_ICstructure -{ - u_int8_t pnp_signature[4] __attribute__ ((packed)); - u_int8_t pnp_version __attribute__ ((packed)); - u_int8_t pnp_length __attribute__ ((packed)); - u_int16_t pnp_BIOScontrol __attribute__ ((packed)); - u_int8_t pnp_checksum __attribute__ ((packed)); - u_int32_t pnp_eventflag __attribute__ ((packed)); - u_int16_t pnp_rmip __attribute__ ((packed)); - u_int16_t pnp_rmcs __attribute__ ((packed)); - u_int16_t pnp_pmip __attribute__ ((packed)); - u_int32_t pnp_pmcs __attribute__ ((packed)); - u_int8_t pnp_OEMdev[4] __attribute__ ((packed)); - u_int16_t pnp_rmds __attribute__ ((packed)); - u_int32_t pnp_pmds __attribute__ ((packed)); -}; - -struct pnp_devNode -{ - u_int16_t dn_size __attribute__ ((packed)); - u_int8_t dn_handle __attribute__ ((packed)); - u_int8_t dn_id[4] __attribute__ ((packed)); - u_int8_t dn_type[3] __attribute__ ((packed)); - u_int16_t dn_attrib __attribute__ ((packed)); - u_int8_t dn_data[0] __attribute__ ((packed)); -}; - -struct pnp_isaConfiguration -{ - u_int8_t ic_revision __attribute__ ((packed)); - u_int8_t ic_nCSN __attribute__ ((packed)); - u_int16_t ic_rdport __attribute__ ((packed)); - u_int16_t ic_reserved __attribute__ ((packed)); -}; - -static struct pnp_ICstructure *pnp_Icheck = NULL; -static u_int16_t pnp_NumNodes; -static u_int16_t pnp_NodeSize; - -static void biospnp_scanresdata(struct pnpinfo *pi, struct pnp_devNode *dn); -static int biospnp_call(int func, char *fmt, ...); - -#define vsegofs(vptr) (((u_int32_t)VTOPSEG(vptr) << 16) + VTOPOFF(vptr)) -void (* v86bios)(u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) = (void *)v86int; - -#define biospnp_f00(NumNodes, NodeSize) biospnp_call(0x00, "ll", NumNodes, NodeSize) -#define biospnp_f01(Node, devNodeBuffer, Control) biospnp_call(0x01, "llw", Node, devNodeBuffer, Control) -#define biospnp_f40(Configuration) biospnp_call(0x40, "l", Configuration) - -/* PnP BIOS return codes */ -#define PNP_SUCCESS 0x00 -#define PNP_FUNCTION_NOT_SUPPORTED 0x80 - -/* - * Initialisation: locate the PnP BIOS, test that we can call it. - * Returns nonzero if the PnP BIOS is not usable on this system. - */ -static int -biospnp_init(void) -{ - struct pnp_isaConfiguration icfg; - char *sigptr; - int result; - - /* Search for the $PnP signature */ - pnp_Icheck = NULL; - for (sigptr = PTOV(0xf0000); sigptr < PTOV(0xfffff); sigptr += 16) - if (!bcmp(sigptr, "$PnP", 4)) { - pnp_Icheck = (struct pnp_ICstructure *)sigptr; - break; - } - - /* No signature, no BIOS */ - if (pnp_Icheck == NULL) - return(1); - - /* - * Fetch the system table parameters as a test of the BIOS - */ - result = biospnp_f00(vsegofs(&pnp_NumNodes), vsegofs(&pnp_NodeSize)); - if (result != PNP_SUCCESS) { - return(1); - } - - /* - * Look for the PnP ISA configuration table - */ - result = biospnp_f40(vsegofs(&icfg)); - switch (result) { - case PNP_SUCCESS: - /* If the BIOS found some PnP devices, take its hint for the read port */ - if ((icfg.ic_revision == 1) && (icfg.ic_nCSN > 0)) - isapnp_readport = icfg.ic_rdport; - break; - case PNP_FUNCTION_NOT_SUPPORTED: - /* The BIOS says there is no ISA bus (should we trust that this works?) */ - printf("PnP BIOS claims no ISA bus\n"); - isapnp_readport = -1; - break; - } - return(0); -} - -static void -biospnp_enumerate(void) -{ - u_int8_t Node; - struct pnp_devNode *devNodeBuffer; - int result; - struct pnpinfo *pi; - int count; - - /* Init/check state */ - if (biospnp_init()) - return; - - devNodeBuffer = (struct pnp_devNode *)malloc(pnp_NodeSize); - Node = 0; - count = 1000; - while((Node != 0xff) && (count-- > 0)) { - result = biospnp_f01(vsegofs(&Node), vsegofs(devNodeBuffer), 0x1); - if (result != PNP_SUCCESS) { - printf("PnP BIOS node %d: error 0x%x\n", Node, result); - } else { - pi = pnp_allocinfo(); - pnp_addident(pi, pnp_eisaformat(devNodeBuffer->dn_id)); - biospnp_scanresdata(pi, devNodeBuffer); - pnp_addinfo(pi); - } - } -} - -/* - * Scan the resource data in the node's data area for compatible device IDs - * and descriptions. - */ -static void -biospnp_scanresdata(struct pnpinfo *pi, struct pnp_devNode *dn) -{ - int tag, i, rlen, dlen; - u_int8_t *p; - char *str; - - p = dn->dn_data; /* point to resource data */ - dlen = dn->dn_size - (p - (u_int8_t *)dn); /* length of resource data */ - - for (i = 0; i < dlen; i+= rlen) { - tag = p[i]; - i++; - if (PNP_RES_TYPE(tag) == 0) { - rlen = PNP_SRES_LEN(tag); - /* small resource */ - switch (PNP_SRES_NUM(tag)) { - - case COMP_DEVICE_ID: - /* got a compatible device ID */ - pnp_addident(pi, pnp_eisaformat(p + i)); - break; - - case END_TAG: - return; - } - } else { - /* large resource */ - rlen = *(u_int16_t *)(p + i); - i += sizeof(u_int16_t); - - switch(PNP_LRES_NUM(tag)) { - - case ID_STRING_ANSI: - str = malloc(rlen + 1); - bcopy(p + i, str, rlen); - str[rlen] = 0; - if (pi->pi_desc == NULL) { - pi->pi_desc = str; - } else { - free(str); - } - break; - } - } - } -} - - -/* - * Make a 16-bit realmode PnP BIOS call. - * - * The first argument passed is the function number, the last is the - * BIOS data segment selector. Intermediate arguments may be 16 or - * 32 bytes in length, and are described by the format string. - * - * Arguments to the BIOS functions must be packed on the stack, hence - * this evil. - */ -static int -biospnp_call(int func, char *fmt, ...) -{ - va_list ap; - char *p; - u_int8_t *argp; - u_int32_t args[4]; - u_int32_t i; - - /* function number first */ - argp = (u_int8_t *)args; - *(u_int16_t *)argp = func; - argp += sizeof(u_int16_t); - - /* take args according to format */ - va_start(ap, fmt); - for (p = fmt; *p != 0; p++) { - switch(*p) { - - case 'w': - i = va_arg(ap, u_int16_t); - *(u_int16_t *)argp = i; - argp += sizeof(u_int16_t); - break; - - case 'l': - i = va_arg(ap, u_int32_t); - *(u_int32_t *)argp = i; - argp += sizeof(u_int32_t); - break; - } - } - - /* BIOS segment last */ - *(u_int16_t *)argp = pnp_Icheck->pnp_rmds; - argp += sizeof(u_int16_t); - - /* prepare for call */ - v86.ctl = V86_ADDR | V86_CALLF; - v86.addr = ((u_int32_t)pnp_Icheck->pnp_rmcs << 16) + pnp_Icheck->pnp_rmip; - - /* call with packed stack and return */ - v86bios(args[0], args[1], args[2], args[3]); - return(v86.eax & 0xffff); -} diff --git a/sys/boot/i386/libi386/bootinfo.c b/sys/boot/i386/libi386/bootinfo.c index 77ba8b75a83a..5b479cd3446e 100644 --- a/sys/boot/i386/libi386/bootinfo.c +++ b/sys/boot/i386/libi386/bootinfo.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bootinfo.c,v 1.14 1998/10/15 17:06:36 peter Exp $ + * $Id: bootinfo.c,v 1.13 1998/10/14 05:07:23 peter Exp $ */ #include <stand.h> @@ -249,7 +249,9 @@ bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip) printf("can't determine root device\n"); return(EINVAL); } - + + /* Boot from whatever the current device is */ + i386_getdev((void **)(&rootdev), NULL, NULL); switch(rootdev->d_type) { case DEVT_DISK: /* pass in the BIOS device number of the current disk */ diff --git a/sys/boot/i386/libi386/comconsole.c b/sys/boot/i386/libi386/comconsole.c index 7b35d1dce8c9..261e909d225b 100644 --- a/sys/boot/i386/libi386/comconsole.c +++ b/sys/boot/i386/libi386/comconsole.c @@ -22,45 +22,16 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: comconsole.c,v 1.5 1998/11/22 07:59:16 rnordier Exp $ + * From Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp + * + * $Id: comconsole.c,v 1.3 1998/10/02 16:32:45 msmith Exp $ */ #include <stand.h> #include <bootstrap.h> -#include <machine/cpufunc.h> +#include <btxv86.h> #include "libi386.h" -/* selected defines from ns16550.h */ -#define com_data 0 /* data register (R/W) */ -#define com_dlbl 0 /* divisor latch low (W) */ -#define com_dlbh 1 /* divisor latch high (W) */ -#define com_ier 1 /* interrupt enable (W) */ -#define com_iir 2 /* interrupt identification (R) */ -#define com_fifo 2 /* FIFO control (W) */ -#define com_lctl 3 /* line control register (R/W) */ -#define com_cfcr 3 /* line control register (R/W) */ -#define com_mcr 4 /* modem control register (R/W) */ -#define com_lsr 5 /* line status register (R/W) */ -#define com_msr 6 /* modem status register (R/W) */ - -/* selected defines from sioreg.h */ -#define CFCR_DLAB 0x80 -#define MCR_RTS 0x02 -#define MCR_DTR 0x01 -#define LSR_TXRDY 0x20 -#define LSR_RXRDY 0x01 - -#define COMC_FMT 0x3 /* 8N1 */ -#define COMC_TXWAIT 0x40000 /* transmit timeout */ -#define COMC_BPS(x) (115200 / (x)) /* speed to DLAB divisor */ - -#ifndef COMPORT -#define COMPORT 0x3f8 -#endif -#ifndef COMSPEED -#define COMSPEED 9600 -#endif - static void comc_probe(struct console *cp); static int comc_init(int arg); static void comc_putchar(int c); @@ -71,7 +42,7 @@ static int comc_started; struct console comconsole = { "comconsole", - "serial port", + "BIOS serial port", 0, comc_probe, comc_init, @@ -80,6 +51,8 @@ struct console comconsole = { comc_ischar }; +#define BIOS_COMPORT 0 + static void comc_probe(struct console *cp) { @@ -90,19 +63,19 @@ comc_probe(struct console *cp) static int comc_init(int arg) { + int i; + if (comc_started && arg == 0) return 0; comc_started = 1; + v86.ctl = 0; + v86.addr = 0x14; + v86.eax = 0xe3; /* 9600N81 */ + v86.edx = BIOS_COMPORT; /* XXX take as arg, or use env var? */ + v86int(); - outb(COMPORT + com_cfcr, CFCR_DLAB | COMC_FMT); - outb(COMPORT + com_dlbl, COMC_BPS(COMSPEED) & 0xff); - outb(COMPORT + com_dlbh, COMC_BPS(COMSPEED) >> 8); - outb(COMPORT + com_cfcr, COMC_FMT); - outb(COMPORT + com_mcr, MCR_RTS | MCR_DTR); - - do - inb(COMPORT + com_data); - while (inb(COMPORT + com_lsr) & LSR_RXRDY); + for(i = 0; i < 10 && comc_ischar(); i++) + (void)comc_getchar(); return(0); } @@ -110,23 +83,35 @@ comc_init(int arg) static void comc_putchar(int c) { - int wait; - - for (wait = COMC_TXWAIT; wait > 0; wait--) - if (inb(COMPORT + com_lsr) & LSR_TXRDY) { - outb(COMPORT + com_data, c); - break; - } + v86.ctl = 0; + v86.addr = 0x14; + v86.eax = 0x100 | c; /* Function 1 = write */ + v86.edx = BIOS_COMPORT; /* XXX take as arg, or use env var? */ + v86int(); } static int comc_getchar(void) { - return(comc_ischar() ? inb(COMPORT + com_data) : -1); + if (comc_ischar()) { + v86.ctl = 0; + v86.addr = 0x14; + v86.eax = 0x200; /* Function 2 = read */ + v86.edx = BIOS_COMPORT; /* XXX take as arg, or use env var? */ + v86int(); + return(v86.eax & 0xff); + } else { + return(-1); + } } static int comc_ischar(void) { - return(inb(COMPORT + com_lsr) & LSR_RXRDY); + v86.ctl = 0; + v86.addr = 0x14; + v86.eax = 0x300; /* Function 3 = status */ + v86.edx = BIOS_COMPORT; /* XXX take as arg, or use env var? */ + v86int(); + return(v86.eax & 0x100); /* AH bit 1 is "receive data ready" */ } diff --git a/sys/boot/i386/libi386/vidconsole.c b/sys/boot/i386/libi386/vidconsole.c index 05e77110c2ef..c67cd72061b5 100644 --- a/sys/boot/i386/libi386/vidconsole.c +++ b/sys/boot/i386/libi386/vidconsole.c @@ -26,7 +26,7 @@ * * From Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp * - * $Id: vidconsole.c,v 1.10 1998/12/31 13:44:04 abial Exp $ + * $Id: vidconsole.c,v 1.5 1998/10/07 07:34:31 msmith Exp $ */ #include <stand.h> @@ -48,28 +48,6 @@ static int vidc_ischar(void); static int vidc_started; -#ifdef TERM_EMU -void end_term(); -void bail_out(int c); -void vidc_term_emu(int c); -void get_pos(void); -void curs_move(int x, int y); -void write_char(int c, int fg, int bg); -void scroll_up(int rows, int fg, int bg); -void AB(void); -void AF(void); -void CD(void); -void CM(void); -void HO(void); -void ME(void); - -static int args[2],argc,br; -static int fg,bg,dig; -static int fg_c,bg_c,curx,cury; -static int esc; -#endif - - struct console vidconsole = { "vidconsole", "internal video/keyboard", @@ -106,390 +84,21 @@ vidc_init(int arg) if (vidc_started && arg == 0) return; vidc_started = 1; -#ifdef TERM_EMU - /* Init terminal emulator */ - end_term(); - get_pos(); - curs_move(curx,cury); - fg_c=7; - bg_c=0; -#endif for(i = 0; i < 10 && vidc_ischar(); i++) (void)vidc_getchar(); return(0); /* XXX reinit? */ } static void -vidc_biosputchar(int c) +vidc_putchar(int c) { v86.ctl = 0; v86.addr = 0x10; - v86.eax = 0xe00 | (c & 0xff); + v86.eax = 0xe00 | c; v86.ebx = 0x7; v86int(); } -static void -vidc_rawputchar(int c) -{ - int i; - - if(c == '\t') - /* lame tab expansion */ - for (i = 0; i < 8; i++) - vidc_rawputchar(' '); - else { -#ifndef TERM_EMU - vidc_biosputchar(c); -#else - /* Emulate AH=0eh (teletype output) */ - switch(c) { - case '\a': - vidc_biosputchar(c); - return; - case '\r': - curx=0; - curs_move(curx,cury); - return; - case '\n': - cury++; - if(cury>24) { - scroll_up(1,fg_c,bg_c); - cury--; - } else { - curs_move(curx,cury); - } - return; - case '\b': - if(curx>0) { - curx--; - curs_move(curx,cury); - /* write_char(' ',fg_c,bg_c); XXX destructive(!) */ - return; - } - return; - default: - write_char(c,fg_c,bg_c); - curx++; - if(curx>79) { - curx=0; - cury++; - } - if(cury>24) { - curx=0; - scroll_up(1,fg_c,bg_c); - cury--; - } - } - curs_move(curx,cury); -#endif - } -} - -#ifdef TERM_EMU - -/* Get cursor position on the screen. Result is in edx. Sets - * curx and cury appropriately. - */ -void -get_pos(void) -{ - v86.ctl = 0; - v86.addr = 0x10; - v86.eax = 0x0300; - v86.ebx = 0x0; - v86int(); - curx=v86.edx & 0x00ff; - cury=(v86.edx & 0xff00)>>8; -} - -/* Move cursor to x rows and y cols (0-based). */ -void -curs_move(int x, int y) -{ - v86.ctl = 0; - v86.addr = 0x10; - v86.eax = 0x0200; - v86.ebx = 0x0; - v86.edx = ((0x00ff & y)<<8)+(0x00ff & x); - v86int(); - curx=x; - cury=y; - /* If there is ctrl char at this position, cursor would be invisible. - * Make it a space instead. - */ - v86.ctl=0; - v86.addr = 0x10; - v86.eax = 0x0800; - v86.ebx= 0x0; - v86int(); -#define isvisible(c) (((c)>32) && ((c)<255)) - if(!isvisible(v86.eax & 0x00ff)) { - write_char(' ',fg_c,bg_c); - } -} - -/* Scroll up the whole window by a number of rows. If rows==0, - * clear the window. fg and bg are attributes for the new lines - * inserted in the window. - */ -void -scroll_up(int rows, int fg, int bg) -{ - if(rows==0) rows=25; - v86.ctl = 0; - v86.addr = 0x10; - v86.eax = 0x0600+(0x00ff & rows); - v86.ebx = (bg<<12)+(fg<<8); - v86.ecx = 0x0; - v86.edx = 0x184f; - v86int(); -} - -/* Write character and attribute at cursor position. */ -void -write_char(int c, int fg, int bg) -{ - v86.ctl=0; - v86.addr = 0x10; - v86.eax = 0x0900+(0x00ff & c); - v86.ebx = (bg<<4)+fg; - v86.ecx = 0x1; - v86int(); -} - -/* Calculate power of 10 */ -int -pow10(int i) -{ - int res=1; - - while(i-->0) { - res*=10; - } - return res; -} - -/**************************************************************/ -/* - * Screen manipulation functions. They use accumulated data in - * args[] and argc variables. - * - */ - -/* Set background color */ -void -AB(void){ - bg_c=args[0]; - end_term(); -} - -/* Set foreground color */ -void -AF(void) -{ - fg_c=args[0]; - end_term(); -} - -/* Clear display from current position to end of screen */ -void -CD(void) -{ - get_pos(); - v86.ctl = 0; - v86.addr = 0x10; - v86.eax = 0x0600; - v86.ebx = (bg_c<<4)+fg_c; - v86.ecx = v86.edx; - v86.edx = 0x184f; - v86int(); - curx=0; - curs_move(curx,cury); - end_term(); -} - -/* Absolute cursor move to args[0] rows and args[1] columns - * (the coordinates are 1-based). - */ -void -CM(void) -{ - if(args[0]>0) args[0]--; - if(args[1]>0) args[1]--; - curs_move(args[1],args[0]); - end_term(); -} - -/* Home cursor (left top corner) */ -void -HO(void) -{ - argc=1; - args[0]=args[1]=1; - CM(); -} - -/* Exit attribute mode (reset fore/back-ground colors to defaults) */ -void -ME(void) -{ - fg_c=7; - bg_c=0; - end_term(); -} - -/* Clear internal state of the terminal emulation code */ -void -end_term(void) -{ - esc=0; - argc=-1; - fg=bg=br=0; - args[0]=args[1]=0; - dig=0; -} - -/* Gracefully exit ESC-sequence processing in case of misunderstanding */ -void -bail_out(int c) -{ - char buf[6],*ch; - - if(esc) vidc_rawputchar('\033'); - if(br) vidc_rawputchar('['); - if(argc>-1) { - sprintf(buf,"%d",args[0]); - ch=buf; - while(*ch) vidc_rawputchar(*ch++); - - if(argc>0) { - vidc_rawputchar(';'); - sprintf(buf,"%d",args[1]); - ch=buf; - while(*ch) vidc_rawputchar(*ch++); - } - } - vidc_rawputchar(c); - end_term(); -} - -/* Emulate basic capabilities of cons25 terminal */ -void -vidc_term_emu(int c) -{ - - if(!esc) { - if(c=='\033') { - esc=1; - } else { - vidc_rawputchar(c); - } - return; - } - - /* Do ESC sequences processing */ - switch(c) { - case '\033': - /* ESC in ESC sequence - error */ - bail_out(c); - break; - case '[': - /* Check if it's first char after ESC */ - if(argc<0) { - br=1; - } else { - bail_out(c); - } - break; - case 'H': - /* Emulate \E[H (cursor home) and - * \E%d;%dH (cursor absolute move) */ - if(br) { - switch(argc) { - case -1: - HO(); - break; - case 1: - if(fg) args[0]+=pow10(dig)*3; - if(bg) args[0]+=pow10(dig)*4; - CM(); - break; - default: - bail_out(c); - } - } else bail_out(c); - break; - case 'J': - /* Emulate \EJ (clear to end of screen) */ - if(br && argc<0) { - CD(); - } else bail_out(c); - break; - case ';': - /* perhaps args separator */ - if(br && (argc>-1)) { - argc++; - } else bail_out(c); - break; - case 'm': - /* Change char attributes */ - if(br) { - switch(argc) { - case -1: - ME(); - break; - case 0: - if(fg) AF(); - else AB(); - break; - default: - bail_out(c); - } - } else bail_out(c); - break; - default: - if(isdigit(c)) { - /* Carefully collect numeric arguments */ - /* XXX this is ugly. */ - if(br) { - if(argc==-1) { - argc=0; - args[argc]=0; - dig=0; - /* in case we're in error... */ - if(c=='3') { - fg=1; - return; - } - if(c=='4') { - bg=1; - return; - } - args[argc]=(int)(c-'0'); - dig=1; - args[argc+1]=0; - } else { - args[argc]=args[argc]*10+(int)(c-'0'); - if(argc==0) dig++; - } - } else bail_out(c); - } else bail_out(c); - break; - } -} -#endif - -static void -vidc_putchar(int c) -{ -#ifdef TERM_EMU - vidc_term_emu(c); -#else - vidc_rawputchar(c); -#endif -} - static int vidc_getchar(void) { @@ -511,7 +120,9 @@ vidc_ischar(void) v86.addr = 0x16; v86.eax = 0x100; v86int(); - return(!(v86.efl & PSL_Z)); + if (!(v86.efl & PSL_Z)) + return(v86.eax & 0xff); + return(0); } #if KEYBOARD_PROBE @@ -537,7 +148,7 @@ static void delay7(void) { /* - * I know this is broken, but no timer is available yet at this stage... + * I know this is broken, but no timer is avaiable yet at this stage... * See also comments in `delay1ms()'. */ inb(IO_DUMMY); inb(IO_DUMMY); diff --git a/sys/boot/i386/loader/Makefile b/sys/boot/i386/loader/Makefile index 053fbd348862..02fd2d005a1a 100644 --- a/sys/boot/i386/loader/Makefile +++ b/sys/boot/i386/loader/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.27 1999/01/11 05:52:28 msmith Exp $ +# $Id: Makefile,v 1.11 1998/10/12 01:03:00 rnordier Exp $ BASE= loader PROG= ${BASE} @@ -11,17 +11,8 @@ BINDIR?= /boot SRCS= main.c conf.c # Enable PnP and ISA-PnP code. -HAVE_PNP= yes -HAVE_ISABUS= yes - -# Enable BootForth -BOOT_FORTH= yes -CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -.if exists(${.OBJDIR}/../../ficl/libficl.a) -LIBFICL= ${.OBJDIR}/../../ficl/libficl.a -.else -LIBFICL= ${.CURDIR}/../../ficl/libficl.a -.endif +#HAVE_PNP= yes +#HAVE_ISABUS= yes # Always add MI sources .PATH: ${.CURDIR}/../../common @@ -29,7 +20,8 @@ LIBFICL= ${.CURDIR}/../../ficl/libficl.a CFLAGS+= -I${.CURDIR}/../../common CFLAGS+= -I${.CURDIR}/../../.. -I. -CLEANFILES+= vers.c vers.o ${BASE}.list ${BASE}.bin ${BASE}.sym ${BASE}.help +CLEANFILES+= vers.c vers.o ${BASE}.list setdef0.o setdef1.o setdefs.h \ + gensetdefs.o gensetdefs ${BASE}.bin CFLAGS+= -Wall LDFLAGS= -nostdlib -static -Ttext 0x1000 @@ -57,9 +49,6 @@ CFLAGS+= -I${.CURDIR}/../btx/lib # BTX is expecting ELF components CFLAGS+= -elf -# New linker set code -CFLAGS+= -DNEW_LINKER_SET - # Debug me! #CFLAGS+= -g #LDFLAGS+= -g @@ -68,47 +57,34 @@ vers.o: sh ${.CURDIR}/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} ${CC} -c vers.c -${BASE}: ${BASE}.bin ${BTXLDR} ${BTXKERN} ${BTXCRT} ${BASE}.help +${BASE}: ${BASE}.bin ${BTXLDR} ${BTXKERN} btxld -v -f aout -e 0x100000 -o ${.TARGET} -l ${BTXLDR} -b ${BTXKERN} \ ${BASE}.bin -# /usr/bin/kzip ${.TARGET} -# mv ${.TARGET}.kz ${.TARGET} - -${BASE}.bin: ${BASE}.sym - cp ${.ALLSRC} ${.TARGET} - strip ${.TARGET} - -${BASE}.help: help.common help.i386 - cat ${.ALLSRC} | awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET} - -beforeinstall: -.if exists(${DESTDIR}/boot/loader) - mv ${DESTDIR}/boot/loader ${DESTDIR}/boot/loader.old -.endif -.if exists(${.OBJDIR}/loader.help) - ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ - ${.OBJDIR}/${BASE}.help ${DESTDIR}/boot -.else - ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ - ${.CURDIR}/${BASE}.help ${DESTDIR}/boot -.endif -# Cannot use ${OBJS} above this line -.include <bsd.prog.mk> +${BASE}.bin: ${OBJS} ${LIBI386} vers.o setdef0.o setdef1.o + ${CC} ${LDFLAGS} -o ${.TARGET} ${BTXCRT} setdef0.o ${OBJS} vers.o setdef1.o \ + ${LIBSTAND} ${LIBI386} ${LIBSTAND} -${BASE}.sym: ${OBJS} ${LIBI386} ${LIBSTAND} ${LIBFICL} vers.o - ${CC} ${LDFLAGS} -o ${.TARGET} ${BTXCRT} ${OBJS} vers.o \ - ${LIBFICL} ${LIBSTAND} ${LIBI386} ${LIBSTAND} +setdef0.o: setdefs.h -# If it's not there, don't consider it a target -.if exists(${.CURDIR}/../../../i386/include) -beforedepend ${OBJS}: machine +setdef1.o: setdefs.h machine: ln -sf ${.CURDIR}/../../../i386/include machine -.endif - CLEANFILES+= machine +.include <bsd.prog.mk> +# Linker set gymnastics +setdefs.h: gensetdefs ${OBJS} + @echo Generating linker sets + @./gensetdefs ${OBJS} >setdefs.h + +gensetdefs: gensetdefs.o + ${CC} -static gensetdefs.o -o $@ + +gensetdefs.o: gensetdefs.c + ${CC} -c $< + +beforedepend ${OBJS}: machine diff --git a/sys/boot/i386/loader/conf.c b/sys/boot/i386/loader/conf.c index 9b4d554bc1a0..d39d67f33873 100644 --- a/sys/boot/i386/loader/conf.c +++ b/sys/boot/i386/loader/conf.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: conf.c,v 1.9 1998/10/22 20:23:58 msmith Exp $ + * $Id: conf.c,v 1.6 1998/09/30 19:48:42 peter Exp $ */ #include <stand.h> @@ -85,12 +85,10 @@ struct console *consoles[] = { }; extern struct pnphandler isapnphandler; -extern struct pnphandler biospnphandler; -extern struct pnphandler biospcihandler; +/* extern struct pnphandler pcipnphandler;*/ struct pnphandler *pnphandlers[] = { - &biospnphandler, /* should go first, as it may set isapnp_readport */ - &isapnphandler, - &biospcihandler, +/* &isapnphandler, */ +/* &pcipnphandler, */ NULL }; diff --git a/sys/boot/i386/loader/help.i386 b/sys/boot/i386/loader/help.i386 deleted file mode 100644 index 81288250ade0..000000000000 --- a/sys/boot/i386/loader/help.i386 +++ /dev/null @@ -1,34 +0,0 @@ -################################################################################ -# Treboot DReboot the system - - reboot - - Causes the system to immediately reboot. - -################################################################################ -# Theap DDisplay memory management statistics - - heap - - Requests debugging output from the heap manager. For debugging use - only. - -################################################################################ -# Tset Snum_ide_disks DSet the number of IDE disks - - set num_ide_disks=<value> - - When booting from a SCSI disk on a system with one or more IDE disks, - and where the IDE disks are the default boot device, it is necessary - to tell the kernel how many IDE disks there are in order to have it - correctly locate the SCSI disk you are booting from. - -################################################################################ -# Tset Sboot_userconfig DStart Userconfig - - set boot_userconfig - - Requests that the kernel's interactive device configuration program - be run when the kernel is booted. - -################################################################################ diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c index dfd1bfffbb98..b9e93f49b357 100644 --- a/sys/boot/i386/loader/main.c +++ b/sys/boot/i386/loader/main.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: main.c,v 1.13 1998/10/22 20:23:58 msmith Exp $ + * $Id: main.c,v 1.10 1998/10/03 18:27:50 rnordier Exp $ */ /* @@ -58,8 +58,6 @@ static struct bootinfo *initial_bootinfo; struct arch_switch archsw; /* MI/MD interface boundary */ static void extract_currdev(void); -static int isa_inb(int port); -static void isa_outb(int port, int value); /* from vers.c */ extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; @@ -98,11 +96,6 @@ main(void) cons_probe(); /* - * Initialise the block cache - */ - bcache_init(32, 512); /* 16k cache XXX tune this */ - - /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) @@ -112,6 +105,10 @@ main(void) printf("\n"); printf("%s, Revision %s %d/%dkB\n", bootprog_name, bootprog_rev, getbasemem(), getextmem()); printf("(%s, %s)\n", bootprog_maker, bootprog_date); +#if 0 + printf("recovered args howto = 0x%x bootdev = 0x%x bootinfo = %p\n", + initial_howto, initial_bootdev, initial_bootinfo); +#endif extract_currdev(); /* set $currdev and $loaddev */ setenv("LINES", "24", 1); /* optional */ @@ -121,8 +118,6 @@ main(void) archsw.arch_copyin = i386_copyin; archsw.arch_copyout = i386_copyout; archsw.arch_readin = i386_readin; - archsw.arch_isainb = isa_inb; - archsw.arch_isaoutb = isa_outb; interact(); /* doesn't return */ } @@ -200,34 +195,3 @@ command_heap(int argc, char *argv[]) printf("heap base at %p, top at %p\n", end, sbrk(0)); return(CMD_OK); } - -/* ISA bus access functions for PnP, derived from <machine/cpufunc.h> */ -static int -isa_inb(int port) -{ - u_char data; - - if (__builtin_constant_p(port) && - (((port) & 0xffff) < 0x100) && - ((port) < 0x10000)) { - __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); - } else { - __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); - } - return(data); -} - -static void -isa_outb(int port, int value) -{ - u_char al = value; - - if (__builtin_constant_p(port) && - (((port) & 0xffff) < 0x100) && - ((port) < 0x10000)) { - __asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port))); - } else { - __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); - } -} - diff --git a/sys/boot/i386/loader/newvers.sh b/sys/boot/i386/loader/newvers.sh index 476913be37a0..34b0e7e674d9 100755 --- a/sys/boot/i386/loader/newvers.sh +++ b/sys/boot/i386/loader/newvers.sh @@ -35,7 +35,6 @@ # # @(#)newvers.sh 8.1 (Berkeley) 4/20/94 -LC_TIME=C; export LC_TIME u=${USER-root} h=`hostname` t=`date` #r=`head -n 6 $1 | tail -n 1 | awk -F: ' { print $1 } '` r=`awk -F: ' /^[0-9]\.[0-9]+:/ { print $1; exit }' $1` diff --git a/sys/boot/i386/loader/setdef0.c b/sys/boot/i386/loader/setdef0.c new file mode 100644 index 000000000000..e2af74e84393 --- /dev/null +++ b/sys/boot/i386/loader/setdef0.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 1997 John D. Polstra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: setdef0.c,v 1.2 1997/05/21 23:21:30 jdp Exp $ + */ + +#ifdef __ELF__ + +#include <sys/param.h> +#include <sys/kernel.h> + +/* + * DEFINE_SET creates the section and label for a set, and emits the + * count word at the front of it. + */ +#define DEFINE_SET(set, count) \ + __asm__(".section .set." #set ",\"aw\""); \ + __asm__(".globl " #set); \ + __asm__(".type " #set ",@object"); \ + __asm__(".p2align 2"); \ + __asm__(#set ":"); \ + __asm__(".long " #count); \ + __asm__(".previous") + +#include "setdefs.h" /* Contains a `DEFINE_SET' for each set */ + +#endif /* __ELF__ */ diff --git a/sys/boot/i386/loader/setdef1.c b/sys/boot/i386/loader/setdef1.c new file mode 100644 index 000000000000..3f2011920526 --- /dev/null +++ b/sys/boot/i386/loader/setdef1.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 1997 John D. Polstra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: setdef1.c,v 1.2 1997/05/21 23:21:30 jdp Exp $ + */ + +#ifdef __ELF__ + +/* + * DEFINE_SET emits the NULL terminator for a set. + */ +#define DEFINE_SET(set, count) \ + __asm__(".section .set." #set ",\"aw\""); \ + __asm__(".long 0"); \ + __asm__(".previous") + +#include "setdefs.h" /* Contains a `DEFINE_SET' for each set */ + +#endif /* __ELF__ */ |