diff --git a/Makefile b/Makefile index 904bfb6..cf9979c 100644 --- a/Makefile +++ b/Makefile @@ -27,9 +27,9 @@ DUINOMITEEUART = sys/pic32/duinomite-e-uart/DUINOMITE-E-UART PINGUINO = sys/pic32/pinguino-micro/PINGUINO-MICRO DIP = sys/pic32/dip/DIP BAREMETAL = sys/pic32/baremetal/BAREMETAL -RETROONE = sys/pic32/retroone/RETROONE -FUBARINO = sys/pic32/fubarino/FUBARINO -FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC +RETROONE = sys/pic32/retroone/RETROONE +FUBARINO = sys/pic32/fubarino/FUBARINO +FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7 # Select target board @@ -60,59 +60,6 @@ TARGETDIR = $(shell dirname $(TARGET)) TARGETNAME = $(shell basename $(TARGET)) TOPSRC = $(shell pwd) CONFIG = $(TOPSRC)/tools/configsys/config -# -# Filesystem contents. -# -BIN_FILES := $(wildcard bin/*) -SBIN_FILES := $(wildcard sbin/*) -GAMES_FILES := $(shell find games -type f ! -path '*/.*') -LIBEXEC_FILES := $(wildcard libexec/*) -LIB_FILES := lib/crt0.o lib/retroImage $(wildcard lib/*.a) -ETC_FILES = etc/rc etc/rc.local etc/ttys etc/gettytab etc/group \ - etc/passwd etc/shadow etc/fstab etc/motd etc/shells \ - etc/termcap etc/MAKEDEV etc/phones etc/remote -INC_FILES = $(wildcard include/*.h) \ - $(wildcard include/sys/*.h) \ - $(wildcard include/machine/*.h) \ - $(wildcard include/smallc/*.h) \ - $(wildcard include/smallc/sys/*.h) \ - $(wildcard include/arpa/*.h) -SHARE_FILES = share/re.help share/example/Makefile \ - share/example/ashello.S share/example/chello.c \ - share/example/blkjack.bas share/example/hilow.bas \ - share/example/stars.bas share/example/prime.scm \ - share/example/fact.fth share/example/echo.S \ - share/example/stdarg.c share/example/skeleton.c \ - $(wildcard share/smallc/*) -MANFILES = share/man/ share/man/cat1/ share/man/cat2/ share/man/cat3/ \ - share/man/cat4/ share/man/cat5/ share/man/cat6/ share/man/cat7/ \ - share/man/cat8/ $(wildcard share/man/cat?/*) -ALLFILES = $(SBIN_FILES) $(ETC_FILES) $(BIN_FILES) $(LIB_FILES) $(LIBEXEC_FILES) \ - $(INC_FILES) $(SHARE_FILES) $(GAMES_FILES) \ - var/log/messages var/log/wtmp .profile -ALLDIRS = games/ sbin/ bin/ dev/ etc/ tmp/ lib/ libexec/ share/ include/ \ - var/ u/ share/example/ share/misc/ share/smallc/ \ - var/run/ var/log/ var/lock/ games/ games/lib/ include/sys/ \ - include/machine/ include/arpa/ include/smallc/ \ - include/smallc/sys/ share/misc/ share/smallc/ include/sys/ \ - games/lib/ games/lib/atc/ -BDEVS = dev/rd0!b0:0 dev/rd0a!b0:1 dev/rd0b!b0:2 dev/rd0c!b0:3 dev/rd0d!b0:4 -BDEVS += dev/rd1!b1:0 dev/rd1a!b1:1 dev/rd1b!b1:2 dev/rd1c!b1:3 dev/rd1d!b1:4 -BDEVS += dev/rd2!b2:0 dev/rd2a!b2:1 dev/rd2b!b2:2 dev/rd2c!b2:3 dev/rd2d!b2:4 -BDEVS += dev/rd3!b3:0 dev/rd3a!b3:1 dev/rd3b!b3:2 dev/rd3c!b3:3 dev/rd3d!b3:4 -BDEVS += dev/swap!b4:64 dev/swap0!b4:0 dev/swap1!b4:1 dev/swap2!b4:2 - -D_CONSOLE = dev/console!c0:0 -D_MEM = dev/mem!c1:0 dev/kmem!c1:1 dev/null!c1:2 dev/zero!c1:3 -D_TTY = dev/tty!c2:0 -D_FD = dev/stdin!c3:0 dev/stdout!c3:1 dev/stderr!c3:2 -D_TEMP = dev/temp0!c4:0 dev/temp1!c4:1 dev/temp2!c4:2 - -U_DIRS = $(addsuffix /,$(shell find u -type d ! -path '*/.svn*')) -U_FILES = $(shell find u -type f ! -path '*/.svn/*') -#U_ALL = $(patsubst u/%,%,$(U_DIRS) $(U_FILES)) - -CDEVS = $(D_CONSOLE) $(D_MEM) $(D_TTY) $(D_FD) $(D_TEMP) all: tools build kernel $(MAKE) fs @@ -136,24 +83,17 @@ lib: build: tools lib $(MAKE) -C src install -filesys.img: $(FSUTIL) $(ALLFILES) +filesys.img: $(FSUTIL) rootfs.manifest #$(ALLFILES) rm -f $@ - $(FSUTIL) -n$(FS_KBYTES) $@ - $(FSUTIL) -a $@ $(ALLDIRS) - $(FSUTIL) -a $@ $(CDEVS) - $(FSUTIL) -a $@ $(BDEVS) - $(FSUTIL) -a $@ $(ALLFILES) - $(FSUTIL) -a $@ $(MANFILES) + $(FSUTIL) -n$(FS_KBYTES) -Mrootfs.manifest $@ . swap.img: dd if=/dev/zero of=$@ bs=1k count=$(SWAP_KBYTES) -user.img: $(FSUTIL) +user.img: $(FSUTIL) userfs.manifest ifneq ($(U_KBYTES), 0) rm -f $@ - $(FSUTIL) -n$(U_KBYTES) $@ - (cd u; find . -type d -exec ../$(FSUTIL) -a ../$@ '{}/' \;) - (cd u; find . -type f -exec ../$(FSUTIL) -a ../$@ '{}' \+) + $(FSUTIL) -n$(U_KBYTES) -Muserfs.manifest $@ u endif sdcard.rd: filesys.img swap.img user.img @@ -179,6 +119,7 @@ cleanall: clean rm -f games/lib/adventure.dat rm -f games/lib/cfscores rm -f share/re.help + rm -f share/emg.keys rm -f share/misc/more.help rm -f etc/termcap etc/remote etc/phones rm -rf share/unixbench @@ -187,20 +128,20 @@ cleanall: clean rm -f var/log/aculog rm -rf var/lock -installfs: filesys.img +installfs: filesys.img ifdef SDCARD - sudo dd bs=32k if=sdcard.rd of=$(SDCARD) + sudo dd bs=32k if=sdcard.rd of=$(SDCARD) else - @echo "Error: No SDCARD defined." + @echo "Error: No SDCARD defined." endif # TODO: make it relative to Target installflash: - sudo pic32prog sys/pic32/fubarino/unix.hex + sudo pic32prog sys/pic32/fubarino/unix.hex # TODO: make it relative to Target installboot: - sudo pic32prog sys/pic32/fubarino/bootloader.hex + sudo pic32prog sys/pic32/fubarino/bootloader.hex -.profile: etc/root/dot.profile +.profile: etc/root/dot.profile cp etc/root/dot.profile .profile diff --git a/lib/Makefile b/lib/Makefile index e821099..49e6364 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -24,8 +24,9 @@ AOUT_OBJS = aout.o mips-dis.o RANLIB_OBJS = ranlib.o archive.o HEADERS = a.out.h ar.h nlist.h ranlib.h -vpath %.c $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as $(TOPSRC)/src/cmd/ld \ - $(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib $(TOPSRC)/src/cmd +vpath %.c $(TOPSRC)/src/cmd/aout $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as \ + $(TOPSRC)/src/cmd/ld $(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib \ + $(TOPSRC)/src/cmd all install depend: $(HEADERS) $(SUBDIR) $(PROG) -for i in $(SUBDIR); do $(MAKE) -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) $@; done diff --git a/rootfs.manifest b/rootfs.manifest new file mode 100644 index 0000000..47cc8d6 --- /dev/null +++ b/rootfs.manifest @@ -0,0 +1,771 @@ +# +# Manifest file for RetroBSD root filesystem. +# +default +owner 0 +group 0 +dirmode 0775 +filemode 0664 + +# +# Directories. +# +dir /bin +dir /dev +dir /etc +dir /lib +dir /libexec +dir /sbin +dir /tmp +dir /u + +# +# Character devices. +# +cdev /dev/console +major 0 +minor 0 +cdev /dev/mem +major 1 +minor 0 +cdev /dev/kmem +major 1 +minor 1 +cdev /dev/null +major 1 +minor 2 +mode 666 +cdev /dev/zero +major 1 +minor 3 +mode 666 +cdev /dev/tty +major 2 +minor 0 +mode 666 +cdev /dev/stdin +major 3 +minor 0 +cdev /dev/stdout +major 3 +minor 1 +cdev /dev/stderr +major 3 +minor 2 +cdev /dev/temp0 +major 4 +minor 0 +cdev /dev/temp1 +major 4 +minor 1 +cdev /dev/temp2 +major 4 +minor 2 + +# +# Block devices. +# +bdev /dev/rd0 +major 0 +minor 0 +bdev /dev/rd0a +major 0 +minor 1 +bdev /dev/rd0b +major 0 +minor 2 +bdev /dev/rd0c +major 0 +minor 3 +bdev /dev/rd0d +major 0 +minor 4 +bdev /dev/rd1 +major 1 +minor 0 +bdev /dev/rd1a +major 1 +minor 1 +bdev /dev/rd1b +major 1 +minor 2 +bdev /dev/rd1c +major 1 +minor 3 +bdev /dev/rd1d +major 1 +minor 4 +bdev /dev/rd2 +major 2 +minor 0 +bdev /dev/rd2a +major 2 +minor 1 +bdev /dev/rd2b +major 2 +minor 2 +bdev /dev/rd2c +major 2 +minor 3 +bdev /dev/rd2d +major 2 +minor 4 +bdev /dev/rd3 +major 3 +minor 0 +bdev /dev/rd3a +major 3 +minor 1 +bdev /dev/rd3b +major 3 +minor 2 +bdev /dev/rd3c +major 3 +minor 3 +bdev /dev/rd3d +major 3 +minor 4 +bdev /dev/swap +major 4 +minor 64 +bdev /dev/swap0 +major 4 +minor 0 +bdev /dev/swap1 +major 4 +minor 1 +bdev /dev/swap2 +major 4 +minor 2 + +# +# Files: / +# +file /.profile + +# +# Files: /etc +# +file /etc/fstab +file /etc/gettytab +file /etc/group +file /etc/MAKEDEV +mode 0775 +file /etc/motd +file /etc/passwd +file /etc/phones +file /etc/rc +mode 0775 +file /etc/rc.local +mode 0775 +file /etc/remote +file /etc/shadow +file /etc/shells +file /etc/termcap +mode 0444 +file /etc/ttys + +# +# Files: /bin +# +default +filemode 0775 +file /bin/adb +file /bin/adc-demo +file /bin/aout +file /bin/apropos +file /bin/ar +file /bin/as +file /bin/awk +file /bin/basename +file /bin/basic +file /bin/bc +file /bin/cal +file /bin/cat +file /bin/cb +file /bin/cc +file /bin/chat-server +file /bin/chflags +file /bin/chgrp +file /bin/chmod +file /bin/chpass +mode 04755 +file /bin/cmp +file /bin/col +file /bin/comm +file /bin/compress +file /bin/cp +file /bin/cpp +file /bin/crontab +file /bin/date +file /bin/dc +file /bin/dd +file /bin/df +mode 02755 +file /bin/diff +file /bin/du +file /bin/echo +file /bin/ed +file /bin/egrep +file /bin/emg +file /bin/env +file /bin/expr +file /bin/false +file /bin/fgrep +file /bin/file +file /bin/find +file /bin/forth +file /bin/fstat +mode 02755 +file /bin/glcdtest +file /bin/globdump +file /bin/globread +file /bin/globwrite +file /bin/grep +file /bin/groups +file /bin/head +file /bin/hostid +file /bin/hostname +file /bin/id +file /bin/iostat +mode 02755 +file /bin/join +file /bin/kill +file /bin/la +file /bin/last +file /bin/lcc +file /bin/lcpp +file /bin/ld +file /bin/ln +file /bin/login +mode 04755 +file /bin/lol +file /bin/ls +file /bin/mail +mode 04755 +file /bin/make +file /bin/man +file /bin/med +file /bin/mesg +file /bin/mkdir +file /bin/more +file /bin/msec +file /bin/mv +file /bin/nice +file /bin/nm +file /bin/nohup +file /bin/ntpdate +file /bin/od +file /bin/pagesize +file /bin/passwd +mode 04755 +file /bin/picoc +file /bin/portio +file /bin/pr +file /bin/printenv +file /bin/printf +file /bin/ps +mode 02755 +file /bin/pwd +file /bin/pwm +file /bin/ranlib +file /bin/re +file /bin/renice +file /bin/renumber +file /bin/retroforth +file /bin/rev +file /bin/rm +file /bin/rmail +file /bin/rmdir +file /bin/rz +file /bin/scc +file /bin/scm +file /bin/sed +file /bin/setty +file /bin/sh +file /bin/size +file /bin/sl +file /bin/sleep +file /bin/smux +file /bin/sort +file /bin/split +file /bin/strip +file /bin/stty +file /bin/su +mode 04755 +file /bin/sum +file /bin/sync +file /bin/sysctl +file /bin/sz +file /bin/tail +file /bin/tar +file /bin/tee +file /bin/telnet +file /bin/test +file /bin/time +file /bin/tip +file /bin/touch +file /bin/tr +file /bin/true +file /bin/tsort +file /bin/tty +file /bin/uname +file /bin/uncompress +file /bin/uniq +file /bin/uucico +file /bin/uuclean +file /bin/uucp +file /bin/uudecode +file /bin/uuencode +file /bin/uulog +file /bin/uuname +file /bin/uupoll +file /bin/uuq +file /bin/uusend +file /bin/uusnap +file /bin/uux +file /bin/uuxqt +file /bin/vi +file /bin/vmstat +mode 02755 +file /bin/w +file /bin/wall +mode 02755 +file /bin/wc +file /bin/web-client +file /bin/web-server +file /bin/whereis +file /bin/who +file /bin/whoami +file /bin/write +mode 02755 +file /bin/xargs +file /bin/zcat + +link /bin/[ +target /bin/test + +link /bin/whatis +target /bin/apropos + +link /bin/chfn +target /bin/chpass +link /bin/chsh +target /bin/chpass + +link /bin/rb +target /bin/rz +link /bin/rx +target /bin/rz + +link /bin/sb +target /bin/sz +link /bin/sx +target /bin/sz + +# +# Files: /sbin +# +file /sbin/chown +file /sbin/chroot +mode 04755 +file /sbin/cron +file /sbin/devupdate +file /sbin/disktool +file /sbin/fdisk +file /sbin/fsck +file /sbin/init +mode 0700 +file /sbin/mkfs +file /sbin/mknod +file /sbin/mkpasswd +file /sbin/mount +file /sbin/pstat +mode 02755 +file /sbin/rdprof +file /sbin/reboot +file /sbin/shutdown +mode 04750 +file /sbin/talloc +file /sbin/umount +file /sbin/update +file /sbin/updatedb +file /sbin/vipw + +link /sbin/bootloader +target /sbin/reboot +link /sbin/fastboot +target /sbin/reboot +link /sbin/halt +target /sbin/reboot +link /sbin/poweroff +target /sbin/reboot + +# +# Files: /games +# +default +filemode 0775 +dir /games +file /games/adventure +file /games/arithmetic +file /games/backgammon +file /games/banner +file /games/battlestar +file /games/bcd +file /games/canfield +file /games/cfscores +file /games/factor +file /games/fish +file /games/morse +file /games/number +file /games/ppt +file /games/primes +file /games/rain +file /games/rogue +file /games/sail +file /games/teachgammon +file /games/trek +file /games/worm +file /games/worms +file /games/wump + +# +# Files: /games/lib +# +dir /games/lib +file /games/lib/adventure.dat +mode 0444 +file /games/lib/battle_strings +mode 0444 +file /games/lib/cfscores +mode 0666 + +# +# Files: /include +# +default +filemode 0664 +dir /include +dir /include/arpa +dir /include/machine +dir /include/smallc +dir /include/smallc/sys +dir /include/sys +file /include/alloca.h +file /include/a.out.h +file /include/ar.h +file /include/arpa/inet.h +file /include/assert.h +file /include/ctype.h +file /include/curses.h +file /include/dbm.h +file /include/fcntl.h +file /include/float.h +file /include/fstab.h +file /include/grp.h +file /include/kmem.h +file /include/lastlog.h +file /include/limits.h +file /include/machine/cpu.h +file /include/machine/elf_machdep.h +file /include/machine/float.h +file /include/machine/io.h +file /include/machine/limits.h +file /include/machine/machparam.h +file /include/machine/pic32mx.h +file /include/machine/rd_sdramp_config.h +file /include/machine/sdram.h +file /include/machine/ssd1926.h +file /include/machine/usb_ch9.h +file /include/machine/usb_device.h +file /include/machine/usb_function_cdc.h +file /include/machine/usb_function_hid.h +file /include/machine/usb_hal_pic32.h +file /include/math.h +file /include/mtab.h +file /include/ndbm.h +file /include/nlist.h +file /include/paths.h +file /include/pcc.h +file /include/psout.h +file /include/pwd.h +file /include/ranlib.h +file /include/regexp.h +file /include/setjmp.h +file /include/sgtty.h +file /include/smallc/curses.h +file /include/smallc/fcntl.h +file /include/smallc/signal.h +file /include/smallc/stdio.h +file /include/smallc/sys/gpio.h +file /include/smallc/sys/spi.h +file /include/smallc/wiznet.h +file /include/stab.h +file /include/stdarg.h +file /include/stddef.h +file /include/stdint.h +file /include/stdio.h +file /include/stdlib.h +file /include/string.h +file /include/strings.h +file /include/struct.h +file /include/sys/adc.h +file /include/sys/buf.h +file /include/syscall.h +file /include/sys/callout.h +file /include/sys/clist.h +file /include/sys/conf.h +file /include/sys/debug.h +file /include/sys/dir.h +file /include/sys/disk.h +file /include/sys/dkbad.h +file /include/sys/dk.h +file /include/sys/errno.h +file /include/sys/exec_aout.h +file /include/sys/exec_elf.h +file /include/sys/exec.h +file /include/sysexits.h +file /include/sys/fcntl.h +file /include/sys/file.h +file /include/sys/fs.h +file /include/sys/glcd.h +file /include/sys/glob.h +file /include/sys/gpio.h +file /include/sys/inode.h +file /include/sys/ioctl.h +file /include/sys/kernel.h +file /include/sys/map.h +file /include/sys/mount.h +file /include/sys/msgbuf.h +file /include/sys/mtio.h +file /include/sys/namei.h +file /include/sys/oc.h +file /include/sys/param.h +file /include/sys/picga.h +file /include/sys/proc.h +file /include/sys/ptrace.h +file /include/sys/pty.h +file /include/sys/rd_flash.h +file /include/sys/rdisk.h +file /include/sys/rd_mrams.h +file /include/sys/rd_sdramp.h +file /include/sys/rd_sramc.h +file /include/sys/reboot.h +file /include/sys/resource.h +file /include/sys/select.h +file /include/sys/signal.h +file /include/sys/signalvar.h +file /include/sys/spi_bus.h +file /include/sys/spi.h +file /include/sys/stat.h +file /include/sys/swap.h +file /include/sys/sysctl.h +file /include/sys/syslog.h +file /include/sys/systm.h +file /include/sys/time.h +file /include/sys/times.h +file /include/sys/trace.h +file /include/sys/ttychars.h +file /include/sys/ttydev.h +file /include/sys/tty.h +file /include/sys/types.h +file /include/sys/uart.h +file /include/sys/uio.h +file /include/sys/usb_uart.h +file /include/sys/user.h +file /include/sys/utsname.h +file /include/sys/vm.h +file /include/sys/vmmac.h +file /include/sys/vmmeter.h +file /include/sys/vmparam.h +file /include/sys/vmsystm.h +file /include/sys/wait.h +file /include/term.h +file /include/termios-todo.h +file /include/time.h +file /include/ttyent.h +file /include/tzfile.h +file /include/unistd.h +file /include/utmp.h +file /include/vmf.h + +symlink /include/errno.h +target sys/errno.h + +symlink /include/signal.h +target sys/signal.h + +symlink /include/syslog.h +target sys/syslog.h + +# +# Files: /lib +# +file /lib/crt0.o +file /lib/libc.a +file /lib/libcurses.a +file /lib/libtermlib.a +file /lib/libwiznet.a +file /lib/retroImage + +# +# Files: /libexec +# +default +filemode 0775 +file /libexec/bigram +file /libexec/code +file /libexec/diffh +file /libexec/getty +file /libexec/smallc +file /libexec/smlrc + +# +# Files: /share +# +default +filemode 0444 +dir /share +dir /share/misc +file /share/emg.keys +file /share/re.help + +# +# Files: /share/example +# +default +filemode 0664 +dir /share/example +file /share/example/ashello.S +file /share/example/blkjack.bas +file /share/example/chello.c +file /share/example/echo.S +file /share/example/fact.fth +file /share/example/hilow.bas +file /share/example/Makefile +file /share/example/prime.scm +file /share/example/skeleton.c +file /share/example/stars.bas +file /share/example/stdarg.c + +# +# Files: /share/smallc +# +dir /share/smallc +file /share/smallc/adc.c +file /share/smallc/gpio.c +file /share/smallc/hello.c +file /share/smallc/Makefile +file /share/smallc/primelist.c +file /share/smallc/primesum.c +file /share/smallc/q8.c +file /share/smallc/rain.c +file /share/smallc/test1.c +file /share/smallc/test2.c +file /share/smallc/test3.c +file /share/smallc/webserver.c + +# +# Files: /var +# +dir /var +dir /var/lock +dir /var/log +dir /var/run +file /var/log/messages +file /var/log/wtmp + +# +# Files: /share/man +# +dir /share/man +dir /share/man/cat1 +dir /share/man/cat2 +dir /share/man/cat3 +dir /share/man/cat4 +dir /share/man/cat5 +dir /share/man/cat6 +dir /share/man/cat7 +dir /share/man/cat8 +file /share/man/cat1/ar.0 +file /share/man/cat1/chflags.0 +file /share/man/cat1/chpass.0 +file /share/man/cat1/cpp.0 +file /share/man/cat1/crontab.0 +file /share/man/cat1/emg.0 +file /share/man/cat1/groups.0 +file /share/man/cat1/hostname.0 +file /share/man/cat1/id.0 +file /share/man/cat1/la.0 +file /share/man/cat1/lcc.0 +file /share/man/cat1/ld.0 +file /share/man/cat1/passwd.0 +file /share/man/cat1/printf.0 +file /share/man/cat1/ranlib.0 +file /share/man/cat1/rz.0 +file /share/man/cat1/stty.0 +file /share/man/cat1/sz.0 +file /share/man/cat1/test.0 +file /share/man/cat1/uname.0 +file /share/man/cat1/whoami.0 +file /share/man/cat1/xargs.0 +file /share/man/cat3/vmf.0 +file /share/man/cat5/ar.0 +file /share/man/cat5/crontab.0 +file /share/man/cat5/ranlib.0 +file /share/man/cat6/adventure.0 +file /share/man/cat6/arithmetic.0 +file /share/man/cat6/backgammon.0 +file /share/man/cat6/banner.0 +file /share/man/cat6/battlestar.0 +file /share/man/cat6/bcd.0 +file /share/man/cat6/canfield.0 +file /share/man/cat6/fish.0 +file /share/man/cat6/number.0 +file /share/man/cat6/rain.0 +file /share/man/cat6/rogue.0 +file /share/man/cat6/sail.0 +file /share/man/cat6/trek.0 +file /share/man/cat6/worm.0 +file /share/man/cat6/worms.0 +file /share/man/cat6/wump.0 +file /share/man/cat8/chown.0 +file /share/man/cat8/chroot.0 +file /share/man/cat8/cron.0 +file /share/man/cat8/fdisk.0 +file /share/man/cat8/fstat.0 +file /share/man/cat8/init.0 +file /share/man/cat8/mkfs.0 +file /share/man/cat8/mknod.0 +file /share/man/cat8/mkpasswd.0 +file /share/man/cat8/mount.0 +file /share/man/cat8/pstat.0 +file /share/man/cat8/reboot.0 +file /share/man/cat8/renice.0 +file /share/man/cat8/shutdown.0 +file /share/man/cat8/sysctl.0 +file /share/man/cat8/talloc.0 +file /share/man/cat8/umount.0 +file /share/man/cat8/update.0 +file /share/man/cat8/vipw.0 + +link /share/man/cat1/rb.0 +target /share/man/cat1/rz.0 +link /share/man/cat1/rx.0 +target /share/man/cat1/rz.0 + +link /share/man/cat1/sb.0 +target /share/man/cat1/sz.0 +link /share/man/cat1/sx.0 +target /share/man/cat1/sz.0 + +link /share/man/cat8/fastboot.0 +target /share/man/cat8/reboot.0 +link /share/man/cat8/halt.0 +target /share/man/cat8/reboot.0 + +link /share/man/cat1/chfn.0 +target /share/man/cat1/chpass.0 +link /share/man/cat1/chsh.0 +target /share/man/cat1/chpass.0 diff --git a/share/.gitignore b/share/.gitignore index 0d1783a..6847704 100644 --- a/share/.gitignore +++ b/share/.gitignore @@ -1,3 +1,4 @@ re.help misc unixbench +emg.keys diff --git a/src/cmd/Makefile b/src/cmd/Makefile index f3fdf44..5d1484f 100644 --- a/src/cmd/Makefile +++ b/src/cmd/Makefile @@ -10,9 +10,9 @@ CFLAGS += -Werror # Programs that live in subdirectories, and have makefiles of their own. # /bin -SUBDIR = adb adc-demo ar as awk basic cc chflags chpass \ - cpp dc diff env fdisk find forth fstat glcdtest hostname \ - id la lcc lcpp ld ls login make man med \ +SUBDIR = adb adc-demo aout ar as awk basic cc chflags chpass \ + cpp dc diff emg env fdisk find forth fstat glcdtest \ + hostname id la lcc lcpp ld ls login make man med \ more nm passwd picoc portio printf pwm \ rdprof ranlib re renice retroforth scm setty sl \ sed sh smallc smlrc stty sysctl test uname wiznet xargs \ diff --git a/src/cmd/aout/.gitignore b/src/cmd/aout/.gitignore new file mode 100644 index 0000000..347b11f --- /dev/null +++ b/src/cmd/aout/.gitignore @@ -0,0 +1 @@ +aout diff --git a/src/cmd/aout/Makefile b/src/cmd/aout/Makefile new file mode 100644 index 0000000..7ca33a2 --- /dev/null +++ b/src/cmd/aout/Makefile @@ -0,0 +1,25 @@ +# +# aout - Display information from a.out files +# +TOPSRC = $(shell cd ../../..; pwd) +include $(TOPSRC)/target.mk +#include $(TOPSRC)/cross.mk + +CFLAGS += -Werror -Wall -Os +LDFLAGS += + +AOUTOBJS = aout.o mips-dis.o + +all: aout + +aout: $(AOUTOBJS) + ${CC} ${LDFLAGS} -o aout.elf $(AOUTOBJS) ${LIBS} + ${OBJDUMP} -S aout.elf > aout.dis + ${SIZE} aout.elf + ${ELF2AOUT} aout.elf $@ && rm aout.elf + +clean: + rm -f *.o *.0 *.elf aout tags *~ *.dis + +install: all + install aout $(DESTDIR)/bin/ diff --git a/src/cmd/as/aout.c b/src/cmd/aout/aout.c similarity index 100% rename from src/cmd/as/aout.c rename to src/cmd/aout/aout.c diff --git a/src/cmd/as/mips-dis.c b/src/cmd/aout/mips-dis.c similarity index 100% rename from src/cmd/as/mips-dis.c rename to src/cmd/aout/mips-dis.c diff --git a/src/cmd/as/mips-opc.c b/src/cmd/aout/mips-opc.c similarity index 100% rename from src/cmd/as/mips-opc.c rename to src/cmd/aout/mips-opc.c diff --git a/src/cmd/as/mips-opcode.h b/src/cmd/aout/mips-opcode.h similarity index 100% rename from src/cmd/as/mips-opcode.h rename to src/cmd/aout/mips-opcode.h diff --git a/src/cmd/as/mips16-opc.c b/src/cmd/aout/mips16-opc.c similarity index 100% rename from src/cmd/as/mips16-opc.c rename to src/cmd/aout/mips16-opc.c diff --git a/src/cmd/as/Makefile b/src/cmd/as/Makefile index 78d7e12..06a3019 100644 --- a/src/cmd/as/Makefile +++ b/src/cmd/as/Makefile @@ -1,6 +1,5 @@ # # as - Assembler -# aout - Display information from a.out files # TOPSRC = $(shell cd ../../..; pwd) include $(TOPSRC)/target.mk @@ -9,9 +8,7 @@ include $(TOPSRC)/target.mk CFLAGS += -Werror -Wall -Os LDFLAGS += -AOUTOBJS = aout.o mips-dis.o - -all: as aout +all: as as: as.o ${CC} ${LDFLAGS} -o as.elf as.o ${LIBS} @@ -19,26 +16,8 @@ as: as.o ${SIZE} as.elf ${ELF2AOUT} as.elf $@ && rm as.elf -aout: $(AOUTOBJS) - ${CC} ${LDFLAGS} -o aout.elf $(AOUTOBJS) ${LIBS} - ${OBJDUMP} -S aout.elf > aout.dis - ${SIZE} aout.elf - ${ELF2AOUT} aout.elf $@ && rm aout.elf - clean: - rm -f *.o *.0 *.elf as aout tags *~ *.dis tests/*.dis tests/*.gcc-dis tests/*.o - -test: - /usr/local/pic32-tools/bin/pic32-as -al example.s + rm -f *.o *.0 *.elf as tags *~ *.dis tests/*.dis tests/*.gcc-dis tests/*.o install: all install as $(DESTDIR)/bin/ - install aout $(DESTDIR)/bin/ - -test.dis-gcc: test.s - $(AS) $< -o test.o - ${OBJDUMP} -D test.o > $@ - -test.dis: test.s as aout - ./as $< -o test.o - ./aout test.o > $@ diff --git a/src/cmd/cpp/Makefile b/src/cmd/cpp/Makefile index 5467708..6091894 100644 --- a/src/cmd/cpp/Makefile +++ b/src/cmd/cpp/Makefile @@ -3,14 +3,15 @@ include $(TOPSRC)/target.mk #include $(TOPSRC)/cross.mk #CFLAGS = -DCROSS -OBJS = cpp.o cpy.o token.o +OBJS = cpp.o cpy.o token.o compat.o doprnt.o MAN = cpp.0 MANSRC = cpp.1 LDFLAGS += -g CFLAGS += -Werror -Wall -Os -CFLAGS += -DCPP_DEBUG -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC +#CFLAGS += -DCPP_DEBUG -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC +CFLAGS += -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC all: cpp $(MAN) @@ -30,7 +31,7 @@ install: all install cpp $(DESTDIR)/bin/ cp cpp.0 $(DESTDIR)/share/man/cat1/ -cpp.o: cpp.c y.tab.h +cpp.o: cpp.c cpp.h y.tab.h config.h .l.o: $(LEX) $(LFLAGS) $< @@ -61,3 +62,9 @@ test: cmp tests/run9 tests/res9 ./cpp < tests/test10 > tests/run10 cmp tests/run10 tests/res10 + ./cpp < tests/test11 > tests/run11 + cmp tests/run11 tests/res11 + ./cpp < tests/test12 > tests/run12 + cmp tests/run12 tests/res12 + ./cpp < tests/test13 > tests/run13 + cmp tests/run13 tests/res13 diff --git a/src/cmd/cpp/compat.c b/src/cmd/cpp/compat.c new file mode 100644 index 0000000..e01786d --- /dev/null +++ b/src/cmd/cpp/compat.c @@ -0,0 +1,91 @@ +/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ +/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ +/* + * Copyright (c) 1998, 2003-2005, 2010-2011, 2013 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" +#include + +#ifndef HAVE_STRLCAT +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return dlen + strlen(s); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return dlen + (s - src); /* count does not include NUL */ +} +#endif /* HAVE_STRLCAT */ + +#ifndef HAVE_STRLCPY +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return s - src - 1; /* count does not include NUL */ +} +#endif /* HAVE_STRLCPY */ diff --git a/src/cmd/cpp/compat.h b/src/cmd/cpp/compat.h new file mode 100644 index 0000000..6d9e654 --- /dev/null +++ b/src/cmd/cpp/compat.h @@ -0,0 +1,14 @@ +#ifndef COMPAT_H__ +#define COMPAT_H__ + +#include + +#ifndef HAVE_STRLCPY +size_t strlcpy(char* dst, const char* src, size_t size); +#endif + +#ifndef HAVE_STRLCAT +size_t strlcat(char* dst, const char* src, size_t size); +#endif + +#endif // COMPAT_H__ diff --git a/src/cmd/cpp/config.h b/src/cmd/cpp/config.h new file mode 100644 index 0000000..b5d0468 --- /dev/null +++ b/src/cmd/cpp/config.h @@ -0,0 +1,11 @@ +#ifndef CONFIG_H__ +#define CONFIG_H__ + +#define VERSSTR "cpp for RetroBSD" + +#define HAVE_UNISTD_H 1 +#define HAVE_SYS_WAIT_H 1 +//#define HAVE_STRLCPY 1 +//#define HAVE_STRLCAT 1 + +#endif // CONFIG_H__ diff --git a/src/cmd/cpp/cpp.c b/src/cmd/cpp/cpp.c index 94ca6f7..7a14424 100644 --- a/src/cmd/cpp/cpp.c +++ b/src/cmd/cpp/cpp.c @@ -1,8 +1,6 @@ +/* $Id: cpp.c,v 1.124.2.2 2011/03/27 13:17:19 ragge Exp $ */ + /* - * The C preprocessor. - * This code originates from the V6 preprocessor with some additions - * from V7 cpp, and at last ansi/c99 support. - * * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. * @@ -26,32 +24,46 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef CROSS -# include -# include -# include -#else -# include -# include -# include + +/* + * The C preprocessor. + * This code originates from the V6 preprocessor with some additions + * from V7 cpp, and at last ansi/c99 support. + */ + +#include "config.h" + +#ifdef HAVE_SYS_WAIT_H +#include #endif +#include #include +#ifdef HAVE_UNISTD_H #include +#endif +#include #include +#include +#include +#include +#include +#include "compat.h" #include "cpp.h" #include "y.tab.h" -#define MAXARG 20 /* # of args to a macro, limited by char value */ -#define SBSIZE (12*1024) +struct includ *ifiles; +int slow; /* scan slowly for new tokens */ -static uchar sbf[SBSIZE]; +#define SBSIZE (12*1024)//1000000 + +static usch sbf[SBSIZE]; /* C command */ int tflag; /* traditional cpp syntax */ -#ifdef CPP_DEBUG int dflag; /* debug printouts */ +#ifdef CPP_DEBUG #define DPRINT(x) if (dflag) printf x #define DDPRINT(x) if (dflag > 1) printf x #else @@ -59,26 +71,18 @@ int dflag; /* debug printouts */ #define DDPRINT(x) #endif -#define GCC_VARI - int ofd; -uchar outbuf[CPPBUF]; +usch outbuf[CPPBUF]; int obufp, istty; int Cflag, Mflag, dMflag, Pflag; -uchar *Mfile; +usch *Mfile; struct initar *initar; -int readmac; - -/* avoid recursion */ -struct recur { - struct recur *next; - struct symtab *sp; -}; +int readmac, lastoch; /* include dirs */ struct incs { struct incs *next; - uchar *dir; + usch *dir; dev_t dev; ino_t ino; } *incdir[2]; @@ -87,11 +91,12 @@ struct incs { static struct symtab *filloc; static struct symtab *linloc; +static struct symtab *pragloc; int trulvl; int flslvl; int elflvl; int elslvl; -uchar *stringbuf = sbf; +usch *stringbuf = sbf; /* * Macro replacement list syntax: @@ -100,7 +105,7 @@ uchar *stringbuf = sbf; * character WARN followed by the argument number. * - The value element points to the end of the string, to simplify * pushback onto the input queue. - * + * * The first character (from the end) in the replacement list is * the number of arguments: * VARG - ends with ellipsis, next char is argcount without ellips. @@ -111,74 +116,31 @@ uchar *stringbuf = sbf; * WARN is used: * - in stored replacement lists to tell that an argument comes * - When expanding replacement lists to tell that the list ended. + * + * To ensure that an already expanded identifier won't get expanded + * again a EBLOCK char + its number is stored directly before any + * expanded identifier. */ -#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */ -#define VARG 0xfe /* has varargs */ -#define OBJCT 0xff -#define WARN 1 /* SOH, not legal char */ -#define CONC 2 /* STX, not legal char */ -#define SNUFF 3 /* ETX, not legal char */ -#define NOEXP 4 /* EOT, not legal char */ -#define EXPAND 5 /* ENQ, not legal char */ - /* args for lookup() */ #define FIND 0 #define ENTER 1 -static void expdef(const uchar *proto, struct recur *, int gotwarn); +static int readargs(struct symtab *sp, const usch **args); +void prline(const usch *s); +static void prrep(const usch *s); +static void exparg(int); +static void subarg(struct symtab *sp, const usch **args, int); void define(void); -static int canexpand(struct recur *, struct symtab *np); void include(void); void include_next(void); void line(void); void flbuf(void); void usage(void); +usch *xstrdup(const usch *str); static void addidir(char *idir, struct incs **ww); - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -static size_t -my_strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} - -static uchar * -xstrdup(const char *str) -{ - size_t len = strlen(str)+1; - uchar *rv; - - rv = malloc(len); - if (! rv) - error("xstrdup: out of mem"); - my_strlcpy((char *)rv, str, len); - return rv; -} +void imp(const char *); +#define IMP(x) if (dflag>1) imp(x) int main(int argc, char **argv) @@ -186,7 +148,7 @@ main(int argc, char **argv) struct initar *it; struct symtab *nl; register int ch; - const uchar *fn1, *fn2; + const usch *fn1, *fn2; #ifdef TIMING struct timeval t1, t2; @@ -204,8 +166,7 @@ main(int argc, char **argv) case 'U': /* undef */ case 'D': /* define something */ /* XXX should not need malloc() here */ - it = malloc(sizeof(struct initar)); - if (it == NULL) + if ((it = malloc(sizeof(struct initar))) == NULL) error("couldn't apply -%c %s", ch, optarg); it->type = ch; it->str = optarg; @@ -254,48 +215,59 @@ main(int argc, char **argv) argc -= optind; argv += optind; - filloc = lookup((const uchar *)"__FILE__", ENTER); - linloc = lookup((const uchar *)"__LINE__", ENTER); - filloc->value = linloc->value = (const uchar *)""; /* Just something */ + filloc = lookup((const usch *)"__FILE__", ENTER); + linloc = lookup((const usch *)"__LINE__", ENTER); + filloc->value = linloc->value = stringbuf; + savch(OBJCT); + + /* create a complete macro for pragma */ + pragloc = lookup((const usch *)"_Pragma", ENTER); + savch(0); + savstr((const usch *)"_Pragma("); + savch(0); + savch(WARN); + savch(')'); + pragloc->value = stringbuf; + savch(1); if (tflag == 0) { time_t t = time(NULL); - uchar *n = (uchar *)ctime(&t); + usch *n = (usch *)ctime(&t); /* * Manually move in the predefined macros. */ - nl = lookup((const uchar *)"__TIME__", ENTER); + nl = lookup((const usch *)"__TIME__", ENTER); savch(0); savch('"'); n[19] = 0; savstr(&n[11]); savch('"'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__DATE__", ENTER); + nl = lookup((const usch *)"__DATE__", ENTER); savch(0); savch('"'); n[24] = n[11] = 0; savstr(&n[4]); savstr(&n[20]); savch('"'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__STDC__", ENTER); + nl = lookup((const usch *)"__STDC__", ENTER); savch(0); savch('1'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__STDC_VERSION__", ENTER); - savch(0); savstr((const uchar *)"199901L"); savch(OBJCT); + nl = lookup((const usch *)"__STDC_VERSION__", ENTER); + savch(0); savstr((const usch *)"199901L"); savch(OBJCT); nl->value = stringbuf-1; } if (Mflag && !dMflag) { - uchar *c; + usch *c; if (argc < 1) error("-M and no infile"); - if ((c = (uchar *)strrchr(argv[0], '/')) == NULL) - c = (uchar *)argv[0]; + if ((c = (usch *)strrchr(argv[0], '/')) == NULL) + c = (usch *)argv[0]; else c++; Mfile = stringbuf; savstr(c); savch(0); - if ((c = (uchar *)strrchr((char *)Mfile, '.')) == NULL) + if ((c = (usch *)strrchr((char *)Mfile, '.')) == NULL) error("-M and no extension: "); c[1] = 'o'; c[2] = 0; @@ -309,10 +281,10 @@ main(int argc, char **argv) istty = isatty(ofd); if (argc && strcmp(argv[0], "-")) { - fn1 = fn2 = (uchar *)argv[0]; + fn1 = fn2 = (usch *)argv[0]; } else { fn1 = NULL; - fn2 = (const uchar *)""; + fn2 = (const usch *)""; } if (pushfile(fn1, fn2, 0, NULL)) error("cannot open %s", argv[0]); @@ -350,126 +322,20 @@ addidir(char *idir, struct incs **ww) return; ww = &w->next; } - w = calloc(sizeof(struct incs), 1); - if (w == NULL) + if ((w = calloc(sizeof(struct incs), 1)) == NULL) error("couldn't add path %s", idir); - w->dir = (uchar *)idir; + w->dir = (usch *)idir; w->dev = st.st_dev; w->ino = st.st_ino; *ww = w; } -uchar * -gotident(struct symtab *nl) -{ - struct symtab *thisnl; - uchar *osp, *ss2, *base; - int c; - - thisnl = NULL; - readmac++; - base = osp = stringbuf; - goto found; - - while ((c = sloscan()) != 0) { - switch (c) { - case IDENT: - if (flslvl) - break; - osp = stringbuf; - - DPRINT(("IDENT0: %s\n", yytext)); - nl = lookup((uchar *)yytext, FIND); - if (nl == 0 || thisnl == 0) - goto found; - if (thisnl == nl) { - nl = 0; - goto found; - } - ss2 = stringbuf; - if ((c = sloscan()) == WSPACE) { - savstr((uchar *)yytext); - c = sloscan(); - } - if (c != EXPAND) { - unpstr((const uchar *)yytext); - if (ss2 != stringbuf) - unpstr(ss2); - unpstr(nl->namep); - (void)sloscan(); /* get yytext correct */ - nl = 0; /* ignore */ - } else { - thisnl = NULL; - if (nl->value[0] == OBJCT) { - unpstr(nl->namep); - (void)sloscan(); /* get yytext correct */ - nl = 0; - } - } - stringbuf = ss2; - -found: if (nl == 0 || subst(nl, NULL) == 0) { - if (nl) - savstr(nl->namep); - else - savstr((uchar *)yytext); - } else if (osp != stringbuf) { - DPRINT(("IDENT1: unput osp %p stringbuf %p\n", - osp, stringbuf)); - ss2 = stringbuf; - cunput(EXPAND); - while (ss2 > osp) - cunput(*--ss2); - thisnl = nl; - stringbuf = osp; /* clean up heap */ - } - break; - - case EXPAND: - DPRINT(("EXPAND!\n")); - thisnl = NULL; - break; - - case CMNT: - getcmnt(); - break; - - case '\n': - /* sloscan() will not eat */ - (void)cinput(); - savch(c); - break; - - case STRING: - case NUMBER: - case WSPACE: - savstr((uchar *)yytext); - break; - - default: - if (c < 256) - savch(c); - else - savstr((uchar *)yytext); - break; - } - if (thisnl == NULL) { - readmac--; - savch(0); - return base; - } - } - error("premature EOF"); - /* NOTREACHED */ - return NULL; /* XXX gcc */ -} - void line() { - static uchar *lbuf; + static usch *lbuf; static int llen; - uchar *p; + usch *p; int c; if ((c = yylex()) != NUMBER) @@ -482,7 +348,7 @@ line() if (c != STRING) goto bad; - p = (uchar *)yytext; + p = (usch *)yytext; if (*p == 'L') p++; c = strlen((char *)p); @@ -493,7 +359,7 @@ line() llen = c; } p[strlen((char *)p)-1] = 0; - if (my_strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE) + if (strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE) error("line exceeded buffer size"); ifiles->fname = lbuf; @@ -508,17 +374,19 @@ bad: error("bad line directive"); * Return 1 on success. */ static int -fsrch(const uchar *fn, int idx, struct incs *w) +fsrch(const usch *fn, int idx, struct incs *w) { - for (; idx <= SYSINC; idx++) { - if (idx == SYSINC) - w = incdir[SYSINC]; + int i; + + for (i = idx; i < 2; i++) { + if (i > idx) + w = incdir[i]; for (; w; w = w->next) { - uchar *nm = stringbuf; + usch *nm = stringbuf; savstr(w->dir); savch('/'); savstr(fn); savch(0); - if (pushfile(nm, fn, idx, w->next) == 0) + if (pushfile(nm, fn, i, w->next) == 0) return 1; stringbuf = nm; } @@ -535,9 +403,9 @@ void include() { struct symtab *nl; - uchar *osp; - uchar *fn, *safefn; - int c; + usch *osp; + usch *fn, *safefn; + int c/*, it*/; if (flslvl) return; @@ -547,9 +415,12 @@ include() ; if (c == IDENT) { /* sloscan() will not expand idents */ - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) + if ((nl = lookup((usch *)yytext, FIND)) == NULL) goto bad; - unpstr(gotident(nl)); + if (kfind(nl)) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = osp; c = yylex(); } @@ -561,25 +432,26 @@ include() while ((c = sloscan()) != '>' && c != '\n') { if (c == '\n') /* XXX check - cannot reach */ goto bad; - savstr((uchar *)yytext); + savstr((usch *)yytext); } savch('\0'); while ((c = sloscan()) == WSPACE) ; if (c != '\n') goto bad; + //it = SYSINC; safefn = fn; } else { - uchar *nm = stringbuf; + usch *nm = stringbuf; - yytext[strlen(yytext)-1] = 0; - fn = (uchar *)&yytext[1]; + yytext[strlen((char *)yytext)-1] = 0; + fn = (usch *)&yytext[1]; /* first try to open file relative to previous file */ /* but only if it is not an absolute path */ if (*fn != '/') { savstr(ifiles->orgfn); - stringbuf = (uchar *)strrchr((char *)nm, '/'); - if (stringbuf == NULL) + if ((stringbuf = + (usch *)strrchr((char *)nm, '/')) == NULL) stringbuf = nm; else stringbuf++; @@ -594,7 +466,7 @@ include() /* XXX may loose stringbuf space */ } - if (fsrch(safefn, INCINC, incdir[INCINC])) + if (fsrch(safefn, 0, incdir[0])) goto okret; error("cannot find '%s'", safefn); @@ -610,8 +482,8 @@ void include_next() { struct symtab *nl; - uchar *osp; - uchar *fn; + usch *osp; + usch *fn; int c; if (flslvl) @@ -621,9 +493,12 @@ include_next() ; if (c == IDENT) { /* sloscan() will not expand idents */ - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) + if ((nl = lookup((usch *)yytext, FIND)) == NULL) goto bad; - unpstr(gotident(nl)); + if (kfind(nl)) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = osp; c = yylex(); } @@ -632,13 +507,13 @@ include_next() fn = stringbuf; if (c == STRING) { - savstr((uchar *)&yytext[1]); + savstr((usch *)&yytext[1]); stringbuf[-1] = 0; } else { /* < > */ while ((c = sloscan()) != '>') { if (c == '\n') goto bad; - savstr((uchar *)yytext); + savstr((usch *)yytext); } savch('\0'); } @@ -672,14 +547,14 @@ getcmnt(void) { int c; - savstr((uchar *)yytext); + savstr((usch *)yytext); savch(cinput()); /* Lost * */ for (;;) { c = cinput(); if (c == '*') { c = cinput(); if (c == '/') { - savstr((const uchar *)"*/"); + savstr((const usch *)"*/"); return; } cunput(c); @@ -693,7 +568,7 @@ getcmnt(void) * Compare two replacement lists, taking in account comments etc. */ static int -cmprepl(const uchar *o, const uchar *n) +cmprepl(const usch *o, const usch *n) { for (; *o; o--, n--) { /* comment skip */ @@ -738,12 +613,12 @@ void define() { struct symtab *np; - uchar *args[MAXARG], *ubuf, *sbeg; + usch *args[MAXARGS+1], *ubuf, *sbeg; int c, i, redef; int mkstr = 0, narg = -1; int ellips = 0; -#ifdef GCC_VARI - uchar *gccvari = NULL; +#ifdef GCC_COMPAT + usch *gccvari = NULL; int wascon; #endif @@ -755,7 +630,7 @@ define() if (isdigit((int)yytext[0])) goto bad; - np = lookup((uchar *)yytext, ENTER); + np = lookup((usch *)yytext, ENTER); redef = np->value != NULL; readmac = 1; @@ -776,16 +651,18 @@ define() if (c == IDENT) { /* make sure there is no arg of same name */ for (i = 0; i < narg; i++) - if (!strcmp((char *) args[i], yytext)) + if (!strcmp((char *) args[i], (char *)yytext)) error("Duplicate macro " "parameter \"%s\"", yytext); + if (narg == MAXARGS) + error("Too many macro args"); args[narg++] = xstrdup(yytext); if ((c = definp()) == ',') { if ((c = definp()) == ')') goto bad; continue; } -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '.' && isell()) { if (definp() != ')') goto bad; @@ -813,7 +690,7 @@ define() if ((c = sloscan()) == '#') goto bad; savch('\0'); -#ifdef GCC_VARI +#ifdef GCC_COMPAT wascon = 0; #endif goto in2; @@ -822,7 +699,7 @@ define() /* parse replacement-list, substituting arguments */ savch('\0'); while (c != '\n') { -#ifdef GCC_VARI +#ifdef GCC_COMPAT wascon = 0; loop: #endif @@ -830,7 +707,7 @@ loop: case WSPACE: /* remove spaces if it surrounds a ## directive */ ubuf = stringbuf; - savstr((uchar *)yytext); + savstr((usch *)yytext); c = sloscan(); if (c == '#') { if ((c = sloscan()) != '#') @@ -839,7 +716,7 @@ loop: savch(CONC); if ((c = sloscan()) == WSPACE) c = sloscan(); -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '\n') break; wascon = 1; @@ -855,7 +732,7 @@ loop: savch(CONC); if ((c = sloscan()) == WSPACE) c = sloscan(); -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '\n') break; wascon = 1; @@ -863,7 +740,7 @@ loop: #else continue; #endif - } + } in2: if (narg < 0) { /* no meaning in object-type macro */ savch('#'); @@ -874,15 +751,20 @@ in2: if (narg < 0) { if (c == WSPACE) c = sloscan(); /* whitespace, ignore */ mkstr = 1; - if (c == IDENT && strcmp(yytext, "__VA_ARGS__") == 0) + if (c == IDENT && strcmp((char *)yytext, "__VA_ARGS__") == 0) continue; /* FALLTHROUGH */ case IDENT: - if (strcmp(yytext, "__VA_ARGS__") == 0) { + if (strcmp((char *)yytext, "__VA_ARGS__") == 0) { if (ellips == 0) error("unwanted %s", yytext); +#ifdef GCC_COMPAT + savch(wascon ? GCCARG : VARG); +#else savch(VARG); +#endif + savch(WARN); if (mkstr) savch(SNUFF), mkstr = 0; @@ -892,12 +774,12 @@ in2: if (narg < 0) { goto id; /* just add it if object */ /* check if its an argument */ for (i = 0; i < narg; i++) - if (strcmp(yytext, (char *)args[i]) == 0) + if (strcmp((char *)yytext, (char *)args[i]) == 0) break; if (i == narg) { -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (gccvari && - strcmp(yytext, (char *)gccvari) == 0) { + strcmp((char *)yytext, (char *)gccvari) == 0) { savch(wascon ? GCCARG : VARG); savch(WARN); if (mkstr) @@ -920,7 +802,7 @@ in2: if (narg < 0) { break; default: -id: savstr((uchar *)yytext); +id: savstr((usch *)yytext); break; } c = sloscan(); @@ -936,7 +818,7 @@ id: savstr((uchar *)yytext); else break; } -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (gccvari) { savch(narg); savch(VARG); @@ -947,17 +829,20 @@ id: savstr((uchar *)yytext); savch(VARG); } else savch(narg < 0 ? OBJCT : narg); - if (redef) { - if (cmprepl(np->value, stringbuf-1)) - error("%s redefined\nprevious define: %s:%d", + if (redef && ifiles->idx != SYSINC) { + if (cmprepl(np->value, stringbuf-1)) { + sbeg = stringbuf; + np->value = stringbuf-1; + warning("%s redefined\nprevious define: %s:%d", np->namep, np->file, np->line); + } stringbuf = sbeg; /* forget this space */ } else np->value = stringbuf-1; #ifdef CPP_DEBUG if (dflag) { - const uchar *w = np->value; + const usch *w = np->value; printf("!define: "); if (*w == OBJCT) @@ -983,44 +868,107 @@ bad: error("bad define"); } void -xwarning(uchar *s) +xwarning(usch *s) { - uchar *t; - uchar *sb = stringbuf; + usch *t; + usch *sb = stringbuf; + //int dummy; flbuf(); savch(0); if (ifiles != NULL) { t = sheap("%s:%d: warning: ", ifiles->fname, ifiles->lineno); - if (write (2, t, strlen((char *)t)) < 0) - /* ignore */; + write (2, t, strlen((char *)t)); } - if (write (2, s, strlen((char *)s)) < 0) - /* ignore */; - if (write (2, "\n", 1) < 0) - /* ignore */; + /*dummy =*/ write (2, s, strlen((char *)s)); + /*dummy =*/ write (2, "\n", 1); stringbuf = sb; } void -xerror(uchar *s) +xerror(usch *s) { - uchar *t; + usch *t; + //int dummy; flbuf(); savch(0); if (ifiles != NULL) { t = sheap("%s:%d: error: ", ifiles->fname, ifiles->lineno); - if (write (2, t, strlen((char *)t)) < 0) - /* ignore */; + /*dummy =*/ write (2, t, strlen((char *)t)); } - if (write (2, s, strlen((char *)s)) < 0) - /* ignore */; - if (write (2, "\n", 1) < 0) - /* ignore */; + /*dummy =*/ write (2, s, strlen((char *)s)); + /*dummy =*/ write (2, "\n", 1); exit(1); } +static void +sss(void) +{ + savch(EBLOCK); + savch(cinput()); + savch(cinput()); +} + +static int +addmac(struct symtab *sp) +{ + int c, i; + + /* Check if it exists; then save some space */ + /* May be more difficult to debug cpp */ + for (i = 1; i < norepptr; i++) + if (norep[i] == sp) + return i; + if (norepptr >= RECMAX) + error("too many macros"); + /* check norepptr */ + if ((norepptr & 255) == 0) + norepptr++; + if (((norepptr >> 8) & 255) == 0) + norepptr += 256; + c = norepptr; + norep[norepptr++] = sp; + return c; +} + +static void +doblk(void) +{ + int c; + + do { + donex(); + } while ((c = sloscan()) == EBLOCK); + if (c != IDENT) + error("EBLOCK sync error"); +} + +/* Block next nr in lex buffer to expand */ +int +donex(void) +{ + int n, i; + + if (bidx == RECMAX) + error("too deep macro recursion"); + n = cinput(); + n = MKB(n, cinput()); + for (i = 0; i < bidx; i++) + if (bptr[i] == n) + return n; /* already blocked */ + bptr[bidx++] = n; + /* XXX - check for sp buffer overflow */ + if (dflag>1) { + printf("donex %d (%d) blocking:\n", bidx, n); + printf("donex %s(%d) blocking:", norep[n]->namep, n); + for (i = bidx-1; i >= 0; i--) + printf(" '%s'", norep[bptr[i]]->namep); + printf("\n"); + } + return n; +} + /* * store a character into the "define" buffer. */ @@ -1028,240 +976,639 @@ void savch(int c) { if (stringbuf-sbf < SBSIZE) { - *stringbuf++ = (uchar)c; + *stringbuf++ = (usch)c; } else { stringbuf = sbf; /* need space to write error message */ error("Too much defining"); - } + } } /* - * substitute namep for sp->value. + * convert _Pragma to #pragma for output. + * Syntax is already correct. */ -int -subst(struct symtab *sp, struct recur *rp) +static void +pragoper(void) { - struct recur rp2; - register const uchar *vp, *cp; - register uchar *obp; - int c, nl; + usch *s; + int t; - DPRINT(("subst: %s\n", sp->namep)); - /* - * First check for special macros. - */ - if (sp == filloc) { - (void)sheap("\"%s\"", ifiles->fname); - return 1; - } else if (sp == linloc) { - (void)sheap("%d", ifiles->lineno); - return 1; + while ((t = sloscan()) != '(') + ; + + while ((t = sloscan()) == WSPACE) + ; + if (t != STRING) + error("pragma must have string argument"); + savstr((const usch *)"\n#pragma "); + s = (usch *)yytext; + if (*s == 'L') + s++; + for (; *s; s++) { + if (*s == '\"') + continue; + if (*s == '\\' && (s[1] == '\"' || s[1] == '\\')) + s++; + savch(*s); } - vp = sp->value; + sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname); + while ((t = sloscan()) == WSPACE) + ; + if (t != ')') + error("pragma syntax error"); +} - rp2.next = rp; - rp2.sp = sp; +/* + * Return true if it is OK to expand this symbol. + */ +static int +okexp(struct symtab *sp) +{ + int i; - if (*vp-- != OBJCT) { - int gotwarn = 0; - - /* should we be here at all? */ - /* check if identifier is followed by parentheses */ - - obp = stringbuf; - nl = 0; - do { - c = cinput(); - *stringbuf++ = (uchar)c; - if (c == WARN) { - gotwarn++; - if (rp == NULL) - break; - } - if (c == '\n') - nl++; - } while (c == ' ' || c == '\t' || c == '\n' || - c == '\r' || c == WARN); - - DPRINT(("c %d\n", c)); - if (c == '(' ) { - cunput(c); - stringbuf = obp; - ifiles->lineno += nl; - expdef(vp, &rp2, gotwarn); - return 1; - } else { - *stringbuf = 0; - unpstr(obp); - unpstr(sp->namep); - if ((c = sloscan()) != IDENT) - error("internal sync error"); - stringbuf = obp; + if (sp == NULL) + return 0; + for (i = 0; i < bidx; i++) + if (norep[bptr[i]] == sp) return 0; - } - } else { - cunput(WARN); - cp = vp; - while (*cp) { - if (*cp != CONC) - cunput(*cp); - cp--; - } - expmac(&rp2); - } return 1; } +/* + * Insert block(s) before each expanded name. + * Input is in lex buffer, output on lex buffer. + */ +static void +insblock(int bnr) +{ + usch *bp = stringbuf; + int c, i; + + IMP("IB"); + while ((c = sloscan()) != WARN) { + if (c == EBLOCK) { + sss(); + continue; + } + if (c == IDENT) { + savch(EBLOCK), savch(bnr & 255), savch(bnr >> 8); + for (i = 0; i < bidx; i++) + savch(EBLOCK), savch(bptr[i] & 255), + savch(bptr[i] >> 8); + } + savstr((const usch *)yytext); + if (c == '\n') + (void)cinput(); + } + savch(0); + cunput(WARN); + unpstr(bp); + stringbuf = bp; + IMP("IBRET"); +} + +/* Delete next WARN on the input stream */ +static void +delwarn(void) +{ + usch *bp = stringbuf; + int c; + + IMP("DELWARN"); + while ((c = sloscan()) != WARN) { + if (c == EBLOCK) { + sss(); + } else + savstr(yytext); + } + savch(0); + unpstr(bp); + stringbuf = bp; + IMP("DELWRET"); +} + +/* + * Handle defined macro keywords found on input stream. + * When finished print out the full expanded line. + * Everything on lex buffer except for the symtab. + */ +int +kfind(struct symtab *sp) +{ + struct symtab *nl; + const usch *argary[MAXARGS+1], *cbp; + usch *sbp; + int c, o, chkf; + + DPRINT(("%d:enter kfind(%s)\n",0,sp->namep)); + IMP("KFIND"); + if (*sp->value == OBJCT) { + if (sp == filloc) { + unpstr(sheap("\"%s\"", ifiles->fname)); + return 1; + } else if (sp == linloc) { + unpstr(sheap("%d", ifiles->lineno)); + return 1; + } + IMP("END1"); + cunput(WARN); + for (cbp = sp->value-1; *cbp; cbp--) + cunput(*cbp); + insblock(addmac(sp)); + IMP("ENDX"); + exparg(1); + +upp: sbp = stringbuf; + chkf = 1; + if (obufp != 0) + lastoch = outbuf[obufp-1]; + if (iswsnl(lastoch)) + chkf = 0; + while ((c = sloscan()) != WARN) { + switch (c) { + case STRING: + /* Remove embedded directives */ + for (cbp = (usch *)yytext; *cbp; cbp++) { + if (*cbp == EBLOCK) + cbp+=2; + else if (*cbp != CONC) + savch(*cbp); + } + break; + + case EBLOCK: + doblk(); + /* FALLTHROUGH */ + case IDENT: + /* + * Tricky: if this is the last identifier + * in the expanded list, and it is defined + * as a function-like macro, then push it + * back on the input stream and let fastscan + * handle it as a new macro. + * BUT: if this macro is blocked then this + * should not be done. + */ + nl = lookup((usch *)yytext, FIND); + o = okexp(nl); + bidx = 0; + /* Deal with pragmas here */ + if (nl == pragloc) { + pragoper(); + break; + } + if (nl == NULL || !o || *nl->value == OBJCT) { + /* Not fun-like macro */ + savstr(yytext); + break; + } + c = cinput(); + if (c == WARN) { + /* succeeded, push back */ + unpstr(yytext); + } else { + savstr(yytext); + } + cunput(c); + break; + + default: + if (chkf && c < 127) + putch(' '); + savstr(yytext); + break; + } + chkf = 0; + } + IMP("END2"); + norepptr = 1; + savch(0); + stringbuf = sbp; + return 1; + } + /* Is a function-like macro */ + + /* Search for '(' */ + sbp = stringbuf; + while (iswsnl(c = cinput())) + savch(c); + savch(0); + stringbuf = sbp; + if (c != '(') { + cunput(c); + unpstr(sbp); + return 0; /* Failed */ + } + + /* Found one, output \n to be in sync */ + for (; *sbp; sbp++) { + if (*sbp == '\n') + putch('\n'), ifiles->lineno++; + } + + /* fetch arguments */ + if (readargs(sp, argary)) + error("readargs"); + + c = addmac(sp); + sbp = stringbuf; + cunput(WARN); + + IMP("KEXP"); + subarg(sp, argary, 1); + IMP("KNEX"); + insblock(c); + IMP("KBLK"); + + stringbuf = sbp; + + exparg(1); + + IMP("END"); + + goto upp; + +} + +/* + * Replace and push-back on input stream the eventual replaced macro. + * The check for whether it can expand or not should already have been done. + * Blocks for this identifier will be added via insblock() after expansion. + */ +int +submac(struct symtab *sp, int lvl) +{ + const usch *argary[MAXARGS+1]; + const usch *cp; + usch *bp; + int ch; + + DPRINT(("%d:submac1: trying '%s'\n", lvl, sp->namep)); + if (*sp->value == OBJCT) { + if (sp == filloc) { + unpstr(sheap("\"%s\"", ifiles->fname)); + return 1; + } else if (sp == linloc) { + unpstr(sheap("%d", ifiles->lineno)); + return 1; + } + + DPRINT(("submac: exp object macro '%s'\n",sp->namep)); + /* expand object-type macros */ + ch = addmac(sp); + cunput(WARN); + + for (cp = sp->value-1; *cp; cp--) + cunput(*cp); + insblock(ch); + delwarn(); + return 1; + } + + /* + * Function-like macro; see if it is followed by a ( + * Be careful about the expand/noexpand balance. + * Store read data on heap meanwhile. + * For directive #define foo() kaka + * If input is foo() then + * output should be kaka. + */ + bp = stringbuf; + while (iswsnl(ch = cinput())) + savch(ch); + savch(0); + stringbuf = bp; + if (ch != '(') { + cunput(ch); + unpstr(bp); + return 0; /* Failed */ + } + + /* no \n should be here */ + + /* + * A function-like macro has been found. Read in the arguments, + * expand them and push-back everything for another scan. + */ + DPRINT(("%d:submac: continue macro '%s'\n", lvl, sp->namep)); + savch(0); + if (readargs(sp, argary)) { + /* Bailed out in the middle of arg list */ + unpstr(bp); + if (dflag>1)printf("%d:noreadargs\n", lvl); + stringbuf = bp; + return 0; + } + + /* when all args are read from input stream */ + ch = addmac(sp); + + DDPRINT(("%d:submac pre\n", lvl)); + cunput(WARN); + + subarg(sp, argary, lvl+1); + + DDPRINT(("%d:submac post\n", lvl)); + insblock(ch); + delwarn(); + + stringbuf = bp; /* Reset heap */ + DPRINT(("%d:Return submac\n", lvl)); + IMP("SM1"); + return 1; +} + +/* + * Read arguments and put in argument array. + * If WARN is encountered return 1, otherwise 0. + */ +int +readargs(struct symtab *sp, const usch **args) +{ + const usch *vp = sp->value; + int c, i, plev, narg, ellips = 0; + int warn; + + DPRINT(("readargs\n")); + + narg = *vp--; + if (narg == VARG) { + narg = *vp--; + ellips = 1; + } + + IMP("RDA1"); + /* + * read arguments and store them on heap. + */ + warn = 0; + c = '('; + for (i = 0; i < narg && c != ')'; i++) { + args[i] = stringbuf; + plev = 0; + while ((c = sloscan()) == WSPACE || c == '\n') + if (c == '\n') + putch(cinput()); + for (;;) { + while (c == EBLOCK) { + sss(); + c = sloscan(); + } + if (c == WARN) { + warn++; + goto oho; + } + if (plev == 0 && (c == ')' || c == ',')) + break; + if (c == '(') + plev++; + if (c == ')') + plev--; + savstr((usch *)yytext); +oho: while ((c = sloscan()) == '\n') { + putch(cinput()); + savch(' '); + } + while (c == CMNT) { + getcmnt(); + c = sloscan(); + } + if (c == 0) + error("eof in macro"); + } + while (args[i] < stringbuf && + iswsnl(stringbuf[-1]) && stringbuf[-3] != EBLOCK) + stringbuf--; + savch('\0'); + if (dflag) { + printf("readargs: save arg %d '", i); + prline(args[i]); + printf("'\n"); + } + } + + IMP("RDA2"); + /* Handle varargs readin */ + if (ellips) + args[i] = (const usch *)""; + if (ellips && c != ')') { + args[i] = stringbuf; + plev = 0; + while ((c = sloscan()) == WSPACE) + ; + for (;;) { + if (plev == 0 && c == ')') + break; + if (c == '(') + plev++; + if (c == ')') + plev--; + if (c == EBLOCK) { + sss(); + } else + savstr((usch *)yytext); + while ((c = sloscan()) == '\n') { + cinput(); + savch(' '); + } + } + while (args[i] < stringbuf && iswsnl(stringbuf[-1])) + stringbuf--; + savch('\0'); + + } + if (narg == 0 && ellips == 0) + while ((c = sloscan()) == WSPACE || c == '\n') + if (c == '\n') + cinput(); + + if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) + error("wrong arg count"); + while (warn) + cunput(WARN), warn--; + return 0; +} + +#if 0 /* * Maybe an indentifier (for macro expansion). */ static int -mayid(uchar *s) +mayid(usch *s) { for (; *s; s++) if (!isdigit(*s) && !isalpha(*s) && *s != '_') return 0; return 1; } +#endif /* - * do macro-expansion until WARN character read. - * read from lex buffer and store result on heap. - * will recurse into lookup() for recursive expansion. - * when returning all expansions on the token list is done. + * expand a function-like macro. + * vp points to end of replacement-list + * reads function arguments from sloscan() + * result is pushed-back for more scanning. */ void -expmac(struct recur *rp) +subarg(struct symtab *nl, const usch **args, int lvl) +{ + int narg, instr, snuff; + const usch *sp, *bp, *ap, *vp; + + DPRINT(("%d:subarg '%s'\n", lvl, nl->namep)); + vp = nl->value; + narg = *vp--; + if (narg == VARG) + narg = *vp--; + + sp = vp; + instr = snuff = 0; + if (dflag>1) { + printf("%d:subarg ARGlist for %s: '", lvl, nl->namep); + prrep(vp); + printf("'\n"); + } + + /* + * push-back replacement-list onto lex buffer while replacing + * arguments. Arguments are macro-expanded if required. + */ + while (*sp != 0) { + if (*sp == SNUFF) + cunput('\"'), snuff ^= 1; + else if (*sp == CONC) + ; + else if (*sp == WARN) { + + if (sp[-1] == VARG) { + bp = ap = args[narg]; + sp--; +#ifdef GCC_COMPAT + } else if (sp[-1] == GCCARG) { + ap = args[narg]; + if (ap[0] == 0) + ap = (const usch *)"0"; + bp = ap; + sp--; +#endif + } else + bp = ap = args[(int)*--sp]; + if (dflag>1){ + printf("%d:subarg GOTwarn; arglist '", lvl); + prline(bp); + printf("'\n"); + } + if (sp[2] != CONC && !snuff && sp[-1] != CONC) { + /* + * Expand an argument; 6.10.3.1: + * "A parameter in the replacement list, + * is replaced by the corresponding argument + * after all macros contained therein have + * been expanded.". + */ + cunput(WARN); + unpstr(bp); + exparg(lvl+1); + delwarn(); + } else { + while (*bp) + bp++; + while (bp > ap) { + bp--; + if (snuff && !instr && iswsnl(*bp)) { + while (iswsnl(*bp)) + bp--; + cunput(' '); + } + + cunput(*bp); + if ((*bp == '\'' || *bp == '"') + && bp[-1] != '\\' && snuff) { + instr ^= 1; + if (instr == 0 && *bp == '"') + cunput('\\'); + } + if (instr && (*bp == '\\' || *bp == '"')) + cunput('\\'); + } + } + } else + cunput(*sp); + sp--; + } + DPRINT(("%d:Return subarg\n", lvl)); + IMP("SUBARG"); +} + +/* + * Do a (correct) expansion of a WARN-terminated buffer of tokens. + * Data is read from the lex buffer, result on lex buffer, WARN-terminated. + * Expansion blocking is not altered here unless when tokens are + * concatenated, in which case they are removed. + */ +void +exparg(int lvl) { struct symtab *nl; - int c, noexp = 0, orgexp; - uchar *och, *stksv; + int c, i; + usch *och; + usch *osb = stringbuf; + int anychange; + + DPRINT(("%d:exparg\n", lvl)); + IMP("EXPARG"); -#ifdef CPP_DEBUG - if (dflag) { - struct recur *rp2 = rp; - printf("\nexpmac\n"); - while (rp2) { - printf("do not expand %s\n", rp2->sp->namep); - rp2 = rp2->next; - } - } -#endif readmac++; +rescan: + anychange = 0; while ((c = sloscan()) != WARN) { + DDPRINT(("%d:exparg swdata %d\n", lvl, c)); + IMP("EA0"); switch (c) { - case NOEXP: noexp++; break; - case EXPAND: noexp--; break; - case NUMBER: /* handled as ident if no .+- in it */ - if (!mayid((uchar *)yytext)) - goto def; + case EBLOCK: + doblk(); /* FALLTHROUGH */ case IDENT: /* * Handle argument concatenation here. - * If an identifier is found and directly - * after EXPAND or NOEXP then push the - * identifier back on the input stream and - * call sloscan() again. - * Be careful to keep the noexp balance. + * In case of concatenation, scratch all blockings. */ + DDPRINT(("%d:exparg ident %d\n", lvl, c)); och = stringbuf; - savstr((uchar *)yytext); - DDPRINT(("id: str %s\n", och)); - orgexp = 0; - while ((c = sloscan()) == EXPAND || c == NOEXP) - if (c == EXPAND) - orgexp--; - else - orgexp++; +sav: savstr(yytext); - DDPRINT(("id1: typ %d noexp %d orgexp %d\n", - c, noexp, orgexp)); - if (c == IDENT || - (c == NUMBER && mayid((uchar *)yytext))) { - DDPRINT(("id2: str %s\n", yytext)); - /* OK to always expand here? */ - savstr((uchar *)yytext); - switch (orgexp) { - case 0: /* been EXP+NOEXP */ - if (noexp == 0) - break; - if (noexp != 1) - error("case 0"); - cunput(NOEXP); - noexp = 0; - break; - case -1: /* been EXP */ - if (noexp != 1) - error("case -1"); - noexp = 0; - break; - case 1: - if (noexp != 0) - error("case 1"); - cunput(NOEXP); - break; - default: - error("orgexp = %d", orgexp); + if ((c = cinput()) == EBLOCK) { + /* yep, are concatenating; forget blocks */ + do { + (void)cinput(); + (void)cinput(); + } while ((c = sloscan()) == EBLOCK); + bidx = 0; + goto sav; + } + cunput(c); + + DPRINT(("%d:exparg: str '%s'\n", lvl, och)); + IMP("EA1"); + /* see if ident is expandable */ + if ((nl = lookup(och, FIND)) && okexp(nl)) { + if (submac(nl, lvl+1)) { + /* Could expand, result on lexbuffer */ + stringbuf = och; /* clear saved name */ + anychange = 1; } - unpstr(och); + } else if (bidx) { + /* must restore blocks */ stringbuf = och; - continue; /* New longer identifier */ + for (i = 0; i < bidx; i++) + savch(EBLOCK), savch(bptr[i] & 255), + savch(bptr[i] >> 8); + savstr(yytext); } - unpstr((const uchar *)yytext); - if (orgexp == -1) - cunput(EXPAND); - else if (orgexp == -2) - cunput(EXPAND), cunput(EXPAND); - else if (orgexp == 1) - cunput(NOEXP); - unpstr(och); - stringbuf = och; - - - sloscan(); /* XXX reget last identifier */ - - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) - goto def; - - if (canexpand(rp, nl) == 0) - goto def; - /* - * If noexp == 0 then expansion of any macro is - * allowed. If noexp == 1 then expansion of a - * fun-like macro is allowed iff there is an - * EXPAND between the identifier and the '('. - */ - if (noexp == 0) { - if ((c = subst(nl, rp)) == 0) - goto def; - break; - } - if (noexp != 1) - error("bad noexp %d", noexp); - stksv = NULL; - if ((c = sloscan()) == WSPACE) { - stksv = xstrdup(yytext); - c = sloscan(); - } - /* only valid for expansion if fun macro */ - if (c == EXPAND && *nl->value != OBJCT) { - noexp--; - if (subst(nl, rp)) - break; - savstr(nl->namep); - if (stksv) - savstr(stksv); - } else { - unpstr((const uchar *)yytext); - if (stksv) - unpstr(stksv); - savstr(nl->namep); - } - if (stksv) - free(stksv); + bidx = 0; + IMP("EA2"); break; case CMNT: @@ -1273,233 +1620,65 @@ expmac(struct recur *rp) savch(' '); break; - case STRING: - /* remove EXPAND/NOEXP from strings */ - if (yytext[1] == NOEXP) { - savch('"'); - och = (uchar *)&yytext[2]; - while (*och != EXPAND) - savch(*och++); - savch('"'); - break; - } - /* FALLTHROUGH */ - -def: default: - savstr((uchar *)yytext); + default: + savstr((usch *)yytext); break; } } - if (noexp) - error("expmac noexp=%d", noexp); - readmac--; - DPRINT(("return from expmac\n")); -} - -/* - * expand a function-like macro. - * vp points to end of replacement-list - * reads function arguments from sloscan() - * result is written on top of heap - */ -void -expdef(const uchar *vp, struct recur *rp, int gotwarn) -{ - const uchar **args, *ap, *bp, *sp; - uchar *sptr; - int narg, c, i, plev, snuff, instr; - int ellips = 0, shot = gotwarn; - - DPRINT(("expdef rp %s\n", (rp ? (const char *)rp->sp->namep : ""))); - c = sloscan(); - if (c != '(') - error("got %c, expected (", c); - - if (vp[1] == VARG) { - narg = *vp--; - ellips = 1; - } else - narg = vp[1]; - - args = malloc(sizeof(uchar *) * (narg+ellips)); - if (args == NULL) - error("expdef: out of mem"); - - /* - * read arguments and store them on heap. - * will be removed just before return from this function. - */ - sptr = stringbuf; - instr = 0; - for (i = 0; i < narg && c != ')'; i++) { - args[i] = stringbuf; - plev = 0; - while ((c = sloscan()) == WSPACE || c == '\n') - if (c == '\n') - putch(cinput()); - DDPRINT((":AAA (%d)", c)); - if (instr == -1) - savch(NOEXP), instr = 1; - if (c == NOEXP) - instr = 1; - for (;;) { - if (plev == 0 && (c == ')' || c == ',')) - break; - if (c == '(') - plev++; - if (c == ')') - plev--; - savstr((uchar *)yytext); - while ((c = sloscan()) == '\n') { - putch(cinput()); - savch('\n'); - } - while (c == CMNT) { - getcmnt(); - c = sloscan(); - } - if (c == EXPAND) - instr = 0; - if (c == 0) - error("eof in macro"); - } - while (args[i] < stringbuf && - (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) - stringbuf--; - if (instr == 1) - savch(EXPAND), instr = -1; - savch('\0'); - } - if (ellips) - args[i] = (const uchar *)""; - if (ellips && c != ')') { - args[i] = stringbuf; - plev = 0; - instr = 0; - while ((c = sloscan()) == WSPACE) - ; - if (c == NOEXP) - instr++; - DDPRINT((":AAY (%d)", c)); - for (;;) { - if (plev == 0 && c == ')') - break; - if (c == '(') - plev++; - if (c == ')') - plev--; - if (plev == 0 && c == ',' && instr) { - savch(EXPAND); - savch(','); - savch(NOEXP); - } else - savstr((uchar *)yytext); - while ((c = sloscan()) == '\n') { - cinput(); - savch('\n'); - } - if (c == EXPAND) - instr--; - } - while (args[i] < stringbuf && - (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) - stringbuf--; - savch('\0'); - - } - if (narg == 0 && ellips == 0) - while ((c = sloscan()) == WSPACE || c == '\n') - if (c == '\n') - cinput(); - - if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) - error("wrong arg count"); - - while (gotwarn--) - cunput(WARN); - - sp = vp; - instr = snuff = 0; - - /* - * push-back replacement-list onto lex buffer while replacing - * arguments. - */ + *stringbuf = 0; cunput(WARN); - while (*sp != 0) { - if (*sp == SNUFF) - cunput('\"'), snuff ^= 1; - else if (*sp == CONC) - ; - else if (*sp == WARN) { - - if (sp[-1] == VARG) { - bp = ap = args[narg]; - sp--; -#ifdef GCC_VARI - } else if (sp[-1] == GCCARG) { - ap = args[narg]; - if (ap[0] == 0) - ap = (const uchar *)"0"; - bp = ap; - sp--; -#endif - } else - bp = ap = args[(int)*--sp]; - if (sp[2] != CONC && !snuff && sp[-1] != CONC) { - struct recur *r2 = rp->next; - cunput(WARN); - while (*bp) - bp++; - while (bp > ap) - cunput(*--bp); - DPRINT(("expand arg %d string %s\n", *sp, ap)); - bp = ap = stringbuf; - savch(NOEXP); - while (shot && r2) - r2 = r2->next, shot--; - expmac(r2); - savch(EXPAND); - savch('\0'); - } - while (*bp) - bp++; - while (bp > ap) { - bp--; - if (snuff && !instr && - (*bp == ' ' || *bp == '\t' || *bp == '\n')){ - while (*bp == ' ' || *bp == '\t' || - *bp == '\n') { - bp--; - } - cunput(' '); - } - if (!snuff || (*bp != EXPAND && *bp != NOEXP)) - cunput(*bp); - if ((*bp == '\'' || *bp == '"') - && bp[-1] != '\\' && snuff) { - instr ^= 1; - if (instr == 0 && *bp == '"') - cunput('\\'); - } - if (instr && (*bp == '\\' || *bp == '"')) - cunput('\\'); - } - } else - cunput(*sp); - sp--; - } - stringbuf = sptr; - - /* scan the input buffer (until WARN) and save result on heap */ - expmac(rp); - free(args); + unpstr(osb); + DPRINT(("%d:exparg return: change %d\n", lvl, anychange)); + IMP("EXPRET"); + stringbuf = osb; + if (anychange) + goto rescan; + readmac--; } -uchar * -savstr(const uchar *str) +void +imp(const char *str) { - uchar *rv = stringbuf; + printf("%s (%d) '", str, bidx); + prline(ifiles->curptr); + printf("'\n"); +} + +void +prrep(const usch *s) +{ + while (*s) { + switch (*s) { + case WARN: printf("", *--s); break; + case CONC: printf(""); break; + case SNUFF: printf(""); break; + case EBLOCK: printf("",s[-1] + s[-2] * 256); s-=2; break; + default: printf("%c", *s); break; + } + s--; + } +} + +void +prline(const usch *s) +{ + while (*s) { + switch (*s) { + case WARN: printf(""); break; + case CONC: printf(""); break; + case SNUFF: printf(""); break; + case EBLOCK: printf("",s[1] + s[2] * 256); s+=2; break; + case '\n': printf(""); break; + default: printf("%c", *s); break; + } + s++; + } +} + +usch * +savstr(const usch *str) +{ + usch *rv = stringbuf; do { if (stringbuf >= &sbf[SBSIZE]) { @@ -1511,25 +1690,23 @@ savstr(const uchar *str) return rv; } -int -canexpand(struct recur *rp, struct symtab *np) -{ - struct recur *w; - - for (w = rp; w && w->sp != np; w = w->next) - ; - if (w != NULL) - return 0; - return 1; -} - void -unpstr(const uchar *c) +unpstr(const usch *c) { - const uchar *d = c; + const usch *d = c; - while (*d) +#if 0 + if (dflag>1) { + printf("Xunpstr: '"); + prline(c); + printf("'\n"); + } +#endif + while (*d) { + if (*d == EBLOCK) + d += 2; d++; + } while (d > c) { cunput(*--d); } @@ -1542,19 +1719,20 @@ flbuf() return; if (Mflag == 0 && write(ofd, outbuf, obufp) < 0) error("obuf write error"); + lastoch = outbuf[obufp-1]; obufp = 0; } void putch(int ch) { - outbuf[obufp++] = (uchar)ch; + outbuf[obufp++] = (usch)ch; if (obufp == CPPBUF || (istty && ch == '\n')) flbuf(); } void -putstr(const uchar *s) +putstr(const usch *s) { for (; *s; s++) { outbuf[obufp++] = *s; @@ -1569,14 +1747,14 @@ putstr(const uchar *s) static void num2str(int num) { - static uchar buf[12]; - uchar *b = buf; + static usch buf[12]; + usch *b = buf; int m = 0; - + if (num < 0) num = -num, m = 1; do { - *b++ = (uchar)(num % 10 + '0'); + *b++ = (usch)(num % 10 + '0'); num /= 10; } while (num); if (m) @@ -1586,14 +1764,14 @@ num2str(int num) } /* - * similar to sprintf, but only handles %s and %d. + * similar to sprintf, but only handles %s and %d. * saves result on heap. */ -uchar * +usch * sheap(const char *fmt, ...) { va_list ap; - uchar *op = stringbuf; + usch *op = stringbuf; va_start(ap, fmt); for (; *fmt; fmt++) { @@ -1601,7 +1779,7 @@ sheap(const char *fmt, ...) fmt++; switch (*fmt) { case 's': - savstr(va_arg(ap, uchar *)); + savstr(va_arg(ap, usch *)); break; case 'd': num2str(va_arg(ap, int)); @@ -1626,13 +1804,26 @@ usage() error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]"); } +#ifdef notyet /* * Symbol table stuff. - * The data structure used is a patricia tree implementation. + * The data structure used is a patricia tree implementation using only + * bytes to store offsets. + * The information stored is (lower address to higher): + * + * unsigned char bitno[2]; bit number in the string + * unsigned char left[3]; offset from base to left element + * unsigned char right[3]; offset from base to right element + */ +#endif + +/* + * This patricia implementation is more-or-less the same as + * used in ccom for string matching. */ struct tree { - int bitno; /* bit number in the string */ - struct tree *lr[2]; /* left/right element */ + int bitno; + struct tree *lr[2]; }; #define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF)) @@ -1650,7 +1841,7 @@ static int numsyms; * Allocate a symtab struct and store the string. */ static struct symtab * -getsymtab(const uchar *str) +getsymtab(const usch *str) { struct symtab *sp = malloc(sizeof(struct symtab)); @@ -1659,7 +1850,7 @@ getsymtab(const uchar *str) sp->namep = savstr(str); savch('\0'); sp->value = NULL; - sp->file = ifiles ? ifiles->orgfn : (const uchar *)""; + sp->file = ifiles ? ifiles->orgfn : (const usch *)""; sp->line = ifiles ? ifiles->lineno : 0; return sp; } @@ -1669,12 +1860,12 @@ getsymtab(const uchar *str) * Only do full string matching, no pointer optimisations. */ struct symtab * -lookup(const uchar *key, int enterf) +lookup(const usch *key, int enterf) { struct symtab *sp; struct tree *w, *new, *last; int len, cix, bit, fbit, svbit, ix, bitno; - const uchar *k, *m; + const usch *k, *m/*, *sm*/; /* Count full string length */ for (k = key, len = 0; *k; k++, len++) @@ -1690,6 +1881,7 @@ lookup(const uchar *key, int enterf) case 1: w = sympole; + svbit = 0; /* XXX gcc */ break; default: @@ -1708,7 +1900,7 @@ lookup(const uchar *key, int enterf) sp = (struct symtab *)w; - m = sp->namep; + /*sm =*/ m = sp->namep; k = key; /* Check for correct string and return */ @@ -1728,8 +1920,7 @@ lookup(const uchar *key, int enterf) ix >>= 1, cix++; /* Create new node */ - new = malloc(sizeof *new); - if (! new) + if ((new = malloc(sizeof *new)) == NULL) error("getree: couldn't allocate tree"); bit = P_BIT(key, cix); new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); @@ -1744,7 +1935,6 @@ lookup(const uchar *key, int enterf) w = sympole; last = NULL; - svbit = 0; /* XXX gcc */ for (;;) { fbit = w->bitno; bitno = BITNO(w->bitno); @@ -1770,3 +1960,15 @@ lookup(const uchar *key, int enterf) new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); return (struct symtab *)new->lr[bit]; } + +usch * +xstrdup(const usch *str) +{ + size_t len = strlen((const char *)str)+1; + usch *rv; + + if ((rv = malloc(len)) == NULL) + error("xstrdup: out of mem"); + strlcpy((char *)rv, (const char *)str, len); + return rv; +} diff --git a/src/cmd/cpp/cpp.h b/src/cmd/cpp/cpp.h index 1356dd8..bebc226 100644 --- a/src/cmd/cpp/cpp.h +++ b/src/cmd/cpp/cpp.h @@ -1,5 +1,7 @@ +/* $Id: cpp.h,v 1.47.2.1 2011/02/26 06:36:40 ragge Exp $ */ + /* - * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). + * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,8 +12,6 @@ * 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -24,25 +24,15 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef CROSS -# include -# include -#else -# include /* for obuf */ -# include -#endif + +#include /* for obuf */ #include -/* Version string */ -#define VERSSTR "cpp for RetroBSD" +#include "config.h" -typedef unsigned char uchar; -#ifdef YYTEXT_POINTER -extern char *yytext; -#else -extern char yytext[]; -#endif -extern uchar *stringbuf; +typedef unsigned char usch; +extern usch yytext[]; +extern usch *stringbuf; extern int trulvl; extern int flslvl; @@ -50,7 +40,7 @@ extern int elflvl; extern int elslvl; extern int tflag, Cflag, Pflag; extern int Mflag, dMflag; -extern uchar *Mfile; +extern usch *Mfile; extern int ofd; /* args for lookup() */ @@ -58,32 +48,77 @@ extern int ofd; #define ENTER 1 /* buffer used internally */ -#define CPPBUF 512 +#define CPPBUF 512 +#ifndef CPPBUF +#if defined(__pdp11__) +#define CPPBUF BUFSIZ +#define BUF_STACK +#elif defined(WIN32) +/* winxp seems to fail > 26608 bytes */ +#define CPPBUF 16384 +#else +#define CPPBUF (65536*2) +#endif +#endif + +#define MAXARGS 20//128 /* Max # of args to a macro. Should be enouth */ #define NAMEMAX CPPBUF /* currently pushbackbuffer */ +#define BBUFSZ (NAMEMAX+CPPBUF+1) + +#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */ +#define VARG 0xfe /* has varargs */ +#define OBJCT 0xff +#define WARN 1 /* SOH, not legal char */ +#define CONC 2 /* STX, not legal char */ +#define SNUFF 3 /* ETX, not legal char */ +#define EBLOCK 4 /* EOT, not legal char */ + +/* Used in macro expansion */ +#define RECMAX 400//10000 /* max # of recursive macros */ +extern struct symtab *norep[RECMAX]; +extern int norepptr; +extern unsigned short bptr[RECMAX]; +extern int bidx; +#define MKB(l,h) (l+((h)<<8)) + +/* quick checks for some characters */ +#define C_SPEC 001 +#define C_EP 002 +#define C_ID 004 +#define C_I (C_SPEC|C_ID) +#define C_2 010 /* for yylex() tokenizing */ +#define C_WSNL 020 /* ' ','\t','\r','\n' */ +#define iswsnl(x) (spechr[x] & C_WSNL) +extern char spechr[]; /* definition for include file info */ struct includ { struct includ *next; - const uchar *fname; /* current fn, changed if #line found */ - const uchar *orgfn; /* current fn, not changed */ + const usch *fname; /* current fn, changed if #line found */ + const usch *orgfn; /* current fn, not changed */ int lineno; int infil; - uchar *curptr; - uchar *maxread; - uchar *ostr; - uchar *buffer; + usch *curptr; + usch *maxread; + usch *ostr; + usch *buffer; int idx; void *incs; - const uchar *fn; - uchar bbuf[NAMEMAX+CPPBUF+1]; -} *ifiles; + const usch *fn; +#ifdef BUF_STACK + usch bbuf[BBUFSZ]; +#else + usch *bbuf; +#endif +}; +extern struct includ *ifiles; /* Symbol table entry */ struct symtab { - const uchar *namep; - const uchar *value; - const uchar *file; + const usch *namep; + const usch *value; + const usch *file; int line; }; @@ -110,13 +145,15 @@ struct nd { #define nd_val n.val #define nd_uval n.uval -struct recur; /* not used outside cpp.c */ -int subst(struct symtab *, struct recur *); -struct symtab *lookup(const uchar *namep, int enterf); -uchar *gotident(struct symtab *nl); -int slow; /* scan slowly for new tokens */ +struct symtab *lookup(const usch *namep, int enterf); +usch *gotident(struct symtab *nl); +extern int slow; /* scan slowly for new tokens */ +int submac(struct symtab *nl, int); +int kfind(struct symtab *nl); +int doexp(void); +int donex(void); -int pushfile(const uchar *fname, const uchar *fn, int idx, void *incs); +int pushfile(const usch *fname, const usch *fn, int idx, void *incs); void popfile(void); void prtline(void); int yylex(void); @@ -128,18 +165,22 @@ void setline(int); void setfile(char *); int yyparse(void); void yyerror(const char *); -void unpstr(const uchar *); -uchar *savstr(const uchar *str); +void unpstr(const usch *); +usch *savstr(const usch *str); void savch(int c); void mainscan(void); void putch(int); -void putstr(const uchar *s); +void putstr(const usch *s); void line(void); -uchar *sheap(const char *fmt, ...); -void xwarning(uchar *); -void xerror(uchar *); -#define warning(args...) xwarning(sheap(args)) -#define error(args...) xerror(sheap(args)) -void expmac(struct recur *); +usch *sheap(const char *fmt, ...); +void xwarning(usch *); +void xerror(usch *); +#ifdef HAVE_CPP_VARARG_MACRO_GCC +#define warning(...) xwarning(sheap(__VA_ARGS__)) +#define error(...) xerror(sheap(__VA_ARGS__)) +#else +#define warning printf +#define error printf +#endif int cinput(void); void getcmnt(void); diff --git a/src/cmd/cpp/cpy.y b/src/cmd/cpp/cpy.y index 4e4c1a5..78bc3ca 100644 --- a/src/cmd/cpp/cpy.y +++ b/src/cmd/cpp/cpy.y @@ -1,3 +1,5 @@ +/* $Id: cpy.y,v 1.18 2010/02/25 15:49:00 ragge Exp $ */ + /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -58,6 +60,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + %{ #include "cpp.h" diff --git a/src/cmd/cpp/doprnt.c b/src/cmd/cpp/doprnt.c new file mode 100644 index 0000000..c5ed28d --- /dev/null +++ b/src/cmd/cpp/doprnt.c @@ -0,0 +1,203 @@ +/* +Copyright (c) 2013, Alexey Frunze +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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +#include +#include +#include + +int _doprnt (char const *fmt, va_list pp, FILE *stream) +{ + int cnt = 0; + const char* p; + const char* phex = "0123456789abcdef"; + char s[1/*sign*/+10/*magnitude*/+1/*\0*/]; // up to 11 octal digits in 32-bit numbers + char* pc; + int n, sign, msign; + int minlen = 0, len; + int leadchar; + + for (p = fmt; *p != '\0'; p++) + { + if (*p != '%' || p[1] == '%') + { + fputc(*p, stream); + p = p + (*p == '%'); + cnt++; + continue; + } + p++; + minlen = 0; + msign = 0; + if (*p == '+') { msign = 1; p++; } + else if (*p == '-') { msign = -1; p++; } + leadchar = ' '; + if (*p >= '0' && *p <= '9') + { + if (*p == '0') + leadchar = '0'; + while (*p >= '0' && *p <= '9') + minlen = minlen * 10 + *p++ - '0'; + if (msign < 0) + minlen = -minlen; + msign = 0; + } + if (!msign) + { + if (*p == '+') { msign = 1; p++; } + else if (*p == '-') { msign = -1; p++; } + } + switch (*p) + { + case 'c': + while (minlen > 1) { fputc(' ', stream); cnt++; minlen--; } + fputc(va_arg(pp, int), stream); + while (-minlen > 1) { fputc(' ', stream); cnt++; minlen++; } + cnt++; + break; + case 's': + pc = va_arg(pp, char*); + len = 0; + if (pc) + len = strlen(pc); + while (minlen > len) { fputc(' ', stream); cnt++; minlen--; } + if (len) + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + case 'i': + case 'd': + pc = &s[sizeof s - 1]; + *pc = '\0'; + len = 0; + n = va_arg(pp, int); + sign = 1 - 2 * (n < 0); + do + { + *--pc = '0' + (n - n / 10 * 10) * sign; + n = n / 10; + len++; + } while (n); + if (sign < 0) + { + *--pc = '-'; + len++; + } + else if (msign > 0) + { + *--pc = '+'; + len++; + msign = 0; + } + while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; } + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + case 'u': + pc = &s[sizeof s - 1]; + *pc = '\0'; + len = 0; + n = va_arg(pp, int); + do + { + unsigned nn = n; + *--pc = '0' + nn % 10; + n = nn / 10; + len++; + } while (n); + if (msign > 0) + { + *--pc = '+'; + len++; + msign = 0; + } + while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; } + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + case 'X': + phex = "0123456789ABCDEF"; + // fallthrough + case 'p': + case 'x': + pc = &s[sizeof s - 1]; + *pc = '\0'; + len = 0; + n = va_arg(pp, int); + do + { + *--pc = phex[n & 0xF]; + n = (n >> 4) & ((1 << (8 * sizeof n - 4)) - 1); // drop sign-extended bits + len++; + } while (n); + while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; } + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + case 'o': + pc = &s[sizeof s - 1]; + *pc = '\0'; + len = 0; + n = va_arg(pp, int); + do + { + *--pc = '0' + (n & 7); + n = (n >> 3) & ((1 << (8 * sizeof n - 3)) - 1); // drop sign-extended bits + len++; + } while (n); + while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; } + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + default: + return -1; + } + } + + return cnt; +} diff --git a/src/cmd/cpp/scanner.l b/src/cmd/cpp/scanner.l new file mode 100644 index 0000000..f1e4bf9 --- /dev/null +++ b/src/cmd/cpp/scanner.l @@ -0,0 +1,939 @@ +%{ +/* $Id: scanner.l,v 1.49 2009/02/14 09:23:55 ragge Exp $ */ + +/* + * Copyright (c) 2004 Anders Magnusson. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ + +#include "config.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "compat.h" +#include "cpp.h" +#include "y.tab.h" +%} + +%{ +static void cvtdig(int rad); +static int charcon(usch *); +static void elsestmt(void); +static void ifdefstmt(void); +static void ifndefstmt(void); +static void endifstmt(void); +static void ifstmt(void); +static void cpperror(void); +static void pragmastmt(void); +static void undefstmt(void); +static void cpperror(void); +static void elifstmt(void); +static void storepb(void); +static void badop(const char *); +void include(void); +void define(void); + +extern int yyget_lineno (void); +extern void yyset_lineno (int); + +static int inch(void); + +static int scale, gotdef, contr; +int inif; + +#ifdef FLEX_SCANNER /* should be set by autoconf instead */ +static int +yyinput(char *b, int m) +{ + int c, i; + + for (i = 0; i < m; i++) { + if ((c = inch()) < 0) + break; + *b++ = c; + if (c == '\n') { + i++; + break; + } + } + return i; +} +#undef YY_INPUT +#undef YY_BUF_SIZE +#define YY_BUF_SIZE (8*65536) +#define YY_INPUT(b,r,m) (r = yyinput(b, m)) +#ifdef HAVE_CPP_VARARG_MACRO_GCC +#define fprintf(x, ...) error(__VA_ARGS__) +#endif +#define ECHO putstr((usch *)yytext) +#undef fileno +#define fileno(x) 0 + +#if YY_FLEX_SUBMINOR_VERSION >= 31 +/* Hack to avoid unnecessary warnings */ +FILE *yyget_in (void); +FILE *yyget_out (void); +int yyget_leng (void); +char *yyget_text (void); +void yyset_in (FILE * in_str ); +void yyset_out (FILE * out_str ); +int yyget_debug (void); +void yyset_debug (int bdebug ); +int yylex_destroy (void); +#endif +#else /* Assume lex here */ +#undef input +#undef unput +#define input() inch() +#define unput(ch) unch(ch) +#endif +#define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((usch *)yytext); +/* protection against recursion in #include */ +#define MAX_INCLEVEL 100 +static int inclevel; +%} + +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +FS (f|F|l|L) +IS (u|U|l|L)* +WS [\t ] + +%s IFR CONTR DEF COMMENT + +%% + +"\n" { int os = YYSTATE; + if (os != IFR) + BEGIN 0; + ifiles->lineno++; + if (flslvl == 0) { + if (ifiles->lineno == 1) + prtline(); + else + putch('\n'); + } + if ((os != 0 || slow) && !contr) + return '\n'; + contr = 0; + } + +"\r" { ; /* Ignore CR's */ } + +"++" { badop("++"); } +"--" { badop("--"); } +"==" { return EQ; } +"!=" { return NE; } +"<=" { return LE; } +"<<" { return LS; } +">>" { return RS; } +">=" { return GE; } +"||" { return OROR; } +"&&" { return ANDAND; } +"defined" { int p, c; + gotdef = 1; + if ((p = c = yylex()) == '(') + c = yylex(); + if (c != IDENT || (p != IDENT && p != '(')) + error("syntax error"); + if (p == '(' && yylex() != ')') + error("syntax error"); + return NUMBER; + } + +{WS}+ { ; } +{L}({L}|{D})* { + yylval.node.op = NUMBER; + if (gotdef) { + yylval.node.nd_val + = lookup((usch *)yytext, FIND) != 0; + gotdef = 0; + return IDENT; + } + yylval.node.nd_val = 0; + return NUMBER; + } + +[0-9][0-9]* { + if (slow && !YYSTATE) + return IDENT; + scale = yytext[0] == '0' ? 8 : 10; + goto num; + } + +0[xX]{H}+{IS}? { scale = 16; + num: if (YYSTATE == IFR) + cvtdig(scale); + PRTOUT(NUMBER); + } +0{D}+{IS}? { scale = 8; goto num; } +{D}+{IS}? { scale = 10; goto num; } +'(\\.|[^\\'])+' { + if (YYSTATE || slow) { + yylval.node.op = NUMBER; + yylval.node.nd_val = charcon((usch *)yytext); + return (NUMBER); + } + if (tflag) + yyless(1); + if (!flslvl) + putstr((usch *)yytext); + } + +. { return yytext[0]; } + +{D}+{E}{FS}? { PRTOUT(FPOINT); } +{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); } +{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); } + +^{WS}*#{WS}* { extern int inmac; + + if (inmac) + error("preprocessor directive found " + "while expanding macro"); + contr = 1; + BEGIN CONTR; + } +{WS}+ { PRTOUT(WSPACE); } + +"ifndef" { contr = 0; ifndefstmt(); } +"ifdef" { contr = 0; ifdefstmt(); } +"if" { contr = 0; storepb(); BEGIN IFR; ifstmt(); BEGIN 0; } +"include" { contr = 0; BEGIN 0; include(); prtline(); } +"else" { contr = 0; elsestmt(); } +"endif" { contr = 0; endifstmt(); } +"error" { contr = 0; if (slow) return IDENT; cpperror(); BEGIN 0; } +"define" { contr = 0; BEGIN DEF; define(); BEGIN 0; } +"undef" { contr = 0; if (slow) return IDENT; undefstmt(); } +"line" { contr = 0; storepb(); BEGIN 0; line(); } +"pragma" { contr = 0; pragmastmt(); BEGIN 0; } +"elif" { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; } + + + +"//".*$ { /* if (tflag) yyless(..) */ + if (Cflag && !flslvl && !slow) + putstr((usch *)yytext); + else if (!flslvl) + putch(' '); + } +"/*" { int c, wrn; + int prtcm = Cflag && !flslvl && !slow; + extern int readmac; + + if (Cflag && !flslvl && readmac) + return CMNT; + + if (prtcm) + putstr((usch *)yytext); + wrn = 0; + more: while ((c = input()) && c != '*') { + if (c == '\n') + putch(c), ifiles->lineno++; + else if (c == 1) /* WARN */ + wrn = 1; + else if (prtcm) + putch(c); + } + if (c == 0) + return 0; + if (prtcm) + putch(c); + if ((c = input()) && c != '/') { + unput(c); + goto more; + } + if (prtcm) + putch(c); + if (c == 0) + return 0; + if (!tflag && !Cflag && !flslvl) + unput(' '); + if (wrn) + unput(1); + } + +"##" { return CONCAT; } +"#" { return MKSTR; } +"..." { return ELLIPS; } +"__VA_ARGS__" { return VA_ARGS; } + +L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); } +[a-zA-Z_0-9]+ { /* {L}({L}|{D})* */ + struct symtab *nl; + if (slow) + return IDENT; + if (YYSTATE == CONTR) { + if (flslvl == 0) { + /*error("undefined control");*/ + while (input() != '\n') + ; + unput('\n'); + BEGIN 0; + goto xx; + } else { + BEGIN 0; /* do nothing */ + } + } + if (flslvl) { + ; /* do nothing */ + } else if (isdigit((int)yytext[0]) == 0 && + (nl = lookup((usch *)yytext, FIND)) != 0) { + usch *op = stringbuf; + putstr(gotident(nl)); + stringbuf = op; + } else + putstr((usch *)yytext); + xx: ; + } + +. { + if (contr) { + while (input() != '\n') + ; + unput('\n'); + BEGIN 0; + contr = 0; + goto yy; + } + if (YYSTATE || slow) + return yytext[0]; + if (yytext[0] == 6) { /* PRAGS */ + usch *obp = stringbuf; + extern usch *prtprag(usch *); + *stringbuf++ = yytext[0]; + do { + *stringbuf = input(); + } while (*stringbuf++ != 14); + prtprag(obp); + stringbuf = obp; + } else { + PRTOUT(yytext[0]); + } + yy:; + } + +%% + +usch *yyp, yybuf[CPPBUF]; + +int yylex(void); +int yywrap(void); + +static int +inpch(void) +{ + int len; + + if (ifiles->curptr < ifiles->maxread) + return *ifiles->curptr++; + + if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0) + error("read error on file %s", ifiles->orgfn); + if (len == 0) + return -1; + ifiles->curptr = ifiles->buffer; + ifiles->maxread = ifiles->buffer + len; + return inpch(); +} + +#define unch(c) *--ifiles->curptr = c + +static int +inch(void) +{ + int c; + +again: switch (c = inpch()) { + case '\\': /* continued lines */ +msdos: if ((c = inpch()) == '\n') { + ifiles->lineno++; + putch('\n'); + goto again; + } else if (c == '\r') + goto msdos; + unch(c); + return '\\'; + case '?': /* trigraphs */ + if ((c = inpch()) != '?') { + unch(c); + return '?'; + } + switch (c = inpch()) { + case '=': c = '#'; break; + case '(': c = '['; break; + case ')': c = ']'; break; + case '<': c = '{'; break; + case '>': c = '}'; break; + case '/': c = '\\'; break; + case '\'': c = '^'; break; + case '!': c = '|'; break; + case '-': c = '~'; break; + default: + unch(c); + unch('?'); + return '?'; + } + unch(c); + goto again; + default: + return c; + } +} + +/* + * Let the command-line args be faked defines at beginning of file. + */ +static void +prinit(struct initar *it, struct includ *ic) +{ + char *a, *pre, *post; + + if (it->next) + prinit(it->next, ic); + pre = post = NULL; /* XXX gcc */ + switch (it->type) { + case 'D': + pre = "#define "; + if ((a = strchr(it->str, '=')) != NULL) { + *a = ' '; + post = "\n"; + } else + post = " 1\n"; + break; + case 'U': + pre = "#undef "; + post = "\n"; + break; + case 'i': + pre = "#include \""; + post = "\"\n"; + break; + default: + error("prinit"); + } + strlcat((char *)ic->buffer, pre, CPPBUF+1); + strlcat((char *)ic->buffer, it->str, CPPBUF+1); + if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1) + error("line exceeds buffer size"); + + ic->lineno--; + while (*ic->maxread) + ic->maxread++; +} + +/* + * A new file included. + * If ifiles == NULL, this is the first file and already opened (stdin). + * Return 0 on success, -1 if file to be included is not found. + */ +int +pushfile(usch *file) +{ + extern struct initar *initar; + struct includ ibuf; + struct includ *ic; + int c, otrulvl; + + ic = &ibuf; + ic->next = ifiles; + + slow = 0; + if (file != NULL) { + if ((ic->infil = open((char *)file, O_RDONLY)) < 0) + return -1; + ic->orgfn = ic->fname = file; + if (++inclevel > MAX_INCLEVEL) + error("Limit for nested includes exceeded"); + } else { + ic->infil = 0; + ic->orgfn = ic->fname = (usch *)""; + } + ic->buffer = ic->bbuf+NAMEMAX; + ic->curptr = ic->buffer; + ifiles = ic; + ic->lineno = 1; + ic->maxread = ic->curptr; + prtline(); + if (initar) { + *ic->maxread = 0; + prinit(initar, ic); + if (dMflag) + write(ofd, ic->buffer, strlen((char *)ic->buffer)); + initar = NULL; + } + + otrulvl = trulvl; + + if ((c = yylex()) != 0) + error("yylex returned %d", c); + + if (otrulvl != trulvl || flslvl) + error("unterminated conditional"); + + ifiles = ic->next; + close(ic->infil); + inclevel--; + return 0; +} + +/* + * Print current position to output file. + */ +void +prtline() +{ + usch *s, *os = stringbuf; + + if (Mflag) { + if (dMflag) + return; /* no output */ + if (ifiles->lineno == 1) { + s = sheap("%s: %s\n", Mfile, ifiles->fname); + write(ofd, s, strlen((char *)s)); + } + } else if (!Pflag) + putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); + stringbuf = os; +} + +void +cunput(int c) +{ +#ifdef CPP_DEBUG + extern int dflag; + if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c); +#endif + unput(c); +} + +int yywrap(void) { return 1; } + +static int +dig2num(int c) +{ + if (c >= 'a') + c = c - 'a' + 10; + else if (c >= 'A') + c = c - 'A' + 10; + else + c = c - '0'; + return c; +} + +/* + * Convert string numbers to unsigned long long and check overflow. + */ +static void +cvtdig(int rad) +{ + unsigned long long rv = 0; + unsigned long long rv2 = 0; + char *y = yytext; + int c; + + c = *y++; + if (rad == 16) + y++; + while (isxdigit(c)) { + rv = rv * rad + dig2num(c); + /* check overflow */ + if (rv / rad < rv2) + error("Constant \"%s\" is out of range", yytext); + rv2 = rv; + c = *y++; + } + y--; + while (*y == 'l' || *y == 'L') + y++; + yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER; + yylval.node.nd_uval = rv; + if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0) + yylval.node.op = UNUMBER; + if (yylval.node.op == NUMBER && yylval.node.nd_val < 0) + /* too large for signed */ + error("Constant \"%s\" is out of range", yytext); +} + +static int +charcon(usch *p) +{ + int val, c; + + p++; /* skip first ' */ + val = 0; + if (*p++ == '\\') { + switch (*p++) { + case 'a': val = '\a'; break; + case 'b': val = '\b'; break; + case 'f': val = '\f'; break; + case 'n': val = '\n'; break; + case 'r': val = '\r'; break; + case 't': val = '\t'; break; + case 'v': val = '\v'; break; + case '\"': val = '\"'; break; + case '\'': val = '\''; break; + case '\\': val = '\\'; break; + case 'x': + while (isxdigit(c = *p)) { + val = val * 16 + dig2num(c); + p++; + } + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + p--; + while (isdigit(c = *p)) { + val = val * 8 + (c - '0'); + p++; + } + break; + default: val = p[-1]; + } + + } else + val = p[-1]; + return val; +} + +static void +chknl(int ignore) +{ + int t; + + slow = 1; + while ((t = yylex()) == WSPACE) + ; + if (t != '\n') { + if (ignore) { + warning("newline expected, got \"%s\"", yytext); + /* ignore rest of line */ + while ((t = yylex()) && t != '\n') + ; + } + else + error("newline expected, got \"%s\"", yytext); + } + slow = 0; +} + +static void +elsestmt(void) +{ + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) { + flslvl++; + } else { + trulvl++; + prtline(); + } + } else if (trulvl) { + flslvl++; + trulvl--; + } else + error("If-less else"); + if (elslvl==trulvl+flslvl) + error("Too many else"); + elslvl=trulvl+flslvl; + chknl(1); +} + +static void +ifdefstmt(void) +{ + int t; + + if (flslvl) { + /* just ignore the rest of the line */ + while (input() != '\n') + ; + unput('\n'); + yylex(); + flslvl++; + return; + } + slow = 1; + do + t = yylex(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifdef"); + slow = 0; + if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0) + trulvl++; + else + flslvl++; + chknl(0); +} + +static void +ifndefstmt(void) +{ + int t; + + slow = 1; + do + t = yylex(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifndef"); + slow = 0; + if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0) + trulvl++; + else + flslvl++; + chknl(0); +} + +static void +endifstmt(void) +{ + if (flslvl) { + flslvl--; + if (flslvl == 0) + prtline(); + } else if (trulvl) + trulvl--; + else + error("If-less endif"); + if (flslvl == 0) + elflvl = 0; + elslvl = 0; + chknl(1); +} + +/* + * Note! Ugly! + * Walk over the string s and search for defined, and replace it with + * spaces and a 1 or 0. + */ +static void +fixdefined(usch *s) +{ + usch *bc, oc; + + for (; *s; s++) { + if (*s != 'd') + continue; + if (memcmp(s, "defined", 7)) + continue; + /* Ok, got defined, can scratch it now */ + memset(s, ' ', 7); + s += 7; +#define WSARG(x) (x == ' ' || x == '\t') + if (*s != '(' && !WSARG(*s)) + continue; + while (WSARG(*s)) + s++; + if (*s == '(') + s++; + while (WSARG(*s)) + s++; +#define IDARG(x) ((x>= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x == '_')) +#define NUMARG(x) (x >= '0' && x <= '9') + if (!IDARG(*s)) + error("bad defined arg"); + bc = s; + while (IDARG(*s) || NUMARG(*s)) + s++; + oc = *s; + *s = 0; + *bc = (lookup(bc, FIND) != 0) + '0'; + memset(bc+1, ' ', s-bc-1); + *s = oc; + } +} + +/* + * get the full line of identifiers after an #if, pushback a WARN and + * the line and prepare for expmac() to expand. + * This is done before switching state. When expmac is finished, + * pushback the expanded line, change state and call yyparse. + */ +static void +storepb(void) +{ + usch *opb = stringbuf; + int c; + + while ((c = input()) != '\n') { + if (c == '/') { + if ((c = input()) == '*') { + /* ignore comments here whatsoever */ + usch *g = stringbuf; + getcmnt(); + stringbuf = g; + continue; + } else if (c == '/') { + while ((c = input()) && c != '\n') + ; + break; + } + unput(c); + c = '/'; + } + savch(c); + } + cunput('\n'); + savch(0); + fixdefined(opb); /* XXX can fail if #line? */ + cunput(1); /* WARN XXX */ + unpstr(opb); + stringbuf = opb; + slow = 1; + expmac(NULL); + slow = 0; + /* line now expanded */ + while (stringbuf > opb) + cunput(*--stringbuf); +} + +static void +ifstmt(void) +{ + if (flslvl == 0) { + slow = 1; + if (yyparse()) + ++trulvl; + else + ++flslvl; + slow = 0; + } else + ++flslvl; +} + +static void +elifstmt(void) +{ + if (flslvl == 0) + elflvl = trulvl; + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) + ++flslvl; + else { + slow = 1; + if (yyparse()) { + ++trulvl; + prtline(); + } else + ++flslvl; + slow = 0; + } + } else if (trulvl) { + ++flslvl; + --trulvl; + } else + error("If-less elif"); +} + +static usch * +svinp(void) +{ + int c; + usch *cp = stringbuf; + + while ((c = input()) && c != '\n') + savch(c); + savch('\n'); + savch(0); + BEGIN 0; + return cp; +} + +static void +cpperror(void) +{ + usch *cp; + int c; + + if (flslvl) + return; + c = yylex(); + if (c != WSPACE && c != '\n') + error("bad error"); + cp = svinp(); + if (flslvl) + stringbuf = cp; + else + error("%s", cp); +} + +static void +undefstmt(void) +{ + struct symtab *np; + + slow = 1; + if (yylex() != WSPACE || yylex() != IDENT) + error("bad undef"); + if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) + np->value = 0; + slow = 0; + chknl(0); +} + +static void +pragmastmt(void) +{ + int c; + + slow = 1; + if (yylex() != WSPACE) + error("bad pragma"); + if (!flslvl) + putstr((usch *)"#pragma "); + do { + c = input(); + if (!flslvl) + putch(c); /* Do arg expansion instead? */ + } while (c && c != '\n'); + ifiles->lineno++; + prtline(); + slow = 0; +} + +static void +badop(const char *op) +{ + error("invalid operator in preprocessor expression: %s", op); +} + +int +cinput() +{ + return input(); +} diff --git a/src/cmd/cpp/tests/res11 b/src/cmd/cpp/tests/res11 new file mode 100644 index 0000000..4c49d18 --- /dev/null +++ b/src/cmd/cpp/tests/res11 @@ -0,0 +1,22 @@ + +# 1 "" + + + + + +a +a b +a b c +a b c d + + + + + + +__attribute__((__noreturn__)) + + +1 2 + diff --git a/src/cmd/cpp/tests/res12 b/src/cmd/cpp/tests/res12 new file mode 100644 index 0000000..1420d39 --- /dev/null +++ b/src/cmd/cpp/tests/res12 @@ -0,0 +1,21 @@ + +# 1 "" + + + + + +2 2 2 2 2; + + + + + + + + + + + + +(0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, diff --git a/src/cmd/cpp/tests/res13 b/src/cmd/cpp/tests/res13 new file mode 100644 index 0000000..5ec9b41 --- /dev/null +++ b/src/cmd/cpp/tests/res13 @@ -0,0 +1,13 @@ + +# 1 "" + + + + +long + + + + + + diff --git a/src/cmd/cpp/tests/res2 b/src/cmd/cpp/tests/res2 index 945449b..e9fb624 100644 --- a/src/cmd/cpp/tests/res2 +++ b/src/cmd/cpp/tests/res2 @@ -15,7 +15,8 @@ f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); -f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); +f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & +f(2 * (0,1))^m(0,1); int i[] = { 1, 23, 4, 5, }; char c[2][6] = { "hello", "" }; diff --git a/src/cmd/cpp/tests/test11 b/src/cmd/cpp/tests/test11 new file mode 100644 index 0000000..5bf4249 --- /dev/null +++ b/src/cmd/cpp/tests/test11 @@ -0,0 +1,20 @@ +#define D1(s, ...) s +#define D2(s, ...) s D1(__VA_ARGS__) +#define D3(s, ...) s D2(__VA_ARGS__) +#define D4(s, ...) s D3(__VA_ARGS__) + +D1(a) +D2(a, b) +D3(a, b, c) +D4(a, b, c, d) + + +#define __sun_attr___noreturn__ __attribute__((__noreturn__)) +#define ___sun_attr_inner(__a) __sun_attr_##__a +#define __sun_attr__(__a) ___sun_attr_inner __a +#define __NORETURN __sun_attr__((__noreturn__)) +__NORETURN +#define X(...) +#define Y(...) 1 __VA_ARGS__ 2 +Y(X X() ()) + diff --git a/src/cmd/cpp/tests/test12 b/src/cmd/cpp/tests/test12 new file mode 100644 index 0000000..a0a36f1 --- /dev/null +++ b/src/cmd/cpp/tests/test12 @@ -0,0 +1,19 @@ +#define y 2 +#define fe(p) sfe(p) p +#define sfe(p) p +#define Y fe(y) y fe(y) + +Y; + +# define S2B_QMIN 0 +# define S2B_CMIN (S2B_QMIN + 8) +#define S2B_1(i) i, +#define S2B_2(i) S2B_1(i) S2B_1(i) +#define S2B_4(i) S2B_2(i) S2B_2(i) +#define S2B_8(i) S2B_4(i) S2B_4(i) +#define S2B_16(i) S2B_8(i) S2B_8(i) +#define S2B_32(i) S2B_16(i) S2B_16(i) +#define S2B_64(i) S2B_32(i) S2B_32(i) +#define S2B_128(i) S2B_64(i) S2B_64(i) +#define S2B_256(i) S2B_128(i) S2B_128(i) +S2B_256(S2B_CMIN + 0) diff --git a/src/cmd/cpp/tests/test13 b/src/cmd/cpp/tests/test13 new file mode 100644 index 0000000..51e2385 --- /dev/null +++ b/src/cmd/cpp/tests/test13 @@ -0,0 +1,11 @@ + +#define UL long, foo +#define D(I,F) I +#define E(I) D(I) +E(UL) + +#define FOO 1 + +#if (FOO == 1) + +#endif /* FOO */ diff --git a/src/cmd/cpp/token.c b/src/cmd/cpp/token.c index aeac691..e6e6d96 100644 --- a/src/cmd/cpp/token.c +++ b/src/cmd/cpp/token.c @@ -1,3 +1,5 @@ +/* $Id: token.c,v 1.48.2.2 2011/03/12 17:08:26 ragge Exp $ */ + /* * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved. * @@ -37,21 +39,24 @@ * - inch() is like inpch but \\n and trigraphs are expanded. * - unch() pushes back a character to the input stream. */ -#ifdef CROSS -# include -#else -# include -#endif + +#include "config.h" + #include +#include +#include +#ifdef HAVE_UNISTD_H #include +#endif #include #include +#include "compat.h" #include "cpp.h" #include "y.tab.h" static void cvtdig(int rad); -static int charcon(uchar *); +static int charcon(usch *); static void elsestmt(void); static void ifdefstmt(void); static void ifndefstmt(void); @@ -75,9 +80,8 @@ extern void yyset_lineno (int); static int inch(void); -size_t strlcat(char *dst, const char *src, size_t siz); - int inif; +extern int dflag; #define PUTCH(ch) if (!flslvl) putch(ch) /* protection against recursion in #include */ @@ -87,25 +91,16 @@ static int inclevel; /* get next character unaltered */ #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch()) -#ifdef YYTEXT_POINTER -static char buf[CPPBUF]; -char *yytext = buf; -#else -char yytext[CPPBUF]; -#endif +usch yytext[CPPBUF]; -#define C_SPEC 1 -#define C_EP 2 -#define C_ID 4 -#define C_I (C_SPEC|C_ID) -#define C_2 8 /* for yylex() tokenizing */ -static const char spechr[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, C_SPEC, 0, 0, 0, 0, 0, +char spechr[256] = { + 0, 0, 0, 0, C_SPEC, C_SPEC, 0, 0, + 0, C_WSNL, C_SPEC|C_WSNL, 0, + 0, C_WSNL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC, + C_WSNL, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC, 0, 0, 0, C_2, 0, C_2, 0, C_SPEC|C_2, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, 0, 0, C_2, C_2, C_2, C_SPEC, @@ -122,14 +117,55 @@ static const char spechr[256] = { }; +/* + * No-replacement array. If a macro is found and exists in this array + * then no replacement shall occur. This is a stack. + */ +struct symtab *norep[RECMAX]; /* Symbol table index table */ +int norepptr = 1; /* Top of index table */ +unsigned short bptr[RECMAX]; /* currently active noexpand macro stack */ +int bidx; /* Top of bptr stack */ + static void unch(int c) { - + --ifiles->curptr; if (ifiles->curptr < ifiles->bbuf) error("pushback buffer full"); - *ifiles->curptr = (uchar)c; + *ifiles->curptr = (usch)c; +} + +static int +eatcmnt(void) +{ + int ch; + + if (Cflag) { PUTCH('/'); PUTCH('*'); } + for (;;) { + ch = inch(); + if (ch == '\n') { + ifiles->lineno++; + PUTCH('\n'); + } + if (ch == -1) + return -1; + if (ch == '*') { + ch = inch(); + if (ch == '/') { + if (Cflag) { + PUTCH('*'); + PUTCH('/'); + } else + PUTCH(' '); + break; + } + unch(ch); + ch = '*'; + } + if (Cflag) PUTCH(ch); + } + return 0; } /* @@ -146,51 +182,38 @@ static void fastscan(void) { struct symtab *nl; - int ch, i; + int ch, i, ccnt/*, onemore*/; + usch *cp; goto run; for (;;) { ch = NXTCH(); xloop: if (ch == -1) return; + if (dflag>1) + printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@'); if ((spechr[ch] & C_SPEC) == 0) { PUTCH(ch); continue; } switch (ch) { + case EBLOCK: + case WARN: + case CONC: + error("bad char passed"); + break; + case '/': /* Comments */ if ((ch = inch()) == '/') { - if (Cflag) { PUTCH(ch); } else { PUTCH(' '); } +cppcmt: if (Cflag) { PUTCH(ch); } else { PUTCH(' '); } do { if (Cflag) PUTCH(ch); ch = inch(); } while (ch != -1 && ch != '\n'); goto xloop; } else if (ch == '*') { - if (Cflag) { PUTCH('/'); PUTCH('*'); } - for (;;) { - ch = inch(); - if (ch == '\n') { - ifiles->lineno++; - PUTCH('\n'); - } - if (ch == -1) - return; - if (ch == '*') { - ch = inch(); - if (ch == '/') { - if (Cflag) { - PUTCH('*'); - PUTCH('/'); - } else - PUTCH(' '); - break; - } - unch(ch); - ch = '*'; - } - if (Cflag) PUTCH(ch); - } + if (eatcmnt()) + return; } else { PUTCH('/'); goto xloop; @@ -213,11 +236,30 @@ xloop: if (ch == -1) goto xloop; case '\n': /* newlines, for pp directives */ - ifiles->lineno++; +run2: ifiles->lineno++; do { PUTCH(ch); run: ch = NXTCH(); + if (ch == '/') { + ch = NXTCH(); + if (ch == '/') + goto cppcmt; + if (ch == '*') { + if (eatcmnt()) + return; + goto run; + } + unch(ch); + ch = '/'; + } } while (ch == ' ' || ch == '\t'); + if (ch == '\\') { + ch = NXTCH(); + if (ch == '\n') + goto run2; + unch(ch); + ch = '\\'; + } if (ch == '#') { ppdir(); continue; @@ -236,7 +278,7 @@ run: ch = NXTCH(); case '\"': /* strings */ str: PUTCH(ch); while ((ch = inch()) != '\"') { - PUTCH(ch); + PUTCH(ch); if (ch == '\\') { ch = inch(); PUTCH(ch); @@ -257,7 +299,16 @@ str: PUTCH(ch); case '5': case '6': case '7': case '8': case '9': do { PUTCH(ch); - ch = NXTCH(); +nxt: ch = NXTCH(); + if (ch == '\\') { + ch = NXTCH(); + if (ch == '\n') { + goto nxt; + } else { + unch(ch); + ch = '\\'; + } + } if (spechr[ch] & C_EP) { PUTCH(ch); ch = NXTCH(); @@ -305,9 +356,9 @@ con: PUTCH(ch); ch = NXTCH(); goto xloop; } - i = 0; + /*onemore =*/ i = ccnt = 0; do { - yytext[i++] = (uchar)ch; + yytext[i++] = (usch)ch; ch = NXTCH(); if (ch == '\\') { ch = NXTCH(); @@ -322,14 +373,17 @@ con: PUTCH(ch); if (ch < 0) return; } while (spechr[ch] & C_ID); + yytext[i] = 0; unch(ch); - if ((nl = lookup((uchar *)yytext, FIND)) != 0) { - uchar *op = stringbuf; - putstr(gotident(nl)); - stringbuf = op; + + cp = stringbuf; + if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) { + putstr(stringbuf); } else - putstr((uchar *)yytext); + putstr((usch *)yytext); + stringbuf = cp; + break; } } @@ -344,7 +398,7 @@ sloscan() zagain: yyp = 0; ch = inch(); - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; switch (ch) { case -1: return 0; @@ -357,24 +411,24 @@ zagain: yyp = 0; break; - case '0': case '1': case '2': case '3': case '4': case '5': + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* readin a "pp-number" */ ppnum: for (;;) { ch = inch(); if (spechr[ch] & C_EP) { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; ch = inch(); if (ch == '-' || ch == '+') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; } else unch(ch); continue; } if ((spechr[ch] & C_ID) || ch == '.') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; continue; - } + } break; } unch(ch); @@ -383,11 +437,11 @@ ppnum: for (;;) { return NUMBER; case '\'': -chlit: +chlit: for (;;) { if ((ch = inch()) == '\\') { - yytext[yyp++] = (uchar)ch; - yytext[yyp++] = (uchar)inch(); + yytext[yyp++] = (usch)ch; + yytext[yyp++] = (usch)inch(); continue; } else if (ch == '\n') { /* not a constant */ @@ -396,7 +450,7 @@ chlit: ch = '\''; goto any; } else - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; if (ch == '\'') break; } @@ -407,7 +461,7 @@ chlit: case ' ': case '\t': while ((ch = inch()) == ' ' || ch == '\t') - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; unch(ch); yytext[yyp] = 0; return(WSPACE); @@ -415,7 +469,7 @@ chlit: case '/': if ((ch = inch()) == '/') { do { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; ch = inch(); } while (ch && ch != '\n'); yytext[yyp] = 0; @@ -435,7 +489,10 @@ chlit: more: while ((c = inch()) && c != '*') { if (c == '\n') putch(c), ifiles->lineno++; - else if (c == 1) /* WARN */ + else if (c == EBLOCK) { + (void)inch(); + (void)inch(); + } else if (c == 1) /* WARN */ wrn = 1; } if (c == 0) @@ -459,7 +516,7 @@ chlit: case '.': ch = inch(); if (isdigit(ch)) { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; goto ppnum; } else { unch(ch); @@ -468,14 +525,16 @@ chlit: goto any; case '\"': + if (tflag) + goto any; strng: for (;;) { if ((ch = inch()) == '\\') { - yytext[yyp++] = (uchar)ch; - yytext[yyp++] = (uchar)inch(); + yytext[yyp++] = (usch)ch; + yytext[yyp++] = (usch)inch(); continue; - } else - yytext[yyp++] = (uchar)ch; + } else + yytext[yyp++] = (usch)ch; if (ch == '\"') break; } @@ -483,26 +542,26 @@ chlit: return(STRING); case 'L': - if ((ch = inch()) == '\"') { - yytext[yyp++] = (uchar)ch; + if ((ch = inch()) == '\"' && !tflag) { + yytext[yyp++] = (usch)ch; goto strng; - } else if (ch == '\'') { - yytext[yyp++] = (uchar)ch; + } else if (ch == '\'' && !tflag) { + yytext[yyp++] = (usch)ch; goto chlit; } unch(ch); /* FALLTHROUGH */ /* Yetch, all identifiers */ - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': - case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': - case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': - case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': - case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': /* {L}({L}|{D})* */ @@ -510,7 +569,7 @@ chlit: for (;;) { /* get chars */ ch = inch(); if (isalpha(ch) || isdigit(ch) || ch == '_') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; } else { unch(ch); break; @@ -584,27 +643,31 @@ yylex() case NUMBER: if (yytext[0] == '\'') { yylval.node.op = NUMBER; - yylval.node.nd_val = charcon((uchar *)yytext); + yylval.node.nd_val = charcon((usch *)yytext); } else cvtdig(yytext[0] != '0' ? 10 : yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8); return NUMBER; case IDENT: - if (strcmp(yytext, "defined") == 0) { + if (strcmp((char *)yytext, "defined") == 0) { ifdef = 1; return DEFINED; } - nl = lookup((uchar *)yytext, FIND); + nl = lookup((usch *)yytext, FIND); if (ifdef) { yylval.node.nd_val = nl != NULL; ifdef = 0; } else if (nl && noex == 0) { - uchar *c, *och = stringbuf; + usch *och = stringbuf; + int i; - c = gotident(nl); - unch(1); - unpstr(c); + i = kfind(nl); + unch(WARN); + if (i) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = och; noex = 1; return yylex(); @@ -613,7 +676,7 @@ yylex() } yylval.node.op = NUMBER; return NUMBER; - case 1: /* WARN */ + case WARN: noex = 0; return yylex(); default: @@ -623,7 +686,7 @@ yylex() return ch; } -uchar *yyp, yybuf[CPPBUF]; +usch *yyp, yybuf[CPPBUF]; int yywrap(void); @@ -671,41 +734,6 @@ msdos: if ((c = inpch()) == '\n') { } } -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(initial dst) + strlen(src); if retval >= siz, - * truncation occurred. - */ -size_t -strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} - /* * Let the command-line args be faked defines at beginning of file. */ @@ -754,30 +782,29 @@ prinit(struct initar *it, struct includ *ic) * Return 0 on success, -1 if file to be included is not found. */ int -pushfile(const uchar *file, const uchar *fn, int idx, void *incs) +pushfile(const usch *file, const usch *fn, int idx, void *incs) { extern struct initar *initar; + struct includ ibuf; struct includ *ic; int otrulvl; - ic = malloc(sizeof(struct includ)); - if (ic == NULL) - error("out of memory for %s", file); + ic = &ibuf; ic->next = ifiles; if (file != NULL) { - ic->infil = open((const char *)file, O_RDONLY); - if (ic->infil < 0) { - free(ic); + if ((ic->infil = open((const char *)file, O_RDONLY)) < 0) return -1; - } ic->orgfn = ic->fname = file; if (++inclevel > MAX_INCLEVEL) error("Limit for nested includes exceeded"); } else { ic->infil = 0; - ic->orgfn = ic->fname = (const uchar *)""; + ic->orgfn = ic->fname = (const usch *)""; } +#ifndef BUF_STACK + ic->bbuf = malloc(BBUFSZ); +#endif ic->buffer = ic->bbuf+NAMEMAX; ic->curptr = ic->buffer; ifiles = ic; @@ -794,8 +821,7 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) prinit(initar, ic); initar = NULL; if (dMflag) - if (write(ofd, ic->buffer, strlen((char *)ic->buffer)) < 0) - /* ignore */; + write(ofd, ic->buffer, strlen((char *)ic->buffer)); fastscan(); prtline(); ic->infil = oin; @@ -808,9 +834,11 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) if (otrulvl != trulvl || flslvl) error("unterminated conditional"); +#ifndef BUF_STACK + free(ic->bbuf); +#endif ifiles = ic->next; close(ic->infil); - free(ic); inclevel--; return 0; } @@ -821,15 +849,14 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) void prtline() { - uchar *s, *os = stringbuf; + usch *s, *os = stringbuf; if (Mflag) { if (dMflag) return; /* no output */ if (ifiles->lineno == 1) { s = sheap("%s: %s\n", Mfile, ifiles->fname); - if (write(ofd, s, strlen((char *)s)) < 0) - /* ignore */; + write(ofd, s, strlen((char *)s)); } } else if (!Pflag) putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); @@ -840,8 +867,8 @@ void cunput(int c) { #ifdef CPP_DEBUG - extern int dflag; - if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c); +// extern int dflag; +// if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c); #endif #if 0 if (c == 10) { @@ -873,7 +900,7 @@ cvtdig(int rad) { unsigned long long rv = 0; unsigned long long rv2 = 0; - char *y = yytext; + usch *y = yytext; int c; c = *y++; @@ -900,7 +927,7 @@ cvtdig(int rad) } static int -charcon(uchar *p) +charcon(usch *p) { int val, c; @@ -993,8 +1020,8 @@ skpln(void) } static void -ifdefstmt(void) -{ +ifdefstmt(void) +{ int t; if (flslvl) { @@ -1006,7 +1033,7 @@ ifdefstmt(void) while (t == WSPACE); if (t != IDENT) error("bad ifdef"); - if (lookup((uchar *)yytext, FIND) == 0) { + if (lookup((usch *)yytext, FIND) == 0) { putch('\n'); flslvl++; } else @@ -1015,8 +1042,8 @@ ifdefstmt(void) } static void -ifndefstmt(void) -{ +ifndefstmt(void) +{ int t; if (flslvl) { @@ -1028,7 +1055,7 @@ ifndefstmt(void) while (t == WSPACE); if (t != IDENT) error("bad ifndef"); - if (lookup((uchar *)yytext, FIND) != 0) { + if (lookup((usch *)yytext, FIND) != 0) { putch('\n'); flslvl++; } else @@ -1037,7 +1064,7 @@ ifndefstmt(void) } static void -endifstmt(void) +endifstmt(void) { if (flslvl) { flslvl--; @@ -1094,11 +1121,11 @@ elifstmt(void) error("If-less elif"); } -static uchar * +static usch * svinp(void) { int c; - uchar *cp = stringbuf; + usch *cp = stringbuf; while ((c = inch()) && c != '\n') savch(c); @@ -1110,7 +1137,7 @@ svinp(void) static void cpperror(void) { - uchar *cp; + usch *cp; int c; if (flslvl) @@ -1128,7 +1155,7 @@ cpperror(void) static void cppwarning(void) { - uchar *cp; + usch *cp; int c; if (flslvl) @@ -1158,7 +1185,7 @@ undefstmt(void) if (sloscan() != WSPACE || sloscan() != IDENT) error("bad undef"); - if (flslvl == 0 && (np = lookup((uchar *)yytext, FIND))) + if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) np->value = 0; chknl(0); } @@ -1171,7 +1198,7 @@ pragmastmt(void) if (sloscan() != WSPACE) error("bad pragma"); if (!flslvl) - putstr((const uchar *)"#pragma "); + putstr((const usch *)"\n#pragma "); do { c = inch(); if (!flslvl) @@ -1265,7 +1292,7 @@ ppdir(void) goto out; /* something else, ignore */ i = 0; do { - bp[i++] = (uchar)ch; + bp[i++] = (usch)ch; if (i == sizeof(bp)-1) goto out; /* too long */ ch = inch(); diff --git a/src/cmd/emg/.gitignore b/src/cmd/emg/.gitignore new file mode 100644 index 0000000..19a9d31 --- /dev/null +++ b/src/cmd/emg/.gitignore @@ -0,0 +1 @@ +emg diff --git a/src/cmd/emg/ChangeLog b/src/cmd/emg/ChangeLog new file mode 100644 index 0000000..8c09437 --- /dev/null +++ b/src/cmd/emg/ChangeLog @@ -0,0 +1,53 @@ +ChangeLog +========= + +July 10, 2014 : emg 1.7 +----------------------- +Searching now correctly updates line number display. +Remove lots of rarely-used word functions. +Remove search+replace: sed(1) is quicker. +Reduce size of some static buffers. + +May 29, 2014 : emg 1.6 +---------------------- +emg is now part of the RetroBSD tree. +Add PgUp and PgDn scrolling. + +March 16, 2014 : emg 1.5 +------------------------ +Add line number to the mode line. +Implement prompted go to line function. +Remove lesser used expensive movement functions. +Documentation tweaks to reflect above changes. + +March 9, 2014 : emg 1.4 +----------------------- +Huge whitespace cleanup. +Make the window creation code mode consistent. +Small documentation fix. + +March 8, 2014 : emg 1.3 +----------------------- +Remove all OpenBSD support. emg is now for RetroBSD only. +Remove tmux alternative keybindings. +Revert Listbuffer command back to CTRL-x CTRL-b. + +December 2, 2013 : emg 1.2 +-------------------------- +Alternate keybindings for RetroBSD users using flow control terminal emulators. +Alternate keybindings for tmux users who are using the default control command. + +October 24, 2013 : emg 1.1 +-------------------------- +Listbuffer command is now CTRL-x l (originally CTRL-x CTRL-b). + This is because the default command keybinding of tmux is CTRL-b. +Search is now executed with instead of . + felt awkward, plus I don't search for newlines. +Lots of code cleanups (ttyio.c). + Removal of unused #if blocks. + Use panic() everywhere. + Fix all warnings from gcc -Wall. + +October 19, 2013 : emg 1.0 +-------------------------- +Initial version of emg. Current targets are OpenBSD and RetroBSD. diff --git a/src/cmd/emg/Makefile b/src/cmd/emg/Makefile new file mode 100644 index 0000000..87b5495 --- /dev/null +++ b/src/cmd/emg/Makefile @@ -0,0 +1,49 @@ +# emg Makefile +# for RetroBSD + +TOPSRC = $(shell cd ../../..; pwd) +include $(TOPSRC)/target.mk + +# Some basic CFLAGS. +CFLAGS = -Os -Wall -Werror + +# With the extra LDFLAGS, save some bytes. +CFLAGS += -ffunction-sections -fdata-sections + +# This reduces code size significantly. +CFLAGS += -mips16 + +# Set the screen size. +# Will default to FORCE_COLS=80 and FORCE_ROWS=24 +# if not set here. +#CFLAGS += -DFORCE_COLS=80 -DFORCE_ROWS=24 + +# with CFLAGS+= -ffunction-sections -fdata-sections +LDFLAGS += -Wl,--gc-sections + +LIBS = -ltermcap -lc + +MAN = emg.0 +MANSRC = emg.1 + +OBJS = basic.o buffer.o display.o file.o fileio.o line.o main.o \ + random.o region.o search.o tcap.o ttyio.o window.o word.o + +all: emg ${MAN} + +emg: ${OBJS} + ${CC} ${LDFLAGS} -o emg.elf ${OBJS} ${LIBS} + ${OBJDUMP} -S emg.elf > emg.dis + ${SIZE} emg.elf + ${ELF2AOUT} emg.elf $@ && rm emg.elf + +${MAN}: ${MANSRC} + ${MANROFF} ${MANSRC} > ${MAN} + +install: all + install emg ${DESTDIR}/bin/emg + cp ${MAN} ${DESTDIR}/share/man/cat1/ + cp -p emg.keys ${DESTDIR}/share/emg.keys + +clean: + rm -f *.o *~ *.core *.bak *.dis emg ${MAN} diff --git a/src/cmd/emg/README b/src/cmd/emg/README new file mode 100644 index 0000000..b6e1015 --- /dev/null +++ b/src/cmd/emg/README @@ -0,0 +1,41 @@ +emg +=== + +emg, or Ersatz Mg, is a very tiny Emacs-like text editor created by +combining elements of Ersatz Emacs and Mg (both the mg1a release and the +current OpenBSD-maintained version). + +The goal of this editor is to have something Emacs like for RetroBSD +(a release of 2.11BSD for PIC32 microcontrollers). After noticing that the +vi clone RetroBSD is using, VIrus, is GPL-licensed, I decided to provide +a better-licensed editor. I also decided that, as a vi user myself, it would +be easier to create an Emacs clone. Like you, I'm also unsure as to how that +conclusion was reached. + +I had initially tried to port Mg to RetroBSD but it was simply too large. +Ersatz Emacs does not build on RetroBSD, as RetroBSD is missing some functions +that Ersatz Emacs requires. It made sense to try to take from each and create +an editor that would work. + +In a way, emg has a double meaning: not only is it a combination of +the two programs that comprise it, it is also a substitute Mg after my initial +port failed. + +I have cleaned up some code where necessary; emg builds without errors on +RetroBSD. + +Patches are also very welcome. I ask that you keep in mind the resource +constraints of RetroBSD: everything must fit in 96K RAM. But of course, +smaller is better. + +I've left Chris Baird's Ersatz Emacs README here so others can better +appreciate the history of this software. + +As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain. + +Versions of emg up to and including 1.2 also supported OpenBSD; OpenBSD +has since dropped the older headers, such as sgtty.h, and it is not worth +reimplementing these for OpenBSD since OpenBSD maintains Mg. + +==================================== +Brian Callahan diff --git a/src/cmd/emg/README-ERSATZ b/src/cmd/emg/README-ERSATZ new file mode 100644 index 0000000..381b816 --- /dev/null +++ b/src/cmd/emg/README-ERSATZ @@ -0,0 +1,39 @@ +This shar file contains the source to a microemacs-derived text editor +that I have been personally hacking on for over a decade. + +Originally this was MicroEMACS 3.6 as released to mod.sources and the +Public Domain by Daniel Lawrence in 1986, and was itself based on the +work of Steve Wilhite and George Jones to MicroEMACS 2.0 (then also +public domain) by Dave Conroy. I would like to reiterate Lawrence's +thanks to them for writing such nice, well structured and documented +code. + +"Ersatz-Emacs", as I call it today, is the above text editor throughly +cleansed of routines and features that I personally never use. It is +also an editor MINIX-creator Andy Tanenbaum could describe as "fitting +inside a student's brain" (namely, mine). + +This source code should compile cleanly on any "modern" UN*X system +with a termcap/curses library. This release has been tested with +NetBSD and various Linux systems, although in the past when it was +still mostly MicroEMACS, proto-Ersatz-Emacs was an editor of choice on +SunOS, Solaris, Xenix, Minix/i386, and AIX. Supporting these and +similar systems should not be difficult. + +I encourage people to personalise this very simple editor to their own +requirements. Please send any useful bug reports and fixes back to me, +but I'm not really interested in incorporating new features unless it +simplifies the program further. Feel free to do a code-fork and +distribute your own perfect text editor. + +The title "Ersatz" comes from the category Richard Stallman uses in +MIT AI Memo 519a to describe those editors that are a surface-deep +imitation (key bindings) of "real" ITS Emacs. If you are familiar with +any Emacs-variant editor, you should have few problems with Ersatz. + +All source code of this program is in the Public Domain. I am a rabid +Stallmanite weenie, but it would be improper to publish this under a +different licence than it was given to me with. + +-- +Chris Baird,, diff --git a/src/cmd/emg/basic.c b/src/cmd/emg/basic.c new file mode 100644 index 0000000..c3e86f7 --- /dev/null +++ b/src/cmd/emg/basic.c @@ -0,0 +1,289 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file move the cursor around on the screen. They + * compute a new value for the cursor, then adjust ".". The display code + * always updates the cursor location, so only moves between lines, or + * functions that adjust the top line in the window and invalidate the + * framing, are hard. + */ + +#include /* atoi(3), ugh */ +#include "estruct.h" +#include "edef.h" + +extern int getccol(int bflg); +extern void mlwrite(); +extern int mlreplyt(); + +int forwchar(int f, int n); +int backchar(int f, int n); +int forwline(int f, int n); +int backline(int f, int n); +int pagedown(int f, int n); +int pageup(int f, int n); + +/* + * This routine, given a pointer to a LINE, and the current cursor goal + * column, return the best choice for the offset. The offset is returned. + * Used by "C-N" and "C-P". + */ +long getgoal(LINE *dlp) +{ + int col = 0; + int dbo = 0; + int newcol, c; + + while (dbo != llength(dlp)) + { + c = lgetc(dlp, dbo); + newcol = col; + if (c == '\t') + newcol |= 0x07; + else if (c < 0x20 || c == 0x7F) + ++newcol; + ++newcol; + if (newcol > curgoal) + break; + col = newcol; + ++dbo; + } + return (dbo); +} + +/* + * Move the cursor to the + * beginning of the current line. + * Trivial. + */ +/* ARGSUSED0 */ +int gotobol(int f, int n) +{ + curwp->w_doto = 0; + return (TRUE); +} + +/* + * Move the cursor to the end of the current line. Trivial. No errors. + */ +/* ARGSUSED0 */ +int gotoeol(int f, int n) +{ + curwp->w_doto = llength(curwp->w_dotp); + return (TRUE); +} + +/* + * Move the cursor backwards by "n" characters. If "n" is less than zero call + * "forwchar" to actually do the move. Otherwise compute the new cursor + * location. Error if you try and move out of the buffer. Set the flag if the + * line pointer for dot changes. + */ +int backchar(int f, int n) +{ + LINE *lp; + + if (n < 0) + return (forwchar(f, -n)); + while (n--) + { + if (curwp->w_doto == 0) + { + if ((lp = lback(curwp->w_dotp)) == curbp->b_linep) + return (FALSE); + curwp->w_dotp = lp; + curwp->w_doto = llength(lp); + curwp->w_flag |= WFMOVE; + curwp->w_dotline--; + } + else + curwp->w_doto--; + } + return (TRUE); +} + +/* + * Move the cursor forwards by "n" characters. If "n" is less than zero call + * "backchar" to actually do the move. Otherwise compute the new cursor + * location, and move ".". Error if you try and move off the end of the + * buffer. Set the flag if the line pointer for dot changes. + */ +int forwchar(int f, int n) +{ + if (n < 0) + return (backchar(f, -n)); + while (n--) + { + if (curwp->w_doto == llength(curwp->w_dotp)) + { + if (curwp->w_dotp == curbp->b_linep) + return (FALSE); + curwp->w_dotp = lforw(curwp->w_dotp); + curwp->w_doto = 0; + curwp->w_flag |= WFMOVE; + curwp->w_dotline++; + } + else + curwp->w_doto++; + } + return (TRUE); +} + +/* + * move to a particular line. argument (n) must be a positive integer for this + * to actually do anything + */ +int gotoline(int f, int n) +{ + if ((n < 1) || (n > curwp->w_bufp->b_lines)) /* if a bogus argument...then leave */ + return (FALSE); /* but we should never get here */ + + /* first, we go to the start of the buffer */ + curwp->w_dotp = lforw(curbp->b_linep); + curwp->w_doto = 0; + curwp->w_dotline = 0; /* and reset the line number */ + return (forwline(f, n - 1)); +} + +/* + * Prompt for which line number we want to go to, then execute gotoline() + * with that number as its argument. + * + * Make sure the bounds are within the file. + * + * Bound to M-G + */ +int setline(int f, int n) +{ + char setl[6]; + int l; + + (void)mlreplyt("Go to line: ", setl, 6, 10); + l = atoi(setl); /* XXX: This sucks! */ + + if (l < 1) + l = 1; + else if (l > curwp->w_bufp->b_lines) + l = curwp->w_bufp->b_lines; + + gotoline(f, l); + return (TRUE); +} + +/* + * Goto the beginning of the buffer. Massive adjustment of dot. This is + * considered to be hard motion; it really isn't if the original value of dot + * is the same as the new value of dot. Normally bound to "M-<". + */ +/* ARGSUSED0 */ +int gotobob(int f, int n) +{ + curwp->w_dotp = lforw(curbp->b_linep); + curwp->w_doto = 0; + curwp->w_flag |= WFHARD; + curwp->w_dotline = 0; + return (TRUE); +} + +/* + * Move to the end of the buffer. Dot is always put at the end of the file + * (ZJ). The standard screen code does most of the hard parts of update. + * Bound to "M->". + */ +/* ARGSUSED0 */ +int gotoeob(int f, int n) +{ + curwp->w_dotp = curbp->b_linep; + curwp->w_doto = 0; + curwp->w_flag |= WFHARD; + curwp->w_dotline = curwp->w_bufp->b_lines; + return (TRUE); +} + +/* + * Move forward by full lines. If the number of lines to move is less than + * zero, call the backward line function to actually do it. The last command + * controls how the goal column is set. Bound to "C-N". No errors are possible. + */ +int forwline(int f, int n) +{ + LINE *dlp; + + if (n < 0) + return (backline(f, -n)); + if ((lastflag & CFCPCN) == 0)/* Reset goal if last */ + curgoal = getccol(FALSE); /* not C-P or C-N */ + thisflag |= CFCPCN; + dlp = curwp->w_dotp; + while (n-- && dlp != curbp->b_linep) + { + dlp = lforw(dlp); + curwp->w_dotline++; + } + curwp->w_dotp = dlp; + curwp->w_doto = getgoal(dlp); + curwp->w_flag |= WFMOVE; + return (TRUE); +} + +/* + * This function is like "forwline", but goes backwards. The scheme is exactly + * the same. Check for arguments that are less than zero and call your + * alternate. Figure out the new line and call "movedot" to perform the + * motion. No errors are possible. Bound to "C-P". + */ +int backline(int f, int n) +{ + LINE *dlp; + + if (n < 0) + return (forwline(f, -n)); + if ((lastflag & CFCPCN) == 0)/* Reset goal if the */ + curgoal = getccol(FALSE); /* last isn't C-P, C-N */ + thisflag |= CFCPCN; + dlp = curwp->w_dotp; + while (n-- && lback(dlp) != curbp->b_linep) + { + dlp = lback(dlp); + curwp->w_dotline--; + } + curwp->w_dotp = dlp; + curwp->w_doto = getgoal(dlp); + curwp->w_flag |= WFMOVE; + return (TRUE); +} + +/* + * PgDn. Scroll down (FORCE_ROWS - 1). + * Just forwline(f, (FORCE_ROWS -1)) + * Bound to C-V + */ +int pagedown(int f, int n) +{ + forwline(f, (FORCE_ROWS - 1)); + return (TRUE); +} + +/* + * PgUp. Scroll up (FORCE_ROWS - 1). + * Just backline(f, (FORCE_ROWS -1)) + * Bound to M-V + */ +int pageup(int f, int n) +{ + backline(f, (FORCE_ROWS - 1)); + return (TRUE); +} + +/* + * Set the mark in the current window to the value of "." in the window. No + * errors are possible. Bound to "M-.". + */ +/* ARGSUSED0 */ +int setmark(int f, int n) +{ + curwp->w_markp = curwp->w_dotp; + curwp->w_marko = curwp->w_doto; + mlwrite("[Mark set]"); + return (TRUE); +} diff --git a/src/cmd/emg/buffer.c b/src/cmd/emg/buffer.c new file mode 100644 index 0000000..ac49d40 --- /dev/null +++ b/src/cmd/emg/buffer.c @@ -0,0 +1,494 @@ +/* This file is in the public domain. */ + +/* + * Buffer management. Some of the functions are internal, and some are actually + * attached to user keys. Like everyone else, they set hints for the display + * system. + */ + +#include /* free(3), malloc(3) */ +#include /* strncpy(3) */ +#include "estruct.h" +#include "edef.h" + +extern int mlreply(char *prompt, char *buf, int nbuf); +extern int readin(char fname[]); +extern void mlwrite(); +extern void mlerase(); +extern int mlyesno(char *prompt); +extern void lfree(LINE *lp); +extern WINDOW *wpopup(); +extern LINE *lalloc(); + +int swbuffer(BUFFER *bp); +int usebuffer(int f, int n); +int nextbuffer(int f, int n); +int killbuffer(int f, int n); +int zotbuf(BUFFER *bp); +int namebuffer(int f, int n); +int listbuffers(int f, int n); +int makelist(); +void itoa(char buf[], int width, int num); +int addline(char *text); +int anycb(); +BUFFER* bfind(char *bname, int cflag, int bflag); +int bclear(BUFFER *bp); + +/* + * make buffer BP current + */ +int swbuffer(BUFFER *bp) +{ + WINDOW *wp; + + if (--curbp->b_nwnd == 0) + { /* Last use. */ + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curwp->w_doto; + curbp->b_markp = curwp->w_markp; + curbp->b_marko = curwp->w_marko; + } + curbp = bp; /* Switch. */ + if (curbp->b_active != TRUE) + { /* buffer not active yet */ + /* read it in and activate it */ + readin(curbp->b_fname); + curbp->b_dotp = lforw(curbp->b_linep); + curbp->b_doto = 0; + curbp->b_active = TRUE; + } + curwp->w_bufp = bp; + curwp->w_linep = bp->b_linep; /* For macros, ignored */ + curwp->w_flag |= WFMODE | WFFORCE | WFHARD; /* Quite nasty */ + if (bp->b_nwnd++ == 0) + { /* First use */ + curwp->w_dotp = bp->b_dotp; + curwp->w_doto = bp->b_doto; + curwp->w_markp = bp->b_markp; + curwp->w_marko = bp->b_marko; + return (TRUE); + } + wp = wheadp; /* Look for old */ + while (wp != 0) + { + if (wp != curwp && wp->w_bufp == bp) + { + curwp->w_dotp = wp->w_dotp; + curwp->w_doto = wp->w_doto; + curwp->w_markp = wp->w_markp; + curwp->w_marko = wp->w_marko; + break; + } + wp = wp->w_wndp; + } + return (TRUE); +} + +/* + * Attach a buffer to a window. The values of dot and mark come from the buffer + * if the use count is 0. Otherwise, they come from some other window. + */ +/* ARGSUSED0 */ +int usebuffer(int f, int n) +{ + BUFFER *bp; + char bufn[NBUFN]; + int s; + + if ((s = mlreply("Use buffer: ", bufn, NBUFN)) != TRUE) + return (s); + if ((bp = bfind(bufn, TRUE, 0)) == NULL) + return (FALSE); + return (swbuffer(bp)); +} + +/* switch to the next buffer in the buffer list + */ +/* ARGSUSED0 */ +int nextbuffer(int f, int n) +{ + BUFFER *bp; + + bp = curbp->b_bufp; + /* cycle through the buffers to find an eligable one */ + while ((bp == NULL) || (bp->b_flag & BFTEMP)) + { + if (bp == NULL) + bp = bheadp; + else + bp = bp->b_bufp; + } + return (swbuffer(bp)); +} + +/* + * Dispose of a buffer, by name. Ask for the name. Look it up (don't get too + * upset if it isn't there at all!). Get quite upset if the buffer is being + * displayed. Clear the buffer (ask if the buffer has been changed). Then free + * the header line and the buffer header. Bound to "C-X K". + */ +/* ARGSUSED0 */ +int killbuffer(int f, int n) +{ + BUFFER *bp; + char bufn[NBUFN]; + int s; + + if ((s = mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE) + return (s); + if ((bp = bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown */ + return (TRUE); + return (zotbuf(bp)); +} + +/* kill the buffer pointed to by bp */ +int zotbuf(BUFFER *bp) +{ + BUFFER *bp1, *bp2; + int s; + + if (bp->b_nwnd != 0) + { /* Error if on screen */ + mlwrite("Buffer is being displayed"); + return (FALSE); + } + if ((s = bclear(bp)) != TRUE) /* Blow text away */ + return (s); + free (bp->b_linep); /* Release header line */ + bp1 = 0; /* Find the header */ + bp2 = bheadp; + while (bp2 != bp) + { + bp1 = bp2; + bp2 = bp2->b_bufp; + } + bp2 = bp2->b_bufp; /* Next one in chain */ + if (bp1 == NULL) /* Unlink it */ + bheadp = bp2; + else + bp1->b_bufp = bp2; + free(bp); /* Release buffer block */ + return (TRUE); +} + +/* Rename the current buffer */ +/* ARGSUSED0 */ +int namebuffer(int f, int n) +{ + BUFFER *bp; /* pointer to scan through all buffers */ + char bufn[NBUFN]; /* buffer to hold buffer name */ + + /* prompt for and get the new buffer name */ + ask: + if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE) + return (FALSE); + + /* and check for duplicates */ + bp = bheadp; + while (bp != 0) + { + if (bp != curbp) + { + /* if the names the same */ + if (strcmp(bufn, bp->b_bname) == 0) + goto ask; /* try again */ + } + bp = bp->b_bufp; /* onward */ + } + + strncpy(curbp->b_bname, bufn, NBUFN); /* copy buffer name to structure */ + curwp->w_flag |= WFMODE; /* make mode line replot */ + mlerase(); + return (TRUE); +} + +/* + * List all of the active buffers. First update the special buffer that holds + * the list. Next make sure at least 1 window is displaying the buffer list, + * splitting the screen if this is what it takes. Lastly, repaint all of the + * windows that are displaying the list. Bound to "C-X C-B". + */ +/* ARGSUSED0 */ +int listbuffers(int f, int n) +{ + WINDOW *wp; + BUFFER *bp; + int s; + + if ((s = makelist()) != TRUE) + return (s); + if (blistp->b_nwnd == 0) + { /* Not on screen yet */ + if ((wp = wpopup()) == NULL) + return (FALSE); + bp = wp->w_bufp; + if (--bp->b_nwnd == 0) + { + bp->b_dotp = wp->w_dotp; + bp->b_doto = wp->w_doto; + bp->b_markp = wp->w_markp; + bp->b_marko = wp->w_marko; + } + wp->w_bufp = blistp; + ++blistp->b_nwnd; + } + wp = wheadp; + while (wp != 0) + { + if (wp->w_bufp == blistp) + { + wp->w_linep = lforw(blistp->b_linep); + wp->w_dotp = lforw(blistp->b_linep); + wp->w_doto = 0; + wp->w_markp = 0; + wp->w_marko = 0; + wp->w_flag |= WFMODE | WFHARD; + } + wp = wp->w_wndp; + } + return (TRUE); +} + +/* + * This routine rebuilds the text in the special secret buffer that holds the + * buffer list. It is called by the list buffers command. Return TRUE if + * everything works. Return FALSE if there is an error (if there is no + * memory). + */ +int makelist() +{ + BUFFER *bp; + LINE *lp; + char *cp1, *cp2; + char b[7], line[128]; + int nbytes, s, c; + + blistp->b_flag &= ~BFCHG; /* Don't complain! */ + if ((s = bclear(blistp)) != TRUE) /* Blow old text away */ + return (s); + strncpy (blistp->b_fname, "", 1); + if (addline("AC Size Buffer File") == FALSE || + addline("-- ------- ------ ----") == FALSE) + return (FALSE); + bp = bheadp; + + /* build line to report global mode settings */ + cp1 = &line[0]; + *cp1++ = ' '; + *cp1++ = ' '; + *cp1++ = ' '; + + /* output the list of buffers */ + while (bp != 0) + { + if ((bp->b_flag & BFTEMP) != 0) + { /* Skip magic ones */ + bp = bp->b_bufp; + continue; + } + cp1 = &line[0]; /* Start at left edge */ + + /* output status of ACTIVE flag (has the file been read in? */ + if (bp->b_active == TRUE) /* "@" if activated */ + *cp1++ = '@'; + else + *cp1++ = ' '; + + /* output status of changed flag */ + if ((bp->b_flag & BFCHG) != 0) /* "*" if changed */ + *cp1++ = '*'; + else + *cp1++ = ' '; + *cp1++ = ' '; /* Gap */ + + nbytes = 0; /* Count bytes in buf */ + lp = lforw(bp->b_linep); + while (lp != bp->b_linep) + { + nbytes += llength(lp) + 1; + lp = lforw(lp); + } + itoa(b, 6, nbytes); /* 6 digit buffer size */ + cp2 = &b[0]; + while ((c = *cp2++) != 0) + *cp1++ = (char)c; + *cp1++ = ' '; /* Gap */ + cp2 = &bp->b_bname[0]; /* Buffer name */ + while ((c = *cp2++) != 0) + *cp1++ = (char)c; + cp2 = &bp->b_fname[0]; /* File name */ + if (*cp2 != 0) + { + while (cp1 < &line[2 + 1 + 5 + 1 + 6 + 1 + NBUFN]) /* XXX ??? */ + *cp1++ = ' '; + while ((c = *cp2++) != 0) + { + if (cp1 < &line[128 - 1]) + *cp1++ = (char)c; + } + } + *cp1 = 0; /* Add to the buffer */ + if (addline(line) == FALSE) + return (FALSE); + bp = bp->b_bufp; + } + return (TRUE); /* All done */ +} + +void itoa(char buf[], int width, int num) +{ + buf[width] = 0; /* End of string */ + while (num >= 10) + { /* Conditional digits */ + buf[--width] = (char)((num % 10) + '0'); + num /= 10; + } + buf[--width] = (char)(num + '0'); /* Always 1 digit */ + while (width != 0) /* Pad with blanks */ + buf[--width] = ' '; +} + +/* + * The argument "text" points to a string. Append this line to the buffer list + * buffer. Handcraft the EOL on the end. Return TRUE if it worked and FALSE if + * you ran out of room. + */ +int addline(char *text) +{ + LINE *lp; + int ntext, i; + + ntext = strlen(text); + if ((lp = lalloc(ntext)) == NULL) + return (FALSE); + for (i = 0; i < ntext; ++i) + lputc(lp, i, text[i]); + blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */ + lp->l_bp = blistp->b_linep->l_bp; + blistp->b_linep->l_bp = lp; + lp->l_fp = blistp->b_linep; + if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */ + blistp->b_dotp = lp; /* move it to new line */ + return (TRUE); +} + +/* + * Look through the list of buffers. Return TRUE if there are any changed + * buffers. Buffers that hold magic internal stuff are not considered; who + * cares if the list of buffer names is hacked. Return FALSE if no buffers + * have been changed. + */ +int anycb() +{ + BUFFER *bp; + + bp = bheadp; + while (bp != NULL) + { + if ((bp->b_flag & BFTEMP) == 0 && (bp->b_flag & BFCHG) != 0) + return (TRUE); + bp = bp->b_bufp; + } + return (FALSE); +} + +/* + * Find a buffer, by name. Return a pointer to the BUFFER structure associated + * with it. If the named buffer is found, but is a TEMP buffer (like the + * buffer list) conplain. If the buffer is not found and the "cflag" is TRUE, + * create it. The "bflag" is the settings for the flags in in buffer. + */ +BUFFER* bfind(char *bname, int cflag, int bflag) +{ + BUFFER *bp, *sb; + LINE *lp; + + bp = bheadp; + while (bp != 0) + { + if (strcmp(bname, bp->b_bname) == 0) + { + if ((bp->b_flag & BFTEMP) != 0) + { + mlwrite ("Cannot select builtin buffer"); + return (0); + } + return (bp); + } + bp = bp->b_bufp; + } + if (cflag != FALSE) + { + if ((bp = (BUFFER *) malloc(sizeof(BUFFER))) == NULL) + return (0); + if ((lp = lalloc(0)) == NULL) + { + free(bp); + return (BUFFER*)0; + } + /* find the place in the list to insert this buffer */ + if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) + { + /* insert at the begining */ + bp->b_bufp = bheadp; + bheadp = bp; + } + else + { + sb = bheadp; + while (sb->b_bufp != 0) + { + if (strcmp(sb->b_bufp->b_bname, bname) > 0) + break; + sb = sb->b_bufp; + } + + /* and insert it */ + bp->b_bufp = sb->b_bufp; + sb->b_bufp = bp; + } + + /* and set up the other buffer fields */ + bp->b_active = TRUE; + bp->b_dotp = lp; + bp->b_doto = 0; + bp->b_markp = 0; + bp->b_marko = 0; + bp->b_flag = (char)bflag; + bp->b_nwnd = 0; + bp->b_linep = lp; + bp->b_lines = 1; + strncpy(bp->b_fname, "", 1); + strncpy(bp->b_bname, bname, NBUFN); + lp->l_fp = lp; + lp->l_bp = lp; + } + return (bp); +} + +/* + * This routine blows away all of the text in a buffer. If the buffer is + * marked as changed then we ask if it is ok to blow it away; this is to save + * the user the grief of losing text. The window chain is nearly always wrong + * if this gets called; the caller must arrange for the updates that are + * required. Return TRUE if everything looks good. + */ +int bclear(BUFFER *bp) +{ + LINE *lp; + int s; + + if ((bp->b_flag & BFTEMP) == 0 /* Not scratch buffer */ + && (bp->b_flag & BFCHG) != 0 /* Something changed */ + && (s = mlyesno("Discard changes")) != TRUE) + return (s); + bp->b_flag &= ~BFCHG; /* Not changed */ + while ((lp = lforw(bp->b_linep)) != bp->b_linep) + lfree(lp); + bp->b_dotp = bp->b_linep; /* Fix "." */ + bp->b_doto = 0; + bp->b_markp = 0; /* Invalidate "mark" */ + bp->b_marko = 0; + bp->b_lines = 1; + return (TRUE); +} diff --git a/src/cmd/emg/display.c b/src/cmd/emg/display.c new file mode 100644 index 0000000..adb36c9 --- /dev/null +++ b/src/cmd/emg/display.c @@ -0,0 +1,1015 @@ +/* This file is in the public domain. */ + +/* + * The functions in this file handle redisplay. There are two halves, the ones + * that update the virtual display screen, and the ones that make the physical + * display screen the same as the virtual display screen. These functions use + * hints that are left in the windows by the commands + */ + +#include +#include +#include +#include "estruct.h" +#include "edef.h" + +extern int typeahead(); +extern int ctrlg(); +extern int getccol(); + +void movecursor(int row, int col); +void mlerase(); +void vtinit(); +void vttidy(); +void vtmove(int row, int col); +void vtputc(int c); +void vtpute(int c); +int vtputs(const char *s); +void vteeol(); +void update(); +void updext(); +void updateline(int row, char vline[], char pline[], short *flags); +void modeline(WINDOW *wp); +void upmode(); +int mlyesno(char *prompt); +int mlreplyt(char *prompt, char *buf, int nbuf, char eolchar); +int mlreply(char *prompt, char *buf, int nbuf); +void mlwrite(); +void mlputs(char *s); +void mlputi(int i, int r); +void mlputli(long l, int r); + +typedef struct VIDEO { + short v_flag; /* Flags */ + char v_text[1]; /* Screen data */ +} VIDEO; + +#define VFCHG 0x0001 /* Changed flag */ +#define VFEXT 0x0002 /* extended (beyond column 80) */ +#define VFREV 0x0004 /* reverse video status */ +#define VFREQ 0x0008 /* reverse video request */ + +int vtrow = 0; /* Row location of SW cursor */ +int vtcol = 0; /* Column location of SW cursor */ +int ttrow = HUGE; /* Row location of HW cursor */ +int ttcol = HUGE; /* Column location of HW cursor */ +int lbound = 0; /* leftmost column of line being displayed */ + +VIDEO **vscreen; /* Virtual screen */ +VIDEO **pscreen; /* Physical screen */ + +/* + * Send a command to the terminal to move the hardware cursor to row "row" and + * column "col". The row and column arguments are origin 0. Optimize out + * random calls. Update "ttrow" and "ttcol". + */ +void movecursor(int row, int col) +{ + if (row != ttrow || col != ttcol) + { + ttrow = row; + ttcol = col; + (*term.t_move) (row, col); + } +} + +/* + * Erase the message line. This is a special routine because the message line + * is not considered to be part of the virtual screen. It always works + * immediately; the terminal buffer is flushed via a call to the flusher. + */ +void mlerase() +{ + int i; + + movecursor(term.t_nrow, 0); + if (eolexist == TRUE) + (*term.t_eeol) (); + else + { + for (i = 0; i < term.t_ncol - 1; i++) + (*term.t_putchar) (' '); + movecursor(term.t_nrow, 1); /* force the move! */ + movecursor(term.t_nrow, 0); + } + (*term.t_flush) (); + mpresf = FALSE; +} + +/* + * Initialize the data structures used by the display code. The edge vectors + * used to access the screens are set up. The operating system's terminal I/O + * channel is set up. All the other things get initialized at compile time. + * The original window has "WFCHG" set, so that it will get completely redrawn + * on the first call to "update". + */ +void vtinit() +{ + int i; + VIDEO *vp; + + (*term.t_open) (); + (*term.t_rev) (FALSE); + vscreen = (VIDEO **) malloc(term.t_nrow * sizeof(VIDEO *)); + + if (vscreen == NULL) + exit (1); + + pscreen = (VIDEO **) malloc(term.t_nrow * sizeof(VIDEO *)); + + if (pscreen == NULL) + exit (1); + + for (i = 0; i < term.t_nrow; ++i) + { + vp = (VIDEO *) malloc(sizeof(VIDEO) + term.t_ncol); + + if (vp == NULL) + exit (1); + + vp->v_flag = 0; + vscreen[i] = vp; + vp = (VIDEO *) malloc(sizeof(VIDEO) + term.t_ncol); + + if (vp == NULL) + exit (1); + + vp->v_flag = 0; + pscreen[i] = vp; + } +} + +/* + * Clean up the virtual terminal system, in anticipation for a return to the + * operating system. Move down to the last line and clear it out (the next + * system prompt will be written in the line). Shut down the channel to the + * terminal. + */ +void vttidy() +{ + mlerase(); + movecursor(term.t_nrow, 0); + (*term.t_close) (); +} + +/* + * Set the virtual cursor to the specified row and column on the virtual + * screen. There is no checking for nonsense values; this might be a good idea + * during the early stages. + */ +void vtmove(int row, int col) +{ + vtrow = row; + vtcol = col; +} + +/* + * Write a character to the virtual screen. The virtual row and column are + * updated. If the line is too long put a "$" in the last column. This routine + * only puts printing characters into the virtual terminal buffers. Only + * column overflow is checked. + */ +void vtputc(int c) +{ + VIDEO *vp; + + vp = vscreen[vtrow]; + + if (vtcol >= term.t_ncol) + { + vtcol = (vtcol + 0x07) & ~0x07; + vp->v_text[term.t_ncol - 1] = '$'; + } + else if (c == '\t') + { + do + { + vtputc(' '); + } + while ((vtcol & 0x07) != 0); + } + else if (c < 0x20 || c == 0x7F) + { + vtputc('^'); + vtputc(c ^ 0x40); + } + else + vp->v_text[vtcol++] = c; +} + +/* put a character to the virtual screen in an extended line. If we are not + * yet on left edge, don't print it yet. check for overflow on the right + * margin + */ +void vtpute(int c) +{ + VIDEO *vp; + + vp = vscreen[vtrow]; + + if (vtcol >= term.t_ncol) + { + vtcol = (vtcol + 0x07) & ~0x07; + vp->v_text[term.t_ncol - 1] = '$'; + } + else if (c == '\t') + { + do + { + vtpute(' '); + } + while (((vtcol + lbound) & 0x07) != 0); + } + else if (c < 0x20 || c == 0x7F) + { + vtpute('^'); + vtpute(c ^ 0x40); + } + else + { + if (vtcol >= 0) + vp->v_text[vtcol] = c; + ++vtcol; + } +} + +/* + * Output a string to the mode line, report how long it was. + * From OpenBSD mg. + */ +int vtputs(const char *s) +{ + int n = 0; + + while (*s != '\0') { + vtputc(*s++); + ++n; + } + return (n); +} + +/* + * [In the virtual screen] Erase from the end of the software cursor to the + * end of the line on which the software cursor is located. + */ +void vteeol() +{ + VIDEO *vp; + + vp = vscreen[vtrow]; + while (vtcol < term.t_ncol) + vp->v_text[vtcol++] = ' '; +} + +/* + * Make sure that the display is right. This is a three part process. First, + * scan through all of the windows looking for dirty ones. Check the framing, + * and refresh the screen. Second, make sure that "currow" and "curcol" are + * correct for the current window. Third, make the virtual and physical + * screens the same + */ +void update() +{ + VIDEO *vp1, *vp2; + LINE *lp; + WINDOW *wp; + int i, j, c; + + if (typeahead()) + return; + + /* update the reverse video flags for any mode lines out there */ + for (i = 0; i < term.t_nrow; ++i) + vscreen[i]->v_flag &= ~VFREQ; + + wp = wheadp; + while (wp != NULL) + { + vscreen[wp->w_toprow + wp->w_ntrows]->v_flag |= VFREQ; + wp = wp->w_wndp; + } + + wp = wheadp; + while (wp != NULL) + { + /* Look at any window with update flags set on */ + if (wp->w_flag != 0) + { + /* If not force reframe, check the framing */ + if ((wp->w_flag & WFFORCE) == 0) + { + lp = wp->w_linep; + for (i = 0; i < wp->w_ntrows; ++i) + { + if (lp == wp->w_dotp) + goto out; + if (lp == wp->w_bufp->b_linep) + break; + lp = lforw(lp); + } + } + /* Not acceptable, better compute a new value for the line at the top + * of the window. Then set the "WFHARD" flag to force full redraw */ + i = wp->w_force; + if (i > 0) + { + --i; + if (i >= wp->w_ntrows) + i = wp->w_ntrows - 1; + } + else if (i < 0) + { + i += wp->w_ntrows; + if (i < 0) + i = 0; + } + else + i = wp->w_ntrows / 2; + lp = wp->w_dotp; + while (i != 0 && lback(lp) != wp->w_bufp->b_linep) + { + --i; + lp = lback(lp); + } + wp->w_linep = lp; + wp->w_flag |= WFHARD; /* Force full */ + + out: + /* Try to use reduced update. Mode line update has its own special + * flag. The fast update is used if the only thing to do is within + * the line editing */ + lp = wp->w_linep; + i = wp->w_toprow; + if ((wp->w_flag & ~WFMODE) == WFEDIT) + { + while (lp != wp->w_dotp) + { + ++i; + lp = lforw(lp); + } + vscreen[i]->v_flag |= VFCHG; + vtmove(i, 0); + for (j = 0; j < llength(lp); ++j) + vtputc(lgetc(lp, j)); + vteeol(); + } + else if ((wp->w_flag & (WFEDIT | WFHARD)) != 0) + { + while (i < wp->w_toprow + wp->w_ntrows) + { + vscreen[i]->v_flag |= VFCHG; + vtmove(i, 0); + /* if line has been changed */ + if (lp != wp->w_bufp->b_linep) + { + for (j = 0; j < llength(lp); ++j) + vtputc(lgetc(lp, j)); + lp = lforw(lp); + } + vteeol(); + ++i; + } + } + } + modeline(wp); /* always update the modeline so line number is correct */ + wp->w_flag = 0; + wp->w_force = 0; + + wp = wp->w_wndp; /* and onward to the next window */ + } + + /* Always recompute the row and column number of the hardware cursor. This + * is the only update for simple moves */ + lp = curwp->w_linep; + currow = curwp->w_toprow; + while (lp != curwp->w_dotp) + { + ++currow; + lp = lforw(lp); + } + + curcol = 0; + i = 0; + while (i < curwp->w_doto) + { + c = lgetc(lp, i++); + if (c == '\t') + curcol |= 0x07; + else if (c < 0x20 || c == 0x7F) + ++curcol; + ++curcol; + } + if (curcol >= term.t_ncol - 1) + { /* extended line */ + /* flag we are extended and changed */ + vscreen[currow]->v_flag |= VFEXT | VFCHG; + updext(); /* and output extended line */ + } + else + lbound = 0; /* not extended line */ + + /* make sure no lines need to be de-extended because the cursor is no + * longer on them */ + + wp = wheadp; + + while (wp != NULL) + { + lp = wp->w_linep; + i = wp->w_toprow; + + while (i < wp->w_toprow + wp->w_ntrows) + { + if (vscreen[i]->v_flag & VFEXT) + { + /* always flag extended lines as changed */ + vscreen[i]->v_flag |= VFCHG; + if ((wp != curwp) || (lp != wp->w_dotp) || + (curcol < term.t_ncol - 1)) + { + vtmove(i, 0); + for (j = 0; j < llength(lp); ++j) + vtputc (lgetc(lp, j)); + vteeol(); + /* this line no longer is extended */ + vscreen[i]->v_flag &= ~VFEXT; + } + } + lp = lforw(lp); + ++i; + } + /* and onward to the next window */ + wp = wp->w_wndp; + } + + /* Special hacking if the screen is garbage. Clear the hardware screen, and + * update your copy to agree with it. Set all the virtual screen change + * bits, to force a full update */ + if (sgarbf != FALSE) + { + for (i = 0; i < term.t_nrow; ++i) + { + vscreen[i]->v_flag |= VFCHG; + vp1 = pscreen[i]; + for (j = 0; j < term.t_ncol; ++j) + vp1->v_text[j] = ' '; + } + + movecursor(0, 0); /* Erase the screen */ + (*term.t_eeop) (); + sgarbf = FALSE; /* Erase-page clears */ + mpresf = FALSE; /* the message area */ + } + /* Make sure that the physical and virtual displays agree. Unlike before, + * the "updateline" code is only called with a line that has been updated + * for sure */ + for (i = 0; i < term.t_nrow; ++i) + { + vp1 = vscreen[i]; + + /* for each line that needs to be updated, or that needs its reverse + * video status changed, call the line updater */ + j = vp1->v_flag; + if (((j & VFCHG) != 0) || (((j & VFREV) == 0) != ((j & VFREQ) == 0))) + { + if (typeahead()) + return; + vp2 = pscreen[i]; + updateline(i, &vp1->v_text[0], &vp2->v_text[0], &vp1->v_flag); + } + } + + /* Finally, update the hardware cursor and flush out buffers */ + movecursor(currow, curcol - lbound); + (*term.t_flush) (); +} + +/* updext: update the extended line which the cursor is currently on at a + * column greater than the terminal width. The line will be scrolled right or + * left to let the user see where the cursor is + */ +void updext() +{ + LINE *lp; /* pointer to current line */ + int rcursor; /* real cursor location */ + int j; /* index into line */ + + /* calculate what column the real cursor will end up in */ + rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin; + lbound = curcol - rcursor + 1; + + /* scan through the line outputing characters to the virtual screen */ + /* once we reach the left edge */ + vtmove(currow, -lbound); /* start scanning offscreen */ + lp = curwp->w_dotp; /* line to output */ + for (j = 0; j < llength(lp); ++j) /* until the end-of-line */ + vtpute (lgetc(lp, j)); + /* truncate the virtual line */ + vteeol(); + /* and put a '$' in column 1 */ + vscreen[currow]->v_text[0] = '$'; +} + +/* + * Update a single line. This does not know how to use insert or delete + * character sequences; we are using VT52 functionality. Update the physical + * row and column variables. It does try an exploit erase to end of line. + */ +void updateline(int row, char vline[], char pline[], short *flags) +{ + char *cp1, *cp2, *cp3, *cp4, *cp5; + int nbflag; /* non-blanks to the right flag? */ + int rev; /* reverse video flag */ + int req; /* reverse video request flag */ + + /* set up pointers to virtual and physical lines */ + cp1 = &vline[0]; + cp2 = &pline[0]; + + /* if we need to change the reverse video status of the current line, we + * need to re-write the entire line */ + rev = *flags & VFREV; + req = *flags & VFREQ; + if (rev != req) + { + movecursor(row, 0); /* Go to start of line */ + (*term.t_rev) (req != FALSE); /* set rev video if needed */ + + /* scan through the line and dump it to the screen and the virtual + * screen array */ + cp3 = &vline[term.t_ncol]; + while (cp1 < cp3) + { + (*term.t_putchar) (*cp1); + ++ttcol; + *cp2++ = *cp1++; + } + (*term.t_rev) (FALSE); /* turn rev video off */ + + /* update the needed flags */ + *flags &= ~VFCHG; + if (req) + *flags |= VFREV; + else + *flags &= ~VFREV; + return; + } + + /* advance past any common chars at the left */ + while (cp1 != &vline[term.t_ncol] && cp1[0] == cp2[0]) + { + ++cp1; + ++cp2; + } + + /* This can still happen, even though we only call this routine on changed + * lines. A hard update is always done when a line splits, a massive change + * is done, or a buffer is displayed twice. This optimizes out most of the + * excess updating. A lot of computes are used, but these tend to be hard + * operations that do a lot of update, so I don't really care */ + /* if both lines are the same, no update needs to be done */ + if (cp1 == &vline[term.t_ncol]) + return; + + /* find out if there is a match on the right */ + nbflag = FALSE; + cp3 = &vline[term.t_ncol]; + cp4 = &pline[term.t_ncol]; + + while (cp3[-1] == cp4[-1]) + { + --cp3; + --cp4; + if (cp3[0] != ' ') /* Note if any nonblank */ + nbflag = TRUE; /* in right match */ + } + + cp5 = cp3; + + if (nbflag == FALSE && eolexist == TRUE) + { /* Erase to EOL ? */ + while (cp5 != cp1 && cp5[-1] == ' ') + --cp5; + if (cp3 - cp5 <= 3) /* Use only if erase is */ + cp5 = cp3; /* fewer characters */ + } + movecursor (row, cp1 - &vline[0]); /* Go to start of line */ + + while (cp1 != cp5) + { /* Ordinary */ + (*term.t_putchar) (*cp1); + ++ttcol; + *cp2++ = *cp1++; + } + + if (cp5 != cp3) + { /* Erase */ + (*term.t_eeol) (); + while (cp1 != cp3) + *cp2++ = *cp1++; + } + *flags &= ~VFCHG; /* flag this line is changed */ +} + +/* + * Redisplay the mode line for the window pointed to by the "wp". This is the + * only routine that has any idea of how the modeline is formatted. You can + * change the modeline format by hacking at this routine. Called by "update" + * any time there is a dirty window. + */ +void modeline(WINDOW *wp) +{ + BUFFER *bp; + int lchar; /* character to draw line in buffer with */ + int n; /* cursor position count */ + int len; /* line/column display check */ + char sl[25]; /* line/column display (probably overkill) */ + + n = wp->w_toprow + wp->w_ntrows; /* Location */ + vscreen[n]->v_flag |= VFCHG; /* Redraw next time */ + vtmove(n, 0); /* Seek to right line */ + if (wp == curwp) /* mark the current buffer */ + lchar = '='; + else + if (revexist) + lchar = ' '; + else + lchar = '-'; + + vtputc(lchar); + bp = wp->w_bufp; + + if ((bp->b_flag & BFCHG) != 0) /* "*" if changed */ + vtputc('*'); + else + vtputc(lchar); + + n = 2; + /* This is the version string. Do not forget to + * increment when releasing a new version. */ + n += vtputs(" emg 1.7 "); + + vtputc(lchar); + vtputc(lchar); + vtputc(' '); + n += 3; + + n += vtputs(&(bp->b_bname[0])); + + vtputc(' '); + vtputc(lchar); + vtputc(lchar); + n += 3; + + if (bp->b_fname[0] != 0) /* File name */ + { + vtputc(' '); + ++n; + n += vtputs("File: "); + + n += vtputs(&(bp->b_fname[0])); + + vtputc(' '); + vtputc(lchar); + vtputc(lchar); + n += 3; + } + + len = snprintf(sl, sizeof(sl), " %d%% (%d,%d) ", + ((100*(wp->w_dotline)) / bp->b_lines), + (wp->w_dotline + 1), getccol(FALSE)); + if (len < sizeof(sl) && len != -1) + n += vtputs(sl); + + while (n < term.t_ncol) /* Pad to full width */ + { + vtputc(lchar); + ++n; + } +} + +/* update all the mode lines */ +void upmode() +{ + WINDOW *wp; + + wp = wheadp; + while (wp != NULL) + { + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } +} + +/* + * Ask a yes or no question in the message line. Return either TRUE, FALSE, or + * ABORT. The ABORT status is returned if the user bumps out of the question + * with a ^G. Used any time a confirmation is required. + */ +int mlyesno(char *prompt) +{ + char c; /* input character */ + char buf[NPAT]; /* prompt to user */ + + for (;;) + { + /* build and prompt the user */ + strncpy(buf, prompt, 60); + + strncat(buf, " [y/n]? ", 9); + mlwrite(buf); + + /* get the responce */ + c = (*term.t_getchar) (); + if (c == BELL) /* Bail out! */ + return (ABORT); + if (c == 'y' || c == 'Y') + return (TRUE); + if (c == 'n' || c == 'N') + return (FALSE); + } +} + +/* A more generalized prompt/reply function allowing the caller to specify the + * proper terminator. If the terminator is not a return ('\n') it will echo as + * "" + */ +int mlreplyt(char *prompt, char *buf, int nbuf, char eolchar) +{ + int cpos, i, c; + + cpos = 0; + + if (kbdmop != NULL) + { + while ((c = *kbdmop++) != '\0') + buf[cpos++] = c; + buf[cpos] = 0; + if (buf[0] == 0) + return (FALSE); + return (TRUE); + } + mlwrite(prompt); + + for (;;) + { + /* get a character from the user. if it is a change it to a */ + c = (*term.t_getchar) (); + if (c == 0x0d) + c = '\n'; + + if (c == eolchar) + { + buf[cpos++] = 0; + + if (kbdmip != NULL) + { + if (kbdmip + cpos > &kbdm[NKBDM - 3]) + { + ctrlg(FALSE, 0); + (*term.t_flush) (); + return (ABORT); + } + for (i = 0; i < cpos; ++i) + *kbdmip++ = buf[i]; + } + (*term.t_putchar) ('\r'); + ttcol = 0; + (*term.t_flush) (); + + if (buf[0] == 0) + return (FALSE); + + return (TRUE); + + } + else if (c == 0x07) + { /* Bell, abort */ + (*term.t_putchar) ('^'); + (*term.t_putchar) ('G'); + ttcol += 2; + ctrlg (FALSE, 0); + (*term.t_flush) (); + return (ABORT); + } + else if (c == 0x7F || c == 0x08) + { /* rubout/erase */ + if (cpos != 0) + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + --ttcol; + + if (buf[--cpos] < 0x20) + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + --ttcol; + } + if (buf[cpos] == '\n') + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + (*term.t_putchar) ('\b'); + --ttcol; + --ttcol; + } + (*term.t_flush) (); + } + } + else if (c == 0x15) + { /* C-U, kill */ + while (cpos != 0) + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + --ttcol; + if (buf[--cpos] < 0x20) + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + --ttcol; + } + } + (*term.t_flush) (); + } + else + { + if (cpos < nbuf - 1) + { + buf[cpos++] = c; + if ((c < ' ') && (c != '\n')) + { + (*term.t_putchar) ('^'); + ++ttcol; + c ^= 0x40; + } + if (c != '\n') + (*term.t_putchar) (c); + else + { /* put out for */ + (*term.t_putchar) ('<'); + (*term.t_putchar) ('N'); + (*term.t_putchar) ('L'); + (*term.t_putchar) ('>'); + ttcol += 3; + } + ++ttcol; + (*term.t_flush) (); + } + } + } +} + +/* + * Write a prompt into the message line, then read back a response. Keep track + * of the physical position of the cursor. If we are in a keyboard macro throw + * the prompt away, and return the remembered response. This lets macros run + * at full speed. The reply is always terminated by a carriage return. Handle + * erase, kill, and abort keys. + */ +int mlreply(char *prompt, char *buf, int nbuf) +{ + return(mlreplyt (prompt, buf, nbuf, '\n')); +} + +/* + * Write a message into the message line. Keep track of the physical cursor + * position. A small class of printf like format items is handled. Assumes the + * stack grows down; this assumption is made by the "++" in the argument scan + * loop. Set the "message line" flag TRUE. + */ +void mlwrite(char *fmt, int arg) +{ + int c; + char *ap; + + if (eolexist == FALSE) + { + mlerase(); + (*term.t_flush) (); + } + movecursor(term.t_nrow, 0); + ap = (char *) &arg; + while ((c = *fmt++) != 0) + { + if (c != '%') + { + (*term.t_putchar) (c); + ++ttcol; + } + else + { + c = *fmt++; + switch (c) + { + case 'd': + mlputi(*(int *) ap, 10); + ap += sizeof(int); + break; + + case 'o': + mlputi(*(int *) ap, 8); + ap += sizeof(int); + break; + + case 'x': + mlputi(*(int *) ap, 16); + ap += sizeof(int); + break; + + case 'D': + mlputli(*(long *) ap, 10); + ap += sizeof(long); + break; + + case 's': + mlputs(*(char **) &ap); + ap += sizeof(char *); + break; + + case 'c': + (*term.t_putchar) (*ap); + ++ttcol; + ap += sizeof(char *); + break; + + default: + (*term.t_putchar) (c); + ++ttcol; + } + } + } + if (eolexist == TRUE) + (*term.t_eeol) (); + (*term.t_flush) (); + mpresf = TRUE; +} + +/* + * Write out a string. Update the physical cursor position. This assumes that + * the characters in the string all have width "1"; if this is not the case + * things will get screwed up a little. + */ +void mlputs(char *s) +{ + int c; + + while ((c = *s++) != 0) + { + (*term.t_putchar) (c); + ++ttcol; + } +} + +/* + * Write out an integer, in the specified radix. Update the physical cursor + * position. This will not handle any negative numbers; maybe it should. + */ +void mlputi(int i, int r) +{ + int q; + static char hexdigits[] = "0123456789abcdef"; + + if (i < 0) + { + i = -i; + (*term.t_putchar) ('-'); + } + q = i / r; + + if (q != 0) + mlputi(q, r); + + (*term.t_putchar) (hexdigits[i % r]); + ++ttcol; +} + +/* + * do the same except as a long integer. + */ +void mlputli(long l, int r) +{ + long q; + + if (l < 0) + { + l = -l; + (*term.t_putchar) ('-'); + } + q = l / r; + + if (q != 0) + mlputli(q, r); + + (*term.t_putchar) ((int) (l % r) + '0'); + ++ttcol; +} + diff --git a/src/cmd/emg/ebind.h b/src/cmd/emg/ebind.h new file mode 100644 index 0000000..2356969 --- /dev/null +++ b/src/cmd/emg/ebind.h @@ -0,0 +1,67 @@ +/* This file is in the public domain. */ + +/* + * This table is *roughly* in ASCII order, left to right across the + * characters of the command. This expains the funny location of the + * control-X commands. + */ + +KEYTAB keytab[] = { + {CTRL | 'A', gotobol}, + {CTRL | 'B', backchar}, + {CTRL | 'D', forwdel}, + {CTRL | 'E', gotoeol}, + {CTRL | 'F', forwchar}, + {CTRL | 'G', ctrlg}, + {CTRL | 'H', backdel}, + {CTRL | 'I', tab}, + {CTRL | 'K', killtext}, + {CTRL | 'L', refresh}, + {CTRL | 'M', newline}, + {CTRL | 'N', forwline}, + {CTRL | 'O', openline}, + {CTRL | 'P', backline}, + {CTRL | 'Q', quote}, + {CTRL | 'R', backsearch}, + {CTRL | 'S', forwsearch}, + {CTRL | 'T', twiddle}, + {CTRL | 'V', pagedown}, + {CTRL | 'W', killregion}, + {CTRL | 'Y', yank}, + {CTLX | '(', ctlxlp}, + {CTLX | ')', ctlxrp}, + {CTLX | '1', onlywind}, + {CTLX | '2', splitwind}, + {CTLX | 'B', usebuffer}, + {CTLX | 'E', ctlxe}, + {CTLX | 'F', setfillcol}, + {CTLX | 'K', killbuffer}, + {CTLX | 'N', filename}, + {CTLX | 'O', nextwind}, + {CTLX | 'S', filesave}, /* non-standard */ + {CTLX | 'Q', quote}, /* non-standard */ + {CTLX | 'X', nextbuffer}, + {CTLX | '^', enlargewind}, + {CTLX | CTRL | 'B', listbuffers}, + {CTLX | CTRL | 'C', quit}, + {CTLX | CTRL | 'F', filefind}, + {CTLX | CTRL | 'I', insfile}, + {CTLX | CTRL | 'R', fileread}, + {CTLX | CTRL | 'S', filesave}, + {CTLX | CTRL | 'W', filewrite}, + {META | '.', setmark}, + {META | '<', gotobob}, + {META | '>', gotoeob}, + {META | 'B', backword}, + {META | 'F', forwword}, + {META | 'G', setline}, /* non-standard */ + {META | 'S', forwsearch}, /* non-standard */ + {META | 'V', pageup}, + {META | 'W', copyregion}, + {META | 'Z', quickexit}, + {META | CTRL | 'N', namebuffer}, + {0x7F, backdel}, + {META | '[', extendedcmd}, + {META | 'O', extendedcmd}, + {0, 0} +}; diff --git a/src/cmd/emg/edef.h b/src/cmd/emg/edef.h new file mode 100644 index 0000000..dd59b1e --- /dev/null +++ b/src/cmd/emg/edef.h @@ -0,0 +1,78 @@ +/* This file is in the public domain. */ + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#ifdef maindef +/* + * for MAIN.C + * initialized global definitions + */ + +short kbdm[NKBDM] = {CTLX | ')'}; /* Macro */ +int fillcol = 72; /* Current fill column */ +char pat[NPAT]; /* Search pattern */ +char rpat[NPAT]; /* replacement pattern */ +int revexist = FALSE; +int eolexist = TRUE; /* does clear to EOL exist */ +int sgarbf = TRUE; /* TRUE if screen is garbage */ +int mpresf = FALSE; /* TRUE if message in last line */ + +/* uninitialized global definitions */ + +int currow; /* Cursor row */ +int curcol; /* Cursor column */ +int thisflag; /* Flags, this command */ +int lastflag; /* Flags, last command */ +int curgoal; /* Goal for C-P, C-N */ +WINDOW *curwp; /* Current window */ +BUFFER *curbp; /* Current buffer */ +WINDOW *wheadp; /* Head of list of windows */ +BUFFER *bheadp; /* Head of list of buffers */ +BUFFER *blistp; /* Buffer for C-X C-B */ +short *kbdmip; /* Input pointer for above */ +short *kbdmop; /* Output pointer for above */ + +#else +/* + * for all the other .C files + * initialized global external declarations + */ + +extern int fillcol; /* Fill column */ +extern short kbdm[]; /* Holds kayboard macro data */ +extern char pat[]; /* Search pattern */ +extern char rpat[]; /* Replacement pattern */ +extern int eolexist; /* does clear to EOL exist? */ +extern int revexist; /* does reverse video exist? */ +extern char *modename[]; /* text names of modes */ +extern char modecode[]; /* letters to represent modes */ +extern KEYTAB keytab[]; /* key bind to functions table */ +extern int gmode; /* global editor mode */ +extern int sgarbf; /* State of screen unknown */ +extern int mpresf; /* Stuff in message line */ +extern int clexec; /* command line execution flag */ + +/* initialized global external declarations */ + +extern int currow; /* Cursor row */ +extern int curcol; /* Cursor column */ +extern int thisflag; /* Flags, this command */ +extern int lastflag; /* Flags, last command */ +extern int curgoal; /* Goal for C-P, C-N */ +extern WINDOW *curwp; /* Current window */ +extern BUFFER *curbp; /* Current buffer */ +extern WINDOW *wheadp; /* Head of list of windows */ +extern BUFFER *bheadp; /* Head of list of buffers */ +extern BUFFER *blistp; /* Buffer for C-X C-B */ +extern short *kbdmip; /* Input pointer for above */ +extern short *kbdmop; /* Output pointer for above */ + +#endif + +/* terminal table defined only in TERM.C */ + +#ifndef termdef +extern TERM term; /* Terminal information */ +#endif diff --git a/src/cmd/emg/efunc.h b/src/cmd/emg/efunc.h new file mode 100644 index 0000000..dd5ae85 --- /dev/null +++ b/src/cmd/emg/efunc.h @@ -0,0 +1,65 @@ +/* This file is in the public domain. */ + +/* EFUNC.H: function declarations and names + * + * This file list all the C code functions used. To add functions, declare it + * here in both the extern function list and the name binding table + */ + +extern int ctrlg(); /* Abort out of things */ +extern int quit(); /* Quit */ +extern int ctlxlp(); /* Begin macro */ +extern int ctlxrp(); /* End macro */ +extern int ctlxe(); /* Execute macro */ +extern int fileread(); /* Get a file, read only */ +extern int filefind(); /* Get a file, read write */ +extern int filewrite(); /* Write a file */ +extern int filesave(); /* Save current file */ +extern int filename(); /* Adjust file name */ +extern int getccol(); /* Get current column */ +extern int gotobol(); /* Move to start of line */ +extern int forwchar(); /* Move forward by characters */ +extern int gotoeol(); /* Move to end of line */ +extern int backchar(); /* Move backward by characters */ +extern int forwline(); /* Move forward by lines */ +extern int backline(); /* Move backward by lines */ +extern int pagedown(); /* PgDn */ +extern int pageup(); /* PgUp */ +extern int gotobob(); /* Move to start of buffer */ +extern int gotoeob(); /* Move to end of buffer */ +extern int setfillcol(); /* Set fill column */ +extern int setmark(); /* Set mark */ +extern int forwsearch(); /* Search forward */ +extern int backsearch(); /* Search backwards */ +extern int nextwind(); /* Move to the next window */ +extern int prevwind(); /* Move to the previous window */ +extern int onlywind(); /* Make current window only one */ +extern int splitwind(); /* Split current window */ +extern int enlargewind(); /* Enlarge display window */ +extern int shrinkwind(); /* Shrink window */ +extern int listbuffers(); /* Display list of buffers */ +extern int usebuffer(); /* Switch a window to a buffer */ +extern int killbuffer(); /* Make a buffer go away */ +extern int refresh(); /* Refresh the screen */ +extern int twiddle(); /* Twiddle characters */ +extern int tab(); /* Insert tab */ +extern int newline(); /* Insert CR-LF */ +extern int openline(); /* Open up a blank line */ +extern int quote(); /* Insert literal */ +extern int backword(); /* Backup by words */ +extern int forwword(); /* Advance by words */ +extern int forwdel(); /* Forward delete */ +extern int backdel(); /* Backward delete */ +extern int killtext(); /* Kill forward */ +extern int yank(); /* Yank back from killbuffer */ +extern int killregion(); /* Kill region */ +extern int copyregion(); /* Copy region to kill buffer */ +extern int quickexit(); /* low keystroke style exit */ +extern int setline(); /* go to a numbered line */ +extern int namebuffer(); /* rename the current buffer */ +extern int deskey(); /* describe a key's binding */ +extern int insfile(); /* insert a file */ +extern int nextbuffer(); /* switch to the next buffer */ +extern int forwhunt(); /* hunt forward for next match */ +extern int backhunt(); /* hunt backwards for next match */ +extern int extendedcmd(); /* parse ANSI/VT100 extended keys */ diff --git a/src/cmd/emg/emg.1 b/src/cmd/emg/emg.1 new file mode 100644 index 0000000..b43b026 --- /dev/null +++ b/src/cmd/emg/emg.1 @@ -0,0 +1,62 @@ +.\" This file is in the public domain. +.\" +.\" Basic emg man page. +.\" As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain. +.\" +.Dd June 17, 2014 +.Os +.Dt EMG 1 +.Sh NAME +.Nm emg +.Nd very small Emacs-like text editor +.Sh SYNOPSIS +.Nm emg +.Op Ar +.Sh DESCRIPTION +.Nm , +or Ersatz Mg, is an Emacs-like text editor designed for RetroBSD +and other memory-constrained environments. +.Nm +was originally created to fit into an operating environment of 96K of RAM, +and one in which Mg did not fit and Ersatz Emacs did not build. +By combining parts of each a working editor was created. +.Pp +When invoked without file arguments, +.Nm +creates a +.Qq main +buffer. +This buffer must be renamed +.Ic ( C-x n ) +in order to be saved +.Ic ( C-x C-s ) . +.Pp +As both Ersatz Emacs and Mg are Public Domain, +.Nm +is also Public Domain. +.Sh FILES +There is a chart of key bindings in +.Pa /usr/local/share/doc/emg/emg.keys . +Consulting this file is a must. +While +.Nm +strives to maintain compatibility with larger Emacs implementations, +there may be features intentionally left unimplemented in order to keep +.Nm +as small as possible. +.Sh AUTHORS +.Nm +is a combination of Ersatz Emacs and Mg and therefore all authors +for both deserve credit. +Ersatz Emacs and Mg were combined by +.An Brian Callahan Aq Mt bcallah@openbsd.org +to create +.Nm . +.Sh BUGS +None known. +However, patches are appreciated if any are found. +.Sh TODO +It would be nice to have automatic window resizing. +It would also be nice if +.Nm +could clear the screen when quit, like Mg does. diff --git a/src/cmd/emg/emg.keys b/src/cmd/emg/emg.keys new file mode 100644 index 0000000..3f66e93 --- /dev/null +++ b/src/cmd/emg/emg.keys @@ -0,0 +1,131 @@ + emg keybindings (July 7, 2014) + Based on Ersatz Emacs (2000/09/14) + +M- means to use the key prior to using another key +^A means to use the control key at the same time as the 'A' key + +------------------------------------------------------------------------------ + MOVING THE CURSOR + +^F Forward character M-F Forward word +^B Backward character M-B Backward word +^N Next line M-P Front of paragraph +^P Previous line M-N End of paragraph +^A Front of line M-< or [HOME] Start of file +^E End of line M-> or [END] End of file +^V or [PgDn] Scroll down M-V or [PgUp] Scroll up +M-G Go to line Arrow keys are active + +------------------------------------------------------------------------------ + DELETING & INSERTING + +<- Delete previous character M-<- Delete previous word +^D Delete next character M-D Delete next word +^K Delete to end of line ^O Insert line + +------------------------------------------------------------------------------ + FORMATTING & TRANSPOSING + +^Q Quote next key, so that control codes may be entered into text. (or ^X Q) + +------------------------------------------------------------------------------ + SEARCHING + +^S Search forward from cursor position. Type in a string and end it with + ENTER. Either case matches. (or M-S) +^R As above, but reverse search from cursor position. + +------------------------------------------------------------------------------ + COPYING AND MOVING + +M-. Set mark at current position. +^W Delete region. +M-W Copy region to kill buffer. +^Y Yank back kill buffer at cursor. + +A region is defined as the area between this mark and the current cursor +position. The kill buffer is the text which has been most recently deleted or +copied. + +Generally, the procedure for copying or moving text is: +1) Mark out region using M-. at the beginning and move the cursor to + the end. +2) Delete it (with ^W) or copy it (with M-W) into the kill buffer. +3) Move the cursor to the desired location and yank it back (with ^Y). + +------------------------------------------------------------------------------ + MULTIPLE BUFFERS + +A buffer contains a COPY of a document being edited, and must be saved for +changes to be kept. Many buffers may be activated at once. + +^X B Switch to another buffer. +^X ^B Show buffer directory in a window (^X 1 to remove). +^X K Delete a non-displayed buffer. +^X X Switch to next buffer in buffer list. +^X N Change the filename associated with the buffer. +M-^N Change the name of the buffer. + +------------------------------------------------------------------------------ + READING FROM DISK + +^X^F Find file; read into a new buffer created from filename. + (This is the usual way to edit a new file.) +^X^R Read file into current buffer, erasing its previous contents. + No new buffer will be created. +^X^I Insert file into current buffer at cursor's location. + +------------------------------------------------------------------------------ + SAVING TO DISK + +^X^S Save current buffer to disk, using the buffer's filename as the name of + the disk file. Any disk file of that name will be overwritten. (or ^X S) +^X^W Write current buffer to disk. Type in a new filename at the prompt to + write to; it will also become the current buffer's filename. + +------------------------------------------------------------------------------ + MULTIPLE WINDOWS + +Many windows may be visible at once on the screen. Windows may show different +parts of the same buffer, or each may display a different one. + +^X 2 Split the current window in two ^X 1 Show only current window +^X O Move cursor to next window ^X ^ Enlarge current window +M-^V Scroll other window down M-^Z Scroll other window up + +------------------------------------------------------------------------------ + EXITING + +^X^C Exit. Any unsaved files will require confirmation. + +------------------------------------------------------------------------------ + MACROS + +^X ( Start recording a keyboard macro. Typing ^G or an error aborts. +^X ) Stop recording macro. +^X E Execute macro. + +------------------------------------------------------------------------------ + REPEAT & NUMBER PREFIX + +^U or M- + Number prefix and universal repeat. May be followed by an integer + (default = 4) and repeats the next command that many times. + Exceptions follow. +^U^L + Reposition the cursor to a particular screen row; i.e., ^U0^L moves the + cursor and the line it is on to the top of the screen. Negative numbers + are from the bottom of the screen. +^U^X F + Set the right margin to column for paragraph formatting. +^U^X^ + Enlarge a split window by rows. A negative number shrinks the + window. + +------------------------------------------------------------------------------ + SPECIAL KEYS + +^G Cancel current command. +^L Redraws the screen completely. + +------------------------------------------------------------------------------ diff --git a/src/cmd/emg/estruct.h b/src/cmd/emg/estruct.h new file mode 100644 index 0000000..9b2bf59 --- /dev/null +++ b/src/cmd/emg/estruct.h @@ -0,0 +1,191 @@ +/* This file is in the public domain. */ + +/* ESTRUCT: Structure and preprocessor */ + +/* internal constants */ +#define NFILEN 32 /* maximum # of bytes, file name */ +#define NBUFN 16 /* maximum # of bytes, buffer name */ +#define NLINE 512 /* maximum # of bytes, line */ +#define NKBDM 128 /* maximum # of strokes, keyboard macro */ +#define NPAT 80 /* maximum # of bytes, pattern */ +#define HUGE 32700 /* Huge number for "impossible" row&col */ + +#define METACH 0x1B /* M- prefix, Control-[, ESC */ +#define BELL 0x07 /* a bell character */ +#define TAB 0x09 /* a tab character */ + +#define CTRL 0x0100 /* Control flag, or'ed in */ +#define META 0x0200 /* Meta flag, or'ed in */ +#define CTLX 0x0400 /* ^X flag, or'ed in */ + +#define FALSE 0 /* False, no, bad, etc */ +#define TRUE 1 /* True, yes, good, etc */ +#define ABORT 2 /* Death, ^G, abort, etc */ + +#define FIOSUC 0 /* File I/O, success */ +#define FIOFNF 1 /* File I/O, file not found */ +#define FIOEOF 2 /* File I/O, end of file */ +#define FIOERR 3 /* File I/O, error */ +#define FIOLNG 4 /* line longer than allowed len */ + +#define CFCPCN 0x0001 /* Last command was C-P, C-N */ +#define CFKILL 0x0002 /* Last command was a kill */ + +/* + * screen constants + * override with + * CFLAGS += -DFORCE_COLS=XXX -DFORCE_ROWS=XXX + */ +#ifndef FORCE_COLS +#define FORCE_COLS 80 +#endif + +#ifndef FORCE_ROWS +#define FORCE_ROWS 24 +#endif + +/* + * XXX: + * Default/sane(?) maximum column and row sizes. + * Taken from mg1a. + * + * Let the user override these with + * CFLAGS += -DMAXCOL=XXX -DMAXROW=XXX + */ +#ifndef MAXCOL +#define MAXCOL 132 +#endif + +#ifndef MAXROW +#define MAXROW 66 +#endif + +/* + * There is a window structure allocated for every active display window. The + * windows are kept in a big list, in top to bottom screen order, with the + * listhead at "wheadp". Each window contains its own values of dot and mark. + * The flag field contains some bits that are set by commands to guide + * redisplay; although this is a bit of a compromise in terms of decoupling, + * the full blown redisplay is just too expensive to run for every input + * character + */ +typedef struct WINDOW +{ + struct WINDOW *w_wndp; /* Next window */ + struct BUFFER *w_bufp; /* Buffer displayed in window */ + struct LINE *w_linep; /* Top line in the window */ + struct LINE *w_dotp; /* Line containing "." */ + long w_doto; /* Byte offset for "." */ + struct LINE *w_markp; /* Line containing "mark" */ + long w_marko; /* Byte offset for "mark" */ + char w_toprow; /* Origin 0 top row of window */ + char w_ntrows; /* # of rows of text in window */ + char w_force; /* If NZ, forcing row */ + char w_flag; /* Flags */ + int w_dotline; /* current line number of dot */ +} WINDOW; + +#define WFFORCE 0x01 /* Window needs forced reframe */ +#define WFMOVE 0x02 /* Movement from line to line */ +#define WFEDIT 0x04 /* Editing within a line */ +#define WFHARD 0x08 /* Better to a full display */ +#define WFMODE 0x10 /* Update mode line */ + +/* + * Text is kept in buffers. A buffer header, described below, exists for every + * buffer in the system. The buffers are kept in a big list, so that commands + * that search for a buffer by name can find the buffer header. There is a + * safe store for the dot and mark in the header, but this is only valid if + * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for + * the buffer is kept in a circularly linked list of lines, with a pointer to + * the header line in "b_linep". Buffers may be "Inactive" which means the + * files accosiated with them have not been read in yet. These get read in at + * "use buffer" time + */ +typedef struct BUFFER +{ + struct BUFFER *b_bufp; /* Link to next BUFFER */ + struct LINE *b_dotp; /* Link to "." LINE structure */ + long b_doto; /* Offset of "." in above LINE */ + struct LINE *b_markp; /* The same as the above two, */ + long b_marko; /* but for the "mark" */ + struct LINE *b_linep; /* Link to the header LINE */ + char b_active; /* window activated flag */ + char b_nwnd; /* Count of windows on buffer */ + char b_flag; /* Flags */ + char b_fname[NFILEN]; /* File name */ + char b_bname[NBUFN]; /* Buffer name */ + int b_lines; /* Number of lines in file */ +} BUFFER; + +#define BFTEMP 0x01 /* Internal temporary buffer */ +#define BFCHG 0x02 /* Changed since last write */ + +/* + * The starting position of a region, and the size of the region in + * characters, is kept in a region structure. Used by the region commands + */ +typedef struct +{ + struct LINE *r_linep; /* Origin LINE address */ + long r_offset; /* Origin LINE offset */ + long r_size; /* Length in characters */ +} REGION; + +/* + * All text is kept in circularly linked lists of "LINE" structures. These + * begin at the header line (which is the blank line beyond the end of the + * buffer). This line is pointed to by the "BUFFER". Each line contains a the + * number of bytes in the line (the "used" size), the size of the text array, + * and the text. The end of line is not stored as a byte; it's implied. Future + * additions will include update hints, and a list of marks into the line + */ +typedef struct LINE +{ + struct LINE *l_fp; /* Link to the next line */ + struct LINE *l_bp; /* Link to the previous line */ + int l_size; /* Allocated size */ + int l_used; /* Used size */ + char l_text[1]; /* A bunch of characters */ +} LINE; + +#define lforw(lp) ((lp)->l_fp) +#define lback(lp) ((lp)->l_bp) +#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF) +#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c)) +#define llength(lp) ((lp)->l_used) + +/* + * The editor communicates with the display using a high level interface. A + * "TERM" structure holds useful variables, and indirect pointers to routines + * that do useful operations. The low level get and put routines are here too. + * This lets a terminal, in addition to having non standard commands, have + * funny get and put character code too. The calls might get changed to + * "termp->t_field" style in the future, to make it possible to run more than + * one terminal type + */ +typedef struct +{ + int t_nrow; /* Number of rows */ + int t_ncol; /* Number of columns */ + int t_margin; /* min margin for extended lines */ + int t_scrsiz; /* size of scroll region " */ + void (*t_open) (); /* Open terminal at the start */ + void (*t_close) (); /* Close terminal at end */ + int (*t_getchar) (); /* Get character from keyboard */ + void (*t_putchar) (); /* Put character to display */ + void (*t_flush) (); /* Flush output buffers */ + void (*t_move) (); /* Move the cursor, origin 0 */ + void (*t_eeol) (); /* Erase to end of line */ + void (*t_eeop) (); /* Erase to end of page */ + void (*t_beep) (); /* Beep */ + void (*t_rev) (); /* set reverse video state */ +} TERM; + +/* structure for the table of initial key bindings */ + +typedef struct +{ + short k_code; /* Key code */ + int (*k_fp) (); /* Routine to handle it */ +} KEYTAB; diff --git a/src/cmd/emg/file.c b/src/cmd/emg/file.c new file mode 100644 index 0000000..326b823 --- /dev/null +++ b/src/cmd/emg/file.c @@ -0,0 +1,465 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file handle the reading and writing of disk files. + * All details about the reading and writing of the disk are in "fileio.c" + */ + +#include /* strncpy(3) */ +#include "estruct.h" +#include "edef.h" + +extern int mlreply(char *prompt, char *buf, int nbuf); +extern int swbuffer(BUFFER *bp); +extern void mlwrite(); +extern int bclear(BUFFER *bp); +extern int ffropen(char *fn); +extern int ffgetline(char buf[], int nbuf); +extern int ffwopen(char *fn); +extern int ffclose(); +extern int ffputline(char buf[], int nbuf); +extern BUFFER *bfind(); +extern LINE *lalloc(); + +int fileread(int f, int n); +int insfile(int f, int n); +int filefind(int f, int n); +int getfile(char fname[]); +int readin(char fname[]); +void makename(char bname[], char fname[]); +int filewrite(int f, int n); +int filesave(int f, int n); +int writeout(char *fn); +int filename(int f, int n); +int ifile(char fname[]); + +/* + * Read a file into the current buffer. This is really easy; all you do it + * find the name of the file, and call the standard "read a file into the + * current buffer" code. Bound to "C-X C-R" + */ +int fileread(int f, int n) +{ + int s; + char fname[NFILEN]; + + if ((s = mlreply("Read file: ", fname, NFILEN)) != TRUE) + return (s); + return (readin(fname)); +} + +/* + * Insert a file into the current buffer. This is really easy; all you do it + * find the name of the file, and call the standard "insert a file into the + * current buffer" code. Bound to "C-X C-I". + */ +int insfile(int f, int n) +{ + int s; + char fname[NFILEN]; + + if ((s = mlreply("Insert file: ", fname, NFILEN)) != TRUE) + return (s); + return (ifile(fname)); +} + +/* + * Select a file for editing. Look around to see if you can find the fine in + * another buffer; if you can find it just switch to the buffer. If you cannot + * find the file, create a new buffer, read in the text, and switch to the new + * buffer. Bound to C-X C-F. + */ +int filefind(int f, int n) +{ + char fname[NFILEN]; /* file user wishes to find */ + int s; /* status return */ + + if ((s = mlreply("Find file: ", fname, NFILEN)) != TRUE) + return (s); + return (getfile(fname)); +} + +int getfile(char fname[]) +{ + BUFFER *bp; + LINE *lp; + char bname[NBUFN]; /* buffer name to put file */ + int i, s; + + for (bp = bheadp; bp != (BUFFER*)0; bp = bp->b_bufp) + { + if ((bp->b_flag & BFTEMP) == 0 && strcmp(bp->b_fname, fname) == 0) + { + if (--curbp->b_nwnd == 0) + { + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curwp->w_doto; + curbp->b_markp = curwp->w_markp; + curbp->b_marko = curwp->w_marko; + } + swbuffer(bp); + lp = curwp->w_dotp; + i = curwp->w_ntrows / 2; + while (i-- && lback(lp) != curbp->b_linep) + lp = lback(lp); + curwp->w_linep = lp; + curwp->w_flag |= WFMODE | WFHARD; + mlwrite("[Old buffer]"); + return (TRUE); + } + } + makename(bname, fname); /* New buffer name */ + while ((bp = bfind(bname, FALSE, 0)) != (BUFFER*)0) + { + s = mlreply("Buffer name: ", bname, NBUFN); + if (s == ABORT) /* ^G to just quit */ + return (s); + if (s == FALSE) + { /* CR to clobber it */ + makename(bname, fname); + break; + } + } + if (bp == (BUFFER*)0 && (bp = bfind(bname, TRUE, 0)) == (BUFFER*)0) + { + mlwrite("Cannot create buffer"); + return (FALSE); + } + if (--curbp->b_nwnd == 0) + { /* Undisplay */ + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curwp->w_doto; + curbp->b_markp = curwp->w_markp; + curbp->b_marko = curwp->w_marko; + } + curbp = bp; /* Switch to it */ + curwp->w_bufp = bp; + curbp->b_nwnd++; + return (readin(fname)); /* Read it in */ +} + +/* + * Read file "fname" into the current buffer, blowing away any text found + * there. Called by both the read and find commands. Return the final status + * of the read. Also called by the mainline, to read in a file specified on + * the command line as an argument. + */ +int readin(char fname[]) +{ + LINE *lp1, *lp2; + WINDOW *wp; + BUFFER *bp; + char line[NLINE]; + int nbytes, s, i; + int nline = 0; /* initialize here to silence a gcc warning */ + int lflag; /* any lines longer than allowed? */ + + bp = curbp; /* Cheap */ + if ((s = bclear(bp)) != TRUE) /* Might be old */ + return (s); + bp->b_flag &= ~(BFTEMP | BFCHG); + strncpy(bp->b_fname, fname, NFILEN); + if ((s = ffropen(fname)) == FIOERR) /* Hard file open */ + goto out; + if (s == FIOFNF) + { /* File not found */ + mlwrite("[New file]"); + goto out; + } + mlwrite("[Reading file]"); + lflag = FALSE; + while ((s = ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) + { + if (s == FIOLNG) + lflag = TRUE; + nbytes = strlen(line); + if ((lp1 = lalloc(nbytes)) == NULL) + { + s = FIOERR; /* Keep message on the display */ + break; + } + lp2 = lback(curbp->b_linep); + lp2->l_fp = lp1; + lp1->l_fp = curbp->b_linep; + lp1->l_bp = lp2; + curbp->b_linep->l_bp = lp1; + for (i = 0; i < nbytes; ++i) + lputc(lp1, i, line[i]); + ++nline; + } + ffclose(); /* Ignore errors */ + if (s == FIOEOF) + { /* Don't zap message! */ + if (nline != 1) + mlwrite("[Read %d lines]", nline); + else + mlwrite("[Read 1 line]"); + } + if (lflag) + { + if (nline != 1) + mlwrite("[Read %d lines: Long lines wrapped]", nline); + else + mlwrite("[Read 1 line: Long lines wrapped]"); + } + curwp->w_bufp->b_lines = nline; + out: + for (wp = wheadp; wp != NULL; wp = wp->w_wndp) + { + if (wp->w_bufp == curbp) + { + wp->w_linep = lforw(curbp->b_linep); + wp->w_dotp = lforw(curbp->b_linep); + wp->w_doto = 0; + wp->w_markp = NULL; + wp->w_marko = 0; + wp->w_flag |= WFMODE | WFHARD; + } + } + if (s == FIOERR || s == FIOFNF) /* False if error */ + return (FALSE); + return (TRUE); +} + +/* + * Take a file name, and from it fabricate a buffer name. This routine knows + * about the syntax of file names on the target system. I suppose that this + * information could be put in a better place than a line of code. + */ +void makename(char bname[], char fname[]) +{ + char *cp1, *cp2; + + cp1 = &fname[0]; + while (*cp1 != 0) + ++cp1; + + while (cp1 != &fname[0] && cp1[-1] != '/') + --cp1; + cp2 = &bname[0]; + while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != ';') + *cp2++ = *cp1++; + *cp2 = 0; +} + +/* + * Ask for a file name, and write the contents of the current buffer to that + * file. Update the remembered file name and clear the buffer changed flag. + * This handling of file names is different from the earlier versions, and is + * more compatable with Gosling EMACS than with ITS EMACS. Bound to "C-X C-W". + */ +int filewrite(int f, int n) +{ + WINDOW *wp; + char fname[NFILEN]; + int s; + + if ((s = mlreply("Write file: ", fname, NFILEN)) != TRUE) + return (s); + if ((s = writeout(fname)) == TRUE) + { + strncpy(curbp->b_fname, fname, NFILEN); + curbp->b_flag &= ~BFCHG; + wp = wheadp; /* Update mode lines */ + while (wp != NULL) + { + if (wp->w_bufp == curbp) + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } + } + return (s); +} + +/* + * Save the contents of the current buffer in its associatd file. No nothing + * if nothing has changed (this may be a bug, not a feature). Error if there + * is no remembered file name for the buffer. Bound to "C-X C-S". May get + * called by "C-Z" + */ +int filesave(int f, int n) +{ + WINDOW *wp; + int s; + + if ((curbp->b_flag & BFCHG) == 0) /* Return, no changes */ + return (TRUE); + if (curbp->b_fname[0] == 0) + { /* Must have a name */ + mlwrite("No file name"); + return (FALSE); + } + if ((s = writeout(curbp->b_fname)) == TRUE) + { + curbp->b_flag &= ~BFCHG; + wp = wheadp; /* Update mode lines */ + while (wp != NULL) + { + if (wp->w_bufp == curbp) + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } + } + return (s); +} + +/* + * This function performs the details of file writing. Uses the file + * management routines in the "fileio.c" package. The number of lines written + * is displayed. Sadly, it looks inside a LINE; provide a macro for this. Most + * of the grief is error checking of some sort. + */ +int writeout(char *fn) +{ + LINE *lp; + int nline, s; + + if ((s = ffwopen(fn)) != FIOSUC) /* Open writes message */ + return (FALSE); + mlwrite("[Writing]"); /* tell us were writing */ + lp = lforw(curbp->b_linep); /* First line */ + nline = 0; /* Number of lines */ + while (lp != curbp->b_linep) + { + if ((s = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) + break; + ++nline; + lp = lforw(lp); + } + if (s == FIOSUC) + { /* No write error */ + s = ffclose(); + if (s == FIOSUC) + { /* No close error */ + if (nline != 1) + mlwrite("[Wrote %d lines]", nline); + else + mlwrite("[Wrote 1 line]"); + } + } + else /* ignore close error */ + ffclose(); /* if a write error */ + if (s != FIOSUC) /* some sort of error */ + return (FALSE); + return (TRUE); +} + +/* + * The command allows the user to modify the file name associated with the + * current buffer. It is like the "f" command in UNIX "ed". The operation is + * simple; just zap the name in the BUFFER structure, and mark the windows as + * needing an update. You can type a blank line at the prompt if you wish. + */ +int filename(int f, int n) +{ + WINDOW *wp; + char fname[NFILEN]; + int s; + + if ((s = mlreply("Name: ", fname, NFILEN)) == ABORT) + return (s); + if (s == FALSE) + strncpy(curbp->b_fname, "", 1); + else + strncpy(curbp->b_fname, fname, NFILEN); + wp = wheadp; /* update mode lines */ + while (wp != NULL) + { + if (wp->w_bufp == curbp) + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } + return (TRUE); +} + +/* + * Insert file "fname" into the current buffer, Called by insert file command. + * Return the final status of the read. + */ +int ifile(char fname[]) +{ + LINE *lp0, *lp1, *lp2; + BUFFER *bp; + char line[NLINE]; + int i, s, nbytes; + int nline = 0; + int lflag; /* any lines longer than allowed? */ + + bp = curbp; /* Cheap */ + bp->b_flag |= BFCHG; /* we have changed */ + bp->b_flag &= ~BFTEMP; /* and are not temporary */ + if ((s = ffropen(fname)) == FIOERR) /* Hard file open */ + goto out; + if (s == FIOFNF) + { /* File not found */ + mlwrite("[No such file]"); + return (FALSE); + } + mlwrite("[Inserting file]"); + + /* back up a line and save the mark here */ + curwp->w_dotp = lback(curwp->w_dotp); + curwp->w_doto = 0; + curwp->w_markp = curwp->w_dotp; + curwp->w_marko = 0; + + lflag = FALSE; + while ((s = ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) + { + if (s == FIOLNG) + lflag = TRUE; + nbytes = strlen(line); + if ((lp1 = lalloc(nbytes)) == NULL) + { + s = FIOERR; /* keep message on the */ + break; /* display */ + } + lp0 = curwp->w_dotp; /* line previous to insert */ + lp2 = lp0->l_fp; /* line after insert */ + + /* re-link new line between lp0 and lp2 */ + lp2->l_bp = lp1; + lp0->l_fp = lp1; + lp1->l_bp = lp0; + lp1->l_fp = lp2; + + /* and advance and write out the current line */ + curwp->w_dotp = lp1; + for (i = 0; i < nbytes; ++i) + lputc(lp1, i, line[i]); + ++nline; + } + ffclose(); /* Ignore errors */ + curwp->w_markp = lforw(curwp->w_markp); + if (s == FIOEOF) + { /* Don't zap message! */ + if (nline != 1) + mlwrite("[Inserted %d lines]", nline); + else + mlwrite("[Inserted 1 line]"); + } + if (lflag) + { + if (nline != 1) + mlwrite("[Inserted %d lines: Long lines wrapped]", nline); + else + mlwrite("[Inserted 1 line: Long lines wrapped]"); + } + out: + /* advance to the next line and mark the window for changes */ + curwp->w_dotp = lforw(curwp->w_dotp); + curwp->w_flag |= WFHARD; + + /* copy window parameters back to the buffer structure */ + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curwp->w_doto; + curbp->b_markp = curwp->w_markp; + curbp->b_marko = curwp->w_marko; + + /* we need to update number of lines in the buffer */ + curwp->w_bufp->b_lines += nline; + + if (s == FIOERR) /* False if error */ + return (FALSE); + return (TRUE); +} diff --git a/src/cmd/emg/fileio.c b/src/cmd/emg/fileio.c new file mode 100644 index 0000000..d61b005 --- /dev/null +++ b/src/cmd/emg/fileio.c @@ -0,0 +1,121 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file read and write ASCII files from the disk. All of + * the knowledge about files is here. A better message writing scheme should + * be used + */ + +#include /* fopen(3), et.al. */ +#include "estruct.h" + +extern void mlwrite(); + +int ffropen(char *fn); +int ffwopen(char *fn); +int ffclose(); +int ffputline(char buf[], int nbuf); +int ffgetline(char buf[], int nbuf); + +FILE *ffp; /* File pointer, all functions */ + +/* + * Open a file for reading. + */ +int ffropen(char *fn) +{ + if ((ffp = fopen(fn, "r")) == NULL) + return (FIOFNF); + return (FIOSUC); +} + +/* + * Open a file for writing. Return TRUE if all is well, and FALSE on error + * (cannot create). + */ +int ffwopen(char *fn) +{ + if ((ffp = fopen(fn, "w")) == NULL) + { + mlwrite("Cannot open file for writing"); + return (FIOERR); + } + return (FIOSUC); +} + +/* + * Close a file. Should look at the status in all systems. + */ +int ffclose() +{ + if (fclose(ffp) != FALSE) + { + mlwrite("Error closing file"); + return (FIOERR); + } + return (FIOSUC); +} + +/* + * Write a line to the already opened file. The "buf" points to the buffer, + * and the "nbuf" is its length, less the free newline. Return the status. + * Check only at the newline. + */ +int ffputline(char buf[], int nbuf) +{ + int i; + + for (i = 0; i < nbuf; ++i) + fputc(buf[i] & 0xFF, ffp); + + fputc('\n', ffp); + + if (ferror(ffp)) + { + mlwrite("Write I/O error"); + return (FIOERR); + } + return (FIOSUC); +} + +/* + * Read a line from a file, and store the bytes in the supplied buffer. The + * "nbuf" is the length of the buffer. Complain about long lines and lines at + * the end of the file that don't have a newline present. Check for I/O errors + * too. Return status. + */ +int ffgetline(char buf[], int nbuf) +{ + int c, i; + + i = 0; + + while ((c = fgetc(ffp)) != EOF && c != '\n') + { + if (i >= nbuf - 2) + { + buf[nbuf - 2] = c; /* store last char read */ + buf[nbuf - 1] = 0; /* and terminate it */ + mlwrite("File has long lines"); + return (FIOLNG); + } + buf[i++] = c; + } + + if (c == EOF) + { + if (ferror(ffp)) + { + mlwrite("File read error"); + return (FIOERR); + } + if (i != 0) + { + mlwrite("No newline at EOF"); + return (FIOERR); + } + return (FIOEOF); + } + buf[i] = 0; + return (FIOSUC); +} diff --git a/src/cmd/emg/line.c b/src/cmd/emg/line.c new file mode 100644 index 0000000..df05774 --- /dev/null +++ b/src/cmd/emg/line.c @@ -0,0 +1,507 @@ +/* This file is in the public domain. */ + +/* + * The functions in this file are a general set of line management utilities. + * They are the only routines that touch the text. They also touch the buffer + * and window structures, to make sure that the necessary updating gets done. + * There are routines in this file that handle the kill buffer too. It isn't + * here for any good reason. + * + * Note that this code only updates the dot and mark values in the window + * list. Since all the code acts on the current window, the buffer that we are + * editing must be being displayed, which means that "b_nwnd" is non zero, + * which means that the dot and mark values in the buffer headers are + * nonsense + */ + +#include /* malloc(3) */ +#include "estruct.h" +#include "edef.h" + +extern void mlwrite(); +extern int backchar(int f, int n); + +LINE* lalloc(int used); +void lfree(LINE *lp); +void lchange(int flag); +int linsert(int n, int c); +int lnewline(); +int ldelete(int n, int kflag); +int ldelnewline(); +void kdelete(); +int kinsert(int c); +int kremove(int n); + +#define NBLOCK 16 /* Line block chunk size */ +#define KBLOCK 1024 /* Kill buffer block size */ + +char *kbufp = NULL; /* Kill buffer data */ +unsigned long kused = 0; /* # of bytes used in KB */ +unsigned long ksize = 0; /* # of bytes allocated in KB */ + +/* + * This routine allocates a block of memory large enough to hold a LINE + * containing "used" characters. The block is always rounded up a bit. Return + * a pointer to the new block, or NULL if there isn't any memory left. Print a + * message in the message line if no space. + */ +LINE* lalloc(int used) +{ + LINE *lp; + int size; + + size = (used + NBLOCK - 1) & ~(NBLOCK - 1); + if (size == 0) /* Assume that an empty */ + size = NBLOCK; /* line is for type-in */ + if ((lp = (LINE *) malloc(sizeof(LINE) + size)) == NULL) + { + mlwrite("Cannot allocate %d bytes", size); + return (NULL); + } + lp->l_size = size; + lp->l_used = used; + return (lp); +} + +/* + * Delete line "lp". Fix all of the links that might point at it (they are + * moved to offset 0 of the next line. Unlink the line from whatever buffer it + * might be in. Release the memory. The buffers are updated too; the magic + * conditions described in the above comments don't hold here + */ +void lfree(LINE *lp) +{ + BUFFER *bp; + WINDOW *wp; + + wp = wheadp; + while (wp != NULL) + { + if (wp->w_linep == lp) + wp->w_linep = lp->l_fp; + if (wp->w_dotp == lp) + { + wp->w_dotp = lp->l_fp; + wp->w_doto = 0; + } + if (wp->w_markp == lp) + { + wp->w_markp = lp->l_fp; + wp->w_marko = 0; + } + wp = wp->w_wndp; + } + bp = bheadp; + while (bp != NULL) + { + if (bp->b_nwnd == 0) + { + if (bp->b_dotp == lp) + { + bp->b_dotp = lp->l_fp; + bp->b_doto = 0; + } + if (bp->b_markp == lp) + { + bp->b_markp = lp->l_fp; + bp->b_marko = 0; + } + } + bp = bp->b_bufp; + } + lp->l_bp->l_fp = lp->l_fp; + lp->l_fp->l_bp = lp->l_bp; + free((char *) lp); +} + +/* + * This routine gets called when a character is changed in place in the + * current buffer. It updates all of the required flags in the buffer and + * window system. The flag used is passed as an argument; if the buffer is + * being displayed in more than 1 window we change EDIT t HARD. Set MODE if + * the mode line needs to be updated (the "*" has to be set). + */ +void lchange(int flag) +{ + WINDOW *wp; + + if (curbp->b_nwnd != 1) /* Ensure hard */ + flag = WFHARD; + if ((curbp->b_flag & BFCHG) == 0) + { /* First change, so */ + flag |= WFMODE; /* update mode lines */ + curbp->b_flag |= BFCHG; + } + wp = wheadp; + while (wp != NULL) + { + if (wp->w_bufp == curbp) + wp->w_flag |= flag; + wp = wp->w_wndp; + } +} + +/* + * Insert "n" copies of the character "c" at the current location of dot. In + * the easy case all that happens is the text is stored in the line. In the + * hard case, the line has to be reallocated. When the window list is updated, + * take special care; I screwed it up once. You always update dot in the + * current window. You update mark, and a dot in another window, if it is + * greater than the place where you did the insert. Return TRUE if all is + * well, and FALSE on errors + */ +int linsert(int n, int c) +{ + WINDOW *wp; + LINE *lp1, *lp2, *lp3; + char *cp1, *cp2; + int i, doto; + + lchange(WFEDIT); + lp1 = curwp->w_dotp; /* Current line */ + if (lp1 == curbp->b_linep) + { /* At the end: special */ + if (curwp->w_doto != 0) + { + mlwrite("Bug: linsert"); + return (FALSE); + } + if ((lp2 = lalloc(n)) == NULL) /* Allocate new line */ + return (FALSE); + lp3 = lp1->l_bp; /* Previous line */ + lp3->l_fp = lp2; /* Link in */ + lp2->l_fp = lp1; + lp1->l_bp = lp2; + lp2->l_bp = lp3; + for (i = 0; i < n; ++i) + lp2->l_text[i] = c; + curwp->w_dotp = lp2; + curwp->w_doto = n; + return (TRUE); + } + doto = curwp->w_doto; /* Save for later */ + if (lp1->l_used + n > lp1->l_size) + { /* Hard: reallocate */ + if ((lp2 = lalloc(lp1->l_used + n)) == NULL) + return (FALSE); + cp1 = &lp1->l_text[0]; + cp2 = &lp2->l_text[0]; + while (cp1 != &lp1->l_text[doto]) + *cp2++ = *cp1++; + cp2 += n; + while (cp1 != &lp1->l_text[lp1->l_used]) + *cp2++ = *cp1++; + lp1->l_bp->l_fp = lp2; + lp2->l_fp = lp1->l_fp; + lp1->l_fp->l_bp = lp2; + lp2->l_bp = lp1->l_bp; + free((char *) lp1); + } + else + { /* Easy: in place */ + lp2 = lp1; /* Pretend new line */ + lp2->l_used += n; + cp2 = &lp1->l_text[lp1->l_used]; + cp1 = cp2 - n; + while (cp1 != &lp1->l_text[doto]) + *--cp2 = *--cp1; + } + for (i = 0; i < n; ++i) /* Add the characters */ + lp2->l_text[doto + i] = c; + wp = wheadp; /* Update windows */ + while (wp != NULL) + { + if (wp->w_linep == lp1) + wp->w_linep = lp2; + if (wp->w_dotp == lp1) + { + wp->w_dotp = lp2; + if (wp == curwp || wp->w_doto > doto) + wp->w_doto += n; + } + if (wp->w_markp == lp1) + { + wp->w_markp = lp2; + if (wp->w_marko > doto) + wp->w_marko += n; + } + wp = wp->w_wndp; + } + return (TRUE); +} + +/* + * Insert a newline into the buffer at the current location of dot in the + * current window. The funny ass-backwards way it does things is not a botch; + * it just makes the last line in the file not a special case. Return TRUE if + * everything works out and FALSE on error (memory allocation failure). The + * update of dot and mark is a bit easier then in the above case, because the + * split forces more updating. + */ +int lnewline() +{ + WINDOW *wp; + char *cp1, *cp2; + LINE *lp1, *lp2; + int doto; + + lchange(WFHARD); + + curwp->w_bufp->b_lines++; + + lp1 = curwp->w_dotp; /* Get the address and */ + doto = curwp->w_doto; /* offset of "." */ + if ((lp2 = lalloc(doto)) == NULL) /* New first half line */ + return (FALSE); + cp1 = &lp1->l_text[0]; /* Shuffle text around */ + cp2 = &lp2->l_text[0]; + while (cp1 != &lp1->l_text[doto]) + *cp2++ = *cp1++; + cp2 = &lp1->l_text[0]; + while (cp1 != &lp1->l_text[lp1->l_used]) + *cp2++ = *cp1++; + lp1->l_used -= doto; + lp2->l_bp = lp1->l_bp; + lp1->l_bp = lp2; + lp2->l_bp->l_fp = lp2; + lp2->l_fp = lp1; + wp = wheadp; /* Windows */ + while (wp != NULL) + { + if (wp->w_linep == lp1) + wp->w_linep = lp2; + if (wp->w_dotp == lp1) + { + if (wp->w_doto < doto) + wp->w_dotp = lp2; + else + wp->w_doto -= doto; + } + if (wp->w_markp == lp1) + { + if (wp->w_marko < doto) + wp->w_markp = lp2; + else + wp->w_marko -= doto; + } + wp = wp->w_wndp; + } + curwp->w_dotline++; + return (TRUE); +} + +/* + * This function deletes "n" bytes, starting at dot. It understands how do + * deal with end of lines, etc. It returns TRUE if all of the characters were + * deleted, and FALSE if they were not (because dot ran into the end of the + * buffer. The "kflag" is TRUE if the text should be put in the kill buffer. + */ +int ldelete(int n, int kflag) +{ + LINE *dotp; + WINDOW *wp; + char *cp1, *cp2; + int doto, chunk; + + while (n != 0) + { + dotp = curwp->w_dotp; + doto = curwp->w_doto; + if (dotp == curbp->b_linep) /* Hit end of buffer */ + return (FALSE); + chunk = dotp->l_used - doto; /* Size of chunk */ + if (chunk > n) + chunk = n; + if (chunk == 0) + { /* End of line, merge */ + lchange(WFHARD); + if (ldelnewline() == FALSE + || (kflag != FALSE && kinsert('\n') == FALSE)) + return (FALSE); + --n; + continue; + } + lchange(WFEDIT); + cp1 = &dotp->l_text[doto]; /* Scrunch text */ + cp2 = cp1 + chunk; + if (kflag != FALSE) + { /* Kill? */ + while (cp1 != cp2) + { + if (kinsert (*cp1) == FALSE) + return (FALSE); + ++cp1; + } + cp1 = &dotp->l_text[doto]; + } + while (cp2 != &dotp->l_text[dotp->l_used]) + *cp1++ = *cp2++; + dotp->l_used -= chunk; + wp = wheadp; /* Fix windows */ + while (wp != NULL) + { + if (wp->w_dotp == dotp && wp->w_doto >= doto) + { + wp->w_doto -= chunk; + if (wp->w_doto < doto) + wp->w_doto = doto; + } + if (wp->w_markp == dotp && wp->w_marko >= doto) + { + wp->w_marko -= chunk; + if (wp->w_marko < doto) + wp->w_marko = doto; + } + wp = wp->w_wndp; + } + n -= chunk; + } + return (TRUE); +} + +/* + * Delete a newline. Join the current line with the next line. If the next + * line is the magic header line always return TRUE; merging the last line + * with the header line can be thought of as always being a successful + * operation, even if nothing is done, and this makes the kill buffer work + * "right". Easy cases can be done by shuffling data around. Hard cases + * require that lines be moved about in memory. Return FALSE on error and TRUE + * if all looks ok. Called by "ldelete" only. + */ +int ldelnewline() +{ + LINE *lp1, *lp2, *lp3; + WINDOW *wp; + char *cp1, *cp2; + + lp1 = curwp->w_dotp; + lp2 = lp1->l_fp; + if (lp2 == curbp->b_linep) + { /* At the buffer end */ + if (lp1->l_used == 0) /* Blank line */ + lfree(lp1); + return (TRUE); + } + /* Keep line counts in sync */ + curwp->w_bufp->b_lines--; + if (lp2->l_used <= lp1->l_size - lp1->l_used) + { + cp1 = &lp1->l_text[lp1->l_used]; + cp2 = &lp2->l_text[0]; + while (cp2 != &lp2->l_text[lp2->l_used]) + *cp1++ = *cp2++; + wp = wheadp; + while (wp != NULL) + { + if (wp->w_linep == lp2) + wp->w_linep = lp1; + if (wp->w_dotp == lp2) + { + wp->w_dotp = lp1; + wp->w_doto += lp1->l_used; + } + if (wp->w_markp == lp2) + { + wp->w_markp = lp1; + wp->w_marko += lp1->l_used; + } + wp = wp->w_wndp; + } + lp1->l_used += lp2->l_used; + lp1->l_fp = lp2->l_fp; + lp2->l_fp->l_bp = lp1; + free((char *) lp2); + return (TRUE); + } + if ((lp3 = lalloc(lp1->l_used + lp2->l_used)) == NULL) + return (FALSE); + cp1 = &lp1->l_text[0]; + cp2 = &lp3->l_text[0]; + while (cp1 != &lp1->l_text[lp1->l_used]) + *cp2++ = *cp1++; + cp1 = &lp2->l_text[0]; + while (cp1 != &lp2->l_text[lp2->l_used]) + *cp2++ = *cp1++; + lp1->l_bp->l_fp = lp3; + lp3->l_fp = lp2->l_fp; + lp2->l_fp->l_bp = lp3; + lp3->l_bp = lp1->l_bp; + wp = wheadp; + while (wp != NULL) + { + if (wp->w_linep == lp1 || wp->w_linep == lp2) + wp->w_linep = lp3; + if (wp->w_dotp == lp1) + wp->w_dotp = lp3; + else if (wp->w_dotp == lp2) + { + wp->w_dotp = lp3; + wp->w_doto += lp1->l_used; + } + if (wp->w_markp == lp1) + wp->w_markp = lp3; + else if (wp->w_markp == lp2) + { + wp->w_markp = lp3; + wp->w_marko += lp1->l_used; + } + wp = wp->w_wndp; + } + free((char *) lp1); + free((char *) lp2); + return (TRUE); +} + +/* + * Delete all of the text saved in the kill buffer. Called by commands when a + * new kill context is being created. The kill buffer array is released, just + * in case the buffer has grown to immense size. No errors. + */ +void kdelete() +{ + if (kbufp != NULL) + { + free((char *) kbufp); + kbufp = NULL; + kused = 0; + ksize = 0; + } +} + +/* + * Insert a character to the kill buffer, enlarging the buffer if there isn't + * any room. Always grow the buffer in chunks, on the assumption that if you + * put something in the kill buffer you are going to put more stuff there too + * later. Return TRUE if all is well, and FALSE on errors. + */ +int kinsert(int c) +{ + char *nbufp; + + if (kused == ksize) + { + if (ksize == 0) /* first time through? */ + nbufp = malloc(KBLOCK); /* alloc the first block */ + else /* or re allocate a bigger block */ + nbufp = realloc(kbufp, ksize + KBLOCK); + if (nbufp == NULL) /* abort if it fails */ + return (FALSE); + kbufp = nbufp; /* point our global at it */ + ksize += KBLOCK; /* and adjust the size */ + } + kbufp[kused++] = c; + return (TRUE); +} + +/* + * This function gets characters from the kill buffer. If the character index + * "n" is off the end, it returns "-1". This lets the caller just scan along + * until it gets a "-1" back. + */ +int kremove(int n) +{ + if (n >= kused) + return (-1); + else + return (kbufp[n] & 0xFF); +} diff --git a/src/cmd/emg/main.c b/src/cmd/emg/main.c new file mode 100644 index 0000000..fd48cf1 --- /dev/null +++ b/src/cmd/emg/main.c @@ -0,0 +1,469 @@ +/* This file is in the public domain. */ + +/* + * This program is in public domain; originally written by Dave G. Conroy. + * This file contains the main driving routine, and some keyboard processing + * code + */ + +#define maindef /* make global definitions not external */ + +#include /* strncpy(3) */ +#include /* malloc(3) */ +#include "estruct.h" /* global structures and defines */ +#include "efunc.h" /* function declarations and name table */ +#include "edef.h" /* global definitions */ +#include "ebind.h" + +extern void getwinsize(); +extern void vtinit(); +extern void vttidy(); +extern void update(); +extern void mlerase(); +extern void mlwrite(); +extern int mlyesno(char *prompt); +extern void makename(char bname[], char fname[]); +extern int readin(char fname[]); +extern int linsert(int f, int n); +extern int anycb(); +extern BUFFER *bfind(); + +void edinit(char bname[]); +int execute(int c, int f, int n); +int getkey(); +int getctl(); +int quickexit(int f, int n); +int quit(int f, int n); +int ctlxlp(int f, int n); +int ctlxrp(int f, int n); +int ctlxe(int f, int n); +int ctrlg(int f, int n); +int extendedcmd(int f, int n); + +int main(int argc, char *argv[]) +{ + BUFFER *bp; + char bname[NBUFN]; /* buffer name of file to read */ + int c, f, n, mflag; + int ffile; /* first file flag */ + int carg; /* current arg to scan */ + int basec; /* c stripped of meta character */ + + /* initialize the editor and process the startup file */ + getwinsize(); /* find out the "real" screen size */ + strncpy(bname, "main", 5); /* default buffer name */ + edinit(bname); /* Buffers, windows */ + vtinit(); /* Displays */ + ffile = TRUE; /* no file to edit yet */ + update(); /* let the user know we are here */ + + /* scan through the command line and get the files to edit */ + for (carg = 1; carg < argc; ++carg) + { + /* set up a buffer for this file */ + makename(bname, argv[carg]); + + /* if this is the first file, read it in */ + if (ffile) + { + bp = curbp; + makename(bname, argv[carg]); + strncpy(bp->b_bname, bname, NBUFN); + strncpy(bp->b_fname, argv[carg], NFILEN); + if (readin(argv[carg]) == ABORT) + { + strncpy(bp->b_bname, "main", 5); + strncpy(bp->b_fname, "", 1); + } + bp->b_dotp = bp->b_linep; + bp->b_doto = 0; + ffile = FALSE; + } + else + { + /* set this to inactive */ + bp = bfind(bname, TRUE, 0); + strncpy(bp->b_fname, argv[carg], NFILEN); + bp->b_active = FALSE; + } + } + + /* setup to process commands */ + lastflag = 0; /* Fake last flags */ + curwp->w_flag |= WFMODE; /* and force an update */ + + loop: + update(); /* Fix up the screen */ + c = getkey(); + if (mpresf != FALSE) + { + mlerase(); + update(); + } + f = FALSE; + n = 1; + + /* do META-# processing if needed */ + + basec = c & ~META; /* strip meta char off if there */ + if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) + { + f = TRUE; /* there is a # arg */ + n = 0; /* start with a zero default */ + mflag = 1; /* current minus flag */ + c = basec; /* strip the META */ + while ((c >= '0' && c <= '9') || (c == '-')) + { + if (c == '-') + { + /* already hit a minus or digit? */ + if ((mflag == -1) || (n != 0)) + break; + mflag = -1; + } + else + n = n * 10 + (c - '0'); + if ((n == 0) && (mflag == -1)) /* lonely - */ + mlwrite("Arg:"); + else + mlwrite("Arg: %d", n * mflag); + + c = getkey(); /* get the next key */ + } + n = n * mflag; /* figure in the sign */ + } + /* do ^U repeat argument processing */ + + if (c == (CTRL | 'U')) + { /* ^U, start argument */ + f = TRUE; + n = 4; /* with argument of 4 */ + mflag = 0; /* that can be discarded */ + mlwrite("Arg: 4"); + while (((c = getkey ()) >= '0') + && ((c <= '9') || (c == (CTRL | 'U')) || (c == '-'))) + { + if (c == (CTRL | 'U')) + n = n * 4; + /* + * If dash, and start of argument string, set arg. + * to -1. Otherwise, insert it. + */ + else if (c == '-') + { + if (mflag) + break; + n = 0; + mflag = -1; + } + /* + * If first digit entered, replace previous argument + * with digit and set sign. Otherwise, append to arg. + */ + else + { + if (!mflag) + { + n = 0; + mflag = 1; + } + n = 10 * n + c - '0'; + } + mlwrite("Arg: %d", (mflag >= 0) ? n : (n ? -n : -1)); + } + /* + * Make arguments preceded by a minus sign negative and change + * the special argument "^U -" to an effective "^U -1". + */ + if (mflag == -1) + { + if (n == 0) + n++; + n = -n; + } + } + + if (c == (CTRL | 'X')) /* ^X is a prefix */ + c = CTLX | getctl (); + if (kbdmip != NULL) + { /* Save macro strokes */ + if (c != (CTLX | ')') && kbdmip > &kbdm[NKBDM - 6]) + { + ctrlg(FALSE, 0); + goto loop; + } + if (f != FALSE) + { + *kbdmip++ = (CTRL | 'U'); + *kbdmip++ = n; + } + *kbdmip++ = c; + } + execute(c, f, n); /* Do it */ + goto loop; +} + +/* + * Initialize all of the buffers and windows. The buffer name is passed down + * as an argument, because the main routine may have been told to read in a + * file by default, and we want the buffer name to be right. + */ +void edinit(char bname[]) +{ + BUFFER *bp; + WINDOW *wp; + + bp = bfind(bname, TRUE, 0); /* First buffer */ + blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer */ + wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */ + if (bp == NULL || wp == NULL || blistp == NULL) + exit (1); + curbp = bp; /* Make this current */ + wheadp = wp; + curwp = wp; + wp->w_wndp = NULL; /* Initialize window */ + wp->w_bufp = bp; + bp->b_nwnd = 1; /* Displayed */ + wp->w_linep = bp->b_linep; + wp->w_dotp = bp->b_linep; + wp->w_doto = 0; + wp->w_markp = NULL; + wp->w_marko = 0; + wp->w_toprow = 0; + wp->w_ntrows = term.t_nrow - 1; /* "-1" for mode line */ + wp->w_force = 0; + wp->w_flag = WFMODE | WFHARD; /* Full */ +} + +/* + * This is the general command execution routine. It handles the fake binding + * of all the keys to "self-insert". It also clears out the "thisflag" word, + * and arranges to move it to the "lastflag", so that the next command can + * look at it. Return the status of command. + */ +int execute(int c, int f, int n) +{ + KEYTAB *ktp; + int status; + + ktp = &keytab[0]; /* Look in key table */ + while (ktp->k_fp != NULL) + { + if (ktp->k_code == c) + { + thisflag = 0; + status = (*ktp->k_fp) (f, n); + lastflag = thisflag; + return (status); + } + ++ktp; + } + + if ((c >= 0x20 && c <= 0x7E) /* Self inserting */ + || (c >= 0xA0 && c <= 0xFE)) + { + if (n <= 0) + { /* Fenceposts */ + lastflag = 0; + return (n < 0 ? FALSE : TRUE); + } + thisflag = 0; /* For the future */ + + status = linsert(n, c); + + lastflag = thisflag; + return (status); + } + mlwrite("\007[Key not bound]"); /* complain */ + lastflag = 0; /* Fake last flags */ + return (FALSE); +} + +/* + * Read in a key. Do the standard keyboard preprocessing. Convert the keys to + * the internal character set. + */ +int getkey() +{ + int c; + + c = (*term.t_getchar) (); + + if (c == METACH) + { /* Apply M- prefix */ + c = getctl (); + return (META | c); + } + if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */ + c = CTRL | (c + '@'); + return (c); +} + +/* + * Get a key. Apply control modifications to the read key. + */ +int getctl() +{ + int c; + + c = (*term.t_getchar) (); + if (c >= 'a' && c <= 'z') /* Force to upper */ + c -= 0x20; + if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */ + c = CTRL | (c + '@'); + return (c); +} + +/* + * Fancy quit command, as implemented by Norm. If any buffer has changed + * do a write on that buffer and exit emacs, otherwise simply exit. + */ +int quickexit(int f, int n) +{ + BUFFER *bp; /* scanning pointer to buffers */ + + bp = bheadp; + while (bp != NULL) + { + if ((bp->b_flag & BFCHG) != 0 /* Changed */ + && (bp->b_flag & BFTEMP) == 0) + { /* Real */ + curbp = bp; /* make that buffer current */ + mlwrite("[Saving %s]", (int*)bp->b_fname); + filesave(f, n); + } + bp = bp->b_bufp; /* on to the next buffer */ + } + return quit(f, n); /* conditionally quit */ +} + +/* + * Quit command. If an argument, always quit. Otherwise confirm if a buffer + * has been changed and not written out. Normally bound to "C-X C-C". + */ +int quit(int f, int n) +{ + int s; + + if (f != FALSE /* Argument forces it */ + || anycb () == FALSE /* All buffers clean */ + || (s = mlyesno("Modified buffers exist. Leave anyway")) == TRUE) + { + vttidy(); + exit (0); + } + mlwrite(""); + return (s); +} + +/* + * Begin a keyboard macro. Error if not at the top level in keyboard + * processing. Set up variables and return. + */ +int ctlxlp(int f, int n) +{ + if (kbdmip != NULL || kbdmop != NULL) + { + mlwrite("Not now"); + return (FALSE); + } + mlwrite("[Start macro]"); + kbdmip = &kbdm[0]; + return (TRUE); +} + +/* + * End keyboard macro. Check for the same limit conditions as the above + * routine. Set up the variables and return to the caller. + */ +int ctlxrp(int f, int n) +{ + if (kbdmip == NULL) + { + mlwrite("Not now"); + return (FALSE); + } + mlwrite("[End macro]"); + kbdmip = NULL; + return (TRUE); +} + +/* + * Execute a macro. The command argument is the number of times to loop. Quit + * as soon as a command gets an error. Return TRUE if all ok, else FALSE. + */ +int ctlxe(int f, int n) +{ + int c, af, an, s; + + if (kbdmip != NULL || kbdmop != NULL) + { + mlwrite("No macro defined"); + return (FALSE); + } + if (n <= 0) + return (TRUE); + do + { + kbdmop = &kbdm[0]; + do + { + af = FALSE; + an = 1; + if ((c = *kbdmop++) == (CTRL | 'U')) + { + af = TRUE; + an = *kbdmop++; + c = *kbdmop++; + } + s = TRUE; + } + while (c != (CTLX | ')') && (s = execute(c, af, an)) == TRUE); + kbdmop = NULL; + } + while (s == TRUE && --n); + return (s); +} + +/* + * Abort. Beep the beeper. Kill off any keyboard macro, etc., that is in + * progress. Sometimes called as a routine, to do general aborting of stuff. + */ +int ctrlg(int f, int n) +{ + (*term.t_beep) (); + if (kbdmip != NULL) + { + kbdm[0] = (CTLX | ')'); + kbdmip = NULL; + } + mlwrite("[Aborted]"); + return (ABORT); +} + +/* + * Handle ANSI escape-extended commands (with "ESC [" or "ESC O" prefix) + */ +int extendedcmd(int f, int n) +{ + int (*cmd)(); + int c; + + c = getctl(); + switch (c) + { + case 'A': cmd = backline; break; + case 'B': cmd = forwline; break; + case 'C': cmd = forwchar; break; + case 'D': cmd = backchar; break; + case 'H': cmd = gotobob; break; + case 'W': cmd = gotoeob; break; + case '5': cmd = pageup; getctl(); break; + case '6': cmd = pagedown; getctl(); break; + case '7': cmd = gotobob; getctl(); break; + case '8': cmd = gotoeob; getctl(); break; + default: mlwrite("\007[Key not bound]"); + return (FALSE); + } + return cmd(f, n); +} diff --git a/src/cmd/emg/random.c b/src/cmd/emg/random.c new file mode 100644 index 0000000..39e48c8 --- /dev/null +++ b/src/cmd/emg/random.c @@ -0,0 +1,290 @@ +/* This file is in the public domain. */ + +/* + * This file contains the command processing functions for a number of random + * commands. There is no functional grouping here, for sure. + */ + +#include "estruct.h" +#include "edef.h" + +extern void mlwrite(); +extern void lchange(int flag); +extern int lnewline(); +extern int linsert(int n, int c); +extern int backchar(int f, int n); +extern void kdelete(); +extern int ldelete(int f, int n); +extern int kremove(int k); + +int setfillcol(int f, int n); +int getccol(int bflg); +int twiddle(int f, int n); +int quote(int f, int n); +int tab(int f, int n); +int openline(int f, int n); +int newline(int f, int n); +int forwdel(int f, int n); +int backdel(int f, int n); +int killtext(int f, int n); +int yank(int f, int n); + +/* + * Set fill column to n. + */ +int setfillcol(int f, int n) +{ + fillcol = n; + mlwrite("[Fill column is %d]", n); + return (TRUE); +} + +/* + * Return current column. Stop at first non-blank given TRUE argument. + */ +int getccol(int bflg) +{ + int c, i, col; + + col = 0; + for (i = 0; i < curwp->w_doto; ++i) + { + c = lgetc(curwp->w_dotp, i); + if (c != ' ' && c != '\t' && bflg) + break; + if (c == '\t') + col |= 0x07; + else if (c < 0x20 || c == 0x7F) + ++col; + ++col; + } + return (col); +} + +/* + * Twiddle the two characters on either side of dot. If dot is at the end of + * the line twiddle the two characters before it. Return with an error if dot + * is at the beginning of line; it seems to be a bit pointless to make this + * work. This fixes up a very common typo with a single stroke. Normally bound + * to "C-T". This always works within a line, so "WFEDIT" is good enough + */ +int twiddle(int f, int n) +{ + LINE *dotp; + int doto, cl, cr; + + dotp = curwp->w_dotp; + doto = curwp->w_doto; + if (doto == llength(dotp) && --doto < 0) + return (FALSE); + cr = lgetc(dotp, doto); + if (--doto < 0) + return (FALSE); + cl = lgetc(dotp, doto); + lputc(dotp, doto + 0, cr); + lputc(dotp, doto + 1, cl); + lchange(WFEDIT); + return (TRUE); +} + +/* + * Quote the next character, and insert it into the buffer. All the characters + * are taken literally, with the exception of the newline, which always has + * its line splitting meaning. The character is always read, even if it is + * inserted 0 times, for regularity. Bound to "C-Q" + */ +int quote(int f, int n) +{ + int s, c; + + c = (*term.t_getchar) (); + if (n < 0) + return (FALSE); + if (n == 0) + return (TRUE); + if (c == '\n') + { + do + { + s = lnewline(); + } + while (s == TRUE && --n); + return (s); + } + return (linsert(n, c)); +} + +/* + * Insert a tab into file. + * Bound to "C-I" + */ +int tab(int f, int n) +{ + if (n < 0) + return (FALSE); + return (linsert(n, 9)); +} + +/* + * Open up some blank space. The basic plan is to insert a bunch of newlines, + * and then back up over them. Everything is done by the subcommand + * processors. They even handle the looping. Normally this is bound to "C-O" + */ +int openline(int f, int n) +{ + int i, s; + + if (n < 0) + return (FALSE); + if (n == 0) + return (TRUE); + i = n; /* Insert newlines */ + do + { + s = lnewline(); + } + while (s == TRUE && --i); + if (s == TRUE) /* Then back up overtop */ + s = backchar(f, n); /* of them all */ + return (s); +} + +/* + * Insert a newline. Bound to "C-M". + */ +int newline(int f, int n) +{ + int s; + + if (n < 0) + return (FALSE); + + /* insert some lines */ + while (n--) + { + if ((s = lnewline()) != TRUE) + return (s); + } + return (TRUE); +} + +/* + * Delete forward. This is real easy, because the basic delete routine does + * all of the work. Watches for negative arguments, and does the right thing. + * If any argument is present, it kills rather than deletes, to prevent loss + * of text if typed with a big argument. Normally bound to "C-D" + */ +int forwdel(int f, int n) +{ + if (n < 0) + return (backdel(f, -n)); + if (f != FALSE) + { /* Really a kill */ + if ((lastflag & CFKILL) == 0) + kdelete(); + thisflag |= CFKILL; + } + return (ldelete(n, f)); +} + +/* + * Delete backwards. This is quite easy too, because it's all done with other + * functions. Just move the cursor back, and delete forwards. Like delete + * forward, this actually does a kill if presented with an argument. Bound to + * both "RUBOUT" and "C-H" + */ +int backdel(int f, int n) +{ + int s; + + if (n < 0) + return (forwdel(f, -n)); + if (f != FALSE) + { /* Really a kill */ + if ((lastflag & CFKILL) == 0) + kdelete(); + thisflag |= CFKILL; + } + if ((s = backchar(f, n)) == TRUE) + s = ldelete(n, f); + return (s); +} + +/* + * Kill text. If called without an argument, it kills from dot to the end of + * the line, unless it is at the end of the line, when it kills the newline. + * If called with an argument of 0, it kills from the start of the line to + * dot. If called with a positive argument, it kills from dot forward over + * that number of newlines. If called with a negative argument it kills + * backwards that number of newlines. Normally bound to "C-K" + */ +int killtext(int f, int n) +{ + LINE *nextp; + int chunk; + + if ((lastflag & CFKILL) == 0)/* Clear kill buffer if last wasn't a kill */ + kdelete(); + thisflag |= CFKILL; + if (f == FALSE) + { + chunk = llength(curwp->w_dotp) - curwp->w_doto; + if (chunk == 0) + chunk = 1; + } + else if (n == 0) + { + chunk = curwp->w_doto; + curwp->w_doto = 0; + } + else if (n > 0) + { + chunk = llength(curwp->w_dotp) - curwp->w_doto + 1; + nextp = lforw(curwp->w_dotp); + while (--n) + { + if (nextp == curbp->b_linep) + return (FALSE); + chunk += llength(nextp) + 1; + nextp = lforw(nextp); + } + } + else + { + mlwrite("neg kill"); + return (FALSE); + } + return (ldelete(chunk, TRUE)); +} + +/* + * Yank text back from the kill buffer. This is really easy. All of the work + * is done by the standard insert routines. All you do is run the loop, and + * check for errors. Bound to "C-Y" + */ +int yank(int f, int n) +{ + int c, i; + + if (n < 0) + return (FALSE); + while (n--) + { + i = 0; + while ((c = kremove(i)) >= 0) + { + if (c == '\n') + { + if (lnewline(FALSE, 1) == FALSE) + return (FALSE); + } + else + { + if (linsert(1, c) == FALSE) + return (FALSE); + } + ++i; + } + } + return (TRUE); +} diff --git a/src/cmd/emg/region.c b/src/cmd/emg/region.c new file mode 100644 index 0000000..1d85d32 --- /dev/null +++ b/src/cmd/emg/region.c @@ -0,0 +1,142 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file deal with the region, that magic space between + * "." and mark. Some functions are commands. Some functions are just for + * internal use + */ + +#include "estruct.h" +#include "edef.h" + +extern void kdelete(); +extern int ldelete(int f, int n); +extern int kinsert(int c); +extern void mlwrite(); + +int killregion(int f, int n); +int copyregion(int f, int n); +int getregion(REGION *rp); + +/* + * Kill the region. Ask "getregion" to figure out the bounds of the region. + * Move "." to the start, and kill the characters. Bound to "C-W" + */ +int killregion(int f, int n) +{ + REGION region; + int s; + + if ((s = getregion(®ion)) != TRUE) + return (s); + if ((lastflag & CFKILL) == 0) /* This is a kill type */ + kdelete(); /* command, so do magic */ + thisflag |= CFKILL; /* kill buffer stuff */ + curwp->w_dotp = region.r_linep; + curwp->w_doto = region.r_offset; + return (ldelete(region.r_size, TRUE)); +} + +/* + * Copy all of the characters in the region to the kill buffer. Don't move dot + * at all. This is a bit like a kill region followed by a yank. Bound to "M-W" + */ +int copyregion(int f, int n) +{ + LINE *linep; + REGION region; + int loffs, s; + + if ((s = getregion(®ion)) != TRUE) + return (s); + if ((lastflag & CFKILL) == 0) /* Kill type command */ + kdelete(); + thisflag |= CFKILL; + linep = region.r_linep; /* Current line */ + loffs = region.r_offset; /* Current offset */ + while (region.r_size--) + { + if (loffs == llength(linep)) + { /* End of line */ + if ((s = kinsert('\n')) != TRUE) + return (s); + linep = lforw(linep); + loffs = 0; + } + else + { /* Middle of line */ + if ((s = kinsert(lgetc(linep, loffs))) != TRUE) + return (s); + ++loffs; + } + } + return (TRUE); +} + +/* + * This routine figures out the bounds of the region in the current window, + * and fills in the fields of the "REGION" structure pointed to by "rp". + * Because the dot and mark are usually very close together, we scan outward + * from dot looking for mark. This should save time. Return a standard code. + * Callers of this routine should be prepared to get an "ABORT" status; we + * might make this have the conform thing later + */ +int getregion(REGION *rp) +{ + LINE *flp, *blp; + int fsize, bsize; + + if (curwp->w_markp == (struct LINE*)0) + { + mlwrite("No mark set in this window"); + return (FALSE); + } + if (curwp->w_dotp == curwp->w_markp) + { + rp->r_linep = curwp->w_dotp; + if (curwp->w_doto < curwp->w_marko) + { + rp->r_offset = curwp->w_doto; + rp->r_size = curwp->w_marko - curwp->w_doto; + } + else + { + rp->r_offset = curwp->w_marko; + rp->r_size = curwp->w_doto - curwp->w_marko; + } + return (TRUE); + } + blp = curwp->w_dotp; + bsize = curwp->w_doto; + flp = curwp->w_dotp; + fsize = llength(flp) - curwp->w_doto + 1; + while (flp != curbp->b_linep || lback(blp) != curbp->b_linep) + { + if (flp != curbp->b_linep) + { + flp = lforw(flp); + if (flp == curwp->w_markp) + { + rp->r_linep = curwp->w_dotp; + rp->r_offset = curwp->w_doto; + rp->r_size = fsize + curwp->w_marko; + return (TRUE); + } + fsize += llength(flp) + 1; + } + if (lback(blp) != curbp->b_linep) + { + blp = lback(blp); + bsize += llength(blp) + 1; + if (blp == curwp->w_markp) + { + rp->r_linep = blp; + rp->r_offset = curwp->w_marko; + rp->r_size = bsize - curwp->w_marko; + return (TRUE); + } + } + } + mlwrite("Bug: lost mark"); + return (FALSE); +} diff --git a/src/cmd/emg/search.c b/src/cmd/emg/search.c new file mode 100644 index 0000000..e9649a8 --- /dev/null +++ b/src/cmd/emg/search.c @@ -0,0 +1,383 @@ +/* This file is in the public domain. */ + +/* + * The functions in this file implement commands that search in the forward + * and backward directions. There are no special characters in the search + * strings + */ + +#include /* strncpy(3), strncat(3) */ +#include "estruct.h" +#include "edef.h" + +extern void mlwrite(); +extern int mlreplyt(char *prompt, char *buf, int nbuf, char eolchar); +extern void update(); +extern int forwchar(int f, int n); +extern int ldelete(int n, int kflag); +extern int lnewline(); +extern int linsert(int n, int c); + +int forwsearch(int f, int n); +int forwhunt(int f, int n); +int backsearch(int f, int n); +int backhunt(int f, int n); +int bsearch(int f, int n); +int eq(int bc, int pc); +int readpattern(char *prompt); +int forscan(char *patrn, int leavep); +void expandp(char *srcstr, char *deststr, int maxlength); + +#define PTBEG 1 /* leave the point at the begining on search */ +#define PTEND 2 /* leave the point at the end on search */ + +/* + * Search forward. Get a search string from the user, and search, beginning at + * ".", for the string. If found, reset the "." to be just after the match + * string, and [perhaps] repaint the display. Bound to "C-S" + */ +int forwsearch(int f, int n) +{ + int status; + int curline = curwp->w_dotline; + + if (n == 0) /* resolve the repeat count */ + n = 1; + if (n < 1) /* search backwards */ + return (backsearch(f, -n)); + + /* ask the user for the text of a pattern */ + if ((status = readpattern("Search")) != TRUE) + return (status); + + /* search for the pattern */ + while (n-- > 0) + { + if ((status = forscan(&pat[0], PTEND)) == FALSE) + break; + } + + /* and complain if not there */ + if (status == FALSE) { + mlwrite("Not found"); + curwp->w_dotline = curline; + } + return (status); +} + +int forwhunt(int f, int n) +{ + int status = 0; + int curline = curwp->w_dotline; + + /* resolve the repeat count */ + if (n == 0) + n = 1; + if (n < 1) /* search backwards */ + return (backhunt(f, -n)); + + /* Make sure a pattern exists */ + if (pat[0] == 0) + { + mlwrite("No pattern set"); + return (FALSE); + } + /* search for the pattern */ + while (n-- > 0) + { + if ((status = forscan(&pat[0], PTEND)) == FALSE) + break; + } + + /* and complain if not there */ + if (status == FALSE) { + mlwrite("Not found"); + curwp->w_dotline = curline; + } + return (status); +} + +/* + * Reverse search. Get a search string from the user, and search, starting at + * "." and proceeding toward the front of the buffer. If found "." is left + * pointing at the first character of the pattern [the last character that was + * matched]. Bound to "C-R" + */ +int backsearch(int f, int n) +{ + int s; + + if (n == 0) /* resolve null and negative arguments */ + n = 1; + if (n < 1) + return (forwsearch(f, -n)); + + if ((s = readpattern("Reverse search")) != TRUE) /* get a pattern to search */ + return (s); + + return bsearch(f, n); /* and go search for it */ +} + +/* hunt backward for the last search string entered + */ +int backhunt(int f, int n) +{ + if (n == 0) /* resolve null and negative arguments */ + n = 1; + if (n < 1) + return (forwhunt(f, -n)); + + if (pat[0] == 0) /* Make sure a pattern exists */ + { + mlwrite("No pattern set"); + return (FALSE); + } + return bsearch(f, n); /* go search */ +} + +int bsearch(int f, int n) +{ + LINE *clp, *tlp; + char *epp, *pp; + int cbo, tbo, c; + int curline = curwp->w_dotline; + + /* find a pointer to the end of the pattern */ + for (epp = &pat[0]; epp[1] != 0; ++epp) + ; + + /* make local copies of the starting location */ + clp = curwp->w_dotp; + cbo = curwp->w_doto; + + while (n-- > 0) + { + for (;;) + { + /* if we are at the begining of the line, wrap back around */ + if (cbo == 0) + { + clp = lback(clp); + curwp->w_dotline--; + + if (clp == curbp->b_linep) + { + mlwrite("Not found"); + curwp->w_dotline = curline; + return (FALSE); + } + cbo = llength(clp) + 1; + } + /* fake the at the end of a line */ + if (--cbo == llength(clp)) + c = '\n'; + else + c = lgetc(clp, cbo); + + /* check for a match against the end of the pattern */ + if (eq(c, *epp) != FALSE) + { + tlp = clp; + tbo = cbo; + pp = epp; + /* scanning backwards through the rest of the pattern + * looking for a match */ + while (pp != &pat[0]) + { + /* wrap across a line break */ + if (tbo == 0) + { + tlp = lback(tlp); + curwp->w_dotline--; + if (tlp == curbp->b_linep) + goto fail; + + tbo = llength(tlp) + 1; + } + /* fake the */ + if (--tbo == llength(tlp)) + c = '\n'; + else + c = lgetc(tlp, tbo); + + if (eq(c, *--pp) == FALSE) + goto fail; + } + + /* A Match! reset the current cursor */ + curwp->w_dotp = tlp; + curwp->w_doto = tbo; + curwp->w_flag |= WFMOVE; + goto next; + } + fail:; + } + next:; + } + return (TRUE); +} + +/* + * Compare two characters. The "bc" comes from the buffer. It has it's case + * folded out. The "pc" is from the pattern + */ +int eq(int bc, int pc) +{ + if (bc >= 'a' && bc <= 'z') + bc -= 0x20; + if (pc >= 'a' && pc <= 'z') + pc -= 0x20; + if (bc == pc) + return (TRUE); + return (FALSE); +} + +/* + * Read a pattern. Stash it in the external variable "pat". The "pat" is not + * updated if the user types in an empty line. If the user typed an empty + * line, and there is no old pattern, it is an error. Display the old pattern, + * in the style of Jeff Lomicka. There is some do-it-yourself control + * expansion. + */ +int readpattern(char *prompt) +{ + char tpat[NPAT + 20]; + int s; + + strncpy(tpat, prompt, NPAT-12); /* copy prompt to output string */ + strncat(tpat, " [", 3); /* build new prompt string */ + expandp(&pat[0], &tpat[strlen (tpat)], NPAT / 2); /* add old pattern */ + strncat(tpat, "]: ", 4); + + s = mlreplyt(tpat, tpat, NPAT, 10); /* Read pattern */ + + if (s == TRUE) /* Specified */ + strncpy(pat, tpat, NPAT); + else if (s == FALSE && pat[0] != 0) /* CR, but old one */ + s = TRUE; + + return (s); +} + +/* search forward for a + */ +int forscan(char *patrn, int leavep) +{ + LINE *curline; /* current line during scan */ + LINE *lastline; /* last line position during scan */ + LINE *matchline; /* current line during matching */ + char *patptr; /* pointer into pattern */ + int curoff; /* position within current line */ + int lastoff; /* position within last line */ + int c; /* character at current position */ + int matchoff; /* position in matching line */ + + /* setup local scan pointers to global "." */ + curline = curwp->w_dotp; + curoff = curwp->w_doto; + + /* scan each character until we hit the head link record */ + while (curline != curbp->b_linep) + { + /* save the current position in case we need to restore it on a match */ + lastline = curline; + lastoff = curoff; + + /* get the current character resolving EOLs */ + if (curoff == llength(curline)) + { /* if at EOL */ + curline = lforw(curline); /* skip to next line */ + curwp->w_dotline++; + curoff = 0; + c = '\n'; /* and return a */ + } + else + c = lgetc(curline, curoff++); /* get the char */ + + /* test it against first char in pattern */ + if (eq(c, patrn[0]) != FALSE) /* if we find it. */ + { + /* setup match pointers */ + matchline = curline; + matchoff = curoff; + patptr = &patrn[0]; + + /* scan through patrn for a match */ + while (*++patptr != 0) + { + /* advance all the pointers */ + if (matchoff == llength(matchline)) + { + /* advance past EOL */ + matchline = lforw(matchline); + curwp->w_dotline++; + matchoff = 0; + c = '\n'; + } + else + c = lgetc(matchline, matchoff++); + + /* and test it against the pattern */ + if (eq(*patptr, c) == FALSE) + goto fail; + } + + /* A SUCCESSFULL MATCH!!! */ + /* reset the global "." pointers */ + if (leavep == PTEND) + { /* at end of string */ + curwp->w_dotp = matchline; + curwp->w_doto = matchoff; + } + else + { /* at begining of string */ + curwp->w_dotp = lastline; + curwp->w_doto = lastoff; + } + curwp->w_flag |= WFMOVE; /* flag that we have moved */ + return (TRUE); + } + fail:; /* continue to search */ + } + /* we could not find a match */ + return (FALSE); +} + +/* expandp: expand control key sequences for output + */ +void expandp(char *srcstr, char *deststr, int maxlength) +{ + char c; /* current char to translate */ + + /* scan through the string */ + while ((c = *srcstr++) != 0) + { + if (c < 0x20 || c == 0x7f) + { /* control character */ + *deststr++ = '^'; + *deststr++ = c ^ 0x40; + maxlength -= 2; + } + else if (c == '%') + { + *deststr++ = '%'; + *deststr++ = '%'; + maxlength -= 2; + } + else + { /* any other character */ + *deststr++ = c; + maxlength--; + } + + /* check for maxlength */ + if (maxlength < 4) + { + *deststr++ = '$'; + *deststr = '\0'; + return; + } + } + *deststr = '\0'; + return; +} diff --git a/src/cmd/emg/tcap.c b/src/cmd/emg/tcap.c new file mode 100644 index 0000000..522833d --- /dev/null +++ b/src/cmd/emg/tcap.c @@ -0,0 +1,117 @@ +/* This file is in the public domain. */ + +/* termios video driver */ + +#define termdef 1 /* don't define "term" externally */ + +#include /* puts(3), snprintf(3) */ +#include "estruct.h" +#include "edef.h" +#undef CTRL /* Needs to be done here. */ +#include + +extern int tgetent(); +extern char *tgetstr(); +extern char *tgoto(); +extern void tputs(); + +extern char *getenv(); +extern void ttopen(); +extern int ttgetc(); +extern void ttputc(); +extern void ttflush(); +extern void ttclose(); + +extern void panic(); + +void getwinsize(); +void tcapopen(); +void tcapmove(int row, int col); +void tcapeeol(); +void tcapeeop(); +void tcaprev(); +void tcapbeep(); + +#define MARGIN 8 +#define SCRSIZ 64 +#define BEL 0x07 +#define TCAPSLEN 64 + +char tcapbuf[TCAPSLEN]; /* capabilities actually used */ +char *CM, *CE, *CL, *SO, *SE; + +TERM term = { + 0, 0, MARGIN, SCRSIZ, tcapopen, ttclose, ttgetc, ttputc, + ttflush, tcapmove, tcapeeol, tcapeeop, tcapbeep, tcaprev +}; + +void getwinsize() +{ + int cols = FORCE_COLS; + int rows = FORCE_ROWS; + + /* Too small and we're out */ + if ((cols < 10) || (rows < 3)) + panic("Too few columns or rows"); + + if (FORCE_COLS > MAXCOL) + cols = MAXCOL; + if (FORCE_ROWS > MAXROW) + rows = MAXROW; + + term.t_ncol = cols; + term.t_nrow = rows - 1; +} + +void tcapopen() +{ + char tcbuf[1024]; + char *p, *tv_stype; + + if ((tv_stype = getenv("TERM")) == NULL) + panic("TERM not defined"); + if ((tgetent(tcbuf, tv_stype)) != 1) + panic("Unknown terminal type"); + p = tcapbuf; + CL = tgetstr("cl", &p); + CM = tgetstr("cm", &p); + CE = tgetstr("ce", &p); + SE = tgetstr("se", &p); + SO = tgetstr("so", &p); + + if (CE == NULL) + eolexist = FALSE; + if (SO != NULL && SE != NULL) + revexist = TRUE; + if (CL == NULL || CM == NULL) + panic("Need cl & cm abilities"); + if (p >= &tcapbuf[TCAPSLEN]) /* XXX */ + panic("Description too big"); + ttopen (); +} + +void tcaprev(int state) +{ + if (revexist) + tputs((state ? SO : SE), 1, ttputc); +} + +void tcapmove (int row, int col) +{ + tputs(tgoto(CM, col, row), 1, ttputc); +} + +void tcapeeol() +{ + tputs(CE, 1, ttputc); +} + +void tcapeeop() +{ + tputs(CL, 1, ttputc); +} + +void tcapbeep() +{ + ttputc(BEL); +} diff --git a/src/cmd/emg/ttyio.c b/src/cmd/emg/ttyio.c new file mode 100644 index 0000000..f94e26e --- /dev/null +++ b/src/cmd/emg/ttyio.c @@ -0,0 +1,163 @@ +/* This file is in the public domain. */ + +/* + * This file comes from mg1a. + * Uses the panic function from OpenBSD's mg. + */ + +/* + * Ultrix-32 and Unix terminal I/O. + * The functions in this file + * negotiate with the operating system for + * keyboard characters, and write characters to + * the display in a barely buffered fashion. + */ + +#include +#include +#include +#include +#include +#undef CTRL +#include "estruct.h" + +void ttflush(void); +void panic(char *); + +extern void getwinsize(); + +#define NROW 66 /* Rows. */ +#define NCOL 132 /* Columns. */ +#define NOBUF 512 /* Output buffer size. */ + +char obuf[NOBUF]; /* Output buffer. */ +int nobuf; +struct sgttyb oldtty; /* V6/V7 stty data. */ +struct sgttyb newtty; +struct tchars oldtchars; /* V7 editing. */ +struct tchars newtchars; +struct ltchars oldltchars; /* 4.2 BSD editing. */ +struct ltchars newltchars; + +/* + * This function gets called once, to set up + * the terminal channel. + */ +void ttopen(void) { + register char *tv_stype; + char *getenv(), *tgetstr(), tcbuf[1024]; + + if (ioctl(0, TIOCGETP, (char *) &oldtty) < 0) + panic("ttopen can't get sgtty"); + newtty.sg_ospeed = oldtty.sg_ospeed; + newtty.sg_ispeed = oldtty.sg_ispeed; + newtty.sg_erase = oldtty.sg_erase; + newtty.sg_kill = oldtty.sg_kill; + newtty.sg_flags = oldtty.sg_flags; + newtty.sg_flags &= ~(ECHO|CRMOD); /* Kill echo, CR=>NL. */ + newtty.sg_flags |= RAW|ANYP; /* raw mode for 8 bit path.*/ + if (ioctl(0, TIOCSETP, (char *) &newtty) < 0) + panic("ttopen can't set sgtty"); + if (ioctl(0, TIOCGETC, (char *) &oldtchars) < 0) + panic("ttopen can't get chars"); + newtchars.t_intrc = 0xFF; /* Interrupt. */ + newtchars.t_quitc = 0xFF; /* Quit. */ + newtchars.t_startc = 0xFF; /* ^Q, for terminal. */ + newtchars.t_stopc = 0xFF; /* ^S, for terminal. */ + newtchars.t_eofc = 0xFF; + newtchars.t_brkc = 0xFF; + if (ioctl(0, TIOCSETC, (char *) &newtchars) < 0) + panic("ttopen can't set chars"); + if (ioctl(0, TIOCGLTC, (char *) &oldltchars) < 0) + panic("ttopen can't get ltchars"); + newltchars.t_suspc = 0xFF; /* Suspend #1. */ + newltchars.t_dsuspc = 0xFF; /* Suspend #2. */ + newltchars.t_rprntc = 0xFF; + newltchars.t_flushc = 0xFF; /* Output flush. */ + newltchars.t_werasc = 0xFF; + newltchars.t_lnextc = 0xFF; /* Literal next. */ + if (ioctl(0, TIOCSLTC, (char *) &newltchars) < 0) + panic("ttopen can't set ltchars"); + +/* do this the REAL way */ + if ((tv_stype = getenv("TERM")) == NULL) + panic("TERM not defined"); + + if((tgetent(tcbuf, tv_stype)) != 1) + panic("Unknown terminal type"); + + getwinsize(); +} + +/* + * This function gets called just + * before we go back home to the shell. Put all of + * the terminal parameters back. + */ +void ttclose(void) { + ttflush(); + if (ioctl(0, TIOCSLTC, (char *) &oldltchars) < 0) + panic("ttclose can't set ltchars"); + if (ioctl(0, TIOCSETC, (char *) &oldtchars) < 0) + panic("ttclose can't set chars"); + if (ioctl(0, TIOCSETP, (char *) &oldtty) < 0) + panic("ttclose can't set sgtty"); +} + +/* + * Write character to the display. + * Characters are buffered up, to make things + * a little bit more efficient. + */ +int ttputc(int c) { + if (nobuf >= NOBUF) + ttflush(); + obuf[nobuf++] = c; + return (c); +} + +/* + * Flush output. + */ +void ttflush(void) { + if (nobuf != 0) { + if (write(1, obuf, nobuf) != nobuf) + panic("ttflush write failed"); + nobuf = 0; + } +} + +/* + * Read character from terminal. + * All 8 bits are returned, so that you can use + * a multi-national terminal. + */ +int ttgetc(void) { + char buf[1]; + + while (read(0, &buf[0], 1) != 1); + return (buf[0] & 0xFF); +} + +/* + * typeahead returns TRUE if there are characters available to be read + * in. + */ +int typeahead(void) { + int x; + + return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x); +} + +/* + * panic - just exit, as quickly as we can. + * From OpenBSD's mg. + */ +void panic(char *s) +{ + ttclose(); + (void) fputs("panic: ", stderr); + (void) fputs(s, stderr); + (void) fputc('\n', stderr); + exit(1); +} diff --git a/src/cmd/emg/window.c b/src/cmd/emg/window.c new file mode 100644 index 0000000..a1e6947 --- /dev/null +++ b/src/cmd/emg/window.c @@ -0,0 +1,336 @@ +/* This file is in the public domain. */ + +/* + * Window management. Some of the functions are internal, and some are + * attached to keys that the user actually types + */ + +#include /* free(3), malloc(3) */ +#include "estruct.h" +#include "edef.h" + +extern void upmode(); +extern void mlwrite(); + +int refresh(int f, int n); +int nextwind(int f, int n); +int prevwind(int f, int n); +int onlywind(int f, int n); +int splitwind(int f, int n); +int enlargewind(int f, int n); +int shrinkwind(int f, int n); +WINDOW* wpopup(); + +/* + * Refresh the screen. With no argument, it does the refresh and centers + * the cursor on the screen. With an argument it does a reposition instead. + * Bound to "C-L" + */ +int refresh(int f, int n) +{ + if (n >= 0) + n++; /* adjust to screen row */ + if (f == FALSE) + { + sgarbf = TRUE; + n = 0; /* Center dot */ + } + curwp->w_force = n; + curwp->w_flag |= WFFORCE; + return (TRUE); +} + +/* + * The command make the next window (next => down the screen) the current + * window. There are no real errors, although the command does nothing if + * there is only 1 window on the screen. Bound to "C-X C-N" + */ +int nextwind(int f, int n) +{ + WINDOW *wp; + + if ((wp = curwp->w_wndp) == NULL) + wp = wheadp; + + curwp = wp; + curbp = wp->w_bufp; + upmode(); + return (TRUE); +} + +/* + * This command makes the previous window (previous => up the screen) the + * current window. There arn't any errors, although the command does not do a + * lot if there is 1 window + */ +int prevwind(int f, int n) +{ + WINDOW *wp1, *wp2; + + wp1 = wheadp; + wp2 = curwp; + + if (wp1 == wp2) + wp2 = NULL; + + while (wp1->w_wndp != wp2) + wp1 = wp1->w_wndp; + + curwp = wp1; + curbp = wp1->w_bufp; + upmode(); + return (TRUE); +} + +/* + * This command makes the current window the only window on the screen. Bound + * to "C-X 1". Try to set the framing so that "." does not have to move on the + * display. Some care has to be taken to keep the values of dot and mark in + * the buffer structures right if the distruction of a window makes a buffer + * become undisplayed + */ +int onlywind(int f, int n) +{ + WINDOW *wp; + LINE *lp; + int i; + + while (wheadp != curwp) + { + wp = wheadp; + wheadp = wp->w_wndp; + if (--wp->w_bufp->b_nwnd == 0) + { + wp->w_bufp->b_dotp = wp->w_dotp; + wp->w_bufp->b_doto = wp->w_doto; + wp->w_bufp->b_markp = wp->w_markp; + wp->w_bufp->b_marko = wp->w_marko; + } + free((char *) wp); + } + while (curwp->w_wndp != NULL) + { + wp = curwp->w_wndp; + curwp->w_wndp = wp->w_wndp; + if (--wp->w_bufp->b_nwnd == 0) + { + wp->w_bufp->b_dotp = wp->w_dotp; + wp->w_bufp->b_doto = wp->w_doto; + wp->w_bufp->b_markp = wp->w_markp; + wp->w_bufp->b_marko = wp->w_marko; + } + free((char *) wp); + } + lp = curwp->w_linep; + i = curwp->w_toprow; + while (i != 0 && lback (lp) != curbp->b_linep) + { + --i; + lp = lback(lp); + } + curwp->w_toprow = 0; + curwp->w_ntrows = term.t_nrow - 1; + curwp->w_linep = lp; + curwp->w_flag |= WFMODE | WFHARD; + return (TRUE); +} + +/* + * Split the current window. A window smaller than 3 lines cannot be split. + * The only other error that is possible is a "malloc" failure allocating the + * structure for the new window. Bound to "C-X 2" + */ +int splitwind(int f, int n) +{ + LINE *lp; + WINDOW *wp, *wp1, *wp2; + int ntru, ntrl, ntrd; + + if (curwp->w_ntrows < 3) + { + mlwrite("Cannot split a %d line window", curwp->w_ntrows); + return (FALSE); + } + if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) + { + mlwrite("Cannot allocate WINDOW block"); + return (FALSE); + } + ++curbp->b_nwnd; /* Displayed twice */ + wp->w_bufp = curbp; + wp->w_dotp = curwp->w_dotp; + wp->w_doto = curwp->w_doto; + wp->w_markp = curwp->w_markp; + wp->w_marko = curwp->w_marko; + wp->w_flag = 0; + wp->w_force = 0; + ntru = (curwp->w_ntrows - 1) / 2; /* Upper size */ + ntrl = (curwp->w_ntrows - 1) - ntru; /* Lower size */ + lp = curwp->w_linep; + ntrd = 0; + while (lp != curwp->w_dotp) + { + ++ntrd; + lp = lforw(lp); + } + lp = curwp->w_linep; + if (ntrd <= ntru) + { /* Old is upper window */ + if (ntrd == ntru) /* Hit mode line */ + lp = lforw(lp); + curwp->w_ntrows = ntru; + wp->w_wndp = curwp->w_wndp; + curwp->w_wndp = wp; + wp->w_toprow = curwp->w_toprow + ntru + 1; + wp->w_ntrows = ntrl; + } + else + { /* Old is lower window */ + wp1 = NULL; + wp2 = wheadp; + while (wp2 != curwp) + { + wp1 = wp2; + wp2 = wp2->w_wndp; + } + if (wp1 == NULL) + wheadp = wp; + else + wp1->w_wndp = wp; + wp->w_wndp = curwp; + wp->w_toprow = curwp->w_toprow; + wp->w_ntrows = ntru; + ++ntru; /* Mode line */ + curwp->w_toprow += ntru; + curwp->w_ntrows = ntrl; + while (ntru--) + lp = lforw (lp); + } + curwp->w_linep = lp; /* Adjust the top lines */ + wp->w_linep = lp; /* if necessary */ + curwp->w_flag |= WFMODE | WFHARD; + wp->w_flag |= WFMODE | WFHARD; + return (TRUE); +} + +/* + * Enlarge the current window. Find the window that loses space. Make sure it + * is big enough. If so, hack the window descriptions, and ask redisplay to do + * all the hard work. You don't just set "force reframe" because dot would + * move. Bound to "C-X Z" + */ +int enlargewind(int f, int n) +{ + WINDOW *adjwp; + LINE *lp; + int i; + + if (n < 0) + return (shrinkwind(f, -n)); + if (wheadp->w_wndp == NULL) + { + mlwrite("Only one window"); + return (FALSE); + } + if ((adjwp = curwp->w_wndp) == NULL) + { + adjwp = wheadp; + while (adjwp->w_wndp != curwp) + adjwp = adjwp->w_wndp; + } + if (adjwp->w_ntrows <= n) + { + mlwrite("Impossible change"); + return (FALSE); + } + if (curwp->w_wndp == adjwp) + { /* Shrink below */ + lp = adjwp->w_linep; + for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i) + lp = lforw(lp); + adjwp->w_linep = lp; + adjwp->w_toprow += n; + } + else + { /* Shrink above */ + lp = curwp->w_linep; + for (i = 0; i < n && lback(lp) != curbp->b_linep; ++i) + lp = lback(lp); + curwp->w_linep = lp; + curwp->w_toprow -= n; + } + curwp->w_ntrows += n; + adjwp->w_ntrows -= n; + curwp->w_flag |= WFMODE | WFHARD; + adjwp->w_flag |= WFMODE | WFHARD; + return (TRUE); +} + +/* + * Shrink the current window. Find the window that gains space. Hack at the + * window descriptions. Ask the redisplay to do all the hard work + */ +int shrinkwind(int f, int n) +{ + WINDOW *adjwp; + LINE *lp; + int i; + + if (n < 0) + return (enlargewind(f, -n)); + if (wheadp->w_wndp == NULL) + { + mlwrite("Only one window"); + return (FALSE); + } + if ((adjwp = curwp->w_wndp) == NULL) + { + adjwp = wheadp; + while (adjwp->w_wndp != curwp) + adjwp = adjwp->w_wndp; + } + if (curwp->w_ntrows <= n) + { + mlwrite("Impossible change"); + return (FALSE); + } + if (curwp->w_wndp == adjwp) + { /* Grow below */ + lp = adjwp->w_linep; + for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep; ++i) + lp = lback(lp); + adjwp->w_linep = lp; + adjwp->w_toprow -= n; + } + else + { /* Grow above */ + lp = curwp->w_linep; + for (i = 0; i < n && lp != curbp->b_linep; ++i) + lp = lforw(lp); + curwp->w_linep = lp; + curwp->w_toprow += n; + } + curwp->w_ntrows -= n; + adjwp->w_ntrows += n; + curwp->w_flag |= WFMODE | WFHARD; + adjwp->w_flag |= WFMODE | WFHARD; + return (TRUE); +} + +/* + * Pick a window for a pop-up. Split the screen if there is only one window. + * Pick the uppermost window that isn't the current window. An LRU algorithm + * might be better. Return a pointer, or NULL on error + */ +WINDOW* wpopup() +{ + WINDOW *wp; + + if (wheadp->w_wndp == NULL /* Only 1 window */ + && splitwind(FALSE, 0) == FALSE) /* and it won't split */ + return (NULL); + wp = wheadp; /* Find window to use */ + while (wp != NULL && wp == curwp) + wp = wp->w_wndp; + return (wp); +} diff --git a/src/cmd/emg/word.c b/src/cmd/emg/word.c new file mode 100644 index 0000000..4943920 --- /dev/null +++ b/src/cmd/emg/word.c @@ -0,0 +1,90 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file implement commands that work word at a time. + * There are all sorts of word mode commands. If I do any sentence and/or + * paragraph mode commands, they are likely to be put in this file + */ + +#include "estruct.h" +#include "edef.h" + +extern int backchar(int f, int n); +extern int forwchar(int f, int n); + +int backword(int f, int n); +int forwword(int f, int n); +int inword(void); + +/* + * Move the cursor backward by "n" words. All of the details of motion are + * performed by the "backchar" and "forwchar" routines. Error if you try to + * move beyond the buffers + */ +int backword(int f, int n) +{ + if (n < 0) + return (forwword(f, -n)); + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + while (n--) + { + while (inword() == FALSE) + { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() != FALSE) + { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (forwchar(FALSE, 1)); +} + +/* + * Move the cursor forward by the specified number of words. All of the motion + * is done by "forwchar". Error if you try and move beyond the buffer's end + */ +int forwword(int f, int n) +{ + if (n < 0) + return (backword(f, -n)); + while (n--) + { + while (inword() != FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() == FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (TRUE); +} + +/* + * Return TRUE if the character at dot is a character that is considered to be + * part of a word. The word character list is hard coded. Should be setable + */ +int inword(void) +{ + int c; + + if (curwp->w_doto == llength(curwp->w_dotp)) + return (FALSE); + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (c >= 'a' && c <= 'z') + return (TRUE); + if (c >= 'A' && c <= 'Z') + return (TRUE); + if (c >= '0' && c <= '9') + return (TRUE); + if (c == '$' || c == '_') /* For identifiers */ + return (TRUE); + return (FALSE); +} diff --git a/src/cmd/smlrc/smlrc.c b/src/cmd/smlrc/smlrc.c index 987bcd2..87360b7 100644 --- a/src/cmd/smlrc/smlrc.c +++ b/src/cmd/smlrc/smlrc.c @@ -6401,7 +6401,6 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label) int hasInit = tok == '='; int needsGlobalInit = isGlobal & !external; int sz = GetDeclSize(lastSyntaxPtr, 0); - int localAllocSize = 0; int skipLabel = 0; int initLabel = 0; @@ -6525,7 +6524,6 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label) // update its offset in the offset token SyntaxStack[lastSyntaxPtr + 1][1] = CurFxnLocalOfs; - localAllocSize = oldOfs - CurFxnLocalOfs; if (CurFxnMinLocalOfs > CurFxnLocalOfs) CurFxnMinLocalOfs = CurFxnLocalOfs; @@ -6878,7 +6876,9 @@ void AddFxnParamSymbols(int SyntaxPtr) if (tok == tokIdent) { int sz; +#ifndef NO_ANNOTATIONS int paramPtr; +#endif if (i + 1 >= SyntaxStackCnt) //error("Internal error: AddFxnParamSymbols(): Invalid input\n"); @@ -6896,7 +6896,9 @@ void AddFxnParamSymbols(int SyntaxPtr) // Let's calculate this parameter's relative on-stack location CurFxnParamOfs = (CurFxnParamOfs + SizeOfWord - 1) / SizeOfWord * SizeOfWord; +#ifndef NO_ANNOTATIONS paramPtr = SyntaxStackCnt; +#endif PushSyntax2(SyntaxStack[i][0], SyntaxStack[i][1]); PushSyntax2(tokLocalOfs, CurFxnParamOfs); CurFxnParamOfs += sz; diff --git a/src/cmd/smux/Makefile b/src/cmd/smux/Makefile index 24ba798..1adc829 100644 --- a/src/cmd/smux/Makefile +++ b/src/cmd/smux/Makefile @@ -1,10 +1,10 @@ all: - make -C retro - make -C linux + ${MAKE} -C retro + ${MAKE} -C linux install: - make -C retro install + ${MAKE} -C retro install clean: - make -C retro clean - make -C linux clean + ${MAKE} -C retro clean + ${MAKE} -C linux clean diff --git a/src/cmd/tip/Makefile b/src/cmd/tip/Makefile index bbccde6..ff6cde3 100644 --- a/src/cmd/tip/Makefile +++ b/src/cmd/tip/Makefile @@ -68,18 +68,18 @@ acutab.o: acutab.c log.o remote.o: Makefile aculib: FRC - cd aculib; make ${MFLAGS} + cd aculib; ${MAKE} ${MFLAGS} clean: FRC rm -f ${OBJS} core tip tip.elf tip.dis - cd aculib; make ${MFLAGS} clean + cd aculib; ${MAKE} ${MFLAGS} clean depend: FRC mkdep ${CFLAGS} ${SRCS} - cd aculib; make ${MFLAGS} depend + cd aculib; ${MAKE} ${MFLAGS} depend install: aculib tip - cd aculib; make ${MFLAGS} install + cd aculib; ${MAKE} ${MFLAGS} install cp tip ${DESTDIR}/bin/tip rm -f ${DESTDIR}/bin/cu touch ${DESTDIR}/${ADM}/aculog diff --git a/src/cmd/uucp/Makefile b/src/cmd/uucp/Makefile index 3923691..fde7bb8 100644 --- a/src/cmd/uucp/Makefile +++ b/src/cmd/uucp/Makefile @@ -44,7 +44,7 @@ SUBDIRS=C. D.${HOSTNAME}X D.${HOSTNAME} D. X. TM. all: libacu $(ALL) libacu: - cd aculib && make + cd aculib && ${MAKE} uuencode: uuencode.o @@ -136,7 +136,7 @@ install: uuencode uuencode clean: rm -f *.o $(ALL) libuucp.a *.dis *.elf - cd aculib; make ${MFLAGS} clean + cd aculib; ${MAKE} ${MFLAGS} clean depend: mkdep ${CFLAGS} *.c diff --git a/src/games/Makefile b/src/games/Makefile index 45e87b3..4c7e678 100644 --- a/src/games/Makefile +++ b/src/games/Makefile @@ -42,7 +42,7 @@ FRC: install: $(STD) $(NSTD) -for i in $(SUBDIR); do \ - make -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) install; done + ${MAKE} -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) install; done -for i in $(STD) $(NSTD); do \ install $$i $(DESTDIR)/games/$$i; done -for i in *.6; do \ @@ -52,7 +52,7 @@ install: $(STD) $(NSTD) clean: rm -f a.out core *.s *.o *.dis *.elf $(STD) $(NSTD) - -for i in $(SUBDIR); do make -C $$i $(MFLAGS) clean; done + -for i in $(SUBDIR); do ${MAKE} -C $$i $(MFLAGS) clean; done # Files listed in $(NSTD) have explicit make lines given below. diff --git a/src/libc/Makefile b/src/libc/Makefile index 3d0c081..44cf99f 100644 --- a/src/libc/Makefile +++ b/src/libc/Makefile @@ -40,7 +40,7 @@ all: ../libc.a rm -rf tmp ${ALL}: FRC - cd $@; make ${MFLAGS} DEFS="${DEFS}" + cd $@; ${MAKE} ${MFLAGS} DEFS="${DEFS}" FRC: @@ -51,9 +51,9 @@ install: ../libc.a clean: for i in ${ALL}; \ - do (cd $$i; make ${MFLAGS} clean); done + do (cd $$i; ${MAKE} ${MFLAGS} clean); done rm -rf tmp *.a *~ depend: for i in ${ALL}; \ - do (cd $$i; make ${MFLAGS} DEFS="${DEFS}" depend); done + do (cd $$i; ${MAKE} ${MFLAGS} DEFS="${DEFS}" depend); done diff --git a/src/libc/gen/modff.c b/src/libc/gen/modff.c index 7eeac60..0595a33 100644 --- a/src/libc/gen/modff.c +++ b/src/libc/gen/modff.c @@ -1,9 +1,9 @@ /* * Written by Serge Vakulenko . * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. */ #include @@ -11,8 +11,6 @@ * modff(float x, float *iptr) * return fraction part of x, and return x's integral part in *iptr. */ -static const float one = 1.0; - float modff (float fx, float *iptr) { union { diff --git a/src/libc/mips/Makefile b/src/libc/mips/Makefile index 87fb931..a62fcda 100644 --- a/src/libc/mips/Makefile +++ b/src/libc/mips/Makefile @@ -17,19 +17,19 @@ mips.a: ${ALL} rm -rf tmp ${ALL}: FRC - cd $@; make ${MFLAGS} DEFS=${DEFS} + cd $@; ${MAKE} ${MFLAGS} DEFS=${DEFS} FRC: tags: for i in ${ALL}; do \ - (cd $$i; make ${MFLAGS} TAGSFILE=../${TAGSFILE} tags); \ + (cd $$i; ${MAKE} ${MFLAGS} TAGSFILE=../${TAGSFILE} tags); \ done clean: - for i in ${ALL}; do (cd $$i; make ${MFLAGS} clean); done + for i in ${ALL}; do (cd $$i; ${MAKE} ${MFLAGS} clean); done rm -rf *.a tmp *~ depend: for i in ${ALL}; do \ - (cd $$i; make ${MFLAGS} DEFS=${DEFS} depend); done + (cd $$i; ${MAKE} ${MFLAGS} DEFS=${DEFS} depend); done diff --git a/src/libtermlib/Makefile b/src/libtermlib/Makefile index 386f77b..5614e26 100644 --- a/src/libtermlib/Makefile +++ b/src/libtermlib/Makefile @@ -26,7 +26,7 @@ all: ../libtermcap.a termcap .PHONY: termcap termcap: - cd termcap && make + cd termcap && ${MAKE} ../libtermcap.a: ${OBJS} $(AR) cr ../libtermcap.a ${OBJS} diff --git a/src/share/Makefile b/src/share/Makefile index bd0a113..34ce823 100644 --- a/src/share/Makefile +++ b/src/share/Makefile @@ -11,14 +11,14 @@ SUBDIR = misc all: ${SUBDIR} ${SUBDIR}: FRC - cd $@; make ${MFLAGS} + cd $@; ${MAKE} ${MFLAGS} FRC: install: FRC -for i in ${SUBDIR}; do \ - (cd $$i; make ${MFLAGS} DESTDIR=${DESTDIR} install); done + (cd $$i; ${MAKE} ${MFLAGS} DESTDIR=${DESTDIR} install); done clean: rm -f *~ - for i in ${SUBDIR}; do (cd $$i; make ${MFLAGS} clean); done + for i in ${SUBDIR}; do (cd $$i; ${MAKE} ${MFLAGS} clean); done diff --git a/sys/include/fonts/default.h b/sys/include/fonts/default.h new file mode 100644 index 0000000..fe80ee6 --- /dev/null +++ b/sys/include/fonts/default.h @@ -0,0 +1,259 @@ +const unsigned char Default[] = { + 0x08, 0x01, 0x00, 0xFF, 1, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x0E, 0x1F, 0x15, 0x1F, 0x1B, 0x11, 0x0E, 0x00, + 0x06, 0x0E, 0x1F, 0x15, 0x1F, 0x11, 0x1B, 0x0E, 0x00, + 0x06, 0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0E, 0x04, 0x00, + 0x06, 0x00, 0x04, 0x0E, 0x1F, 0x1F, 0x0E, 0x04, 0x00, + 0x06, 0x0E, 0x0A, 0x1F, 0x15, 0x1F, 0x04, 0x0E, 0x00, + 0x06, 0x04, 0x0E, 0x1F, 0x1F, 0x1F, 0x04, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x04, 0x0E, 0x0E, 0x04, 0x00, 0x00, + 0x06, 0x1F, 0x1F, 0x1B, 0x11, 0x11, 0x1B, 0x1F, 0x1F, + 0x06, 0x00, 0x00, 0x04, 0x0A, 0x0A, 0x04, 0x00, 0x00, + 0x06, 0x1F, 0x1F, 0x1B, 0x15, 0x15, 0x1B, 0x1F, 0x1F, + 0x06, 0x00, 0x1C, 0x18, 0x16, 0x05, 0x05, 0x02, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x0E, 0x04, 0x1F, 0x04, 0x00, + 0x06, 0x1E, 0x12, 0x1E, 0x02, 0x02, 0x02, 0x03, 0x00, + 0x06, 0x1E, 0x12, 0x1E, 0x12, 0x12, 0x1A, 0x03, 0x00, + 0x06, 0x04, 0x15, 0x0E, 0x1B, 0x1B, 0x0E, 0x15, 0x04, + 0x06, 0x01, 0x03, 0x0F, 0x1F, 0x0F, 0x03, 0x01, 0x00, + 0x06, 0x10, 0x18, 0x1E, 0x1F, 0x1E, 0x18, 0x10, 0x00, + 0x06, 0x04, 0x0E, 0x15, 0x04, 0x15, 0x0E, 0x04, 0x00, + 0x06, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x1B, 0x00, + 0x06, 0x1E, 0x15, 0x15, 0x16, 0x14, 0x14, 0x14, 0x00, + 0x06, 0x0C, 0x12, 0x0A, 0x14, 0x08, 0x12, 0x12, 0x0C, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, + 0x06, 0x04, 0x0E, 0x15, 0x04, 0x15, 0x0E, 0x04, 0x1F, + 0x06, 0x00, 0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x00, 0x04, 0x04, 0x04, 0x15, 0x0E, 0x04, 0x00, + 0x06, 0x00, 0x04, 0x08, 0x1F, 0x08, 0x04, 0x00, 0x00, + 0x06, 0x00, 0x04, 0x02, 0x1F, 0x02, 0x04, 0x00, 0x00, + 0x06, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x0A, 0x1F, 0x1F, 0x0A, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x04, 0x04, 0x0E, 0x1F, 0x1F, 0x00, 0x00, + 0x06, 0x00, 0x1F, 0x1F, 0x0E, 0x04, 0x04, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, + 0x06, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x0A, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x0A, 0x00, + 0x06, 0x04, 0x1E, 0x05, 0x0E, 0x14, 0x0F, 0x04, 0x00, + 0x06, 0x03, 0x13, 0x08, 0x04, 0x02, 0x19, 0x18, 0x00, + 0x06, 0x02, 0x05, 0x05, 0x02, 0x15, 0x09, 0x16, 0x00, + 0x06, 0x0C, 0x0C, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, + 0x06, 0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02, 0x00, + 0x06, 0x04, 0x15, 0x0E, 0x1F, 0x0E, 0x15, 0x04, 0x00, + 0x06, 0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x04, 0x02, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, + 0x06, 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, + 0x06, 0x0E, 0x11, 0x19, 0x15, 0x13, 0x11, 0x0E, 0x00, + 0x06, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, + 0x06, 0x0E, 0x11, 0x10, 0x0E, 0x01, 0x01, 0x1F, 0x00, + 0x06, 0x1F, 0x10, 0x08, 0x0C, 0x10, 0x11, 0x0E, 0x00, + 0x06, 0x08, 0x0C, 0x0A, 0x09, 0x1F, 0x08, 0x08, 0x00, + 0x06, 0x1F, 0x01, 0x0F, 0x10, 0x10, 0x11, 0x0E, 0x00, + 0x06, 0x1C, 0x02, 0x01, 0x0F, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x1F, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x1E, 0x10, 0x08, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x02, 0x00, + 0x06, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, + 0x06, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, 0x00, + 0x06, 0x0E, 0x11, 0x10, 0x0C, 0x04, 0x00, 0x04, 0x00, + 0x06, 0x0E, 0x11, 0x15, 0x1D, 0x0D, 0x01, 0x1E, 0x00, + 0x06, 0x04, 0x0A, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x00, + 0x06, 0x0F, 0x11, 0x11, 0x0F, 0x11, 0x11, 0x0F, 0x00, + 0x06, 0x0E, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0E, 0x00, + 0x06, 0x0F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0F, 0x00, + 0x06, 0x1F, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x1F, 0x00, + 0x06, 0x1F, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x01, 0x00, + 0x06, 0x1E, 0x11, 0x01, 0x01, 0x19, 0x11, 0x1E, 0x00, + 0x06, 0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11, 0x00, + 0x06, 0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, + 0x06, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06, 0x00, + 0x06, 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11, 0x00, + 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x00, + 0x06, 0x11, 0x1B, 0x15, 0x15, 0x15, 0x11, 0x11, 0x00, + 0x06, 0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x0F, 0x11, 0x11, 0x0F, 0x01, 0x01, 0x01, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x11, 0x15, 0x09, 0x16, 0x00, + 0x06, 0x0F, 0x11, 0x11, 0x0F, 0x05, 0x09, 0x11, 0x00, + 0x06, 0x0E, 0x11, 0x01, 0x0E, 0x10, 0x11, 0x0E, 0x00, + 0x06, 0x1F, 0x15, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04, 0x00, + 0x06, 0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0A, 0x00, + 0x06, 0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11, 0x00, + 0x06, 0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x1F, 0x10, 0x08, 0x0E, 0x02, 0x01, 0x1F, 0x00, + 0x06, 0x1E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x1E, 0x00, + 0x06, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, + 0x06, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00, + 0x06, 0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x06, 0x06, 0x06, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x01, 0x01, 0x0D, 0x13, 0x11, 0x13, 0x0D, 0x00, + 0x06, 0x00, 0x00, 0x0E, 0x11, 0x01, 0x11, 0x0E, 0x00, + 0x06, 0x10, 0x10, 0x16, 0x19, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x00, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x0E, 0x00, + 0x06, 0x08, 0x14, 0x04, 0x0E, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x0E, 0x19, 0x19, 0x16, 0x10, 0x0E, + 0x06, 0x01, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x11, 0x00, + 0x06, 0x04, 0x00, 0x06, 0x04, 0x04, 0x04, 0x0E, 0x00, + 0x06, 0x08, 0x00, 0x08, 0x08, 0x08, 0x09, 0x06, 0x00, + 0x06, 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00, + 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x0B, 0x15, 0x15, 0x15, 0x15, 0x00, + 0x06, 0x00, 0x00, 0x0D, 0x13, 0x11, 0x11, 0x11, 0x00, + 0x06, 0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x0D, 0x13, 0x13, 0x0D, 0x01, 0x01, + 0x06, 0x00, 0x00, 0x16, 0x19, 0x19, 0x16, 0x10, 0x10, + 0x06, 0x00, 0x00, 0x0D, 0x13, 0x01, 0x01, 0x01, 0x00, + 0x06, 0x00, 0x00, 0x1E, 0x01, 0x0E, 0x10, 0x0F, 0x00, + 0x06, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x14, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0A, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x11, 0x15, 0x15, 0x0A, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x11, 0x1E, 0x10, 0x11, 0x0E, + 0x06, 0x00, 0x00, 0x1F, 0x08, 0x04, 0x02, 0x1F, 0x00, + 0x06, 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, + 0x06, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x02, 0x04, 0x04, 0x08, 0x04, 0x04, 0x02, 0x00, + 0x06, 0x02, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x0E, 0x1B, 0x11, 0x11, 0x1F, 0x00, 0x00, + 0x06, 0x0E, 0x11, 0x01, 0x01, 0x11, 0x0E, 0x08, 0x06, + 0x06, 0x00, 0x11, 0x00, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x18, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x1E, 0x00, + 0x06, 0x1F, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x11, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x03, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x0C, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x08, 0x0C, 0x00, + 0x06, 0x1F, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x1E, 0x00, + 0x06, 0x11, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x1E, 0x00, + 0x06, 0x03, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x1E, 0x00, + 0x06, 0x14, 0x00, 0x0C, 0x08, 0x08, 0x08, 0x1C, 0x00, + 0x06, 0x0C, 0x12, 0x0C, 0x08, 0x08, 0x08, 0x1C, 0x00, + 0x06, 0x06, 0x00, 0x0C, 0x08, 0x08, 0x08, 0x1C, 0x00, + 0x06, 0x0A, 0x00, 0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, + 0x06, 0x04, 0x00, 0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, + 0x06, 0x0C, 0x00, 0x0F, 0x01, 0x07, 0x01, 0x0F, 0x00, + 0x06, 0x00, 0x00, 0x1E, 0x08, 0x1E, 0x09, 0x1E, 0x00, + 0x06, 0x1C, 0x0A, 0x09, 0x1F, 0x09, 0x09, 0x19, 0x00, + 0x06, 0x0E, 0x11, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x11, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x03, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x0E, 0x11, 0x00, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x00, 0x03, 0x00, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x12, 0x00, 0x12, 0x12, 0x12, 0x1C, 0x10, 0x0E, + 0x06, 0x11, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x11, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x04, 0x04, 0x1F, 0x05, 0x05, 0x1F, 0x04, 0x04, + 0x06, 0x0C, 0x1A, 0x12, 0x07, 0x02, 0x12, 0x1F, 0x00, + 0x06, 0x1B, 0x1B, 0x0E, 0x1F, 0x04, 0x1F, 0x04, 0x04, + 0x06, 0x07, 0x09, 0x09, 0x07, 0x09, 0x1D, 0x09, 0x09, + 0x06, 0x18, 0x14, 0x04, 0x0E, 0x04, 0x04, 0x05, 0x03, + 0x06, 0x18, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x18, 0x00, 0x0C, 0x08, 0x08, 0x08, 0x1C, 0x00, + 0x06, 0x00, 0x18, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x18, 0x00, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x00, 0x1E, 0x00, 0x0E, 0x12, 0x12, 0x12, 0x00, + 0x06, 0x1F, 0x00, 0x13, 0x17, 0x1D, 0x19, 0x11, 0x00, + 0x06, 0x0E, 0x09, 0x09, 0x1E, 0x00, 0x1F, 0x00, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x0E, 0x00, 0x1F, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x04, 0x06, 0x01, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x00, 0x00, + 0x06, 0x01, 0x11, 0x09, 0x1D, 0x12, 0x19, 0x04, 0x1C, + 0x06, 0x01, 0x11, 0x09, 0x15, 0x1A, 0x1D, 0x10, 0x10, + 0x06, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x00, 0x14, 0x0A, 0x05, 0x0A, 0x14, 0x00, 0x00, + 0x06, 0x00, 0x05, 0x0A, 0x14, 0x0A, 0x05, 0x00, 0x00, + 0x06, 0x04, 0x11, 0x04, 0x11, 0x04, 0x11, 0x04, 0x11, + 0x06, 0x0A, 0x15, 0x0A, 0x15, 0x0A, 0x15, 0x0A, 0x15, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x0F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08, 0x08, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14, + 0x06, 0x00, 0x00, 0x0F, 0x08, 0x0F, 0x08, 0x08, 0x08, + 0x06, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x06, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x18, 0x08, 0x08, 0x08, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x1F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x18, 0x08, 0x18, 0x08, 0x08, 0x08, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x04, 0x1C, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x1C, 0x04, 0x14, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x17, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x1F, 0x00, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x04, 0x14, 0x14, 0x14, 0x14, + 0x06, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x14, 0x14, 0x17, 0x00, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x08, 0x08, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x08, 0x08, 0x08, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x1C, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x08, 0x18, 0x08, 0x18, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x18, 0x08, 0x18, 0x08, 0x08, 0x08, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x1F, 0x14, 0x14, 0x14, + 0x06, 0x08, 0x08, 0x1F, 0x08, 0x1F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x0F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, + 0x06, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, + 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x06, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x06, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x16, 0x09, 0x09, 0x09, 0x16, 0x00, + 0x06, 0x00, 0x0E, 0x19, 0x0F, 0x19, 0x0F, 0x01, 0x00, + 0x06, 0x00, 0x1F, 0x19, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x06, 0x00, 0x1F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + 0x06, 0x1F, 0x11, 0x02, 0x04, 0x02, 0x11, 0x1F, 0x00, + 0x06, 0x00, 0x00, 0x1E, 0x09, 0x09, 0x09, 0x06, 0x00, + 0x06, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x16, 0x03, 0x00, + 0x06, 0x00, 0x1F, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x1F, 0x04, 0x0E, 0x11, 0x11, 0x0E, 0x04, 0x1F, + 0x06, 0x04, 0x0A, 0x11, 0x1F, 0x11, 0x0A, 0x04, 0x00, + 0x06, 0x04, 0x0A, 0x11, 0x11, 0x0A, 0x0A, 0x1B, 0x00, + 0x06, 0x0C, 0x02, 0x0C, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x15, 0x15, 0x0E, 0x00, + 0x06, 0x10, 0x0E, 0x19, 0x15, 0x15, 0x13, 0x0E, 0x01, + 0x06, 0x0E, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x0E, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, + 0x06, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, + 0x06, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x1F, 0x00, + 0x06, 0x02, 0x04, 0x08, 0x04, 0x02, 0x00, 0x1F, 0x00, + 0x06, 0x08, 0x04, 0x02, 0x04, 0x08, 0x00, 0x1F, 0x00, + 0x06, 0x1C, 0x14, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x07, + 0x06, 0x0C, 0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x0C, 0x00, + 0x06, 0x00, 0x17, 0x1D, 0x00, 0x17, 0x1D, 0x00, 0x00, + 0x06, 0x0E, 0x1B, 0x1B, 0x0E, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x06, 0x1C, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x04, + 0x06, 0x0E, 0x12, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, + 0x06, 0x0E, 0x18, 0x0C, 0x06, 0x1E, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + diff --git a/sys/include/fonts/topaz.h b/sys/include/fonts/topaz.h new file mode 100644 index 0000000..c2f576c --- /dev/null +++ b/sys/include/fonts/topaz.h @@ -0,0 +1,2307 @@ +const unsigned char Topaz[] = { + 0x08, 0x01, 0x00, 0xFF, 1, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b01111110, + 0b10000001, + 0b10100101, + 0b10000001, + 0b10111101, + 0b10011001, + 0b10000001, + 0b01111110, + 0x08, + 0b01111110, + 0b11111111, + 0b11011011, + 0b11111111, + 0b11000011, + 0b11100111, + 0b11111111, + 0b01111110, + 0x08, + 0b00110110, + 0b01111111, + 0b01111111, + 0b01111111, + 0b00111110, + 0b00011100, + 0b00001000, + 0b00000000, + 0x08, + 0b00001000, + 0b00011100, + 0b00111110, + 0b01111111, + 0b00111110, + 0b00011100, + 0b00001000, + 0b00000000, + 0x08, + 0b00011100, + 0b00111110, + 0b00011100, + 0b01111111, + 0b01111111, + 0b01101011, + 0b00001000, + 0b00011100, + 0x08, + 0b00001000, + 0b00001000, + 0b00011100, + 0b00111110, + 0b01111111, + 0b00111110, + 0b00001000, + 0b00011100, + 0x08, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00111100, + 0b00111100, + 0b00011000, + 0b00000000, + 0b00000000, + 0x08, + 0b11111111, + 0b11111111, + 0b11100111, + 0b11000011, + 0b11000011, + 0b11100111, + 0b11111111, + 0b11111111, + 0x08, + 0b00000000, + 0b00111100, + 0b01100110, + 0b01000010, + 0b01000010, + 0b01100110, + 0b00111100, + 0b00000000, + 0x08, + 0b11111111, + 0b11000011, + 0b10011001, + 0b10111101, + 0b10111101, + 0b10011001, + 0b11000011, + 0b11111111, + 0x08, + 0b11110000, + 0b11100000, + 0b11110000, + 0b10111110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0x08, + 0b00111100, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00011000, + 0b01111110, + 0b00011000, + 0x08, + 0b11111100, + 0b11001100, + 0b11111100, + 0b00001100, + 0b00001100, + 0b00001110, + 0b00001111, + 0b00000111, + 0x08, + 0b11111110, + 0b11000110, + 0b11111110, + 0b11000110, + 0b11000110, + 0b11100110, + 0b01100111, + 0b00000011, + 0x08, + 0b10011001, + 0b01011010, + 0b00111100, + 0b11100111, + 0b11100111, + 0b00111100, + 0b01011010, + 0b10011001, + 0x08, + 0b00000001, + 0b00000111, + 0b00011111, + 0b01111111, + 0b00011111, + 0b00000111, + 0b00000001, + 0b00000000, + 0x08, + 0b01000000, + 0b01110000, + 0b01111100, + 0b01111111, + 0b01111100, + 0b01110000, + 0b01000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00111100, + 0b01111110, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00111100, + 0b00011000, + 0x08, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00000000, + 0b01100110, + 0b00000000, + 0x08, + 0b11111110, + 0b11011011, + 0b11011011, + 0b11011110, + 0b11011000, + 0b11011000, + 0b11011000, + 0b00000000, + 0x08, + 0b01111110, + 0b11000011, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00110001, + 0b00011111, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111110, + 0b01111110, + 0b01111110, + 0b00000000, + 0x08, + 0b00011000, + 0b00111100, + 0b01111110, + 0b00011000, + 0b01111110, + 0b00111100, + 0b00011000, + 0b11111111, + 0x08, + 0b00011000, + 0b00111100, + 0b01111110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00111100, + 0b00011000, + 0b00000000, + 0x08, + 0b00000000, + 0b00011000, + 0b00110000, + 0b01111111, + 0b00110000, + 0b00011000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00001100, + 0b00000110, + 0b01111111, + 0b00000110, + 0b00001100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000011, + 0b00000011, + 0b00000011, + 0b01111111, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00100100, + 0b01100110, + 0b11111111, + 0b01100110, + 0b00100100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00011000, + 0b00111100, + 0b01111110, + 0b11111111, + 0b11111111, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b11111111, + 0b11111111, + 0b01111110, + 0b00111100, + 0b00011000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00001100, + 0b00011110, + 0b00011110, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00000000, + 0x08, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00110110, + 0b00110110, + 0b01111111, + 0b00110110, + 0b01111111, + 0b00110110, + 0b00110110, + 0b00000000, + 0x08, + 0b00001100, + 0b00111110, + 0b00000011, + 0b00011110, + 0b00110000, + 0b00011111, + 0b00001100, + 0b00000000, + 0x08, + 0b00000000, + 0b01100011, + 0b00110011, + 0b00011000, + 0b00001100, + 0b01100110, + 0b01100011, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b00011100, + 0b01101110, + 0b00111011, + 0b00110011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000110, + 0b00000110, + 0b00000011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00000000, + 0x08, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000000, + 0x08, + 0b00000000, + 0b01100110, + 0b00111100, + 0b11111111, + 0b00111100, + 0b01100110, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00111111, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00000110, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0x08, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b00000001, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00111011, + 0b00111111, + 0b00110111, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00001100, + 0b00001111, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00111111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110000, + 0b00011100, + 0b00000110, + 0b00110011, + 0b00111111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110000, + 0b00011100, + 0b00110000, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00111000, + 0b00111100, + 0b00110110, + 0b00110011, + 0b01111111, + 0b00110000, + 0b00110000, + 0b00000000, + 0x08, + 0b00111111, + 0b00000011, + 0b00011111, + 0b00110000, + 0b00110000, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011100, + 0b00000110, + 0b00000011, + 0b00011111, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00111111, + 0b00110011, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000110, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00011000, + 0b00001110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00000110, + 0x08, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00000000, + 0x08, + 0b00111110, + 0b01100011, + 0b01111011, + 0b01111011, + 0b01111011, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b00001100, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00111111, + 0b01100110, + 0b01100110, + 0b00111110, + 0b01100110, + 0b01100110, + 0b00111111, + 0b00000000, + 0x08, + 0b00111100, + 0b01100110, + 0b00000011, + 0b00000011, + 0b00000011, + 0b01100110, + 0b00111100, + 0b00000000, + 0x08, + 0b00111111, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00110110, + 0b00111111, + 0b00000000, + 0x08, + 0b01111111, + 0b01000110, + 0b00010110, + 0b00011110, + 0b00010110, + 0b01000110, + 0b01111111, + 0b00000000, + 0x08, + 0b01111111, + 0b01000110, + 0b00010110, + 0b00011110, + 0b00010110, + 0b00000110, + 0b00001111, + 0b00000000, + 0x08, + 0b00111100, + 0b01100110, + 0b00000011, + 0b00000011, + 0b01110011, + 0b01100110, + 0b01111100, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00011110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b01111000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b01100111, + 0b01100110, + 0b00110110, + 0b00011110, + 0b00110110, + 0b01100110, + 0b01100111, + 0b00000000, + 0x08, + 0b00001111, + 0b00000110, + 0b00000110, + 0b00000110, + 0b01000110, + 0b01100110, + 0b01111111, + 0b00000000, + 0x08, + 0b01100011, + 0b01110111, + 0b01111111, + 0b01101011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0x08, + 0b01100011, + 0b01100111, + 0b01101111, + 0b01111011, + 0b01110011, + 0b01100011, + 0b01100011, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00000000, + 0x08, + 0b00111111, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111011, + 0b00011110, + 0b00111000, + 0b00000000, + 0x08, + 0b00111111, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00011110, + 0b00110110, + 0b01100111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00000111, + 0b00011100, + 0b00111000, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00111111, + 0b00101101, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00001100, + 0b00000000, + 0x08, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01111111, + 0b01110111, + 0b01100011, + 0b00000000, + 0x08, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b01111111, + 0b00110011, + 0b00011001, + 0b00001100, + 0b01000110, + 0b01100011, + 0b01111111, + 0b00000000, + 0x08, + 0b00011110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00011110, + 0b00000000, + 0x08, + 0b00000011, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00110000, + 0b01100000, + 0b01000000, + 0b00000000, + 0x08, + 0b00011110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011110, + 0b00000000, + 0x08, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0x08, + 0b00001100, + 0b00001100, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000111, + 0b00000110, + 0b00111110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111101, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00000011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00111000, + 0b00110000, + 0b00110000, + 0b00111110, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b00000110, + 0b00001111, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00011111, + 0x08, + 0b00000111, + 0b00000110, + 0b00110110, + 0b01101110, + 0b01100110, + 0b01100110, + 0b01100111, + 0b00000000, + 0x08, + 0b00001100, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00011000, + 0b00000000, + 0b00011110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011011, + 0b00001110, + 0x08, + 0b00000111, + 0b00000110, + 0b01100110, + 0b00110110, + 0b00011110, + 0b00110110, + 0b01100111, + 0b00000000, + 0x08, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00110111, + 0b01111111, + 0b01101011, + 0b01100011, + 0b01100011, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111011, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00001111, + 0x08, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b01111000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011011, + 0b00110110, + 0b00110110, + 0b00000110, + 0b00001111, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111110, + 0b00000011, + 0b00011110, + 0b00110000, + 0b00011111, + 0b00000000, + 0x08, + 0b00001000, + 0b00001100, + 0b00111110, + 0b00001100, + 0b00001100, + 0b00101100, + 0b00011000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00001100, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01111111, + 0b00110110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00110110, + 0b01100011, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00011111, + 0x08, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00011001, + 0b00001100, + 0b00100110, + 0b00111111, + 0b00000000, + 0x08, + 0b00111000, + 0b00001100, + 0b00001100, + 0b00000111, + 0b00001100, + 0b00001100, + 0b00111000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0x08, + 0b00000111, + 0b00001100, + 0b00001100, + 0b00111000, + 0b00001100, + 0b00001100, + 0b00000111, + 0b00000000, + 0x08, + 0b01101110, + 0b00111011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00000011, + 0b00110011, + 0b00011110, + 0b00011000, + 0b00110000, + 0b00011110, + 0x08, + 0b00000000, + 0b00110011, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00111000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b01111110, + 0b11000011, + 0b00111100, + 0b01100000, + 0b01111100, + 0b01100110, + 0b11111100, + 0b00000000, + 0x08, + 0b00110011, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000111, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111110, + 0b00000011, + 0b00000011, + 0b00111110, + 0b01100000, + 0b00111100, + 0x08, + 0b01111110, + 0b11000011, + 0b00111100, + 0b01100110, + 0b01111110, + 0b00000110, + 0b00111100, + 0b00000000, + 0x08, + 0b00110011, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000111, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b00110011, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00111110, + 0b01100011, + 0b00011100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0x08, + 0b00000111, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00110011, + 0b00001100, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00110011, + 0b00000000, + 0x08, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00110011, + 0b00000000, + 0x08, + 0b00111000, + 0b00000000, + 0b00111111, + 0b00000110, + 0b00011110, + 0b00000110, + 0b00111111, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111110, + 0b00110000, + 0b11111110, + 0b00110011, + 0b11111110, + 0b00000000, + 0x08, + 0b01111100, + 0b00110110, + 0b00110011, + 0b01111111, + 0b00110011, + 0b00110011, + 0b01110011, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00110011, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000111, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000111, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000000, + 0b00110011, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00110000, + 0b00011111, + 0x08, + 0b01100011, + 0b00011100, + 0b00111110, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00011100, + 0b00000000, + 0x08, + 0b00110011, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00000011, + 0b00000011, + 0b01111110, + 0b00011000, + 0b00011000, + 0x08, + 0b00011100, + 0b00110110, + 0b00100110, + 0b00001111, + 0b00000110, + 0b01100111, + 0b00111111, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00111111, + 0b00001100, + 0b00111111, + 0b00001100, + 0b00000000, + 0x08, + 0b00001111, + 0b00011011, + 0b00011011, + 0b00101111, + 0b00110011, + 0b01111011, + 0b00110011, + 0b01110000, + 0x08, + 0b01110000, + 0b11011000, + 0b00011000, + 0b01111110, + 0b00011000, + 0b00011000, + 0b00011011, + 0b00001110, + 0x08, + 0b00111000, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00011100, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00111000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00111000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000000, + 0b00011111, + 0b00000000, + 0b00011111, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00111111, + 0b00000000, + 0b00110011, + 0b00110111, + 0b00111111, + 0b00111011, + 0b00110011, + 0b00000000, + 0x08, + 0b00111100, + 0b00110110, + 0b00110110, + 0b01111100, + 0b00000000, + 0b01111110, + 0b00000000, + 0b00000000, + 0x08, + 0b00111100, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00000000, + 0b01111110, + 0b00000000, + 0b00000000, + 0x08, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00000011, + 0b00000011, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00110000, + 0b00110000, + 0b00000000, + 0b00000000, + 0x08, + 0b01100011, + 0b00110011, + 0b00011011, + 0b01111100, + 0b11000110, + 0b01110011, + 0b00011001, + 0b11111000, + 0x08, + 0b01100011, + 0b00110011, + 0b00011011, + 0b11001111, + 0b11100110, + 0b11110011, + 0b11111001, + 0b11000000, + 0x08, + 0b00000000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00111100, + 0b00011000, + 0x08, + 0b00000000, + 0b11001100, + 0b01100110, + 0b00110011, + 0b01100110, + 0b11001100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00110011, + 0b01100110, + 0b11001100, + 0b01100110, + 0b00110011, + 0b00000000, + 0b00000000, + 0x08, + 0b01000100, + 0b00010001, + 0b01000100, + 0b00010001, + 0b01000100, + 0b00010001, + 0b01000100, + 0b00010001, + 0x08, + 0b10101010, + 0b01010101, + 0b10101010, + 0b01010101, + 0b10101010, + 0b01010101, + 0b10101010, + 0b01010101, + 0x08, + 0b00111011, + 0b01101110, + 0b00111011, + 0b01101110, + 0b00111011, + 0b01101110, + 0b00111011, + 0b01101110, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101111, + 0b01100000, + 0b01101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100000, + 0b01101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b01101111, + 0b01100000, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b11101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b11101100, + 0b00001100, + 0b11111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111100, + 0b00001100, + 0b11101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b11101111, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b11101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b11101100, + 0b00001100, + 0b11101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b01101100, + 0b01101100, + 0b11101111, + 0b00000000, + 0b11101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00011000, + 0b00011000, + 0b11111111, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b11111111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b11111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b11101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00011000, + 0b00011000, + 0b11111111, + 0b00000000, + 0b11111111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0x08, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0x08, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0x08, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00111011, + 0b00010011, + 0b00111011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00011111, + 0b00110011, + 0b00011111, + 0b00000011, + 0b00000011, + 0x08, + 0b00000000, + 0b01111111, + 0b01100011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b00000000, + 0x08, + 0b00000000, + 0b01111111, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00000000, + 0x08, + 0b01111111, + 0b01100110, + 0b00001100, + 0b00011000, + 0b00001100, + 0b01100110, + 0b01111111, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01111110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00000011, + 0x08, + 0b00000000, + 0b01101110, + 0b00111011, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0x08, + 0b00111111, + 0b00001100, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00001100, + 0b00111111, + 0x08, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01111111, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00110110, + 0b01110111, + 0b00000000, + 0x08, + 0b00111000, + 0b00001100, + 0b00011000, + 0b00111110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01111110, + 0b11011011, + 0b11011011, + 0b01111110, + 0b00000000, + 0b00000000, + 0x08, + 0b01100000, + 0b00110000, + 0b01111110, + 0b11011011, + 0b11011011, + 0b01111110, + 0b00000110, + 0b00000011, + 0x08, + 0b00111100, + 0b00000110, + 0b00000011, + 0b00111111, + 0b00000011, + 0b00000110, + 0b00111100, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00000000, + 0x08, + 0b00001100, + 0b00001100, + 0b00111111, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00111111, + 0b00000000, + 0x08, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000000, + 0b00111111, + 0b00000000, + 0x08, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00000000, + 0b00111111, + 0b00000000, + 0x08, + 0b01110000, + 0b11011000, + 0b11011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011011, + 0b00011011, + 0b00001110, + 0x08, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0x08, + 0b00000000, + 0b01001110, + 0b00111001, + 0b00000000, + 0b01001110, + 0b00111001, + 0b00000000, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b00110110, + 0b00011100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b11110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110111, + 0b00110110, + 0b00111100, + 0b00111000, + 0x08, + 0b00011110, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011110, + 0b00110000, + 0b00011100, + 0b00000110, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111100, + 0b00111100, + 0b00111100, + 0b00111100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +}; diff --git a/sys/include/fonts/vga.h b/sys/include/fonts/vga.h new file mode 100644 index 0000000..afa0a10 --- /dev/null +++ b/sys/include/fonts/vga.h @@ -0,0 +1,1833 @@ +static const unsigned char vga[] = { + + 16, // lpc + 1, // bpl + 32, // start + 0x7f, // end + 1, // bpp + +// 32 $20 'space' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 33 $21 'exclam' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00111100, + 0b00111100, + 0b00111100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 34 $22 'quotedbl' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00100100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 35 $23 'numbersign' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00110110, + 0b00110110, + 0b01111111, + 0b00110110, + 0b00110110, + 0b00110110, + 0b01111111, + 0b00110110, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 36 $24 'dollar' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00011000, + 0b00011000, + 0b00111110, + 0b01100011, + 0b01000011, + 0b00000011, + 0b00111110, + 0b01100000, + 0b01100000, + 0b01100001, + 0b01100011, + 0b00111110, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, +// 37 $25 'percent' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000011, + 0b01100011, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b01100011, + 0b01100001, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 38 $26 'ampersand' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00110110, + 0b00110110, + 0b00011100, + 0b01101110, + 0b00111011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 39 $27 'quotesingle' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00000100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 40 $28 'parenleft' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011000, + 0b00110000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 41 $29 'parenright' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00011000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 42 $2a 'asterisk' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100110, + 0b00111100, + 0b11111111, + 0b00111100, + 0b01100110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 43 $2b 'plus' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 44 $2c 'comma' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, +// 45 $2d 'hyphen' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 46 $2e 'period' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 47 $2f 'slash' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b00000001, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 48 $30 'zero' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01101011, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 49 $31 'one' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011100, + 0b00011110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 50 $32 'two' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b01100011, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 51 $33 'three' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100000, + 0b01100000, + 0b00111100, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 52 $34 'four' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00110000, + 0b00111000, + 0b00111100, + 0b00110110, + 0b00110011, + 0b01111111, + 0b00110000, + 0b00110000, + 0b00110000, + 0b01111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 53 $35 'five' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b00000011, + 0b00000011, + 0b00000011, + 0b00111111, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 54 $36 'six' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00000110, + 0b00000011, + 0b00000011, + 0b00111111, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 55 $37 'seven' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100011, + 0b01100000, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 56 $38 'eight' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 57 $39 'nine' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111110, + 0b01100000, + 0b01100000, + 0b01100000, + 0b00110000, + 0b00011110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 58 $3a 'colon' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 59 $3b 'semicolon' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 60 $3c 'less' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00110000, + 0b01100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 61 $3d 'equal' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111110, + 0b00000000, + 0b00000000, + 0b01111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 62 $3e 'greater' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00110000, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 63 $3f 'question' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b00110000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 64 $40 'at' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01111011, + 0b01111011, + 0b01111011, + 0b00111011, + 0b00000011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 65 $41 'A' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01111111, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 66 $42 'B' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111111, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 67 $43 'C' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b01100110, + 0b01000011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b01000011, + 0b01100110, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 68 $44 'D' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00110110, + 0b00011111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 69 $45 'E' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100110, + 0b01000110, + 0b00010110, + 0b00011110, + 0b00010110, + 0b00000110, + 0b01000110, + 0b01100110, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 70 $46 'F' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100110, + 0b01000110, + 0b00010110, + 0b00011110, + 0b00010110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 71 $47 'G' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b01100110, + 0b01000011, + 0b00000011, + 0b00000011, + 0b01111011, + 0b01100011, + 0b01100011, + 0b01100110, + 0b01011100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 72 $48 'H' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111111, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 73 $49 'I' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 74 $4a 'J' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 75 $4b 'K' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100111, + 0b01100110, + 0b01100110, + 0b00110110, + 0b00011110, + 0b00011110, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 76 $4c 'L' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001111, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b01000110, + 0b01100110, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 77 $4d 'M' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01110111, + 0b01111111, + 0b01111111, + 0b01101011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 78 $4e 'N' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100111, + 0b01101111, + 0b01111111, + 0b01111011, + 0b01110011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 79 $4f 'O' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 80 $50 'P' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111111, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 81 $51 'Q' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01111011, + 0b00111110, + 0b00110000, + 0b01110000, + 0b00000000, + 0b00000000, +// 82 $52 'R' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111111, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 83 $53 'S' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b00000110, + 0b00011100, + 0b00110000, + 0b01100000, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 84 $54 'T' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111110, + 0b01111110, + 0b01011010, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 85 $55 'U' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 86 $56 'V' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00001000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 87 $57 'W' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01101011, + 0b01101011, + 0b01111111, + 0b01110111, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 88 $58 '1' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00111110, + 0b00011100, + 0b00011100, + 0b00111110, + 0b00110110, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 89 $59 'Y' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 90 $5a 'Z' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100011, + 0b01100001, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b01000011, + 0b01100011, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 91 $5b 'bracketleft' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 92 $5c 'backslash' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000001, + 0b00000011, + 0b00000111, + 0b00001110, + 0b00011100, + 0b00111000, + 0b01110000, + 0b01100000, + 0b01000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 93 $5d 'bracketright' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 94 $5e 'asciicircum' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 95 $5f 'underscore' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, +// 96 $60 'grave' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00001100, + 0b00001100, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 97 $61 'a' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 98 $62 'b' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000111, + 0b00000110, + 0b00000110, + 0b00011110, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 99 $63 'c' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 100 $64 'd' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111000, + 0b00110000, + 0b00110000, + 0b00111100, + 0b00110110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 101 $65 'e' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01111111, + 0b00000011, + 0b00000011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 102 $66 'f' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00110110, + 0b00100110, + 0b00000110, + 0b00001111, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 103 $67 'g' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00110011, + 0b00011110, + 0b00000000, +// 104 $68 'h' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000111, + 0b00000110, + 0b00000110, + 0b00110110, + 0b01101110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 105 $69 'i' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 106 $6a 'j' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100000, + 0b01100000, + 0b00000000, + 0b01110000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00000000, +// 107 $6b 'k' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000111, + 0b00000110, + 0b00000110, + 0b01100110, + 0b00110110, + 0b00011110, + 0b00011110, + 0b00110110, + 0b01100110, + 0b01100111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 108 $6c 'l' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 109 $6d 'm' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00110111, + 0b01111111, + 0b01101011, + 0b01101011, + 0b01101011, + 0b01101011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 110 $6e 'n' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111011, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 111 $6f 'o' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 112 $70 'p' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111011, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, +// 113 $71 'q' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00110000, + 0b01111000, + 0b00000000, +// 114 $72 'r' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111011, + 0b01101110, + 0b01100110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 115 $73 's' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b00000110, + 0b00011100, + 0b00110000, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 116 $74 't' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001000, + 0b00001100, + 0b00001100, + 0b00111111, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b01101100, + 0b00111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 117 $75 'u' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 118 $76 'v' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 119 $77 'w' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01101011, + 0b01101011, + 0b01111111, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 120 $78 'x' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00011100, + 0b00011100, + 0b00110110, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 121 $79 'y' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111110, + 0b01100000, + 0b00110000, + 0b00011111, + 0b00000000, +// 122 $7a 'z' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111111, + 0b00110011, + 0b00011000, + 0b00001100, + 0b00000110, + 0b01100011, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 123 $7b 'braceleft' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01110000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00001110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b01110000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 124 $7c 'bar' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 125 $7d 'braceright' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b01110000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00001110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 126 $7e 'asciitilde' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00111011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 127 $7f 'char127' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +}; diff --git a/sys/include/hx8357.h b/sys/include/hx8357.h new file mode 100644 index 0000000..9562826 --- /dev/null +++ b/sys/include/hx8357.h @@ -0,0 +1,21 @@ +#ifndef _HX8356_H +#define _HX8357_H + +#include "tty.h" + +extern const struct devspec hx8357devs[]; +extern int hx8357_open(dev_t dev, int flag, int mode); +extern int hx8357_close(dev_t dev, int flag, int mode); +extern int hx8357_read(dev_t dev, struct uio *uio, int flag); +extern int hx8357_write(dev_t dev, struct uio *uio, int flag); +extern int hx8357_ioctl(dev_t dev, register u_int cmd, caddr_t addr, int flag); +extern int hx8357_select(dev_t dev, int rw); +extern void hx8357_putc(dev_t dev, char c); +extern char hx8357_getc(dev_t dev); +extern void hx8357_init(); + + +extern struct tty hx8357_ttys[1]; + + +#endif diff --git a/sys/include/rd_spirams.h b/sys/include/rd_spirams.h new file mode 100644 index 0000000..8ab721d --- /dev/null +++ b/sys/include/rd_spirams.h @@ -0,0 +1,9 @@ +#ifndef _SPIRAMS_H +#define _SPIRAMS_H + +extern int spirams_size(int unit); +extern int spirams_read(int unit, unsigned int offset, char *data, unsigned int bcount); +extern int spirams_write (int unit, unsigned offset, char *data, unsigned bcount); +extern void spirams_preinit (int unit); + +#endif diff --git a/sys/kernel/rdisk.c b/sys/kernel/rdisk.c index 5a91f93..6752eaf 100644 --- a/sys/kernel/rdisk.c +++ b/sys/kernel/rdisk.c @@ -43,6 +43,9 @@ extern int sdsize(int unit); #ifdef MRAMS_ENABLED #include #endif +#ifdef SPIRAMS_ENABLED +#include +#endif int no_deinit(int u) { return 0; } void no_preinit(int u) { return; } @@ -85,6 +88,10 @@ const struct diskentry disks[] = { {mrams_preinit, no_init, no_deinit, no_open, mrams_size, mrams_read, mrams_write, 0, RD_DEFAULT}, #endif +#ifdef SPIRAMS_ENABLED + {spirams_preinit, no_init, no_deinit, no_open, spirams_size, spirams_read, spirams_write, 0, RD_DEFAULT}, +#endif + }; #define NRDSK sizeof(disks)/sizeof(struct diskentry) diff --git a/sys/pic32/32mxsdram-uart/Makefile b/sys/pic32/32mxsdram-uart/Makefile index 4edfea6..1a220e5 100644 --- a/sys/pic32/32mxsdram-uart/Makefile +++ b/sys/pic32/32mxsdram-uart/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o oc.o rd_sd.o rd_sdramp.o rdisk.o sdram.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o oc.o rd_sd.o rd_sdramp.o rdisk.o sdram.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/Makefile b/sys/pic32/Makefile index d06a76f..dc975c9 100644 --- a/sys/pic32/Makefile +++ b/sys/pic32/Makefile @@ -4,20 +4,21 @@ SUBDIR = baremetal dip duinomite duinomite-uart duinomite-e \ duinomite-e-uart explorer16 max32 max32-eth maximite \ meb pinguino-micro starter-kit ubw32 ubw32-uart \ - ubw32-uart-sdram baremetal fubarino fubarino-uart \ - fubarino-uart-sramc mmb-mx7 maximite-color \ - 32mxsdram-uart + ubw32-uart-sdram baremetal fubarino mmb-mx7 maximite-color \ + 32mxsdram-uart picadillo default: all: - -for i in $(SUBDIR); do make -C $$i all; done + -for i in $(SUBDIR); do ${MAKE} -C $$i all; done install: clean: - -for i in $(SUBDIR); do make -C $$i clean; done + -for i in $(SUBDIR); do ${MAKE} -C $$i clean; done find .. -name \*~ | xargs rm -f reconfig: - -for i in $(SUBDIR); do echo $$i; I=`echo $$i | awk '{print toupper($$0)}'`; (cd $$i; ../../../tools/configsys/config $$I); done + -for i in $(SUBDIR); do echo $$i; \ + I=`echo $$i | awk '{print toupper($$0)}'`; \ + (cd $$i; ../../../tools/configsys/config $$I); done diff --git a/sys/pic32/baremetal/Makefile b/sys/pic32/baremetal/Makefile index ba3e606..1351297 100644 --- a/sys/pic32/baremetal/Makefile +++ b/sys/pic32/baremetal/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/cfg/hxtft.dev b/sys/pic32/cfg/hxtft.dev new file mode 100644 index 0000000..15fc01f --- /dev/null +++ b/sys/pic32/cfg/hxtft.dev @@ -0,0 +1,4 @@ +always + file hx8357.o + define HX8357_ENABLED +end always diff --git a/sys/pic32/cfg/kernel.dev b/sys/pic32/cfg/kernel.dev index e18f2b8..9888aa2 100644 --- a/sys/pic32/cfg/kernel.dev +++ b/sys/pic32/cfg/kernel.dev @@ -4,7 +4,7 @@ always define EXEC_AOUT define EXEC_ELF define EXEC_SCRIPT - file _startup.o + file startup.o file clock.o file devsw.o file sysctl.o diff --git a/sys/pic32/cfg/picadillo.map b/sys/pic32/cfg/picadillo.map new file mode 100644 index 0000000..e23e884 --- /dev/null +++ b/sys/pic32/cfg/picadillo.map @@ -0,0 +1,76 @@ +# Format is: silk port pin +# silk is the name of the pin, port and pin is what it maps to. +0 F 2 +1 F 8 +2 E 8 +3 A 3 +4 F 3 +5 G 15 +6 D 11 +7 E 9 +8 D 15 +9 D 3 +10 C 4 +11 D 10 +12 D 9 +13 D 0 +A0 B 0 +14 B 0 +A1 B 1 +15 B 1 +A2 B 2 +16 B 2 +A3 B 3 +17 B 3 +A4 B 4 +18 B 4 +A5 B 5 +19 B 5 +A6 B 6 +20 B 6 +A7 B 7 +21 B 7 +A8 B 8 +22 B 8 +A9 B 9 +23 B 9 +A10 B 10 +24 B 10 +A11 B 11 +25 B 11 +26 A 0 +27 A 1 +28 A 4 +29 A 5 +30 A 2 +31 D 1 +32 D 2 +A14 B 14 +33 B 14 +34 D 14 +35 D 8 +36 A 6 +37 A 7 +38 G 14 +39 G 12 +40 G 13 +41 A 9 +42 A 10 +43 B 12 +44 B 13 +45 C 2 +46 C 13 +47 C 1 +48 G 9 +49 F 4 +50 F 13 +51 F 5 +52 F 5 +53 A 15 +54 A 14 +55 G 7 +56 G 8 +57 G 6 + + + diff --git a/sys/pic32/cfg/spirams.dev b/sys/pic32/cfg/spirams.dev new file mode 100644 index 0000000..bf896ff --- /dev/null +++ b/sys/pic32/cfg/spirams.dev @@ -0,0 +1,184 @@ +always + define SPIRAMS_ENABLED + file rd_spirams.o + require rdisk + require spibus + define SPIRAMS_CHIPSIZE 128 +end always + +option chips + define SPIRAMS_CHIPS %1 +end option + +option port + define SPIRAMS_PORT %1 +end option + +option chipsize + define SPIRAMS_CHIPSIZE %1 +end option + +option mhz + define SPIRAMS_MHZ %1 +end option + +option cs0 + define SPIRAMS_CS0_PORT $TRIS(%1) + define SPIRAMS_CS0_PIN $PIN(%1) +end option + +option cs1 + define SPIRAMS_CS1_PORT $TRIS(%1) + define SPIRAMS_CS1_PIN $PIN(%1) +end option + +option cs2 + define SPIRAMS_CS2_PORT $TRIS(%1) + define SPIRAMS_CS2_PIN $PIN(%1) +end option + +option cs3 + define SPIRAMS_CS3_PORT $TRIS(%1) + define SPIRAMS_CS3_PIN $PIN(%1) +end option + +option cs4 + define SPIRAMS_CS4_PORT $TRIS(%1) + define SPIRAMS_CS4_PIN $PIN(%1) +end option + +option cs5 + define SPIRAMS_CS5_PORT $TRIS(%1) + define SPIRAMS_CS5_PIN $PIN(%1) +end option + +option cs6 + define SPIRAMS_CS6_PORT $TRIS(%1) + define SPIRAMS_CS6_PIN $PIN(%1) +end option + +option cs7 + define SPIRAMS_CS7_PORT $TRIS(%1) + define SPIRAMS_CS7_PIN $PIN(%1) +end option + +option cs8 + define SPIRAMS_CS8_PORT $TRIS(%1) + define SPIRAMS_CS8_PIN $PIN(%1) +end option + +option cs9 + define SPIRAMS_CS9_PORT $TRIS(%1) + define SPIRAMS_CS9_PIN $PIN(%1) +end option + +option cs10 + define SPIRAMS_CS10_PORT $TRIS(%1) + define SPIRAMS_CS10_PIN $PIN(%1) +end option + +option cs11 + define SPIRAMS_CS11_PORT $TRIS(%1) + define SPIRAMS_CS11_PIN $PIN(%1) +end option + +option cs12 + define SPIRAMS_CS12_PORT $TRIS(%1) + define SPIRAMS_CS12_PIN $PIN(%1) +end option + +option cs13 + define SPIRAMS_CS13_PORT $TRIS(%1) + define SPIRAMS_CS13_PIN $PIN(%1) +end option + +option cs14 + define SPIRAMS_CS14_PORT $TRIS(%1) + define SPIRAMS_CS14_PIN $PIN(%1) +end option + +option cs15 + define SPIRAMS_CS15_PORT $TRIS(%1) + define SPIRAMS_CS15_PIN $PIN(%1) +end option + +option led0 + define SPIRAMS_LED0_PORT $TRIS(%1) + define SPIRAMS_LED0_PIN $PIN(%1) +end option + +option led1 + define SPIRAMS_LED1_PORT $TRIS(%1) + define SPIRAMS_LED1_PIN $PIN(%1) +end option + +option led2 + define SPIRAMS_LED2_PORT $TRIS(%1) + define SPIRAMS_LED2_PIN $PIN(%1) +end option + +option led3 + define SPIRAMS_LED3_PORT $TRIS(%1) + define SPIRAMS_LED3_PIN $PIN(%1) +end option + +option led4 + define SPIRAMS_LED4_PORT $TRIS(%1) + define SPIRAMS_LED4_PIN $PIN(%1) +end option + +option led5 + define SPIRAMS_LED5_PORT $TRIS(%1) + define SPIRAMS_LED5_PIN $PIN(%1) +end option + +option led6 + define SPIRAMS_LED6_PORT $TRIS(%1) + define SPIRAMS_LED6_PIN $PIN(%1) +end option + +option led7 + define SPIRAMS_LED7_PORT $TRIS(%1) + define SPIRAMS_LED7_PIN $PIN(%1) +end option + +option led8 + define SPIRAMS_LED8_PORT $TRIS(%1) + define SPIRAMS_LED8_PIN $PIN(%1) +end option + +option led9 + define SPIRAMS_LED9_PORT $TRIS(%1) + define SPIRAMS_LED9_PIN $PIN(%1) +end option + +option led10 + define SPIRAMS_LED10_PORT $TRIS(%1) + define SPIRAMS_LED10_PIN $PIN(%1) +end option + +option led11 + define SPIRAMS_LED11_PORT $TRIS(%1) + define SPIRAMS_LED11_PIN $PIN(%1) +end option + +option led12 + define SPIRAMS_LED12_PORT $TRIS(%1) + define SPIRAMS_LED12_PIN $PIN(%1) +end option + +option led13 + define SPIRAMS_LED13_PORT $TRIS(%1) + define SPIRAMS_LED13_PIN $PIN(%1) +end option + +option led14 + define SPIRAMS_LED14_PORT $TRIS(%1) + define SPIRAMS_LED14_PIN $PIN(%1) +end option + +option led15 + define SPIRAMS_LED15_PORT $TRIS(%1) + define SPIRAMS_LED15_PIN $PIN(%1) +end option + diff --git a/sys/pic32/devsw.c b/sys/pic32/devsw.c index 45a511e..769bb52 100644 --- a/sys/pic32/devsw.c +++ b/sys/pic32/devsw.c @@ -54,6 +54,10 @@ extern int strcmp(char *s1, char *s2); #include "pty.h" #endif +#ifdef HX8357_ENABLED +#include "hx8357.h" +#endif + /* * Null routine; placed in insignificant entries * in the bdevsw and cdevsw tables. @@ -239,6 +243,14 @@ const struct cdevsw cdevsw[] = { }, #endif +#ifdef HX8357_ENABLED +{ + hx8357_open, hx8357_close, hx8357_read, hx8357_write, + hx8357_ioctl, nulldev, hx8357_ttys, hx8357_select, + nostrategy, hx8357_getc, hx8357_putc, hx8357devs +}, +#endif + // End the list with a blank entry { 0, 0, 0, 0, diff --git a/sys/pic32/dip/Makefile b/sys/pic32/dip/Makefile index 2a83cab..3c80da9 100644 --- a/sys/pic32/dip/Makefile +++ b/sys/pic32/dip/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=6 diff --git a/sys/pic32/duinomite-e-uart/DUINOMITE-E-UART b/sys/pic32/duinomite-e-uart/DUINOMITE-E-UART index 525a055..f68fb27 100644 --- a/sys/pic32/duinomite-e-uart/DUINOMITE-E-UART +++ b/sys/pic32/duinomite-e-uart/DUINOMITE-E-UART @@ -10,7 +10,7 @@ linker bootloader-maximite device kernel cpu_khz=80000 bus_khz=40000 led=B15 -device console port=UART5 +device console device=tty5 device uart5 baud=115200 power=G13 device rdisk led=C1 diff --git a/sys/pic32/duinomite-e-uart/Makefile b/sys/pic32/duinomite-e-uart/Makefile index b23e0d0..3906a5e 100644 --- a/sys/pic32/duinomite-e-uart/Makefile +++ b/sys/pic32/duinomite-e-uart/Makefile @@ -6,11 +6,44 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_glob.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_log.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_conf.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +EXTRA_TARGETS = +DEFS += -DBUS_DIV=1 DEFS += -DBUS_KHZ=40000 -DEFS += -DCONSOLE_UART5=YES +DEFS += -DCONSOLE_DEVICE=tty5 +DEFS += -DCPU_IDIV=2 DEFS += -DCPU_KHZ=80000 +DEFS += -DCPU_MUL=20 +DEFS += -DCPU_ODIV=1 +DEFS += -DCRYSTAL=8 +DEFS += -DDC0_DEBUG=DEVCFG0_DEBUG_DISABLED +DEFS += -DDC0_ICE=0 +DEFS += -DDC1_CKM=0 +DEFS += -DDC1_CKS=0 +DEFS += -DDC1_FNOSC=DEVCFG1_FNOSC_PRIPLL +DEFS += -DDC1_IESO=DEVCFG1_IESO +DEFS += -DDC1_OSCIOFNC=0 +DEFS += -DDC1_PBDIV=DEVCFG1_FPBDIV_1 +DEFS += -DDC1_POSCMOD=DEVCFG1_POSCMOD_HS +DEFS += -DDC1_SOSC=0 +DEFS += -DDC1_WDTEN=0 +DEFS += -DDC1_WDTPS=DEVCFG1_WDTPS_1 +DEFS += -DDC2_PLLIDIV=DEVCFG2_FPLLIDIV_2 +DEFS += -DDC2_PLLMUL=DEVCFG2_FPLLMUL_20 +DEFS += -DDC2_PLLODIV=DEVCFG2_FPLLODIV_1 +DEFS += -DDC2_UPLL=0 +DEFS += -DDC2_UPLLIDIV=DEVCFG2_UPLLIDIV_2 +DEFS += -DDC3_CAN=DEVCFG3_FCANIO +DEFS += -DDC3_ETH=DEVCFG3_FETHIO +DEFS += -DDC3_MII=DEVCFG3_FMIIEN +DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 +DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO +DEFS += -DDC3_USERID=0xffff +DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT DEFS += -DGPIO_ENABLED=YES DEFS += -DKERNEL DEFS += -DLED_DISK_PIN=1 @@ -30,6 +63,9 @@ DEFS += -DUART5_ENA_PORT=TRISG DEFS += -DUCB_METER -LDSCRIPT = ../../../tools/configsys/../../sys/pic32/lds/bootloader-maximite.ld +LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-maximite.ld + +CONFIG = DUINOMITE-E-UART +CONFIGPATH = ../../../tools/configsys include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/duinomite-e/DUINOMITE-E b/sys/pic32/duinomite-e/DUINOMITE-E index ed4577e..c69448c 100644 --- a/sys/pic32/duinomite-e/DUINOMITE-E +++ b/sys/pic32/duinomite-e/DUINOMITE-E @@ -11,11 +11,10 @@ linker bootloader-maximite device kernel cpu_khz=80000 bus_khz=40000 led=B15 -device console port=USB +device console device=ttyUSB0 device uartusb device rdisk led=C1 device sd0 port=3 cs=G12 power=G13 device gpio - diff --git a/sys/pic32/duinomite-e/Makefile b/sys/pic32/duinomite-e/Makefile index aab6603..edb68f2 100644 --- a/sys/pic32/duinomite-e/Makefile +++ b/sys/pic32/duinomite-e/Makefile @@ -6,11 +6,44 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_glob.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_log.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_conf.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +EXTRA_TARGETS = +DEFS += -DBUS_DIV=1 DEFS += -DBUS_KHZ=40000 -DEFS += -DCONSOLE_USB=YES +DEFS += -DCONSOLE_DEVICE=ttyUSB0 +DEFS += -DCPU_IDIV=2 DEFS += -DCPU_KHZ=80000 +DEFS += -DCPU_MUL=20 +DEFS += -DCPU_ODIV=1 +DEFS += -DCRYSTAL=8 +DEFS += -DDC0_DEBUG=DEVCFG0_DEBUG_DISABLED +DEFS += -DDC0_ICE=0 +DEFS += -DDC1_CKM=0 +DEFS += -DDC1_CKS=0 +DEFS += -DDC1_FNOSC=DEVCFG1_FNOSC_PRIPLL +DEFS += -DDC1_IESO=DEVCFG1_IESO +DEFS += -DDC1_OSCIOFNC=0 +DEFS += -DDC1_PBDIV=DEVCFG1_FPBDIV_1 +DEFS += -DDC1_POSCMOD=DEVCFG1_POSCMOD_HS +DEFS += -DDC1_SOSC=0 +DEFS += -DDC1_WDTEN=0 +DEFS += -DDC1_WDTPS=DEVCFG1_WDTPS_1 +DEFS += -DDC2_PLLIDIV=DEVCFG2_FPLLIDIV_2 +DEFS += -DDC2_PLLMUL=DEVCFG2_FPLLMUL_20 +DEFS += -DDC2_PLLODIV=DEVCFG2_FPLLODIV_1 +DEFS += -DDC2_UPLL=0 +DEFS += -DDC2_UPLLIDIV=DEVCFG2_UPLLIDIV_2 +DEFS += -DDC3_CAN=DEVCFG3_FCANIO +DEFS += -DDC3_ETH=DEVCFG3_FETHIO +DEFS += -DDC3_MII=DEVCFG3_FMIIEN +DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 +DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO +DEFS += -DDC3_USERID=0xffff +DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT DEFS += -DGPIO_ENABLED=YES DEFS += -DKERNEL DEFS += -DLED_DISK_PIN=1 @@ -29,6 +62,9 @@ DEFS += -DUSB_MAX_EP_NUMBER=3 DEFS += -DUSB_NUM_STRING_DESCRIPTORS=3 -LDSCRIPT = ../../../tools/configsys/../../sys/pic32/lds/bootloader-maximite.ld +LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-maximite.ld + +CONFIG = DUINOMITE-E +CONFIGPATH = ../../../tools/configsys include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/duinomite-uart/Makefile b/sys/pic32/duinomite-uart/Makefile index 2a94d01..e8c795e 100644 --- a/sys/pic32/duinomite-uart/Makefile +++ b/sys/pic32/duinomite-uart/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/duinomite/Makefile b/sys/pic32/duinomite/Makefile index a62bfe2..8fba7b2 100644 --- a/sys/pic32/duinomite/Makefile +++ b/sys/pic32/duinomite/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/exception.c b/sys/pic32/exception.c index 2d70c7d..5434a85 100644 --- a/sys/pic32/exception.c +++ b/sys/pic32/exception.c @@ -158,7 +158,7 @@ dumpregs (frame) printf( "*******STACK DUMP START*************\n"); printf( "frame = %8x\n", frame ); printf( "stack data\n" ); - while( p <= stacktop ) + while( p <= stacktop ) { printf( " %8x", *p++ ); if( p <= stacktop ) printf( " %8x", *p++ ); @@ -343,14 +343,14 @@ exception (frame) mips_write_c0_register (C0_COMPARE, 0, c); } while ((int) (c - (unsigned)mips_read_c0_register (C0_COUNT, 0)) < 0); hardclock ((caddr_t) frame [FRAME_PC], status); - + #ifdef POWER_ENABLED power_switch_check(); #endif #ifdef UARTUSB_ENABLED /* Poll USB on every timer tick. */ - usbintr(0); + usbintr(0); #endif break; #ifdef UART1_ENABLED @@ -389,7 +389,7 @@ exception (frame) #ifdef UARTUSB_ENABLED case PIC32_VECT_USB: /* USB */ IFSCLR(1) = 1 << (PIC32_IRQ_USB - 32); - usbintr(0); + usbintr(0); break; #endif @@ -418,7 +418,7 @@ exception (frame) if (sp < u.u_procp->p_daddr + u.u_dsize) { /* Process has trashed its stack; give it an illegal * instruction violation to halt it in its tracks. */ - panic ("unexpected exception 2"); + panic ("unexpected exception 2"); psig = SIGSEGV; break; } diff --git a/sys/pic32/explorer16/.gitignore b/sys/pic32/explorer16/.gitignore index 6a22af6..2b28c2d 100644 --- a/sys/pic32/explorer16/.gitignore +++ b/sys/pic32/explorer16/.gitignore @@ -4,6 +4,7 @@ machine sys unix.bin +boot.bin unix.map usbboot.map vers.c diff --git a/sys/pic32/explorer16/Makefile b/sys/pic32/explorer16/Makefile index a4a9fd7..af3189f 100644 --- a/sys/pic32/explorer16/Makefile +++ b/sys/pic32/explorer16/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/fubarino/Makefile b/sys/pic32/fubarino/Makefile index 5f852c2..f9ace21 100644 --- a/sys/pic32/fubarino/Makefile +++ b/sys/pic32/fubarino/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o glcd.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o oc.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o glcd.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o oc.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/gcc-config.mk b/sys/pic32/gcc-config.mk index 47efd99..ac5fdbe 100644 --- a/sys/pic32/gcc-config.mk +++ b/sys/pic32/gcc-config.mk @@ -47,6 +47,13 @@ ifndef GCCPREFIX $(error Unable to locate any GCC MIPS toolchain!) endif +# UECIDE on Linux +ifneq (,$(wildcard $UECIDE/cores/chipKIT)) + AVRDUDE = $UECIDE/cores/chipKIT/tools/linux64/avrdude \ + -C $UECIDE/cores/chipKIT/tools/linux64/avrdude.conf -V \ + -P /dev/ttyUSB* +endif + # chipKIT MPIDE on Mac OS X ifneq (,$(wildcard /Applications/Mpide.app/Contents/Resources/Java/hardware/tools/avr)) AVRDUDE = /Applications/Mpide.app/Contents/Resources/Java/hardware/tools/avr/bin/avrdude \ diff --git a/sys/pic32/hx8357.c b/sys/pic32/hx8357.c new file mode 100644 index 0000000..5934a33 --- /dev/null +++ b/sys/pic32/hx8357.c @@ -0,0 +1,774 @@ +/* + * HX8357 TFT driver for PIC32. + * + * Copyright (C) 2014 Majenko Technologies + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ + +#include "param.h" +#include "conf.h" +#include "user.h" +#include "ioctl.h" +#include "systm.h" +#include "uio.h" +#include "adc.h" +#include "debug.h" +#include "hx8357.h" + +#include "fonts/default.h" + +char frame[40][80]; + +typedef struct { + unsigned char linesPerCharacter; + unsigned char bytesPerLine; + unsigned char startGlyph; + unsigned char endGlyph; + unsigned char bitsPerPixel; +} FontHeader; + + +struct tty hx8357_ttys[1]; + +typedef struct { + union { + unsigned short value; + struct { + unsigned r:5; + unsigned g:6; + unsigned b:5; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)) Color565; + + +#define HX8357_EXIT_SLEEP_MODE 0x11 +#define HX8357_SET_DISPLAY_OFF 0x28 +#define HX8357_SET_DISPLAY_ON 0x29 +#define HX8357_SET_COLUMN_ADDRESS 0x2A +#define HX8357_SET_PAGE_ADDRESS 0x2B +#define HX8357_WRITE_MEMORY_START 0x2C +#define HX8357_READ_MEMORY_START 0x2E +#define HX8357_SET_TEAR_ON 0x35 +#define HX8357_SET_ADDRESS_MODE 0x36 +#define HX8357_SET_PIXEL_FORMAT 0x3A +#define HX8357_WRITE_MEMORY_CONTINUE 0x3C +#define HX8357_READ_MEMORY_CONTINUE 0x3E +#define HX8357_SET_INTERNAL_OSCILLATOR 0xB0 +#define HX8357_SET_POWER_CONTROL 0xB1 +#define HX8357_SET_DISPLAY_MODE 0xB4 +#define HX8357_SET_VCOM_VOLTAGE 0xB6 +#define HX8357_ENABLE_EXTENSION_COMMAND 0xB9 +#define HX8357_SET_PANEL_DRIVING 0xC0 // not documented! +#define HX8357_SET_PANEL_CHARACTERISTIC 0xCC +#define HX8357_SET_GAMMA_CURVE 0xE0 + +static int _width = 320; +static int _height = 480; + +static int cursor_x = 0; +static int cursor_y = 0; + +static int rotation = 0; + +static unsigned short textcolor = 0x7BEF; +static unsigned short texthicolor = 0xFFFF; +static unsigned short textbgcolor = 0x0000; + +const unsigned char *font = Default; +const unsigned char _font_width = 6; +const unsigned char _font_height = 8; + +const struct devspec hx8357devs[] = { + { 0, "tft0" }, + { 1, "tftin0" }, + { 0, 0 } +}; + +void inline static writeCommand(unsigned short c) { + while (PMMODE & PIC32_PMMODE_BUSY); + PMADDR = 0x0000; + PMDIN = c; +} + +void inline static writeData(unsigned short c) { + while (PMMODE & PIC32_PMMODE_BUSY); + PMADDR = 0x0001; + PMDIN = c; +} + +void initDisplay() { + PMCONCLR = PIC32_PMCON_ON; + asm volatile("nop"); + + PMCONSET = PIC32_PMCON_PTWREN | PIC32_PMCON_PTRDEN; + PMCONCLR = PIC32_PMCON_CSF; + PMAEN = 0x0001; // Enable PMA0 pin for RS pin and CS1 as CS + PMMODE = PIC32_PMMODE_MODE16 | PIC32_PMMODE_MODE_MAST2; + PMADDR = 0; + PMCONSET = PIC32_PMCON_ON; + + + writeCommand(HX8357_EXIT_SLEEP_MODE); //Sleep Out + udelay(150000); + writeCommand(HX8357_ENABLE_EXTENSION_COMMAND); + writeData(0xFF); + writeData(0x83); + writeData(0x57); + udelay(1000); + writeCommand(HX8357_SET_POWER_CONTROL); + writeData(0x00); + writeData(0x12); + writeData(0x12); + writeData(0x12); + writeData(0xC3); + writeData(0x44); + udelay(1000); + writeCommand(HX8357_SET_DISPLAY_MODE); + writeData(0x02); + writeData(0x40); + writeData(0x00); + writeData(0x2A); + writeData(0x2A); + writeData(0x20); + writeData(0x91); + udelay(1000); + writeCommand(HX8357_SET_VCOM_VOLTAGE); + writeData(0x38); + udelay(1000); + writeCommand(HX8357_SET_INTERNAL_OSCILLATOR); + writeData(0x68); + writeCommand(0xE3); //Unknown Command + writeData(0x2F); + writeData(0x1F); + writeCommand(0xB5); //Set BGP + writeData(0x01); + writeData(0x01); + writeData(0x67); + writeCommand(HX8357_SET_PANEL_DRIVING); + writeData(0x70); + writeData(0x70); + writeData(0x01); + writeData(0x3C); + writeData(0xC8); + writeData(0x08); + udelay(1000); + writeCommand(0xC2); // Set Gate EQ + writeData(0x00); + writeData(0x08); + writeData(0x04); + udelay(1000); + writeCommand(HX8357_SET_PANEL_CHARACTERISTIC); + writeData(0x09); + udelay(1000); + writeCommand(HX8357_SET_GAMMA_CURVE); + writeData(0x01); + writeData(0x02); + writeData(0x03); + writeData(0x05); + writeData(0x0E); + writeData(0x22); + writeData(0x32); + writeData(0x3B); + writeData(0x5C); + writeData(0x54); + writeData(0x4C); + writeData(0x41); + writeData(0x3D); + writeData(0x37); + writeData(0x31); + writeData(0x21); + writeData(0x01); + writeData(0x02); + writeData(0x03); + writeData(0x05); + writeData(0x0E); + writeData(0x22); + writeData(0x32); + writeData(0x3B); + writeData(0x5C); + writeData(0x54); + writeData(0x4C); + writeData(0x41); + writeData(0x3D); + writeData(0x37); + writeData(0x31); + writeData(0x21); + writeData(0x00); + writeData(0x01); + udelay(1000); + writeCommand(HX8357_SET_PIXEL_FORMAT); //COLMOD RGB888 + writeData(0x55); + writeCommand(HX8357_SET_ADDRESS_MODE); + writeData(0x00); + writeCommand(HX8357_SET_TEAR_ON); //TE ON + writeData(0x00); + udelay(10000); + writeCommand(HX8357_SET_DISPLAY_ON); //Display On + udelay(10000); + writeCommand(HX8357_WRITE_MEMORY_START); //Write SRAM Data + int l, c; + for (l = 0; l < 39; l++) { + for (c = 0; c < 80; c++) { + frame[l][c]=' '; + } + } +} + +void inline static setAddrWindow(unsigned short x0, unsigned short y0, unsigned short x1, unsigned short y1) { + writeCommand(HX8357_SET_COLUMN_ADDRESS); // Column addr set + writeData((x0) >> 8); + writeData(x0); // XSTART + writeData((x1) >> 8); + writeData(x1); // XEND + + writeCommand(HX8357_SET_PAGE_ADDRESS); // Row addr set + writeData((y0) >> 8); + writeData(y0); // YSTART + writeData((y1) >> 8); + writeData(y1); // YEND + + writeCommand(HX8357_WRITE_MEMORY_START); //Write SRAM Data +} + +void inline static setPixel(int x, int y, unsigned short color) { + if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) + return; + setAddrWindow(x,y,x+1,y+1); + while (PMMODE & PIC32_PMMODE_BUSY); + PMADDR = 0x0001; + PMDIN = color; +} + + +void inline static fillRectangle(int x, int y, int w, int h, unsigned short color) +{ + setAddrWindow(x, y, x+w-1, y+h-1); + + while (PMMODE & PIC32_PMMODE_BUSY); + PMADDR = 0x0001; + for(y=h; y>0; y--) { + for(x=w; x>0; x--) { + while (PMMODE & PIC32_PMMODE_BUSY); + PMDIN = color; + } + } +} + +void inline static setRotation(unsigned char m) +{ + writeCommand(HX8357_SET_ADDRESS_MODE); + rotation = m % 4; // can't be higher than 3 + switch (rotation) + { + case 0: + //PORTRAIT + writeData(0x0000); + _width = 320; + _height = 480; + break; + case 1: + //LANDSCAPE + writeData(0x0060); + _width = 480; + _height = 320; + break; + case 2: + //UPSIDE DOWN PORTRAIT + writeData(0x00C0); + _width = 320; + _height = 480; + break; + case 3: + //UPSIDE DOWN LANDSCAPE + writeData(0x00A0); + _width = 480; + _height = 320; + break; + } +} + +unsigned short inline static mix(unsigned short a, unsigned short b, unsigned char pct) { + Color565 col_a; + Color565 col_b; + Color565 col_out; + col_a.value = a; + col_b.value = b; + unsigned int temp; + temp = (((int)col_a.r * (255-pct)) / 255) + (((unsigned int)col_b.r * pct) / 255); + col_out.r = temp; + temp = (((int)col_a.g * (255-pct)) / 255) + (((unsigned int)col_b.g * pct) / 255); + col_out.g = temp; + temp = (((int)col_a.b * (255-pct)) / 255) + (((unsigned int)col_b.b * pct) / 255); + col_out.b = temp; + return col_out.value; +} + + +unsigned char drawChar(int x, int y, unsigned char c, unsigned short color, unsigned short bg) { + + if (font == NULL) { + return 0; + } + + FontHeader *header = (FontHeader *)font; + + if (c < header->startGlyph || c > header->endGlyph) { + return 0; + } + + c = c - header->startGlyph; + + // Start of this character's data is the character number multiplied by the + // number of lines in a character (plus one for the character width) multiplied + // by the number of bytes in a line, and then offset by 4 for the header. + unsigned int charstart = (c * ((header->linesPerCharacter * header->bytesPerLine) + 1)) + sizeof(FontHeader); // Start of character data + unsigned char charwidth = font[charstart++]; // The first byte of a block is the width of the character + + unsigned int bitmask = (1 << header->bitsPerPixel) - 1; + + setAddrWindow(x, y, x + charwidth - 1, y + header->linesPerCharacter - 1); + + char lineNumber = 0; + for (lineNumber = 0; lineNumber < header->linesPerCharacter; lineNumber++ ) { + unsigned char lineData = 0; + + char bitsLeft = -1; + unsigned char byteNumber = 0; + + char pixelNumber = 0; + for (pixelNumber = 0; pixelNumber < charwidth; pixelNumber++) { + if (bitsLeft <= 0) { + bitsLeft = 8; + lineData = font[charstart + (lineNumber * header->bytesPerLine) + (header->bytesPerLine - byteNumber - 1)]; + byteNumber++; + } + unsigned int pixelValue = lineData & bitmask; + if (pixelValue > 0) { + writeData(color); + } else { + writeData(bg); + } + lineData >>= header->bitsPerPixel; + bitsLeft -= header->bitsPerPixel; + } + } + return charwidth; +} + +void updateLine(int l) { + if (l < 0) return; + if (l > 39) return; + + int c; + for (c = 0; c < 80; c++) { + drawChar(c * _font_width, l * _font_height, frame[l][c] & 0x7F, frame[l][c] & 0x80 ? texthicolor : textcolor, textbgcolor); + } +} + +void scrollUp() { + int l, c; + for (l = 0; l < 39; l++) { + for (c = 0; c < 80; c++) { + frame[l][c] = frame[l+1][c]; + } + updateLine(l); + } + for (c = 0; c < 80; c++) { + frame[39][c] = ' '; + } + updateLine(39); +} + +int inEscape = 0; + +int edValPos = 0; +int edVal[4]; + +int bold = 0; + +void printChar(unsigned char c) { + switch (c) { + case '\n': + cursor_y ++; + if (cursor_y > 39) { + scrollUp(); + cursor_y = 39; + } + break; + case '\r': + cursor_x = 0; + break; + case 8: + cursor_x--; + if (cursor_x < 0) { + cursor_x = 79; + cursor_y--; + if (cursor_y < 0) { + cursor_y = 0; + } + } + break; + default: + frame[cursor_y][cursor_x] = c | (bold ? 0x80 : 0x00); + cursor_x++; + if (cursor_x == 80) { + cursor_x = 0; + cursor_y++; + if (cursor_y == 40) { + cursor_y = 39; + scrollUp(); + } + } + updateLine(cursor_y); + + } +} + +int extended = 0; + +void writeChar(unsigned char c) { + + int i, j; + updateLine(cursor_y); + + if (inEscape == 1) { + + switch (c) { + case 27: + inEscape = 0; + printChar('^'); + printChar('['); + break; + case '[': + extended = 1; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + edVal[edValPos%4] *= 10; + edVal[edValPos%4] += c - '0'; + break; + case ';': + edValPos++; + edVal[edValPos%4] = 0; + break; + case 'J': + if (extended == 1) { + if (edVal[0] == 0) { + for (i = cursor_y; i < 40; i++) { + for (j = 0; j < 80; j++) { + frame[i][j] = ' '; + } + updateLine(i); + } + } else if (edVal[0] == 1) { + for (i = 0; i < cursor_y; i++) { + for (j = 0; j < 80; j++) { + frame[i][j] = ' '; + } + updateLine(i); + } + } else if (edVal[0] == 2) { + for (i = 0; i < 40; i++) { + for (j = 0; j < 80; j++) { + frame[i][j] = ' '; + } + updateLine(i); + } + } + } + inEscape = 0; + break; + case 'H': + if (extended == 1) { + if (edVal[0] == 0) { + edVal[0] = 1; + } + if (edVal[1] == 0) { + edVal[1] = 1; + } + cursor_x = (edVal[1] - 1) % 80; + cursor_y = (edVal[0] - 1) % 40; + } + inEscape = 0; + break; + case 'm': + if (extended == 1) { + if (edVal[0] == 0) { + bold = 0; + } else if (edVal[0] == 1) { + bold = 1; + } + } + inEscape = 0; + break; + + case 'A': + if (extended == 0) { + cursor_y--; + if (cursor_y > 0) { + cursor_y = 39; + } + } + inEscape = 0; + break; + + case 'B': + if (extended == 0) { + cursor_y++; + if (cursor_y == 40) { + cursor_y = 0; + } + } + inEscape = 0; + break; + + case 'C': + if (extended == 0) { + cursor_x++; + if (cursor_x == 80) { + cursor_x = 0; + cursor_y++; + if (cursor_y == 40) { + cursor_y = 0; + } + } + } + inEscape = 0; + break; + + case 'D': + if (extended == 0) { + cursor_x--; + if (cursor_x < 0) { + cursor_x = 79; + cursor_y--; + if (cursor_y < 0) { + cursor_y = 39; + } + } + } + inEscape = 0; + break; + + case 'K': + if (extended == 1) { + if (edVal[0] == 0) { + for (i = cursor_x; i < 80; i++) { + frame[cursor_y][i] = ' '; + } + } else if (edVal[1] == 1) { + for (i = 0; i < cursor_x; i++) { + frame[cursor_y][i] = ' '; + } + } else { + for (i = 0; i < 80; i++) { + frame[cursor_y][i] = ' '; + } + } + updateLine(cursor_y); + } + inEscape = 0; + break; + + default: + if (extended) { + printf("Unhandled extended escape code %c\n", c); + } else { + printf("Unhandled escape code %c\n", c); + } + inEscape = 0; + break; + } + + } else { + if (c == 27) { + inEscape = 1; + extended = 0; + edVal[0] = 0; + edValPos = 0; + } else { + printChar(c); + } + } + drawChar(cursor_x * _font_width, cursor_y * _font_height, frame[cursor_y][cursor_x] & 0x7F, 0x0000, bold ? texthicolor : textcolor); +// for (i = 0; i < _font_width; i++) { +// setPixel(cursor_x * _font_width + i, (cursor_y + 1) * _font_height - 1, 0xFFFF); +// } + +} + +void hx8357_start(struct tty *tp) { + register int s; + + s = spltty(); + ttyowake(tp); +// tp->t_state &= TS_BUSY; + if (tp->t_outq.c_cc > 0) { + led_control (LED_TTY, 1); + while (tp->t_outq.c_cc != 0) { + int c = getc (&tp->t_outq); + writeChar(c); + } + led_control (LED_TTY, 0); + } +// tp->t_state |= TS_BUSY; + splx (s); +} + +void hx8357_init() { + initDisplay(); + setRotation(1); + int i,j; + for (i = 0; i < 40; i++) { + for (j = 0; j < 80; j++) { + frame[i][j] = ' '; + } + updateLine(i); + } +} + +int ttyIsOpen = 0; + +int hx8357_open(dev_t dev, int flag, int mode) { + int unit = minor(dev); + + if (unit == 0) { + ttyIsOpen = 1; + struct tty *tp = &hx8357_ttys[0]; + tp->t_oproc = hx8357_start; + tp->t_state = TS_ISOPEN | TS_CARR_ON; + tp->t_flags = ECHO | XTABS | CRMOD | CRTBS | CRTERA | CTLECH | CRTKIL; + return ttyopen(dev, tp); + } + if (unit == 1) { + if (!ttyIsOpen) { + return EIO; + } + return 0; + } + return ENODEV; +} + +int hx8357_close(dev_t dev, int flag, int mode) { + int unit = minor(dev); + + if (unit == 0) { + ttyIsOpen = 0; + struct tty *tp = &hx8357_ttys[0]; + ttyclose(tp); + return 0; + } + + if (unit == 1) { + return 0; + } + return ENODEV; +} + +int hx8357_read(dev_t dev, struct uio *uio, int flag) { + int unit = minor(dev); + + if (unit == 0) { + struct tty *tp = &hx8357_ttys[unit]; + return ttread(tp, uio, flag); + } + if (unit == 1) { + return EIO; + } + + return ENODEV; +} + +int hx8357_write(dev_t dev, struct uio *uio, int flag) { + int unit = minor(dev); + + if (unit == 0) { + struct tty *tp = &hx8357_ttys[0]; + return ttwrite(tp, uio, flag); + } + + if (unit == 1) { + if (!ttyIsOpen) { + return EIO; + } + struct tty *tp = &hx8357_ttys[0]; + struct iovec *iov = uio->uio_iov; + + while (iov->iov_len > 0) { + ttyinput(*(iov->iov_base), tp); + iov->iov_base ++; + iov->iov_len --; + uio->uio_resid --; + uio->uio_offset ++; + } + return 0; + } + return ENODEV; +} + +int hx8357_ioctl(dev_t dev, register u_int cmd, caddr_t addr, int flag) { + int unit = minor(dev); + + if (unit == 0) { + struct tty *tp = &hx8357_ttys[unit]; + int error; + + error = ttioctl(tp, cmd, addr, flag); + if (error < 0) + error = ENOTTY; + return (error); + } + if (unit == 1) { + return EIO; + } + + return ENODEV; + +} + +void hx8357_putc(dev_t dev, char c) { + writeChar(c); +} + +char hx8357_getc(dev_t dev) { + return 0; +} + +int hx8357_select (dev_t dev, int rw) { + int unit = minor(dev); + if (unit == 0) { + struct tty *tp = &hx8357_ttys[unit]; + return (ttyselect (tp, rw)); + } + if (unit == 1) { + return EIO; + } + return ENODEV; +} + diff --git a/sys/pic32/kernel-post.mk b/sys/pic32/kernel-post.mk index b73fd0e..8628c0d 100644 --- a/sys/pic32/kernel-post.mk +++ b/sys/pic32/kernel-post.mk @@ -40,7 +40,9 @@ unix.elf: $(KERNOBJ) $(LDSCRIPT) $(CC) $(LDFLAGS) $(KERNOBJ) -o $@ chmod -x $@ $(OBJDUMP) -d -S $@ > unix.dis - $(OBJCOPY) -O binary $@ unix.bin + $(OBJCOPY) -O binary -R .boot -R .config $@ unix.bin + $(OBJCOPY) -O binary -j .boot -j .config $@ boot.bin + test -s boot.bin || rm boot.bin $(OBJCOPY) -O ihex --change-addresses=0x80000000 $@ unix.hex chmod -x $@ unix.bin @@ -65,6 +67,9 @@ bl_devcfg.o: $(BUILDPATH)/devcfg.c load: unix.hex pic32prog $(BLREBOOT) unix.hex +loadmax: unix.hex + $(PROGTOOL) -U flash:w:unix.hex:i + loadboot: bootloader.hex pic32prog $(BLREBOOT) bootloader.hex diff --git a/sys/pic32/machdep.c b/sys/pic32/machdep.c index 6ae6c9b..7ccea87 100644 --- a/sys/pic32/machdep.c +++ b/sys/pic32/machdep.c @@ -27,6 +27,10 @@ # include #endif +#ifdef HX8357_ENABLED +#include "hx8357.h" +#endif + #ifdef POWER_ENABLED extern void power_init(); extern void power_off(); @@ -194,22 +198,38 @@ startup() */ INTCON = 0; /* Interrupt Control */ IPTMR = 0; /* Temporal Proximity Timer */ - IFS(0) = - PIC32_IPC_IP0(2) | PIC32_IPC_IP1(1) | - PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) | - PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) | - PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ; - IFS(1) = IFS(2) = 0; /* Interrupt Flag Status */ - IEC(0) = IEC(1) = IEC(2) = 0; /* Interrupt Enable Control */ - IPC(0) = IPC(1) = IPC(2) = IPC(3) = /* Interrupt Priority Control */ - IPC(4) = IPC(5) = IPC(6) = IPC(7) = - IPC(8) = IPC(9) = IPC(10) = IPC(11) = - IPC(12) = - PIC32_IPC_IP0(1) | PIC32_IPC_IP1(1) | - PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) | - PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) | - PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ; + /* Interrupt Flag Status */ + IFS(0) = PIC32_IPC_IP0(2) | PIC32_IPC_IP1(1) | + PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) | + PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) | + PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ; + IFS(1) = 0; + IFS(2) = 0; + + /* Interrupt Enable Control */ + IEC(0) = 0; + IEC(1) = 0; + IEC(2) = 0; + + /* Interrupt Priority Control */ + unsigned ipc = PIC32_IPC_IP0(1) | PIC32_IPC_IP1(1) | + PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) | + PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) | + PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ; + IPC(0) = ipc; + IPC(1) = ipc; + IPC(2) = ipc; + IPC(3) = ipc; + IPC(4) = ipc; + IPC(5) = ipc; + IPC(6) = ipc; + IPC(7) = ipc; + IPC(8) = ipc; + IPC(9) = ipc; + IPC(10) = ipc; + IPC(11) = ipc; + IPC(12) = ipc; /* * Setup wait states. @@ -328,6 +348,9 @@ startup() #endif #ifdef UARTUSB_ENABLED usbinit(); +#endif +#ifdef HX8357_ENABLED + hx8357_init(); #endif cninit(); diff --git a/sys/pic32/max32-eth/Makefile b/sys/pic32/max32-eth/Makefile index 12601e9..81652c2 100644 --- a/sys/pic32/max32-eth/Makefile +++ b/sys/pic32/max32-eth/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/max32/Makefile b/sys/pic32/max32/Makefile index 5a647f2..43b9bd3 100644 --- a/sys/pic32/max32/Makefile +++ b/sys/pic32/max32/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/maximite-color/MAXCOLOR b/sys/pic32/maximite-color/MAXIMITE-COLOR similarity index 100% rename from sys/pic32/maximite-color/MAXCOLOR rename to sys/pic32/maximite-color/MAXIMITE-COLOR diff --git a/sys/pic32/maximite-color/Makefile b/sys/pic32/maximite-color/Makefile index 2629593..856905a 100644 --- a/sys/pic32/maximite-color/Makefile +++ b/sys/pic32/maximite-color/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=13 @@ -45,6 +45,9 @@ DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO DEFS += -DDC3_USERID=0xffff DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT DEFS += -DFLASH_USER=0x1d005000 DEFS += -DGPIO_ENABLED=YES DEFS += -DHID_FEATURE_REPORT_BYTES=2 @@ -72,7 +75,7 @@ DEFS += -DUSB_NUM_STRING_DESCRIPTORS=3 LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-maxcolor.ld -CONFIG = MAXCOLOR +CONFIG = MAXIMITE-COLOR CONFIGPATH = ../../../tools/configsys include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/maximite/Makefile b/sys/pic32/maximite/Makefile index 248067b..95dd29a 100644 --- a/sys/pic32/maximite/Makefile +++ b/sys/pic32/maximite/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=13 diff --git a/sys/pic32/meb/Makefile b/sys/pic32/meb/Makefile index ba53acd..7a022df 100644 --- a/sys/pic32/meb/Makefile +++ b/sys/pic32/meb/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/mmb-mx7/Makefile b/sys/pic32/mmb-mx7/Makefile index 9eae304..6566e10 100644 --- a/sys/pic32/mmb-mx7/Makefile +++ b/sys/pic32/mmb-mx7/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/picadillo/Makefile b/sys/pic32/picadillo/Makefile new file mode 100644 index 0000000..a2e2339 --- /dev/null +++ b/sys/pic32/picadillo/Makefile @@ -0,0 +1,64 @@ +BUILDPATH = ../../../tools/configsys/../../sys/pic32 +H = ../../../tools/configsys/../../sys/include +M = ../../../tools/configsys/../../sys/pic32 +S = ../../../tools/configsys/../../sys/kernel + +vpath %.c $(M):$(S) +vpath %.S $(M):$(S) + +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +EXTRA_TARGETS = + +DEFS += -DADC_ENABLED=YES +DEFS += -DBUS_DIV=1 +DEFS += -DBUS_KHZ=80000 +DEFS += -DCONSOLE_DEVICE=tty0 +DEFS += -DCPU_IDIV=2 +DEFS += -DCPU_KHZ=80000 +DEFS += -DCPU_MUL=20 +DEFS += -DCPU_ODIV=1 +DEFS += -DCRYSTAL=8 +DEFS += -DDC0_DEBUG=DEVCFG0_DEBUG_DISABLED +DEFS += -DDC0_ICE=0 +DEFS += -DDC1_CKM=0 +DEFS += -DDC1_CKS=0 +DEFS += -DDC1_FNOSC=DEVCFG1_FNOSC_PRIPLL +DEFS += -DDC1_IESO=DEVCFG1_IESO +DEFS += -DDC1_OSCIOFNC=0 +DEFS += -DDC1_PBDIV=DEVCFG1_FPBDIV_1 +DEFS += -DDC1_POSCMOD=DEVCFG1_POSCMOD_HS +DEFS += -DDC1_SOSC=0 +DEFS += -DDC1_WDTEN=0 +DEFS += -DDC1_WDTPS=DEVCFG1_WDTPS_1 +DEFS += -DDC2_PLLIDIV=DEVCFG2_FPLLIDIV_2 +DEFS += -DDC2_PLLMUL=DEVCFG2_FPLLMUL_20 +DEFS += -DDC2_PLLODIV=DEVCFG2_FPLLODIV_1 +DEFS += -DDC2_UPLL=0 +DEFS += -DDC2_UPLLIDIV=DEVCFG2_UPLLIDIV_2 +DEFS += -DDC3_CAN=DEVCFG3_FCANIO +DEFS += -DDC3_ETH=DEVCFG3_FETHIO +DEFS += -DDC3_MII=DEVCFG3_FMIIEN +DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 +DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO +DEFS += -DDC3_USERID=0xffff +DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT +DEFS += -DGPIO_ENABLED=YES +DEFS += -DKERNEL +DEFS += -DPIC32MX7 +DEFS += -DSD0_CS_PIN=9 +DEFS += -DSD0_CS_PORT=TRISG +DEFS += -DSD0_PORT=2 +DEFS += -DUART1_BAUD=115200 +DEFS += -DUART1_ENABLED=YES +DEFS += -DUCB_METER + + +LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-max32.ld + +CONFIG = PICADILLO +CONFIGPATH = ../../../tools/configsys + +include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/picadillo/PICADILLO b/sys/pic32/picadillo/PICADILLO new file mode 100644 index 0000000..a23858b --- /dev/null +++ b/sys/pic32/picadillo/PICADILLO @@ -0,0 +1,19 @@ +# +# Picadillo 35T board +# =================== + +core pic32mx7 +mapping picadillo +linker bootloader-max32 + +device kernel cpu_khz=80000 bus_khz=80000 + +device console device=tty0 +device uart1 baud=115200 + +device rdisk +device sd0 port=2 cs=48 + +device gpio +device adc +device foreignbootloader diff --git a/sys/pic32/picadillo_rambo/Makefile b/sys/pic32/picadillo_rambo/Makefile new file mode 100644 index 0000000..a37cfa6 --- /dev/null +++ b/sys/pic32/picadillo_rambo/Makefile @@ -0,0 +1,102 @@ +BUILDPATH = ../../../tools/configsys/../../sys/pic32 +H = ../../../tools/configsys/../../sys/include +M = ../../../tools/configsys/../../sys/pic32 +S = ../../../tools/configsys/../../sys/kernel + +vpath %.c $(M):$(S) +vpath %.S $(M):$(S) + +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o hx8357.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rd_spirams.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +EXTRA_TARGETS = + +DEFS += -DADC_ENABLED=YES +DEFS += -DBUS_DIV=1 +DEFS += -DBUS_KHZ=80000 +DEFS += -DCONSOLE_DEVICE=tft0 +DEFS += -DCPU_IDIV=2 +DEFS += -DCPU_KHZ=80000 +DEFS += -DCPU_MUL=20 +DEFS += -DCPU_ODIV=1 +DEFS += -DCRYSTAL=8 +DEFS += -DDC0_DEBUG=DEVCFG0_DEBUG_DISABLED +DEFS += -DDC0_ICE=0 +DEFS += -DDC1_CKM=0 +DEFS += -DDC1_CKS=0 +DEFS += -DDC1_FNOSC=DEVCFG1_FNOSC_PRIPLL +DEFS += -DDC1_IESO=DEVCFG1_IESO +DEFS += -DDC1_OSCIOFNC=0 +DEFS += -DDC1_PBDIV=DEVCFG1_FPBDIV_1 +DEFS += -DDC1_POSCMOD=DEVCFG1_POSCMOD_HS +DEFS += -DDC1_SOSC=0 +DEFS += -DDC1_WDTEN=0 +DEFS += -DDC1_WDTPS=DEVCFG1_WDTPS_1 +DEFS += -DDC2_PLLIDIV=DEVCFG2_FPLLIDIV_2 +DEFS += -DDC2_PLLMUL=DEVCFG2_FPLLMUL_20 +DEFS += -DDC2_PLLODIV=DEVCFG2_FPLLODIV_1 +DEFS += -DDC2_UPLL=0 +DEFS += -DDC2_UPLLIDIV=DEVCFG2_UPLLIDIV_2 +DEFS += -DDC3_CAN=DEVCFG3_FCANIO +DEFS += -DDC3_ETH=DEVCFG3_FETHIO +DEFS += -DDC3_MII=DEVCFG3_FMIIEN +DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 +DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO +DEFS += -DDC3_USERID=0xffff +DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT +DEFS += -DGPIO_ENABLED=YES +DEFS += -DHX8357_ENABLED +DEFS += -DKERNEL +DEFS += -DPARTITION="spirams0:sa@2040" +DEFS += -DPIC32MX7 +DEFS += -DSD0_CS_PIN=9 +DEFS += -DSD0_CS_PORT=TRISG +DEFS += -DSD0_PORT=2 +DEFS += -DSPIRAMS_CHIPS=16 +DEFS += -DSPIRAMS_CHIPSIZE=128 +DEFS += -DSPIRAMS_CS0_PIN=0 +DEFS += -DSPIRAMS_CS0_PORT=TRISA +DEFS += -DSPIRAMS_CS10_PIN=6 +DEFS += -DSPIRAMS_CS10_PORT=TRISA +DEFS += -DSPIRAMS_CS11_PIN=7 +DEFS += -DSPIRAMS_CS11_PORT=TRISA +DEFS += -DSPIRAMS_CS12_PIN=14 +DEFS += -DSPIRAMS_CS12_PORT=TRISG +DEFS += -DSPIRAMS_CS13_PIN=12 +DEFS += -DSPIRAMS_CS13_PORT=TRISG +DEFS += -DSPIRAMS_CS14_PIN=13 +DEFS += -DSPIRAMS_CS14_PORT=TRISG +DEFS += -DSPIRAMS_CS15_PIN=5 +DEFS += -DSPIRAMS_CS15_PORT=TRISF +DEFS += -DSPIRAMS_CS1_PIN=1 +DEFS += -DSPIRAMS_CS1_PORT=TRISA +DEFS += -DSPIRAMS_CS2_PIN=4 +DEFS += -DSPIRAMS_CS2_PORT=TRISA +DEFS += -DSPIRAMS_CS3_PIN=5 +DEFS += -DSPIRAMS_CS3_PORT=TRISA +DEFS += -DSPIRAMS_CS4_PIN=2 +DEFS += -DSPIRAMS_CS4_PORT=TRISA +DEFS += -DSPIRAMS_CS5_PIN=1 +DEFS += -DSPIRAMS_CS5_PORT=TRISD +DEFS += -DSPIRAMS_CS6_PIN=2 +DEFS += -DSPIRAMS_CS6_PORT=TRISD +DEFS += -DSPIRAMS_CS7_PIN=14 +DEFS += -DSPIRAMS_CS7_PORT=TRISB +DEFS += -DSPIRAMS_CS8_PIN=14 +DEFS += -DSPIRAMS_CS8_PORT=TRISD +DEFS += -DSPIRAMS_CS9_PIN=8 +DEFS += -DSPIRAMS_CS9_PORT=TRISD +DEFS += -DSPIRAMS_ENABLED +DEFS += -DSPIRAMS_PORT=4 +DEFS += -DUART1_BAUD=115200 +DEFS += -DUART1_ENABLED=YES +DEFS += -DUCB_METER + + +LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-max32.ld + +CONFIG = PICADILLO_RAMBO +CONFIGPATH = ../../../tools/configsys + +include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/picadillo_rambo/PICADILLO_RAMBO b/sys/pic32/picadillo_rambo/PICADILLO_RAMBO new file mode 100644 index 0000000..9e8dd20 --- /dev/null +++ b/sys/pic32/picadillo_rambo/PICADILLO_RAMBO @@ -0,0 +1,23 @@ +# +# Picadillo 35T board +# =================== + +core pic32mx7 +mapping picadillo +linker bootloader-max32 + +device kernel cpu_khz=80000 bus_khz=80000 + +device console device=tft0 +device uart1 baud=115200 + +device rdisk +device sd0 port=2 cs=48 +device spirams0 port=4 chips=16 cs0=26 cs1=27 cs2=28 cs3=29 cs4=30 cs5=31 cs6=32 cs7=33 cs8=34 cs9=35 cs10=36 cs11=37 cs12=38 cs13=39 cs14=40 cs15=51 + +option PARTITION=spirams0:sa@2040 + +device hxtft +device gpio +device adc +device foreignbootloader diff --git a/sys/pic32/pinguino-micro/Makefile b/sys/pic32/pinguino-micro/Makefile index 2b3706f..633a7a7 100644 --- a/sys/pic32/pinguino-micro/Makefile +++ b/sys/pic32/pinguino-micro/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/rd_sd.c b/sys/pic32/rd_sd.c index 2634f37..8cd84f2 100644 --- a/sys/pic32/rd_sd.c +++ b/sys/pic32/rd_sd.c @@ -42,12 +42,12 @@ /* * Two SD/MMC disks on SPI. * Signals for SPI1: - * D0 - SDO1 - * D10 - SCK1 - * C4 - SDI1 + * D0 - SDO1 + * D10 - SCK1 + * C4 - SDI1 */ -#define NSD 2 -#define SECTSIZE 512 +#define NSD 2 +#define SECTSIZE 512 #define SPI_ENHANCED /* use SPI fifo */ #ifndef SD0_MHZ #define SD0_MHZ 13 /* speed 13.33 MHz */ @@ -82,23 +82,23 @@ int sd_timo_wait_widle; /* * Definitions for MMC/SDC commands. */ -#define CMD_GO_IDLE 0 /* CMD0 */ -#define CMD_SEND_OP_MMC 1 /* CMD1 (MMC) */ -#define CMD_SEND_IF_COND 8 -#define CMD_SEND_CSD 9 -#define CMD_SEND_CID 10 -#define CMD_STOP 12 -#define CMD_SEND_STATUS 13 /* CMD13 */ -#define CMD_SET_BLEN 16 -#define CMD_READ_SINGLE 17 -#define CMD_READ_MULTIPLE 18 -#define CMD_SET_BCOUNT 23 /* (MMC) */ -#define CMD_SET_WBECNT 23 /* ACMD23 (SDC) */ -#define CMD_WRITE_SINGLE 24 -#define CMD_WRITE_MULTIPLE 25 -#define CMD_SEND_OP_SDC 41 /* ACMD41 (SDC) */ -#define CMD_APP 55 /* CMD55 */ -#define CMD_READ_OCR 58 +#define CMD_GO_IDLE 0 /* CMD0 */ +#define CMD_SEND_OP_MMC 1 /* CMD1 (MMC) */ +#define CMD_SEND_IF_COND 8 +#define CMD_SEND_CSD 9 +#define CMD_SEND_CID 10 +#define CMD_STOP 12 +#define CMD_SEND_STATUS 13 /* CMD13 */ +#define CMD_SET_BLEN 16 +#define CMD_READ_SINGLE 17 +#define CMD_READ_MULTIPLE 18 +#define CMD_SET_BCOUNT 23 /* (MMC) */ +#define CMD_SET_WBECNT 23 /* ACMD23 (SDC) */ +#define CMD_WRITE_SINGLE 24 +#define CMD_WRITE_MULTIPLE 25 +#define CMD_SEND_OP_SDC 41 /* ACMD41 (SDC) */ +#define CMD_APP 55 /* CMD55 */ +#define CMD_READ_OCR 58 #define DATA_START_BLOCK 0xFE /* start data for single block */ #define STOP_TRAN_TOKEN 0xFD /* stop token for write multiple */ @@ -122,9 +122,9 @@ static void spi_wait_ready (int unit, int limit, int *maxcount) int i; spi_transfer(sd_fd[unit],0xFF); - for (i=0; i> 24); - spi_transfer(sd_fd[unit],addr >> 16); - spi_transfer(sd_fd[unit],addr >> 8); - spi_transfer(sd_fd[unit],addr); + /* Send a comand packet (6 bytes). */ + spi_transfer(sd_fd[unit],cmd | 0x40); + spi_transfer(sd_fd[unit],addr >> 24); + spi_transfer(sd_fd[unit],addr >> 16); + spi_transfer(sd_fd[unit],addr >> 8); + spi_transfer(sd_fd[unit],addr); - /* Send cmd checksum for CMD_GO_IDLE. + /* Send cmd checksum for CMD_GO_IDLE. * For all other commands, CRC is ignored. */ if (cmd == CMD_GO_IDLE) spi_transfer(sd_fd[unit],0x95); @@ -175,23 +175,23 @@ static int card_cmd(unsigned int unit, unsigned int cmd, unsigned int addr) else spi_transfer(sd_fd[unit],0xFF); - /* Wait for a response. */ - for (i=0; i= TIMO_SEND_OP) + spi_select(sd_fd[unit]); + if (reply == 0) + break; + if (i >= TIMO_SEND_OP) { /* Init timed out. */ printf ("card_init: SEND_OP timed out, reply = %d\n", reply); - return 0; - } - } + return 0; + } + } if (sd_timo_send_op < i) sd_timo_send_op = i; /* If SD2 read OCR register to check for SDHC card. */ - if (sd_type[unit] == 2) + if (sd_type[unit] == 2) { spi_select(sd_fd[unit]); reply = card_cmd(unit, CMD_READ_OCR, 0); - if (reply != 0) + if (reply != 0) { sd_deselect(sd_fd[unit]); printf ("sd%d: READ_OCR failed, reply=%02x\n", unit, reply); @@ -291,7 +291,7 @@ int card_init(int unit) response[2] = spi_transfer(sd_fd[unit],0xFF); response[3] = spi_transfer(sd_fd[unit],0xFF); sd_deselect(sd_fd[unit]); - if ((response[0] & 0xC0) == 0xC0) + if ((response[0] & 0xC0) == 0xC0) { sd_type[unit] = 3; } @@ -303,7 +303,7 @@ int card_init(int unit) if(unit == 1) spi_brg(sd_fd[unit],SD1_MHZ * 1000); #endif - return 1; + return 1; } /* @@ -312,52 +312,52 @@ int card_init(int unit) */ int sdsize(int unit) { - unsigned char csd [16]; - unsigned csize, n; - int reply, i; - int nsectors; + unsigned char csd [16]; + unsigned csize, n; + int reply, i; + int nsectors; - spi_select(sd_fd[unit]); - reply = card_cmd(unit,CMD_SEND_CSD, 0); - if (reply != 0) + spi_select(sd_fd[unit]); + reply = card_cmd(unit,CMD_SEND_CSD, 0); + if (reply != 0) { - /* Command rejected. */ - sd_deselect(sd_fd[unit]); - return 0; - } - /* Wait for a response. */ - for (i=0; ; i++) + /* Command rejected. */ + sd_deselect(sd_fd[unit]); + return 0; + } + /* Wait for a response. */ + for (i=0; ; i++) { - reply = spi_transfer(sd_fd[unit],0xFF); - if (reply == DATA_START_BLOCK) - break; - if (i >= TIMO_SEND_CSD) + reply = spi_transfer(sd_fd[unit],0xFF); + if (reply == DATA_START_BLOCK) + break; + if (i >= TIMO_SEND_CSD) { - /* Command timed out. */ - sd_deselect(sd_fd[unit]); - printf ("sd%d: card_size: SEND_CSD timed out, reply = %d\n", + /* Command timed out. */ + sd_deselect(sd_fd[unit]); + printf ("sd%d: card_size: SEND_CSD timed out, reply = %d\n", unit, reply); - return 0; - } - } + return 0; + } + } if (sd_timo_send_csd < i) sd_timo_send_csd = i; - /* Read data. */ - for (i=0; i> 6) + switch (csd[0] >> 6) { case 1: /* SDC ver 2.00 */ csize = csd[9] + (csd[8] << 8) + 1; @@ -370,8 +370,8 @@ int sdsize(int unit) break; default: /* Unknown version. */ return 0; - } - return nsectors>>1; + } + return nsectors>>1; } /* @@ -380,44 +380,44 @@ int sdsize(int unit) */ int card_read(int unit, unsigned int offset, char *data, unsigned int bcount) { - int reply, i; + int reply, i; - /* Send read-multiple command. */ - spi_select(sd_fd[unit]); - if (sd_type[unit] != 3) offset <<= 9; - reply = card_cmd(unit, CMD_READ_MULTIPLE, offset<<1); - if (reply != 0) + /* Send read-multiple command. */ + spi_select(sd_fd[unit]); + if (sd_type[unit] != 3) offset <<= 9; + reply = card_cmd(unit, CMD_READ_MULTIPLE, offset<<1); + if (reply != 0) { - /* Command rejected. */ + /* Command rejected. */ printf ("sd%d: card_read: bad READ_MULTIPLE reply = %d, offset = %08x\n", unit, reply, offset<<1); - sd_deselect(sd_fd[unit]); - return 0; - } + sd_deselect(sd_fd[unit]); + return 0; + } again: - /* Wait for a response. */ - for (i=0; ; i++) + /* Wait for a response. */ + for (i=0; ; i++) { int x = spl0(); - reply = spi_transfer(sd_fd[unit],0xFF); - splx(x); - if (reply == DATA_START_BLOCK) - break; - if (i >= TIMO_READ) + reply = spi_transfer(sd_fd[unit],0xFF); + splx(x); + if (reply == DATA_START_BLOCK) + break; + if (i >= TIMO_READ) { - /* Command timed out. */ + /* Command timed out. */ printf ("sd%d: card_read: READ_MULTIPLE timed out, reply = %d\n", unit, reply); - sd_deselect(sd_fd[unit]); - return 0; - } - } + sd_deselect(sd_fd[unit]); + return 0; + } + } if (sd_timo_read < i) sd_timo_read = i; - /* Read data. */ - if (bcount >= SECTSIZE) + /* Read data. */ + if (bcount >= SECTSIZE) { spi_bulk_read_32_be(sd_fd[unit],SECTSIZE,data); data += SECTSIZE; @@ -427,11 +427,11 @@ again: for (i=bcount; i SECTSIZE) + if (bcount > SECTSIZE) { /* Next sector. */ bcount -= SECTSIZE; @@ -439,9 +439,9 @@ again: } /* Stop a read-multiple sequence. */ - card_cmd(unit, CMD_STOP, 0); - sd_deselect(sd_fd[unit]); - return 1; + card_cmd(unit, CMD_STOP, 0); + sd_deselect(sd_fd[unit]); + return 1; } /* @@ -451,40 +451,40 @@ again: int card_write (int unit, unsigned offset, char *data, unsigned bcount) { - unsigned reply, i; + unsigned reply, i; - /* Send pre-erase count. */ - spi_select(sd_fd[unit]); + /* Send pre-erase count. */ + spi_select(sd_fd[unit]); card_cmd(unit, CMD_APP, 0); - reply = card_cmd(unit, CMD_SET_WBECNT, (bcount + SECTSIZE - 1) / SECTSIZE); - if (reply != 0) + reply = card_cmd(unit, CMD_SET_WBECNT, (bcount + SECTSIZE - 1) / SECTSIZE); + if (reply != 0) { - /* Command rejected. */ - sd_deselect(sd_fd[unit]); + /* Command rejected. */ + sd_deselect(sd_fd[unit]); printf("sd%d: card_write: bad SET_WBECNT reply = %02x, count = %u\n", unit, reply, (bcount + SECTSIZE - 1) / SECTSIZE); - return 0; - } + return 0; + } - /* Send write-multiple command. */ - if (sd_type[unit] != 3) offset <<= 9; - reply = card_cmd(unit, CMD_WRITE_MULTIPLE, offset<<1); - if (reply != 0) + /* Send write-multiple command. */ + if (sd_type[unit] != 3) offset <<= 9; + reply = card_cmd(unit, CMD_WRITE_MULTIPLE, offset<<1); + if (reply != 0) { - /* Command rejected. */ - sd_deselect(sd_fd[unit]); + /* Command rejected. */ + sd_deselect(sd_fd[unit]); printf("sd%d: card_write: bad WRITE_MULTIPLE reply = %02x\n", unit, reply); - return 0; - } - sd_deselect(sd_fd[unit]); + return 0; + } + sd_deselect(sd_fd[unit]); again: /* Select, wait while busy. */ - spi_select(sd_fd[unit]); + spi_select(sd_fd[unit]); spi_wait_ready(unit, TIMO_WAIT_WDATA, &sd_timo_wait_wdata); - /* Send data. */ - spi_transfer(sd_fd[unit],WRITE_MULTIPLE_TOKEN); - if (bcount >= SECTSIZE) + /* Send data. */ + spi_transfer(sd_fd[unit],WRITE_MULTIPLE_TOKEN); + if (bcount >= SECTSIZE) { spi_bulk_write_32_be(sd_fd[unit],SECTSIZE,data); data += SECTSIZE; @@ -494,27 +494,27 @@ again: for (i=bcount; i SECTSIZE) + if (bcount > SECTSIZE) { /* Next sector. */ bcount -= SECTSIZE; @@ -522,18 +522,18 @@ again: } /* Stop a write-multiple sequence. */ - spi_select(sd_fd[unit]); + spi_select(sd_fd[unit]); spi_wait_ready(unit, TIMO_WAIT_WSTOP, &sd_timo_wait_wstop); - spi_transfer(sd_fd[unit],STOP_TRAN_TOKEN); + spi_transfer(sd_fd[unit],STOP_TRAN_TOKEN); spi_wait_ready(unit, TIMO_WAIT_WIDLE, &sd_timo_wait_widle); - sd_deselect(sd_fd[unit]); - return 1; + sd_deselect(sd_fd[unit]); + return 1; } void sd_preinit (int unit) { - if (unit >= NSD) - return; + if (unit >= NSD) + return; int fd = -1; if(unit==0) @@ -575,7 +575,7 @@ void sd_preinit (int unit) int sdinit (int unit, int flag) { - unsigned nsectors; + unsigned nsectors; /* Detect a card. */ #ifdef SD0_ENA_PORT @@ -596,12 +596,12 @@ int sdinit (int unit, int flag) } #endif - if (!card_init(unit)) + if (!card_init(unit)) { printf ("sd%d: no SD/MMC card detected\n", unit); return ENODEV; } - if ((nsectors=sdsize(unit))==0) + if ((nsectors=sdsize(unit))==0) { printf ("sd%d: cannot get card size\n", unit); return ENODEV; @@ -614,8 +614,8 @@ int sdinit (int unit, int flag) nsectors, spi_get_brg(sd_fd[unit]) / 1000); } - DEBUG("sd%d: init done\n",unit); - return 0; + DEBUG("sd%d: init done\n",unit); + return 0; } int sddeinit(int unit) @@ -642,6 +642,6 @@ int sddeinit(int unit) int sdopen(int unit, int flags, int mode) { - DEBUG("sd%d: open\n",unit); - return 0; + DEBUG("sd%d: open\n",unit); + return 0; } diff --git a/sys/pic32/rd_spirams.c b/sys/pic32/rd_spirams.c new file mode 100644 index 0000000..531080b --- /dev/null +++ b/sys/pic32/rd_spirams.c @@ -0,0 +1,438 @@ +#include "param.h" +#include "systm.h" +#include "buf.h" +#include "errno.h" +#include "dk.h" +#include "rdisk.h" +#include "spi_bus.h" + +#include "debug.h" + +#define SPIRAM_WREN 0x06 +#define SPIRAM_WRDI 0x04 +#define SPIRAM_RDSR 0x05 +#define SPIRAM_WRSR 0x01 +#define SPIRAM_READ 0x03 +#define SPIRAM_WRITE 0x02 +#define SPIRAM_SLEEP 0xB9 +#define SPIRAM_WAKE 0xAB + +#ifndef SPIRAMS_MHZ +#define SPIRAMS_MHZ 10 +#endif + +int fd[SPIRAMS_CHIPS]; + +int spirams_size(int unit) +{ + return SPIRAMS_CHIPS * SPIRAMS_CHIPSIZE; +} + +#define MRBSIZE 1024 +#define MRBLOG2 10 + +unsigned int spir_read_block(unsigned int chip, unsigned int address, unsigned int length, char *data) +{ + register unsigned int cs = 0; + + switch(chip) + { + case 0: + #ifdef SPIRAMS_LED0_PORT + TRIS_CLR(SPIRAMS_LED0_PORT) = 1<>16); + spi_transfer(fd[chip], address>>8); + spi_transfer(fd[chip], address); + + // If the length is a multiple of 32 bits, then do a 32 bit transfer +/* + if((length & 0x03) == 0) + spi_bulk_read_32(fd[chip],length,data); + else if((length & 0x01) == 0) + spi_bulk_read_16(fd[chip],length,data); + else +*/ + spi_bulk_read(fd[chip],length,(unsigned char *)data); + + spi_deselect(fd[chip]); + + switch(chip) + { + case 0: + #ifdef SPIRAMS_LED0_PORT + LAT_CLR(SPIRAMS_LED0_PORT) = 1< 0) + { + pass++; + toread = bcount; + if(toread > MRBSIZE) + toread = MRBSIZE; + + chip = offset / SPIRAMS_CHIPSIZE; + + address = (offset<<10) - (chip * (SPIRAMS_CHIPSIZE*1024)); + + + if(chip>=SPIRAMS_CHIPS) + { + printf("!!!EIO\n"); + return EIO; + } + spir_read_block(chip, address, toread, data); + bcount -= toread; + offset += (toread>>MRBLOG2); + data += toread; + } + return 1; +} + +unsigned int spir_write_block(unsigned int chip, unsigned int address, unsigned int length, char *data) +{ + register unsigned int cs = 0; + char blank __attribute__((unused)); + + switch(chip) + { + case 0: + #ifdef SPIRAMS_LED0_PORT + TRIS_CLR(SPIRAMS_LED0_PORT) = 1<>16); + spi_transfer(fd[chip], address>>8); + spi_transfer(fd[chip], address); + +/* + if((length & 0x03) == 0) + spi_bulk_write_32(fd[chip],length,data); + else if((length & 0x01) == 0) + spi_bulk_write_16(fd[chip],length,data); + else +*/ + spi_bulk_write(fd[chip],length,(unsigned char *)data); + + spi_deselect(fd[chip]); + + switch(chip) + { + case 0: + #ifdef SPIRAMS_LED0_PORT + LAT_CLR(SPIRAMS_LED0_PORT) = 1< 0) + { + pass++; + towrite = bcount; + if(towrite > MRBSIZE) + towrite = MRBSIZE; + + chip = offset / SPIRAMS_CHIPSIZE; + address = (offset<<10) - (chip * (SPIRAMS_CHIPSIZE*MRBSIZE)); + + if(chip>=SPIRAMS_CHIPS) + { + printf("!!!EIO\n"); + return EIO; + } + + spir_write_block(chip, address, towrite, data); + bcount -= towrite; + offset += (towrite>>MRBLOG2); + data += towrite; + } + return 1; +} + +void spirams_preinit (int unit) +{ + struct buf *bp; + + if (unit >= 1) + return; + + /* Initialize hardware. */ + + + fd[0] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS0_PORT,SPIRAMS_CS0_PIN); + if(fd[0]==-1) return; + + spi_brg(fd[0],SPIRAMS_MHZ * 1000); + spi_set(fd[0],PIC32_SPICON_CKE); + +#ifdef SPIRAMS_CS1_PORT + fd[1] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS1_PORT,SPIRAMS_CS1_PIN); + + spi_brg(fd[1],SPIRAMS_MHZ * 1000); + spi_set(fd[1],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS2_PORT + fd[2] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS2_PORT,SPIRAMS_CS2_PIN); + + spi_brg(fd[2],SPIRAMS_MHZ * 1000); + spi_set(fd[2],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS3_PORT + fd[3] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS3_PORT,SPIRAMS_CS3_PIN); + + spi_brg(fd[3],SPIRAMS_MHZ * 1000); + spi_set(fd[3],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS4_PORT + fd[4] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS4_PORT,SPIRAMS_CS4_PIN); + + spi_brg(fd[4],SPIRAMS_MHZ * 1000); + spi_set(fd[4],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS5_PORT + fd[5] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS5_PORT,SPIRAMS_CS5_PIN); + + spi_brg(fd[5],SPIRAMS_MHZ * 1000); + spi_set(fd[5],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS6_PORT + fd[6] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS6_PORT,SPIRAMS_CS6_PIN); + + spi_brg(fd[6],SPIRAMS_MHZ * 1000); + spi_set(fd[6],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS7_PORT + fd[7] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS7_PORT,SPIRAMS_CS7_PIN); + + spi_brg(fd[7],SPIRAMS_MHZ * 1000); + spi_set(fd[7],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS8_PORT + fd[8] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS8_PORT,SPIRAMS_CS8_PIN); + + spi_brg(fd[8],SPIRAMS_MHZ * 1000); + spi_set(fd[8],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS9_PORT + fd[9] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS9_PORT,SPIRAMS_CS9_PIN); + + spi_brg(fd[9],SPIRAMS_MHZ * 1000); + spi_set(fd[9],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS10_PORT + fd[10] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS10_PORT,SPIRAMS_CS10_PIN); + + spi_brg(fd[10],SPIRAMS_MHZ * 1000); + spi_set(fd[10],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS11_PORT + fd[11] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS11_PORT,SPIRAMS_CS11_PIN); + + spi_brg(fd[11],SPIRAMS_MHZ * 1000); + spi_set(fd[11],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS12_PORT + fd[12] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS12_PORT,SPIRAMS_CS12_PIN); + + spi_brg(fd[12],SPIRAMS_MHZ * 1000); + spi_set(fd[12],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS13_PORT + fd[13] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS13_PORT,SPIRAMS_CS13_PIN); + + spi_brg(fd[13],SPIRAMS_MHZ * 1000); + spi_set(fd[13],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS14_PORT + fd[14] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS14_PORT,SPIRAMS_CS14_PIN); + + spi_brg(fd[14],SPIRAMS_MHZ * 1000); + spi_set(fd[14],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS15_PORT + fd[15] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS15_PORT,SPIRAMS_CS15_PIN); + + spi_brg(fd[15],SPIRAMS_MHZ * 1000); + spi_set(fd[15],PIC32_SPICON_CKE); +#endif + + printf("spirams0: port %d %s, size %dKB, speed %d Mbit/sec\n", + SPIRAMS_PORT, spi_name(fd[0]),SPIRAMS_CHIPS * SPIRAMS_CHIPSIZE, + spi_get_brg(fd[0]) / 1000); + bp = prepartition_device("spirams0"); + if(bp) + { + spirams_write (0, 0, bp->b_addr, 512); + brelse(bp); + } +} diff --git a/sys/pic32/spi_bus.c b/sys/pic32/spi_bus.c index 130478c..b9e0574 100644 --- a/sys/pic32/spi_bus.c +++ b/sys/pic32/spi_bus.c @@ -8,7 +8,7 @@ #define NSPI 4 /* Ports SPI1...SPI4 */ -#define MAXSPIDEV 10 +#define MAXSPIDEV 20 struct spi_dev spi_devices[MAXSPIDEV]; @@ -616,7 +616,7 @@ char *spi_name(int dno) return "SPI?"; if(spi_devices[dno].bus==NULL) - return "SPI?"; + return "NO SPI BUS"; if(spi_devices[dno].bus == (struct spireg *)&SPI1CON) return "SPI1"; diff --git a/sys/pic32/starter-kit/Makefile b/sys/pic32/starter-kit/Makefile index efba415..7d8d018 100644 --- a/sys/pic32/starter-kit/Makefile +++ b/sys/pic32/starter-kit/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/_startup.S b/sys/pic32/startup.S similarity index 97% rename from sys/pic32/_startup.S rename to sys/pic32/startup.S index dddbdee..44b0bd4 100644 --- a/sys/pic32/_startup.S +++ b/sys/pic32/startup.S @@ -109,6 +109,17 @@ _entry_vector_: .globl _entry_vector_ jr $k0 nop +/* + * Data for bootloader. + */ + .org 0xf8 + .type _ebase, @object +_ebase: .word 0x9d000000 # EBase value + + .type _imgptr, @object +_imgptr: .word -1 # Image header pointer + + #--------------------------------------- # Exception vector: handle interrupts and exceptions # diff --git a/sys/pic32/uart.c b/sys/pic32/uart.c index d2093e7..26e2cb5 100644 --- a/sys/pic32/uart.c +++ b/sys/pic32/uart.c @@ -639,7 +639,7 @@ void uartstart (register struct tty *tp) s = spltty(); if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { out: /* Disable transmit_interrupt. */ - led_control (LED_TTY, 0); + led_control (LED_TTY, 0); splx (s); return; } @@ -705,7 +705,7 @@ again: if (--timo == 0) break; if (tp->t_state & TS_BUSY) { - uartintr (0); + uartintr (dev); goto again; } led_control (LED_TTY, 1); diff --git a/sys/pic32/ubw32-uart-sdram/Makefile b/sys/pic32/ubw32-uart-sdram/Makefile index 84b52ed..8e73a02 100644 --- a/sys/pic32/ubw32-uart-sdram/Makefile +++ b/sys/pic32/ubw32-uart-sdram/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rd_sdramp.o rdisk.o sdram.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rd_sdramp.o rdisk.o sdram.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=7 diff --git a/sys/pic32/ubw32-uart/Makefile b/sys/pic32/ubw32-uart/Makefile index 8ff0aec..a0f2b45 100644 --- a/sys/pic32/ubw32-uart/Makefile +++ b/sys/pic32/ubw32-uart/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=7 diff --git a/sys/pic32/ubw32/Makefile b/sys/pic32/ubw32/Makefile index 39699a2..64f97a9 100644 --- a/sys/pic32/ubw32/Makefile +++ b/sys/pic32/ubw32/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=7 diff --git a/tools/fsutil/Makefile b/tools/fsutil/Makefile index 02c4297..fa1a27b 100644 --- a/tools/fsutil/Makefile +++ b/tools/fsutil/Makefile @@ -1,12 +1,17 @@ CC = gcc -g CFLAGS = -O -Wall DESTDIR = /usr/local -OBJS = fsutil.o superblock.o block.c inode.o create.o check.o file.o +OBJS = fsutil.o superblock.o block.c inode.o create.o check.o \ + file.o mount.o manifest.o PROG = fsutil # For Mac OS X #LIBS = -largp +# Fuse +MOUNT_CFLAGS = $(shell pkg-config fuse --cflags) +LIBS += $(shell pkg-config fuse --libs) + all: $(PROG) install: $(PROG) @@ -25,10 +30,14 @@ root.bin: $(PROG) swap.bin: dd bs=1k count=2048 < /dev/zero > $@ +mount.o: mount.c bsdfs.h + $(CC) $(CFLAGS) $(MOUNT_CFLAGS) -c -o $@ $< + block.o: block.c bsdfs.h check.o: check.c bsdfs.h create.o: create.c bsdfs.h file.o: file.c bsdfs.h -fsutil.o: fsutil.c bsdfs.h +fsutil.o: fsutil.c bsdfs.h manifest.h inode.o: inode.c bsdfs.h +manifest.o: manifest.c bsdfs.h manifest.h superblock.o: superblock.c bsdfs.h diff --git a/tools/fsutil/block.c b/tools/fsutil/block.c index d178e66..0606c58 100644 --- a/tools/fsutil/block.c +++ b/tools/fsutil/block.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include "bsdfs.h" @@ -14,29 +28,29 @@ extern int verbose; int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data) { - if (verbose > 3) - printf ("read block %d\n", bnum); - if (bnum < fs->isize) - return 0; - if (! fs_seek (fs, bnum * BSDFS_BSIZE)) - return 0; - if (! fs_read (fs, data, BSDFS_BSIZE)) - return 0; - return 1; + if (verbose > 3) + printf ("read block %d\n", bnum); + if (bnum < fs->isize) + return 0; + if (! fs_seek (fs, bnum * BSDFS_BSIZE)) + return 0; + if (! fs_read (fs, data, BSDFS_BSIZE)) + return 0; + return 1; } int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data) { - if (verbose > 3) - printf ("write block %d\n", bnum); - if (! fs->writable || bnum < fs->isize) - return 0; - if (! fs_seek (fs, bnum * BSDFS_BSIZE)) - return 0; - if (! fs_write (fs, data, BSDFS_BSIZE)) - return 0; - fs->modified = 1; - return 1; + if (verbose > 3) + printf ("write block %d\n", bnum); + if (! fs->writable || bnum < fs->isize) + return 0; + if (! fs_seek (fs, bnum * BSDFS_BSIZE)) + return 0; + if (! fs_write (fs, data, BSDFS_BSIZE)) + return 0; + fs->modified = 1; + return 1; } /* @@ -44,93 +58,110 @@ int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data) */ int fs_block_free (fs_t *fs, unsigned int bno) { - int i; - unsigned buf [BSDFS_BSIZE / 4]; + int i; + unsigned buf [BSDFS_BSIZE / 4]; - if (verbose > 1) - printf ("free block %d, total %d\n", bno, fs->nfree); - if (fs->nfree >= NICFREE) { - buf[0] = fs->nfree; - for (i=0; ifree[i]; - if (! fs_write_block (fs, bno, (unsigned char*) buf)) { - fprintf (stderr, "block_free: write error at block %d\n", bno); - return 0; - } - fs->nfree = 0; - } - fs->free [fs->nfree] = bno; - fs->nfree++; - fs->dirty = 1; - if (bno) /* Count total free blocks. */ - ++fs->tfree; - return 1; + if (verbose > 1) + printf ("free block %d, total %d\n", bno, fs->nfree); + if (fs->nfree >= NICFREE) { + buf[0] = fs->nfree; + for (i=0; ifree[i]; + if (! fs_write_block (fs, bno, (unsigned char*) buf)) { + fprintf (stderr, "block_free: write error at block %d\n", bno); + return 0; + } + fs->nfree = 0; + } + fs->free [fs->nfree] = bno; + fs->nfree++; + fs->dirty = 1; + if (bno) /* Count total free blocks. */ + ++fs->tfree; + return 1; } /* * Free an indirect block. */ -int fs_indirect_block_free (fs_t *fs, unsigned int bno) +int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-2; i>=0; i-=2) { - nb = data [i+1] << 8 | data [i]; - if (nb) - fs_block_free (fs, nb); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_block_free (fs, nb); + } + fs_block_free (fs, bno); + return 1; } /* * Free a double indirect block. */ -int fs_double_indirect_block_free (fs_t *fs, unsigned int bno) +int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-2; i>=0; i-=2) { - nb = data [i+1] << 8 | data [i]; - if (nb) - fs_indirect_block_free (fs, nb); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 * BSDFS_BSIZE/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_indirect_block_free (fs, nb, + nblk - i/4 * BSDFS_BSIZE/4); + } + fs_block_free (fs, bno); + return 1; } /* * Free a triple indirect block. */ -int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno) +int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-2; i>=0; i-=2) { - nb = data [i+1] << 8 | data [i]; - if (nb) - fs_double_indirect_block_free (fs, nb); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_double_indirect_block_free (fs, nb, + nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4); + } + fs_block_free (fs, bno); + return 1; } /* @@ -138,26 +169,26 @@ int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno) */ int fs_block_alloc (fs_t *fs, unsigned int *bno) { - int i; - unsigned buf [BSDFS_BSIZE / 4]; + int i; + unsigned buf [BSDFS_BSIZE / 4]; again: - if (fs->nfree == 0) - return 0; - fs->nfree--; - --fs->tfree; /* Count total free blocks. */ - *bno = fs->free [fs->nfree]; - if (verbose) - printf ("allocate new block %d from slot %d\n", *bno, fs->nfree); - fs->free [fs->nfree] = 0; - fs->dirty = 1; - if (fs->nfree <= 0) { - if (! fs_read_block (fs, *bno, (unsigned char*) buf)) - return 0; - fs->nfree = buf[0]; - for (i=0; ifree[i] = buf[i+1]; - } - if (*bno == 0) - goto again; - return 1; + if (fs->nfree == 0) + return 0; + fs->nfree--; + --fs->tfree; /* Count total free blocks. */ + *bno = fs->free [fs->nfree]; + if (verbose) + printf ("allocate new block %d from slot %d\n", *bno, fs->nfree); + fs->free [fs->nfree] = 0; + fs->dirty = 1; + if (fs->nfree <= 0) { + if (! fs_read_block (fs, *bno, (unsigned char*) buf)) + return 0; + fs->nfree = buf[0]; + for (i=0; ifree[i] = buf[i+1]; + } + if (*bno == 0) + goto again; + return 1; } diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index 4dc8ff9..ee11332 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -3,136 +3,155 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ -#define BSDFS_BSIZE 1024 /* block size */ -#define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */ -#define BSDFS_LOSTFOUND_INODE 3 /* lost+found directory in inode 3 */ -#define BSDFS_SWAP_INODE 4 /* swap file in inode 4 */ -#define BSDFS_INODES_PER_BLOCK 16 /* inodes per block */ +#define BSDFS_BSIZE 1024 /* block size */ +#define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */ +#define BSDFS_LOSTFOUND_INODE 3 /* lost+found directory in inode 3 */ +#define BSDFS_SWAP_INODE 4 /* swap file in inode 4 */ +#define BSDFS_INODES_PER_BLOCK 16 /* inodes per block */ -#define NICINOD 32 /* number of superblock inodes */ -#define NICFREE 200 /* number of superblock free blocks */ +#define NICINOD 32 /* number of superblock inodes */ +#define NICFREE 200 /* number of superblock free blocks */ /* * 28 of the di_addr address bytes are used; 7 addresses of 4 * bytes each: 4 direct (4Kb directly accessible) and 3 indirect. */ -#define NDADDR 4 /* direct addresses in inode */ -#define NIADDR 3 /* indirect addresses in inode */ -#define NADDR (NDADDR + NIADDR) /* total addresses in inode */ +#define NDADDR 4 /* direct addresses in inode */ +#define NIADDR 3 /* indirect addresses in inode */ +#define NADDR (NDADDR + NIADDR) /* total addresses in inode */ /* * NINDIR is the number of indirects in a file system block. */ -#define NINDIR (DEV_BSIZE / sizeof(daddr_t)) -#define NSHIFT 8 /* log2(NINDIR) */ -#define NMASK 0377L /* NINDIR - 1 */ +#define NINDIR (DEV_BSIZE / sizeof(daddr_t)) +#define NSHIFT 8 /* log2(NINDIR) */ +#define NMASK 0377L /* NINDIR - 1 */ /* * The path name on which the file system is mounted is maintained * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in * the super block for this name. */ -#define MAXMNTLEN 28 +#define MAXMNTLEN 28 -#define MAXNAMLEN 63 - -#define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24) -#define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24) +#define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24) +#define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24) typedef struct { - const char *filename; - int fd; - unsigned long seek; - int writable; - int dirty; /* sync needed */ - int modified; /* write_block was called */ + const char *filename; + int fd; + unsigned long seek; + int writable; + int dirty; /* sync needed */ + int modified; /* write_block was called */ - unsigned isize; /* size in blocks of superblock + I list */ - unsigned fsize; /* size in blocks of entire volume */ - unsigned swapsz; /* size in blocks of swap area */ - unsigned nfree; /* number of in core free blocks (0-100) */ - unsigned free [NICFREE]; /* in core free blocks */ - unsigned ninode; /* number of in core I nodes (0-100) */ - unsigned inode [NICINOD]; /* in core free I nodes */ - unsigned flock; /* lock during free list manipulation */ - unsigned ilock; /* lock during I list manipulation */ - unsigned fmod; /* super block modified flag */ - unsigned ronly; /* mounted read-only flag */ - long utime; /* current date of last update */ - unsigned tfree; /* total free blocks */ - unsigned tinode; /* total free inodes */ - char fsmnt [MAXMNTLEN]; /* ordinary file mounted on */ - unsigned lasti; /* start place for circular search */ - unsigned nbehind; /* est # free inodes before s_lasti */ - unsigned flags; /* mount time flags */ + unsigned isize; /* size in blocks of superblock + I list */ + unsigned fsize; /* size in blocks of entire volume */ + unsigned swapsz; /* size in blocks of swap area */ + unsigned nfree; /* number of in core free blocks (0-100) */ + unsigned free [NICFREE]; /* in core free blocks */ + unsigned ninode; /* number of in core I nodes (0-100) */ + unsigned inode [NICINOD]; /* in core free I nodes */ + unsigned flock; /* lock during free list manipulation */ + unsigned ilock; /* lock during I list manipulation */ + unsigned fmod; /* super block modified flag */ + unsigned ronly; /* mounted read-only flag */ + long utime; /* current date of last update */ + unsigned tfree; /* total free blocks */ + unsigned tinode; /* total free inodes */ + char fsmnt [MAXMNTLEN]; /* ordinary file mounted on */ + unsigned lasti; /* start place for circular search */ + unsigned nbehind; /* est # free inodes before s_lasti */ + unsigned flags; /* mount time flags */ } fs_t; typedef struct { - fs_t *fs; - unsigned number; - int dirty; /* save needed */ + fs_t *fs; + unsigned number; + int dirty; /* save needed */ - unsigned short mode; /* file type and access mode */ -#define INODE_MODE_FMT 0170000 /* type of file */ -#define INODE_MODE_FCHR 020000 /* character special */ -#define INODE_MODE_FDIR 040000 /* directory */ -#define INODE_MODE_FBLK 060000 /* block special */ -#define INODE_MODE_FREG 0100000 /* regular */ -#define INODE_MODE_FLNK 0120000 /* symbolic link */ -#define INODE_MODE_FSOCK 0140000 /* socket */ -#define INODE_MODE_SUID 04000 /* set user id on execution */ -#define INODE_MODE_SGID 02000 /* set group id on execution */ -#define INODE_MODE_SVTX 01000 /* save swapped text even after use */ -#define INODE_MODE_READ 0400 /* read, write, execute permissions */ -#define INODE_MODE_WRITE 0200 -#define INODE_MODE_EXEC 0100 + unsigned short mode; /* file type and access mode */ +#define INODE_MODE_FMT 0170000 /* type of file */ +#define INODE_MODE_FCHR 020000 /* character special */ +#define INODE_MODE_FDIR 040000 /* directory */ +#define INODE_MODE_FBLK 060000 /* block special */ +#define INODE_MODE_FREG 0100000 /* regular */ +#define INODE_MODE_FLNK 0120000 /* symbolic link */ +#define INODE_MODE_FSOCK 0140000 /* socket */ +#define INODE_MODE_SUID 04000 /* set user id on execution */ +#define INODE_MODE_SGID 02000 /* set group id on execution */ +#define INODE_MODE_SVTX 01000 /* save swapped text even after use */ +#define INODE_MODE_READ 0400 /* read, write, execute permissions */ +#define INODE_MODE_WRITE 0200 +#define INODE_MODE_EXEC 0100 - unsigned short nlink; /* directory entries */ - unsigned uid; /* owner */ - unsigned gid; /* group */ - unsigned long size; /* size */ - unsigned addr [7]; /* device addresses constituting file */ - unsigned flags; /* user defined flags */ + unsigned short nlink; /* directory entries */ + unsigned uid; /* owner */ + unsigned gid; /* group */ + unsigned long size; /* size */ + unsigned addr [7]; /* device addresses constituting file */ + unsigned flags; /* user defined flags */ /* * Super-user and owner changeable flags. */ -#define USER_SETTABLE 0x00ff /* mask of owner changeable flags */ -#define USER_NODUMP 0x0001 /* do not dump file */ -#define USER_IMMUTABLE 0x0002 /* file may not be changed */ -#define USER_APPEND 0x0004 /* writes to file may only append */ +#define USER_SETTABLE 0x00ff /* mask of owner changeable flags */ +#define USER_NODUMP 0x0001 /* do not dump file */ +#define USER_IMMUTABLE 0x0002 /* file may not be changed */ +#define USER_APPEND 0x0004 /* writes to file may only append */ /* * Super-user changeable flags. */ -#define SYS_SETTABLE 0xff00 /* mask of superuser changeable flags */ -#define SYS_ARCHIVED 0x0100 /* file is archived */ -#define SYS_IMMUTABLE 0x0200 /* file may not be changed */ -#define SYS_APPEND 0x0400 /* writes to file may only append */ +#define SYS_SETTABLE 0xff00 /* mask of superuser changeable flags */ +#define SYS_ARCHIVED 0x0100 /* file is archived */ +#define SYS_IMMUTABLE 0x0200 /* file may not be changed */ +#define SYS_APPEND 0x0400 /* writes to file may only append */ - long atime; /* time last accessed */ - long mtime; /* time last modified */ - long ctime; /* time created */ + long atime; /* time last accessed */ + long mtime; /* time last modified */ + long ctime; /* time created */ } fs_inode_t; typedef struct { - unsigned ino; - unsigned reclen; - unsigned namlen; - char name [MAXNAMLEN+1]; + unsigned ino; + unsigned reclen; + unsigned namlen; + char name [63+1]; } fs_dirent_t; typedef void (*fs_directory_scanner_t) (fs_inode_t *dir, - fs_inode_t *file, char *dirname, char *filename, void *arg); + fs_inode_t *file, char *dirname, char *filename, void *arg); typedef struct { - fs_inode_t inode; - int writable; /* write allowed */ - unsigned long offset; /* current i/o offset */ + fs_inode_t inode; + int writable; /* write allowed */ + unsigned long offset; /* current i/o offset */ } fs_file_t; +typedef enum { + INODE_OP_LOOKUP, /* lookup inode by name */ + INODE_OP_CREATE, /* create new file */ + INODE_OP_DELETE, /* delete file */ + INODE_OP_LINK, /* make a link to a file */ +} fs_op_t; + int fs_seek (fs_t *fs, unsigned long offset); int fs_read8 (fs_t *fs, unsigned char *val); int fs_read16 (fs_t *fs, unsigned short *val); @@ -148,41 +167,47 @@ int fs_open (fs_t *fs, const char *filename, int writable); void fs_close (fs_t *fs); int fs_sync (fs_t *fs, int force); int fs_create (fs_t *fs, const char *filename, unsigned kbytes, - unsigned swap_kbytes); + unsigned swap_kbytes); int fs_check (fs_t *fs); void fs_print (fs_t *fs, FILE *out); +int fs_mount(fs_t *fs, char *dirname); + int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum); int fs_inode_save (fs_inode_t *inode, int force); void fs_inode_clear (fs_inode_t *inode); -void fs_inode_truncate (fs_inode_t *inode); +void fs_inode_truncate (fs_inode_t *inode, unsigned long size); void fs_inode_print (fs_inode_t *inode, FILE *out); int fs_inode_read (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes); + unsigned char *data, unsigned long bytes); int fs_inode_write (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes); + unsigned char *data, unsigned long bytes); int fs_inode_alloc (fs_t *fs, fs_inode_t *inode); -int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, char *name, - int op, int mode); +int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, + fs_op_t op, int mode); +int fs_inode_lookup (fs_t *fs, fs_inode_t *inode, const char *name); +int fs_inode_create (fs_t *fs, fs_inode_t *inode, const char *name, int mode); +int fs_inode_delete (fs_t *fs, fs_inode_t *inode, const char *name); +int fs_inode_link (fs_t *fs, fs_inode_t *inode, const char *name, int mode); int inode_build_list (fs_t *fs); int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data); int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data); int fs_block_free (fs_t *fs, unsigned int bno); int fs_block_alloc (fs_t *fs, unsigned int *bno); -int fs_indirect_block_free (fs_t *fs, unsigned int bno); -int fs_double_indirect_block_free (fs_t *fs, unsigned int bno); -int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno); +int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); +int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); +int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); void fs_directory_scan (fs_inode_t *inode, char *dirname, - fs_directory_scanner_t scanner, void *arg); + fs_directory_scanner_t scanner, void *arg); void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent); void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data); -int fs_file_create (fs_t *fs, fs_file_t *file, char *name, int mode); -int fs_file_open (fs_t *fs, fs_file_t *file, char *name, int wflag); +int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode); +int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag); int fs_file_read (fs_file_t *file, unsigned char *data, - unsigned long bytes); + unsigned long bytes); int fs_file_write (fs_file_t *file, unsigned char *data, - unsigned long bytes); + unsigned long bytes); int fs_file_close (fs_file_t *file); diff --git a/tools/fsutil/check.c b/tools/fsutil/check.c index cae91b7..2aa9e80 100644 --- a/tools/fsutil/check.c +++ b/tools/fsutil/check.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include @@ -17,138 +31,138 @@ extern int verbose; -#define MAXDUP 10 /* limit on dup blks (per inode) */ -#define MAXBAD 10 /* limit on bad blks (per inode) */ -#define DUP_LIST_SIZE 100 /* num of dup blocks to remember */ -#define LINK_LIST_SIZE 20 /* num zero link cnts to remember */ +#define MAXDUP 10 /* limit on dup blks (per inode) */ +#define MAXBAD 10 /* limit on bad blks (per inode) */ +#define DUP_LIST_SIZE 100 /* num of dup blocks to remember */ +#define LINK_LIST_SIZE 20 /* num zero link cnts to remember */ -#define STATE_BITS 2 /* bits per inode state */ -#define STATE_MASK 3 /* mask for inode state */ -#define STATES_PER_BYTE 4 /* inode states per byte */ -#define USTATE 0 /* inode not allocated */ -#define FSTATE 1 /* inode is file */ -#define DSTATE 2 /* inode is directory */ -#define CLEAR 3 /* inode is to be cleared */ +#define STATE_BITS 2 /* bits per inode state */ +#define STATE_MASK 3 /* mask for inode state */ +#define STATES_PER_BYTE 4 /* inode states per byte */ +#define USTATE 0 /* inode not allocated */ +#define FSTATE 1 /* inode is file */ +#define DSTATE 2 /* inode is directory */ +#define CLEAR 3 /* inode is to be cleared */ -#define DATA 1 /* flags for scan_inode() */ -#define ADDR 0 +#define DATA 1 /* flags for scan_inode() */ +#define ADDR 0 -#define ALTERD 010 /* values returned by scan functions */ -#define KEEPON 004 -#define SKIP 002 -#define STOP 001 +#define ALTERD 010 /* values returned by scan functions */ +#define KEEPON 004 +#define SKIP 002 +#define STOP 001 -#define outrange(fs,x) ((x) < (fs)->isize || (x) >= (fs)->fsize) +#define outrange(fs,x) ((x) < (fs)->isize || (x) >= (fs)->fsize) /* block scan function, called by scan_inode for every file block */ typedef int scanner_t (fs_inode_t *inode, unsigned blk, void *arg); -static unsigned char buf_data [BSDFS_BSIZE]; /* buffer data for scan_directory */ -static unsigned buf_bno; /* buffer block number */ -static int buf_dirty; /* buffer data modified */ +static unsigned char buf_data [BSDFS_BSIZE]; /* buffer data for scan_directory */ +static unsigned buf_bno; /* buffer block number */ +static int buf_dirty; /* buffer data modified */ -static unsigned dup_list [DUP_LIST_SIZE]; /* dup block table */ -static unsigned *dup_end; /* next entry in dup table */ -static unsigned *dup_multi; /* multiple dups part of table */ +static unsigned dup_list [DUP_LIST_SIZE]; /* dup block table */ +static unsigned *dup_end; /* next entry in dup table */ +static unsigned *dup_multi; /* multiple dups part of table */ -static unsigned bad_link_list [LINK_LIST_SIZE]; /* inos with zero link cnts */ -static unsigned *bad_link_end; /* next entry in table */ +static unsigned bad_link_list [LINK_LIST_SIZE]; /* inos with zero link cnts */ +static unsigned *bad_link_end; /* next entry in table */ -static char *block_map; /* primary blk allocation map */ -static char *free_map; /* secondary blk allocation map */ -static char *state_map; /* inode state table */ -static int *link_count; /* link count table */ +static char *block_map; /* primary blk allocation map */ +static char *free_map; /* secondary blk allocation map */ +static char *state_map; /* inode state table */ +static int *link_count; /* link count table */ -static char pathname [256]; /* file path name for pass2 */ -static char *pathp; /* pointer to pathname position */ -static char *thisname; /* ptr to current pathname component */ +static char pathname [256]; /* file path name for pass2 */ +static char *pathp; /* pointer to pathname position */ +static char *thisname; /* ptr to current pathname component */ -static char *lost_found_name = "lost+found"; -static unsigned lost_found_inode; /* lost & found directory */ +static char *lost_found_name = "lost+found"; +static unsigned lost_found_inode; /* lost & found directory */ -static int free_list_corrupted; /* corrupted free list */ -static int bad_blocks; /* num of bad blks seen (per inode) */ -static int dup_blocks; /* num of dup blks seen (per inode) */ +static int free_list_corrupted; /* corrupted free list */ +static int bad_blocks; /* num of bad blks seen (per inode) */ +static int dup_blocks; /* num of dup blks seen (per inode) */ -static char *find_inode_name; /* searching for this name */ -static unsigned find_inode_result; /* result of inode search */ -static unsigned lost_inode; /* lost file to reconnect */ +static char *find_inode_name; /* searching for this name */ +static unsigned find_inode_result; /* result of inode search */ +static unsigned lost_inode; /* lost file to reconnect */ -static unsigned long scan_filesize; /* file size, decremented during scan */ -static unsigned total_files; /* number of files seen */ +static unsigned long scan_filesize; /* file size, decremented during scan */ +static unsigned total_files; /* number of files seen */ static void set_inode_state (unsigned inum, int s) { - unsigned int byte, shift; + unsigned int byte, shift; - byte = inum / STATES_PER_BYTE; - shift = inum % STATES_PER_BYTE * STATE_BITS; - state_map [byte] &= ~(STATE_MASK << shift); - state_map [byte] |= s << shift; + byte = inum / STATES_PER_BYTE; + shift = inum % STATES_PER_BYTE * STATE_BITS; + state_map [byte] &= ~(STATE_MASK << shift); + state_map [byte] |= s << shift; } static int inode_state (unsigned inum) { - unsigned int byte, shift; + unsigned int byte, shift; - byte = inum / STATES_PER_BYTE; - shift = inum % STATES_PER_BYTE * STATE_BITS; - return (state_map [byte] >> shift) & STATE_MASK; + byte = inum / STATES_PER_BYTE; + shift = inum % STATES_PER_BYTE * STATE_BITS; + return (state_map [byte] >> shift) & STATE_MASK; } static int block_is_busy (unsigned blk) { - return block_map [blk >> 3] & (1 << (blk & 7)); + return block_map [blk >> 3] & (1 << (blk & 7)); } static void mark_block_busy (unsigned blk) { - block_map [blk >> 3] |= 1 << (blk & 7); + block_map [blk >> 3] |= 1 << (blk & 7); } static void mark_block_free (unsigned blk) { - block_map [blk >> 3] &= ~(1 << (blk & 7)); + block_map [blk >> 3] &= ~(1 << (blk & 7)); } static void mark_free_list (unsigned blk) { - free_map [blk >> 3] |= 1 << (blk & 7); + free_map [blk >> 3] |= 1 << (blk & 7); } static int in_free_list (unsigned blk) { - return free_map [blk >> 3] & (1 << (blk & 7)); + return free_map [blk >> 3] & (1 << (blk & 7)); } static void print_io_error (char *s, unsigned blk) { - printf ("\nCAN NOT %s: BLK %d\n", s, blk); + printf ("\nCAN NOT %s: BLK %d\n", s, blk); } static void buf_flush (fs_t *fs) { - if (buf_dirty && fs->writable) { + if (buf_dirty && fs->writable) { /*printf ("WRITE blk %d\n", buf_bno);*/ - if (! fs_write_block (fs, buf_bno, buf_data)) - print_io_error ("WRITE", buf_bno); - } - buf_dirty = 0; + if (! fs_write_block (fs, buf_bno, buf_data)) + print_io_error ("WRITE", buf_bno); + } + buf_dirty = 0; } static int buf_get (fs_t *fs, unsigned blk) { - if (buf_bno == blk) - return 1; - buf_flush (fs); + if (buf_bno == blk) + return 1; + buf_flush (fs); /*printf ("read blk %d\n", blk);*/ - if (! fs_read_block (fs, blk, buf_data)) { - print_io_error ("READ", blk); - buf_bno = (unsigned)-1; - return 0; - } - buf_bno = blk; - return 1; + if (! fs_read_block (fs, blk, buf_data)) { + print_io_error ("READ", blk); + buf_bno = (unsigned)-1; + return 0; + } + buf_bno = blk; + return 1; } /* @@ -156,39 +170,39 @@ static int buf_get (fs_t *fs, unsigned blk) * and for every block call the given function. */ static int scan_indirect_block (fs_inode_t *inode, unsigned blk, - int double_indirect, int flg, scanner_t *func, void *arg) + int double_indirect, int flg, scanner_t *func, void *arg) { - unsigned nb; - int ret, i; - unsigned char data [BSDFS_BSIZE]; + unsigned nb; + int ret, i; + unsigned char data [BSDFS_BSIZE]; /*printf ("check %siblock %d: \n", double_indirect > 1 ? "triple " : double_indirect ? "double " : "", blk);*/ - if (flg == ADDR) { - ret = (*func) (inode, blk, arg); - if (! (ret & KEEPON)) - return ret; - } - if (outrange (inode->fs, blk)) /* protect thyself */ - return SKIP; + if (flg == ADDR) { + ret = (*func) (inode, blk, arg); + if (! (ret & KEEPON)) + return ret; + } + if (outrange (inode->fs, blk)) /* protect thyself */ + return SKIP; - if (! fs_read_block (inode->fs, blk, data)) { - print_io_error ("READ", blk); - return SKIP; - } - for (i = 0; i < BSDFS_BSIZE; i+=2) { - nb = data [i+1] << 8 | data [i]; - if (nb) { - if (double_indirect) - ret = scan_indirect_block (inode, nb, - double_indirect - 1, flg, func, arg); - else - ret = (*func) (inode, nb, arg); + if (! fs_read_block (inode->fs, blk, data)) { + print_io_error ("READ", blk); + return SKIP; + } + for (i = 0; i < BSDFS_BSIZE; i+=2) { + nb = data [i+1] << 8 | data [i]; + if (nb) { + if (double_indirect) + ret = scan_indirect_block (inode, nb, + double_indirect - 1, flg, func, arg); + else + ret = (*func) (inode, nb, arg); - if (ret & STOP) - return ret; - } - } - return KEEPON; + if (ret & STOP) + return ret; + } + } + return KEEPON; } /* @@ -200,50 +214,50 @@ static int scan_indirect_block (fs_inode_t *inode, unsigned blk, */ static int scan_inode (fs_inode_t *inode, int flg, scanner_t *func, void *arg) { - unsigned *ap; - int ret; + unsigned *ap; + int ret; /*printf ("check inode %d: %#o\n", inode->number, inode->mode);*/ - if (((inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) || - ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR)) - return KEEPON; - scan_filesize = inode->size; + if (((inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) || + ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR)) + return KEEPON; + scan_filesize = inode->size; - /* Check direct blocks. */ - for (ap = inode->addr; ap < &inode->addr[NDADDR]; ap++) { - if (*ap) { - ret = (*func) (inode, *ap, arg); - if (ret & STOP) - return ret; - } - } - if (inode->addr[NADDR-3]) { - /* Check the indirect block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-3], 0, - flg, func, arg); - if (ret & STOP) - return (ret); - } - if (inode->addr[NADDR-2]) { - /* Check the double indirect block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-2], 1, - flg, func, arg); - if (ret & STOP) - return (ret); - } - if (inode->addr[NADDR-1]) { - /* Check the last (triple indirect) block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-1], 2, - flg, func, arg); - if (ret & STOP) - return (ret); - } - return KEEPON; + /* Check direct blocks. */ + for (ap = inode->addr; ap < &inode->addr[NDADDR]; ap++) { + if (*ap) { + ret = (*func) (inode, *ap, arg); + if (ret & STOP) + return ret; + } + } + if (inode->addr[NADDR-3]) { + /* Check the indirect block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-3], 0, + flg, func, arg); + if (ret & STOP) + return (ret); + } + if (inode->addr[NADDR-2]) { + /* Check the double indirect block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-2], 1, + flg, func, arg); + if (ret & STOP) + return (ret); + } + if (inode->addr[NADDR-1]) { + /* Check the last (triple indirect) block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-1], 2, + flg, func, arg); + if (ret & STOP) + return (ret); + } + return KEEPON; } static void print_block_error (char *s, unsigned blk, unsigned inum) { - printf ("%u %s I=%u\n", blk, s, inum); + printf ("%u %s I=%u\n", blk, s, inum); } /* @@ -253,64 +267,64 @@ static void print_block_error (char *s, unsigned blk, unsigned inum) */ static int pass1 (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; - unsigned *blocks = arg; + unsigned *dlp; + unsigned *blocks = arg; /*printf ("pass1 inode %d block %d: \n", inode->number, blk);*/ - if (outrange (inode->fs, blk)) { - print_block_error ("BAD", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - if (++bad_blocks >= MAXBAD) { - printf ("EXCESSIVE BAD BLKS I=%u\n", inode->number); - return STOP; - } - return SKIP; - } - if (block_is_busy (blk)) { - print_block_error ("DUP", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - if (++dup_blocks >= MAXDUP) { - printf ("EXCESSIVE DUP BLKS I=%u\n", inode->number); - return STOP; - } - if (dup_end >= &dup_list[DUP_LIST_SIZE]) { - printf ("DUP TABLE OVERFLOW.\n"); - return STOP; - } - for (dlp = dup_list; dlp < dup_multi; dlp++) { - if (*dlp == blk) { - *dup_end++ = blk; - break; - } - } - if (dlp >= dup_multi) { - *dup_end++ = *dup_multi; - *dup_multi++ = blk; - } - } else { - if (blocks) - ++*blocks; - mark_block_busy (blk); - } - return KEEPON; + if (outrange (inode->fs, blk)) { + print_block_error ("BAD", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + if (++bad_blocks >= MAXBAD) { + printf ("EXCESSIVE BAD BLKS I=%u\n", inode->number); + return STOP; + } + return SKIP; + } + if (block_is_busy (blk)) { + print_block_error ("DUP", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + if (++dup_blocks >= MAXDUP) { + printf ("EXCESSIVE DUP BLKS I=%u\n", inode->number); + return STOP; + } + if (dup_end >= &dup_list[DUP_LIST_SIZE]) { + printf ("DUP TABLE OVERFLOW.\n"); + return STOP; + } + for (dlp = dup_list; dlp < dup_multi; dlp++) { + if (*dlp == blk) { + *dup_end++ = blk; + break; + } + } + if (dlp >= dup_multi) { + *dup_end++ = *dup_multi; + *dup_multi++ = blk; + } + } else { + if (blocks) + ++*blocks; + mark_block_busy (blk); + } + return KEEPON; } static int pass1b (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; + unsigned *dlp; - if (outrange (inode->fs, blk)) - return SKIP; - for (dlp = dup_list; dlp < dup_multi; dlp++) { - if (*dlp == blk) { - print_block_error ("DUP", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - *dlp = *--dup_multi; - *dup_multi = blk; - return (dup_multi == dup_list ? STOP : KEEPON); - } - } - return KEEPON; + if (outrange (inode->fs, blk)) + return SKIP; + for (dlp = dup_list; dlp < dup_multi; dlp++) { + if (*dlp == blk) { + print_block_error ("DUP", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + *dlp = *--dup_multi; + *dup_multi = blk; + return (dup_multi == dup_list ? STOP : KEEPON); + } + } + return KEEPON; } /* @@ -319,68 +333,68 @@ static int pass1b (fs_inode_t *inode, unsigned blk, void *arg) */ static int scan_directory (fs_inode_t *inode, unsigned blk, void *arg) { - fs_dirent_t direntry; - unsigned char *dirp; - int (*func) () = arg; - int n; + fs_dirent_t direntry; + unsigned char *dirp; + int (*func) () = arg; + int n; /*printf ("scan_directory: I=%d, blk=%d\n", inode->number, blk);*/ - if (outrange (inode->fs, blk)) { - scan_filesize -= BSDFS_BSIZE; - return SKIP; - } - dirp = buf_data; - while (dirp < &buf_data[BSDFS_BSIZE] && scan_filesize > 0) { - if (! buf_get (inode->fs, blk)) { - scan_filesize -= (&buf_data[BSDFS_BSIZE] - dirp); - return SKIP; - } - fs_dirent_unpack (&direntry, dirp); - if (direntry.reclen == 0) - break; + if (outrange (inode->fs, blk)) { + scan_filesize -= BSDFS_BSIZE; + return SKIP; + } + dirp = buf_data; + while (dirp < &buf_data[BSDFS_BSIZE] && scan_filesize > 0) { + if (! buf_get (inode->fs, blk)) { + scan_filesize -= (&buf_data[BSDFS_BSIZE] - dirp); + return SKIP; + } + fs_dirent_unpack (&direntry, dirp); + if (direntry.reclen == 0) + break; - /* For every directory entry, call handler. */ - n = (*func) (inode->fs, &direntry); + /* For every directory entry, call handler. */ + n = (*func) (inode->fs, &direntry); - if (n & ALTERD) { - if (buf_get (inode->fs, blk)) { - fs_dirent_pack (dirp, &direntry); - buf_dirty = 1; - } else - n &= ~ALTERD; - } - if (n & STOP) - return n; - dirp += direntry.reclen; - scan_filesize -= direntry.reclen; - } - return (scan_filesize > 0) ? KEEPON : STOP; + if (n & ALTERD) { + if (buf_get (inode->fs, blk)) { + fs_dirent_pack (dirp, &direntry); + buf_dirty = 1; + } else + n &= ~ALTERD; + } + if (n & STOP) + return n; + dirp += direntry.reclen; + scan_filesize -= direntry.reclen; + } + return (scan_filesize > 0) ? KEEPON : STOP; } static void print_inode (fs_inode_t *inode) { - char *p; + char *p; - printf (" I=%u ", inode->number); - printf (" OWNER=%d ", inode->uid); - printf ("MODE=%o\n", inode->mode); - printf ("SIZE=%ld ", inode->size); - p = ctime (&inode->mtime); - printf ("MTIME=%12.12s %4.4s\n", p+4, p+20); + printf (" I=%u ", inode->number); + printf (" OWNER=%d ", inode->uid); + printf ("MODE=%o\n", inode->mode); + printf ("SIZE=%ld ", inode->size); + p = ctime (&inode->mtime); + printf ("MTIME=%12.12s %4.4s\n", p+4, p+20); } static void print_dir_error (fs_t *fs, unsigned inum, char *s) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) { - printf ("%s I=%u\nNAME=%s\n", s, inum, pathname); - return; - } - printf ("%s ", s); - print_inode (&inode); - printf ("%s=%s\n", ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE", pathname); + if (! fs_inode_get (fs, &inode, inum)) { + printf ("%s I=%u\nNAME=%s\n", s, inum, pathname); + return; + } + printf ("%s ", s); + print_inode (&inode); + printf ("%s=%s\n", ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE", pathname); } static void scan_pass2 (fs_t *fs, unsigned inum); @@ -391,53 +405,53 @@ static void scan_pass2 (fs_t *fs, unsigned inum); */ static int pass2 (fs_t *fs, fs_dirent_t *dirp) { - int inum, ret = KEEPON; - fs_inode_t inode; + int inum, ret = KEEPON; + fs_inode_t inode; - inum = dirp->ino; - if (inum == 0) - return KEEPON; + inum = dirp->ino; + if (inum == 0) + return KEEPON; - /* Copy file name from dirp to pathp */ - thisname = pathp; - strcpy (pathp, dirp->name); - pathp += strlen (pathp); + /* Copy file name from dirp to pathp */ + thisname = pathp; + strcpy (pathp, dirp->name); + pathp += strlen (pathp); /*printf ("%s %d\n", pathname, inum);*/ - if (inum > (fs->isize - 1) * BSDFS_INODES_PER_BLOCK || - inum < BSDFS_ROOT_INODE) - print_dir_error (fs, inum, "I OUT OF RANGE"); - else { -again: switch (inode_state (inum)) { - case USTATE: - print_dir_error (fs, inum, "UNALLOCATED"); - if (fs->writable) { - dirp->ino = 0; - ret |= ALTERD; - break; - } - break; - case CLEAR: - print_dir_error (fs, inum, "DUP/BAD"); - if (fs->writable) { - dirp->ino = 0; - ret |= ALTERD; - break; - } - if (! fs_inode_get (fs, &inode, inum)) - break; - set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? DSTATE : FSTATE); - goto again; - case FSTATE: - --link_count [inum]; - break; - case DSTATE: - --link_count [inum]; - scan_pass2 (fs, inum); - } - } - pathp = thisname; - return ret; + if (inum > (fs->isize - 1) * BSDFS_INODES_PER_BLOCK || + inum < BSDFS_ROOT_INODE) + print_dir_error (fs, inum, "I OUT OF RANGE"); + else { +again: switch (inode_state (inum)) { + case USTATE: + print_dir_error (fs, inum, "UNALLOCATED"); + if (fs->writable) { + dirp->ino = 0; + ret |= ALTERD; + break; + } + break; + case CLEAR: + print_dir_error (fs, inum, "DUP/BAD"); + if (fs->writable) { + dirp->ino = 0; + ret |= ALTERD; + break; + } + if (! fs_inode_get (fs, &inode, inum)) + break; + set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? DSTATE : FSTATE); + goto again; + case FSTATE: + --link_count [inum]; + break; + case DSTATE: + --link_count [inum]; + scan_pass2 (fs, inum); + } + } + pathp = thisname; + return ret; } /* @@ -446,20 +460,20 @@ again: switch (inode_state (inum)) { */ static void scan_pass2 (fs_t *fs, unsigned inum) { - fs_inode_t inode; - char *savname; - unsigned long savsize; + fs_inode_t inode; + char *savname; + unsigned long savsize; - set_inode_state (inum, FSTATE); - if (! fs_inode_get (fs, &inode, inum)) - return; - *pathp++ = '/'; - savname = thisname; - savsize = scan_filesize; - scan_inode (&inode, DATA, scan_directory, pass2); - scan_filesize = savsize; - thisname = savname; - *--pathp = 0; + set_inode_state (inum, FSTATE); + if (! fs_inode_get (fs, &inode, inum)) + return; + *pathp++ = '/'; + savname = thisname; + savsize = scan_filesize; + scan_inode (&inode, DATA, scan_directory, pass2); + scan_filesize = savsize; + thisname = savname; + *--pathp = 0; } /* @@ -469,15 +483,15 @@ static void scan_pass2 (fs_t *fs, unsigned inum) */ static int find_inode (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->ino == 0) - return KEEPON; - if (strcmp (find_inode_name, dirp->name) == 0) { - if (dirp->ino >= BSDFS_ROOT_INODE && - dirp->ino < (fs->isize-1) * BSDFS_INODES_PER_BLOCK) - find_inode_result = dirp->ino; - return STOP; - } - return KEEPON; + if (dirp->ino == 0) + return KEEPON; + if (strcmp (find_inode_name, dirp->name) == 0) { + if (dirp->ino >= BSDFS_ROOT_INODE && + dirp->ino < (fs->isize-1) * BSDFS_INODES_PER_BLOCK) + find_inode_result = dirp->ino; + return STOP; + } + return KEEPON; } /* @@ -486,11 +500,11 @@ static int find_inode (fs_t *fs, fs_dirent_t *dirp) */ static int make_lost_entry (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->ino) - return KEEPON; - dirp->ino = lost_inode; - sprintf (dirp->name, "#%05d", dirp->ino); - return ALTERD | STOP; + if (dirp->ino) + return KEEPON; + dirp->ino = lost_inode; + sprintf (dirp->name, "#%05d", dirp->ino); + return ALTERD | STOP; } /* @@ -498,12 +512,12 @@ static int make_lost_entry (fs_t *fs, fs_dirent_t *dirp) */ static int dotdot_to_lost_found (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->name[0] == '.' && dirp->name[1] == '.' && - dirp->name[2] == 0) { - dirp->ino = lost_found_inode; - return ALTERD | STOP; - } - return KEEPON; + if (dirp->name[0] == '.' && dirp->name[1] == '.' && + dirp->name[2] == 0) { + dirp->ino = lost_found_inode; + return ALTERD | STOP; + } + return KEEPON; } /* @@ -512,15 +526,15 @@ static int dotdot_to_lost_found (fs_t *fs, fs_dirent_t *dirp) */ static unsigned find_lost_found (fs_t *fs) { - fs_inode_t root; + fs_inode_t root; - /* Find lost_found directory inode number. */ - if (! fs_inode_get (fs, &root, BSDFS_ROOT_INODE)) - return 0; - find_inode_name = lost_found_name; - find_inode_result = 0; - scan_inode (&root, DATA, scan_directory, find_inode); - return find_inode_result; + /* Find lost_found directory inode number. */ + if (! fs_inode_get (fs, &root, BSDFS_ROOT_INODE)) + return 0; + find_inode_name = lost_found_name; + find_inode_result = 0; + scan_inode (&root, DATA, scan_directory, find_inode); + return find_inode_result; } /* @@ -528,61 +542,61 @@ static unsigned find_lost_found (fs_t *fs) */ static int move_to_lost_found (fs_inode_t *inode) { - fs_inode_t lost_found; + fs_inode_t lost_found; - printf ("UNREF %s ", ((inode->mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE"); - print_inode (inode); - if (! inode->fs->writable) - return 0; + printf ("UNREF %s ", ((inode->mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE"); + print_inode (inode); + if (! inode->fs->writable) + return 0; - /* Get lost+found inode. */ - if (lost_found_inode == 0) { - /* Find lost_found directory inode number. */ - lost_found_inode = find_lost_found (inode->fs); - if (! lost_found_inode) { - printf ("SORRY. NO lost+found DIRECTORY\n\n"); - return 0; - } - } - if (! fs_inode_get (inode->fs, &lost_found, lost_found_inode) || - ((lost_found.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) || - inode_state (lost_found_inode) != FSTATE) { - printf ("SORRY. NO lost+found DIRECTORY\n\n"); - return 0; - } - if (lost_found.size % BSDFS_BSIZE) { - lost_found.size = (lost_found.size + BSDFS_BSIZE - 1) / - BSDFS_BSIZE * BSDFS_BSIZE; - if (! fs_inode_save (&lost_found, 1)) { - printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); - return 0; - } - } + /* Get lost+found inode. */ + if (lost_found_inode == 0) { + /* Find lost_found directory inode number. */ + lost_found_inode = find_lost_found (inode->fs); + if (! lost_found_inode) { + printf ("SORRY. NO lost+found DIRECTORY\n\n"); + return 0; + } + } + if (! fs_inode_get (inode->fs, &lost_found, lost_found_inode) || + ((lost_found.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) || + inode_state (lost_found_inode) != FSTATE) { + printf ("SORRY. NO lost+found DIRECTORY\n\n"); + return 0; + } + if (lost_found.size % BSDFS_BSIZE) { + lost_found.size = (lost_found.size + BSDFS_BSIZE - 1) / + BSDFS_BSIZE * BSDFS_BSIZE; + if (! fs_inode_save (&lost_found, 1)) { + printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); + return 0; + } + } - /* Put a file to lost+found. */ - lost_inode = inode->number; - if ((scan_inode (&lost_found, DATA, scan_directory, make_lost_entry) & - ALTERD) == 0) { - printf ("SORRY. NO SPACE IN lost+found DIRECTORY\n\n"); - return 0; - } - --link_count [inode->number]; + /* Put a file to lost+found. */ + lost_inode = inode->number; + if ((scan_inode (&lost_found, DATA, scan_directory, make_lost_entry) & + ALTERD) == 0) { + printf ("SORRY. NO SPACE IN lost+found DIRECTORY\n\n"); + return 0; + } + --link_count [inode->number]; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* For ".." set inode number to lost_found_inode. */ - scan_inode (inode, DATA, scan_directory, dotdot_to_lost_found); - if (fs_inode_get (inode->fs, &lost_found, lost_found_inode)) { - lost_found.nlink++; - ++link_count [lost_found.number]; - if (! fs_inode_save (&lost_found, 1)) { - printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); - return 0; - } - } - printf ("DIR I=%u CONNECTED.\n\n", inode->number); - } - return 1; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* For ".." set inode number to lost_found_inode. */ + scan_inode (inode, DATA, scan_directory, dotdot_to_lost_found); + if (fs_inode_get (inode->fs, &lost_found, lost_found_inode)) { + lost_found.nlink++; + ++link_count [lost_found.number]; + if (! fs_inode_save (&lost_found, 1)) { + printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); + return 0; + } + } + printf ("DIR I=%u CONNECTED.\n\n", inode->number); + } + return 1; } /* @@ -590,23 +604,23 @@ static int move_to_lost_found (fs_inode_t *inode) */ static int pass4 (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; - unsigned *blocks = arg; + unsigned *dlp; + unsigned *blocks = arg; - if (outrange (inode->fs, blk)) - return SKIP; - if (block_is_busy (blk)) { - /* Free block. */ - for (dlp = dup_list; dlp < dup_end; dlp++) - if (*dlp == blk) { - *dlp = *--dup_end; - return KEEPON; - } - mark_block_free (blk); - if (blocks) - --*blocks; - } - return KEEPON; + if (outrange (inode->fs, blk)) + return SKIP; + if (block_is_busy (blk)) { + /* Free block. */ + for (dlp = dup_list; dlp < dup_end; dlp++) + if (*dlp == blk) { + *dlp = *--dup_end; + return KEEPON; + } + mark_block_free (blk); + if (blocks) + --*blocks; + } + return KEEPON; } /* @@ -614,21 +628,21 @@ static int pass4 (fs_inode_t *inode, unsigned blk, void *arg) */ static void clear_inode (fs_t *fs, unsigned inum, char *msg) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) - return; - if (msg) { - printf ("%s %s", msg, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE"); - print_inode (&inode); - } - if (fs->writable) { - total_files--; - scan_inode (&inode, ADDR, pass4, 0); - fs_inode_clear (&inode); - fs_inode_save (&inode, 1); - } + if (! fs_inode_get (fs, &inode, inum)) + return; + if (msg) { + printf ("%s %s", msg, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE"); + print_inode (&inode); + } + if (fs->writable) { + total_files--; + scan_inode (&inode, ADDR, pass4, 0); + fs_inode_clear (&inode); + fs_inode_save (&inode, 1); + } } /* @@ -637,26 +651,26 @@ static void clear_inode (fs_t *fs, unsigned inum, char *msg) */ static void adjust_link_count (fs_t *fs, unsigned inum, unsigned lcnt) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) - return; - if (inode.nlink == lcnt) { - /* No links to file - move to lost+found. */ - if (! move_to_lost_found (&inode)) - clear_inode (fs, inum, 0); - } else { - printf ("LINK COUNT %s", (lost_found_inode==inum) ? lost_found_name : - (((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) ? - "DIR" : "FILE")); - print_inode (&inode); - printf ("COUNT %d SHOULD BE %d\n", - inode.nlink, inode.nlink - lcnt); - if (fs->writable) { - inode.nlink -= lcnt; - fs_inode_save (&inode, 1); - } - } + if (! fs_inode_get (fs, &inode, inum)) + return; + if (inode.nlink == lcnt) { + /* No links to file - move to lost+found. */ + if (! move_to_lost_found (&inode)) + clear_inode (fs, inum, 0); + } else { + printf ("LINK COUNT %s", (lost_found_inode==inum) ? lost_found_name : + (((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) ? + "DIR" : "FILE")); + print_inode (&inode); + printf ("COUNT %d SHOULD BE %d\n", + inode.nlink, inode.nlink - lcnt); + if (fs->writable) { + inode.nlink -= lcnt; + fs_inode_save (&inode, 1); + } + } } /* @@ -665,25 +679,25 @@ static void adjust_link_count (fs_t *fs, unsigned inum, unsigned lcnt) */ static int pass5 (fs_t *fs, unsigned blk, unsigned *free_blocks) { - if (outrange (fs, blk)) { - free_list_corrupted = 1; - if (++bad_blocks >= MAXBAD) { - printf ("EXCESSIVE BAD BLKS IN FREE LIST.\n"); - return STOP; - } - return SKIP; - } - if (in_free_list (blk)) { - free_list_corrupted = 1; - if (++dup_blocks >= DUP_LIST_SIZE) { - printf ("EXCESSIVE DUP BLKS IN FREE LIST.\n"); - return STOP; - } - } else { - ++*free_blocks; - mark_free_list (blk); - } - return KEEPON; + if (outrange (fs, blk)) { + free_list_corrupted = 1; + if (++bad_blocks >= MAXBAD) { + printf ("EXCESSIVE BAD BLKS IN FREE LIST.\n"); + return STOP; + } + return SKIP; + } + if (in_free_list (blk)) { + free_list_corrupted = 1; + if (++dup_blocks >= DUP_LIST_SIZE) { + printf ("EXCESSIVE DUP BLKS IN FREE LIST.\n"); + return STOP; + } + } else { + ++*free_blocks; + mark_free_list (blk); + } + return KEEPON; } /* @@ -692,40 +706,40 @@ static int pass5 (fs_t *fs, unsigned blk, unsigned *free_blocks) */ static unsigned check_free_list (fs_t *fs) { - unsigned *ap, *base; - unsigned free_blocks, nfree; - unsigned data [BSDFS_BSIZE / 4]; - unsigned list [NICFREE]; - int i; + unsigned *ap, *base; + unsigned free_blocks, nfree; + unsigned data [BSDFS_BSIZE / 4]; + unsigned list [NICFREE]; + int i; - if (fs->nfree == 0) - return 0; - free_blocks = 0; - nfree = fs->nfree; - base = fs->free; - for (;;) { - if (nfree <= 0 || nfree > NICFREE) { - printf ("BAD FREEBLK COUNT\n"); - free_list_corrupted = 1; - break; - } - ap = base + nfree; - while (--ap > base) { - if (pass5 (fs, *ap, &free_blocks) == STOP) - return free_blocks; - } - if (*ap == 0 || pass5 (fs, *ap, &free_blocks) != KEEPON) - break; - if (! fs_read_block (fs, *ap, (unsigned char*) data)) { - print_io_error ("READ", *ap); - break; - } - nfree = data[0]; - for (i=0; infree == 0) + return 0; + free_blocks = 0; + nfree = fs->nfree; + base = fs->free; + for (;;) { + if (nfree <= 0 || nfree > NICFREE) { + printf ("BAD FREEBLK COUNT\n"); + free_list_corrupted = 1; + break; + } + ap = base + nfree; + while (--ap > base) { + if (pass5 (fs, *ap, &free_blocks) == STOP) + return free_blocks; + } + if (*ap == 0 || pass5 (fs, *ap, &free_blocks) != KEEPON) + break; + if (! fs_read_block (fs, *ap, (unsigned char*) data)) { + print_io_error ("READ", *ap); + break; + } + nfree = data[0]; + for (i=0; ininode; i++) { - inum = fs->inode[i]; - if (inode_state (inum) != USTATE) { - printf ("ALLOCATED INODE(S) IN IFREE LIST\n"); - if (fs->writable) { - fs->ninode = i - 1; - while (i < NICINOD) - fs->inode [i++] = 0; - fs->dirty = 1; - } - return; - } - } + for (i=0; ininode; i++) { + inum = fs->inode[i]; + if (inode_state (inum) != USTATE) { + printf ("ALLOCATED INODE(S) IN IFREE LIST\n"); + if (fs->writable) { + fs->ninode = i - 1; + while (i < NICINOD) + fs->inode [i++] = 0; + fs->dirty = 1; + } + return; + } + } } /* @@ -756,26 +770,26 @@ static void check_free_inode_list (fs_t *fs) */ static unsigned make_free_list (fs_t *fs) { - unsigned free_blocks, n; + unsigned free_blocks, n; - fs->nfree = 0; - fs->flock = 0; - fs->fmod = 0; - fs->ilock = 0; - fs->ronly = 0; - fs->dirty = 1; - free_blocks = 0; + fs->nfree = 0; + fs->flock = 0; + fs->fmod = 0; + fs->ilock = 0; + fs->ronly = 0; + fs->dirty = 1; + free_blocks = 0; - /* Build a list of free blocks */ - fs_block_free (fs, 0); - for (n = fs->fsize - 1; n >= fs->isize; n--) { - if (block_is_busy (n)) - continue; - ++free_blocks; - if (! fs_block_free (fs, n)) - return 0; - } - return free_blocks; + /* Build a list of free blocks */ + fs_block_free (fs, 0); + for (n = fs->fsize - 1; n >= fs->isize; n--) { + if (block_is_busy (n)) + continue; + ++free_blocks; + if (! fs_block_free (fs, n)) + return 0; + } + return free_blocks; } /* @@ -785,220 +799,220 @@ static unsigned make_free_list (fs_t *fs) */ int fs_check (fs_t *fs) { - fs_inode_t inode; - int n; - unsigned inum; - unsigned block_map_size; /* number of free blocks */ - unsigned free_blocks; /* number of free blocks */ - unsigned used_blocks; /* number of blocks used */ - unsigned last_allocated_inode; /* hiwater mark of inodes */ + fs_inode_t inode; + int n; + unsigned inum; + unsigned block_map_size; /* number of free blocks */ + unsigned free_blocks; /* number of free blocks */ + unsigned used_blocks; /* number of blocks used */ + unsigned last_allocated_inode; /* hiwater mark of inodes */ - if (fs->isize >= fs->fsize) { - printf ("Bad filesystem size: total %d blocks with %d inode blocks\n", - fs->fsize, fs->isize); - return 0; - } - free_list_corrupted = 0; - total_files = 0; - used_blocks = 0; - dup_multi = dup_end = &dup_list[0]; - bad_link_end = &bad_link_list[0]; - lost_found_inode = 0; - buf_dirty = 0; - buf_bno = (unsigned) -1; + if (fs->isize >= fs->fsize) { + printf ("Bad filesystem size: total %d blocks with %d inode blocks\n", + fs->fsize, fs->isize); + return 0; + } + free_list_corrupted = 0; + total_files = 0; + used_blocks = 0; + dup_multi = dup_end = &dup_list[0]; + bad_link_end = &bad_link_list[0]; + lost_found_inode = 0; + buf_dirty = 0; + buf_bno = (unsigned) -1; - /* Allocate memory. */ - block_map_size = (fs->fsize + 7) / 8; - block_map = calloc (block_map_size, sizeof (*block_map)); - state_map = calloc (((fs->isize-1) * BSDFS_INODES_PER_BLOCK + - STATES_PER_BYTE) / STATES_PER_BYTE, sizeof (*state_map)); - link_count = calloc ((fs->isize-1) * BSDFS_INODES_PER_BLOCK + 1, - sizeof (*link_count)); - if (! block_map || ! state_map || ! link_count) { - printf ("Cannot allocate memory\n"); -fatal: if (block_map) - free (block_map); - if (state_map) - free (state_map); - if (link_count) - free (link_count); - return 0; - } + /* Allocate memory. */ + block_map_size = (fs->fsize + 7) / 8; + block_map = calloc (block_map_size, sizeof (*block_map)); + state_map = calloc (((fs->isize-1) * BSDFS_INODES_PER_BLOCK + + STATES_PER_BYTE) / STATES_PER_BYTE, sizeof (*state_map)); + link_count = calloc ((fs->isize-1) * BSDFS_INODES_PER_BLOCK + 1, + sizeof (*link_count)); + if (! block_map || ! state_map || ! link_count) { + printf ("Cannot allocate memory\n"); +fatal: if (block_map) + free (block_map); + if (state_map) + free (state_map); + if (link_count) + free (link_count); + return 0; + } - printf ("** Phase 1 - Check Blocks and Sizes\n"); - last_allocated_inode = 0; - for (inum = 1; inum <= (fs->isize-1) * BSDFS_INODES_PER_BLOCK; inum++) { - if (! fs_inode_get (fs, &inode, inum)) - continue; - if (inode.mode & INODE_MODE_FMT) { + printf ("** Phase 1 - Check Blocks and Sizes\n"); + last_allocated_inode = 0; + for (inum = 1; inum <= (fs->isize-1) * BSDFS_INODES_PER_BLOCK; inum++) { + if (! fs_inode_get (fs, &inode, inum)) + continue; + if (inode.mode & INODE_MODE_FMT) { /*printf ("inode %d: %#o\n", inode.number, inode.mode);*/ - last_allocated_inode = inum; - total_files++; - link_count[inum] = inode.nlink; - if (link_count[inum] <= 0) { - if (bad_link_end < &bad_link_list[LINK_LIST_SIZE]) - *bad_link_end++ = inum; - else { - printf ("LINK COUNT TABLE OVERFLOW\n"); - } - } - set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? DSTATE : FSTATE); - bad_blocks = dup_blocks = 0; - scan_inode (&inode, ADDR, pass1, &used_blocks); - n = inode_state (inum); - if (n == DSTATE || n == FSTATE) { - if ((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR && - (inode.size % 4) != 0) { - printf ("DIRECTORY MISALIGNED I=%u\n\n", - inode.number); - } - } - } - else if (inode.mode != 0) { - printf ("PARTIALLY ALLOCATED INODE I=%u\n", inum); - if (fs->writable) - fs_inode_clear (&inode); - } - fs_inode_save (&inode, 0); - } - if (dup_end != &dup_list[0]) { - printf ("** Phase 1b - Rescan For More DUPS\n"); - for (inum = 1; inum <= last_allocated_inode; inum++) { - if (inode_state (inum) == USTATE) - continue; - if (! fs_inode_get (fs, &inode, inum)) - continue; - if (scan_inode (&inode, ADDR, pass1b, 0) & STOP) - break; - } - } + last_allocated_inode = inum; + total_files++; + link_count[inum] = inode.nlink; + if (link_count[inum] <= 0) { + if (bad_link_end < &bad_link_list[LINK_LIST_SIZE]) + *bad_link_end++ = inum; + else { + printf ("LINK COUNT TABLE OVERFLOW\n"); + } + } + set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? DSTATE : FSTATE); + bad_blocks = dup_blocks = 0; + scan_inode (&inode, ADDR, pass1, &used_blocks); + n = inode_state (inum); + if (n == DSTATE || n == FSTATE) { + if ((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR && + (inode.size % 4) != 0) { + printf ("DIRECTORY MISALIGNED I=%u\n\n", + inode.number); + } + } + } + else if (inode.mode != 0) { + printf ("PARTIALLY ALLOCATED INODE I=%u\n", inum); + if (fs->writable) + fs_inode_clear (&inode); + } + fs_inode_save (&inode, 0); + } + if (dup_end != &dup_list[0]) { + printf ("** Phase 1b - Rescan For More DUPS\n"); + for (inum = 1; inum <= last_allocated_inode; inum++) { + if (inode_state (inum) == USTATE) + continue; + if (! fs_inode_get (fs, &inode, inum)) + continue; + if (scan_inode (&inode, ADDR, pass1b, 0) & STOP) + break; + } + } - printf ("** Phase 2 - Check Pathnames\n"); - thisname = pathp = pathname; - switch (inode_state (BSDFS_ROOT_INODE)) { - case USTATE: - printf ("ROOT INODE UNALLOCATED. TERMINATING.\n"); - goto fatal; - case FSTATE: - printf ("ROOT INODE NOT DIRECTORY\n"); - if (! fs->writable) - goto fatal; - if (! fs_inode_get (fs, &inode, BSDFS_ROOT_INODE)) - goto fatal; - inode.mode &= ~INODE_MODE_FMT; - inode.mode |= INODE_MODE_FDIR; - fs_inode_save (&inode, 1); - set_inode_state (BSDFS_ROOT_INODE, DSTATE); - case DSTATE: - scan_pass2 (fs, BSDFS_ROOT_INODE); - break; - case CLEAR: - printf ("DUPS/BAD IN ROOT INODE\n"); - set_inode_state (BSDFS_ROOT_INODE, DSTATE); - scan_pass2 (fs, BSDFS_ROOT_INODE); - } + printf ("** Phase 2 - Check Pathnames\n"); + thisname = pathp = pathname; + switch (inode_state (BSDFS_ROOT_INODE)) { + case USTATE: + printf ("ROOT INODE UNALLOCATED. TERMINATING.\n"); + goto fatal; + case FSTATE: + printf ("ROOT INODE NOT DIRECTORY\n"); + if (! fs->writable) + goto fatal; + if (! fs_inode_get (fs, &inode, BSDFS_ROOT_INODE)) + goto fatal; + inode.mode &= ~INODE_MODE_FMT; + inode.mode |= INODE_MODE_FDIR; + fs_inode_save (&inode, 1); + set_inode_state (BSDFS_ROOT_INODE, DSTATE); + case DSTATE: + scan_pass2 (fs, BSDFS_ROOT_INODE); + break; + case CLEAR: + printf ("DUPS/BAD IN ROOT INODE\n"); + set_inode_state (BSDFS_ROOT_INODE, DSTATE); + scan_pass2 (fs, BSDFS_ROOT_INODE); + } - printf ("** Phase 3 - Check Connectivity\n"); - for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { - if (inode_state (inum) == DSTATE) { - unsigned ino; + printf ("** Phase 3 - Check Connectivity\n"); + for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { + if (inode_state (inum) == DSTATE) { + unsigned ino; - find_inode_name = ".."; - ino = inum; - do { - if (! fs_inode_get (fs, &inode, ino)) - break; - find_inode_result = 0; - scan_inode (&inode, DATA, scan_directory, find_inode); - if (find_inode_result == 0) { - /* Parent link lost. */ - if (move_to_lost_found (&inode)) { - thisname = pathp = pathname; - *pathp++ = '?'; - scan_pass2 (fs, ino); - } - break; - } - ino = find_inode_result; - } while (inode_state (ino) == DSTATE); - } - } + find_inode_name = ".."; + ino = inum; + do { + if (! fs_inode_get (fs, &inode, ino)) + break; + find_inode_result = 0; + scan_inode (&inode, DATA, scan_directory, find_inode); + if (find_inode_result == 0) { + /* Parent link lost. */ + if (move_to_lost_found (&inode)) { + thisname = pathp = pathname; + *pathp++ = '?'; + scan_pass2 (fs, ino); + } + break; + } + ino = find_inode_result; + } while (inode_state (ino) == DSTATE); + } + } - printf ("** Phase 4 - Check Reference Counts\n"); - for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { - switch (inode_state (inum)) { - case FSTATE: - n = link_count [inum]; - if (n) - adjust_link_count (fs, inum, n); - else { - unsigned *blp; + printf ("** Phase 4 - Check Reference Counts\n"); + for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { + switch (inode_state (inum)) { + case FSTATE: + n = link_count [inum]; + if (n) + adjust_link_count (fs, inum, n); + else { + unsigned *blp; - for (blp = bad_link_list; blp < bad_link_end; blp++) - if (*blp == inum) { - clear_inode (fs, inum, "UNREF"); - break; - } - } - break; - case DSTATE: - clear_inode (fs, inum, "UNREF"); - break; - case CLEAR: - clear_inode (fs, inum, "BAD/DUP"); - } - } - buf_flush (fs); + for (blp = bad_link_list; blp < bad_link_end; blp++) + if (*blp == inum) { + clear_inode (fs, inum, "UNREF"); + break; + } + } + break; + case DSTATE: + clear_inode (fs, inum, "UNREF"); + break; + case CLEAR: + clear_inode (fs, inum, "BAD/DUP"); + } + } + buf_flush (fs); - printf ("** Phase 5 - Check Free List\n"); - free (link_count); - check_free_inode_list (fs); - free (state_map); - bad_blocks = dup_blocks = 0; - free_map = calloc (block_map_size, sizeof (*free_map)); - if (! free_map) { - printf ("NO MEMORY TO CHECK FREE LIST\n"); - free_list_corrupted = 1; - free_blocks = 0; - } else { - memcpy (free_map, block_map, block_map_size); - free_blocks = check_free_list (fs); - free (free_map); - } - if (bad_blocks) - printf ("%d BAD BLKS IN FREE LIST\n", bad_blocks); - if (dup_blocks) - printf ("%d DUP BLKS IN FREE LIST\n", dup_blocks); - if (free_list_corrupted == 0) { - if (used_blocks + free_blocks != fs->fsize - fs->isize) { - printf ("%d BLK(S) MISSING\n", fs->fsize - - fs->isize - used_blocks - free_blocks); - free_list_corrupted = 1; - } - } - if (free_list_corrupted) { - printf ("BAD FREE LIST\n"); - if (! fs->writable) - free_list_corrupted = 0; - } + printf ("** Phase 5 - Check Free List\n"); + free (link_count); + check_free_inode_list (fs); + free (state_map); + bad_blocks = dup_blocks = 0; + free_map = calloc (block_map_size, sizeof (*free_map)); + if (! free_map) { + printf ("NO MEMORY TO CHECK FREE LIST\n"); + free_list_corrupted = 1; + free_blocks = 0; + } else { + memcpy (free_map, block_map, block_map_size); + free_blocks = check_free_list (fs); + free (free_map); + } + if (bad_blocks) + printf ("%d BAD BLKS IN FREE LIST\n", bad_blocks); + if (dup_blocks) + printf ("%d DUP BLKS IN FREE LIST\n", dup_blocks); + if (free_list_corrupted == 0) { + if (used_blocks + free_blocks != fs->fsize - fs->isize) { + printf ("%d BLK(S) MISSING\n", fs->fsize - + fs->isize - used_blocks - free_blocks); + free_list_corrupted = 1; + } + } + if (free_list_corrupted) { + printf ("BAD FREE LIST\n"); + if (! fs->writable) + free_list_corrupted = 0; + } - if (free_list_corrupted) { - printf ("** Phase 6 - Salvage Free List\n"); - free_blocks = make_free_list (fs); - } + if (free_list_corrupted) { + printf ("** Phase 6 - Salvage Free List\n"); + free_blocks = make_free_list (fs); + } - printf ("%d files %d blocks %d free\n", - total_files, used_blocks, free_blocks); - if (fs->modified) { - time (&fs->utime); - fs->dirty = 1; - } - buf_flush (fs); - fs_sync (fs, 0); - if (fs->modified) - printf ("\n***** FILE SYSTEM WAS MODIFIED *****\n"); + printf ("%d files %d blocks %d free\n", + total_files, used_blocks, free_blocks); + if (fs->modified) { + time (&fs->utime); + fs->dirty = 1; + } + buf_flush (fs); + fs_sync (fs, 0); + if (fs->modified) + printf ("\n***** FILE SYSTEM WAS MODIFIED *****\n"); - free (block_map); - return 1; + free (block_map); + return 1; } diff --git a/tools/fsutil/create.c b/tools/fsutil/create.c index ad3eea9..66ef485 100644 --- a/tools/fsutil/create.c +++ b/tools/fsutil/create.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include @@ -19,368 +33,370 @@ extern int verbose; int inode_build_list (fs_t *fs) { - fs_inode_t inode; - unsigned int inum, total_inodes; + fs_inode_t inode; + unsigned int inum, total_inodes; - total_inodes = (fs->isize - 1) * BSDFS_INODES_PER_BLOCK; - for (inum = 1; inum <= total_inodes; inum++) { - if (! fs_inode_get (fs, &inode, inum)) - return 0; - if (inode.mode == 0) { - fs->inode [fs->ninode++] = inum; - if (fs->ninode >= NICINOD) - break; - } - } - return 1; + total_inodes = (fs->isize - 1) * BSDFS_INODES_PER_BLOCK; + for (inum = 1; inum <= total_inodes; inum++) { + if (! fs_inode_get (fs, &inode, inum)) + return 0; + if (inode.mode == 0) { + fs->inode [fs->ninode++] = inum; + if (fs->ninode >= NICINOD) + break; + } + } + return 1; } static int create_inode1 (fs_t *fs) { - fs_inode_t inode; + fs_inode_t inode; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FREG; - inode.fs = fs; - inode.number = 1; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FREG; + inode.fs = fs; + inode.number = 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static int create_root_directory (fs_t *fs) { - fs_inode_t inode; - unsigned char buf [BSDFS_BSIZE]; - unsigned int bno; + fs_inode_t inode; + unsigned char buf [BSDFS_BSIZE]; + unsigned int bno; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FDIR | 0777; - inode.fs = fs; - inode.number = BSDFS_ROOT_INODE; - inode.size = BSDFS_BSIZE; - inode.flags = 0; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FDIR | 0777; + inode.fs = fs; + inode.number = BSDFS_ROOT_INODE; + inode.size = BSDFS_BSIZE; + inode.flags = 0; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - /* directory - put in extra links */ - memset (buf, 0, sizeof(buf)); - buf[0] = inode.number; - buf[1] = inode.number >> 8; - buf[2] = inode.number >> 16; - buf[3] = inode.number >> 24; - buf[4] = 12; - buf[5] = 12 >> 8; - buf[6] = 1; - buf[7] = 1 >> 8; - buf[8] = '.'; - buf[9] = 0; - buf[10] = 0; - buf[11] = 0; + /* directory - put in extra links */ + memset (buf, 0, sizeof(buf)); + buf[0] = inode.number; + buf[1] = inode.number >> 8; + buf[2] = inode.number >> 16; + buf[3] = inode.number >> 24; + buf[4] = 12; + buf[5] = 12 >> 8; + buf[6] = 1; + buf[7] = 1 >> 8; + buf[8] = '.'; + buf[9] = 0; + buf[10] = 0; + buf[11] = 0; - buf[12+0] = BSDFS_ROOT_INODE; - buf[12+1] = BSDFS_ROOT_INODE >> 8; - buf[12+2] = BSDFS_ROOT_INODE >> 16; - buf[12+3] = BSDFS_ROOT_INODE >> 24; - buf[12+4] = 12; - buf[12+5] = 12 >> 8; - buf[12+6] = 2; - buf[12+7] = 2 >> 8; - buf[12+8] = '.'; - buf[12+9] = '.'; - buf[12+10] = 0; - buf[12+11] = 0; + buf[12+0] = BSDFS_ROOT_INODE; + buf[12+1] = BSDFS_ROOT_INODE >> 8; + buf[12+2] = BSDFS_ROOT_INODE >> 16; + buf[12+3] = BSDFS_ROOT_INODE >> 24; + buf[12+4] = 12; + buf[12+5] = 12 >> 8; + buf[12+6] = 2; + buf[12+7] = 2 >> 8; + buf[12+8] = '.'; + buf[12+9] = '.'; + buf[12+10] = 0; + buf[12+11] = 0; - buf[24+0] = BSDFS_LOSTFOUND_INODE; - buf[24+1] = BSDFS_LOSTFOUND_INODE >> 8; - buf[24+2] = BSDFS_LOSTFOUND_INODE >> 16; - buf[24+3] = BSDFS_LOSTFOUND_INODE >> 24; - buf[24+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12); - buf[24+5] = (BSDFS_BSIZE - 12 - 12) >> 8; - buf[24+6] = 10; - buf[24+7] = 10 >> 8; - memcpy (&buf[24+8], "lost+found\0\0", 12); + buf[24+0] = BSDFS_LOSTFOUND_INODE; + buf[24+1] = BSDFS_LOSTFOUND_INODE >> 8; + buf[24+2] = BSDFS_LOSTFOUND_INODE >> 16; + buf[24+3] = BSDFS_LOSTFOUND_INODE >> 24; + buf[24+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12); + buf[24+5] = (BSDFS_BSIZE - 12 - 12) >> 8; + buf[24+6] = 10; + buf[24+7] = 10 >> 8; + memcpy (&buf[24+8], "lost+found\0\0", 12); - if (fs->swapsz != 0) { - buf[24+4] = 20; - buf[24+5] = 20 >> 8; - buf[44+0] = BSDFS_SWAP_INODE; - buf[44+1] = BSDFS_SWAP_INODE >> 8; - buf[44+2] = BSDFS_SWAP_INODE >> 16; - buf[44+3] = BSDFS_SWAP_INODE >> 24; - buf[44+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12 - 20); - buf[44+5] = (BSDFS_BSIZE - 12 - 12 - 20) >> 8; - buf[44+6] = 4; - buf[44+7] = 4 >> 8; - memcpy (&buf[44+8], "swap\0\0\0\0", 8); - } - inode.nlink = 3; + if (fs->swapsz != 0) { + buf[24+4] = 20; + buf[24+5] = 20 >> 8; + buf[44+0] = BSDFS_SWAP_INODE; + buf[44+1] = BSDFS_SWAP_INODE >> 8; + buf[44+2] = BSDFS_SWAP_INODE >> 16; + buf[44+3] = BSDFS_SWAP_INODE >> 24; + buf[44+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12 - 20); + buf[44+5] = (BSDFS_BSIZE - 12 - 12 - 20) >> 8; + buf[44+6] = 4; + buf[44+7] = 4 >> 8; + memcpy (&buf[44+8], "swap\0\0\0\0", 8); + } + inode.nlink = 3; - if (! fs_block_alloc (fs, &bno)) - return 0; - if (! fs_write_block (fs, bno, buf)) - return 0; - inode.addr[0] = bno; + if (! fs_block_alloc (fs, &bno)) + return 0; + if (! fs_write_block (fs, bno, buf)) + return 0; + inode.addr[0] = bno; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static int create_lost_found_directory (fs_t *fs) { - fs_inode_t inode; - unsigned char buf [BSDFS_BSIZE]; - unsigned int bno; + fs_inode_t inode; + unsigned char buf [BSDFS_BSIZE]; + unsigned int bno; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FDIR | 0777; - inode.fs = fs; - inode.number = BSDFS_LOSTFOUND_INODE; - inode.size = BSDFS_BSIZE; - inode.flags = 0; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FDIR | 0777; + inode.fs = fs; + inode.number = BSDFS_LOSTFOUND_INODE; + inode.size = BSDFS_BSIZE; + inode.flags = 0; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - /* directory - put in extra links */ - memset (buf, 0, sizeof(buf)); - buf[0] = inode.number; - buf[1] = inode.number >> 8; - buf[2] = inode.number >> 16; - buf[3] = inode.number >> 24; - buf[4] = 12; - buf[5] = 12 >> 8; - buf[6] = 1; - buf[7] = 1 >> 8; - buf[8] = '.'; - buf[9] = 0; - buf[10] = 0; - buf[11] = 0; + /* directory - put in extra links */ + memset (buf, 0, sizeof(buf)); + buf[0] = inode.number; + buf[1] = inode.number >> 8; + buf[2] = inode.number >> 16; + buf[3] = inode.number >> 24; + buf[4] = 12; + buf[5] = 12 >> 8; + buf[6] = 1; + buf[7] = 1 >> 8; + buf[8] = '.'; + buf[9] = 0; + buf[10] = 0; + buf[11] = 0; - buf[12+0] = BSDFS_ROOT_INODE; - buf[12+1] = BSDFS_ROOT_INODE >> 8; - buf[12+2] = BSDFS_ROOT_INODE >> 16; - buf[12+3] = BSDFS_ROOT_INODE >> 24; - buf[12+4] = (unsigned char) (BSDFS_BSIZE - 12); - buf[12+5] = (BSDFS_BSIZE - 12) >> 8; - buf[12+6] = 2; - buf[12+7] = 2 >> 8; - buf[12+8] = '.'; - buf[12+9] = '.'; - buf[12+10] = 0; - buf[12+11] = 0; + buf[12+0] = BSDFS_ROOT_INODE; + buf[12+1] = BSDFS_ROOT_INODE >> 8; + buf[12+2] = BSDFS_ROOT_INODE >> 16; + buf[12+3] = BSDFS_ROOT_INODE >> 24; + buf[12+4] = (unsigned char) (BSDFS_BSIZE - 12); + buf[12+5] = (BSDFS_BSIZE - 12) >> 8; + buf[12+6] = 2; + buf[12+7] = 2 >> 8; + buf[12+8] = '.'; + buf[12+9] = '.'; + buf[12+10] = 0; + buf[12+11] = 0; - inode.nlink = 2; + inode.nlink = 2; - if (! fs_block_alloc (fs, &bno)) - return 0; - if (! fs_write_block (fs, bno, buf)) - return 0; - inode.addr[0] = bno; + if (! fs_block_alloc (fs, &bno)) + return 0; + if (! fs_write_block (fs, bno, buf)) + return 0; + inode.addr[0] = bno; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static void map_block_swap (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int bn, indir, newb, shift, i, j; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int bn, indir, newb, shift, i, j; - /* - * Blocks 0..NADDR-3 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - inode->addr[lbn] = inode->fs->isize + lbn; - return; - } + /* + * Blocks 0..NADDR-3 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + inode->addr[lbn] = inode->fs->isize + lbn; + return; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - shift = 0; - i = 1; - bn = lbn - (NADDR-3); - for (j=3; ; j--) { - if (j == 0) { - fprintf (stderr, "swap: too large size\n"); - exit (-1); - } - shift += NSHIFT; - i <<= NSHIFT; - if (bn < i) - break; - bn -= i; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + shift = 0; + i = 1; + bn = lbn - (NADDR-3); + for (j=3; ; j--) { + if (j == 0) { + fprintf (stderr, "swap: too large size\n"); + exit (-1); + } + shift += NSHIFT; + i <<= NSHIFT; + if (bn < i) + break; + bn -= i; + } - /* - * Fetch the first indirect block. - */ - indir = inode->addr [NADDR-j]; - if (indir == 0) { - if (! fs_block_alloc (inode->fs, &indir)) { -alloc_error: fprintf (stderr, "swap: cannot allocate indirect block\n"); - exit (-1); - } - if (verbose) - printf ("swap: allocate indirect block %d (j=%d)\n", indir, j); - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) { -write_error: fprintf (stderr, "swap: cannot write indirect block %d\n", indir); - exit (-1); - } - inode->addr [NADDR-j] = indir; - } + /* + * Fetch the first indirect block. + */ + indir = inode->addr [NADDR-j]; + if (indir == 0) { + if (! fs_block_alloc (inode->fs, &indir)) { +alloc_error: + fprintf (stderr, "swap: cannot allocate indirect block\n"); + exit (-1); + } + if (verbose) + printf ("swap: allocate indirect block %d (j=%d)\n", indir, j); + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) { +write_error: + fprintf (stderr, "swap: cannot write indirect block %d\n", indir); + exit (-1); + } + inode->addr [NADDR-j] = indir; + } - /* - * Fetch through the indirect blocks - */ - for (; ; j++) { - if (! fs_read_block (inode->fs, indir, (unsigned char*) block)) { - fprintf (stderr, "swap: cannot read indirect block %d\n", indir); - exit (-1); - } - shift -= NSHIFT; - i = (bn >> shift) & NMASK; - if (j == 3) { - block[i] = inode->fs->isize + lbn; - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) - goto write_error; - return; - } - if (block[i] != 0) { - indir = block [i]; - continue; - } - /* Allocate new indirect block. */ - if (! fs_block_alloc (inode->fs, &newb)) - goto alloc_error; - if (verbose) - printf ("swap: allocate new block %d (j=%d)\n", newb, j); - block[i] = newb; - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) - goto write_error; - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) { - fprintf (stderr, "swap: cannot write block %d\n", newb); - exit (-1); - } - indir = newb; - } + /* + * Fetch through the indirect blocks + */ + for (; ; j++) { + if (! fs_read_block (inode->fs, indir, (unsigned char*) block)) { + fprintf (stderr, "swap: cannot read indirect block %d\n", indir); + exit (-1); + } + shift -= NSHIFT; + i = (bn >> shift) & NMASK; + if (j == 3) { + block[i] = inode->fs->isize + lbn; + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) + goto write_error; + return; + } + if (block[i] != 0) { + indir = block [i]; + continue; + } + /* Allocate new indirect block. */ + if (! fs_block_alloc (inode->fs, &newb)) + goto alloc_error; + if (verbose) + printf ("swap: allocate new block %d (j=%d)\n", newb, j); + block[i] = newb; + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) + goto write_error; + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) { + fprintf (stderr, "swap: cannot write block %d\n", newb); + exit (-1); + } + indir = newb; + } } static int create_swap_file (fs_t *fs) { - fs_inode_t inode; - unsigned lbn; + fs_inode_t inode; + unsigned lbn; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FREG | 0400; - inode.fs = fs; - inode.number = BSDFS_SWAP_INODE; - inode.size = fs->swapsz * BSDFS_BSIZE; - inode.flags = /*SYS_IMMUTABLE |*/ USER_IMMUTABLE | USER_NODUMP; - inode.nlink = 1; - inode.dirty = 1; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FREG | 0400; + inode.fs = fs; + inode.number = BSDFS_SWAP_INODE; + inode.size = fs->swapsz * BSDFS_BSIZE; + inode.flags = /*SYS_IMMUTABLE |*/ USER_IMMUTABLE | USER_NODUMP; + inode.nlink = 1; + inode.dirty = 1; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - for (lbn=0; lbnswapsz; lbn++) - map_block_swap (&inode, lbn); + for (lbn=0; lbnswapsz; lbn++) + map_block_swap (&inode, lbn); - if (! fs_inode_save (&inode, 0)) { - fprintf (stderr, "swap: cannot save file inode\n"); - return 0; - } - return 1; + if (! fs_inode_save (&inode, 0)) { + fprintf (stderr, "swap: cannot save file inode\n"); + return 0; + } + return 1; } int fs_create (fs_t *fs, const char *filename, unsigned kbytes, - unsigned swap_kbytes) + unsigned swap_kbytes) { - int n; - unsigned char buf [BSDFS_BSIZE]; - off_t bytes, offset; + int n; + unsigned char buf [BSDFS_BSIZE]; + off_t bytes, offset; - memset (fs, 0, sizeof (*fs)); - fs->filename = filename; - fs->seek = 0; + memset (fs, 0, sizeof (*fs)); + fs->filename = filename; + fs->seek = 0; - fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666); - if (fs->fd < 0) - return 0; - fs->writable = 1; + fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666); + if (fs->fd < 0) + return 0; + fs->writable = 1; - /* get total disk size - * and inode block size */ - bytes = (off_t) kbytes * 1024ULL; - fs->fsize = bytes / BSDFS_BSIZE; - fs->isize = 1 + (fs->fsize / 16 + BSDFS_INODES_PER_BLOCK - 1) / - BSDFS_INODES_PER_BLOCK; - if (fs->isize < 2) - return 0; + /* get total disk size + * and inode block size */ + bytes = (off_t) kbytes * 1024ULL; + fs->fsize = bytes / BSDFS_BSIZE; + fs->isize = 1 + (fs->fsize / 16 + BSDFS_INODES_PER_BLOCK - 1) / + BSDFS_INODES_PER_BLOCK; + if (fs->isize < 2) + return 0; - /* make sure the file is of proper size */ - offset = lseek (fs->fd, bytes-1, SEEK_SET); - if (offset != bytes-1) - return 0; - if (write (fs->fd, "", 1) != 1) { - perror ("write"); - return 0; - } - lseek (fs->fd, 0, SEEK_SET); + /* make sure the file is of proper size */ + offset = lseek (fs->fd, bytes-1, SEEK_SET); + if (offset != bytes-1) + return 0; + if (write (fs->fd, "", 1) != 1) { + perror ("write"); + return 0; + } + lseek (fs->fd, 0, SEEK_SET); - /* build a list of free blocks */ - fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE; - fs_block_free (fs, 0); - for (n = fs->fsize - 1; n >= fs->isize + fs->swapsz; n--) - if (! fs_block_free (fs, n)) - return 0; + /* build a list of free blocks */ + fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE; + fs_block_free (fs, 0); + for (n = fs->fsize - 1; n >= fs->isize + fs->swapsz; n--) + if (! fs_block_free (fs, n)) + return 0; - /* initialize inodes */ - memset (buf, 0, BSDFS_BSIZE); - if (! fs_seek (fs, BSDFS_BSIZE)) - return 0; - for (n=1; n < fs->isize; n++) { - if (! fs_write (fs, buf, BSDFS_BSIZE)) - return 0; - fs->tinode += BSDFS_INODES_PER_BLOCK; - } + /* initialize inodes */ + memset (buf, 0, BSDFS_BSIZE); + if (! fs_seek (fs, BSDFS_BSIZE)) + return 0; + for (n=1; n < fs->isize; n++) { + if (! fs_write (fs, buf, BSDFS_BSIZE)) + return 0; + fs->tinode += BSDFS_INODES_PER_BLOCK; + } - /* legacy empty inode 1 */ - if (! create_inode1 (fs)) - return 0; + /* legacy empty inode 1 */ + if (! create_inode1 (fs)) + return 0; - /* lost+found directory */ - if (! create_lost_found_directory (fs)) - return 0; + /* lost+found directory */ + if (! create_lost_found_directory (fs)) + return 0; - /* root directory */ - if (! create_root_directory (fs)) - return 0; + /* root directory */ + if (! create_root_directory (fs)) + return 0; - /* swap file */ - if (fs->swapsz != 0 && ! create_swap_file (fs)) - return 0; + /* swap file */ + if (fs->swapsz != 0 && ! create_swap_file (fs)) + return 0; - /* build a list of free inodes */ - if (! inode_build_list (fs)) - return 0; + /* build a list of free inodes */ + if (! inode_build_list (fs)) + return 0; - /* write out super block */ - return fs_sync (fs, 1); + /* write out super block */ + return fs_sync (fs, 1); } diff --git a/tools/fsutil/file.c b/tools/fsutil/file.c index aed769b..50b4f37 100644 --- a/tools/fsutil/file.c +++ b/tools/fsutil/file.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include @@ -13,70 +27,70 @@ extern int verbose; -int fs_file_create (fs_t *fs, fs_file_t *file, char *name, int mode) +int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) { - if (! fs_inode_by_name (fs, &file->inode, name, 1, mode)) { - fprintf (stderr, "%s: inode open failed\n", name); - return 0; - } - if ((file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Cannot open directory on write. */ - return 0; - } - fs_inode_truncate (&file->inode); - fs_inode_save (&file->inode, 0); - file->writable = 1; - file->offset = 0; - return 1; + if (! fs_inode_create (fs, &file->inode, name, mode)) { + fprintf (stderr, "%s: inode open failed\n", name); + return 0; + } + if ((file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot open directory on write. */ + return 0; + } + fs_inode_truncate (&file->inode, 0); + fs_inode_save (&file->inode, 0); + file->writable = 1; + file->offset = 0; + return 1; } -int fs_file_open (fs_t *fs, fs_file_t *file, char *name, int wflag) +int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag) { - if (! fs_inode_by_name (fs, &file->inode, name, 0, 0)) { - fprintf (stderr, "%s: inode open failed\n", name); - return 0; - } - if (wflag && (file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Cannot open directory on write. */ - return 0; - } - file->writable = wflag; - file->offset = 0; - return 1; + if (! fs_inode_lookup (fs, &file->inode, name)) { + fprintf (stderr, "%s: inode open failed\n", name); + return 0; + } + if (wflag && (file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot open directory on write. */ + return 0; + } + file->writable = wflag; + file->offset = 0; + return 1; } int fs_file_read (fs_file_t *file, unsigned char *data, unsigned long bytes) { - if (! fs_inode_read (&file->inode, file->offset, data, bytes)) { - fprintf (stderr, "inode %d: file write failed\n", - file->inode.number); - return 0; - } - file->offset += bytes; - return 1; + if (! fs_inode_read (&file->inode, file->offset, data, bytes)) { + fprintf (stderr, "inode %d: file read failed, %lu bytes at offset %lu\n", + file->inode.number, bytes, file->offset); + return 0; + } + file->offset += bytes; + return 1; } int fs_file_write (fs_file_t *file, unsigned char *data, unsigned long bytes) { - if (! file->writable) - return 0; - if (! fs_inode_write (&file->inode, file->offset, data, bytes)) { - fprintf (stderr, "inode %d: error writing %lu bytes at offset %lu\n", - file->inode.number, bytes, file->offset); - return 0; - } - file->offset += bytes; - return 1; + if (! file->writable) + return 0; + if (! fs_inode_write (&file->inode, file->offset, data, bytes)) { + fprintf (stderr, "inode %d: file write failed, %lu bytes at offset %lu\n", + file->inode.number, bytes, file->offset); + return 0; + } + file->offset += bytes; + return 1; } int fs_file_close (fs_file_t *file) { - if (file->writable) { - if (! fs_inode_save (&file->inode, 0)) { - fprintf (stderr, "inode %d: file close failed\n", - file->inode.number); - return 0; - } - } - return 1; + if (file->writable) { + if (! fs_inode_save (&file->inode, 0)) { + fprintf (stderr, "inode %d: file close failed\n", + file->inode.number); + return 0; + } + } + return 1; } diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 8f7eca1..ea3aa05 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -3,19 +3,36 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include #include #include #include +#include #include #include #include +#include #include "bsdfs.h" +#include "manifest.h" int verbose; int extract; @@ -23,497 +40,732 @@ int add; int newfs; int check; int fix; +int mount; +int scan; unsigned kbytes; unsigned swap_kbytes; static const char *program_version = - "BSD 2.x file system utility, version 1.0\n" - "Copyright (C) 2011 Serge Vakulenko"; + "BSD 2.x file system utility, version 1.1\n" + "Copyright (C) 2011-2014 Serge Vakulenko"; static const char *program_bug_address = ""; static struct option program_options[] = { - { "help", no_argument, 0, 'h' }, - { "version", no_argument, 0, 'V' }, - { "verbose", no_argument, 0, 'v' }, - { "add", no_argument, 0, 'a' }, - { "extract", no_argument, 0, 'x' }, - { "check", no_argument, 0, 'c' }, - { "fix", no_argument, 0, 'f' }, - { "new", required_argument, 0, 'n' }, - { "swap", required_argument, 0, 's' }, - { 0 } + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'V' }, + { "verbose", no_argument, 0, 'v' }, + { "add", no_argument, 0, 'a' }, + { "extract", no_argument, 0, 'x' }, + { "check", no_argument, 0, 'c' }, + { "fix", no_argument, 0, 'f' }, + { "mount", no_argument, 0, 'm' }, + { "scan", no_argument, 0, 'S' }, + { "new", required_argument, 0, 'n' }, + { "swap", required_argument, 0, 's' }, + { "manifest", required_argument, 0, 'M' }, + { 0 } }; static void print_help (char *progname) { - char *p = strrchr (progname, '/'); - if (p) - progname = p+1; + char *p = strrchr (progname, '/'); + if (p) + progname = p+1; - printf ("%s\n", program_version); - printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n" - "see the GNU General Public License for more details.\n"); - printf ("\n"); - printf ("Usage:\n"); - printf (" %s [--verbose] filesys.bin\n", progname); - printf (" %s --add filesys.bin files...\n", progname); - printf (" %s --extract filesys.bin\n", progname); - printf (" %s --check [--fix] filesys.bin\n", progname); - printf (" %s --new=kbytes [--swap=kbytes] filesys.bin\n", progname); - printf ("\n"); - printf ("Options:\n"); - printf (" -a, --add Add files to filesystem.\n"); - printf (" -x, --extract Extract all files.\n"); - printf (" -c, --check Check filesystem, use -c -f to fix.\n"); - printf (" -f, --fix Fix bugs in filesystem.\n"); - printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); - printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); - printf (" -v, --verbose Print verbose information.\n"); - printf (" -V, --version Print version information and then exit.\n"); - printf (" -h, --help Print this message.\n"); - printf ("\n"); - printf ("Report bugs to \"%s\".\n", program_bug_address); + printf ("%s\n", program_version); + printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n" + "see the BSD 3-Clause License for more details.\n"); + printf ("\n"); + printf ("Usage:\n"); + printf (" %s [--verbose] filesys.img\n", progname); + printf (" %s --check [--fix] filesys.img\n", progname); + printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); + printf (" %s --mount filesys.img dir\n", progname); + printf (" %s --add filesys.img files...\n", progname); + printf (" %s --extract filesys.img\n", progname); + printf (" %s --scan dir > file\n", progname); + printf ("\n"); + printf ("Options:\n"); + printf (" -c, --check Check filesystem, use -c -f to fix.\n"); + printf (" -f, --fix Fix bugs in filesystem.\n"); + printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); + printf (" Add files from specified directory (optional)\n"); + printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); + printf (" -M file, --manifest=file List of files and attributes to create.\n"); + printf (" -m, --mount Mount the filesystem.\n"); + printf (" -a, --add Add files to filesystem.\n"); + printf (" -x, --extract Extract all files.\n"); + printf (" -S, --scan Create a manifest from directory contents.\n"); + printf (" -v, --verbose Be verbose.\n"); + printf (" -V, --version Print version information and then exit.\n"); + printf (" -h, --help Print this message.\n"); + printf ("\n"); + printf ("Report bugs to \"%s\".\n", program_bug_address); } void print_inode (fs_inode_t *inode, - char *dirname, char *filename, FILE *out) + char *dirname, char *filename, FILE *out) { - fprintf (out, "%s/%s", dirname, filename); - switch (inode->mode & INODE_MODE_FMT) { - case INODE_MODE_FDIR: - if (filename[0] != 0) - fprintf (out, "/"); - break; - case INODE_MODE_FCHR: - fprintf (out, " - char %d %d", - inode->addr[1] >> 8, inode->addr[1] & 0xff); - break; - case INODE_MODE_FBLK: - fprintf (out, " - block %d %d", - inode->addr[1] >> 8, inode->addr[1] & 0xff); - break; - default: - fprintf (out, " - %lu bytes", inode->size); - break; - } - fprintf (out, "\n"); + fprintf (out, "%s/%s", dirname, filename); + switch (inode->mode & INODE_MODE_FMT) { + case INODE_MODE_FDIR: + if (filename[0] != 0) + fprintf (out, "/"); + break; + case INODE_MODE_FCHR: + fprintf (out, " - char %d %d", + inode->addr[1] >> 8, inode->addr[1] & 0xff); + break; + case INODE_MODE_FBLK: + fprintf (out, " - block %d %d", + inode->addr[1] >> 8, inode->addr[1] & 0xff); + break; + default: + fprintf (out, " - %lu bytes", inode->size); + break; + } + fprintf (out, "\n"); } void print_indirect_block (fs_t *fs, unsigned int bno, FILE *out) { - unsigned short nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned short nb; + unsigned char data [BSDFS_BSIZE]; + int i; - fprintf (out, " [%d]", bno); - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "read error at block %d\n", bno); - return; - } - for (i=0; imode & INODE_MODE_FMT) == INODE_MODE_FCHR || - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) - return; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) + return; - fprintf (out, " "); - for (i=0; iaddr[i] == 0) - continue; - fprintf (out, " %d", inode->addr[i]); - } - if (inode->addr[NDADDR] != 0) - print_indirect_block (inode->fs, inode->addr[NDADDR], out); - if (inode->addr[NDADDR+1] != 0) - print_double_indirect_block (inode->fs, - inode->addr[NDADDR+1], out); - if (inode->addr[NDADDR+2] != 0) - print_triple_indirect_block (inode->fs, - inode->addr[NDADDR+2], out); - fprintf (out, "\n"); + fprintf (out, " "); + for (i=0; iaddr[i] == 0) + continue; + fprintf (out, " %d", inode->addr[i]); + } + if (inode->addr[NDADDR] != 0) + print_indirect_block (inode->fs, inode->addr[NDADDR], out); + if (inode->addr[NDADDR+1] != 0) + print_double_indirect_block (inode->fs, + inode->addr[NDADDR+1], out); + if (inode->addr[NDADDR+2] != 0) + print_triple_indirect_block (inode->fs, + inode->addr[NDADDR+2], out); + fprintf (out, "\n"); } void extract_inode (fs_inode_t *inode, char *path) { - int fd, n, mode; - unsigned long offset; - unsigned char data [BSDFS_BSIZE]; + int fd, n, mode; + unsigned long offset; + unsigned char data [BSDFS_BSIZE]; - /* Allow read/write for user. */ - mode = (inode->mode & 0777) | 0600; - fd = open (path, O_CREAT | O_RDWR, mode); - if (fd < 0) { - perror (path); - return; - } - for (offset = 0; offset < inode->size; offset += BSDFS_BSIZE) { - n = inode->size - offset; - if (n > BSDFS_BSIZE) - n = BSDFS_BSIZE; - if (! fs_inode_read (inode, offset, data, n)) { - fprintf (stderr, "%s: read error at offset %ld\n", - path, offset); - break; - } - if (write (fd, data, n) != n) { - fprintf (stderr, "%s: write error\n", path); - break; - } - } - close (fd); + /* Allow read/write for user. */ + mode = (inode->mode & 0777) | 0600; + fd = open (path, O_CREAT | O_RDWR, mode); + if (fd < 0) { + perror (path); + return; + } + for (offset = 0; offset < inode->size; offset += BSDFS_BSIZE) { + n = inode->size - offset; + if (n > BSDFS_BSIZE) + n = BSDFS_BSIZE; + if (! fs_inode_read (inode, offset, data, n)) { + fprintf (stderr, "%s: read error at offset %ld\n", + path, offset); + break; + } + if (write (fd, data, n) != n) { + fprintf (stderr, "%s: write error\n", path); + break; + } + } + close (fd); } void extractor (fs_inode_t *dir, fs_inode_t *inode, - char *dirname, char *filename, void *arg) + char *dirname, char *filename, void *arg) { - FILE *out = arg; - char *path, *relpath; + FILE *out = arg; + char *path, *relpath; - if (verbose) - print_inode (inode, dirname, filename, out); + if (verbose) + print_inode (inode, dirname, filename, out); - if ((inode->mode & INODE_MODE_FMT) != INODE_MODE_FDIR && - (inode->mode & INODE_MODE_FMT) != INODE_MODE_FREG) - return; + if ((inode->mode & INODE_MODE_FMT) != INODE_MODE_FDIR && + (inode->mode & INODE_MODE_FMT) != INODE_MODE_FREG) + return; - path = alloca (strlen (dirname) + strlen (filename) + 2); - strcpy (path, dirname); - strcat (path, "/"); - strcat (path, filename); - for (relpath=path; *relpath == '/'; relpath++) - continue; + path = alloca (strlen (dirname) + strlen (filename) + 2); + strcpy (path, dirname); + strcat (path, "/"); + strcat (path, filename); + for (relpath=path; *relpath == '/'; relpath++) + continue; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - if (mkdir (relpath, 0775) < 0 && errno != EEXIST) - perror (relpath); - /* Scan subdirectory. */ - fs_directory_scan (inode, path, extractor, arg); - } else { - extract_inode (inode, relpath); - } + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + if (mkdir (relpath, 0775) < 0 && errno != EEXIST) + perror (relpath); + /* Scan subdirectory. */ + fs_directory_scan (inode, path, extractor, arg); + } else { + extract_inode (inode, relpath); + } } void scanner (fs_inode_t *dir, fs_inode_t *inode, - char *dirname, char *filename, void *arg) + char *dirname, char *filename, void *arg) { - FILE *out = arg; - char *path; + FILE *out = arg; + char *path; - print_inode (inode, dirname, filename, out); + print_inode (inode, dirname, filename, out); - if (verbose > 1) { - /* Print a list of blocks. */ - print_inode_blocks (inode, out); - if (verbose > 2) { - fs_inode_print (inode, out); - printf ("--------\n"); - } - } - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR && - inode->number != BSDFS_ROOT_INODE) { - /* Scan subdirectory. */ - path = alloca (strlen (dirname) + strlen (filename) + 2); - strcpy (path, dirname); - strcat (path, "/"); - strcat (path, filename); - fs_directory_scan (inode, path, scanner, arg); - } + if (verbose > 1) { + /* Print a list of blocks. */ + print_inode_blocks (inode, out); + if (verbose > 2) { + fs_inode_print (inode, out); + printf ("--------\n"); + } + } + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR && + inode->number != BSDFS_ROOT_INODE) { + /* Scan subdirectory. */ + path = alloca (strlen (dirname) + strlen (filename) + 2); + strcpy (path, dirname); + strcat (path, "/"); + strcat (path, filename); + fs_directory_scan (inode, path, scanner, arg); + } } /* * Create a directory. */ -void add_directory (fs_t *fs, char *name) +void add_directory (fs_t *fs, char *name, int mode, int owner, int group) { - fs_inode_t dir, parent; - char buf [BSDFS_BSIZE], *p; + fs_inode_t dir, parent; + char buf [BSDFS_BSIZE], *p; - /* Open parent directory. */ - strcpy (buf, name); - p = strrchr (buf, '/'); - if (p) - *p = 0; - else - *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, 0, 0)) { - fprintf (stderr, "%s: cannot open directory\n", buf); - return; - } + /* Open parent directory. */ + strcpy (buf, name); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_lookup (fs, &parent, buf)) { + fprintf (stderr, "%s: cannot open directory\n", buf); + return; + } - /* Create directory. */ - int done = fs_inode_by_name (fs, &dir, name, 1, INODE_MODE_FDIR | 0777); - if (! done) { - fprintf (stderr, "%s: directory inode create failed\n", name); - return; - } - if (done == 1) { - /* The directory already existed. */ - return; - } - fs_inode_save (&dir, 0); + /* Create directory. */ + mode &= 07777; + mode |= INODE_MODE_FDIR; + int done = fs_inode_create (fs, &dir, name, mode); + if (! done) { + fprintf (stderr, "%s: directory inode create failed\n", name); + return; + } + if (done == 1) { + /* The directory already existed. */ + return; + } + dir.uid = owner; + dir.gid = group; + fs_inode_save (&dir, 1); - /* Make parent link '..' */ - strcpy (buf, name); - strcat (buf, "/.."); - if (! fs_inode_by_name (fs, &dir, buf, 3, parent.number)) { - fprintf (stderr, "%s: dotdot link failed\n", name); - return; - } - if (! fs_inode_get (fs, &parent, parent.number)) { - fprintf (stderr, "inode %d: cannot open parent\n", parent.number); - return; - } - ++parent.nlink; - fs_inode_save (&parent, 1); + /* Make parent link '..' */ + strcpy (buf, name); + strcat (buf, "/.."); + if (! fs_inode_link (fs, &dir, buf, parent.number)) { + fprintf (stderr, "%s: dotdot link failed\n", name); + return; + } + if (! fs_inode_get (fs, &parent, parent.number)) { + fprintf (stderr, "inode %d: cannot open parent\n", parent.number); + return; + } + ++parent.nlink; + fs_inode_save (&parent, 1); /*printf ("*** inode %d: increment link counter to %d\n", parent.number, parent.nlink);*/ } /* * Create a device node. */ -void add_device (fs_t *fs, char *name, char *spec) +void add_device (fs_t *fs, char *name, int mode, int owner, int group, + int type, int majr, int minr) { - fs_inode_t dev; - int majr, minr; - char type; + fs_inode_t dev; - if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 || - (type != 'c' && type != 'b') || - majr < 0 || majr > 255 || minr < 0 || minr > 255) { - fprintf (stderr, "%s: invalid device specification\n", spec); - fprintf (stderr, "expected c: or b:\n"); - return; - } - if (! fs_inode_by_name (fs, &dev, name, 1, 0666 | - ((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) { - fprintf (stderr, "%s: device inode create failed\n", name); - return; - } - dev.addr[1] = majr << 8 | minr; - fs_inode_save (&dev, 1); + mode &= 07777; + mode |= (type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR; + if (! fs_inode_create (fs, &dev, name, mode)) { + fprintf (stderr, "%s: device inode create failed\n", name); + return; + } + dev.addr[1] = majr << 8 | minr; + dev.uid = owner; + dev.gid = group; + time (&dev.mtime); + fs_inode_save (&dev, 1); } /* - * Copy file to filesystem. + * Copy regular file to filesystem. + */ +void add_file (fs_t *fs, const char *path, const char *dirname, + int mode, int owner, int group) +{ + fs_file_t file; + FILE *fd; + char accpath [BSDFS_BSIZE]; + unsigned char data [BSDFS_BSIZE]; + struct stat st; + int len; + + if (dirname && *dirname) { + /* Concatenate directory name and file name. */ + strcpy (accpath, dirname); + len = strlen (accpath); + if (accpath[len-1] != '/' && path[0] != '/') + strcat (accpath, "/"); + strcat (accpath, path); + } else { + /* Use filename relative to current directory. */ + strcpy (accpath, path); + } + fd = fopen (accpath, "r"); + if (! fd) { + perror (accpath); + return; + } + fstat (fileno(fd), &st); + if (mode == -1) + mode = st.st_mode; + mode &= 07777; + mode |= INODE_MODE_FREG; + if (! fs_file_create (fs, &file, path, mode)) { + fprintf (stderr, "%s: cannot create\n", path); + return; + } + for (;;) { + len = fread (data, 1, sizeof (data), fd); +/* printf ("read %d bytes from %s\n", len, accpath);*/ + if (len < 0) + perror (accpath); + if (len <= 0) + break; + if (! fs_file_write (&file, data, len)) { + fprintf (stderr, "%s: write error\n", path); + break; + } + } + file.inode.uid = owner; + file.inode.gid = group; + file.inode.mtime = st.st_mtime; + file.inode.dirty = 1; + fs_file_close (&file); + fclose (fd); +} + +/* + * Create a symlink. + */ +void add_symlink (fs_t *fs, const char *path, const char *link, + int mode, int owner, int group) +{ + fs_file_t file; + int len; + + mode &= 07777; + mode |= INODE_MODE_FLNK; + if (! fs_file_create (fs, &file, path, mode)) { + fprintf (stderr, "%s: cannot create\n", path); + return; + } + len = strlen (link); + if (! fs_file_write (&file, (unsigned char*) link, len)) { + fprintf (stderr, "%s: write error\n", path); + return; + } + file.inode.uid = owner; + file.inode.gid = group; + time (&file.inode.mtime); + file.inode.dirty = 1; + fs_file_close (&file); +} + +/* + * Create a hard link. + */ +void add_hardlink (fs_t *fs, const char *path, const char *link) +{ + fs_inode_t source, target; + + /* Find source. */ + if (! fs_inode_lookup (fs, &source, link)) { + fprintf (stderr, "%s: link source not found\n", link); + return; + } + if ((source.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + fprintf (stderr, "%s: cannot link directories\n", link); + return; + } + + /* Create target link. */ + if (! fs_inode_link (fs, &target, path, source.number)) { + fprintf (stderr, "%s: link failed\n", path); + return; + } + source.nlink++; + fs_inode_save (&source, 1); +} + +/* + * Create a file/device/directory in the filesystem. * When name is ended by slash as "name/", directory is created. */ -void add_file (fs_t *fs, char *name) +void add_object (fs_t *fs, char *name) { - fs_file_t file; - FILE *fd; - unsigned char data [BSDFS_BSIZE]; - struct stat st; - char *p; - int len; + int majr, minr; + char type; + char *p; - if (verbose) { - printf ("%s\n", name); - } - p = strrchr (name, '/'); - if (p && p[1] == 0) { - *p = 0; - add_directory (fs, name); - return; - } - p = strrchr (name, '!'); - if (p) { - *p++ = 0; - add_device (fs, name, p); - return; - } - fd = fopen (name, "r"); - if (! fd) { - perror (name); - return; - } - stat (name, &st); - if (! fs_file_create (fs, &file, name, st.st_mode)) { - fprintf (stderr, "%s: cannot create\n", name); - return; - } - for (;;) { - len = fread (data, 1, sizeof (data), fd); -/* printf ("read %d bytes from %s\n", len, name);*/ - if (len < 0) - perror (name); - if (len <= 0) - break; - if (! fs_file_write (&file, data, len)) { - fprintf (stderr, "%s: write error\n", name); - break; - } - } - file.inode.mtime = st.st_mtime; - fs_file_close (&file); - fclose (fd); + if (verbose) { + printf ("%s\n", name); + } + p = strrchr (name, '/'); + if (p && p[1] == 0) { + *p = 0; + add_directory (fs, name, 0777, 0, 0); + return; + } + p = strrchr (name, '!'); + if (p) { + *p++ = 0; + if (sscanf (p, "%c%d:%d", &type, &majr, &minr) != 3 || + (type != 'c' && type != 'b') || + majr < 0 || majr > 255 || minr < 0 || minr > 255) { + fprintf (stderr, "%s: invalid device specification\n", p); + fprintf (stderr, "expected c: or b:\n"); + return; + } + add_device (fs, name, 0666, 0, 0, type, majr, minr); + return; + } + add_file (fs, name, 0, -1, 0, 0); +} + +/* + * Add the contents from the specified directory. + * Use the optional manifest file. + */ +void add_contents (fs_t *fs, const char *dirname, const char *manifest) +{ + manifest_t m; + void *cursor; + char *path, *link; + int filetype, mode, owner, group, majr, minr; + int ndirs = 0, nfiles = 0, nlinks = 0, nsymlinks = 0, ndevs = 0; + + if (manifest) { + /* Load manifest from file. */ + if (! manifest_load (&m, manifest)) { + fprintf (stderr, "%s: cannot read\n", manifest); + return; + } + } else { + /* Create manifest from directory contents. */ + if (! manifest_scan (&m, dirname)) { + fprintf (stderr, "%s: cannot read\n", dirname); + return; + } + } + + /* For every file in the manifest, + * add it to the target filesystem. */ + cursor = 0; + while ((filetype = manifest_iterate (&m, &cursor, &path, &link, &mode, + &owner, &group, &majr, &minr)) != 0) + { + switch (filetype) { + case 'd': + add_directory (fs, path, mode, owner, group); + ndirs++; + break; + case 'f': + add_file (fs, path, dirname, mode, owner, group); + nfiles++; + break; + case 'l': + add_hardlink (fs, path, link); + nlinks++; + break; + case 's': + add_symlink (fs, path, link, mode, owner, group); + nsymlinks++; + break; + case 'b': + add_device (fs, path, mode, owner, group, 'b', majr, minr); + ndevs++; + break; + case 'c': + add_device (fs, path, mode, owner, group, 'c', majr, minr); + ndevs++; + break; + } + } + fs_sync (fs, 0); + fs_close (fs); + printf ("Installed %u directories, %u files, %u devices, %u links, %u symlinks\n", + ndirs, nfiles, ndevs, nlinks, nsymlinks); } int main (int argc, char **argv) { - int i, key; - fs_t fs; - fs_inode_t inode; + int i, key; + fs_t fs; + fs_inode_t inode; + manifest_t m; + const char *manifest = 0; - for (;;) { - key = getopt_long (argc, argv, "vaxn:cfs:", - program_options, 0); - if (key == -1) - break; - switch (key) { - case 'v': - ++verbose; - break; - case 'a': - ++add; - break; - case 'x': - ++extract; - break; - case 'n': - ++newfs; - kbytes = strtol (optarg, 0, 0); - break; - case 'c': - ++check; - break; - case 'f': - ++fix; - break; - case 's': - swap_kbytes = strtol (optarg, 0, 0); - break; - case 'V': - printf ("%s\n", program_version); - return 0; - case 'h': - print_help (argv[0]); - return 0; - default: - print_help (argv[0]); - return -1; - } - } - i = optind; - if ((! add && i != argc-1) || (add && i >= argc) || - (extract + newfs + check + add > 1) || - (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) { - print_help (argv[0]); - return -1; - } + for (;;) { + key = getopt_long (argc, argv, "vaxmSn:cfs:M:", + program_options, 0); + if (key == -1) + break; + switch (key) { + case 'v': + ++verbose; + break; + case 'a': + ++add; + break; + case 'x': + ++extract; + break; + case 'n': + ++newfs; + kbytes = strtol (optarg, 0, 0); + break; + case 'c': + ++check; + break; + case 'f': + ++fix; + break; + case 'm': + ++mount; + break; + case 'S': + ++scan; + break; + case 's': + swap_kbytes = strtol (optarg, 0, 0); + break; + case 'M': + manifest = optarg; + break; + case 'V': + printf ("%s\n", program_version); + return 0; + case 'h': + print_help (argv[0]); + return 0; + default: + print_help (argv[0]); + return -1; + } + } + i = optind; + if (extract + newfs + check + add + mount + scan > 1) { + print_help (argv[0]); + return -1; + } - if (newfs) { - /* Create new filesystem. */ - if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) { - fprintf (stderr, "%s: cannot create filesystem\n", argv[i]); - return -1; - } - printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes); - fs_close (&fs); - return 0; - } + if (newfs) { + /* Create new filesystem. */ + if (i != argc-1 && i != argc-2) { + print_help (argv[0]); + return -1; + } + if (kbytes < BSDFS_BSIZE * 10 / 1024) { + /* Need at least 10 blocks. */ + fprintf (stderr, "%s: too small\n", argv[i]); + return -1; + } - if (check) { - /* Check filesystem for errors, and optionally fix them. */ - if (! fs_open (&fs, argv[i], fix)) { - fprintf (stderr, "%s: cannot open\n", argv[i]); - return -1; - } - fs_check (&fs); - fs_close (&fs); - return 0; - } + if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) { + fprintf (stderr, "%s: cannot create filesystem\n", argv[i]); + return -1; + } + printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes); - /* Add or extract or info. */ - if (! fs_open (&fs, argv[i], (add != 0))) { - fprintf (stderr, "%s: cannot open\n", argv[i]); - return -1; - } + if (i == argc-2) { + /* Add the contents from the specified directory. + * Use the optional manifest file. */ + add_contents (&fs, argv[i+1], manifest); + } + fs_close (&fs); + return 0; + } - if (extract) { - /* Extract all files to current directory. */ - if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { - fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); - return -1; - } - fs_directory_scan (&inode, "", extractor, (void*) stdout); - fs_close (&fs); - return 0; - } + if (check) { + /* Check filesystem for errors, and optionally fix them. */ + if (i != argc-1) { + print_help (argv[0]); + return -1; + } + if (! fs_open (&fs, argv[i], fix)) { + fprintf (stderr, "%s: cannot open\n", argv[i]); + return -1; + } + fs_check (&fs); + fs_close (&fs); + return 0; + } - if (add) { - /* Add files i+1..argc-1 to filesystem. */ - while (++i < argc) - add_file (&fs, argv[i]); - fs_sync (&fs, 0); - fs_close (&fs); - return 0; - } + if (scan) { + /* Create a manifest from directory contents. */ + if (i != argc-1) { + print_help (argv[0]); + return -1; + } + if (! manifest_scan (&m, argv[i])) { + fprintf (stderr, "%s: cannot read\n", argv[i]); + return -1; + } + manifest_print (&m); + return 0; + } - /* Print the structure of flesystem. */ - fs_print (&fs, stdout); - if (verbose) { - printf ("--------\n"); - if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { - fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); - return -1; - } - printf ("/\n"); - if (verbose > 1) { - /* Print a list of blocks. */ - print_inode_blocks (&inode, stdout); - if (verbose > 2) { - fs_inode_print (&inode, stdout); - printf ("--------\n"); - } - } - fs_directory_scan (&inode, "", scanner, (void*) stdout); - } - fs_close (&fs); - return 0; + /* Add or extract or info. */ + if (i >= argc) { + print_help (argv[0]); + return -1; + } + if (! fs_open (&fs, argv[i], (add + mount != 0))) { + fprintf (stderr, "%s: cannot open\n", argv[i]); + return -1; + } + + if (extract) { + /* Extract all files to current directory. */ + if (i != argc-1) { + print_help (argv[0]); + return -1; + } + if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { + fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); + return -1; + } + fs_directory_scan (&inode, "", extractor, (void*) stdout); + fs_close (&fs); + return 0; + } + + if (add) { + /* Add files i+1..argc-1 to filesystem. */ + if (i >= argc) { + print_help (argv[0]); + return -1; + } + while (++i < argc) + add_object (&fs, argv[i]); + fs_sync (&fs, 0); + fs_close (&fs); + return 0; + } + + if (mount) { + /* Mount the filesystem. */ + if (i != argc-2) { + print_help (argv[0]); + return -1; + } + return fs_mount(&fs, argv[i+1]); + } + + /* Print the structure of flesystem. */ + if (i != argc-1) { + print_help (argv[0]); + return -1; + } + fs_print (&fs, stdout); + if (verbose) { + printf ("--------\n"); + if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { + fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); + return -1; + } + printf ("/\n"); + if (verbose > 1) { + /* Print a list of blocks. */ + print_inode_blocks (&inode, stdout); + if (verbose > 2) { + fs_inode_print (&inode, stdout); + printf ("--------\n"); + } + } + fs_directory_scan (&inode, "", scanner, (void*) stdout); + } + fs_close (&fs); + return 0; } diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index da70cf5..38bdc22 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include @@ -18,53 +32,53 @@ extern int verbose; int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum) { - unsigned long offset; - int i, reserved; + unsigned long offset; + int i, reserved; - memset (inode, 0, sizeof (*inode)); - inode->fs = fs; - inode->number = inum; + memset (inode, 0, sizeof (*inode)); + inode->fs = fs; + inode->number = inum; - /* Inodes are numbered starting from 1. - * 64 bytes per inode, 16 inodes per block. - * Skip first block. */ - if (inum == 0 || inum > (fs->isize-1) * BSDFS_INODES_PER_BLOCK) - return 0; - offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * - BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; + /* Inodes are numbered starting from 1. + * 64 bytes per inode, 16 inodes per block. + * Skip first block. */ + if (inum == 0 || inum > (fs->isize-1) * BSDFS_INODES_PER_BLOCK) + return 0; + offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * + BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; - if (! fs_seek (fs, offset)) - return 0; + if (! fs_seek (fs, offset)) + return 0; - if (! fs_read16 (fs, &inode->mode)) /* file type and access mode */ - return 0; - if (! fs_read16 (fs, &inode->nlink)) /* directory entries */ - return 0; - if (! fs_read32 (fs, &inode->uid)) /* owner */ - return 0; - if (! fs_read32 (fs, &inode->gid)) /* group */ - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->size)) /* size */ - return 0; + if (! fs_read16 (fs, &inode->mode)) /* file type and access mode */ + return 0; + if (! fs_read16 (fs, &inode->nlink)) /* directory entries */ + return 0; + if (! fs_read32 (fs, &inode->uid)) /* owner */ + return 0; + if (! fs_read32 (fs, &inode->gid)) /* group */ + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->size)) /* size */ + return 0; - for (i=0; iaddr[i])) - return 0; - } - if (! fs_read32 (fs, (unsigned*) &reserved)) - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->flags)) - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->atime)) - return 0; /* last access time */ - if (! fs_read32 (fs, (unsigned*) &inode->mtime)) - return 0; /* last modification time */ - if (! fs_read32 (fs, (unsigned*) &inode->ctime)) - return 0; /* creation time */ + for (i=0; iaddr[i])) + return 0; + } + if (! fs_read32 (fs, (unsigned*) &reserved)) + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->flags)) + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->atime)) + return 0; /* last access time */ + if (! fs_read32 (fs, (unsigned*) &inode->mtime)) + return 0; /* last modification time */ + if (! fs_read32 (fs, (unsigned*) &inode->ctime)) + return 0; /* creation time */ /*if (inode->mode) { fs_inode_print (inode, stdout); printf ("---\n"); }*/ - if (verbose > 3) - printf ("get inode %u\n", inode->number); - return 1; + if (verbose > 3) + printf ("get inode %u\n", inode->number); + return 1; } /* @@ -76,179 +90,189 @@ int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum) * a contiguous free list much longer * than FIFO. */ -void fs_inode_truncate (fs_inode_t *inode) +void fs_inode_truncate (fs_inode_t *inode, unsigned long size) { - unsigned *blk; + int i, nblk; + unsigned *blk; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) - return; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) + return; -#define SINGLE 4 /* index of single indirect block */ -#define DOUBLE 5 /* index of double indirect block */ -#define TRIPLE 6 /* index of triple indirect block */ +#define SINGLE NDADDR /* index of single indirect block */ +#define DOUBLE (SINGLE+1) /* index of double indirect block */ +#define TRIPLE (DOUBLE+1) /* index of triple indirect block */ - for (blk = &inode->addr[TRIPLE]; blk >= &inode->addr[0]; --blk) { - if (*blk == 0) - continue; + nblk = (size + BSDFS_BSIZE - 1) / BSDFS_BSIZE; + for (i=TRIPLE; i>=0; --i) { + blk = &inode->addr[i]; + if (*blk == 0) + continue; - if (blk == &inode->addr [TRIPLE]) - fs_triple_indirect_block_free (inode->fs, *blk); - else if (blk == &inode->addr [DOUBLE]) - fs_double_indirect_block_free (inode->fs, *blk); - else if (blk == &inode->addr [SINGLE]) - fs_indirect_block_free (inode->fs, *blk); - else - fs_block_free (inode->fs, *blk); + if (i == TRIPLE) { + if (! fs_triple_indirect_block_free (inode->fs, *blk, + nblk - (NDADDR + BSDFS_BSIZE/4 + BSDFS_BSIZE/4*BSDFS_BSIZE/4))) + break; + } else if (i == DOUBLE) { + if (! fs_double_indirect_block_free (inode->fs, *blk, + nblk - (NDADDR + BSDFS_BSIZE/4))) + break; + } else if (i == SINGLE) { + if (! fs_indirect_block_free (inode->fs, *blk, nblk - NDADDR)) + break; + } else { + if (i * BSDFS_BSIZE < size) + break; + fs_block_free (inode->fs, *blk); + } - *blk = 0; - } + *blk = 0; + } - inode->size = 0; - inode->dirty = 1; + inode->size = size; + inode->dirty = 1; } void fs_inode_clear (fs_inode_t *inode) { - inode->dirty = 1; - inode->mode = 0; - inode->nlink = 0; - inode->uid = 0; - inode->size = 0; - memset (inode->addr, 0, sizeof(inode->addr)); - inode->atime = 0; - inode->mtime = 0; + inode->dirty = 1; + inode->mode = 0; + inode->nlink = 0; + inode->uid = 0; + inode->size = 0; + memset (inode->addr, 0, sizeof(inode->addr)); + inode->atime = 0; + inode->mtime = 0; } int fs_inode_save (fs_inode_t *inode, int force) { - unsigned long offset; - int i; + unsigned long offset; + int i; - if (! inode->fs->writable) - return 0; - if (! force && ! inode->dirty) - return 1; - if (inode->number == 0 || - inode->number > (inode->fs->isize-1) * BSDFS_INODES_PER_BLOCK) - return 0; - offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * - BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; + if (! inode->fs->writable) + return 0; + if (! force && ! inode->dirty) + return 1; + if (inode->number == 0 || + inode->number > (inode->fs->isize-1) * BSDFS_INODES_PER_BLOCK) + return 0; + offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * + BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; - time (&inode->atime); - //time (&inode->mtime); + time (&inode->atime); - if (! fs_seek (inode->fs, offset)) - return 0; + if (! fs_seek (inode->fs, offset)) + return 0; - if (! fs_write16 (inode->fs, inode->mode)) /* file type and access mode */ - return 0; - if (! fs_write16 (inode->fs, inode->nlink)) /* directory entries */ - return 0; - if (! fs_write32 (inode->fs, inode->uid)) /* owner */ - return 0; - if (! fs_write32 (inode->fs, inode->gid)) /* group */ - return 0; - if (! fs_write32 (inode->fs, inode->size)) /* size */ - return 0; + if (! fs_write16 (inode->fs, inode->mode)) /* file type and access mode */ + return 0; + if (! fs_write16 (inode->fs, inode->nlink)) /* directory entries */ + return 0; + if (! fs_write32 (inode->fs, inode->uid)) /* owner */ + return 0; + if (! fs_write32 (inode->fs, inode->gid)) /* group */ + return 0; + if (! fs_write32 (inode->fs, inode->size)) /* size */ + return 0; - for (i=0; ifs, inode->addr[i])) - return 0; - } - if (! fs_write32 (inode->fs, 0)) /* reserved */ - return 0; - if (! fs_write32 (inode->fs, inode->flags)) /* flags */ - return 0; - if (! fs_write32 (inode->fs, inode->atime)) /* last access time */ - return 0; - if (! fs_write32 (inode->fs, inode->mtime)) /* last modification time */ - return 0; - if (! fs_write32 (inode->fs, inode->ctime)) /* creation time */ - return 0; + for (i=0; ifs, inode->addr[i])) + return 0; + } + if (! fs_write32 (inode->fs, 0)) /* reserved */ + return 0; + if (! fs_write32 (inode->fs, inode->flags)) /* flags */ + return 0; + if (! fs_write32 (inode->fs, inode->atime)) /* last access time */ + return 0; + if (! fs_write32 (inode->fs, inode->mtime)) /* last modification time */ + return 0; + if (! fs_write32 (inode->fs, inode->ctime)) /* creation time */ + return 0; - inode->dirty = 0; - if (verbose > 3) - printf ("save inode %u\n", inode->number); - return 1; + inode->dirty = 0; + if (verbose > 3) + printf ("save inode %u\n", inode->number); + return 1; } void fs_inode_print (fs_inode_t *inode, FILE *out) { - int i; + int i; - fprintf (out, " I-node: %u\n", inode->number); - fprintf (out, " Type: %s\n", - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR ? "Directory" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ? "Character device" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK ? "Block device" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FREG ? "File" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FLNK ? "Symbolic link" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FSOCK? "Socket" : - "Unknown"); - fprintf (out, " Size: %lu bytes\n", inode->size); - fprintf (out, " Mode: %#o\n", inode->mode); + fprintf (out, " I-node: %u\n", inode->number); + fprintf (out, " Type: %s\n", + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR ? "Directory" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ? "Character device" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK ? "Block device" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FREG ? "File" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FLNK ? "Symbolic link" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FSOCK? "Socket" : + "Unknown"); + fprintf (out, " Size: %lu bytes\n", inode->size); + fprintf (out, " Mode: %#o\n", inode->mode); - fprintf (out, " "); - if (inode->mode & INODE_MODE_SUID) fprintf (out, " SUID"); - if (inode->mode & INODE_MODE_SGID) fprintf (out, " SGID"); - if (inode->mode & INODE_MODE_SVTX) fprintf (out, " SVTX"); - if (inode->mode & INODE_MODE_READ) fprintf (out, " READ"); - if (inode->mode & INODE_MODE_WRITE) fprintf (out, " WRITE"); - if (inode->mode & INODE_MODE_EXEC) fprintf (out, " EXEC"); - fprintf (out, "\n"); + fprintf (out, " "); + if (inode->mode & INODE_MODE_SUID) fprintf (out, " SUID"); + if (inode->mode & INODE_MODE_SGID) fprintf (out, " SGID"); + if (inode->mode & INODE_MODE_SVTX) fprintf (out, " SVTX"); + if (inode->mode & INODE_MODE_READ) fprintf (out, " READ"); + if (inode->mode & INODE_MODE_WRITE) fprintf (out, " WRITE"); + if (inode->mode & INODE_MODE_EXEC) fprintf (out, " EXEC"); + fprintf (out, "\n"); - fprintf (out, " Links: %u\n", inode->nlink); - fprintf (out, " Owner id: %u\n", inode->uid); + fprintf (out, " Links: %u\n", inode->nlink); + fprintf (out, " Owner id: %u\n", inode->uid); - fprintf (out, " Blocks:"); - for (i=0; iaddr[i]); - } - fprintf (out, "\n"); + fprintf (out, " Blocks:"); + for (i=0; iaddr[i]); + } + fprintf (out, "\n"); - fprintf (out, " Created: %s", ctime (&inode->ctime)); - fprintf (out, " Modified: %s", ctime (&inode->mtime)); - fprintf (out, "Last access: %s", ctime (&inode->atime)); + fprintf (out, " Created: %s", ctime (&inode->ctime)); + fprintf (out, " Modified: %s", ctime (&inode->mtime)); + fprintf (out, "Last access: %s", ctime (&inode->atime)); } void fs_directory_scan (fs_inode_t *dir, char *dirname, - fs_directory_scanner_t scanner, void *arg) + fs_directory_scanner_t scanner, void *arg) { - fs_inode_t file; - unsigned long offset; - unsigned char name [BSDFS_BSIZE - 12]; - struct { - unsigned int inum; - unsigned short reclen; - unsigned short namlen; - } dirent; + fs_inode_t file; + unsigned long offset; + unsigned char name [BSDFS_BSIZE - 12]; + struct { + unsigned int inum; + unsigned short reclen; + unsigned short namlen; + } dirent; - /* Variable record per file */ - for (offset = 0; offset < dir->size; offset += dirent.reclen) { - if (! fs_inode_read (dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "%s: read error at offset %ld\n", - dirname[0] ? dirname : "/", offset); - return; - } + /* Variable record per file */ + for (offset = 0; offset < dir->size; offset += dirent.reclen) { + if (! fs_inode_read (dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "%s: read error at offset %ld\n", + dirname[0] ? dirname : "/", offset); + return; + } /*printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen);*/ - if (! fs_inode_read (dir, offset+sizeof(dirent), name, (dirent.namlen + 4) / 4 * 4)) { - fprintf (stderr, "%s: name read error at offset %ld\n", - dirname[0] ? dirname : "/", offset); - return; - } + if (! fs_inode_read (dir, offset+sizeof(dirent), name, (dirent.namlen + 4) / 4 * 4)) { + fprintf (stderr, "%s: name read error at offset %ld\n", + dirname[0] ? dirname : "/", offset); + return; + } /*printf ("scan offset %lu: name='%s'\n", offset, name);*/ - if (dirent.inum == 0 || (name[0]=='.' && name[1]==0) || - (name[0]=='.' && name[1]=='.' && name[2]==0)) - continue; + if (dirent.inum == 0 || (name[0]=='.' && name[1]==0) || + (name[0]=='.' && name[1]=='.' && name[2]==0)) + continue; - if (! fs_inode_get (dir->fs, &file, dirent.inum)) { - fprintf (stderr, "cannot scan inode %d\n", dirent.inum); - continue; - } - scanner (dir, &file, dirname, (char*) name, arg); - } + if (! fs_inode_get (dir->fs, &file, dirent.inum)) { + fprintf (stderr, "cannot scan inode %d\n", dirent.inum); + continue; + } + scanner (dir, &file, dirname, (char*) name, arg); + } } /* @@ -257,57 +281,57 @@ void fs_directory_scan (fs_inode_t *dir, char *dirname, */ static unsigned map_block (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int nb, i, j, sh; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int nb, i, j, sh; - /* - * Blocks 0..NADDR-4 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - return inode->addr [lbn]; - } + /* + * Blocks 0..NADDR-4 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + return inode->addr [lbn]; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - sh = 0; - nb = 1; - lbn -= NADDR-3; - for (j=3; ; j--) { - if (j == 0) - return 0; - sh += NSHIFT; - nb <<= NSHIFT; - if (lbn < nb) - break; - lbn -= nb; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + sh = 0; + nb = 1; + lbn -= NADDR-3; + for (j=3; ; j--) { + if (j == 0) + return 0; + sh += NSHIFT; + nb <<= NSHIFT; + if (lbn < nb) + break; + lbn -= nb; + } - /* - * Fetch the first indirect block. - */ - nb = inode->addr [NADDR-j]; - if (nb == 0) - return 0; + /* + * Fetch the first indirect block. + */ + nb = inode->addr [NADDR-j]; + if (nb == 0) + return 0; - /* - * Fetch through the indirect blocks. - */ - for(; j <= 3; j++) { - if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) - return 0; + /* + * Fetch through the indirect blocks. + */ + for(; j <= 3; j++) { + if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) + return 0; - sh -= NSHIFT; - i = (lbn >> sh) & NMASK; - nb = block [i]; - if (nb == 0) - return 0; - } - return nb; + sh -= NSHIFT; + i = (lbn >> sh) & NMASK; + nb = block [i]; + if (nb == 0) + return 0; + } + return nb; } /* @@ -317,161 +341,163 @@ static unsigned map_block (fs_inode_t *inode, unsigned lbn) */ static unsigned map_block_write (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int nb, newb, sh, i, j; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int nb, newb, sh, i, j; - /* - * Blocks 0..NADDR-3 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - nb = inode->addr [lbn]; - if (nb != 0) { - if (verbose) - printf ("map logical block %d to physical %d\n", lbn, nb); - return nb; - } + /* + * Blocks 0..NADDR-3 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + nb = inode->addr [lbn]; + if (nb != 0) { + if (verbose) + printf ("map logical block %d to physical %d\n", lbn, nb); + return nb; + } - /* allocate new block */ - if (! fs_block_alloc (inode->fs, &nb)) - return 0; - inode->addr[lbn] = nb; - inode->dirty = 1; - return nb; - } + /* allocate new block */ + if (! fs_block_alloc (inode->fs, &nb)) + return 0; + inode->addr[lbn] = nb; + inode->dirty = 1; + return nb; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - sh = 0; - nb = 1; - lbn -= NADDR-3; - for (j=3; ; j--) { - if (j == 0) - return 0; - sh += NSHIFT; - nb <<= NSHIFT; - if (lbn < nb) - break; - lbn -= nb; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + sh = 0; + nb = 1; + lbn -= NADDR-3; + for (j=3; ; j--) { + if (j == 0) + return 0; + sh += NSHIFT; + nb <<= NSHIFT; + if (lbn < nb) + break; + lbn -= nb; + } - /* - * Fetch the first indirect block. - */ - nb = inode->addr [NADDR-j]; - if (nb == 0) { - if (! fs_block_alloc (inode->fs, &nb)) - return 0; - if (verbose) - printf ("inode %d: allocate new block %d\n", inode->number, nb); - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) - return 0; - inode->addr [NADDR-j] = nb; - inode->dirty = 1; - } + /* + * Fetch the first indirect block. + */ + nb = inode->addr [NADDR-j]; + if (nb == 0) { + if (! fs_block_alloc (inode->fs, &nb)) + return 0; + if (verbose) + printf ("inode %d: allocate new block %d\n", inode->number, nb); + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) + return 0; + inode->addr [NADDR-j] = nb; + inode->dirty = 1; + } - /* - * Fetch through the indirect blocks - */ - for(; j <= 3; j++) { - if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) - return 0; + /* + * Fetch through the indirect blocks + */ + for(; j <= 3; j++) { + if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) + return 0; - sh -= NSHIFT; - i = (lbn >> sh) & NMASK; - if (block [i] != 0) - nb = block [i]; - else { - /* Allocate new block. */ - if (! fs_block_alloc (inode->fs, &newb)) - return 0; - if (verbose) - printf ("inode %d: allocate new block %d\n", inode->number, newb); - block[i] = newb; - if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) - return 0; - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) - return 0; - nb = newb; - } - } - return nb; + sh -= NSHIFT; + i = (lbn >> sh) & NMASK; + if (block [i] != 0) + nb = block [i]; + else { + /* Allocate new block. */ + if (! fs_block_alloc (inode->fs, &newb)) + return 0; + if (verbose) + printf ("inode %d: allocate new block %d\n", inode->number, newb); + block[i] = newb; + if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) + return 0; + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) + return 0; + nb = newb; + } + } + return nb; } int fs_inode_read (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes) + unsigned char *data, unsigned long bytes) { - unsigned char block [BSDFS_BSIZE]; - unsigned long n; - unsigned int bn, inblock_offset; + unsigned char block [BSDFS_BSIZE]; + unsigned long n; + unsigned int bn, inblock_offset; - if (bytes + offset > inode->size) - return 0; - while (bytes != 0) { - inblock_offset = offset % BSDFS_BSIZE; - n = BSDFS_BSIZE - inblock_offset; - if (n > bytes) - n = bytes; + if (bytes + offset > inode->size) + return 0; + while (bytes != 0) { + inblock_offset = offset % BSDFS_BSIZE; + n = BSDFS_BSIZE - inblock_offset; + if (n > bytes) + n = bytes; - bn = map_block (inode, offset / BSDFS_BSIZE); - if (bn == 0) - return 0; + bn = map_block (inode, offset / BSDFS_BSIZE); + if (bn == 0) + return 0; - if (! fs_read_block (inode->fs, bn, block)) - return 0; - memcpy (data, block + inblock_offset, n); - offset += n; - bytes -= n; - } - return 1; + if (! fs_read_block (inode->fs, bn, block)) + return 0; + memcpy (data, block + inblock_offset, n); + data += n; + offset += n; + bytes -= n; + } + return 1; } int fs_inode_write (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes) + unsigned char *data, unsigned long bytes) { - unsigned char block [BSDFS_BSIZE]; - unsigned long n; - unsigned int bn, inblock_offset; + unsigned char block [BSDFS_BSIZE]; + unsigned long n; + unsigned int bn, inblock_offset; - time (&inode->mtime); - while (bytes != 0) { - inblock_offset = offset % BSDFS_BSIZE; - n = BSDFS_BSIZE - inblock_offset; - if (n > bytes) - n = bytes; + time (&inode->mtime); + while (bytes != 0) { + inblock_offset = offset % BSDFS_BSIZE; + n = BSDFS_BSIZE - inblock_offset; + if (n > bytes) + n = bytes; - bn = map_block_write (inode, offset / BSDFS_BSIZE); - if (bn == 0) - return 0; - if (inode->size < offset + n) { - /* Increase file size. */ - inode->size = offset + n; - inode->dirty = 1; - } - if (verbose) - printf ("inode %d offset %ld: write %ld bytes to block %d\n", - inode->number, offset, n, bn); + bn = map_block_write (inode, offset / BSDFS_BSIZE); + if (bn == 0) + return 0; + if (inode->size < offset + n) { + /* Increase file size. */ + inode->size = offset + n; + inode->dirty = 1; + } + if (verbose) + printf ("inode %d offset %ld: write %ld bytes to block %d\n", + inode->number, offset, n, bn); - if (n == BSDFS_BSIZE) { - if (! fs_write_block (inode->fs, bn, data)) - return 0; - } else { - if (! fs_read_block (inode->fs, bn, block)) - return 0; - memcpy (block + inblock_offset, data, n); - if (! fs_write_block (inode->fs, bn, block)) - return 0; - } - offset += n; - bytes -= n; - } - return 1; + if (n == BSDFS_BSIZE) { + if (! fs_write_block (inode->fs, bn, data)) + return 0; + } else { + if (! fs_read_block (inode->fs, bn, block)) + return 0; + memcpy (block + inblock_offset, data, n); + if (! fs_write_block (inode->fs, bn, block)) + return 0; + } + data += n; + offset += n; + bytes -= n; + } + return 1; } /* @@ -479,20 +505,20 @@ int fs_inode_write (fs_inode_t *inode, unsigned long offset, */ void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent) { - int i; + int i; - *data++ = dirent->ino; - *data++ = dirent->ino >> 8; - *data++ = dirent->ino >> 16; - *data++ = dirent->ino >> 24; - *data++ = dirent->reclen; - *data++ = dirent->reclen >> 8; - *data++ = dirent->namlen; - *data++ = dirent->namlen >> 8; - for (i=0; dirent->name[i]; ++i) - *data++ = dirent->name[i]; - for (; i & 3; ++i) - *data++ = 0; + *data++ = dirent->ino; + *data++ = dirent->ino >> 8; + *data++ = dirent->ino >> 16; + *data++ = dirent->ino >> 24; + *data++ = dirent->reclen; + *data++ = dirent->reclen >> 8; + *data++ = dirent->namlen; + *data++ = dirent->namlen >> 8; + for (i=0; dirent->name[i]; ++i) + *data++ = dirent->name[i]; + for (; i & 3; ++i) + *data++ = 0; } /* @@ -500,16 +526,16 @@ void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent) */ void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data) { - dirent->ino = *data++; - dirent->ino |= *data++ << 8; - dirent->ino |= *data++ << 16; - dirent->ino |= *data++ << 24; - dirent->reclen = *data++; - dirent->reclen |= *data++ << 8; - dirent->namlen = *data++; - dirent->namlen |= *data++ << 8; - memset (dirent->name, 0, sizeof (dirent->name)); - memcpy (dirent->name, data, dirent->namlen); + dirent->ino = *data++; + dirent->ino |= *data++ << 8; + dirent->ino |= *data++ << 16; + dirent->ino |= *data++ << 24; + dirent->reclen = *data++; + dirent->reclen |= *data++ << 8; + dirent->namlen = *data++; + dirent->namlen |= *data++ << 8; + memset (dirent->name, 0, sizeof (dirent->name)); + memcpy (dirent->name, data, dirent->namlen); } /* @@ -517,281 +543,276 @@ void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data) * an inode. Note that the inode is locked. * * op = 0 if name is saught - * 1 if name is to be created, mode is given - * 2 if name is to be deleted - * 3 if name is to be linked, mode contains inode number + * 1 if name is to be created, mode is given + * 2 if name is to be deleted + * 3 if name is to be linked, mode contains inode number * * Return 0 on any error. * Return 1 when the inode was found. * Return 2 when the inode was created/deleted/linked. */ -#define LOOKUP 0 /* perform name lookup only */ -#define CREATE 1 /* setup for file creation */ -#define DELETE 2 /* setup for file deletion */ -#define LINK 3 /* setup for link */ - -int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, char *name, - int op, int mode) +int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, + fs_op_t op, int mode) { - fs_inode_t dir; - int c, namlen, reclen; - char *namptr; - unsigned long offset, last_offset; - struct { + fs_inode_t dir; + int c, namlen, reclen; + const char *namptr; + unsigned long offset, last_offset; + struct { + unsigned int inum; + unsigned short reclen; + unsigned short namlen; + } dirent; + + /* Start from root. */ + if (! fs_inode_get (fs, &dir, BSDFS_ROOT_INODE)) { + fprintf (stderr, "inode_open(): cannot get root\n"); + return 0; + } + c = *name++; + while (c == '/') + c = *name++; + if (! c && op != INODE_OP_LOOKUP) { + /* Cannot write or delete root directory. */ + return 0; + } +cloop: + /* Here inode contains pointer + * to last component matched. */ + if (! c) { + *inode = dir; + return 1; + } + + /* If there is another component, + * inode must be a directory. */ + if ((dir.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { + return 0; + } + + /* Gather up dir name into buffer. */ + namptr = name - 1; + while (c && c != '/') { + c = *name++; + } + namlen = name - namptr - 1; + while (c == '/') + c = *name++; + + /* Search a directory, variable record per file */ + if (verbose > 2) + printf ("scan for '%.*s', %d bytes\n", namlen, namptr, namlen); + last_offset = 0; + for (offset = 0; offset < dir.size; last_offset = offset, offset += dirent.reclen) { + unsigned char fname [BSDFS_BSIZE - 12]; + + if (! fs_inode_read (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: read error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen); + if (dirent.inum == 0 || dirent.namlen != namlen) + continue; + if (! fs_inode_read (&dir, offset+sizeof(dirent), fname, namlen)) { + fprintf (stderr, "inode %d: name read error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("scan offset %lu: name='%.*s'\n", offset, namlen, fname); + if (strncmp (namptr, (char*) fname, namlen) == 0) { + /* Here a component matched in a directory. + * If there is more pathname, go back to + * cloop, otherwise return. */ + if (op == INODE_OP_DELETE && ! c) { + goto delete_file; + } + if (! fs_inode_get (fs, &dir, dirent.inum)) { + fprintf (stderr, "inode_open(): cannot get inode %d\n", dirent.inum); + return 0; + } + goto cloop; + } + } + /* If at the end of the directory, the search failed. + * Report what is appropriate as per flag. */ + if (op == INODE_OP_CREATE && ! c) + goto create_file; + if (op == INODE_OP_LINK && ! c) + goto create_link; + return 0; + + /* + * Make a new file, and return it's inode. + */ +create_file: + if (! fs_inode_alloc (fs, inode)) { + fprintf (stderr, "%s: cannot allocate inode\n", namptr); + return 0; + } + inode->dirty = 1; + inode->mode = mode & (07777 | INODE_MODE_FMT); + if ((inode->mode & INODE_MODE_FMT) == 0) + inode->mode |= INODE_MODE_FREG; + inode->nlink = 1; + inode->uid = 0; + inode->flags = 0; + time (&inode->ctime); + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Make link '.' */ + struct { unsigned int inum; unsigned short reclen; unsigned short namlen; - } dirent; - - /* Start from root. */ - if (! fs_inode_get (fs, &dir, BSDFS_ROOT_INODE)) { - fprintf (stderr, "inode_open(): cannot get root\n"); - return 0; - } - c = *name++; - while (c == '/') - c = *name++; - if (! c && op != LOOKUP) { - /* Cannot write or delete root directory. */ - return 0; - } -cloop: - /* Here inode contains pointer - * to last component matched. */ - if (! c) { - *inode = dir; - return 1; - } - - /* If there is another component, - * inode must be a directory. */ - if ((dir.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { - return 0; - } - - /* Gather up dir name into buffer. */ - namptr = name - 1; - while (c && c != '/') { - c = *name++; - } - namlen = name - namptr - 1; - while (c == '/') - c = *name++; - - /* Search a directory, variable record per file */ - if (verbose > 2) - printf ("scan for '%.*s', %d bytes\n", namlen, namptr, namlen); - last_offset = 0; - for (offset = 0; offset < dir.size; last_offset = offset, offset += dirent.reclen) { - unsigned char fname [BSDFS_BSIZE - 12]; - - if (! fs_inode_read (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: read error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen); - if (dirent.inum == 0 || dirent.namlen != namlen) - continue; - if (! fs_inode_read (&dir, offset+sizeof(dirent), fname, namlen)) { - fprintf (stderr, "inode %d: name read error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("scan offset %lu: name='%.*s'\n", offset, namlen, fname); - if (strncmp (namptr, (char*) fname, namlen) == 0) { - /* Here a component matched in a directory. - * If there is more pathname, go back to - * cloop, otherwise return. */ - if (op == DELETE && ! c) { - goto delete_file; - } - if (! fs_inode_get (fs, &dir, dirent.inum)) { - fprintf (stderr, "inode_open(): cannot get inode %d\n", dirent.inum); - return 0; - } - goto cloop; - } - } - /* If at the end of the directory, the search failed. - * Report what is appropriate as per flag. */ - if (op == CREATE && ! c) - goto create_file; - if (op == LINK && ! c) - goto create_link; - return 0; - - /* - * Make a new file, and return it's inode. - */ -create_file: - if (! fs_inode_alloc (fs, inode)) { - fprintf (stderr, "%s: cannot allocate inode\n", name); - return 0; - } - inode->dirty = 1; - inode->mode = mode & (07777 | INODE_MODE_FMT); - if ((inode->mode & INODE_MODE_FMT) == 0) - inode->mode |= INODE_MODE_FREG; - inode->nlink = 1; - inode->uid = 0; - inode->flags = 0; - time (&inode->ctime); - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Make link '.' */ - struct { - unsigned int inum; - unsigned short reclen; - unsigned short namlen; - char name [4]; - } dotent; - dotent.inum = inode->number; - dotent.reclen = BSDFS_BSIZE; - dotent.namlen = 1; - memcpy (dotent.name, ".\0\0\0", 4); - if (! fs_inode_write (inode, 0, (unsigned char*) &dotent, sizeof(dotent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - inode->number, 0L); - return 0; - } - /* Increase file size. */ - inode->size = BSDFS_BSIZE; - ++inode->nlink; + char name [4]; + } dotent; + dotent.inum = inode->number; + dotent.reclen = BSDFS_BSIZE; + dotent.namlen = 1; + memcpy (dotent.name, ".\0\0\0", 4); + if (! fs_inode_write (inode, 0, (unsigned char*) &dotent, sizeof(dotent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + inode->number, 0L); + return 0; } - if (! fs_inode_save (inode, 0)) { - fprintf (stderr, "%s: cannot save file inode\n", name); - return 0; - } + /* Increase file size. */ + inode->size = BSDFS_BSIZE; + ++inode->nlink; + } + if (! fs_inode_save (inode, 0)) { + fprintf (stderr, "%s: cannot save file inode\n", namptr); + return 0; + } - /* Write a directory entry. */ - if (verbose > 2) - printf ("*** create file '%.*s', inode %d\n", namlen, namptr, inode->number); - reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; - c = 8 + (namlen + 4) / 4 * 4; - if (reclen >= c) { - /* Enough space */ - dirent.reclen -= reclen; - if (verbose > 2) - printf ("*** previous entry %u-%u-%u at offset %lu\n", - dirent.inum, dirent.reclen, dirent.namlen, last_offset); - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - } else { - /* No space, extend directory. */ - if (verbose > 2) - printf ("*** extend dir, previous entry %u-%u-%u at offset %lu\n", - dirent.inum, dirent.reclen, dirent.namlen, last_offset); - reclen = BSDFS_BSIZE; - } - offset = last_offset + dirent.reclen; - dirent.inum = inode->number; - dirent.reclen = reclen; - dirent.namlen = namlen; - if (verbose > 2) - printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); - if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); - if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset+sizeof(dirent)); - return 0; - } - /* Align directory size. */ - dir.size = (dir.size + BSDFS_BSIZE - 1) / BSDFS_BSIZE * BSDFS_BSIZE; - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", name); - return 0; - } - return 2; - - /* - * Delete file. Return inode of deleted file. - */ -delete_file: - if (verbose > 2) - printf ("*** delete inode %d\n", dirent.inum); - if (! fs_inode_get (fs, inode, dirent.inum)) { - fprintf (stderr, "%s: cannot get inode %d\n", name, dirent.inum); - return 0; - } - inode->dirty = 1; - inode->nlink--; - if (inode->nlink <= 0) { - fs_inode_truncate (inode); - fs_inode_clear (inode); - if (inode->fs->ninode < NICINOD) { - inode->fs->inode [inode->fs->ninode++] = dirent.inum; - inode->fs->dirty = 1; - } - } - /* Extend previous entry to cover the empty space. */ - reclen = dirent.reclen; - if (! fs_inode_read (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: read error at offset %ld\n", - dir.number, last_offset); - return 0; - } - dirent.reclen += reclen; - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", name); - return 0; - } - return 2; - - /* - * Make a link. Return a directory inode. - */ -create_link: - if (verbose > 2) - printf ("*** link inode %d to '%.*s', directory %d\n", mode, namlen, namptr, dir.number); - reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + /* Write a directory entry. */ + if (verbose > 2) + printf ("*** create file '%.*s', inode %d\n", namlen, namptr, inode->number); + reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + c = 8 + (namlen + 4) / 4 * 4; + if (reclen >= c) { + /* Enough space */ dirent.reclen -= reclen; if (verbose > 2) - printf ("*** previous entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, last_offset); - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - offset = last_offset + dirent.reclen; - dirent.inum = mode; - dirent.reclen = reclen; - dirent.namlen = namlen; + printf ("*** previous entry %u-%u-%u at offset %lu\n", + dirent.inum, dirent.reclen, dirent.namlen, last_offset); + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + } else { + /* No space, extend directory. */ if (verbose > 2) - printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); - if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); - if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset+sizeof(dirent)); - return 0; - } - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", name); - return 0; - } - *inode = dir; - return 2; + printf ("*** extend dir, previous entry %u-%u-%u at offset %lu\n", + dirent.inum, dirent.reclen, dirent.namlen, last_offset); + reclen = BSDFS_BSIZE; + } + offset = last_offset + dirent.reclen; + dirent.inum = inode->number; + dirent.reclen = reclen; + dirent.namlen = namlen; + if (verbose > 2) + printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); + if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); + if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset+sizeof(dirent)); + return 0; + } + /* Align directory size. */ + dir.size = (dir.size + BSDFS_BSIZE - 1) / BSDFS_BSIZE * BSDFS_BSIZE; + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + return 2; + + /* + * Delete file. Return inode of deleted file. + */ +delete_file: + if (verbose > 2) + printf ("*** delete inode %d\n", dirent.inum); + if (! fs_inode_get (fs, inode, dirent.inum)) { + fprintf (stderr, "%s: cannot get inode %d\n", namptr, dirent.inum); + return 0; + } + inode->dirty = 1; + inode->nlink--; + if (inode->nlink <= 0) { + fs_inode_truncate (inode, 0); + fs_inode_clear (inode); + if (inode->fs->ninode < NICINOD) { + inode->fs->inode [inode->fs->ninode++] = dirent.inum; + inode->fs->dirty = 1; + } + } + /* Extend previous entry to cover the empty space. */ + reclen = dirent.reclen; + if (! fs_inode_read (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: read error at offset %ld\n", + dir.number, last_offset); + return 0; + } + dirent.reclen += reclen; + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + return 2; + + /* + * Make a link. Return a directory inode. + */ +create_link: + if (verbose > 2) + printf ("*** link inode %d to '%.*s', directory %d\n", mode, namlen, namptr, dir.number); + reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + dirent.reclen -= reclen; + if (verbose > 2) + printf ("*** previous entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, last_offset); + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + offset = last_offset + dirent.reclen; + dirent.inum = mode; + dirent.reclen = reclen; + dirent.namlen = namlen; + if (verbose > 2) + printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); + if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); + if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset+sizeof(dirent)); + return 0; + } + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + *inode = dir; + return 2; } /* @@ -803,30 +824,71 @@ create_link: */ int fs_inode_alloc (fs_t *fs, fs_inode_t *inode) { - int ino; + int ino; - for (;;) { - if (fs->ninode <= 0) { - /* Build a list of free inodes. */ - if (! inode_build_list (fs)) { - fprintf (stderr, "inode_alloc: cannot build inode list\n"); - return 0; - } - if (fs->ninode <= 0) { - fprintf (stderr, "inode_alloc: out of in-core inodes\n"); - return 0; - } - } - ino = fs->inode[--fs->ninode]; - fs->dirty = 1; - fs->tinode--; - if (! fs_inode_get (fs, inode, ino)) { - fprintf (stderr, "inode_alloc: cannot get inode %d\n", ino); - return 0; - } - if (inode->mode == 0) { - fs_inode_clear (inode); - return 1; - } - } + for (;;) { + if (fs->ninode <= 0) { + /* Build a list of free inodes. */ + if (! inode_build_list (fs)) { + fprintf (stderr, "inode_alloc: cannot build inode list\n"); + return 0; + } + if (fs->ninode <= 0) { + fprintf (stderr, "inode_alloc: out of in-core inodes\n"); + return 0; + } + } + ino = fs->inode[--fs->ninode]; + fs->dirty = 1; + fs->tinode--; + if (! fs_inode_get (fs, inode, ino)) { + fprintf (stderr, "inode_alloc: cannot get inode %d\n", ino); + return 0; + } + if (inode->mode == 0) { + fs_inode_clear (inode); + return 1; + } + } +} + +/* + * Find inode by name. + * Return 0 on any error. + * Return 1 when the inode was found. + */ +int fs_inode_lookup (fs_t *fs, fs_inode_t *inode, const char *name) +{ + return fs_inode_by_name (fs, inode, name, INODE_OP_LOOKUP, 0); +} + +/* + * Create inode by name. + * Return 0 on any error. + * Return 1 when the inode was found. + * Return 2 when the inode was created. + */ +int fs_inode_create (fs_t *fs, fs_inode_t *inode, const char *name, int mode) +{ + return fs_inode_by_name (fs, inode, name, INODE_OP_CREATE, mode); +} + +/* + * Delete inode by name. + * Return 0 on any error. + * Return 2 when the inode was created. + */ +int fs_inode_delete (fs_t *fs, fs_inode_t *inode, const char *name) +{ + return fs_inode_by_name (fs, inode, name, INODE_OP_DELETE, 0); +} + +/* + * Create a new link for the inode. + * Return 0 on any error. + * Return 2 when the inode was linked. + */ +int fs_inode_link (fs_t *fs, fs_inode_t *inode, const char *name, int inum) +{ + return fs_inode_by_name (fs, inode, name, INODE_OP_LINK, inum); } diff --git a/tools/fsutil/manifest.c b/tools/fsutil/manifest.c new file mode 100644 index 0000000..da20ec2 --- /dev/null +++ b/tools/fsutil/manifest.c @@ -0,0 +1,523 @@ +/* + * Routines to handle manifest files. + * + * Copyright (C) 2014 Serge Vakulenko, + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include +#include +#include +#include +#include +#include +#include "bsdfs.h" +#include "manifest.h" + +/* + * Manifest entry. + */ +struct _entry_t { + entry_t *next; + int type; /* d, f, l, s, b or c */ + int mode; + int owner; + int group; + int major; + int minor; + char *link; /* Target for link or symlink */ + char path[1]; +}; + +/* + * Linked list of information for finding hard links. + */ +typedef struct _link_info_t link_info_t; +struct _link_info_t { + link_info_t *next; + dev_t dev; + ino_t ino; + char path[1]; +}; + +static link_info_t *link_list; /* List of hard links. */ + +/* + * Store information about the hard link: dev, inode and path. + */ +static void keep_link (dev_t dev, ino_t ino, char *path) +{ + link_info_t *info; + + info = (link_info_t*) malloc (strlen (path) + sizeof (link_info_t)); + if (! info) { + fprintf (stderr, "%s: no memory for link info\n", path); + return; + } + info->dev = dev; + info->ino = ino; + strcpy (info->path, path); + + /* Insert into the list. */ + info->next = link_list; + link_list = info; +} + +/* + * Find a hard link by dev and inode number. + * Return a path. + */ +static char *find_link (dev_t dev, ino_t ino) +{ + link_info_t *info = link_list; + + for (info=link_list; info; info=info->next) { + if (info->dev == dev && info->ino == ino) + return info->path; + } + return 0; +} + +/* + * Add new entry to the manifest. + */ +static void add_entry (manifest_t *m, int filetype, char *path, char *link, + int mode, int owner, int group, int majr, int minr) +{ + entry_t *e; + + e = malloc (sizeof(entry_t) + strlen (path)); + if (! e) { + fprintf (stderr, "%s: no memory for entry\n", path); + return; + } + + e->next = 0; + e->type = filetype; + e->mode = mode; + e->owner = owner; + e->group = group; + e->major = majr; + e->minor = minr; + e->link = 0; + e->link = link ? strdup (link) : 0; + strcpy (e->path, path); + + /* Append to the tail of the list. */ + if (m->first == 0) { + m->first = e; + } else { + m->last->next = e; + } + m->last = e; +} + +/* + * Compare two entries of file traverse scan. + */ +static int ftsent_compare (const FTSENT **a, const FTSENT **b) +{ + return strcmp((*a)->fts_name, (*b)->fts_name); +} + +/* + * Scan the directory and create a manifest from it's contents. + * Return 0 on error. + */ +int manifest_scan (manifest_t *m, const char *dirname) +{ + FTS *dir; + FTSENT *node; + char *argv[2], *path, *target, buf[BSDFS_BSIZE]; + struct stat st; + int prefix_len, mode, len; + + /* Clear manifest header. */ + m->first = 0; + m->last = 0; + m->filemode = 0664; + m->dirmode = 0775; + m->owner = 0; + m->group = 0; + + /* Open directory. */ + argv[0] = (char*) dirname; + argv[1] = 0; + dir = fts_open (argv, FTS_PHYSICAL | FTS_NOCHDIR, &ftsent_compare); + if (! dir) { + fprintf (stderr, "%s: cannot open\n", dirname); + return 0; + } + prefix_len = strlen (dirname); + + printf ("# Manifest for directory %s\n", dirname); + for (;;) { + /* Read next directory entry. */ + node = fts_read(dir); + if (! node) + break; + + path = node->fts_path + prefix_len; + if (path[0] == 0) + continue; + + st = *node->fts_statp; + mode = st.st_mode & 07777; + + switch (node->fts_info) { + case FTS_D: + /* Directory. */ + add_entry (m, 'd', path, 0, mode, st.st_uid, st.st_gid, 0, 0); + break; + + case FTS_F: + /* Regular file. */ + if (st.st_nlink > 1) { + /* Hard link to file. */ + target = find_link (st.st_dev, st.st_ino); + if (target) { + add_entry (m, 'l', path, target, mode, st.st_uid, st.st_gid, 0, 0); + break; + } + keep_link (st.st_dev, st.st_ino, path); + } + add_entry (m, 'f', path, 0, mode, st.st_uid, st.st_gid, 0, 0); + break; + + case FTS_SL: + /* Symlink. */ + if (st.st_nlink > 1) { + /* Hard link to symlink. */ + target = find_link (st.st_dev, st.st_ino); + if (target) { + add_entry (m, 'l', path, target, mode, st.st_uid, st.st_gid, 0, 0); + break; + } + keep_link (st.st_dev, st.st_ino, path); + } + /* Get the target of symlink. */ + len = readlink (node->fts_accpath, buf, sizeof(buf) - 1); + if (len < 0) { + fprintf (stderr, "%s: cannot read\n", node->fts_accpath); + break; + } + buf[len] = 0; + add_entry (m, 's', path, buf, mode, st.st_uid, st.st_gid, 0, 0); + break; + + default: + /* Ignore all other variants. */ + break; + } + } + fts_close (dir); + return 1; +} + +/* + * Dump the manifest to a text file. + */ +void manifest_print (manifest_t *m) +{ + void *cursor; + char *path, *link; + int filetype, mode, owner, group, major, minor; + + cursor = 0; + while ((filetype = manifest_iterate (m, &cursor, &path, &link, &mode, + &owner, &group, &major, &minor)) != 0) + { + switch (filetype) { + case 'd': + /* Directory. */ + printf ("\ndir %s\n", path); + break; + case 'f': + /* Regular file. */ + printf ("\nfile %s\n", path); + break; + case 'l': + /* Hard link to file. */ + printf ("\nlink %s\n", path); + printf ("target %s\n", link); + continue; + case 's': + /* Symlink. */ + printf ("\nsymlink %s\n", path); + printf ("target %s\n", link); + break; + case 'b': + /* Block device. */ + printf ("\nbdev %s\n", path); + printf ("major %u\n", major); + printf ("minor %u\n", minor); + break; + case 'c': + /* Character device. */ + printf ("\ncdev %s\n", path); + printf ("major %u\n", major); + printf ("minor %u\n", minor); + break; + default: + /* Ignore all other variants. */ + continue; + } + printf ("mode %#o\n", mode); + printf ("owner %u\n", owner); + printf ("group %u\n", group); + } +} + +/* + * Load a manifest from the text file. + * Return 0 on error. + */ +int manifest_load (manifest_t *m, const char *filename) +{ + FILE *fd; + char line [1024], *p, *cmd = 0, *arg = 0, *path = 0, *target = 0; + int type = 0, default_dirmode = 0775, default_filemode = 0664; + int default_owner = 0, default_group = 0; + int mode = -1, owner = -1, group = -1, majr = -1, minr = -1; + + /* Clear manifest header. */ + m->first = 0; + m->last = 0; + m->filemode = 0664; + m->dirmode = 0775; + m->owner = 0; + m->group = 0; + + /* Open file. */ + fd = fopen (filename, "r"); + if (! fd) { + perror (filename); + return 0; + } + + /* Parse the manifest file. */ + while (fgets (line, sizeof(line), fd)) { + /* Remove trailing spaces. */ + p = line + strlen(line); + while (p-- >line && (*p==' ' || *p == '\t' || *p == '\r' || *p == '\n')) + *p = 0; + + /* Remove spaces at line beginning. */ + p = line; + while (*p==' ' || *p == '\t' || *p == '\r' || *p == '\n') + ++p; + if (*p == 0) + continue; + + /* Skip comments. */ + if (*p == '#') + continue; + + /* Split into command and agrument. */ + cmd = p; + p = strchr (p, ' '); + if (p) { + *p = 0; + arg = p+1; + } else { + arg = ""; + } + + /* + * Process options. + */ + if (strcmp ("dirmode", cmd) == 0) { + if (type != 0) { +notdef: fprintf (stderr, "%s: command '%s' allowed only in default section\n", filename, cmd); + fclose (fd); + return 0; + } + default_dirmode = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("filemode", cmd) == 0) { + if (type != 0) + goto notdef; + default_filemode = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("owner", cmd) == 0) { + if (type != 0) + owner = strtoul (arg, 0, 0); + else + default_owner = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("group", cmd) == 0) { + if (type != 0) + group = strtoul (arg, 0, 0); + else + default_group = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("mode", cmd) == 0) { + if (type == 0) { +baddef: fprintf (stderr, "%s: command '%s' not allowed in default section\n", filename, cmd); + fclose (fd); + return 0; + } + mode = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("major", cmd) == 0) { + if (type == 0) + goto baddef; + majr = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("minor", cmd) == 0) { + if (type == 0) + goto baddef; + minr = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("target", cmd) == 0) { + if (type != 'l' && type != 's') { + fprintf (stderr, "%s: command '%s' allowed only for links\n", filename, cmd); + fclose (fd); + return 0; + } + target = strdup (arg); + continue; + } + + /* + * End of section: add new object. + */ + if (type != 0) { +newobj: /* Check parameters. */ + if ((type == 'l' || type == 's') && ! target) { + fprintf (stderr, "%s: target missing for link '%s'\n", filename, path); + fclose (fd); + return 0; + } + if ((type == 'b' || type == 'c') && majr == -1) { + fprintf (stderr, "%s: major index missing for device '%s'\n", filename, path); + fclose (fd); + return 0; + } + if ((type == 'b' || type == 'c') && minr == -1) { + fprintf (stderr, "%s: minor index missing for device '%s'\n", filename, path); + fclose (fd); + return 0; + } + if (mode == -1) + mode = (type == 'd') ? default_dirmode : default_filemode; + if (owner == -1) + owner = default_owner; + if (group == -1) + group = default_group; + + /* Create new object. */ + add_entry (m, type, path, target, mode, owner, group, majr, minr); + + /* Set parameters to defaults. */ + type = 0; + free (path); + path = 0; + if (target) { + free (target); + target = 0; + } + mode = -1; + owner = -1; + group = -1; + majr = -1; + minr = -1; + if (! fd) { + /* Last object done. */ + return 1; + } + } + + /* + * Start new section. + */ + if (strcmp ("default", cmd) == 0) { + type = 0; + } + else if (strcmp ("dir", cmd) == 0) { + type = 'd'; + path = strdup (arg); + } + else if (strcmp ("file", cmd) == 0) { + type = 'f'; + path = strdup (arg); + } + else if (strcmp ("link", cmd) == 0) { + type = 'l'; + path = strdup (arg); + } + else if (strcmp ("symlink", cmd) == 0) { + type = 's'; + path = strdup (arg); + } + else if (strcmp ("bdev", cmd) == 0) { + type = 'b'; + path = strdup (arg); + } + else if (strcmp ("cdev", cmd) == 0) { + type = 'c'; + path = strdup (arg); + } + else { + fprintf (stderr, "%s: unknown command '%s'\n", filename, cmd); + fclose (fd); + return 0; + } + } + + /* Done. */ + fclose (fd); + if (type != 0) { + /* Create last object. */ + fd = 0; + goto newobj; + } + return 1; +} + +/* + * Iterate through the manifest. + */ +int manifest_iterate (manifest_t *m, void **last, char **path, char **link, + int *mode, int *owner, int *group, int *major, int *minor) +{ + /* Get the next entry. */ + entry_t *e = *last ? ((entry_t*)*last)->next : m->first; + + if (! e) + return 0; + + /* Fetch information about this entry. */ + *last = (void*) e; /* Pointer to a last processed entry. */ + *path = e->path; + *link = e->link; + *mode = (e->mode != -1) ? e->mode : (e->type == 'd') ? m->dirmode : m->filemode; + *owner = (e->owner != -1) ? e->owner : m->owner; + *group = (e->group != -1) ? e->group : m->group; + *major = e->major; + *minor = e->minor; + return e->type; +} diff --git a/tools/fsutil/manifest.h b/tools/fsutil/manifest.h new file mode 100644 index 0000000..063c0bd --- /dev/null +++ b/tools/fsutil/manifest.h @@ -0,0 +1,81 @@ +/* + * Routines to handle manifest files. + * + * Copyright (C) 2014 Serge Vakulenko, + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ + +/* + * Manifest header holds a linked list of file entries. + */ +typedef struct _manifest_t manifest_t; +typedef struct _entry_t entry_t; +struct _manifest_t { + entry_t *first; + entry_t *last; + int filemode; /* Default mode for files */ + int dirmode; /* Default mode for directories */ + int owner; /* Default owner */ + int group; /* Default group */ +}; + +/* + * Manifest entry. + */ + +/* + * Scan the directory and create a manifest from it's contents. + * Return 0 on error. + */ +int manifest_scan (manifest_t *m, const char *dirname); + +/* + * Load a manifest from the text file. + * Return 0 on error. + */ +int manifest_load (manifest_t *m, const char *filename); + +/* + * Dump the manifest to a text file. + */ +void manifest_print (manifest_t *m); + +/* + * Iterate through the manifest. + * Example: + * void *cursor = 0; + * char *path, *link; + * int filetype, mode, owner, group, major, minor; + * + * while ((filetype = manifest_iterate (m, &cursor, &path, &link, + * &mode, &owner, &group, &major, &minor)) != 0) + * { + * switch (filetype) { + * case 'd': // directory + * case 'f': // regular file + * case 'l': // hard link + * case 's': // symlink + * case 'b': // block device + * case 'c': // char device + * } + * } + */ +int manifest_iterate (manifest_t *m, void **cursor, char **path, char **link, + int *mode, int *owner, int *group, int *major, int *minor); diff --git a/tools/fsutil/manifest.txt b/tools/fsutil/manifest.txt new file mode 100644 index 0000000..c0a8a4c --- /dev/null +++ b/tools/fsutil/manifest.txt @@ -0,0 +1,27 @@ +# +# Skeleton of manifest file. +# +default +owner 0 +group 0 +dirmode 0775 +filemode 0664 + +dir /tmp + +file /etc/passwd +mode 0444 + +link /etc/aliases +target mail/aliases + +symlink /var/tmp +target /tmp + +cdev /dev/tty +major 5 +minor 0 + +bdev /dev/sda +major 8 +minor 0 diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c new file mode 100644 index 0000000..489e84d --- /dev/null +++ b/tools/fsutil/mount.c @@ -0,0 +1,911 @@ +/* + * Mount 2.xBSD filesystem via FUSE interface. + * + * Copyright (C) 2014 Serge Vakulenko, + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include +#include +#include +#include +#include +#include + +#define FUSE_USE_VERSION 26 +#include + +#include "bsdfs.h" + +extern int verbose; + +/* + * Print a message to log file. + */ +static void printlog(const char *format, ...) +{ + va_list ap; + + if (verbose) { + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fflush(stderr); + } +} + +static dev_t make_rdev(unsigned raw) +{ + return makedev (raw >> 8, raw & 0xff); +} + +/* + * Copy data to struct stat. + */ +static int getstat (fs_inode_t *inode, struct stat *statbuf) +{ + statbuf->st_mode = inode->mode & 07777; /* protection */ + statbuf->st_ino = inode->number; /* inode number */ + statbuf->st_nlink = inode->nlink; /* number of hard links */ + statbuf->st_uid = inode->uid; /* user ID of owner */ + statbuf->st_gid = inode->gid; /* group ID of owner */ + statbuf->st_rdev = 0; /* device ID (if special file) */ + statbuf->st_size = inode->size; /* total size, in bytes */ + statbuf->st_blocks = inode->size >> 9; /* number of blocks allocated */ + statbuf->st_atime = inode->atime; /* time of last access */ + statbuf->st_mtime = inode->mtime; /* time of last modification */ + statbuf->st_ctime = inode->ctime; /* time of last status change */ + + switch (inode->mode & INODE_MODE_FMT) { /* type of file */ + case INODE_MODE_FREG: /* regular */ + statbuf->st_mode |= S_IFREG; + break; + case INODE_MODE_FDIR: /* directory */ + statbuf->st_mode |= S_IFDIR; + break; + case INODE_MODE_FCHR: /* character special */ + statbuf->st_mode |= S_IFCHR; + statbuf->st_rdev = make_rdev (inode->addr[1]); + break; + case INODE_MODE_FBLK: /* block special */ + statbuf->st_mode |= S_IFBLK; + statbuf->st_rdev = make_rdev (inode->addr[1]); + break; + case INODE_MODE_FLNK: /* symbolic link */ + statbuf->st_mode |= S_IFLNK; + break; + case INODE_MODE_FSOCK: /* socket */ + statbuf->st_mode |= S_IFSOCK; + break; + default: /* cannot happen */ + printlog("--- unknown file type %#x\n", inode->mode & INODE_MODE_FMT); + return -ENOENT; + } + return 0; +} + +/* + * Get file attributes. + */ +int op_getattr(const char *path, struct stat *statbuf) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", path, statbuf); + + if (! fs_inode_lookup (fs, &inode, path)) { + printlog("--- search failed\n"); + return -ENOENT; + } + return getstat (&inode, statbuf); +} + +/* + * Get attributes from an open file. + */ +int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi) +{ + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + + printlog("--- op_fgetattr(path=\"%s\", statbuf=%p, fi=%p)\n", + path, statbuf, fi); + + if (strcmp(path, "/") == 0) + return op_getattr(path, statbuf); + + if (! fh) + return -EBADF; + + return getstat (&fh->inode, statbuf); +} + +/* + * File open operation. + */ +int op_open(const char *path, struct fuse_file_info *fi) +{ + fs_t *fs = fuse_get_context()->private_data; + int write_flag = (fi->flags & O_ACCMODE) != O_RDONLY; + + printlog("--- op_open(path=\"%s\", fi=%p) flags=%#x \n", + path, fi, fi->flags); + + fs_file_t *fh = calloc (1, sizeof(fs_file_t)); + if (! fh) { + printlog("--- out of memory\n"); + return -ENOMEM; + } + + if (! fs_file_open (fs, fh, path, write_flag)) { + printlog("--- open failed\n"); + free (fh); + fi->fh = 0; + return -ENOENT; + } + + if ((fh->inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + /* Cannot open special files. */ + free (fh); + fi->fh = 0; + return -ENXIO; + } + + if (fi->flags & O_APPEND) { + fh->offset = fh->inode.size; + } + fi->fh = (intptr_t) fh; + return 0; +} + +/* + * Create and open a file. + */ +int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + fs_t *fs = fuse_get_context()->private_data; + + printlog("--- op_create(path=\"%s\", mode=0%03o, fi=%p)\n", + path, mode, fi); + + fs_file_t *fh = calloc (1, sizeof(fs_file_t)); + if (! fh) { + printlog("--- out of memory\n"); + return -ENOMEM; + } + + if (! fs_file_create (fs, fh, path, mode & 07777)) { + printlog("--- create failed\n"); + if ((fh->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + free (fh); + fi->fh = 0; + return -EISDIR; + } + free (fh); + fi->fh = 0; + return -EIO; + } + fh->inode.mtime = time(0); + fh->inode.dirty = 1; + fs_file_close (fh); + fi->fh = (intptr_t) fh; + return 0; +} + +/* + * Read data from an open file. + */ +int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) +{ + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + + printlog("--- op_read(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", + path, buf, size, offset, fi); + + if (offset >= fh->inode.size) + return 0; + + fh->offset = offset; + if (size > fh->inode.size - offset) + size = fh->inode.size - offset; + + if (! fs_file_read (fh, (unsigned char*) buf, size)) { + printlog("--- read failed\n"); + return -EIO; + } + printlog("--- read returned %u\n", size); + return size; +} + +/* + * Write data to an open file. + */ +int op_write(const char *path, const char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + + printlog("--- op_write(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", + path, buf, size, offset, fi); + + fh->offset = offset; + if (! fs_file_write (fh, (unsigned char*) buf, size)) { + printlog("--- read failed\n"); + return -EIO; + } + fh->inode.mtime = time(0); + fh->inode.dirty = 1; + return size; +} + +/* + * Release an open file. + */ +int op_release(const char *path, struct fuse_file_info *fi) +{ + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + + printlog("--- op_release(path=\"%s\", fi=%p)\n", path, fi); + + if (! fh) + return -EBADF; + + fs_file_close (fh); + free (fh); + fi->fh = 0; + return 0; +} + +/* + * Change the size of a file + */ +int op_truncate(const char *path, off_t newsize) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_file_t f; + + printlog("--- op_truncate(path=\"%s\", newsize=%lld)\n", path, newsize); + + if (! fs_file_open (fs, &f, path, 1)) { + printlog("--- open failed\n"); + return -ENOENT; + } + + if ((f.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + /* Cannot truncate special files. */ + return -EINVAL; + } + fs_inode_truncate (&f.inode, newsize); + f.inode.mtime = time(0); + f.inode.dirty = 1; + fs_file_close (&f); + return 0; +} + +/* + * Change the size of an open file. + */ +int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) +{ + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + + printlog("--- op_ftruncate(path=\"%s\", offset=%lld, fi=%p)\n", + path, offset, fi); + + if (! fh->writable) + return -EACCES; + + if ((fh->inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + /* Cannot truncate special files. */ + return -EINVAL; + } + fs_inode_truncate (&fh->inode, offset); + fh->inode.mtime = time(0); + fh->inode.dirty = 1; + fs_file_close (fh); + return 0; +} + +/* + * Remove a file. + */ +int op_unlink(const char *path) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_unlink(path=\"%s\")\n", path); + + /* Get the file type. */ + if (! fs_inode_lookup (fs, &inode, path)) { + printlog("--- search failed\n"); + return -ENOENT; + } + if ((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot unlink directories. */ + return -EISDIR; + } + + /* Delete file. */ + if (! fs_inode_delete (fs, &inode, path)) { + printlog("--- delete failed\n"); + return -EIO; + } + fs_inode_save (&inode, 1); + return 0; +} + +/* + * Remove a directory. + */ +int op_rmdir(const char *path) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode, parent; + char buf [BSDFS_BSIZE], *p; + + printlog("--- op_rmdir(path=\"%s\")\n", path); + + /* Get the file type. */ + if (! fs_inode_lookup (fs, &inode, path)) { + printlog("--- search failed\n"); + return -ENOENT; + } + if ((inode.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { + /* Cannot remove files. */ + return -ENOTDIR; + } + if (inode.nlink > 2) { + /* Cannot remove non-empty directories. */ + return -ENOTEMPTY; + } + + /* Open parent directory. */ + strcpy (buf, path); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_lookup (fs, &parent, buf)) { + printlog("--- parent not found\n"); + return -ENOENT; + } + + /* Delete directory. + * Need to decrease a link count first. */ + if (! fs_inode_lookup (fs, &inode, path)) { + printlog("--- directory not found\n"); + return -ENOENT; + } + --inode.nlink; + fs_inode_save (&inode, 1); + if (! fs_inode_delete (fs, &inode, path)) { + printlog("--- delete failed\n"); + return -EIO; + } + fs_inode_save (&inode, 1); + + /* Decrease a parent's link counter. */ + if (! fs_inode_get (fs, &parent, parent.number)) { + printlog("--- cannot reopen parent\n"); + return -EIO; + } + --parent.nlink; + fs_inode_save (&parent, 1); + return 0; +} + +/* + * Create a directory. + */ +int op_mkdir(const char *path, mode_t mode) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t dir, parent; + char buf [BSDFS_BSIZE], *p; + + printlog("--- op_mkdir(path=\"%s\", mode=0%3o)\n", path, mode); + + /* Open parent directory. */ + strcpy (buf, path); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_lookup (fs, &parent, buf)) { + printlog("--- parent not found\n"); + return -ENOENT; + } + + /* Create directory. */ + mode &= 07777; + mode |= INODE_MODE_FDIR; + int done = fs_inode_create (fs, &dir, path, mode); + if (! done) { + printlog("--- cannot create dir inode\n"); + return -ENOENT; + } + if (done == 1) { + /* The directory already existed. */ + return -EEXIST; + } + fs_inode_save (&dir, 0); + + /* Make parent link '..' */ + strcpy (buf, path); + strcat (buf, "/.."); + if (! fs_inode_link (fs, &dir, buf, parent.number)) { + printlog("--- dotdot link failed\n"); + return -EIO; + } + if (! fs_inode_get (fs, &parent, parent.number)) { + printlog("--- cannot reopen parent\n"); + return -EIO; + } + ++parent.nlink; + fs_inode_save (&parent, 1); + return 0; +} + +/* + * Create a hard link to a file. + */ +int op_link(const char *path, const char *newpath) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t source, target; + + printlog("--- op_link(path=\"%s\", newpath=\"%s\")\n", path, newpath); + + /* Find source. */ + if (! fs_inode_lookup (fs, &source, path)) { + printlog("--- source not found\n"); + return -ENOENT; + } + + if ((source.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot link directories. */ + return -EPERM; + } + + /* Create target link. */ + if (! fs_inode_link (fs, &target, newpath, source.number)) { + printlog("--- link failed\n"); + return -EIO; + } + source.nlink++; + fs_inode_save (&source, 1); + return 0; +} + +/* + * Rename a file. + */ +int op_rename(const char *path, const char *newpath) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t source, target; + + printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", path, newpath); + + /* Find source and increase the link count. */ + if (! fs_inode_lookup (fs, &source, path)) { + printlog("--- source not found\n"); + return -ENOENT; + } + source.nlink++; + fs_inode_save (&source, 1); + + /* Create target link. */ + if (! fs_inode_link (fs, &target, newpath, source.number)) { + printlog("--- link failed\n"); + return -EIO; + } + + /* Delete the source. */ + if (! fs_inode_delete (fs, &source, path)) { + printlog("--- delete failed\n"); + return -EIO; + } + fs_inode_save (&source, 1); + return 0; +} + +/* + * Create a file node. + */ +int op_mknod(const char *path, mode_t mode, dev_t dev) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_mknod(path=\"%s\", mode=0%3o, dev=%lld)\n", + path, mode, dev); + + /* Check if the file already exists. */ + if (fs_inode_lookup (fs, &inode, path)) { + printlog("--- already exists\n"); + return -EEXIST; + } + + /* Encode a mode bitmask. */ + if (S_ISREG(mode)) { + mode = (mode & 07777) | INODE_MODE_FREG; + } else if (S_ISCHR(mode)) { + mode = (mode & 07777) | INODE_MODE_FCHR; + } else if (S_ISBLK(mode)) { + mode = (mode & 07777) | INODE_MODE_FBLK; + } else + return -EINVAL; + + /* Create the file. */ + if (! fs_inode_create (fs, &inode, path, mode)) { + printlog("--- create failed\n"); + return -EIO; + } + if (S_ISCHR(mode) || S_ISBLK(mode)) { + inode.addr[1] = major(dev) << 8 | minor(dev); + } + inode.mtime = time(0); + inode.dirty = 1; + if (! fs_inode_save (&inode, 0)) { + printlog("--- create failed\n"); + return -EIO; + } + return 0; +} + +/* + * Read the target of a symbolic link. + */ +int op_readlink(const char *path, char *link, size_t size) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_readlink(path=\"%s\", link=\"%s\", size=%d)\n", + path, link, size); + + /* Open the file. */ + if (! fs_inode_lookup (fs, &inode, path)) { + printlog("--- file not found\n"); + return -ENOENT; + } + + if ((inode.mode & INODE_MODE_FMT) != INODE_MODE_FLNK) + return -EINVAL; + + /* Leave one byte for the terminating null. */ + if (size > inode.size + 1) + size = inode.size + 1; + if (! fs_inode_read (&inode, 0, (unsigned char*)link, size-1)) { + printlog("--- read failed\n"); + return -EIO; + } + link[size-1] = 0; + return 0; +} + +/* + * Create a symbolic link. + */ +int op_symlink(const char *path, const char *newpath) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + int len, mode; + + printlog("--- op_symlink(path=\"%s\", newpath=\"%s\")\n", path, newpath); + + /* Check if the file already exists. */ + if (fs_inode_lookup (fs, &inode, newpath)) { + printlog("--- already exists\n"); + return -EEXIST; + } + + /* Create symlink. */ + mode = 0777 | INODE_MODE_FLNK; + if (! fs_inode_create (fs, &inode, newpath, mode)) { + printlog("--- create failed\n"); + return -EIO; + } + fs_inode_save (&inode, 0); + + len = strlen (path); + if (! fs_inode_write (&inode, 0, (unsigned char*)path, len)) { + printlog("--- write failed\n"); + return -EIO; + } + inode.mtime = time(0); + inode.dirty = 1; + if (! fs_inode_save (&inode, 0)) { + printlog("--- create failed\n"); + return -EIO; + } + return 0; +} + +/* + * Change the permission bits of a file. + */ +int op_chmod(const char *path, mode_t mode) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", path, mode); + + /* Open the file. */ + if (! fs_inode_lookup (fs, &inode, path)) { + printlog("--- file not found\n"); + return -ENOENT; + } + + /* Modify the access mode. */ + inode.mode &= ~07777; + inode.mode |= mode; + inode.dirty = 1; + fs_inode_save (&inode, 0); + return 0; +} + +/* + * Change the owner and group of a file. + */ +int op_chown(const char *path, uid_t uid, gid_t gid) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", path, uid, gid); + + /* Open the file. */ + if (! fs_inode_lookup (fs, &inode, path)) { + printlog("--- file not found\n"); + return -ENOENT; + } + + /* Modify the owner and group. */ + inode.uid = uid; + inode.gid = gid; + inode.dirty = 1; + fs_inode_save (&inode, 0); + return 0; +} + +/* + * Change the access and/or modification times of a file. + */ +int op_utime(const char *path, struct utimbuf *ubuf) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", path, ubuf); + + /* Open the file. */ + if (! fs_inode_lookup (fs, &inode, path)) { + printlog("--- file not found\n"); + return -ENOENT; + } + + /* Modify the access and modification times. */ + inode.atime = ubuf->actime; + inode.mtime = ubuf->modtime; + inode.dirty = 1; + fs_inode_save (&inode, 0); + return 0; +} + +/* + * Get file system statistics. + * + * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored + */ +int op_statfs(const char *path, struct statvfs *statv) +{ + fs_dirent_t dirent; + + printlog("--- op_statfs(path=\"%s\", statv=%p)\n", path, statv); + + /* The maximum length in bytes of a file name on this file system. */ + statv->f_namemax = sizeof(dirent.name) - 1; + + /* The preferred length of I/O requests for files on this file system. */ + statv->f_bsize = BSDFS_BSIZE; + return 0; +} + +/* + * Possibly flush cached data. + */ +int op_flush(const char *path, struct fuse_file_info *fi) +{ + printlog("--- op_flush(path=\"%s\", fi=%p)\n", path, fi); + return 0; +} + +/* + * Synchronize file contents. + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. + */ +int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) +{ + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + + printlog("--- op_fsync(path=\"%s\", datasync=%d, fi=%p)\n", + path, datasync, fi); + + if (datasync == 0 && fh->writable) { + if (! fs_inode_save (&fh->inode, 0)) + return -EIO; + } + return 0; +} + +/* + * Open directory. + */ +int op_opendir(const char *path, struct fuse_file_info *fi) +{ + printlog("--- op_opendir(path=\"%s\", fi=%p)\n", path, fi); + return 0; +} + +/* + * Read directory. + */ +int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, + struct fuse_file_info *fi) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t dir; + char name [BSDFS_BSIZE - 12]; + struct { + unsigned int inum; + unsigned short reclen; + unsigned short namlen; + } dirent; + + printlog("--- op_readdir(path=\"%s\", buf=%p, filler=%p, offset=%lld, fi=%p)\n", + path, buf, filler, offset, fi); + + if (! fs_inode_lookup (fs, &dir, path)) { + printlog("--- cannot find path %s\n", path); + return -ENOENT; + } + + /* Copy the entire directory into the buffer. */ + for (offset = 0; offset < dir.size; offset += dirent.reclen) { + if (! fs_inode_read (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + printlog("--- read error at offset %ld\n", offset); + return -EIO; + } + //printlog("--- readdir offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen); + + if (! fs_inode_read (&dir, offset+sizeof(dirent), + (unsigned char*)name, (dirent.namlen + 4) / 4 * 4)) + { + printlog("--- name read error at offset %ld\n", offset); + return -EIO; + } + //printlog("--- readdir offset %lu: name='%s'\n", offset, name); + + if (dirent.inum != 0) { + //printlog("calling filler with name %s\n", name); + name[dirent.namlen] = 0; + if (filler(buf, name, NULL, 0) != 0) { + printlog(" ERROR op_readdir filler: buffer full"); + return -ENOMEM; + } + } + } + return 0; +} + +/* + * Release directory. + */ +int op_releasedir(const char *path, struct fuse_file_info *fi) +{ + printlog("--- op_releasedir(path=\"%s\", fi=%p)\n", path, fi); + return 0; +} + +/* + * Clean up filesystem. + * Called on filesystem exit. + */ +void op_destroy(void *userdata) +{ + printlog("--- op_destroy(userdata=%p)\n", userdata); +} + +/* + * Check file access permissions. + */ +int op_access(const char *path, int mask) +{ + printlog("--- op_access(path=\"%s\", mask=0%o)\n", path, mask); + + /* Always permitted. */ + return 0; +} + +static struct fuse_operations mount_ops = { + .access = op_access, + .chmod = op_chmod, + .chown = op_chown, + .create = op_create, + .destroy = op_destroy, + .fgetattr = op_fgetattr, + .flush = op_flush, + .fsync = op_fsync, + .ftruncate = op_ftruncate, + .getattr = op_getattr, + .link = op_link, + .mkdir = op_mkdir, + .mknod = op_mknod, + .open = op_open, + .opendir = op_opendir, + .readdir = op_readdir, + .readlink = op_readlink, + .read = op_read, + .release = op_release, + .releasedir = op_releasedir, + .rename = op_rename, + .rmdir = op_rmdir, + .statfs = op_statfs, + .symlink = op_symlink, + .truncate = op_truncate, + .unlink = op_unlink, + .utime = op_utime, + .write = op_write, +}; + +int fs_mount(fs_t *fs, char *dirname) +{ + char *av[8]; + int ret, ac; + + printf ("Filesystem mounted as %s\n", dirname); + printf ("Press ^C to unmount\n"); + + /* Invoke FUSE to mount the filesystem. */ + ac = 0; + av[ac++] = "fsutil"; + av[ac++] = "-f"; /* foreground */ + av[ac++] = "-s"; /* single-threaded */ + if (verbose > 1) + av[ac++] = "-d"; /* debug */ + av[ac++] = dirname; + av[ac] = 0; + ret = fuse_main(ac, av, &mount_ops, fs); + if (ret != 0) { + perror ("fuse_main failed"); + return -1; + } + fs_sync (fs, 0); + fs_close (fs); + printf ("\nFilesystem %s unmounted\n", dirname); + return ret; +} diff --git a/tools/fsutil/superblock.c b/tools/fsutil/superblock.c index e8c02aa..cc96ef7 100644 --- a/tools/fsutil/superblock.c +++ b/tools/fsutil/superblock.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include @@ -18,298 +32,300 @@ extern int verbose; int fs_seek (fs_t *fs, unsigned long offset) { -/* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/ - if (lseek (fs->fd, offset, 0) < 0) { - if (verbose) - printf ("error seeking %ld, block %ld\n", - offset, offset / BSDFS_BSIZE); - return 0; - } - fs->seek = offset; - return 1; +/* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/ + if (lseek (fs->fd, offset, 0) < 0) { + if (verbose) + printf ("error seeking %ld, block %ld\n", + offset, offset / BSDFS_BSIZE); + return 0; + } + fs->seek = offset; + return 1; } int fs_read8 (fs_t *fs, unsigned char *val) { - if (read (fs->fd, val, 1) != 1) { - if (verbose) - printf ("error read8, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - return 1; + if (read (fs->fd, val, 1) != 1) { + if (verbose) + printf ("error read8, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + return 1; } int fs_read16 (fs_t *fs, unsigned short *val) { - unsigned char data [2]; + unsigned char data [2]; - if (read (fs->fd, data, 2) != 2) { - if (verbose) - printf ("error read16, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - *val = data[1] << 8 | data[0]; - return 1; + if (read (fs->fd, data, 2) != 2) { + if (verbose) + printf ("error read16, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + *val = data[1] << 8 | data[0]; + return 1; } int fs_read32 (fs_t *fs, unsigned *val) { - unsigned char data [4]; + unsigned char data [4]; - if (read (fs->fd, data, 4) != 4) { - if (verbose) - printf ("error read32, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - *val = (unsigned long) data[0] | (unsigned long) data[1] << 8 | - data[2] << 16 | data[3] << 24; - return 1; + if (read (fs->fd, data, 4) != 4) { + if (verbose) + printf ("error read32, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + *val = (unsigned long) data[0] | (unsigned long) data[1] << 8 | + data[2] << 16 | data[3] << 24; + return 1; } int fs_write8 (fs_t *fs, unsigned char val) { - if (write (fs->fd, &val, 1) != 1) - return 0; - return 1; + if (write (fs->fd, &val, 1) != 1) + return 0; + return 1; } int fs_write16 (fs_t *fs, unsigned short val) { - unsigned char data [2]; + unsigned char data [2]; - data[0] = val; - data[1] = val >> 8; - if (write (fs->fd, data, 2) != 2) - return 0; - return 1; + data[0] = val; + data[1] = val >> 8; + if (write (fs->fd, data, 2) != 2) + return 0; + return 1; } int fs_write32 (fs_t *fs, unsigned val) { - unsigned char data [4]; + unsigned char data [4]; - data[0] = val; - data[1] = val >> 8; - data[2] = val >> 16; - data[3] = val >> 24; - if (write (fs->fd, data, 4) != 4) - return 0; - return 1; + data[0] = val; + data[1] = val >> 8; + data[2] = val >> 16; + data[3] = val >> 24; + if (write (fs->fd, data, 4) != 4) + return 0; + return 1; } int fs_read (fs_t *fs, unsigned char *data, int bytes) { - int len; + int len; - while (bytes > 0) { - len = bytes; - if (len > 16*BSDFS_BSIZE) - len = 16*BSDFS_BSIZE; - if (read (fs->fd, data, len) != len) - return 0; - data += len; - bytes -= len; - } - return 1; + while (bytes > 0) { + len = bytes; + if (len > 16*BSDFS_BSIZE) + len = 16*BSDFS_BSIZE; + if (read (fs->fd, data, len) != len) + return 0; + data += len; + bytes -= len; + } + return 1; } int fs_write (fs_t *fs, unsigned char *data, int bytes) { - int len; + int len; - if (! fs->writable) - return 0; - while (bytes > 0) { - len = bytes; - if (len > 16*BSDFS_BSIZE) - len = 16*BSDFS_BSIZE; - if (write (fs->fd, data, len) != len) - return 0; - data += len; - bytes -= len; - } - return 1; + if (! fs->writable) + return 0; + while (bytes > 0) { + len = bytes; + if (len > 16*BSDFS_BSIZE) + len = 16*BSDFS_BSIZE; + if (write (fs->fd, data, len) != len) + return 0; + data += len; + bytes -= len; + } + return 1; } int fs_open (fs_t *fs, const char *filename, int writable) { - int i; - unsigned magic; + int i; + unsigned magic; - memset (fs, 0, sizeof (*fs)); - fs->filename = filename; - fs->seek = 0; + memset (fs, 0, sizeof (*fs)); + fs->filename = filename; + fs->seek = 0; - fs->fd = open (fs->filename, writable ? O_RDWR : O_RDONLY); - if (fs->fd < 0) - return 0; - fs->writable = writable; + fs->fd = open (fs->filename, writable ? O_RDWR : O_RDONLY); + if (fs->fd < 0) + return 0; + fs->writable = writable; - if (! fs_read32 (fs, &magic) || /* magic word */ - magic != FSMAGIC1) { - if (verbose) - printf ("fs_open: bad magic1 = %08x, expected %08x\n", - magic, FSMAGIC1); - return 0; - } - if (! fs_read32 (fs, &fs->isize)) /* size in blocks of I list */ - return 0; - if (! fs_read32 (fs, &fs->fsize)) /* size in blocks of entire volume */ - return 0; - if (! fs_read32 (fs, &fs->swapsz)) /* size in blocks of swap area */ - return 0; - if (! fs_read32 (fs, &fs->nfree)) /* number of in core free blocks */ - return 0; - for (i=0; ifree[i])) - return 0; - } - if (! fs_read32 (fs, &fs->ninode)) /* number of in core I nodes */ - return 0; - for (i=0; iinode[i])) - return 0; - } - if (! fs_read32 (fs, &fs->flock)) - return 0; - if (! fs_read32 (fs, &fs->fmod)) - return 0; - if (! fs_read32 (fs, &fs->ilock)) - return 0; - if (! fs_read32 (fs, &fs->ronly)) - return 0; - if (! fs_read32 (fs, (unsigned*) &fs->utime)) - return 0; /* current date of last update */ - if (! fs_read32 (fs, &fs->tfree)) /* total free blocks */ - return 0; - if (! fs_read32 (fs, &fs->tinode)) /* total free inodes */ - return 0; - if (! fs_read (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) - return 0; /* ordinary file mounted on */ - if (! fs_read32 (fs, &fs->lasti)) /* start place for circular search */ - return 0; - if (! fs_read32 (fs, &fs->nbehind)) /* est # free inodes before s_lasti */ - return 0; - if (! fs_read32 (fs, &fs->flags)) /* mount time flags */ - return 0; - if (! fs_read32 (fs, &magic) || /* magic word */ - magic != FSMAGIC2) { - if (verbose) - printf ("fs_open: bad magic2 = %08x, expected %08x\n", - magic, FSMAGIC2); - return 0; - } - return 1; + if (! fs_read32 (fs, &magic) || /* magic word */ + magic != FSMAGIC1) { + if (verbose) + printf ("fs_open: bad magic1 = %08x, expected %08x\n", + magic, FSMAGIC1); + return 0; + } + if (! fs_read32 (fs, &fs->isize)) /* size in blocks of I list */ + return 0; + if (! fs_read32 (fs, &fs->fsize)) /* size in blocks of entire volume */ + return 0; + if (! fs_read32 (fs, &fs->swapsz)) /* size in blocks of swap area */ + return 0; + if (! fs_read32 (fs, &fs->nfree)) /* number of in core free blocks */ + return 0; + for (i=0; ifree[i])) + return 0; + } + if (! fs_read32 (fs, &fs->ninode)) /* number of in core I nodes */ + return 0; + for (i=0; iinode[i])) + return 0; + } + if (! fs_read32 (fs, &fs->flock)) + return 0; + if (! fs_read32 (fs, &fs->fmod)) + return 0; + if (! fs_read32 (fs, &fs->ilock)) + return 0; + if (! fs_read32 (fs, &fs->ronly)) + return 0; + if (! fs_read32 (fs, (unsigned*) &fs->utime)) + return 0; /* current date of last update */ + if (! fs_read32 (fs, &fs->tfree)) /* total free blocks */ + return 0; + if (! fs_read32 (fs, &fs->tinode)) /* total free inodes */ + return 0; + if (! fs_read (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) + return 0; /* ordinary file mounted on */ + if (! fs_read32 (fs, &fs->lasti)) /* start place for circular search */ + return 0; + if (! fs_read32 (fs, &fs->nbehind)) /* est # free inodes before s_lasti */ + return 0; + if (! fs_read32 (fs, &fs->flags)) /* mount time flags */ + return 0; + if (! fs_read32 (fs, &magic) || /* magic word */ + magic != FSMAGIC2) { + if (verbose) + printf ("fs_open: bad magic2 = %08x, expected %08x\n", + magic, FSMAGIC2); + return 0; + } + return 1; } int fs_sync (fs_t *fs, int force) { - int i; + int i; - if (! fs->writable) - return 0; - if (! force && ! fs->dirty) - return 1; + if (! fs->writable) + return 0; + if (! force && ! fs->dirty) + return 1; - time (&fs->utime); - if (! fs_seek (fs, 0)) - return 0; + time (&fs->utime); + if (! fs_seek (fs, 0)) + return 0; - if (! fs_write32 (fs, FSMAGIC1)) /* magic word */ - return 0; - if (! fs_write32 (fs, fs->isize)) /* size in blocks of I list */ - return 0; - if (! fs_write32 (fs, fs->fsize)) /* size in blocks of entire volume */ - return 0; - if (! fs_write32 (fs, fs->swapsz)) /* size in blocks of swap area */ - return 0; - if (! fs_write32 (fs, fs->nfree)) /* number of in core free blocks */ - return 0; - for (i=0; ifree[i])) - return 0; - } - if (! fs_write32 (fs, fs->ninode)) /* number of in core I nodes */ - return 0; - for (i=0; iinode[i])) - return 0; - } - if (! fs_write32 (fs, fs->flock)) - return 0; - if (! fs_write32 (fs, fs->fmod)) - return 0; - if (! fs_write32 (fs, fs->ilock)) - return 0; - if (! fs_write32 (fs, fs->ronly)) - return 0; - if (! fs_write32 (fs, fs->utime)) /* current date of last update */ - return 0; - if (! fs_write32 (fs, fs->tfree)) /* total free blocks */ - return 0; - if (! fs_write32 (fs, fs->tinode)) /* total free inodes */ - return 0; - if (! fs_write (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) - return 0; /* ordinary file mounted on */ - if (! fs_write32 (fs, 0)) /* lasti*/ - return 0; - if (! fs_write32 (fs, 0)) /* nbehind */ - return 0; - if (! fs_write32 (fs, 0)) /* flags */ - return 0; - if (! fs_write32 (fs, FSMAGIC2)) /* magic word */ - return 0; - fs->dirty = 0; - return 1; + if (! fs_write32 (fs, FSMAGIC1)) /* magic word */ + return 0; + if (! fs_write32 (fs, fs->isize)) /* size in blocks of I list */ + return 0; + if (! fs_write32 (fs, fs->fsize)) /* size in blocks of entire volume */ + return 0; + if (! fs_write32 (fs, fs->swapsz)) /* size in blocks of swap area */ + return 0; + if (! fs_write32 (fs, fs->nfree)) /* number of in core free blocks */ + return 0; + for (i=0; ifree[i])) + return 0; + } + if (! fs_write32 (fs, fs->ninode)) /* number of in core I nodes */ + return 0; + for (i=0; iinode[i])) + return 0; + } + if (! fs_write32 (fs, fs->flock)) + return 0; + if (! fs_write32 (fs, fs->fmod)) + return 0; + if (! fs_write32 (fs, fs->ilock)) + return 0; + if (! fs_write32 (fs, fs->ronly)) + return 0; + if (! fs_write32 (fs, fs->utime)) /* current date of last update */ + return 0; + if (! fs_write32 (fs, fs->tfree)) /* total free blocks */ + return 0; + if (! fs_write32 (fs, fs->tinode)) /* total free inodes */ + return 0; + if (! fs_write (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) + return 0; /* ordinary file mounted on */ + if (! fs_write32 (fs, 0)) /* lasti*/ + return 0; + if (! fs_write32 (fs, 0)) /* nbehind */ + return 0; + if (! fs_write32 (fs, 0)) /* flags */ + return 0; + if (! fs_write32 (fs, FSMAGIC2)) /* magic word */ + return 0; + fs->dirty = 0; + return 1; } void fs_print (fs_t *fs, FILE *out) { - int i; + int i; - fprintf (out, " File: %s\n", fs->filename); - fprintf (out, " Volume size: %u blocks\n", fs->fsize); - fprintf (out, " Inode list size: %u blocks\n", fs->isize); - fprintf (out, " Swap size: %u blocks\n", fs->swapsz); - fprintf (out, " Total free blocks: %u blocks\n", fs->tfree); - fprintf (out, " Total free inodes: %u inodes\n", fs->tinode); - fprintf (out, " Last mounted on: %.*s\n", MAXMNTLEN, - fs->fsmnt[0] ? fs->fsmnt : "(none)"); - fprintf (out, " In-core free list: %u blocks", fs->nfree); - if (verbose) - for (i=0; i < NICFREE && i < fs->nfree; ++i) { - if (i % 10 == 0) - fprintf (out, "\n "); - fprintf (out, " %u", fs->free[i]); - } - fprintf (out, "\n"); + fprintf (out, " File: %s\n", fs->filename); + fprintf (out, " Volume size: %u blocks\n", fs->fsize); + fprintf (out, " Inode list size: %u blocks\n", fs->isize); + fprintf (out, " Swap size: %u blocks\n", fs->swapsz); + fprintf (out, " Total free blocks: %u blocks\n", fs->tfree); + fprintf (out, " Total free inodes: %u inodes\n", fs->tinode); + fprintf (out, " Last mounted on: %.*s\n", MAXMNTLEN, + fs->fsmnt[0] ? fs->fsmnt : "(none)"); + fprintf (out, " In-core free list: %u blocks", fs->nfree); + if (verbose) { + for (i=0; i < NICFREE && i < fs->nfree; ++i) { + if (i % 10 == 0) + fprintf (out, "\n "); + fprintf (out, " %u", fs->free[i]); + } + } + fprintf (out, "\n"); - fprintf (out, " In-core free inodes: %u inodes", fs->ninode); - if (verbose) - for (i=0; i < NICINOD && i < fs->ninode; ++i) { - if (i % 10 == 0) - fprintf (out, "\n "); - fprintf (out, " %u", fs->inode[i]); - } - fprintf (out, "\n"); - if (verbose) { -// fprintf (out, " Free list lock: %u\n", fs->flock); -// fprintf (out, " Inode list lock: %u\n", fs->ilock); -// fprintf (out, "Super block modified: %u\n", fs->fmod); -// fprintf (out, " Mounted read-only: %u\n", fs->ronly); -// fprintf (out, " Circ.search start: %u\n", fs->lasti); -// fprintf (out, " Circ.search behind: %u\n", fs->nbehind); -// fprintf (out, " Mount flags: 0x%x\n", fs->flags); - } + fprintf (out, " In-core free inodes: %u inodes", fs->ninode); + if (verbose) { + for (i=0; i < NICINOD && i < fs->ninode; ++i) { + if (i % 10 == 0) + fprintf (out, "\n "); + fprintf (out, " %u", fs->inode[i]); + } + } + fprintf (out, "\n"); + if (verbose) { +// fprintf (out, " Free list lock: %u\n", fs->flock); +// fprintf (out, " Inode list lock: %u\n", fs->ilock); +// fprintf (out, "Super block modified: %u\n", fs->fmod); +// fprintf (out, " Mounted read-only: %u\n", fs->ronly); +// fprintf (out, " Circ.search start: %u\n", fs->lasti); +// fprintf (out, " Circ.search behind: %u\n", fs->nbehind); +// fprintf (out, " Mount flags: 0x%x\n", fs->flags); + } - fprintf (out, " Last update time: %s", ctime (&fs->utime)); + fprintf (out, " Last update time: %s", ctime (&fs->utime)); } void fs_close (fs_t *fs) { - if (fs->fd < 0) - return; + if (fs->fd < 0) + return; - close (fs->fd); - fs->fd = -1; + close (fs->fd); + fs->fd = -1; } diff --git a/tools/virtualmips/Makefile b/tools/virtualmips/Makefile index ad1f9db..46ae104 100644 --- a/tools/virtualmips/Makefile +++ b/tools/virtualmips/Makefile @@ -6,6 +6,9 @@ # chipKIT Max32 CFLAGS = -DSIM_PIC32 -DPIC32MX7 -DMAX32 +# Maximite +#CFLAGS = -DSIM_PIC32 -DPIC32MX7 -DMAXIMITE + # Microchip Explorer 16 #CFLAGS = -DSIM_PIC32 -DPIC32MX7 -DEXPLORER16 diff --git a/tools/virtualmips/dev_sdcard.c b/tools/virtualmips/dev_sdcard.c index 478cbac..82b8f9b 100644 --- a/tools/virtualmips/dev_sdcard.c +++ b/tools/virtualmips/dev_sdcard.c @@ -33,6 +33,7 @@ #define CMD_GO_IDLE (0x40+0) /* CMD0 */ #define CMD_SEND_OP_SDC (0x40+41) /* ACMD41 (SDC) */ #define CMD_SET_BLEN (0x40+16) +#define CMD_SEND_IF_COND (0x40+8) #define CMD_SEND_CSD (0x40+9) #define CMD_STOP (0x40+12) #define CMD_READ_SINGLE (0x40+17) @@ -330,6 +331,12 @@ unsigned dev_sdcard_io (cpu_mips_t *cpu, unsigned data) d->read_multiple = 0; reply = 0; break; + case CMD_SEND_IF_COND: /* Stop read-multiple sequence */ + if (d->count > 1) + break; + d->read_multiple = 0; + reply = 4; /* Unknown command */ + break; case 0: /* Reply */ if (d->count <= d->limit) { reply = d->buf [d->count++]; diff --git a/tools/virtualmips/pic32_explorer16.conf b/tools/virtualmips/pic32_explorer16.conf index fbde208..211e9d0 100644 --- a/tools/virtualmips/pic32_explorer16.conf +++ b/tools/virtualmips/pic32_explorer16.conf @@ -16,14 +16,21 @@ flash_size = 492 # kbytes flash_phy_address = 0x1d000000 flash_file_name = ../../sys/pic32/explorer16/unix.bin -start_address = 0x9d001000 # user program +# +# Boot flash +# +boot_flash_size = 12 # kbytes +boot_flash_address = 0x1fc00000 +boot_file_name = ../../sys/pic32/explorer16/boot.bin + +start_address = 0x9fc00000 # user program # # SD/MMC cards # sdcard_port = 1 # SPI1 -sdcard0_size = 16 # Mbytes -sdcard0_file_name = ../../filesys.img +sdcard0_size = 340 # Mbytes +sdcard0_file_name = ../../sdcard.rd # # UARTs 1..6 diff --git a/tools/virtualmips/pic32_max32.conf b/tools/virtualmips/pic32_max32.conf index 2bce54f..b962fa1 100644 --- a/tools/virtualmips/pic32_max32.conf +++ b/tools/virtualmips/pic32_max32.conf @@ -28,7 +28,7 @@ sdcard0_file_name = ../../sdcard.rd # # UARTs 1..6 # -uart1_type = console +uart1_type = console # # Debug level: @@ -38,4 +38,4 @@ uart1_type = console # 3 - trace all inctructions # debug_level = 0 -#trace_address = 0x9d00720c +#trace_address = 0x9d00720c diff --git a/tools/virtualmips/pic32_maximite.conf b/tools/virtualmips/pic32_maximite.conf index 28e103d..8dcdc7f 100644 --- a/tools/virtualmips/pic32_maximite.conf +++ b/tools/virtualmips/pic32_maximite.conf @@ -22,7 +22,7 @@ start_address = 0x9d006000 # user program # SD/MMC cards # sdcard_port = 4 # SPI4 -sdcard0_size = 16 # Mbytes +sdcard0_size = 340 # Mbytes sdcard0_file_name = ../../filesys.img # diff --git a/tools/virtualmips/pic32_ubw32.conf b/tools/virtualmips/pic32_ubw32.conf index 2ccd87b..ab5649d 100644 --- a/tools/virtualmips/pic32_ubw32.conf +++ b/tools/virtualmips/pic32_ubw32.conf @@ -22,7 +22,7 @@ start_address = 0x9d006000 # user program # SD/MMC cards # sdcard_port = 1 # SPI1 -sdcard0_size = 16 # Mbytes +sdcard0_size = 340 # Mbytes sdcard0_file_name = ../../filesys.img #sdcard1_size = 2 # Mbytes #sdcard1_file_name = ../../home.img diff --git a/u/README.txt b/u/README.txt new file mode 100644 index 0000000..aa96d61 --- /dev/null +++ b/u/README.txt @@ -0,0 +1 @@ +User filesystem. diff --git a/userfs.manifest b/userfs.manifest new file mode 100644 index 0000000..4de6f25 --- /dev/null +++ b/userfs.manifest @@ -0,0 +1,10 @@ +# +# Manifest file for user filesystem. +# +default +owner 0 +group 0 +dirmode 0775 +filemode 0664 + +file README.txt