98 Commits

Author SHA1 Message Date
Serge Vakulenko
f33305f894 Levee editor compiled for RetroBSD. 2015-01-06 13:42:43 -08:00
Serge Vakulenko
e834303650 Levee editor compiled on Linux. 2015-01-06 12:58:23 -08:00
Serge Vakulenko
476573dae6 Imported levee editor sources from http://www.pell.portland.or.us/~orc/Code/levee/levee-3.5a.tar.gz 2015-01-06 12:54:38 -08:00
Serge Vakulenko
8e2c046406 Merge pull request #41 from alexfru/master
SmallerC: generate smaller & faster code; bugfixes
2014-12-29 20:06:10 -08:00
alex
dad5247184 Merge branch 'master' of https://github.com/alexfru/retrobsd 2014-12-29 16:36:58 -08:00
alex
b1f67fbca0 SmallerC: generate smaller & faster code; bugfixes
Improvements:
- use registers more efficiently
- eliminate some register copies and stack manipulations
- promote left operands to right immediate operands
- improve simple assignments to auto/static vars
- use bltz, blez, bgtz, bgez
- change mul/divu (by powers of 2) to sll/srl/and
- use seb, seh for sign extension instead of sll/sra
- overall generate a bit tighter, faster and more readable asm code

Fixes:
- >>= should be unsigned when the left operand is unsigned int.
The right operand isn't important here.
- very subtle bug in e.g. void f(){int a; &a+1;/*wrong value of &a+1*/}

Other:
- include stdarg.c and skeleton.c in /share/example/Makefile
2014-12-29 16:28:56 -08:00
Serge Vakulenko
f76ab8417c Merge pull request #39 from alexfru/master
Smaller C: Fix >>=
2014-12-13 01:19:36 -08:00
Alexey Frunze
3bb914c8b4 Fix >>=
>>= should be unsigned when the left operand is unsigned int. The right
operand isn't important here.
2014-12-13 01:06:53 -08:00
Serge Vakulenko
8b099bcf76 Merge pull request #38 from alexfru/master
Correct sd card image name.
2014-12-07 21:58:35 -08:00
Alexey Frunze
2fc41d34cf Correct sd card image name. 2014-12-07 21:51:06 -08:00
Serge Vakulenko
2301571ecb Merge pull request #37 from alexfru/master
Smaller C fixes and improvements.
2014-12-06 16:38:56 -08:00
alex
00269e9387 Smaller C fixes and improvements:
- move va_list type detection under #ifdef as it's rarely needed anyway
- allow up to 254 characters in a string literal
- generate a warning when an integer is passed instead of a pointer (and
vice versa) as a function parameter (pass -Wall for this)
- when printing an unexpected token, print identifier tokens instead of
'<tokIdent>'
- fix: allow most control characters inside '' and ""
- fix handling of -I<path> and -SI<path>
- switch() now supports Duff's device
- for() now supports declarations in its first clause as in C99/C++
2014-12-06 16:18:17 -08:00
Serge Vakulenko
687695d0db Fixed missing .profile at top level. 2014-10-23 19:08:11 -07:00
Serge Vakulenko
0aa5e1c462 README updated. 2014-10-21 11:28:22 -07:00
Serge Vakulenko
3a7cde7974 Merge pull request #36 from alexfru/master
Smaller C: Fix MIPS code generation for -= and postfix --. Also convert most of Small C sample programs to Smaller C.
2014-10-21 00:16:19 -07:00
alex
f57cc446b0 Remove no longer applicable comment. 2014-10-19 00:53:29 -07:00
alex
1a55933faf Merge branch 'master' of https://github.com/alexfru/retrobsd 2014-10-19 00:25:23 -07:00
alex
b18ce0aa87 Fix MIPS code generation for -= and postfix --.
Also convert most of Small C sample programs to Smaller C.
2014-10-19 00:22:44 -07:00
alex
5bbf8d4e73 Fix MIPS code generation for -= and postfix --.
Convert most of Small C sample programs to Smaller C.
2014-10-19 00:13:00 -07:00
Sergey
7aa774702b Fubarino configuration modified to use Arduino-compatible bootloader. 2014-10-04 14:30:21 -07:00
Sergey
64430a0f91 Added comfiguration for Majenko SDXL board.
DIP and Pinguino-micro boards removed - nobody uses these.
Deleted unused linker scripts.
2014-10-04 13:57:03 -07:00
Serge Vakulenko
d5e30d7b79 Fixed help message for fsutil. 2014-09-26 21:05:27 -07:00
Serge Vakulenko
a8d9b3d01f Makefiles updated for man sources. 2014-09-25 19:31:55 -07:00
Serge Vakulenko
ebd35d772f Fixed bug in 'make installfs'. 2014-09-25 18:09:06 -07:00
Serge Vakulenko
c4da2137e1 Added man sources from 2.11bsd tape. 2014-09-25 17:14:51 -07:00
Serge Vakulenko
c42133cdff Fixed newlines in crib game. 2014-09-25 13:44:51 -07:00
Sergey
dc66e6fdda Fsutil enhanced to create and handle partitions. 2014-09-20 18:54:13 -07:00
Serge Vakulenko
f58c7a7426 Added missing files for atc, boggle, btlgammon, cribbage. 2014-09-17 13:54:28 -07:00
Serge Vakulenko
5c4309942a Merge branch 'games'. 2014-09-17 13:21:59 -07:00
Serge Vakulenko
e557c88b1e Added manual for atc game.
Cribbage manuals installed.
2014-09-17 13:00:06 -07:00
Serge Vakulenko
850797db2e Fixed snake game.
Fixed newline bug in libcurses.

File /etc/termcap replaced by small version. Five TERM types supported:
ansi - simple generic display;
xterm - common for most modern terminal emulators;
linux - for Linux console;
cons25 - for BSD console;
vt100 - for DEC VT100 terminal emulators.

Terminal type xterm set by default.
2014-09-15 20:40:04 -07:00
Serge Vakulenko
cae7db41ca Snake fixed. 2014-09-15 14:24:17 -07:00
Serge Vakulenko
808dfaf6ef Ported snake game. 2014-09-15 12:28:43 -07:00
Sergey
d3d48970e3 Some progress with snake game. 2014-09-14 23:19:06 -07:00
Sergey
93d95abc69 Fixed warning in fsutil. 2014-09-13 15:17:30 -07:00
Serge Vakulenko
c5ac22d17f Ported robots game. 2014-09-12 13:32:16 -07:00
Serge Vakulenko
e7b77dadc3 Ported quiz game. 2014-09-12 12:03:11 -07:00
Serge Vakulenko
2ea9e02ba5 Monop game done. 2014-09-10 20:48:05 -07:00
Serge Vakulenko
d9d91365c0 Fixed warning in mille. 2014-09-10 20:09:59 -07:00
Serge Vakulenko
2da083e9bd Some progress on 'monop' game. 2014-09-08 21:36:15 -07:00
Serge Vakulenko
e4e9ff1ef4 Ported mille game. 2014-09-08 19:19:18 -07:00
Serge Vakulenko
aecac2f5d7 Ported hangman. 2014-09-08 18:07:59 -07:00
Serge Vakulenko
8886a00340 Ported fortune. 2014-09-08 12:30:17 -07:00
Serge Vakulenko
25bcc79a69 Merge branch 'master' into games.
Conflicts:
	Makefile
2014-09-08 11:31:12 -07:00
Serge Vakulenko
8d55f87ab8 Fsutil: dynamically allocate data structure for file i/o. 2014-09-04 19:29:18 -07:00
Matt Jenkins
9adca14b87 Added hx8357 TFT driver for PICadillo 2014-08-30 21:17:16 +01:00
Matt Jenkins
83a999be0a Added definitions for picadillo, and spi sram device 2014-08-27 23:13:26 +01:00
Sergey
1462eeb400 Using manifest files to create root and user filesystems. 2014-08-03 15:53:53 -07:00
Serge Vakulenko
d42bfdc7b9 Fsutil: can read manifest files.
Added a manifest for root filesystem.
2014-08-01 21:23:38 -07:00
Serge Vakulenko
1cdf42ef94 Fsutil: inode API simplified. 2014-08-01 18:17:38 -07:00
Serge Vakulenko
8f4aad27f9 Fsutil: able to create filesystem contents from manifest. 2014-08-01 17:49:59 -07:00
Serge Vakulenko
cb4ca7f73a Fsutuil: move manifest routines to a separate file. 2014-08-01 14:29:22 -07:00
Serge Vakulenko
b44cab756f Fsutil: new option --scan to create manifest from directory contents. 2014-07-31 20:55:42 -07:00
Serge Vakulenko
c2b3647d5e Fsutil: sources reformatted to 4-space indents. 2014-07-31 18:37:15 -07:00
Serge Vakulenko
4d8233582a Fsutil: added --manifest option. 2014-07-31 18:16:39 -07:00
Serge Vakulenko
eb1fb36b6b Fsutil library: use names for inode ops. 2014-07-31 17:46:24 -07:00
Sergey
2293493bfd Fixed bugs in fsutil. 2014-07-20 17:23:57 -07:00
Sergey
61ce169328 Fsutil mount complete. 2014-07-20 16:57:36 -07:00
Sergey
173efb822d Fsutil mount: symlink() and readlink() calls completed. 2014-07-19 15:06:55 -07:00
Serge Vakulenko
21babaf947 Fsutil mount: added rename and mknod calls. 2014-07-18 19:07:51 -07:00
Serge Vakulenko
3a789348da Fsutol mount: fixed rmdir call. 2014-07-18 17:41:08 -07:00
Serge Vakulenko
d6e558bea0 Fsutil mount: added truncate, mkdir, rmdir, link and unlink calls. 2014-07-18 00:13:27 -07:00
Serge Vakulenko
847e2bff77 Fsutil: allow truncate to arbitrary length. 2014-07-17 21:31:49 -07:00
Serge Vakulenko
08c79d7fec Fsutil --mount can read and write files. 2014-07-17 20:16:25 -07:00
Serge Vakulenko
0cef044377 Fsutil: added option -m to mount the filesystem via FUSE. 2014-07-16 20:31:03 -07:00
Serge Vakulenko
61c7c690b9 Merge pull request #33 from ibara/master
Emg updated to version 1.7.
2014-07-11 12:17:26 -07:00
Brian Callahan
294ccae3be emg 1.7 2014-07-10 18:11:43 -04:00
Serge Vakulenko
1c4e562363 Added kernel configuration for PICadillo-35T board. 2014-06-23 22:15:51 -07:00
Serge Vakulenko
09b50bf614 Merge pull request #31 from ibara/master
Update emg man page.
2014-06-18 10:59:57 -07:00
Serge Vakulenko
8439672624 Merge pull request #32 from jturner/fix-build
Fix build after aout reorganization.
2014-06-18 10:58:32 -07:00
James Turner
b6e105c87b Fix build after aout reorganization 2014-06-18 13:45:24 -04:00
Brian Callahan
70b8d93b21 Update emg man page. 2014-06-17 08:43:13 -04:00
Serge Vakulenko
5fa78e772b Moved aout sources to separate directory.
Fsutil and modff license changed to BSD style.
2014-06-04 11:46:33 -07:00
Serge Vakulenko
7b1bf93d3a Merge pull request #30 from ibara/master
Changes for emg 1.6 merged.
2014-05-30 21:01:53 -07:00
Brian Callahan
04208ea903 Remove unusued variable... put this down and walk away until tomorrow. 2014-05-29 18:20:55 -04:00
Brian Callahan
e003436e91 Dumbest off-by-one ever... 2014-05-29 18:16:24 -04:00
Brian Callahan
29904aacd7 I should trust my instincts. I had this right the first time. 2014-05-29 18:03:39 -04:00
Brian Callahan
dbe51ae294 This is cleaner, prevent the percent from being greater than 100. 2014-05-29 15:06:16 -04:00
Brian Callahan
87489937bf Add PgUp and PgDn scrolling to emg, release this as emg 1.6
Make sure emg.keys is installed.
2014-05-29 14:31:58 -04:00
Brian Callahan
bbba8d6f95 Remove all hardcoded make commands, changing them to ${MAKE}.
This is a first step towards being able to build RetroBSD on *BSD.
2014-05-25 16:25:15 -04:00
Sergey
b3abe580bd Added emg editor from github.com/ibara/emg. 2014-05-24 19:37:02 -07:00
Serge Vakulenko
66ffc30ccd Kernel makefiles updated. 2014-05-23 11:33:58 -07:00
Serge Vakulenko
0b31486402 Added loadmax target to kernel Makefile.
Use "make loadmax" in sys/pic32/max32 directory to upload the kernel image
to chipKIT Max32 board.
2014-05-21 12:26:24 -07:00
Serge Vakulenko
5bd8f3a470 Fixed sd timeout in the simulator.
SD driver reformatted with 4 spaces per tab.
2014-05-16 20:44:53 -07:00
Serge Vakulenko
fa46b819f0 Merge branch 'master' of https://github.com/RetroBSD/retrobsd 2014-05-16 18:01:00 -07:00
Serge Vakulenko
91468f005f Fixed build and simulator configuration for Explorer1 board. 2014-05-16 17:59:53 -07:00
Serge Vakulenko
e2cb851fbf Merge pull request #28 from alexfru/master
Update cpp to pcc 1.0.0's cpp
2014-05-14 22:39:59 -07:00
Alexey Frunze
e725ab2b44 Update cpp to pcc 1.0.0's cpp
Update the preprocessor to fix some of its bugs.
2014-05-14 02:49:38 -07:00
Sergey
a0d4e7f517 Initialization of interrupt controller simplified.. 2014-05-12 23:52:09 -07:00
Serge Vakulenko
dc1a7a5f25 Merge pull request #27 from alexfru/master
C compiler improvements
2014-05-10 00:15:24 -07:00
Alexey Frunze
17f417f519 C compiler improvements
Fix malloc(0) issue (#26) in cpp.
Reduce cpp size and allow for larger inputs.
Clean up unused variables in Smaller C.
2014-05-09 23:53:52 -07:00
Sergey
8423492f33 More games ported: boggle, btlgammon, cribbage.
Simulator modified to allow CR in UART output.
2014-05-09 23:39:23 -07:00
Sergey
8e8fc70ed5 Merge branch 'games' of https://github.com/RetroBSD/retrobsd into games 2014-05-09 21:01:09 -07:00
Sergey
d8305bc374 Added words file - needed for games. 2014-05-09 21:00:43 -07:00
Serge Vakulenko
8871099aab Assembler modified to support local common blocks. 2014-05-08 20:00:57 -07:00
Serge Vakulenko
6a2230d867 Fixed couple of issues in assembler:
(1) incorrect opcodes for bnez and beqz instructions;
(2) macro li simplified when low part of constant is zero.
2014-05-08 19:11:19 -07:00
Serge Vakulenko
688209e604 Using gcc 4.8.1 instead of 4.7.2. 2014-05-08 13:06:26 -07:00
Serge Vakulenko
3942e87cd1 Compiled atc game. Fixed include file for curses library. 2014-04-23 20:02:02 -07:00
1083 changed files with 151396 additions and 12915 deletions

145
Makefile
View File

@@ -24,24 +24,23 @@ DUINOMITE = sys/pic32/duinomite/DUINOMITE
DUINOMITEUART = sys/pic32/duinomite-uart/DUINOMITE-UART
DUINOMITEE = sys/pic32/duinomite-e/DUINOMITE-E
DUINOMITEEUART = sys/pic32/duinomite-e-uart/DUINOMITE-E-UART
PINGUINO = sys/pic32/pinguino-micro/PINGUINO-MICRO
DIP = sys/pic32/dip/DIP
BAREMETAL = sys/pic32/baremetal/BAREMETAL
RETROONE = sys/pic32/retroone/RETROONE
FUBARINO = sys/pic32/fubarino/FUBARINO
FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC
RETROONE = sys/pic32/retroone/RETROONE
FUBARINO = sys/pic32/fubarino/FUBARINO
FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC
SDXL = sys/pic32/sdxl/SDXL
MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7
# Select target board
TARGET ?= $(MAX32)
# Filesystem and swap sizes.
FS_KBYTES = 102400
U_KBYTES = 102400
SWAP_KBYTES = 2048
FS_MBYTES = 100
U_MBYTES = 100
SWAP_MBYTES = 2
# Set this to the device name for your SD card. With this
# enabled you can use "make installfs" to copy the filesys.img
# enabled you can use "make installfs" to copy the sdcard.img
# to the SD card.
#SDCARD = /dev/sdb
@@ -60,68 +59,13 @@ TARGETDIR = $(shell dirname $(TARGET))
TARGETNAME = $(shell basename $(TARGET))
TOPSRC = $(shell pwd)
CONFIG = $(TOPSRC)/tools/configsys/config
#
# Filesystem contents.
#
BIN_FILES := $(wildcard bin/*)
SBIN_FILES := $(wildcard sbin/*)
GAMES_FILES := $(shell find games -type f ! -path '*/.*')
LIBEXEC_FILES := $(wildcard libexec/*)
LIB_FILES := lib/crt0.o lib/retroImage $(wildcard lib/*.a)
ETC_FILES = etc/rc etc/rc.local etc/ttys etc/gettytab etc/group \
etc/passwd etc/shadow etc/fstab etc/motd etc/shells \
etc/termcap etc/MAKEDEV etc/phones etc/remote
INC_FILES = $(wildcard include/*.h) \
$(wildcard include/sys/*.h) \
$(wildcard include/machine/*.h) \
$(wildcard include/smallc/*.h) \
$(wildcard include/smallc/sys/*.h) \
$(wildcard include/arpa/*.h)
SHARE_FILES = share/re.help share/example/Makefile \
share/example/ashello.S share/example/chello.c \
share/example/blkjack.bas share/example/hilow.bas \
share/example/stars.bas share/example/prime.scm \
share/example/fact.fth share/example/echo.S \
share/example/stdarg.c share/example/skeleton.c \
$(wildcard share/smallc/*)
MANFILES = share/man/ share/man/cat1/ share/man/cat2/ share/man/cat3/ \
share/man/cat4/ share/man/cat5/ share/man/cat6/ share/man/cat7/ \
share/man/cat8/ $(wildcard share/man/cat?/*)
ALLFILES = $(SBIN_FILES) $(ETC_FILES) $(BIN_FILES) $(LIB_FILES) $(LIBEXEC_FILES) \
$(INC_FILES) $(SHARE_FILES) $(GAMES_FILES) \
var/log/messages var/log/wtmp .profile
ALLDIRS = games/ sbin/ bin/ dev/ etc/ tmp/ lib/ libexec/ share/ include/ \
var/ u/ share/example/ share/misc/ share/smallc/ \
var/run/ var/log/ var/lock/ games/ games/lib/ include/sys/ \
include/machine/ include/arpa/ include/smallc/ \
include/smallc/sys/ share/misc/ share/smallc/ include/sys/ \
games/lib/
BDEVS = dev/rd0!b0:0 dev/rd0a!b0:1 dev/rd0b!b0:2 dev/rd0c!b0:3 dev/rd0d!b0:4
BDEVS += dev/rd1!b1:0 dev/rd1a!b1:1 dev/rd1b!b1:2 dev/rd1c!b1:3 dev/rd1d!b1:4
BDEVS += dev/rd2!b2:0 dev/rd2a!b2:1 dev/rd2b!b2:2 dev/rd2c!b2:3 dev/rd2d!b2:4
BDEVS += dev/rd3!b3:0 dev/rd3a!b3:1 dev/rd3b!b3:2 dev/rd3c!b3:3 dev/rd3d!b3:4
BDEVS += dev/swap!b4:64 dev/swap0!b4:0 dev/swap1!b4:1 dev/swap2!b4:2
D_CONSOLE = dev/console!c0:0
D_MEM = dev/mem!c1:0 dev/kmem!c1:1 dev/null!c1:2 dev/zero!c1:3
D_TTY = dev/tty!c2:0
D_FD = dev/stdin!c3:0 dev/stdout!c3:1 dev/stderr!c3:2
D_TEMP = dev/temp0!c4:0 dev/temp1!c4:1 dev/temp2!c4:2
U_DIRS = $(addsuffix /,$(shell find u -type d ! -path '*/.svn*'))
U_FILES = $(shell find u -type f ! -path '*/.svn/*')
#U_ALL = $(patsubst u/%,%,$(U_DIRS) $(U_FILES))
CDEVS = $(D_CONSOLE) $(D_MEM) $(D_TTY) $(D_FD) $(D_TEMP)
all: tools build kernel
$(MAKE) fs
fs: sdcard.rd
.PHONY: tools
tools:
all: .profile
$(MAKE) -C tools
$(MAKE) -C lib
$(MAKE) -C src install
$(MAKE) kernel
$(MAKE) fs
kernel: $(TARGETDIR)/Makefile
$(MAKE) -C $(TARGETDIR)
@@ -129,39 +73,14 @@ kernel: $(TARGETDIR)/Makefile
$(TARGETDIR)/Makefile: $(CONFIG) $(TARGETDIR)/$(TARGETNAME)
cd $(TARGETDIR) && ../../../tools/configsys/config $(TARGETNAME)
.PHONY: lib
lib:
$(MAKE) -C lib
fs: sdcard.img
build: tools lib
$(MAKE) -C src install
filesys.img: $(FSUTIL) $(ALLFILES)
.PHONY: sdcard.img
sdcard.img: $(FSUTIL) rootfs.manifest userfs.manifest
rm -f $@
$(FSUTIL) -n$(FS_KBYTES) $@
$(FSUTIL) -a $@ $(ALLDIRS)
$(FSUTIL) -a $@ $(CDEVS)
$(FSUTIL) -a $@ $(BDEVS)
$(FSUTIL) -a $@ $(ALLFILES)
$(FSUTIL) -a $@ $(MANFILES)
swap.img:
dd if=/dev/zero of=$@ bs=1k count=$(SWAP_KBYTES)
user.img: $(FSUTIL)
ifneq ($(U_KBYTES), 0)
rm -f $@
$(FSUTIL) -n$(U_KBYTES) $@
(cd u; find . -type d -exec ../$(FSUTIL) -a ../$@ '{}/' \;)
(cd u; find . -type f -exec ../$(FSUTIL) -a ../$@ '{}' \+)
endif
sdcard.rd: filesys.img swap.img user.img
ifneq ($(U_KBYTES), 0)
tools/mkrd/mkrd -out $@ -boot filesys.img -swap swap.img -fs user.img
else
tools/mkrd/mkrd -out $@ -boot filesys.img -swap swap.img
endif
$(FSUTIL) --repartition=fs=$(FS_MBYTES)M:swap=$(SWAP_MBYTES)M:fs=$(U_MBYTES)M $@
$(FSUTIL) --new --partition=1 --manifest=rootfs.manifest $@ .
$(FSUTIL) --new --partition=3 --manifest=userfs.manifest $@ u
$(FSUTIL):
cd tools/fsutil; $(MAKE)
@@ -175,32 +94,30 @@ clean:
cleanall: clean
$(MAKE) -C lib clean
rm -f sys/pic32/*/unix.hex bin/* sbin/* games/[a-k]* games/[m-z]* libexec/* share/man/cat*/*
rm -f games/lib/adventure.dat
rm -f games/lib/cfscores
rm -f share/re.help
rm -f share/misc/more.help
rm -f sys/pic32/*/unix.hex bin/* sbin/* libexec/*
rm -f games/[a-k]* games/[m-z]* share/man/cat*/*
rm -f games/lib/adventure.dat games/lib/cfscores
rm -f share/re.help share/emg.keys share/misc/more.help
rm -f etc/termcap etc/remote etc/phones
rm -rf share/unixbench
rm -f games/lib/adventure.dat games/lib/cfscores share/re.help share/misc/more.help etc/termcap
rm -f tools/configsys/.depend
rm -f var/log/aculog
rm -rf var/lock
rm -rf var/lock share/unixbench
installfs: filesys.img
installfs:
ifdef SDCARD
sudo dd bs=32k if=sdcard.rd of=$(SDCARD)
@[ -f sdcard.img ] || $(MAKE) sdcard.img
sudo dd bs=32k if=sdcard.img of=$(SDCARD)
else
@echo "Error: No SDCARD defined."
@echo "Error: No SDCARD defined."
endif
# TODO: make it relative to Target
installflash:
sudo pic32prog sys/pic32/fubarino/unix.hex
sudo pic32prog sys/pic32/fubarino/unix.hex
# TODO: make it relative to Target
installboot:
sudo pic32prog sys/pic32/fubarino/bootloader.hex
sudo pic32prog sys/pic32/fubarino/bootloader.hex
.profile: etc/root/dot.profile
.profile: etc/root/dot.profile
cp etc/root/dot.profile .profile

View File

@@ -27,6 +27,14 @@
## Build
To compile everything from sources, you'll need some packages installed, namely:
Berkeley YACC, GNU bison and flex, ELF library and FUSE library.
Under Ubuntu, for example, you can do it by command:
```shell
$ sudo apt-get install bison byacc flex libelf-dev libfuse-dev
```
By default, the system is configured for the Max32 board.
To select another target board, edit a top-level user-specific Makefile called "Makefile.user"
and set a TARGET value:
@@ -45,8 +53,6 @@ TARGET = $(DUINOMITE) # for the Duinomite board with USB console
TARGET = $(DUINOMITEUART) # for the Duinomite board with UART console
TARGET = $(DUINOMITEE) # for the Duinomite E board with USB console
TARGET = $(DUINOMITEEUART) # for the Duinomite E board with UART console
TARGET = $(PINGUINO) # for the Pinguino-Micro board
TARGET = $(DIP) # for the DIP board
TARGET = $(BAREMETAL) # Bare PIC32 chip on a breakout board
TARGET = $(FUBARINO) # Fubarino SD board
TARGET = $(FUBARINOBIG) # Fubarino SD board with 8MB SRAM RAMDISK
@@ -65,7 +71,7 @@ To compile the kernel and build a filesystem image, run:
$ make
```
A resulting root filesystem image is in file `sdcard.rd`.
A resulting root filesystem image is in file `sdcard.img`.
A kernel is in file `unix.hex` in your target board subdirectory.
@@ -76,7 +82,7 @@ Win32DiskImager utility (https://launchpad.net/win32-image-writer/+download).
On Linux, run:
```shell
$ sudo dd if=sdcard.rd of=/dev/XYZ
$ sudo dd if=sdcard.img of=/dev/XYZ
```
Here `XYZ` is a device name of SD card, as recognized by Linux (sdb in my case).
@@ -154,13 +160,3 @@ $ ./pic32
```
Configuration of simulated board is stored in file `pic32_max32.conf`.
## Build packages
For building under Ubuntu you need the following packages installed:
```shell
$ sudo apt-get install byacc libelf-dev
```

View File

@@ -1,7 +1,7 @@
DESTDIR = /usr/local/retrobsd
MACHINE = mips
CC = gcc
CC = gcc -m32
AS = $(CC) -x assembler-with-cpp
LD = ld

1
etc/.gitignore vendored
View File

@@ -1,3 +1,4 @@
phones
remote
termcap
termcap.full

View File

@@ -1,16 +1,16 @@
#
# name getty type status comments
#
console "/libexec/getty std.default" vt100 on secure #special
console "/libexec/getty std.default" xterm on secure #special
# Enable some of these for additional logins. Do NOT enable the same one as the
# console port, or strange things will happen. You can turn off the console port
# if you would rather use the getty on the real tty - it's up to you.
tty0 "/libexec/getty std.default" vt100 off secure
tty1 "/libexec/getty std.default" vt100 off secure
tty2 "/libexec/getty std.default" vt100 off secure
tty3 "/libexec/getty std.default" vt100 off secure
tty4 "/libexec/getty std.default" vt100 off secure
tty5 "/libexec/getty std.default" vt100 off secure
ttyUSB0 "/libexec/getty std.default" vt100 off secure
tty0 "/libexec/getty std.default" xterm off secure
tty1 "/libexec/getty std.default" xterm off secure
tty2 "/libexec/getty std.default" xterm off secure
tty3 "/libexec/getty std.default" xterm off secure
tty4 "/libexec/getty std.default" xterm off secure
tty5 "/libexec/getty std.default" xterm off secure
ttyUSB0 "/libexec/getty std.default" xterm off secure

View File

@@ -181,6 +181,10 @@ int waddstr (WINDOW *, char *);
int wgetstr (WINDOW *, char *);
int wdeleteln (WINDOW *);
void mvcur(int ly, int lx, int y, int x);
void overwrite(WINDOW *win1, WINDOW *win2);
void wclrtobot(WINDOW *win);
int mvprintw(int y, int x, char *fmt, ...);
int mvwprintw(WINDOW *win, int y, int x, char *fmt, ...);
/*
* Used to be in unctrl.h.

View File

@@ -24,8 +24,9 @@ AOUT_OBJS = aout.o mips-dis.o
RANLIB_OBJS = ranlib.o archive.o
HEADERS = a.out.h ar.h nlist.h ranlib.h
vpath %.c $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as $(TOPSRC)/src/cmd/ld \
$(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib $(TOPSRC)/src/cmd
vpath %.c $(TOPSRC)/src/cmd/aout $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as \
$(TOPSRC)/src/cmd/ld $(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib \
$(TOPSRC)/src/cmd
all install depend: $(HEADERS) $(SUBDIR) $(PROG)
-for i in $(SUBDIR); do $(MAKE) -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) $@; done

863
rootfs.manifest Normal file
View 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
View File

@@ -1,3 +1,4 @@
re.help
misc
unixbench
emg.keys

25486
share/dict/words Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
all: ashello echo chello
all: ashello echo chello stdarg skeleton
ashello: ashello.o
$(LD) ashello.o -o $@
@@ -10,5 +10,11 @@ chello: chello.o
echo: echo.o
$(LD) $@.o -o $@
stdarg: stdarg.o
$(CC) stdarg.o -o $@
skeleton: skeleton.o
$(CC) skeleton.o -o $@
clean:
rm -f *.o ashello echo chello *.dis *~
rm -f *.o ashello echo chello stdarg skeleton *.dis *~

View File

@@ -0,0 +1,3 @@
makewhatis.sed
man.template
whatis

View File

@@ -1,6 +1,4 @@
extern int printf();
int main()
main()
{
printf ("Hello, SmallC World!\n");
}

38
share/smallerc/Makefile Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1,6 @@
#include <stdio.h>
int main(void)
{
printf("Hello, Smaller C World!\n");
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

View File

@@ -9,7 +9,7 @@ include $(TOPSRC)/target.mk
# Programs that live in subdirectories, and have makefiles of their own.
#
SUBDIR = startup-$(MACHINE) libc libm libutil libtermlib libcurses \
libvmf libwiznet share cmd games
libvmf libwiznet share cmd games man
all: $(SUBDIR)

View File

@@ -10,9 +10,9 @@ CFLAGS += -Werror
# Programs that live in subdirectories, and have makefiles of their own.
# /bin
SUBDIR = adb adc-demo ar as awk basic cc chflags chpass \
cpp dc diff env fdisk find forth fstat glcdtest hostname \
id la lcc lcpp ld ls login make man med \
SUBDIR = adb adc-demo aout ar as awk basic cc chflags chpass \
cpp dc diff emg env fdisk find forth fstat glcdtest \
hostname id la lcc lcpp ld levee ls login make man med \
more nm passwd picoc portio printf pwm \
rdprof ranlib re renice retroforth scm setty sl \
sed sh smallc smlrc stty sysctl test uname wiznet xargs \

1
src/cmd/aout/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
aout

25
src/cmd/aout/Makefile Normal file
View 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/

View File

@@ -1,6 +1,5 @@
#
# as - Assembler
# aout - Display information from a.out files
#
TOPSRC = $(shell cd ../../..; pwd)
include $(TOPSRC)/target.mk
@@ -9,9 +8,7 @@ include $(TOPSRC)/target.mk
CFLAGS += -Werror -Wall -Os
LDFLAGS +=
AOUTOBJS = aout.o mips-dis.o
all: as aout
all: as
as: as.o
${CC} ${LDFLAGS} -o as.elf as.o ${LIBS}
@@ -19,26 +16,8 @@ as: as.o
${SIZE} as.elf
${ELF2AOUT} as.elf $@ && rm as.elf
aout: $(AOUTOBJS)
${CC} ${LDFLAGS} -o aout.elf $(AOUTOBJS) ${LIBS}
${OBJDUMP} -S aout.elf > aout.dis
${SIZE} aout.elf
${ELF2AOUT} aout.elf $@ && rm aout.elf
clean:
rm -f *.o *.0 *.elf as aout tags *~ *.dis tests/*.dis tests/*.gcc-dis tests/*.o
test:
/usr/local/pic32-tools/bin/pic32-as -al example.s
rm -f *.o *.0 *.elf as tags *~ *.dis tests/*.dis tests/*.gcc-dis tests/*.o
install: all
install as $(DESTDIR)/bin/
install aout $(DESTDIR)/bin/
test.dis-gcc: test.s
$(AS) $< -o test.o
${OBJDUMP} -D test.o > $@
test.dis: test.s as aout
./as $< -o test.o
./aout test.o > $@

View File

@@ -216,7 +216,8 @@ const struct optable optable [] = {
{ 0x04110000, "bal", FAOFF18 | FDSLOT },
{ 0x10000000, "beq", FRS1 | FRT2 | FOFF18 | FDSLOT },
{ 0x50000000, "beql", FRS1 | FRT2 | FOFF18 | FDSLOT },
{ 0x50000000, "beqz", FRS1 | FOFF18 | FDSLOT },
{ 0x10000000, "beqz", FRS1 | FOFF18 | FDSLOT },
{ 0x50000000, "beqzl", FRS1 | FOFF18 | FDSLOT },
{ 0x04010000, "bgez", FRS1 | FOFF18 | FDSLOT },
{ 0x04110000, "bgezal", FRS1 | FOFF18 | FDSLOT },
{ 0x04130000, "bgezall", FRS1 | FOFF18 | FDSLOT },
@@ -231,7 +232,8 @@ const struct optable optable [] = {
{ 0x04020000, "bltzl", FRS1 | FOFF18 | FDSLOT },
{ 0x14000000, "bne", FRS1 | FRT2 | FOFF18 | FDSLOT },
{ 0x54000000, "bnel", FRS1 | FRT2 | FOFF18 | FDSLOT },
{ 0x54000000, "bnez", FRS1 | FOFF18 | FDSLOT },
{ 0x14000000, "bnez", FRS1 | FOFF18 | FDSLOT },
{ 0x54000000, "bnezl", FRS1 | FOFF18 | FDSLOT },
{ 0x0000000d, "break", FCODE16 },
{ 0x70000021, "clo", FRD1 | FRS2 | FRTD | FMOD },
{ 0x70000020, "clz", FRD1 | FRS2 | FRTD | FMOD },
@@ -1271,6 +1273,9 @@ void emit_li (opcode, relinfo)
} else if (value >= -0x8000) {
/* addiu d, $zero, value */
opcode |= 0x24000000 | (value & 0xffff);
} else if ((value & 0xffff) == 0) {
/* lui d, value[31:16] */
opcode |= 0x3c000000 | (value >> 16);
} else {
/* lui d, value[31:16]
* ori d, d, value[15:0]) */
@@ -1627,6 +1632,9 @@ foff16: expr_flags = 0;
} else if (offset >= -0x8000) {
/* addiu $1, $zero, value */
emitword (0x24010000 | (offset & 0xffff), &relabs, 1);
} else if ((offset & 0xffff) == 0) {
/* lui $1, value[31:16] */
emitword (0x3c010000 | (offset >> 16), &relabs, 1);
} else {
/* lui $1, value[31:16]
* ori $1, $1, value[15:0]) */
@@ -2158,7 +2166,7 @@ void pass1 ()
}
break;
case LCOMM:
/* .comm name,len */
/* .comm name,len[,alignment] */
if (getlex (&cval) != LNAME)
uerror ("bad parameter of .comm");
cval = lookname();
@@ -2369,18 +2377,28 @@ int findlabel (int addr, int sym)
void middle ()
{
register int i, snum;
register int i, snum, nbytes;
stlength = 0;
for (snum=0, i=0; i<stabfree; i++) {
/* Without -u option, undefined symbol is considered external */
if (stab[i].n_type == N_UNDF) {
switch (stab[i].n_type) {
case N_UNDF:
/* Without -u option, undefined symbol is considered external */
if (uflag)
uerror ("name undefined", stab[i].n_name);
stab[i].n_type |= N_EXT;
break;
case N_COMM:
/* Allocate a local common block */
nbytes = stab[i].n_value;
stab[i].n_value = count[SBSS];
stab[i].n_type = N_BSS;
count[SBSS] += nbytes;
break;
}
if (xflags)
newindex[i] = snum;
if (! xflags || (stab[i].n_type & N_EXT) ||
(Xflag && ! IS_LOCAL(&stab[i])))
{

View File

@@ -3,14 +3,15 @@ include $(TOPSRC)/target.mk
#include $(TOPSRC)/cross.mk
#CFLAGS = -DCROSS
OBJS = cpp.o cpy.o token.o
OBJS = cpp.o cpy.o token.o compat.o doprnt.o
MAN = cpp.0
MANSRC = cpp.1
LDFLAGS += -g
CFLAGS += -Werror -Wall -Os
CFLAGS += -DCPP_DEBUG -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC
#CFLAGS += -DCPP_DEBUG -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC
CFLAGS += -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC
all: cpp $(MAN)
@@ -30,7 +31,7 @@ install: all
install cpp $(DESTDIR)/bin/
cp cpp.0 $(DESTDIR)/share/man/cat1/
cpp.o: cpp.c y.tab.h
cpp.o: cpp.c cpp.h y.tab.h config.h
.l.o:
$(LEX) $(LFLAGS) $<
@@ -61,3 +62,9 @@ test:
cmp tests/run9 tests/res9
./cpp < tests/test10 > tests/run10
cmp tests/run10 tests/res10
./cpp < tests/test11 > tests/run11
cmp tests/run11 tests/res11
./cpp < tests/test12 > tests/run12
cmp tests/run12 tests/res12
./cpp < tests/test13 > tests/run13
cmp tests/run13 tests/res13

91
src/cmd/cpp/compat.c Normal file
View 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
View 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
View 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__

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
/* $Id: cpp.h,v 1.47.2.1 2011/02/26 06:36:40 ragge Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
* Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,8 +12,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -24,25 +24,15 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef CROSS
# include </usr/include/stdio.h>
# include </usr/include/ctype.h>
#else
# include <stdio.h> /* for obuf */
# include <ctype.h>
#endif
#include <stdio.h> /* for obuf */
#include <stdlib.h>
/* Version string */
#define VERSSTR "cpp for RetroBSD"
#include "config.h"
typedef unsigned char uchar;
#ifdef YYTEXT_POINTER
extern char *yytext;
#else
extern char yytext[];
#endif
extern uchar *stringbuf;
typedef unsigned char usch;
extern usch yytext[];
extern usch *stringbuf;
extern int trulvl;
extern int flslvl;
@@ -50,7 +40,7 @@ extern int elflvl;
extern int elslvl;
extern int tflag, Cflag, Pflag;
extern int Mflag, dMflag;
extern uchar *Mfile;
extern usch *Mfile;
extern int ofd;
/* args for lookup() */
@@ -58,32 +48,77 @@ extern int ofd;
#define ENTER 1
/* buffer used internally */
#define CPPBUF 512
#define CPPBUF 512
#ifndef CPPBUF
#if defined(__pdp11__)
#define CPPBUF BUFSIZ
#define BUF_STACK
#elif defined(WIN32)
/* winxp seems to fail > 26608 bytes */
#define CPPBUF 16384
#else
#define CPPBUF (65536*2)
#endif
#endif
#define MAXARGS 20//128 /* Max # of args to a macro. Should be enouth */
#define NAMEMAX CPPBUF /* currently pushbackbuffer */
#define BBUFSZ (NAMEMAX+CPPBUF+1)
#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */
#define VARG 0xfe /* has varargs */
#define OBJCT 0xff
#define WARN 1 /* SOH, not legal char */
#define CONC 2 /* STX, not legal char */
#define SNUFF 3 /* ETX, not legal char */
#define EBLOCK 4 /* EOT, not legal char */
/* Used in macro expansion */
#define RECMAX 400//10000 /* max # of recursive macros */
extern struct symtab *norep[RECMAX];
extern int norepptr;
extern unsigned short bptr[RECMAX];
extern int bidx;
#define MKB(l,h) (l+((h)<<8))
/* quick checks for some characters */
#define C_SPEC 001
#define C_EP 002
#define C_ID 004
#define C_I (C_SPEC|C_ID)
#define C_2 010 /* for yylex() tokenizing */
#define C_WSNL 020 /* ' ','\t','\r','\n' */
#define iswsnl(x) (spechr[x] & C_WSNL)
extern char spechr[];
/* definition for include file info */
struct includ {
struct includ *next;
const uchar *fname; /* current fn, changed if #line found */
const uchar *orgfn; /* current fn, not changed */
const usch *fname; /* current fn, changed if #line found */
const usch *orgfn; /* current fn, not changed */
int lineno;
int infil;
uchar *curptr;
uchar *maxread;
uchar *ostr;
uchar *buffer;
usch *curptr;
usch *maxread;
usch *ostr;
usch *buffer;
int idx;
void *incs;
const uchar *fn;
uchar bbuf[NAMEMAX+CPPBUF+1];
} *ifiles;
const usch *fn;
#ifdef BUF_STACK
usch bbuf[BBUFSZ];
#else
usch *bbuf;
#endif
};
extern struct includ *ifiles;
/* Symbol table entry */
struct symtab {
const uchar *namep;
const uchar *value;
const uchar *file;
const usch *namep;
const usch *value;
const usch *file;
int line;
};
@@ -110,13 +145,15 @@ struct nd {
#define nd_val n.val
#define nd_uval n.uval
struct recur; /* not used outside cpp.c */
int subst(struct symtab *, struct recur *);
struct symtab *lookup(const uchar *namep, int enterf);
uchar *gotident(struct symtab *nl);
int slow; /* scan slowly for new tokens */
struct symtab *lookup(const usch *namep, int enterf);
usch *gotident(struct symtab *nl);
extern int slow; /* scan slowly for new tokens */
int submac(struct symtab *nl, int);
int kfind(struct symtab *nl);
int doexp(void);
int donex(void);
int pushfile(const uchar *fname, const uchar *fn, int idx, void *incs);
int pushfile(const usch *fname, const usch *fn, int idx, void *incs);
void popfile(void);
void prtline(void);
int yylex(void);
@@ -128,18 +165,22 @@ void setline(int);
void setfile(char *);
int yyparse(void);
void yyerror(const char *);
void unpstr(const uchar *);
uchar *savstr(const uchar *str);
void unpstr(const usch *);
usch *savstr(const usch *str);
void savch(int c);
void mainscan(void);
void putch(int);
void putstr(const uchar *s);
void putstr(const usch *s);
void line(void);
uchar *sheap(const char *fmt, ...);
void xwarning(uchar *);
void xerror(uchar *);
#define warning(args...) xwarning(sheap(args))
#define error(args...) xerror(sheap(args))
void expmac(struct recur *);
usch *sheap(const char *fmt, ...);
void xwarning(usch *);
void xerror(usch *);
#ifdef HAVE_CPP_VARARG_MACRO_GCC
#define warning(...) xwarning(sheap(__VA_ARGS__))
#define error(...) xerror(sheap(__VA_ARGS__))
#else
#define warning printf
#define error printf
#endif
int cinput(void);
void getcmnt(void);

View File

@@ -1,3 +1,5 @@
/* $Id: cpy.y,v 1.18 2010/02/25 15:49:00 ragge Exp $ */
/*
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
* All rights reserved.
@@ -58,6 +60,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
%{
#include "cpp.h"

203
src/cmd/cpp/doprnt.c Normal file
View File

@@ -0,0 +1,203 @@
/*
Copyright (c) 2013, Alexey Frunze
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
int _doprnt (char const *fmt, va_list pp, FILE *stream)
{
int cnt = 0;
const char* p;
const char* phex = "0123456789abcdef";
char s[1/*sign*/+10/*magnitude*/+1/*\0*/]; // up to 11 octal digits in 32-bit numbers
char* pc;
int n, sign, msign;
int minlen = 0, len;
int leadchar;
for (p = fmt; *p != '\0'; p++)
{
if (*p != '%' || p[1] == '%')
{
fputc(*p, stream);
p = p + (*p == '%');
cnt++;
continue;
}
p++;
minlen = 0;
msign = 0;
if (*p == '+') { msign = 1; p++; }
else if (*p == '-') { msign = -1; p++; }
leadchar = ' ';
if (*p >= '0' && *p <= '9')
{
if (*p == '0')
leadchar = '0';
while (*p >= '0' && *p <= '9')
minlen = minlen * 10 + *p++ - '0';
if (msign < 0)
minlen = -minlen;
msign = 0;
}
if (!msign)
{
if (*p == '+') { msign = 1; p++; }
else if (*p == '-') { msign = -1; p++; }
}
switch (*p)
{
case 'c':
while (minlen > 1) { fputc(' ', stream); cnt++; minlen--; }
fputc(va_arg(pp, int), stream);
while (-minlen > 1) { fputc(' ', stream); cnt++; minlen++; }
cnt++;
break;
case 's':
pc = va_arg(pp, char*);
len = 0;
if (pc)
len = strlen(pc);
while (minlen > len) { fputc(' ', stream); cnt++; minlen--; }
if (len)
while (*pc != '\0')
{
fputc(*pc++, stream);
cnt++;
}
while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; }
break;
case 'i':
case 'd':
pc = &s[sizeof s - 1];
*pc = '\0';
len = 0;
n = va_arg(pp, int);
sign = 1 - 2 * (n < 0);
do
{
*--pc = '0' + (n - n / 10 * 10) * sign;
n = n / 10;
len++;
} while (n);
if (sign < 0)
{
*--pc = '-';
len++;
}
else if (msign > 0)
{
*--pc = '+';
len++;
msign = 0;
}
while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; }
while (*pc != '\0')
{
fputc(*pc++, stream);
cnt++;
}
while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; }
break;
case 'u':
pc = &s[sizeof s - 1];
*pc = '\0';
len = 0;
n = va_arg(pp, int);
do
{
unsigned nn = n;
*--pc = '0' + nn % 10;
n = nn / 10;
len++;
} while (n);
if (msign > 0)
{
*--pc = '+';
len++;
msign = 0;
}
while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; }
while (*pc != '\0')
{
fputc(*pc++, stream);
cnt++;
}
while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; }
break;
case 'X':
phex = "0123456789ABCDEF";
// fallthrough
case 'p':
case 'x':
pc = &s[sizeof s - 1];
*pc = '\0';
len = 0;
n = va_arg(pp, int);
do
{
*--pc = phex[n & 0xF];
n = (n >> 4) & ((1 << (8 * sizeof n - 4)) - 1); // drop sign-extended bits
len++;
} while (n);
while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; }
while (*pc != '\0')
{
fputc(*pc++, stream);
cnt++;
}
while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; }
break;
case 'o':
pc = &s[sizeof s - 1];
*pc = '\0';
len = 0;
n = va_arg(pp, int);
do
{
*--pc = '0' + (n & 7);
n = (n >> 3) & ((1 << (8 * sizeof n - 3)) - 1); // drop sign-extended bits
len++;
} while (n);
while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; }
while (*pc != '\0')
{
fputc(*pc++, stream);
cnt++;
}
while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; }
break;
default:
return -1;
}
}
return cnt;
}

939
src/cmd/cpp/scanner.l Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1,13 @@
# 1 "<stdin>"
long

View File

@@ -15,7 +15,8 @@
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) &
f(2 * (0,1))^m(0,1);
int i[] = { 1, 23, 4, 5, };
char c[2][6] = { "hello", "" };

20
src/cmd/cpp/tests/test11 Normal file
View 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
View 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
View 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 */

View File

@@ -1,3 +1,5 @@
/* $Id: token.c,v 1.48.2.2 2011/03/12 17:08:26 ragge Exp $ */
/*
* Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
*
@@ -37,21 +39,24 @@
* - inch() is like inpch but \\n and trigraphs are expanded.
* - unch() pushes back a character to the input stream.
*/
#ifdef CROSS
# include </usr/include/string.h>
#else
# include <string.h>
#endif
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include "compat.h"
#include "cpp.h"
#include "y.tab.h"
static void cvtdig(int rad);
static int charcon(uchar *);
static int charcon(usch *);
static void elsestmt(void);
static void ifdefstmt(void);
static void ifndefstmt(void);
@@ -75,9 +80,8 @@ extern void yyset_lineno (int);
static int inch(void);
size_t strlcat(char *dst, const char *src, size_t siz);
int inif;
extern int dflag;
#define PUTCH(ch) if (!flslvl) putch(ch)
/* protection against recursion in #include */
@@ -87,25 +91,16 @@ static int inclevel;
/* get next character unaltered */
#define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
#ifdef YYTEXT_POINTER
static char buf[CPPBUF];
char *yytext = buf;
#else
char yytext[CPPBUF];
#endif
usch yytext[CPPBUF];
#define C_SPEC 1
#define C_EP 2
#define C_ID 4
#define C_I (C_SPEC|C_ID)
#define C_2 8 /* for yylex() tokenizing */
static const char spechr[256] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, C_SPEC, 0, 0, 0, 0, 0,
char spechr[256] = {
0, 0, 0, 0, C_SPEC, C_SPEC, 0, 0,
0, C_WSNL, C_SPEC|C_WSNL, 0,
0, C_WSNL, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC,
C_WSNL, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC,
0, 0, 0, C_2, 0, C_2, 0, C_SPEC|C_2,
C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I,
C_I, C_I, 0, 0, C_2, C_2, C_2, C_SPEC,
@@ -122,14 +117,55 @@ static const char spechr[256] = {
};
/*
* No-replacement array. If a macro is found and exists in this array
* then no replacement shall occur. This is a stack.
*/
struct symtab *norep[RECMAX]; /* Symbol table index table */
int norepptr = 1; /* Top of index table */
unsigned short bptr[RECMAX]; /* currently active noexpand macro stack */
int bidx; /* Top of bptr stack */
static void
unch(int c)
{
--ifiles->curptr;
if (ifiles->curptr < ifiles->bbuf)
error("pushback buffer full");
*ifiles->curptr = (uchar)c;
*ifiles->curptr = (usch)c;
}
static int
eatcmnt(void)
{
int ch;
if (Cflag) { PUTCH('/'); PUTCH('*'); }
for (;;) {
ch = inch();
if (ch == '\n') {
ifiles->lineno++;
PUTCH('\n');
}
if (ch == -1)
return -1;
if (ch == '*') {
ch = inch();
if (ch == '/') {
if (Cflag) {
PUTCH('*');
PUTCH('/');
} else
PUTCH(' ');
break;
}
unch(ch);
ch = '*';
}
if (Cflag) PUTCH(ch);
}
return 0;
}
/*
@@ -146,51 +182,38 @@ static void
fastscan(void)
{
struct symtab *nl;
int ch, i;
int ch, i, ccnt/*, onemore*/;
usch *cp;
goto run;
for (;;) {
ch = NXTCH();
xloop: if (ch == -1)
return;
if (dflag>1)
printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
if ((spechr[ch] & C_SPEC) == 0) {
PUTCH(ch);
continue;
}
switch (ch) {
case EBLOCK:
case WARN:
case CONC:
error("bad char passed");
break;
case '/': /* Comments */
if ((ch = inch()) == '/') {
if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
cppcmt: if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
do {
if (Cflag) PUTCH(ch);
ch = inch();
} while (ch != -1 && ch != '\n');
goto xloop;
} else if (ch == '*') {
if (Cflag) { PUTCH('/'); PUTCH('*'); }
for (;;) {
ch = inch();
if (ch == '\n') {
ifiles->lineno++;
PUTCH('\n');
}
if (ch == -1)
return;
if (ch == '*') {
ch = inch();
if (ch == '/') {
if (Cflag) {
PUTCH('*');
PUTCH('/');
} else
PUTCH(' ');
break;
}
unch(ch);
ch = '*';
}
if (Cflag) PUTCH(ch);
}
if (eatcmnt())
return;
} else {
PUTCH('/');
goto xloop;
@@ -213,11 +236,30 @@ xloop: if (ch == -1)
goto xloop;
case '\n': /* newlines, for pp directives */
ifiles->lineno++;
run2: ifiles->lineno++;
do {
PUTCH(ch);
run: ch = NXTCH();
if (ch == '/') {
ch = NXTCH();
if (ch == '/')
goto cppcmt;
if (ch == '*') {
if (eatcmnt())
return;
goto run;
}
unch(ch);
ch = '/';
}
} while (ch == ' ' || ch == '\t');
if (ch == '\\') {
ch = NXTCH();
if (ch == '\n')
goto run2;
unch(ch);
ch = '\\';
}
if (ch == '#') {
ppdir();
continue;
@@ -236,7 +278,7 @@ run: ch = NXTCH();
case '\"': /* strings */
str: PUTCH(ch);
while ((ch = inch()) != '\"') {
PUTCH(ch);
PUTCH(ch);
if (ch == '\\') {
ch = inch();
PUTCH(ch);
@@ -257,7 +299,16 @@ str: PUTCH(ch);
case '5': case '6': case '7': case '8': case '9':
do {
PUTCH(ch);
ch = NXTCH();
nxt: ch = NXTCH();
if (ch == '\\') {
ch = NXTCH();
if (ch == '\n') {
goto nxt;
} else {
unch(ch);
ch = '\\';
}
}
if (spechr[ch] & C_EP) {
PUTCH(ch);
ch = NXTCH();
@@ -305,9 +356,9 @@ con: PUTCH(ch);
ch = NXTCH();
goto xloop;
}
i = 0;
/*onemore =*/ i = ccnt = 0;
do {
yytext[i++] = (uchar)ch;
yytext[i++] = (usch)ch;
ch = NXTCH();
if (ch == '\\') {
ch = NXTCH();
@@ -322,14 +373,17 @@ con: PUTCH(ch);
if (ch < 0)
return;
} while (spechr[ch] & C_ID);
yytext[i] = 0;
unch(ch);
if ((nl = lookup((uchar *)yytext, FIND)) != 0) {
uchar *op = stringbuf;
putstr(gotident(nl));
stringbuf = op;
cp = stringbuf;
if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
putstr(stringbuf);
} else
putstr((uchar *)yytext);
putstr((usch *)yytext);
stringbuf = cp;
break;
}
}
@@ -344,7 +398,7 @@ sloscan()
zagain:
yyp = 0;
ch = inch();
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
switch (ch) {
case -1:
return 0;
@@ -357,24 +411,24 @@ zagain:
yyp = 0;
break;
case '0': case '1': case '2': case '3': case '4': case '5':
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
/* readin a "pp-number" */
ppnum: for (;;) {
ch = inch();
if (spechr[ch] & C_EP) {
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
ch = inch();
if (ch == '-' || ch == '+') {
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
} else
unch(ch);
continue;
}
if ((spechr[ch] & C_ID) || ch == '.') {
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
continue;
}
}
break;
}
unch(ch);
@@ -383,11 +437,11 @@ ppnum: for (;;) {
return NUMBER;
case '\'':
chlit:
chlit:
for (;;) {
if ((ch = inch()) == '\\') {
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (uchar)inch();
yytext[yyp++] = (usch)ch;
yytext[yyp++] = (usch)inch();
continue;
} else if (ch == '\n') {
/* not a constant */
@@ -396,7 +450,7 @@ chlit:
ch = '\'';
goto any;
} else
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
if (ch == '\'')
break;
}
@@ -407,7 +461,7 @@ chlit:
case ' ':
case '\t':
while ((ch = inch()) == ' ' || ch == '\t')
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
unch(ch);
yytext[yyp] = 0;
return(WSPACE);
@@ -415,7 +469,7 @@ chlit:
case '/':
if ((ch = inch()) == '/') {
do {
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
ch = inch();
} while (ch && ch != '\n');
yytext[yyp] = 0;
@@ -435,7 +489,10 @@ chlit:
more: while ((c = inch()) && c != '*') {
if (c == '\n')
putch(c), ifiles->lineno++;
else if (c == 1) /* WARN */
else if (c == EBLOCK) {
(void)inch();
(void)inch();
} else if (c == 1) /* WARN */
wrn = 1;
}
if (c == 0)
@@ -459,7 +516,7 @@ chlit:
case '.':
ch = inch();
if (isdigit(ch)) {
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
goto ppnum;
} else {
unch(ch);
@@ -468,14 +525,16 @@ chlit:
goto any;
case '\"':
if (tflag)
goto any;
strng:
for (;;) {
if ((ch = inch()) == '\\') {
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (uchar)inch();
yytext[yyp++] = (usch)ch;
yytext[yyp++] = (usch)inch();
continue;
} else
yytext[yyp++] = (uchar)ch;
} else
yytext[yyp++] = (usch)ch;
if (ch == '\"')
break;
}
@@ -483,26 +542,26 @@ chlit:
return(STRING);
case 'L':
if ((ch = inch()) == '\"') {
yytext[yyp++] = (uchar)ch;
if ((ch = inch()) == '\"' && !tflag) {
yytext[yyp++] = (usch)ch;
goto strng;
} else if (ch == '\'') {
yytext[yyp++] = (uchar)ch;
} else if (ch == '\'' && !tflag) {
yytext[yyp++] = (usch)ch;
goto chlit;
}
unch(ch);
/* FALLTHROUGH */
/* Yetch, all identifiers */
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K':
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z':
case '_': /* {L}({L}|{D})* */
@@ -510,7 +569,7 @@ chlit:
for (;;) { /* get chars */
ch = inch();
if (isalpha(ch) || isdigit(ch) || ch == '_') {
yytext[yyp++] = (uchar)ch;
yytext[yyp++] = (usch)ch;
} else {
unch(ch);
break;
@@ -584,27 +643,31 @@ yylex()
case NUMBER:
if (yytext[0] == '\'') {
yylval.node.op = NUMBER;
yylval.node.nd_val = charcon((uchar *)yytext);
yylval.node.nd_val = charcon((usch *)yytext);
} else
cvtdig(yytext[0] != '0' ? 10 :
yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
return NUMBER;
case IDENT:
if (strcmp(yytext, "defined") == 0) {
if (strcmp((char *)yytext, "defined") == 0) {
ifdef = 1;
return DEFINED;
}
nl = lookup((uchar *)yytext, FIND);
nl = lookup((usch *)yytext, FIND);
if (ifdef) {
yylval.node.nd_val = nl != NULL;
ifdef = 0;
} else if (nl && noex == 0) {
uchar *c, *och = stringbuf;
usch *och = stringbuf;
int i;
c = gotident(nl);
unch(1);
unpstr(c);
i = kfind(nl);
unch(WARN);
if (i)
unpstr(stringbuf);
else
unpstr(nl->namep);
stringbuf = och;
noex = 1;
return yylex();
@@ -613,7 +676,7 @@ yylex()
}
yylval.node.op = NUMBER;
return NUMBER;
case 1: /* WARN */
case WARN:
noex = 0;
return yylex();
default:
@@ -623,7 +686,7 @@ yylex()
return ch;
}
uchar *yyp, yybuf[CPPBUF];
usch *yyp, yybuf[CPPBUF];
int yywrap(void);
@@ -671,41 +734,6 @@ msdos: if ((c = inpch()) == '\n') {
}
}
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(initial dst) + strlen(src); if retval >= siz,
* truncation occurred.
*/
size_t
strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
/*
* Let the command-line args be faked defines at beginning of file.
*/
@@ -754,30 +782,29 @@ prinit(struct initar *it, struct includ *ic)
* Return 0 on success, -1 if file to be included is not found.
*/
int
pushfile(const uchar *file, const uchar *fn, int idx, void *incs)
pushfile(const usch *file, const usch *fn, int idx, void *incs)
{
extern struct initar *initar;
struct includ ibuf;
struct includ *ic;
int otrulvl;
ic = malloc(sizeof(struct includ));
if (ic == NULL)
error("out of memory for %s", file);
ic = &ibuf;
ic->next = ifiles;
if (file != NULL) {
ic->infil = open((const char *)file, O_RDONLY);
if (ic->infil < 0) {
free(ic);
if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
return -1;
}
ic->orgfn = ic->fname = file;
if (++inclevel > MAX_INCLEVEL)
error("Limit for nested includes exceeded");
} else {
ic->infil = 0;
ic->orgfn = ic->fname = (const uchar *)"<stdin>";
ic->orgfn = ic->fname = (const usch *)"<stdin>";
}
#ifndef BUF_STACK
ic->bbuf = malloc(BBUFSZ);
#endif
ic->buffer = ic->bbuf+NAMEMAX;
ic->curptr = ic->buffer;
ifiles = ic;
@@ -794,8 +821,7 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs)
prinit(initar, ic);
initar = NULL;
if (dMflag)
if (write(ofd, ic->buffer, strlen((char *)ic->buffer)) < 0)
/* ignore */;
write(ofd, ic->buffer, strlen((char *)ic->buffer));
fastscan();
prtline();
ic->infil = oin;
@@ -808,9 +834,11 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs)
if (otrulvl != trulvl || flslvl)
error("unterminated conditional");
#ifndef BUF_STACK
free(ic->bbuf);
#endif
ifiles = ic->next;
close(ic->infil);
free(ic);
inclevel--;
return 0;
}
@@ -821,15 +849,14 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs)
void
prtline()
{
uchar *s, *os = stringbuf;
usch *s, *os = stringbuf;
if (Mflag) {
if (dMflag)
return; /* no output */
if (ifiles->lineno == 1) {
s = sheap("%s: %s\n", Mfile, ifiles->fname);
if (write(ofd, s, strlen((char *)s)) < 0)
/* ignore */;
write(ofd, s, strlen((char *)s));
}
} else if (!Pflag)
putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
@@ -840,8 +867,8 @@ void
cunput(int c)
{
#ifdef CPP_DEBUG
extern int dflag;
if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c);
// extern int dflag;
// if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
#endif
#if 0
if (c == 10) {
@@ -873,7 +900,7 @@ cvtdig(int rad)
{
unsigned long long rv = 0;
unsigned long long rv2 = 0;
char *y = yytext;
usch *y = yytext;
int c;
c = *y++;
@@ -900,7 +927,7 @@ cvtdig(int rad)
}
static int
charcon(uchar *p)
charcon(usch *p)
{
int val, c;
@@ -993,8 +1020,8 @@ skpln(void)
}
static void
ifdefstmt(void)
{
ifdefstmt(void)
{
int t;
if (flslvl) {
@@ -1006,7 +1033,7 @@ ifdefstmt(void)
while (t == WSPACE);
if (t != IDENT)
error("bad ifdef");
if (lookup((uchar *)yytext, FIND) == 0) {
if (lookup((usch *)yytext, FIND) == 0) {
putch('\n');
flslvl++;
} else
@@ -1015,8 +1042,8 @@ ifdefstmt(void)
}
static void
ifndefstmt(void)
{
ifndefstmt(void)
{
int t;
if (flslvl) {
@@ -1028,7 +1055,7 @@ ifndefstmt(void)
while (t == WSPACE);
if (t != IDENT)
error("bad ifndef");
if (lookup((uchar *)yytext, FIND) != 0) {
if (lookup((usch *)yytext, FIND) != 0) {
putch('\n');
flslvl++;
} else
@@ -1037,7 +1064,7 @@ ifndefstmt(void)
}
static void
endifstmt(void)
endifstmt(void)
{
if (flslvl) {
flslvl--;
@@ -1094,11 +1121,11 @@ elifstmt(void)
error("If-less elif");
}
static uchar *
static usch *
svinp(void)
{
int c;
uchar *cp = stringbuf;
usch *cp = stringbuf;
while ((c = inch()) && c != '\n')
savch(c);
@@ -1110,7 +1137,7 @@ svinp(void)
static void
cpperror(void)
{
uchar *cp;
usch *cp;
int c;
if (flslvl)
@@ -1128,7 +1155,7 @@ cpperror(void)
static void
cppwarning(void)
{
uchar *cp;
usch *cp;
int c;
if (flslvl)
@@ -1158,7 +1185,7 @@ undefstmt(void)
if (sloscan() != WSPACE || sloscan() != IDENT)
error("bad undef");
if (flslvl == 0 && (np = lookup((uchar *)yytext, FIND)))
if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
np->value = 0;
chknl(0);
}
@@ -1171,7 +1198,7 @@ pragmastmt(void)
if (sloscan() != WSPACE)
error("bad pragma");
if (!flslvl)
putstr((const uchar *)"#pragma ");
putstr((const usch *)"\n#pragma ");
do {
c = inch();
if (!flslvl)
@@ -1265,7 +1292,7 @@ ppdir(void)
goto out; /* something else, ignore */
i = 0;
do {
bp[i++] = (uchar)ch;
bp[i++] = (usch)ch;
if (i == sizeof(bp)-1)
goto out; /* too long */
ch = inch();

1
src/cmd/emg/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
emg

53
src/cmd/emg/ChangeLog Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

67
src/cmd/emg/ebind.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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(&region)) != 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(&region)) != 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
View 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
View 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
View 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
View 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
View 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);
}

View File

@@ -32,7 +32,7 @@ depend: ${SRCS}
install: all
install -m 755 $(BIN) ${DESTDIR}/sbin
install -m 755 $(MAN) ${DESTDIR}/share/man/cat8
cp $(MAN) ${DESTDIR}/share/man/cat8
lint: ${SRCS}
lint -hax ${SRCS}

1
src/cmd/levee/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
lv

56
src/cmd/levee/Makefile Normal file
View 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

View 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
View 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
View File

@@ -0,0 +1 @@
3.5a

48
src/cmd/levee/beep.c Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

112
src/cmd/levee/configure.sh Executable file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

237
src/cmd/levee/extern.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

Some files were not shown because too many files have changed in this diff Show More