!/bin/sh # This is a shell archive (produced by GNU sharutils 4.2). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Made on 1998-10-12 10:36 CDT by . # Source directory was `/nfs/rainbow/ars/eric/pups/ug/1/london'. # # Existing files will *not* be overwritten unless `-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 5480 -rw------- em.n # 23036 -rw------- em1.c # 8870 -rw------- em2.c # 3560 -rw------- emdoc # 676 -rw------- emhelp # save_IFS="${IFS}" IFS="${IFS}:" gettext_dir=FAILED locale_dir=FAILED first_param="$1" for dir in $PATH do if test "$gettext_dir" = FAILED && test -f $dir/gettext \ && ($dir/gettext --version >/dev/null 2>&1) then set `$dir/gettext --version 2>&1` if test "$3" = GNU then gettext_dir=$dir fi fi if test "$locale_dir" = FAILED && test -f $dir/shar \ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) then locale_dir=`$dir/shar --print-text-domain-dir` fi done IFS="$save_IFS" if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED then echo=echo else TEXTDOMAINDIR=$locale_dir export TEXTDOMAINDIR TEXTDOMAIN=sharutils export TEXTDOMAIN echo="$gettext_dir/gettext -s" fi touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo $echo 'WARNING: not restoring timestamps. Consider getting and' $echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # if mkdir _sh13396; then $echo 'x -' 'creating lock directory' else $echo 'failed to create lock directory' exit 1 fi # ============= em.n ============== if test -f 'em.n' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'em.n' '(file already exists)' else $echo 'x -' extracting 'em.n' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'em.n' && X.th EM I 4/2/76 X.if t .ds q \(aa X.if n .ds q ' X.sh NAME em \*- editor for mortals X.sh SYNOPSIS em [ X.bd \*- ] [ -p ] [ name ] X.sh DESCRIPTION X.it Em is a QMC variant of the standard Unix text editor - ed. It includes all of ed, so the documentation for ed is fully applicable to em. Em also has a number of new commands and facilities designed to improve its interaction and increase its usefulness to users at fast vdu terminals (such as the ITT's at QMC). X X.it Em differs from ed in that it normally prefixes command lines with a '>'. For those who prefer silence, if the editor is invoked by any name not having 'm' as its second character, no prompts will appear. Other ways of controlling prompts are described below. X Commands to em may be typed in upper- or lower-case letters. X X.it Em has the following extra commands. They are designed principally for use at any Teletype-compatible terminal operating at speeds of 1200 baud or more. X.s3 X.lp +5 5 b X.lp+5 5 b- X.br The 'break' command 'b' turns on automatic line breaks. During subsequent input to the 'open' command (see below), the first space after character position 60 of each line typed will be replaced by a 'newline'. Automatic line breaks are inserted only during input with one of the variants of the 'o' command. They may be suppressed by the command 'b-'. If the current saved filename ends in '.n' or '.r', then 'b' is automatically invoked. X.s3 X.lp +5 5 h X.br The 'help' command displays a summary of the commands available in em. The summary resides in /usr/lib/emhelp, and is designed to fill exactly 18 lines of 80 characters. X.s3 X.lp +5 5 ( \fB. \fR, \fB. \fR)o X.lp +5 5 ( \fB. \fR, \fB. \fR)o/regular expression/ X.lp+5 5 ( \fB. \fR, \fB. \fR)o+ X.lp+5 5 ( \fB. \fR, \fB. \fR)o- X.lp+5 5 ( \fB. \fR, \fB. \fR)o\\ X.br The 'open' command provides an additional level of editing for interactive corrections during input of new lines of text and for alterations to existing lines. The first two forms of the 'o' command operate on an existing line. The line is opened with the cursor positioned at the first occurence of the regular expression if present, otherwise at the start of the line. X The commands 'o+', 'o-' and 'o\\' are equivalent to the 'a', 'i' and 'c' commands respectively, except in their use of the control keys listed below, and in that they are not terminated by a line containing a single '.', but by an ESCAPE or ^D. 'o;' is equivalent to 'o+'. In all variants of the 'o' command it is possible to position the cursor within the line, to delete characters, words or portions of the line, and to insert new text at any point, using control keys as follows: X X.nf X.in +5 X ^A re-display curent line to cursor ^B move cursor back one word ESCAPE or ^D exit from 'o' mode ^E display all of current line ^F delete forwards to end of current line ^H gives summary of control keys ^Q display next character ^R Release margin ^S re-scan from start of current line ^V verify spelling of preceding alphabetic X string (see "spell(I)") ^W display next word ^Z delete preceding word # or ^X delete preceding character @ delete backwards to start of current line RUBOUT exit with current line unchanged X.in -5 X.fi X X Other characters (including RETURN) are inserted as typed. In this mode, diagnostic information is provided on ITT terminals in the form of a backward '?' when control keys are used inappropriately. When the automatic line break facility is operative, a 'bell' is transmitted to the terminal before each newline is inserted. The newline may be inhibited by the '^R' code. X X.s3 X.lp +5 5 ( \fB. \fR, \fB. \fR)x/regular expression/replacement/ X.br The exchange command performs exactly the same functions as an equivalent substitute command 's', except that it enables the user to determine interactively whether or not each replacement is to be performed. Each instance of the specified regular expression is displayed, underscored with '^' characters. The user must type '.' RETURN to perform the replacement or just RETURN to omit it. X X.s3 X.lp +5 5 ( \fB. \fR) " X.br The " command is equivalent to '.+1,.+17p'. X.s3 X.lp +5 5 ( \fB. \fR) % X.br The % command is equivalent to '.-7,.+7p', except that the value of '.' is unchanged by it, and the current line is separated from its neighbours on the screen by a line of '-'s. X.s3 X.lp +5 5 ( \fB. \fR) & X.br This is equivalent to '.-16,.p'. X.s3 X.lp +5 5 ! X.br Two additional facilities are available under the '!' (escape to UNIX) command. '!!'repeats the last command executed in ! mode. X '%' anywhere in a '!' line is replaced by the currently selected filename. X.s3 X.lp +5 5 > X.lp +5 5 < X.br X '>' turns prompting off, '<' turns it on again. X X.in -5 When using 'x' or 's' in em it is possible to obtain a count of the number of replacements performed by postfixing the command with an 'n'. Unsuccessful searches for strings in em are indicated by '??'. X.sh FILES X /usr/emhelp X.sh "SEE ALSO" ed(I), spell(I) X.br A Tutorial Introduction to the ED Text Editor (B. W. Kernighan) X.sh BUGS The underscoring in the 'x' command is sometimes incorrect on ITT terminals, especially when the line contains {,},\\- or \\!. The ",% and & commands should restrict their scope to the dimensions of whatever screen is in use. Tab settings are assumed to be at every eighth character position. SHAR_EOF $shar_touch -am 0218224596 'em.n' && chmod 0600 'em.n' || $echo 'restore of' 'em.n' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'em.n:' 'MD5 check failed' 6d0c85d7e66ef971facf99c427afb330 em.n SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'em.n'`" test 5480 -eq "$shar_count" || $echo 'em.n:' 'original size' '5480,' 'current size' "$shar_count!" fi fi # ============= em1.c ============== if test -f 'em1.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'em1.c' '(file already exists)' else $echo 'x -' extracting 'em1.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'em1.c' && # X /* X * Unix 6 X * Editor X * with QMC mods Feb. 76, by George Coulouris X * mods are: X prompts (suppress with '-p' flag) X ",%,&, to display a screen full of context X 'x' - as 's' but interactive X 'n' flag when appended to 's' or 'x' commands prints number of replacements X X * also mods by jrh 26 Feb 76 X % == current file name in ! commands X !! == repeat the last ! command you executed X -e flag == "elfic" mode :- X no "w", "r\n" commands, auto w before q X X More mods by George March 76: X X 'o' command for text input with local editing via control keys X 'b' to set a threshold for automatic line breaks in 'o' mode. X 'h' displays a screen full of help with editor commands X (the help is in /usr/lib/emhelp) bugs: X should not use printf in substitute() X (for space reasons). X */ X /* this file contains all of the code except that used in the 'o' command. X that is in a second segment called em2.c */ X /* screen dimensions */ #define LINES 18 #define LENGTH 80 #define SPLIT '-' #define PROMPT '>' #define CONFIRM '.' #define SCORE "^" #define FORM 014 #define SIGHUP 1 #define SIGINTR 2 #define SIGQUIT 3 #define FNSIZE 64 #define LBSIZE 512 #define ESIZE 128 #define GBSIZE 256 #define NBRA 5 #define EOF -1 X #define CBRA 1 #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define CKET 12 X #define STAR 01 X #define error goto errlab #define READ 0 #define WRITE 1 X X #define UNIXBUFL 100 X extern int margin; /* used to set threshold in 'open' */ X int elfic 0; /* true if "elfic" (-e) flag */ int firstime 1; /* ugh - used to frigg initial "read" */ int peekc; int lastc; char unixbuffer [UNIXBUFL]; char savedfile[FNSIZE]; char file[FNSIZE]; char linebuf[LBSIZE]; char rhsbuf[LBSIZE/2]; char expbuf[ESIZE+4]; int circfl; int *zero; int *dot; int *dol; int *endcore; int *fendcore; int *addr1; int *addr2; char genbuf[LBSIZE]; int count[2]; char *nextip; char *linebp; int ninbuf; int io; int pflag; int onhup; int onquit; int vflag 0; int xflag 0; /*used in 'xchange' command */ int listf; int col; char *globp; int tfile -1; int tline; char *tfname; char *loc1; char *loc2; char *locs; char ibuff[512]; int iblock -1; char obuff[512]; int oblock -1; int ichanged; int nleft; int errfunc(); int *errlab errfunc; char TMPERR[] "TMP"; int names[26]; char *braslist[NBRA]; char *braelist[NBRA]; X main(argc, argv) char **argv; { X register char *p1, *p2; X extern int onintr(); X X onquit = signal(SIGQUIT, 1); X onhup = signal(SIGHUP, 1); X if(*(*argv+1) == 'm') vflag = 1; X argv++; X if (argc > 1 && **argv=='-') { X p1 = *argv+1; X while (*p1) { X switch (*p1++) { X case 'q': X signal(SIGQUIT, 0); X break; X case 'e': X elfic = 1; X break; X case 'p': X vflag = 0; X break; X case 's': X vflag = -1; X break; X } X } X if (!(*argv)[1]) X vflag = -1; X argv++; X argc--; X } X if (argc>1) { X p1 = *argv; X p2 = savedfile; X while (*p2++ = *p1++); X breaks(p1-3); X globp = "r"; X } X fendcore = sbrk(0); X if (vflag>0) puts("Editor"); X init(); X if ((signal(SIGINTR, 1) & 01) == 0) X signal(SIGINTR, onintr); X setexit(); X commands(vflag); X unlink(tfname); } X commands(prompt) { X int getfile(), gettty(); X register *a1, c; X register char *p; X char *p1,*p2; X int fd, r, n; X X for (;;) { X if (pflag) { X pflag = 0; X addr1 = addr2 = dot; X goto print; X } X if (prompt>0 && globp == 0) putch(PROMPT); X addr1 = 0; X addr2 = 0; X xflag = 0; X do { X addr1 = addr2; X if ((a1 = address())==0) { X c = getchar(); X break; X } X addr2 = a1; X if ((c=getchar()) == ';') { X c = ','; X dot = a1; X } X } while (c==','); X if (addr1==0) X addr1 = addr2; X if (c>= 'A' && c<= 'Z') X c =| 040; X switch(c) { X X case 'a': X setdot(); X newline(); X append(gettty, addr2); X continue; X X case 'b': X if((c=peekc=getchar())== '+' || c =='-') X peekc = 0; X else if(c != '\n') error; X margin = c == '-' ? LBSIZE - 40 : LENGTH - 20; X newline(); X continue; X X case 'c': X setdot(); X newline(); X delete(); X append(gettty, addr1-1); X continue; X X case 'd': X setdot(); X newline(); X delete(); X continue; X X case 'e': X if (elfic) X error; X setnoaddr(); X if ((peekc = getchar()) != ' ') X error; X savedfile[0] = 0; X init(); X addr2 = zero; X goto caseread; X X case 'f': X if (elfic) X error; X setnoaddr(); X if ((c = getchar()) != '\n') { X peekc = c; X savedfile[0] = 0; X filename(); X } X puts(savedfile); X continue; X X case 'g': X global(1); X continue; X X case 'h': X newline(); X if((fd = open("/usr/lib/emhelp",0))<0) { X puts("/usr/lib/emhelp not found"); X continue; X } X while (n = read( fd, linebuf, 512)) X write(1, linebuf, n); X close( fd); X continue; X X case 'i': X setdot(); X nonzero(); X newline(); X append(gettty, addr2-1); X continue; X X case 'k': X if ((c = getchar()) < 'a' || c > 'z') X error; X newline(); X setdot(); X nonzero(); X names[c-'a'] = *addr2 | 01; X continue; X X case 'm': X move(0); X continue; X X case '\n': X if (addr2==0) X addr2 = dot+1; X addr1 = addr2; X goto print; X X case 'l': X listf++; X case 'p': X newline(); X print: X setdot(); X nonzero(); X a1 = addr1; X do X puts(getline(*a1++)); X while (a1 <= addr2); X dot = addr2; X listf = 0; X continue; X X case 'o': X setdot(); X op(globp); X continue; X X case 'q': X setnoaddr(); X newline(); X if (elfic) { X firstime = 1; X goto writeout; X } X quitit: X unlink(tfname); X exit(); X X case 'r': X caseread: X filename(); X if ((io = open(file, 0)) < 0) { X lastc = '\n'; X error; X } X setall(); X ninbuf = 0; X append(getfile, addr2); X exfile(); X continue; X X case 'x': X xflag = 1; X case 's': X setdot(); X nonzero(); X substitute(globp); X xflag = 0; X continue; X X case 't': X move(1); X continue; X X case 'v': X global(0); X continue; X X case 'w': X if (elfic) X error; X writeout: X setall(); X nonzero(); X if (elfic) { X p1 = savedfile; X if (*p1==0) X error; X p2 = file; X while (*p2++ = *p1++); X } X else X filename (); X if ((io = creat(file, 0666)) < 0) X error; X putfile(); X exfile(); X if (elfic) X goto quitit; X continue; X X case '"': X setdot(); X newline(); X nonzero(); X dot = addr1; X if (dot == dol) error; X addr1 = dot+1; X addr2 = dot +LINES-1; X addr2 = addr2>dol? dol: addr2; X outlines: X putchar(FORM); X a1 = addr1-1; X while (++a1 <= addr2) puts(getline(*a1)); X dot = addr2; X continue; X X case '&': X setdot(); X newline(); X nonzero(); X dot = addr1; X addr1 = dot - (LINES-2); X addr2 = dot; X addr1 = addr1>zero? addr1: zero+1; X goto outlines; X X case '%': X newline(); X setdot(); X nonzero(); X dot = addr1; X addr1 = dot - (LINES/2 - 2); X addr2 = dot + (LINES/2 - 2); X addr1 = addr1>zero? addr1 : zero+1; X addr2 = addr2>dol? dol : addr2; X a1 = addr1 - 1; X putchar(FORM); X while(++a1 <= addr2) { X if (a1 == dot) screensplit(); X puts(getline(*a1)); X if (a1 == dot) screensplit(); X } X continue; X X case '>': X vflag = vflag>0? 0: vflag; X reset(); X X case '<': X vflag = 1; X reset(); X X case '=': X setall(); X newline(); X count[1] = (addr2-zero)&077777; X putd(); X putchar('\n'); X continue; X X case '!': X unix(); X continue; X X case EOF: X if(prompt == -2 || ttyn(0) == 'x') return; X continue; X X } X error; X } } X address() { X register *a1, minus, c; X int n, relerr; X X minus = 0; X a1 = 0; X for (;;) { X c = getchar(); X if ('0'<=c && c<='9') { X n = 0; X do { X n =* 10; X n =+ c - '0'; X } while ((c = getchar())>='0' && c<='9'); X peekc = c; X if (a1==0) X a1 = zero; X if (minus<0) X n = -n; X a1 =+ n; X minus = 0; X continue; X } X relerr = 0; X if (a1 || minus) X relerr++; X switch(c) { X case ' ': X case '\t': X continue; X X case '+': X minus++; X if (a1==0) X a1 = dot; X continue; X X case '-': X case '^': X minus--; X if (a1==0) X a1 = dot; X continue; X X case '?': X case '/': X compile(c); X a1 = dot; X for (;;) { X if (c=='/') { X a1++; X if (a1 > dol) X a1 = zero; X } else { X a1--; X if (a1 < zero) X a1 = dol; X } X if (execute(0, a1)) X break; X if (a1==dot) X {putchar('?'); error;} X /* two '?'s for failed search */ X } X break; X X case '$': X a1 = dol; X break; X X case '.': X a1 = dot; X break; X X case '\'': X if ((c = getchar()) < 'a' || c > 'z') X error; X for (a1=zero; a1<=dol; a1++) X if (names[c-'a'] == (*a1|01)) X break; X break; X X default: X peekc = c; X if (a1==0) X return(0); X a1 =+ minus; X if (a1dol) X error; X return(a1); X } X if (relerr) X error; X } } X setdot() { X if (addr2 == 0) X addr1 = addr2 = dot; X if (addr1 > addr2) X error; } X setall() { X if (addr2==0) { X addr1 = zero+1; X addr2 = dol; X if (dol==zero) X addr1 = zero; X } X setdot(); } X setnoaddr() { X if (addr2) X error; } X nonzero() { X if (addr1<=zero || addr2>dol) X error; } X newline() { X register c; X X if ((c = getchar()) == '\n') X return; X c = c >= 'A' && c <= 'Z' ? c + 32 : c; X if (c=='p' || c=='l') { X pflag++; X if (c=='l') X listf++; X if (getchar() == '\n') X return; X } X error; } X filename() { X register char *p1, *p2; X register c; X X count[1] = 0; X c = getchar(); X if (c=='\n' || c==EOF) { X if (elfic && !firstime) X error; X else X firstime = 0; X p1 = savedfile; X if (*p1==0) X error; X p2 = file; X while (*p2++ = *p1++); X return; X } X if (c!=' ') X error; X while ((c = getchar()) == ' '); X if (c=='\n') X error; X p1 = file; X do { X *p1++ = c; X } while ((c = getchar()) != '\n'); X *p1++ = 0; X if (savedfile[0]==0) { X p1 = savedfile; X p2 = file; X while (*p1++ = *p2++); X breaks(p1 - 3); X } } X breaks(p) char *p; X { X if(*p++ == '.') X if(*p == 'r' || *p == 'n') margin = LENGTH -20; } X exfile() { X close(io); X io = -1; X if (vflag>=0) { X putd(); X putchar('\n'); X } } X onintr() { X signal(SIGINTR, onintr); X putchar('\n'); X lastc = '\n'; X error; } X errfunc() { X register c; X X listf = 0; X puts("?"); X count[0] = 0; X seek(0, 0, 2); X pflag = 0; X if (globp) X lastc = '\n'; X globp = 0; X peekc = lastc; X while ((c = getchar()) != '\n' && c != EOF); X if (io > 0) { X close(io); X io = -1; X } X reset(); } X getchar() { X if (lastc=peekc) { X peekc = 0; X return(lastc); X } X if (globp) { X if ((lastc = *globp++) != 0) X return(lastc); X globp = 0; X return(EOF); X } X if (read(0, &lastc, 1) <= 0) X return(lastc = EOF); X lastc =& 0177; X return(lastc); } X gettty() { X register c, gf; X register char *p; X X p = linebuf; X gf = globp; X while ((c = getchar()) != '\n') { X if (c==EOF) { X if (gf) X peekc = c; X return(c); X } X if ((c =& 0177) == 0) X continue; X *p++ = c; X if (p >= &linebuf[LBSIZE-2]) X error; X } X *p++ = 0; X if (linebuf[0]=='.' && linebuf[1]==0) X return(EOF); X return(0); } X getfile() { X register c; X register char *lp, *fp; X X lp = linebuf; X fp = nextip; X do { X if (--ninbuf < 0) { X if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) X return(EOF); X fp = genbuf; X } X if (lp >= &linebuf[LBSIZE]) X error; X if ((*lp++ = c = *fp++ & 0177) == 0) { X lp--; X continue; X } X if (++count[1] == 0) X ++count[0]; X } while (c != '\n'); X *--lp = 0; X nextip = fp; X return(0); } X putfile() { X int *a1; X register char *fp, *lp; X register nib; X X nib = 512; X fp = genbuf; X a1 = addr1; X do { X lp = getline(*a1++); X for (;;) { X if (--nib < 0) { X write(io, genbuf, fp-genbuf); X nib = 511; X fp = genbuf; X } X if (++count[1] == 0) X ++count[0]; X if ((*fp++ = *lp++) == 0) { X fp[-1] = '\n'; X break; X } X } X } while (a1 <= addr2); X write(io, genbuf, fp-genbuf); } X append(f, a) int (*f)(); { X register *a1, *a2, *rdot; X int nline, tl; X struct { int integer; }; X X nline = 0; X dot = a; X while ((*f)() == 0) { X if (dol >= endcore) { X if (sbrk(1024) == -1) X error; X endcore.integer =+ 1024; X } X tl = putline(); X nline++; X a1 = ++dol; X a2 = a1+1; X rdot = ++dot; X while (a1 > rdot) X *--a2 = *--a1; X *rdot = tl; X } X return(nline); } X unix() { X register savint, pid, rpid; X int retcode; X char c,*lp,*fp; X pid = 0; X if ((c=getchar ()) != '!') { X lp = unixbuffer; X do { X if (c != '%') X *lp++ = c; X else { X pid = 1; X fp = savedfile; X while ((*lp++ = *fp++)); X lp--; X } X c = getchar(); X } while (c != '\n'); X *lp = '\0'; X } X else { pid = 1; X while (getchar () != '\n');} X if(pid) { X putchar('!'); X puts(unixbuffer); X } X setnoaddr(); X if ((pid = fork()) == 0) { X signal(SIGHUP, onhup); X signal(SIGQUIT, onquit); X execl ("/bin/sh", "sh", "-c", unixbuffer, 0); X exit(); X } X savint = signal(SIGINTR, 1); X while ((rpid = wait(&retcode)) != pid && rpid != -1); X signal(SIGINTR, savint); X puts("!"); } X delete() { X register *a1, *a2, *a3; X X nonzero(); X a1 = addr1; X a2 = addr2+1; X a3 = dol; X dol =- a2 - a1; X do X *a1++ = *a2++; X while (a2 <= a3); X a1 = addr1; X if (a1 > dol) X a1 = dol; X dot = a1; } X getline(tl) { X register char *bp, *lp; X register nl; X X lp = linebuf; X bp = getblock(tl, READ); X nl = nleft; X tl =& ~0377; X while (*lp++ = *bp++) X if (--nl == 0) { X bp = getblock(tl=+0400, READ); X nl = nleft; X } X return(linebuf); } X putline() { X register char *bp, *lp; X register nl; X int tl; X X lp = linebuf; X tl = tline; X bp = getblock(tl, WRITE); X nl = nleft; X tl =& ~0377; X while (*bp = *lp++) { X if (*bp++ == '\n') { X *--bp = 0; X linebp = lp; X break; X } X if (--nl == 0) { X bp = getblock(tl=+0400, WRITE); X nl = nleft; X } X } X nl = tline; X tline =+ (((lp-linebuf)+03)>>1)&077776; X return(nl); } X getblock(atl, iof) { X extern read(), write(); X register bno, off; X X bno = (atl>>8)&0377; X off = (atl<<1)&0774; X if (bno >= 255) { X puts(TMPERR); X error; X } X nleft = 512 - off; X if (bno==iblock) { X ichanged =| iof; X return(ibuff+off); X } X if (bno==oblock) X return(obuff+off); X if (iof==READ) { X if (ichanged) X blkio(iblock, ibuff, write); X ichanged = 0; X iblock = bno; X blkio(bno, ibuff, read); X return(ibuff+off); X } X if (oblock>=0) X blkio(oblock, obuff, write); X oblock = bno; X return(obuff+off); } X blkio(b, buf, iofcn) int (*iofcn)(); { X seek(tfile, b, 3); X if ((*iofcn)(tfile, buf, 512) != 512) { X puts(TMPERR); X error; X } } X init() { X register char *p; X register pid; X X close(tfile); X tline = 0; X iblock = -1; X oblock = -1; X tfname = "/tmp/exxxxx"; X ichanged = 0; X pid = getpid(); X for (p = &tfname[11]; p > &tfname[6];) { X *--p = (pid&07) + '0'; X pid =>> 3; X } X close(creat(tfname, 0600)); X tfile = open(tfname, 2); X brk(fendcore); X dot = zero = dol = fendcore; X endcore = fendcore - 2; } X global(k) { X register char *gp; X register c; X register int *a1; X char globuf[GBSIZE]; X X if (globp) X error; X setall(); X nonzero(); X if ((c=getchar())=='\n') X error; X compile(c); X gp = globuf; X while ((c = getchar()) != '\n') { X if (c==EOF) X error; X if (c=='\\') { X c = getchar(); X if (c!='\n') X *gp++ = '\\'; X } X *gp++ = c; X if (gp >= &globuf[GBSIZE-2]) X error; X } X *gp++ = '\n'; X *gp++ = 0; X for (a1=zero; a1<=dol; a1++) { X *a1 =& ~01; X if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k) X *a1 =| 01; X } X for (a1=zero; a1<=dol; a1++) { X if (*a1 & 01) { X *a1 =& ~01; X dot = a1; X globp = globuf; X commands(-2); X a1 = zero; X } X } } X substitute(inglob) { X register gsubf, *a1, nl; X int nflag, nn, getsub(); X X gsubf = compsub(); X nflag = gsubf > 1 ? 1 : 0; X nn = 0; X gsubf =& 01; X gsubf =| xflag; X for (a1 = addr1; a1 <= addr2; a1++) { X if (execute(0, a1)==0) X continue; X inglob =| 01; X if (confirmed()) { dosub(); nn++; } X else donothing(); X if (gsubf) { X while (*loc2) { X if (execute(1)==0) X break; X if(confirmed()) { dosub(); nn++; } X else donothing(); X } X } X *a1 = putline(); X nl = append(getsub, a1); X a1 =+ nl; X addr2 =+ nl; X } X if (inglob==0) X {putchar('?'); error; } X /* two queries distinguish failed match */ X /* should use putd() and count here */ X if (nflag) printf( " %d \n", nn); } X donothing() { X char t1,t2; X t1 = rhsbuf[0]; X t2 = rhsbuf[1]; X rhsbuf[0] = '&'; X rhsbuf[1] = 0; X dosub(); X rhsbuf[0] = t1; X rhsbuf[1] = t2; } X confirmed() { int ch; X if(xflag) { X puts(linebuf); X underline(linebuf, loc1, loc2, SCORE); X ch = getchar(); X if ( ch != '\n') { while (getchar() != '\n'); X if ( ch != CONFIRM ) puts("? '.' to confirm"); X } X return (ch == CONFIRM ? 1: 0); X } X return 1; } X X underline (line, l1, l2, score) char *line, *l1, *l2, *score; { X char *ch, *ll; int i; X register char *p; X X p = line; X ch = " "; X ll = l1; X i = 2; X while (i--) { X while (*p && p < ll) { X write (1, (*p == '\t' ? p : ch),1); X p++; X } X ch = score; X ll = l2; X } } X screensplit() { X register a; X X a = LENGTH; X while(a--) putchar(SPLIT); X putchar('\n'); } X compsub() { X register seof, c; X register char *p; X int gsubf; X X gsubf = 0; X if ((seof = getchar()) == '\n') X error; X compile(seof); X p = rhsbuf; X for (;;) { X c = getchar(); X if (c=='\\') X c = getchar() | 0200; X if (c=='\n') X error; X if (c==seof) X break; X *p++ = c; X if (p >= &rhsbuf[LBSIZE/2]) X error; X } X *p++ = 0; X if(((peekc = getchar())| 040) == 'g') { X peekc = 0; X gsubf =| 1; X } X if (((peekc = getchar())| 040) == 'n') { X peekc = 0; X gsubf =| 2; X } X newline(); X return(gsubf); } X getsub() { X register char *p1, *p2; X X p1 = linebuf; X if ((p2 = linebp) == 0) X return(EOF); X while (*p1++ = *p2++); X linebp = 0; X return(0); } X dosub() { X register char *lp, *sp, *rp; X int c; X X lp = linebuf; X sp = genbuf; X rp = rhsbuf; X while (lp < loc1) X *sp++ = *lp++; X while (c = *rp++) { X if (c=='&') { X sp = place(sp, loc1, loc2); X continue; X } else if (c<0 && (c =& 0177) >='1' && c < NBRA+'1') { X sp = place(sp, braslist[c-'1'], braelist[c-'1']); X continue; X } X *sp++ = c&0177; X if (sp >= &genbuf[LBSIZE]) X error; X } X lp = loc2; X loc2 = sp + linebuf - genbuf; X while (*sp++ = *lp++) X if (sp >= &genbuf[LBSIZE]) X error; X lp = linebuf; X sp = genbuf; X while (*lp++ = *sp++); } X place(asp, al1, al2) { X register char *sp, *l1, *l2; X X sp = asp; X l1 = al1; X l2 = al2; X while (l1 < l2) { X *sp++ = *l1++; X if (sp >= &genbuf[LBSIZE]) X error; X } X return(sp); } X move(cflag) { X register int *adt, *ad1, *ad2; X int getcopy(); X X setdot(); X nonzero(); X if ((adt = address())==0) X error; X newline(); X ad1 = addr1; X ad2 = addr2; X if (cflag) { X ad1 = dol; X append(getcopy, ad1++); X ad2 = dol; X } X ad2++; X if (adt= ad2) { X dot = adt++; X reverse(ad1, ad2); X reverse(ad2, adt); X reverse(ad1, adt); X } else X error; } X reverse(aa1, aa2) { X register int *a1, *a2, t; X X a1 = aa1; X a2 = aa2; X for (;;) { X t = *--a2; X if (a2 <= a1) X return; X *a2 = *a1; X *a1++ = t; X } } X getcopy() { X if (addr1 > addr2) X return(EOF); X getline(*addr1++); X return(0); } X compile(aeof) { X register eof, c; X register char *ep; X char *lastep; X char bracket[NBRA], *bracketp; X int nbra; X int cclcnt; X X ep = expbuf; X eof = aeof; X bracketp = bracket; X nbra = 0; X if ((c = getchar()) == eof) { X if (*ep==0) X error; X return; X } X circfl = 0; X if (c=='^') { X c = getchar(); X circfl++; X } X if (c=='*') X goto cerror; X peekc = c; X for (;;) { X if (ep >= &expbuf[ESIZE]) X goto cerror; X c = getchar(); X if (c==eof) { X *ep++ = CEOF; X return; X } X if (c!='*') X lastep = ep; X switch (c) { X X case '\\': X if ((c = getchar())=='(') { X if (nbra >= NBRA) X goto cerror; X *bracketp++ = nbra; X *ep++ = CBRA; X *ep++ = nbra++; X continue; X } X if (c == ')') { X if (bracketp <= bracket) X goto cerror; X *ep++ = CKET; X *ep++ = *--bracketp; X continue; X } X *ep++ = CCHR; X if (c=='\n') X goto cerror; X *ep++ = c; X continue; X X case '.': X *ep++ = CDOT; X continue; X X case '\n': X goto cerror; X X case '*': X if (*lastep==CBRA || *lastep==CKET) X error; X *lastep =| STAR; X continue; X X case '$': X if ((peekc=getchar()) != eof) X goto defchar; X *ep++ = CDOL; X continue; X X case '[': X *ep++ = CCL; X *ep++ = 0; X cclcnt = 1; X if ((c=getchar()) == '^') { X c = getchar(); X ep[-2] = NCCL; X } X do { X if (c=='\n') X goto cerror; X *ep++ = c; X cclcnt++; X if (ep >= &expbuf[ESIZE]) X goto cerror; X } while ((c = getchar()) != ']'); X lastep[1] = cclcnt; X continue; X X defchar: X default: X *ep++ = CCHR; X *ep++ = c; X } X } X cerror: X expbuf[0] = 0; X error; } X execute(gf, addr) int *addr; { X register char *p1, *p2, c; X X if (gf) { X if (circfl) X return(0); X p1 = linebuf; X p2 = genbuf; X while (*p1++ = *p2++); X locs = p1 = loc2; X } else { X if (addr==zero) X return(0); X p1 = getline(*addr); X locs = 0; X } X p2 = expbuf; X if (circfl) { X loc1 = p1; X return(advance(p1, p2)); X } X /* fast check for first character */ X if (*p2==CCHR) { X c = p2[1]; X do { X if (*p1!=c) X continue; X if (advance(p1, p2)) { X loc1 = p1; X return(1); X } X } while (*p1++); X return(0); X } X /* regular algorithm */ X do { X if (advance(p1, p2)) { X loc1 = p1; X return(1); X } X } while (*p1++); X return(0); } X advance(alp, aep) { X register char *lp, *ep, *curlp; X char *nextep; X X lp = alp; X ep = aep; X for (;;) switch (*ep++) { X X case CCHR: X if (*ep++ == *lp++) X continue; X return(0); X X case CDOT: X if (*lp++) X continue; X return(0); X X case CDOL: X if (*lp==0) X continue; X return(0); X X case CEOF: X loc2 = lp; X return(1); X X case CCL: X if (cclass(ep, *lp++, 1)) { X ep =+ *ep; X continue; X } X return(0); X X case NCCL: X if (cclass(ep, *lp++, 0)) { X ep =+ *ep; X continue; X } X return(0); X X case CBRA: X braslist[*ep++] = lp; X continue; X X case CKET: X braelist[*ep++] = lp; X continue; X X case CDOT|STAR: X curlp = lp; X while (*lp++); X goto star; X X case CCHR|STAR: X curlp = lp; X while (*lp++ == *ep); X ep++; X goto star; X X case CCL|STAR: X case NCCL|STAR: X curlp = lp; X while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); X ep =+ *ep; X goto star; X X star: X do { X lp--; X if (lp==locs) X break; X if (advance(lp, ep)) X return(1); X } while (lp > curlp); X return(0); X X default: X error; X } } X cclass(aset, ac, af) { X register char *set, c; X register n; X X set = aset; X if ((c = ac) == 0) X return(0); X n = *set++; X while (--n) X if (*set++ == c) X return(af); X return(!af); } X putd() { X register r; X extern ldivr; X X count[1] = ldiv(count[0], count[1], 10); X count[0] = 0; X r = ldivr; X if (count[1]) X putd(); X putchar(r + '0'); } X puts(as) char *as; { X register char *sp; X X sp = as; X col = 0; X while (*sp) X putchar(*sp++); X putchar('\n'); } X char line[70]; char *linp line; X putchar(ac) { X register char *lp; X register c; X X lp = linp; X c = ac; X if (listf) { X col++; X if (col >= 72) { X col = 0; X *lp++ = '\\'; X *lp++ = '\n'; X } X if (c=='\t') { X c = '>'; X goto esc; X } X if (c=='\b') { X c = '<'; X esc: X *lp++ = '-'; X *lp++ = '\b'; X *lp++ = c; X goto out; X } X if (c<' ' && c!= '\n') { X *lp++ = '\\'; X *lp++ = (c>>3)+'0'; X *lp++ = (c&07)+'0'; X col =+ 2; X goto out; X } X } X *lp++ = c; out: X if(c == '\n' || lp >= &line[64]) { X linp = line; X write(1, line, lp-line); X return; X } X linp = lp; } X /* X * Get process ID routine if system call is unavailable. getpid() { X register f; X int b[1]; X X f = open("/dev/kmem", 0); X if(f < 0) X return(-1); X seek(f, 0140074, 0); X read(f, b, 2); X seek(f, b[0]+8, 0); X read(f, b, 2); X close(f); X return(b[0]); } X */ SHAR_EOF $shar_touch -am 0218224596 'em1.c' && chmod 0600 'em1.c' || $echo 'restore of' 'em1.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'em1.c:' 'MD5 check failed' 71a0843ed5d56b34c769dc3ad44f97f3 em1.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'em1.c'`" test 23036 -eq "$shar_count" || $echo 'em1.c:' 'original size' '23036,' 'current size' "$shar_count!" fi fi # ============= em2.c ============== if test -f 'em2.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'em2.c' '(file already exists)' else $echo 'x -' extracting 'em2.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'em2.c' && # /* This is the second and final segment of the QMC Unix Editor - em */ #define EOF -1 #define LBSIZE 512 #define SIGHUP 1 #define SIGINTR 2 #define SIGQUIT 3 #define UNIXBUFL 100 #define error goto errlab #define TABSET 7 /* this should be determined dynamically */ X #define RAW 040 #define ECHO 010 #define OPEN '/' #define BELL 07 #define ESCAPE 033 #define SPACE 040 #define BACKSL 0134 #define RUBOUT 0177 #define CTRLA 01 #define CTRLB 02 #define CTRLC 03 #define CTRLD 04 #define CTRLE 05 #define CTRLF 06 #define CTRLH 010 #define CTRLI 011 #define CTRLQ 021 #define CTRLR 022 #define CTRLS 023 #define CTRLV 026 #define CTRLW 027 #define CTRLX 030 #define CTRLZ 032 X #define ITT 0100000 X extern char peekc, *linebp, *loc2, linebuf[LBSIZE], genbuf[LBSIZE], X unixbuffer[UNIXBUFL]; extern int onquit,onhup; extern int *zero, *addr1, *addr2; extern int *errlab; int margin LBSIZE - 40; int oflag; char *threshold, *savethresh; char *lnp,*gnp,*brp; int savetty, tty[3]; X X op(inglob) { register *a1; X register char *lp, *sp; X char seof, ch; X int t, nl, getopen(), getnil(); X X threshold = genbuf + margin; X savethresh = 0; X X switch (ch = peekc = getchar()) { X case BACKSL: X t = 1; X delete(); X addr2 = addr1; X break; X X case ';': X case '+': X t = 0; X break; X X case '-': X t =1; X break; X X default: X goto normal; X X } X X peekc = 0; X if(addr1 != addr2) error; X oflag = 0; X append(getnil, addr2 - t); X addr1 = addr2 =- (t-1); X setdot(); X nonzero(); X X normal: X if(addr1 == zero) error; X if ((seof = getchar()) == '\n') { loc2 = linebuf-1; X seof = 0;} X else compile(seof); X setraw(); /* terminal into raw mode*/ X X for ( a1 = addr1; a1 <= addr2; a1++) { X if (seof) {if (execute(0,a1) == 0) continue;} X else getline(*a1); X puts("\\\r"); X lp = linebuf; X sp = genbuf; X inglob =| 01; X while (lp < loc2){ putch(*lp); *sp++ = *lp++; } X lnp = lp; X gnp = sp; X X X oflag = gopen(); /* open the current line */ X *a1 = putline(); /* write revised line */ X nl = append( getopen,a1); X a1 =+ nl; X addr2 =+ nl; X } X setcook(); /* terminal in cook mode */ X putchar('\n'); X if (inglob == 0) { putchar('?'); error;} } X getnil() { X if(oflag == EOF) return EOF; X linebuf[0] = '\0'; X oflag = EOF; X return 0; } X setraw() { X if(gtty(0,tty) == -1) error; X savetty = tty[2]; X tty[2] =| RAW; X stty(0, tty); } X setcook() { X tty[2] = savetty; X stty(0, tty); } X inword(c) char c; { if(c -'0' < 0 ) return 0; X if(c - '9' <= 0) return 1; X c =& 0137; X if(c -'A' < 0) return 0; X if(c - 'Z' <= 0) return 1; X return 0; } X rescan() { register char *lp, *sp; X X if(savethresh) { threshold = savethresh; savethresh = 0; } X lp = linebuf; X sp = genbuf; X while(*lp++ = *sp++) if(lp>linebuf+LBSIZE) { X *(--lp) = 0; X return 0; X } } X X gopen() X /*leaves revised line in linebuf, X returns 0 if more to follow, EOF if last line */ { register char *lp, *sp, *rp; X char ch, *br, *pr; X int tabs; X int retcode, savint, pid, rpid; X X lp = lnp; X sp = gnp; X tabs = 0; X for (rp = genbuf; rp < sp; rp++) if (*rp == CTRLI) tabs =+ TABSET; X X for(;;){ X switch (ch = getchar()) { X X case CTRLD: X case ESCAPE: /* close the line (see case '\n' also) */ X close: X putb(lp); X while(*sp++ = *lp++); X rescan(); X return(EOF); X X case CTRLA: /* verify line */ X verify: puts("\\\r"); X *sp = '\0'; X putb(genbuf); X continue; X X case CTRLB: /* back a word */ X if(sp == genbuf) goto backquery; X X while((*(--lp) = *(--sp)) == SPACE) X if(sp < genbuf) goto out; X if(inword(*sp)) { X while(inword((*(--lp) = *(--sp)))) X if(sp < genbuf) goto out; X if(*sp == SPACE) X while((*(--lp) = *(--sp)) == SPACE) X if(sp < genbuf) goto out; X } X else while(sp >= genbuf && !inword(*sp)) X if((*lp-- = *sp--) == CTRLI) tabs =- TABSET; X out: sp++; X lp++; X goto verify; X X case CTRLC: X case CTRLQ: /* forward one char */ X if(*lp == 0) goto backquery; X putch(*lp); X forward: X if(*lp == SPACE && sp + tabs > threshold) { X putch('\r'); X ch = '\n'; putch(ch); X lp++; X *sp++ = ch; X br = sp; X break; X } X if(*lp == CTRLI) tabs =+ TABSET; X *sp++ = *lp++; /* one character */ X if(sp + tabs == threshold) putch(BELL); X continue; X X X case CTRLF: X /* delete forward */ X while(*lp++); X lp--; X goto verify; X X case CTRLE: X putb(lp); X goto verify; X X case CTRLH: help(); goto verify; X X case CTRLR: /* margin release */ X if(threshold-genbuf= genbuf) X *(--pr) = *rp--; X if(*pr == 0) goto backquery; X puts("!!"); X setcook(); X if((pid = fork()) == 0) X {signal(SIGHUP, onhup); X signal(SIGQUIT, onquit); X execl("/bin/spell", "spell", pr, 0); X puts("sorry, can't spell today"); X exit(); X } X savint = signal(SIGINTR,1); X while((rpid = wait(&retcode)) != pid X && rpid != -1); X signal(SIGINTR, savint); X setraw(); X puts("!!"); X goto verify; X X X case CTRLW: /* forward one word */ X if(*lp == '\0') goto backquery; X while(*lp == SPACE) X putch(*sp++ = *lp++); X if(inword(*lp)) { X while(inword(*lp)) { X putch(*sp++ = *lp++); X if(sp+tabs==threshold) putch(BELL); X } X if(*lp == SPACE) { X if(sp+tabs>threshold) { X ch = '\n'; X lp++; X *sp++ = ch; X br = sp; X putch('\r'); X putch('\n'); X } X if(*lp == SPACE) X while(*(lp+1) == SPACE) X putch(*sp++ = *lp++); X } X } X else while(*lp && !inword(*lp)) { X if(*lp == CTRLI) tabs =+ TABSET; X putch(*sp++ = *lp++); X if(sp+tabs==threshold) putch(BELL); X } X break; X X X case CTRLZ: /* delete a word */ X if(sp == genbuf) goto backquery; X X while(*(--sp) == SPACE) if(sp < genbuf) goto zout; X if(inword(*sp)) { X while(inword(*(--sp))) X if(sp < genbuf) goto zout; X if(*sp == SPACE) X while(*(--sp) == SPACE) X if(sp < genbuf) goto zout; X } X else while(sp >= genbuf && !inword(*sp)) X if(*sp-- == CTRLI) tabs =- TABSET; X zout: sp++; X goto verify; X X case '@': /*delete displayed line */ X /* delete backward */ X sp = genbuf; X tabs = 0; X goto verify; X X case RUBOUT: X puts("\\\r"); X setcook(); X error; X X case CTRLX: X putch('#'); X case '#': X if( sp == genbuf) goto backquery; X if(*(--sp) == CTRLI) tabs =- TABSET; X if( ch == CTRLX) goto verify; X continue; X X case '\n': X case '\r': /* split line, actually handled at X end of switch block */ X ch = '\n'; X *sp++ = ch; X br = sp; X break; X X case BACKSL: /* special symbols */ X switch (ch = peekc = getchar()) { X case '(': ch = '{'; peekc = 0; break; X case ')': ch = '}'; peekc = 0; break; X case '!': ch = '|'; peekc = 0; break; X case '^': ch = '~'; peekc = 0; break; X case '\'': ch = '`'; peekc = 0; break; X case BACKSL: X case '#': X case '@': peekc = 0; break; X X default: if(ch >= 'a' && ch <= 'z') { X peekc = 0; ch =- 040;} X else { X *(--lp) = BACKSL; X goto forward; X } X } X X default: *(--lp) = ch; X goto forward; X } X X if (ch == '\n') { /* split line */ X if(*(br-1) != '\n') puts("!!"); /*debugging only */ X lnp = sp; X while(*sp++ = *lp++); /*move the rest over */ X brp = linebuf +(br - genbuf); X lnp = linebuf + (lnp - br); X rescan(); X *(brp-1) ='\0'; X return(0); X } X else continue; X backquery: putch(CTRLZ); X } /* end of forloop block */ } /* end of gopen */ X X X getopen() /* calls gopen, deals with multiple lines etc. */ { register char *lp, *sp; X if (oflag == EOF) return EOF; X /* otherwise, multiple lines */ X X lp = linebuf; X sp = brp; X while(*lp++ = *sp++); /*move it down */ X sp = genbuf; X lp = linebuf; X while (lp < lnp) *sp++ = *lp++; X gnp = sp; X /* should check whether empty line returned */ X oflag = gopen(); X return 0; } X putch(ch) char ch; { write(1, &ch, 1); } X putb(ptr) char *ptr; /*display string */ X { register char *p; X X p = ptr; X if(*p == '\0') return; X while(*(++p)); X write(1,ptr,p-ptr); } X help() { puts("\n"); X puts(" ^A display Again ^Q next character"); X puts(" ^B backup word ^R Release margin"); X puts(" ESCAPE ^S re-scan from Start"); X puts(" or ^D close line and exit ^V verify spelling"); X puts(" ^E display to End ^W next Word"); X puts(" ^F delete line Forward ^Z delete word"); X puts(" ^H Help # or ^X delete character"); X puts(" RUBOUT exit unchanged @ delete line backward\n"); X puts(" Other characters (including RETURN) inserted as typed"); } X SHAR_EOF $shar_touch -am 0218224596 'em2.c' && chmod 0600 'em2.c' || $echo 'restore of' 'em2.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'em2.c:' 'MD5 check failed' 8a9e8dbe61a35f6708884acefc9dd94e em2.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'em2.c'`" test 8870 -eq "$shar_count" || $echo 'em2.c:' 'original size' '8870,' 'current size' "$shar_count!" fi fi # ============= emdoc ============== if test -f 'emdoc' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'emdoc' '(file already exists)' else $echo 'x -' extracting 'emdoc' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'emdoc' && X How to Generate 'em' X X X gfc 17 X X Thu Apr 29 1976 X X X How to Generate the QMC Unix Editor 'em' X --------------------------------------- X X X Author: George Coulouris X X Computer Systems Laboratory X Queen Mary College Mile End Road London E1 4NS (01-980 4811 x751) X X X X Summary X X This is the system documentation for 'em'. It should be used X in conjunction with the manual section supplied with 'em' X (EM(I), 3/22/76). A tutorial introduction to 'em' is in X preparation. X X X X X Files X X There are five relevant files: X X emdoc - the text of this document X X em.n - the text of the manual section X on 'em' in 'nroff' format X X emhelp - a file containing a summary of X editor commands, used in X the 'help' command X X em1.c - the first of the two C source seg- X ments X X em2.c - the second and last segment X X X Generation X X To compile 'em': X X cc -n -s em1.c em2.c X X leaves a suitable object program in 'a.out'. Just move it to X '/bin/em': X X mv a.out /bin/em X X 1 X How to Generate 'em' X X X to produce a command 'em'. If you also want a version with all X of the 'em' features except prompting, you can make a link to X the same object program with any name not having 'm' as its X second character. We use the 'ed' name: X X ln /bin/em /bin/ed X X If you want the editor to be permanently held in the disc X swapping area (and therefore entered more quickly in response X to the 'em' command) change the mode: X X chmod 1755 /bin/em X X Frills X X If you want the 'h' command to provide a screen full of help, X put the text for the help in /usr/lib/emhelp. You can use the X file supplied, or make your own. X X There is a rather pleasing feature available when you type X '^V' in the 'o' command that enables the spelling of a word to X be given from a lexicon file once the first few letters of the X word have been typed. This is implemented through a command X in our Unix system: X X spell arg X X that takes an argument containing an alphabetic string and X outputs all of the words in a lexicon file that begin with X that string. Our version of the spell program is a crude (but X fast) affair using 26 files. There must be a better way, so if X you want the '^V' facility we suggest you implement your own X spell command. 'em' will use it if it is there, otherwise it X will display a suitable message. X X X ---------------/---------------- X X X X X X X X X X X X X X X X X X X X 2 SHAR_EOF $shar_touch -am 0218224596 'emdoc' && chmod 0600 'emdoc' || $echo 'restore of' 'emdoc' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'emdoc:' 'MD5 check failed' 7f5f5d332db74c87835569e501b949b3 emdoc SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'emdoc'`" test 3560 -eq "$shar_count" || $echo 'emdoc:' 'original size' '3560,' 'current size' "$shar_count!" fi fi # ============= emhelp ============== if test -f 'emhelp' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'emhelp' '(file already exists)' else $echo 'x -' extracting 'emhelp' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'emhelp' && X b line breaks on r read file b- line breaks off s substitute /old/new/ d delete line(s) t copy line(s) e edit a new file v globally if not f set file name w write on file g globally if x substitute interactively h display this summary ('.' to confirm) k mark line / delimit search string m move line(s) ? delimit backward l list line(s) search string o open line(s) for mods ! unix command X (^H for help in 'o') = line number o\ replace line(s) > prompts off o- insert new lines % display context o+ append new lines & .-16,.p p print line(s) " .+1,.+17p q quit editor +,- .+1p,.-1p SHAR_EOF $shar_touch -am 0218224596 'emhelp' && chmod 0600 'emhelp' || $echo 'restore of' 'emhelp' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'emhelp:' 'MD5 check failed' 6caaa0cd1d6a484d717d6674d38d1545 emhelp SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'emhelp'`" test 676 -eq "$shar_count" || $echo 'emhelp:' 'original size' '676,' 'current size' "$shar_count!" fi fi rm -fr _sh13396 exit 0