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
|
DUINOMITEUART = sys/pic32/duinomite-uart/DUINOMITE-UART
|
||||||
DUINOMITEE = sys/pic32/duinomite-e/DUINOMITE-E
|
DUINOMITEE = sys/pic32/duinomite-e/DUINOMITE-E
|
||||||
DUINOMITEEUART = sys/pic32/duinomite-e-uart/DUINOMITE-E-UART
|
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
|
BAREMETAL = sys/pic32/baremetal/BAREMETAL
|
||||||
RETROONE = sys/pic32/retroone/RETROONE
|
RETROONE = sys/pic32/retroone/RETROONE
|
||||||
FUBARINO = sys/pic32/fubarino/FUBARINO
|
FUBARINO = sys/pic32/fubarino/FUBARINO
|
||||||
FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC
|
FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC
|
||||||
|
SDXL = sys/pic32/sdxl/SDXL
|
||||||
MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7
|
MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7
|
||||||
|
|
||||||
# Select target board
|
# Select target board
|
||||||
TARGET ?= $(MAX32)
|
TARGET ?= $(MAX32)
|
||||||
|
|
||||||
# Filesystem and swap sizes.
|
# Filesystem and swap sizes.
|
||||||
FS_KBYTES = 102400
|
FS_MBYTES = 100
|
||||||
U_KBYTES = 102400
|
U_MBYTES = 100
|
||||||
SWAP_KBYTES = 2048
|
SWAP_MBYTES = 2
|
||||||
|
|
||||||
# Set this to the device name for your SD card. With this
|
# 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.
|
# to the SD card.
|
||||||
|
|
||||||
#SDCARD = /dev/sdb
|
#SDCARD = /dev/sdb
|
||||||
@@ -60,68 +59,13 @@ TARGETDIR = $(shell dirname $(TARGET))
|
|||||||
TARGETNAME = $(shell basename $(TARGET))
|
TARGETNAME = $(shell basename $(TARGET))
|
||||||
TOPSRC = $(shell pwd)
|
TOPSRC = $(shell pwd)
|
||||||
CONFIG = $(TOPSRC)/tools/configsys/config
|
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
|
all: .profile
|
||||||
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:
|
|
||||||
$(MAKE) -C tools
|
$(MAKE) -C tools
|
||||||
|
$(MAKE) -C lib
|
||||||
|
$(MAKE) -C src install
|
||||||
|
$(MAKE) kernel
|
||||||
|
$(MAKE) fs
|
||||||
|
|
||||||
kernel: $(TARGETDIR)/Makefile
|
kernel: $(TARGETDIR)/Makefile
|
||||||
$(MAKE) -C $(TARGETDIR)
|
$(MAKE) -C $(TARGETDIR)
|
||||||
@@ -129,39 +73,14 @@ kernel: $(TARGETDIR)/Makefile
|
|||||||
$(TARGETDIR)/Makefile: $(CONFIG) $(TARGETDIR)/$(TARGETNAME)
|
$(TARGETDIR)/Makefile: $(CONFIG) $(TARGETDIR)/$(TARGETNAME)
|
||||||
cd $(TARGETDIR) && ../../../tools/configsys/config $(TARGETNAME)
|
cd $(TARGETDIR) && ../../../tools/configsys/config $(TARGETNAME)
|
||||||
|
|
||||||
.PHONY: lib
|
fs: sdcard.img
|
||||||
lib:
|
|
||||||
$(MAKE) -C lib
|
|
||||||
|
|
||||||
build: tools lib
|
.PHONY: sdcard.img
|
||||||
$(MAKE) -C src install
|
sdcard.img: $(FSUTIL) rootfs.manifest userfs.manifest
|
||||||
|
|
||||||
filesys.img: $(FSUTIL) $(ALLFILES)
|
|
||||||
rm -f $@
|
rm -f $@
|
||||||
$(FSUTIL) -n$(FS_KBYTES) $@
|
$(FSUTIL) --repartition=fs=$(FS_MBYTES)M:swap=$(SWAP_MBYTES)M:fs=$(U_MBYTES)M $@
|
||||||
$(FSUTIL) -a $@ $(ALLDIRS)
|
$(FSUTIL) --new --partition=1 --manifest=rootfs.manifest $@ .
|
||||||
$(FSUTIL) -a $@ $(CDEVS)
|
$(FSUTIL) --new --partition=3 --manifest=userfs.manifest $@ u
|
||||||
$(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):
|
$(FSUTIL):
|
||||||
cd tools/fsutil; $(MAKE)
|
cd tools/fsutil; $(MAKE)
|
||||||
@@ -175,32 +94,30 @@ clean:
|
|||||||
|
|
||||||
cleanall: clean
|
cleanall: clean
|
||||||
$(MAKE) -C lib 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 sys/pic32/*/unix.hex bin/* sbin/* libexec/*
|
||||||
rm -f games/lib/adventure.dat
|
rm -f games/[a-k]* games/[m-z]* share/man/cat*/*
|
||||||
rm -f games/lib/cfscores
|
rm -f games/lib/adventure.dat games/lib/cfscores
|
||||||
rm -f share/re.help
|
rm -f share/re.help share/emg.keys share/misc/more.help
|
||||||
rm -f share/misc/more.help
|
|
||||||
rm -f etc/termcap etc/remote etc/phones
|
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 tools/configsys/.depend
|
||||||
rm -f var/log/aculog
|
rm -f var/log/aculog
|
||||||
rm -rf var/lock
|
rm -rf var/lock share/unixbench
|
||||||
|
|
||||||
installfs: filesys.img
|
installfs:
|
||||||
ifdef SDCARD
|
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
|
else
|
||||||
@echo "Error: No SDCARD defined."
|
@echo "Error: No SDCARD defined."
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# TODO: make it relative to Target
|
# TODO: make it relative to Target
|
||||||
installflash:
|
installflash:
|
||||||
sudo pic32prog sys/pic32/fubarino/unix.hex
|
sudo pic32prog sys/pic32/fubarino/unix.hex
|
||||||
|
|
||||||
# TODO: make it relative to Target
|
# TODO: make it relative to Target
|
||||||
installboot:
|
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
|
cp etc/root/dot.profile .profile
|
||||||
|
|||||||
24
README.md
24
README.md
@@ -27,6 +27,14 @@
|
|||||||
|
|
||||||
## Build
|
## 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.
|
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"
|
To select another target board, edit a top-level user-specific Makefile called "Makefile.user"
|
||||||
and set a TARGET value:
|
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 = $(DUINOMITEUART) # for the Duinomite board with UART console
|
||||||
TARGET = $(DUINOMITEE) # for the Duinomite E board with USB console
|
TARGET = $(DUINOMITEE) # for the Duinomite E board with USB console
|
||||||
TARGET = $(DUINOMITEEUART) # for the Duinomite E board with UART 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 = $(BAREMETAL) # Bare PIC32 chip on a breakout board
|
||||||
TARGET = $(FUBARINO) # Fubarino SD board
|
TARGET = $(FUBARINO) # Fubarino SD board
|
||||||
TARGET = $(FUBARINOBIG) # Fubarino SD board with 8MB SRAM RAMDISK
|
TARGET = $(FUBARINOBIG) # Fubarino SD board with 8MB SRAM RAMDISK
|
||||||
@@ -65,7 +71,7 @@ To compile the kernel and build a filesystem image, run:
|
|||||||
$ make
|
$ 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.
|
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:
|
On Linux, run:
|
||||||
|
|
||||||
```shell
|
```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).
|
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`.
|
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
|
DESTDIR = /usr/local/retrobsd
|
||||||
MACHINE = mips
|
MACHINE = mips
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc -m32
|
||||||
|
|
||||||
AS = $(CC) -x assembler-with-cpp
|
AS = $(CC) -x assembler-with-cpp
|
||||||
LD = ld
|
LD = ld
|
||||||
|
|||||||
1
etc/.gitignore
vendored
1
etc/.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
phones
|
phones
|
||||||
remote
|
remote
|
||||||
termcap
|
termcap
|
||||||
|
termcap.full
|
||||||
|
|||||||
16
etc/ttys
16
etc/ttys
@@ -1,16 +1,16 @@
|
|||||||
#
|
#
|
||||||
# name getty type status comments
|
# 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
|
# 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
|
# 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.
|
# if you would rather use the getty on the real tty - it's up to you.
|
||||||
|
|
||||||
tty0 "/libexec/getty std.default" vt100 off secure
|
tty0 "/libexec/getty std.default" xterm off secure
|
||||||
tty1 "/libexec/getty std.default" vt100 off secure
|
tty1 "/libexec/getty std.default" xterm off secure
|
||||||
tty2 "/libexec/getty std.default" vt100 off secure
|
tty2 "/libexec/getty std.default" xterm off secure
|
||||||
tty3 "/libexec/getty std.default" vt100 off secure
|
tty3 "/libexec/getty std.default" xterm off secure
|
||||||
tty4 "/libexec/getty std.default" vt100 off secure
|
tty4 "/libexec/getty std.default" xterm off secure
|
||||||
tty5 "/libexec/getty std.default" vt100 off secure
|
tty5 "/libexec/getty std.default" xterm off secure
|
||||||
ttyUSB0 "/libexec/getty std.default" vt100 off secure
|
ttyUSB0 "/libexec/getty std.default" xterm off secure
|
||||||
|
|||||||
@@ -181,6 +181,10 @@ int waddstr (WINDOW *, char *);
|
|||||||
int wgetstr (WINDOW *, char *);
|
int wgetstr (WINDOW *, char *);
|
||||||
int wdeleteln (WINDOW *);
|
int wdeleteln (WINDOW *);
|
||||||
void mvcur(int ly, int lx, int y, int x);
|
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.
|
* Used to be in unctrl.h.
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ AOUT_OBJS = aout.o mips-dis.o
|
|||||||
RANLIB_OBJS = ranlib.o archive.o
|
RANLIB_OBJS = ranlib.o archive.o
|
||||||
HEADERS = a.out.h ar.h nlist.h ranlib.h
|
HEADERS = a.out.h ar.h nlist.h ranlib.h
|
||||||
|
|
||||||
vpath %.c $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as $(TOPSRC)/src/cmd/ld \
|
vpath %.c $(TOPSRC)/src/cmd/aout $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as \
|
||||||
$(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib $(TOPSRC)/src/cmd
|
$(TOPSRC)/src/cmd/ld $(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib \
|
||||||
|
$(TOPSRC)/src/cmd
|
||||||
|
|
||||||
all install depend: $(HEADERS) $(SUBDIR) $(PROG)
|
all install depend: $(HEADERS) $(SUBDIR) $(PROG)
|
||||||
-for i in $(SUBDIR); do $(MAKE) -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) $@; done
|
-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
|
re.help
|
||||||
misc
|
misc
|
||||||
unixbench
|
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
|
ashello: ashello.o
|
||||||
$(LD) ashello.o -o $@
|
$(LD) ashello.o -o $@
|
||||||
@@ -10,5 +10,11 @@ chello: chello.o
|
|||||||
echo: echo.o
|
echo: echo.o
|
||||||
$(LD) $@.o -o $@
|
$(LD) $@.o -o $@
|
||||||
|
|
||||||
|
stdarg: stdarg.o
|
||||||
|
$(CC) stdarg.o -o $@
|
||||||
|
|
||||||
|
skeleton: skeleton.o
|
||||||
|
$(CC) skeleton.o -o $@
|
||||||
|
|
||||||
clean:
|
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();
|
main()
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
{
|
||||||
printf ("Hello, SmallC World!\n");
|
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.
|
# Programs that live in subdirectories, and have makefiles of their own.
|
||||||
#
|
#
|
||||||
SUBDIR = startup-$(MACHINE) libc libm libutil libtermlib libcurses \
|
SUBDIR = startup-$(MACHINE) libc libm libutil libtermlib libcurses \
|
||||||
libvmf libwiznet share cmd games
|
libvmf libwiznet share cmd games man
|
||||||
|
|
||||||
all: $(SUBDIR)
|
all: $(SUBDIR)
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ CFLAGS += -Werror
|
|||||||
|
|
||||||
# Programs that live in subdirectories, and have makefiles of their own.
|
# Programs that live in subdirectories, and have makefiles of their own.
|
||||||
# /bin
|
# /bin
|
||||||
SUBDIR = adb adc-demo ar as awk basic cc chflags chpass \
|
SUBDIR = adb adc-demo aout ar as awk basic cc chflags chpass \
|
||||||
cpp dc diff env fdisk find forth fstat glcdtest hostname \
|
cpp dc diff emg env fdisk find forth fstat glcdtest \
|
||||||
id la lcc lcpp ld ls login make man med \
|
hostname id la lcc lcpp ld levee ls login make man med \
|
||||||
more nm passwd picoc portio printf pwm \
|
more nm passwd picoc portio printf pwm \
|
||||||
rdprof ranlib re renice retroforth scm setty sl \
|
rdprof ranlib re renice retroforth scm setty sl \
|
||||||
sed sh smallc smlrc stty sysctl test uname wiznet xargs \
|
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
|
# as - Assembler
|
||||||
# aout - Display information from a.out files
|
|
||||||
#
|
#
|
||||||
TOPSRC = $(shell cd ../../..; pwd)
|
TOPSRC = $(shell cd ../../..; pwd)
|
||||||
include $(TOPSRC)/target.mk
|
include $(TOPSRC)/target.mk
|
||||||
@@ -9,9 +8,7 @@ include $(TOPSRC)/target.mk
|
|||||||
CFLAGS += -Werror -Wall -Os
|
CFLAGS += -Werror -Wall -Os
|
||||||
LDFLAGS +=
|
LDFLAGS +=
|
||||||
|
|
||||||
AOUTOBJS = aout.o mips-dis.o
|
all: as
|
||||||
|
|
||||||
all: as aout
|
|
||||||
|
|
||||||
as: as.o
|
as: as.o
|
||||||
${CC} ${LDFLAGS} -o as.elf as.o ${LIBS}
|
${CC} ${LDFLAGS} -o as.elf as.o ${LIBS}
|
||||||
@@ -19,26 +16,8 @@ as: as.o
|
|||||||
${SIZE} as.elf
|
${SIZE} as.elf
|
||||||
${ELF2AOUT} as.elf $@ && rm 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:
|
clean:
|
||||||
rm -f *.o *.0 *.elf as aout tags *~ *.dis tests/*.dis tests/*.gcc-dis tests/*.o
|
rm -f *.o *.0 *.elf as tags *~ *.dis tests/*.dis tests/*.gcc-dis tests/*.o
|
||||||
|
|
||||||
test:
|
|
||||||
/usr/local/pic32-tools/bin/pic32-as -al example.s
|
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
install as $(DESTDIR)/bin/
|
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
|
#include $(TOPSRC)/cross.mk
|
||||||
#CFLAGS = -DCROSS
|
#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
|
MAN = cpp.0
|
||||||
MANSRC = cpp.1
|
MANSRC = cpp.1
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ install: all
|
|||||||
install cpp $(DESTDIR)/bin/
|
install cpp $(DESTDIR)/bin/
|
||||||
cp cpp.0 $(DESTDIR)/share/man/cat1/
|
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:
|
.l.o:
|
||||||
$(LEX) $(LFLAGS) $<
|
$(LEX) $(LFLAGS) $<
|
||||||
@@ -62,3 +62,9 @@ test:
|
|||||||
cmp tests/run9 tests/res9
|
cmp tests/run9 tests/res9
|
||||||
./cpp < tests/test10 > tests/run10
|
./cpp < tests/test10 > tests/run10
|
||||||
cmp tests/run10 tests/res10
|
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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* 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
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* 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
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#ifdef CROSS
|
|
||||||
# include </usr/include/stdio.h>
|
#include <stdio.h> /* for obuf */
|
||||||
# include </usr/include/ctype.h>
|
|
||||||
#else
|
|
||||||
# include <stdio.h> /* for obuf */
|
|
||||||
# include <ctype.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* Version string */
|
#include "config.h"
|
||||||
#define VERSSTR "cpp for RetroBSD"
|
|
||||||
|
|
||||||
typedef unsigned char uchar;
|
typedef unsigned char usch;
|
||||||
#ifdef YYTEXT_POINTER
|
extern usch yytext[];
|
||||||
extern char *yytext;
|
extern usch *stringbuf;
|
||||||
#else
|
|
||||||
extern char yytext[];
|
|
||||||
#endif
|
|
||||||
extern uchar *stringbuf;
|
|
||||||
|
|
||||||
extern int trulvl;
|
extern int trulvl;
|
||||||
extern int flslvl;
|
extern int flslvl;
|
||||||
@@ -50,7 +40,7 @@ extern int elflvl;
|
|||||||
extern int elslvl;
|
extern int elslvl;
|
||||||
extern int tflag, Cflag, Pflag;
|
extern int tflag, Cflag, Pflag;
|
||||||
extern int Mflag, dMflag;
|
extern int Mflag, dMflag;
|
||||||
extern uchar *Mfile;
|
extern usch *Mfile;
|
||||||
extern int ofd;
|
extern int ofd;
|
||||||
|
|
||||||
/* args for lookup() */
|
/* args for lookup() */
|
||||||
@@ -58,32 +48,77 @@ extern int ofd;
|
|||||||
#define ENTER 1
|
#define ENTER 1
|
||||||
|
|
||||||
/* buffer used internally */
|
/* 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 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 */
|
/* definition for include file info */
|
||||||
struct includ {
|
struct includ {
|
||||||
struct includ *next;
|
struct includ *next;
|
||||||
const uchar *fname; /* current fn, changed if #line found */
|
const usch *fname; /* current fn, changed if #line found */
|
||||||
const uchar *orgfn; /* current fn, not changed */
|
const usch *orgfn; /* current fn, not changed */
|
||||||
int lineno;
|
int lineno;
|
||||||
int infil;
|
int infil;
|
||||||
uchar *curptr;
|
usch *curptr;
|
||||||
uchar *maxread;
|
usch *maxread;
|
||||||
uchar *ostr;
|
usch *ostr;
|
||||||
uchar *buffer;
|
usch *buffer;
|
||||||
int idx;
|
int idx;
|
||||||
void *incs;
|
void *incs;
|
||||||
const uchar *fn;
|
const usch *fn;
|
||||||
uchar bbuf[NAMEMAX+CPPBUF+1];
|
#ifdef BUF_STACK
|
||||||
} *ifiles;
|
usch bbuf[BBUFSZ];
|
||||||
|
#else
|
||||||
|
usch *bbuf;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
extern struct includ *ifiles;
|
||||||
|
|
||||||
/* Symbol table entry */
|
/* Symbol table entry */
|
||||||
struct symtab {
|
struct symtab {
|
||||||
const uchar *namep;
|
const usch *namep;
|
||||||
const uchar *value;
|
const usch *value;
|
||||||
const uchar *file;
|
const usch *file;
|
||||||
int line;
|
int line;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -110,13 +145,15 @@ struct nd {
|
|||||||
#define nd_val n.val
|
#define nd_val n.val
|
||||||
#define nd_uval n.uval
|
#define nd_uval n.uval
|
||||||
|
|
||||||
struct recur; /* not used outside cpp.c */
|
struct symtab *lookup(const usch *namep, int enterf);
|
||||||
int subst(struct symtab *, struct recur *);
|
usch *gotident(struct symtab *nl);
|
||||||
struct symtab *lookup(const uchar *namep, int enterf);
|
extern int slow; /* scan slowly for new tokens */
|
||||||
uchar *gotident(struct symtab *nl);
|
int submac(struct symtab *nl, int);
|
||||||
int slow; /* scan slowly for new tokens */
|
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 popfile(void);
|
||||||
void prtline(void);
|
void prtline(void);
|
||||||
int yylex(void);
|
int yylex(void);
|
||||||
@@ -128,18 +165,22 @@ void setline(int);
|
|||||||
void setfile(char *);
|
void setfile(char *);
|
||||||
int yyparse(void);
|
int yyparse(void);
|
||||||
void yyerror(const char *);
|
void yyerror(const char *);
|
||||||
void unpstr(const uchar *);
|
void unpstr(const usch *);
|
||||||
uchar *savstr(const uchar *str);
|
usch *savstr(const usch *str);
|
||||||
void savch(int c);
|
void savch(int c);
|
||||||
void mainscan(void);
|
void mainscan(void);
|
||||||
void putch(int);
|
void putch(int);
|
||||||
void putstr(const uchar *s);
|
void putstr(const usch *s);
|
||||||
void line(void);
|
void line(void);
|
||||||
uchar *sheap(const char *fmt, ...);
|
usch *sheap(const char *fmt, ...);
|
||||||
void xwarning(uchar *);
|
void xwarning(usch *);
|
||||||
void xerror(uchar *);
|
void xerror(usch *);
|
||||||
#define warning(args...) xwarning(sheap(args))
|
#ifdef HAVE_CPP_VARARG_MACRO_GCC
|
||||||
#define error(args...) xerror(sheap(args))
|
#define warning(...) xwarning(sheap(__VA_ARGS__))
|
||||||
void expmac(struct recur *);
|
#define error(...) xerror(sheap(__VA_ARGS__))
|
||||||
|
#else
|
||||||
|
#define warning printf
|
||||||
|
#define error printf
|
||||||
|
#endif
|
||||||
int cinput(void);
|
int cinput(void);
|
||||||
void getcmnt(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).
|
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@@ -58,6 +60,7 @@
|
|||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
#include "cpp.h"
|
#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 * (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, };
|
int i[] = { 1, 23, 4, 5, };
|
||||||
char c[2][6] = { "hello", "" };
|
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.
|
* Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -37,21 +39,24 @@
|
|||||||
* - inch() is like inpch but \\n and trigraphs are expanded.
|
* - inch() is like inpch but \\n and trigraphs are expanded.
|
||||||
* - unch() pushes back a character to the input stream.
|
* - unch() pushes back a character to the input stream.
|
||||||
*/
|
*/
|
||||||
#ifdef CROSS
|
|
||||||
# include </usr/include/string.h>
|
#include "config.h"
|
||||||
#else
|
|
||||||
# include <string.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
#include "cpp.h"
|
#include "cpp.h"
|
||||||
#include "y.tab.h"
|
#include "y.tab.h"
|
||||||
|
|
||||||
static void cvtdig(int rad);
|
static void cvtdig(int rad);
|
||||||
static int charcon(uchar *);
|
static int charcon(usch *);
|
||||||
static void elsestmt(void);
|
static void elsestmt(void);
|
||||||
static void ifdefstmt(void);
|
static void ifdefstmt(void);
|
||||||
static void ifndefstmt(void);
|
static void ifndefstmt(void);
|
||||||
@@ -75,9 +80,8 @@ extern void yyset_lineno (int);
|
|||||||
|
|
||||||
static int inch(void);
|
static int inch(void);
|
||||||
|
|
||||||
size_t strlcat(char *dst, const char *src, size_t siz);
|
|
||||||
|
|
||||||
int inif;
|
int inif;
|
||||||
|
extern int dflag;
|
||||||
|
|
||||||
#define PUTCH(ch) if (!flslvl) putch(ch)
|
#define PUTCH(ch) if (!flslvl) putch(ch)
|
||||||
/* protection against recursion in #include */
|
/* protection against recursion in #include */
|
||||||
@@ -87,25 +91,16 @@ static int inclevel;
|
|||||||
/* get next character unaltered */
|
/* get next character unaltered */
|
||||||
#define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
|
#define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
|
||||||
|
|
||||||
#ifdef YYTEXT_POINTER
|
usch yytext[CPPBUF];
|
||||||
static char buf[CPPBUF];
|
|
||||||
char *yytext = buf;
|
|
||||||
#else
|
|
||||||
char yytext[CPPBUF];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define C_SPEC 1
|
char spechr[256] = {
|
||||||
#define C_EP 2
|
0, 0, 0, 0, C_SPEC, C_SPEC, 0, 0,
|
||||||
#define C_ID 4
|
0, C_WSNL, C_SPEC|C_WSNL, 0,
|
||||||
#define C_I (C_SPEC|C_ID)
|
0, C_WSNL, 0, 0,
|
||||||
#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,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 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,
|
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, 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,
|
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
|
static void
|
||||||
unch(int c)
|
unch(int c)
|
||||||
{
|
{
|
||||||
|
|
||||||
--ifiles->curptr;
|
--ifiles->curptr;
|
||||||
if (ifiles->curptr < ifiles->bbuf)
|
if (ifiles->curptr < ifiles->bbuf)
|
||||||
error("pushback buffer full");
|
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)
|
fastscan(void)
|
||||||
{
|
{
|
||||||
struct symtab *nl;
|
struct symtab *nl;
|
||||||
int ch, i;
|
int ch, i, ccnt/*, onemore*/;
|
||||||
|
usch *cp;
|
||||||
|
|
||||||
goto run;
|
goto run;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ch = NXTCH();
|
ch = NXTCH();
|
||||||
xloop: if (ch == -1)
|
xloop: if (ch == -1)
|
||||||
return;
|
return;
|
||||||
|
if (dflag>1)
|
||||||
|
printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
|
||||||
if ((spechr[ch] & C_SPEC) == 0) {
|
if ((spechr[ch] & C_SPEC) == 0) {
|
||||||
PUTCH(ch);
|
PUTCH(ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
case EBLOCK:
|
||||||
|
case WARN:
|
||||||
|
case CONC:
|
||||||
|
error("bad char passed");
|
||||||
|
break;
|
||||||
|
|
||||||
case '/': /* Comments */
|
case '/': /* Comments */
|
||||||
if ((ch = inch()) == '/') {
|
if ((ch = inch()) == '/') {
|
||||||
if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
|
cppcmt: if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
|
||||||
do {
|
do {
|
||||||
if (Cflag) PUTCH(ch);
|
if (Cflag) PUTCH(ch);
|
||||||
ch = inch();
|
ch = inch();
|
||||||
} while (ch != -1 && ch != '\n');
|
} while (ch != -1 && ch != '\n');
|
||||||
goto xloop;
|
goto xloop;
|
||||||
} else if (ch == '*') {
|
} else if (ch == '*') {
|
||||||
if (Cflag) { PUTCH('/'); PUTCH('*'); }
|
if (eatcmnt())
|
||||||
for (;;) {
|
return;
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
PUTCH('/');
|
PUTCH('/');
|
||||||
goto xloop;
|
goto xloop;
|
||||||
@@ -213,11 +236,30 @@ xloop: if (ch == -1)
|
|||||||
goto xloop;
|
goto xloop;
|
||||||
|
|
||||||
case '\n': /* newlines, for pp directives */
|
case '\n': /* newlines, for pp directives */
|
||||||
ifiles->lineno++;
|
run2: ifiles->lineno++;
|
||||||
do {
|
do {
|
||||||
PUTCH(ch);
|
PUTCH(ch);
|
||||||
run: ch = NXTCH();
|
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');
|
} while (ch == ' ' || ch == '\t');
|
||||||
|
if (ch == '\\') {
|
||||||
|
ch = NXTCH();
|
||||||
|
if (ch == '\n')
|
||||||
|
goto run2;
|
||||||
|
unch(ch);
|
||||||
|
ch = '\\';
|
||||||
|
}
|
||||||
if (ch == '#') {
|
if (ch == '#') {
|
||||||
ppdir();
|
ppdir();
|
||||||
continue;
|
continue;
|
||||||
@@ -236,7 +278,7 @@ run: ch = NXTCH();
|
|||||||
case '\"': /* strings */
|
case '\"': /* strings */
|
||||||
str: PUTCH(ch);
|
str: PUTCH(ch);
|
||||||
while ((ch = inch()) != '\"') {
|
while ((ch = inch()) != '\"') {
|
||||||
PUTCH(ch);
|
PUTCH(ch);
|
||||||
if (ch == '\\') {
|
if (ch == '\\') {
|
||||||
ch = inch();
|
ch = inch();
|
||||||
PUTCH(ch);
|
PUTCH(ch);
|
||||||
@@ -257,7 +299,16 @@ str: PUTCH(ch);
|
|||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
do {
|
do {
|
||||||
PUTCH(ch);
|
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) {
|
if (spechr[ch] & C_EP) {
|
||||||
PUTCH(ch);
|
PUTCH(ch);
|
||||||
ch = NXTCH();
|
ch = NXTCH();
|
||||||
@@ -305,9 +356,9 @@ con: PUTCH(ch);
|
|||||||
ch = NXTCH();
|
ch = NXTCH();
|
||||||
goto xloop;
|
goto xloop;
|
||||||
}
|
}
|
||||||
i = 0;
|
/*onemore =*/ i = ccnt = 0;
|
||||||
do {
|
do {
|
||||||
yytext[i++] = (uchar)ch;
|
yytext[i++] = (usch)ch;
|
||||||
ch = NXTCH();
|
ch = NXTCH();
|
||||||
if (ch == '\\') {
|
if (ch == '\\') {
|
||||||
ch = NXTCH();
|
ch = NXTCH();
|
||||||
@@ -322,14 +373,17 @@ con: PUTCH(ch);
|
|||||||
if (ch < 0)
|
if (ch < 0)
|
||||||
return;
|
return;
|
||||||
} while (spechr[ch] & C_ID);
|
} while (spechr[ch] & C_ID);
|
||||||
|
|
||||||
yytext[i] = 0;
|
yytext[i] = 0;
|
||||||
unch(ch);
|
unch(ch);
|
||||||
if ((nl = lookup((uchar *)yytext, FIND)) != 0) {
|
|
||||||
uchar *op = stringbuf;
|
cp = stringbuf;
|
||||||
putstr(gotident(nl));
|
if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
|
||||||
stringbuf = op;
|
putstr(stringbuf);
|
||||||
} else
|
} else
|
||||||
putstr((uchar *)yytext);
|
putstr((usch *)yytext);
|
||||||
|
stringbuf = cp;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +398,7 @@ sloscan()
|
|||||||
zagain:
|
zagain:
|
||||||
yyp = 0;
|
yyp = 0;
|
||||||
ch = inch();
|
ch = inch();
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case -1:
|
case -1:
|
||||||
return 0;
|
return 0;
|
||||||
@@ -357,24 +411,24 @@ zagain:
|
|||||||
yyp = 0;
|
yyp = 0;
|
||||||
break;
|
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':
|
case '6': case '7': case '8': case '9':
|
||||||
/* readin a "pp-number" */
|
/* readin a "pp-number" */
|
||||||
ppnum: for (;;) {
|
ppnum: for (;;) {
|
||||||
ch = inch();
|
ch = inch();
|
||||||
if (spechr[ch] & C_EP) {
|
if (spechr[ch] & C_EP) {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
ch = inch();
|
ch = inch();
|
||||||
if (ch == '-' || ch == '+') {
|
if (ch == '-' || ch == '+') {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
} else
|
} else
|
||||||
unch(ch);
|
unch(ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((spechr[ch] & C_ID) || ch == '.') {
|
if ((spechr[ch] & C_ID) || ch == '.') {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
unch(ch);
|
unch(ch);
|
||||||
@@ -383,11 +437,11 @@ ppnum: for (;;) {
|
|||||||
return NUMBER;
|
return NUMBER;
|
||||||
|
|
||||||
case '\'':
|
case '\'':
|
||||||
chlit:
|
chlit:
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((ch = inch()) == '\\') {
|
if ((ch = inch()) == '\\') {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
yytext[yyp++] = (uchar)inch();
|
yytext[yyp++] = (usch)inch();
|
||||||
continue;
|
continue;
|
||||||
} else if (ch == '\n') {
|
} else if (ch == '\n') {
|
||||||
/* not a constant */
|
/* not a constant */
|
||||||
@@ -396,7 +450,7 @@ chlit:
|
|||||||
ch = '\'';
|
ch = '\'';
|
||||||
goto any;
|
goto any;
|
||||||
} else
|
} else
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
if (ch == '\'')
|
if (ch == '\'')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -407,7 +461,7 @@ chlit:
|
|||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
while ((ch = inch()) == ' ' || ch == '\t')
|
while ((ch = inch()) == ' ' || ch == '\t')
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
unch(ch);
|
unch(ch);
|
||||||
yytext[yyp] = 0;
|
yytext[yyp] = 0;
|
||||||
return(WSPACE);
|
return(WSPACE);
|
||||||
@@ -415,7 +469,7 @@ chlit:
|
|||||||
case '/':
|
case '/':
|
||||||
if ((ch = inch()) == '/') {
|
if ((ch = inch()) == '/') {
|
||||||
do {
|
do {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
ch = inch();
|
ch = inch();
|
||||||
} while (ch && ch != '\n');
|
} while (ch && ch != '\n');
|
||||||
yytext[yyp] = 0;
|
yytext[yyp] = 0;
|
||||||
@@ -435,7 +489,10 @@ chlit:
|
|||||||
more: while ((c = inch()) && c != '*') {
|
more: while ((c = inch()) && c != '*') {
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
putch(c), ifiles->lineno++;
|
putch(c), ifiles->lineno++;
|
||||||
else if (c == 1) /* WARN */
|
else if (c == EBLOCK) {
|
||||||
|
(void)inch();
|
||||||
|
(void)inch();
|
||||||
|
} else if (c == 1) /* WARN */
|
||||||
wrn = 1;
|
wrn = 1;
|
||||||
}
|
}
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
@@ -459,7 +516,7 @@ chlit:
|
|||||||
case '.':
|
case '.':
|
||||||
ch = inch();
|
ch = inch();
|
||||||
if (isdigit(ch)) {
|
if (isdigit(ch)) {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
goto ppnum;
|
goto ppnum;
|
||||||
} else {
|
} else {
|
||||||
unch(ch);
|
unch(ch);
|
||||||
@@ -468,14 +525,16 @@ chlit:
|
|||||||
goto any;
|
goto any;
|
||||||
|
|
||||||
case '\"':
|
case '\"':
|
||||||
|
if (tflag)
|
||||||
|
goto any;
|
||||||
strng:
|
strng:
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((ch = inch()) == '\\') {
|
if ((ch = inch()) == '\\') {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
yytext[yyp++] = (uchar)inch();
|
yytext[yyp++] = (usch)inch();
|
||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
if (ch == '\"')
|
if (ch == '\"')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -483,26 +542,26 @@ chlit:
|
|||||||
return(STRING);
|
return(STRING);
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
if ((ch = inch()) == '\"') {
|
if ((ch = inch()) == '\"' && !tflag) {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
goto strng;
|
goto strng;
|
||||||
} else if (ch == '\'') {
|
} else if (ch == '\'' && !tflag) {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
goto chlit;
|
goto chlit;
|
||||||
}
|
}
|
||||||
unch(ch);
|
unch(ch);
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
/* Yetch, all identifiers */
|
/* Yetch, all identifiers */
|
||||||
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 'l':
|
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 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
|
||||||
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||||
case 'y': case 'z':
|
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 'G': case 'H': case 'I': case 'J': case 'K':
|
||||||
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
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 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
||||||
case 'Y': case 'Z':
|
case 'Y': case 'Z':
|
||||||
case '_': /* {L}({L}|{D})* */
|
case '_': /* {L}({L}|{D})* */
|
||||||
|
|
||||||
@@ -510,7 +569,7 @@ chlit:
|
|||||||
for (;;) { /* get chars */
|
for (;;) { /* get chars */
|
||||||
ch = inch();
|
ch = inch();
|
||||||
if (isalpha(ch) || isdigit(ch) || ch == '_') {
|
if (isalpha(ch) || isdigit(ch) || ch == '_') {
|
||||||
yytext[yyp++] = (uchar)ch;
|
yytext[yyp++] = (usch)ch;
|
||||||
} else {
|
} else {
|
||||||
unch(ch);
|
unch(ch);
|
||||||
break;
|
break;
|
||||||
@@ -584,27 +643,31 @@ yylex()
|
|||||||
case NUMBER:
|
case NUMBER:
|
||||||
if (yytext[0] == '\'') {
|
if (yytext[0] == '\'') {
|
||||||
yylval.node.op = NUMBER;
|
yylval.node.op = NUMBER;
|
||||||
yylval.node.nd_val = charcon((uchar *)yytext);
|
yylval.node.nd_val = charcon((usch *)yytext);
|
||||||
} else
|
} else
|
||||||
cvtdig(yytext[0] != '0' ? 10 :
|
cvtdig(yytext[0] != '0' ? 10 :
|
||||||
yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
|
yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
|
||||||
return NUMBER;
|
return NUMBER;
|
||||||
|
|
||||||
case IDENT:
|
case IDENT:
|
||||||
if (strcmp(yytext, "defined") == 0) {
|
if (strcmp((char *)yytext, "defined") == 0) {
|
||||||
ifdef = 1;
|
ifdef = 1;
|
||||||
return DEFINED;
|
return DEFINED;
|
||||||
}
|
}
|
||||||
nl = lookup((uchar *)yytext, FIND);
|
nl = lookup((usch *)yytext, FIND);
|
||||||
if (ifdef) {
|
if (ifdef) {
|
||||||
yylval.node.nd_val = nl != NULL;
|
yylval.node.nd_val = nl != NULL;
|
||||||
ifdef = 0;
|
ifdef = 0;
|
||||||
} else if (nl && noex == 0) {
|
} else if (nl && noex == 0) {
|
||||||
uchar *c, *och = stringbuf;
|
usch *och = stringbuf;
|
||||||
|
int i;
|
||||||
|
|
||||||
c = gotident(nl);
|
i = kfind(nl);
|
||||||
unch(1);
|
unch(WARN);
|
||||||
unpstr(c);
|
if (i)
|
||||||
|
unpstr(stringbuf);
|
||||||
|
else
|
||||||
|
unpstr(nl->namep);
|
||||||
stringbuf = och;
|
stringbuf = och;
|
||||||
noex = 1;
|
noex = 1;
|
||||||
return yylex();
|
return yylex();
|
||||||
@@ -613,7 +676,7 @@ yylex()
|
|||||||
}
|
}
|
||||||
yylval.node.op = NUMBER;
|
yylval.node.op = NUMBER;
|
||||||
return NUMBER;
|
return NUMBER;
|
||||||
case 1: /* WARN */
|
case WARN:
|
||||||
noex = 0;
|
noex = 0;
|
||||||
return yylex();
|
return yylex();
|
||||||
default:
|
default:
|
||||||
@@ -623,7 +686,7 @@ yylex()
|
|||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
uchar *yyp, yybuf[CPPBUF];
|
usch *yyp, yybuf[CPPBUF];
|
||||||
|
|
||||||
int yywrap(void);
|
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.
|
* 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.
|
* Return 0 on success, -1 if file to be included is not found.
|
||||||
*/
|
*/
|
||||||
int
|
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;
|
extern struct initar *initar;
|
||||||
|
struct includ ibuf;
|
||||||
struct includ *ic;
|
struct includ *ic;
|
||||||
int otrulvl;
|
int otrulvl;
|
||||||
|
|
||||||
ic = malloc(sizeof(struct includ));
|
ic = &ibuf;
|
||||||
if (ic == NULL)
|
|
||||||
error("out of memory for %s", file);
|
|
||||||
ic->next = ifiles;
|
ic->next = ifiles;
|
||||||
|
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
ic->infil = open((const char *)file, O_RDONLY);
|
if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
|
||||||
if (ic->infil < 0) {
|
|
||||||
free(ic);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
ic->orgfn = ic->fname = file;
|
ic->orgfn = ic->fname = file;
|
||||||
if (++inclevel > MAX_INCLEVEL)
|
if (++inclevel > MAX_INCLEVEL)
|
||||||
error("Limit for nested includes exceeded");
|
error("Limit for nested includes exceeded");
|
||||||
} else {
|
} else {
|
||||||
ic->infil = 0;
|
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->buffer = ic->bbuf+NAMEMAX;
|
||||||
ic->curptr = ic->buffer;
|
ic->curptr = ic->buffer;
|
||||||
ifiles = ic;
|
ifiles = ic;
|
||||||
@@ -794,8 +821,7 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs)
|
|||||||
prinit(initar, ic);
|
prinit(initar, ic);
|
||||||
initar = NULL;
|
initar = NULL;
|
||||||
if (dMflag)
|
if (dMflag)
|
||||||
if (write(ofd, ic->buffer, strlen((char *)ic->buffer)) < 0)
|
write(ofd, ic->buffer, strlen((char *)ic->buffer));
|
||||||
/* ignore */;
|
|
||||||
fastscan();
|
fastscan();
|
||||||
prtline();
|
prtline();
|
||||||
ic->infil = oin;
|
ic->infil = oin;
|
||||||
@@ -808,9 +834,11 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs)
|
|||||||
if (otrulvl != trulvl || flslvl)
|
if (otrulvl != trulvl || flslvl)
|
||||||
error("unterminated conditional");
|
error("unterminated conditional");
|
||||||
|
|
||||||
|
#ifndef BUF_STACK
|
||||||
|
free(ic->bbuf);
|
||||||
|
#endif
|
||||||
ifiles = ic->next;
|
ifiles = ic->next;
|
||||||
close(ic->infil);
|
close(ic->infil);
|
||||||
free(ic);
|
|
||||||
inclevel--;
|
inclevel--;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -821,15 +849,14 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs)
|
|||||||
void
|
void
|
||||||
prtline()
|
prtline()
|
||||||
{
|
{
|
||||||
uchar *s, *os = stringbuf;
|
usch *s, *os = stringbuf;
|
||||||
|
|
||||||
if (Mflag) {
|
if (Mflag) {
|
||||||
if (dMflag)
|
if (dMflag)
|
||||||
return; /* no output */
|
return; /* no output */
|
||||||
if (ifiles->lineno == 1) {
|
if (ifiles->lineno == 1) {
|
||||||
s = sheap("%s: %s\n", Mfile, ifiles->fname);
|
s = sheap("%s: %s\n", Mfile, ifiles->fname);
|
||||||
if (write(ofd, s, strlen((char *)s)) < 0)
|
write(ofd, s, strlen((char *)s));
|
||||||
/* ignore */;
|
|
||||||
}
|
}
|
||||||
} else if (!Pflag)
|
} else if (!Pflag)
|
||||||
putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
|
putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
|
||||||
@@ -840,8 +867,8 @@ void
|
|||||||
cunput(int c)
|
cunput(int c)
|
||||||
{
|
{
|
||||||
#ifdef CPP_DEBUG
|
#ifdef CPP_DEBUG
|
||||||
extern int dflag;
|
// extern int dflag;
|
||||||
if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c);
|
// if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
|
||||||
#endif
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
if (c == 10) {
|
if (c == 10) {
|
||||||
@@ -873,7 +900,7 @@ cvtdig(int rad)
|
|||||||
{
|
{
|
||||||
unsigned long long rv = 0;
|
unsigned long long rv = 0;
|
||||||
unsigned long long rv2 = 0;
|
unsigned long long rv2 = 0;
|
||||||
char *y = yytext;
|
usch *y = yytext;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
c = *y++;
|
c = *y++;
|
||||||
@@ -900,7 +927,7 @@ cvtdig(int rad)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
charcon(uchar *p)
|
charcon(usch *p)
|
||||||
{
|
{
|
||||||
int val, c;
|
int val, c;
|
||||||
|
|
||||||
@@ -993,8 +1020,8 @@ skpln(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ifdefstmt(void)
|
ifdefstmt(void)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
if (flslvl) {
|
if (flslvl) {
|
||||||
@@ -1006,7 +1033,7 @@ ifdefstmt(void)
|
|||||||
while (t == WSPACE);
|
while (t == WSPACE);
|
||||||
if (t != IDENT)
|
if (t != IDENT)
|
||||||
error("bad ifdef");
|
error("bad ifdef");
|
||||||
if (lookup((uchar *)yytext, FIND) == 0) {
|
if (lookup((usch *)yytext, FIND) == 0) {
|
||||||
putch('\n');
|
putch('\n');
|
||||||
flslvl++;
|
flslvl++;
|
||||||
} else
|
} else
|
||||||
@@ -1015,8 +1042,8 @@ ifdefstmt(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ifndefstmt(void)
|
ifndefstmt(void)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
if (flslvl) {
|
if (flslvl) {
|
||||||
@@ -1028,7 +1055,7 @@ ifndefstmt(void)
|
|||||||
while (t == WSPACE);
|
while (t == WSPACE);
|
||||||
if (t != IDENT)
|
if (t != IDENT)
|
||||||
error("bad ifndef");
|
error("bad ifndef");
|
||||||
if (lookup((uchar *)yytext, FIND) != 0) {
|
if (lookup((usch *)yytext, FIND) != 0) {
|
||||||
putch('\n');
|
putch('\n');
|
||||||
flslvl++;
|
flslvl++;
|
||||||
} else
|
} else
|
||||||
@@ -1037,7 +1064,7 @@ ifndefstmt(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
endifstmt(void)
|
endifstmt(void)
|
||||||
{
|
{
|
||||||
if (flslvl) {
|
if (flslvl) {
|
||||||
flslvl--;
|
flslvl--;
|
||||||
@@ -1094,11 +1121,11 @@ elifstmt(void)
|
|||||||
error("If-less elif");
|
error("If-less elif");
|
||||||
}
|
}
|
||||||
|
|
||||||
static uchar *
|
static usch *
|
||||||
svinp(void)
|
svinp(void)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
uchar *cp = stringbuf;
|
usch *cp = stringbuf;
|
||||||
|
|
||||||
while ((c = inch()) && c != '\n')
|
while ((c = inch()) && c != '\n')
|
||||||
savch(c);
|
savch(c);
|
||||||
@@ -1110,7 +1137,7 @@ svinp(void)
|
|||||||
static void
|
static void
|
||||||
cpperror(void)
|
cpperror(void)
|
||||||
{
|
{
|
||||||
uchar *cp;
|
usch *cp;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (flslvl)
|
if (flslvl)
|
||||||
@@ -1128,7 +1155,7 @@ cpperror(void)
|
|||||||
static void
|
static void
|
||||||
cppwarning(void)
|
cppwarning(void)
|
||||||
{
|
{
|
||||||
uchar *cp;
|
usch *cp;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (flslvl)
|
if (flslvl)
|
||||||
@@ -1158,7 +1185,7 @@ undefstmt(void)
|
|||||||
|
|
||||||
if (sloscan() != WSPACE || sloscan() != IDENT)
|
if (sloscan() != WSPACE || sloscan() != IDENT)
|
||||||
error("bad undef");
|
error("bad undef");
|
||||||
if (flslvl == 0 && (np = lookup((uchar *)yytext, FIND)))
|
if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
|
||||||
np->value = 0;
|
np->value = 0;
|
||||||
chknl(0);
|
chknl(0);
|
||||||
}
|
}
|
||||||
@@ -1171,7 +1198,7 @@ pragmastmt(void)
|
|||||||
if (sloscan() != WSPACE)
|
if (sloscan() != WSPACE)
|
||||||
error("bad pragma");
|
error("bad pragma");
|
||||||
if (!flslvl)
|
if (!flslvl)
|
||||||
putstr((const uchar *)"#pragma ");
|
putstr((const usch *)"\n#pragma ");
|
||||||
do {
|
do {
|
||||||
c = inch();
|
c = inch();
|
||||||
if (!flslvl)
|
if (!flslvl)
|
||||||
@@ -1265,7 +1292,7 @@ ppdir(void)
|
|||||||
goto out; /* something else, ignore */
|
goto out; /* something else, ignore */
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
bp[i++] = (uchar)ch;
|
bp[i++] = (usch)ch;
|
||||||
if (i == sizeof(bp)-1)
|
if (i == sizeof(bp)-1)
|
||||||
goto out; /* too long */
|
goto out; /* too long */
|
||||||
ch = inch();
|
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: all
|
||||||
install -m 755 $(BIN) ${DESTDIR}/sbin
|
install -m 755 $(BIN) ${DESTDIR}/sbin
|
||||||
install -m 755 $(MAN) ${DESTDIR}/share/man/cat8
|
cp $(MAN) ${DESTDIR}/share/man/cat8
|
||||||
|
|
||||||
lint: ${SRCS}
|
lint: ${SRCS}
|
||||||
lint -hax ${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