Compare commits
131 Commits
dual_sramc
...
levee-edit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f33305f894 | ||
|
|
e834303650 | ||
|
|
476573dae6 | ||
|
|
8e2c046406 | ||
|
|
dad5247184 | ||
|
|
b1f67fbca0 | ||
|
|
f76ab8417c | ||
|
|
3bb914c8b4 | ||
|
|
8b099bcf76 | ||
|
|
2fc41d34cf | ||
|
|
2301571ecb | ||
|
|
00269e9387 | ||
|
|
687695d0db | ||
|
|
0aa5e1c462 | ||
|
|
3a7cde7974 | ||
|
|
f57cc446b0 | ||
|
|
1a55933faf | ||
|
|
b18ce0aa87 | ||
|
|
5bbf8d4e73 | ||
|
|
7aa774702b | ||
|
|
64430a0f91 | ||
|
|
d5e30d7b79 | ||
|
|
a8d9b3d01f | ||
|
|
ebd35d772f | ||
|
|
c4da2137e1 | ||
|
|
c42133cdff | ||
|
|
dc66e6fdda | ||
|
|
f58c7a7426 | ||
|
|
5c4309942a | ||
|
|
e557c88b1e | ||
|
|
850797db2e | ||
|
|
cae7db41ca | ||
|
|
808dfaf6ef | ||
|
|
d3d48970e3 | ||
|
|
93d95abc69 | ||
|
|
c5ac22d17f | ||
|
|
e7b77dadc3 | ||
|
|
2ea9e02ba5 | ||
|
|
d9d91365c0 | ||
|
|
2da083e9bd | ||
|
|
e4e9ff1ef4 | ||
|
|
aecac2f5d7 | ||
|
|
8886a00340 | ||
|
|
25bcc79a69 | ||
|
|
8d55f87ab8 | ||
|
|
9adca14b87 | ||
|
|
83a999be0a | ||
|
|
1462eeb400 | ||
|
|
d42bfdc7b9 | ||
|
|
1cdf42ef94 | ||
|
|
8f4aad27f9 | ||
|
|
cb4ca7f73a | ||
|
|
b44cab756f | ||
|
|
c2b3647d5e | ||
|
|
4d8233582a | ||
|
|
eb1fb36b6b | ||
|
|
2293493bfd | ||
|
|
61ce169328 | ||
|
|
173efb822d | ||
|
|
21babaf947 | ||
|
|
3a789348da | ||
|
|
d6e558bea0 | ||
|
|
847e2bff77 | ||
|
|
08c79d7fec | ||
|
|
0cef044377 | ||
|
|
61c7c690b9 | ||
|
|
294ccae3be | ||
|
|
1c4e562363 | ||
|
|
09b50bf614 | ||
|
|
8439672624 | ||
|
|
b6e105c87b | ||
|
|
70b8d93b21 | ||
|
|
5fa78e772b | ||
|
|
7b1bf93d3a | ||
|
|
04208ea903 | ||
|
|
e003436e91 | ||
|
|
29904aacd7 | ||
|
|
dbe51ae294 | ||
|
|
87489937bf | ||
|
|
bbba8d6f95 | ||
|
|
b3abe580bd | ||
|
|
66ffc30ccd | ||
|
|
0b31486402 | ||
|
|
5bd8f3a470 | ||
|
|
fa46b819f0 | ||
|
|
91468f005f | ||
|
|
e2cb851fbf | ||
|
|
e725ab2b44 | ||
|
|
a0d4e7f517 | ||
|
|
dc1a7a5f25 | ||
|
|
17f417f519 | ||
|
|
8423492f33 | ||
|
|
8e8fc70ed5 | ||
|
|
d8305bc374 | ||
|
|
8871099aab | ||
|
|
6a2230d867 | ||
|
|
688209e604 | ||
|
|
b238afb5b9 | ||
|
|
bca48c9a66 | ||
|
|
2395d5a9fa | ||
|
|
60c7fe0fd3 | ||
|
|
4be5e54c38 | ||
|
|
5e58ad0f3d | ||
|
|
6ccaa1a940 | ||
|
|
3c025a1e89 | ||
|
|
cdf8933448 | ||
|
|
058804256a | ||
|
|
a0d072f271 | ||
|
|
f40da13b35 | ||
|
|
19cf54c0c1 | ||
|
|
ed92365a4c | ||
|
|
a433085324 | ||
|
|
f39a1429bf | ||
|
|
06d027b4c5 | ||
|
|
6f47acb2ae | ||
|
|
a2bc88bdb6 | ||
|
|
e0ba612250 | ||
|
|
babef284ae | ||
|
|
51a8fd3313 | ||
|
|
f67b9db8b5 | ||
|
|
777ad1471b | ||
|
|
aff46df8dd | ||
|
|
6f15f0ba23 | ||
|
|
6f8e71c1b8 | ||
|
|
f105cb5bbd | ||
|
|
037fc65e93 | ||
|
|
ce1f5ce4dc | ||
|
|
b652f52cb6 | ||
|
|
b98de3368e | ||
|
|
3a38f291a7 | ||
|
|
3942e87cd1 |
148
Makefile
148
Makefile
@@ -24,24 +24,23 @@ DUINOMITE = sys/pic32/duinomite/DUINOMITE
|
||||
DUINOMITEUART = sys/pic32/duinomite-uart/DUINOMITE-UART
|
||||
DUINOMITEE = sys/pic32/duinomite-e/DUINOMITE-E
|
||||
DUINOMITEEUART = sys/pic32/duinomite-e-uart/DUINOMITE-E-UART
|
||||
PINGUINO = sys/pic32/pinguino-micro/PINGUINO-MICRO
|
||||
DIP = sys/pic32/dip/DIP
|
||||
BAREMETAL = sys/pic32/baremetal/BAREMETAL
|
||||
RETROONE = sys/pic32/retroone/RETROONE
|
||||
FUBARINO = sys/pic32/fubarino/FUBARINO
|
||||
FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC
|
||||
RETROONE = sys/pic32/retroone/RETROONE
|
||||
FUBARINO = sys/pic32/fubarino/FUBARINO
|
||||
FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC
|
||||
SDXL = sys/pic32/sdxl/SDXL
|
||||
MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7
|
||||
|
||||
# Select target board
|
||||
TARGET ?= $(MAX32)
|
||||
|
||||
# Filesystem and swap sizes.
|
||||
FS_KBYTES = 102400
|
||||
U_KBYTES = 102400
|
||||
SWAP_KBYTES = 2048
|
||||
FS_MBYTES = 100
|
||||
U_MBYTES = 100
|
||||
SWAP_MBYTES = 2
|
||||
|
||||
# Set this to the device name for your SD card. With this
|
||||
# enabled you can use "make installfs" to copy the filesys.img
|
||||
# enabled you can use "make installfs" to copy the sdcard.img
|
||||
# to the SD card.
|
||||
|
||||
#SDCARD = /dev/sdb
|
||||
@@ -60,67 +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 \
|
||||
$(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)
|
||||
@@ -128,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)
|
||||
@@ -174,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
|
||||
installflash:
|
||||
sudo pic32prog sys/pic32/fubarino/unix.hex
|
||||
|
||||
# TODO: make it relative to Target
|
||||
installboot:
|
||||
sudo pic32prog sys/pic32/fubarino/bootloader.hex
|
||||
installboot:
|
||||
sudo pic32prog sys/pic32/fubarino/bootloader.hex
|
||||
|
||||
.profile: etc/root/dot.profile
|
||||
.profile: etc/root/dot.profile
|
||||
cp etc/root/dot.profile .profile
|
||||
|
||||
24
README.md
24
README.md
@@ -27,6 +27,14 @@
|
||||
|
||||
## Build
|
||||
|
||||
To compile everything from sources, you'll need some packages installed, namely:
|
||||
Berkeley YACC, GNU bison and flex, ELF library and FUSE library.
|
||||
Under Ubuntu, for example, you can do it by command:
|
||||
|
||||
```shell
|
||||
$ sudo apt-get install bison byacc flex libelf-dev libfuse-dev
|
||||
```
|
||||
|
||||
By default, the system is configured for the Max32 board.
|
||||
To select another target board, edit a top-level user-specific Makefile called "Makefile.user"
|
||||
and set a TARGET value:
|
||||
@@ -45,8 +53,6 @@ TARGET = $(DUINOMITE) # for the Duinomite board with USB console
|
||||
TARGET = $(DUINOMITEUART) # for the Duinomite board with UART console
|
||||
TARGET = $(DUINOMITEE) # for the Duinomite E board with USB console
|
||||
TARGET = $(DUINOMITEEUART) # for the Duinomite E board with UART console
|
||||
TARGET = $(PINGUINO) # for the Pinguino-Micro board
|
||||
TARGET = $(DIP) # for the DIP board
|
||||
TARGET = $(BAREMETAL) # Bare PIC32 chip on a breakout board
|
||||
TARGET = $(FUBARINO) # Fubarino SD board
|
||||
TARGET = $(FUBARINOBIG) # Fubarino SD board with 8MB SRAM RAMDISK
|
||||
@@ -65,7 +71,7 @@ To compile the kernel and build a filesystem image, run:
|
||||
$ make
|
||||
```
|
||||
|
||||
A resulting root filesystem image is in file `sdcard.rd`.
|
||||
A resulting root filesystem image is in file `sdcard.img`.
|
||||
A kernel is in file `unix.hex` in your target board subdirectory.
|
||||
|
||||
|
||||
@@ -76,7 +82,7 @@ Win32DiskImager utility (https://launchpad.net/win32-image-writer/+download).
|
||||
On Linux, run:
|
||||
|
||||
```shell
|
||||
$ sudo dd if=sdcard.rd of=/dev/XYZ
|
||||
$ sudo dd if=sdcard.img of=/dev/XYZ
|
||||
```
|
||||
|
||||
Here `XYZ` is a device name of SD card, as recognized by Linux (sdb in my case).
|
||||
@@ -154,13 +160,3 @@ $ ./pic32
|
||||
```
|
||||
|
||||
Configuration of simulated board is stored in file `pic32_max32.conf`.
|
||||
|
||||
## Build packages
|
||||
|
||||
|
||||
For building under Ubuntu you need the following packages installed:
|
||||
|
||||
```shell
|
||||
$ sudo apt-get install byacc libelf-dev
|
||||
```
|
||||
|
||||
|
||||
2
cross.mk
2
cross.mk
@@ -1,7 +1,7 @@
|
||||
DESTDIR = /usr/local/retrobsd
|
||||
MACHINE = mips
|
||||
|
||||
CC = gcc
|
||||
CC = gcc -m32
|
||||
|
||||
AS = $(CC) -x assembler-with-cpp
|
||||
LD = ld
|
||||
|
||||
1
etc/.gitignore
vendored
1
etc/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
phones
|
||||
remote
|
||||
termcap
|
||||
termcap.full
|
||||
|
||||
16
etc/ttys
16
etc/ttys
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# name getty type status comments
|
||||
#
|
||||
console "/libexec/getty std.default" vt100 on secure #special
|
||||
console "/libexec/getty std.default" xterm on secure #special
|
||||
|
||||
# Enable some of these for additional logins. Do NOT enable the same one as the
|
||||
# console port, or strange things will happen. You can turn off the console port
|
||||
# if you would rather use the getty on the real tty - it's up to you.
|
||||
|
||||
tty0 "/libexec/getty std.default" vt100 off secure
|
||||
tty1 "/libexec/getty std.default" vt100 off secure
|
||||
tty2 "/libexec/getty std.default" vt100 off secure
|
||||
tty3 "/libexec/getty std.default" vt100 off secure
|
||||
tty4 "/libexec/getty std.default" vt100 off secure
|
||||
tty5 "/libexec/getty std.default" vt100 off secure
|
||||
ttyUSB0 "/libexec/getty std.default" vt100 off secure
|
||||
tty0 "/libexec/getty std.default" xterm off secure
|
||||
tty1 "/libexec/getty std.default" xterm off secure
|
||||
tty2 "/libexec/getty std.default" xterm off secure
|
||||
tty3 "/libexec/getty std.default" xterm off secure
|
||||
tty4 "/libexec/getty std.default" xterm off secure
|
||||
tty5 "/libexec/getty std.default" xterm off secure
|
||||
ttyUSB0 "/libexec/getty std.default" xterm off secure
|
||||
|
||||
@@ -33,29 +33,7 @@
|
||||
#ifndef _AOUT_H_
|
||||
#define _AOUT_H_
|
||||
|
||||
#include <sys/exec.h>
|
||||
|
||||
/* Valid magic number check. */
|
||||
#define N_BADMAG(x) (((x).a_magic) != RMAGIC && \
|
||||
((x).a_magic) != OMAGIC && \
|
||||
((x).a_magic) != NMAGIC)
|
||||
|
||||
/* Text segment offset. */
|
||||
#define N_TXTOFF(x) sizeof(struct exec)
|
||||
|
||||
/* Data segment offset. */
|
||||
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
|
||||
|
||||
/* Text relocation table offset. */
|
||||
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
|
||||
|
||||
/* Data relocation table offset. */
|
||||
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_reltext)
|
||||
|
||||
/* Symbol table offset. */
|
||||
#define N_SYMOFF(x) ((x).a_magic == RMAGIC ? \
|
||||
N_DRELOFF(x) + (x).a_reldata : \
|
||||
N_DATOFF(x) + (x).a_data)
|
||||
#include <sys/exec_aout.h>
|
||||
|
||||
#define _AOUT_INCLUDE_
|
||||
#include <nlist.h>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -4,32 +4,49 @@
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
/* Define __gnuc_va_list. */
|
||||
/*
|
||||
* Define va_start, va_arg, va_end, va_copy.
|
||||
*/
|
||||
#if defined(__GNUC__) /* Gnu C */
|
||||
# define va_start(ap, last) __builtin_va_start((ap), last)
|
||||
# define va_arg(ap, type) __builtin_va_arg((ap), type)
|
||||
# define va_end(ap) __builtin_va_end((ap))
|
||||
# define va_copy(dest, src) __builtin_va_copy((dest), (src))
|
||||
|
||||
#elif defined(__PCC__) /* PCC */
|
||||
# define va_start(ap, last) __builtin_stdarg_start((ap), last)
|
||||
# define va_arg(ap, type) __builtin_va_arg((ap), type)
|
||||
# define va_end(ap) __builtin_va_end((ap))
|
||||
# define va_copy(dest, src) __builtin_va_copy((dest), (src))
|
||||
|
||||
#ifdef __GNUC__
|
||||
# ifndef __GNUC_VA_LIST
|
||||
# define __GNUC_VA_LIST
|
||||
typedef __builtin_va_list __gnuc_va_list;
|
||||
# endif
|
||||
# define va_start(ap, last) __builtin_va_start((ap), last)
|
||||
#else /* SmallerC, LCC */
|
||||
# define va_start(ap, last) (ap = ((char*)&(last) + \
|
||||
(((sizeof(last) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))))
|
||||
# define va_arg(ap, type) ((type*)(ap += \
|
||||
sizeof(type) == sizeof(int) ? sizeof(type) : \
|
||||
(-(int)(ap) & (sizeof(type) - 1)) + sizeof(type)))[-1]
|
||||
# define va_end(ap)
|
||||
# define va_copy(dest, src) (dest = (src))
|
||||
#endif
|
||||
#ifdef __PCC__
|
||||
# define va_start(ap, last) __builtin_stdarg_start((ap), last)
|
||||
#endif
|
||||
#define va_arg(ap, type) __builtin_va_arg((ap), type)
|
||||
#define va_end(ap) __builtin_va_end((ap))
|
||||
#define va_copy(dest, src) __builtin_va_copy((dest), (src))
|
||||
|
||||
|
||||
/*
|
||||
* Define va_list.
|
||||
*/
|
||||
#ifndef _VA_LIST_T
|
||||
#define _VA_LIST_T
|
||||
#ifdef __GNUC__
|
||||
# define _VA_LIST_T
|
||||
# if defined(__GNUC__) || defined(__PCC__)
|
||||
typedef __builtin_va_list va_list;
|
||||
# else
|
||||
typedef char *va_list;
|
||||
# endif
|
||||
#endif
|
||||
#ifdef __SMALLER_C__
|
||||
typedef int *va_list;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define __gnuc_va_list.
|
||||
*/
|
||||
#if defined(__GNUC__) && !defined(__GNUC_VA_LIST)
|
||||
# define __GNUC_VA_LIST
|
||||
typedef __builtin_va_list __gnuc_va_list;
|
||||
#endif
|
||||
|
||||
#endif /* not _STDARG_H */
|
||||
|
||||
@@ -110,7 +110,12 @@ int scanf (const char *, ...);
|
||||
int sscanf (const char *, const char *, ...);
|
||||
|
||||
#ifndef _VA_LIST_
|
||||
#define va_list __builtin_va_list /* For GCC */
|
||||
# ifdef __GNUC__
|
||||
# define va_list __builtin_va_list /* For Gnu C */
|
||||
# endif
|
||||
# ifdef __SMALLER_C__
|
||||
# define va_list char * /* For Smaller C */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
int vfprintf (FILE *, const char *, va_list);
|
||||
@@ -126,7 +131,7 @@ int _doprnt (const char *, va_list, FILE *);
|
||||
int _doscan (FILE *, const char *, va_list);
|
||||
|
||||
#ifndef _VA_LIST_
|
||||
#undef va_list
|
||||
# undef va_list
|
||||
#endif
|
||||
|
||||
void perror (const char *);
|
||||
|
||||
@@ -54,49 +54,51 @@
|
||||
|
||||
#define RAND_MAX 0x7fff
|
||||
|
||||
void abort();
|
||||
void abort (void);
|
||||
int abs (int);
|
||||
int atexit (void (*)(void));
|
||||
double atof();
|
||||
int atoi();
|
||||
long atol();
|
||||
int atoi (const char *);
|
||||
long atol (const char *);
|
||||
void *calloc (size_t, size_t);
|
||||
void exit (int);
|
||||
void free (void *);
|
||||
char *getenv();
|
||||
char *getenv (const char *);
|
||||
long labs (long);
|
||||
void *malloc (size_t);
|
||||
char *mktemp (char *);
|
||||
int mkstemp (char *);
|
||||
void qsort();
|
||||
int rand();
|
||||
void qsort (void *, size_t, size_t, int (*)(const void *, const void *));
|
||||
int rand (void);
|
||||
void *realloc (void*, size_t);
|
||||
void srand();
|
||||
double strtod();
|
||||
long strtol();
|
||||
unsigned long strtoul();
|
||||
int system();
|
||||
void srand (unsigned);
|
||||
long strtol (const char *, char **, int);
|
||||
unsigned long strtoul (const char *, char **, int);
|
||||
int system (const char *);
|
||||
|
||||
int putenv (char *string);
|
||||
int setenv (const char *name, const char *value, int overwrite);
|
||||
int unsetenv (const char *name);
|
||||
char *_findenv (const char *name, int *offset);
|
||||
|
||||
void *alloca();
|
||||
void *alloca (size_t size);
|
||||
|
||||
int daemon();
|
||||
char *devname();
|
||||
int getloadavg(unsigned loadavg[], int nelem);
|
||||
int daemon (int, int);
|
||||
char *devname (dev_t dev, mode_t type);
|
||||
int getloadavg (unsigned loadavg[], int nelem);
|
||||
|
||||
extern char *suboptarg; /* getsubopt(3) external variable */
|
||||
int getsubopt();
|
||||
int getsubopt (char **, char **, char **);
|
||||
|
||||
long random (void);
|
||||
char *setstate (char *);
|
||||
void srandom (unsigned);
|
||||
|
||||
char *ecvt (double, int, int *, int *);
|
||||
char *fcvt (double, int, int *, int *);
|
||||
char *gcvt (double, int, char *);
|
||||
#ifndef __SMALLER_C__
|
||||
double atof (const char *);
|
||||
double strtod (const char *, char **);
|
||||
char *ecvt (double, int, int *, int *);
|
||||
char *fcvt (double, int, int *, int *);
|
||||
char *gcvt (double, int, char *);
|
||||
#endif
|
||||
|
||||
#endif /* _STDLIB_H_ */
|
||||
|
||||
@@ -143,7 +143,12 @@ extern char *optarg; /* getopt(3) external variables */
|
||||
extern int opterr, optind, optopt;
|
||||
|
||||
#ifndef _VA_LIST_
|
||||
#define va_list __builtin_va_list /* For GCC */
|
||||
# ifdef __GNUC__
|
||||
# define va_list __builtin_va_list /* For Gnu C */
|
||||
# endif
|
||||
# ifdef __SMALLER_C__
|
||||
# define va_list char * /* For Smaller C */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void err (int eval, const char *fmt, ...);
|
||||
@@ -156,6 +161,6 @@ void vwarn (const char *fmt, va_list ap);
|
||||
void vwarnx (const char *fmt, va_list ap);
|
||||
|
||||
#ifndef _VA_LIST_
|
||||
#undef va_list
|
||||
# undef va_list
|
||||
#endif
|
||||
#endif /* !_UNISTD_H_ */
|
||||
|
||||
1
lib/.gitignore
vendored
1
lib/.gitignore
vendored
@@ -11,3 +11,4 @@ ranlib.h
|
||||
retroImage
|
||||
size
|
||||
strip
|
||||
gccdump.s
|
||||
|
||||
@@ -24,8 +24,9 @@ AOUT_OBJS = aout.o mips-dis.o
|
||||
RANLIB_OBJS = ranlib.o archive.o
|
||||
HEADERS = a.out.h ar.h nlist.h ranlib.h
|
||||
|
||||
vpath %.c $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as $(TOPSRC)/src/cmd/ld \
|
||||
$(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib $(TOPSRC)/src/cmd
|
||||
vpath %.c $(TOPSRC)/src/cmd/aout $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as \
|
||||
$(TOPSRC)/src/cmd/ld $(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib \
|
||||
$(TOPSRC)/src/cmd
|
||||
|
||||
all install depend: $(HEADERS) $(SUBDIR) $(PROG)
|
||||
-for i in $(SUBDIR); do $(MAKE) -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) $@; done
|
||||
|
||||
863
rootfs.manifest
Normal file
863
rootfs.manifest
Normal file
@@ -0,0 +1,863 @@
|
||||
#
|
||||
# Manifest file for RetroBSD root filesystem.
|
||||
#
|
||||
default
|
||||
owner 0
|
||||
group 0
|
||||
dirmode 0775
|
||||
filemode 0664
|
||||
|
||||
#
|
||||
# Directories.
|
||||
#
|
||||
dir /bin
|
||||
dir /dev
|
||||
dir /etc
|
||||
dir /lib
|
||||
dir /libexec
|
||||
dir /sbin
|
||||
dir /tmp
|
||||
dir /u
|
||||
|
||||
#
|
||||
# Character devices.
|
||||
#
|
||||
cdev /dev/console
|
||||
major 0
|
||||
minor 0
|
||||
cdev /dev/mem
|
||||
major 1
|
||||
minor 0
|
||||
cdev /dev/kmem
|
||||
major 1
|
||||
minor 1
|
||||
cdev /dev/null
|
||||
major 1
|
||||
minor 2
|
||||
mode 666
|
||||
cdev /dev/zero
|
||||
major 1
|
||||
minor 3
|
||||
mode 666
|
||||
cdev /dev/tty
|
||||
major 2
|
||||
minor 0
|
||||
mode 666
|
||||
cdev /dev/stdin
|
||||
major 3
|
||||
minor 0
|
||||
cdev /dev/stdout
|
||||
major 3
|
||||
minor 1
|
||||
cdev /dev/stderr
|
||||
major 3
|
||||
minor 2
|
||||
cdev /dev/temp0
|
||||
major 4
|
||||
minor 0
|
||||
cdev /dev/temp1
|
||||
major 4
|
||||
minor 1
|
||||
cdev /dev/temp2
|
||||
major 4
|
||||
minor 2
|
||||
|
||||
#
|
||||
# Block devices.
|
||||
#
|
||||
bdev /dev/rd0
|
||||
major 0
|
||||
minor 0
|
||||
bdev /dev/rd0a
|
||||
major 0
|
||||
minor 1
|
||||
bdev /dev/rd0b
|
||||
major 0
|
||||
minor 2
|
||||
bdev /dev/rd0c
|
||||
major 0
|
||||
minor 3
|
||||
bdev /dev/rd0d
|
||||
major 0
|
||||
minor 4
|
||||
bdev /dev/rd1
|
||||
major 1
|
||||
minor 0
|
||||
bdev /dev/rd1a
|
||||
major 1
|
||||
minor 1
|
||||
bdev /dev/rd1b
|
||||
major 1
|
||||
minor 2
|
||||
bdev /dev/rd1c
|
||||
major 1
|
||||
minor 3
|
||||
bdev /dev/rd1d
|
||||
major 1
|
||||
minor 4
|
||||
bdev /dev/rd2
|
||||
major 2
|
||||
minor 0
|
||||
bdev /dev/rd2a
|
||||
major 2
|
||||
minor 1
|
||||
bdev /dev/rd2b
|
||||
major 2
|
||||
minor 2
|
||||
bdev /dev/rd2c
|
||||
major 2
|
||||
minor 3
|
||||
bdev /dev/rd2d
|
||||
major 2
|
||||
minor 4
|
||||
bdev /dev/rd3
|
||||
major 3
|
||||
minor 0
|
||||
bdev /dev/rd3a
|
||||
major 3
|
||||
minor 1
|
||||
bdev /dev/rd3b
|
||||
major 3
|
||||
minor 2
|
||||
bdev /dev/rd3c
|
||||
major 3
|
||||
minor 3
|
||||
bdev /dev/rd3d
|
||||
major 3
|
||||
minor 4
|
||||
bdev /dev/swap
|
||||
major 4
|
||||
minor 64
|
||||
bdev /dev/swap0
|
||||
major 4
|
||||
minor 0
|
||||
bdev /dev/swap1
|
||||
major 4
|
||||
minor 1
|
||||
bdev /dev/swap2
|
||||
major 4
|
||||
minor 2
|
||||
|
||||
#
|
||||
# Files: /
|
||||
#
|
||||
file /.profile
|
||||
|
||||
#
|
||||
# Files: /etc
|
||||
#
|
||||
file /etc/fstab
|
||||
file /etc/gettytab
|
||||
file /etc/group
|
||||
file /etc/MAKEDEV
|
||||
mode 0775
|
||||
file /etc/motd
|
||||
file /etc/passwd
|
||||
file /etc/phones
|
||||
file /etc/rc
|
||||
mode 0775
|
||||
file /etc/rc.local
|
||||
mode 0775
|
||||
file /etc/remote
|
||||
file /etc/shadow
|
||||
file /etc/shells
|
||||
file /etc/termcap
|
||||
mode 0444
|
||||
file /etc/ttys
|
||||
|
||||
#
|
||||
# Files: /bin
|
||||
#
|
||||
default
|
||||
filemode 0775
|
||||
file /bin/adb
|
||||
file /bin/adc-demo
|
||||
file /bin/aout
|
||||
file /bin/apropos
|
||||
file /bin/ar
|
||||
file /bin/as
|
||||
file /bin/awk
|
||||
file /bin/basename
|
||||
file /bin/basic
|
||||
file /bin/bc
|
||||
file /bin/cal
|
||||
file /bin/cat
|
||||
file /bin/cb
|
||||
file /bin/cc
|
||||
file /bin/chat-server
|
||||
file /bin/chflags
|
||||
file /bin/chgrp
|
||||
file /bin/chmod
|
||||
file /bin/chpass
|
||||
mode 04755
|
||||
file /bin/cmp
|
||||
file /bin/col
|
||||
file /bin/comm
|
||||
file /bin/compress
|
||||
file /bin/cp
|
||||
file /bin/cpp
|
||||
file /bin/crontab
|
||||
file /bin/date
|
||||
file /bin/dc
|
||||
file /bin/dd
|
||||
file /bin/df
|
||||
mode 02755
|
||||
file /bin/diff
|
||||
file /bin/du
|
||||
file /bin/echo
|
||||
file /bin/ed
|
||||
file /bin/egrep
|
||||
file /bin/emg
|
||||
file /bin/env
|
||||
file /bin/expr
|
||||
file /bin/false
|
||||
file /bin/fgrep
|
||||
file /bin/file
|
||||
file /bin/find
|
||||
file /bin/forth
|
||||
file /bin/fstat
|
||||
mode 02755
|
||||
file /bin/glcdtest
|
||||
file /bin/globdump
|
||||
file /bin/globread
|
||||
file /bin/globwrite
|
||||
file /bin/grep
|
||||
file /bin/groups
|
||||
file /bin/head
|
||||
file /bin/hostid
|
||||
file /bin/hostname
|
||||
file /bin/id
|
||||
file /bin/iostat
|
||||
mode 02755
|
||||
file /bin/join
|
||||
file /bin/kill
|
||||
file /bin/la
|
||||
file /bin/last
|
||||
file /bin/lcc
|
||||
file /bin/lcpp
|
||||
file /bin/ld
|
||||
file /bin/ln
|
||||
file /bin/login
|
||||
mode 04755
|
||||
file /bin/lol
|
||||
file /bin/ls
|
||||
file /bin/lv
|
||||
file /bin/mail
|
||||
mode 04755
|
||||
file /bin/make
|
||||
file /bin/man
|
||||
file /bin/med
|
||||
file /bin/mesg
|
||||
file /bin/mkdir
|
||||
file /bin/more
|
||||
file /bin/msec
|
||||
file /bin/mv
|
||||
file /bin/nice
|
||||
file /bin/nm
|
||||
file /bin/nohup
|
||||
file /bin/ntpdate
|
||||
file /bin/od
|
||||
file /bin/pagesize
|
||||
file /bin/passwd
|
||||
mode 04755
|
||||
file /bin/picoc
|
||||
file /bin/portio
|
||||
file /bin/pr
|
||||
file /bin/printenv
|
||||
file /bin/printf
|
||||
file /bin/ps
|
||||
mode 02755
|
||||
file /bin/pwd
|
||||
file /bin/pwm
|
||||
file /bin/ranlib
|
||||
file /bin/re
|
||||
file /bin/renice
|
||||
file /bin/renumber
|
||||
file /bin/retroforth
|
||||
file /bin/rev
|
||||
file /bin/rm
|
||||
file /bin/rmail
|
||||
file /bin/rmdir
|
||||
file /bin/rz
|
||||
file /bin/scc
|
||||
file /bin/scm
|
||||
file /bin/sed
|
||||
file /bin/setty
|
||||
file /bin/sh
|
||||
file /bin/size
|
||||
file /bin/sl
|
||||
file /bin/sleep
|
||||
file /bin/smux
|
||||
file /bin/sort
|
||||
file /bin/split
|
||||
file /bin/strip
|
||||
file /bin/stty
|
||||
file /bin/su
|
||||
mode 04755
|
||||
file /bin/sum
|
||||
file /bin/sync
|
||||
file /bin/sysctl
|
||||
file /bin/sz
|
||||
file /bin/tail
|
||||
file /bin/tar
|
||||
file /bin/tee
|
||||
file /bin/telnet
|
||||
file /bin/test
|
||||
file /bin/time
|
||||
file /bin/tip
|
||||
file /bin/touch
|
||||
file /bin/tr
|
||||
file /bin/true
|
||||
file /bin/tsort
|
||||
file /bin/tty
|
||||
file /bin/uname
|
||||
file /bin/uncompress
|
||||
file /bin/uniq
|
||||
file /bin/uucico
|
||||
file /bin/uuclean
|
||||
file /bin/uucp
|
||||
file /bin/uudecode
|
||||
file /bin/uuencode
|
||||
file /bin/uulog
|
||||
file /bin/uuname
|
||||
file /bin/uupoll
|
||||
file /bin/uuq
|
||||
file /bin/uusend
|
||||
file /bin/uusnap
|
||||
file /bin/uux
|
||||
file /bin/uuxqt
|
||||
file /bin/vi
|
||||
file /bin/vmstat
|
||||
mode 02755
|
||||
file /bin/w
|
||||
file /bin/wall
|
||||
mode 02755
|
||||
file /bin/wc
|
||||
file /bin/web-client
|
||||
file /bin/web-server
|
||||
file /bin/whereis
|
||||
file /bin/who
|
||||
file /bin/whoami
|
||||
file /bin/write
|
||||
mode 02755
|
||||
file /bin/xargs
|
||||
file /bin/zcat
|
||||
|
||||
link /bin/[
|
||||
target /bin/test
|
||||
|
||||
link /bin/whatis
|
||||
target /bin/apropos
|
||||
|
||||
link /bin/chfn
|
||||
target /bin/chpass
|
||||
link /bin/chsh
|
||||
target /bin/chpass
|
||||
|
||||
link /bin/rb
|
||||
target /bin/rz
|
||||
link /bin/rx
|
||||
target /bin/rz
|
||||
|
||||
link /bin/sb
|
||||
target /bin/sz
|
||||
link /bin/sx
|
||||
target /bin/sz
|
||||
|
||||
#
|
||||
# Files: /sbin
|
||||
#
|
||||
file /sbin/chown
|
||||
file /sbin/chroot
|
||||
mode 04755
|
||||
file /sbin/cron
|
||||
file /sbin/devupdate
|
||||
file /sbin/disktool
|
||||
file /sbin/fdisk
|
||||
file /sbin/fsck
|
||||
file /sbin/init
|
||||
mode 0700
|
||||
file /sbin/mkfs
|
||||
file /sbin/mknod
|
||||
file /sbin/mkpasswd
|
||||
file /sbin/mount
|
||||
file /sbin/pstat
|
||||
mode 02755
|
||||
file /sbin/rdprof
|
||||
file /sbin/reboot
|
||||
file /sbin/shutdown
|
||||
mode 04750
|
||||
file /sbin/talloc
|
||||
file /sbin/umount
|
||||
file /sbin/update
|
||||
file /sbin/updatedb
|
||||
file /sbin/vipw
|
||||
|
||||
link /sbin/bootloader
|
||||
target /sbin/reboot
|
||||
link /sbin/fastboot
|
||||
target /sbin/reboot
|
||||
link /sbin/halt
|
||||
target /sbin/reboot
|
||||
link /sbin/poweroff
|
||||
target /sbin/reboot
|
||||
|
||||
#
|
||||
# Files: /games
|
||||
#
|
||||
default
|
||||
filemode 0775
|
||||
dir /games
|
||||
file /games/adventure
|
||||
file /games/arithmetic
|
||||
file /games/atc
|
||||
file /games/backgammon
|
||||
file /games/banner
|
||||
file /games/battlestar
|
||||
file /games/bcd
|
||||
file /games/boggle
|
||||
file /games/btlgammon
|
||||
file /games/canfield
|
||||
file /games/cfscores
|
||||
file /games/cribbage
|
||||
file /games/factor
|
||||
file /games/fish
|
||||
file /games/fortune
|
||||
file /games/hangman
|
||||
file /games/mille
|
||||
file /games/monop
|
||||
file /games/morse
|
||||
file /games/number
|
||||
file /games/ppt
|
||||
file /games/primes
|
||||
file /games/quiz
|
||||
file /games/rain
|
||||
file /games/robots
|
||||
file /games/rogue
|
||||
file /games/sail
|
||||
file /games/snake
|
||||
file /games/snscore
|
||||
file /games/teachgammon
|
||||
file /games/trek
|
||||
file /games/worm
|
||||
file /games/worms
|
||||
file /games/wump
|
||||
|
||||
#
|
||||
# Files: /games/lib
|
||||
#
|
||||
default
|
||||
filemode 0444
|
||||
dir /games/lib
|
||||
file /games/lib/adventure.dat
|
||||
file /games/lib/battle_strings
|
||||
file /games/lib/backrules
|
||||
file /games/lib/bogdict
|
||||
file /games/lib/cfscores
|
||||
file /games/lib/crib.instr
|
||||
mode 0666
|
||||
file /games/lib/fortunes.dat
|
||||
file /games/lib/cards.pck
|
||||
file /games/lib/robots_roll
|
||||
mode 0666
|
||||
file /games/lib/snakerawscores
|
||||
mode 0666
|
||||
dir /games/lib/atc
|
||||
file /games/lib/atc/ATC_scores
|
||||
file /games/lib/atc/crossover
|
||||
file /games/lib/atc/default
|
||||
file /games/lib/atc/easy
|
||||
file /games/lib/atc/game_2
|
||||
file /games/lib/atc/Game_List
|
||||
file /games/lib/atc/Killer
|
||||
dir /games/lib/quiz.k
|
||||
file /games/lib/quiz.k/africa
|
||||
file /games/lib/quiz.k/america
|
||||
file /games/lib/quiz.k/areas
|
||||
file /games/lib/quiz.k/arith
|
||||
file /games/lib/quiz.k/asia
|
||||
file /games/lib/quiz.k/babies
|
||||
file /games/lib/quiz.k/bard
|
||||
file /games/lib/quiz.k/chinese
|
||||
file /games/lib/quiz.k/collectives
|
||||
file /games/lib/quiz.k/ed
|
||||
file /games/lib/quiz.k/elements
|
||||
file /games/lib/quiz.k/europe
|
||||
file /games/lib/quiz.k/greek
|
||||
file /games/lib/quiz.k/inca
|
||||
file /games/lib/quiz.k/index
|
||||
file /games/lib/quiz.k/latin
|
||||
file /games/lib/quiz.k/locomotive
|
||||
file /games/lib/quiz.k/midearth
|
||||
file /games/lib/quiz.k/morse
|
||||
file /games/lib/quiz.k/murders
|
||||
file /games/lib/quiz.k/poetry
|
||||
file /games/lib/quiz.k/posneg
|
||||
file /games/lib/quiz.k/pres
|
||||
file /games/lib/quiz.k/province
|
||||
file /games/lib/quiz.k/seq-easy
|
||||
file /games/lib/quiz.k/seq-hard
|
||||
file /games/lib/quiz.k/sexes
|
||||
file /games/lib/quiz.k/sov
|
||||
file /games/lib/quiz.k/spell
|
||||
file /games/lib/quiz.k/state
|
||||
file /games/lib/quiz.k/trek
|
||||
file /games/lib/quiz.k/ucc
|
||||
|
||||
#
|
||||
# Files: /include
|
||||
#
|
||||
default
|
||||
filemode 0664
|
||||
dir /include
|
||||
dir /include/arpa
|
||||
dir /include/machine
|
||||
dir /include/smallc
|
||||
dir /include/smallc/sys
|
||||
dir /include/sys
|
||||
file /include/alloca.h
|
||||
file /include/a.out.h
|
||||
file /include/ar.h
|
||||
file /include/arpa/inet.h
|
||||
file /include/assert.h
|
||||
file /include/ctype.h
|
||||
file /include/curses.h
|
||||
file /include/dbm.h
|
||||
file /include/fcntl.h
|
||||
file /include/float.h
|
||||
file /include/fstab.h
|
||||
file /include/grp.h
|
||||
file /include/kmem.h
|
||||
file /include/lastlog.h
|
||||
file /include/limits.h
|
||||
file /include/machine/cpu.h
|
||||
file /include/machine/elf_machdep.h
|
||||
file /include/machine/float.h
|
||||
file /include/machine/io.h
|
||||
file /include/machine/limits.h
|
||||
file /include/machine/machparam.h
|
||||
file /include/machine/pic32mx.h
|
||||
file /include/machine/rd_sdramp_config.h
|
||||
file /include/machine/sdram.h
|
||||
file /include/machine/ssd1926.h
|
||||
file /include/machine/usb_ch9.h
|
||||
file /include/machine/usb_device.h
|
||||
file /include/machine/usb_function_cdc.h
|
||||
file /include/machine/usb_function_hid.h
|
||||
file /include/machine/usb_hal_pic32.h
|
||||
file /include/math.h
|
||||
file /include/mtab.h
|
||||
file /include/ndbm.h
|
||||
file /include/nlist.h
|
||||
file /include/paths.h
|
||||
file /include/pcc.h
|
||||
file /include/psout.h
|
||||
file /include/pwd.h
|
||||
file /include/ranlib.h
|
||||
file /include/regexp.h
|
||||
file /include/setjmp.h
|
||||
file /include/sgtty.h
|
||||
file /include/smallc/curses.h
|
||||
file /include/smallc/fcntl.h
|
||||
file /include/smallc/signal.h
|
||||
file /include/smallc/stdio.h
|
||||
file /include/smallc/sys/gpio.h
|
||||
file /include/smallc/sys/spi.h
|
||||
file /include/smallc/wiznet.h
|
||||
file /include/stab.h
|
||||
file /include/stdarg.h
|
||||
file /include/stddef.h
|
||||
file /include/stdint.h
|
||||
file /include/stdio.h
|
||||
file /include/stdlib.h
|
||||
file /include/string.h
|
||||
file /include/strings.h
|
||||
file /include/struct.h
|
||||
file /include/sys/adc.h
|
||||
file /include/sys/buf.h
|
||||
file /include/syscall.h
|
||||
file /include/sys/callout.h
|
||||
file /include/sys/clist.h
|
||||
file /include/sys/conf.h
|
||||
file /include/sys/debug.h
|
||||
file /include/sys/dir.h
|
||||
file /include/sys/disk.h
|
||||
file /include/sys/dkbad.h
|
||||
file /include/sys/dk.h
|
||||
file /include/sys/errno.h
|
||||
file /include/sys/exec_aout.h
|
||||
file /include/sys/exec_elf.h
|
||||
file /include/sys/exec.h
|
||||
file /include/sysexits.h
|
||||
file /include/sys/fcntl.h
|
||||
file /include/sys/file.h
|
||||
file /include/sys/fs.h
|
||||
file /include/sys/glcd.h
|
||||
file /include/sys/glob.h
|
||||
file /include/sys/gpio.h
|
||||
file /include/sys/inode.h
|
||||
file /include/sys/ioctl.h
|
||||
file /include/sys/kernel.h
|
||||
file /include/sys/map.h
|
||||
file /include/sys/mount.h
|
||||
file /include/sys/msgbuf.h
|
||||
file /include/sys/mtio.h
|
||||
file /include/sys/namei.h
|
||||
file /include/sys/oc.h
|
||||
file /include/sys/param.h
|
||||
file /include/sys/picga.h
|
||||
file /include/sys/proc.h
|
||||
file /include/sys/ptrace.h
|
||||
file /include/sys/pty.h
|
||||
file /include/sys/rd_flash.h
|
||||
file /include/sys/rdisk.h
|
||||
file /include/sys/rd_mrams.h
|
||||
file /include/sys/rd_sdramp.h
|
||||
file /include/sys/rd_sramc.h
|
||||
file /include/sys/reboot.h
|
||||
file /include/sys/resource.h
|
||||
file /include/sys/select.h
|
||||
file /include/sys/signal.h
|
||||
file /include/sys/signalvar.h
|
||||
file /include/sys/spi_bus.h
|
||||
file /include/sys/spi.h
|
||||
file /include/sys/stat.h
|
||||
file /include/sys/swap.h
|
||||
file /include/sys/sysctl.h
|
||||
file /include/sys/syslog.h
|
||||
file /include/sys/systm.h
|
||||
file /include/sys/time.h
|
||||
file /include/sys/times.h
|
||||
file /include/sys/trace.h
|
||||
file /include/sys/ttychars.h
|
||||
file /include/sys/ttydev.h
|
||||
file /include/sys/tty.h
|
||||
file /include/sys/types.h
|
||||
file /include/sys/uart.h
|
||||
file /include/sys/uio.h
|
||||
file /include/sys/usb_uart.h
|
||||
file /include/sys/user.h
|
||||
file /include/sys/utsname.h
|
||||
file /include/sys/vm.h
|
||||
file /include/sys/vmmac.h
|
||||
file /include/sys/vmmeter.h
|
||||
file /include/sys/vmparam.h
|
||||
file /include/sys/vmsystm.h
|
||||
file /include/sys/wait.h
|
||||
file /include/term.h
|
||||
file /include/termios-todo.h
|
||||
file /include/time.h
|
||||
file /include/ttyent.h
|
||||
file /include/tzfile.h
|
||||
file /include/unistd.h
|
||||
file /include/utmp.h
|
||||
file /include/vmf.h
|
||||
|
||||
symlink /include/errno.h
|
||||
target sys/errno.h
|
||||
|
||||
symlink /include/signal.h
|
||||
target sys/signal.h
|
||||
|
||||
symlink /include/syslog.h
|
||||
target sys/syslog.h
|
||||
|
||||
#
|
||||
# Files: /lib
|
||||
#
|
||||
file /lib/crt0.o
|
||||
file /lib/libc.a
|
||||
file /lib/libcurses.a
|
||||
file /lib/libtermlib.a
|
||||
file /lib/libwiznet.a
|
||||
file /lib/retroImage
|
||||
|
||||
#
|
||||
# Files: /libexec
|
||||
#
|
||||
default
|
||||
filemode 0775
|
||||
file /libexec/bigram
|
||||
file /libexec/code
|
||||
file /libexec/diffh
|
||||
file /libexec/getty
|
||||
file /libexec/smallc
|
||||
file /libexec/smlrc
|
||||
|
||||
#
|
||||
# Files: /share
|
||||
#
|
||||
default
|
||||
filemode 0444
|
||||
dir /share
|
||||
dir /share/dict
|
||||
dir /share/misc
|
||||
file /share/emg.keys
|
||||
file /share/re.help
|
||||
file /share/dict/words
|
||||
file /share/misc/more.help
|
||||
|
||||
#
|
||||
# Files: /share/example
|
||||
#
|
||||
default
|
||||
filemode 0664
|
||||
dir /share/example
|
||||
file /share/example/ashello.S
|
||||
file /share/example/blkjack.bas
|
||||
file /share/example/chello.c
|
||||
file /share/example/echo.S
|
||||
file /share/example/fact.fth
|
||||
file /share/example/hilow.bas
|
||||
file /share/example/Makefile
|
||||
file /share/example/prime.scm
|
||||
file /share/example/skeleton.c
|
||||
file /share/example/stars.bas
|
||||
file /share/example/stdarg.c
|
||||
|
||||
#
|
||||
# Files: /share/smallc
|
||||
#
|
||||
dir /share/smallc
|
||||
file /share/smallc/adc.c
|
||||
file /share/smallc/gpio.c
|
||||
file /share/smallc/hello.c
|
||||
file /share/smallc/Makefile
|
||||
file /share/smallc/primelist.c
|
||||
file /share/smallc/primesum.c
|
||||
file /share/smallc/q8.c
|
||||
file /share/smallc/rain.c
|
||||
file /share/smallc/test1.c
|
||||
file /share/smallc/test2.c
|
||||
file /share/smallc/test3.c
|
||||
file /share/smallc/webserver.c
|
||||
|
||||
#
|
||||
# Files: /share/smallerc
|
||||
#
|
||||
dir /share/smallerc
|
||||
file /share/smallerc/adc.c
|
||||
file /share/smallerc/gpio.c
|
||||
file /share/smallerc/hello.c
|
||||
file /share/smallerc/Makefile
|
||||
file /share/smallerc/primelist.c
|
||||
file /share/smallerc/primesum.c
|
||||
file /share/smallerc/q8.c
|
||||
file /share/smallerc/rain.c
|
||||
file /share/smallerc/test1.c
|
||||
file /share/smallerc/test2.c
|
||||
file /share/smallerc/test3.c
|
||||
|
||||
#
|
||||
# Files: /var
|
||||
#
|
||||
dir /var
|
||||
dir /var/lock
|
||||
dir /var/log
|
||||
dir /var/run
|
||||
file /var/log/messages
|
||||
file /var/log/wtmp
|
||||
|
||||
#
|
||||
# Files: /share/man
|
||||
#
|
||||
dir /share/man
|
||||
dir /share/man/cat1
|
||||
dir /share/man/cat2
|
||||
dir /share/man/cat3
|
||||
dir /share/man/cat4
|
||||
dir /share/man/cat5
|
||||
dir /share/man/cat6
|
||||
dir /share/man/cat7
|
||||
dir /share/man/cat8
|
||||
file /share/man/cat1/ar.0
|
||||
file /share/man/cat1/chflags.0
|
||||
file /share/man/cat1/chpass.0
|
||||
file /share/man/cat1/cpp.0
|
||||
file /share/man/cat1/crontab.0
|
||||
file /share/man/cat1/emg.0
|
||||
file /share/man/cat1/groups.0
|
||||
file /share/man/cat1/hostname.0
|
||||
file /share/man/cat1/id.0
|
||||
file /share/man/cat1/la.0
|
||||
file /share/man/cat1/lcc.0
|
||||
file /share/man/cat1/ld.0
|
||||
file /share/man/cat1/lv.0
|
||||
file /share/man/cat1/passwd.0
|
||||
file /share/man/cat1/printf.0
|
||||
file /share/man/cat1/ranlib.0
|
||||
file /share/man/cat1/rz.0
|
||||
file /share/man/cat1/stty.0
|
||||
file /share/man/cat1/sz.0
|
||||
file /share/man/cat1/test.0
|
||||
file /share/man/cat1/uname.0
|
||||
file /share/man/cat1/whoami.0
|
||||
file /share/man/cat1/xargs.0
|
||||
file /share/man/cat3/vmf.0
|
||||
file /share/man/cat5/ar.0
|
||||
file /share/man/cat5/crontab.0
|
||||
file /share/man/cat5/ranlib.0
|
||||
file /share/man/cat6/adventure.0
|
||||
file /share/man/cat6/arithmetic.0
|
||||
file /share/man/cat6/atc.0
|
||||
file /share/man/cat6/backgammon.0
|
||||
file /share/man/cat6/banner.0
|
||||
file /share/man/cat6/battlestar.0
|
||||
file /share/man/cat6/bcd.0
|
||||
file /share/man/cat6/canfield.0
|
||||
file /share/man/cat6/cribbage.0
|
||||
file /share/man/cat6/fish.0
|
||||
file /share/man/cat6/fortune.0
|
||||
file /share/man/cat6/hangman.0
|
||||
file /share/man/cat6/mille.0
|
||||
file /share/man/cat6/monop.0
|
||||
file /share/man/cat6/number.0
|
||||
file /share/man/cat6/quiz.0
|
||||
file /share/man/cat6/rain.0
|
||||
file /share/man/cat6/robots.0
|
||||
file /share/man/cat6/rogue.0
|
||||
file /share/man/cat6/sail.0
|
||||
file /share/man/cat6/snake.0
|
||||
file /share/man/cat6/trek.0
|
||||
file /share/man/cat6/worm.0
|
||||
file /share/man/cat6/worms.0
|
||||
file /share/man/cat6/wump.0
|
||||
file /share/man/cat8/chown.0
|
||||
file /share/man/cat8/chroot.0
|
||||
file /share/man/cat8/cron.0
|
||||
file /share/man/cat8/fdisk.0
|
||||
file /share/man/cat8/fstat.0
|
||||
file /share/man/cat8/init.0
|
||||
file /share/man/cat8/mkfs.0
|
||||
file /share/man/cat8/mknod.0
|
||||
file /share/man/cat8/mkpasswd.0
|
||||
file /share/man/cat8/mount.0
|
||||
file /share/man/cat8/pstat.0
|
||||
file /share/man/cat8/reboot.0
|
||||
file /share/man/cat8/renice.0
|
||||
file /share/man/cat8/shutdown.0
|
||||
file /share/man/cat8/sysctl.0
|
||||
#file /share/man/cat8/talloc.0
|
||||
file /share/man/cat8/umount.0
|
||||
file /share/man/cat8/update.0
|
||||
file /share/man/cat8/vipw.0
|
||||
|
||||
link /share/man/cat1/rb.0
|
||||
target /share/man/cat1/rz.0
|
||||
link /share/man/cat1/rx.0
|
||||
target /share/man/cat1/rz.0
|
||||
|
||||
link /share/man/cat1/sb.0
|
||||
target /share/man/cat1/sz.0
|
||||
link /share/man/cat1/sx.0
|
||||
target /share/man/cat1/sz.0
|
||||
|
||||
link /share/man/cat8/fastboot.0
|
||||
target /share/man/cat8/reboot.0
|
||||
link /share/man/cat8/halt.0
|
||||
target /share/man/cat8/reboot.0
|
||||
|
||||
link /share/man/cat1/chfn.0
|
||||
target /share/man/cat1/chpass.0
|
||||
link /share/man/cat1/chsh.0
|
||||
target /share/man/cat1/chpass.0
|
||||
1
share/.gitignore
vendored
1
share/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
re.help
|
||||
misc
|
||||
unixbench
|
||||
emg.keys
|
||||
|
||||
25486
share/dict/words
Normal file
25486
share/dict/words
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
|
||||
all: ashello echo
|
||||
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 *.dis *~
|
||||
rm -f *.o ashello echo chello stdarg skeleton *.dis *~
|
||||
|
||||
@@ -5,13 +5,13 @@ CFLAGS += -Werror
|
||||
ASFLAGS += -DCROSS
|
||||
ASLDFLAGS = --oformat=elf32-tradlittlemips -N -nostartfiles -T $(TOPSRC)/src/elf32-mips.ld
|
||||
|
||||
all: hello cplus
|
||||
all: chello cplus echo stdarg
|
||||
|
||||
hello: hello.o
|
||||
${CC} ${LDFLAGS} -o hello.elf hello.o ${LIBS}
|
||||
${OBJDUMP} -S hello.elf > hello.dis
|
||||
${SIZE} hello.elf
|
||||
${ELF2AOUT} hello.elf $@
|
||||
chello: chello.o
|
||||
${CC} ${LDFLAGS} -o chello.elf chello.o ${LIBS}
|
||||
${OBJDUMP} -S chello.elf > chello.dis
|
||||
${SIZE} chello.elf
|
||||
${ELF2AOUT} chello.elf $@
|
||||
|
||||
cplus: cplus.o
|
||||
${CXX} ${LDFLAGS} -nostdlib -o cplus.elf cplus.o ${LIBS}
|
||||
@@ -24,7 +24,6 @@ echo: echo.o
|
||||
${OBJDUMP} -S $@.elf > $@.dis
|
||||
${SIZE} $@.elf
|
||||
${ELF2AOUT} $@.elf $@
|
||||
./aout $@ > $@.dis
|
||||
|
||||
clean:
|
||||
rm -f *.o *.elf ${MAN} hello cplus *.elf *.dis tags *~
|
||||
rm -f *.o *.elf ${MAN} chello cplus echo stdarg *.elf *.dis tags *~
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
printf ("Hello, C World!\n");
|
||||
return 0;
|
||||
printf ("Hello, C World!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
92
share/example/skeleton.c
Normal file
92
share/example/skeleton.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Generic skeleton for a C program.
|
||||
* When you create your own program based on this skeleton,
|
||||
* you can replace the author's name and copyright with
|
||||
* whatever your want. When you redistribute this skeleton or
|
||||
* enhance it, please leave my name and copyright on it.
|
||||
*
|
||||
* Copyright (C) 1993-2014 Serge Vakulenko, <vak@cronyx.ru>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software
|
||||
* and its documentation for any purpose and without fee is hereby
|
||||
* granted, provided that the above copyright notice appear in all
|
||||
* copies and that both that the copyright notice and this
|
||||
* permission notice and warranty disclaimer appear in supporting
|
||||
* documentation, and that the name of the author not be used in
|
||||
* advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission.
|
||||
*
|
||||
* The author disclaim all warranties with regard to this
|
||||
* software, including all implied warranties of merchantability
|
||||
* and fitness. In no event shall the author be liable for any
|
||||
* special, indirect or consequential damages or any damages
|
||||
* whatsoever resulting from loss of use, data or profits, whether
|
||||
* in an action of contract, negligence or other tortious action,
|
||||
* arising out of or in connection with the use or performance of
|
||||
* this software.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char version[] = "1.0";
|
||||
const char copyright[] = "Copyright (C) 1993-2014 Serge Vakulenko";
|
||||
|
||||
char *progname; /* Name of the current program (argv[0]) */
|
||||
int verbose; /* Option -v */
|
||||
int trace; /* Option -t */
|
||||
int debug; /* Option -d */
|
||||
|
||||
void usage ()
|
||||
{
|
||||
fprintf (stderr, "Generic C skeleton, Version %s, %s\n", version, copyright);
|
||||
fprintf (stderr, "Usage:\n\t%s [-vtd] [-r count] file...\n", progname);
|
||||
fprintf (stderr, "Options:\n");
|
||||
fprintf (stderr, "\t-v\tverbose mode\n");
|
||||
fprintf (stderr, "\t-t\ttrace mode\n");
|
||||
fprintf (stderr, "\t-d\tdebug\n");
|
||||
fprintf (stderr, "\t-r #\trepeat count\n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
int count = 1; /* Option -r # */
|
||||
|
||||
progname = *argv;
|
||||
for (;;) {
|
||||
switch (getopt (argc, argv, "vtdr:")) {
|
||||
case EOF:
|
||||
break;
|
||||
case 'v':
|
||||
++verbose;
|
||||
continue;
|
||||
case 't':
|
||||
++trace;
|
||||
continue;
|
||||
case 'd':
|
||||
++debug;
|
||||
continue;
|
||||
case 'r':
|
||||
count = strtol (optarg, 0, 0);
|
||||
continue;
|
||||
default:
|
||||
usage ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1)
|
||||
usage ();
|
||||
|
||||
while (count-- > 0) {
|
||||
int i;
|
||||
|
||||
for (i=0; i<argc; ++i)
|
||||
printf ("%s ", argv[i]);
|
||||
printf ("\n");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
34
share/example/stdarg.c
Normal file
34
share/example/stdarg.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
void print(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int d;
|
||||
char c, *s;
|
||||
|
||||
va_start(ap, fmt);
|
||||
while (*fmt) {
|
||||
switch (*fmt++) {
|
||||
case 's': /* string */
|
||||
s = va_arg(ap, char*);
|
||||
printf("string %s\n", s);
|
||||
break;
|
||||
case 'd': /* int */
|
||||
d = va_arg(ap, int);
|
||||
printf("int %d\n", d);
|
||||
break;
|
||||
case 'c': /* char */
|
||||
c = va_arg(ap, int);
|
||||
printf("char %c\n", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
print("sdcsdc", "abracadabra", 12345, 'Z', "foo", 365, '%');
|
||||
return 0;
|
||||
}
|
||||
3
share/man/.gitignore
vendored
3
share/man/.gitignore
vendored
@@ -0,0 +1,3 @@
|
||||
makewhatis.sed
|
||||
man.template
|
||||
whatis
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
extern int printf();
|
||||
|
||||
int main()
|
||||
main()
|
||||
{
|
||||
printf ("Hello, SmallC World!\n");
|
||||
}
|
||||
|
||||
38
share/smallerc/Makefile
Normal file
38
share/smallerc/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
CC = cc
|
||||
PROG = hello primelist primesum test1 test2 test3 gpio adc rain \
|
||||
q8
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
hello: hello.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) hello.c
|
||||
|
||||
primelist: primelist.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) primelist.c
|
||||
|
||||
primesum: primesum.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) primesum.c
|
||||
|
||||
gpio: gpio.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) gpio.c
|
||||
|
||||
adc: adc.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) adc.c
|
||||
|
||||
rain: rain.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) rain.c
|
||||
|
||||
q8: q8.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) q8.c
|
||||
|
||||
test1: test1.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) test1.c
|
||||
|
||||
test2: test2.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) test2.c
|
||||
|
||||
test3: test3.c
|
||||
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) test3.c
|
||||
|
||||
clean:
|
||||
rm -f *.o $(PROG)
|
||||
29
share/smallerc/adc.c
Normal file
29
share/smallerc/adc.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Example of reading ADC data.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char buf[100];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i, fd, value;
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
sprintf(buf, "/dev/adc%d", i);
|
||||
fd = open(buf, O_RDWR);
|
||||
if (fd < 0) {
|
||||
printf("Error: unable to open %s\n", buf);
|
||||
} else {
|
||||
if (read(fd, buf, 20) > 0) {
|
||||
value = strtol (buf, 0, 0);
|
||||
printf("adc%-2d = %d\n", i, value);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
26
share/smallerc/gpio.c
Normal file
26
share/smallerc/gpio.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Example of polling general purpose i/o pins.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/gpio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fd, pnum, value;
|
||||
|
||||
fd = open ("/dev/porta", O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror ("/dev/porta");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (pnum=0; pnum<7; pnum++) {
|
||||
value = ioctl (fd, GPIO_POLL | GPIO_PORT (pnum), 0);
|
||||
if (value < 0)
|
||||
perror ("GPIO_POLL");
|
||||
printf ("port%c = 0x%04x\n", pnum + 'A', value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
6
share/smallerc/hello.c
Normal file
6
share/smallerc/hello.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Hello, Smaller C World!\n");
|
||||
}
|
||||
35
share/smallerc/primelist.c
Normal file
35
share/smallerc/primelist.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Print the list of prime numbers up to 100.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
int isprime(int);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n=2; n<100; ++n) {
|
||||
if (isprime(n)) {
|
||||
printf("%d ", n);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int isprime(int n)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (n == 2)
|
||||
return 1;
|
||||
|
||||
if (n % 2 == 0)
|
||||
return 0;
|
||||
|
||||
for (j=3; j*j<=n; j+=2)
|
||||
if (n % j == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
35
share/smallerc/primesum.c
Normal file
35
share/smallerc/primesum.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Compute the sum of prime numbers up to 10000.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
int isprime(int);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int sum, n;
|
||||
|
||||
sum = 0;
|
||||
for (n=2; n<10000; ++n) {
|
||||
if (isprime(n)) {
|
||||
sum += n;
|
||||
}
|
||||
}
|
||||
printf("Sum of primes less than 10000: %d\n", sum);
|
||||
}
|
||||
|
||||
int isprime(int n)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (n == 2)
|
||||
return 1;
|
||||
|
||||
if (n % 2 == 0)
|
||||
return 0;
|
||||
|
||||
for (j=3; j*j<=n; j+=2)
|
||||
if (n % j == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
209
share/smallerc/q8.c
Normal file
209
share/smallerc/q8.c
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Eight Queens puzzle
|
||||
*
|
||||
* (C) 2010 by Mark Sproul
|
||||
* Open source as per standard Arduino code
|
||||
* Modified by Pito 12/2012 for SmallC and then by Alexey Frunze for Smaller C
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
unsigned int gChessBoard[8];
|
||||
unsigned int gLoopCounter;
|
||||
int gValidCount;
|
||||
|
||||
int CheckCurrentBoard(void)
|
||||
{
|
||||
int ii;
|
||||
int jj;
|
||||
int theRow;
|
||||
int theLongRow;
|
||||
int theLongColumns;
|
||||
int bitCount;
|
||||
|
||||
//* we know we have 1 in each row,
|
||||
//* Check for 1 in each column
|
||||
theRow = 0;
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theRow |= gChessBoard[ii];
|
||||
}
|
||||
if (theRow != 0x0ff) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//* we have 1 in each column, now check the diagonals
|
||||
theLongColumns = 0;
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theLongRow = gChessBoard[ii] & 0x0ff;
|
||||
theLongRow = theLongRow << ii;
|
||||
|
||||
theLongColumns |= theLongRow;
|
||||
}
|
||||
|
||||
//* now count the bits
|
||||
bitCount = 0;
|
||||
for (ii=0; ii<16; ii++) {
|
||||
if ((theLongColumns & 0x01) == 0x01) {
|
||||
bitCount++;
|
||||
}
|
||||
theLongColumns = theLongColumns >> 1;
|
||||
}
|
||||
|
||||
if (bitCount != 8) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//* we now have to check the other diagonal
|
||||
theLongColumns = 0;
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theLongRow = gChessBoard[ii] & 0x0ff;
|
||||
theLongRow = theLongRow << 8;
|
||||
theLongRow = theLongRow >> ii;
|
||||
|
||||
theLongColumns |= theLongRow;
|
||||
}
|
||||
|
||||
//* now count the bits
|
||||
bitCount = 0;
|
||||
for (ii=0; ii<16; ii++) {
|
||||
if ((theLongColumns & 0x01) == 0x01) {
|
||||
bitCount++;
|
||||
}
|
||||
theLongColumns = theLongColumns >> 1;
|
||||
}
|
||||
|
||||
if (bitCount != 8) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CheckForDone(void)
|
||||
{
|
||||
int ii;
|
||||
int weAreDone;
|
||||
int theRow;
|
||||
|
||||
weAreDone = FALSE;
|
||||
|
||||
//* we know we have 1 in each row,
|
||||
//* Check for 1 in each column
|
||||
theRow = 0;
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theRow |= gChessBoard[ii];
|
||||
}
|
||||
|
||||
if (theRow == 0x01) {
|
||||
weAreDone = TRUE;
|
||||
}
|
||||
return weAreDone;
|
||||
}
|
||||
|
||||
void RotateQueens(void)
|
||||
{
|
||||
int ii;
|
||||
int keepGoing;
|
||||
int theRow;
|
||||
|
||||
ii = 0;
|
||||
keepGoing = TRUE;
|
||||
while (keepGoing && (ii < 8)) {
|
||||
theRow = gChessBoard[ii] & 0x0ff;
|
||||
theRow = (theRow >> 1) & 0x0ff;
|
||||
if (theRow != 0) {
|
||||
gChessBoard[ii] = theRow;
|
||||
keepGoing = FALSE;
|
||||
} else {
|
||||
gChessBoard[ii] = 0x080;
|
||||
}
|
||||
ii++;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintChessBoard(void)
|
||||
{
|
||||
int ii;
|
||||
int jj;
|
||||
int theRow;
|
||||
char textString[32];
|
||||
|
||||
printf("\nLoop= %d\n", gLoopCounter);
|
||||
printf("Solution count= %d\n", gValidCount);
|
||||
|
||||
printf("+----------------+\n");
|
||||
for (ii=0; ii<8; ii++) {
|
||||
theRow = gChessBoard[ii];
|
||||
|
||||
printf("|");
|
||||
for (jj=0; jj<8; jj++) {
|
||||
if (theRow & 0x080) {
|
||||
printf("Q ");
|
||||
} else {
|
||||
printf(". ");
|
||||
}
|
||||
theRow = theRow << 1;
|
||||
}
|
||||
printf("|\n");
|
||||
}
|
||||
printf("+----------------+\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int ii;
|
||||
|
||||
printf("\nEight Queens brute force");
|
||||
printf("\n************************\n");
|
||||
//* put the 8 queens on the board, 1 in each row
|
||||
for (ii=0; ii<8; ii++) {
|
||||
gChessBoard[ii] = 0x080;
|
||||
}
|
||||
PrintChessBoard();
|
||||
|
||||
gLoopCounter = 0;
|
||||
gValidCount = 0;
|
||||
|
||||
|
||||
while (1) {
|
||||
gLoopCounter++;
|
||||
|
||||
if (CheckCurrentBoard()) {
|
||||
gValidCount++;
|
||||
PrintChessBoard();
|
||||
} else if ((gLoopCounter % 1000) == 0) {
|
||||
//PrintChessBoard();
|
||||
}
|
||||
|
||||
RotateQueens();
|
||||
if (CheckForDone()) {
|
||||
//int elapsedSeconds;
|
||||
//int elapsedMinutes;
|
||||
//int elapsedHours;
|
||||
|
||||
//elapsedSeconds = millis() / 1000;
|
||||
//elapsedMinutes = elapsedSeconds / 60;
|
||||
//elapsedHours = elapsedMinutes / 60;
|
||||
|
||||
printf("----------------------------------\n");
|
||||
printf("All done\n");
|
||||
|
||||
PrintChessBoard();
|
||||
printf("----------------------------------\n");
|
||||
|
||||
//Serial.print("total seconds=");
|
||||
//Serial.println(elapsedSeconds);
|
||||
|
||||
//Serial.print("hours=");
|
||||
//Serial.println(elapsedHours);
|
||||
|
||||
//Serial.print("minutes=");
|
||||
//Serial.println(elapsedMinutes % 60);
|
||||
|
||||
//Serial.print("seconds=");
|
||||
//Serial.println(elapsedSeconds % 60);
|
||||
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
129
share/smallerc/rain.c
Normal file
129
share/smallerc/rain.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Example of using termcap library for SmallC.
|
||||
* 11/3/1980 EPS/CITHEP
|
||||
*
|
||||
* Copyright (c) 1980 Regents of the University of California.
|
||||
* All rights reserved. The Berkeley software License Agreement
|
||||
* specifies the terms and conditions for redistribution.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define CO 80 /* number of columns */
|
||||
#define LI 24 /* number of lines */
|
||||
|
||||
#define CL "\33[H\33[J" /* clear the screen */
|
||||
#define CM "\33[%u;%uH" /* move the cursor to row, column */
|
||||
#define BC "\b" /* move cursor left */
|
||||
#define DN "\33[B" /* move cursor down */
|
||||
#define ND " " /* move cursor right */
|
||||
|
||||
int xpos[5], ypos[5];
|
||||
char outbuf[BUFSIZ];
|
||||
|
||||
void moveto(int col, int row)
|
||||
{
|
||||
printf(CM, row, col);
|
||||
}
|
||||
|
||||
void onsig(int n)
|
||||
{
|
||||
moveto(0, LI - 1);
|
||||
fflush(stdout);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x, y, j;
|
||||
|
||||
setbuf(stdout, outbuf);
|
||||
for (j = SIGHUP; j <= SIGTERM; j++)
|
||||
if (signal(j, SIG_IGN) != SIG_IGN)
|
||||
signal(j, onsig);
|
||||
|
||||
fputs(CL, stdout);
|
||||
fflush(stdout);
|
||||
for (j = 5; --j >= 0; ) {
|
||||
xpos[j] = 2 + rand() % (CO - 4);
|
||||
ypos[j] = 2 + rand() % (LI - 4);
|
||||
}
|
||||
for (j = 0; ; ) {
|
||||
x = 2 + rand() % (CO - 4);
|
||||
y = 2 + rand() % (LI - 4);
|
||||
moveto(x, y);
|
||||
putchar('.');
|
||||
moveto(xpos[j], ypos[j]);
|
||||
putchar('o');
|
||||
if (j == 0)
|
||||
j = 4;
|
||||
else
|
||||
--j;
|
||||
moveto(xpos[j], ypos[j]);
|
||||
putchar('O');
|
||||
if (j == 0)
|
||||
j = 4;
|
||||
else
|
||||
--j;
|
||||
moveto(xpos[j], ypos[j]-1);
|
||||
putchar('-');
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs("|.|", stdout);
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
putchar('-');
|
||||
if (j == 0)
|
||||
j = 4;
|
||||
else
|
||||
--j;
|
||||
moveto(xpos[j], ypos[j]-2);
|
||||
putchar('-');
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs("/ \\", stdout);
|
||||
moveto(xpos[j]-2, ypos[j]);
|
||||
fputs("| O |", stdout);
|
||||
moveto(xpos[j]-1, ypos[j]+1);
|
||||
fputs("\\ /", stdout);
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
putchar('-');
|
||||
if (j == 0)
|
||||
j = 4;
|
||||
else
|
||||
--j;
|
||||
moveto(xpos[j], ypos[j]-2);
|
||||
putchar(' ');
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
putchar(' ');
|
||||
fputs(ND, stdout);
|
||||
putchar(' ');
|
||||
moveto(xpos[j]-2, ypos[j]);
|
||||
putchar(' ');
|
||||
fputs(ND, stdout);
|
||||
putchar(' ');
|
||||
fputs(ND, stdout);
|
||||
putchar(' ');
|
||||
moveto(xpos[j]-1, ypos[j]+1);
|
||||
putchar(' ');
|
||||
fputs(ND, stdout);
|
||||
putchar(' ');
|
||||
fputs(DN, stdout);
|
||||
fputs(BC, stdout);
|
||||
fputs(BC, stdout);
|
||||
putchar(' ');
|
||||
xpos[j] = x;
|
||||
ypos[j] = y;
|
||||
fflush(stdout);
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
214
share/smallerc/test1.c
Normal file
214
share/smallerc/test1.c
Normal file
@@ -0,0 +1,214 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int ga[5];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int a, b, c, d;
|
||||
int arr[5];
|
||||
int *pi;
|
||||
char arrc[5];
|
||||
char *pic;
|
||||
int s1, s2;
|
||||
int z;
|
||||
int t;
|
||||
int *pip;
|
||||
int *picp;
|
||||
int e1, e2;
|
||||
|
||||
ga[0] = 10;
|
||||
ga[1] = 20;
|
||||
ga[2] = 30;
|
||||
ga[3] = 40;
|
||||
ga[4] = 50;
|
||||
|
||||
a = 21;
|
||||
b = 31;
|
||||
c = 71;
|
||||
d = 82;
|
||||
|
||||
arr[0] = 10;
|
||||
arr[1] = 20;
|
||||
arr[2] = 30;
|
||||
arr[3] = 40;
|
||||
arr[4] = 50;
|
||||
pi = &arr[0];
|
||||
|
||||
arrc[0] = 13;
|
||||
arrc[1] = 23;
|
||||
arrc[2] = 33;
|
||||
arrc[3] = 43;
|
||||
arrc[4] = 53;
|
||||
pic = &arrc[0];
|
||||
|
||||
printf(" 21 + 31 = %d (52)\n", a + b);
|
||||
printf(" 21 - 31 = %d (-10)\n", a - b);
|
||||
printf(" 21 & 71 = %d (5)\n", a & c);
|
||||
printf(" 21 | 82 = %d (87)\n", a | d);
|
||||
printf(" 21 ^ 82 = %d (71)\n", a ^ d);
|
||||
printf(" 21 * 82 = %d (1722)\n", a * d);
|
||||
printf(" 82 %% 21 = %d (19)\n", d % a);
|
||||
printf(" 82 / 21 = %d (3)\n", d / a);
|
||||
printf(" *pi = %d (10)\n", *pi);
|
||||
printf(" *pi + 1 = %d (11)\n", *pi + 1);
|
||||
printf(" *(pi + 1) = %d (20)\n", *(pi + 1));
|
||||
printf("&arr[3] - &arr[0] = %d (3)\n", &arr[3] - &arr[0]);
|
||||
printf(" arr[3]-arr[0] = %d (30)\n", arr[3] - arr[0]);
|
||||
printf(" arr[3]+arr[0] = %d (50)\n", arr[3] + arr[0]);
|
||||
printf(" &ga[3] - &ga[0] = %d (3)\n", &ga[3] - &ga[0]);
|
||||
printf(" ga[3]-ga[0] = %d (30)\n", ga[3] - ga[0]);
|
||||
printf(" ga[3]+ga[0] = %d (50)\n", ga[3] + ga[0]);
|
||||
printf("\n");
|
||||
|
||||
printf(" *pic = %d (13)\n", *pic);
|
||||
printf(" *pic + 1 = %d (14)\n", *pic+1);
|
||||
printf(" *(pic + 1) = %d (23)\n", *(pic+1));
|
||||
printf("&arrc[3] - &arrc[0] = %d (3)\n", &arrc[3]-&arrc[0]);
|
||||
printf("\n");
|
||||
|
||||
s1 = 3;
|
||||
s2 = -200;
|
||||
printf(" 82 << 3 = %d (656)\n", d << s1);
|
||||
printf(" 82 >> 3 = %d (10)\n", d >> s1);
|
||||
printf("-200 >> 3 = %d (-25)\n", s2 >> s1);
|
||||
printf("-200 << 3 = %d (-1600)\n", s2 << s1);
|
||||
printf("\n");
|
||||
|
||||
printf("-s1 = %d (-3)\n", -s1);
|
||||
printf("-s2 = %d (200)\n", -s2);
|
||||
printf("\n");
|
||||
|
||||
printf("~82 = %d (-83)\n", ~d);
|
||||
printf("\n");
|
||||
|
||||
z = 0;
|
||||
printf("!82 = %d (0)\n", !d);
|
||||
printf(" !0 = %d (1)\n", !z);
|
||||
printf("\n");
|
||||
|
||||
printf(" 0 && 0 = %d (0)\n", z && z);
|
||||
printf(" 0 && 21 = %d (0)\n", z && a);
|
||||
printf(" 3 && 21 = %d (1)\n", s1 && a);
|
||||
printf("21 && 3 = %d (1)\n", a && s1);
|
||||
printf("\n");
|
||||
|
||||
printf(" 0 || 0 = %d (0)\n", z || z);
|
||||
printf(" 0 || 21 = %d (1)\n", z || a);
|
||||
printf(" 3 || 21 = %d (1)\n", s1 || a);
|
||||
printf("21 || 3 = %d (1)\n", a || s1);
|
||||
printf("\n");
|
||||
|
||||
pi = 4;
|
||||
printf("pi++ = %d (4)\n", pi++);
|
||||
printf(" pi = %d (8)\n", pi);
|
||||
printf("++pi = %d (12)\n", ++pi);
|
||||
printf("pi-- = %d (12)\n", pi--);
|
||||
printf(" pi = %d (8)\n", pi);
|
||||
printf("--pi = %d (4)\n", --pi);
|
||||
printf("\n");
|
||||
|
||||
pic = 4;
|
||||
printf("pic++ = %d (4)\n", pic++);
|
||||
printf(" pic = %d (5)\n", pic);
|
||||
printf("++pic = %d (6)\n", ++pic);
|
||||
printf("pic-- = %d (6)\n", pic--);
|
||||
printf(" pic = %d (5)\n", pic);
|
||||
printf("--pic = %d (4)\n", --pic);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf("t++ = %d (4)\n", t++);
|
||||
printf(" t = %d (5)\n", t);
|
||||
printf("++t = %d (6)\n", ++t);
|
||||
printf("t-- = %d (6)\n", t--);
|
||||
printf(" t = %d (5)\n", t);
|
||||
printf("--t = %d (4)\n", --t);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf(" t==4 = %d (1)\n", t == 4);
|
||||
printf(" t==3 = %d (0)\n", t == 3);
|
||||
printf(" t==5 = %d (0)\n", t == 5);
|
||||
t = -4;
|
||||
printf("t==-4 = %d (1)\n", t == -4);
|
||||
printf("t==-3 = %d (0)\n", t == -3);
|
||||
printf("t==-5 = %d (0)\n", t == -5);
|
||||
printf(" t==4 = %d (0)\n", t == 4);
|
||||
printf(" t==3 = %d (0)\n", t == 3);
|
||||
printf(" t==5 = %d (0)\n", t == 5);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf(" t!=4 = %d (0)\n", t != 4);
|
||||
printf(" t!=3 = %d (1)\n", t != 3);
|
||||
printf(" t!=5 = %d (1)\n", t != 5);
|
||||
t = -4;
|
||||
printf("t!=-4 = %d (0)\n", t != -4);
|
||||
printf("t!=-3 = %d (1)\n", t != -3);
|
||||
printf("t!=-5 = %d (1)\n", t != -5);
|
||||
printf(" t!=4 = %d (1)\n", t != 4);
|
||||
printf(" t!=3 = %d (1)\n", t != 3);
|
||||
printf(" t!=5 = %d (1)\n", t != 5);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf(" t<4 = %d (0)\n", t < 4);
|
||||
printf(" t<3 = %d (0)\n", t < 3);
|
||||
printf(" t<5 = %d (1)\n", t < 5);
|
||||
printf("t<-1 = %d (0)\n", t < -1);
|
||||
printf("\n");
|
||||
|
||||
printf(" t<=4 = %d (1)\n", t <= 4);
|
||||
printf(" t<=3 = %d (0)\n", t <= 3);
|
||||
printf(" t<=5 = %d (1)\n", t <= 5);
|
||||
printf("t<=-1 = %d (0)\n", t <= -1);
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf(" t>4 = %d (0)\n", t > 4);
|
||||
printf(" t>3 = %d (1)\n", t > 3);
|
||||
printf(" t>5 = %d (0)\n", t > 5);
|
||||
printf("t>-1 = %d (1)\n", t > -1);
|
||||
printf("\n");
|
||||
|
||||
printf(" t>=4 = %d (1)\n", t >= 4);
|
||||
printf(" t>=3 = %d (1)\n", t >= 3);
|
||||
printf(" t>=5 = %d (0)\n", t >= 5);
|
||||
printf("t>=-1 = %d (1)\n", t >= -1);
|
||||
printf("\n");
|
||||
|
||||
pi = -100;
|
||||
printf(" pi<4 = %d (0)\n", pi < (int*)4);
|
||||
printf(" pi<3 = %d (0)\n", pi < (int*)3);
|
||||
printf("pi<-100 = %d (0)\n", pi < (int*)-100);
|
||||
printf(" pi<-1 = %d (1)\n", pi < (int*)-1);
|
||||
printf("\n");
|
||||
|
||||
printf(" pi<=4 = %d (0)\n", pi <= (int*)4);
|
||||
printf(" pi<=3 = %d (0)\n", pi <= (int*)3);
|
||||
printf("pi<=-100 = %d (1)\n", pi <= (int*)-100);
|
||||
printf(" pi<=-1 = %d (1)\n", pi <= (int*)-1);
|
||||
printf("\n");
|
||||
|
||||
pi = -100;
|
||||
printf(" pi>4 = %d (1)\n", pi > (int*)4);
|
||||
printf(" pi>3 = %d (1)\n", pi > (int*)3);
|
||||
printf("pi>-100 = %d (0)\n", pi > (int*)-100);
|
||||
printf(" pi>-1 = %d (0)\n", pi > (int*)-1);
|
||||
printf("\n");
|
||||
|
||||
printf(" pi>=4 = %d (1)\n", pi >= (int*)4);
|
||||
printf(" pi>=3 = %d (1)\n", pi >= (int*)3);
|
||||
printf("pi>=-100 = %d (1)\n", pi >= (int*)-100);
|
||||
printf(" pi>=-1 = %d (0)\n", pi >= (int*)-1);
|
||||
printf("\n");
|
||||
|
||||
pi = &arr[0];
|
||||
pip = &arr[3];
|
||||
printf(" *pip - *pi: %d (30)\n", *pip - *pi);
|
||||
printf(" pip - pi: %d (3)\n", pip - pi);
|
||||
printf(" *pip: %d (40)\n", *pip);
|
||||
printf(" *(pip - 3): %d (10)\n", *(pip - 3));
|
||||
printf(" *&arr[3]: %d (40)\n", *&arr[3]);
|
||||
printf("*(&arr[3] - 3): %d (10)\n", *(&arr[3]-3));
|
||||
}
|
||||
128
share/smallerc/test2.c
Normal file
128
share/smallerc/test2.c
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int aaa;
|
||||
int bbb;
|
||||
int ccc;
|
||||
char gc;
|
||||
char gbuffer[3];
|
||||
int gibuffer[4];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char b;
|
||||
int la;
|
||||
unsigned int u1, u2;
|
||||
int s1, s2;
|
||||
unsigned char uc1, uc2;
|
||||
char sc1, sc2;
|
||||
int fd;
|
||||
char buffer[6];
|
||||
int ibuffer[7];
|
||||
|
||||
printf(" sizeof(uc1): %d 1\n", sizeof(uc1));
|
||||
printf(" sizeof(sc1): %d 1\n", sizeof(sc1));
|
||||
printf(" sizeof(u1): %d 4\n", sizeof(u1));
|
||||
printf(" sizeof(s1): %d 4\n", sizeof(s1));
|
||||
printf(" sizeof(aaa): %d 4\n", sizeof(aaa));
|
||||
printf(" sizeof(bbb): %d 4\n", sizeof(bbb));
|
||||
printf(" sizeof(gc): %d 1\n", sizeof(gc));
|
||||
printf(" sizeof(buffer): %d 6\n", sizeof(buffer));
|
||||
printf(" sizeof(ibuffer): %d 28\n", sizeof(ibuffer));
|
||||
printf(" sizeof(char): %d 1\n", sizeof(char));
|
||||
printf(" sizeof(int): %d 4\n", sizeof(int));
|
||||
printf(" sizeof(gbuffer): %d 3\n", sizeof(gbuffer));
|
||||
printf(" sizeof(gibuffer): %d 16\n", sizeof(gibuffer));
|
||||
// sizeof(ibuffer[0]) is not supported, so the following can be used...
|
||||
printf("sizeof(ibuffer)/sizeof(int): %d 7\n", sizeof(ibuffer)/sizeof(int));
|
||||
|
||||
aaa = 1;
|
||||
bbb = 2;
|
||||
la = 4;
|
||||
printf("%d 1\n", aaa);
|
||||
printf("%d 2\n", bbb);
|
||||
printf("%d 4\n", la);
|
||||
|
||||
uc1 = 0x80;
|
||||
sc1 = 0x80;
|
||||
s1 = uc1;
|
||||
s2 = sc1;
|
||||
printf("unsigned char (0x80) -> int: %d 128\n", s1);
|
||||
printf(" signed char (0x80) -> int: %d -128\n", s2);
|
||||
|
||||
u1 = uc1;
|
||||
u2 = sc1;
|
||||
printf("unsigned char (0x80) -> unsigned: %d 128\n", u1);
|
||||
printf(" signed char (0x80) -> unsigned: %d -128\n", u2);
|
||||
|
||||
la = errno;
|
||||
printf("errno: %d 0\n", la);
|
||||
|
||||
write(1, "abcd ", 5);
|
||||
la = errno;
|
||||
printf("errno after good write call: %d 0\n", la);
|
||||
|
||||
write(10, "abcde", 5);
|
||||
la = errno;
|
||||
printf("errno after bad write call: %d 9\n", la);
|
||||
|
||||
write(1, "abcd ", 5);
|
||||
la = errno;
|
||||
printf("good write after failed should not overwrite errno: %d 9\n", la);
|
||||
|
||||
errno = 0;
|
||||
write(1, "abcd ", 5);
|
||||
la = errno;
|
||||
printf("good write after errno set to zero: %d 0\n", la);
|
||||
|
||||
la = write(1, "abcd ", 5);
|
||||
printf("write() return: %d 5\n", la);
|
||||
|
||||
la = write(10, "abcd ", 5);
|
||||
printf("write(bad fd) return: %d -1\n", la);
|
||||
|
||||
fd = open("/a.txt", O_WRONLY | O_CREAT, 0666);
|
||||
if (fd != -1) {
|
||||
printf("open success\n");
|
||||
la = write(fd, "abcd\n", 5);
|
||||
if (la == 5) printf("write success\n"); else printf("write failed\n");
|
||||
la = close(fd);
|
||||
if (la != -1) printf("close success\n"); else printf("close failed\n");
|
||||
} else {
|
||||
printf("open failed\n");
|
||||
}
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
buffer[4] = 0;
|
||||
buffer[5] = 0;
|
||||
|
||||
fd = open("/a.txt", O_RDONLY, 0666);
|
||||
if (fd != -1) {
|
||||
printf("open success\n");
|
||||
la = read(fd, buffer, 5);
|
||||
printf(buffer);
|
||||
if (la == 5) printf("read success\n"); else printf("read failed\n");
|
||||
la = close(fd);
|
||||
if (la != -1) printf("close success\n"); else printf("close failed\n");
|
||||
} else {
|
||||
printf("open failed\n");
|
||||
}
|
||||
|
||||
if (buffer[0] != 'a') printf("data0 readback from file MISMATCH\n");
|
||||
if (buffer[1] != 'b') printf("data1 readback from file MISMATCH\n");
|
||||
if (buffer[2] != 'c') printf("data2 readback from file MISMATCH\n");
|
||||
if (buffer[3] != 'd') printf("data3 readback from file MISMATCH\n");
|
||||
if (buffer[4] != '\n') printf("data4 readback from file MISMATCH\n");
|
||||
|
||||
if (buffer[0] != 'a' || buffer[1] != 'b' || buffer[2] != 'c' ||
|
||||
buffer[3] != 'd' || buffer[4] != '\n') {
|
||||
printf("data readback from file MISMATCH\n");
|
||||
} else {
|
||||
printf("data readback from file OK\n");
|
||||
}
|
||||
}
|
||||
51
share/smallerc/test3.c
Normal file
51
share/smallerc/test3.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void printt(int t, char* str);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = 0;
|
||||
if (t) printt(t, "failure"); else printt(t, "success");
|
||||
t = 1;
|
||||
if (t) printt(t, "success"); else printt(t, "failure");
|
||||
t = 8;
|
||||
if (t) printt(t, "success"); else printt(t, "failure");
|
||||
t = -2;
|
||||
if (t) printt(t, "success"); else printt(t, "failure");
|
||||
printf("\n");
|
||||
|
||||
t = 4;
|
||||
printf("switch test: ");
|
||||
switch (t) {
|
||||
case 3:
|
||||
printf("failure");
|
||||
break;
|
||||
case 4:
|
||||
printf("success");
|
||||
break;
|
||||
case 5:
|
||||
printf("failure");
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("switch fallthrough test: ");
|
||||
switch (t) {
|
||||
case 3:
|
||||
printf("failure");
|
||||
break;
|
||||
case 4:
|
||||
printf("OKSOFAR: ");
|
||||
case 5:
|
||||
printf("success if oksofar printed before this in caps");
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void printt(int t, char* str)
|
||||
{
|
||||
printf("bool test on value %d %s\n", t, str);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ include $(TOPSRC)/target.mk
|
||||
# Programs that live in subdirectories, and have makefiles of their own.
|
||||
#
|
||||
SUBDIR = startup-$(MACHINE) libc libm libutil libtermlib libcurses \
|
||||
libvmf libwiznet share cmd games
|
||||
libvmf libwiznet share cmd games man
|
||||
|
||||
all: $(SUBDIR)
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ CFLAGS += -Werror
|
||||
|
||||
# Programs that live in subdirectories, and have makefiles of their own.
|
||||
# /bin
|
||||
SUBDIR = adb adc-demo ar as awk basic cc chflags chpass \
|
||||
cpp dc diff env fdisk find forth fstat glcdtest hostname \
|
||||
id la lcc lcpp ld ls login make man med \
|
||||
SUBDIR = adb adc-demo aout ar as awk basic cc chflags chpass \
|
||||
cpp dc diff emg env fdisk find forth fstat glcdtest \
|
||||
hostname id la lcc lcpp ld levee ls login make man med \
|
||||
more nm passwd picoc portio printf pwm \
|
||||
rdprof ranlib re renice retroforth scm setty sl \
|
||||
sed sh smallc smlrc stty sysctl test uname wiznet xargs \
|
||||
|
||||
1
src/cmd/aout/.gitignore
vendored
Normal file
1
src/cmd/aout/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
aout
|
||||
25
src/cmd/aout/Makefile
Normal file
25
src/cmd/aout/Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# aout - Display information from a.out files
|
||||
#
|
||||
TOPSRC = $(shell cd ../../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
#include $(TOPSRC)/cross.mk
|
||||
|
||||
CFLAGS += -Werror -Wall -Os
|
||||
LDFLAGS +=
|
||||
|
||||
AOUTOBJS = aout.o mips-dis.o
|
||||
|
||||
all: aout
|
||||
|
||||
aout: $(AOUTOBJS)
|
||||
${CC} ${LDFLAGS} -o aout.elf $(AOUTOBJS) ${LIBS}
|
||||
${OBJDUMP} -S aout.elf > aout.dis
|
||||
${SIZE} aout.elf
|
||||
${ELF2AOUT} aout.elf $@ && rm aout.elf
|
||||
|
||||
clean:
|
||||
rm -f *.o *.0 *.elf aout tags *~ *.dis
|
||||
|
||||
install: all
|
||||
install aout $(DESTDIR)/bin/
|
||||
@@ -55,7 +55,7 @@ int fgethdr (text, h)
|
||||
register FILE *text;
|
||||
register struct exec *h;
|
||||
{
|
||||
h->a_magic = fgetword (text);
|
||||
h->a_midmag = fgetword (text);
|
||||
h->a_text = fgetword (text);
|
||||
h->a_data = fgetword (text);
|
||||
h->a_bss = fgetword (text);
|
||||
@@ -235,7 +235,7 @@ void disasm (fname)
|
||||
return;
|
||||
}
|
||||
if (rflag) {
|
||||
if (hdr.a_magic != RMAGIC) {
|
||||
if (N_GETMAGIC(hdr) != RMAGIC) {
|
||||
fprintf (stderr, "aout: %s is not relocatable\n",
|
||||
fname);
|
||||
rflag = 0;
|
||||
@@ -250,9 +250,9 @@ void disasm (fname)
|
||||
}
|
||||
printf ("File %s:\n", fname);
|
||||
printf (" a_magic = %08x (%s)\n", hdr.a_magic,
|
||||
hdr.a_magic == RMAGIC ? "relocatable" :
|
||||
hdr.a_magic == OMAGIC ? "OMAGIC" :
|
||||
hdr.a_magic == NMAGIC ? "NMAGIC" : "unknown");
|
||||
N_GETMAGIC(hdr) == RMAGIC ? "relocatable" :
|
||||
N_GETMAGIC(hdr) == OMAGIC ? "OMAGIC" :
|
||||
N_GETMAGIC(hdr) == NMAGIC ? "NMAGIC" : "unknown");
|
||||
printf (" a_text = %08x (%u bytes)\n", hdr.a_text, hdr.a_text);
|
||||
printf (" a_data = %08x (%u bytes)\n", hdr.a_data, hdr.a_data);
|
||||
printf (" a_bss = %08x (%u bytes)\n", hdr.a_bss, hdr.a_bss);
|
||||
@@ -261,7 +261,7 @@ void disasm (fname)
|
||||
printf (" a_syms = %08x (%u bytes)\n", hdr.a_syms, hdr.a_syms);
|
||||
printf (" a_entry = %08x\n", hdr.a_entry);
|
||||
|
||||
addr = (hdr.a_magic == RMAGIC) ? 0 : USER_CODE_START;
|
||||
addr = ((hdr.a_magic) == RMAGIC) ? 0 : USER_CODE_START;
|
||||
|
||||
if (hdr.a_text > 0) {
|
||||
printf ("\nSection .text:\n");
|
||||
@@ -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 > $@
|
||||
|
||||
124
src/cmd/as/as.c
124
src/cmd/as/as.c
@@ -83,6 +83,7 @@ enum {
|
||||
LIDENT, /* .ident */
|
||||
LWEAK, /* .weak */
|
||||
LLOCAL, /* .local */
|
||||
LNAN, /* .nan */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -215,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 },
|
||||
@@ -230,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 },
|
||||
@@ -372,7 +375,7 @@ int mode_reorder = 1; /* .set reorder option (default) */
|
||||
int mode_macro; /* .set macro option */
|
||||
int mode_mips16; /* .set mips16 option */
|
||||
int mode_micromips; /* .set micromips option */
|
||||
int mode_at; /* .set at option */
|
||||
int mode_at = 1; /* .set at option */
|
||||
int reorder_full; /* instruction buffered for reorder */
|
||||
unsigned reorder_word; /* buffered instruction... */
|
||||
unsigned reorder_clobber; /* ...modified this register */
|
||||
@@ -731,6 +734,9 @@ int lookacmd ()
|
||||
case 'm':
|
||||
if (! strcmp (".mask", name)) return (LMASK);
|
||||
break;
|
||||
case 'n':
|
||||
if (! strcmp (".nan", name)) return (LNAN);
|
||||
break;
|
||||
case 'p':
|
||||
if (! strcmp (".previous", name)) return (LPREVIOUS);
|
||||
break;
|
||||
@@ -1238,7 +1244,7 @@ void emitword (w, r, clobber_reg)
|
||||
reorder_word = w;
|
||||
reorder_rel = *r;
|
||||
reorder_full = 1;
|
||||
reorder_clobber = clobber_reg;
|
||||
reorder_clobber = clobber_reg & 15;
|
||||
} else {
|
||||
fputword (w, sfile[segm]);
|
||||
fputrel (r, rfile[segm]);
|
||||
@@ -1267,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]) */
|
||||
@@ -1317,10 +1326,9 @@ void makecmd (opcode, type, emitfunc)
|
||||
unsigned opcode;
|
||||
void (*emitfunc) (unsigned, struct reloc*);
|
||||
{
|
||||
register int clex;
|
||||
register unsigned offset;
|
||||
unsigned offset, orig_opcode = 0;
|
||||
struct reloc relinfo;
|
||||
int cval, segment, clobber_reg, negate_literal;
|
||||
int clex, cval, segment, clobber_reg, negate_literal;
|
||||
|
||||
offset = 0;
|
||||
relinfo.flags = RABS;
|
||||
@@ -1480,6 +1488,7 @@ frs1: clex = getlex (&cval);
|
||||
cval = (opcode >> 11) & 31; /* get 1-st register */
|
||||
newop |= cval << 16; /* set 1-st register */
|
||||
newop |= opcode & (31 << 21); /* set 2-nd register */
|
||||
orig_opcode = opcode;
|
||||
opcode = newop;
|
||||
type = FRT1 | FRS2 | FOFF16 | FMOD;
|
||||
goto foff16;
|
||||
@@ -1572,24 +1581,68 @@ fsa: offset = getexpr (&segment);
|
||||
}
|
||||
} else if (type & (FOFF16 | FOFF18 | FAOFF18 | FAOFF28 | FHIGH16)) {
|
||||
/* Relocatable offset */
|
||||
int valid_range;
|
||||
|
||||
if ((type & (FOFF16 | FOFF18 | FHIGH16)) && getlex (&cval) != ',')
|
||||
uerror ("comma expected");
|
||||
foff16: expr_flags = 0;
|
||||
offset = getexpr (&segment);
|
||||
relinfo.flags = segmrel [segment];
|
||||
if (negate_literal) {
|
||||
// Negate literal arg for sub and subu
|
||||
offset = -offset;
|
||||
if (relinfo.flags != RABS)
|
||||
uerror ("cannot negate relocatable literal");
|
||||
}
|
||||
if (relinfo.flags == REXT)
|
||||
relinfo.index = extref;
|
||||
if (expr_flags & EXPR_GPREL)
|
||||
relinfo.flags |= RGPREL;
|
||||
switch (type & (FOFF16 | FOFF18 | FAOFF18 | FAOFF28 | FHIGH16)) {
|
||||
case FOFF16: /* low 16-bit byte address */
|
||||
opcode |= offset & 0xffff;
|
||||
/* Test whether the immediate is in valid range
|
||||
* for the opcode. */
|
||||
if (negate_literal) {
|
||||
// Negate literal arg for sub and subu
|
||||
offset = -offset;
|
||||
if (relinfo.flags != RABS)
|
||||
uerror ("cannot negate relocatable literal");
|
||||
}
|
||||
switch (opcode & 0xfc000000) {
|
||||
default: /* addi, addiu, slti, sltiu, lw, sw */
|
||||
/* 16-bit signed value. */
|
||||
valid_range = (offset >= -0x8000) || (offset <= 0x7fff);
|
||||
break;
|
||||
case 0x30000000: /* andi */
|
||||
case 0x34000000: /* ori */
|
||||
case 0x38000000: /* xori */
|
||||
/* 16-bit unsigned value. */
|
||||
valid_range = (offset <= 0xffff);
|
||||
break;
|
||||
}
|
||||
if (valid_range) {
|
||||
opcode |= offset & 0xffff;
|
||||
} else if (orig_opcode == 0 || ! mode_at) {
|
||||
uerror ("value out of range");
|
||||
} else {
|
||||
/* Convert back to 3-reg opcode.
|
||||
* Insert an extra LI instruction. */
|
||||
if (segment != SABS)
|
||||
uerror ("absolute value required");
|
||||
if (negate_literal)
|
||||
offset = -offset;
|
||||
|
||||
if (offset <= 0xffff) {
|
||||
/* ori $1, $zero, value */
|
||||
emitword (0x34010000 | offset, &relabs, 1);
|
||||
} 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]) */
|
||||
emitword (0x3c010000 | (offset >> 16), &relabs, 1);
|
||||
emitword (0x34210000 | (offset & 0xffff), &relabs, 1);
|
||||
}
|
||||
opcode = orig_opcode | 0x10000;
|
||||
}
|
||||
break;
|
||||
case FHIGH16: /* high 16-bit byte address */
|
||||
if (expr_flags & EXPR_HI) {
|
||||
@@ -2113,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();
|
||||
@@ -2157,7 +2210,7 @@ void pass1 ()
|
||||
case LSECTION:
|
||||
/* .section name[,"flags"[,type[,entsize]]] */
|
||||
clex = getlex (&cval);
|
||||
if (clex != LNAME && clex != LBSS)
|
||||
if (clex != LNAME && clex != LBSS && clex != LTEXT && clex != LDATA)
|
||||
uerror ("bad name of .section");
|
||||
setsection();
|
||||
clex = getlex (&cval);
|
||||
@@ -2165,7 +2218,12 @@ void pass1 ()
|
||||
ungetlex (clex, cval);
|
||||
break;
|
||||
}
|
||||
skipstring();
|
||||
clex = getlex (&cval);
|
||||
if (clex == '"') {
|
||||
ungetlex (clex, cval);
|
||||
skipstring();
|
||||
} else if (clex != LNAME)
|
||||
uerror ("bad type of .section");
|
||||
clex = getlex (&cval);
|
||||
if (clex != ',') {
|
||||
ungetlex (clex, cval);
|
||||
@@ -2212,6 +2270,12 @@ void pass1 ()
|
||||
uerror ("bad parameter of .end");
|
||||
cval = lookname();
|
||||
break;
|
||||
case LNAN:
|
||||
/* .nan name */
|
||||
clex = getlex (&cval);
|
||||
if (clex != LNAME)
|
||||
uerror ("bad parameter of .nan");
|
||||
break;
|
||||
case LTYPE:
|
||||
/* .type name,type */
|
||||
if (getlex (&cval) != LNAME)
|
||||
@@ -2313,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])))
|
||||
{
|
||||
@@ -2341,7 +2415,7 @@ void makeheader (rtsize, rdsize)
|
||||
{
|
||||
struct exec hdr;
|
||||
|
||||
hdr.a_magic = RMAGIC;
|
||||
hdr.a_midmag = RMAGIC;
|
||||
hdr.a_text = count [STEXT];
|
||||
hdr.a_data = count [SDATA] + count [SSTRNG];
|
||||
hdr.a_bss = count [SBSS];
|
||||
@@ -2661,8 +2735,12 @@ int main (argc, argv)
|
||||
break;
|
||||
case 'I': /* include dir */
|
||||
// TODO
|
||||
while (*++cp);
|
||||
--cp;
|
||||
if (cp[1] == 0) {
|
||||
i++;
|
||||
} else {
|
||||
while (*++cp);
|
||||
--cp;
|
||||
}
|
||||
break;
|
||||
case 'O': /* optimization level */
|
||||
// TODO
|
||||
|
||||
@@ -226,7 +226,7 @@ RDHWR Read Hardware Register Allows unprivileged acce
|
||||
RDPGPR Read GPR from Previous Shadow Set Rt = SGPR[SRSCtl.PSS, Rd]
|
||||
|
||||
RESTORE Restore registers and deallocate stack See Architecture Reference Manual
|
||||
frame (MIPS16eª only)
|
||||
frame (MIPS16e only)
|
||||
|
||||
ROTR Rotate Word Right Rd = Rt[sa-1..0] || Rt[31..sa]
|
||||
|
||||
|
||||
@@ -1534,7 +1534,7 @@ int get_value()
|
||||
value = get_num();
|
||||
else {
|
||||
++cmdptr;
|
||||
switch (c) {
|
||||
switch ((int)c) {
|
||||
case '(': /* nesting */
|
||||
value = eval_sub();
|
||||
break;
|
||||
|
||||
@@ -26,4 +26,4 @@ clean:
|
||||
install: all
|
||||
install cc $(DESTDIR)/bin/
|
||||
install cc $(DESTDIR)/bin/scc
|
||||
install cc $(DESTDIR)/bin/srcc
|
||||
install cc $(DESTDIR)/bin/lcc
|
||||
|
||||
@@ -449,17 +449,16 @@ main(int argc, char *argv[])
|
||||
pass0 = LIBEXECDIR "/smallc";
|
||||
incdir = STDINC "/smallc";
|
||||
|
||||
} else if (strcmp ("srcc", progname) == 0) {
|
||||
/* Smaller C. */
|
||||
mode = MODE_SMALLERC;
|
||||
cppadd[0] = "-D__SMALLER_C__";
|
||||
pass0 = LIBEXECDIR "/smlrc";
|
||||
incdir = STDINC "/smallerc";
|
||||
} else {
|
||||
} else if (strcmp ("lcc", progname) == 0) {
|
||||
/* LCC: retargetable C compiler. */
|
||||
mode = MODE_LCC;
|
||||
cppadd[0] = "-D__LCC__";
|
||||
pass0 = LIBEXECDIR "/lccom";
|
||||
} else {
|
||||
/* Smaller C. */
|
||||
mode = MODE_SMALLERC;
|
||||
cppadd[0] = "-D__SMALLER_C__";
|
||||
pass0 = LIBEXECDIR "/smlrc";
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -24,13 +25,13 @@ $(MAN): ${MANSRC}
|
||||
${MANROFF} $< > $@
|
||||
|
||||
clean:
|
||||
rm -f *.o *.0 *.elf cpp *.elf *.dis tags *~ lex.yy.c y.tab.[ch] tests/run*
|
||||
rm -f *.o *.0 *.elf cpp *.dis tags *~ lex.yy.c y.tab.[ch] tests/run*
|
||||
|
||||
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) $<
|
||||
@@ -41,23 +42,29 @@ cpy.o y.tab.h: cpy.y
|
||||
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o cpy.o y.tab.c
|
||||
|
||||
test:
|
||||
./cpp.elf < tests/test1 > tests/run1
|
||||
./cpp < tests/test1 > tests/run1
|
||||
cmp tests/run1 tests/res1
|
||||
./cpp.elf < tests/test2 > tests/run2
|
||||
./cpp < tests/test2 > tests/run2
|
||||
cmp tests/run2 tests/res2
|
||||
./cpp.elf < tests/test3 > tests/run3
|
||||
./cpp < tests/test3 > tests/run3
|
||||
cmp tests/run3 tests/res3
|
||||
./cpp.elf < tests/test4 > tests/run4
|
||||
./cpp < tests/test4 > tests/run4
|
||||
cmp tests/run4 tests/res4
|
||||
./cpp.elf < tests/test5 > tests/run5
|
||||
./cpp < tests/test5 > tests/run5
|
||||
cmp tests/run5 tests/res5
|
||||
./cpp.elf < tests/test6 > tests/run6
|
||||
./cpp < tests/test6 > tests/run6
|
||||
cmp tests/run6 tests/res6
|
||||
./cpp.elf < tests/test7 > tests/run7
|
||||
./cpp < tests/test7 > tests/run7
|
||||
cmp tests/run7 tests/res7
|
||||
./cpp.elf < tests/test8 > tests/run8
|
||||
./cpp < tests/test8 > tests/run8
|
||||
cmp tests/run8 tests/res8
|
||||
./cpp.elf < tests/test9 > tests/run9
|
||||
./cpp < tests/test9 > tests/run9
|
||||
cmp tests/run9 tests/res9
|
||||
./cpp.elf < tests/test10 > tests/run10
|
||||
./cpp < tests/test10 > tests/run10
|
||||
cmp tests/run10 tests/res10
|
||||
./cpp < tests/test11 > tests/run11
|
||||
cmp tests/run11 tests/res11
|
||||
./cpp < tests/test12 > tests/run12
|
||||
cmp tests/run12 tests/res12
|
||||
./cpp < tests/test13 > tests/run13
|
||||
cmp tests/run13 tests/res13
|
||||
|
||||
91
src/cmd/cpp/compat.c
Normal file
91
src/cmd/cpp/compat.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */
|
||||
/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1998, 2003-2005, 2010-2011, 2013
|
||||
* Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return dlen + strlen(s);
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return dlen + (s - src); /* count does not include NUL */
|
||||
}
|
||||
#endif /* HAVE_STRLCAT */
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0 && --n != 0) {
|
||||
do {
|
||||
if ((*d++ = *s++) == 0)
|
||||
break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return s - src - 1; /* count does not include NUL */
|
||||
}
|
||||
#endif /* HAVE_STRLCPY */
|
||||
14
src/cmd/cpp/compat.h
Normal file
14
src/cmd/cpp/compat.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef COMPAT_H__
|
||||
#define COMPAT_H__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t strlcpy(char* dst, const char* src, size_t size);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
size_t strlcat(char* dst, const char* src, size_t size);
|
||||
#endif
|
||||
|
||||
#endif // COMPAT_H__
|
||||
11
src/cmd/cpp/config.h
Normal file
11
src/cmd/cpp/config.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef CONFIG_H__
|
||||
#define CONFIG_H__
|
||||
|
||||
#define VERSSTR "cpp for RetroBSD"
|
||||
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
//#define HAVE_STRLCPY 1
|
||||
//#define HAVE_STRLCAT 1
|
||||
|
||||
#endif // CONFIG_H__
|
||||
1643
src/cmd/cpp/cpp.c
1643
src/cmd/cpp/cpp.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,7 @@
|
||||
/* $Id: cpp.h,v 1.47.2.1 2011/02/26 06:36:40 ragge Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
|
||||
* Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se).
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -10,8 +12,6 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
@@ -24,25 +24,15 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef CROSS
|
||||
# include </usr/include/stdio.h>
|
||||
# include </usr/include/ctype.h>
|
||||
#else
|
||||
# include <stdio.h> /* for obuf */
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* for obuf */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Version string */
|
||||
#define VERSSTR "cpp for RetroBSD"
|
||||
#include "config.h"
|
||||
|
||||
typedef unsigned char uchar;
|
||||
#ifdef YYTEXT_POINTER
|
||||
extern char *yytext;
|
||||
#else
|
||||
extern char yytext[];
|
||||
#endif
|
||||
extern uchar *stringbuf;
|
||||
typedef unsigned char usch;
|
||||
extern usch yytext[];
|
||||
extern usch *stringbuf;
|
||||
|
||||
extern int trulvl;
|
||||
extern int flslvl;
|
||||
@@ -50,7 +40,7 @@ extern int elflvl;
|
||||
extern int elslvl;
|
||||
extern int tflag, Cflag, Pflag;
|
||||
extern int Mflag, dMflag;
|
||||
extern uchar *Mfile;
|
||||
extern usch *Mfile;
|
||||
extern int ofd;
|
||||
|
||||
/* args for lookup() */
|
||||
@@ -58,32 +48,77 @@ extern int ofd;
|
||||
#define ENTER 1
|
||||
|
||||
/* buffer used internally */
|
||||
#define CPPBUF 512
|
||||
#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,16 +165,16 @@ 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 *);
|
||||
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__))
|
||||
@@ -145,6 +182,5 @@ void xerror(uchar *);
|
||||
#define warning printf
|
||||
#define error printf
|
||||
#endif
|
||||
void expmac(struct recur *);
|
||||
int cinput(void);
|
||||
void getcmnt(void);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* $Id: cpy.y,v 1.18 2010/02/25 15:49:00 ragge Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
|
||||
* All rights reserved.
|
||||
@@ -58,6 +60,7 @@
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
#include "cpp.h"
|
||||
|
||||
203
src/cmd/cpp/doprnt.c
Normal file
203
src/cmd/cpp/doprnt.c
Normal 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;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
%{
|
||||
/* $Id: scanner.l,v 1.49 2009/02/14 09:23:55 ragge Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 Anders Magnusson. All rights reserved.
|
||||
*
|
||||
@@ -24,10 +26,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.
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
@@ -38,7 +45,7 @@
|
||||
|
||||
%{
|
||||
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);
|
||||
@@ -86,7 +93,7 @@ yyinput(char *b, int m)
|
||||
#ifdef HAVE_CPP_VARARG_MACRO_GCC
|
||||
#define fprintf(x, ...) error(__VA_ARGS__)
|
||||
#endif
|
||||
#define ECHO putstr((uchar *)yytext)
|
||||
#define ECHO putstr((usch *)yytext)
|
||||
#undef fileno
|
||||
#define fileno(x) 0
|
||||
|
||||
@@ -108,7 +115,7 @@ int yylex_destroy (void);
|
||||
#define input() inch()
|
||||
#define unput(ch) unch(ch)
|
||||
#endif
|
||||
#define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((uchar *)yytext);
|
||||
#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;
|
||||
@@ -169,7 +176,7 @@ WS [\t ]
|
||||
yylval.node.op = NUMBER;
|
||||
if (gotdef) {
|
||||
yylval.node.nd_val
|
||||
= lookup((uchar *)yytext, FIND) != 0;
|
||||
= lookup((usch *)yytext, FIND) != 0;
|
||||
gotdef = 0;
|
||||
return IDENT;
|
||||
}
|
||||
@@ -185,7 +192,7 @@ WS [\t ]
|
||||
}
|
||||
|
||||
0[xX]{H}+{IS}? { scale = 16;
|
||||
num: if (YYSTATE == IFR)
|
||||
num: if (YYSTATE == IFR)
|
||||
cvtdig(scale);
|
||||
PRTOUT(NUMBER);
|
||||
}
|
||||
@@ -194,13 +201,13 @@ WS [\t ]
|
||||
'(\\.|[^\\'])+' {
|
||||
if (YYSTATE || slow) {
|
||||
yylval.node.op = NUMBER;
|
||||
yylval.node.nd_val = charcon((uchar *)yytext);
|
||||
yylval.node.nd_val = charcon((usch *)yytext);
|
||||
return (NUMBER);
|
||||
}
|
||||
if (tflag)
|
||||
yyless(1);
|
||||
if (!flslvl)
|
||||
putstr((uchar *)yytext);
|
||||
putstr((usch *)yytext);
|
||||
}
|
||||
|
||||
<IFR>. { return yytext[0]; }
|
||||
@@ -236,7 +243,7 @@ WS [\t ]
|
||||
|
||||
"//".*$ { /* if (tflag) yyless(..) */
|
||||
if (Cflag && !flslvl && !slow)
|
||||
putstr((uchar *)yytext);
|
||||
putstr((usch *)yytext);
|
||||
else if (!flslvl)
|
||||
putch(' ');
|
||||
}
|
||||
@@ -248,7 +255,7 @@ WS [\t ]
|
||||
return CMNT;
|
||||
|
||||
if (prtcm)
|
||||
putstr((uchar *)yytext);
|
||||
putstr((usch *)yytext);
|
||||
wrn = 0;
|
||||
more: while ((c = input()) && c != '*') {
|
||||
if (c == '\n')
|
||||
@@ -301,12 +308,12 @@ L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); }
|
||||
if (flslvl) {
|
||||
; /* do nothing */
|
||||
} else if (isdigit((int)yytext[0]) == 0 &&
|
||||
(nl = lookup((uchar *)yytext, FIND)) != 0) {
|
||||
uchar *op = stringbuf;
|
||||
(nl = lookup((usch *)yytext, FIND)) != 0) {
|
||||
usch *op = stringbuf;
|
||||
putstr(gotident(nl));
|
||||
stringbuf = op;
|
||||
} else
|
||||
putstr((uchar *)yytext);
|
||||
putstr((usch *)yytext);
|
||||
xx: ;
|
||||
}
|
||||
|
||||
@@ -322,8 +329,8 @@ L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); }
|
||||
if (YYSTATE || slow)
|
||||
return yytext[0];
|
||||
if (yytext[0] == 6) { /* PRAGS */
|
||||
uchar *obp = stringbuf;
|
||||
extern uchar *prtprag(uchar *);
|
||||
usch *obp = stringbuf;
|
||||
extern usch *prtprag(usch *);
|
||||
*stringbuf++ = yytext[0];
|
||||
do {
|
||||
*stringbuf = input();
|
||||
@@ -338,7 +345,7 @@ L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); }
|
||||
|
||||
%%
|
||||
|
||||
uchar *yyp, yybuf[CPPBUF];
|
||||
usch *yyp, yybuf[CPPBUF];
|
||||
|
||||
int yylex(void);
|
||||
int yywrap(void);
|
||||
@@ -451,7 +458,7 @@ prinit(struct initar *it, struct includ *ic)
|
||||
* Return 0 on success, -1 if file to be included is not found.
|
||||
*/
|
||||
int
|
||||
pushfile(uchar *file)
|
||||
pushfile(usch *file)
|
||||
{
|
||||
extern struct initar *initar;
|
||||
struct includ ibuf;
|
||||
@@ -470,7 +477,7 @@ pushfile(uchar *file)
|
||||
error("Limit for nested includes exceeded");
|
||||
} else {
|
||||
ic->infil = 0;
|
||||
ic->orgfn = ic->fname = (uchar *)"<stdin>";
|
||||
ic->orgfn = ic->fname = (usch *)"<stdin>";
|
||||
}
|
||||
ic->buffer = ic->bbuf+NAMEMAX;
|
||||
ic->curptr = ic->buffer;
|
||||
@@ -506,7 +513,7 @@ pushfile(uchar *file)
|
||||
void
|
||||
prtline()
|
||||
{
|
||||
uchar *s, *os = stringbuf;
|
||||
usch *s, *os = stringbuf;
|
||||
|
||||
if (Mflag) {
|
||||
if (dMflag)
|
||||
@@ -579,7 +586,7 @@ cvtdig(int rad)
|
||||
}
|
||||
|
||||
static int
|
||||
charcon(uchar *p)
|
||||
charcon(usch *p)
|
||||
{
|
||||
int val, c;
|
||||
|
||||
@@ -664,8 +671,8 @@ elsestmt(void)
|
||||
}
|
||||
|
||||
static void
|
||||
ifdefstmt(void)
|
||||
{
|
||||
ifdefstmt(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (flslvl) {
|
||||
@@ -684,7 +691,7 @@ ifdefstmt(void)
|
||||
if (t != IDENT)
|
||||
error("bad ifdef");
|
||||
slow = 0;
|
||||
if (flslvl == 0 && lookup((uchar *)yytext, FIND) != 0)
|
||||
if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0)
|
||||
trulvl++;
|
||||
else
|
||||
flslvl++;
|
||||
@@ -692,8 +699,8 @@ ifdefstmt(void)
|
||||
}
|
||||
|
||||
static void
|
||||
ifndefstmt(void)
|
||||
{
|
||||
ifndefstmt(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
slow = 1;
|
||||
@@ -703,7 +710,7 @@ ifndefstmt(void)
|
||||
if (t != IDENT)
|
||||
error("bad ifndef");
|
||||
slow = 0;
|
||||
if (flslvl == 0 && lookup((uchar *)yytext, FIND) == 0)
|
||||
if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0)
|
||||
trulvl++;
|
||||
else
|
||||
flslvl++;
|
||||
@@ -711,7 +718,7 @@ ifndefstmt(void)
|
||||
}
|
||||
|
||||
static void
|
||||
endifstmt(void)
|
||||
endifstmt(void)
|
||||
{
|
||||
if (flslvl) {
|
||||
flslvl--;
|
||||
@@ -729,13 +736,13 @@ endifstmt(void)
|
||||
|
||||
/*
|
||||
* Note! Ugly!
|
||||
* Walk over the string s and search for defined, and replace it with
|
||||
* spaces and a 1 or 0.
|
||||
* Walk over the string s and search for defined, and replace it with
|
||||
* spaces and a 1 or 0.
|
||||
*/
|
||||
static void
|
||||
fixdefined(uchar *s)
|
||||
fixdefined(usch *s)
|
||||
{
|
||||
uchar *bc, oc;
|
||||
usch *bc, oc;
|
||||
|
||||
for (; *s; s++) {
|
||||
if (*s != 'd')
|
||||
@@ -778,14 +785,14 @@ fixdefined(uchar *s)
|
||||
static void
|
||||
storepb(void)
|
||||
{
|
||||
uchar *opb = stringbuf;
|
||||
usch *opb = stringbuf;
|
||||
int c;
|
||||
|
||||
while ((c = input()) != '\n') {
|
||||
if (c == '/') {
|
||||
if ((c = input()) == '*') {
|
||||
/* ignore comments here whatsoever */
|
||||
uchar *g = stringbuf;
|
||||
usch *g = stringbuf;
|
||||
getcmnt();
|
||||
stringbuf = g;
|
||||
continue;
|
||||
@@ -853,11 +860,11 @@ elifstmt(void)
|
||||
error("If-less elif");
|
||||
}
|
||||
|
||||
static uchar *
|
||||
static usch *
|
||||
svinp(void)
|
||||
{
|
||||
int c;
|
||||
uchar *cp = stringbuf;
|
||||
usch *cp = stringbuf;
|
||||
|
||||
while ((c = input()) && c != '\n')
|
||||
savch(c);
|
||||
@@ -870,7 +877,7 @@ svinp(void)
|
||||
static void
|
||||
cpperror(void)
|
||||
{
|
||||
uchar *cp;
|
||||
usch *cp;
|
||||
int c;
|
||||
|
||||
if (flslvl)
|
||||
@@ -893,7 +900,7 @@ undefstmt(void)
|
||||
slow = 1;
|
||||
if (yylex() != WSPACE || yylex() != IDENT)
|
||||
error("bad undef");
|
||||
if (flslvl == 0 && (np = lookup((uchar *)yytext, FIND)))
|
||||
if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
|
||||
np->value = 0;
|
||||
slow = 0;
|
||||
chknl(0);
|
||||
@@ -908,7 +915,7 @@ pragmastmt(void)
|
||||
if (yylex() != WSPACE)
|
||||
error("bad pragma");
|
||||
if (!flslvl)
|
||||
putstr((uchar *)"#pragma ");
|
||||
putstr((usch *)"#pragma ");
|
||||
do {
|
||||
c = input();
|
||||
if (!flslvl)
|
||||
|
||||
22
src/cmd/cpp/tests/res11
Normal file
22
src/cmd/cpp/tests/res11
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
a
|
||||
a b
|
||||
a b c
|
||||
a b c d
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__attribute__((__noreturn__))
|
||||
|
||||
|
||||
1 2
|
||||
|
||||
21
src/cmd/cpp/tests/res12
Normal file
21
src/cmd/cpp/tests/res12
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2 2 2 2 2;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0,
|
||||
13
src/cmd/cpp/tests/res13
Normal file
13
src/cmd/cpp/tests/res13
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
long
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
|
||||
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
|
||||
f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
|
||||
f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) &
|
||||
f(2 * (0,1))^m(0,1);
|
||||
int i[] = { 1, 23, 4, 5, };
|
||||
char c[2][6] = { "hello", "" };
|
||||
|
||||
|
||||
20
src/cmd/cpp/tests/test11
Normal file
20
src/cmd/cpp/tests/test11
Normal file
@@ -0,0 +1,20 @@
|
||||
#define D1(s, ...) s
|
||||
#define D2(s, ...) s D1(__VA_ARGS__)
|
||||
#define D3(s, ...) s D2(__VA_ARGS__)
|
||||
#define D4(s, ...) s D3(__VA_ARGS__)
|
||||
|
||||
D1(a)
|
||||
D2(a, b)
|
||||
D3(a, b, c)
|
||||
D4(a, b, c, d)
|
||||
|
||||
|
||||
#define __sun_attr___noreturn__ __attribute__((__noreturn__))
|
||||
#define ___sun_attr_inner(__a) __sun_attr_##__a
|
||||
#define __sun_attr__(__a) ___sun_attr_inner __a
|
||||
#define __NORETURN __sun_attr__((__noreturn__))
|
||||
__NORETURN
|
||||
#define X(...)
|
||||
#define Y(...) 1 __VA_ARGS__ 2
|
||||
Y(X X() ())
|
||||
|
||||
19
src/cmd/cpp/tests/test12
Normal file
19
src/cmd/cpp/tests/test12
Normal file
@@ -0,0 +1,19 @@
|
||||
#define y 2
|
||||
#define fe(p) sfe(p) p
|
||||
#define sfe(p) p
|
||||
#define Y fe(y) y fe(y)
|
||||
|
||||
Y;
|
||||
|
||||
# define S2B_QMIN 0
|
||||
# define S2B_CMIN (S2B_QMIN + 8)
|
||||
#define S2B_1(i) i,
|
||||
#define S2B_2(i) S2B_1(i) S2B_1(i)
|
||||
#define S2B_4(i) S2B_2(i) S2B_2(i)
|
||||
#define S2B_8(i) S2B_4(i) S2B_4(i)
|
||||
#define S2B_16(i) S2B_8(i) S2B_8(i)
|
||||
#define S2B_32(i) S2B_16(i) S2B_16(i)
|
||||
#define S2B_64(i) S2B_32(i) S2B_32(i)
|
||||
#define S2B_128(i) S2B_64(i) S2B_64(i)
|
||||
#define S2B_256(i) S2B_128(i) S2B_128(i)
|
||||
S2B_256(S2B_CMIN + 0)
|
||||
11
src/cmd/cpp/tests/test13
Normal file
11
src/cmd/cpp/tests/test13
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
#define UL long, foo
|
||||
#define D(I,F) I
|
||||
#define E(I) D(I)
|
||||
E(UL)
|
||||
|
||||
#define FOO 1
|
||||
|
||||
#if (FOO == 1)
|
||||
|
||||
#endif /* FOO */
|
||||
@@ -1,3 +1,5 @@
|
||||
/* $Id: token.c,v 1.48.2.2 2011/03/12 17:08:26 ragge Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
|
||||
*
|
||||
@@ -37,21 +39,24 @@
|
||||
* - inch() is like inpch but \\n and trigraphs are expanded.
|
||||
* - unch() pushes back a character to the input stream.
|
||||
*/
|
||||
#ifdef CROSS
|
||||
# include </usr/include/string.h>
|
||||
#else
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "cpp.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
static void cvtdig(int rad);
|
||||
static int charcon(uchar *);
|
||||
static int charcon(usch *);
|
||||
static void elsestmt(void);
|
||||
static void ifdefstmt(void);
|
||||
static void ifndefstmt(void);
|
||||
@@ -75,9 +80,8 @@ extern void yyset_lineno (int);
|
||||
|
||||
static int inch(void);
|
||||
|
||||
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||
|
||||
int inif;
|
||||
extern int dflag;
|
||||
|
||||
#define PUTCH(ch) if (!flslvl) putch(ch)
|
||||
/* protection against recursion in #include */
|
||||
@@ -87,25 +91,16 @@ static int inclevel;
|
||||
/* get next character unaltered */
|
||||
#define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
|
||||
|
||||
#ifdef YYTEXT_POINTER
|
||||
static char buf[CPPBUF];
|
||||
char *yytext = buf;
|
||||
#else
|
||||
char yytext[CPPBUF];
|
||||
#endif
|
||||
usch yytext[CPPBUF];
|
||||
|
||||
#define C_SPEC 1
|
||||
#define C_EP 2
|
||||
#define C_ID 4
|
||||
#define C_I (C_SPEC|C_ID)
|
||||
#define C_2 8 /* for yylex() tokenizing */
|
||||
static const char spechr[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, C_SPEC, 0, 0, 0, 0, 0,
|
||||
char spechr[256] = {
|
||||
0, 0, 0, 0, C_SPEC, C_SPEC, 0, 0,
|
||||
0, C_WSNL, C_SPEC|C_WSNL, 0,
|
||||
0, C_WSNL, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
0, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC,
|
||||
C_WSNL, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC,
|
||||
0, 0, 0, C_2, 0, C_2, 0, C_SPEC|C_2,
|
||||
C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I,
|
||||
C_I, C_I, 0, 0, C_2, C_2, C_2, C_SPEC,
|
||||
@@ -122,14 +117,55 @@ static const char spechr[256] = {
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* No-replacement array. If a macro is found and exists in this array
|
||||
* then no replacement shall occur. This is a stack.
|
||||
*/
|
||||
struct symtab *norep[RECMAX]; /* Symbol table index table */
|
||||
int norepptr = 1; /* Top of index table */
|
||||
unsigned short bptr[RECMAX]; /* currently active noexpand macro stack */
|
||||
int bidx; /* Top of bptr stack */
|
||||
|
||||
static void
|
||||
unch(int c)
|
||||
{
|
||||
|
||||
|
||||
--ifiles->curptr;
|
||||
if (ifiles->curptr < ifiles->bbuf)
|
||||
error("pushback buffer full");
|
||||
*ifiles->curptr = (uchar)c;
|
||||
*ifiles->curptr = (usch)c;
|
||||
}
|
||||
|
||||
static int
|
||||
eatcmnt(void)
|
||||
{
|
||||
int ch;
|
||||
|
||||
if (Cflag) { PUTCH('/'); PUTCH('*'); }
|
||||
for (;;) {
|
||||
ch = inch();
|
||||
if (ch == '\n') {
|
||||
ifiles->lineno++;
|
||||
PUTCH('\n');
|
||||
}
|
||||
if (ch == -1)
|
||||
return -1;
|
||||
if (ch == '*') {
|
||||
ch = inch();
|
||||
if (ch == '/') {
|
||||
if (Cflag) {
|
||||
PUTCH('*');
|
||||
PUTCH('/');
|
||||
} else
|
||||
PUTCH(' ');
|
||||
break;
|
||||
}
|
||||
unch(ch);
|
||||
ch = '*';
|
||||
}
|
||||
if (Cflag) PUTCH(ch);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -146,51 +182,38 @@ static void
|
||||
fastscan(void)
|
||||
{
|
||||
struct symtab *nl;
|
||||
int ch, i;
|
||||
int ch, i, ccnt/*, onemore*/;
|
||||
usch *cp;
|
||||
|
||||
goto run;
|
||||
for (;;) {
|
||||
ch = NXTCH();
|
||||
xloop: if (ch == -1)
|
||||
return;
|
||||
if (dflag>1)
|
||||
printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
|
||||
if ((spechr[ch] & C_SPEC) == 0) {
|
||||
PUTCH(ch);
|
||||
continue;
|
||||
}
|
||||
switch (ch) {
|
||||
case EBLOCK:
|
||||
case WARN:
|
||||
case CONC:
|
||||
error("bad char passed");
|
||||
break;
|
||||
|
||||
case '/': /* Comments */
|
||||
if ((ch = inch()) == '/') {
|
||||
if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
|
||||
cppcmt: if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
|
||||
do {
|
||||
if (Cflag) PUTCH(ch);
|
||||
ch = inch();
|
||||
} while (ch != -1 && ch != '\n');
|
||||
goto xloop;
|
||||
} else if (ch == '*') {
|
||||
if (Cflag) { PUTCH('/'); PUTCH('*'); }
|
||||
for (;;) {
|
||||
ch = inch();
|
||||
if (ch == '\n') {
|
||||
ifiles->lineno++;
|
||||
PUTCH('\n');
|
||||
}
|
||||
if (ch == -1)
|
||||
return;
|
||||
if (ch == '*') {
|
||||
ch = inch();
|
||||
if (ch == '/') {
|
||||
if (Cflag) {
|
||||
PUTCH('*');
|
||||
PUTCH('/');
|
||||
} else
|
||||
PUTCH(' ');
|
||||
break;
|
||||
}
|
||||
unch(ch);
|
||||
ch = '*';
|
||||
}
|
||||
if (Cflag) PUTCH(ch);
|
||||
}
|
||||
if (eatcmnt())
|
||||
return;
|
||||
} else {
|
||||
PUTCH('/');
|
||||
goto xloop;
|
||||
@@ -213,11 +236,30 @@ xloop: if (ch == -1)
|
||||
goto xloop;
|
||||
|
||||
case '\n': /* newlines, for pp directives */
|
||||
ifiles->lineno++;
|
||||
run2: ifiles->lineno++;
|
||||
do {
|
||||
PUTCH(ch);
|
||||
run: ch = NXTCH();
|
||||
if (ch == '/') {
|
||||
ch = NXTCH();
|
||||
if (ch == '/')
|
||||
goto cppcmt;
|
||||
if (ch == '*') {
|
||||
if (eatcmnt())
|
||||
return;
|
||||
goto run;
|
||||
}
|
||||
unch(ch);
|
||||
ch = '/';
|
||||
}
|
||||
} while (ch == ' ' || ch == '\t');
|
||||
if (ch == '\\') {
|
||||
ch = NXTCH();
|
||||
if (ch == '\n')
|
||||
goto run2;
|
||||
unch(ch);
|
||||
ch = '\\';
|
||||
}
|
||||
if (ch == '#') {
|
||||
ppdir();
|
||||
continue;
|
||||
@@ -236,7 +278,7 @@ run: ch = NXTCH();
|
||||
case '\"': /* strings */
|
||||
str: PUTCH(ch);
|
||||
while ((ch = inch()) != '\"') {
|
||||
PUTCH(ch);
|
||||
PUTCH(ch);
|
||||
if (ch == '\\') {
|
||||
ch = inch();
|
||||
PUTCH(ch);
|
||||
@@ -257,7 +299,16 @@ str: PUTCH(ch);
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
do {
|
||||
PUTCH(ch);
|
||||
ch = NXTCH();
|
||||
nxt: ch = NXTCH();
|
||||
if (ch == '\\') {
|
||||
ch = NXTCH();
|
||||
if (ch == '\n') {
|
||||
goto nxt;
|
||||
} else {
|
||||
unch(ch);
|
||||
ch = '\\';
|
||||
}
|
||||
}
|
||||
if (spechr[ch] & C_EP) {
|
||||
PUTCH(ch);
|
||||
ch = NXTCH();
|
||||
@@ -305,9 +356,9 @@ con: PUTCH(ch);
|
||||
ch = NXTCH();
|
||||
goto xloop;
|
||||
}
|
||||
i = 0;
|
||||
/*onemore =*/ i = ccnt = 0;
|
||||
do {
|
||||
yytext[i++] = (uchar)ch;
|
||||
yytext[i++] = (usch)ch;
|
||||
ch = NXTCH();
|
||||
if (ch == '\\') {
|
||||
ch = NXTCH();
|
||||
@@ -322,14 +373,17 @@ con: PUTCH(ch);
|
||||
if (ch < 0)
|
||||
return;
|
||||
} while (spechr[ch] & C_ID);
|
||||
|
||||
yytext[i] = 0;
|
||||
unch(ch);
|
||||
if ((nl = lookup((uchar *)yytext, FIND)) != 0) {
|
||||
uchar *op = stringbuf;
|
||||
putstr(gotident(nl));
|
||||
stringbuf = op;
|
||||
|
||||
cp = stringbuf;
|
||||
if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
|
||||
putstr(stringbuf);
|
||||
} else
|
||||
putstr((uchar *)yytext);
|
||||
putstr((usch *)yytext);
|
||||
stringbuf = cp;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -344,7 +398,7 @@ sloscan()
|
||||
zagain:
|
||||
yyp = 0;
|
||||
ch = inch();
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
switch (ch) {
|
||||
case -1:
|
||||
return 0;
|
||||
@@ -357,24 +411,24 @@ zagain:
|
||||
yyp = 0;
|
||||
break;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4': case '5':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5':
|
||||
case '6': case '7': case '8': case '9':
|
||||
/* readin a "pp-number" */
|
||||
ppnum: for (;;) {
|
||||
ch = inch();
|
||||
if (spechr[ch] & C_EP) {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
ch = inch();
|
||||
if (ch == '-' || ch == '+') {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
} else
|
||||
unch(ch);
|
||||
continue;
|
||||
}
|
||||
if ((spechr[ch] & C_ID) || ch == '.') {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
unch(ch);
|
||||
@@ -383,11 +437,11 @@ ppnum: for (;;) {
|
||||
return NUMBER;
|
||||
|
||||
case '\'':
|
||||
chlit:
|
||||
chlit:
|
||||
for (;;) {
|
||||
if ((ch = inch()) == '\\') {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (uchar)inch();
|
||||
yytext[yyp++] = (usch)ch;
|
||||
yytext[yyp++] = (usch)inch();
|
||||
continue;
|
||||
} else if (ch == '\n') {
|
||||
/* not a constant */
|
||||
@@ -396,7 +450,7 @@ chlit:
|
||||
ch = '\'';
|
||||
goto any;
|
||||
} else
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
if (ch == '\'')
|
||||
break;
|
||||
}
|
||||
@@ -407,7 +461,7 @@ chlit:
|
||||
case ' ':
|
||||
case '\t':
|
||||
while ((ch = inch()) == ' ' || ch == '\t')
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
unch(ch);
|
||||
yytext[yyp] = 0;
|
||||
return(WSPACE);
|
||||
@@ -415,7 +469,7 @@ chlit:
|
||||
case '/':
|
||||
if ((ch = inch()) == '/') {
|
||||
do {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
ch = inch();
|
||||
} while (ch && ch != '\n');
|
||||
yytext[yyp] = 0;
|
||||
@@ -435,7 +489,10 @@ chlit:
|
||||
more: while ((c = inch()) && c != '*') {
|
||||
if (c == '\n')
|
||||
putch(c), ifiles->lineno++;
|
||||
else if (c == 1) /* WARN */
|
||||
else if (c == EBLOCK) {
|
||||
(void)inch();
|
||||
(void)inch();
|
||||
} else if (c == 1) /* WARN */
|
||||
wrn = 1;
|
||||
}
|
||||
if (c == 0)
|
||||
@@ -459,7 +516,7 @@ chlit:
|
||||
case '.':
|
||||
ch = inch();
|
||||
if (isdigit(ch)) {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
goto ppnum;
|
||||
} else {
|
||||
unch(ch);
|
||||
@@ -468,14 +525,16 @@ chlit:
|
||||
goto any;
|
||||
|
||||
case '\"':
|
||||
if (tflag)
|
||||
goto any;
|
||||
strng:
|
||||
for (;;) {
|
||||
if ((ch = inch()) == '\\') {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (uchar)inch();
|
||||
yytext[yyp++] = (usch)ch;
|
||||
yytext[yyp++] = (usch)inch();
|
||||
continue;
|
||||
} else
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
} else
|
||||
yytext[yyp++] = (usch)ch;
|
||||
if (ch == '\"')
|
||||
break;
|
||||
}
|
||||
@@ -483,26 +542,26 @@ chlit:
|
||||
return(STRING);
|
||||
|
||||
case 'L':
|
||||
if ((ch = inch()) == '\"') {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
if ((ch = inch()) == '\"' && !tflag) {
|
||||
yytext[yyp++] = (usch)ch;
|
||||
goto strng;
|
||||
} else if (ch == '\'') {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
} else if (ch == '\'' && !tflag) {
|
||||
yytext[yyp++] = (usch)ch;
|
||||
goto chlit;
|
||||
}
|
||||
unch(ch);
|
||||
/* FALLTHROUGH */
|
||||
|
||||
/* Yetch, all identifiers */
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
|
||||
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
|
||||
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
|
||||
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
|
||||
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||
case 'G': case 'H': case 'I': case 'J': case 'K':
|
||||
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
||||
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
||||
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
||||
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
||||
case 'Y': case 'Z':
|
||||
case '_': /* {L}({L}|{D})* */
|
||||
|
||||
@@ -510,7 +569,7 @@ chlit:
|
||||
for (;;) { /* get chars */
|
||||
ch = inch();
|
||||
if (isalpha(ch) || isdigit(ch) || ch == '_') {
|
||||
yytext[yyp++] = (uchar)ch;
|
||||
yytext[yyp++] = (usch)ch;
|
||||
} else {
|
||||
unch(ch);
|
||||
break;
|
||||
@@ -584,27 +643,31 @@ yylex()
|
||||
case NUMBER:
|
||||
if (yytext[0] == '\'') {
|
||||
yylval.node.op = NUMBER;
|
||||
yylval.node.nd_val = charcon((uchar *)yytext);
|
||||
yylval.node.nd_val = charcon((usch *)yytext);
|
||||
} else
|
||||
cvtdig(yytext[0] != '0' ? 10 :
|
||||
yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
|
||||
return NUMBER;
|
||||
|
||||
case IDENT:
|
||||
if (strcmp(yytext, "defined") == 0) {
|
||||
if (strcmp((char *)yytext, "defined") == 0) {
|
||||
ifdef = 1;
|
||||
return DEFINED;
|
||||
}
|
||||
nl = lookup((uchar *)yytext, FIND);
|
||||
nl = lookup((usch *)yytext, FIND);
|
||||
if (ifdef) {
|
||||
yylval.node.nd_val = nl != NULL;
|
||||
ifdef = 0;
|
||||
} else if (nl && noex == 0) {
|
||||
uchar *c, *och = stringbuf;
|
||||
usch *och = stringbuf;
|
||||
int i;
|
||||
|
||||
c = gotident(nl);
|
||||
unch(1);
|
||||
unpstr(c);
|
||||
i = kfind(nl);
|
||||
unch(WARN);
|
||||
if (i)
|
||||
unpstr(stringbuf);
|
||||
else
|
||||
unpstr(nl->namep);
|
||||
stringbuf = och;
|
||||
noex = 1;
|
||||
return yylex();
|
||||
@@ -613,7 +676,7 @@ yylex()
|
||||
}
|
||||
yylval.node.op = NUMBER;
|
||||
return NUMBER;
|
||||
case 1: /* WARN */
|
||||
case WARN:
|
||||
noex = 0;
|
||||
return yylex();
|
||||
default:
|
||||
@@ -623,7 +686,7 @@ yylex()
|
||||
return ch;
|
||||
}
|
||||
|
||||
uchar *yyp, yybuf[CPPBUF];
|
||||
usch *yyp, yybuf[CPPBUF];
|
||||
|
||||
int yywrap(void);
|
||||
|
||||
@@ -671,41 +734,6 @@ msdos: if ((c = inpch()) == '\n') {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(initial dst) + strlen(src); if retval >= siz,
|
||||
* truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
|
||||
/*
|
||||
* Let the command-line args be faked defines at beginning of file.
|
||||
*/
|
||||
@@ -754,28 +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)
|
||||
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;
|
||||
@@ -792,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;
|
||||
@@ -806,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;
|
||||
}
|
||||
@@ -819,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));
|
||||
@@ -838,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) {
|
||||
@@ -871,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++;
|
||||
@@ -898,7 +927,7 @@ cvtdig(int rad)
|
||||
}
|
||||
|
||||
static int
|
||||
charcon(uchar *p)
|
||||
charcon(usch *p)
|
||||
{
|
||||
int val, c;
|
||||
|
||||
@@ -991,8 +1020,8 @@ skpln(void)
|
||||
}
|
||||
|
||||
static void
|
||||
ifdefstmt(void)
|
||||
{
|
||||
ifdefstmt(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (flslvl) {
|
||||
@@ -1004,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
|
||||
@@ -1013,8 +1042,8 @@ ifdefstmt(void)
|
||||
}
|
||||
|
||||
static void
|
||||
ifndefstmt(void)
|
||||
{
|
||||
ifndefstmt(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (flslvl) {
|
||||
@@ -1026,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
|
||||
@@ -1035,7 +1064,7 @@ ifndefstmt(void)
|
||||
}
|
||||
|
||||
static void
|
||||
endifstmt(void)
|
||||
endifstmt(void)
|
||||
{
|
||||
if (flslvl) {
|
||||
flslvl--;
|
||||
@@ -1092,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);
|
||||
@@ -1108,7 +1137,7 @@ svinp(void)
|
||||
static void
|
||||
cpperror(void)
|
||||
{
|
||||
uchar *cp;
|
||||
usch *cp;
|
||||
int c;
|
||||
|
||||
if (flslvl)
|
||||
@@ -1126,7 +1155,7 @@ cpperror(void)
|
||||
static void
|
||||
cppwarning(void)
|
||||
{
|
||||
uchar *cp;
|
||||
usch *cp;
|
||||
int c;
|
||||
|
||||
if (flslvl)
|
||||
@@ -1156,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);
|
||||
}
|
||||
@@ -1169,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)
|
||||
@@ -1263,7 +1292,7 @@ ppdir(void)
|
||||
goto out; /* something else, ignore */
|
||||
i = 0;
|
||||
do {
|
||||
bp[i++] = (uchar)ch;
|
||||
bp[i++] = (usch)ch;
|
||||
if (i == sizeof(bp)-1)
|
||||
goto out; /* too long */
|
||||
ch = inch();
|
||||
|
||||
1
src/cmd/emg/.gitignore
vendored
Normal file
1
src/cmd/emg/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
emg
|
||||
53
src/cmd/emg/ChangeLog
Normal file
53
src/cmd/emg/ChangeLog
Normal file
@@ -0,0 +1,53 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
July 10, 2014 : emg 1.7
|
||||
-----------------------
|
||||
Searching now correctly updates line number display.
|
||||
Remove lots of rarely-used word functions.
|
||||
Remove search+replace: sed(1) is quicker.
|
||||
Reduce size of some static buffers.
|
||||
|
||||
May 29, 2014 : emg 1.6
|
||||
----------------------
|
||||
emg is now part of the RetroBSD tree.
|
||||
Add PgUp and PgDn scrolling.
|
||||
|
||||
March 16, 2014 : emg 1.5
|
||||
------------------------
|
||||
Add line number to the mode line.
|
||||
Implement prompted go to line function.
|
||||
Remove lesser used expensive movement functions.
|
||||
Documentation tweaks to reflect above changes.
|
||||
|
||||
March 9, 2014 : emg 1.4
|
||||
-----------------------
|
||||
Huge whitespace cleanup.
|
||||
Make the window creation code mode consistent.
|
||||
Small documentation fix.
|
||||
|
||||
March 8, 2014 : emg 1.3
|
||||
-----------------------
|
||||
Remove all OpenBSD support. emg is now for RetroBSD only.
|
||||
Remove tmux alternative keybindings.
|
||||
Revert Listbuffer command back to CTRL-x CTRL-b.
|
||||
|
||||
December 2, 2013 : emg 1.2
|
||||
--------------------------
|
||||
Alternate keybindings for RetroBSD users using flow control terminal emulators.
|
||||
Alternate keybindings for tmux users who are using the default control command.
|
||||
|
||||
October 24, 2013 : emg 1.1
|
||||
--------------------------
|
||||
Listbuffer command is now CTRL-x l (originally CTRL-x CTRL-b).
|
||||
This is because the default command keybinding of tmux is CTRL-b.
|
||||
Search is now executed with <ENTER> instead of <ESC>.
|
||||
<ESC> felt awkward, plus I don't search for newlines.
|
||||
Lots of code cleanups (ttyio.c).
|
||||
Removal of unused #if blocks.
|
||||
Use panic() everywhere.
|
||||
Fix all warnings from gcc -Wall.
|
||||
|
||||
October 19, 2013 : emg 1.0
|
||||
--------------------------
|
||||
Initial version of emg. Current targets are OpenBSD and RetroBSD.
|
||||
49
src/cmd/emg/Makefile
Normal file
49
src/cmd/emg/Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
# emg Makefile
|
||||
# for RetroBSD
|
||||
|
||||
TOPSRC = $(shell cd ../../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
|
||||
# Some basic CFLAGS.
|
||||
CFLAGS = -Os -Wall -Werror
|
||||
|
||||
# With the extra LDFLAGS, save some bytes.
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
|
||||
# This reduces code size significantly.
|
||||
CFLAGS += -mips16
|
||||
|
||||
# Set the screen size.
|
||||
# Will default to FORCE_COLS=80 and FORCE_ROWS=24
|
||||
# if not set here.
|
||||
#CFLAGS += -DFORCE_COLS=80 -DFORCE_ROWS=24
|
||||
|
||||
# with CFLAGS+= -ffunction-sections -fdata-sections
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
LIBS = -ltermcap -lc
|
||||
|
||||
MAN = emg.0
|
||||
MANSRC = emg.1
|
||||
|
||||
OBJS = basic.o buffer.o display.o file.o fileio.o line.o main.o \
|
||||
random.o region.o search.o tcap.o ttyio.o window.o word.o
|
||||
|
||||
all: emg ${MAN}
|
||||
|
||||
emg: ${OBJS}
|
||||
${CC} ${LDFLAGS} -o emg.elf ${OBJS} ${LIBS}
|
||||
${OBJDUMP} -S emg.elf > emg.dis
|
||||
${SIZE} emg.elf
|
||||
${ELF2AOUT} emg.elf $@ && rm emg.elf
|
||||
|
||||
${MAN}: ${MANSRC}
|
||||
${MANROFF} ${MANSRC} > ${MAN}
|
||||
|
||||
install: all
|
||||
install emg ${DESTDIR}/bin/emg
|
||||
cp ${MAN} ${DESTDIR}/share/man/cat1/
|
||||
cp -p emg.keys ${DESTDIR}/share/emg.keys
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ *.core *.bak *.dis emg ${MAN}
|
||||
41
src/cmd/emg/README
Normal file
41
src/cmd/emg/README
Normal file
@@ -0,0 +1,41 @@
|
||||
emg
|
||||
===
|
||||
|
||||
emg, or Ersatz Mg, is a very tiny Emacs-like text editor created by
|
||||
combining elements of Ersatz Emacs and Mg (both the mg1a release and the
|
||||
current OpenBSD-maintained version).
|
||||
|
||||
The goal of this editor is to have something Emacs like for RetroBSD
|
||||
(a release of 2.11BSD for PIC32 microcontrollers). After noticing that the
|
||||
vi clone RetroBSD is using, VIrus, is GPL-licensed, I decided to provide
|
||||
a better-licensed editor. I also decided that, as a vi user myself, it would
|
||||
be easier to create an Emacs clone. Like you, I'm also unsure as to how that
|
||||
conclusion was reached.
|
||||
|
||||
I had initially tried to port Mg to RetroBSD but it was simply too large.
|
||||
Ersatz Emacs does not build on RetroBSD, as RetroBSD is missing some functions
|
||||
that Ersatz Emacs requires. It made sense to try to take from each and create
|
||||
an editor that would work.
|
||||
|
||||
In a way, emg has a double meaning: not only is it a combination of
|
||||
the two programs that comprise it, it is also a substitute Mg after my initial
|
||||
port failed.
|
||||
|
||||
I have cleaned up some code where necessary; emg builds without errors on
|
||||
RetroBSD.
|
||||
|
||||
Patches are also very welcome. I ask that you keep in mind the resource
|
||||
constraints of RetroBSD: everything must fit in 96K RAM. But of course,
|
||||
smaller is better.
|
||||
|
||||
I've left Chris Baird's Ersatz Emacs README here so others can better
|
||||
appreciate the history of this software.
|
||||
|
||||
As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain.
|
||||
|
||||
Versions of emg up to and including 1.2 also supported OpenBSD; OpenBSD
|
||||
has since dropped the older headers, such as sgtty.h, and it is not worth
|
||||
reimplementing these for OpenBSD since OpenBSD maintains Mg.
|
||||
|
||||
====================================
|
||||
Brian Callahan <bcallah@openbsd.org>
|
||||
39
src/cmd/emg/README-ERSATZ
Normal file
39
src/cmd/emg/README-ERSATZ
Normal file
@@ -0,0 +1,39 @@
|
||||
This shar file contains the source to a microemacs-derived text editor
|
||||
that I have been personally hacking on for over a decade.
|
||||
|
||||
Originally this was MicroEMACS 3.6 as released to mod.sources and the
|
||||
Public Domain by Daniel Lawrence in 1986, and was itself based on the
|
||||
work of Steve Wilhite and George Jones to MicroEMACS 2.0 (then also
|
||||
public domain) by Dave Conroy. I would like to reiterate Lawrence's
|
||||
thanks to them for writing such nice, well structured and documented
|
||||
code.
|
||||
|
||||
"Ersatz-Emacs", as I call it today, is the above text editor throughly
|
||||
cleansed of routines and features that I personally never use. It is
|
||||
also an editor MINIX-creator Andy Tanenbaum could describe as "fitting
|
||||
inside a student's brain" (namely, mine).
|
||||
|
||||
This source code should compile cleanly on any "modern" UN*X system
|
||||
with a termcap/curses library. This release has been tested with
|
||||
NetBSD and various Linux systems, although in the past when it was
|
||||
still mostly MicroEMACS, proto-Ersatz-Emacs was an editor of choice on
|
||||
SunOS, Solaris, Xenix, Minix/i386, and AIX. Supporting these and
|
||||
similar systems should not be difficult.
|
||||
|
||||
I encourage people to personalise this very simple editor to their own
|
||||
requirements. Please send any useful bug reports and fixes back to me,
|
||||
but I'm not really interested in incorporating new features unless it
|
||||
simplifies the program further. Feel free to do a code-fork and
|
||||
distribute your own perfect text editor.
|
||||
|
||||
The title "Ersatz" comes from the category Richard Stallman uses in
|
||||
MIT AI Memo 519a to describe those editors that are a surface-deep
|
||||
imitation (key bindings) of "real" ITS Emacs. If you are familiar with
|
||||
any Emacs-variant editor, you should have few problems with Ersatz.
|
||||
|
||||
All source code of this program is in the Public Domain. I am a rabid
|
||||
Stallmanite weenie, but it would be improper to publish this under a
|
||||
different licence than it was given to me with.
|
||||
|
||||
--
|
||||
Chris Baird,, <cjb@brushtail.apana.org.au>
|
||||
289
src/cmd/emg/basic.c
Normal file
289
src/cmd/emg/basic.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* The routines in this file move the cursor around on the screen. They
|
||||
* compute a new value for the cursor, then adjust ".". The display code
|
||||
* always updates the cursor location, so only moves between lines, or
|
||||
* functions that adjust the top line in the window and invalidate the
|
||||
* framing, are hard.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* atoi(3), ugh */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern int getccol(int bflg);
|
||||
extern void mlwrite();
|
||||
extern int mlreplyt();
|
||||
|
||||
int forwchar(int f, int n);
|
||||
int backchar(int f, int n);
|
||||
int forwline(int f, int n);
|
||||
int backline(int f, int n);
|
||||
int pagedown(int f, int n);
|
||||
int pageup(int f, int n);
|
||||
|
||||
/*
|
||||
* This routine, given a pointer to a LINE, and the current cursor goal
|
||||
* column, return the best choice for the offset. The offset is returned.
|
||||
* Used by "C-N" and "C-P".
|
||||
*/
|
||||
long getgoal(LINE *dlp)
|
||||
{
|
||||
int col = 0;
|
||||
int dbo = 0;
|
||||
int newcol, c;
|
||||
|
||||
while (dbo != llength(dlp))
|
||||
{
|
||||
c = lgetc(dlp, dbo);
|
||||
newcol = col;
|
||||
if (c == '\t')
|
||||
newcol |= 0x07;
|
||||
else if (c < 0x20 || c == 0x7F)
|
||||
++newcol;
|
||||
++newcol;
|
||||
if (newcol > curgoal)
|
||||
break;
|
||||
col = newcol;
|
||||
++dbo;
|
||||
}
|
||||
return (dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor to the
|
||||
* beginning of the current line.
|
||||
* Trivial.
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int gotobol(int f, int n)
|
||||
{
|
||||
curwp->w_doto = 0;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor to the end of the current line. Trivial. No errors.
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int gotoeol(int f, int n)
|
||||
{
|
||||
curwp->w_doto = llength(curwp->w_dotp);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor backwards by "n" characters. If "n" is less than zero call
|
||||
* "forwchar" to actually do the move. Otherwise compute the new cursor
|
||||
* location. Error if you try and move out of the buffer. Set the flag if the
|
||||
* line pointer for dot changes.
|
||||
*/
|
||||
int backchar(int f, int n)
|
||||
{
|
||||
LINE *lp;
|
||||
|
||||
if (n < 0)
|
||||
return (forwchar(f, -n));
|
||||
while (n--)
|
||||
{
|
||||
if (curwp->w_doto == 0)
|
||||
{
|
||||
if ((lp = lback(curwp->w_dotp)) == curbp->b_linep)
|
||||
return (FALSE);
|
||||
curwp->w_dotp = lp;
|
||||
curwp->w_doto = llength(lp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
curwp->w_dotline--;
|
||||
}
|
||||
else
|
||||
curwp->w_doto--;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor forwards by "n" characters. If "n" is less than zero call
|
||||
* "backchar" to actually do the move. Otherwise compute the new cursor
|
||||
* location, and move ".". Error if you try and move off the end of the
|
||||
* buffer. Set the flag if the line pointer for dot changes.
|
||||
*/
|
||||
int forwchar(int f, int n)
|
||||
{
|
||||
if (n < 0)
|
||||
return (backchar(f, -n));
|
||||
while (n--)
|
||||
{
|
||||
if (curwp->w_doto == llength(curwp->w_dotp))
|
||||
{
|
||||
if (curwp->w_dotp == curbp->b_linep)
|
||||
return (FALSE);
|
||||
curwp->w_dotp = lforw(curwp->w_dotp);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
curwp->w_dotline++;
|
||||
}
|
||||
else
|
||||
curwp->w_doto++;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* move to a particular line. argument (n) must be a positive integer for this
|
||||
* to actually do anything
|
||||
*/
|
||||
int gotoline(int f, int n)
|
||||
{
|
||||
if ((n < 1) || (n > curwp->w_bufp->b_lines)) /* if a bogus argument...then leave */
|
||||
return (FALSE); /* but we should never get here */
|
||||
|
||||
/* first, we go to the start of the buffer */
|
||||
curwp->w_dotp = lforw(curbp->b_linep);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_dotline = 0; /* and reset the line number */
|
||||
return (forwline(f, n - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Prompt for which line number we want to go to, then execute gotoline()
|
||||
* with that number as its argument.
|
||||
*
|
||||
* Make sure the bounds are within the file.
|
||||
*
|
||||
* Bound to M-G
|
||||
*/
|
||||
int setline(int f, int n)
|
||||
{
|
||||
char setl[6];
|
||||
int l;
|
||||
|
||||
(void)mlreplyt("Go to line: ", setl, 6, 10);
|
||||
l = atoi(setl); /* XXX: This sucks! */
|
||||
|
||||
if (l < 1)
|
||||
l = 1;
|
||||
else if (l > curwp->w_bufp->b_lines)
|
||||
l = curwp->w_bufp->b_lines;
|
||||
|
||||
gotoline(f, l);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Goto the beginning of the buffer. Massive adjustment of dot. This is
|
||||
* considered to be hard motion; it really isn't if the original value of dot
|
||||
* is the same as the new value of dot. Normally bound to "M-<".
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int gotobob(int f, int n)
|
||||
{
|
||||
curwp->w_dotp = lforw(curbp->b_linep);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFHARD;
|
||||
curwp->w_dotline = 0;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the end of the buffer. Dot is always put at the end of the file
|
||||
* (ZJ). The standard screen code does most of the hard parts of update.
|
||||
* Bound to "M->".
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int gotoeob(int f, int n)
|
||||
{
|
||||
curwp->w_dotp = curbp->b_linep;
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFHARD;
|
||||
curwp->w_dotline = curwp->w_bufp->b_lines;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move forward by full lines. If the number of lines to move is less than
|
||||
* zero, call the backward line function to actually do it. The last command
|
||||
* controls how the goal column is set. Bound to "C-N". No errors are possible.
|
||||
*/
|
||||
int forwline(int f, int n)
|
||||
{
|
||||
LINE *dlp;
|
||||
|
||||
if (n < 0)
|
||||
return (backline(f, -n));
|
||||
if ((lastflag & CFCPCN) == 0)/* Reset goal if last */
|
||||
curgoal = getccol(FALSE); /* not C-P or C-N */
|
||||
thisflag |= CFCPCN;
|
||||
dlp = curwp->w_dotp;
|
||||
while (n-- && dlp != curbp->b_linep)
|
||||
{
|
||||
dlp = lforw(dlp);
|
||||
curwp->w_dotline++;
|
||||
}
|
||||
curwp->w_dotp = dlp;
|
||||
curwp->w_doto = getgoal(dlp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is like "forwline", but goes backwards. The scheme is exactly
|
||||
* the same. Check for arguments that are less than zero and call your
|
||||
* alternate. Figure out the new line and call "movedot" to perform the
|
||||
* motion. No errors are possible. Bound to "C-P".
|
||||
*/
|
||||
int backline(int f, int n)
|
||||
{
|
||||
LINE *dlp;
|
||||
|
||||
if (n < 0)
|
||||
return (forwline(f, -n));
|
||||
if ((lastflag & CFCPCN) == 0)/* Reset goal if the */
|
||||
curgoal = getccol(FALSE); /* last isn't C-P, C-N */
|
||||
thisflag |= CFCPCN;
|
||||
dlp = curwp->w_dotp;
|
||||
while (n-- && lback(dlp) != curbp->b_linep)
|
||||
{
|
||||
dlp = lback(dlp);
|
||||
curwp->w_dotline--;
|
||||
}
|
||||
curwp->w_dotp = dlp;
|
||||
curwp->w_doto = getgoal(dlp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* PgDn. Scroll down (FORCE_ROWS - 1).
|
||||
* Just forwline(f, (FORCE_ROWS -1))
|
||||
* Bound to C-V
|
||||
*/
|
||||
int pagedown(int f, int n)
|
||||
{
|
||||
forwline(f, (FORCE_ROWS - 1));
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* PgUp. Scroll up (FORCE_ROWS - 1).
|
||||
* Just backline(f, (FORCE_ROWS -1))
|
||||
* Bound to M-V
|
||||
*/
|
||||
int pageup(int f, int n)
|
||||
{
|
||||
backline(f, (FORCE_ROWS - 1));
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the mark in the current window to the value of "." in the window. No
|
||||
* errors are possible. Bound to "M-.".
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int setmark(int f, int n)
|
||||
{
|
||||
curwp->w_markp = curwp->w_dotp;
|
||||
curwp->w_marko = curwp->w_doto;
|
||||
mlwrite("[Mark set]");
|
||||
return (TRUE);
|
||||
}
|
||||
494
src/cmd/emg/buffer.c
Normal file
494
src/cmd/emg/buffer.c
Normal file
@@ -0,0 +1,494 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* Buffer management. Some of the functions are internal, and some are actually
|
||||
* attached to user keys. Like everyone else, they set hints for the display
|
||||
* system.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* free(3), malloc(3) */
|
||||
#include <string.h> /* strncpy(3) */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern int mlreply(char *prompt, char *buf, int nbuf);
|
||||
extern int readin(char fname[]);
|
||||
extern void mlwrite();
|
||||
extern void mlerase();
|
||||
extern int mlyesno(char *prompt);
|
||||
extern void lfree(LINE *lp);
|
||||
extern WINDOW *wpopup();
|
||||
extern LINE *lalloc();
|
||||
|
||||
int swbuffer(BUFFER *bp);
|
||||
int usebuffer(int f, int n);
|
||||
int nextbuffer(int f, int n);
|
||||
int killbuffer(int f, int n);
|
||||
int zotbuf(BUFFER *bp);
|
||||
int namebuffer(int f, int n);
|
||||
int listbuffers(int f, int n);
|
||||
int makelist();
|
||||
void itoa(char buf[], int width, int num);
|
||||
int addline(char *text);
|
||||
int anycb();
|
||||
BUFFER* bfind(char *bname, int cflag, int bflag);
|
||||
int bclear(BUFFER *bp);
|
||||
|
||||
/*
|
||||
* make buffer BP current
|
||||
*/
|
||||
int swbuffer(BUFFER *bp)
|
||||
{
|
||||
WINDOW *wp;
|
||||
|
||||
if (--curbp->b_nwnd == 0)
|
||||
{ /* Last use. */
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
}
|
||||
curbp = bp; /* Switch. */
|
||||
if (curbp->b_active != TRUE)
|
||||
{ /* buffer not active yet */
|
||||
/* read it in and activate it */
|
||||
readin(curbp->b_fname);
|
||||
curbp->b_dotp = lforw(curbp->b_linep);
|
||||
curbp->b_doto = 0;
|
||||
curbp->b_active = TRUE;
|
||||
}
|
||||
curwp->w_bufp = bp;
|
||||
curwp->w_linep = bp->b_linep; /* For macros, ignored */
|
||||
curwp->w_flag |= WFMODE | WFFORCE | WFHARD; /* Quite nasty */
|
||||
if (bp->b_nwnd++ == 0)
|
||||
{ /* First use */
|
||||
curwp->w_dotp = bp->b_dotp;
|
||||
curwp->w_doto = bp->b_doto;
|
||||
curwp->w_markp = bp->b_markp;
|
||||
curwp->w_marko = bp->b_marko;
|
||||
return (TRUE);
|
||||
}
|
||||
wp = wheadp; /* Look for old */
|
||||
while (wp != 0)
|
||||
{
|
||||
if (wp != curwp && wp->w_bufp == bp)
|
||||
{
|
||||
curwp->w_dotp = wp->w_dotp;
|
||||
curwp->w_doto = wp->w_doto;
|
||||
curwp->w_markp = wp->w_markp;
|
||||
curwp->w_marko = wp->w_marko;
|
||||
break;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach a buffer to a window. The values of dot and mark come from the buffer
|
||||
* if the use count is 0. Otherwise, they come from some other window.
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int usebuffer(int f, int n)
|
||||
{
|
||||
BUFFER *bp;
|
||||
char bufn[NBUFN];
|
||||
int s;
|
||||
|
||||
if ((s = mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
|
||||
return (s);
|
||||
if ((bp = bfind(bufn, TRUE, 0)) == NULL)
|
||||
return (FALSE);
|
||||
return (swbuffer(bp));
|
||||
}
|
||||
|
||||
/* switch to the next buffer in the buffer list
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int nextbuffer(int f, int n)
|
||||
{
|
||||
BUFFER *bp;
|
||||
|
||||
bp = curbp->b_bufp;
|
||||
/* cycle through the buffers to find an eligable one */
|
||||
while ((bp == NULL) || (bp->b_flag & BFTEMP))
|
||||
{
|
||||
if (bp == NULL)
|
||||
bp = bheadp;
|
||||
else
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
return (swbuffer(bp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispose of a buffer, by name. Ask for the name. Look it up (don't get too
|
||||
* upset if it isn't there at all!). Get quite upset if the buffer is being
|
||||
* displayed. Clear the buffer (ask if the buffer has been changed). Then free
|
||||
* the header line and the buffer header. Bound to "C-X K".
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int killbuffer(int f, int n)
|
||||
{
|
||||
BUFFER *bp;
|
||||
char bufn[NBUFN];
|
||||
int s;
|
||||
|
||||
if ((s = mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
|
||||
return (s);
|
||||
if ((bp = bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown */
|
||||
return (TRUE);
|
||||
return (zotbuf(bp));
|
||||
}
|
||||
|
||||
/* kill the buffer pointed to by bp */
|
||||
int zotbuf(BUFFER *bp)
|
||||
{
|
||||
BUFFER *bp1, *bp2;
|
||||
int s;
|
||||
|
||||
if (bp->b_nwnd != 0)
|
||||
{ /* Error if on screen */
|
||||
mlwrite("Buffer is being displayed");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((s = bclear(bp)) != TRUE) /* Blow text away */
|
||||
return (s);
|
||||
free (bp->b_linep); /* Release header line */
|
||||
bp1 = 0; /* Find the header */
|
||||
bp2 = bheadp;
|
||||
while (bp2 != bp)
|
||||
{
|
||||
bp1 = bp2;
|
||||
bp2 = bp2->b_bufp;
|
||||
}
|
||||
bp2 = bp2->b_bufp; /* Next one in chain */
|
||||
if (bp1 == NULL) /* Unlink it */
|
||||
bheadp = bp2;
|
||||
else
|
||||
bp1->b_bufp = bp2;
|
||||
free(bp); /* Release buffer block */
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* Rename the current buffer */
|
||||
/* ARGSUSED0 */
|
||||
int namebuffer(int f, int n)
|
||||
{
|
||||
BUFFER *bp; /* pointer to scan through all buffers */
|
||||
char bufn[NBUFN]; /* buffer to hold buffer name */
|
||||
|
||||
/* prompt for and get the new buffer name */
|
||||
ask:
|
||||
if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
|
||||
return (FALSE);
|
||||
|
||||
/* and check for duplicates */
|
||||
bp = bheadp;
|
||||
while (bp != 0)
|
||||
{
|
||||
if (bp != curbp)
|
||||
{
|
||||
/* if the names the same */
|
||||
if (strcmp(bufn, bp->b_bname) == 0)
|
||||
goto ask; /* try again */
|
||||
}
|
||||
bp = bp->b_bufp; /* onward */
|
||||
}
|
||||
|
||||
strncpy(curbp->b_bname, bufn, NBUFN); /* copy buffer name to structure */
|
||||
curwp->w_flag |= WFMODE; /* make mode line replot */
|
||||
mlerase();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* List all of the active buffers. First update the special buffer that holds
|
||||
* the list. Next make sure at least 1 window is displaying the buffer list,
|
||||
* splitting the screen if this is what it takes. Lastly, repaint all of the
|
||||
* windows that are displaying the list. Bound to "C-X C-B".
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int listbuffers(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
BUFFER *bp;
|
||||
int s;
|
||||
|
||||
if ((s = makelist()) != TRUE)
|
||||
return (s);
|
||||
if (blistp->b_nwnd == 0)
|
||||
{ /* Not on screen yet */
|
||||
if ((wp = wpopup()) == NULL)
|
||||
return (FALSE);
|
||||
bp = wp->w_bufp;
|
||||
if (--bp->b_nwnd == 0)
|
||||
{
|
||||
bp->b_dotp = wp->w_dotp;
|
||||
bp->b_doto = wp->w_doto;
|
||||
bp->b_markp = wp->w_markp;
|
||||
bp->b_marko = wp->w_marko;
|
||||
}
|
||||
wp->w_bufp = blistp;
|
||||
++blistp->b_nwnd;
|
||||
}
|
||||
wp = wheadp;
|
||||
while (wp != 0)
|
||||
{
|
||||
if (wp->w_bufp == blistp)
|
||||
{
|
||||
wp->w_linep = lforw(blistp->b_linep);
|
||||
wp->w_dotp = lforw(blistp->b_linep);
|
||||
wp->w_doto = 0;
|
||||
wp->w_markp = 0;
|
||||
wp->w_marko = 0;
|
||||
wp->w_flag |= WFMODE | WFHARD;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine rebuilds the text in the special secret buffer that holds the
|
||||
* buffer list. It is called by the list buffers command. Return TRUE if
|
||||
* everything works. Return FALSE if there is an error (if there is no
|
||||
* memory).
|
||||
*/
|
||||
int makelist()
|
||||
{
|
||||
BUFFER *bp;
|
||||
LINE *lp;
|
||||
char *cp1, *cp2;
|
||||
char b[7], line[128];
|
||||
int nbytes, s, c;
|
||||
|
||||
blistp->b_flag &= ~BFCHG; /* Don't complain! */
|
||||
if ((s = bclear(blistp)) != TRUE) /* Blow old text away */
|
||||
return (s);
|
||||
strncpy (blistp->b_fname, "", 1);
|
||||
if (addline("AC Size Buffer File") == FALSE ||
|
||||
addline("-- ------- ------ ----") == FALSE)
|
||||
return (FALSE);
|
||||
bp = bheadp;
|
||||
|
||||
/* build line to report global mode settings */
|
||||
cp1 = &line[0];
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' ';
|
||||
|
||||
/* output the list of buffers */
|
||||
while (bp != 0)
|
||||
{
|
||||
if ((bp->b_flag & BFTEMP) != 0)
|
||||
{ /* Skip magic ones */
|
||||
bp = bp->b_bufp;
|
||||
continue;
|
||||
}
|
||||
cp1 = &line[0]; /* Start at left edge */
|
||||
|
||||
/* output status of ACTIVE flag (has the file been read in? */
|
||||
if (bp->b_active == TRUE) /* "@" if activated */
|
||||
*cp1++ = '@';
|
||||
else
|
||||
*cp1++ = ' ';
|
||||
|
||||
/* output status of changed flag */
|
||||
if ((bp->b_flag & BFCHG) != 0) /* "*" if changed */
|
||||
*cp1++ = '*';
|
||||
else
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' '; /* Gap */
|
||||
|
||||
nbytes = 0; /* Count bytes in buf */
|
||||
lp = lforw(bp->b_linep);
|
||||
while (lp != bp->b_linep)
|
||||
{
|
||||
nbytes += llength(lp) + 1;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
itoa(b, 6, nbytes); /* 6 digit buffer size */
|
||||
cp2 = &b[0];
|
||||
while ((c = *cp2++) != 0)
|
||||
*cp1++ = (char)c;
|
||||
*cp1++ = ' '; /* Gap */
|
||||
cp2 = &bp->b_bname[0]; /* Buffer name */
|
||||
while ((c = *cp2++) != 0)
|
||||
*cp1++ = (char)c;
|
||||
cp2 = &bp->b_fname[0]; /* File name */
|
||||
if (*cp2 != 0)
|
||||
{
|
||||
while (cp1 < &line[2 + 1 + 5 + 1 + 6 + 1 + NBUFN]) /* XXX ??? */
|
||||
*cp1++ = ' ';
|
||||
while ((c = *cp2++) != 0)
|
||||
{
|
||||
if (cp1 < &line[128 - 1])
|
||||
*cp1++ = (char)c;
|
||||
}
|
||||
}
|
||||
*cp1 = 0; /* Add to the buffer */
|
||||
if (addline(line) == FALSE)
|
||||
return (FALSE);
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
return (TRUE); /* All done */
|
||||
}
|
||||
|
||||
void itoa(char buf[], int width, int num)
|
||||
{
|
||||
buf[width] = 0; /* End of string */
|
||||
while (num >= 10)
|
||||
{ /* Conditional digits */
|
||||
buf[--width] = (char)((num % 10) + '0');
|
||||
num /= 10;
|
||||
}
|
||||
buf[--width] = (char)(num + '0'); /* Always 1 digit */
|
||||
while (width != 0) /* Pad with blanks */
|
||||
buf[--width] = ' ';
|
||||
}
|
||||
|
||||
/*
|
||||
* The argument "text" points to a string. Append this line to the buffer list
|
||||
* buffer. Handcraft the EOL on the end. Return TRUE if it worked and FALSE if
|
||||
* you ran out of room.
|
||||
*/
|
||||
int addline(char *text)
|
||||
{
|
||||
LINE *lp;
|
||||
int ntext, i;
|
||||
|
||||
ntext = strlen(text);
|
||||
if ((lp = lalloc(ntext)) == NULL)
|
||||
return (FALSE);
|
||||
for (i = 0; i < ntext; ++i)
|
||||
lputc(lp, i, text[i]);
|
||||
blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */
|
||||
lp->l_bp = blistp->b_linep->l_bp;
|
||||
blistp->b_linep->l_bp = lp;
|
||||
lp->l_fp = blistp->b_linep;
|
||||
if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */
|
||||
blistp->b_dotp = lp; /* move it to new line */
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look through the list of buffers. Return TRUE if there are any changed
|
||||
* buffers. Buffers that hold magic internal stuff are not considered; who
|
||||
* cares if the list of buffer names is hacked. Return FALSE if no buffers
|
||||
* have been changed.
|
||||
*/
|
||||
int anycb()
|
||||
{
|
||||
BUFFER *bp;
|
||||
|
||||
bp = bheadp;
|
||||
while (bp != NULL)
|
||||
{
|
||||
if ((bp->b_flag & BFTEMP) == 0 && (bp->b_flag & BFCHG) != 0)
|
||||
return (TRUE);
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a buffer, by name. Return a pointer to the BUFFER structure associated
|
||||
* with it. If the named buffer is found, but is a TEMP buffer (like the
|
||||
* buffer list) conplain. If the buffer is not found and the "cflag" is TRUE,
|
||||
* create it. The "bflag" is the settings for the flags in in buffer.
|
||||
*/
|
||||
BUFFER* bfind(char *bname, int cflag, int bflag)
|
||||
{
|
||||
BUFFER *bp, *sb;
|
||||
LINE *lp;
|
||||
|
||||
bp = bheadp;
|
||||
while (bp != 0)
|
||||
{
|
||||
if (strcmp(bname, bp->b_bname) == 0)
|
||||
{
|
||||
if ((bp->b_flag & BFTEMP) != 0)
|
||||
{
|
||||
mlwrite ("Cannot select builtin buffer");
|
||||
return (0);
|
||||
}
|
||||
return (bp);
|
||||
}
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
if (cflag != FALSE)
|
||||
{
|
||||
if ((bp = (BUFFER *) malloc(sizeof(BUFFER))) == NULL)
|
||||
return (0);
|
||||
if ((lp = lalloc(0)) == NULL)
|
||||
{
|
||||
free(bp);
|
||||
return (BUFFER*)0;
|
||||
}
|
||||
/* find the place in the list to insert this buffer */
|
||||
if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0)
|
||||
{
|
||||
/* insert at the begining */
|
||||
bp->b_bufp = bheadp;
|
||||
bheadp = bp;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb = bheadp;
|
||||
while (sb->b_bufp != 0)
|
||||
{
|
||||
if (strcmp(sb->b_bufp->b_bname, bname) > 0)
|
||||
break;
|
||||
sb = sb->b_bufp;
|
||||
}
|
||||
|
||||
/* and insert it */
|
||||
bp->b_bufp = sb->b_bufp;
|
||||
sb->b_bufp = bp;
|
||||
}
|
||||
|
||||
/* and set up the other buffer fields */
|
||||
bp->b_active = TRUE;
|
||||
bp->b_dotp = lp;
|
||||
bp->b_doto = 0;
|
||||
bp->b_markp = 0;
|
||||
bp->b_marko = 0;
|
||||
bp->b_flag = (char)bflag;
|
||||
bp->b_nwnd = 0;
|
||||
bp->b_linep = lp;
|
||||
bp->b_lines = 1;
|
||||
strncpy(bp->b_fname, "", 1);
|
||||
strncpy(bp->b_bname, bname, NBUFN);
|
||||
lp->l_fp = lp;
|
||||
lp->l_bp = lp;
|
||||
}
|
||||
return (bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine blows away all of the text in a buffer. If the buffer is
|
||||
* marked as changed then we ask if it is ok to blow it away; this is to save
|
||||
* the user the grief of losing text. The window chain is nearly always wrong
|
||||
* if this gets called; the caller must arrange for the updates that are
|
||||
* required. Return TRUE if everything looks good.
|
||||
*/
|
||||
int bclear(BUFFER *bp)
|
||||
{
|
||||
LINE *lp;
|
||||
int s;
|
||||
|
||||
if ((bp->b_flag & BFTEMP) == 0 /* Not scratch buffer */
|
||||
&& (bp->b_flag & BFCHG) != 0 /* Something changed */
|
||||
&& (s = mlyesno("Discard changes")) != TRUE)
|
||||
return (s);
|
||||
bp->b_flag &= ~BFCHG; /* Not changed */
|
||||
while ((lp = lforw(bp->b_linep)) != bp->b_linep)
|
||||
lfree(lp);
|
||||
bp->b_dotp = bp->b_linep; /* Fix "." */
|
||||
bp->b_doto = 0;
|
||||
bp->b_markp = 0; /* Invalidate "mark" */
|
||||
bp->b_marko = 0;
|
||||
bp->b_lines = 1;
|
||||
return (TRUE);
|
||||
}
|
||||
1015
src/cmd/emg/display.c
Normal file
1015
src/cmd/emg/display.c
Normal file
File diff suppressed because it is too large
Load Diff
67
src/cmd/emg/ebind.h
Normal file
67
src/cmd/emg/ebind.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* This table is *roughly* in ASCII order, left to right across the
|
||||
* characters of the command. This expains the funny location of the
|
||||
* control-X commands.
|
||||
*/
|
||||
|
||||
KEYTAB keytab[] = {
|
||||
{CTRL | 'A', gotobol},
|
||||
{CTRL | 'B', backchar},
|
||||
{CTRL | 'D', forwdel},
|
||||
{CTRL | 'E', gotoeol},
|
||||
{CTRL | 'F', forwchar},
|
||||
{CTRL | 'G', ctrlg},
|
||||
{CTRL | 'H', backdel},
|
||||
{CTRL | 'I', tab},
|
||||
{CTRL | 'K', killtext},
|
||||
{CTRL | 'L', refresh},
|
||||
{CTRL | 'M', newline},
|
||||
{CTRL | 'N', forwline},
|
||||
{CTRL | 'O', openline},
|
||||
{CTRL | 'P', backline},
|
||||
{CTRL | 'Q', quote},
|
||||
{CTRL | 'R', backsearch},
|
||||
{CTRL | 'S', forwsearch},
|
||||
{CTRL | 'T', twiddle},
|
||||
{CTRL | 'V', pagedown},
|
||||
{CTRL | 'W', killregion},
|
||||
{CTRL | 'Y', yank},
|
||||
{CTLX | '(', ctlxlp},
|
||||
{CTLX | ')', ctlxrp},
|
||||
{CTLX | '1', onlywind},
|
||||
{CTLX | '2', splitwind},
|
||||
{CTLX | 'B', usebuffer},
|
||||
{CTLX | 'E', ctlxe},
|
||||
{CTLX | 'F', setfillcol},
|
||||
{CTLX | 'K', killbuffer},
|
||||
{CTLX | 'N', filename},
|
||||
{CTLX | 'O', nextwind},
|
||||
{CTLX | 'S', filesave}, /* non-standard */
|
||||
{CTLX | 'Q', quote}, /* non-standard */
|
||||
{CTLX | 'X', nextbuffer},
|
||||
{CTLX | '^', enlargewind},
|
||||
{CTLX | CTRL | 'B', listbuffers},
|
||||
{CTLX | CTRL | 'C', quit},
|
||||
{CTLX | CTRL | 'F', filefind},
|
||||
{CTLX | CTRL | 'I', insfile},
|
||||
{CTLX | CTRL | 'R', fileread},
|
||||
{CTLX | CTRL | 'S', filesave},
|
||||
{CTLX | CTRL | 'W', filewrite},
|
||||
{META | '.', setmark},
|
||||
{META | '<', gotobob},
|
||||
{META | '>', gotoeob},
|
||||
{META | 'B', backword},
|
||||
{META | 'F', forwword},
|
||||
{META | 'G', setline}, /* non-standard */
|
||||
{META | 'S', forwsearch}, /* non-standard */
|
||||
{META | 'V', pageup},
|
||||
{META | 'W', copyregion},
|
||||
{META | 'Z', quickexit},
|
||||
{META | CTRL | 'N', namebuffer},
|
||||
{0x7F, backdel},
|
||||
{META | '[', extendedcmd},
|
||||
{META | 'O', extendedcmd},
|
||||
{0, 0}
|
||||
};
|
||||
78
src/cmd/emg/edef.h
Normal file
78
src/cmd/emg/edef.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#ifdef maindef
|
||||
/*
|
||||
* for MAIN.C
|
||||
* initialized global definitions
|
||||
*/
|
||||
|
||||
short kbdm[NKBDM] = {CTLX | ')'}; /* Macro */
|
||||
int fillcol = 72; /* Current fill column */
|
||||
char pat[NPAT]; /* Search pattern */
|
||||
char rpat[NPAT]; /* replacement pattern */
|
||||
int revexist = FALSE;
|
||||
int eolexist = TRUE; /* does clear to EOL exist */
|
||||
int sgarbf = TRUE; /* TRUE if screen is garbage */
|
||||
int mpresf = FALSE; /* TRUE if message in last line */
|
||||
|
||||
/* uninitialized global definitions */
|
||||
|
||||
int currow; /* Cursor row */
|
||||
int curcol; /* Cursor column */
|
||||
int thisflag; /* Flags, this command */
|
||||
int lastflag; /* Flags, last command */
|
||||
int curgoal; /* Goal for C-P, C-N */
|
||||
WINDOW *curwp; /* Current window */
|
||||
BUFFER *curbp; /* Current buffer */
|
||||
WINDOW *wheadp; /* Head of list of windows */
|
||||
BUFFER *bheadp; /* Head of list of buffers */
|
||||
BUFFER *blistp; /* Buffer for C-X C-B */
|
||||
short *kbdmip; /* Input pointer for above */
|
||||
short *kbdmop; /* Output pointer for above */
|
||||
|
||||
#else
|
||||
/*
|
||||
* for all the other .C files
|
||||
* initialized global external declarations
|
||||
*/
|
||||
|
||||
extern int fillcol; /* Fill column */
|
||||
extern short kbdm[]; /* Holds kayboard macro data */
|
||||
extern char pat[]; /* Search pattern */
|
||||
extern char rpat[]; /* Replacement pattern */
|
||||
extern int eolexist; /* does clear to EOL exist? */
|
||||
extern int revexist; /* does reverse video exist? */
|
||||
extern char *modename[]; /* text names of modes */
|
||||
extern char modecode[]; /* letters to represent modes */
|
||||
extern KEYTAB keytab[]; /* key bind to functions table */
|
||||
extern int gmode; /* global editor mode */
|
||||
extern int sgarbf; /* State of screen unknown */
|
||||
extern int mpresf; /* Stuff in message line */
|
||||
extern int clexec; /* command line execution flag */
|
||||
|
||||
/* initialized global external declarations */
|
||||
|
||||
extern int currow; /* Cursor row */
|
||||
extern int curcol; /* Cursor column */
|
||||
extern int thisflag; /* Flags, this command */
|
||||
extern int lastflag; /* Flags, last command */
|
||||
extern int curgoal; /* Goal for C-P, C-N */
|
||||
extern WINDOW *curwp; /* Current window */
|
||||
extern BUFFER *curbp; /* Current buffer */
|
||||
extern WINDOW *wheadp; /* Head of list of windows */
|
||||
extern BUFFER *bheadp; /* Head of list of buffers */
|
||||
extern BUFFER *blistp; /* Buffer for C-X C-B */
|
||||
extern short *kbdmip; /* Input pointer for above */
|
||||
extern short *kbdmop; /* Output pointer for above */
|
||||
|
||||
#endif
|
||||
|
||||
/* terminal table defined only in TERM.C */
|
||||
|
||||
#ifndef termdef
|
||||
extern TERM term; /* Terminal information */
|
||||
#endif
|
||||
65
src/cmd/emg/efunc.h
Normal file
65
src/cmd/emg/efunc.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/* EFUNC.H: function declarations and names
|
||||
*
|
||||
* This file list all the C code functions used. To add functions, declare it
|
||||
* here in both the extern function list and the name binding table
|
||||
*/
|
||||
|
||||
extern int ctrlg(); /* Abort out of things */
|
||||
extern int quit(); /* Quit */
|
||||
extern int ctlxlp(); /* Begin macro */
|
||||
extern int ctlxrp(); /* End macro */
|
||||
extern int ctlxe(); /* Execute macro */
|
||||
extern int fileread(); /* Get a file, read only */
|
||||
extern int filefind(); /* Get a file, read write */
|
||||
extern int filewrite(); /* Write a file */
|
||||
extern int filesave(); /* Save current file */
|
||||
extern int filename(); /* Adjust file name */
|
||||
extern int getccol(); /* Get current column */
|
||||
extern int gotobol(); /* Move to start of line */
|
||||
extern int forwchar(); /* Move forward by characters */
|
||||
extern int gotoeol(); /* Move to end of line */
|
||||
extern int backchar(); /* Move backward by characters */
|
||||
extern int forwline(); /* Move forward by lines */
|
||||
extern int backline(); /* Move backward by lines */
|
||||
extern int pagedown(); /* PgDn */
|
||||
extern int pageup(); /* PgUp */
|
||||
extern int gotobob(); /* Move to start of buffer */
|
||||
extern int gotoeob(); /* Move to end of buffer */
|
||||
extern int setfillcol(); /* Set fill column */
|
||||
extern int setmark(); /* Set mark */
|
||||
extern int forwsearch(); /* Search forward */
|
||||
extern int backsearch(); /* Search backwards */
|
||||
extern int nextwind(); /* Move to the next window */
|
||||
extern int prevwind(); /* Move to the previous window */
|
||||
extern int onlywind(); /* Make current window only one */
|
||||
extern int splitwind(); /* Split current window */
|
||||
extern int enlargewind(); /* Enlarge display window */
|
||||
extern int shrinkwind(); /* Shrink window */
|
||||
extern int listbuffers(); /* Display list of buffers */
|
||||
extern int usebuffer(); /* Switch a window to a buffer */
|
||||
extern int killbuffer(); /* Make a buffer go away */
|
||||
extern int refresh(); /* Refresh the screen */
|
||||
extern int twiddle(); /* Twiddle characters */
|
||||
extern int tab(); /* Insert tab */
|
||||
extern int newline(); /* Insert CR-LF */
|
||||
extern int openline(); /* Open up a blank line */
|
||||
extern int quote(); /* Insert literal */
|
||||
extern int backword(); /* Backup by words */
|
||||
extern int forwword(); /* Advance by words */
|
||||
extern int forwdel(); /* Forward delete */
|
||||
extern int backdel(); /* Backward delete */
|
||||
extern int killtext(); /* Kill forward */
|
||||
extern int yank(); /* Yank back from killbuffer */
|
||||
extern int killregion(); /* Kill region */
|
||||
extern int copyregion(); /* Copy region to kill buffer */
|
||||
extern int quickexit(); /* low keystroke style exit */
|
||||
extern int setline(); /* go to a numbered line */
|
||||
extern int namebuffer(); /* rename the current buffer */
|
||||
extern int deskey(); /* describe a key's binding */
|
||||
extern int insfile(); /* insert a file */
|
||||
extern int nextbuffer(); /* switch to the next buffer */
|
||||
extern int forwhunt(); /* hunt forward for next match */
|
||||
extern int backhunt(); /* hunt backwards for next match */
|
||||
extern int extendedcmd(); /* parse ANSI/VT100 extended keys */
|
||||
62
src/cmd/emg/emg.1
Normal file
62
src/cmd/emg/emg.1
Normal file
@@ -0,0 +1,62 @@
|
||||
.\" This file is in the public domain.
|
||||
.\"
|
||||
.\" Basic emg man page.
|
||||
.\" As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain.
|
||||
.\"
|
||||
.Dd June 17, 2014
|
||||
.Os
|
||||
.Dt EMG 1
|
||||
.Sh NAME
|
||||
.Nm emg
|
||||
.Nd very small Emacs-like text editor
|
||||
.Sh SYNOPSIS
|
||||
.Nm emg
|
||||
.Op Ar
|
||||
.Sh DESCRIPTION
|
||||
.Nm ,
|
||||
or Ersatz Mg, is an Emacs-like text editor designed for RetroBSD
|
||||
and other memory-constrained environments.
|
||||
.Nm
|
||||
was originally created to fit into an operating environment of 96K of RAM,
|
||||
and one in which Mg did not fit and Ersatz Emacs did not build.
|
||||
By combining parts of each a working editor was created.
|
||||
.Pp
|
||||
When invoked without file arguments,
|
||||
.Nm
|
||||
creates a
|
||||
.Qq main
|
||||
buffer.
|
||||
This buffer must be renamed
|
||||
.Ic ( C-x n )
|
||||
in order to be saved
|
||||
.Ic ( C-x C-s ) .
|
||||
.Pp
|
||||
As both Ersatz Emacs and Mg are Public Domain,
|
||||
.Nm
|
||||
is also Public Domain.
|
||||
.Sh FILES
|
||||
There is a chart of key bindings in
|
||||
.Pa /usr/local/share/doc/emg/emg.keys .
|
||||
Consulting this file is a must.
|
||||
While
|
||||
.Nm
|
||||
strives to maintain compatibility with larger Emacs implementations,
|
||||
there may be features intentionally left unimplemented in order to keep
|
||||
.Nm
|
||||
as small as possible.
|
||||
.Sh AUTHORS
|
||||
.Nm
|
||||
is a combination of Ersatz Emacs and Mg and therefore all authors
|
||||
for both deserve credit.
|
||||
Ersatz Emacs and Mg were combined by
|
||||
.An Brian Callahan Aq Mt bcallah@openbsd.org
|
||||
to create
|
||||
.Nm .
|
||||
.Sh BUGS
|
||||
None known.
|
||||
However, patches are appreciated if any are found.
|
||||
.Sh TODO
|
||||
It would be nice to have automatic window resizing.
|
||||
It would also be nice if
|
||||
.Nm
|
||||
could clear the screen when quit, like Mg does.
|
||||
131
src/cmd/emg/emg.keys
Normal file
131
src/cmd/emg/emg.keys
Normal file
@@ -0,0 +1,131 @@
|
||||
emg keybindings (July 7, 2014)
|
||||
Based on Ersatz Emacs (2000/09/14)
|
||||
|
||||
M- means to use the <ESC> key prior to using another key
|
||||
^A means to use the control key at the same time as the 'A' key
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
MOVING THE CURSOR
|
||||
|
||||
^F Forward character M-F Forward word
|
||||
^B Backward character M-B Backward word
|
||||
^N Next line M-P Front of paragraph
|
||||
^P Previous line M-N End of paragraph
|
||||
^A Front of line M-< or [HOME] Start of file
|
||||
^E End of line M-> or [END] End of file
|
||||
^V or [PgDn] Scroll down M-V or [PgUp] Scroll up
|
||||
M-G Go to line Arrow keys are active
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
DELETING & INSERTING
|
||||
|
||||
<- Delete previous character M-<- Delete previous word
|
||||
^D Delete next character M-D Delete next word
|
||||
^K Delete to end of line ^O Insert line
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
FORMATTING & TRANSPOSING
|
||||
|
||||
^Q Quote next key, so that control codes may be entered into text. (or ^X Q)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
SEARCHING
|
||||
|
||||
^S Search forward from cursor position. Type in a string and end it with
|
||||
ENTER. Either case matches. (or M-S)
|
||||
^R As above, but reverse search from cursor position.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
COPYING AND MOVING
|
||||
|
||||
M-. Set mark at current position.
|
||||
^W Delete region.
|
||||
M-W Copy region to kill buffer.
|
||||
^Y Yank back kill buffer at cursor.
|
||||
|
||||
A region is defined as the area between this mark and the current cursor
|
||||
position. The kill buffer is the text which has been most recently deleted or
|
||||
copied.
|
||||
|
||||
Generally, the procedure for copying or moving text is:
|
||||
1) Mark out region using M-. at the beginning and move the cursor to
|
||||
the end.
|
||||
2) Delete it (with ^W) or copy it (with M-W) into the kill buffer.
|
||||
3) Move the cursor to the desired location and yank it back (with ^Y).
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
MULTIPLE BUFFERS
|
||||
|
||||
A buffer contains a COPY of a document being edited, and must be saved for
|
||||
changes to be kept. Many buffers may be activated at once.
|
||||
|
||||
^X B Switch to another buffer.
|
||||
^X ^B Show buffer directory in a window (^X 1 to remove).
|
||||
^X K Delete a non-displayed buffer.
|
||||
^X X Switch to next buffer in buffer list.
|
||||
^X N Change the filename associated with the buffer.
|
||||
M-^N Change the name of the buffer.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
READING FROM DISK
|
||||
|
||||
^X^F Find file; read into a new buffer created from filename.
|
||||
(This is the usual way to edit a new file.)
|
||||
^X^R Read file into current buffer, erasing its previous contents.
|
||||
No new buffer will be created.
|
||||
^X^I Insert file into current buffer at cursor's location.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
SAVING TO DISK
|
||||
|
||||
^X^S Save current buffer to disk, using the buffer's filename as the name of
|
||||
the disk file. Any disk file of that name will be overwritten. (or ^X S)
|
||||
^X^W Write current buffer to disk. Type in a new filename at the prompt to
|
||||
write to; it will also become the current buffer's filename.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
MULTIPLE WINDOWS
|
||||
|
||||
Many windows may be visible at once on the screen. Windows may show different
|
||||
parts of the same buffer, or each may display a different one.
|
||||
|
||||
^X 2 Split the current window in two ^X 1 Show only current window
|
||||
^X O Move cursor to next window ^X ^ Enlarge current window
|
||||
M-^V Scroll other window down M-^Z Scroll other window up
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
EXITING
|
||||
|
||||
^X^C Exit. Any unsaved files will require confirmation.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
MACROS
|
||||
|
||||
^X ( Start recording a keyboard macro. Typing ^G or an error aborts.
|
||||
^X ) Stop recording macro.
|
||||
^X E Execute macro.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
REPEAT & NUMBER PREFIX
|
||||
|
||||
^U<number> or M-<number>
|
||||
Number prefix and universal repeat. May be followed by an integer
|
||||
(default = 4) and repeats the next command that many times.
|
||||
Exceptions follow.
|
||||
^U<number>^L
|
||||
Reposition the cursor to a particular screen row; i.e., ^U0^L moves the
|
||||
cursor and the line it is on to the top of the screen. Negative numbers
|
||||
are from the bottom of the screen.
|
||||
^U<number>^X F
|
||||
Set the right margin to column <number> for paragraph formatting.
|
||||
^U<number>^X^
|
||||
Enlarge a split window by <number> rows. A negative number shrinks the
|
||||
window.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
SPECIAL KEYS
|
||||
|
||||
^G Cancel current command.
|
||||
^L Redraws the screen completely.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
191
src/cmd/emg/estruct.h
Normal file
191
src/cmd/emg/estruct.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/* ESTRUCT: Structure and preprocessor */
|
||||
|
||||
/* internal constants */
|
||||
#define NFILEN 32 /* maximum # of bytes, file name */
|
||||
#define NBUFN 16 /* maximum # of bytes, buffer name */
|
||||
#define NLINE 512 /* maximum # of bytes, line */
|
||||
#define NKBDM 128 /* maximum # of strokes, keyboard macro */
|
||||
#define NPAT 80 /* maximum # of bytes, pattern */
|
||||
#define HUGE 32700 /* Huge number for "impossible" row&col */
|
||||
|
||||
#define METACH 0x1B /* M- prefix, Control-[, ESC */
|
||||
#define BELL 0x07 /* a bell character */
|
||||
#define TAB 0x09 /* a tab character */
|
||||
|
||||
#define CTRL 0x0100 /* Control flag, or'ed in */
|
||||
#define META 0x0200 /* Meta flag, or'ed in */
|
||||
#define CTLX 0x0400 /* ^X flag, or'ed in */
|
||||
|
||||
#define FALSE 0 /* False, no, bad, etc */
|
||||
#define TRUE 1 /* True, yes, good, etc */
|
||||
#define ABORT 2 /* Death, ^G, abort, etc */
|
||||
|
||||
#define FIOSUC 0 /* File I/O, success */
|
||||
#define FIOFNF 1 /* File I/O, file not found */
|
||||
#define FIOEOF 2 /* File I/O, end of file */
|
||||
#define FIOERR 3 /* File I/O, error */
|
||||
#define FIOLNG 4 /* line longer than allowed len */
|
||||
|
||||
#define CFCPCN 0x0001 /* Last command was C-P, C-N */
|
||||
#define CFKILL 0x0002 /* Last command was a kill */
|
||||
|
||||
/*
|
||||
* screen constants
|
||||
* override with
|
||||
* CFLAGS += -DFORCE_COLS=XXX -DFORCE_ROWS=XXX
|
||||
*/
|
||||
#ifndef FORCE_COLS
|
||||
#define FORCE_COLS 80
|
||||
#endif
|
||||
|
||||
#ifndef FORCE_ROWS
|
||||
#define FORCE_ROWS 24
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX:
|
||||
* Default/sane(?) maximum column and row sizes.
|
||||
* Taken from mg1a.
|
||||
*
|
||||
* Let the user override these with
|
||||
* CFLAGS += -DMAXCOL=XXX -DMAXROW=XXX
|
||||
*/
|
||||
#ifndef MAXCOL
|
||||
#define MAXCOL 132
|
||||
#endif
|
||||
|
||||
#ifndef MAXROW
|
||||
#define MAXROW 66
|
||||
#endif
|
||||
|
||||
/*
|
||||
* There is a window structure allocated for every active display window. The
|
||||
* windows are kept in a big list, in top to bottom screen order, with the
|
||||
* listhead at "wheadp". Each window contains its own values of dot and mark.
|
||||
* The flag field contains some bits that are set by commands to guide
|
||||
* redisplay; although this is a bit of a compromise in terms of decoupling,
|
||||
* the full blown redisplay is just too expensive to run for every input
|
||||
* character
|
||||
*/
|
||||
typedef struct WINDOW
|
||||
{
|
||||
struct WINDOW *w_wndp; /* Next window */
|
||||
struct BUFFER *w_bufp; /* Buffer displayed in window */
|
||||
struct LINE *w_linep; /* Top line in the window */
|
||||
struct LINE *w_dotp; /* Line containing "." */
|
||||
long w_doto; /* Byte offset for "." */
|
||||
struct LINE *w_markp; /* Line containing "mark" */
|
||||
long w_marko; /* Byte offset for "mark" */
|
||||
char w_toprow; /* Origin 0 top row of window */
|
||||
char w_ntrows; /* # of rows of text in window */
|
||||
char w_force; /* If NZ, forcing row */
|
||||
char w_flag; /* Flags */
|
||||
int w_dotline; /* current line number of dot */
|
||||
} WINDOW;
|
||||
|
||||
#define WFFORCE 0x01 /* Window needs forced reframe */
|
||||
#define WFMOVE 0x02 /* Movement from line to line */
|
||||
#define WFEDIT 0x04 /* Editing within a line */
|
||||
#define WFHARD 0x08 /* Better to a full display */
|
||||
#define WFMODE 0x10 /* Update mode line */
|
||||
|
||||
/*
|
||||
* Text is kept in buffers. A buffer header, described below, exists for every
|
||||
* buffer in the system. The buffers are kept in a big list, so that commands
|
||||
* that search for a buffer by name can find the buffer header. There is a
|
||||
* safe store for the dot and mark in the header, but this is only valid if
|
||||
* the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
|
||||
* the buffer is kept in a circularly linked list of lines, with a pointer to
|
||||
* the header line in "b_linep". Buffers may be "Inactive" which means the
|
||||
* files accosiated with them have not been read in yet. These get read in at
|
||||
* "use buffer" time
|
||||
*/
|
||||
typedef struct BUFFER
|
||||
{
|
||||
struct BUFFER *b_bufp; /* Link to next BUFFER */
|
||||
struct LINE *b_dotp; /* Link to "." LINE structure */
|
||||
long b_doto; /* Offset of "." in above LINE */
|
||||
struct LINE *b_markp; /* The same as the above two, */
|
||||
long b_marko; /* but for the "mark" */
|
||||
struct LINE *b_linep; /* Link to the header LINE */
|
||||
char b_active; /* window activated flag */
|
||||
char b_nwnd; /* Count of windows on buffer */
|
||||
char b_flag; /* Flags */
|
||||
char b_fname[NFILEN]; /* File name */
|
||||
char b_bname[NBUFN]; /* Buffer name */
|
||||
int b_lines; /* Number of lines in file */
|
||||
} BUFFER;
|
||||
|
||||
#define BFTEMP 0x01 /* Internal temporary buffer */
|
||||
#define BFCHG 0x02 /* Changed since last write */
|
||||
|
||||
/*
|
||||
* The starting position of a region, and the size of the region in
|
||||
* characters, is kept in a region structure. Used by the region commands
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
struct LINE *r_linep; /* Origin LINE address */
|
||||
long r_offset; /* Origin LINE offset */
|
||||
long r_size; /* Length in characters */
|
||||
} REGION;
|
||||
|
||||
/*
|
||||
* All text is kept in circularly linked lists of "LINE" structures. These
|
||||
* begin at the header line (which is the blank line beyond the end of the
|
||||
* buffer). This line is pointed to by the "BUFFER". Each line contains a the
|
||||
* number of bytes in the line (the "used" size), the size of the text array,
|
||||
* and the text. The end of line is not stored as a byte; it's implied. Future
|
||||
* additions will include update hints, and a list of marks into the line
|
||||
*/
|
||||
typedef struct LINE
|
||||
{
|
||||
struct LINE *l_fp; /* Link to the next line */
|
||||
struct LINE *l_bp; /* Link to the previous line */
|
||||
int l_size; /* Allocated size */
|
||||
int l_used; /* Used size */
|
||||
char l_text[1]; /* A bunch of characters */
|
||||
} LINE;
|
||||
|
||||
#define lforw(lp) ((lp)->l_fp)
|
||||
#define lback(lp) ((lp)->l_bp)
|
||||
#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)
|
||||
#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
|
||||
#define llength(lp) ((lp)->l_used)
|
||||
|
||||
/*
|
||||
* The editor communicates with the display using a high level interface. A
|
||||
* "TERM" structure holds useful variables, and indirect pointers to routines
|
||||
* that do useful operations. The low level get and put routines are here too.
|
||||
* This lets a terminal, in addition to having non standard commands, have
|
||||
* funny get and put character code too. The calls might get changed to
|
||||
* "termp->t_field" style in the future, to make it possible to run more than
|
||||
* one terminal type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int t_nrow; /* Number of rows */
|
||||
int t_ncol; /* Number of columns */
|
||||
int t_margin; /* min margin for extended lines */
|
||||
int t_scrsiz; /* size of scroll region " */
|
||||
void (*t_open) (); /* Open terminal at the start */
|
||||
void (*t_close) (); /* Close terminal at end */
|
||||
int (*t_getchar) (); /* Get character from keyboard */
|
||||
void (*t_putchar) (); /* Put character to display */
|
||||
void (*t_flush) (); /* Flush output buffers */
|
||||
void (*t_move) (); /* Move the cursor, origin 0 */
|
||||
void (*t_eeol) (); /* Erase to end of line */
|
||||
void (*t_eeop) (); /* Erase to end of page */
|
||||
void (*t_beep) (); /* Beep */
|
||||
void (*t_rev) (); /* set reverse video state */
|
||||
} TERM;
|
||||
|
||||
/* structure for the table of initial key bindings */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short k_code; /* Key code */
|
||||
int (*k_fp) (); /* Routine to handle it */
|
||||
} KEYTAB;
|
||||
465
src/cmd/emg/file.c
Normal file
465
src/cmd/emg/file.c
Normal file
@@ -0,0 +1,465 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* The routines in this file handle the reading and writing of disk files.
|
||||
* All details about the reading and writing of the disk are in "fileio.c"
|
||||
*/
|
||||
|
||||
#include <string.h> /* strncpy(3) */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern int mlreply(char *prompt, char *buf, int nbuf);
|
||||
extern int swbuffer(BUFFER *bp);
|
||||
extern void mlwrite();
|
||||
extern int bclear(BUFFER *bp);
|
||||
extern int ffropen(char *fn);
|
||||
extern int ffgetline(char buf[], int nbuf);
|
||||
extern int ffwopen(char *fn);
|
||||
extern int ffclose();
|
||||
extern int ffputline(char buf[], int nbuf);
|
||||
extern BUFFER *bfind();
|
||||
extern LINE *lalloc();
|
||||
|
||||
int fileread(int f, int n);
|
||||
int insfile(int f, int n);
|
||||
int filefind(int f, int n);
|
||||
int getfile(char fname[]);
|
||||
int readin(char fname[]);
|
||||
void makename(char bname[], char fname[]);
|
||||
int filewrite(int f, int n);
|
||||
int filesave(int f, int n);
|
||||
int writeout(char *fn);
|
||||
int filename(int f, int n);
|
||||
int ifile(char fname[]);
|
||||
|
||||
/*
|
||||
* Read a file into the current buffer. This is really easy; all you do it
|
||||
* find the name of the file, and call the standard "read a file into the
|
||||
* current buffer" code. Bound to "C-X C-R"
|
||||
*/
|
||||
int fileread(int f, int n)
|
||||
{
|
||||
int s;
|
||||
char fname[NFILEN];
|
||||
|
||||
if ((s = mlreply("Read file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
return (readin(fname));
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a file into the current buffer. This is really easy; all you do it
|
||||
* find the name of the file, and call the standard "insert a file into the
|
||||
* current buffer" code. Bound to "C-X C-I".
|
||||
*/
|
||||
int insfile(int f, int n)
|
||||
{
|
||||
int s;
|
||||
char fname[NFILEN];
|
||||
|
||||
if ((s = mlreply("Insert file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
return (ifile(fname));
|
||||
}
|
||||
|
||||
/*
|
||||
* Select a file for editing. Look around to see if you can find the fine in
|
||||
* another buffer; if you can find it just switch to the buffer. If you cannot
|
||||
* find the file, create a new buffer, read in the text, and switch to the new
|
||||
* buffer. Bound to C-X C-F.
|
||||
*/
|
||||
int filefind(int f, int n)
|
||||
{
|
||||
char fname[NFILEN]; /* file user wishes to find */
|
||||
int s; /* status return */
|
||||
|
||||
if ((s = mlreply("Find file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
return (getfile(fname));
|
||||
}
|
||||
|
||||
int getfile(char fname[])
|
||||
{
|
||||
BUFFER *bp;
|
||||
LINE *lp;
|
||||
char bname[NBUFN]; /* buffer name to put file */
|
||||
int i, s;
|
||||
|
||||
for (bp = bheadp; bp != (BUFFER*)0; bp = bp->b_bufp)
|
||||
{
|
||||
if ((bp->b_flag & BFTEMP) == 0 && strcmp(bp->b_fname, fname) == 0)
|
||||
{
|
||||
if (--curbp->b_nwnd == 0)
|
||||
{
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
}
|
||||
swbuffer(bp);
|
||||
lp = curwp->w_dotp;
|
||||
i = curwp->w_ntrows / 2;
|
||||
while (i-- && lback(lp) != curbp->b_linep)
|
||||
lp = lback(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
mlwrite("[Old buffer]");
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
makename(bname, fname); /* New buffer name */
|
||||
while ((bp = bfind(bname, FALSE, 0)) != (BUFFER*)0)
|
||||
{
|
||||
s = mlreply("Buffer name: ", bname, NBUFN);
|
||||
if (s == ABORT) /* ^G to just quit */
|
||||
return (s);
|
||||
if (s == FALSE)
|
||||
{ /* CR to clobber it */
|
||||
makename(bname, fname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bp == (BUFFER*)0 && (bp = bfind(bname, TRUE, 0)) == (BUFFER*)0)
|
||||
{
|
||||
mlwrite("Cannot create buffer");
|
||||
return (FALSE);
|
||||
}
|
||||
if (--curbp->b_nwnd == 0)
|
||||
{ /* Undisplay */
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
}
|
||||
curbp = bp; /* Switch to it */
|
||||
curwp->w_bufp = bp;
|
||||
curbp->b_nwnd++;
|
||||
return (readin(fname)); /* Read it in */
|
||||
}
|
||||
|
||||
/*
|
||||
* Read file "fname" into the current buffer, blowing away any text found
|
||||
* there. Called by both the read and find commands. Return the final status
|
||||
* of the read. Also called by the mainline, to read in a file specified on
|
||||
* the command line as an argument.
|
||||
*/
|
||||
int readin(char fname[])
|
||||
{
|
||||
LINE *lp1, *lp2;
|
||||
WINDOW *wp;
|
||||
BUFFER *bp;
|
||||
char line[NLINE];
|
||||
int nbytes, s, i;
|
||||
int nline = 0; /* initialize here to silence a gcc warning */
|
||||
int lflag; /* any lines longer than allowed? */
|
||||
|
||||
bp = curbp; /* Cheap */
|
||||
if ((s = bclear(bp)) != TRUE) /* Might be old */
|
||||
return (s);
|
||||
bp->b_flag &= ~(BFTEMP | BFCHG);
|
||||
strncpy(bp->b_fname, fname, NFILEN);
|
||||
if ((s = ffropen(fname)) == FIOERR) /* Hard file open */
|
||||
goto out;
|
||||
if (s == FIOFNF)
|
||||
{ /* File not found */
|
||||
mlwrite("[New file]");
|
||||
goto out;
|
||||
}
|
||||
mlwrite("[Reading file]");
|
||||
lflag = FALSE;
|
||||
while ((s = ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG)
|
||||
{
|
||||
if (s == FIOLNG)
|
||||
lflag = TRUE;
|
||||
nbytes = strlen(line);
|
||||
if ((lp1 = lalloc(nbytes)) == NULL)
|
||||
{
|
||||
s = FIOERR; /* Keep message on the display */
|
||||
break;
|
||||
}
|
||||
lp2 = lback(curbp->b_linep);
|
||||
lp2->l_fp = lp1;
|
||||
lp1->l_fp = curbp->b_linep;
|
||||
lp1->l_bp = lp2;
|
||||
curbp->b_linep->l_bp = lp1;
|
||||
for (i = 0; i < nbytes; ++i)
|
||||
lputc(lp1, i, line[i]);
|
||||
++nline;
|
||||
}
|
||||
ffclose(); /* Ignore errors */
|
||||
if (s == FIOEOF)
|
||||
{ /* Don't zap message! */
|
||||
if (nline != 1)
|
||||
mlwrite("[Read %d lines]", nline);
|
||||
else
|
||||
mlwrite("[Read 1 line]");
|
||||
}
|
||||
if (lflag)
|
||||
{
|
||||
if (nline != 1)
|
||||
mlwrite("[Read %d lines: Long lines wrapped]", nline);
|
||||
else
|
||||
mlwrite("[Read 1 line: Long lines wrapped]");
|
||||
}
|
||||
curwp->w_bufp->b_lines = nline;
|
||||
out:
|
||||
for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
|
||||
{
|
||||
if (wp->w_bufp == curbp)
|
||||
{
|
||||
wp->w_linep = lforw(curbp->b_linep);
|
||||
wp->w_dotp = lforw(curbp->b_linep);
|
||||
wp->w_doto = 0;
|
||||
wp->w_markp = NULL;
|
||||
wp->w_marko = 0;
|
||||
wp->w_flag |= WFMODE | WFHARD;
|
||||
}
|
||||
}
|
||||
if (s == FIOERR || s == FIOFNF) /* False if error */
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a file name, and from it fabricate a buffer name. This routine knows
|
||||
* about the syntax of file names on the target system. I suppose that this
|
||||
* information could be put in a better place than a line of code.
|
||||
*/
|
||||
void makename(char bname[], char fname[])
|
||||
{
|
||||
char *cp1, *cp2;
|
||||
|
||||
cp1 = &fname[0];
|
||||
while (*cp1 != 0)
|
||||
++cp1;
|
||||
|
||||
while (cp1 != &fname[0] && cp1[-1] != '/')
|
||||
--cp1;
|
||||
cp2 = &bname[0];
|
||||
while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != ';')
|
||||
*cp2++ = *cp1++;
|
||||
*cp2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask for a file name, and write the contents of the current buffer to that
|
||||
* file. Update the remembered file name and clear the buffer changed flag.
|
||||
* This handling of file names is different from the earlier versions, and is
|
||||
* more compatable with Gosling EMACS than with ITS EMACS. Bound to "C-X C-W".
|
||||
*/
|
||||
int filewrite(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
char fname[NFILEN];
|
||||
int s;
|
||||
|
||||
if ((s = mlreply("Write file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
if ((s = writeout(fname)) == TRUE)
|
||||
{
|
||||
strncpy(curbp->b_fname, fname, NFILEN);
|
||||
curbp->b_flag &= ~BFCHG;
|
||||
wp = wheadp; /* Update mode lines */
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the contents of the current buffer in its associatd file. No nothing
|
||||
* if nothing has changed (this may be a bug, not a feature). Error if there
|
||||
* is no remembered file name for the buffer. Bound to "C-X C-S". May get
|
||||
* called by "C-Z"
|
||||
*/
|
||||
int filesave(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
int s;
|
||||
|
||||
if ((curbp->b_flag & BFCHG) == 0) /* Return, no changes */
|
||||
return (TRUE);
|
||||
if (curbp->b_fname[0] == 0)
|
||||
{ /* Must have a name */
|
||||
mlwrite("No file name");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((s = writeout(curbp->b_fname)) == TRUE)
|
||||
{
|
||||
curbp->b_flag &= ~BFCHG;
|
||||
wp = wheadp; /* Update mode lines */
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function performs the details of file writing. Uses the file
|
||||
* management routines in the "fileio.c" package. The number of lines written
|
||||
* is displayed. Sadly, it looks inside a LINE; provide a macro for this. Most
|
||||
* of the grief is error checking of some sort.
|
||||
*/
|
||||
int writeout(char *fn)
|
||||
{
|
||||
LINE *lp;
|
||||
int nline, s;
|
||||
|
||||
if ((s = ffwopen(fn)) != FIOSUC) /* Open writes message */
|
||||
return (FALSE);
|
||||
mlwrite("[Writing]"); /* tell us were writing */
|
||||
lp = lforw(curbp->b_linep); /* First line */
|
||||
nline = 0; /* Number of lines */
|
||||
while (lp != curbp->b_linep)
|
||||
{
|
||||
if ((s = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
|
||||
break;
|
||||
++nline;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
if (s == FIOSUC)
|
||||
{ /* No write error */
|
||||
s = ffclose();
|
||||
if (s == FIOSUC)
|
||||
{ /* No close error */
|
||||
if (nline != 1)
|
||||
mlwrite("[Wrote %d lines]", nline);
|
||||
else
|
||||
mlwrite("[Wrote 1 line]");
|
||||
}
|
||||
}
|
||||
else /* ignore close error */
|
||||
ffclose(); /* if a write error */
|
||||
if (s != FIOSUC) /* some sort of error */
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The command allows the user to modify the file name associated with the
|
||||
* current buffer. It is like the "f" command in UNIX "ed". The operation is
|
||||
* simple; just zap the name in the BUFFER structure, and mark the windows as
|
||||
* needing an update. You can type a blank line at the prompt if you wish.
|
||||
*/
|
||||
int filename(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
char fname[NFILEN];
|
||||
int s;
|
||||
|
||||
if ((s = mlreply("Name: ", fname, NFILEN)) == ABORT)
|
||||
return (s);
|
||||
if (s == FALSE)
|
||||
strncpy(curbp->b_fname, "", 1);
|
||||
else
|
||||
strncpy(curbp->b_fname, fname, NFILEN);
|
||||
wp = wheadp; /* update mode lines */
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert file "fname" into the current buffer, Called by insert file command.
|
||||
* Return the final status of the read.
|
||||
*/
|
||||
int ifile(char fname[])
|
||||
{
|
||||
LINE *lp0, *lp1, *lp2;
|
||||
BUFFER *bp;
|
||||
char line[NLINE];
|
||||
int i, s, nbytes;
|
||||
int nline = 0;
|
||||
int lflag; /* any lines longer than allowed? */
|
||||
|
||||
bp = curbp; /* Cheap */
|
||||
bp->b_flag |= BFCHG; /* we have changed */
|
||||
bp->b_flag &= ~BFTEMP; /* and are not temporary */
|
||||
if ((s = ffropen(fname)) == FIOERR) /* Hard file open */
|
||||
goto out;
|
||||
if (s == FIOFNF)
|
||||
{ /* File not found */
|
||||
mlwrite("[No such file]");
|
||||
return (FALSE);
|
||||
}
|
||||
mlwrite("[Inserting file]");
|
||||
|
||||
/* back up a line and save the mark here */
|
||||
curwp->w_dotp = lback(curwp->w_dotp);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_markp = curwp->w_dotp;
|
||||
curwp->w_marko = 0;
|
||||
|
||||
lflag = FALSE;
|
||||
while ((s = ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG)
|
||||
{
|
||||
if (s == FIOLNG)
|
||||
lflag = TRUE;
|
||||
nbytes = strlen(line);
|
||||
if ((lp1 = lalloc(nbytes)) == NULL)
|
||||
{
|
||||
s = FIOERR; /* keep message on the */
|
||||
break; /* display */
|
||||
}
|
||||
lp0 = curwp->w_dotp; /* line previous to insert */
|
||||
lp2 = lp0->l_fp; /* line after insert */
|
||||
|
||||
/* re-link new line between lp0 and lp2 */
|
||||
lp2->l_bp = lp1;
|
||||
lp0->l_fp = lp1;
|
||||
lp1->l_bp = lp0;
|
||||
lp1->l_fp = lp2;
|
||||
|
||||
/* and advance and write out the current line */
|
||||
curwp->w_dotp = lp1;
|
||||
for (i = 0; i < nbytes; ++i)
|
||||
lputc(lp1, i, line[i]);
|
||||
++nline;
|
||||
}
|
||||
ffclose(); /* Ignore errors */
|
||||
curwp->w_markp = lforw(curwp->w_markp);
|
||||
if (s == FIOEOF)
|
||||
{ /* Don't zap message! */
|
||||
if (nline != 1)
|
||||
mlwrite("[Inserted %d lines]", nline);
|
||||
else
|
||||
mlwrite("[Inserted 1 line]");
|
||||
}
|
||||
if (lflag)
|
||||
{
|
||||
if (nline != 1)
|
||||
mlwrite("[Inserted %d lines: Long lines wrapped]", nline);
|
||||
else
|
||||
mlwrite("[Inserted 1 line: Long lines wrapped]");
|
||||
}
|
||||
out:
|
||||
/* advance to the next line and mark the window for changes */
|
||||
curwp->w_dotp = lforw(curwp->w_dotp);
|
||||
curwp->w_flag |= WFHARD;
|
||||
|
||||
/* copy window parameters back to the buffer structure */
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
|
||||
/* we need to update number of lines in the buffer */
|
||||
curwp->w_bufp->b_lines += nline;
|
||||
|
||||
if (s == FIOERR) /* False if error */
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
121
src/cmd/emg/fileio.c
Normal file
121
src/cmd/emg/fileio.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* The routines in this file read and write ASCII files from the disk. All of
|
||||
* the knowledge about files is here. A better message writing scheme should
|
||||
* be used
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* fopen(3), et.al. */
|
||||
#include "estruct.h"
|
||||
|
||||
extern void mlwrite();
|
||||
|
||||
int ffropen(char *fn);
|
||||
int ffwopen(char *fn);
|
||||
int ffclose();
|
||||
int ffputline(char buf[], int nbuf);
|
||||
int ffgetline(char buf[], int nbuf);
|
||||
|
||||
FILE *ffp; /* File pointer, all functions */
|
||||
|
||||
/*
|
||||
* Open a file for reading.
|
||||
*/
|
||||
int ffropen(char *fn)
|
||||
{
|
||||
if ((ffp = fopen(fn, "r")) == NULL)
|
||||
return (FIOFNF);
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a file for writing. Return TRUE if all is well, and FALSE on error
|
||||
* (cannot create).
|
||||
*/
|
||||
int ffwopen(char *fn)
|
||||
{
|
||||
if ((ffp = fopen(fn, "w")) == NULL)
|
||||
{
|
||||
mlwrite("Cannot open file for writing");
|
||||
return (FIOERR);
|
||||
}
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a file. Should look at the status in all systems.
|
||||
*/
|
||||
int ffclose()
|
||||
{
|
||||
if (fclose(ffp) != FALSE)
|
||||
{
|
||||
mlwrite("Error closing file");
|
||||
return (FIOERR);
|
||||
}
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a line to the already opened file. The "buf" points to the buffer,
|
||||
* and the "nbuf" is its length, less the free newline. Return the status.
|
||||
* Check only at the newline.
|
||||
*/
|
||||
int ffputline(char buf[], int nbuf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nbuf; ++i)
|
||||
fputc(buf[i] & 0xFF, ffp);
|
||||
|
||||
fputc('\n', ffp);
|
||||
|
||||
if (ferror(ffp))
|
||||
{
|
||||
mlwrite("Write I/O error");
|
||||
return (FIOERR);
|
||||
}
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a line from a file, and store the bytes in the supplied buffer. The
|
||||
* "nbuf" is the length of the buffer. Complain about long lines and lines at
|
||||
* the end of the file that don't have a newline present. Check for I/O errors
|
||||
* too. Return status.
|
||||
*/
|
||||
int ffgetline(char buf[], int nbuf)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
i = 0;
|
||||
|
||||
while ((c = fgetc(ffp)) != EOF && c != '\n')
|
||||
{
|
||||
if (i >= nbuf - 2)
|
||||
{
|
||||
buf[nbuf - 2] = c; /* store last char read */
|
||||
buf[nbuf - 1] = 0; /* and terminate it */
|
||||
mlwrite("File has long lines");
|
||||
return (FIOLNG);
|
||||
}
|
||||
buf[i++] = c;
|
||||
}
|
||||
|
||||
if (c == EOF)
|
||||
{
|
||||
if (ferror(ffp))
|
||||
{
|
||||
mlwrite("File read error");
|
||||
return (FIOERR);
|
||||
}
|
||||
if (i != 0)
|
||||
{
|
||||
mlwrite("No newline at EOF");
|
||||
return (FIOERR);
|
||||
}
|
||||
return (FIOEOF);
|
||||
}
|
||||
buf[i] = 0;
|
||||
return (FIOSUC);
|
||||
}
|
||||
507
src/cmd/emg/line.c
Normal file
507
src/cmd/emg/line.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* The functions in this file are a general set of line management utilities.
|
||||
* They are the only routines that touch the text. They also touch the buffer
|
||||
* and window structures, to make sure that the necessary updating gets done.
|
||||
* There are routines in this file that handle the kill buffer too. It isn't
|
||||
* here for any good reason.
|
||||
*
|
||||
* Note that this code only updates the dot and mark values in the window
|
||||
* list. Since all the code acts on the current window, the buffer that we are
|
||||
* editing must be being displayed, which means that "b_nwnd" is non zero,
|
||||
* which means that the dot and mark values in the buffer headers are
|
||||
* nonsense
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* malloc(3) */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern void mlwrite();
|
||||
extern int backchar(int f, int n);
|
||||
|
||||
LINE* lalloc(int used);
|
||||
void lfree(LINE *lp);
|
||||
void lchange(int flag);
|
||||
int linsert(int n, int c);
|
||||
int lnewline();
|
||||
int ldelete(int n, int kflag);
|
||||
int ldelnewline();
|
||||
void kdelete();
|
||||
int kinsert(int c);
|
||||
int kremove(int n);
|
||||
|
||||
#define NBLOCK 16 /* Line block chunk size */
|
||||
#define KBLOCK 1024 /* Kill buffer block size */
|
||||
|
||||
char *kbufp = NULL; /* Kill buffer data */
|
||||
unsigned long kused = 0; /* # of bytes used in KB */
|
||||
unsigned long ksize = 0; /* # of bytes allocated in KB */
|
||||
|
||||
/*
|
||||
* This routine allocates a block of memory large enough to hold a LINE
|
||||
* containing "used" characters. The block is always rounded up a bit. Return
|
||||
* a pointer to the new block, or NULL if there isn't any memory left. Print a
|
||||
* message in the message line if no space.
|
||||
*/
|
||||
LINE* lalloc(int used)
|
||||
{
|
||||
LINE *lp;
|
||||
int size;
|
||||
|
||||
size = (used + NBLOCK - 1) & ~(NBLOCK - 1);
|
||||
if (size == 0) /* Assume that an empty */
|
||||
size = NBLOCK; /* line is for type-in */
|
||||
if ((lp = (LINE *) malloc(sizeof(LINE) + size)) == NULL)
|
||||
{
|
||||
mlwrite("Cannot allocate %d bytes", size);
|
||||
return (NULL);
|
||||
}
|
||||
lp->l_size = size;
|
||||
lp->l_used = used;
|
||||
return (lp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete line "lp". Fix all of the links that might point at it (they are
|
||||
* moved to offset 0 of the next line. Unlink the line from whatever buffer it
|
||||
* might be in. Release the memory. The buffers are updated too; the magic
|
||||
* conditions described in the above comments don't hold here
|
||||
*/
|
||||
void lfree(LINE *lp)
|
||||
{
|
||||
BUFFER *bp;
|
||||
WINDOW *wp;
|
||||
|
||||
wp = wheadp;
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_linep == lp)
|
||||
wp->w_linep = lp->l_fp;
|
||||
if (wp->w_dotp == lp)
|
||||
{
|
||||
wp->w_dotp = lp->l_fp;
|
||||
wp->w_doto = 0;
|
||||
}
|
||||
if (wp->w_markp == lp)
|
||||
{
|
||||
wp->w_markp = lp->l_fp;
|
||||
wp->w_marko = 0;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
bp = bheadp;
|
||||
while (bp != NULL)
|
||||
{
|
||||
if (bp->b_nwnd == 0)
|
||||
{
|
||||
if (bp->b_dotp == lp)
|
||||
{
|
||||
bp->b_dotp = lp->l_fp;
|
||||
bp->b_doto = 0;
|
||||
}
|
||||
if (bp->b_markp == lp)
|
||||
{
|
||||
bp->b_markp = lp->l_fp;
|
||||
bp->b_marko = 0;
|
||||
}
|
||||
}
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
lp->l_bp->l_fp = lp->l_fp;
|
||||
lp->l_fp->l_bp = lp->l_bp;
|
||||
free((char *) lp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine gets called when a character is changed in place in the
|
||||
* current buffer. It updates all of the required flags in the buffer and
|
||||
* window system. The flag used is passed as an argument; if the buffer is
|
||||
* being displayed in more than 1 window we change EDIT t HARD. Set MODE if
|
||||
* the mode line needs to be updated (the "*" has to be set).
|
||||
*/
|
||||
void lchange(int flag)
|
||||
{
|
||||
WINDOW *wp;
|
||||
|
||||
if (curbp->b_nwnd != 1) /* Ensure hard */
|
||||
flag = WFHARD;
|
||||
if ((curbp->b_flag & BFCHG) == 0)
|
||||
{ /* First change, so */
|
||||
flag |= WFMODE; /* update mode lines */
|
||||
curbp->b_flag |= BFCHG;
|
||||
}
|
||||
wp = wheadp;
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= flag;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert "n" copies of the character "c" at the current location of dot. In
|
||||
* the easy case all that happens is the text is stored in the line. In the
|
||||
* hard case, the line has to be reallocated. When the window list is updated,
|
||||
* take special care; I screwed it up once. You always update dot in the
|
||||
* current window. You update mark, and a dot in another window, if it is
|
||||
* greater than the place where you did the insert. Return TRUE if all is
|
||||
* well, and FALSE on errors
|
||||
*/
|
||||
int linsert(int n, int c)
|
||||
{
|
||||
WINDOW *wp;
|
||||
LINE *lp1, *lp2, *lp3;
|
||||
char *cp1, *cp2;
|
||||
int i, doto;
|
||||
|
||||
lchange(WFEDIT);
|
||||
lp1 = curwp->w_dotp; /* Current line */
|
||||
if (lp1 == curbp->b_linep)
|
||||
{ /* At the end: special */
|
||||
if (curwp->w_doto != 0)
|
||||
{
|
||||
mlwrite("Bug: linsert");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((lp2 = lalloc(n)) == NULL) /* Allocate new line */
|
||||
return (FALSE);
|
||||
lp3 = lp1->l_bp; /* Previous line */
|
||||
lp3->l_fp = lp2; /* Link in */
|
||||
lp2->l_fp = lp1;
|
||||
lp1->l_bp = lp2;
|
||||
lp2->l_bp = lp3;
|
||||
for (i = 0; i < n; ++i)
|
||||
lp2->l_text[i] = c;
|
||||
curwp->w_dotp = lp2;
|
||||
curwp->w_doto = n;
|
||||
return (TRUE);
|
||||
}
|
||||
doto = curwp->w_doto; /* Save for later */
|
||||
if (lp1->l_used + n > lp1->l_size)
|
||||
{ /* Hard: reallocate */
|
||||
if ((lp2 = lalloc(lp1->l_used + n)) == NULL)
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0];
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*cp2++ = *cp1++;
|
||||
cp2 += n;
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_bp->l_fp = lp2;
|
||||
lp2->l_fp = lp1->l_fp;
|
||||
lp1->l_fp->l_bp = lp2;
|
||||
lp2->l_bp = lp1->l_bp;
|
||||
free((char *) lp1);
|
||||
}
|
||||
else
|
||||
{ /* Easy: in place */
|
||||
lp2 = lp1; /* Pretend new line */
|
||||
lp2->l_used += n;
|
||||
cp2 = &lp1->l_text[lp1->l_used];
|
||||
cp1 = cp2 - n;
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*--cp2 = *--cp1;
|
||||
}
|
||||
for (i = 0; i < n; ++i) /* Add the characters */
|
||||
lp2->l_text[doto + i] = c;
|
||||
wp = wheadp; /* Update windows */
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_linep == lp1)
|
||||
wp->w_linep = lp2;
|
||||
if (wp->w_dotp == lp1)
|
||||
{
|
||||
wp->w_dotp = lp2;
|
||||
if (wp == curwp || wp->w_doto > doto)
|
||||
wp->w_doto += n;
|
||||
}
|
||||
if (wp->w_markp == lp1)
|
||||
{
|
||||
wp->w_markp = lp2;
|
||||
if (wp->w_marko > doto)
|
||||
wp->w_marko += n;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a newline into the buffer at the current location of dot in the
|
||||
* current window. The funny ass-backwards way it does things is not a botch;
|
||||
* it just makes the last line in the file not a special case. Return TRUE if
|
||||
* everything works out and FALSE on error (memory allocation failure). The
|
||||
* update of dot and mark is a bit easier then in the above case, because the
|
||||
* split forces more updating.
|
||||
*/
|
||||
int lnewline()
|
||||
{
|
||||
WINDOW *wp;
|
||||
char *cp1, *cp2;
|
||||
LINE *lp1, *lp2;
|
||||
int doto;
|
||||
|
||||
lchange(WFHARD);
|
||||
|
||||
curwp->w_bufp->b_lines++;
|
||||
|
||||
lp1 = curwp->w_dotp; /* Get the address and */
|
||||
doto = curwp->w_doto; /* offset of "." */
|
||||
if ((lp2 = lalloc(doto)) == NULL) /* New first half line */
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0]; /* Shuffle text around */
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*cp2++ = *cp1++;
|
||||
cp2 = &lp1->l_text[0];
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_used -= doto;
|
||||
lp2->l_bp = lp1->l_bp;
|
||||
lp1->l_bp = lp2;
|
||||
lp2->l_bp->l_fp = lp2;
|
||||
lp2->l_fp = lp1;
|
||||
wp = wheadp; /* Windows */
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_linep == lp1)
|
||||
wp->w_linep = lp2;
|
||||
if (wp->w_dotp == lp1)
|
||||
{
|
||||
if (wp->w_doto < doto)
|
||||
wp->w_dotp = lp2;
|
||||
else
|
||||
wp->w_doto -= doto;
|
||||
}
|
||||
if (wp->w_markp == lp1)
|
||||
{
|
||||
if (wp->w_marko < doto)
|
||||
wp->w_markp = lp2;
|
||||
else
|
||||
wp->w_marko -= doto;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
curwp->w_dotline++;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function deletes "n" bytes, starting at dot. It understands how do
|
||||
* deal with end of lines, etc. It returns TRUE if all of the characters were
|
||||
* deleted, and FALSE if they were not (because dot ran into the end of the
|
||||
* buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
|
||||
*/
|
||||
int ldelete(int n, int kflag)
|
||||
{
|
||||
LINE *dotp;
|
||||
WINDOW *wp;
|
||||
char *cp1, *cp2;
|
||||
int doto, chunk;
|
||||
|
||||
while (n != 0)
|
||||
{
|
||||
dotp = curwp->w_dotp;
|
||||
doto = curwp->w_doto;
|
||||
if (dotp == curbp->b_linep) /* Hit end of buffer */
|
||||
return (FALSE);
|
||||
chunk = dotp->l_used - doto; /* Size of chunk */
|
||||
if (chunk > n)
|
||||
chunk = n;
|
||||
if (chunk == 0)
|
||||
{ /* End of line, merge */
|
||||
lchange(WFHARD);
|
||||
if (ldelnewline() == FALSE
|
||||
|| (kflag != FALSE && kinsert('\n') == FALSE))
|
||||
return (FALSE);
|
||||
--n;
|
||||
continue;
|
||||
}
|
||||
lchange(WFEDIT);
|
||||
cp1 = &dotp->l_text[doto]; /* Scrunch text */
|
||||
cp2 = cp1 + chunk;
|
||||
if (kflag != FALSE)
|
||||
{ /* Kill? */
|
||||
while (cp1 != cp2)
|
||||
{
|
||||
if (kinsert (*cp1) == FALSE)
|
||||
return (FALSE);
|
||||
++cp1;
|
||||
}
|
||||
cp1 = &dotp->l_text[doto];
|
||||
}
|
||||
while (cp2 != &dotp->l_text[dotp->l_used])
|
||||
*cp1++ = *cp2++;
|
||||
dotp->l_used -= chunk;
|
||||
wp = wheadp; /* Fix windows */
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_dotp == dotp && wp->w_doto >= doto)
|
||||
{
|
||||
wp->w_doto -= chunk;
|
||||
if (wp->w_doto < doto)
|
||||
wp->w_doto = doto;
|
||||
}
|
||||
if (wp->w_markp == dotp && wp->w_marko >= doto)
|
||||
{
|
||||
wp->w_marko -= chunk;
|
||||
if (wp->w_marko < doto)
|
||||
wp->w_marko = doto;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
n -= chunk;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a newline. Join the current line with the next line. If the next
|
||||
* line is the magic header line always return TRUE; merging the last line
|
||||
* with the header line can be thought of as always being a successful
|
||||
* operation, even if nothing is done, and this makes the kill buffer work
|
||||
* "right". Easy cases can be done by shuffling data around. Hard cases
|
||||
* require that lines be moved about in memory. Return FALSE on error and TRUE
|
||||
* if all looks ok. Called by "ldelete" only.
|
||||
*/
|
||||
int ldelnewline()
|
||||
{
|
||||
LINE *lp1, *lp2, *lp3;
|
||||
WINDOW *wp;
|
||||
char *cp1, *cp2;
|
||||
|
||||
lp1 = curwp->w_dotp;
|
||||
lp2 = lp1->l_fp;
|
||||
if (lp2 == curbp->b_linep)
|
||||
{ /* At the buffer end */
|
||||
if (lp1->l_used == 0) /* Blank line */
|
||||
lfree(lp1);
|
||||
return (TRUE);
|
||||
}
|
||||
/* Keep line counts in sync */
|
||||
curwp->w_bufp->b_lines--;
|
||||
if (lp2->l_used <= lp1->l_size - lp1->l_used)
|
||||
{
|
||||
cp1 = &lp1->l_text[lp1->l_used];
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp2 != &lp2->l_text[lp2->l_used])
|
||||
*cp1++ = *cp2++;
|
||||
wp = wheadp;
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_linep == lp2)
|
||||
wp->w_linep = lp1;
|
||||
if (wp->w_dotp == lp2)
|
||||
{
|
||||
wp->w_dotp = lp1;
|
||||
wp->w_doto += lp1->l_used;
|
||||
}
|
||||
if (wp->w_markp == lp2)
|
||||
{
|
||||
wp->w_markp = lp1;
|
||||
wp->w_marko += lp1->l_used;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
lp1->l_used += lp2->l_used;
|
||||
lp1->l_fp = lp2->l_fp;
|
||||
lp2->l_fp->l_bp = lp1;
|
||||
free((char *) lp2);
|
||||
return (TRUE);
|
||||
}
|
||||
if ((lp3 = lalloc(lp1->l_used + lp2->l_used)) == NULL)
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0];
|
||||
cp2 = &lp3->l_text[0];
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
cp1 = &lp2->l_text[0];
|
||||
while (cp1 != &lp2->l_text[lp2->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_bp->l_fp = lp3;
|
||||
lp3->l_fp = lp2->l_fp;
|
||||
lp2->l_fp->l_bp = lp3;
|
||||
lp3->l_bp = lp1->l_bp;
|
||||
wp = wheadp;
|
||||
while (wp != NULL)
|
||||
{
|
||||
if (wp->w_linep == lp1 || wp->w_linep == lp2)
|
||||
wp->w_linep = lp3;
|
||||
if (wp->w_dotp == lp1)
|
||||
wp->w_dotp = lp3;
|
||||
else if (wp->w_dotp == lp2)
|
||||
{
|
||||
wp->w_dotp = lp3;
|
||||
wp->w_doto += lp1->l_used;
|
||||
}
|
||||
if (wp->w_markp == lp1)
|
||||
wp->w_markp = lp3;
|
||||
else if (wp->w_markp == lp2)
|
||||
{
|
||||
wp->w_markp = lp3;
|
||||
wp->w_marko += lp1->l_used;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
free((char *) lp1);
|
||||
free((char *) lp2);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all of the text saved in the kill buffer. Called by commands when a
|
||||
* new kill context is being created. The kill buffer array is released, just
|
||||
* in case the buffer has grown to immense size. No errors.
|
||||
*/
|
||||
void kdelete()
|
||||
{
|
||||
if (kbufp != NULL)
|
||||
{
|
||||
free((char *) kbufp);
|
||||
kbufp = NULL;
|
||||
kused = 0;
|
||||
ksize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a character to the kill buffer, enlarging the buffer if there isn't
|
||||
* any room. Always grow the buffer in chunks, on the assumption that if you
|
||||
* put something in the kill buffer you are going to put more stuff there too
|
||||
* later. Return TRUE if all is well, and FALSE on errors.
|
||||
*/
|
||||
int kinsert(int c)
|
||||
{
|
||||
char *nbufp;
|
||||
|
||||
if (kused == ksize)
|
||||
{
|
||||
if (ksize == 0) /* first time through? */
|
||||
nbufp = malloc(KBLOCK); /* alloc the first block */
|
||||
else /* or re allocate a bigger block */
|
||||
nbufp = realloc(kbufp, ksize + KBLOCK);
|
||||
if (nbufp == NULL) /* abort if it fails */
|
||||
return (FALSE);
|
||||
kbufp = nbufp; /* point our global at it */
|
||||
ksize += KBLOCK; /* and adjust the size */
|
||||
}
|
||||
kbufp[kused++] = c;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function gets characters from the kill buffer. If the character index
|
||||
* "n" is off the end, it returns "-1". This lets the caller just scan along
|
||||
* until it gets a "-1" back.
|
||||
*/
|
||||
int kremove(int n)
|
||||
{
|
||||
if (n >= kused)
|
||||
return (-1);
|
||||
else
|
||||
return (kbufp[n] & 0xFF);
|
||||
}
|
||||
469
src/cmd/emg/main.c
Normal file
469
src/cmd/emg/main.c
Normal file
@@ -0,0 +1,469 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* This program is in public domain; originally written by Dave G. Conroy.
|
||||
* This file contains the main driving routine, and some keyboard processing
|
||||
* code
|
||||
*/
|
||||
|
||||
#define maindef /* make global definitions not external */
|
||||
|
||||
#include <string.h> /* strncpy(3) */
|
||||
#include <stdlib.h> /* malloc(3) */
|
||||
#include "estruct.h" /* global structures and defines */
|
||||
#include "efunc.h" /* function declarations and name table */
|
||||
#include "edef.h" /* global definitions */
|
||||
#include "ebind.h"
|
||||
|
||||
extern void getwinsize();
|
||||
extern void vtinit();
|
||||
extern void vttidy();
|
||||
extern void update();
|
||||
extern void mlerase();
|
||||
extern void mlwrite();
|
||||
extern int mlyesno(char *prompt);
|
||||
extern void makename(char bname[], char fname[]);
|
||||
extern int readin(char fname[]);
|
||||
extern int linsert(int f, int n);
|
||||
extern int anycb();
|
||||
extern BUFFER *bfind();
|
||||
|
||||
void edinit(char bname[]);
|
||||
int execute(int c, int f, int n);
|
||||
int getkey();
|
||||
int getctl();
|
||||
int quickexit(int f, int n);
|
||||
int quit(int f, int n);
|
||||
int ctlxlp(int f, int n);
|
||||
int ctlxrp(int f, int n);
|
||||
int ctlxe(int f, int n);
|
||||
int ctrlg(int f, int n);
|
||||
int extendedcmd(int f, int n);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
BUFFER *bp;
|
||||
char bname[NBUFN]; /* buffer name of file to read */
|
||||
int c, f, n, mflag;
|
||||
int ffile; /* first file flag */
|
||||
int carg; /* current arg to scan */
|
||||
int basec; /* c stripped of meta character */
|
||||
|
||||
/* initialize the editor and process the startup file */
|
||||
getwinsize(); /* find out the "real" screen size */
|
||||
strncpy(bname, "main", 5); /* default buffer name */
|
||||
edinit(bname); /* Buffers, windows */
|
||||
vtinit(); /* Displays */
|
||||
ffile = TRUE; /* no file to edit yet */
|
||||
update(); /* let the user know we are here */
|
||||
|
||||
/* scan through the command line and get the files to edit */
|
||||
for (carg = 1; carg < argc; ++carg)
|
||||
{
|
||||
/* set up a buffer for this file */
|
||||
makename(bname, argv[carg]);
|
||||
|
||||
/* if this is the first file, read it in */
|
||||
if (ffile)
|
||||
{
|
||||
bp = curbp;
|
||||
makename(bname, argv[carg]);
|
||||
strncpy(bp->b_bname, bname, NBUFN);
|
||||
strncpy(bp->b_fname, argv[carg], NFILEN);
|
||||
if (readin(argv[carg]) == ABORT)
|
||||
{
|
||||
strncpy(bp->b_bname, "main", 5);
|
||||
strncpy(bp->b_fname, "", 1);
|
||||
}
|
||||
bp->b_dotp = bp->b_linep;
|
||||
bp->b_doto = 0;
|
||||
ffile = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set this to inactive */
|
||||
bp = bfind(bname, TRUE, 0);
|
||||
strncpy(bp->b_fname, argv[carg], NFILEN);
|
||||
bp->b_active = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* setup to process commands */
|
||||
lastflag = 0; /* Fake last flags */
|
||||
curwp->w_flag |= WFMODE; /* and force an update */
|
||||
|
||||
loop:
|
||||
update(); /* Fix up the screen */
|
||||
c = getkey();
|
||||
if (mpresf != FALSE)
|
||||
{
|
||||
mlerase();
|
||||
update();
|
||||
}
|
||||
f = FALSE;
|
||||
n = 1;
|
||||
|
||||
/* do META-# processing if needed */
|
||||
|
||||
basec = c & ~META; /* strip meta char off if there */
|
||||
if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-'))
|
||||
{
|
||||
f = TRUE; /* there is a # arg */
|
||||
n = 0; /* start with a zero default */
|
||||
mflag = 1; /* current minus flag */
|
||||
c = basec; /* strip the META */
|
||||
while ((c >= '0' && c <= '9') || (c == '-'))
|
||||
{
|
||||
if (c == '-')
|
||||
{
|
||||
/* already hit a minus or digit? */
|
||||
if ((mflag == -1) || (n != 0))
|
||||
break;
|
||||
mflag = -1;
|
||||
}
|
||||
else
|
||||
n = n * 10 + (c - '0');
|
||||
if ((n == 0) && (mflag == -1)) /* lonely - */
|
||||
mlwrite("Arg:");
|
||||
else
|
||||
mlwrite("Arg: %d", n * mflag);
|
||||
|
||||
c = getkey(); /* get the next key */
|
||||
}
|
||||
n = n * mflag; /* figure in the sign */
|
||||
}
|
||||
/* do ^U repeat argument processing */
|
||||
|
||||
if (c == (CTRL | 'U'))
|
||||
{ /* ^U, start argument */
|
||||
f = TRUE;
|
||||
n = 4; /* with argument of 4 */
|
||||
mflag = 0; /* that can be discarded */
|
||||
mlwrite("Arg: 4");
|
||||
while (((c = getkey ()) >= '0')
|
||||
&& ((c <= '9') || (c == (CTRL | 'U')) || (c == '-')))
|
||||
{
|
||||
if (c == (CTRL | 'U'))
|
||||
n = n * 4;
|
||||
/*
|
||||
* If dash, and start of argument string, set arg.
|
||||
* to -1. Otherwise, insert it.
|
||||
*/
|
||||
else if (c == '-')
|
||||
{
|
||||
if (mflag)
|
||||
break;
|
||||
n = 0;
|
||||
mflag = -1;
|
||||
}
|
||||
/*
|
||||
* If first digit entered, replace previous argument
|
||||
* with digit and set sign. Otherwise, append to arg.
|
||||
*/
|
||||
else
|
||||
{
|
||||
if (!mflag)
|
||||
{
|
||||
n = 0;
|
||||
mflag = 1;
|
||||
}
|
||||
n = 10 * n + c - '0';
|
||||
}
|
||||
mlwrite("Arg: %d", (mflag >= 0) ? n : (n ? -n : -1));
|
||||
}
|
||||
/*
|
||||
* Make arguments preceded by a minus sign negative and change
|
||||
* the special argument "^U -" to an effective "^U -1".
|
||||
*/
|
||||
if (mflag == -1)
|
||||
{
|
||||
if (n == 0)
|
||||
n++;
|
||||
n = -n;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == (CTRL | 'X')) /* ^X is a prefix */
|
||||
c = CTLX | getctl ();
|
||||
if (kbdmip != NULL)
|
||||
{ /* Save macro strokes */
|
||||
if (c != (CTLX | ')') && kbdmip > &kbdm[NKBDM - 6])
|
||||
{
|
||||
ctrlg(FALSE, 0);
|
||||
goto loop;
|
||||
}
|
||||
if (f != FALSE)
|
||||
{
|
||||
*kbdmip++ = (CTRL | 'U');
|
||||
*kbdmip++ = n;
|
||||
}
|
||||
*kbdmip++ = c;
|
||||
}
|
||||
execute(c, f, n); /* Do it */
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize all of the buffers and windows. The buffer name is passed down
|
||||
* as an argument, because the main routine may have been told to read in a
|
||||
* file by default, and we want the buffer name to be right.
|
||||
*/
|
||||
void edinit(char bname[])
|
||||
{
|
||||
BUFFER *bp;
|
||||
WINDOW *wp;
|
||||
|
||||
bp = bfind(bname, TRUE, 0); /* First buffer */
|
||||
blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer */
|
||||
wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */
|
||||
if (bp == NULL || wp == NULL || blistp == NULL)
|
||||
exit (1);
|
||||
curbp = bp; /* Make this current */
|
||||
wheadp = wp;
|
||||
curwp = wp;
|
||||
wp->w_wndp = NULL; /* Initialize window */
|
||||
wp->w_bufp = bp;
|
||||
bp->b_nwnd = 1; /* Displayed */
|
||||
wp->w_linep = bp->b_linep;
|
||||
wp->w_dotp = bp->b_linep;
|
||||
wp->w_doto = 0;
|
||||
wp->w_markp = NULL;
|
||||
wp->w_marko = 0;
|
||||
wp->w_toprow = 0;
|
||||
wp->w_ntrows = term.t_nrow - 1; /* "-1" for mode line */
|
||||
wp->w_force = 0;
|
||||
wp->w_flag = WFMODE | WFHARD; /* Full */
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the general command execution routine. It handles the fake binding
|
||||
* of all the keys to "self-insert". It also clears out the "thisflag" word,
|
||||
* and arranges to move it to the "lastflag", so that the next command can
|
||||
* look at it. Return the status of command.
|
||||
*/
|
||||
int execute(int c, int f, int n)
|
||||
{
|
||||
KEYTAB *ktp;
|
||||
int status;
|
||||
|
||||
ktp = &keytab[0]; /* Look in key table */
|
||||
while (ktp->k_fp != NULL)
|
||||
{
|
||||
if (ktp->k_code == c)
|
||||
{
|
||||
thisflag = 0;
|
||||
status = (*ktp->k_fp) (f, n);
|
||||
lastflag = thisflag;
|
||||
return (status);
|
||||
}
|
||||
++ktp;
|
||||
}
|
||||
|
||||
if ((c >= 0x20 && c <= 0x7E) /* Self inserting */
|
||||
|| (c >= 0xA0 && c <= 0xFE))
|
||||
{
|
||||
if (n <= 0)
|
||||
{ /* Fenceposts */
|
||||
lastflag = 0;
|
||||
return (n < 0 ? FALSE : TRUE);
|
||||
}
|
||||
thisflag = 0; /* For the future */
|
||||
|
||||
status = linsert(n, c);
|
||||
|
||||
lastflag = thisflag;
|
||||
return (status);
|
||||
}
|
||||
mlwrite("\007[Key not bound]"); /* complain */
|
||||
lastflag = 0; /* Fake last flags */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in a key. Do the standard keyboard preprocessing. Convert the keys to
|
||||
* the internal character set.
|
||||
*/
|
||||
int getkey()
|
||||
{
|
||||
int c;
|
||||
|
||||
c = (*term.t_getchar) ();
|
||||
|
||||
if (c == METACH)
|
||||
{ /* Apply M- prefix */
|
||||
c = getctl ();
|
||||
return (META | c);
|
||||
}
|
||||
if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */
|
||||
c = CTRL | (c + '@');
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a key. Apply control modifications to the read key.
|
||||
*/
|
||||
int getctl()
|
||||
{
|
||||
int c;
|
||||
|
||||
c = (*term.t_getchar) ();
|
||||
if (c >= 'a' && c <= 'z') /* Force to upper */
|
||||
c -= 0x20;
|
||||
if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */
|
||||
c = CTRL | (c + '@');
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fancy quit command, as implemented by Norm. If any buffer has changed
|
||||
* do a write on that buffer and exit emacs, otherwise simply exit.
|
||||
*/
|
||||
int quickexit(int f, int n)
|
||||
{
|
||||
BUFFER *bp; /* scanning pointer to buffers */
|
||||
|
||||
bp = bheadp;
|
||||
while (bp != NULL)
|
||||
{
|
||||
if ((bp->b_flag & BFCHG) != 0 /* Changed */
|
||||
&& (bp->b_flag & BFTEMP) == 0)
|
||||
{ /* Real */
|
||||
curbp = bp; /* make that buffer current */
|
||||
mlwrite("[Saving %s]", (int*)bp->b_fname);
|
||||
filesave(f, n);
|
||||
}
|
||||
bp = bp->b_bufp; /* on to the next buffer */
|
||||
}
|
||||
return quit(f, n); /* conditionally quit */
|
||||
}
|
||||
|
||||
/*
|
||||
* Quit command. If an argument, always quit. Otherwise confirm if a buffer
|
||||
* has been changed and not written out. Normally bound to "C-X C-C".
|
||||
*/
|
||||
int quit(int f, int n)
|
||||
{
|
||||
int s;
|
||||
|
||||
if (f != FALSE /* Argument forces it */
|
||||
|| anycb () == FALSE /* All buffers clean */
|
||||
|| (s = mlyesno("Modified buffers exist. Leave anyway")) == TRUE)
|
||||
{
|
||||
vttidy();
|
||||
exit (0);
|
||||
}
|
||||
mlwrite("");
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin a keyboard macro. Error if not at the top level in keyboard
|
||||
* processing. Set up variables and return.
|
||||
*/
|
||||
int ctlxlp(int f, int n)
|
||||
{
|
||||
if (kbdmip != NULL || kbdmop != NULL)
|
||||
{
|
||||
mlwrite("Not now");
|
||||
return (FALSE);
|
||||
}
|
||||
mlwrite("[Start macro]");
|
||||
kbdmip = &kbdm[0];
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* End keyboard macro. Check for the same limit conditions as the above
|
||||
* routine. Set up the variables and return to the caller.
|
||||
*/
|
||||
int ctlxrp(int f, int n)
|
||||
{
|
||||
if (kbdmip == NULL)
|
||||
{
|
||||
mlwrite("Not now");
|
||||
return (FALSE);
|
||||
}
|
||||
mlwrite("[End macro]");
|
||||
kbdmip = NULL;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute a macro. The command argument is the number of times to loop. Quit
|
||||
* as soon as a command gets an error. Return TRUE if all ok, else FALSE.
|
||||
*/
|
||||
int ctlxe(int f, int n)
|
||||
{
|
||||
int c, af, an, s;
|
||||
|
||||
if (kbdmip != NULL || kbdmop != NULL)
|
||||
{
|
||||
mlwrite("No macro defined");
|
||||
return (FALSE);
|
||||
}
|
||||
if (n <= 0)
|
||||
return (TRUE);
|
||||
do
|
||||
{
|
||||
kbdmop = &kbdm[0];
|
||||
do
|
||||
{
|
||||
af = FALSE;
|
||||
an = 1;
|
||||
if ((c = *kbdmop++) == (CTRL | 'U'))
|
||||
{
|
||||
af = TRUE;
|
||||
an = *kbdmop++;
|
||||
c = *kbdmop++;
|
||||
}
|
||||
s = TRUE;
|
||||
}
|
||||
while (c != (CTLX | ')') && (s = execute(c, af, an)) == TRUE);
|
||||
kbdmop = NULL;
|
||||
}
|
||||
while (s == TRUE && --n);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Abort. Beep the beeper. Kill off any keyboard macro, etc., that is in
|
||||
* progress. Sometimes called as a routine, to do general aborting of stuff.
|
||||
*/
|
||||
int ctrlg(int f, int n)
|
||||
{
|
||||
(*term.t_beep) ();
|
||||
if (kbdmip != NULL)
|
||||
{
|
||||
kbdm[0] = (CTLX | ')');
|
||||
kbdmip = NULL;
|
||||
}
|
||||
mlwrite("[Aborted]");
|
||||
return (ABORT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle ANSI escape-extended commands (with "ESC [" or "ESC O" prefix)
|
||||
*/
|
||||
int extendedcmd(int f, int n)
|
||||
{
|
||||
int (*cmd)();
|
||||
int c;
|
||||
|
||||
c = getctl();
|
||||
switch (c)
|
||||
{
|
||||
case 'A': cmd = backline; break;
|
||||
case 'B': cmd = forwline; break;
|
||||
case 'C': cmd = forwchar; break;
|
||||
case 'D': cmd = backchar; break;
|
||||
case 'H': cmd = gotobob; break;
|
||||
case 'W': cmd = gotoeob; break;
|
||||
case '5': cmd = pageup; getctl(); break;
|
||||
case '6': cmd = pagedown; getctl(); break;
|
||||
case '7': cmd = gotobob; getctl(); break;
|
||||
case '8': cmd = gotoeob; getctl(); break;
|
||||
default: mlwrite("\007[Key not bound]");
|
||||
return (FALSE);
|
||||
}
|
||||
return cmd(f, n);
|
||||
}
|
||||
290
src/cmd/emg/random.c
Normal file
290
src/cmd/emg/random.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* This file contains the command processing functions for a number of random
|
||||
* commands. There is no functional grouping here, for sure.
|
||||
*/
|
||||
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern void mlwrite();
|
||||
extern void lchange(int flag);
|
||||
extern int lnewline();
|
||||
extern int linsert(int n, int c);
|
||||
extern int backchar(int f, int n);
|
||||
extern void kdelete();
|
||||
extern int ldelete(int f, int n);
|
||||
extern int kremove(int k);
|
||||
|
||||
int setfillcol(int f, int n);
|
||||
int getccol(int bflg);
|
||||
int twiddle(int f, int n);
|
||||
int quote(int f, int n);
|
||||
int tab(int f, int n);
|
||||
int openline(int f, int n);
|
||||
int newline(int f, int n);
|
||||
int forwdel(int f, int n);
|
||||
int backdel(int f, int n);
|
||||
int killtext(int f, int n);
|
||||
int yank(int f, int n);
|
||||
|
||||
/*
|
||||
* Set fill column to n.
|
||||
*/
|
||||
int setfillcol(int f, int n)
|
||||
{
|
||||
fillcol = n;
|
||||
mlwrite("[Fill column is %d]", n);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return current column. Stop at first non-blank given TRUE argument.
|
||||
*/
|
||||
int getccol(int bflg)
|
||||
{
|
||||
int c, i, col;
|
||||
|
||||
col = 0;
|
||||
for (i = 0; i < curwp->w_doto; ++i)
|
||||
{
|
||||
c = lgetc(curwp->w_dotp, i);
|
||||
if (c != ' ' && c != '\t' && bflg)
|
||||
break;
|
||||
if (c == '\t')
|
||||
col |= 0x07;
|
||||
else if (c < 0x20 || c == 0x7F)
|
||||
++col;
|
||||
++col;
|
||||
}
|
||||
return (col);
|
||||
}
|
||||
|
||||
/*
|
||||
* Twiddle the two characters on either side of dot. If dot is at the end of
|
||||
* the line twiddle the two characters before it. Return with an error if dot
|
||||
* is at the beginning of line; it seems to be a bit pointless to make this
|
||||
* work. This fixes up a very common typo with a single stroke. Normally bound
|
||||
* to "C-T". This always works within a line, so "WFEDIT" is good enough
|
||||
*/
|
||||
int twiddle(int f, int n)
|
||||
{
|
||||
LINE *dotp;
|
||||
int doto, cl, cr;
|
||||
|
||||
dotp = curwp->w_dotp;
|
||||
doto = curwp->w_doto;
|
||||
if (doto == llength(dotp) && --doto < 0)
|
||||
return (FALSE);
|
||||
cr = lgetc(dotp, doto);
|
||||
if (--doto < 0)
|
||||
return (FALSE);
|
||||
cl = lgetc(dotp, doto);
|
||||
lputc(dotp, doto + 0, cr);
|
||||
lputc(dotp, doto + 1, cl);
|
||||
lchange(WFEDIT);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quote the next character, and insert it into the buffer. All the characters
|
||||
* are taken literally, with the exception of the newline, which always has
|
||||
* its line splitting meaning. The character is always read, even if it is
|
||||
* inserted 0 times, for regularity. Bound to "C-Q"
|
||||
*/
|
||||
int quote(int f, int n)
|
||||
{
|
||||
int s, c;
|
||||
|
||||
c = (*term.t_getchar) ();
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
if (n == 0)
|
||||
return (TRUE);
|
||||
if (c == '\n')
|
||||
{
|
||||
do
|
||||
{
|
||||
s = lnewline();
|
||||
}
|
||||
while (s == TRUE && --n);
|
||||
return (s);
|
||||
}
|
||||
return (linsert(n, c));
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a tab into file.
|
||||
* Bound to "C-I"
|
||||
*/
|
||||
int tab(int f, int n)
|
||||
{
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
return (linsert(n, 9));
|
||||
}
|
||||
|
||||
/*
|
||||
* Open up some blank space. The basic plan is to insert a bunch of newlines,
|
||||
* and then back up over them. Everything is done by the subcommand
|
||||
* processors. They even handle the looping. Normally this is bound to "C-O"
|
||||
*/
|
||||
int openline(int f, int n)
|
||||
{
|
||||
int i, s;
|
||||
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
if (n == 0)
|
||||
return (TRUE);
|
||||
i = n; /* Insert newlines */
|
||||
do
|
||||
{
|
||||
s = lnewline();
|
||||
}
|
||||
while (s == TRUE && --i);
|
||||
if (s == TRUE) /* Then back up overtop */
|
||||
s = backchar(f, n); /* of them all */
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a newline. Bound to "C-M".
|
||||
*/
|
||||
int newline(int f, int n)
|
||||
{
|
||||
int s;
|
||||
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
|
||||
/* insert some lines */
|
||||
while (n--)
|
||||
{
|
||||
if ((s = lnewline()) != TRUE)
|
||||
return (s);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete forward. This is real easy, because the basic delete routine does
|
||||
* all of the work. Watches for negative arguments, and does the right thing.
|
||||
* If any argument is present, it kills rather than deletes, to prevent loss
|
||||
* of text if typed with a big argument. Normally bound to "C-D"
|
||||
*/
|
||||
int forwdel(int f, int n)
|
||||
{
|
||||
if (n < 0)
|
||||
return (backdel(f, -n));
|
||||
if (f != FALSE)
|
||||
{ /* Really a kill */
|
||||
if ((lastflag & CFKILL) == 0)
|
||||
kdelete();
|
||||
thisflag |= CFKILL;
|
||||
}
|
||||
return (ldelete(n, f));
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete backwards. This is quite easy too, because it's all done with other
|
||||
* functions. Just move the cursor back, and delete forwards. Like delete
|
||||
* forward, this actually does a kill if presented with an argument. Bound to
|
||||
* both "RUBOUT" and "C-H"
|
||||
*/
|
||||
int backdel(int f, int n)
|
||||
{
|
||||
int s;
|
||||
|
||||
if (n < 0)
|
||||
return (forwdel(f, -n));
|
||||
if (f != FALSE)
|
||||
{ /* Really a kill */
|
||||
if ((lastflag & CFKILL) == 0)
|
||||
kdelete();
|
||||
thisflag |= CFKILL;
|
||||
}
|
||||
if ((s = backchar(f, n)) == TRUE)
|
||||
s = ldelete(n, f);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Kill text. If called without an argument, it kills from dot to the end of
|
||||
* the line, unless it is at the end of the line, when it kills the newline.
|
||||
* If called with an argument of 0, it kills from the start of the line to
|
||||
* dot. If called with a positive argument, it kills from dot forward over
|
||||
* that number of newlines. If called with a negative argument it kills
|
||||
* backwards that number of newlines. Normally bound to "C-K"
|
||||
*/
|
||||
int killtext(int f, int n)
|
||||
{
|
||||
LINE *nextp;
|
||||
int chunk;
|
||||
|
||||
if ((lastflag & CFKILL) == 0)/* Clear kill buffer if last wasn't a kill */
|
||||
kdelete();
|
||||
thisflag |= CFKILL;
|
||||
if (f == FALSE)
|
||||
{
|
||||
chunk = llength(curwp->w_dotp) - curwp->w_doto;
|
||||
if (chunk == 0)
|
||||
chunk = 1;
|
||||
}
|
||||
else if (n == 0)
|
||||
{
|
||||
chunk = curwp->w_doto;
|
||||
curwp->w_doto = 0;
|
||||
}
|
||||
else if (n > 0)
|
||||
{
|
||||
chunk = llength(curwp->w_dotp) - curwp->w_doto + 1;
|
||||
nextp = lforw(curwp->w_dotp);
|
||||
while (--n)
|
||||
{
|
||||
if (nextp == curbp->b_linep)
|
||||
return (FALSE);
|
||||
chunk += llength(nextp) + 1;
|
||||
nextp = lforw(nextp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mlwrite("neg kill");
|
||||
return (FALSE);
|
||||
}
|
||||
return (ldelete(chunk, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Yank text back from the kill buffer. This is really easy. All of the work
|
||||
* is done by the standard insert routines. All you do is run the loop, and
|
||||
* check for errors. Bound to "C-Y"
|
||||
*/
|
||||
int yank(int f, int n)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
while (n--)
|
||||
{
|
||||
i = 0;
|
||||
while ((c = kremove(i)) >= 0)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
if (lnewline(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (linsert(1, c) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
142
src/cmd/emg/region.c
Normal file
142
src/cmd/emg/region.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* The routines in this file deal with the region, that magic space between
|
||||
* "." and mark. Some functions are commands. Some functions are just for
|
||||
* internal use
|
||||
*/
|
||||
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern void kdelete();
|
||||
extern int ldelete(int f, int n);
|
||||
extern int kinsert(int c);
|
||||
extern void mlwrite();
|
||||
|
||||
int killregion(int f, int n);
|
||||
int copyregion(int f, int n);
|
||||
int getregion(REGION *rp);
|
||||
|
||||
/*
|
||||
* Kill the region. Ask "getregion" to figure out the bounds of the region.
|
||||
* Move "." to the start, and kill the characters. Bound to "C-W"
|
||||
*/
|
||||
int killregion(int f, int n)
|
||||
{
|
||||
REGION region;
|
||||
int s;
|
||||
|
||||
if ((s = getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
if ((lastflag & CFKILL) == 0) /* This is a kill type */
|
||||
kdelete(); /* command, so do magic */
|
||||
thisflag |= CFKILL; /* kill buffer stuff */
|
||||
curwp->w_dotp = region.r_linep;
|
||||
curwp->w_doto = region.r_offset;
|
||||
return (ldelete(region.r_size, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy all of the characters in the region to the kill buffer. Don't move dot
|
||||
* at all. This is a bit like a kill region followed by a yank. Bound to "M-W"
|
||||
*/
|
||||
int copyregion(int f, int n)
|
||||
{
|
||||
LINE *linep;
|
||||
REGION region;
|
||||
int loffs, s;
|
||||
|
||||
if ((s = getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
if ((lastflag & CFKILL) == 0) /* Kill type command */
|
||||
kdelete();
|
||||
thisflag |= CFKILL;
|
||||
linep = region.r_linep; /* Current line */
|
||||
loffs = region.r_offset; /* Current offset */
|
||||
while (region.r_size--)
|
||||
{
|
||||
if (loffs == llength(linep))
|
||||
{ /* End of line */
|
||||
if ((s = kinsert('\n')) != TRUE)
|
||||
return (s);
|
||||
linep = lforw(linep);
|
||||
loffs = 0;
|
||||
}
|
||||
else
|
||||
{ /* Middle of line */
|
||||
if ((s = kinsert(lgetc(linep, loffs))) != TRUE)
|
||||
return (s);
|
||||
++loffs;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine figures out the bounds of the region in the current window,
|
||||
* and fills in the fields of the "REGION" structure pointed to by "rp".
|
||||
* Because the dot and mark are usually very close together, we scan outward
|
||||
* from dot looking for mark. This should save time. Return a standard code.
|
||||
* Callers of this routine should be prepared to get an "ABORT" status; we
|
||||
* might make this have the conform thing later
|
||||
*/
|
||||
int getregion(REGION *rp)
|
||||
{
|
||||
LINE *flp, *blp;
|
||||
int fsize, bsize;
|
||||
|
||||
if (curwp->w_markp == (struct LINE*)0)
|
||||
{
|
||||
mlwrite("No mark set in this window");
|
||||
return (FALSE);
|
||||
}
|
||||
if (curwp->w_dotp == curwp->w_markp)
|
||||
{
|
||||
rp->r_linep = curwp->w_dotp;
|
||||
if (curwp->w_doto < curwp->w_marko)
|
||||
{
|
||||
rp->r_offset = curwp->w_doto;
|
||||
rp->r_size = curwp->w_marko - curwp->w_doto;
|
||||
}
|
||||
else
|
||||
{
|
||||
rp->r_offset = curwp->w_marko;
|
||||
rp->r_size = curwp->w_doto - curwp->w_marko;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
blp = curwp->w_dotp;
|
||||
bsize = curwp->w_doto;
|
||||
flp = curwp->w_dotp;
|
||||
fsize = llength(flp) - curwp->w_doto + 1;
|
||||
while (flp != curbp->b_linep || lback(blp) != curbp->b_linep)
|
||||
{
|
||||
if (flp != curbp->b_linep)
|
||||
{
|
||||
flp = lforw(flp);
|
||||
if (flp == curwp->w_markp)
|
||||
{
|
||||
rp->r_linep = curwp->w_dotp;
|
||||
rp->r_offset = curwp->w_doto;
|
||||
rp->r_size = fsize + curwp->w_marko;
|
||||
return (TRUE);
|
||||
}
|
||||
fsize += llength(flp) + 1;
|
||||
}
|
||||
if (lback(blp) != curbp->b_linep)
|
||||
{
|
||||
blp = lback(blp);
|
||||
bsize += llength(blp) + 1;
|
||||
if (blp == curwp->w_markp)
|
||||
{
|
||||
rp->r_linep = blp;
|
||||
rp->r_offset = curwp->w_marko;
|
||||
rp->r_size = bsize - curwp->w_marko;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
mlwrite("Bug: lost mark");
|
||||
return (FALSE);
|
||||
}
|
||||
383
src/cmd/emg/search.c
Normal file
383
src/cmd/emg/search.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* The functions in this file implement commands that search in the forward
|
||||
* and backward directions. There are no special characters in the search
|
||||
* strings
|
||||
*/
|
||||
|
||||
#include <string.h> /* strncpy(3), strncat(3) */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern void mlwrite();
|
||||
extern int mlreplyt(char *prompt, char *buf, int nbuf, char eolchar);
|
||||
extern void update();
|
||||
extern int forwchar(int f, int n);
|
||||
extern int ldelete(int n, int kflag);
|
||||
extern int lnewline();
|
||||
extern int linsert(int n, int c);
|
||||
|
||||
int forwsearch(int f, int n);
|
||||
int forwhunt(int f, int n);
|
||||
int backsearch(int f, int n);
|
||||
int backhunt(int f, int n);
|
||||
int bsearch(int f, int n);
|
||||
int eq(int bc, int pc);
|
||||
int readpattern(char *prompt);
|
||||
int forscan(char *patrn, int leavep);
|
||||
void expandp(char *srcstr, char *deststr, int maxlength);
|
||||
|
||||
#define PTBEG 1 /* leave the point at the begining on search */
|
||||
#define PTEND 2 /* leave the point at the end on search */
|
||||
|
||||
/*
|
||||
* Search forward. Get a search string from the user, and search, beginning at
|
||||
* ".", for the string. If found, reset the "." to be just after the match
|
||||
* string, and [perhaps] repaint the display. Bound to "C-S"
|
||||
*/
|
||||
int forwsearch(int f, int n)
|
||||
{
|
||||
int status;
|
||||
int curline = curwp->w_dotline;
|
||||
|
||||
if (n == 0) /* resolve the repeat count */
|
||||
n = 1;
|
||||
if (n < 1) /* search backwards */
|
||||
return (backsearch(f, -n));
|
||||
|
||||
/* ask the user for the text of a pattern */
|
||||
if ((status = readpattern("Search")) != TRUE)
|
||||
return (status);
|
||||
|
||||
/* search for the pattern */
|
||||
while (n-- > 0)
|
||||
{
|
||||
if ((status = forscan(&pat[0], PTEND)) == FALSE)
|
||||
break;
|
||||
}
|
||||
|
||||
/* and complain if not there */
|
||||
if (status == FALSE) {
|
||||
mlwrite("Not found");
|
||||
curwp->w_dotline = curline;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
int forwhunt(int f, int n)
|
||||
{
|
||||
int status = 0;
|
||||
int curline = curwp->w_dotline;
|
||||
|
||||
/* resolve the repeat count */
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
if (n < 1) /* search backwards */
|
||||
return (backhunt(f, -n));
|
||||
|
||||
/* Make sure a pattern exists */
|
||||
if (pat[0] == 0)
|
||||
{
|
||||
mlwrite("No pattern set");
|
||||
return (FALSE);
|
||||
}
|
||||
/* search for the pattern */
|
||||
while (n-- > 0)
|
||||
{
|
||||
if ((status = forscan(&pat[0], PTEND)) == FALSE)
|
||||
break;
|
||||
}
|
||||
|
||||
/* and complain if not there */
|
||||
if (status == FALSE) {
|
||||
mlwrite("Not found");
|
||||
curwp->w_dotline = curline;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reverse search. Get a search string from the user, and search, starting at
|
||||
* "." and proceeding toward the front of the buffer. If found "." is left
|
||||
* pointing at the first character of the pattern [the last character that was
|
||||
* matched]. Bound to "C-R"
|
||||
*/
|
||||
int backsearch(int f, int n)
|
||||
{
|
||||
int s;
|
||||
|
||||
if (n == 0) /* resolve null and negative arguments */
|
||||
n = 1;
|
||||
if (n < 1)
|
||||
return (forwsearch(f, -n));
|
||||
|
||||
if ((s = readpattern("Reverse search")) != TRUE) /* get a pattern to search */
|
||||
return (s);
|
||||
|
||||
return bsearch(f, n); /* and go search for it */
|
||||
}
|
||||
|
||||
/* hunt backward for the last search string entered
|
||||
*/
|
||||
int backhunt(int f, int n)
|
||||
{
|
||||
if (n == 0) /* resolve null and negative arguments */
|
||||
n = 1;
|
||||
if (n < 1)
|
||||
return (forwhunt(f, -n));
|
||||
|
||||
if (pat[0] == 0) /* Make sure a pattern exists */
|
||||
{
|
||||
mlwrite("No pattern set");
|
||||
return (FALSE);
|
||||
}
|
||||
return bsearch(f, n); /* go search */
|
||||
}
|
||||
|
||||
int bsearch(int f, int n)
|
||||
{
|
||||
LINE *clp, *tlp;
|
||||
char *epp, *pp;
|
||||
int cbo, tbo, c;
|
||||
int curline = curwp->w_dotline;
|
||||
|
||||
/* find a pointer to the end of the pattern */
|
||||
for (epp = &pat[0]; epp[1] != 0; ++epp)
|
||||
;
|
||||
|
||||
/* make local copies of the starting location */
|
||||
clp = curwp->w_dotp;
|
||||
cbo = curwp->w_doto;
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
/* if we are at the begining of the line, wrap back around */
|
||||
if (cbo == 0)
|
||||
{
|
||||
clp = lback(clp);
|
||||
curwp->w_dotline--;
|
||||
|
||||
if (clp == curbp->b_linep)
|
||||
{
|
||||
mlwrite("Not found");
|
||||
curwp->w_dotline = curline;
|
||||
return (FALSE);
|
||||
}
|
||||
cbo = llength(clp) + 1;
|
||||
}
|
||||
/* fake the <NL> at the end of a line */
|
||||
if (--cbo == llength(clp))
|
||||
c = '\n';
|
||||
else
|
||||
c = lgetc(clp, cbo);
|
||||
|
||||
/* check for a match against the end of the pattern */
|
||||
if (eq(c, *epp) != FALSE)
|
||||
{
|
||||
tlp = clp;
|
||||
tbo = cbo;
|
||||
pp = epp;
|
||||
/* scanning backwards through the rest of the pattern
|
||||
* looking for a match */
|
||||
while (pp != &pat[0])
|
||||
{
|
||||
/* wrap across a line break */
|
||||
if (tbo == 0)
|
||||
{
|
||||
tlp = lback(tlp);
|
||||
curwp->w_dotline--;
|
||||
if (tlp == curbp->b_linep)
|
||||
goto fail;
|
||||
|
||||
tbo = llength(tlp) + 1;
|
||||
}
|
||||
/* fake the <NL> */
|
||||
if (--tbo == llength(tlp))
|
||||
c = '\n';
|
||||
else
|
||||
c = lgetc(tlp, tbo);
|
||||
|
||||
if (eq(c, *--pp) == FALSE)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* A Match! reset the current cursor */
|
||||
curwp->w_dotp = tlp;
|
||||
curwp->w_doto = tbo;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
goto next;
|
||||
}
|
||||
fail:;
|
||||
}
|
||||
next:;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two characters. The "bc" comes from the buffer. It has it's case
|
||||
* folded out. The "pc" is from the pattern
|
||||
*/
|
||||
int eq(int bc, int pc)
|
||||
{
|
||||
if (bc >= 'a' && bc <= 'z')
|
||||
bc -= 0x20;
|
||||
if (pc >= 'a' && pc <= 'z')
|
||||
pc -= 0x20;
|
||||
if (bc == pc)
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a pattern. Stash it in the external variable "pat". The "pat" is not
|
||||
* updated if the user types in an empty line. If the user typed an empty
|
||||
* line, and there is no old pattern, it is an error. Display the old pattern,
|
||||
* in the style of Jeff Lomicka. There is some do-it-yourself control
|
||||
* expansion.
|
||||
*/
|
||||
int readpattern(char *prompt)
|
||||
{
|
||||
char tpat[NPAT + 20];
|
||||
int s;
|
||||
|
||||
strncpy(tpat, prompt, NPAT-12); /* copy prompt to output string */
|
||||
strncat(tpat, " [", 3); /* build new prompt string */
|
||||
expandp(&pat[0], &tpat[strlen (tpat)], NPAT / 2); /* add old pattern */
|
||||
strncat(tpat, "]: ", 4);
|
||||
|
||||
s = mlreplyt(tpat, tpat, NPAT, 10); /* Read pattern */
|
||||
|
||||
if (s == TRUE) /* Specified */
|
||||
strncpy(pat, tpat, NPAT);
|
||||
else if (s == FALSE && pat[0] != 0) /* CR, but old one */
|
||||
s = TRUE;
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* search forward for a <patrn>
|
||||
*/
|
||||
int forscan(char *patrn, int leavep)
|
||||
{
|
||||
LINE *curline; /* current line during scan */
|
||||
LINE *lastline; /* last line position during scan */
|
||||
LINE *matchline; /* current line during matching */
|
||||
char *patptr; /* pointer into pattern */
|
||||
int curoff; /* position within current line */
|
||||
int lastoff; /* position within last line */
|
||||
int c; /* character at current position */
|
||||
int matchoff; /* position in matching line */
|
||||
|
||||
/* setup local scan pointers to global "." */
|
||||
curline = curwp->w_dotp;
|
||||
curoff = curwp->w_doto;
|
||||
|
||||
/* scan each character until we hit the head link record */
|
||||
while (curline != curbp->b_linep)
|
||||
{
|
||||
/* save the current position in case we need to restore it on a match */
|
||||
lastline = curline;
|
||||
lastoff = curoff;
|
||||
|
||||
/* get the current character resolving EOLs */
|
||||
if (curoff == llength(curline))
|
||||
{ /* if at EOL */
|
||||
curline = lforw(curline); /* skip to next line */
|
||||
curwp->w_dotline++;
|
||||
curoff = 0;
|
||||
c = '\n'; /* and return a <NL> */
|
||||
}
|
||||
else
|
||||
c = lgetc(curline, curoff++); /* get the char */
|
||||
|
||||
/* test it against first char in pattern */
|
||||
if (eq(c, patrn[0]) != FALSE) /* if we find it. */
|
||||
{
|
||||
/* setup match pointers */
|
||||
matchline = curline;
|
||||
matchoff = curoff;
|
||||
patptr = &patrn[0];
|
||||
|
||||
/* scan through patrn for a match */
|
||||
while (*++patptr != 0)
|
||||
{
|
||||
/* advance all the pointers */
|
||||
if (matchoff == llength(matchline))
|
||||
{
|
||||
/* advance past EOL */
|
||||
matchline = lforw(matchline);
|
||||
curwp->w_dotline++;
|
||||
matchoff = 0;
|
||||
c = '\n';
|
||||
}
|
||||
else
|
||||
c = lgetc(matchline, matchoff++);
|
||||
|
||||
/* and test it against the pattern */
|
||||
if (eq(*patptr, c) == FALSE)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* A SUCCESSFULL MATCH!!! */
|
||||
/* reset the global "." pointers */
|
||||
if (leavep == PTEND)
|
||||
{ /* at end of string */
|
||||
curwp->w_dotp = matchline;
|
||||
curwp->w_doto = matchoff;
|
||||
}
|
||||
else
|
||||
{ /* at begining of string */
|
||||
curwp->w_dotp = lastline;
|
||||
curwp->w_doto = lastoff;
|
||||
}
|
||||
curwp->w_flag |= WFMOVE; /* flag that we have moved */
|
||||
return (TRUE);
|
||||
}
|
||||
fail:; /* continue to search */
|
||||
}
|
||||
/* we could not find a match */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/* expandp: expand control key sequences for output
|
||||
*/
|
||||
void expandp(char *srcstr, char *deststr, int maxlength)
|
||||
{
|
||||
char c; /* current char to translate */
|
||||
|
||||
/* scan through the string */
|
||||
while ((c = *srcstr++) != 0)
|
||||
{
|
||||
if (c < 0x20 || c == 0x7f)
|
||||
{ /* control character */
|
||||
*deststr++ = '^';
|
||||
*deststr++ = c ^ 0x40;
|
||||
maxlength -= 2;
|
||||
}
|
||||
else if (c == '%')
|
||||
{
|
||||
*deststr++ = '%';
|
||||
*deststr++ = '%';
|
||||
maxlength -= 2;
|
||||
}
|
||||
else
|
||||
{ /* any other character */
|
||||
*deststr++ = c;
|
||||
maxlength--;
|
||||
}
|
||||
|
||||
/* check for maxlength */
|
||||
if (maxlength < 4)
|
||||
{
|
||||
*deststr++ = '$';
|
||||
*deststr = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
*deststr = '\0';
|
||||
return;
|
||||
}
|
||||
117
src/cmd/emg/tcap.c
Normal file
117
src/cmd/emg/tcap.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/* termios video driver */
|
||||
|
||||
#define termdef 1 /* don't define "term" externally */
|
||||
|
||||
#include <stdio.h> /* puts(3), snprintf(3) */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
#undef CTRL /* Needs to be done here. */
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
extern int tgetent();
|
||||
extern char *tgetstr();
|
||||
extern char *tgoto();
|
||||
extern void tputs();
|
||||
|
||||
extern char *getenv();
|
||||
extern void ttopen();
|
||||
extern int ttgetc();
|
||||
extern void ttputc();
|
||||
extern void ttflush();
|
||||
extern void ttclose();
|
||||
|
||||
extern void panic();
|
||||
|
||||
void getwinsize();
|
||||
void tcapopen();
|
||||
void tcapmove(int row, int col);
|
||||
void tcapeeol();
|
||||
void tcapeeop();
|
||||
void tcaprev();
|
||||
void tcapbeep();
|
||||
|
||||
#define MARGIN 8
|
||||
#define SCRSIZ 64
|
||||
#define BEL 0x07
|
||||
#define TCAPSLEN 64
|
||||
|
||||
char tcapbuf[TCAPSLEN]; /* capabilities actually used */
|
||||
char *CM, *CE, *CL, *SO, *SE;
|
||||
|
||||
TERM term = {
|
||||
0, 0, MARGIN, SCRSIZ, tcapopen, ttclose, ttgetc, ttputc,
|
||||
ttflush, tcapmove, tcapeeol, tcapeeop, tcapbeep, tcaprev
|
||||
};
|
||||
|
||||
void getwinsize()
|
||||
{
|
||||
int cols = FORCE_COLS;
|
||||
int rows = FORCE_ROWS;
|
||||
|
||||
/* Too small and we're out */
|
||||
if ((cols < 10) || (rows < 3))
|
||||
panic("Too few columns or rows");
|
||||
|
||||
if (FORCE_COLS > MAXCOL)
|
||||
cols = MAXCOL;
|
||||
if (FORCE_ROWS > MAXROW)
|
||||
rows = MAXROW;
|
||||
|
||||
term.t_ncol = cols;
|
||||
term.t_nrow = rows - 1;
|
||||
}
|
||||
|
||||
void tcapopen()
|
||||
{
|
||||
char tcbuf[1024];
|
||||
char *p, *tv_stype;
|
||||
|
||||
if ((tv_stype = getenv("TERM")) == NULL)
|
||||
panic("TERM not defined");
|
||||
if ((tgetent(tcbuf, tv_stype)) != 1)
|
||||
panic("Unknown terminal type");
|
||||
p = tcapbuf;
|
||||
CL = tgetstr("cl", &p);
|
||||
CM = tgetstr("cm", &p);
|
||||
CE = tgetstr("ce", &p);
|
||||
SE = tgetstr("se", &p);
|
||||
SO = tgetstr("so", &p);
|
||||
|
||||
if (CE == NULL)
|
||||
eolexist = FALSE;
|
||||
if (SO != NULL && SE != NULL)
|
||||
revexist = TRUE;
|
||||
if (CL == NULL || CM == NULL)
|
||||
panic("Need cl & cm abilities");
|
||||
if (p >= &tcapbuf[TCAPSLEN]) /* XXX */
|
||||
panic("Description too big");
|
||||
ttopen ();
|
||||
}
|
||||
|
||||
void tcaprev(int state)
|
||||
{
|
||||
if (revexist)
|
||||
tputs((state ? SO : SE), 1, ttputc);
|
||||
}
|
||||
|
||||
void tcapmove (int row, int col)
|
||||
{
|
||||
tputs(tgoto(CM, col, row), 1, ttputc);
|
||||
}
|
||||
|
||||
void tcapeeol()
|
||||
{
|
||||
tputs(CE, 1, ttputc);
|
||||
}
|
||||
|
||||
void tcapeeop()
|
||||
{
|
||||
tputs(CL, 1, ttputc);
|
||||
}
|
||||
|
||||
void tcapbeep()
|
||||
{
|
||||
ttputc(BEL);
|
||||
}
|
||||
163
src/cmd/emg/ttyio.c
Normal file
163
src/cmd/emg/ttyio.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* This file comes from mg1a.
|
||||
* Uses the panic function from OpenBSD's mg.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ultrix-32 and Unix terminal I/O.
|
||||
* The functions in this file
|
||||
* negotiate with the operating system for
|
||||
* keyboard characters, and write characters to
|
||||
* the display in a barely buffered fashion.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sgtty.h>
|
||||
#include <stdlib.h>
|
||||
#include <term.h>
|
||||
#include <unistd.h>
|
||||
#undef CTRL
|
||||
#include "estruct.h"
|
||||
|
||||
void ttflush(void);
|
||||
void panic(char *);
|
||||
|
||||
extern void getwinsize();
|
||||
|
||||
#define NROW 66 /* Rows. */
|
||||
#define NCOL 132 /* Columns. */
|
||||
#define NOBUF 512 /* Output buffer size. */
|
||||
|
||||
char obuf[NOBUF]; /* Output buffer. */
|
||||
int nobuf;
|
||||
struct sgttyb oldtty; /* V6/V7 stty data. */
|
||||
struct sgttyb newtty;
|
||||
struct tchars oldtchars; /* V7 editing. */
|
||||
struct tchars newtchars;
|
||||
struct ltchars oldltchars; /* 4.2 BSD editing. */
|
||||
struct ltchars newltchars;
|
||||
|
||||
/*
|
||||
* This function gets called once, to set up
|
||||
* the terminal channel.
|
||||
*/
|
||||
void ttopen(void) {
|
||||
register char *tv_stype;
|
||||
char *getenv(), *tgetstr(), tcbuf[1024];
|
||||
|
||||
if (ioctl(0, TIOCGETP, (char *) &oldtty) < 0)
|
||||
panic("ttopen can't get sgtty");
|
||||
newtty.sg_ospeed = oldtty.sg_ospeed;
|
||||
newtty.sg_ispeed = oldtty.sg_ispeed;
|
||||
newtty.sg_erase = oldtty.sg_erase;
|
||||
newtty.sg_kill = oldtty.sg_kill;
|
||||
newtty.sg_flags = oldtty.sg_flags;
|
||||
newtty.sg_flags &= ~(ECHO|CRMOD); /* Kill echo, CR=>NL. */
|
||||
newtty.sg_flags |= RAW|ANYP; /* raw mode for 8 bit path.*/
|
||||
if (ioctl(0, TIOCSETP, (char *) &newtty) < 0)
|
||||
panic("ttopen can't set sgtty");
|
||||
if (ioctl(0, TIOCGETC, (char *) &oldtchars) < 0)
|
||||
panic("ttopen can't get chars");
|
||||
newtchars.t_intrc = 0xFF; /* Interrupt. */
|
||||
newtchars.t_quitc = 0xFF; /* Quit. */
|
||||
newtchars.t_startc = 0xFF; /* ^Q, for terminal. */
|
||||
newtchars.t_stopc = 0xFF; /* ^S, for terminal. */
|
||||
newtchars.t_eofc = 0xFF;
|
||||
newtchars.t_brkc = 0xFF;
|
||||
if (ioctl(0, TIOCSETC, (char *) &newtchars) < 0)
|
||||
panic("ttopen can't set chars");
|
||||
if (ioctl(0, TIOCGLTC, (char *) &oldltchars) < 0)
|
||||
panic("ttopen can't get ltchars");
|
||||
newltchars.t_suspc = 0xFF; /* Suspend #1. */
|
||||
newltchars.t_dsuspc = 0xFF; /* Suspend #2. */
|
||||
newltchars.t_rprntc = 0xFF;
|
||||
newltchars.t_flushc = 0xFF; /* Output flush. */
|
||||
newltchars.t_werasc = 0xFF;
|
||||
newltchars.t_lnextc = 0xFF; /* Literal next. */
|
||||
if (ioctl(0, TIOCSLTC, (char *) &newltchars) < 0)
|
||||
panic("ttopen can't set ltchars");
|
||||
|
||||
/* do this the REAL way */
|
||||
if ((tv_stype = getenv("TERM")) == NULL)
|
||||
panic("TERM not defined");
|
||||
|
||||
if((tgetent(tcbuf, tv_stype)) != 1)
|
||||
panic("Unknown terminal type");
|
||||
|
||||
getwinsize();
|
||||
}
|
||||
|
||||
/*
|
||||
* This function gets called just
|
||||
* before we go back home to the shell. Put all of
|
||||
* the terminal parameters back.
|
||||
*/
|
||||
void ttclose(void) {
|
||||
ttflush();
|
||||
if (ioctl(0, TIOCSLTC, (char *) &oldltchars) < 0)
|
||||
panic("ttclose can't set ltchars");
|
||||
if (ioctl(0, TIOCSETC, (char *) &oldtchars) < 0)
|
||||
panic("ttclose can't set chars");
|
||||
if (ioctl(0, TIOCSETP, (char *) &oldtty) < 0)
|
||||
panic("ttclose can't set sgtty");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write character to the display.
|
||||
* Characters are buffered up, to make things
|
||||
* a little bit more efficient.
|
||||
*/
|
||||
int ttputc(int c) {
|
||||
if (nobuf >= NOBUF)
|
||||
ttflush();
|
||||
obuf[nobuf++] = c;
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush output.
|
||||
*/
|
||||
void ttflush(void) {
|
||||
if (nobuf != 0) {
|
||||
if (write(1, obuf, nobuf) != nobuf)
|
||||
panic("ttflush write failed");
|
||||
nobuf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read character from terminal.
|
||||
* All 8 bits are returned, so that you can use
|
||||
* a multi-national terminal.
|
||||
*/
|
||||
int ttgetc(void) {
|
||||
char buf[1];
|
||||
|
||||
while (read(0, &buf[0], 1) != 1);
|
||||
return (buf[0] & 0xFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* typeahead returns TRUE if there are characters available to be read
|
||||
* in.
|
||||
*/
|
||||
int typeahead(void) {
|
||||
int x;
|
||||
|
||||
return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x);
|
||||
}
|
||||
|
||||
/*
|
||||
* panic - just exit, as quickly as we can.
|
||||
* From OpenBSD's mg.
|
||||
*/
|
||||
void panic(char *s)
|
||||
{
|
||||
ttclose();
|
||||
(void) fputs("panic: ", stderr);
|
||||
(void) fputs(s, stderr);
|
||||
(void) fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
336
src/cmd/emg/window.c
Normal file
336
src/cmd/emg/window.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* Window management. Some of the functions are internal, and some are
|
||||
* attached to keys that the user actually types
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* free(3), malloc(3) */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern void upmode();
|
||||
extern void mlwrite();
|
||||
|
||||
int refresh(int f, int n);
|
||||
int nextwind(int f, int n);
|
||||
int prevwind(int f, int n);
|
||||
int onlywind(int f, int n);
|
||||
int splitwind(int f, int n);
|
||||
int enlargewind(int f, int n);
|
||||
int shrinkwind(int f, int n);
|
||||
WINDOW* wpopup();
|
||||
|
||||
/*
|
||||
* Refresh the screen. With no argument, it does the refresh and centers
|
||||
* the cursor on the screen. With an argument it does a reposition instead.
|
||||
* Bound to "C-L"
|
||||
*/
|
||||
int refresh(int f, int n)
|
||||
{
|
||||
if (n >= 0)
|
||||
n++; /* adjust to screen row */
|
||||
if (f == FALSE)
|
||||
{
|
||||
sgarbf = TRUE;
|
||||
n = 0; /* Center dot */
|
||||
}
|
||||
curwp->w_force = n;
|
||||
curwp->w_flag |= WFFORCE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The command make the next window (next => down the screen) the current
|
||||
* window. There are no real errors, although the command does nothing if
|
||||
* there is only 1 window on the screen. Bound to "C-X C-N"
|
||||
*/
|
||||
int nextwind(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
|
||||
if ((wp = curwp->w_wndp) == NULL)
|
||||
wp = wheadp;
|
||||
|
||||
curwp = wp;
|
||||
curbp = wp->w_bufp;
|
||||
upmode();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This command makes the previous window (previous => up the screen) the
|
||||
* current window. There arn't any errors, although the command does not do a
|
||||
* lot if there is 1 window
|
||||
*/
|
||||
int prevwind(int f, int n)
|
||||
{
|
||||
WINDOW *wp1, *wp2;
|
||||
|
||||
wp1 = wheadp;
|
||||
wp2 = curwp;
|
||||
|
||||
if (wp1 == wp2)
|
||||
wp2 = NULL;
|
||||
|
||||
while (wp1->w_wndp != wp2)
|
||||
wp1 = wp1->w_wndp;
|
||||
|
||||
curwp = wp1;
|
||||
curbp = wp1->w_bufp;
|
||||
upmode();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This command makes the current window the only window on the screen. Bound
|
||||
* to "C-X 1". Try to set the framing so that "." does not have to move on the
|
||||
* display. Some care has to be taken to keep the values of dot and mark in
|
||||
* the buffer structures right if the distruction of a window makes a buffer
|
||||
* become undisplayed
|
||||
*/
|
||||
int onlywind(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
LINE *lp;
|
||||
int i;
|
||||
|
||||
while (wheadp != curwp)
|
||||
{
|
||||
wp = wheadp;
|
||||
wheadp = wp->w_wndp;
|
||||
if (--wp->w_bufp->b_nwnd == 0)
|
||||
{
|
||||
wp->w_bufp->b_dotp = wp->w_dotp;
|
||||
wp->w_bufp->b_doto = wp->w_doto;
|
||||
wp->w_bufp->b_markp = wp->w_markp;
|
||||
wp->w_bufp->b_marko = wp->w_marko;
|
||||
}
|
||||
free((char *) wp);
|
||||
}
|
||||
while (curwp->w_wndp != NULL)
|
||||
{
|
||||
wp = curwp->w_wndp;
|
||||
curwp->w_wndp = wp->w_wndp;
|
||||
if (--wp->w_bufp->b_nwnd == 0)
|
||||
{
|
||||
wp->w_bufp->b_dotp = wp->w_dotp;
|
||||
wp->w_bufp->b_doto = wp->w_doto;
|
||||
wp->w_bufp->b_markp = wp->w_markp;
|
||||
wp->w_bufp->b_marko = wp->w_marko;
|
||||
}
|
||||
free((char *) wp);
|
||||
}
|
||||
lp = curwp->w_linep;
|
||||
i = curwp->w_toprow;
|
||||
while (i != 0 && lback (lp) != curbp->b_linep)
|
||||
{
|
||||
--i;
|
||||
lp = lback(lp);
|
||||
}
|
||||
curwp->w_toprow = 0;
|
||||
curwp->w_ntrows = term.t_nrow - 1;
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Split the current window. A window smaller than 3 lines cannot be split.
|
||||
* The only other error that is possible is a "malloc" failure allocating the
|
||||
* structure for the new window. Bound to "C-X 2"
|
||||
*/
|
||||
int splitwind(int f, int n)
|
||||
{
|
||||
LINE *lp;
|
||||
WINDOW *wp, *wp1, *wp2;
|
||||
int ntru, ntrl, ntrd;
|
||||
|
||||
if (curwp->w_ntrows < 3)
|
||||
{
|
||||
mlwrite("Cannot split a %d line window", curwp->w_ntrows);
|
||||
return (FALSE);
|
||||
}
|
||||
if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL)
|
||||
{
|
||||
mlwrite("Cannot allocate WINDOW block");
|
||||
return (FALSE);
|
||||
}
|
||||
++curbp->b_nwnd; /* Displayed twice */
|
||||
wp->w_bufp = curbp;
|
||||
wp->w_dotp = curwp->w_dotp;
|
||||
wp->w_doto = curwp->w_doto;
|
||||
wp->w_markp = curwp->w_markp;
|
||||
wp->w_marko = curwp->w_marko;
|
||||
wp->w_flag = 0;
|
||||
wp->w_force = 0;
|
||||
ntru = (curwp->w_ntrows - 1) / 2; /* Upper size */
|
||||
ntrl = (curwp->w_ntrows - 1) - ntru; /* Lower size */
|
||||
lp = curwp->w_linep;
|
||||
ntrd = 0;
|
||||
while (lp != curwp->w_dotp)
|
||||
{
|
||||
++ntrd;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
lp = curwp->w_linep;
|
||||
if (ntrd <= ntru)
|
||||
{ /* Old is upper window */
|
||||
if (ntrd == ntru) /* Hit mode line */
|
||||
lp = lforw(lp);
|
||||
curwp->w_ntrows = ntru;
|
||||
wp->w_wndp = curwp->w_wndp;
|
||||
curwp->w_wndp = wp;
|
||||
wp->w_toprow = curwp->w_toprow + ntru + 1;
|
||||
wp->w_ntrows = ntrl;
|
||||
}
|
||||
else
|
||||
{ /* Old is lower window */
|
||||
wp1 = NULL;
|
||||
wp2 = wheadp;
|
||||
while (wp2 != curwp)
|
||||
{
|
||||
wp1 = wp2;
|
||||
wp2 = wp2->w_wndp;
|
||||
}
|
||||
if (wp1 == NULL)
|
||||
wheadp = wp;
|
||||
else
|
||||
wp1->w_wndp = wp;
|
||||
wp->w_wndp = curwp;
|
||||
wp->w_toprow = curwp->w_toprow;
|
||||
wp->w_ntrows = ntru;
|
||||
++ntru; /* Mode line */
|
||||
curwp->w_toprow += ntru;
|
||||
curwp->w_ntrows = ntrl;
|
||||
while (ntru--)
|
||||
lp = lforw (lp);
|
||||
}
|
||||
curwp->w_linep = lp; /* Adjust the top lines */
|
||||
wp->w_linep = lp; /* if necessary */
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
wp->w_flag |= WFMODE | WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enlarge the current window. Find the window that loses space. Make sure it
|
||||
* is big enough. If so, hack the window descriptions, and ask redisplay to do
|
||||
* all the hard work. You don't just set "force reframe" because dot would
|
||||
* move. Bound to "C-X Z"
|
||||
*/
|
||||
int enlargewind(int f, int n)
|
||||
{
|
||||
WINDOW *adjwp;
|
||||
LINE *lp;
|
||||
int i;
|
||||
|
||||
if (n < 0)
|
||||
return (shrinkwind(f, -n));
|
||||
if (wheadp->w_wndp == NULL)
|
||||
{
|
||||
mlwrite("Only one window");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((adjwp = curwp->w_wndp) == NULL)
|
||||
{
|
||||
adjwp = wheadp;
|
||||
while (adjwp->w_wndp != curwp)
|
||||
adjwp = adjwp->w_wndp;
|
||||
}
|
||||
if (adjwp->w_ntrows <= n)
|
||||
{
|
||||
mlwrite("Impossible change");
|
||||
return (FALSE);
|
||||
}
|
||||
if (curwp->w_wndp == adjwp)
|
||||
{ /* Shrink below */
|
||||
lp = adjwp->w_linep;
|
||||
for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i)
|
||||
lp = lforw(lp);
|
||||
adjwp->w_linep = lp;
|
||||
adjwp->w_toprow += n;
|
||||
}
|
||||
else
|
||||
{ /* Shrink above */
|
||||
lp = curwp->w_linep;
|
||||
for (i = 0; i < n && lback(lp) != curbp->b_linep; ++i)
|
||||
lp = lback(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_toprow -= n;
|
||||
}
|
||||
curwp->w_ntrows += n;
|
||||
adjwp->w_ntrows -= n;
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
adjwp->w_flag |= WFMODE | WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shrink the current window. Find the window that gains space. Hack at the
|
||||
* window descriptions. Ask the redisplay to do all the hard work
|
||||
*/
|
||||
int shrinkwind(int f, int n)
|
||||
{
|
||||
WINDOW *adjwp;
|
||||
LINE *lp;
|
||||
int i;
|
||||
|
||||
if (n < 0)
|
||||
return (enlargewind(f, -n));
|
||||
if (wheadp->w_wndp == NULL)
|
||||
{
|
||||
mlwrite("Only one window");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((adjwp = curwp->w_wndp) == NULL)
|
||||
{
|
||||
adjwp = wheadp;
|
||||
while (adjwp->w_wndp != curwp)
|
||||
adjwp = adjwp->w_wndp;
|
||||
}
|
||||
if (curwp->w_ntrows <= n)
|
||||
{
|
||||
mlwrite("Impossible change");
|
||||
return (FALSE);
|
||||
}
|
||||
if (curwp->w_wndp == adjwp)
|
||||
{ /* Grow below */
|
||||
lp = adjwp->w_linep;
|
||||
for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep; ++i)
|
||||
lp = lback(lp);
|
||||
adjwp->w_linep = lp;
|
||||
adjwp->w_toprow -= n;
|
||||
}
|
||||
else
|
||||
{ /* Grow above */
|
||||
lp = curwp->w_linep;
|
||||
for (i = 0; i < n && lp != curbp->b_linep; ++i)
|
||||
lp = lforw(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_toprow += n;
|
||||
}
|
||||
curwp->w_ntrows -= n;
|
||||
adjwp->w_ntrows += n;
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
adjwp->w_flag |= WFMODE | WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a window for a pop-up. Split the screen if there is only one window.
|
||||
* Pick the uppermost window that isn't the current window. An LRU algorithm
|
||||
* might be better. Return a pointer, or NULL on error
|
||||
*/
|
||||
WINDOW* wpopup()
|
||||
{
|
||||
WINDOW *wp;
|
||||
|
||||
if (wheadp->w_wndp == NULL /* Only 1 window */
|
||||
&& splitwind(FALSE, 0) == FALSE) /* and it won't split */
|
||||
return (NULL);
|
||||
wp = wheadp; /* Find window to use */
|
||||
while (wp != NULL && wp == curwp)
|
||||
wp = wp->w_wndp;
|
||||
return (wp);
|
||||
}
|
||||
90
src/cmd/emg/word.c
Normal file
90
src/cmd/emg/word.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* The routines in this file implement commands that work word at a time.
|
||||
* There are all sorts of word mode commands. If I do any sentence and/or
|
||||
* paragraph mode commands, they are likely to be put in this file
|
||||
*/
|
||||
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern int backchar(int f, int n);
|
||||
extern int forwchar(int f, int n);
|
||||
|
||||
int backword(int f, int n);
|
||||
int forwword(int f, int n);
|
||||
int inword(void);
|
||||
|
||||
/*
|
||||
* Move the cursor backward by "n" words. All of the details of motion are
|
||||
* performed by the "backchar" and "forwchar" routines. Error if you try to
|
||||
* move beyond the buffers
|
||||
*/
|
||||
int backword(int f, int n)
|
||||
{
|
||||
if (n < 0)
|
||||
return (forwword(f, -n));
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
while (n--)
|
||||
{
|
||||
while (inword() == FALSE)
|
||||
{
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
while (inword() != FALSE)
|
||||
{
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return (forwchar(FALSE, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor forward by the specified number of words. All of the motion
|
||||
* is done by "forwchar". Error if you try and move beyond the buffer's end
|
||||
*/
|
||||
int forwword(int f, int n)
|
||||
{
|
||||
if (n < 0)
|
||||
return (backword(f, -n));
|
||||
while (n--)
|
||||
{
|
||||
while (inword() != FALSE)
|
||||
{
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
while (inword() == FALSE)
|
||||
{
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if the character at dot is a character that is considered to be
|
||||
* part of a word. The word character list is hard coded. Should be setable
|
||||
*/
|
||||
int inword(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (curwp->w_doto == llength(curwp->w_dotp))
|
||||
return (FALSE);
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return (TRUE);
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return (TRUE);
|
||||
if (c >= '0' && c <= '9')
|
||||
return (TRUE);
|
||||
if (c == '$' || c == '_') /* For identifiers */
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
@@ -32,7 +32,7 @@ depend: ${SRCS}
|
||||
|
||||
install: all
|
||||
install -m 755 $(BIN) ${DESTDIR}/sbin
|
||||
install -m 755 $(MAN) ${DESTDIR}/share/man/cat8
|
||||
cp $(MAN) ${DESTDIR}/share/man/cat8
|
||||
|
||||
lint: ${SRCS}
|
||||
lint -hax ${SRCS}
|
||||
|
||||
@@ -172,7 +172,7 @@ int fgethdr (text, h)
|
||||
register FILE *text;
|
||||
register struct exec *h;
|
||||
{
|
||||
h->a_magic = fgetword (text);
|
||||
h->a_midmag = fgetword (text);
|
||||
h->a_text = fgetword (text);
|
||||
h->a_data = fgetword (text);
|
||||
h->a_bss = fgetword (text);
|
||||
@@ -860,7 +860,7 @@ void readhdr (loc)
|
||||
fseek (text, loc, 0);
|
||||
if (! fgethdr (text, &filhdr))
|
||||
error (2, "bad format");
|
||||
if (filhdr.a_magic != RMAGIC)
|
||||
if (N_GETMAGIC(filhdr) != RMAGIC)
|
||||
error (2, "bad magic");
|
||||
if (filhdr.a_text % W)
|
||||
error (2, "bad length of text");
|
||||
@@ -880,7 +880,7 @@ int load1 (loc, libflg, nloc)
|
||||
int savindex, ndef, type, symlen, nsymbol;
|
||||
|
||||
readhdr (loc);
|
||||
if (filhdr.a_magic != RMAGIC) {
|
||||
if (N_GETMAGIC(filhdr) != RMAGIC) {
|
||||
error (1, "file not relocatable");
|
||||
return (0);
|
||||
}
|
||||
@@ -1293,7 +1293,7 @@ void setupout ()
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
tcreat (&toutb, 1);
|
||||
tcreat (&doutb, 1);
|
||||
|
||||
@@ -1494,7 +1494,7 @@ void finishout ()
|
||||
while (ssize++ % W)
|
||||
putc (0, outb);
|
||||
}
|
||||
filhdr.a_magic = output_relinfo ? RMAGIC : OMAGIC;
|
||||
filhdr.a_midmag = output_relinfo ? RMAGIC : OMAGIC;
|
||||
filhdr.a_text = tsize;
|
||||
filhdr.a_data = dsize;
|
||||
filhdr.a_bss = bsize;
|
||||
|
||||
1
src/cmd/levee/.gitignore
vendored
Normal file
1
src/cmd/levee/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
lv
|
||||
56
src/cmd/levee/Makefile
Normal file
56
src/cmd/levee/Makefile
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# Public Domain. 1995/03/13 - Steven Schultz
|
||||
#
|
||||
TOPSRC = $(shell cd ../../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
|
||||
#CFLAGS += -Werror
|
||||
LIBS += -ltermcap
|
||||
|
||||
OBJS = blockio.o display.o editcor.o exec.o find.o \
|
||||
unixcall.o globals.o insert.o main.o misc.o \
|
||||
modify.o move.o ucsd.o undo.o wildargs.o \
|
||||
version.o
|
||||
MAN = lv.0
|
||||
|
||||
all: lv ${MAN}
|
||||
|
||||
lv: ${OBJS}
|
||||
${CC} ${LDFLAGS} -o lv.elf ${OBJS} ${LIBS}
|
||||
${OBJDUMP} -S lv.elf > lv.dis
|
||||
${SIZE} lv.elf
|
||||
${ELF2AOUT} lv.elf $@ && rm lv.elf
|
||||
|
||||
version.o: version.c VERSION
|
||||
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
|
||||
|
||||
.SUFFIXES: .0 .1
|
||||
|
||||
.1.0:
|
||||
${MANROFF} $*.1 > $@
|
||||
|
||||
clean:
|
||||
rm -f *.o *.elf ${MAN} lv *.elf *.dis tags *~
|
||||
|
||||
install: all
|
||||
install lv ${DESTDIR}/bin/
|
||||
cp lv.0 ${DESTDIR}/share/man/cat1/
|
||||
|
||||
# Dependencies
|
||||
|
||||
blockio.o : levee.h extern.h blockio.c config.h
|
||||
display.o : levee.h extern.h termcap.i display.c config.h
|
||||
editcor.o : levee.h extern.h editcor.c config.h
|
||||
exec.o : levee.h extern.h exec.c config.h
|
||||
find.o : levee.h extern.h grep.h find.c config.h
|
||||
globals.o : levee.h globals.c config.h
|
||||
insert.o : levee.h extern.h insert.c config.h
|
||||
main.o : levee.h extern.h main.c config.h
|
||||
misc.o : levee.h extern.h misc.c config.h
|
||||
modify.o : levee.h extern.h grep.h modify.c config.h
|
||||
move.o : levee.h extern.h move.c config.h
|
||||
rmxcall.o : levee.h rmxcall.c config.h
|
||||
ucsd.o : levee.h extern.h ucsd.c config.h
|
||||
undo.o : levee.h extern.h undo.c config.h
|
||||
unixcall.o : levee.h extern.h unixcall.c config.h
|
||||
wildargs.o : levee.h extern.h wildargs.c config.h
|
||||
56
src/cmd/levee/Makefile-linux
Normal file
56
src/cmd/levee/Makefile-linux
Normal file
@@ -0,0 +1,56 @@
|
||||
# makefile for Levee
|
||||
|
||||
exedir=/usr/local/bin
|
||||
mandir=/usr/local/man
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-g
|
||||
LDFLAGS=-g
|
||||
|
||||
OBJS = blockio.o display.o editcor.o exec.o find.o \
|
||||
unixcall.o globals.o insert.o main.o misc.o \
|
||||
modify.o move.o ucsd.o undo.o wildargs.o \
|
||||
version.o
|
||||
|
||||
lev: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o lev $(OBJS) -lcurses
|
||||
|
||||
version.o: version.c VERSION
|
||||
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
|
||||
|
||||
clean:
|
||||
rm -f *.o lev
|
||||
|
||||
distclean spotless: clean
|
||||
rm -f Makefile config.cmd config.sub config.h config.mak config.log config.md
|
||||
|
||||
install: install.bin install.man
|
||||
|
||||
install.bin: lev
|
||||
/home/sergev/Daily/workdir-2015-01-06/levee-3.5a/config.md $(PREFIX)$(exedir)
|
||||
/usr/bin/install -s -m 755 lev $(PREFIX)$(exedir)/levee
|
||||
/bin/ln -s -f levee $(PREFIX)$(exedir)/lv
|
||||
|
||||
install.man:
|
||||
/home/sergev/Daily/workdir-2015-01-06/levee-3.5a/config.md $(PREFIX)$(mandir)/man1
|
||||
/usr/bin/install -m 444 lv.1 $(PREFIX)$(mandir)/man1/levee.1
|
||||
echo ".so man1/levee.1" > $(PREFIX)$(mandir)/man1/lv.1
|
||||
|
||||
# Dependencies
|
||||
|
||||
blockio.o : levee.h extern.h blockio.c config.h
|
||||
display.o : levee.h extern.h termcap.i display.c config.h
|
||||
editcor.o : levee.h extern.h editcor.c config.h
|
||||
exec.o : levee.h extern.h exec.c config.h
|
||||
find.o : levee.h extern.h grep.h find.c config.h
|
||||
globals.o : levee.h globals.c config.h
|
||||
insert.o : levee.h extern.h insert.c config.h
|
||||
main.o : levee.h extern.h main.c config.h
|
||||
misc.o : levee.h extern.h misc.c config.h
|
||||
modify.o : levee.h extern.h grep.h modify.c config.h
|
||||
move.o : levee.h extern.h move.c config.h
|
||||
rmxcall.o : levee.h rmxcall.c config.h
|
||||
ucsd.o : levee.h extern.h ucsd.c config.h
|
||||
undo.o : levee.h extern.h undo.c config.h
|
||||
unixcall.o : levee.h extern.h unixcall.c config.h
|
||||
wildargs.o : levee.h extern.h wildargs.c config.h
|
||||
56
src/cmd/levee/Makefile.in
Normal file
56
src/cmd/levee/Makefile.in
Normal file
@@ -0,0 +1,56 @@
|
||||
# makefile for Levee
|
||||
|
||||
exedir=@exedir@
|
||||
mandir=@mandir@
|
||||
CC=@CC@
|
||||
|
||||
CFLAGS=@CFLAGS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
|
||||
OBJS = blockio.o display.o editcor.o exec.o find.o \
|
||||
unixcall.o globals.o insert.o main.o misc.o \
|
||||
modify.o move.o ucsd.o undo.o wildargs.o \
|
||||
version.o
|
||||
|
||||
lev: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o lev $(OBJS) @LIBS@
|
||||
|
||||
version.o: version.c VERSION
|
||||
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
|
||||
|
||||
clean:
|
||||
rm -f *.o lev
|
||||
|
||||
distclean spotless: clean
|
||||
rm -f @GENERATED_FILES@ @CONFIGURE_FILES@
|
||||
|
||||
install: install.bin install.man
|
||||
|
||||
install.bin: lev
|
||||
@INSTALL_DIR@ $(PREFIX)$(exedir)
|
||||
@INSTALL_PROGRAM@ lev $(PREFIX)$(exedir)/levee
|
||||
@NOMK@@LN_S@ -f levee $(PREFIX)$(exedir)/lv
|
||||
|
||||
install.man:
|
||||
@INSTALL_DIR@ $(PREFIX)$(mandir)/man1
|
||||
@INSTALL_DATA@ lv.1 $(PREFIX)$(mandir)/man1/levee.1
|
||||
@NOMK@echo ".so man1/levee.1" > $(PREFIX)$(mandir)/man1/lv.1
|
||||
|
||||
# Dependencies
|
||||
|
||||
blockio.o : levee.h extern.h blockio.c config.h
|
||||
display.o : levee.h extern.h termcap.i display.c config.h
|
||||
editcor.o : levee.h extern.h editcor.c config.h
|
||||
exec.o : levee.h extern.h exec.c config.h
|
||||
find.o : levee.h extern.h grep.h find.c config.h
|
||||
globals.o : levee.h globals.c config.h
|
||||
insert.o : levee.h extern.h insert.c config.h
|
||||
main.o : levee.h extern.h main.c config.h
|
||||
misc.o : levee.h extern.h misc.c config.h
|
||||
modify.o : levee.h extern.h grep.h modify.c config.h
|
||||
move.o : levee.h extern.h move.c config.h
|
||||
rmxcall.o : levee.h rmxcall.c config.h
|
||||
ucsd.o : levee.h extern.h ucsd.c config.h
|
||||
undo.o : levee.h extern.h undo.c config.h
|
||||
unixcall.o : levee.h extern.h unixcall.c config.h
|
||||
wildargs.o : levee.h extern.h wildargs.c config.h
|
||||
1
src/cmd/levee/VERSION
Normal file
1
src/cmd/levee/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
3.5a
|
||||
48
src/cmd/levee/beep.c
Normal file
48
src/cmd/levee/beep.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#include "levee.h"
|
||||
|
||||
#if OS_ATARI
|
||||
#include <atari\osbind.h>
|
||||
|
||||
char sound[] = {
|
||||
0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00,
|
||||
0xF8,0x10,0x10,0x10,0x00,0x20,0x03
|
||||
};
|
||||
|
||||
#define SADDR 0xFF8800L
|
||||
|
||||
typedef char srdef[4];
|
||||
|
||||
srdef *SOUND = (srdef *)SADDR;
|
||||
|
||||
main()
|
||||
{
|
||||
register i;
|
||||
long ssp;
|
||||
|
||||
ssp = Super(0L);
|
||||
for (i=0; i<sizeof(sound); i++) {
|
||||
(*SOUND)[0] = i;
|
||||
(*SOUND)[2] = sound[i];
|
||||
}
|
||||
Super(ssp);
|
||||
}
|
||||
#endif /*OS_ATARI*/
|
||||
50
src/cmd/levee/blockio.c
Normal file
50
src/cmd/levee/blockio.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* LEVEE, or Captain Video; A vi clone
|
||||
*
|
||||
* Copyright (c) 1982-2007 David L Parsons
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, without or
|
||||
* without modification, are permitted provided that the above
|
||||
* copyright notice and this paragraph are duplicated in all such
|
||||
* forms and that any documentation, advertising materials, and
|
||||
* other materials related to such distribution and use acknowledge
|
||||
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
|
||||
* My name may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE.
|
||||
*/
|
||||
#include "levee.h"
|
||||
#include "extern.h"
|
||||
|
||||
/* read in a file -- return TRUE -- read file
|
||||
FALSE-- file too big
|
||||
*/
|
||||
|
||||
int PROC
|
||||
addfile(f, start, endd, size)
|
||||
FILE *f;
|
||||
int start;
|
||||
int endd, *size;
|
||||
{
|
||||
register int chunk;
|
||||
|
||||
chunk = read(fileno(f), core+start, (endd-start)-1);
|
||||
|
||||
*size = chunk;
|
||||
return chunk < (endd-start)-1;
|
||||
}
|
||||
|
||||
|
||||
/* write out a file -- return TRUE if ok. */
|
||||
|
||||
bool PROC
|
||||
putfile(f, start, endd)
|
||||
register FILE *f;
|
||||
register int start, endd;
|
||||
{
|
||||
return write(fileno(f), core+start, endd-start) == (endd-start);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user