Compare commits
92 Commits
mz-startup
...
levee-edit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f33305f894 | ||
|
|
e834303650 | ||
|
|
476573dae6 | ||
|
|
8e2c046406 | ||
|
|
dad5247184 | ||
|
|
b1f67fbca0 | ||
|
|
f76ab8417c | ||
|
|
3bb914c8b4 | ||
|
|
8b099bcf76 | ||
|
|
2fc41d34cf | ||
|
|
2301571ecb | ||
|
|
00269e9387 | ||
|
|
687695d0db | ||
|
|
0aa5e1c462 | ||
|
|
3a7cde7974 | ||
|
|
f57cc446b0 | ||
|
|
1a55933faf | ||
|
|
b18ce0aa87 | ||
|
|
5bbf8d4e73 | ||
|
|
7aa774702b | ||
|
|
64430a0f91 | ||
|
|
d5e30d7b79 | ||
|
|
a8d9b3d01f | ||
|
|
ebd35d772f | ||
|
|
c4da2137e1 | ||
|
|
c42133cdff | ||
|
|
dc66e6fdda | ||
|
|
f58c7a7426 | ||
|
|
5c4309942a | ||
|
|
e557c88b1e | ||
|
|
850797db2e | ||
|
|
cae7db41ca | ||
|
|
808dfaf6ef | ||
|
|
d3d48970e3 | ||
|
|
93d95abc69 | ||
|
|
c5ac22d17f | ||
|
|
e7b77dadc3 | ||
|
|
2ea9e02ba5 | ||
|
|
d9d91365c0 | ||
|
|
2da083e9bd | ||
|
|
e4e9ff1ef4 | ||
|
|
aecac2f5d7 | ||
|
|
8886a00340 | ||
|
|
25bcc79a69 | ||
|
|
8d55f87ab8 | ||
|
|
9adca14b87 | ||
|
|
83a999be0a | ||
|
|
1462eeb400 | ||
|
|
d42bfdc7b9 | ||
|
|
1cdf42ef94 | ||
|
|
8f4aad27f9 | ||
|
|
cb4ca7f73a | ||
|
|
b44cab756f | ||
|
|
c2b3647d5e | ||
|
|
4d8233582a | ||
|
|
eb1fb36b6b | ||
|
|
2293493bfd | ||
|
|
61ce169328 | ||
|
|
173efb822d | ||
|
|
21babaf947 | ||
|
|
3a789348da | ||
|
|
d6e558bea0 | ||
|
|
847e2bff77 | ||
|
|
08c79d7fec | ||
|
|
0cef044377 | ||
|
|
61c7c690b9 | ||
|
|
294ccae3be | ||
|
|
1c4e562363 | ||
|
|
09b50bf614 | ||
|
|
8439672624 | ||
|
|
b6e105c87b | ||
|
|
70b8d93b21 | ||
|
|
5fa78e772b | ||
|
|
7b1bf93d3a | ||
|
|
04208ea903 | ||
|
|
e003436e91 | ||
|
|
29904aacd7 | ||
|
|
dbe51ae294 | ||
|
|
87489937bf | ||
|
|
bbba8d6f95 | ||
|
|
b3abe580bd | ||
|
|
66ffc30ccd | ||
|
|
0b31486402 | ||
|
|
5bd8f3a470 | ||
|
|
fa46b819f0 | ||
|
|
91468f005f | ||
|
|
e2cb851fbf | ||
|
|
e725ab2b44 | ||
|
|
8423492f33 | ||
|
|
8e8fc70ed5 | ||
|
|
d8305bc374 | ||
|
|
3942e87cd1 |
145
Makefile
145
Makefile
@@ -24,24 +24,23 @@ DUINOMITE = sys/pic32/duinomite/DUINOMITE
|
||||
DUINOMITEUART = sys/pic32/duinomite-uart/DUINOMITE-UART
|
||||
DUINOMITEE = sys/pic32/duinomite-e/DUINOMITE-E
|
||||
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
|
||||
SDXL = sys/pic32/sdxl/SDXL
|
||||
MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7
|
||||
|
||||
# Select target board
|
||||
TARGET ?= $(MAX32)
|
||||
|
||||
# Filesystem and swap sizes.
|
||||
FS_KBYTES = 102400
|
||||
U_KBYTES = 102400
|
||||
SWAP_KBYTES = 2048
|
||||
FS_MBYTES = 100
|
||||
U_MBYTES = 100
|
||||
SWAP_MBYTES = 2
|
||||
|
||||
# Set this to the device name for your SD card. With this
|
||||
# enabled you can use "make installfs" to copy the filesys.img
|
||||
# enabled you can use "make installfs" to copy the sdcard.img
|
||||
# to the SD card.
|
||||
|
||||
#SDCARD = /dev/sdb
|
||||
@@ -60,68 +59,13 @@ 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/
|
||||
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
|
||||
|
||||
fs: sdcard.rd
|
||||
|
||||
.PHONY: tools
|
||||
tools:
|
||||
all: .profile
|
||||
$(MAKE) -C tools
|
||||
$(MAKE) -C lib
|
||||
$(MAKE) -C src install
|
||||
$(MAKE) kernel
|
||||
$(MAKE) fs
|
||||
|
||||
kernel: $(TARGETDIR)/Makefile
|
||||
$(MAKE) -C $(TARGETDIR)
|
||||
@@ -129,39 +73,14 @@ kernel: $(TARGETDIR)/Makefile
|
||||
$(TARGETDIR)/Makefile: $(CONFIG) $(TARGETDIR)/$(TARGETNAME)
|
||||
cd $(TARGETDIR) && ../../../tools/configsys/config $(TARGETNAME)
|
||||
|
||||
.PHONY: lib
|
||||
lib:
|
||||
$(MAKE) -C lib
|
||||
fs: sdcard.img
|
||||
|
||||
build: tools lib
|
||||
$(MAKE) -C src install
|
||||
|
||||
filesys.img: $(FSUTIL) $(ALLFILES)
|
||||
.PHONY: sdcard.img
|
||||
sdcard.img: $(FSUTIL) rootfs.manifest userfs.manifest
|
||||
rm -f $@
|
||||
$(FSUTIL) -n$(FS_KBYTES) $@
|
||||
$(FSUTIL) -a $@ $(ALLDIRS)
|
||||
$(FSUTIL) -a $@ $(CDEVS)
|
||||
$(FSUTIL) -a $@ $(BDEVS)
|
||||
$(FSUTIL) -a $@ $(ALLFILES)
|
||||
$(FSUTIL) -a $@ $(MANFILES)
|
||||
|
||||
swap.img:
|
||||
dd if=/dev/zero of=$@ bs=1k count=$(SWAP_KBYTES)
|
||||
|
||||
user.img: $(FSUTIL)
|
||||
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 ../$@ '{}' \+)
|
||||
endif
|
||||
|
||||
sdcard.rd: filesys.img swap.img user.img
|
||||
ifneq ($(U_KBYTES), 0)
|
||||
tools/mkrd/mkrd -out $@ -boot filesys.img -swap swap.img -fs user.img
|
||||
else
|
||||
tools/mkrd/mkrd -out $@ -boot filesys.img -swap swap.img
|
||||
endif
|
||||
$(FSUTIL) --repartition=fs=$(FS_MBYTES)M:swap=$(SWAP_MBYTES)M:fs=$(U_MBYTES)M $@
|
||||
$(FSUTIL) --new --partition=1 --manifest=rootfs.manifest $@ .
|
||||
$(FSUTIL) --new --partition=3 --manifest=userfs.manifest $@ u
|
||||
|
||||
$(FSUTIL):
|
||||
cd tools/fsutil; $(MAKE)
|
||||
@@ -175,32 +94,30 @@ clean:
|
||||
|
||||
cleanall: clean
|
||||
$(MAKE) -C lib clean
|
||||
rm -f sys/pic32/*/unix.hex bin/* sbin/* games/[a-k]* games/[m-z]* libexec/* share/man/cat*/*
|
||||
rm -f games/lib/adventure.dat
|
||||
rm -f games/lib/cfscores
|
||||
rm -f share/re.help
|
||||
rm -f share/misc/more.help
|
||||
rm -f sys/pic32/*/unix.hex bin/* sbin/* libexec/*
|
||||
rm -f games/[a-k]* games/[m-z]* share/man/cat*/*
|
||||
rm -f games/lib/adventure.dat games/lib/cfscores
|
||||
rm -f share/re.help share/emg.keys share/misc/more.help
|
||||
rm -f etc/termcap etc/remote etc/phones
|
||||
rm -rf share/unixbench
|
||||
rm -f games/lib/adventure.dat games/lib/cfscores share/re.help share/misc/more.help etc/termcap
|
||||
rm -f tools/configsys/.depend
|
||||
rm -f var/log/aculog
|
||||
rm -rf var/lock
|
||||
rm -rf var/lock share/unixbench
|
||||
|
||||
installfs: filesys.img
|
||||
installfs:
|
||||
ifdef SDCARD
|
||||
sudo dd bs=32k if=sdcard.rd of=$(SDCARD)
|
||||
@[ -f sdcard.img ] || $(MAKE) sdcard.img
|
||||
sudo dd bs=32k if=sdcard.img 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
|
||||
|
||||
24
README.md
24
README.md
@@ -27,6 +27,14 @@
|
||||
|
||||
## Build
|
||||
|
||||
To compile everything from sources, you'll need some packages installed, namely:
|
||||
Berkeley YACC, GNU bison and flex, ELF library and FUSE library.
|
||||
Under Ubuntu, for example, you can do it by command:
|
||||
|
||||
```shell
|
||||
$ sudo apt-get install bison byacc flex libelf-dev libfuse-dev
|
||||
```
|
||||
|
||||
By default, the system is configured for the Max32 board.
|
||||
To select another target board, edit a top-level user-specific Makefile called "Makefile.user"
|
||||
and set a TARGET value:
|
||||
@@ -45,8 +53,6 @@ TARGET = $(DUINOMITE) # for the Duinomite board with USB console
|
||||
TARGET = $(DUINOMITEUART) # for the Duinomite board with UART console
|
||||
TARGET = $(DUINOMITEE) # for the Duinomite E board with USB console
|
||||
TARGET = $(DUINOMITEEUART) # for the Duinomite E board with UART console
|
||||
TARGET = $(PINGUINO) # for the Pinguino-Micro board
|
||||
TARGET = $(DIP) # for the DIP board
|
||||
TARGET = $(BAREMETAL) # Bare PIC32 chip on a breakout board
|
||||
TARGET = $(FUBARINO) # Fubarino SD board
|
||||
TARGET = $(FUBARINOBIG) # Fubarino SD board with 8MB SRAM RAMDISK
|
||||
@@ -65,7 +71,7 @@ To compile the kernel and build a filesystem image, run:
|
||||
$ make
|
||||
```
|
||||
|
||||
A resulting root filesystem image is in file `sdcard.rd`.
|
||||
A resulting root filesystem image is in file `sdcard.img`.
|
||||
A kernel is in file `unix.hex` in your target board subdirectory.
|
||||
|
||||
|
||||
@@ -76,7 +82,7 @@ Win32DiskImager utility (https://launchpad.net/win32-image-writer/+download).
|
||||
On Linux, run:
|
||||
|
||||
```shell
|
||||
$ sudo dd if=sdcard.rd of=/dev/XYZ
|
||||
$ sudo dd if=sdcard.img of=/dev/XYZ
|
||||
```
|
||||
|
||||
Here `XYZ` is a device name of SD card, as recognized by Linux (sdb in my case).
|
||||
@@ -154,13 +160,3 @@ $ ./pic32
|
||||
```
|
||||
|
||||
Configuration of simulated board is stored in file `pic32_max32.conf`.
|
||||
|
||||
## Build packages
|
||||
|
||||
|
||||
For building under Ubuntu you need the following packages installed:
|
||||
|
||||
```shell
|
||||
$ sudo apt-get install byacc libelf-dev
|
||||
```
|
||||
|
||||
|
||||
2
cross.mk
2
cross.mk
@@ -1,7 +1,7 @@
|
||||
DESTDIR = /usr/local/retrobsd
|
||||
MACHINE = mips
|
||||
|
||||
CC = gcc
|
||||
CC = gcc -m32
|
||||
|
||||
AS = $(CC) -x assembler-with-cpp
|
||||
LD = ld
|
||||
|
||||
1
etc/.gitignore
vendored
1
etc/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
phones
|
||||
remote
|
||||
termcap
|
||||
termcap.full
|
||||
|
||||
16
etc/ttys
16
etc/ttys
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# name getty type status comments
|
||||
#
|
||||
console "/libexec/getty std.default" vt100 on secure #special
|
||||
console "/libexec/getty std.default" xterm on secure #special
|
||||
|
||||
# Enable some of these for additional logins. Do NOT enable the same one as the
|
||||
# console port, or strange things will happen. You can turn off the console port
|
||||
# if you would rather use the getty on the real tty - it's up to you.
|
||||
|
||||
tty0 "/libexec/getty std.default" vt100 off secure
|
||||
tty1 "/libexec/getty std.default" vt100 off secure
|
||||
tty2 "/libexec/getty std.default" vt100 off secure
|
||||
tty3 "/libexec/getty std.default" vt100 off secure
|
||||
tty4 "/libexec/getty std.default" vt100 off secure
|
||||
tty5 "/libexec/getty std.default" vt100 off secure
|
||||
ttyUSB0 "/libexec/getty std.default" vt100 off secure
|
||||
tty0 "/libexec/getty std.default" xterm off secure
|
||||
tty1 "/libexec/getty std.default" xterm off secure
|
||||
tty2 "/libexec/getty std.default" xterm off secure
|
||||
tty3 "/libexec/getty std.default" xterm off secure
|
||||
tty4 "/libexec/getty std.default" xterm off secure
|
||||
tty5 "/libexec/getty std.default" xterm off secure
|
||||
ttyUSB0 "/libexec/getty std.default" xterm off secure
|
||||
|
||||
@@ -181,6 +181,10 @@ int waddstr (WINDOW *, char *);
|
||||
int wgetstr (WINDOW *, char *);
|
||||
int wdeleteln (WINDOW *);
|
||||
void mvcur(int ly, int lx, int y, int x);
|
||||
void overwrite(WINDOW *win1, WINDOW *win2);
|
||||
void wclrtobot(WINDOW *win);
|
||||
int mvprintw(int y, int x, char *fmt, ...);
|
||||
int mvwprintw(WINDOW *win, int y, int x, char *fmt, ...);
|
||||
|
||||
/*
|
||||
* Used to be in unctrl.h.
|
||||
|
||||
@@ -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
|
||||
|
||||
863
rootfs.manifest
Normal file
863
rootfs.manifest
Normal file
@@ -0,0 +1,863 @@
|
||||
#
|
||||
# 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/lv
|
||||
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/atc
|
||||
file /games/backgammon
|
||||
file /games/banner
|
||||
file /games/battlestar
|
||||
file /games/bcd
|
||||
file /games/boggle
|
||||
file /games/btlgammon
|
||||
file /games/canfield
|
||||
file /games/cfscores
|
||||
file /games/cribbage
|
||||
file /games/factor
|
||||
file /games/fish
|
||||
file /games/fortune
|
||||
file /games/hangman
|
||||
file /games/mille
|
||||
file /games/monop
|
||||
file /games/morse
|
||||
file /games/number
|
||||
file /games/ppt
|
||||
file /games/primes
|
||||
file /games/quiz
|
||||
file /games/rain
|
||||
file /games/robots
|
||||
file /games/rogue
|
||||
file /games/sail
|
||||
file /games/snake
|
||||
file /games/snscore
|
||||
file /games/teachgammon
|
||||
file /games/trek
|
||||
file /games/worm
|
||||
file /games/worms
|
||||
file /games/wump
|
||||
|
||||
#
|
||||
# Files: /games/lib
|
||||
#
|
||||
default
|
||||
filemode 0444
|
||||
dir /games/lib
|
||||
file /games/lib/adventure.dat
|
||||
file /games/lib/battle_strings
|
||||
file /games/lib/backrules
|
||||
file /games/lib/bogdict
|
||||
file /games/lib/cfscores
|
||||
file /games/lib/crib.instr
|
||||
mode 0666
|
||||
file /games/lib/fortunes.dat
|
||||
file /games/lib/cards.pck
|
||||
file /games/lib/robots_roll
|
||||
mode 0666
|
||||
file /games/lib/snakerawscores
|
||||
mode 0666
|
||||
dir /games/lib/atc
|
||||
file /games/lib/atc/ATC_scores
|
||||
file /games/lib/atc/crossover
|
||||
file /games/lib/atc/default
|
||||
file /games/lib/atc/easy
|
||||
file /games/lib/atc/game_2
|
||||
file /games/lib/atc/Game_List
|
||||
file /games/lib/atc/Killer
|
||||
dir /games/lib/quiz.k
|
||||
file /games/lib/quiz.k/africa
|
||||
file /games/lib/quiz.k/america
|
||||
file /games/lib/quiz.k/areas
|
||||
file /games/lib/quiz.k/arith
|
||||
file /games/lib/quiz.k/asia
|
||||
file /games/lib/quiz.k/babies
|
||||
file /games/lib/quiz.k/bard
|
||||
file /games/lib/quiz.k/chinese
|
||||
file /games/lib/quiz.k/collectives
|
||||
file /games/lib/quiz.k/ed
|
||||
file /games/lib/quiz.k/elements
|
||||
file /games/lib/quiz.k/europe
|
||||
file /games/lib/quiz.k/greek
|
||||
file /games/lib/quiz.k/inca
|
||||
file /games/lib/quiz.k/index
|
||||
file /games/lib/quiz.k/latin
|
||||
file /games/lib/quiz.k/locomotive
|
||||
file /games/lib/quiz.k/midearth
|
||||
file /games/lib/quiz.k/morse
|
||||
file /games/lib/quiz.k/murders
|
||||
file /games/lib/quiz.k/poetry
|
||||
file /games/lib/quiz.k/posneg
|
||||
file /games/lib/quiz.k/pres
|
||||
file /games/lib/quiz.k/province
|
||||
file /games/lib/quiz.k/seq-easy
|
||||
file /games/lib/quiz.k/seq-hard
|
||||
file /games/lib/quiz.k/sexes
|
||||
file /games/lib/quiz.k/sov
|
||||
file /games/lib/quiz.k/spell
|
||||
file /games/lib/quiz.k/state
|
||||
file /games/lib/quiz.k/trek
|
||||
file /games/lib/quiz.k/ucc
|
||||
|
||||
#
|
||||
# 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/dict
|
||||
dir /share/misc
|
||||
file /share/emg.keys
|
||||
file /share/re.help
|
||||
file /share/dict/words
|
||||
file /share/misc/more.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: /share/smallerc
|
||||
#
|
||||
dir /share/smallerc
|
||||
file /share/smallerc/adc.c
|
||||
file /share/smallerc/gpio.c
|
||||
file /share/smallerc/hello.c
|
||||
file /share/smallerc/Makefile
|
||||
file /share/smallerc/primelist.c
|
||||
file /share/smallerc/primesum.c
|
||||
file /share/smallerc/q8.c
|
||||
file /share/smallerc/rain.c
|
||||
file /share/smallerc/test1.c
|
||||
file /share/smallerc/test2.c
|
||||
file /share/smallerc/test3.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/lv.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/atc.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/cribbage.0
|
||||
file /share/man/cat6/fish.0
|
||||
file /share/man/cat6/fortune.0
|
||||
file /share/man/cat6/hangman.0
|
||||
file /share/man/cat6/mille.0
|
||||
file /share/man/cat6/monop.0
|
||||
file /share/man/cat6/number.0
|
||||
file /share/man/cat6/quiz.0
|
||||
file /share/man/cat6/rain.0
|
||||
file /share/man/cat6/robots.0
|
||||
file /share/man/cat6/rogue.0
|
||||
file /share/man/cat6/sail.0
|
||||
file /share/man/cat6/snake.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
|
||||
1
share/.gitignore
vendored
1
share/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
re.help
|
||||
misc
|
||||
unixbench
|
||||
emg.keys
|
||||
|
||||
25486
share/dict/words
Normal file
25486
share/dict/words
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
|
||||
all: ashello echo chello
|
||||
all: ashello echo chello stdarg skeleton
|
||||
|
||||
ashello: ashello.o
|
||||
$(LD) ashello.o -o $@
|
||||
@@ -10,5 +10,11 @@ chello: chello.o
|
||||
echo: echo.o
|
||||
$(LD) $@.o -o $@
|
||||
|
||||
stdarg: stdarg.o
|
||||
$(CC) stdarg.o -o $@
|
||||
|
||||
skeleton: skeleton.o
|
||||
$(CC) skeleton.o -o $@
|
||||
|
||||
clean:
|
||||
rm -f *.o ashello echo chello *.dis *~
|
||||
rm -f *.o ashello echo chello stdarg skeleton *.dis *~
|
||||
|
||||
3
share/man/.gitignore
vendored
3
share/man/.gitignore
vendored
@@ -0,0 +1,3 @@
|
||||
makewhatis.sed
|
||||
man.template
|
||||
whatis
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
extern int printf();
|
||||
|
||||
int main()
|
||||
main()
|
||||
{
|
||||
printf ("Hello, SmallC World!\n");
|
||||
}
|
||||
|
||||
38
share/smallerc/Makefile
Normal file
38
share/smallerc/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
CC = cc
|
||||
PROG = hello primelist primesum test1 test2 test3 gpio adc rain \
|
||||
q8
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
hello: hello.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) hello.c
|
||||
|
||||
primelist: primelist.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) primelist.c
|
||||
|
||||
primesum: primesum.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) primesum.c
|
||||
|
||||
gpio: gpio.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) gpio.c
|
||||
|
||||
adc: adc.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) adc.c
|
||||
|
||||
rain: rain.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) rain.c
|
||||
|
||||
q8: q8.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) q8.c
|
||||
|
||||
test1: test1.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) test1.c
|
||||
|
||||
test2: test2.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) test2.c
|
||||
|
||||
test3: test3.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) test3.c
|
||||
|
||||
clean:
|
||||
rm -f *.o $(PROG)
|
||||
29
share/smallerc/adc.c
Normal file
29
share/smallerc/adc.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Example of reading ADC data.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char buf[100];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i, fd, value;
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
sprintf(buf, "/dev/adc%d", i);
|
||||
fd = open(buf, O_RDWR);
|
||||
if (fd < 0) {
|
||||
printf("Error: unable to open %s\n", buf);
|
||||
} else {
|
||||
if (read(fd, buf, 20) > 0) {
|
||||
value = strtol (buf, 0, 0);
|
||||
printf("adc%-2d = %d\n", i, value);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
26
share/smallerc/gpio.c
Normal file
26
share/smallerc/gpio.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Example of polling general purpose i/o pins.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/gpio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fd, pnum, value;
|
||||
|
||||
fd = open ("/dev/porta", O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror ("/dev/porta");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (pnum=0; pnum<7; pnum++) {
|
||||
value = ioctl (fd, GPIO_POLL | GPIO_PORT (pnum), 0);
|
||||
if (value < 0)
|
||||
perror ("GPIO_POLL");
|
||||
printf ("port%c = 0x%04x\n", pnum + 'A', value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
6
share/smallerc/hello.c
Normal file
6
share/smallerc/hello.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Hello, Smaller C World!\n");
|
||||
}
|
||||
35
share/smallerc/primelist.c
Normal file
35
share/smallerc/primelist.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Print the list of prime numbers up to 100.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
int isprime(int);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n=2; n<100; ++n) {
|
||||
if (isprime(n)) {
|
||||
printf("%d ", n);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int isprime(int n)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (n == 2)
|
||||
return 1;
|
||||
|
||||
if (n % 2 == 0)
|
||||
return 0;
|
||||
|
||||
for (j=3; j*j<=n; j+=2)
|
||||
if (n % j == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
35
share/smallerc/primesum.c
Normal file
35
share/smallerc/primesum.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Compute the sum of prime numbers up to 10000.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
int isprime(int);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int sum, n;
|
||||
|
||||
sum = 0;
|
||||
for (n=2; n<10000; ++n) {
|
||||
if (isprime(n)) {
|
||||
sum += n;
|
||||
}
|
||||
}
|
||||
printf("Sum of primes less than 10000: %d\n", sum);
|
||||
}
|
||||
|
||||
int isprime(int n)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (n == 2)
|
||||
return 1;
|
||||
|
||||
if (n % 2 == 0)
|
||||
return 0;
|
||||
|
||||
for (j=3; j*j<=n; j+=2)
|
||||
if (n % j == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
209
share/smallerc/q8.c
Normal file
209
share/smallerc/q8.c
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Eight Queens puzzle
|
||||
*
|
||||
* (C) 2010 by Mark Sproul
|
||||
* Open source as per standard Arduino code
|
||||
* Modified by Pito 12/2012 for SmallC and then by Alexey Frunze for Smaller C
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
unsigned int gChessBoard[8];
|
||||
unsigned int gLoopCounter;
|
||||
int gValidCount;
|
||||
|
||||
int CheckCurrentBoard(void)
|
||||
{
|
||||
int ii;
|
||||
int jj;
|
||||
int theRow;
|
||||
int theLongRow;
|
||||
int theLongColumns;
|
||||
int bitCount;
|
||||
|
||||
//* we know we have 1 in each row,
|
||||
//* Check for 1 in each column
|
||||
theRow = 0;
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theRow |= gChessBoard[ii];
|
||||
}
|
||||
if (theRow != 0x0ff) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//* we have 1 in each column, now check the diagonals
|
||||
theLongColumns = 0;
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theLongRow = gChessBoard[ii] & 0x0ff;
|
||||
theLongRow = theLongRow << ii;
|
||||
|
||||
theLongColumns |= theLongRow;
|
||||
}
|
||||
|
||||
//* now count the bits
|
||||
bitCount = 0;
|
||||
for (ii=0; ii<16; ii++) {
|
||||
if ((theLongColumns & 0x01) == 0x01) {
|
||||
bitCount++;
|
||||
}
|
||||
theLongColumns = theLongColumns >> 1;
|
||||
}
|
||||
|
||||
if (bitCount != 8) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//* we now have to check the other diagonal
|
||||
theLongColumns = 0;
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theLongRow = gChessBoard[ii] & 0x0ff;
|
||||
theLongRow = theLongRow << 8;
|
||||
theLongRow = theLongRow >> ii;
|
||||
|
||||
theLongColumns |= theLongRow;
|
||||
}
|
||||
|
||||
//* now count the bits
|
||||
bitCount = 0;
|
||||
for (ii=0; ii<16; ii++) {
|
||||
if ((theLongColumns & 0x01) == 0x01) {
|
||||
bitCount++;
|
||||
}
|
||||
theLongColumns = theLongColumns >> 1;
|
||||
}
|
||||
|
||||
if (bitCount != 8) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CheckForDone(void)
|
||||
{
|
||||
int ii;
|
||||
int weAreDone;
|
||||
int theRow;
|
||||
|
||||
weAreDone = FALSE;
|
||||
|
||||
//* we know we have 1 in each row,
|
||||
//* Check for 1 in each column
|
||||
theRow = 0;
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theRow |= gChessBoard[ii];
|
||||
}
|
||||
|
||||
if (theRow == 0x01) {
|
||||
weAreDone = TRUE;
|
||||
}
|
||||
return weAreDone;
|
||||
}
|
||||
|
||||
void RotateQueens(void)
|
||||
{
|
||||
int ii;
|
||||
int keepGoing;
|
||||
int theRow;
|
||||
|
||||
ii = 0;
|
||||
keepGoing = TRUE;
|
||||
while (keepGoing && (ii < 8)) {
|
||||
theRow = gChessBoard[ii] & 0x0ff;
|
||||
theRow = (theRow >> 1) & 0x0ff;
|
||||
if (theRow != 0) {
|
||||
gChessBoard[ii] = theRow;
|
||||
keepGoing = FALSE;
|
||||
} else {
|
||||
gChessBoard[ii] = 0x080;
|
||||
}
|
||||
ii++;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintChessBoard(void)
|
||||
{
|
||||
int ii;
|
||||
int jj;
|
||||
int theRow;
|
||||
char textString[32];
|
||||
|
||||
printf("\nLoop= %d\n", gLoopCounter);
|
||||
printf("Solution count= %d\n", gValidCount);
|
||||
|
||||
printf("+----------------+\n");
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theRow = gChessBoard[ii];
|
||||
|
||||
printf("|");
|
||||
for (jj=0; jj<8; jj++) {
|
||||
if (theRow & 0x080) {
|
||||
printf("Q ");
|
||||
} else {
|
||||
printf(". ");
|
||||
}
|
||||
theRow = theRow << 1;
|
||||
}
|
||||
printf("|\n");
|
||||
}
|
||||
printf("+----------------+\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int ii;
|
||||
|
||||
printf("\nEight Queens brute force");
|
||||
printf("\n************************\n");
|
||||
//* put the 8 queens on the board, 1 in each row
|
||||
for (ii=0; ii<8; ii++) {
|
||||
gChessBoard[ii] = 0x080;
|
||||
}
|
||||
PrintChessBoard();
|
||||
|
||||
gLoopCounter = 0;
|
||||
gValidCount = 0;
|
||||
|
||||
|
||||
while (1) {
|
||||
gLoopCounter++;
|
||||
|
||||
if (CheckCurrentBoard()) {
|
||||
gValidCount++;
|
||||
PrintChessBoard();
|
||||
} else if ((gLoopCounter % 1000) == 0) {
|
||||
//PrintChessBoard();
|
||||
}
|
||||
|
||||
RotateQueens();
|
||||
if (CheckForDone()) {
|
||||
//int elapsedSeconds;
|
||||
//int elapsedMinutes;
|
||||
//int elapsedHours;
|
||||
|
||||
//elapsedSeconds = millis() / 1000;
|
||||
//elapsedMinutes = elapsedSeconds / 60;
|
||||
//elapsedHours = elapsedMinutes / 60;
|
||||
|
||||
printf("----------------------------------\n");
|
||||
printf("All done\n");
|
||||
|
||||
PrintChessBoard();
|
||||
printf("----------------------------------\n");
|
||||
|
||||
//Serial.print("total seconds=");
|
||||
//Serial.println(elapsedSeconds);
|
||||
|
||||
//Serial.print("hours=");
|
||||
//Serial.println(elapsedHours);
|
||||
|
||||
//Serial.print("minutes=");
|
||||
//Serial.println(elapsedMinutes % 60);
|
||||
|
||||
//Serial.print("seconds=");
|
||||
//Serial.println(elapsedSeconds % 60);
|
||||
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
129
share/smallerc/rain.c
Normal file
129
share/smallerc/rain.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Example of using termcap library for SmallC.
|
||||
* 11/3/1980 EPS/CITHEP
|
||||
*
|
||||
* Copyright (c) 1980 Regents of the University of California.
|
||||
* All rights reserved. The Berkeley software License Agreement
|
||||
* specifies the terms and conditions for redistribution.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define CO 80 /* number of columns */
|
||||
#define LI 24 /* number of lines */
|
||||
|
||||
#define CL "\33[H\33[J" /* clear the screen */
|
||||
#define CM "\33[%u;%uH" /* move the cursor to row, column */
|
||||
#define BC "\b" /* move cursor left */
|
||||
#define DN "\33[B" /* move cursor down */
|
||||
#define ND " " /* move cursor right */
|
||||
|
||||
int xpos[5], ypos[5];
|
||||
char outbuf[BUFSIZ];
|
||||
|
||||
void moveto(int col, int row)
|
||||
{
|
||||
printf(CM, row, col);
|
||||
}
|
||||
|
||||
void onsig(int n)
|
||||
{
|
||||
moveto(0, LI - 1);
|
||||
fflush(stdout);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x, y, j;
|
||||
|
||||
setbuf(stdout, outbuf);
|
||||
for (j = SIGHUP; j <= SIGTERM; j++)
|
||||
if (signal(j, SIG_IGN) != SIG_IGN)
|
||||
signal(j, onsig);
|
||||
|
||||
fputs(CL, stdout);
|
||||
fflush(stdout);
|
||||
for (j = 5; --j >= 0; ) {
|
||||
xpos[j] = 2 + rand() % (CO - 4);
|
||||
ypos[j] = 2 + rand() % (LI - 4);
|
||||
}
|
||||
for (j = 0; ; ) {
|
||||
x = 2 + rand() % (CO - 4);
|
||||
y = 2 + rand() % (LI - 4);
|
||||
moveto(x, y);
|
||||
putchar('.');
|
||||
moveto(xpos[j], ypos[j]);
|
||||
putchar('o');
|
||||
if (j == 0)
|
||||
j = 4;
|
||||
else
|
||||
--j;
|
||||
moveto(xpos[j], ypos[j]);
|
||||
putchar('O');
|
||||
if (j == 0)
|
||||
j = 4;
|
||||
else
|
||||
--j;
|
||||
moveto(xpos[j], ypos[j]-1);
|
||||
putchar('-');
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs("|.|", stdout);
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
putchar('-');
|
||||
if (j == 0)
|
||||
j = 4;
|
||||
else
|
||||
--j;
|
||||
moveto(xpos[j], ypos[j]-2);
|
||||
putchar('-');
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs("/ \\", stdout);
|
||||
moveto(xpos[j]-2, ypos[j]);
|
||||
fputs("| O |", stdout);
|
||||
moveto(xpos[j]-1, ypos[j]+1);
|
||||
fputs("\\ /", stdout);
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
putchar('-');
|
||||
if (j == 0)
|
||||
j = 4;
|
||||
else
|
||||
--j;
|
||||
moveto(xpos[j], ypos[j]-2);
|
||||
putchar(' ');
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
putchar(' ');
|
||||
fputs(ND, stdout);
|
||||
putchar(' ');
|
||||
moveto(xpos[j]-2, ypos[j]);
|
||||
putchar(' ');
|
||||
fputs(ND, stdout);
|
||||
putchar(' ');
|
||||
fputs(ND, stdout);
|
||||
putchar(' ');
|
||||
moveto(xpos[j]-1, ypos[j]+1);
|
||||
putchar(' ');
|
||||
fputs(ND, stdout);
|
||||
putchar(' ');
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
putchar(' ');
|
||||
xpos[j] = x;
|
||||
ypos[j] = y;
|
||||
fflush(stdout);
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
214
share/smallerc/test1.c
Normal file
214
share/smallerc/test1.c
Normal file
@@ -0,0 +1,214 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int ga[5];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int a, b, c, d;
|
||||
int arr[5];
|
||||
int *pi;
|
||||
char arrc[5];
|
||||
char *pic;
|
||||
int s1, s2;
|
||||
int z;
|
||||
int t;
|
||||
int *pip;
|
||||
int *picp;
|
||||
int e1, e2;
|
||||
|
||||
ga[0] = 10;
|
||||
ga[1] = 20;
|
||||
ga[2] = 30;
|
||||
ga[3] = 40;
|
||||
ga[4] = 50;
|
||||
|
||||
a = 21;
|
||||
b = 31;
|
||||
c = 71;
|
||||
d = 82;
|
||||
|
||||
arr[0] = 10;
|
||||
arr[1] = 20;
|
||||
arr[2] = 30;
|
||||
arr[3] = 40;
|
||||
arr[4] = 50;
|
||||
pi = &arr[0];
|
||||
|
||||
arrc[0] = 13;
|
||||
arrc[1] = 23;
|
||||
arrc[2] = 33;
|
||||
arrc[3] = 43;
|
||||
arrc[4] = 53;
|
||||
pic = &arrc[0];
|
||||
|
||||
printf(" 21 + 31 = %d (52)\n", a + b);
|
||||
printf(" 21 - 31 = %d (-10)\n", a - b);
|
||||
printf(" 21 & 71 = %d (5)\n", a & c);
|
||||
printf(" 21 | 82 = %d (87)\n", a | d);
|
||||
printf(" 21 ^ 82 = %d (71)\n", a ^ d);
|
||||
printf(" 21 * 82 = %d (1722)\n", a * d);
|
||||
printf(" 82 %% 21 = %d (19)\n", d % a);
|
||||
printf(" 82 / 21 = %d (3)\n", d / a);
|
||||
printf(" *pi = %d (10)\n", *pi);
|
||||
printf(" *pi + 1 = %d (11)\n", *pi + 1);
|
||||
printf(" *(pi + 1) = %d (20)\n", *(pi + 1));
|
||||
printf("&arr[3] - &arr[0] = %d (3)\n", &arr[3] - &arr[0]);
|
||||
printf(" arr[3]-arr[0] = %d (30)\n", arr[3] - arr[0]);
|
||||
printf(" arr[3]+arr[0] = %d (50)\n", arr[3] + arr[0]);
|
||||
printf(" &ga[3] - &ga[0] = %d (3)\n", &ga[3] - &ga[0]);
|
||||
printf(" ga[3]-ga[0] = %d (30)\n", ga[3] - ga[0]);
|
||||
printf(" ga[3]+ga[0] = %d (50)\n", ga[3] + ga[0]);
|
||||
printf("\n");
|
||||
|
||||
printf(" *pic = %d (13)\n", *pic);
|
||||
printf(" *pic + 1 = %d (14)\n", *pic+1);
|
||||
printf(" *(pic + 1) = %d (23)\n", *(pic+1));
|
||||
printf("&arrc[3] - &arrc[0] = %d (3)\n", &arrc[3]-&arrc[0]);
|
||||
printf("\n");
|
||||
|
||||
s1 = 3;
|
||||
s2 = -200;
|
||||
printf(" 82 << 3 = %d (656)\n", d << s1);
|
||||
printf(" 82 >> 3 = %d (10)\n", d >> s1);
|
||||
printf("-200 >> 3 = %d (-25)\n", s2 >> s1);
|
||||
printf("-200 << 3 = %d (-1600)\n", s2 << s1);
|
||||
printf("\n");
|
||||
|
||||
printf("-s1 = %d (-3)\n", -s1);
|
||||
printf("-s2 = %d (200)\n", -s2);
|
||||
printf("\n");
|
||||
|
||||
printf("~82 = %d (-83)\n", ~d);
|
||||
printf("\n");
|
||||
|
||||
z = 0;
|
||||
printf("!82 = %d (0)\n", !d);
|
||||
printf(" !0 = %d (1)\n", !z);
|
||||
printf("\n");
|
||||
|
||||
printf(" 0 && 0 = %d (0)\n", z && z);
|
||||
printf(" 0 && 21 = %d (0)\n", z && a);
|
||||
printf(" 3 && 21 = %d (1)\n", s1 && a);
|
||||
printf("21 && 3 = %d (1)\n", a && s1);
|
||||
printf("\n");
|
||||
|
||||
printf(" 0 || 0 = %d (0)\n", z || z);
|
||||
printf(" 0 || 21 = %d (1)\n", z || a);
|
||||
printf(" 3 || 21 = %d (1)\n", s1 || a);
|
||||
printf("21 || 3 = %d (1)\n", a || s1);
|
||||
printf("\n");
|
||||
|
||||
pi = 4;
|
||||
printf("pi++ = %d (4)\n", pi++);
|
||||
printf(" pi = %d (8)\n", pi);
|
||||
printf("++pi = %d (12)\n", ++pi);
|
||||
printf("pi-- = %d (12)\n", pi--);
|
||||
printf(" pi = %d (8)\n", pi);
|
||||
printf("--pi = %d (4)\n", --pi);
|
||||
printf("\n");
|
||||
|
||||
pic = 4;
|
||||
printf("pic++ = %d (4)\n", pic++);
|
||||
printf(" pic = %d (5)\n", pic);
|
||||
printf("++pic = %d (6)\n", ++pic);
|
||||
printf("pic-- = %d (6)\n", pic--);
|
||||
printf(" pic = %d (5)\n", pic);
|
||||
printf("--pic = %d (4)\n", --pic);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf("t++ = %d (4)\n", t++);
|
||||
printf(" t = %d (5)\n", t);
|
||||
printf("++t = %d (6)\n", ++t);
|
||||
printf("t-- = %d (6)\n", t--);
|
||||
printf(" t = %d (5)\n", t);
|
||||
printf("--t = %d (4)\n", --t);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf(" t==4 = %d (1)\n", t == 4);
|
||||
printf(" t==3 = %d (0)\n", t == 3);
|
||||
printf(" t==5 = %d (0)\n", t == 5);
|
||||
t = -4;
|
||||
printf("t==-4 = %d (1)\n", t == -4);
|
||||
printf("t==-3 = %d (0)\n", t == -3);
|
||||
printf("t==-5 = %d (0)\n", t == -5);
|
||||
printf(" t==4 = %d (0)\n", t == 4);
|
||||
printf(" t==3 = %d (0)\n", t == 3);
|
||||
printf(" t==5 = %d (0)\n", t == 5);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf(" t!=4 = %d (0)\n", t != 4);
|
||||
printf(" t!=3 = %d (1)\n", t != 3);
|
||||
printf(" t!=5 = %d (1)\n", t != 5);
|
||||
t = -4;
|
||||
printf("t!=-4 = %d (0)\n", t != -4);
|
||||
printf("t!=-3 = %d (1)\n", t != -3);
|
||||
printf("t!=-5 = %d (1)\n", t != -5);
|
||||
printf(" t!=4 = %d (1)\n", t != 4);
|
||||
printf(" t!=3 = %d (1)\n", t != 3);
|
||||
printf(" t!=5 = %d (1)\n", t != 5);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf(" t<4 = %d (0)\n", t < 4);
|
||||
printf(" t<3 = %d (0)\n", t < 3);
|
||||
printf(" t<5 = %d (1)\n", t < 5);
|
||||
printf("t<-1 = %d (0)\n", t < -1);
|
||||
printf("\n");
|
||||
|
||||
printf(" t<=4 = %d (1)\n", t <= 4);
|
||||
printf(" t<=3 = %d (0)\n", t <= 3);
|
||||
printf(" t<=5 = %d (1)\n", t <= 5);
|
||||
printf("t<=-1 = %d (0)\n", t <= -1);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf(" t>4 = %d (0)\n", t > 4);
|
||||
printf(" t>3 = %d (1)\n", t > 3);
|
||||
printf(" t>5 = %d (0)\n", t > 5);
|
||||
printf("t>-1 = %d (1)\n", t > -1);
|
||||
printf("\n");
|
||||
|
||||
printf(" t>=4 = %d (1)\n", t >= 4);
|
||||
printf(" t>=3 = %d (1)\n", t >= 3);
|
||||
printf(" t>=5 = %d (0)\n", t >= 5);
|
||||
printf("t>=-1 = %d (1)\n", t >= -1);
|
||||
printf("\n");
|
||||
|
||||
pi = -100;
|
||||
printf(" pi<4 = %d (0)\n", pi < (int*)4);
|
||||
printf(" pi<3 = %d (0)\n", pi < (int*)3);
|
||||
printf("pi<-100 = %d (0)\n", pi < (int*)-100);
|
||||
printf(" pi<-1 = %d (1)\n", pi < (int*)-1);
|
||||
printf("\n");
|
||||
|
||||
printf(" pi<=4 = %d (0)\n", pi <= (int*)4);
|
||||
printf(" pi<=3 = %d (0)\n", pi <= (int*)3);
|
||||
printf("pi<=-100 = %d (1)\n", pi <= (int*)-100);
|
||||
printf(" pi<=-1 = %d (1)\n", pi <= (int*)-1);
|
||||
printf("\n");
|
||||
|
||||
pi = -100;
|
||||
printf(" pi>4 = %d (1)\n", pi > (int*)4);
|
||||
printf(" pi>3 = %d (1)\n", pi > (int*)3);
|
||||
printf("pi>-100 = %d (0)\n", pi > (int*)-100);
|
||||
printf(" pi>-1 = %d (0)\n", pi > (int*)-1);
|
||||
printf("\n");
|
||||
|
||||
printf(" pi>=4 = %d (1)\n", pi >= (int*)4);
|
||||
printf(" pi>=3 = %d (1)\n", pi >= (int*)3);
|
||||
printf("pi>=-100 = %d (1)\n", pi >= (int*)-100);
|
||||
printf(" pi>=-1 = %d (0)\n", pi >= (int*)-1);
|
||||
printf("\n");
|
||||
|
||||
pi = &arr[0];
|
||||
pip = &arr[3];
|
||||
printf(" *pip - *pi: %d (30)\n", *pip - *pi);
|
||||
printf(" pip - pi: %d (3)\n", pip - pi);
|
||||
printf(" *pip: %d (40)\n", *pip);
|
||||
printf(" *(pip - 3): %d (10)\n", *(pip - 3));
|
||||
printf(" *&arr[3]: %d (40)\n", *&arr[3]);
|
||||
printf("*(&arr[3] - 3): %d (10)\n", *(&arr[3]-3));
|
||||
}
|
||||
128
share/smallerc/test2.c
Normal file
128
share/smallerc/test2.c
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int aaa;
|
||||
int bbb;
|
||||
int ccc;
|
||||
char gc;
|
||||
char gbuffer[3];
|
||||
int gibuffer[4];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char b;
|
||||
int la;
|
||||
unsigned int u1, u2;
|
||||
int s1, s2;
|
||||
unsigned char uc1, uc2;
|
||||
char sc1, sc2;
|
||||
int fd;
|
||||
char buffer[6];
|
||||
int ibuffer[7];
|
||||
|
||||
printf(" sizeof(uc1): %d 1\n", sizeof(uc1));
|
||||
printf(" sizeof(sc1): %d 1\n", sizeof(sc1));
|
||||
printf(" sizeof(u1): %d 4\n", sizeof(u1));
|
||||
printf(" sizeof(s1): %d 4\n", sizeof(s1));
|
||||
printf(" sizeof(aaa): %d 4\n", sizeof(aaa));
|
||||
printf(" sizeof(bbb): %d 4\n", sizeof(bbb));
|
||||
printf(" sizeof(gc): %d 1\n", sizeof(gc));
|
||||
printf(" sizeof(buffer): %d 6\n", sizeof(buffer));
|
||||
printf(" sizeof(ibuffer): %d 28\n", sizeof(ibuffer));
|
||||
printf(" sizeof(char): %d 1\n", sizeof(char));
|
||||
printf(" sizeof(int): %d 4\n", sizeof(int));
|
||||
printf(" sizeof(gbuffer): %d 3\n", sizeof(gbuffer));
|
||||
printf(" sizeof(gibuffer): %d 16\n", sizeof(gibuffer));
|
||||
// sizeof(ibuffer[0]) is not supported, so the following can be used...
|
||||
printf("sizeof(ibuffer)/sizeof(int): %d 7\n", sizeof(ibuffer)/sizeof(int));
|
||||
|
||||
aaa = 1;
|
||||
bbb = 2;
|
||||
la = 4;
|
||||
printf("%d 1\n", aaa);
|
||||
printf("%d 2\n", bbb);
|
||||
printf("%d 4\n", la);
|
||||
|
||||
uc1 = 0x80;
|
||||
sc1 = 0x80;
|
||||
s1 = uc1;
|
||||
s2 = sc1;
|
||||
printf("unsigned char (0x80) -> int: %d 128\n", s1);
|
||||
printf(" signed char (0x80) -> int: %d -128\n", s2);
|
||||
|
||||
u1 = uc1;
|
||||
u2 = sc1;
|
||||
printf("unsigned char (0x80) -> unsigned: %d 128\n", u1);
|
||||
printf(" signed char (0x80) -> unsigned: %d -128\n", u2);
|
||||
|
||||
la = errno;
|
||||
printf("errno: %d 0\n", la);
|
||||
|
||||
write(1, "abcd ", 5);
|
||||
la = errno;
|
||||
printf("errno after good write call: %d 0\n", la);
|
||||
|
||||
write(10, "abcde", 5);
|
||||
la = errno;
|
||||
printf("errno after bad write call: %d 9\n", la);
|
||||
|
||||
write(1, "abcd ", 5);
|
||||
la = errno;
|
||||
printf("good write after failed should not overwrite errno: %d 9\n", la);
|
||||
|
||||
errno = 0;
|
||||
write(1, "abcd ", 5);
|
||||
la = errno;
|
||||
printf("good write after errno set to zero: %d 0\n", la);
|
||||
|
||||
la = write(1, "abcd ", 5);
|
||||
printf("write() return: %d 5\n", la);
|
||||
|
||||
la = write(10, "abcd ", 5);
|
||||
printf("write(bad fd) return: %d -1\n", la);
|
||||
|
||||
fd = open("/a.txt", O_WRONLY | O_CREAT, 0666);
|
||||
if (fd != -1) {
|
||||
printf("open success\n");
|
||||
la = write(fd, "abcd\n", 5);
|
||||
if (la == 5) printf("write success\n"); else printf("write failed\n");
|
||||
la = close(fd);
|
||||
if (la != -1) printf("close success\n"); else printf("close failed\n");
|
||||
} else {
|
||||
printf("open failed\n");
|
||||
}
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
buffer[4] = 0;
|
||||
buffer[5] = 0;
|
||||
|
||||
fd = open("/a.txt", O_RDONLY, 0666);
|
||||
if (fd != -1) {
|
||||
printf("open success\n");
|
||||
la = read(fd, buffer, 5);
|
||||
printf(buffer);
|
||||
if (la == 5) printf("read success\n"); else printf("read failed\n");
|
||||
la = close(fd);
|
||||
if (la != -1) printf("close success\n"); else printf("close failed\n");
|
||||
} else {
|
||||
printf("open failed\n");
|
||||
}
|
||||
|
||||
if (buffer[0] != 'a') printf("data0 readback from file MISMATCH\n");
|
||||
if (buffer[1] != 'b') printf("data1 readback from file MISMATCH\n");
|
||||
if (buffer[2] != 'c') printf("data2 readback from file MISMATCH\n");
|
||||
if (buffer[3] != 'd') printf("data3 readback from file MISMATCH\n");
|
||||
if (buffer[4] != '\n') printf("data4 readback from file MISMATCH\n");
|
||||
|
||||
if (buffer[0] != 'a' || buffer[1] != 'b' || buffer[2] != 'c' ||
|
||||
buffer[3] != 'd' || buffer[4] != '\n') {
|
||||
printf("data readback from file MISMATCH\n");
|
||||
} else {
|
||||
printf("data readback from file OK\n");
|
||||
}
|
||||
}
|
||||
51
share/smallerc/test3.c
Normal file
51
share/smallerc/test3.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void printt(int t, char* str);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = 0;
|
||||
if (t) printt(t, "failure"); else printt(t, "success");
|
||||
t = 1;
|
||||
if (t) printt(t, "success"); else printt(t, "failure");
|
||||
t = 8;
|
||||
if (t) printt(t, "success"); else printt(t, "failure");
|
||||
t = -2;
|
||||
if (t) printt(t, "success"); else printt(t, "failure");
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf("switch test: ");
|
||||
switch (t) {
|
||||
case 3:
|
||||
printf("failure");
|
||||
break;
|
||||
case 4:
|
||||
printf("success");
|
||||
break;
|
||||
case 5:
|
||||
printf("failure");
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("switch fallthrough test: ");
|
||||
switch (t) {
|
||||
case 3:
|
||||
printf("failure");
|
||||
break;
|
||||
case 4:
|
||||
printf("OKSOFAR: ");
|
||||
case 5:
|
||||
printf("success if oksofar printed before this in caps");
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void printt(int t, char* str)
|
||||
{
|
||||
printf("bool test on value %d %s\n", t, str);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ include $(TOPSRC)/target.mk
|
||||
# Programs that live in subdirectories, and have makefiles of their own.
|
||||
#
|
||||
SUBDIR = startup-$(MACHINE) libc libm libutil libtermlib libcurses \
|
||||
libvmf libwiznet share cmd games
|
||||
libvmf libwiznet share cmd games man
|
||||
|
||||
all: $(SUBDIR)
|
||||
|
||||
|
||||
@@ -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 levee 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 \
|
||||
|
||||
1
src/cmd/aout/.gitignore
vendored
Normal file
1
src/cmd/aout/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
aout
|
||||
25
src/cmd/aout/Makefile
Normal file
25
src/cmd/aout/Makefile
Normal file
@@ -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/
|
||||
@@ -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 > $@
|
||||
|
||||
@@ -3,7 +3,7 @@ include $(TOPSRC)/target.mk
|
||||
#include $(TOPSRC)/cross.mk
|
||||
#CFLAGS = -DCROSS
|
||||
|
||||
OBJS = cpp.o cpy.o token.o doprnt.o
|
||||
OBJS = cpp.o cpy.o token.o compat.o doprnt.o
|
||||
MAN = cpp.0
|
||||
MANSRC = cpp.1
|
||||
|
||||
@@ -31,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) $<
|
||||
@@ -62,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
|
||||
|
||||
91
src/cmd/cpp/compat.c
Normal file
91
src/cmd/cpp/compat.c
Normal file
@@ -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 <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* 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 <string.h>
|
||||
|
||||
#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 */
|
||||
14
src/cmd/cpp/compat.h
Normal file
14
src/cmd/cpp/compat.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef COMPAT_H__
|
||||
#define COMPAT_H__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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__
|
||||
11
src/cmd/cpp/config.h
Normal file
11
src/cmd/cpp/config.h
Normal file
@@ -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__
|
||||
1654
src/cmd/cpp/cpp.c
1654
src/cmd/cpp/cpp.c
File diff suppressed because it is too large
Load Diff
@@ -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 </usr/include/stdio.h>
|
||||
# include </usr/include/ctype.h>
|
||||
#else
|
||||
# include <stdio.h> /* for obuf */
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* for obuf */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
939
src/cmd/cpp/scanner.l
Normal file
939
src/cmd/cpp/scanner.l
Normal file
@@ -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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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 */ }
|
||||
|
||||
<IFR>"++" { badop("++"); }
|
||||
<IFR>"--" { badop("--"); }
|
||||
<IFR>"==" { return EQ; }
|
||||
<IFR>"!=" { return NE; }
|
||||
<IFR>"<=" { return LE; }
|
||||
<IFR>"<<" { return LS; }
|
||||
<IFR>">>" { return RS; }
|
||||
<IFR>">=" { return GE; }
|
||||
<IFR>"||" { return OROR; }
|
||||
<IFR>"&&" { return ANDAND; }
|
||||
<IFR>"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;
|
||||
}
|
||||
|
||||
<IFR>{WS}+ { ; }
|
||||
<IFR>{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);
|
||||
}
|
||||
|
||||
<IFR>. { 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); }
|
||||
|
||||
<CONTR>"ifndef" { contr = 0; ifndefstmt(); }
|
||||
<CONTR>"ifdef" { contr = 0; ifdefstmt(); }
|
||||
<CONTR>"if" { contr = 0; storepb(); BEGIN IFR; ifstmt(); BEGIN 0; }
|
||||
<CONTR>"include" { contr = 0; BEGIN 0; include(); prtline(); }
|
||||
<CONTR>"else" { contr = 0; elsestmt(); }
|
||||
<CONTR>"endif" { contr = 0; endifstmt(); }
|
||||
<CONTR>"error" { contr = 0; if (slow) return IDENT; cpperror(); BEGIN 0; }
|
||||
<CONTR>"define" { contr = 0; BEGIN DEF; define(); BEGIN 0; }
|
||||
<CONTR>"undef" { contr = 0; if (slow) return IDENT; undefstmt(); }
|
||||
<CONTR>"line" { contr = 0; storepb(); BEGIN 0; line(); }
|
||||
<CONTR>"pragma" { contr = 0; pragmastmt(); BEGIN 0; }
|
||||
<CONTR>"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);
|
||||
}
|
||||
|
||||
<DEF>"##" { return CONCAT; }
|
||||
<DEF>"#" { return MKSTR; }
|
||||
<DEF>"..." { return ELLIPS; }
|
||||
<DEF>"__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 *)"<stdin>";
|
||||
}
|
||||
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();
|
||||
}
|
||||
22
src/cmd/cpp/tests/res11
Normal file
22
src/cmd/cpp/tests/res11
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
a
|
||||
a b
|
||||
a b c
|
||||
a b c d
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__attribute__((__noreturn__))
|
||||
|
||||
|
||||
1 2
|
||||
|
||||
21
src/cmd/cpp/tests/res12
Normal file
21
src/cmd/cpp/tests/res12
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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,
|
||||
13
src/cmd/cpp/tests/res13
Normal file
13
src/cmd/cpp/tests/res13
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
long
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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", "" };
|
||||
|
||||
|
||||
20
src/cmd/cpp/tests/test11
Normal file
20
src/cmd/cpp/tests/test11
Normal file
@@ -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() ())
|
||||
|
||||
19
src/cmd/cpp/tests/test12
Normal file
19
src/cmd/cpp/tests/test12
Normal file
@@ -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)
|
||||
11
src/cmd/cpp/tests/test13
Normal file
11
src/cmd/cpp/tests/test13
Normal file
@@ -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 */
|
||||
@@ -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 </usr/include/string.h>
|
||||
#else
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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 *)"<stdin>";
|
||||
ic->orgfn = ic->fname = (const usch *)"<stdin>";
|
||||
}
|
||||
#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();
|
||||
|
||||
1
src/cmd/emg/.gitignore
vendored
Normal file
1
src/cmd/emg/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
emg
|
||||
53
src/cmd/emg/ChangeLog
Normal file
53
src/cmd/emg/ChangeLog
Normal file
@@ -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 <ENTER> instead of <ESC>.
|
||||
<ESC> 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.
|
||||
49
src/cmd/emg/Makefile
Normal file
49
src/cmd/emg/Makefile
Normal file
@@ -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}
|
||||
41
src/cmd/emg/README
Normal file
41
src/cmd/emg/README
Normal file
@@ -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 <bcallah@openbsd.org>
|
||||
39
src/cmd/emg/README-ERSATZ
Normal file
39
src/cmd/emg/README-ERSATZ
Normal file
@@ -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,, <cjb@brushtail.apana.org.au>
|
||||
289
src/cmd/emg/basic.c
Normal file
289
src/cmd/emg/basic.c
Normal file
@@ -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 <stdlib.h> /* 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);
|
||||
}
|
||||
494
src/cmd/emg/buffer.c
Normal file
494
src/cmd/emg/buffer.c
Normal file
@@ -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 <stdlib.h> /* free(3), malloc(3) */
|
||||
#include <string.h> /* 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);
|
||||
}
|
||||
1015
src/cmd/emg/display.c
Normal file
1015
src/cmd/emg/display.c
Normal file
File diff suppressed because it is too large
Load Diff
67
src/cmd/emg/ebind.h
Normal file
67
src/cmd/emg/ebind.h
Normal file
@@ -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}
|
||||
};
|
||||
78
src/cmd/emg/edef.h
Normal file
78
src/cmd/emg/edef.h
Normal file
@@ -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
|
||||
65
src/cmd/emg/efunc.h
Normal file
65
src/cmd/emg/efunc.h
Normal file
@@ -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 */
|
||||
62
src/cmd/emg/emg.1
Normal file
62
src/cmd/emg/emg.1
Normal file
@@ -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.
|
||||
131
src/cmd/emg/emg.keys
Normal file
131
src/cmd/emg/emg.keys
Normal file
@@ -0,0 +1,131 @@
|
||||
emg keybindings (July 7, 2014)
|
||||
Based on Ersatz Emacs (2000/09/14)
|
||||
|
||||
M- means to use the <ESC> 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<number> or M-<number>
|
||||
Number prefix and universal repeat. May be followed by an integer
|
||||
(default = 4) and repeats the next command that many times.
|
||||
Exceptions follow.
|
||||
^U<number>^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<number>^X F
|
||||
Set the right margin to column <number> for paragraph formatting.
|
||||
^U<number>^X^
|
||||
Enlarge a split window by <number> rows. A negative number shrinks the
|
||||
window.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
SPECIAL KEYS
|
||||
|
||||
^G Cancel current command.
|
||||
^L Redraws the screen completely.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
191
src/cmd/emg/estruct.h
Normal file
191
src/cmd/emg/estruct.h
Normal file
@@ -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;
|
||||
465
src/cmd/emg/file.c
Normal file
465
src/cmd/emg/file.c
Normal file
@@ -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 <string.h> /* 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);
|
||||
}
|
||||
121
src/cmd/emg/fileio.c
Normal file
121
src/cmd/emg/fileio.c
Normal file
@@ -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 <stdio.h> /* 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);
|
||||
}
|
||||
507
src/cmd/emg/line.c
Normal file
507
src/cmd/emg/line.c
Normal file
@@ -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 <stdlib.h> /* 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);
|
||||
}
|
||||
469
src/cmd/emg/main.c
Normal file
469
src/cmd/emg/main.c
Normal file
@@ -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 <string.h> /* strncpy(3) */
|
||||
#include <stdlib.h> /* 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);
|
||||
}
|
||||
290
src/cmd/emg/random.c
Normal file
290
src/cmd/emg/random.c
Normal file
@@ -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);
|
||||
}
|
||||
142
src/cmd/emg/region.c
Normal file
142
src/cmd/emg/region.c
Normal file
@@ -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);
|
||||
}
|
||||
383
src/cmd/emg/search.c
Normal file
383
src/cmd/emg/search.c
Normal file
@@ -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 <string.h> /* 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 <NL> 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 <NL> */
|
||||
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 <patrn>
|
||||
*/
|
||||
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 <NL> */
|
||||
}
|
||||
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;
|
||||
}
|
||||
117
src/cmd/emg/tcap.c
Normal file
117
src/cmd/emg/tcap.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/* termios video driver */
|
||||
|
||||
#define termdef 1 /* don't define "term" externally */
|
||||
|
||||
#include <stdio.h> /* puts(3), snprintf(3) */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
#undef CTRL /* Needs to be done here. */
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
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);
|
||||
}
|
||||
163
src/cmd/emg/ttyio.c
Normal file
163
src/cmd/emg/ttyio.c
Normal file
@@ -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 <stdio.h>
|
||||
#include <sgtty.h>
|
||||
#include <stdlib.h>
|
||||
#include <term.h>
|
||||
#include <unistd.h>
|
||||
#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);
|
||||
}
|
||||
336
src/cmd/emg/window.c
Normal file
336
src/cmd/emg/window.c
Normal file
@@ -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 <stdlib.h> /* 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);
|
||||
}
|
||||
90
src/cmd/emg/word.c
Normal file
90
src/cmd/emg/word.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -32,7 +32,7 @@ depend: ${SRCS}
|
||||
|
||||
install: all
|
||||
install -m 755 $(BIN) ${DESTDIR}/sbin
|
||||
install -m 755 $(MAN) ${DESTDIR}/share/man/cat8
|
||||
cp $(MAN) ${DESTDIR}/share/man/cat8
|
||||
|
||||
lint: ${SRCS}
|
||||
lint -hax ${SRCS}
|
||||
|
||||
1
src/cmd/levee/.gitignore
vendored
Normal file
1
src/cmd/levee/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
lv
|
||||
56
src/cmd/levee/Makefile
Normal file
56
src/cmd/levee/Makefile
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# Public Domain. 1995/03/13 - Steven Schultz
|
||||
#
|
||||
TOPSRC = $(shell cd ../../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
|
||||
#CFLAGS += -Werror
|
||||
LIBS += -ltermcap
|
||||
|
||||
OBJS = blockio.o display.o editcor.o exec.o find.o \
|
||||
unixcall.o globals.o insert.o main.o misc.o \
|
||||
modify.o move.o ucsd.o undo.o wildargs.o \
|
||||
version.o
|
||||
MAN = lv.0
|
||||
|
||||
all: lv ${MAN}
|
||||
|
||||
lv: ${OBJS}
|
||||
${CC} ${LDFLAGS} -o lv.elf ${OBJS} ${LIBS}
|
||||
${OBJDUMP} -S lv.elf > lv.dis
|
||||
${SIZE} lv.elf
|
||||
${ELF2AOUT} lv.elf $@ && rm lv.elf
|
||||
|
||||
version.o: version.c VERSION
|
||||
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
|
||||
|
||||
.SUFFIXES: .0 .1
|
||||
|
||||
.1.0:
|
||||
${MANROFF} $*.1 > $@
|
||||
|
||||
clean:
|
||||
rm -f *.o *.elf ${MAN} lv *.elf *.dis tags *~
|
||||
|
||||
install: all
|
||||
install lv ${DESTDIR}/bin/
|
||||
cp lv.0 ${DESTDIR}/share/man/cat1/
|
||||
|
||||
# Dependencies
|
||||
|
||||
blockio.o : levee.h extern.h blockio.c config.h
|
||||
display.o : levee.h extern.h termcap.i display.c config.h
|
||||
editcor.o : levee.h extern.h editcor.c config.h
|
||||
exec.o : levee.h extern.h exec.c config.h
|
||||
find.o : levee.h extern.h grep.h find.c config.h
|
||||
globals.o : levee.h globals.c config.h
|
||||
insert.o : levee.h extern.h insert.c config.h
|
||||
main.o : levee.h extern.h main.c config.h
|
||||
misc.o : levee.h extern.h misc.c config.h
|
||||
modify.o : levee.h extern.h grep.h modify.c config.h
|
||||
move.o : levee.h extern.h move.c config.h
|
||||
rmxcall.o : levee.h rmxcall.c config.h
|
||||
ucsd.o : levee.h extern.h ucsd.c config.h
|
||||
undo.o : levee.h extern.h undo.c config.h
|
||||
unixcall.o : levee.h extern.h unixcall.c config.h
|
||||
wildargs.o : levee.h extern.h wildargs.c config.h
|
||||
56
src/cmd/levee/Makefile-linux
Normal file
56
src/cmd/levee/Makefile-linux
Normal file
@@ -0,0 +1,56 @@
|
||||
# makefile for Levee
|
||||
|
||||
exedir=/usr/local/bin
|
||||
mandir=/usr/local/man
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-g
|
||||
LDFLAGS=-g
|
||||
|
||||
OBJS = blockio.o display.o editcor.o exec.o find.o \
|
||||
unixcall.o globals.o insert.o main.o misc.o \
|
||||
modify.o move.o ucsd.o undo.o wildargs.o \
|
||||
version.o
|
||||
|
||||
lev: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o lev $(OBJS) -lcurses
|
||||
|
||||
version.o: version.c VERSION
|
||||
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
|
||||
|
||||
clean:
|
||||
rm -f *.o lev
|
||||
|
||||
distclean spotless: clean
|
||||
rm -f Makefile config.cmd config.sub config.h config.mak config.log config.md
|
||||
|
||||
install: install.bin install.man
|
||||
|
||||
install.bin: lev
|
||||
/home/sergev/Daily/workdir-2015-01-06/levee-3.5a/config.md $(PREFIX)$(exedir)
|
||||
/usr/bin/install -s -m 755 lev $(PREFIX)$(exedir)/levee
|
||||
/bin/ln -s -f levee $(PREFIX)$(exedir)/lv
|
||||
|
||||
install.man:
|
||||
/home/sergev/Daily/workdir-2015-01-06/levee-3.5a/config.md $(PREFIX)$(mandir)/man1
|
||||
/usr/bin/install -m 444 lv.1 $(PREFIX)$(mandir)/man1/levee.1
|
||||
echo ".so man1/levee.1" > $(PREFIX)$(mandir)/man1/lv.1
|
||||
|
||||
# Dependencies
|
||||
|
||||
blockio.o : levee.h extern.h blockio.c config.h
|
||||
display.o : levee.h extern.h termcap.i display.c config.h
|
||||
editcor.o : levee.h extern.h editcor.c config.h
|
||||
exec.o : levee.h extern.h exec.c config.h
|
||||
find.o : levee.h extern.h grep.h find.c config.h
|
||||
globals.o : levee.h globals.c config.h
|
||||
insert.o : levee.h extern.h insert.c config.h
|
||||
main.o : levee.h extern.h main.c config.h
|
||||
misc.o : levee.h extern.h misc.c config.h
|
||||
modify.o : levee.h extern.h grep.h modify.c config.h
|
||||
move.o : levee.h extern.h move.c config.h
|
||||
rmxcall.o : levee.h rmxcall.c config.h
|
||||
ucsd.o : levee.h extern.h ucsd.c config.h
|
||||
undo.o : levee.h extern.h undo.c config.h
|
||||
unixcall.o : levee.h extern.h unixcall.c config.h
|
||||
wildargs.o : levee.h extern.h wildargs.c config.h
|
||||
56
src/cmd/levee/Makefile.in
Normal file
56
src/cmd/levee/Makefile.in
Normal file
@@ -0,0 +1,56 @@
|
||||
# makefile for Levee
|
||||
|
||||
exedir=@exedir@
|
||||
mandir=@mandir@
|
||||
CC=@CC@
|
||||
|
||||
CFLAGS=@CFLAGS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
|
||||
OBJS = blockio.o display.o editcor.o exec.o find.o \
|
||||
unixcall.o globals.o insert.o main.o misc.o \
|
||||
modify.o move.o ucsd.o undo.o wildargs.o \
|
||||
version.o
|
||||
|
||||
lev: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o lev $(OBJS) @LIBS@
|
||||
|
||||
version.o: version.c VERSION
|
||||
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
|
||||
|
||||
clean:
|
||||
rm -f *.o lev
|
||||
|
||||
distclean spotless: clean
|
||||
rm -f @GENERATED_FILES@ @CONFIGURE_FILES@
|
||||
|
||||
install: install.bin install.man
|
||||
|
||||
install.bin: lev
|
||||
@INSTALL_DIR@ $(PREFIX)$(exedir)
|
||||
@INSTALL_PROGRAM@ lev $(PREFIX)$(exedir)/levee
|
||||
@NOMK@@LN_S@ -f levee $(PREFIX)$(exedir)/lv
|
||||
|
||||
install.man:
|
||||
@INSTALL_DIR@ $(PREFIX)$(mandir)/man1
|
||||
@INSTALL_DATA@ lv.1 $(PREFIX)$(mandir)/man1/levee.1
|
||||
@NOMK@echo ".so man1/levee.1" > $(PREFIX)$(mandir)/man1/lv.1
|
||||
|
||||
# Dependencies
|
||||
|
||||
blockio.o : levee.h extern.h blockio.c config.h
|
||||
display.o : levee.h extern.h termcap.i display.c config.h
|
||||
editcor.o : levee.h extern.h editcor.c config.h
|
||||
exec.o : levee.h extern.h exec.c config.h
|
||||
find.o : levee.h extern.h grep.h find.c config.h
|
||||
globals.o : levee.h globals.c config.h
|
||||
insert.o : levee.h extern.h insert.c config.h
|
||||
main.o : levee.h extern.h main.c config.h
|
||||
misc.o : levee.h extern.h misc.c config.h
|
||||
modify.o : levee.h extern.h grep.h modify.c config.h
|
||||
move.o : levee.h extern.h move.c config.h
|
||||
rmxcall.o : levee.h rmxcall.c config.h
|
||||
ucsd.o : levee.h extern.h ucsd.c config.h
|
||||
undo.o : levee.h extern.h undo.c config.h
|
||||
unixcall.o : levee.h extern.h unixcall.c config.h
|
||||
wildargs.o : levee.h extern.h wildargs.c config.h
|
||||
1
src/cmd/levee/VERSION
Normal file
1
src/cmd/levee/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
3.5a
|
||||
48
src/cmd/levee/beep.c
Normal file
48
src/cmd/levee/beep.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#include "levee.h"
|
||||
|
||||
#if OS_ATARI
|
||||
#include <atari\osbind.h>
|
||||
|
||||
char sound[] = {
|
||||
0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00,
|
||||
0xF8,0x10,0x10,0x10,0x00,0x20,0x03
|
||||
};
|
||||
|
||||
#define SADDR 0xFF8800L
|
||||
|
||||
typedef char srdef[4];
|
||||
|
||||
srdef *SOUND = (srdef *)SADDR;
|
||||
|
||||
main()
|
||||
{
|
||||
register i;
|
||||
long ssp;
|
||||
|
||||
ssp = Super(0L);
|
||||
for (i=0; i<sizeof(sound); i++) {
|
||||
(*SOUND)[0] = i;
|
||||
(*SOUND)[2] = sound[i];
|
||||
}
|
||||
Super(ssp);
|
||||
}
|
||||
#endif /*OS_ATARI*/
|
||||
50
src/cmd/levee/blockio.c
Normal file
50
src/cmd/levee/blockio.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#include "levee.h"
|
||||
#include "extern.h"
|
||||
|
||||
/* read in a file -- return TRUE -- read file
|
||||
FALSE-- file too big
|
||||
*/
|
||||
|
||||
int PROC
|
||||
addfile(f, start, endd, size)
|
||||
FILE *f;
|
||||
int start;
|
||||
int endd, *size;
|
||||
{
|
||||
register int chunk;
|
||||
|
||||
chunk = read(fileno(f), core+start, (endd-start)-1);
|
||||
|
||||
*size = chunk;
|
||||
return chunk < (endd-start)-1;
|
||||
}
|
||||
|
||||
|
||||
/* write out a file -- return TRUE if ok. */
|
||||
|
||||
bool PROC
|
||||
putfile(f, start, endd)
|
||||
register FILE *f;
|
||||
register int start, endd;
|
||||
{
|
||||
return write(fileno(f), core+start, endd-start) == (endd-start);
|
||||
}
|
||||
26
src/cmd/levee/config.h
Normal file
26
src/cmd/levee/config.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* configuration for levee, generated Tue Jan 6 12:41:26 PST 2015
|
||||
* by sergev@ubuntu-sergev
|
||||
*/
|
||||
#ifndef __AC_LEVEE_D
|
||||
#define __AC_LEVEE_D 1
|
||||
|
||||
// Size of editor data buffer.
|
||||
#define SIZE 16000
|
||||
|
||||
#define OS_UNIX 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_MEMSET 1
|
||||
#define HAVE_STRCHR 1
|
||||
#define HAVE_BASENAME 1
|
||||
#define HAVE_SIGNAL_H 1
|
||||
#define HAVE_SIGNAL 1
|
||||
#define HAVE_TGETENT 1
|
||||
#define USE_TERMCAP 1
|
||||
#define HAVE_MVCUR 1
|
||||
#define mvcur __mvcur
|
||||
#define HAVE_TCGETATTR 1
|
||||
#define PATH_FIND "/bin/find"
|
||||
#define PATH_SED "/bin/sed"
|
||||
|
||||
#endif/* __AC_LEVEE_D */
|
||||
1219
src/cmd/levee/configure.inc
Executable file
1219
src/cmd/levee/configure.inc
Executable file
File diff suppressed because it is too large
Load Diff
112
src/cmd/levee/configure.sh
Executable file
112
src/cmd/levee/configure.sh
Executable file
@@ -0,0 +1,112 @@
|
||||
#! /bin/sh
|
||||
|
||||
# local options: ac_help is the help message that describes them
|
||||
# and LOCAL_AC_OPTIONS is the script that interprets them. LOCAL_AC_OPTIONS
|
||||
# is a script that's processed with eval, so you need to be very careful to
|
||||
# make certain that what you quote is what you want to quote.
|
||||
|
||||
ac_help="
|
||||
--use-termcap Link with termcap instead of curses, if possible
|
||||
--partial-install Don\'t install the lv, lv(1) name links
|
||||
--size=NNN Use a NNN-byte edit buffer
|
||||
--dos compile for ms-dos or microsoft windows
|
||||
--tos compile for the Atari ST
|
||||
--rmx compile for RMX
|
||||
--flexos compile for FlexOS"
|
||||
|
||||
LOCAL_AC_OPTIONS='
|
||||
case Z$1 in
|
||||
Z--partial-install)
|
||||
missing_lv=1;;
|
||||
Z--dos) ac_os=DOS;;
|
||||
Z--tos) ac_os=ATARI=1;;
|
||||
Z--flexos) ac_os=FLEXOS=1;;
|
||||
Z--rmx) ac_os=RMX;;
|
||||
Z--size=*) SIZE=$(echo Z$1 | sed -e 's/^Z--size=//') ;;
|
||||
*) ac_error=1;;
|
||||
esac;shift'
|
||||
|
||||
# load in the configuration file
|
||||
#
|
||||
TARGET=levee
|
||||
. ./configure.inc
|
||||
AC_INIT $TARGET
|
||||
|
||||
# validate --size=
|
||||
#
|
||||
case X"${SIZE}" in
|
||||
X[0-9][0-9]*) ;;
|
||||
X[0-9][0-9]*[Ll]);;
|
||||
X) ;;
|
||||
X*) AC_FAIL "--size=$SIZE is not a valid number" ;;
|
||||
esac
|
||||
|
||||
AC_PROG_CC
|
||||
|
||||
if [ "$OS_DOS" ]; then
|
||||
AC_DEFINE SIZE ${SIZE:-32000}
|
||||
AC_DEFINE PROC _fastcall
|
||||
AC_DEFINE TTY_ANSI 1
|
||||
AC_CHECK_FUNCS basename
|
||||
elif [ "$OS_ATARI" ]; then
|
||||
AC_DEFINE SIZE ${SIZE:-32000}
|
||||
AC_DEFINE TTY_VT52 1
|
||||
AC_DEFINE HAVE_BLKFILL 1
|
||||
AC_CHECK_FUNCS basename
|
||||
elif [ "$OS_FLEXOS" ]; then
|
||||
AC_DEFINE SIZE ${SIZE:-256000}
|
||||
AC_CHECK_FUNCS basename
|
||||
else
|
||||
AC_DEFINE SIZE ${SIZE:-256000}
|
||||
AC_DEFINE OS_UNIX 1
|
||||
|
||||
if AC_CHECK_HEADERS string.h; then
|
||||
# Assume a mainly ANSI-compliant world, where the
|
||||
# existance of string.h implies a memset() and strchr()
|
||||
AC_DEFINE HAVE_MEMSET 1
|
||||
AC_DEFINE HAVE_STRCHR 1
|
||||
else
|
||||
AC_CHECK_FUNCS memset
|
||||
AC_CHECK_FUNCS strchr
|
||||
fi
|
||||
|
||||
# for basename
|
||||
if AC_CHECK_FUNCS basename; then
|
||||
AC_CHECK_HEADERS libgen.h
|
||||
fi
|
||||
|
||||
if AC_CHECK_HEADERS signal.h; then
|
||||
# Assume a mainly sane world where the existance
|
||||
# of signal.h means that signal() exists
|
||||
AC_DEFINE HAVE_SIGNAL 1
|
||||
fi
|
||||
|
||||
if [ "$USE_TERMCAP" ]; then
|
||||
LIBORDER="-ltermcap -lcurses -lncurses"
|
||||
else
|
||||
LIBORDER="-lcurses -lncurses -ltermcap"
|
||||
fi
|
||||
|
||||
if AC_LIBRARY tgetent $LIBORDER; then
|
||||
AC_CHECK_HEADERS termcap.h || AC_FAIL "levee needs <termcap.h>"
|
||||
AC_DEFINE USE_TERMCAP 1
|
||||
# our -libtermcap might be (n)curses in disguise. If so,
|
||||
# it might have a colliding mvcur() that we need to define
|
||||
# ourselves out from.
|
||||
AC_QUIET AC_CHECK_FUNCS mvcur && AC_DEFINE mvcur __mvcur
|
||||
else
|
||||
# have to use a local termcap
|
||||
AC_DEFINE TERMCAP_EMULATION 1
|
||||
AC_DEFINE USE_TERMCAP 1
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS termios.h && AC_CHECK_FUNCS tcgetattr
|
||||
fi
|
||||
|
||||
if AC_PROG_LN_S && test -z "$missing_lv"; then
|
||||
AC_SUB NOMK ''
|
||||
else
|
||||
AC_SUB NOMK '@#'
|
||||
fi
|
||||
|
||||
AC_OUTPUT Makefile
|
||||
349
src/cmd/levee/display.c
Normal file
349
src/cmd/levee/display.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#include "levee.h"
|
||||
#include "extern.h"
|
||||
|
||||
/* do a gotoXY -- allowing -1 for same row/column */
|
||||
|
||||
#if USE_TERMCAP | OS_ATARI
|
||||
|
||||
#define MAXCOLS 160
|
||||
|
||||
#if USE_TERMCAP
|
||||
#include "termcap.i"
|
||||
#endif
|
||||
|
||||
#else /*!(USE_TERMCAP | OS_ATARI)*/
|
||||
|
||||
#define MAXCOLS COLS
|
||||
|
||||
#endif
|
||||
|
||||
VOID PROC
|
||||
mvcur(y,x)
|
||||
int y,x;
|
||||
{
|
||||
#if TERMCAP_EMULATION || TTY_ANSI
|
||||
static char gt[30];
|
||||
#endif
|
||||
|
||||
if (y == -1)
|
||||
y = curpos.y;
|
||||
else
|
||||
curpos.y = y;
|
||||
if (y >= LINES)
|
||||
y = LINES-1;
|
||||
if (x == -1)
|
||||
x = curpos.x;
|
||||
else
|
||||
curpos.x = x;
|
||||
if (x >= COLS)
|
||||
x = COLS-1;
|
||||
|
||||
#if TERMCAP_EMULATION
|
||||
tgoto(gt,y,x);
|
||||
strput(gt);
|
||||
#elif USE_TERMCAP
|
||||
strput( tgoto(CM, x, y) );
|
||||
#elif TTY_ZTERM
|
||||
zgoto(x,y);
|
||||
#elif TTY_ANSI
|
||||
{ register char *p = gt; /* make a ansi gotoXY string */
|
||||
*p++ = 033;
|
||||
*p++ = '[';
|
||||
numtoa(p,1+y); p += strlen(p);
|
||||
*p++ = ';';
|
||||
numtoa(p,1+x); p += strlen(p);
|
||||
*p++ = 'H';
|
||||
WRITE_TEXT(1, gt, (p-gt));
|
||||
}
|
||||
#elif TTY_VT52
|
||||
CM[2] = y+32;
|
||||
CM[3] = x+32;
|
||||
strput(CM);
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
numtoa(str,num)
|
||||
char *str;
|
||||
int num;
|
||||
{
|
||||
int i = 10; /* I sure hope that str is 10 bytes long... */
|
||||
bool neg = (num < 0);
|
||||
|
||||
if (neg)
|
||||
num = -num;
|
||||
|
||||
str[--i] = 0;
|
||||
do{
|
||||
str[--i] = (num%10)+'0';
|
||||
num /= 10;
|
||||
}while (num > 0);
|
||||
if (neg)
|
||||
str[--i] = '-';
|
||||
moveleft(&str[i], str, 10-i);
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
printi(num)
|
||||
int num;
|
||||
{
|
||||
char nb[10];
|
||||
register int size;
|
||||
|
||||
numtoa(nb,num);
|
||||
size = min(strlen(nb),COLS-curpos.x);
|
||||
if (size > 0) {
|
||||
nb[size] = 0;
|
||||
zwrite(nb, size);
|
||||
curpos.x += size;
|
||||
}
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
println()
|
||||
{
|
||||
zwrite("\r\n", 2);
|
||||
curpos.x = 0;
|
||||
curpos.y = min(curpos.y+1, LINES-1);
|
||||
}
|
||||
|
||||
/* print a character out in a readable form --
|
||||
* ^<x> for control-<x>
|
||||
* spaces for <tab>
|
||||
* normal for everything else
|
||||
*/
|
||||
|
||||
static char hexdig[] = "0123456789ABCDEF";
|
||||
|
||||
int PROC
|
||||
format(out,c)
|
||||
/* format: put a displayable version of c into out */
|
||||
register char *out;
|
||||
register unsigned c;
|
||||
{
|
||||
if (c >= ' ' && c < '') {
|
||||
out[0] = c;
|
||||
return 1;
|
||||
}
|
||||
else if (c == '\t' && !list) {
|
||||
register int i;
|
||||
int size;
|
||||
|
||||
for (i = size = tabsize - (curpos.x % tabsize);i > 0;)
|
||||
out[--i] = ' ';
|
||||
return size;
|
||||
}
|
||||
else if (c < 128) {
|
||||
out[0] = '^';
|
||||
out[1] = c^64;
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
#if OS_DOS
|
||||
out[0] = c;
|
||||
return 1;
|
||||
#else
|
||||
out[0] = '\\';
|
||||
out[1] = hexdig[(c>>4)&017];
|
||||
out[2] = hexdig[c&017];
|
||||
return 3;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
printch(c)
|
||||
char c;
|
||||
{
|
||||
register int size;
|
||||
char buf[MAXCOLS];
|
||||
|
||||
size = min(format(buf,c),COLS-curpos.x);
|
||||
if (size > 0) {
|
||||
buf[size] = 0;
|
||||
zwrite(buf, size);
|
||||
curpos.x += size;
|
||||
}
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
prints(s)
|
||||
char *s;
|
||||
{
|
||||
int size,oxp = curpos.x;
|
||||
char buf[MAXCOLS+1];
|
||||
register int bi = 0;
|
||||
|
||||
while (*s && curpos.x < COLS) {
|
||||
size = format(&buf[bi],*s++);
|
||||
bi += size;
|
||||
curpos.x += size;
|
||||
}
|
||||
size = min(bi,COLS-oxp);
|
||||
if (size > 0) {
|
||||
buf[size] = 0;
|
||||
zwrite(buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
writeline(y,x,start)
|
||||
int y,x,start;
|
||||
{
|
||||
int endd,oxp;
|
||||
register int size;
|
||||
char buf[MAXCOLS+1];
|
||||
register int bi = 0;
|
||||
|
||||
endd = fseekeol(start);
|
||||
if (start==0 || core[start-1] == EOL)
|
||||
mvcur(y, 0);
|
||||
else
|
||||
mvcur(y, x);
|
||||
oxp = curpos.x;
|
||||
|
||||
while (start < endd && curpos.x < COLS) {
|
||||
size = format(&buf[bi],core[start++]);
|
||||
bi += size;
|
||||
curpos.x += size;
|
||||
}
|
||||
if (list) {
|
||||
buf[bi++] = '$';
|
||||
curpos.x++;
|
||||
}
|
||||
size = min(bi,COLS-oxp);
|
||||
if (size > 0) {
|
||||
buf[size] = 0;
|
||||
zwrite(buf, size);
|
||||
}
|
||||
if (curpos.x < COLS)
|
||||
strput(CE);
|
||||
}
|
||||
|
||||
/* redraw && refresh the screen */
|
||||
|
||||
VOID PROC
|
||||
refresh(y,x,start,endd,rest)
|
||||
int y,x,start,endd;
|
||||
bool rest;
|
||||
{
|
||||
int sp;
|
||||
|
||||
#if OS_ATARI
|
||||
/* turn the cursor off */
|
||||
asm(" clr.l -(sp) ");
|
||||
asm(" move.w #21,-(sp) ");
|
||||
asm(" trap #14 ");
|
||||
asm(" addq.l #6,sp ");
|
||||
#endif
|
||||
sp = start;
|
||||
while (sp <= endd) {
|
||||
writeline(y, x, sp);
|
||||
sp = 1+fseekeol(sp);
|
||||
y++;
|
||||
x = 0;
|
||||
}
|
||||
if (rest && sp >= bufmax)
|
||||
while (y<LINES-1) { /* fill screen with ~ */
|
||||
mvcur(y, 0);
|
||||
printch('~'); strput(CE);
|
||||
y++;
|
||||
}
|
||||
#if OS_ATARI
|
||||
/* turn the cursor back on */
|
||||
asm(" clr.w -(sp) ");
|
||||
asm(" move.w #1,-(sp) ");
|
||||
asm(" move.w #21,-(sp) ");
|
||||
asm(" trap #14 ");
|
||||
asm(" addq.l #6,sp ");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* redraw everything */
|
||||
|
||||
VOID PROC
|
||||
redisplay(flag)
|
||||
bool flag;
|
||||
{
|
||||
if (flag)
|
||||
clrprompt();
|
||||
refresh(0, 0, ptop, pend, TRUE);
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
scrollback(curr)
|
||||
int curr;
|
||||
{
|
||||
mvcur(0,0); /* move to the top line */
|
||||
do {
|
||||
ptop = bseekeol(ptop-1);
|
||||
strput(UpS);
|
||||
writeline(0, 0, ptop);
|
||||
} while (ptop > curr);
|
||||
setend();
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
scrollforward(curr)
|
||||
int curr;
|
||||
{
|
||||
do {
|
||||
writeline(LINES-1, 0, pend+1);
|
||||
zwrite("\n", 1);
|
||||
pend = fseekeol(pend+1);
|
||||
ptop = fseekeol(ptop)+1;
|
||||
} while (pend < curr);
|
||||
}
|
||||
|
||||
/* find if the number of lines between top && bottom is less than dofscroll */
|
||||
|
||||
bool PROC
|
||||
ok_to_scroll(top,bottom)
|
||||
int top,bottom;
|
||||
{
|
||||
int nl, i;
|
||||
|
||||
nl = dofscroll;
|
||||
i = top;
|
||||
do
|
||||
i += 1+scan(bufmax-i,'=',EOL, &core[i]);
|
||||
while (--nl > 0 && i < bottom);
|
||||
return(nl>0);
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
clrprompt()
|
||||
{
|
||||
mvcur(LINES-1,0);
|
||||
strput(CE);
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
prompt(toot,s)
|
||||
bool toot;
|
||||
char *s;
|
||||
{
|
||||
if (toot)
|
||||
error();
|
||||
clrprompt();
|
||||
prints(s);
|
||||
}
|
||||
50
src/cmd/levee/dos.asm
Normal file
50
src/cmd/levee/dos.asm
Normal file
@@ -0,0 +1,50 @@
|
||||
name dos
|
||||
page 55,80
|
||||
title 'DOS.ASM -- assembly routines for the teeny-shell under DOS'
|
||||
|
||||
_TEXT segment byte public 'CODE'
|
||||
|
||||
assume cs:_TEXT
|
||||
|
||||
public _fail_criterr
|
||||
;
|
||||
; If we get a critical error, just fail it - dos 3.0 and up only, please!
|
||||
;
|
||||
_fail_criterr proc far
|
||||
mov al, 3
|
||||
iret
|
||||
_fail_criterr endp
|
||||
|
||||
public _ignore_ctrlc
|
||||
;
|
||||
; If the user presses ^C, don't do any special handling of it.
|
||||
;
|
||||
_ignore_ctrlc proc far
|
||||
iret
|
||||
_ignore_ctrlc endp
|
||||
_pexec endp
|
||||
|
||||
public _intr_on_ctrlc
|
||||
;
|
||||
; If the user presses ^C, terminate the current process.
|
||||
;
|
||||
_intr_on_ctrlc proc far
|
||||
mov ah, 4ch
|
||||
mov al, 0ffh
|
||||
int 21h
|
||||
_intr_on_ctrlc endp
|
||||
|
||||
public _crawcin
|
||||
;
|
||||
; get a character from standard input without any sort of magical
|
||||
; processing.
|
||||
;
|
||||
_crawcin proc far
|
||||
mov ah, 07h
|
||||
int 21h
|
||||
ret
|
||||
_crawcin endp
|
||||
|
||||
_TEXT ends
|
||||
|
||||
end
|
||||
200
src/cmd/levee/doscall.c
Normal file
200
src/cmd/levee/doscall.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
/*
|
||||
* dos interface for levee (Microsoft C)
|
||||
*/
|
||||
#include "levee.h"
|
||||
|
||||
#if OS_DOS
|
||||
#include <glob.h>
|
||||
#include <dos.h>
|
||||
|
||||
int PROC
|
||||
min(a,b)
|
||||
int a,b;
|
||||
{
|
||||
return (a>b) ? b : a;
|
||||
}
|
||||
|
||||
int PROC
|
||||
max(a,b)
|
||||
int a,b;
|
||||
{
|
||||
return (a<b) ? b : a;
|
||||
}
|
||||
|
||||
PROC
|
||||
strput(s)
|
||||
char *s;
|
||||
{
|
||||
write(1, s, strlen(s));
|
||||
}
|
||||
|
||||
/* get a key, mapping certain control sequences
|
||||
*/
|
||||
PROC
|
||||
getKey()
|
||||
{
|
||||
register c;
|
||||
extern char _far crawcin();
|
||||
|
||||
c = crawcin();
|
||||
|
||||
if (c == 0 || c == 0xe0)
|
||||
switch (c=crawcin()) {
|
||||
case 'K': return LTARROW;
|
||||
case 'M': return RTARROW;
|
||||
case 'H': return UPARROW;
|
||||
case 'P': return DNARROW;
|
||||
case 'I': return 'U'-'@'; /* page-up */
|
||||
case 'Q': return 'D'-'@'; /* page-down */
|
||||
default : return 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/* don't allow interruptions to happen
|
||||
*/
|
||||
PROC
|
||||
nointr()
|
||||
{
|
||||
extern void _cdecl _interrupt _far ignore_ctrlc();
|
||||
_dos_setvect(0x23, ignore_ctrlc);
|
||||
} /* nointr */
|
||||
|
||||
|
||||
/* have ^C do what it usually does
|
||||
*/
|
||||
PROC
|
||||
allowintr()
|
||||
{
|
||||
extern void _cdecl _interrupt _far intr_on_ctrlc();
|
||||
_dos_setvect(0x23, intr_on_ctrlc);
|
||||
} /* allowintr */
|
||||
|
||||
|
||||
/*
|
||||
* basename() returns the filename part of a pathname
|
||||
*/
|
||||
char *
|
||||
basename(s)
|
||||
register char *s;
|
||||
{
|
||||
register char *p = s;
|
||||
|
||||
for (p = s+strlen(s); p > s; --p)
|
||||
if (p[-1] == '/' || p[-1] == '\\' || p[-1] == ':')
|
||||
return p;
|
||||
return s;
|
||||
} /* basename */
|
||||
|
||||
|
||||
/*
|
||||
* glob() expands a wildcard, via calls to _dos_findfirst/_next()
|
||||
* and pathname retention.
|
||||
*/
|
||||
char *
|
||||
glob(path, dta)
|
||||
char *path;
|
||||
struct glob_t *dta;
|
||||
{
|
||||
static char path_bfr[256]; /* full pathname to return */
|
||||
static char *file_part; /* points at file - for filling */
|
||||
static char isdotpattern; /* looking for files starting with . */
|
||||
static char isdotordotdot; /* special case . or .. */
|
||||
static struct glob_t *dta_bfr; /* pointer to desired dta */
|
||||
static struct find_t dird; /* DOS dta */
|
||||
|
||||
register st; /* status from _dos_findxxx */
|
||||
|
||||
if (path) {
|
||||
/* when we start searching, save the path part of the filename in
|
||||
* a safe place.
|
||||
*/
|
||||
strcpy(path_bfr, path);
|
||||
file_part = basename(path_bfr);
|
||||
|
||||
/* set up initial parameters for DosFindFirst()
|
||||
*/
|
||||
dta_bfr = dta;
|
||||
|
||||
if (isdotpattern = (*file_part == '.'))
|
||||
/* _dos_findfirst() magically expands . and .. into their
|
||||
* directory names. Admittedly, there are cases where
|
||||
* this can be useful, but this is not one of them. So,
|
||||
* if we find that we're matching . and .., we just
|
||||
* special-case ourselves into oblivion to get around
|
||||
* this particular bit of DOS silliness.
|
||||
*/
|
||||
isdotordotdot = (file_part[1] == 0 || file_part[1] == '.');
|
||||
else
|
||||
isdotordotdot = 0;
|
||||
|
||||
st = _dos_findfirst(path, 0x16, &dird);
|
||||
}
|
||||
else
|
||||
st = _dos_findnext(&dird);
|
||||
|
||||
while (st == 0) {
|
||||
/* Unless the pattern has a leading ., don't include any file
|
||||
* that starts with .
|
||||
*/
|
||||
if (dird.name[0] == '.' && !isdotpattern)
|
||||
st = _dos_findnext(&dird);
|
||||
else {
|
||||
/* found a file - affix the path leading to it, then return
|
||||
* a pointer to the (static) buffer holding the path+the name.
|
||||
*/
|
||||
strlwr(dird.name); /* DOS & OS/2 are case-insensitive */
|
||||
|
||||
if (dta_bfr) {
|
||||
dta_bfr->wr_time = dird.wr_time;
|
||||
dta_bfr->wr_date = dird.wr_date;
|
||||
if (isdotordotdot)
|
||||
strcpy(dta_bfr->name, file_part);
|
||||
else {
|
||||
strncpy(dta_bfr->name, dird.name, sizeof(dta_bfr->name)-1);
|
||||
dta_bfr->name[sizeof(dta_bfr->name)-1] = 0;
|
||||
}
|
||||
dta_bfr->size = dird.size;
|
||||
dta_bfr->attrib = dird.attrib;
|
||||
}
|
||||
if (!isdotordotdot)
|
||||
strcpy(file_part, dird.name);
|
||||
return path_bfr;
|
||||
}
|
||||
}
|
||||
/* nothing matched
|
||||
*/
|
||||
if (path && isdotordotdot) {
|
||||
/* must be at root, so statting dot will most likely fail. Fake a
|
||||
* dta.
|
||||
*/
|
||||
if (dta_bfr) {
|
||||
memset(dta_bfr, 0, sizeof *dta_bfr);
|
||||
dta_bfr->attrib = 0x10;
|
||||
dta_bfr->name[0] = '.';
|
||||
}
|
||||
return path_bfr;
|
||||
}
|
||||
return (char*)0;
|
||||
} /* glob */
|
||||
#endif /*OS_DOS*/
|
||||
644
src/cmd/levee/editcor.c
Normal file
644
src/cmd/levee/editcor.c
Normal file
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2008 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#include "levee.h"
|
||||
#include "extern.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* do some undoable modification */
|
||||
|
||||
/* These variables make docommand nonrecursive */
|
||||
|
||||
bool ok;
|
||||
int newend, /* end position after change */
|
||||
disp, /* start redisplay here */
|
||||
newc, /* new cursor position for wierd cmds */
|
||||
endY; /* final yp for endp */
|
||||
|
||||
/* move a line of text right || left */
|
||||
|
||||
VOID PROC
|
||||
adjuster(sleft, endd, sw)
|
||||
bool sleft;
|
||||
int endd, sw;
|
||||
{
|
||||
bool noerror;
|
||||
int np, ts,
|
||||
ip,
|
||||
ss, adjp,
|
||||
DLEnum;
|
||||
|
||||
if (sw == -1)
|
||||
sw = shiftwidth;
|
||||
if (sleft)
|
||||
sw = -sw;
|
||||
curr = bseekeol(curr);
|
||||
ip = curr;
|
||||
noerror = TRUE;
|
||||
do {
|
||||
DLEnum = sw + findDLE(ip, &np, bufmax,0);
|
||||
if (DLEnum >= 0 && DLEnum <= COLS && core[np] != EOL && np < bufmax) {
|
||||
ts = DLEnum / tabsize;
|
||||
ss = DLEnum % tabsize;
|
||||
adjp = ts+ss+ip;
|
||||
if (np-adjp < 0) { /* expand the buf */
|
||||
moveright(&core[np], &core[adjp], bufmax-np);
|
||||
insert_to_undo(&undo, adjp, adjp - np);
|
||||
}
|
||||
else
|
||||
delete_to_undo(&undo, adjp, np - adjp);
|
||||
|
||||
endd += (adjp-np);
|
||||
noerror = move_to_undo(&undo, ip, ts+ss);
|
||||
fillchar(&core[ip], ts, TAB);
|
||||
fillchar(&core[ip+ts], ss, 32);
|
||||
}
|
||||
else if (np > ip) { /* remove the indent code */
|
||||
noerror = delete_to_undo(&undo, ip, np-ip);
|
||||
endd += (ip - np);
|
||||
}
|
||||
ip = 1 + fseekeol(ip);
|
||||
} while (noerror && ip < endd);
|
||||
if (!noerror)
|
||||
error();
|
||||
newc = skipws(curr);
|
||||
disp = curr;
|
||||
newend = endd;
|
||||
endY = setY(min(newend, pend));
|
||||
}
|
||||
|
||||
/* join <count> lines together */
|
||||
|
||||
VOID PROC
|
||||
join(count)
|
||||
int count;
|
||||
{
|
||||
bool ok;
|
||||
int lp, first;
|
||||
|
||||
if (lend < bufmax) { /* are we in the buffer? */
|
||||
disp = lend; /* start redraw here */
|
||||
newc = lend;
|
||||
do { /* join until.. */
|
||||
first = lend;
|
||||
lp = skipws(1+first);
|
||||
ok = delete_to_undo(&undo, 1+first, lp-(1+first));
|
||||
if (ok) {
|
||||
ok = move_to_undo(&undo, first, 1);
|
||||
core[first] = ' '; /* spaces between lines */
|
||||
}
|
||||
count--;
|
||||
lend = fseekeol(first);
|
||||
} while (ok && count > 0);
|
||||
endY = MAGICNUMBER;
|
||||
newend = lend;
|
||||
if (!ok)
|
||||
error();
|
||||
}
|
||||
else
|
||||
error();
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
squiggle(endp, c, dorepl)
|
||||
int endp;
|
||||
char c;
|
||||
bool dorepl;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (endp >= curr) {
|
||||
ok = move_to_undo(&undo,curr,endp-curr+1);
|
||||
if (ok) {
|
||||
for (i = curr;i<=endp;i++) {
|
||||
if (!dorepl) { /* squiggle it to uc - lc */
|
||||
if (core[i] >='A' && core[i] <='Z')
|
||||
core[i] += 32;
|
||||
else if (core[i]>='a' && core[i]<='z')
|
||||
core[i] -= 32;
|
||||
}
|
||||
else
|
||||
core[i] = c;
|
||||
}
|
||||
newend = min(endp+1,lend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
bigreplace()
|
||||
{
|
||||
int len, tsiz;
|
||||
|
||||
tsiz = lend-curr;
|
||||
if (move_to_undo(&undo, curr, tsiz))
|
||||
if (SIZE - bufmax > tsiz) { /* enough room for temp copy? */
|
||||
moveleft(&core[curr], &core[bufmax],lend-curr);
|
||||
if (line(core, curr, lend, &len) != ESC)
|
||||
error();
|
||||
newend = curr+len;
|
||||
moveright(&core[bufmax+len], &core[newend], lend-newend);
|
||||
}
|
||||
}
|
||||
|
||||
bool PROC
|
||||
put(before)
|
||||
bool before;
|
||||
{
|
||||
endY = setY(curr);
|
||||
if (!before)
|
||||
if (yank.lines)
|
||||
curr = min(lend+1,bufmax);
|
||||
else
|
||||
curr = min(curr+1, lend);
|
||||
else if (yank.lines)
|
||||
curr = lstart;
|
||||
newc = disp = curr;
|
||||
return(putback(curr, &newend));
|
||||
}
|
||||
|
||||
bool PROC
|
||||
execute(start, end)
|
||||
{
|
||||
int tf;
|
||||
FILE *f;
|
||||
char scratch[20];
|
||||
bool ret = FALSE;
|
||||
int size;
|
||||
|
||||
strcpy(scratch, "/tmp/lv.XXXXXX");
|
||||
|
||||
clrprompt();
|
||||
printch('!');
|
||||
if ( !getlin(instring) )
|
||||
return FALSE;
|
||||
|
||||
if ( (tf = mkstemp(scratch)) < 0 ) {
|
||||
prints("[tempfile error]");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strcat(instring, " 2>&1 <");
|
||||
strcat(instring, scratch);
|
||||
|
||||
if ( (size = write(tf, core+start, end-start)) == (end-start) ) {
|
||||
if ( (f=popen(instring, "r")) ) {
|
||||
if ( deletion(start, end) && (insertfile(f, 1, start, &size) > 0) )
|
||||
ret = TRUE;
|
||||
pclose(f);
|
||||
}
|
||||
else
|
||||
error();
|
||||
}
|
||||
|
||||
close(tf);
|
||||
unlink(scratch);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
gcount()
|
||||
{
|
||||
do {
|
||||
count = (count*10) + (ch-'0');
|
||||
readchar(); /* get a char to replace the one we dumped */
|
||||
} while ( count >= 0 && isdigit(ch) );
|
||||
}
|
||||
|
||||
VOID PROC
|
||||
docommand(cmd)
|
||||
cmdtype cmd;
|
||||
{
|
||||
cmdtype movecmd; /* movement command for y, d, c */
|
||||
char cmdch;
|
||||
int oldc; /* old count */
|
||||
int endp; /* end position before change */
|
||||
extern bool s_wrapped;
|
||||
|
||||
resetX(); /* un-derange the cursor */
|
||||
oldc = newc = -1;
|
||||
endY = yp;
|
||||
newend = disp = curr;
|
||||
ok = TRUE; /* so far everything is working */
|
||||
cmdch = ch;
|
||||
if (cmd != UNDO_C && cmd != YANK_C) {
|
||||
if (macro<0)
|
||||
zerostack(&undo);
|
||||
if (redoing != TRUE) {
|
||||
rcp = rcb; /* point at start of redo buffer */
|
||||
if (count > 1) { /* put in a count? */
|
||||
numtoa(rcb,count);
|
||||
rcp += strlen(rcb);
|
||||
}
|
||||
*rcp++ = cmdch; /* the command char goes in... */
|
||||
xerox = TRUE; /* hoist the magical flags */
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd <= YANK_C) {
|
||||
readchar();
|
||||
if ( isdigit(ch) && ch != '0' ) {
|
||||
oldc = count;
|
||||
count = 0;
|
||||
gcount(); /* get a new count */
|
||||
if (cmd == ADJUST_C) /* special for >>,<< wierdness */
|
||||
swap(&count, &oldc); /* reverse sw & count */
|
||||
else
|
||||
count = count*max(oldc,1); /* combine them */
|
||||
}
|
||||
if (ch == cmdch) { /* diddle lines */
|
||||
yank.lines = TRUE;
|
||||
endp = nextline(TRUE, curr, count);
|
||||
curr = bseekeol(curr);
|
||||
disp = curr;
|
||||
}
|
||||
else { /* diddle 'things' */
|
||||
yank.lines = FALSE;
|
||||
movecmd = movemap[(unsigned int)ch];
|
||||
|
||||
if ( (ok = (findCP(curr,&endp,movecmd) == LEGALMOVE)) ) {
|
||||
if (curr > endp) {
|
||||
swap(&curr,&endp);
|
||||
ok = (cmd != CHANGE_C);
|
||||
}
|
||||
if (adjcurr[(unsigned int)movecmd])
|
||||
curr++;
|
||||
if (adjendp[(unsigned int)movecmd])
|
||||
endp++;
|
||||
}
|
||||
if (!ok) {
|
||||
if (ch != ESC)
|
||||
error();
|
||||
goto killredo;
|
||||
}
|
||||
}
|
||||
|
||||
endY = setY(endp);
|
||||
newend = curr;
|
||||
disp = curr;
|
||||
switch (cmd) {
|
||||
case EXEC_C:
|
||||
ok = execute(curr, endp);
|
||||
break;
|
||||
case DELETE_C:
|
||||
ok = deletion(curr, endp);
|
||||
break;
|
||||
case ADJUST_C:
|
||||
adjuster((cmdch == '<'), endp-1, oldc);
|
||||
break;
|
||||
case CHANGE_C:
|
||||
if (endp <= pend+1) {
|
||||
mvcur(setY(endp-1), setX(endp-1));
|
||||
printch('$');
|
||||
mvcur(yp, xp);
|
||||
}
|
||||
if (deletion(curr, endp))
|
||||
ok = ((newend = insertion(1, 0, &disp, &endY, TRUE)) >= 0);
|
||||
else
|
||||
ok = FALSE;
|
||||
break;
|
||||
case YANK_C:
|
||||
if (!doyank(curr, endp))
|
||||
error();
|
||||
return; /* xerox will not be true, nor will redoing */
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
endp = curr;
|
||||
endY = yp;
|
||||
|
||||
switch (cmd) {
|
||||
case I_AT_NONWHITE:
|
||||
case A_AT_END:
|
||||
case APPEND_C:
|
||||
case INSERT_C: /* variations on insert */
|
||||
if (cmd != INSERT_C) {
|
||||
if (cmd == APPEND_C)
|
||||
curr = min(curr+1, lend);
|
||||
else if (cmd == A_AT_END)
|
||||
curr = lend;
|
||||
else /* if (cmd == I_AT_NONWHITE) */
|
||||
curr = skipws(lstart);
|
||||
xp = setX(curr);
|
||||
mvcur(yp,xp);
|
||||
}
|
||||
newend = insertion(count, 0, &disp, &endY, TRUE);
|
||||
ok = (newend >= 0);
|
||||
break;
|
||||
case OPEN_C:
|
||||
case OPENUP_C:
|
||||
newend = insertion(1,setstep[ (cmd==OPENUP_C)&1 ],
|
||||
&disp,&endY,TRUE)-1;
|
||||
ok = (newend >= 0);
|
||||
break;
|
||||
case REPLACE_C:
|
||||
case TWIDDLE_C:
|
||||
if (cmd == REPLACE_C) {
|
||||
if ((cmdch = readchar()) == ESC)
|
||||
goto killredo;
|
||||
}
|
||||
if (findCP(curr, &endp, GO_RIGHT) == LEGALMOVE)
|
||||
squiggle(endp-1, cmdch, (cmd==REPLACE_C));
|
||||
break;
|
||||
case PUT_BEFORE:
|
||||
case PUT_AFTER:
|
||||
ok = put(cmd==PUT_AFTER);
|
||||
break;
|
||||
case BIG_REPL_C:
|
||||
bigreplace();
|
||||
break;
|
||||
case RESUBST_C:
|
||||
ok = FALSE;
|
||||
if (dst[0] != 0) {
|
||||
newend = chop(curr, &lend, TRUE, &ok);
|
||||
if (newend >= 0) {
|
||||
endY = setY(newend+strlen(dst));
|
||||
ok = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JOIN_C:
|
||||
join(count); /* join lines */
|
||||
break;
|
||||
case UNDO_C: /* undo last modification */
|
||||
ok = fixcore(&newend) >= 0;
|
||||
disp = newend;
|
||||
endY = MAGICNUMBER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
setpos((newc<0)?newend:newc);
|
||||
setend();
|
||||
if (curr < ptop || curr > pend) {
|
||||
yp = settop(12);
|
||||
redisplay(TRUE);
|
||||
}
|
||||
else {
|
||||
yp = setY(curr);
|
||||
if (endY != setY(newend)) /* shuffled lines */
|
||||
refresh(setY(disp), setX(disp), disp, pend, TRUE);
|
||||
else /* refresh to end position */
|
||||
refresh(setY(disp), setX(disp), disp, newend, FALSE);
|
||||
}
|
||||
if (curr >= bufmax && bufmax > 0) { /* adjust off end of buffer */
|
||||
setpos(bufmax-1);
|
||||
yp = setY(curr);
|
||||
}
|
||||
if (s_wrapped) {
|
||||
prompt(FALSE, "search wrapped around end of buffer");
|
||||
s_wrapped = 0;
|
||||
}
|
||||
else
|
||||
clrprompt();
|
||||
modified = TRUE;
|
||||
}
|
||||
else {
|
||||
error();
|
||||
killredo:
|
||||
rcb[0] = 0;
|
||||
}
|
||||
mvcur(yp, xp);
|
||||
if (xerox)
|
||||
*rcp = 0; /* terminate the redo */
|
||||
redoing = FALSE;
|
||||
xerox = FALSE;
|
||||
core[bufmax] = EOL;
|
||||
}
|
||||
|
||||
/* Initialize && execute a macro */
|
||||
|
||||
VOID PROC
|
||||
exmacro()
|
||||
{
|
||||
int mp;
|
||||
|
||||
mp = lookup(ch);
|
||||
if (mp > 0) {
|
||||
if (macro<0)
|
||||
zerostack(&undo);
|
||||
insertmacro(mbuffer[mp].m_text, count);
|
||||
}
|
||||
else
|
||||
error();
|
||||
}
|
||||
|
||||
/* redraw the screen w.r.t. the cursor */
|
||||
|
||||
VOID PROC
|
||||
zdraw(code)
|
||||
unsigned char code;
|
||||
{
|
||||
int nl = ERR,
|
||||
np = (count>0)?to_index(count):curr;
|
||||
|
||||
if (movemap[code] == CR_FWD)
|
||||
nl = 0;
|
||||
else if (movemap[code] == CR_BACK)
|
||||
nl = LINES-1;
|
||||
else if (code == '.')
|
||||
nl = LINES / 2;
|
||||
if (nl >= 0) {
|
||||
curr = np;
|
||||
yp = settop(nl);
|
||||
redisplay(TRUE);
|
||||
mvcur(yp,xp);
|
||||
}
|
||||
else
|
||||
error();
|
||||
}
|
||||
|
||||
/* start up a built-in macro */
|
||||
|
||||
VOID PROC
|
||||
macrocommand()
|
||||
{
|
||||
if (count > 1)
|
||||
numtoa(gcb,count);
|
||||
else
|
||||
gcb[0] = 0;
|
||||
switch (ch) { /* which macro? */
|
||||
case 'x': /* x out characters */
|
||||
strcat(gcb,"dl"); break;
|
||||
case 'X': /* ... backwards */
|
||||
strcat(gcb,"dh"); break;
|
||||
case 's': /* substitute over chars */
|
||||
strcat(gcb,"cl"); break;
|
||||
case 'D': /* delete to end of line */
|
||||
strcat(gcb,"d$"); break;
|
||||
case 'C': /* change ... */
|
||||
strcat(gcb,"c$"); break;
|
||||
case 'Y': /* yank ... */
|
||||
strcat(gcb,"y$"); break;
|
||||
case '': /* scroll up one page */
|
||||
strcpy(gcb,"22"); break;
|
||||
case '': /* ... down one page */
|
||||
strcpy(gcb,"22"); break;
|
||||
case '': /* scroll up one line */
|
||||
strcpy(gcb,"1"); break;
|
||||
case '': /* ... down one line */
|
||||
strcpy(gcb,"1"); break;
|
||||
default:
|
||||
error();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if (macro<0)
|
||||
zerostack(&undo);
|
||||
insertmacro(gcb, 1);
|
||||
}
|
||||
|
||||
/* scroll the window up || down */
|
||||
|
||||
VOID PROC
|
||||
scroll(down)
|
||||
bool down;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (count <= 0)
|
||||
count = dofscroll;
|
||||
strput(CURoff);
|
||||
if (down) {
|
||||
curr = min(bufmax-1, nextline(TRUE, curr, count));
|
||||
i = min(bufmax-1, nextline(TRUE, pend, count));
|
||||
if (i > pend)
|
||||
scrollforward(i);
|
||||
}
|
||||
else {
|
||||
curr = bseekeol(max(0,nextline(FALSE, curr, count)));
|
||||
i = bseekeol(max(0,nextline(FALSE, ptop, count)));
|
||||
if (i < ptop) {
|
||||
if (canUPSCROLL)
|
||||
scrollback(i);
|
||||
else {
|
||||
ptop = i;
|
||||
setend();
|
||||
redisplay(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
strput(CURon);
|
||||
setpos(skipws(curr)); /* initialize new position - first nonwhite */
|
||||
yp = setY(curr);
|
||||
mvcur(yp, xp); /* go there */
|
||||
}
|
||||
|
||||
exec_type PROC
|
||||
editcore()
|
||||
{
|
||||
cmdtype cmd;
|
||||
extern bool s_wrapped;
|
||||
|
||||
/* rcb[0] = 0; rcp = rcb; */
|
||||
|
||||
if (diddled) {
|
||||
setpos(skipws(curr)); /* set cursor x position.. */
|
||||
yp = settop(LINES / 2); /* Y position */
|
||||
}
|
||||
if (diddled || zotscreen) /* redisplay? */
|
||||
redisplay(FALSE);
|
||||
mvcur(yp, xp); /* and move the cursor */
|
||||
|
||||
for (;;) {
|
||||
s_wrapped = 0;
|
||||
ch = readchar(); /* get a char */
|
||||
count = 0;
|
||||
if (isdigit(ch) && ch != '0')
|
||||
gcount(); /* ... a possible count */
|
||||
switch (cmd = movemap[(unsigned int)ch]) {
|
||||
case FILE_C:
|
||||
wr_stat(); /* write file stats */
|
||||
mvcur(yp, xp);
|
||||
break;
|
||||
|
||||
case WINDOW_UP:
|
||||
case WINDOW_DOWN:
|
||||
scroll(cmd==WINDOW_UP); /* scroll the window */
|
||||
break;
|
||||
|
||||
case REDRAW_C: /* redraw the window */
|
||||
redisplay(TRUE);
|
||||
mvcur(yp, xp);
|
||||
break;
|
||||
|
||||
case MARKER_C: /* set a marker */
|
||||
ch = tolower(readchar());
|
||||
if (ch >= 'a' && ch <= 'z')
|
||||
contexts[ch-'`'] = curr;
|
||||
else if (ch != ESC)
|
||||
error();
|
||||
break;
|
||||
|
||||
case REDO_C:
|
||||
if (rcb[0] != 0) {
|
||||
zerostack(&undo);
|
||||
insertmacro(rcb, 1);
|
||||
redoing = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case REWINDOW:
|
||||
zdraw(readchar()); /* shift the window */
|
||||
break;
|
||||
|
||||
case DEBUG_C: /* debugging stuff -- unused */
|
||||
break;
|
||||
|
||||
case ZZ_C: /* shortcut for :xit */
|
||||
ch = readchar();
|
||||
if (ch == 'Z')
|
||||
insertmacro(":x\r", 1);
|
||||
else if (ch != ESC)
|
||||
error();
|
||||
break;
|
||||
|
||||
case EDIT_C: /* drop into line mode */
|
||||
return E_EDIT;
|
||||
|
||||
case COLIN_C: /* do one exec mode command */
|
||||
return E_VISUAL;
|
||||
|
||||
case HARDMACRO:
|
||||
macrocommand(); /* 'hard-wired' macros */
|
||||
break;
|
||||
|
||||
case SOFTMACRO:
|
||||
exmacro(); /* run a macro */
|
||||
break;
|
||||
|
||||
case INSMACRO: /* macro for insert mode */
|
||||
case BAD_COMMAND:
|
||||
error();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (cmd < DELETE_C)
|
||||
movearound(cmd);
|
||||
else /*if (cmd < HARDMACRO)*/
|
||||
docommand(cmd);
|
||||
break;
|
||||
}
|
||||
lastexec = 0;
|
||||
}
|
||||
/* never exits here */
|
||||
}
|
||||
1114
src/cmd/levee/exec.c
Normal file
1114
src/cmd/levee/exec.c
Normal file
File diff suppressed because it is too large
Load Diff
237
src/cmd/levee/extern.h
Normal file
237
src/cmd/levee/extern.h
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#ifndef GLOBALS_D
|
||||
#define GLOBALS_D
|
||||
extern
|
||||
char lastchar, /* Last character read via peekc */
|
||||
ch; /* Global command char */
|
||||
extern
|
||||
exec_type mode; /* editor init state */
|
||||
extern
|
||||
int lastexec; /* last exec mode command */
|
||||
|
||||
extern
|
||||
int contexts['z'-'`'+1]; /* Labels */
|
||||
/* C O N S T A N T S */
|
||||
extern
|
||||
bool adjcurr[PARA_BACK+1],
|
||||
adjendp[PARA_BACK+1];
|
||||
/* A R G U M E N T S */
|
||||
extern
|
||||
char startcmd[]; /* initial command after read */
|
||||
extern
|
||||
char **argv; /* Arguments */
|
||||
extern
|
||||
int argc, /* # arguments */
|
||||
pc; /* Index into arguments */
|
||||
/* M A C R O S T U F F */
|
||||
extern
|
||||
struct macrecord mbuffer[];
|
||||
extern
|
||||
struct tmacro mcr[]; /* A place for executing macros */
|
||||
/* S E A R C H S T U F F */
|
||||
extern
|
||||
char dst[], /* last replacement pattern */
|
||||
lastpatt[], /* last search pattern */
|
||||
pattern[];
|
||||
extern
|
||||
int RE_start[9], /* start of substitute argument */
|
||||
RE_size [9], /* size of substitute argument */
|
||||
lastp; /* last character matched in search */
|
||||
extern
|
||||
struct undostack undo; /* To undo a command */
|
||||
/* R A N D O M S T R I N G S */
|
||||
|
||||
extern
|
||||
char instring[], /* Latest input */
|
||||
filenm[], /* Filename */
|
||||
altnm[], /* Alternate filename */
|
||||
gcb[]; /* Command buffer for mutations of insert */
|
||||
|
||||
extern
|
||||
char undobuf[],
|
||||
undotmp[],
|
||||
yankbuf[];
|
||||
extern
|
||||
int uread, /* reading from the undo stack */
|
||||
uwrite; /* writing to the undo stack */
|
||||
/* B U F F E R S */
|
||||
extern
|
||||
char rcb[], *rcp, /* last modification command */
|
||||
core[]; /* data space */
|
||||
|
||||
extern
|
||||
struct ybuf yank; /* last deleted/yanked text */
|
||||
/* STATIC INITIALIZATIONS: */
|
||||
|
||||
/* ttydef stuff */
|
||||
#if OS_ATARI | USE_TERMCAP
|
||||
extern int LINES, COLS;
|
||||
#endif
|
||||
|
||||
#if USE_TERMCAP
|
||||
extern bool CA, canUPSCROLL;
|
||||
extern char FkL,
|
||||
CurRT,
|
||||
CurLT,
|
||||
CurDN,
|
||||
CurUP;
|
||||
#endif /*USE_TERMCAP*/
|
||||
|
||||
extern char *TERMNAME,
|
||||
*HO,
|
||||
*UP,
|
||||
*CE,
|
||||
*CL,
|
||||
*OL,
|
||||
*BELL,
|
||||
*CM,
|
||||
*UpS,
|
||||
*CURoff,
|
||||
*CURon;
|
||||
|
||||
extern
|
||||
char Erasechar,
|
||||
eraseline;
|
||||
|
||||
extern
|
||||
char codeversion[], /* Editor version */
|
||||
fismod[], /* File is modified message */
|
||||
fisro[]; /* permission denied message */
|
||||
|
||||
extern
|
||||
char *excmds[],
|
||||
wordset[],
|
||||
spaces[];
|
||||
extern
|
||||
struct variable vars[];
|
||||
extern
|
||||
int autowrite,
|
||||
autocopy,
|
||||
overwrite,
|
||||
beautify,
|
||||
autoindent,
|
||||
dofscroll,
|
||||
shiftwidth,
|
||||
tabsize,
|
||||
list,
|
||||
wrapscan,
|
||||
bell,
|
||||
magic;
|
||||
/*extern
|
||||
char *suffix; */
|
||||
/* For movement routines */
|
||||
extern
|
||||
int setstep[];
|
||||
/* Where the last diddling left us */
|
||||
extern
|
||||
struct coord curpos;
|
||||
|
||||
/* initialize the buffer */
|
||||
extern
|
||||
int curr, /* Global cursor pos */
|
||||
lstart, lend, /* Start & end of current line */
|
||||
count, /* Latest count */
|
||||
xp, yp, /* Cursor window position */
|
||||
bufmax, /* End of file here */
|
||||
ptop, pend; /* Top & bottom of CRT window */
|
||||
extern
|
||||
bool modified, /* File has been modified */
|
||||
readonly, /* is this file readonly? */
|
||||
needchar, /* Peekc flag */
|
||||
deranged, /* Up-arrow || down-arrow left xpos in Oz. */
|
||||
indirect, /* Reading from an indirect file?? */
|
||||
redoing, /* doing a redo? */
|
||||
xerox, /* making a redo buffer? */
|
||||
newfile, /* Editing a new file? */
|
||||
newline, /* Last insert/delete included a EOL */
|
||||
lineonly, /* Dumb terminal? */
|
||||
zotscreen, /* do more after command in execmode */
|
||||
diddled; /* force redraw when I enter editcore */
|
||||
|
||||
extern
|
||||
int macro; /* Index into MCR macro execution stack */
|
||||
extern
|
||||
char lsearch;
|
||||
/* movement, command codes */
|
||||
extern
|
||||
cmdtype movemap[];
|
||||
#endif /*GLOBALS_D*/
|
||||
#ifndef EXTERN_D
|
||||
#define EXTERN_D
|
||||
#define wc(ch) (scan(65,'=',(ch),wordset)<65)
|
||||
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_MEMSET
|
||||
#define fillchar(p,l,c) memset((p),(c),(l))
|
||||
#elif HAVE_BLKFILL
|
||||
#define fillchar(p,l,c) blkfill((p),(c),(l))
|
||||
#endif
|
||||
#if HAVE_STRCHR
|
||||
#define index(s,c) strchr((s),(c))
|
||||
#endif
|
||||
|
||||
extern findstates PROC findCP();
|
||||
extern exec_type PROC editcore();
|
||||
|
||||
extern char PROC line(), peekc(), readchar();
|
||||
extern char PROC *findparse(),*makepat();
|
||||
|
||||
extern bool PROC getlin();
|
||||
extern bool PROC putfile();
|
||||
extern bool PROC doyank(), deletion(), putback();
|
||||
extern bool PROC pushb(),pushi(),pushmem(),uputcmd(), delete_to_undo();
|
||||
extern bool PROC ok_to_scroll(), move_to_undo();
|
||||
|
||||
extern int PROC min(), max(), fseekeol(), bseekeol(), settop();
|
||||
extern int PROC scan(), findDLE(), setY(), skipws(), nextline(), setX();
|
||||
extern int PROC insertion(), chop(), fixcore(), lookup(), to_index();
|
||||
extern int PROC doaddwork(), addfile(), expandargs(), to_line();
|
||||
extern int PROC findfwd(), findback(), getcontext(), getKey();
|
||||
extern int PROC cclass();
|
||||
extern int PROC insertfile();
|
||||
|
||||
extern VOID PROC strput(), numtoa(), clrprompt(), setend(), error();
|
||||
extern VOID PROC insert_to_undo(), resetX(), zerostack(), swap();
|
||||
extern VOID PROC mvcur(), printch(), prints(), writeline(), refresh();
|
||||
extern VOID PROC redisplay(), scrollback(), scrollforward(), prompt();
|
||||
extern VOID PROC setpos(), resetX(), insertmacro(), wr_stat();
|
||||
extern VOID PROC movearound(), printi(), println(), killargs();
|
||||
extern VOID PROC exec(), initcon(), fixcon(), version(), setcmd();
|
||||
extern VOID PROC toedit(), inputf(), fixmarkers(), errmsg();
|
||||
|
||||
#ifndef moveleft
|
||||
extern VOID PROC moveleft();
|
||||
#endif
|
||||
#ifndef moveright
|
||||
extern VOID PROC moveright();
|
||||
#endif
|
||||
#ifndef fillchar
|
||||
extern VOID PROC fillchar();
|
||||
#endif
|
||||
|
||||
#if USE_TERMCAP
|
||||
extern void tc_init();
|
||||
#endif
|
||||
|
||||
#endif /*EXTERN_D*/
|
||||
514
src/cmd/levee/find.c
Normal file
514
src/cmd/levee/find.c
Normal file
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#include "levee.h"
|
||||
#include "extern.h"
|
||||
#include "grep.h"
|
||||
#include <ctype.h>
|
||||
|
||||
int PROC amatch();
|
||||
int PROC locate();
|
||||
VOID PROC patsize();
|
||||
|
||||
static int arg; /* arguments inside of a RE */
|
||||
|
||||
int PROC
|
||||
REmatch(pattern, start, end)
|
||||
char *pattern;
|
||||
int start,end;
|
||||
{
|
||||
char *endp = &core[end];
|
||||
|
||||
if (!*pattern)
|
||||
return -1;
|
||||
arg = 0;
|
||||
while (start <= end && !amatch(pattern, &core[start], endp))
|
||||
start++;
|
||||
return start;
|
||||
}
|
||||
|
||||
int PROC
|
||||
omatch(pattern, cp, endp)
|
||||
char *pattern, **cp, *endp;
|
||||
{
|
||||
register int flag;
|
||||
extern int ignorecase;
|
||||
|
||||
switch (*pattern) {
|
||||
case LEND:
|
||||
return (**cp == EOL);
|
||||
case LSTART:
|
||||
return (*cp == core) || (*(*cp-1) == EOL);
|
||||
case TOKENB:
|
||||
return (*cp == core) || !isalnum(*(*cp-1));
|
||||
case TOKENE:
|
||||
return !isalnum(**cp);
|
||||
case LITCHAR:
|
||||
if (ignorecase)
|
||||
flag = (toupper(**cp) == toupper(*(pattern+1)));
|
||||
else
|
||||
flag = (**cp == *(pattern+1));
|
||||
break;
|
||||
case ANY:
|
||||
flag = (**cp != EOL);
|
||||
break;
|
||||
case CCL:
|
||||
flag = locate(pattern,*cp);
|
||||
break;
|
||||
case NCCL:
|
||||
flag = !locate(pattern,*cp);
|
||||
break;
|
||||
case ARGSTART:
|
||||
RE_start[arg] = (*cp)-core;
|
||||
return TRUE;
|
||||
case ARGEND:
|
||||
RE_size[arg] = ((*cp)-core) - RE_start[arg];
|
||||
++arg;
|
||||
return TRUE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (*cp <= endp && flag) {
|
||||
(*cp)++;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int PROC
|
||||
amatch(pattern,start,endp)
|
||||
char *pattern, *endp, *start;
|
||||
{
|
||||
int sarg = arg; /* save old arg match count for errors */
|
||||
|
||||
while (*pattern) {
|
||||
if (*pattern == CLOSURE) {
|
||||
/* Find the longest closure possible and work backwards trying
|
||||
* to match the rest of the pattern.
|
||||
*/
|
||||
char *oldstart = start;
|
||||
|
||||
++pattern; /* skip over the closure token */
|
||||
while (start <= endp && omatch(pattern,&start,endp))
|
||||
;
|
||||
/* start points at the character that failed the search.
|
||||
* Try to match the rest of the pattern against it, working
|
||||
* back down the line if failure
|
||||
*/
|
||||
patsize(&pattern);
|
||||
while (start >= oldstart)
|
||||
if (amatch(pattern,start--,endp))
|
||||
return TRUE;
|
||||
arg = sarg;
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
if (!omatch(pattern,&start,endp)) {
|
||||
arg = sarg;
|
||||
return FALSE;
|
||||
}
|
||||
patsize(&pattern);
|
||||
}
|
||||
}
|
||||
lastp = start-core;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* increment pattern by the size of the token being scanned
|
||||
*/
|
||||
VOID PROC
|
||||
patsize(pattern)
|
||||
register char **pattern;
|
||||
{
|
||||
register int count;
|
||||
|
||||
switch (**pattern) {
|
||||
case LITCHAR:
|
||||
*pattern += 2;
|
||||
break;
|
||||
case CCL:
|
||||
case NCCL:
|
||||
count = *(++*pattern) & 0xff;
|
||||
*pattern += 1+count;
|
||||
break;
|
||||
default:
|
||||
(*pattern)++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int PROC
|
||||
locate(pattern,linep)
|
||||
/* locate: find a character in a closure */
|
||||
char *pattern;
|
||||
register char *linep;
|
||||
{
|
||||
register char *p = 1+pattern;
|
||||
register int count;
|
||||
|
||||
if ((count = (*p++)&0xff) == 0)
|
||||
return FALSE;
|
||||
while (count--)
|
||||
if (*p++ == *linep)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
char *p;
|
||||
|
||||
VOID PROC
|
||||
concatch(c)
|
||||
/* add a character to the pattern */
|
||||
char c;
|
||||
{
|
||||
if (p < &pattern[MAXPAT-1])
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
char PROC
|
||||
esc(s)
|
||||
char **s;
|
||||
{
|
||||
if (**s != ESCAPE || *(1+*s) == 0)
|
||||
return **s;
|
||||
++(*s);
|
||||
switch (**s) {
|
||||
case 't': return TAB;
|
||||
case 'n': return EOL;
|
||||
}
|
||||
return **s;
|
||||
}
|
||||
|
||||
char * PROC
|
||||
dodash(src)
|
||||
/* parse the innards of a [] */
|
||||
char *src;
|
||||
{
|
||||
int k;
|
||||
char *start = src;
|
||||
char cs[128];
|
||||
|
||||
fillchar(cs,sizeof(cs),FALSE);
|
||||
while (*src && *src != CCLEND) {
|
||||
if (*src == DASH && src>start && src[1] != CCLEND && src[-1]<src[1]) {
|
||||
for ( k = src[-1]; k <= src[1]; k++)
|
||||
cs[k] = TRUE;
|
||||
src++;
|
||||
}
|
||||
else
|
||||
cs[(unsigned int)esc(&src)] = TRUE;
|
||||
src++;
|
||||
}
|
||||
for (k=0; k < sizeof(cs); k++)
|
||||
if (cs[k])
|
||||
concatch((char)k);
|
||||
return src;
|
||||
}
|
||||
|
||||
char * PROC
|
||||
badccl(src)
|
||||
/* a [] was encountered. is it a CCL (match one of the included
|
||||
* characters); or is it a NCCL (match all but the included characters)?
|
||||
*/
|
||||
char *src;
|
||||
{
|
||||
char *jstart;
|
||||
|
||||
if (*src == NEGATE) {
|
||||
concatch(NCCL);
|
||||
++src;
|
||||
}
|
||||
else
|
||||
concatch(CCL);
|
||||
jstart = p;
|
||||
concatch(0); /* this will be the length of the pattern */
|
||||
src = dodash(src);
|
||||
*jstart = (p-jstart)-1;
|
||||
return src;
|
||||
}
|
||||
|
||||
/* patterns that cannot be closed */
|
||||
char badclose[] = { LSTART, LEND, CLOSURE, 0 };
|
||||
|
||||
char * PROC
|
||||
makepat(string,delim)
|
||||
char *string, delim;
|
||||
/* make up the pattern string for find -- ripped from 'Software Tools' */
|
||||
{
|
||||
char *cp = 0, *oldcp;
|
||||
char *start = string;
|
||||
int inarg = FALSE;
|
||||
|
||||
for(arg=0;arg<9;++arg)
|
||||
RE_start[arg] = RE_size[arg] = (-1);
|
||||
arg = 0;
|
||||
p = pattern;
|
||||
|
||||
while ((*string != delim) && (*string != 0)) {
|
||||
oldcp = cp;
|
||||
cp = p;
|
||||
|
||||
if (!magic) /* kludge for nonmagical patterns */
|
||||
goto normal;
|
||||
if (*string == ANY)
|
||||
concatch(ANY);
|
||||
else if ((*string == LSTART) && (string == start))
|
||||
concatch(LSTART);
|
||||
else if ((*string == LEND) && (string[1] == delim || string[1] == 0))
|
||||
concatch(LEND);
|
||||
else if (*string == CCL)
|
||||
string = badccl(1+string);
|
||||
else if ((*string == CLOSURE) && (p > pattern)) {
|
||||
cp = oldcp;
|
||||
if (strchr(badclose, *cp) || p >= &pattern[MAXPAT-1])
|
||||
return NULL;
|
||||
moveright(cp,1+cp,(int)(p-cp));
|
||||
*cp = CLOSURE;
|
||||
p++;
|
||||
}
|
||||
else if (*string == ESCAPE) {
|
||||
if (string[1] == ARGSTART || string[1] == ARGEND) {
|
||||
if (string[1] == ARGEND)
|
||||
if (!inarg)
|
||||
goto normal;
|
||||
if (string[1] == ARGSTART) {
|
||||
if (inarg)
|
||||
goto normal;
|
||||
if (++arg > 9)
|
||||
return NULL;
|
||||
}
|
||||
inarg = !inarg;
|
||||
}
|
||||
else if (string[1] != TOKENB && string[1] != TOKENE)
|
||||
goto normal;
|
||||
++string;
|
||||
concatch(*string);
|
||||
}
|
||||
else {
|
||||
normal:concatch(LITCHAR);
|
||||
concatch(esc(&string));
|
||||
}
|
||||
if (*string)
|
||||
string++;
|
||||
}
|
||||
if (inarg)
|
||||
concatch(ARGEND);
|
||||
if (p > pattern) { /* new pattern was created */
|
||||
strncpy(lastpatt,start,(int)(string-start));
|
||||
lastpatt[string-start] = 0;
|
||||
concatch(0);
|
||||
if (p-pattern >= MAXPAT)
|
||||
return NULL;
|
||||
}
|
||||
return (*string == delim)?(string+1):(string);
|
||||
}
|
||||
|
||||
int PROC
|
||||
findfwd(pattern,start,endp)
|
||||
/* look for a regular expression forward */
|
||||
char *pattern;
|
||||
int start, endp;
|
||||
{
|
||||
int ep;
|
||||
|
||||
while (start < endp) {
|
||||
ep = fseekeol(start);
|
||||
if ((start = REmatch(pattern, start, ep)) <= ep)
|
||||
return start;
|
||||
}
|
||||
return ERR;
|
||||
}
|
||||
|
||||
int PROC
|
||||
findback(pattern,start,endp)
|
||||
/* look for a regular expression backwards */
|
||||
char *pattern;
|
||||
int start, endp;
|
||||
{
|
||||
int ep,i;
|
||||
|
||||
while (start > endp) {
|
||||
ep = bseekeol(start);
|
||||
if ((i = REmatch(pattern, ep, start)) <= start)
|
||||
return i;
|
||||
start = ep-1;
|
||||
}
|
||||
return ERR;
|
||||
}
|
||||
|
||||
bool s_wrapped = 0;
|
||||
|
||||
char * PROC
|
||||
search(pat, start)
|
||||
/* get a token for find & find it in the buffer
|
||||
*/
|
||||
char *pat;
|
||||
int *start;
|
||||
{
|
||||
bool forwd;
|
||||
int pos;
|
||||
char *p;
|
||||
|
||||
forwd = ((lsearch = *pat) == '/');
|
||||
if ((p=makepat(pat+1,*pat)) == NULL) {
|
||||
*start = ERR;
|
||||
return pat;
|
||||
}
|
||||
do {
|
||||
if (forwd) {
|
||||
pos = findfwd(pattern, (*start)+1, bufmax-1);
|
||||
if ((pos == ERR) && wrapscan) {
|
||||
s_wrapped = 1;
|
||||
pos = findfwd(pattern, 0, (*start)-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pos = findback(pattern, (*start)-1, 0);
|
||||
if ((pos == ERR) && wrapscan) {
|
||||
s_wrapped = 1;
|
||||
pos = findback(pattern, bufmax-1, (*start)+1);
|
||||
}
|
||||
}
|
||||
*start = pos;
|
||||
} while (--count > 0 && *start != ERR);
|
||||
return p;
|
||||
}
|
||||
|
||||
char * PROC
|
||||
findparse(src,idx,start) /* driver for ?, /, && : lineranges */
|
||||
char *src;
|
||||
int *idx,start;
|
||||
{
|
||||
int addr = start;
|
||||
char c;
|
||||
|
||||
s_wrapped = 0;
|
||||
|
||||
switch (*src) {
|
||||
case '/':
|
||||
case '?':
|
||||
/* get a token for find & find it in the buffer */
|
||||
src = search(src,&addr);
|
||||
break;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
/* fabricate a count */
|
||||
count = 0;
|
||||
while (*src >= '0' && *src <= '9')
|
||||
count = (count*10) + *(src++) - '0';
|
||||
|
||||
addr = to_index(count);
|
||||
break;
|
||||
case '$':
|
||||
addr = bufmax-1;
|
||||
src++;
|
||||
break;
|
||||
case '.' :
|
||||
src++;
|
||||
break;
|
||||
case '`':
|
||||
case '\'':
|
||||
addr = getcontext(*(src+1), (*src == '\''));
|
||||
src += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
while (addr>=0 && (*src =='+' || *src == '-')) {
|
||||
c = *(src++);
|
||||
/* skip delimiter */
|
||||
if (*src == '/' || *src == '?') {
|
||||
count = 1;
|
||||
if ((src = search(src,&addr)) == NULL)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (*src >= '0' && *src <= '9') {
|
||||
/* fabricate a count */
|
||||
count = 0;
|
||||
while (*src >= '0' && *src <= '9')
|
||||
count = (count*10) + *(src++) - '0';
|
||||
}
|
||||
else
|
||||
count = -1; /* for naked + & - */
|
||||
if (count == 0) /* +0 goes to beginning of line */
|
||||
addr = bseekeol(addr);
|
||||
else {
|
||||
addr = nextline((c=='+'), addr, count);
|
||||
if (c=='-' && addr > 0)
|
||||
addr = bseekeol(addr);
|
||||
}
|
||||
if (addr >= bufmax)
|
||||
addr = -1;
|
||||
}
|
||||
}
|
||||
*idx = addr;
|
||||
return(src);
|
||||
}
|
||||
|
||||
int PROC
|
||||
nextline(advance,dest,count)
|
||||
bool advance;
|
||||
int dest,count;
|
||||
{
|
||||
if (advance)
|
||||
do {
|
||||
dest = fseekeol(dest) + 1;
|
||||
count--;
|
||||
} while (count>0 && dest<bufmax);
|
||||
else
|
||||
do {
|
||||
dest = bseekeol(dest) - 1;
|
||||
count--;
|
||||
} while (count>0 && dest>=0);
|
||||
return(dest);
|
||||
}
|
||||
|
||||
int PROC
|
||||
fseekeol(origin)
|
||||
int origin;
|
||||
{
|
||||
return(origin + scan(bufmax-origin-1,'=',EOL,&core[origin]));
|
||||
}
|
||||
|
||||
int PROC
|
||||
bseekeol(origin)
|
||||
int origin;
|
||||
{
|
||||
return(origin + scan(-origin,'=',EOL,&core[origin-1]));
|
||||
}
|
||||
|
||||
/* get something from the context table */
|
||||
|
||||
int PROC
|
||||
getcontext(c,begline)
|
||||
char c;
|
||||
bool begline;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (c == '\'')
|
||||
c = '`';
|
||||
if (c >= '`' && c <= 'z')
|
||||
i = contexts[c-'`'];
|
||||
else
|
||||
i = -1;
|
||||
if (begline && i>=0)
|
||||
return(bseekeol(i));
|
||||
return(i);
|
||||
}
|
||||
122
src/cmd/levee/flexcall.c
Normal file
122
src/cmd/levee/flexcall.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
/*
|
||||
* flexos interface for levee (Metaware C)
|
||||
*/
|
||||
#include "levee.h"
|
||||
|
||||
#if OS_FLEXOS
|
||||
#include <flexos.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static int oldkmode;
|
||||
static int oldsmode;
|
||||
|
||||
int
|
||||
min(a,b)
|
||||
{
|
||||
return (a>b) ? b : a;
|
||||
}
|
||||
|
||||
int
|
||||
max(a,b)
|
||||
{
|
||||
return (a<b) ? b : a;
|
||||
}
|
||||
|
||||
strput(s)
|
||||
char *s;
|
||||
{
|
||||
s_write(0x01, 1L, s, (long)strlen(s), 0L);
|
||||
}
|
||||
|
||||
char *
|
||||
basename(s)
|
||||
char *s;
|
||||
{
|
||||
char *strrchr();
|
||||
char *p;
|
||||
|
||||
if ((p=strrchr(s,'/')) || (p=strrchr(s,'\\')) || (p = strrchr(s,':')))
|
||||
return 1+p;
|
||||
return s;
|
||||
}
|
||||
|
||||
getKey()
|
||||
{
|
||||
char c;
|
||||
|
||||
s_read(0x0101, 0L, &c, 1L, 0L);
|
||||
return c;
|
||||
}
|
||||
|
||||
initcon()
|
||||
{
|
||||
CONSOLE tty;
|
||||
|
||||
s_get(T_CON, 1L, &tty, SSIZE(tty));
|
||||
oldkmode = tty.con_kmode;
|
||||
oldsmode = tty.con_smode;
|
||||
tty.con_kmode = 0x0667;
|
||||
tty.con_smode = 0;
|
||||
s_set(T_CON, 1L, &tty, SSIZE(tty));
|
||||
}
|
||||
|
||||
fixcon()
|
||||
{
|
||||
CONSOLE tty;
|
||||
|
||||
s_get(T_CON, 1L, &tty, SSIZE(tty));
|
||||
tty.con_kmode = oldkmode;
|
||||
tty.con_smode = oldsmode;
|
||||
s_set(T_CON, 1L, &tty, SSIZE(tty));
|
||||
}
|
||||
|
||||
char *
|
||||
strdup(s)
|
||||
char *s;
|
||||
{
|
||||
char *malloc();
|
||||
char *p;
|
||||
|
||||
if (p=malloc(strlen(s)+1))
|
||||
strcpy(p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
getpid()
|
||||
{
|
||||
PROCESS myself;
|
||||
|
||||
s_get(T_PDEF, 0L, &myself, SSIZE(myself));
|
||||
|
||||
return myself.ps_pid;
|
||||
}
|
||||
|
||||
strlwr(s)
|
||||
char *s;
|
||||
{
|
||||
while (*s) {
|
||||
if (isupper(*s))
|
||||
*s += 32;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
70
src/cmd/levee/gemcall.c
Normal file
70
src/cmd/levee/gemcall.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
/*
|
||||
* Gemdos (Atari ST) bindings for levee (Alcyon/Sozobon C)
|
||||
*/
|
||||
#include "levee.h"
|
||||
|
||||
#if OS_ATARI
|
||||
#include <atari\osbind.h>
|
||||
|
||||
strput(s)
|
||||
register char *s;
|
||||
{
|
||||
write(1, s, strlen(s));
|
||||
}
|
||||
|
||||
|
||||
zwrite(s,len)
|
||||
char *s;
|
||||
{
|
||||
write(1, s, len);
|
||||
}
|
||||
|
||||
|
||||
min(a,b)
|
||||
register int a, b;
|
||||
{
|
||||
return (a<b)?a:b;
|
||||
}
|
||||
|
||||
|
||||
max(a,b)
|
||||
register int a, b;
|
||||
{
|
||||
return (a>b)?a:b;
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
getKey()
|
||||
/* get input from the keyboard. All odd keys (function keys, et al) that
|
||||
* do not produce a character have their scancode orred with $80 and returned.
|
||||
*/
|
||||
{
|
||||
unsigned c;
|
||||
long key;
|
||||
|
||||
c = (key = Crawcin()) & 0xff;
|
||||
if (!c)
|
||||
c = (((unsigned)(key>>16))|0x80) & 0xff;
|
||||
return c;
|
||||
} /* getKey */
|
||||
#endif /*OS_ATARI*/
|
||||
547
src/cmd/levee/globals.c
Normal file
547
src/cmd/levee/globals.c
Normal file
@@ -0,0 +1,547 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2008 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
/* global declarations */
|
||||
|
||||
#include "levee.h"
|
||||
#define GLOBALS
|
||||
|
||||
char lastchar, /* Last character read via peekc */
|
||||
ch; /* Global command char */
|
||||
|
||||
exec_type mode; /* editor init state */
|
||||
int lastexec = 0; /* last exec command */
|
||||
|
||||
int contexts['z'-'`'+1]; /* Labels */
|
||||
|
||||
/* C O N S T A N T S */
|
||||
|
||||
bool adjcurr[PARA_BACK+1],
|
||||
adjendp[PARA_BACK+1];
|
||||
|
||||
/* A R G U M E N T S */
|
||||
char startcmd[80] = ""; /* initial command after read */
|
||||
char **argv; /* Arguments */
|
||||
int argc=0, /* # arguments */
|
||||
pc=0; /* Index into arguments */
|
||||
#if 0
|
||||
struct stat thisfile; /* status on current file, for writeout... */
|
||||
#endif
|
||||
|
||||
/* M A C R O S T U F F */
|
||||
struct macrecord mbuffer[MAXMACROS];
|
||||
struct tmacro mcr[NMACROS]; /* A place for executing macros */
|
||||
|
||||
/* S E A R C H S T U F F */
|
||||
char dst[80] = "", /* last replacement pattern */
|
||||
lastpatt[80] = "", /* last search pattern */
|
||||
pattern[MAXPAT] = ""; /* encoded last pattern */
|
||||
|
||||
int RE_start[9], /* start of substitution arguments */
|
||||
RE_size [9], /* size of substitution arguments */
|
||||
lastp; /* end of last pattern */
|
||||
|
||||
struct undostack undo; /* To undo a command */
|
||||
|
||||
|
||||
/* R A N D O M S T R I N G S */
|
||||
|
||||
char instring[200], /* Latest input */
|
||||
filenm[80] = "", /* Filename */
|
||||
altnm[80] = ""; /* Alternate filename */
|
||||
char gcb[16]; /* Command buffer for mutations of insert */
|
||||
|
||||
char undobuf[40];
|
||||
char undotmp[40];
|
||||
char yankbuf[40];
|
||||
|
||||
HANDLE uread, /* reading from the undo stack */
|
||||
uwrite; /* writing to the undo stack */
|
||||
|
||||
/* B U F F E R S */
|
||||
char rcb[256]; /* last modification command */
|
||||
char *rcp; /* this points at the end of the redo */
|
||||
char core[SIZE+1]; /* data space */
|
||||
|
||||
struct ybuf yank; /* last deleted/yanked text */
|
||||
|
||||
|
||||
/* STATIC INITIALIZATIONS: */
|
||||
|
||||
/* ttydef stuff */
|
||||
|
||||
#if OS_ATARI | USE_TERMCAP
|
||||
int LINES, COLS;
|
||||
#endif
|
||||
|
||||
#if TTY_ZTERM
|
||||
char *TERMNAME = "zterm",
|
||||
*HO = "\001", /* goto top of screen */
|
||||
*UP = "\002", /* move up 1 line? */
|
||||
*CE = "\003", /* clear to end of line */
|
||||
*CL = "\004", /* clearscreen */
|
||||
*OL = "\005", /* open current line down */
|
||||
*UpS = "\006", /* scroll up 1 line */
|
||||
*BELL= "\007", /* ring the bell */
|
||||
*CM = "yes", /* cursor movement exists */
|
||||
*CURoff,
|
||||
*CURon;
|
||||
#endif /*ZTERM*/
|
||||
|
||||
#if TTY_ANSI
|
||||
#if OS_DOS
|
||||
char *TERMNAME = "braindamaged ansi",
|
||||
#else
|
||||
char *TERMNAME = "hardwired ansi",
|
||||
#endif
|
||||
*HO = "\033[H",
|
||||
*UP = "\033[A",
|
||||
*CE = "\033[K",
|
||||
*CL = "\033[H\033[J",
|
||||
#if OS_DOS
|
||||
*OL = NULL,
|
||||
*UpS = NULL,
|
||||
#else
|
||||
*OL = "\033[L",
|
||||
*UpS = "\033[L",
|
||||
#endif
|
||||
*BELL= "\007",
|
||||
*CM = "\033[%d;%dH",
|
||||
*CURoff,
|
||||
*CURon;
|
||||
#endif /*TTY_ANSI*/
|
||||
|
||||
#if TTY_VT52
|
||||
#if OS_ATARI
|
||||
char *TERMNAME = "Atari ST",
|
||||
#else
|
||||
#if OS_FLEXOS
|
||||
char *TERMNAME = "Flexos console",
|
||||
#else
|
||||
char *TERMNAME = "hardwired vt52",
|
||||
#endif /*OS_FLEXOS*/
|
||||
#endif /*OS_ATARI*/
|
||||
*HO = "\033H",
|
||||
*UP = "\033A",
|
||||
*CE = "\033K",
|
||||
*CL = "\033E",
|
||||
*OL = "\033L",
|
||||
*BELL= "\007",
|
||||
*CM = "\033Y??",
|
||||
#if OS_FLEXOS
|
||||
*UpS = NULL, /* Reverse scrolling is painfully slow */
|
||||
#else
|
||||
*UpS = "\033I",
|
||||
#endif
|
||||
*CURoff= "\033f",
|
||||
*CURon = "\033e";
|
||||
#endif /*TTY_VT52*/
|
||||
|
||||
#if USE_TERMCAP
|
||||
bool CA, canUPSCROLL;
|
||||
char FkL, CurRT, CurLT, CurUP, CurDN;
|
||||
|
||||
char *TERMNAME, /* will be set in termcap handling */
|
||||
*HO,
|
||||
*UP,
|
||||
*CE,
|
||||
*CL,
|
||||
*OL,
|
||||
*BELL,
|
||||
*CM,
|
||||
*UpS,
|
||||
*CURoff,
|
||||
*CURon;
|
||||
#endif /*USE_TERMCAP*/
|
||||
|
||||
char Erasechar = ERASE, /* our erase character */
|
||||
eraseline = 'X'-'@'; /* and line-kill character */
|
||||
|
||||
char fismod[] = "File is modified", /* File is modified message */
|
||||
fisro[] = "File is readonly"; /* when you can't write the file */
|
||||
|
||||
char *excmds[] = {
|
||||
"print", /* lines to screen */
|
||||
"quit", /* quit editor */
|
||||
"read", /* add file to buffer */
|
||||
"edit", /* replace buffer with file */
|
||||
"write", /* write out file */
|
||||
"wq", /* write file and quit */
|
||||
"next", /* make new arglist or traverse this one */
|
||||
"substitute", /* pattern */
|
||||
"xit", /* write changes and quit */
|
||||
"file", /* show/set file name */
|
||||
"set", /* options */
|
||||
"rm", /* a file */
|
||||
"previous", /* back up in arglist */
|
||||
"delete", /* lines from buffer */
|
||||
"=", /* tell line number */
|
||||
"yank", /* lines from buffer */
|
||||
"put", /* back yanked lines */
|
||||
"visual", /* go to visual mode */
|
||||
"exec", /* go to exec mode */
|
||||
"insert", /* text below current line */
|
||||
"open", /* insert text above current line */
|
||||
"change", /* lines */
|
||||
"undo", /* last change */
|
||||
"!", /* shell escape */
|
||||
"map", /* keyboard macro */
|
||||
"unmap", /* keyboard macro */
|
||||
"source", /* read commands from file */
|
||||
"version", /* print version # */
|
||||
"args", /* print argument list */
|
||||
"rewind", /* rewind argument list */
|
||||
NULL
|
||||
};
|
||||
|
||||
char wordset[] = "0123456789$_#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
char spaces[] = { TAB,EOL,' ',0 };
|
||||
|
||||
int shiftwidth = 4,
|
||||
#if USE_TERMCAP | OS_ATARI
|
||||
dofscroll,
|
||||
#else
|
||||
dofscroll = LINES/2,
|
||||
#endif
|
||||
tabsize = 8;
|
||||
int autoindent = YES,
|
||||
autocopy = NO,
|
||||
autowrite = YES,
|
||||
wrapscan = YES,
|
||||
overwrite = YES,
|
||||
beautify = YES,
|
||||
list = NO,
|
||||
magic = YES,
|
||||
bell = YES,
|
||||
#if OS_ATARI
|
||||
mapslash,
|
||||
#endif
|
||||
ignorecase = NO;
|
||||
|
||||
struct variable vars[]={
|
||||
{"terminal", "", VSTR, V_CONST, (void*)&TERMNAME },
|
||||
{"shiftwidth","sw", VINT, 0, (void*)&shiftwidth },
|
||||
{"scroll", "", VINT, 0, (void*)&dofscroll },
|
||||
{"tabsize", "ts", VINT, V_DISPLAY, (void*)&tabsize },
|
||||
{"autoindent","ai", VBOOL, 0, (void*)&autoindent },
|
||||
{"autocopy", "ac", VBOOL, 0, (void*)&autocopy },
|
||||
{"autowrite", "aw", VBOOL, 0, (void*)&autowrite },
|
||||
{"wrapscan", "ws", VBOOL, 0, (void*)&wrapscan },
|
||||
{"overwrite", "ow", VBOOL, 0, (void*)&overwrite },
|
||||
{"beautify", "be", VBOOL, 0, (void*)&beautify },
|
||||
{"list", "", VBOOL, V_DISPLAY, (void*)&list },
|
||||
{"magic", "", VBOOL, 0, (void*)&magic },
|
||||
{"ignorecase","ic", VBOOL, 0, (void*)&ignorecase },
|
||||
{"bell", "", VBOOL, 0, (void*)&bell },
|
||||
#if OS_ATARI
|
||||
{"mapslash", "ms", VBOOL, 0, (void*)&mapslash },
|
||||
#endif
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/* For movement routines */
|
||||
int setstep[2] = {-1,1};
|
||||
|
||||
/* Where the last diddling left us */
|
||||
struct coord curpos={0, 0};
|
||||
|
||||
/* initialize the buffer */
|
||||
int bufmax = 0, /* End of file here */
|
||||
lstart = 0, lend = 0, /* Start & end of current line */
|
||||
ptop = 0, pend = 0, /* Top & bottom of CRT window */
|
||||
curr = 0, /* Global cursor pos */
|
||||
xp = 0, yp = 0, /* Cursor window position */
|
||||
count = 0; /* Latest count */
|
||||
|
||||
bool modified= NO, /* File has been modified */
|
||||
readonly= NO, /* is this file readonly? */
|
||||
needchar= YES, /* Peekc flag */
|
||||
deranged= NO, /* Up-arrow || down-arrow left xpos in Oz. */
|
||||
indirect= NO, /* Reading from an indirect file?? */
|
||||
redoing = NO, /* doing a redo? */
|
||||
xerox = NO, /* making a redo buffer? */
|
||||
newfile = YES, /* Editing a new file? */
|
||||
newline = NO, /* Last insert/delete included a EOL */
|
||||
lineonly= NO, /* Dumb terminal? */
|
||||
zotscreen=NO, /* ask for [more] in execmode */
|
||||
diddled = NO; /* force new window in editcore */
|
||||
|
||||
int macro = -1; /* Index into MCR */
|
||||
char lsearch = 0; /* for N and n'ing... */
|
||||
|
||||
/* movement, command codes */
|
||||
|
||||
cmdtype movemap[256]={
|
||||
/*^@*/ BAD_COMMAND,
|
||||
/*^A*/ DEBUG_C,
|
||||
/*^B*/ HARDMACRO,
|
||||
/*^C*/ BAD_COMMAND,
|
||||
/*^D*/ WINDOW_UP,
|
||||
/*^E*/ HARDMACRO,
|
||||
/*^F*/ HARDMACRO,
|
||||
/*^G*/ FILE_C,
|
||||
/*^H*/ GO_LEFT, /* also leftarrow */
|
||||
/*^I*/ REDRAW_C,
|
||||
/*^J*/ GO_DOWN, /* also downarrow */
|
||||
/*^K*/ GO_UP, /* also uparrow */
|
||||
/*^L*/ GO_RIGHT, /* also rightarrow */
|
||||
/*^M*/ CR_FWD,
|
||||
/*^N*/ BAD_COMMAND,
|
||||
/*^O*/ BAD_COMMAND,
|
||||
/*^P*/ BAD_COMMAND,
|
||||
/*^Q*/ BAD_COMMAND,
|
||||
/*^R*/ BAD_COMMAND,
|
||||
/*^S*/ BAD_COMMAND,
|
||||
/*^T*/ BAD_COMMAND,
|
||||
/*^U*/ WINDOW_DOWN,
|
||||
/*^V*/ BAD_COMMAND,
|
||||
/*^W*/ BAD_COMMAND,
|
||||
/*^X*/ BAD_COMMAND,
|
||||
/*^Y*/ HARDMACRO,
|
||||
/*^Z*/ BAD_COMMAND,
|
||||
/*^[*/ BAD_COMMAND,
|
||||
/*^\*/ BAD_COMMAND,
|
||||
/*^]*/ BAD_COMMAND,
|
||||
/*^^*/ BAD_COMMAND,
|
||||
/*^_*/ BAD_COMMAND,
|
||||
/* */ GO_RIGHT,
|
||||
/*! */ EXEC_C,
|
||||
/*" */ BAD_COMMAND,
|
||||
/*# */ BAD_COMMAND,
|
||||
/*$ */ TO_EOL,
|
||||
/*% */ MATCHEXPR,
|
||||
/*& */ RESUBST_C,
|
||||
/*\ */ TO_MARK_LINE,
|
||||
/*( */ SENT_BACK,
|
||||
/*) */ SENT_FWD,
|
||||
/** */ BAD_COMMAND,
|
||||
/*+ */ CR_FWD,
|
||||
/*, */ BAD_COMMAND,
|
||||
/*- */ CR_BACK,
|
||||
/*. */ REDO_C,
|
||||
/*/ */ PATT_FWD,
|
||||
/*0 */ TO_COL,
|
||||
/*1 */ BAD_COMMAND,
|
||||
/*2 */ BAD_COMMAND,
|
||||
/*3 */ BAD_COMMAND,
|
||||
/*4 */ BAD_COMMAND,
|
||||
/*5 */ BAD_COMMAND,
|
||||
/*6 */ BAD_COMMAND,
|
||||
/*7 */ BAD_COMMAND,
|
||||
/*8 */ BAD_COMMAND,
|
||||
/*9 */ BAD_COMMAND,
|
||||
/*: */ COLIN_C,
|
||||
/*; */ BAD_COMMAND,
|
||||
/*< */ ADJUST_C,
|
||||
/*= */ BAD_COMMAND,
|
||||
/*> */ ADJUST_C,
|
||||
/*? */ PATT_BACK,
|
||||
/*@ */ BAD_COMMAND,
|
||||
/*A */ A_AT_END,
|
||||
/*B */ BACK_WD,
|
||||
/*C */ HARDMACRO,
|
||||
/*D */ HARDMACRO,
|
||||
/*E */ BAD_COMMAND,
|
||||
/*F */ BACK_CHAR,
|
||||
/*G */ GLOBAL_LINE,
|
||||
/*H */ PAGE_BEGIN,
|
||||
/*I */ I_AT_NONWHITE,
|
||||
/*J */ JOIN_C,
|
||||
/*K */ BAD_COMMAND,
|
||||
/*L */ PAGE_END,
|
||||
/*M */ PAGE_MIDDLE,
|
||||
/*N */ BSEARCH,
|
||||
/*O */ OPENUP_C,
|
||||
/*P */ PUT_AFTER,
|
||||
/*Q */ EDIT_C,
|
||||
/*R */ BIG_REPL_C,
|
||||
/*S */ BAD_COMMAND,
|
||||
/*T */ BACKTO_CHAR,
|
||||
/*U */ BAD_COMMAND,
|
||||
/*V */ BAD_COMMAND,
|
||||
/*W */ FORWD,
|
||||
/*X */ HARDMACRO,
|
||||
/*Y */ HARDMACRO,
|
||||
/*Z */ ZZ_C,
|
||||
/*[ */ BAD_COMMAND,
|
||||
/*\ */ BAD_COMMAND,
|
||||
/*] */ BAD_COMMAND,
|
||||
/*^ */ NOTWHITE,
|
||||
/*_ */ BAD_COMMAND,
|
||||
/*` */ TO_MARK,
|
||||
/*a */ APPEND_C,
|
||||
/*b */ BACK_WD,
|
||||
/*c */ CHANGE_C,
|
||||
/*d */ DELETE_C,
|
||||
/*e */ FORWD,
|
||||
/*f */ TO_CHAR,
|
||||
/*g */ BAD_COMMAND,
|
||||
/*h */ GO_LEFT,
|
||||
/*i */ INSERT_C,
|
||||
/*j */ GO_DOWN,
|
||||
/*k */ GO_UP,
|
||||
/*l */ GO_RIGHT,
|
||||
/*m */ MARKER_C,
|
||||
/*n */ FSEARCH,
|
||||
/*o */ OPEN_C,
|
||||
/*p */ PUT_BEFORE,
|
||||
/*q */ BAD_COMMAND,
|
||||
/*r */ REPLACE_C,
|
||||
/*s */ HARDMACRO,
|
||||
/*t */ UPTO_CHAR,
|
||||
/*u */ UNDO_C,
|
||||
/*v */ BTO_WD,
|
||||
/*w */ TO_WD,
|
||||
/*x */ HARDMACRO,
|
||||
/*y */ YANK_C,
|
||||
/*z */ REWINDOW,
|
||||
/*{ */ PARA_BACK,
|
||||
/*| */ TO_COL,
|
||||
/*} */ PARA_FWD,
|
||||
/*~ */ TWIDDLE_C,
|
||||
/*^?*/ BAD_COMMAND,
|
||||
/*80*/ BAD_COMMAND,
|
||||
/*81*/ BAD_COMMAND,
|
||||
/*82*/ BAD_COMMAND,
|
||||
/*83*/ BAD_COMMAND,
|
||||
/*84*/ BAD_COMMAND,
|
||||
/*85*/ BAD_COMMAND,
|
||||
/*x6*/ BAD_COMMAND,
|
||||
/*x7*/ BAD_COMMAND,
|
||||
/*x8*/ BAD_COMMAND,
|
||||
/*x9*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND,
|
||||
/*xx*/ BAD_COMMAND
|
||||
};
|
||||
36
src/cmd/levee/grep.h
Normal file
36
src/cmd/levee/grep.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#define LEND '$'
|
||||
#define LSTART '^'
|
||||
#define LITCHAR 'c'
|
||||
#define ANY '.'
|
||||
#define CCL '['
|
||||
#define NCCL '!'
|
||||
#define DASH '-'
|
||||
#define CCLEND ']'
|
||||
#define NEGATE '^'
|
||||
#define CLOSURE '*'
|
||||
#define ESCAPE '\\'
|
||||
#define TOKENB '<'
|
||||
#define TOKENE '>'
|
||||
|
||||
#define ARGSTART '('
|
||||
#define ARGEND ')'
|
||||
#define AMPERSAND '&'
|
||||
156
src/cmd/levee/insert.c
Normal file
156
src/cmd/levee/insert.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#include "levee.h"
|
||||
#include "extern.h"
|
||||
|
||||
int PROC
|
||||
insertion(count, openflag, dp, yp, visual)
|
||||
int count, openflag, *dp, *yp;
|
||||
bool visual;
|
||||
{
|
||||
char cmd, c;
|
||||
int rp; /* number of spaces to diddle */
|
||||
int ts, ss; /* tabs && spaces to insert */
|
||||
register int cp; /* current position */
|
||||
int i; /* random index */
|
||||
int endd; /* last open place */
|
||||
register int rsize; /* size of upper buffer */
|
||||
int currDLE = 0; /* what DLE is now */
|
||||
int len; /* full insert size */
|
||||
bool Dflag;
|
||||
|
||||
if (openflag != 0) { /* opening a line above || below */
|
||||
if (openflag<0 && bufmax>0 && curr<bufmax) {
|
||||
curr = 1+lend;
|
||||
if (visual)
|
||||
zwrite("\n", 1);
|
||||
}
|
||||
else { /* open above current line */
|
||||
(*yp)--;
|
||||
curr = lstart;
|
||||
}
|
||||
if (autoindent)
|
||||
currDLE = findDLE(lstart, &i, skipws(lstart),0);
|
||||
if (visual) {
|
||||
#if TTY_VT52
|
||||
if (OL) {
|
||||
#else
|
||||
if (OL && (*yp) < LINES-2) {
|
||||
#endif
|
||||
strput(OL);
|
||||
(*yp)++;
|
||||
curpos.y = *yp;
|
||||
}
|
||||
else {
|
||||
mvcur(1+(*yp), 0);
|
||||
strput(CE);
|
||||
}
|
||||
}
|
||||
mvcur(-1, currDLE);
|
||||
}
|
||||
else {
|
||||
if (autoindent)
|
||||
currDLE = findDLE(lstart, &i, curr, 0);
|
||||
if (curr == i) {
|
||||
if (!delete_to_undo(&undo, lstart, i-lstart))
|
||||
return(-1);
|
||||
curr = lstart;
|
||||
}
|
||||
}
|
||||
|
||||
rsize = (bufmax-curr); /* amount of stuff above curr */
|
||||
endd = SIZE - rsize; /* split the buffer */
|
||||
if (rsize > 0)
|
||||
moveright(&core[curr], &core[endd], rsize);
|
||||
|
||||
cp = curr;
|
||||
do { /* Insert loop */
|
||||
Dflag = (cp==0 || core[cp-1]==EOL);
|
||||
do {
|
||||
if (Dflag)
|
||||
while ((cmd=peekc()) == '' || cmd == '') {
|
||||
if (readchar() == '')
|
||||
currDLE = min(COLS,currDLE+shiftwidth);
|
||||
else
|
||||
currDLE = max(0,currDLE-shiftwidth);
|
||||
mvcur(-1, currDLE);
|
||||
}
|
||||
} while (!(c = line(core, cp, endd-1, &len)));
|
||||
if (Dflag && (len > 0 || c == ESC)) {
|
||||
/* makeDLE : optimize leading whitespace for insert */
|
||||
currDLE = findDLE(cp, &rp, cp+len, currDLE);
|
||||
if (rp > cp) {
|
||||
len -= (rp-cp);
|
||||
moveleft(&core[rp], &core[cp], len); /* squash whitespace */
|
||||
}
|
||||
if (currDLE > 0) { /* create DLE indent */
|
||||
ts = currDLE / tabsize;
|
||||
ss = currDLE % tabsize;
|
||||
moveright(&core[cp], &core[cp+ts+ss], len);
|
||||
len += (ts+ss);
|
||||
fillchar(&core[cp ], ts, TAB);
|
||||
fillchar(&core[cp+ts], ss, 32);
|
||||
}
|
||||
}
|
||||
cp += len;
|
||||
if (c == EOL) { /* Diddle-Diddle */
|
||||
core[cp++] = EOL; /* add in a \n */
|
||||
strput(CE); /* clear this line */
|
||||
println();
|
||||
if (visual) {
|
||||
#if OS_RMX
|
||||
/* at OL at bottom kludge... */
|
||||
if (OL && (*yp) < LINES-2) {
|
||||
#else
|
||||
if (OL) {
|
||||
#endif
|
||||
strput(OL);
|
||||
(*yp)++;
|
||||
}
|
||||
else
|
||||
strput(CE);
|
||||
}
|
||||
if (!autoindent) /* reset currDLE? */
|
||||
currDLE = 0;
|
||||
mvcur(-1, currDLE);
|
||||
}
|
||||
} while (c != ESC && cp <= endd-INSSIZE);
|
||||
*dp = cp; /* start display here */
|
||||
|
||||
if (count > 1) { /* repeated insertion */
|
||||
len = cp-curr;
|
||||
if ((count-1)*len < endd-cp)
|
||||
for (i = 1;i <count;i++) {
|
||||
moveright(&core[cp-len], &core[cp], len);
|
||||
cp += len;
|
||||
}
|
||||
}
|
||||
|
||||
if (openflag != 0 /* open or insert at end of buffer */
|
||||
|| (rsize < 1 && cp > curr && core[cp-1] != EOL))
|
||||
core[cp++] = EOL;
|
||||
len = cp-curr;
|
||||
|
||||
if (rsize > 0) /* if not at end of buffer, stitch things together */
|
||||
moveleft(&core[endd], &core[cp], rsize);
|
||||
insert_to_undo(&undo, curr, len);
|
||||
core[bufmax] = EOL;
|
||||
return(cp);
|
||||
}
|
||||
386
src/cmd/levee/levee.h
Normal file
386
src/cmd/levee/levee.h
Normal file
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1980-2008 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*
|
||||
* Levee v3.C
|
||||
* C version for Unix/Atari ST/MS-DOS/OS-2/FlexOs/iRMX/etc
|
||||
* Pascal version for UCSD Pascal 4.X
|
||||
*
|
||||
* written fall 82' - now (approx) by David L. Parsons.
|
||||
*
|
||||
* many patches, suggestions,
|
||||
* and impractical design goals by:
|
||||
* Jim Bolland,
|
||||
* John Plocher,
|
||||
* John Tainter
|
||||
*/
|
||||
#ifndef LEVEE_D
|
||||
|
||||
#define LEVEE_D
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1) /* Nobody defines TRUE & FALSE, so I will do */
|
||||
#define FALSE (0) /* it myself */
|
||||
#endif
|
||||
|
||||
#define HANDLE int /* default file handle type */
|
||||
|
||||
#define PROC /* for magic function types (MSDOS) */
|
||||
#define VOID void /* ancient creaking C compilers won't understand void */
|
||||
|
||||
/*
|
||||
* Compilation defines for different systems.
|
||||
*/
|
||||
|
||||
#if OS_ATARI
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define void int /* Alcyon C don't know void */
|
||||
|
||||
/* extractions from osbind.h */
|
||||
#define OPEN_OLD(n) gemdos(0x3d,n,/*open mode*/0)
|
||||
#define OPEN_NEW(n) gemdos(0x3c,n,/*permissions*/0)
|
||||
#define CLOSE_FILE(f) gemdos(0x3e,f)
|
||||
#define SEEK_POSITION(f,o,m) gemdos(0x42,(long)(o),f,m)
|
||||
#define READ_TEXT(f,b,c) gemdos(0x3f,f,(long)(c),b)
|
||||
#define WRITE_TEXT(f,b,c) gemdos(0x40,f,(long)(c),b)
|
||||
|
||||
extern char *malloc();
|
||||
extern long gemdos();
|
||||
|
||||
#endif /*OS_ATARI*/
|
||||
|
||||
#if OS_RMX
|
||||
#include <:inc:stdio.h>
|
||||
#include <:inc:udi.h>
|
||||
|
||||
#define OPEN_OLD(n) open(n, /*open mode*/0)
|
||||
#define OPEN_NEW(n) creat(n,/*permissions*/0)
|
||||
#define CLOSE_FILE(f) close(f)
|
||||
#define SEEK_POSITION(f,o,m) lseek((f),(long)(o),(m))
|
||||
#define READ_TEXT(f,p,c) read((f),(p),(unsigned)(c))
|
||||
#define WRITE_TEXT(f,p,c) write((f),(p),(unsigned)(c))
|
||||
|
||||
#define zwrite(p,s) write(1,(p), (unsigned)(s))
|
||||
|
||||
#endif /*OS_RMX*/
|
||||
|
||||
#if OS_DOS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define OPEN_OLD(n) open(n, O_RDONLY|O_BINARY)
|
||||
#define OPEN_NEW(n) open(n, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666)
|
||||
#define CLOSE_FILE(f) close(f)
|
||||
#define SEEK_POSITION(f,o,m) lseek(f, (long)(o), (m))
|
||||
#define READ_TEXT(f,p,c) read(f, p, (int)(c))
|
||||
#define WRITE_TEXT(f,p,c) write(f, p, (int)(c))
|
||||
|
||||
#define zwrite(p,s) WRITE_TEXT(fileno(stdout), p, s)
|
||||
|
||||
#undef PROC
|
||||
#define PROC _fastcall
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#endif /*OS_DOS*/
|
||||
|
||||
#if OS_UNIX
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define OPEN_OLD(n) open(n, O_RDONLY)
|
||||
#define OPEN_NEW(n) open(n, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
#define CLOSE_FILE(f) close(f)
|
||||
#define SEEK_POSITION(f,o,m) lseek(f, (long)(o), (m))
|
||||
#define READ_TEXT(f,p,c) read(f, p, (int)(c))
|
||||
#define WRITE_TEXT(f,p,c) write(f, p, (int)(c))
|
||||
|
||||
#define zwrite(p,s) fwrite(p, 1, s, stdout)
|
||||
|
||||
#endif /*OS_UNIX*/
|
||||
|
||||
#if OS_FLEXOS
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define OPEN_OLD(n) s_open(m,0x08) /* note reversed parameters! */
|
||||
#define OPEN_NEW(n) s_create(0,0,n,0,0/*mode*/,0)
|
||||
#define CLOSE_FILE(f) s_close(0,f) /* Full close on handle */
|
||||
#define SEEK_POSITION(f,o,m) s_seek((m&03)<<9, f, o)
|
||||
#define READ_TEXT(f,p,c) s_read(0x0100,(long)(f),p,(long)(c),0L)
|
||||
#define WRITE_TEXT(f,p,c) s_write(0x0101,(long)(f),p,(long)(c),0L)
|
||||
|
||||
#define zwrite(p,s) s_write(0x0101, 1L, p, (long)(s),0L)
|
||||
|
||||
#define unlink(n) s_delete(0, n)
|
||||
#define rename(a,b) s_rename(0, a, b)
|
||||
|
||||
/* OPEN_OLD mode flags */
|
||||
|
||||
#undef HANDLE
|
||||
#define HANDLE long
|
||||
|
||||
#endif /*OS_FLEXOS*/
|
||||
|
||||
#define bool int
|
||||
|
||||
/* ttydef stuff */
|
||||
#if !(OS_ATARI | USE_TERMCAP)
|
||||
|
||||
#ifndef LINES
|
||||
#define LINES 25
|
||||
#endif /*LINES*/
|
||||
#define COLS 79
|
||||
|
||||
#endif
|
||||
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
#define UPARROW 11
|
||||
#define DNARROW 10
|
||||
#define LTARROW erase
|
||||
#define RTARROW 12
|
||||
|
||||
#if !USE_TERMCAP
|
||||
#define CA TRUE
|
||||
#if !(OS_DOS||OS_FLEXOS)
|
||||
#define canUPSCROLL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* nospecific stuff */
|
||||
#define MAGICNUMBER 42
|
||||
#define hell_freezes_over FALSE
|
||||
#define BUGS 7 /* sometime when you least expect it.. */
|
||||
|
||||
#define DW 23 /* Delete Word */
|
||||
#define EOL 10 /* End Of Line */
|
||||
#define DLE 16 /* Space compression lead-in */
|
||||
#define ESC 27 /* Escape */
|
||||
|
||||
/* hardwired line kill and erase character for non-unix machines */
|
||||
#define DEL 21 /* ^U */
|
||||
#if RMX
|
||||
#define ERASE 127
|
||||
#else
|
||||
#define ERASE 8 /* ^H */
|
||||
#endif
|
||||
|
||||
#define TAB 9
|
||||
|
||||
/* variable types */
|
||||
#define VBOOL 0
|
||||
#define VINT 1
|
||||
#define VSTR 2
|
||||
|
||||
#define ERR (-1)
|
||||
|
||||
/* Undostack commands */
|
||||
#define U_ADDC 'A'
|
||||
#define U_MOVEC 'M'
|
||||
#define U_DELC 'D'
|
||||
|
||||
/* magic things for find */
|
||||
#define MAXPAT ((int)300)
|
||||
|
||||
/* exec mode commands */
|
||||
#define EX_CR (ERR-1)
|
||||
#define EX_PR 0
|
||||
#define EX_QUIT 1
|
||||
#define EX_READ 2
|
||||
#define EX_EDIT 3
|
||||
#define EX_WRITE 4
|
||||
#define EX_WQ 5
|
||||
#define EX_NEXT 6
|
||||
#define EX_SUBS 7
|
||||
#define EX_XIT 8
|
||||
#define EX_FILE 9
|
||||
#define EX_SET 10
|
||||
#define EX_RM 11
|
||||
#define EX_PREV 12
|
||||
#define EX_DELETE 13
|
||||
#define EX_LINE 14
|
||||
#define EX_YANK 15
|
||||
#define EX_PUT 16
|
||||
#define EX_VI 17
|
||||
#define EX_EX 18
|
||||
#define EX_INSERT 19
|
||||
#define EX_OPEN 20
|
||||
#define EX_CHANGE 21
|
||||
#define EX_UNDO 22
|
||||
#define EX_ESCAPE 23
|
||||
#define EX_MAP 24
|
||||
#define EX_UNMAP 25
|
||||
#define EX_SOURCE 26
|
||||
#define EX_VERSION 27
|
||||
#define EX_ARGS 28
|
||||
#define EX_REWIND 29
|
||||
|
||||
/* movement return states */
|
||||
#define LEGALMOVE 0
|
||||
#define BADMOVE 1
|
||||
#define ESCAPED 2
|
||||
#define findstates char
|
||||
|
||||
/* command codes */
|
||||
#define BAD_COMMAND 0
|
||||
/*visual movement*/
|
||||
#define GO_RIGHT 1
|
||||
#define GO_LEFT 2
|
||||
#define GO_UP 3
|
||||
#define GO_DOWN 4
|
||||
#define FORWD 5
|
||||
#define TO_WD 6
|
||||
#define BACK_WD 7
|
||||
#define BTO_WD 8
|
||||
#define NOTWHITE 9
|
||||
#define TO_COL 10
|
||||
#define TO_EOL 11
|
||||
#define MATCHEXPR 12
|
||||
#define TO_CHAR 13
|
||||
#define UPTO_CHAR 14
|
||||
#define BACK_CHAR 15
|
||||
#define BACKTO_CHAR 16
|
||||
#define SENT_FWD 17
|
||||
#define SENT_BACK 18
|
||||
#define PAGE_BEGIN 19
|
||||
#define PAGE_END 20
|
||||
#define PAGE_MIDDLE 21
|
||||
#define CR_FWD 22
|
||||
#define CR_BACK 23
|
||||
#define PATT_FWD 24
|
||||
#define PATT_BACK 25
|
||||
#define FSEARCH 26
|
||||
#define BSEARCH 27
|
||||
#define GLOBAL_LINE 28
|
||||
#define TO_MARK 29
|
||||
#define TO_MARK_LINE 30
|
||||
#define PARA_FWD 31
|
||||
#define PARA_BACK 32
|
||||
/*modifications*/
|
||||
#define DELETE_C 39
|
||||
#define EXEC_C 40
|
||||
#define ADJUST_C 41
|
||||
#define CHANGE_C 42
|
||||
#define YANK_C 43
|
||||
#define INSERT_C 44
|
||||
#define APPEND_C 45
|
||||
#define I_AT_NONWHITE 46
|
||||
#define A_AT_END 47
|
||||
#define OPEN_C 48
|
||||
#define OPENUP_C 49
|
||||
#define REPLACE_C 50
|
||||
#define TWIDDLE_C 51
|
||||
#define RESUBST_C 52
|
||||
#define JOIN_C 53
|
||||
#define UNDO_C 54
|
||||
#define BIG_REPL_C 55
|
||||
#define PUT_BEFORE 56
|
||||
#define PUT_AFTER 57
|
||||
/*everything else*/
|
||||
#define HARDMACRO 70
|
||||
#define REWINDOW 71
|
||||
#define ZZ_C 72
|
||||
#define DEBUG_C 73
|
||||
#define FILE_C 74
|
||||
#define WINDOW_UP 75
|
||||
#define WINDOW_DOWN 76
|
||||
#define REDRAW_C 77
|
||||
#define MARKER_C 78
|
||||
#define REDO_C 79
|
||||
#define EDIT_C 80
|
||||
#define COLIN_C 81
|
||||
/*macros*/
|
||||
#define SOFTMACRO 100
|
||||
#define INSMACRO 101
|
||||
#define cmdtype char
|
||||
|
||||
/* exec mode states */
|
||||
#define E_VISUAL 0
|
||||
#define E_INIT 1
|
||||
#define E_EDIT 2
|
||||
#define exec_type char
|
||||
|
||||
/* various sizes */
|
||||
#define INSSIZE ((int)80) /* Insert string size */
|
||||
#define FSIZE ((int)39) /* File string size */
|
||||
#ifndef SIZE
|
||||
# define SIZE ((int)32760) /* Edit buffer size */
|
||||
#endif
|
||||
|
||||
#define SBUFSIZE ((int)4096) /* Incore yank buffer size */
|
||||
#define MAXMACROS 32 /* Maximum # of macros */
|
||||
#define NMACROS 9 /* Nexting level for macros */
|
||||
|
||||
#define PAGESIZE ((int)1024) /* Bytes per block */
|
||||
|
||||
struct coord { /* Screen Coordinate */
|
||||
int x,y;
|
||||
};
|
||||
|
||||
struct ybuf { /* Yank Buffer */
|
||||
int size; /* Bytes yanked */
|
||||
bool lines, /* Yanked whole lines? */
|
||||
has_eol; /* Yanked a EOL? */
|
||||
char stuff[SBUFSIZE]; /* The stuff */
|
||||
};
|
||||
|
||||
struct undostack { /* Undo Stack Descriptor */
|
||||
int blockp, /* block address of core block */
|
||||
ptr; /* offset within coreblock */
|
||||
int coreblock[PAGESIZE]; /* core block */
|
||||
};
|
||||
|
||||
union optionrec { /* Black Magic Option Structure */
|
||||
int valu; /* if integer, the value */
|
||||
char *strp; /* or if string, a pointer to it */
|
||||
};
|
||||
|
||||
struct macrecord { /* Macro Descriptor */
|
||||
char token; /* Character mapped */
|
||||
cmdtype oldmap; /* Old value in movemap */
|
||||
char *m_text; /* Replacement text */
|
||||
};
|
||||
|
||||
struct tmacro { /* For running a macro */
|
||||
char *mtext, /* Pointer to macro text */
|
||||
*ip; /* Pointer into macro text */
|
||||
int m_iter; /* Number of times to execute */
|
||||
};
|
||||
|
||||
#define V_CONST 1 /* this option cannot be modified */
|
||||
#define V_DISPLAY 2 /* this option affects the display */
|
||||
|
||||
struct variable { /* Settable Variable Record */
|
||||
char *v_name; /* full name */
|
||||
char *v_abbr; /* abbreviated name */
|
||||
int v_tipe; /* what kind of variable */
|
||||
int v_flags; /* special attributes... */
|
||||
union optionrec *u; /* pointer to it */
|
||||
};
|
||||
#endif /*LEVEE_D*/
|
||||
955
src/cmd/levee/lv.1
Normal file
955
src/cmd/levee/lv.1
Normal file
@@ -0,0 +1,955 @@
|
||||
.TH LEVEE 1 "29 August 1998" "Mastodon Linux"
|
||||
.SH NAME
|
||||
.B levee
|
||||
\-
|
||||
A Screen Oriented Editor.
|
||||
.SH SYNOPSIS
|
||||
.B levee
|
||||
[\fI+address\fR] [\fIfile \fB...\fR]
|
||||
.SH DESCRIPTION
|
||||
Levee is a screen oriented editor based on the Unix editor
|
||||
"vi". It provides a terse, powerful way to enter and edit text
|
||||
(however, if you want a word-processor, you're better off with
|
||||
WordStar.)
|
||||
|
||||
Levee is a moded editor. It operates in 3 modes -- visual,
|
||||
command, and insert. Most of the editing work is done is visual
|
||||
mode, file reading and writing is done in command mode, and
|
||||
insert mode does what you would expect.
|
||||
.PP
|
||||
When you enter Levee, you may specify an address to start
|
||||
editing at. These addresses are in the same format as command
|
||||
mode addresses, except that a naked + will put you at the very
|
||||
end of the file.
|
||||
.PP
|
||||
Levee is copyright (c) 1982-2008 by David L. Parsons. (see
|
||||
the notice at the end of this document for distribution terms)
|
||||
|
||||
.SH "COMMAND MODE COMMANDS"
|
||||
|
||||
These commands are used for editing new files, writing
|
||||
modified files, changing options, doing substitutions, and
|
||||
a subset of the visual commands. They take as input whole
|
||||
lines, terminated by return (to execute), or escape (to
|
||||
abort.)
|
||||
|
||||
Command mode is reached by typing ":" or "Q" from visual
|
||||
mode. If you enter command mode by typing ":", Levee will
|
||||
execute one command, then return to visual mode after
|
||||
prompting you with "[more]". If you type anything except
|
||||
a space or return, Levee will accept another command, and so
|
||||
forth. If, however, you enter command mode via "Q", Levee
|
||||
will remain in command mode until you enter the "visual"
|
||||
command.
|
||||
|
||||
|
||||
.SS "A NOTE ON COMMAND SYNTAX"
|
||||
.PP
|
||||
A command may be preceded by an optional line-range. If
|
||||
you do not provide a line-range, Levee will use the default
|
||||
line-range shown by the command. A line-range is one or two
|
||||
address specifications in the following format:
|
||||
|
||||
.RS
|
||||
(\fB.\fR|\fB$\fR|\fB'x\fR|\fB#\fR) [ (\fB+\fR|\fB-\fR) (\fB/\fIpatt\fB\fB/\fR|\fB?\fIpatt\fB?\fR|\fB#\fR) ]
|
||||
.TP
|
||||
.B \.
|
||||
current line.
|
||||
.TP
|
||||
.B $
|
||||
last line.
|
||||
.TP
|
||||
.B 'x
|
||||
the line with mark x on it.
|
||||
.TP
|
||||
.B #
|
||||
line #.
|
||||
.RE
|
||||
|
||||
.PP
|
||||
For example, ".-5,.+5p" will print every line within ten
|
||||
lines of the current line. "$-5" is the fifth line from the
|
||||
end of the file, and "/end/+2" is the second line past the
|
||||
next occurrence of the pattern "end". Patterns may be
|
||||
regular expressions (see below.)
|
||||
|
||||
Also, a naked line-range will set the current line to
|
||||
the first line in the range and print all the lines in that
|
||||
range. "1,10" sets the current line to 1, then prints lines
|
||||
1 to 10.
|
||||
|
||||
If you specify a non-existent line in a range, the command
|
||||
will abort and Levee will tell you "bad address".
|
||||
|
||||
.SS "Command mode commands"
|
||||
|
||||
.TP
|
||||
.B args
|
||||
show the current argument list, if one exists. The file that you
|
||||
are currently editing will be framed by '[' and ']'.
|
||||
|
||||
.TP
|
||||
.IB (.,.) change
|
||||
delete lines, then enter insert mode.
|
||||
|
||||
.TP
|
||||
.IB (.,.) delete
|
||||
delete lines. Deleted lines are stored in a Yank Buffer for
|
||||
later putback with "put".
|
||||
|
||||
.TP
|
||||
.B "edit[!] [file]"
|
||||
Discard the current file and start editing a new one. If
|
||||
changes were made to the current file, you must enter "edit!"
|
||||
to force Levee to discard the changes. If you do not specify
|
||||
a filename, Levee will try to reedit the current filename.
|
||||
|
||||
When Levee reads in a new file, it will tell you how many
|
||||
bytes it read in, or [overflow] if the file is larger than the
|
||||
internal buffer (256000 bytes on most platforms; 20k on USCD
|
||||
Pascal.)
|
||||
|
||||
.TP
|
||||
.B execmode
|
||||
Remain in command mode until you use the "visual" command.
|
||||
|
||||
.TP
|
||||
.BI file [name]
|
||||
Echo what the current filename is, its status, and the current
|
||||
line. If you provide it with a name, it will change the filename
|
||||
to that.
|
||||
|
||||
.TP
|
||||
.IB (.) insert
|
||||
Insert text above the current line. If you specify a line number,
|
||||
Levee will make that the current line, then insert above it.
|
||||
|
||||
.RS
|
||||
.SS "Insert mode commands"
|
||||
.TP
|
||||
.B ^W
|
||||
back over the last word you entered.
|
||||
.TP
|
||||
.B ^H
|
||||
back over one character.
|
||||
.TP
|
||||
.B ^U
|
||||
back over all input on this line.
|
||||
.TP
|
||||
.B ^V
|
||||
escape the next character typed. (For example,
|
||||
.B ^V^H
|
||||
will put a ^H into the file.)
|
||||
.TP
|
||||
.B ESC
|
||||
exit insert mode.
|
||||
.TP
|
||||
.B ^D
|
||||
If at start of line, reduce indentation 'shiftwidth' columns.
|
||||
.TP
|
||||
.B ^T
|
||||
If at start of line, increase indentation 'shiftwidth' columns.
|
||||
.RE
|
||||
|
||||
.PP
|
||||
|
||||
When in insert mode, Levee will not allow you to enter any control
|
||||
characters except return and tab. Return ends input on this line and
|
||||
opens a new line for input.
|
||||
|
||||
.TP
|
||||
.BI map[!] [key [text]]
|
||||
Define/list macros. There are 3 forms of map:
|
||||
.TP
|
||||
.I map.
|
||||
This lists all the active macros.
|
||||
.TP
|
||||
.IR map (key).
|
||||
This shows the macro associated with (key), if any.
|
||||
.TP
|
||||
.IR map "(key) (text)"
|
||||
This maps (key) to (text). You may map any
|
||||
key except ":" and escape. In the normal
|
||||
form (map), the macro will be effective
|
||||
in visual mode, but in the alternate form,
|
||||
(map!), the macro will be effective in
|
||||
insert and command modes.
|
||||
|
||||
.PP
|
||||
For example, if you map!ped return to "hello world", every time
|
||||
you entered a return in command or visual mode, the string "hello
|
||||
world" would pop up.
|
||||
|
||||
.TP
|
||||
.BI next [file ...]
|
||||
Edit the next file in the arglist, or edit a new arglist. Levee
|
||||
takes its initial arglist off the command line when you execute it.
|
||||
If "autowrite" is set, Levee will write out the changes to the
|
||||
current file before editing the next one.
|
||||
|
||||
.TP
|
||||
.IB (.) open
|
||||
Insert below the current line. Otherwise just like insert.
|
||||
|
||||
.TP
|
||||
.B previous
|
||||
Edit the previous file in the arglist. Otherwise, like next.
|
||||
|
||||
.TP
|
||||
.IB (.,.) print
|
||||
Display lines without changing the current line.
|
||||
|
||||
.TP
|
||||
.IB (.) put
|
||||
Put the contents of the yank buffer back on the line below
|
||||
the current line. If you specify a line, it resets the current
|
||||
line, then puts the yank buffer back. The yank buffer is filled
|
||||
by the delete, change, or yank commands. Put does not destroy
|
||||
the yank buffer, so you may put back text multiple times.
|
||||
|
||||
.TP
|
||||
.B quit[!]
|
||||
Exit Levee. If you want to discard changes, use "quit!"
|
||||
|
||||
.TP
|
||||
.IB (.) read [file]
|
||||
put the contents of 'file' after the current line.
|
||||
|
||||
.TP
|
||||
.BI rm file
|
||||
Delete 'file' from disk.
|
||||
|
||||
.TP
|
||||
.BI set [option=value]
|
||||
Set a tunable variable. Levee has a dozen or so user-definable
|
||||
variables which you can twiddle via this command. There are boolean,
|
||||
integer, and string variables that you can set. A string or integer
|
||||
variable is set by 'set xxx=yyy', a boolean variable is set via
|
||||
'set xxx' or 'set noxxx'.
|
||||
|
||||
Here are the settable variables (and abbreviations):
|
||||
.TP
|
||||
.BI tabsize (ts)
|
||||
tab stop.
|
||||
.TP
|
||||
.BI shiftwidth (sw)
|
||||
columns to shift on ^D, ^T, >>, or <<
|
||||
.TP
|
||||
.B scroll
|
||||
number of lines to scroll on ^D, ^U
|
||||
.TP
|
||||
.BI autoindent (ai)
|
||||
supply indentation during insert mode.
|
||||
.TP
|
||||
.BI autowrite (aw)
|
||||
write out changes before :next, :prev
|
||||
.TP
|
||||
.BI autocopy (ac)
|
||||
make backup copies before writing changes.
|
||||
.TP
|
||||
.B list
|
||||
display tabs as ^I, end of line as $.
|
||||
.TP
|
||||
.B magic
|
||||
use regular expressions in searches.
|
||||
.TP
|
||||
.B suffix
|
||||
if the filename does not have a . in
|
||||
it, supply the suffix. (this is the
|
||||
only string variable.)
|
||||
.TP
|
||||
.BI overwrite (ow)
|
||||
destroy old file first, then write.
|
||||
.TP
|
||||
.BI beautify (be)
|
||||
When set, Levee will not allow insert
|
||||
of any control character except tab
|
||||
and return unless you escape it with
|
||||
ctrl-V.
|
||||
.TP
|
||||
.B wrapscan
|
||||
searches wrap around end of buffer.
|
||||
.TP
|
||||
.BI ignorecase (ic)
|
||||
Ignore the case of alphabetic characters
|
||||
during searches.
|
||||
.TP
|
||||
.B "mapslash"
|
||||
(ST version only) Map '/' in filenames to
|
||||
'\\'. If the environment contains `mapslash'
|
||||
when levee is called, this variable will
|
||||
default to true, otherwise it defaults to
|
||||
false. (See the documentation for the
|
||||
Teeny-shell on how the teeny-shell interprets
|
||||
`mapslash')
|
||||
.TP
|
||||
.BI lines (li)
|
||||
(ST version only) How many lines on the display.
|
||||
This is primarily for running levee through
|
||||
the serial port - put set li=xx into your
|
||||
LVRC for a xx line terminal.
|
||||
.TP
|
||||
.BI cols (co)
|
||||
(ST version only) How many columns on the
|
||||
display. Like the lines variable, it's for
|
||||
running levee through the serial port.
|
||||
|
||||
.PP
|
||||
You may set multiple variables on one line, as in 'set ws noai'.
|
||||
To see the current settings of these variables, :set -- without any
|
||||
arguments -- will show the current settings.
|
||||
|
||||
At startup, Levee looks in the environment variable LVRC for
|
||||
a list of variables to set (GEMDOS/MS-DOS). LVRC is one line
|
||||
of the form 'option=value ...'. If you have a LVRC defined that
|
||||
is 'ts=4 ow nows', Levee will set tabsize to 4, turn on overwrite,
|
||||
and turn off wrapscan.
|
||||
|
||||
If you are using RMX, Levee looks in the file ":home:r?lvrc"
|
||||
for initialization. If you are using Osy/SWOs, Levee looks in the
|
||||
file "*.lvrc". The format of these files are different from the
|
||||
LVRC variable -- see "source" for more information.
|
||||
|
||||
.TP
|
||||
.BI source file
|
||||
Take command mode commands from 'file'. These commands can be
|
||||
any legal command, except "visual". If a error happens during
|
||||
execution of 'file', Levee abandons that level of source'ing.
|
||||
|
||||
In Osy/SWOs, there are a few differences in insert mode from
|
||||
within a sourced file. No character has special meaning except a
|
||||
line containing nothing but a period, which terminates insert mode.
|
||||
For example:
|
||||
|
||||
.RS
|
||||
:commands
|
||||
.br
|
||||
.
|
||||
.br
|
||||
.
|
||||
.br
|
||||
:insert
|
||||
.br
|
||||
blah blah blah blah blah blah
|
||||
.br
|
||||
blah blah blah blah blah blah
|
||||
.br
|
||||
blah blah blah blah blah blah
|
||||
.br
|
||||
.
|
||||
.br
|
||||
:more commands
|
||||
.RE
|
||||
|
||||
If you are running Levee under any other operating system,
|
||||
you cannot do a insert from a :source file.
|
||||
|
||||
.TP
|
||||
.B (.,.)substitute(delim)patt(delim)repl(delim)[qcpg]
|
||||
.TP
|
||||
.B (.,.)substitute&
|
||||
|
||||
Search for patt and replace it with repl. Levee will look for
|
||||
patt once on each line and replace it with repl. The delimiter
|
||||
may be any ascii character.
|
||||
|
||||
The pattern is a regular expression, just like a search pattern.
|
||||
|
||||
You may include parts of the pattern in the replacement string;
|
||||
A '&' in the replacement pattern copies in the whole source pattern,
|
||||
so if you do a 'sub/this/& and that/g', every instance of 'this'
|
||||
will be replaced with 'this and that'. Also, you may pull parts of
|
||||
the pattern out by using the \\( and \\) argument meta-characters.
|
||||
Arguments gotten by \\( & \\) are put into the replacement string
|
||||
everywhere you do a \\1..\\9 [ \\1 is the first argument you set up
|
||||
with \\( & \\) ]. So, if you want to reverse the order of two substrings,
|
||||
you can do 'sub/\\(string1\\)\\(string2\\)/\\2\\1/'.
|
||||
|
||||
substitute& redoes the last substitution.
|
||||
|
||||
Options:
|
||||
.TP
|
||||
.B q,c
|
||||
before doing the substitute, display the affected
|
||||
line and wait for you to type a character. If you
|
||||
type 'y', it will do the substitution. 'q' aborts
|
||||
the substitute, 'a' does the rest of the change
|
||||
without prompting, and 'n' does not do it.
|
||||
.TP
|
||||
.B p
|
||||
print the affected lines after the change.
|
||||
.TP
|
||||
.B g
|
||||
do the change globally. That is, do it for every
|
||||
occurence of patt on a line, rather than just
|
||||
once.
|
||||
.PP
|
||||
|
||||
.TP
|
||||
.B undo
|
||||
Undo the last modification to the file (except :edit, :next, :rm,
|
||||
or :write.) You can only undo the last change to a file -- undo counts
|
||||
as a change. :undo followed by :undo does nothing to the file.
|
||||
|
||||
.TP
|
||||
.BI unmap (key)
|
||||
Undefine a macro (see map).
|
||||
|
||||
.TP
|
||||
.BI visual [list]
|
||||
If you entered command mode by "Q" or "execmode", return to
|
||||
visual mode. If you provide an argument list, it also does a
|
||||
`:next' on that list.
|
||||
|
||||
.TP
|
||||
.B version
|
||||
Show which version of levee this is.
|
||||
|
||||
.TP
|
||||
.IB (.,.) "write \fI[file]"
|
||||
Write lines to a file. If you write the everything to 'file',
|
||||
the filename is set to 'file', and if you do not specify a file,
|
||||
Levee will write to the filename.
|
||||
|
||||
.TP
|
||||
.IB (.,.) "wq \fI[file]"
|
||||
Write to a file, then quit.
|
||||
|
||||
.TP
|
||||
.IB (.,.) yank
|
||||
Yank lines from the file into the yank buffer, for later
|
||||
putback with "put".
|
||||
|
||||
.TP
|
||||
.B xit[!]
|
||||
Write changes to the current file, then exit. If there are
|
||||
more files in the arglist, use "xit!"
|
||||
|
||||
.TP
|
||||
.B ![command]
|
||||
Execute command.
|
||||
|
||||
Example:
|
||||
|
||||
.RS
|
||||
!ls => does a 'ls'.
|
||||
.RE
|
||||
|
||||
This command is available only under GEMDOS, MSDOS, RMX, and
|
||||
Unix.
|
||||
|
||||
.TP
|
||||
.B ($)=
|
||||
Give the line number of the addressed line. /end/= gives you
|
||||
the line number of the next line with a 'end' on it.
|
||||
|
||||
|
||||
.SH "VISUAL MODE COMMANDS"
|
||||
Visual mode commands move you around and modify the file.
|
||||
There are movement commands to move the cursor by a variety of
|
||||
objects.
|
||||
|
||||
In the description, a (#) means a optional count. If a
|
||||
command has a optional count, it will tell you what the count
|
||||
does in parenthesis. A (*) means that the command can be used
|
||||
in the delete, yank, and change commands.
|
||||
|
||||
Counts are made up by entering digits. If you type '45',
|
||||
the count will be set to 45. To cancel a count, type ESC.
|
||||
|
||||
This section discusses 'whitespace' occasionally.
|
||||
Whitespace is tabs, spaces, and end of line.
|
||||
|
||||
.SS "How the display works"
|
||||
|
||||
Characters are displayed on the screen as you would
|
||||
expect, except that nonprinting characters are shown as ^x,
|
||||
and tabs expand to spaces ( unless you set the option list,
|
||||
then they show as ^I.) When sitting on a control character or
|
||||
tab, the cursor is placed on the FIRST character displayed. If
|
||||
you move the cursor to any other part of them ( via j or k --
|
||||
see below), any changes will start at the next character.
|
||||
|
||||
Levee does not display a end of file marker, but lines
|
||||
past the end of the file are denoted by ~ lines.
|
||||
|
||||
If list is set, tabs display as ^I, and the end of line
|
||||
displays as $.
|
||||
|
||||
If a line is too long for the screen, it will just disappear off the end of the screen.
|
||||
|
||||
Levee will handle any screen resolution and any monospaced
|
||||
font you hand it ( if you are running in low resolution, Levee
|
||||
will give you a 25x40 window, for example.)
|
||||
|
||||
.SS "Visual mode commands"
|
||||
.TP
|
||||
.B ^A
|
||||
Show a debugging message at the bottom of the screen. This is not at
|
||||
all useful unless you are debugging the editor. Ignore it.
|
||||
|
||||
.TP
|
||||
.B (#)^D
|
||||
Scroll the screen down a half screen. If a count is specified, scroll
|
||||
down the specified number of lines.
|
||||
|
||||
.TP
|
||||
.B ^E
|
||||
Scroll down 1 line (shorthand for 1^D )
|
||||
|
||||
.TP
|
||||
.B ^G
|
||||
Show file statistics. Exactly like ':file'.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)^H
|
||||
Move the cursor left one (count) chars.
|
||||
|
||||
.TP
|
||||
.B ^I
|
||||
Redraw the screen.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)^J
|
||||
Move down one (count) lines. When you use ^J and ^K (below) to move
|
||||
up or down lines, the cursor will remain in the same column, even if
|
||||
it is in the middle of a tabstop or past the end of a line.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)^K
|
||||
Move up one (count) lines.
|
||||
.TP
|
||||
.IB (*) (#)^L
|
||||
Move right one (count) characters.
|
||||
.TP
|
||||
.IB (*) (#)^M
|
||||
Move to the first nonwhite space on the next line. If a count is specified,
|
||||
move to the first nonwhite count lines down.
|
||||
.TP
|
||||
.B (#)^U
|
||||
Scroll the screen up a half page. If a count is specified, scroll up
|
||||
count lines.
|
||||
|
||||
.TP
|
||||
.B ^Y
|
||||
Scroll the screen up 1 line (shorthand for 1^U.)
|
||||
|
||||
.TP
|
||||
.B (#)a
|
||||
Insert text AFTER the cursor. If you give a count, the insertion will
|
||||
be repeated count times ( 40i-ESC will give you a line of 40 dashes).
|
||||
|
||||
The commands in insert mode are the same for visual and command mode.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)b
|
||||
Move to the beginning of the last word (the count'th word back).
|
||||
A word is a collection of alphanumeric characters (a-z0-9$_#) or
|
||||
any other nonwhite character (i.e. anything but space, tab, eoln).
|
||||
|
||||
.TP
|
||||
.B c
|
||||
Change a object. Change deletes an object, then enters insert mode without
|
||||
redrawing the screen. When you tell it the object to be changed, Levee
|
||||
puts a '$' on the last character of the object. You cannot change
|
||||
backwards.
|
||||
|
||||
The object may be any visual mode command marked with a '(*) '. For
|
||||
example, 'c4l' will change the next 4 characters on the line to something
|
||||
else. (4cl does the same thing -- 4c4l changes the next 16 characters on
|
||||
this line.)
|
||||
|
||||
'cc' will change whole lines.
|
||||
|
||||
When changing, deleting, or yanking a object, it will be placed into
|
||||
a yank buffer, where it can be retrieved by the 'p' or 'P' commands.
|
||||
|
||||
.TP
|
||||
.B (#)d
|
||||
Delete an object. Like 'cc', 'dd' affects whole lines.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)e
|
||||
Move to the end of the current word.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)f(x)
|
||||
Find the next (count'th) occurance of a character on the current line.
|
||||
For example, if the cursor is sitting on the first character of the
|
||||
line 'abcdef', typing "ff" will put the cursor on the 'f'.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)h
|
||||
Move left one (count) characters. Exactly like ^H.
|
||||
|
||||
.TP
|
||||
.B (#)i
|
||||
Start inserting characters at the cursor. If you specify a count,
|
||||
the insertion will be duplicated count times.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)j
|
||||
Move down one (count) lines. Exactly like ^J.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)k
|
||||
Move up one (count) lines. Exactly like ^K.
|
||||
|
||||
.TP
|
||||
,B (*) (#)l
|
||||
Move right one (count) character. Exactly like ^L.
|
||||
|
||||
.TP
|
||||
.B m(x)
|
||||
Set the marker (x). There are 26 markers available (a-z). You may
|
||||
move to a marker by use of the ' or ` commands.
|
||||
|
||||
.TP
|
||||
.IB (*) n
|
||||
Find the next occurance of a search pattern. When you do a search with
|
||||
a / or ? command, Levee will remember the pattern and the direction you
|
||||
searched in. 'n' will search in the same direction for the pattern, 'N'
|
||||
searches in the opposite direction.
|
||||
|
||||
.TP
|
||||
.B o
|
||||
Open a line below the current line for insertion.
|
||||
|
||||
.TP
|
||||
.B p
|
||||
Put yanked/deleted text back after the cursor. Text is yanked
|
||||
by the delete (d,x,X,D), change (c,C,s,S), and yank (y,Y) commands.
|
||||
|
||||
.TP
|
||||
.B (#)r(x)
|
||||
Replace characters (up to end of line) with (x). '4ra' will change the
|
||||
next 4 characters after the cursor into 'aaaa'.
|
||||
|
||||
.TP
|
||||
.B (#)s
|
||||
change one (count) characters. Shorthand for (#)cl.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)t(x)
|
||||
Move up to a character on the current line. If you are on the first
|
||||
character of the line 'abcdef' and you type 'tf', you will end up sitting
|
||||
on the 'e'.
|
||||
|
||||
.TP
|
||||
.B u
|
||||
Undo last modification. You can undo ANY modification command except
|
||||
:edit, :next, :rm, or :write. (Just like :undo).
|
||||
|
||||
.TP
|
||||
.IB (*) (#)v
|
||||
Move back to the very end of the previous (count'th) word.
|
||||
See 'b' for the definition of a word.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)w
|
||||
Move up to the very beginning of the next (count'th) word.
|
||||
|
||||
.TP
|
||||
.B (#)x
|
||||
Delete one (count) characters forward. Shorthand for (#)dl.
|
||||
|
||||
.TP
|
||||
.B y
|
||||
Yank an object for later use by put. 'yy' yanks whole lines.
|
||||
|
||||
.TP
|
||||
.B A
|
||||
Append text at the end of the line. Shorthand for $a.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)B
|
||||
Move to the beginning of the current word. Exactly like 'b'.
|
||||
|
||||
.B NOTE:
|
||||
this is incorrect. the capitalized word movement commands should,
|
||||
and will in the future, be used for movement by space-delimited words.
|
||||
|
||||
.TP
|
||||
.B C
|
||||
Change to the end of the line. Shorthand for c$.
|
||||
|
||||
.TP
|
||||
.B D
|
||||
Delete to the end of the line. Shorthand for d$.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)F(x)
|
||||
Move to the first (count'th) previous occurance of a character on the
|
||||
current line. If you are sitting at the end of the line 'abcdef', typing
|
||||
"Fa" will move you back to the 'a' at the start of the line.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)G
|
||||
Goto line. If you specify a count, Levee will move to that line, and if
|
||||
there is no count, Levee moves to the absolute end of the file.
|
||||
|
||||
To get to the start of the file, type "1G". To the end, just "G".
|
||||
|
||||
.TP
|
||||
.IB (*) H
|
||||
Move to the first nonwhite character at the top of the screen.
|
||||
|
||||
.TP
|
||||
.B I
|
||||
Insert at the end of the current line. Shorthand for $i.
|
||||
|
||||
.TP
|
||||
.B (#)J
|
||||
Join two (count+1) lines together. Joining appends the second line at
|
||||
the end of the first, putting a space between them. If the first line
|
||||
ends in whitespace, Levee will not put in a space.
|
||||
|
||||
.TP
|
||||
.IB (*) L
|
||||
Move to the last nonwhite character on the last line of the screen.
|
||||
|
||||
.TP
|
||||
.IB (*) M
|
||||
Move to the first nonwhite character in the middle of the screen.
|
||||
|
||||
.TP
|
||||
.B O
|
||||
Open a line above the current line. Otherwise works just like 'o'.
|
||||
|
||||
.TP
|
||||
.B P
|
||||
Put back the yank buffer at the cursor. Otherwise works just like 'p'.
|
||||
|
||||
.TP
|
||||
.B Q
|
||||
Enter and remain in command mode. Just like the command :exec. To get
|
||||
back to visual mode, you must enter the command ':visual'.
|
||||
|
||||
.TP
|
||||
.B R
|
||||
Replace mode. A limited subset of insert mode that overwrites characters
|
||||
up to end of line. All of the normal insert mode commands apply.
|
||||
If you overwrite a character, then back over it with ^H,^U, or ^W, it
|
||||
will reappear after you exit Replace mode.
|
||||
|
||||
Escape exits replace mode.
|
||||
|
||||
.B NOTE:
|
||||
due to a bug, entering a <return> in Replace mode will drop you
|
||||
back into visual mode with an error. The replacements you have made
|
||||
will remain.
|
||||
|
||||
.TP
|
||||
.B S
|
||||
Change characters backwards. Shorthand for (#)ch.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)T(x)
|
||||
Move back to character on current line. If you are on the last character
|
||||
of the line 'abcdef', typing "Ta" will move you back to the 'b'.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)W
|
||||
Move to end of word. Exactly like 'e'.
|
||||
|
||||
.TP
|
||||
.B (#)X
|
||||
Delete characters backwards. Shorthand for (#)dh.
|
||||
|
||||
.TP
|
||||
.B Y
|
||||
Yank to end of line. Shorthand for y$.
|
||||
|
||||
.TP
|
||||
.B ZZ
|
||||
Write changes to current file and exit if last file in arglist.
|
||||
Exactly like :xit.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)$
|
||||
Move to end of line. If you give a count, move to the end of the (count-1)
|
||||
line down (so 2$ moves you to the end of the next line.).
|
||||
|
||||
.TP
|
||||
.B 0
|
||||
Move to the beginning of the current line. Shorthand for 0|.
|
||||
|
||||
.TP
|
||||
.B (#)!
|
||||
Pipe an object through an external program. Like 'cc', '!!' affects whole lines.
|
||||
|
||||
.TP
|
||||
.IB (*) %
|
||||
Find matching bracket, parenthesis, or squiggly bracket. If you are not
|
||||
sitting on a '[]{}()', Levee will search forward for one of them on the
|
||||
current line, then match whatever it finds.
|
||||
|
||||
.TP
|
||||
.B [space]
|
||||
Move to the first nonwhite character on the current line.
|
||||
|
||||
.TP
|
||||
.B &
|
||||
Redo last substitution command.
|
||||
|
||||
.TP
|
||||
.IB (*) (#){
|
||||
Move to the beginning of the count'th paragraph back. A paragraph is
|
||||
delimited by a blank line.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)}
|
||||
Move to the end of the count'th paragraph forward.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)(
|
||||
Move to the beginning of the count'th sentence back. A sentence is
|
||||
delimited by a ., a !, or a ? followed by a space, a tab, or end of line.
|
||||
|
||||
.TP
|
||||
.IB (*) (#))
|
||||
Move to the end of the count'th sentence forward.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)-
|
||||
Move to the (count'th) previous line, first nonwhite.
|
||||
|
||||
.TP
|
||||
.IB (*) (#)+
|
||||
Move to the (count'th) next line, first nonwhite.
|
||||
|
||||
.TP
|
||||
.B (#)~
|
||||
Change the case of the next count characters. Upper case becomes lowercase,
|
||||
lowercase becomes uppercase.
|
||||
|
||||
.TP
|
||||
.IB (*) `(x)
|
||||
Move to the exact position of mark (x). There is a special mark for some
|
||||
of the visual mode move ment commands -- '' will move you to where you
|
||||
were before the last (,),',`,G,/,?,n,N command.
|
||||
|
||||
.TP
|
||||
.B :
|
||||
Execute one command mode command. When the command is done, it will return
|
||||
to visual mode if it produces one line of output, but if it scrolls the
|
||||
screen, Levee will prompt [more] before returning to visual mode. If you
|
||||
type a : in response to the [more] prompt, Levee will remain in command
|
||||
mode for one more command.
|
||||
|
||||
.TP
|
||||
.B (#)<(#)
|
||||
Shift one (count) objects left. If you specify a second count, Levee will
|
||||
shift the object left that many columns -- if you do not, they will be sh
|
||||
shifted shiftwidth columns.
|
||||
|
||||
This is a nondestructive shift. If the shift would carry past the left
|
||||
margin, the objects will be moved up to the left margin but no farther.
|
||||
|
||||
Like the other object movement commands, '<<' will affect whole lines.
|
||||
|
||||
.TP
|
||||
.B (#)>(#)
|
||||
Shift one (count) objects right. Just like <, except it will not shift
|
||||
objects past the right margin of the screen. If you do shift an object
|
||||
past the right margin of the screen, all of its indent will be removed
|
||||
and it will end up by the left margin.
|
||||
|
||||
.TP
|
||||
.B \.
|
||||
Repeat last modification command. (except undo)
|
||||
|
||||
.TP
|
||||
.IB (*) ?
|
||||
Search for pattern backwards. Escape aborts the search pattern, and a
|
||||
empty pattern means search for the last pattern again.
|
||||
|
||||
.TP
|
||||
.IB (*) /
|
||||
Search for pattern forwards. Otherwise like ?.
|
||||
|
||||
.TP
|
||||
.B (#)|
|
||||
Move to specified column. If you don't have a count, move to column 0.
|
||||
|
||||
.SH "REGULAR EXPRESSIONS"
|
||||
|
||||
Levee gives special meanings to some characters during
|
||||
a pattern match. The character "." will match any one char,
|
||||
the character "*" will match zero or more occurances of the
|
||||
previous char ( so, a* will match 'a','aa','aaa', etc, or it
|
||||
will match nothing at all). If a pattern begins with "^", it
|
||||
will only match at the beginning of a line, and patterns
|
||||
ending with a "$" will only match at the end of a line.
|
||||
|
||||
Brackets ('[]') have special meaning as well. They mean
|
||||
match any one of the characters inside the brackets. '[abc]'
|
||||
will match 'a', 'b', or 'c'. You may specify a range of
|
||||
characters inside brackets by using a dash (-). '[a-z]' will
|
||||
match any lowercase alphabetic character. If ^ is the first
|
||||
character in the bracket, it means match any character
|
||||
except those in the brackets. '[^abc]' will match anything
|
||||
except 'a','b', or 'c'.
|
||||
|
||||
Backslash takes away special meaning for these chars,
|
||||
but '\\t' specifies a tab, and \\( & \\) delimit arguments
|
||||
inside a pattern (used only by :substitute.) The patterns
|
||||
\\< and \\> have special meaning, too; they match the start
|
||||
and end of alpha-numeric tokens.
|
||||
|
||||
If you turn off the editor variable 'magic', none of
|
||||
the above characters will have special meaning inside of
|
||||
a pattern (see 'set').
|
||||
|
||||
Some example patterns:
|
||||
|
||||
.TP
|
||||
.B ^end$
|
||||
Find a line that is just 'end'.
|
||||
.TP
|
||||
.B [Ee][Nn][Dd]
|
||||
Find a 'end', ignoring case.
|
||||
.TP
|
||||
.B [A-Za-z][A-Za-z0-9]*
|
||||
Find the next identifier.
|
||||
.TP
|
||||
.B (\\*.*\\*)
|
||||
Find the next one-line pascal comment.
|
||||
.TP
|
||||
.B \<the\>
|
||||
Find the next occurance of `the'.
|
||||
|
||||
|
||||
.SH LIMITATIONS
|
||||
Levee can only edit files up to 256000 characters long. ^M is used
|
||||
as its internal line separator, so inserting ^M will have interesting
|
||||
consequences.
|
||||
|
||||
.SH BUGS
|
||||
Probably infinite.
|
||||
|
||||
.SH AUTHOR
|
||||
.B "David L. Parsons"
|
||||
.I (orc@pell.chi.il.us)
|
||||
.br
|
||||
Testing, suggestions, and impractical design goals by:
|
||||
Jim Bolland. John Tainter. John Plocher.
|
||||
|
||||
.SH COPYRIGHT
|
||||
Copyright (c) 1982-2007 David L Parsons
|
||||
.br
|
||||
All rights reserved.
|
||||
.br
|
||||
|
||||
Redistribution and use in source and binary forms, without or
|
||||
without modification, are permitted provided that the above
|
||||
copyright notice and this paragraph are duplicated in all such
|
||||
forms and that any documentation, advertising materials, and
|
||||
other materials related to such distribution and use acknowledge
|
||||
that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
My name may not be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user