v08i012: A Micro-Emacs variant that resembles GNU Emacs
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Wed Jan 28 04:20:07 AEST 1987
Submitted by: Bob Larson <seismo!usc-oberon!blarson>
Mod.sources: Volume 8, Issue 12
Archive-name: micrognu/Part05
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# tty/termcap/ttykbd.c
# sys/bsd/Makefile
# sys/bsd/fileio.c
# sys/bsd/spawn.c
# sys/bsd/sysdef.h
# sys/bsd/ttyio.c
# sys/sysv/Makefile
# sys/sysv/fileio.c
# sys/sysv/spawn.c
# sys/sysv/ttyio.c
# sys/sysv/sysdef.h
# sys/osk/readme.osk
# sys/osk/sysdef.h
# sys/osk/varargs.h
# sys/osk/fileio.c
# sys/osk/spawn.c
# sys/osk/ttyio.c
# sys/osk/makefile
# This archive created: Sat Nov 15 15:16:30 1986
export PATH; PATH=/bin:$PATH
if test ! -d sys/bsd
then
mkdir sys/bsd
fi
if test ! -d sys/sysv
then
mkdir sys/sysv
fi
if test ! -d sys/osk
then
mkdir sys/osk
fi
if test -f 'tty/termcap/ttykbd.c'
then
echo shar: will not over-write existing file "'tty/termcap/ttykbd.c'"
else
cat << \SHAR_EOF > 'tty/termcap/ttykbd.c'
/*
* Name: MicroEmacs
* Version: 30
* Termcap keyboard driver
* Created: 21-Aug-1986
* Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic
* Last edit: 03-Sep-86
*
* [ Several of the nasty comments about the XKEYS code are
* by me. [Bob Larson (usc-oberon!blarson)] It is my opinion
* that function keys cannot be made to work with standard
* emacs keybindings except on a very limited set of terminals.
* I just work with to many that do not fit the assumptions Mic's
* XKEYS code makes to consider it useful to me, and think that
* others considering using this code should look and see what
* it realy does first.
* ]
*
* If XKEYS is defined this routine looks for the following
* termcap sequences, which are obtained by "tty.c":
*
* ks -- start using the function keypad
* ke -- finish using the function keypad
* kh -- home key
* ku -- up arrow
* kd -- down arrow
* kl -- left arrow
* kr -- right arrow
* k0-k9 -- standard termcap function keys
* l0-l9 -- labels for termcap function keys
* (nonstandard)
* K0-K9 -- extra keys that we look for -- the get mapped
* internally to F10-F19
* L0-L9 -- labels for same.
*
* Bugs/features/problems:
*
* XKEYS and DPROMPT do not work together well.
*
* If the META introducer is used as the initial character of
* a function key sequence, what should the key parser do when the
* user wants to type a META-ed key, or just the META introducer
* alone? This is of practical importance on DEC terminals, where
* the META introducer is the Escape key. Even worse things happen
* on terminals that have something (or more than one thing) other
* than the META introducer as the inital character of a function
* sequence.
*
* The approach I took was that if the META introducer is the first
* character in a function sequence, and the second character c
* isn't part of a function key sequence, the parser returns
* (KMETA | c). If it sees two META introducers in a row, it
* returns one instance of METACH. This approach is subject to
* discussion and debate, but it works. [In at lease some cases.]
*
* If the META introducer is NOT the first character in a function
* sequence (including arrow keys) this code has a very nasty
* side effect of eating that key. For example, on an Adds viewpoint
* 60, six normal control characters are eaten if you have defined
* XKEYS and put the keys in the termcap. More than a little
* creativity is needed because ^U is one of the arrow keys, and
* prefixes aren't bindable.
*
* [ From a quick look at the code, it seems that a single character
* funciton key won't work, but it is still put in the table.
* ]
*/
#include "def.h"
/*
* Default key name table. Can be overridden by
* definitions of l0-l9 in the termcap entry. You
* can't redefine the names for the arrow keys
* and the home key.
*/
#ifdef XKEYS
/* key sequences (from tty.c) */
extern char *K[], *L[], *KS, *KE, *KH, *KU, *KD, *KL, *KR;
extern int putpad(); /* also from tty.c */
char *keystrings[] = {
NULL, "Home", "Down-Arrow", "Up-Arrow",
"Left-Arrow", "Right-Arrow", "F0", "F1",
"F2", "F3", "F4", "F5",
"F6", "F7", "F8", "F9",
"F10", "F11", "F12", "F13",
"F14", "F15", "F16", "F17",
"F18", "F19", NULL, NULL,
NULL, NULL, NULL, NULL
};
#else
char *keystrings[] = {
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL
};
#endif
#ifdef XKEYS
/*
* Type declarations for data structure we
* use to parse for function key sequences
*/
#define NODE 0 /* internal node */
#define VALUE 1 /* internal key code value */
#define SENTINEL 2 /* sentinel value */
typedef struct trienode {
int type; /* one of NODE, LEAF */
struct trienode *sibling, *child;
KEY value;
} TRIENODE, *TRIE;
TRIE keywords, sentinel, talloc(), tinsert();
#endif
/*
* Get keyboard character, and interpret
* any special keys on the keyboard. If XKEYS is
* #defined, use a dictionary organized as a
* trie to keep the parsing overhead down.
*
* To keep the function call overhead down, do the
* first level of parse() inside getkbd().
*
* Also, since ESC (the usual value of METACH) is
* the first character in many function key sequences,
* we return (KMETA | ch) if METACH-<ch> is not
* the start of an escape sequence. Blecch. Furthermore,
* if we see METACH-METACH, we return the value METACH.
* Phhhht.
*/
getkbd() {
#ifndef XKEYS
return (ttgetc());
#else
register TRIE t;
register int c;
KEY code;
c = ttgetc();
for (t = keywords; t->type == NODE; t = t->sibling)
if (t->value == c) { /* possible function key sequence */
if (c != METACH)
return (parse(t->child));
else { /* maybe sequence, maybe META char */
c = ttgetc();
for (t = t->child; t->type == NODE; t = t->sibling)
if (t->value == c)
return (parse(t->child));
/* METACH-METACH -> METACH */
if (c == METACH)
return (METACH);
/* Else make c into a META character */
if (ISLOWER(c) != FALSE)
c = TOUPPER(c);
if (c>=0x00 && c<=0x1F)
c = KCTRL | (c+'@');
return (KMETA | c);
}
}
return (c);
#endif
}
#ifdef XKEYS
static parse(first)
TRIE first;
{
register TRIE t;
register int c;
if (first->type == VALUE) /* found a match! */
return (first->value);
c = ttgetc();
for (t = first; t->type == NODE; t = t->sibling)/* look thru list */
if (t->value == c)
return (parse(t->child)); /* try next level */
return (c); /* nothing matched */
}
#endif
/*
* If XKEYS is defined, get key definitions from the termcap
* entry and put them in the parse table.
*/
ttykeymapinit()
{
#ifdef XKEYS
register int i;
register int s;
register char *cp;
register SYMBOL *sp;
if (KS && *KS) /* turn on keypad */
putpad(KS);
tinit(); /* set up initial trie */
for (i = 0; i < NFKEYS; i++) {
if (K[i] && *K[i])
adddict(K[i], (KEY) (KF0 + i));
if (L[i] && *L[i]) /* record new name */
keystrings[(KF0-KFIRST)+i] = L[i];
}
/*
* Add the home and arrow keys
*/
if (KH && *KH)
adddict(KH, (KEY) KHOME);
if (KU && *KU)
adddict(KU, (KEY) KUP);
if (KD && *KD)
adddict(KD, (KEY) KDOWN);
if (KL && *KL)
adddict(KL, (KEY) KLEFT);
if (KR && *KR)
adddict(KR, (KEY) KRIGHT);
/*
* Bind things to the movement keys
*/
keydup(KHOME, "beginning-of-buffer"); /* for now */
keydup(KUP, "previous-line");
keydup(KDOWN, "next-line");
keydup(KLEFT, "backward-char");
keydup(KRIGHT, "forward-char");
/*
* These bindings sort of go with the termcap I use for my vt220
* clone, which is why they're #ifdef'd. I don't really use
* them, but it gives you an example of what to do...
*/
#ifdef MPK
keydup((KEY)KF0, "describe-key-briefly"); /* Help */
keydup((KEY)KF1, "execute-extended-command"); /* Do */
keydup((KEY)KF2, "search-forward"); /* Find */
keydup((KEY)KF3, "yank"); /* Insert here */
keydup((KEY)KF4, "kill-region"); /* Remove */
keydup((KEY)KF5, "set-mark-command"); /* Select */
keydup((KEY)KF6, "scroll-down"); /* Prev Screen */
keydup((KEY)KF7, "scroll-up"); /* Next Screen */
/* Don't expect these to make much sense, I'm just filling in */
/* the keymap B-] */
keydup((KEY)KF10, "suspend-emacs"); /* PF1 */
keydup((KEY)KF11, "query-replace"); /* PF2 */
keydup((KEY)KF12, "call-last-kbd-macro"); /* PF3 */
keydup((KEY)KF13, "save-buffers-kill-emacs"); /* PF4 */
#endif MPK
#endif XKEYS
}
#ifdef XKEYS
/*
* Clean up the keyboard -- called by tttidy()
*/
ttykeymaptidy()
{
tdelete(keywords); /* get rid of parse tree */
free(sentinel); /* remove sentinel value */
if (KE && *KE)
putpad(KE); /* turn off keypad */
}
/*
* * * * * * * * Dictionary management * * * * * * * * *
*/
/*
* Add a key string to the dictionary.
*/
static adddict(kstr, kcode)
char *kstr;
KEY kcode;
{
keywords = tinsert(kstr, kcode, keywords);
}
/*
* Initialize the parse tree by creating the sentinel value
*/
static tinit()
{
keywords = sentinel = talloc();
sentinel->type = SENTINEL;
sentinel->value = (KEY) -1;
sentinel->sibling = sentinel->child = sentinel; /* set up a loop */
}
/*
* Deallocate all the space used by the trie --
* Tell all the siblings to deallocate space, then
* all the children.
*/
static tdelete(t)
register TRIE t;
{
if (t->type != SENTINEL) {
tdelete(t->sibling);
tdelete(t->child);
free(t);
}
}
/*
* Insert a dictionary key string and a value into the dictionary,
* returning as the value the first sibling in the current sublevel,
* which may have been changed by an insertion into the list of siblings.
*/
static TRIE tinsert(kstring, kcode, first)
register char *kstring;
register KEY kcode;
TRIE first;
{
register TRIE match;
register TRIE p;
if (!*kstring) { /* base case -- return a value node */
p = talloc();
p->type = VALUE;
p->value = kcode;
p->sibling = p->child = sentinel;
return (p);
}
/* recursive case -- insert rest of string in trie */
/* search for sibling that matches the current character */
match = NULL;
for (p = first; p->type == NODE; p = p->sibling)
if (p->value == *kstring) {
match = p;
break;
}
if (match == NULL) { /* if not, add it to beginning of the list */
match = talloc();
match->type = NODE;
match->value = *kstring;
match->sibling = first;
match->child = sentinel;
first = match;
}
/* add rest of string to this child's subtrie */
match->child = tinsert(kstring+1, kcode, match->child);
return (first);
}
/*
* Allocate a trie node
*/
static TRIE talloc()
{
char *malloc();
TRIE t;
if ((t = (TRIE) malloc(sizeof(TRIENODE))) == NULL)
panic("talloc: can't allocate trie node!");
return (t);
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/Makefile'
then
echo shar: will not over-write existing file "'sys/bsd/Makefile'"
else
cat << \SHAR_EOF > 'sys/bsd/Makefile'
# Makefile for MicroEMACS.
# Is there a better way to do the rebuilds, other than using
# the links?
SYS = bsd
TTY = termcap
LIBS = -ltermcap
# CDEFS gets defines, and gets passed to lint. CFLAGS gets flags, and doesn't
# get passed to lint.
CDEFS = -DDO_METAKEY -DSTARTUP
CFLAGS = -g $(CDEFS)
OBJ = basic.o buffer.o cinfo.o display.o echo.o extend.o file.o kbd.o \
line.o main.o match.o random.o region.o search.o symbol.o version.o \
window.o paragraph.o prefix.o \
word.o fileio.o spawn.o ttyio.o tty.o ttykbd.o
OSRCS = fileio.c spawn.c ttyio.c tty.c ttykbd.c
SRCS = basic.c buffer.c cinfo.c display.c echo.c extend.c file.c kbd.c \
line.c main.c match.c random.c region.c search.c symbol.c version.c \
window.c word.c paragraph.c prefix.c
OINCS = ttydef.h sysdef.h
INCS = def.h
mg: $(OBJ)
cc $(CFLAGS) -o mg $(OBJ) $(LIBS)
# the v arg to lint turns off all the complaints about args f, n & k.
# It's a good idea to take that out and rerun make lint after getting
# a clean lint, just to verify that f, n & k are the ONLY unused args.
lint: $(SRCS) $(OSRCS)
lint -ahb $(CDEFS) $(SRCS) $(OSRCS)
$(OBJ): def.h sysdef.h ttydef.h
sysdef.h: sys/$(SYS)/sysdef.h # Update links, if needed.
rm -f sysdef.h
ln sys/$(SYS)/sysdef.h .
ttydef.h: tty/$(TTY)/ttydef.h
rm -f ttydef.h
ln tty/$(TTY)/ttydef.h .
fileio.c: sys/$(SYS)/fileio.c
rm -f fileio.c
ln sys/$(SYS)/fileio.c .
spawn.c: sys/$(SYS)/spawn.c
rm -f spawn.c
ln sys/$(SYS)/spawn.c .
tty.c: tty/$(TTY)/tty.c
rm -f tty.c
ln tty/$(TTY)/tty.c .
ttyio.c: sys/$(SYS)/ttyio.c
rm -f ttyio.c
ln sys/$(SYS)/ttyio.c .
ttykbd.c: tty/$(TTY)/ttykbd.c
rm -f ttykbd.c
ln tty/$(TTY)/ttykbd.c .
port: $(SRCS) $(INCS)
rm -f port
tar cfb port 1 $?
clean:; rm -f $(OBJ) $(OSRCS) $(OINCS)
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/fileio.c'
then
echo shar: will not over-write existing file "'sys/bsd/fileio.c'"
else
cat << \SHAR_EOF > 'sys/bsd/fileio.c'
/*
* bsd (4.2, others?) and Ultrix-32 file I/O.
*/
#include "def.h"
static FILE *ffp;
extern char *getenv();
/*
* handle C-shell style names
*/
static char *bsd(fn, buf, bufsiz) char *fn, *buf; int bufsiz;
{
if (*fn != '~')
return (fn);
else { /* C-shell $HOME-relative names */
strncpy(buf, getenv("HOME"), bufsiz);
strncat(buf, fn + 1, bufsiz);
return (buf);
}
}
/*
* Open a file for reading.
*/
ffropen(fn) char *fn; {
char buf[NFILEN];
fn = bsd(fn, buf, sizeof(buf));
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).
*/
ffwopen(fn) char *fn; {
char buf[NFILEN];
fn = bsd(fn, buf, sizeof(buf));
if ((ffp=fopen(fn, "w")) == NULL) {
ewprintf("Cannot open file for writing");
return (FIOERR);
}
return (FIOSUC);
}
/*
* Close a file.
* Should look at the status.
*/
ffclose() {
(VOID) fclose(ffp);
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.
*/
ffputline(buf, nbuf) register char buf[]; {
register int i;
/* What's with putc? */
for (i=0; i<nbuf; ++i)
putc(buf[i]&0xFF, ffp);
putc('\n', ffp);
if (ferror(ffp) != FALSE) {
ewprintf("Write I/O error");
return (FIOERR);
}
return (FIOSUC);
}
/*
* Read a line from a file, and store the bytes
* in the supplied buffer. Stop on end of file or end of
* line. Don't get upset by files that don't have an end of
* line on the last line; this seem to be common on CP/M-86 and
* MS-DOS (the suspected culprit is VAX/VMS kermit, but this
* has not been confirmed. If this is sufficiently researched
* it may be possible to pull this kludge). Delete any CR
* followed by an LF. This is mainly for runoff documents,
* both on VMS and on Ultrix (they get copied over from
* VMS systems with DECnet).
*/
ffgetline(buf, nbuf) register char buf[]; {
register int c;
register int i;
i = 0;
for (;;) {
c = getc(ffp);
if (c == '\r') { /* Delete any non-stray */
c = getc(ffp); /* carriage returns. */
if (c != '\n') {
if (i >= nbuf-1) {
ewprintf("File has long line");
return (FIOERR);
}
buf[i++] = '\r';
}
}
if (c==EOF || c=='\n') /* End of line. */
break;
if (i >= nbuf-1) {
ewprintf("File has long line");
return (FIOERR);
}
buf[i++] = c;
}
if (c == EOF) { /* End of file. */
if (ferror(ffp) != FALSE) {
ewprintf("File read error");
return (FIOERR);
}
if (i == 0) /* Don't get upset if */
return (FIOEOF); /* no newline at EOF. */
}
buf[i] = 0;
return (FIOSUC);
}
#if BACKUP
/*
* Rename the file "fname" into a backup
* copy. On Unix the backup has the same name as the
* original file, with a "~" on the end; this seems to
* be newest of the new-speak. The error handling is
* all in "file.c". The "unlink" is perhaps not the
* right thing here; I don't care that much as
* I don't enable backups myself.
*/
fbackupfile(fn) char *fn; {
register char *nname;
char *malloc();
char buf[NFILEN];
fn = bsd(fn, buf, sizeof(buf));
if ((nname=malloc(strlen(fn)+1+1)) == NULL) {
ewprintf("Can't get %d bytes", strlen(fn) + 1);
return (ABORT);
}
(void) strcpy(nname, fn);
(void) strcat(nname, "~");
(void) unlink(nname); /* Ignore errors. */
if (rename(fn, nname) < 0) {
free(nname);
return (FALSE);
}
free(nname);
return (TRUE);
}
#endif
/*
* The string "fn" is a file name.
* Perform any required case adjustments. All sustems
* we deal with so far have case insensitive file systems.
* We zap everything to lower case. The problem we are trying
* to solve is getting 2 buffers holding the same file if
* you visit one of them with the "caps lock" key down.
* On UNIX file names are dual case, so we leave
* everything alone.
*/
/*ARGSUSED*/
adjustcase(fn) register char *fn; {
#if 0
register int c;
while ((c = *fn) != 0) {
if (c>='A' && c<='Z')
*fn = c + 'a' - 'A';
++fn;
}
#endif
}
#ifdef STARTUP
#include <sys/file.h>
/*
* find the users startup file, and return it's name. Check for
* $HOME/.mg then for $HOME/.emacs, then give up.
*/
char *
startupfile() {
register char *file;
static char home[NFILEN];
char *getenv();
if ((file = getenv("HOME")) == NULL) return NULL;
if (strlen(file)+7 >= NFILEN - 1) return NULL;
(VOID) strcpy(home, file);
file = &(home[strlen(home)]);
*file++ = '/';
(VOID) strcpy(file, ".mg");
if (access(home, F_OK ) == 0) return home;
(VOID) strcpy(file, ".emacs");
if (access(home, F_OK) == 0) return home;
return NULL;
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/spawn.c'
then
echo shar: will not over-write existing file "'sys/bsd/spawn.c'"
else
cat << \SHAR_EOF > 'sys/bsd/spawn.c'
/*
* Spawn. New version, which
* interracts with the job control stuff
* in the 4.X BSD C shell.
* Last edit: Wed Aug 27 11:16:07 PDT 1986
* By: rtech!daveb, to use stop for ksh.
*/
#include "def.h"
#include <sgtty.h>
#include <signal.h>
char *shellp = NULL; /* Saved "SHELL" name. */
extern struct sgttyb oldtty; /* There really should be a */
extern struct sgttyb newtty; /* nicer way of doing this, so */
extern struct sgttyb oldtchars; /* spawn does not need to know */
extern struct sgttyb newtchars; /* about the insides of the */
extern struct sgttyb oldltchars; /* terminal I/O code. */
extern struct sgttyb newltchars;
extern char *getenv();
/*
* This code does a one of 2 different
* things, depending on what version of the shell
* you are using. If you are using the C shell, which
* implies that you are using job control, then MicroEMACS
* moves the cursor to a nice place and sends itself a
* stop signal. If you are using the Bourne shell it runs
* a subshell using fork/exec. Bound to "C-C", and used
* as a subcommand by "C-Z".
*
* Daveb -- changed sense of test so that we only spawn if you
* are explicitly using /bin/sh. This makes it stop
* work with the ksh.
*/
/*ARGSUSED*/
spawncli(f, n, k) {
register int pid, wpid, (*oqsig)(), (*oisig)(), omask;
int status;
if (shellp == NULL) {
shellp = getenv("SHELL");
if (shellp == NULL)
shellp = getenv("shell");
if (shellp == NULL)
shellp = "/bin/sh"; /* Safer. */
}
ttcolor(CTEXT);
ttnowindow();
if (strcmp(shellp, "/bin/csh") == 0) {
if (epresf != FALSE) {
ttmove(nrow-1, 0);
tteeol();
epresf = FALSE;
} /* Csh types a "\n" */
ttmove(nrow-2, 0); /* before "Stopped". */
} else {
ttmove(nrow-1, 0);
if (epresf != FALSE) {
tteeol();
epresf = FALSE;
}
}
ttflush();
if (ioctl(0, TIOCSLTC, (char *) &oldltchars) < 0
|| ioctl(0, TIOCSETC, (char *) &oldtchars) < 0
|| ioctl(0, TIOCSETP, (char *) &oldtty) < 0) {
ewprintf("IOCTL #1 to terminal failed");
return (FALSE);
}
if (strcmp(shellp, "/bin/sh") != 0) { /* C shell, ksh */
omask = sigsetmask(0);
(void) kill(0, SIGTSTP);
setttysize() ;
(void) sigsetmask(omask);
} else { /* Bourne shell. */
oqsig = signal(SIGQUIT, SIG_IGN);
oisig = signal(SIGINT, SIG_IGN);
if ((pid=fork()) < 0) {
(void) signal(SIGQUIT, oqsig);
(void) signal(SIGINT, oisig);
ewprintf("Failed to create process");
return (FALSE);
}
if (pid == 0) {
execl(shellp, "sh", "-i", NULL);
_exit(0); /* Should do better! */
}
while ((wpid=wait(&status))>=0 && wpid!=pid)
;
(void) signal(SIGQUIT, oqsig);
(void) signal(SIGINT, oisig);
}
sgarbf = TRUE; /* Force repaint. */
if (ioctl(0, TIOCSETP, (char *) &newtty) < 0
|| ioctl(0, TIOCSETC, (char *) &newtchars) < 0
|| ioctl(0, TIOCSLTC, (char *) &newltchars) < 0) {
ewprintf("IOCTL #2 to terminal failed");
return (FALSE);
}
return (TRUE);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/sysdef.h'
then
echo shar: will not over-write existing file "'sys/bsd/sysdef.h'"
else
cat << \SHAR_EOF > 'sys/bsd/sysdef.h'
/*
* Ultrix-32 system header file.
*/
#define PCC 1 /* "[]" gets an error. */
#define KBLOCK 8192 /* Kill grow. */
#define GOOD 0 /* Good exit status. */
typedef int RSIZE; /* Type for file/region sizes */
typedef short KEY; /* Type for internal keystrokes */
/*
* Macros used by the buffer name making code.
* Start at the end of the file name, scan to the left
* until BDC1 (or BDC2, if defined) is reached. The buffer
* name starts just to the right of that location, and
* stops at end of string (or at the next BDC3 character,
* if defined). BDC2 and BDC3 are mainly for VMS.
*/
#define BDC1 '/' /* Buffer names. */
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/bsd/ttyio.c'
then
echo shar: will not over-write existing file "'sys/bsd/ttyio.c'"
else
cat << \SHAR_EOF > 'sys/bsd/ttyio.c'
/*
* 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 "def.h"
#include <sgtty.h>
#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;
#ifdef TIOCGWINSZ
struct winsize winsize; /* 4.3 BSD window sizing */
#endif
int nrow; /* Terminal size, rows. */
int ncol; /* Terminal size, columns. */
/*
* This function gets called once, to set up
* the terminal channel. On Ultrix is's tricky, since
* we want flow control, but we don't want any characters
* stolen to send signals. Use CBREAK mode, and set all
* characters but start and stop to 0xFF.
*/
ttopen() {
register char *tv_stype;
char *getenv(), *tgetstr(), tcbuf[1024], err_str[72];
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. */
#ifdef FLOWCONTROL
newtty.sg_flags |= CBREAK; /* Half-cooked mode. */
#else
newtty.sg_flags |= RAW|ANYP; /* raw mode for 8 bit path.*/
#endif
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. */
#if FLOWCONTROL
newtchars.t_startc = 0x11; /* ^Q, for terminal. */
newtchars.t_stopc = 0x13; /* ^S, for terminal. */
#else
newtchars.t_startc = 0xFF; /* ^Q, for terminal. */
newtchars.t_stopc = 0xFF; /* ^S, for terminal. */
#endif
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)
{
puts("Environment variable TERM not defined!");
exit(1);
}
if((tgetent(tcbuf, tv_stype)) != 1)
{
(void) sprintf(err_str, "Unknown terminal type %s!", tv_stype);
puts(err_str);
exit(1);
}
setttysize() ;
}
/*
* This function gets called just
* before we go back home to the shell. Put all of
* the terminal parameters back.
*/
ttclose() {
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.
*/
ttputc(c) {
if (nobuf >= NOBUF)
ttflush();
obuf[nobuf++] = c;
}
/*
* Flush output.
*/
ttflush() {
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.
*/
ttgetc() {
char buf[1];
while (read(0, &buf[0], 1) != 1)
;
return (buf[0] & 0xFF);
}
/*
* set the tty size. Functionized for 43BSD.
*/
setttysize() {
#ifdef TIOCGWINSZ
if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
nrow = winsize . ws_row;
ncol = winsize . ws_col;
} else nrow = 0;
if(nrow<=0 || ncol<=0)
#endif
if ((nrow=tgetnum ("li")) <= 0
|| (ncol=tgetnum ("co")) <= 0) {
nrow = 24;
ncol = 80;
}
if (nrow > NROW) /* Don't crash if the */
nrow = NROW; /* termcap entry is */
if (ncol > NCOL) /* too big. */
ncol = NCOL;
}
/*
* typeahead returns TRUE if there are characters available to be read
* in.
*/
typeahead() {
int x;
return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x);
}
/*
* panic - just exit, as quickly as we can.
*/
panic(s) char *s; {
printf(stderr, "panic: %s\n", s);
abort(); /* To leave a core image. */
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/Makefile'
then
echo shar: will not over-write existing file "'sys/sysv/Makefile'"
else
cat << \SHAR_EOF > 'sys/sysv/Makefile'
# Makefile for MicroEMACS.
# Is there a better way to do the rebuilds, other than using
# the links?
SYS = sysv
TTY = termcap
# you may not need (or have) termlib...
LIBS = -lcurses -ltermlib
# CDEFS gets defines, and gets passed to lint. CFLAGS gets flags, and doesn't
# get passed to lint.
CDEFS = -DDO_METAKEY
CFLAGS = -g $(CDEFS)
OBJ = basic.o buffer.o cinfo.o display.o echo.o extend.o file.o kbd.o \
line.o main.o match.o random.o region.o search.o symbol.o version.o \
window.o paragraph.o prefix.o \
word.o fileio.o spawn.o ttyio.o tty.o ttykbd.o
OSRCS = fileio.c spawn.c ttyio.c tty.c ttykbd.c
SRCS = basic.c buffer.c cinfo.c display.c echo.c extend.c file.c kbd.c \
line.c main.c match.o random.c region.c search.c symbol.c version.c \
window.c word.c paragraph.c prefix.c
OINCS = ttydef.h sysdef.h
INCS = def.h
mg: $(OBJ)
cc $(CFLAGS) -o mg $(OBJ) $(LIBS)
# for AT&T UNIX-PC
mg.7300: $(OBJ)
ld /lib/crt0s.o /lib/shlib.ifile $(OBJ) -o mg.7300
lint: $(SRCS) $(OSRCS)
lint $(CDEFS) $(SRCS) $(OSRCS)
$(OBJ): def.h sysdef.h ttydef.h
sysdef.h: sys/$(SYS)/sysdef.h # Update links, if needed.
rm -f sysdef.h
ln sys/$(SYS)/sysdef.h .
ttydef.h: tty/$(TTY)/ttydef.h
rm -f ttydef.h
ln tty/$(TTY)/ttydef.h .
fileio.c: sys/$(SYS)/fileio.c
rm -f fileio.c
ln sys/$(SYS)/fileio.c .
spawn.c: sys/$(SYS)/spawn.c
rm -f spawn.c
ln sys/$(SYS)/spawn.c .
tty.c: tty/$(TTY)/tty.c
rm -f tty.c
ln tty/$(TTY)/tty.c .
ttyio.c: sys/$(SYS)/ttyio.c
rm -f ttyio.c
ln sys/$(SYS)/ttyio.c .
ttykbd.c: tty/$(TTY)/ttykbd.c
rm -f ttykbd.c
ln tty/$(TTY)/ttykbd.c .
clean:; rm -f $(OBJ) $(OSRCS) $(OINCS)
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/fileio.c'
then
echo shar: will not over-write existing file "'sys/sysv/fileio.c'"
else
cat << \SHAR_EOF > 'sys/sysv/fileio.c'
/*
* Name: MicroEMACS
* System V file I/O
*/
#include "def.h"
# ifndef F_OK
# define F_OK 0
# define X_OK 1
# define W_OK 2
# define R_OK 4
# endif
/*
* Move bytes, overlaps OK (daveb).
*
* Doesn't really belong here, but it's system specific since it
* is in assembler in some C libraries.
*/
bcopy( from, to, cnt )
char *from;
char *to;
int cnt;
{
if ( from == to )
return;
if( from > to )
{
while( cnt-- )
*to++ = *from++;
}
else
{
to += cnt;
from += cnt;
while( cnt-- )
*--to = *--from;
}
}
static FILE *ffp;
/*
* Open a file for reading.
*/
ffropen(fn)
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).
*/
ffwopen(fn)
char *fn;
{
if ((ffp=fopen(fn, "w")) == NULL) {
ewprintf("Cannot open file for writing");
return (FIOERR);
}
return (FIOSUC);
}
/*
* Close a file.
* Should look at the status.
*/
ffclose()
{
(VOID) fclose(ffp);
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.
*/
ffputline(buf, nbuf)
register char buf[];
{
register int i;
for (i=0; i<nbuf; ++i)
putc(buf[i]&0xFF, ffp);
putc('\n', ffp);
if (ferror(ffp) != FALSE) {
ewprintf("Write I/O error");
return (FIOERR);
}
return (FIOSUC);
}
/*
* Read a line from a file, and store the bytes
* in the supplied buffer. Stop on end of file or end of
* line. Don't get upset by files that don't have an end of
* line on the last line; this seem to be common on CP/M-86 and
* MS-DOS (the suspected culprit is VAX/VMS kermit, but this
* has not been confirmed. If this is sufficiently researched
* it may be possible to pull this kludge). Delete any CR
* followed by an LF. This is mainly for runoff documents,
* both on VMS and on Ultrix (they get copied over from
* VMS systems with DECnet).
*/
ffgetline(buf, nbuf)
register char buf[];
{
register int c;
register int i;
i = 0;
for (;;) {
c = getc(ffp);
if (c == '\r') { /* Delete any non-stray */
c = getc(ffp); /* carriage returns. */
if (c != '\n') {
if (i >= nbuf-1) {
ewprintf("File has long line");
return (FIOERR);
}
buf[i++] = '\r';
}
}
if (c==EOF || c=='\n') /* End of line. */
break;
if (i >= nbuf-1) {
ewprintf("File has long line");
return (FIOERR);
}
buf[i++] = c;
}
if (c == EOF) { /* End of file. */
if (ferror(ffp) != FALSE) {
ewprintf("File read error");
return (FIOERR);
}
if (i == 0) /* Don't get upset if */
return (FIOEOF); /* no newline at EOF. */
}
buf[i] = 0;
return (FIOSUC);
}
#if BACKUP
/*
* Rename the file "fname" into a backup
* copy. On Unix the backup has the same name as the
* original file, with a "~" on the end; this seems to
* be newest of the new-speak. The error handling is
* all in "file.c". The "unlink" is perhaps not the
* right thing here; I don't care that much as
* I don't enable backups myself.
*/
fbackupfile(fname)
char *fname;
{
register char *nname;
if ((nname=malloc(strlen(fname)+1+1)) == NULL)
return (ABORT);
(void) strcpy(nname, fname);
(void) strcat(nname, "~");
(void) unlink(nname); /* Ignore errors. */
/* no rename on System V, so do it dangerous way. */
if ( link(fname, nname) < 0 || unlink(fname) < 0 ) {
free(nname);
return (FALSE);
}
free(nname);
return (TRUE);
}
#endif
/*
* The string "fn" is a file name.
* Perform any required case adjustments. All sustems
* we deal with so far have case insensitive file systems.
* We zap everything to lower case. The problem we are trying
* to solve is getting 2 buffers holding the same file if
* you visit one of them with the "caps lock" key down.
* On UNIX file names are dual case, so we leave
* everything alone.
*/
/*ARGSUSED*/
adjustcase(fn)
register char *fn;
{
#if 0
register int c;
while ((c = *fn) != 0) {
if (c>='A' && c<='Z')
*fn = c + 'a' - 'A';
++fn;
}
#endif
}
#ifdef STARTUP
#include <sys/types.h>
#include <sys/file.h>
/*
* find the users startup file, and return it's name. Check for
* $HOME/.mg then for $HOME/.emacs, then give up.
*/
char *
startupfile()
{
register char *file;
static char home[NFILEN];
char *getenv();
if ( (file = getenv("HOME")) == NULL
|| strlen(file)+7 >= NFILEN - 1 )
return NULL;
(VOID) strcpy(home, file);
file = &(home[strlen(home)]);
*file++ = '/';
(VOID) strcpy(file, ".mg");
if (access(home, F_OK ) == 0) return home;
(VOID) strcpy(file, ".emacs");
if (access(home, F_OK) == 0) return home;
return NULL;
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/spawn.c'
then
echo shar: will not over-write existing file "'sys/sysv/spawn.c'"
else
cat << \SHAR_EOF > 'sys/sysv/spawn.c'
/*
* Name: MicroEMACS
* Spawn CLI for System V.
* Version: 0
* Last edit: 17-Apr-86
* By: gonzo!daveb
* {sun, amdahl, mtxinu}!rtech!daveb
*
* Spawn for System V.
*/
#include "def.h"
#include <signal.h>
char *shellp = NULL; /* Saved "SHELL" program. */
char *shname = NULL; /* Saved shell name */
extern char *getenv();
/*
* On System V, we no gots job control, so always run
* a subshell using fork/exec. Bound to "C-C", and used
* as a subcommand by "C-Z". (daveb)
*
* Returns 0 if the shell executed OK, something else if
* we couldn't start shell or it exited badly.
*/
spawncli(f, n, k)
{
extern char *strrchr();
register int pid;
register int wpid;
register int (*oqsig)();
register int (*oisig)();
int status;
int errp = FALSE;
if (shellp == NULL) {
shellp = getenv("SHELL");
if (shellp == NULL)
shellp = getenv("shell");
if (shellp == NULL)
shellp = "/bin/sh"; /* Safer. */
shname = strrchr( shellp, '/' );
shname = shname ? shname++ : shellp;
}
ttcolor(CTEXT);
ttnowindow();
ttmove(nrow-1, 0);
if (epresf != FALSE) {
tteeol();
epresf = FALSE;
}
ttclose();
sgarbf = TRUE; /* Force repaint. */
oqsig = signal(SIGQUIT, SIG_IGN);
oisig = signal(SIGINT, SIG_IGN);
if ((pid=fork()) == 0) {
execlp(shellp, shname, "-i", NULL);
_exit(1); /* Should do better! */
}
else if (pid > 0) {
while ((wpid=wait(&status))>=0 && wpid!=pid)
;
}
else errp = TRUE;
signal(SIGINT, oisig);
ttopen();
if(errp)
ewprintf("Failed to create process");
return ( errp | status );
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/ttyio.c'
then
echo shar: will not over-write existing file "'sys/sysv/ttyio.c'"
else
cat << \SHAR_EOF > 'sys/sysv/ttyio.c'
/*
* Name: MicroEMACS
* System V terminal I/O.
* Version: 0
* Last edit: Tue Aug 26 23:57:57 PDT 1986
* By: gonzo!daveb
* {sun, amdahl, mtxinu}!rtech!gonzo!daveb
*
* The functions in this file
* negotiate with the operating system for
* keyboard characters, and write characters to
* the display in a barely buffered fashion.
*
* This version goes along with tty/termcap/tty.c.
* Terminal size is determined there, rather than here, and
* this does not open the termcap file
*/
#include "def.h"
#include <sys/types.h>
#include <fcntl.h>
#include <termio.h>
#define NOBUF 512 /* Output buffer size. */
char obuf[NOBUF]; /* Output buffer. */
int nobuf; /* buffer count */
static struct termio ot; /* entry state of the terminal */
static struct termio nt; /* editor's terminal state */
static int ttyactivep = FALSE; /* terminal in editor mode? */
static int ttysavedp = FALSE; /* terminal state saved? */
int nrow; /* Terminal size, rows. */
int ncol; /* Terminal size, columns. */
/* These are used to implement typeahead on System V */
int kbdflgs; /* saved keyboard fd flags */
int kbdpoll; /* in O_NDELAY mode */
int kbdqp; /* there is a char in kbdq */
char kbdq; /* char we've already read */
/*
* This function gets called once, to set up
* the terminal channel. This version turns off flow
* control. This may be wrong for your system, but no
* good solution has really been found (daveb).
*/
ttopen()
{
register char *cp;
extern char *getenv();
if (ttyactivep)
return;
if( !ttysavedp )
{
if (ioctl(0, TCGETA, &ot) < 0)
abort();
nt = ot; /* save entry state */
nt.c_cc[VMIN] = 1; /* one character read is OK */
nt.c_cc[VTIME] = 0; /* Never time out. */
nt.c_iflag |= IGNBRK;
nt.c_iflag &= ~( ICRNL | INLCR | ISTRIP | IXON | IXOFF );
nt.c_oflag &= ~OPOST;
nt.c_cflag |= CS8; /* allow 8th bit on input */
nt.c_cflag &= ~PARENB; /* Don't check parity */
nt.c_lflag &= ~( ECHO | ICANON | ISIG );
kbdflgs = fcntl( 0, F_GETFL, 0 );
kbdpoll = FALSE;
ttysavedp = TRUE;
}
if (ioctl(0, TCSETAF, &nt) < 0)
abort();
/* This really belongs in tty/termcap... */
if ((cp=getenv("TERMCAP")) == NULL
|| (nrow=getvalue(cp, "li")) <= 0
|| (ncol=getvalue(cp, "co")) <= 0) {
nrow = 24;
ncol = 80;
}
if (nrow > NROW) /* Don't crash if the */
nrow = NROW; /* termcap entry is */
if (ncol > NCOL) /* too big. */
ncol = NCOL;
ttyactivep = TRUE;
}
/*
* This routine scans a string, which is
* actually the return value of a getenv call for the TERMCAP
* variable, looking for numeric parameter "name". Return the value
* if found. Return -1 if not there. Assume that "name" is 2
* characters long. This limited use of the TERMCAP lets us find
* out the size of a window on the X display.
*/
getvalue(cp, name)
register char *cp;
register char *name;
{
for (;;) {
while (*cp!=0 && *cp!=':')
++cp;
if (*cp++ == 0) /* Not found. */
return (-1);
if (cp[0]==name[0] && cp[1]==name[1] && cp[2]=='#')
return (atoi(cp+3)); /* Stops on ":". */
}
}
/*
* This function gets called just
* before we go back home to the shell. Put all of
* the terminal parameters back.
*/
ttclose()
{
if(!ttysavedp || !ttyactivep)
return;
ttflush();
if (ioctl(0, TCSETAF, &ot) < 0 || fcntl( 0, F_SETFL, kbdflgs ) < 0)
abort();
ttyactivep = FALSE;
}
/*
* Write character to the display.
* Characters are buffered up, to make things
* a little bit more efficient.
*/
ttputc(c)
{
if (nobuf >= NOBUF)
ttflush();
obuf[nobuf++] = c;
}
/*
* Flush output.
*/
ttflush()
{
if (nobuf != 0) {
write(1, obuf, nobuf);
nobuf = 0;
}
}
/*
* Read character from terminal.
* All 8 bits are returned, so that you can use
* a multi-national terminal.
*
* If keyboard 'queue' already has typeahead from a typeahead() call,
* just return it. Otherwise, make sure we are in blocking i/o mode
* and read a character.
*/
ttgetc()
{
if( kbdqp )
kbdqp = FALSE;
else
{
if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
abort();
kbdpoll = FALSE;
while (read(0, &kbdq, 1) != 1)
;
}
return ( kbdq & 0xff );
}
/*
* Return non-FALSE if typeahead is pending.
*
* If already got unread typeahead, do nothing.
* Otherwise, set keyboard to O_NDELAY if not already, and try
* a one character read.
*/
typeahead()
{
if( !kbdqp )
{
if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
abort();
kbdqp = (1 == read( 0, &kbdq, 1 ));
}
return ( kbdqp );
}
/*
* panic: print error and die, leaving core file.
* Don't know why this is needed (daveb).
*/
panic(s)
char *s;
{
fprintf(stderr, "%s\r\n", s);
abort();
}
/*
** This should check the size of the window, and reset if needed.
*/
setttysize()
{
#ifdef TIOCGWINSZ
if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
nrow = winsize . ws_row;
ncol = winsize . ws_col;
} else
#endif
if ((nrow=tgetnum ("li")) <= 0
|| (ncol=tgetnum ("co")) <= 0) {
nrow = 24;
ncol = 80;
}
if (nrow > NROW) /* Don't crash if the */
nrow = NROW; /* termcap entry is */
if (ncol > NCOL) /* too big. */
ncol = NCOL;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/sysv/sysdef.h'
then
echo shar: will not over-write existing file "'sys/sysv/sysdef.h'"
else
cat << \SHAR_EOF > 'sys/sysv/sysdef.h'
/*
* Name: MicroEMACS
* Ultrix-32 system header file same for System V.
* Version: 29
* Last edit: 05-Feb-86
* By: rex::conroy
* decvax!decwrl!dec-rhea!dec-rex!conroy
*/
#define PCC 1 /* "[]" gets an error. */
#define KBLOCK 8192 /* Kill grow. */
#define GOOD 0 /* Good exit status. */
typedef int RSIZE; /* Type for file/region sizes */
typedef short KEY; /* Type for internal keystrokes */
/*
* Macros used by the buffer name making code.
* Start at the end of the file name, scan to the left
* until BDC1 (or BDC2, if defined) is reached. The buffer
* name starts just to the right of that location, and
* stops at end of string (or at the next BDC3 character,
* if defined). BDC2 and BDC3 are mainly for VMS.
*/
#define BDC1 '/' /* Buffer names. */
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/readme.osk'
then
echo shar: will not over-write existing file "'sys/osk/readme.osk'"
else
cat << \SHAR_EOF > 'sys/osk/readme.osk'
readme.osk for MicroGnuEmacs 1a Nov 10, 1986
Copy sys/osk/makefile to .
copy sys/osk/varargs.h to /dd/defs/varargs.h if you don't have one.
(I think version 2.1 of the C compiler will include mine.)
Look at makefile for personal preference options and terminal selection.
Use make to compile.
Currently defined for termcap, assuming a termlib library exists.
(I've heard there will be one with version 2.1 of the C compiler. I
can't distribute the one I have.)
Baud should be set correctly in tmode/xmode even if it is set in
hardware as it is on a QT+. This is used for display optimization
and padding.
All files are indented assuming tabs every eight columns, and mg
itself uses tabs there. I have no idea why Microware decided not to
follow this defacto industry standard, but at least they allow you to
change your system to whatever you want.
The enviornment variable TERM is used to determine your terminal type,
and HOME is used to find the .mg startup file.
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/sysdef.h'
then
echo shar: will not over-write existing file "'sys/osk/sysdef.h'"
else
cat << \SHAR_EOF > 'sys/osk/sysdef.h'
/*
* Os9/68K specific definitions for micrognuemacs
*/
#define PCC /* "[]" gets an error. */
#define KBLOCK 1024 /* Kill grow. */
#define GOOD 0 /* Good exit status. */
#define VARARGS /* use my varargs.h rather than */
/* the non-portable code supplied */
#define NO_VOID_TYPE /* void not supported yet */
#define SEOL '\l' /* used in search (because \r==\n) */
#define PC PC_ /* compiler can't handle variable called PC */
#define SR SR_ /* or SR */
#define NO_RESIZE /* terminal doesn't change size */
/* typedefs for gnu version */
typedef int RSIZE; /* Type for file/region sizes */
typedef short KEY; /* Type for internal keystrokes */
/*
* Macros used by the buffer name making code.
* Start at the end of the file name, scan to the left
* until BDC1 (or BDC2, if defined) is reached. The buffer
* name starts just to the right of that location, and
* stops at end of string (or at the next BDC3 character,
* if defined). BDC2 and BDC3 are mainly for VMS.
*/
#define BDC1 '/' /* Buffer names. */
/*
* Needed for lots of small mallocs on os9/68k. _memmins should be
* (maximum malloced memory)/16. (defalt _memmins is 4096)
* Note that malloc may now fail if there isn't _memmins bytes
* contiguous free memory. _memins could be reduced and the malloc
* tried again. (Not currently implemented.)
*/
#ifdef MAXMEM
# define SYSINIT {extern int _memmins; _memmins=MAXMEM*64; }
#else
# define SYSINIT {extern int _memmins; _memmins=32768; }
#endif
/* see "caveates" in the osk C manual on _strass */
#define bcopy(from,to,len) _strass(to,from,len)
/* see comments on these in display.c. OSK can't stand the wasted memory
* without making the score array "remote", which generates lousy code.
* Besides, I don't have an extra 100kb of memory for the score array.
*/
#define XCHAR char
#define XSHORT short
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/varargs.h'
then
echo shar: will not over-write existing file "'sys/osk/varargs.h'"
else
cat << \SHAR_EOF > 'sys/osk/varargs.h'
/* varargs.h for os9/68k by Robert A. Larson */
/* version 0 for os9/68k C 2.0 04/20/86 */
/* varargs is a "portable" way to write a routine that takes a variable */
/* number of arguements. This implemination agrees with both the 4.2bsd*/
/* and Sys V documentation of varargs. Note that just because varargs.h*/
/* is used does not mean that it is used properly. */
/* Ignore the "expression with little effect" warnings. (Seems to be a */
/* compiler bug.) */
#define va_alist _va_arg1, _va_arg2, _va_arg3
#define va_dcl unsigned _va_arg1, _va_arg2, _va_arg3;
typedef struct {
unsigned _va_at; /* number of arguments used, 0, 1, or more */
/* (double as first arg counts as 2) */
union {
struct {
unsigned _va_uns1, _va_uns2;
} _va_uuns;
double _va_udouble;
} _va_union;
char *_va_pointer;
} va_list;
#define va_start(pvar) ( (pvar)._va_at = 0, \
(pvar)._va_union._va_uuns._va_uns1 = _va_arg1,\
(pvar)._va_union._va_uuns._va_uns2 = _va_arg2,\
(pvar)._va_pointer = (char *) &_va_arg3 \
)
#define va_arg(pvar, type) ( \
((pvar)._va_at++) ? ( \
((pvar)._va_at == 2) ? ( \
(sizeof(type) == 8) ? ( \
*(((type *)((pvar)._va_pointer))++) \
) : (type)( \
(pvar)._va_union._va_uuns._va_uns2 \
) \
) : ( \
*(((type *)((pvar)._va_pointer))++) \
) \
) : ( \
(sizeof(type) == 8) ? (type)( \
(pvar)._va_at++, \
(pvar)._va_union._va_udouble \
) : (type)( \
(pvar)._va_union._va_uuns._va_uns1 \
) \
) \
)
#define va_end(pvar) /* va_end is simple */
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/fileio.c'
then
echo shar: will not over-write existing file "'sys/osk/fileio.c'"
else
cat << \SHAR_EOF > 'sys/osk/fileio.c'
/*
* Os9/68k fileio.c for MicroGnuEmacs by Robert A. Larson
* system dependent file io routines
*/
#include "def.h"
char *getenv();
static FILE *ffp;
/*
* Open a file for reading.
*/
ffropen(fn)
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).
*/
ffwopen(fn)
char *fn;
{
if ((ffp=fopen(fn, "w")) == NULL) {
ewprintf("Cannot open file for writing");
return (FIOERR);
}
return (FIOSUC);
}
/*
* Close a file.
* Should look at the status.
*/
ffclose()
{
fclose(ffp);
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.
*/
ffputline(buf, nbuf)
register char buf[];
{
register int i;
for (i=0; i<nbuf; ++i)
putc(buf[i]&0xFF, ffp);
putc('\n', ffp);
if (ferror(ffp) != FALSE) {
ewprintf("Write I/O error");
return (FIOERR);
}
return (FIOSUC);
}
/*
* Read a line from a file, and store the bytes
* in the supplied buffer. Stop on end of file or end of
* line. Don't get upset by files that don't have an end of
* line on the last line; this seem to be common on CP/M-86 and
* MS-DOS (the suspected culprit is VAX/VMS kermit, but this
* has not been confirmed. If this is sufficiently researched
* it may be possible to pull this kludge).
*/
ffgetline(buf, nbuf)
register char *buf;
{
register int c;
register int i;
i = 0;
for (;;) {
c = getc(ffp);
if (c==EOF || c=='\n') /* End of line. */
break;
if (i >= nbuf-1) {
ewprintf("File has long line");
return (FIOERR);
}
buf[i++] = c;
}
if (c == EOF) { /* End of file. */
if (ferror(ffp) != FALSE) {
ewprintf("File read error");
return (FIOERR);
}
if (i == 0) /* Don't get upset if */
return (FIOEOF); /* no newline at EOF. */
}
buf[i] = 0;
return (FIOSUC);
}
#ifdef BACKUP
/*
* Rename the file "fname" into a backup copy.
* The backup copy is the same name with ".BAK" appended unless the file
* name is to long. If your file name is 28 characters long ending in ".BAK"
* you lose. The error handling is all in "file.c".
*/
fbackupfile(fname)
char *fname;
{
register char *params;
int status;
register char *fn;
register int fnamel;
register int fnl;
char *rindex();
if((fn = rindex(fname, '/')) == NULL) fn = fname; else fn++;
fnamel = strlen(fname);
fnl = strlen(fn);
if((params = malloc(strlen(fname)+strlen(fn)+6)) == NULL)
return(ABORT);
/* delete the old backup */
strcpy(params, fname);
if(fnl < 25) strcat(params, ".BAK");
else strcpy(params+(fnamel-fnl+24), ".BAK");
unlink(params); /* ignore errors */
/* now do the rename (This is rather akward) */
strcpy(params, fname);
strcat(params, " ");
strcat(params, fn);
if(fnl < 25) strcat(params, ".BAK");
else strcpy(params+fnamel+1+24, ".BAK");
if(os9fork("rename", strlen(params)+1, params, 0, 0, 0, 0)==-1) {
free(params);
return (FALSE);
}
wait(&status);
free(params);
return ((status & 0xffff)==0);
}
#endif
/*
* The string "fn" is a file name.
* Perform any required case adjustments. All sustems
* we deal with so far have case insensitive file systems.
* We zap everything to lower case. The problem we are trying
* to solve is getting 2 buffers holding the same file if
* you visit one of them with the "caps lock" key down.
* On UNIX file names are dual case, so we leave
* everything alone. Os9's dual case storage but non-case sensitivity
* does not seem to be accounted for here. I'm treating it as a
* mono-case system, but it would be better to beleive the file (if found)
* or the user (if not).
*/
adjustcase(fn)
register char *fn;
{
register int c;
while ((c = *fn) != 0) {
if (c>='A' && c<='Z')
*fn = c + 'a' - 'A';
++fn;
}
}
#ifndef MICRO
char *startupfile()
{
static char startname[64];
char *cp;
if ((cp = getenv("HOME")) == NULL) return ".mg";
strncpy(startname, cp, 64 - 4);
strcat(startname, "/.mg");
return startname;
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/spawn.c'
then
echo shar: will not over-write existing file "'sys/osk/spawn.c'"
else
cat << \SHAR_EOF > 'sys/osk/spawn.c'
/*
* Name: MicroEMACS
* OS9/68k Spawn Shell
* Version: 29ral
* Last edit: 04/20/86
* By: Blarson at Usc-Ecl.Arpa
*
*/
#include "def.h"
#include <sgstat.h>
extern struct sgbuf oldtty; /* There really should be a */
extern struct sgbuf newtty; /* nicer way of doing this, so */
spawncli(f, n, k)
/* what are f, n, and k? They */
/* arn't used by ultrix, so I */
/* ignore them too. */
{
register int pid;
register int wpid;
int status;
ttcolor(CTEXT);
ttnowindow();
ttmove(nrow-1, 0);
if (epresf != FALSE) {
tteeol();
epresf = FALSE;
}
ttflush();
if(_ss_opt(0, &oldtty) == -1) {
ewprintf("_ss_opt #1 to terminal failed");
return (FALSE);
}
if((pid=os9fork("shell", 0, "", 0, 0, 0, 0)) == -1) {
ewprintf("Failed to create process");
return (FALSE);
}
while ((wpid=wait(&status))>=0 && wpid!=pid)
;
sgarbf = TRUE; /* Force repaint. */
if(_ss_opt(0, &newtty) == -1) {
ewprintf("_ss_opt #2 to terminal failed");
return (FALSE);
}
return (TRUE);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/ttyio.c'
then
echo shar: will not over-write existing file "'sys/osk/ttyio.c'"
else
cat << \SHAR_EOF > 'sys/osk/ttyio.c'
/*
* sys/osk/ttyio.c by Robert A. Larson
*
* 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 "def.h"
#include <sgstat.h>
#ifdef DPROMPT
# include <varargs.h>
# define S_RDY 2437 /* arbitrary user signal */
#endif
#define NOBUF 512 /* Output buffer size. */
char obuf[NOBUF]; /* Output buffer. */
int nobuf;
struct sgbuf oldtty, newtty;
int nrow; /* Terminal size, rows. */
int ncol; /* Terminal size, columns. */
short ospeed; /* Terminal speed, for termlib.l */
#ifdef DPROMPT
wakeup(signum)
int signum;
{
/* ignore the signal */
}
#endif
/*
* This function gets called once, to set up
* the terminal channel.
*/
ttopen()
{
if(_gs_opt(0, &oldtty) == -1) panic("can't get options");
ospeed = oldtty.sg_baud;
_strass(&newtty, &oldtty, sizeof(newtty)); /* newtty=oldtty; */
if(oldtty.sg_class == 0) { /* scf */
newtty.sg_backsp=
newtty.sg_delete=
newtty.sg_echo =
newtty.sg_alf =
newtty.sg_pause =
newtty.sg_bspch =
newtty.sg_dlnch =
newtty.sg_eorch =
newtty.sg_eofch =
newtty.sg_rlnch =
newtty.sg_dulnch=
newtty.sg_psch =
newtty.sg_kbich =
newtty.sg_kbach = 0;
#ifndef xon_xoff
newtty.sg_xon =
newtty.sg_xoff = 0;
#endif
if(_ss_opt(0, &newtty) == -1) panic("can't set options");
nrow = oldtty.sg_page == 0 ? NROW : oldtty.sg_page;
} else { /* not scf, fake it */
nrow = NROW;
}
ncol = NCOL;
#ifdef DPROMPT
intercept(wakeup); /* ignore signals */
#endif
}
/*
* This function gets called just
* before we go back home to the shell. Put all of
* the terminal parameters back.
*/
ttclose()
{
ttflush();
if(_ss_opt(0, &oldtty) == -1) panic("can't reset options");
}
/*
* Write character to the display.
* Characters are buffered up, to make things
* a little bit more efficient.
*/
ttputc(c)
{
if (nobuf >= NOBUF)
ttflush();
obuf[nobuf++] = c;
}
/*
* Flush output.
*/
ttflush()
{
if (nobuf != 0) {
write(1, obuf, nobuf);
nobuf = 0;
}
}
/*
* Read character from terminal.
* All 8 bits are returned, so that you can use
* a multi-national terminal.
*/
ttgetc()
{
char buf[1];
while (read(0, &buf[0], 1) != 1)
;
return (buf[0] & 0xFF);
}
int typeahead()
{
return _gs_rdy(0) > 0;
}
panic(s) char *s; {
_ss_opt(0, &oldtty); /* ignore errors */
fputs("Panic: ", stdout); /* avoid printf, don't load all that */
puts(s);
exit(1);
}
#ifdef DPROMPT
ttwait() {
if(_gs_rdy(0) > 0) return FALSE; /* already something waiting */
_ss_ssig(0, S_RDY); /* wake me when you have something */
if(sleep(2)!=0) return FALSE; /* sleep interupted */
_ss_rel(0);
return TRUE;
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'sys/osk/makefile'
then
echo shar: will not over-write existing file "'sys/osk/makefile'"
else
cat << \SHAR_EOF > 'sys/osk/makefile'
# Makefile for OSK MicroGnuEMACS by Robert A. Larson
# 07/12/86 MicroGnuEMACS version
# Copy ./sys/osk/makefile to . before making. Check
# OPTS and LIBS.
#
# mg is short for micrognuemacs. Call it what you want.
NAME = mg
# terminal type or termcap
TERM = TERMCAP
# opts is for user definable options, such as:
# BACKUP define for automatic backups
# CVMVAS define for ^V and M-V to work in pages
# MAXMEM memory available to malloc in kbytes. Default 512 (OSK only)
# NLINE maximum line length, default 256. If big, use -m in LFLAGS.
# DPROMPT print delayed prompt strings for ESC, ^X, etc.
# STARTUP startup file handling
# PREFIXREGION functions for prefixing a region
OPTS = -dBACKUP -dMAXMEM=320 -dNLINE=2048 -dDPROMPT -dSTARTUP
# termlib is needed for termcap.
LFLAGS = -l=/dd/lib/termlib.l -m=4
OBJ = basic.r \
buffer.r \
cinfo.r \
display.r \
echo.r \
extend.r \
file.r \
kbd.r \
line.r \
main.r \
match.r \
paragraph.r \
prefix.r \
random.r \
region.r \
search.r \
symbol.r \
version.r \
window.r \
word.r
# these files are listed individually below
SYSOBJ = SYS/OSK/fileio.r \
SYS/OSK/spawn.r \
SYS/OSK/ttyio.r
# ditto
TERMOBJ = TTY/$(TERM)/tty.r \
TTY/$(TERM)/ttykbd.r
#
$(NAME): $(OBJ) $(SYSOBJ) $(TERMOBJ) makefile
cc -i -t=/r0 -f=$(NAME) $(LFLAGS) $(OBJ) $(SYSOBJ) $(TERMOBJ)
$(OBJ): def.h sysdef.h ttydef.h makefile
cc -r -t=/r0 $(OPTS) $*.c
SYS/OSK/fileio.r: SYS/OSK/fileio.c def.h sysdef.h ttydef.h makefile
cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/fileio.c
SYS/OSK/spawn.r: SYS/OSK/spawn.c def.h sysdef.h ttydef.h makefile
cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/spawn.c
SYS/OSK/ttyio.r: SYS/OSK/ttyio.c def.h sysdef.h ttydef.h makefile
cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/ttyio.c
TTY/$(TERM)/tty.r: TTY/$(TERM)/tty.c def.h sysdef.h ttydef.h makefile
cc -r=TTY/$(TERM) -t=/r0 $(OPTS) TTY/$(TERM)/tty.c
TTY/$(TERM)/ttykbd.r: TTY/$(TERM)/ttykbd.c def.h sysdef.h ttydef.h makefile
cc -r=TTY/$(TERM) -t=/r0 $(OPTS) TTY/$(TERM)/ttykbd.c
# The touch commands are needed to update the modified time.
sysdef.h: SYS/OSK/sysdef.h
copy -r -b=16 -w=. SYS/OSK/sysdef.h
touch sysdef.h
ttydef.h: TTY/$(TERM)/ttydef.h makefile
copy -r -b=16 -w=. TTY/$(TERM)/ttydef.h
touch ttydef.h
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
More information about the Mod.sources
mailing list