v08i002: Georgia Tech 'se' Screen Editor
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Tue Jan 27 07:16:45 AEST 1987
Submitted by: emoryu1!arnold (Arnold D. Robbins)
Mod.sources: Volume 8, Issue 2
Archive-name: se/Part02
Here is the second release of the Georgia Tech Screen Editor, 'se'.
There were enough changes that a whole new posting is warranted.
Major Changes:
All Georgia Tech specific stuff removed.
It understands window size changes on 4.3BSD and ATT Unix PC/3B1
Support for the shared library on the ATT Unix PC/3B1
Considerable source code reorganization in certain files.
Enjoy,
Arnold Robbins
#! /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:
# edit.c
# extern.h
# m4munge
# main.c
# makefile
# misc.c
export PATH; PATH=/bin:$PATH
echo shar: extracting "'edit.c'" '(26346 characters)'
if test -f 'edit.c'
then
echo shar: will not over-write existing file "'edit.c'"
else
cat << \SHAR_EOF > 'edit.c'
#ifndef lint
static char RCSid[] = "$Header: edit.c,v 1.3 86/07/11 15:11:34 osadr Exp $";
#endif
/*
* $Log: edit.c,v $
* Revision 1.3 86/07/11 15:11:34 osadr
* Removed Georgia Tech specific code.
*
* Revision 1.2 86/05/27 17:44:56 osadr
* Removed flexnames dependancy; PREVLINE[2] --> PREVLN[2].
* Improved the sysname() routine, particularly to use the nodename
* member of the utsname structure under System V.
*
* Revision 1.1 86/05/06 13:37:16 osadr
* Initial revision
*
*
*/
/*
** edit.c
**
** editor main routine, plus other routines used a lot.
*/
#include "se.h"
#include "extern.h"
static char Savknm = DEFAULTNAME; /* saved mark name for < and > */
/* edit --- main routine for screen editor */
edit (argc, argv)
int argc;
char *argv[];
{
int cursav, status, len, cursor;
int ckglob (), docmd (), doglob (), doread ();
int getlst (), nextln (), prevln ();
char lin[MAXLINE], term;
watch (); /* display time of day */
#ifdef LOG_USAGE
log (); /* log who used the program */
#endif
serc (); /* execute commands in ./.serc or $HOME/.serc */
status = OK;
while (status == OK && Argno < argc)
{
strcpy (lin, argv[Argno]);
loadstr (lin, Argno, POOPCOL, Ncols);
if (lin[0] == '-')
{
len = strlen (lin) + 1;
lin[len - 1] = '\n';
lin[len] = EOS;
len = 0;
status = doopt (lin, &len);
}
else
{
dfltsopt (lin);
status = doread (Lastln, lin, NO);
}
Argno++;
}
if (status == ERR)
{
if (Errcode == EHANGUP)
hangup ();
printverboseerrormessage ();
}
else
Curln = min (1, Lastln);
Buffer_changed = NO;
First_affected = 1; /* maintained by updscreen & commands */
updscreen ();
if (status != ERR) /* leave offending file name or option */
lin[0] = EOS;
cursor = 0;
/* main command loop */
do {
intrpt (); /* discard pending breaks (interrupts) */
if (Lost_lines > GARB_THRESHOLD
&& (Lastln + Limcnt) / Lost_lines <= GARB_FACTOR)
garbage_collect ();
mswait (); /* check for pending messages */
Cmdrow = Botrow + 1; /* reset the command line location */
prompt ("cmd>");
getcmd (lin, 0, &cursor, &term);
remark (""); /* clear out any error messages */
while (term == CURSOR_UP || term == CURSOR_DOWN
|| term == CURSOR_SAME)
{
switch (term) {
case CURSOR_UP:
if (Curln > 1)
Curln--;
else
Curln = Lastln;
break;
case CURSOR_DOWN:
if (Curln < Lastln)
Curln++;
else
Curln = min (1, Lastln);
break;
}
adjust_window (Curln, Curln);
updscreen ();
getcmd (lin, 0, &cursor, &term);
}
prompt (""); /* remove prompt */
cursav = Curln; /* remember it in case of an error */
Errcode = EEGARB; /* default error code for garbage at end */
len = 0;
if (getlst (lin, &len, &status) == OK)
{
if (ckglob (lin, &len, &status) == OK)
doglob (lin, &len, &cursav, &status);
else if (status != ERR)
docmd (lin, len, NO, &status);
}
if (status == ERR)
{
if (Errcode == EHANGUP)
hangup ();
printverboseerrormessage ();
Curln = min (cursav, Lastln);
}
else if (term != FUNNY)
{
cursor = 0;
lin[0] = EOS;
}
adjust_window (Curln, Curln);
updscreen ();
} while (status != EOF);
clrscreen ();
clrbuf ();
tflush ();
return;
}
/* getlst --- collect line numbers (if any) at lin[*i], increment i */
int getlst (lin, i, status)
char lin[];
int *i, *status;
{
int num;
int getone ();
Line2 = 0;
for (Nlines = 0; getone (lin, i, &num, status) == OK; )
{
Line1 = Line2;
Line2 = num;
Nlines++;
if (lin[*i] != ',' && lin[*i] != ';')
break;
if (lin[*i] == ';')
Curln = num;
(*i)++;
}
if (Nlines > 2)
Nlines = 2;
if (Nlines <= 1)
Line1 = Line2;
if (Line1 > Line2)
{
*status = ERR;
Errcode = EBACKWARD;
}
if (*status != ERR)
*status = OK;
return (*status);
}
/* getnum --- convert one term to line number */
int getnum (lin, i, pnum, status)
char lin[];
register int *i, *pnum, *status;
{
int j, ret;
int ctoi (), optpat (), ptscan (), knscan (), getkn ();
int k;
ret = OK;
SKIPBL (lin, *i);
if (lin[*i] >= Rel_a && lin[*i] <= Rel_z && Absnos == NO)
*pnum = Topln - Toprow + lin[*i] - Rel_a;
else if (lin[*i] == CURLINE)
*pnum = Curln;
else if (lin[*i] == PREVLN || lin[*i] == PREVLN2)
*pnum = Curln - 1;
else if (lin[*i] == LASTLINE)
*pnum = Lastln;
else if (lin[*i] == SCAN || lin[*i] == BACKSCAN)
{
int missing_delim = YES;
/* see if trailing delim supplied, since command can follow pattern */
for (k = *i + 1; lin[k] != EOS; k++)
if (lin[k] == ESCAPE)
k++; /* skip esc, loop will skip escaped char */
else if (lin[k] == lin[*i])
{
missing_delim = NO;
break;
}
/* else
continue */
if (missing_delim == YES)
{
for (; lin[k] != EOS; k++)
;
k--; /* k now at newline */
/* supply trailing delim */
lin[k] = lin[*i];
lin[++k] = '\n';
lin[++k] = EOS;
Peekc = SKIP_RIGHT;
}
if (optpat (lin, i) == ERR)
ret = ERR;
else if (lin[*i] == SCAN)
ret = ptscan (FORWARD, pnum);
else
ret = ptscan (BACKWARD, pnum);
}
else if (lin[*i] == SEARCH || lin[*i] == BACKSEARCH)
{
j = *i;
(*i)++;
if (getkn (lin, i, &Savknm, Savknm) == ERR)
ret = ERR;
else if (lin[j] == SEARCH)
ret = knscan (FORWARD, pnum);
else
ret = knscan (BACKWARD, pnum);
(*i)--;
}
else if (isdigit (lin[*i]))
{
*pnum = ctoi (lin, i);
(*i)--;
}
else if (lin[*i] == TOPLINE)
*pnum = Topln;
else
ret = EOF;
if (ret == OK)
(*i)++;
*status = ret;
return (ret);
}
/* getone --- evaluate one line number expression */
int getone (lin, i, num, status)
char lin[];
register int *i, *num, *status;
{
int pnum, ret;
int getnum ();
char porm; /* "plus or minus" (sic) */
ret = EOF; /* assume we won't find anything for now */
*num = 0;
if (getnum (lin, i, num, status) == OK) /* first term */
{
ret = OK; /* to indicate we've seen something */
do { /* + or - terms */
porm = EOS;
SKIPBL (lin, *i);
if (lin[*i] == '-' || lin[*i] == '+')
{
porm = lin[*i];
(*i)++;
}
if (getnum (lin, i, &pnum, status) == OK)
if (porm == '-')
*num -= pnum;
else
*num += pnum;
if (*status == EOF && porm != EOS) /* trailing + or - */
*status = ERR;
} while (*status == OK);
}
if (*num < 0 || *num > Lastln) /* make sure number is in range */
{
*status = ERR;
Errcode = EORANGE;
}
if (*status == ERR)
ret = ERR;
else
*status = ret;
return (ret);
}
#ifndef OLD_SCRATCH
#ifndef OLD_GLOB
static int special_casing = NO;
#endif
#endif
/* ckglob --- if global prefix, mark lines to be affected */
int ckglob (lin, i, status)
char lin[];
int *i, *status;
{
register int line, tmp;
int usepat, usemark;
int defalt (), match (), optpat (), getkn ();
register LINEDESC *k;
LINEDESC *gettxt (), *getind ();
*status = OK;
usepat = EOF;
usemark = EOF;
#ifndef OLD_SCRATCH
#ifndef OLD_GLOB
if ( /* g/^/m0 or g/$/m0 -- special case the pathological */
/* cases in order to save time */
(lin[*i] == GLOBAL || lin[*i] == UCGLOBAL)
&& (lin[*i + 1] == lin[*i + 3])
&& (lin[*i + 2] == '^' || lin[*i + 2] == '$')
&& (lin[*i + 4] == MOVECOM || lin[*i + 4] == UCMOVECOM)
&& (lin[*i + 5] == '0' && lin[*i + 6] == '\n') )
{
special_casing = YES;
remark ("GLOB");
return (OK);
}
#endif
#endif
if (lin[*i] == GMARK || lin[*i] == XMARK) /* global markname prefix? */
{
if (lin[*i] == GMARK) /* tag lines with the specified markname */
usemark = YES;
else /* tag lines without the specified markname */
usemark = NO;
(*i)++;
*status = getkn (lin, i, &Savknm, Savknm);
}
if (*status == OK) /* check for a pattern prefix too */
{
if (lin[*i] == GLOBAL || lin[*i] == UCGLOBAL)
usepat = YES;
if (lin[*i] == EXCLUDE || lin[*i] == UCEXCLUDE)
usepat = NO;
if (usepat != EOF)
{
(*i)++;
if (optpat (lin, i) == ERR)
*status = ERR;
else
(*i)++;
}
}
if (*status == OK && usepat == EOF && usemark == EOF)
*status = EOF;
else if (*status == OK)
defalt (1, Lastln);
if (*status == OK) /* no errors so far, safe to proceed */
{
remark ("GLOB");
k = Line0; /* unmark all lines preceeding range */
for (line = 0; line < Line1; line++)
{
k -> Globmark = NO;
k = NEXTLINE(k);
}
for (; line <= Line2; line++) /* mark lines in range */
{
if (intrpt ())
{
*status = ERR;
return (*status);
}
tmp = NO;
if (usemark == EOF
|| usemark == YES && k -> Markname == Savknm
|| usemark == NO && k -> Markname != Savknm)
{
if (usepat == EOF) /* no global pattern to look for */
tmp = YES;
else /* there is also a pattern to look for */
{
gtxt (k);
if (match (Txt, Pat) == usepat)
tmp = YES;
}
}
k -> Globmark = tmp;
k = NEXTLINE(k);
}
#ifdef OLD_SCRATCH
/* mark remaining lines */
for (; k != Line0; k = k -> Nextline)
k -> Globmark = NO;
#else
/* mark remaining lines */
for (; line <= Lastln; line++)
{
k -> Globmark = NO;
k = NEXTLINE (k);
}
#endif
remark ("");
}
return (*status);
}
/* doglob --- do command at lin[i] on all marked lines */
int doglob (lin, i, cursav, status)
char lin[];
int *i, *cursav, *status;
{
register int istart, line;
int docmd (), getlst (), nextln ();
register LINEDESC *k;
LINEDESC *getind ();
#ifndef OLD_SCRATCH
#ifndef OLD_GLOB
if (special_casing)
{
/*
remark ("Warp 7, Captain!");
*/
/* not on the screen too long anyway */
reverse (1, Lastln);
Curln = Lastln;
special_casing = NO;
Buffer_changed = YES;
First_affected = min (1, First_affected);
remark ("");
adjust_window (Curln, Curln);
updscreen ();
return (OK);
}
#endif
#endif
*status = OK;
istart = *i;
k = Line0;
line = 0;
do {
line++;
k = NEXTLINE(k);
if (k -> Globmark == YES) /* line is marked */
{
k -> Globmark = NO; /* unmark the line */
Curln = line;
*cursav = Curln; /* remember where we are */
*i = istart;
if (getlst (lin, i, status) == OK)
docmd (lin, *i, YES, status);
line = 0; /* lines may have been moved */
k = Line0;
}
if (intrpt ())
*status = ERR;
} while (line <= Lastln && *status == OK);
return (*status);
}
/* ckchar --- look for ch or altch on lin at i, set flag if found */
int ckchar (ch, altch, lin, i, flag, status)
char ch, altch, lin[];
int *i, *flag, *status;
{
if (lin[*i] == ch || lin[*i] == altch)
{
(*i)++;
*flag = YES;
}
else
*flag = NO;
*status = OK;
return (OK);
}
/* ckp --- check for "p" after command */
int ckp (lin, i, pflag, status)
char lin[];
int i, *pflag, *status;
{
if (lin[i] == PRINT || lin[i] == UCPRINT)
{
i++;
*pflag = YES;
}
else
*pflag = NO;
if (lin[i] == '\n')
*status = OK;
else
*status = ERR;
return (*status);
}
/* ckupd --- make sure it is ok to destroy the buffer */
int ckupd (lin, i, cmd, status)
char lin[], cmd;
int *i, *status;
{
int flag;
int ckchar ();
*status = ckchar (ANYWAY, ANYWAY, lin, i, &flag, status);
if (flag == NO && Buffer_changed == YES && Probation != cmd)
{
*status = ERR;
Errcode = ESTUPID;
Probation = cmd; /* if same command is repeated, */
} /* we'll keep quiet */
return (*status);
}
/* defalt --- set defaulted line numbers */
defalt (def1, def2)
int def1, def2;
{
if (Nlines == 0) /* no line numbers supplied, use defaults */
{
Line1 = def1;
Line2 = def2;
}
return;
}
/* getfn --- get file name from lin[i]... */
int getfn (lin, i, file)
char lin[], file[];
int i;
{
int j, k, ret;
ret = ERR;
if (lin[i + 1] == ' ')
{
j = i + 2; /* get new file name */
SKIPBL (lin, j);
for (k = 0; lin[j] != NEWLINE; k++, j++)
file[k] = lin[j];
file[k] = EOS;
if (k > 0)
ret = OK;
}
else if (lin[i + 1] == '\n' && Savfil[0] != EOS)
{
strcpy (file, Savfil); /* or old name */
ret = OK;
}
else
if (lin[i + 1] == '\n')
Errcode = ENOFN;
else
Errcode = EFILEN;
if (ret == OK && Savfil[1] == EOS)
{
strcpy (Savfil, file); /* save if no old one */
mesg (Savfil, FILE_MSG);
}
return (ret);
}
/* getkn --- get mark name from lin[i], increment i */
int getkn (lin, i, kname, dfltnm)
char lin[], *kname, dfltnm;
int *i;
{
if (lin[*i] == '\n' || lin[*i] == EOS)
{
*kname = dfltnm;
return (EOF);
}
*kname = lin[*i];
(*i)++;
return (OK);
}
/* getrange --- get 'from' range for tlit command */
int getrange (array, k, set, size, allbut)
char array[], set[];
int *k, size, *allbut;
{
int i, j;
int addset ();
Errcode = EBADLIST; /* preset error code */
i = *k + 1;
if (array[i] == NOTINCCL) /* check for negated character class */
{
*allbut = YES;
i++;
}
else
*allbut = NO;
j = 0;
filset (array[*k], array, &i, set, &j, size);
if (array[i] != array[*k])
{
set[0] = EOS;
return (ERR);
}
if (set[0] == EOS)
{
Errcode = ENOLIST;
return (ERR);
}
if (j > 0 && addset (EOS, set, &j, size) == NO)
{
set[0] = EOS;
return (ERR);
}
*k = i;
Errcode = EEGARB;
return (OK);
}
/* getrhs --- get substitution string for 's' command */
int getrhs (lin, i, sub, gflag)
char lin[], sub[];
int *i, *gflag;
{
static char Subs[MAXPAT] = ""; /* saved replacement pattern */
int j, maksub ();
/* saved replacement pattern char */
Errcode = EBADSUB;
if (lin[*i] == EOS) /* missing the middle delimeter */
return (ERR);
if (lin[*i + 1] == '%' && (lin[*i + 2] == lin[*i]
|| lin[*i + 2] == '\n'))
{
/*
* s//%/ --- should mean do the same thing as I did last time, even
* s//&/ --- if I deleted something. So we comment out these lines.
*
if (Subs[0] == EOS)
{
Errcode = ENOSUB;
return (ERR);
}
*/
strcpy (sub, Subs);
*i += 2;
if (lin[*i] == '\n')
{
/* fix it up for pattern matching routines */
lin[*i] = lin[*i - 2];
lin[*i + 1] = '\n';
lin[*i + 2] = EOS;
Peekc = SKIP_RIGHT;
}
}
else /* not using saved substitution pattern */
{
if (lin[*i + 1] == '\n')
{
/* missing the trailing delimiter */
/* pattern was empty */
lin[*i + 1] = lin[*i]; /* supply missing delimiter */
lin[*i + 2] = '\n';
lin[*i + 3] = EOS;
Peekc = SKIP_RIGHT;
/* return (ERR); /* this is the original action */
}
else
{
/* stuff in pattern, check end of line */
for (j = *i; lin[j] != EOS; j++)
;
j -= 2; /* j now points to char before '\n' */
if (lin[j] == 'p' || lin[j] == 'P')
{
--j;
if (lin[j] == GLOBAL || lin[j] == UCGLOBAL)
{
if (j >= *i + 1 && lin[j-1] == lin[*i]
&& (lin[j-2] != ESCAPE
|| lin[j-3] == ESCAPE))
; /* leave alone */
else
{
/* \<delim>gp\n is pattern */
/* supply trailing delim */
j += 2; /* j at \n */
lin[j] = lin[*i];
lin[++j] = '\n';
lin[++j] = EOS;
Peekc = SKIP_RIGHT;
}
}
else if (j >= *i + 1 && lin[j] == lin[*i] &&
(lin[j-1] != ESCAPE
|| lin[j-2] == ESCAPE))
; /* leave alone */
else
{
/* \<delim>p\n is pattern */
/* supply trailing delim */
j += 2;
lin[j] = lin[*i];
lin[++j] = '\n';
lin[++j] = EOS;
Peekc = SKIP_RIGHT;
}
}
else if (lin[j] == GLOBAL || lin[j] == UCGLOBAL)
{
--j;
if (j >= *i + 1 && lin[j] == lin[*i] &&
(lin[j-1] != ESCAPE
|| lin[j-2] == ESCAPE))
; /* leave alone */
else
{
/* \<delim>g\n is pattern */
/* supply trailing delim */
j += 2; /* j at \n */
lin[j] = lin[*i];
lin[++j] = '\n';
lin[++j] = EOS;
Peekc = SKIP_RIGHT;
}
}
else if ((lin[j] != lin[*i]) ||
(lin[j] == lin[*i] &&
lin[j-1] == ESCAPE && lin[j-2] != ESCAPE))
{
/* simply missing trailing delimeter */
/* supply it */
j++; /* j at \n */
lin[j] = lin[*i];
lin[++j] = '\n';
lin[++j] = EOS;
Peekc = SKIP_RIGHT;
}
/* else
unescaped delim is there,
leave well enough alone */
}
if ((*i = maksub (lin, *i + 1, lin[*i], sub)) == ERR)
return (ERR);
strcpy (Subs, sub); /* save pattern for later */
}
if (lin[*i + 1] == GLOBAL || lin[*i + 1] == UCGLOBAL)
{
(*i)++;
*gflag = YES;
}
else
*gflag = NO;
Errcode = EEGARB; /* the default */
return (OK);
}
/* getstr --- get string from lin at i, copy to dst, bump i */
/*
** NOTE: this routine only called for doing the join command.
** therefore, don't do anything else with it.
*/
int getstr (lin, i, dst, maxdst)
char lin[], dst[];
int *i, maxdst;
{
char delim;
char esc ();
int j, k, d;
j = *i;
Errcode = EBADSTR;
delim = lin[j];
if (delim == '\n')
{
lin[j] = '/';
lin[++j] = ' '; /* join with a single blank */
lin[++j] = '/';
lin[++j] = '\n';
lin[++j] = EOS;
j = *i;
delim = lin[j];
Peekc = SKIP_RIGHT;
/* now fall thru */
/* return (ERR); /* old way */
}
else if ((delim == 'p' || delim == 'P') && lin[j + 1] == '\n') /* jp */
{
lin[j] = '/';
lin[++j] = ' '; /* join with a single blank */
lin[++j] = '/';
lin[++j] = delim; /* 'p' or 'P' */
lin[++j] = '\n';
lin[++j] = EOS;
j = *i;
delim = lin[j];
Peekc = SKIP_RIGHT;
/* now fall thru */
}
if (lin[j + 1] == '\n') /* command was 'j/' */
{
dst[0] = EOS;
Errcode = ENOERR;
return (OK);
/* return (ERR); /* old way */
}
/*
* otherwise, stuff there in the string, try to allow for
* a missing final delimiter.
*/
for (k = j + 1; lin[k] != '\n'; k++)
; /* find end */
k--; /* now points to char before newline */
if (lin[k] == 'p' || lin[k] == 'P')
{
k--;
if (lin[k] == delim &&
(lin[k-1] != ESCAPE || lin[k-2] == ESCAPE))
; /* it's fine, leave it alone */
else
{
/* ESCAPE delim p NEWLINE is the join string */
/* supply trailing delimiter. */
k += 2;
lin[k] = delim;
lin[++k] = '\n';
lin[++k] = EOS;
Peekc = SKIP_RIGHT;
}
}
else if (lin[k] != delim || (lin[k-1] == ESCAPE && lin[k-2] != ESCAPE))
{
/* no delim and no p, or last char is escaped delim */
k++;
lin[k] = delim;
lin[++k] = '\n';
lin[++k] = EOS;
Peekc = SKIP_RIGHT;
}
/* else
delim is there
leave well enough alone */
/* code to actually do the join */
for (k = j + 1; lin[k] != delim; k++) /* find end */
{
if (lin[k] == '\n' || lin[k] == EOS)
if (delim == ' ')
break;
else
return (ERR);
esc (lin, &k);
}
if (k - j > maxdst)
return (ERR);
for (d = 0, j++; j < k; d++, j++)
dst[d] = esc (lin, &j);
dst[d] = EOS;
*i = j;
Errcode = EEGARB; /* the default */
return (OK);
}
/* getwrd --- get next word from line at i; increment i */
int getwrd (line, i, word, size)
char line[], word[];
int *i, size;
{
int j;
SKIPBL (line, *i);
j = 0;
while (line[*i] != ' ' && line[*i] != '\n' && line[*i] != EOS)
{
if (j < size - 1)
{
word[j] = line[*i];
j++;
}
(*i)++;
}
word[j] = EOS;
return (j);
}
/* knscan --- scan for a line with a given mark name */
int knscan (way, num)
int way, *num;
{
int nextln ();
LINEDESC *k;
LINEDESC *getind ();
*num = Curln;
k = getind (*num);
do {
bump (num, &k, way);
if (k -> Markname == Savknm)
return (OK);
} while (*num != Curln && ! intrpt ());
if (Errcode = EEGARB)
Errcode = EKNOTFND;
return (ERR);
}
/* makset --- make set from array[k] in set */
int makset (array, k, set, size)
char array[], set[];
int *k, size;
{
static char Tset[MAXPAT] = ""; /* saved translit dest range */
int i, j;
int l;
int addset ();
Errcode = EBADLIST;
/*
* try to allow missing delimiter for translit command.
*/
if (array[*k] == EOS)
return (ERR);
if (array[*k + 1] == '%' && (array[*k + 2] == array[*k]
|| array[*k + 2] == '\n'))
{
strcpy (set, Tset);
*k += 2;
if (array[*k] == '\n')
{
/* fix it up for rest of the routines */
array[*k] = array[*k - 2];
array[*k+ 1] = '\n';
array[*k+ 2] = EOS;
}
Peekc = SKIP_RIGHT;
}
else
{
for (l = *k; array[l] != EOS; l++)
;
l -= 2; /* l now points to char before '\n' */
if (l == *k) /* "y/.../\n" */
{
array[*k + 1] = array[*k]; /* add delimiter */
array[*k + 2] = '\n';
array[*k + 3] = EOS;
Peekc = SKIP_RIGHT;
}
else if (array[l] == 'p' || array[l] == 'P')
{
--l;
if (l >= *k + 1 && array[l] == array[*k] &&
(array[l-1] != ESCAPE || array[l-2] == ESCAPE))
; /* leave alone */
else
{
/* \<delim>p\n is set */
/* supply trailing delim */
l += 2;
array[l] = array[*k];
array[++l] = '\n';
array[++l] = EOS;
Peekc = SKIP_RIGHT;
}
}
else if (array[l] != array[*k] /* no delim, and no p */
|| (array[l-1] == ESCAPE /* or last char is escaped delim */
&& array[l-2] != ESCAPE))
{
/* simply missing trailing delimeter */
/* supply it */
l++; /* l now at \n */
array[l] = array[*k];
array[++l] = '\n';
array[++l] = EOS;
Peekc = SKIP_RIGHT;
}
/* else
delim is there,
leave well enough alone */
j = 0;
i = *k + 1;
filset (array[*k], array, &i, set, &j, size);
if (array[i] != array[*k])
return (ERR);
if (addset (EOS, set, &j, size) == NO)
return (ERR);
strcpy (Tset, set); /* save for later */
*k = i;
}
Errcode = EEGARB;
return (OK);
}
/* optpat --- make pattern specified at lin[i] */
int optpat (lin, i)
char lin[];
int *i;
{
int makpat ();
if (lin[*i] == EOS)
*i = ERR;
else if (lin[*i + 1] == EOS)
*i = ERR;
else if (lin[*i + 1] == lin[*i]) /* repeated delimiter */
(*i)++; /* leave existing pattern alone */
else
*i = makpat (lin, *i + 1, lin[*i], Pat);
if (Pat [0] == EOS)
{
Errcode = ENOPAT;
return (ERR);
}
if (*i == ERR)
{
Pat[0] = EOS;
Errcode = EBADPAT;
return (ERR);
}
return (OK);
}
/* ptscan --- scan for next occurrence of pattern */
int ptscan (way, num)
int way, *num;
{
LINEDESC *getind ();
LINEDESC *k;
int match ();
*num = Curln;
k = getind (*num);
do {
bump (num, &k, way);
gtxt (k);
if (match (Txt, Pat) == YES)
return (OK);
} while (*num != Curln && ! intrpt ());
if (Errcode == EEGARB)
Errcode = EPNOTFND;
return (ERR);
}
/* settab --- set tab stops */
int settab (str)
char str[];
{
int i, j, n, maxstop, last, inc, ret;
int ctoi ();
for (i = 0; i < MAXLINE; i++) /* clear all tab stops */
Tabstops[i] = NO;
ret = OK;
maxstop = 0;
last = 1;
i = 0;
SKIPBL (str, i);
while (str[i] != EOS && str[i] != '\n')
{
if (str[i] == '+') /* increment */
{
i++;
inc = YES;
}
else
inc = NO;
n = ctoi (str, &i);
if (n <= 0 || n >= MAXLINE)
{
ret = ERR;
Errcode = ENONSENSE;
break;
}
if (str[i] != ' ' && str[i] != '+' &&
str[i] != '\n' && str[i] != EOS)
{
ret = ERR;
Errcode = EBADTABS;
break;
}
if (inc == YES)
{
for (j = last + n; j < MAXLINE; j += n)
{
Tabstops[j - 1] = YES;
maxstop = max (j, maxstop);
}
}
else
{
Tabstops[n - 1] = YES;
last = n;
maxstop = max (n, maxstop);
}
SKIPBL (str, i);
} /* while ... */
if (ret == ERR)
maxstop = 0;
if (maxstop == 0) /* no tab stops specified, use defaults */
{
for (i = 4; i < MAXLINE - 1; i += 4)
Tabstops[i] = YES;
maxstop = i - 4 + 1;
}
Tabstops[0] = YES; /* always set to YES */
for (i = maxstop; i < MAXLINE; i++)
Tabstops[i] = YES;
return (ret);
}
/* serc --- read in ./.serc or $HOME/.serc and execute the commands in it. */
/*
* note that se's special control characters are NOT processed,
* and therefore should NOT be used in one's .serc file.
*/
static serc ()
{
char file[MAXLINE];
char lin[MAXLINE];
char *expand_env ();
FILE *fp;
int status = ENOERR;
int len, cursav;
strcpy (file, expand_env ("$HOME/.serc"));
if ((fp = fopen ("./.serc", "r")) == NULL ||
(fp = fopen (file, "r")) == NULL)
return;
while (fgets (lin, sizeof lin, fp) != NULL && status != EOF /*??*/)
{
if (lin[0] == '#' || lin[0] == '\n')
continue; /* comment in .serc file */
/* most of this code stolen from edit() */
len = 0;
cursav = Curln;
if (getlst (lin, &len, &status) == OK)
{
if (ckglob (lin, &len, &status) == OK)
doglob (lin, &len, &cursav, &status);
else if (status != ERR)
docmd (lin, len, NO, &status);
}
if (status == ERR)
{
if (Errcode == EHANGUP)
hangup ();
Curln = min (cursav, Lastln);
}
}
fclose (fp);
}
#ifdef LOG_USAGE
/* log -- log se usage */
static log ()
{
static char logfile[] = "/usr/tmp/se.log"; /* a public file */
char logname[MAXLINE], tod[26]; /* tod => time of day */
long clock;
FILE *fp;
char *ctime ();
long time ();
int old_umask;
#ifdef BSD
char *getlogin ();
#else
char *cuserid ();
#endif
/* get the login name */
#ifdef BSD
strcpy (logname, getlogin ());
#else
cuserid (logname);
#endif
time (&clock);
strcpy (tod, ctime (&clock)); /* see the manual on ctime(3C) */
tod[24] = EOS; /* delete the '\n' at the end */
old_umask = umask (0); /* allow writes for everyone */
/* when first call creates the file */
if ((fp = fopen (logfile, "a")) != NULL)
{
/* all ok, write out statistics */
fprintf (fp, "%s used se on %s.\n", logname, tod);
fclose (fp);
}
/* else
don't do anything */
umask (old_umask);
}
#endif
/* sysname --- return a string telling us who we are */
#ifdef USG
#include <sys/utsname.h> /* stuff to find out who we are */
#endif
char *sysname ()
{
int i, j, k;
char c;
static char buf[MAXLINE] = "";
FILE *fp;
static char unknown[] = "unknown";
#ifdef USG /* System V */
static struct utsname whoarewe;
uname (& whoarewe);
return (whoarewe.nodename);
#else
#ifdef BSD4_2 /* Berkeley 4.2 */
if (buf[0] != EOS)
return (buf);
j = sizeof (buf);
k = gethostname (buf, & j);
if (k != 0)
return (unknown);
else
return (buf);
#else /* Berkeley 4.1 */
if (buf[0] != EOS)
return (buf);
if ((fp = fopen ("/usr/include/whoami.h", "r")) == NULL)
return (unknown);
else
{
auto char *cp;
/*
* file should contain a single line:
* #define sysname "......"
*/
while ((c = getc (fp)) != '"' && c != EOF)
;
if (c == EOF)
cp = unknown;
else
{
for (i = 0; (c = getc (fp)) != '"' && c != EOF; i++)
buf[i] = c;
buf[i] = EOS;
if (c == EOF && i == 0)
cp = unknown;
else
cp = buf;
}
fclose (fp);
return (cp);
}
#endif
#endif
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'extern.h'" '(4770 characters)'
if test -f 'extern.h'
then
echo shar: will not over-write existing file "'extern.h'"
else
cat << \SHAR_EOF > 'extern.h'
/*
* $Header: extern.h,v 1.2 86/07/14 16:44:30 arnold Exp $
*/
/*
* $Log: extern.h,v $
* Revision 1.2 86/07/14 16:44:30 arnold
* Removed stuff that was Georgia Tech specific.
*
* Revision 1.1 86/05/06 13:36:05 osadr
* Initial revision
*
*
*/
/*
** extern.h
**
** external data definitions
** for the screen editor
*/
/* Concerning line numbers: */
extern int Line1; /* first line number on command */
extern int Line2; /* second line number on command */
extern int Nlines; /* number of line numbers specified */
extern int Curln; /* current line; value of dot */
extern int Lastln; /* last line; value of dollar */
/* Concerning patterns: */
extern char Pat[MAXPAT]; /* saved pattern */
/* Concerning the text of lines: */
extern char Txt[MAXLINE]; /* text of current line */
/* Concerning file names: */
extern char Savfil[MAXLINE]; /* remembered file name */
/* Concerning line descriptors: */
extern LINEDESC Buf[MAXBUF];
#ifdef OLD_SCRATCH
extern LINEDESC *Lastbf; /* last pointer used in Buf */
extern LINEDESC *Free; /* head of free list */
#endif
extern LINEDESC *Line0; /* head of list of line descriptors */
/* Concerning the 'undo' command: */
extern LINEDESC *Limbo; /* head of limbo list for undo */
extern int Limcnt; /* number of lines in limbo list */
/* Concerning the scratch file: */
extern filedes Scr; /* scratch file descriptor */
extern unsigned Scrend; /* end of info on scratch file */
extern char Scrname[MAXLINE]; /* name of scratch file */
extern int Lost_lines; /* number of garbage lines in scratch file */
/* Concerning miscellaneous variables */
extern int Buffer_changed; /* YES if buffer changed since last write */
extern int Errcode; /* cause of most recent error */
extern int Saverrcode; /* cause of previous error */
extern int Probation; /* YES if unsaved buffer can be destroyed */
extern int Argno; /* command line argument pointer */
extern char Last_char_scanned; /* last char scanned with ctl-s or -l */
#ifdef HARD_TERMS
extern int Tspeed; /* terminal speed in characters/second */
#endif
extern char Peekc; /* push a SKIP_RIGHT if adding delimiters */
#ifdef BSD4_2
extern int Reading; /* are we doing terminal input? */
#endif
/* Concerning options: */
extern int Tabstops[MAXLINE]; /* array of tab stops */
extern char Unprintable; /* char to print for unprintable chars */
extern int Absnos; /* use absolute numbers in margin */
extern int Nchoise; /* choice of line number for cont. display */
extern int Overlay_col; /* initial cursor column for 'v' command */
extern int Warncol; /* where to turn on column warning */
extern int Firstcol; /* leftmost column to display */
extern int Indent; /* indent col; 0=same as previous line */
extern int Notify; /* notify user if he has mail in mail file */
extern int Globals; /* substitutes in a global don't fail */
extern int No_hardware; /* never use hardware insert/delete */
#ifdef HARD_TERMS
/* Concerning the terminal type */
extern int Term_type; /* terminal type */
#endif
/* Concerning the screen format: */
extern char Screen_image[MAXROWS][MAXCOLS];
extern char Msgalloc[MAXCOLS]; /* column allocation of status line */
extern int Nrows; /* number of rows on screen */
extern int Ncols; /* number of columns on screen */
extern int Currow; /* vertical cursor coordinate */
extern int Curcol; /* horizontal cursor coordinate */
extern int Toprow; /* top row of window field on screen */
extern int Botrow; /* bottom row of window field on screen */
extern int Cmdrow; /* row number of command line */
extern int Topln; /* line number of first line on screen */
extern int Insert_mode; /* flag to specify character insertion */
extern int Invert_case; /* flag to specify case mapping on input */
extern int First_affected; /* number of first line affected by cmd */
extern int Rel_a; /* char to use for first alpha line number */
extern int Rel_z; /* char to use for last alpha line number */
extern int Scline[MAXROWS]; /* lines currently on screen (rel to Sctop) */
extern int Sctop; /* first line currently on screen */
extern int Sclen; /* number of lines currently on screen */
extern char Blanks[MAXCOLS]; /* all blanks for filling in lines on screen */
extern char Tobuf[MAXTOBUF]; /* buffer for collecting terminal output */
extern char *Tobp; /* pointer to last used part of Tobuf */
/* Concerning interrupts: */
extern int Int_caught; /* caught a SIGINT from user */
extern int Hup_caught; /* caught a SIGHUP when phone line dropped */
#ifdef SIGTSTP
extern int Catching_stops; /* catching or ignoring SIGTSTP's? */
#endif
/* Concerning file encryption: */
extern int Crypting; /* doing file encryption? */
extern char Key[KEYSIZE]; /* encryption key */
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'m4munge'" '(704 characters)'
if test -f 'm4munge'
then
echo shar: will not over-write existing file "'m4munge'"
else
cat << \SHAR_EOF > 'm4munge'
#! /bin/sh
# m4munge --- take what the 'where' command produces, and change it for m4
#
# $Header: m4munge,v 1.2 86/07/11 15:13:56 osadr Exp $
#
# $Log: m4munge,v $
# Revision 1.2 86/07/11 15:13:56 osadr
# Removed Georgia Tech specific items.
#
# Revision 1.1 86/05/06 13:35:02 osadr
# Initial revision
#
#
#
for i in $*
do
case $i in
-DUSG) echo 'define(USG,YES)' ;;
-UUSG) echo 'define(USG,NO)' ;;
-DBSD) echo 'define(BSD,YES)' ;;
-UBSD) echo 'define(BSD,NO)' ;;
-DBSD4_2) echo 'define(BSD4_2,YES)' ;;
-UBSD4_2) echo 'define(BSD4_2,NO)' ;;
-DS5R2) echo 'define(S5R2,YES)' ;;
-US5R2) echo 'define(S5R2,NO)' ;;
-DHARD_TERMS) echo 'define(HARD_TERMS,YES)' ;;
esac
done
SHAR_EOF
chmod +x 'm4munge'
fi # end of overwriting check
echo shar: extracting "'main.c'" '(13208 characters)'
if test -f 'main.c'
then
echo shar: will not over-write existing file "'main.c'"
else
cat << \SHAR_EOF > 'main.c'
#ifndef lint
static char RCSid[] = "$Header: main.c,v 1.4 86/10/07 14:50:17 arnold Exp $";
#endif
/*
* $Log: main.c,v $
* Revision 1.4 86/10/07 14:50:17 arnold
* Changed setterm to set_term, to avoid Unix/PC shared library conflict.
*
* Revision 1.3 86/07/17 17:20:58 arnold
* Terminal initialization code cleaned up considerably.
*
* Revision 1.2 86/07/11 15:12:26 osadr
* Removed code that was Georgia Tech specific
*
* Revision 1.1 86/05/06 13:37:38 osadr
* Initial revision
*
*
*/
/*
** main.c
**
** main program and lots of other routines
** for the se screen editor.
*/
#include "se.h"
/* declare global variables */
/* Concerning line numbers: */
int Line1; /* first line number on command */
int Line2; /* second line number on command */
int Nlines; /* number of line numbers specified */
int Curln; /* current line; value of dot */
int Lastln; /* last line; value of dollar */
/* Concerning patterns: */
char Pat[MAXPAT] = ""; /* saved pattern */
/* Concerning the text of lines: */
char Txt[MAXLINE]; /* text of current line */
/* Concerning file names: */
char Savfil[MAXLINE] = ""; /* remembered file name */
/* Concerning line descriptors: */
LINEDESC Buf[MAXBUF];
LINEDESC *Line0; /* head of list of line descriptors */
#ifdef OLD_SCRATCH
LINEDESC *Lastbf; /* last pointer used in Buf */
LINEDESC *Free; /* head of free list */
#endif
/* Concerning the 'undo' command: */
LINEDESC *Limbo; /* head of limbo list for undo */
int Limcnt; /* number of lines in limbo list */
/* Concerning the scratch file: */
filedes Scr; /* scratch file descriptor */
unsigned Scrend; /* end of info on scratch file */
char Scrname[MAXLINE]; /* name of scratch file */
int Lost_lines; /* number of garbage lines in scratch file */
/* Concerning miscellaneous variables */
int Buffer_changed = NO;/* YES if buffer changed since last write */
int Errcode = ENOERR; /* cause of most recent error */
int Saverrcode = ENOERR;/* cause of previous error */
int Probation = NO; /* YES if unsaved buffer can be destroyed */
int Argno; /* command line argument pointer */
char Last_char_scanned = 0; /* last char scanned w/ctl-[sl], init illegal */
char Peekc = EOS; /* push a SKIP_RIGHT if adding delimiters */
#ifdef HARD_TERMS
int Tspeed; /* terminal speed in characters/second */
#endif
#ifdef BSD4_2
int Reading = NO; /* are we doing terminal input? */
#endif
/* Concerning options: */
int Tabstops[MAXLINE]; /* array of tab stops */
char Unprintable = ' '; /* char to print for unprintable chars */
int Absnos = NO; /* use absolute numbers in margin */
int Nchoise = EOS; /* choice of line number for cont. display */
int Overlay_col = 0; /* initial cursor column for 'v' command */
int Warncol; /* where to turn on column warning, set in dosopt() */
int Firstcol = 0; /* leftmost column to display */
int Indent = 1; /* indent col; 0=same as previous line */
int Notify = YES; /* notify user if he has mail in mail file */
int Globals = NO; /* substitutes in a global don't fail */
int No_hardware; /* never use hardware insert/delete */
#ifdef HARD_TERMS
/* Concerning the terminal type */
int Term_type; /* terminal type */
#endif
/* Concerning the screen format: */
char Screen_image[MAXROWS][MAXCOLS];
char Msgalloc[MAXCOLS]; /* column allocation of status line */
int Nrows; /* number of rows on screen */
int Ncols; /* number of columns on screen */
int Currow; /* vertical cursor coordinate */
int Curcol; /* horizontal cursor coordinate */
int Toprow; /* top row of window field on screen */
int Botrow; /* bottom row of window field on screen */
int Cmdrow; /* row number of command line */
int Topln; /* line number of first line on screen */
int Insert_mode; /* flag to specify character insertion */
int Invert_case; /* flag to specify case mapping on input */
int First_affected; /* number of first line affected by cmd */
int Rel_a; /* char to use for first alpha line number */
int Rel_z; /* char to use for last alpha line number */
int Scline[MAXROWS]; /* lines currently on screen (rel to Sctop) */
int Sctop; /* first line currently on screen */
int Sclen; /* number of lines currently on screen */
char Blanks[MAXCOLS]; /* all blanks for filling in lines on screen */
char Tobuf[MAXTOBUF]; /* buffer for collecting terminal output */
char *Tobp = Tobuf - 1; /* pointer to last used part of Tobuf */
/* Concerning interrupts: */
int Int_caught = 0; /* caught a SIGINT from user */
int Hup_caught = 0; /* caught a SIGHUP when phone line dropped */
#ifdef BSD
int Catching_stops; /* catching or ignoring SIGTSTP's? */
#endif
/* Concerning file encryption: */
int Crypting = NO; /* doing file encryption? */
char Key[KEYSIZE] = ""; /* saved encryption key */
extern char *getenv ();
/* main --- main program for screen editor */
main (argc, argv)
int argc;
char *argv[];
{
char *basename ();
int int_hdlr (), hup_hdlr ();
int (*old_int)(), (*old_quit)();
#ifdef BSD
int stop_hdlr (), (*old_stop)();
#endif
/* catch quit and hangup signals */
/*
* In the terminal driver munging routines, we set Control-P
* to generate an interrupt, and turn off generating Quits from
* the terminal. Now we just ignore them if sent from elsewhere.
*/
signal (SIGHUP, hup_hdlr);
old_int = signal (SIGINT, int_hdlr);
old_quit = signal (SIGQUIT, SIG_IGN);
#ifdef notdef
/*
* This is commented out so that se can be run from the news
* software. Commenting it out will also allow you to put it
* in the background, which could give you trouble. So beware.
*/
if (old_int == SIG_IGN || old_quit == SIG_IGN)
{
/* fired off into the background, refuse to run */
if (isatty (fileno (stdin)))
{
fprintf (stderr, "%s: I refuse to run in the background.\n",
basename (argv[0]));
exit (2);
}
/* else
assume input is a script */
}
#endif
#ifdef BSD
old_stop = signal (SIGTSTP, stop_hdlr);
if (old_stop == SIG_IGN) /* running bourne shell */
{
signal (SIGTSTP, SIG_IGN); /* restore it */
Catching_stops = NO;
}
else
Catching_stops = YES;
/* running C-shell or BRL sh, catch Control-Z's */
#endif
/* set terminal to no echo, no output processing, break enabled */
ttyedit ();
#ifdef HARD_TERMS
Tspeed = getspeed (1); /* speed of stdout */
#endif
initialize (argc, argv);
edit (argc, argv);
#ifndef HARD_TERMS
t_exit ();
#endif
/* reset the terminal mode */
ttynormal ();
}
/* error --- print error message and die semi-gracefully */
error (coredump, msg)
int coredump;
char *msg;
{
/*
* You might think we want to try and save the buffer,
* BUT, fatal errors can be caused by buffer problems,
* which would end up putting us into a non-ending recursion.
*/
ttynormal ();
fprintf (stderr, "%s\n", msg);
signal (SIGQUIT, SIG_DFL); /* restore normal quit handling */
if (coredump)
kill (getpid (), SIGQUIT); /* dump memory */
else
exit (1);
}
/* initialize --- set up global data areas, get terminal type */
initialize (argc, argv)
int argc;
char *argv[];
{
int i, dosopt ();
Argno = 1;
#ifdef HARD_TERMS
/* Determine what type of terminal we're on */
if (Argno < argc && argv[Argno][0] == '-' && argv[Argno][2] == EOS
&& (argv[Argno][1] == 't' || argv[Argno][1] == 'T'))
{
Argno = 2;
if (Argno < argc)
{
strmap (argv[Argno], 'l');
if (set_term (argv[Argno]) == ERR)
usage ();
else
Argno++;
}
else
usage ();
}
else
/* fall through to the if, below */
#endif
if (set_term (getenv ("TERM")) == ERR)
usage ();
/* Initialize the scratch file: */
mkbuf ();
/* Initialize screen format parameters: */
setscreen ();
/* Initialize the array of blanks to blanks */
for (i = 0; i < Ncols; i++)
Blanks[i] = ' ';
Blanks[i] = '\0';
if (dosopt ("") == ERR)
error ("in initialize: can't happen");
}
/* intrpt --- see if there has been an interrupt or hangup */
int intrpt ()
{
if (Int_caught)
{
Errcode = EBREAK;
Int_caught = 0;
return (1);
}
else if (Hup_caught)
{
Errcode = EHANGUP;
Hup_caught = 0;
return (1);
}
return (0);
}
/* int_hdlr --- handle an interrupt signal */
int_hdlr ()
{
#ifndef BSD4_2
signal (SIGINT, int_hdlr);
#endif
Int_caught = 1;
}
/* hup_hdlr --- handle a hangup signal */
hup_hdlr ()
{
#ifndef BSD4_2
signal (SIGHUP, hup_hdlr);
Hup_caught = 1;
#else
/* do things different cause of 4.2 (sigh) */
Hup_caught = 1;
if (Reading) /* doing tty i/o, and that is where hup came from */
hangup ();
#endif
}
#ifdef BSD
/* stop_hdlr --- handle the berkeley stop/suspend signal */
int stop_hdlr ()
{
clrscreen ();
tflush ();
ttynormal ();
#ifdef BSD4_2
/* this handler remains in effect, use uncatchable signal */
kill (getpid(), SIGSTOP);
#else
/* action was reset to default when we caught it */
kill (getpid(), SIGTSTP);
#endif
/*
* user does a "fg"
*/
#ifndef BSD4_2
signal (SIGTSTP, stop_hdlr); /* reset stop catching */
#endif
ttyedit ();
restore_screen ();
}
#endif
/* hangup --- dump contents of edit buffer if SIGHUP occurs */
hangup ()
{
/* close terminal to avoid hanging on any accidental I/O: */
close (0);
close (1);
close (2);
signal (SIGHUP, SIG_IGN);
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
Hup_caught = 0;
Crypting = NO; /* force buffer to be clear text */
dowrit (1, Lastln, "se.hangup", NO, YES, NO);
clrbuf ();
exit (1);
}
/* mswait --- message waiting subroutine */
/* if the user wants to be notified, and the mail file is readable, */
/* and there is something in it, then he is given the message. */
/* the om command toggles Notify, controlling notification. */
#include <sys/types.h>
#include <sys/stat.h>
mswait ()
{
int access ();
struct stat buf;
static char *mbox = NULL;
static int first = YES;
static unsigned long mtime = 0L;
if (! Notify)
return;
if (first)
{
first = NO;
if ((mbox = getenv ("MAIL")) != NULL && access (mbox, 4) == 0)
{
if (stat (mbox, &buf) >= 0)
{
mtime = buf.st_mtime;
if (buf.st_size > 0)
remark ("You have mail");
}
}
}
else if (mbox && stat (mbox, &buf) >= 0 && buf.st_mtime > mtime)
{
mtime = buf.st_mtime;
remark ("You have new mail");
twrite (1, "\007", 1); /* Bell */
}
}
/* printverboseerrormessage --- print verbose error message */
printverboseerrormessage ()
{
switch (Errcode) {
case EBACKWARD:
remark ("Line numbers in backward order");
break;
case ENOPAT:
remark ("No saved pattern -- sorry");
break;
case EBADPAT:
remark ("Bad syntax in pattern");
break;
case EBADSTR:
remark ("Bad syntax in string parameter");
break;
case EBADSUB:
remark ("Bad syntax in substitution string");
break;
case ECANTREAD:
remark ("File is not readable");
break;
case EEGARB:
remark ("Garbage after your command");
break;
case EFILEN:
remark ("Bad syntax in file name");
break;
case EBADTABS:
remark ("Bad tabstop syntax");
break;
case EINSIDEOUT:
remark ("Can't move a group into itself");
break;
case EKNOTFND:
remark ("No line has that mark name");
break;
case ELINE1:
remark ("");
break;
case E2LONG:
remark ("Resultant line too long to handle");
break;
case ENOERR:
remark ("No error to report");
break;
case ENOLIMBO:
remark ("No lines in limbo");
break;
case EODLSSGTR:
remark ("Expected '<', '>', or nothing after 'od'");
break;
case EORANGE:
remark ("Line number out of range");
break;
case EOWHAT:
remark ("Can't recognize option");
break;
case EPNOTFND:
remark ("No line contains that pattern");
break;
case ESTUPID:
remark ("Buffer hasn't been saved");
break;
case EWHATZAT:
remark ("No command recognized");
break;
case EBREAK:
remark ("You interrupted me");
break;
case ELINE2:
remark ("Last line number beyond end of file");
break;
case ECANTWRITE:
remark ("File is not writeable");
break;
case ECANTINJECT:
remark ("No room for any more lines!");
break;
case ENOMATCH:
remark ("No match for pattern");
break;
case ENOFN:
remark ("No saved filename");
break;
case EBADLIST:
remark ("Bad syntax in character list");
break;
case ENOLIST:
remark ("No saved character list -- sorry");
break;
case ENONSENSE:
remark ("Unreasonable value");
break;
case ENOHELP:
remark ("No help available");
break;
case EBADLNR:
remark ("Line numbers not allowed");
break;
case EFEXISTS:
remark ("File already exists");
break;
case EBADCOL:
remark ("Improper column number specification");
break;
case ENOLANG:
remark ("Unknown source language");
break;
case ETRUNC:
remark ("Lines were truncated");
break;
case ENOSHELL:
remark ("Type control-q to rebuild screen");
break;
case ECANTFORK:
remark ("Can't fork --- get help!");
break;
case ENOSUB:
remark ("No saved replacement --- sorry");
break;
case ENOCMD:
remark ("No saved shell command --- sorry");
break;
default:
remark ("?");
break;
}
Errcode = ENOERR;
}
/* usage --- print usage diagnostic and die */
usage ()
{
ttynormal ();
fprintf (stderr, "Usage: se%s%s\n",
#ifdef HARD_TERMS
" [ -t <terminal> ] ",
#else
" ",
#endif
"[ --acdfghiklmstuvwxyz ] [ file ... ]");
exit (1);
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'makefile'" '(3680 characters)'
if test -f 'makefile'
then
echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
#
# $Header: makefile,v 1.3 86/09/19 12:16:19 arnold Exp $
#
# $Log: makefile,v $
# Revision 1.3 86/09/19 12:16:19 arnold
# Fixed to ignore return code from shell if statement.
#
# Revision 1.2 86/05/27 17:47:50 osadr
# Changes to support the Unix PC (no egrep, shared library), and
# to support making if . is not in the search path.
#
# Revision 1.1 86/05/06 13:39:18 osadr
# Initial revision
#
#
#
# makefile for the Georgia Tech Screen Editor, 'se'
HEADERS= ascii.h constdefs.h extern.h se.h
SRCS= docmd1.c docmd2.c edit.c main.c misc.c scratch.c screen.c term.c
OBJS= docmd1.o docmd2.o edit.o main.o misc.o scratch.o screen.o term.o
LIBRARIES= libchangetty/libchangetty.a pat/libpat.a
DOCS= makefile README
MANS= scriptse.1 se.1
CFLAGS= -O `cat flags`
LDFLAGS=
# On BSD systems, force make to use the right shell for commands
SHELL=/bin/sh
###########################################################################
# Begin system dependant macro definitions
# PR is to print the files nicely. Use pr -n if available, or else just pr
# I use a private utility called 'prt'
PR=pr
# NROFF is for nroffing. we use the System V nroff.
NROFF=/usr/5bin/nroff
# MANSEC is where to put the manual pages. Use 'l' for local, otherwise '1'.
MANSEC=l
# DESTBIN is where se and scriptse will go
DESTBIN= /usr/local/bin
# OWNER and GROUP are the owner and group respectively
OWNER= root
GROUP= sys
# INSTALL is the program to do the installation, use cp for real work
INSTALL= cp
# CHOWN changes the owner.
CHOWN= /etc/chown
# CHGRP changes the group.
CHGRP= chgrp
# CHMOD will change permissions.
CHMOD= chmod
########
# other things to change:
#
# on non-BSD systems, change the 'lpr' below to 'lp'
########
# Begin list of dependencies
all: se scriptse se.1
@echo all done
se: $(OBJS) $(LIBRARIES)
if grep DBSD flags > /dev/null || grep US5R2 flags > /dev/null; \
then echo -ltermlib > libs; \
else echo -lcurses > libs ; \
fi
-if [ -f /lib/shlib.ifile ] ; \
then ld /lib/crt0s.o /lib/shlib.ifile $(OBJS) $(LIBRARIES) -o $@ ; \
else $(CC) $(LDFLAGS) $(OBJS) $(LIBRARIES) `cat libs` -o $@ ; \
fi
rm libs
$(OBJS): $(HEADERS) flags
flags: where
./where > flags
libchangetty/libchangetty.a: libchangetty/changetty.c
cd libchangetty; make
pat/libpat.a: pat/pat.c
cd pat; make
scriptse: scriptse.c
$(CC) -O scriptse.c -o scriptse
se.1: se.m4 flags
(./m4munge $(CFLAGS) ; cat se.m4) | m4 | sed '/^$$/d' > se.1
install: all $(MANS)
$(INSTALL) se $(DESTBIN)
$(CHOWN) $(OWNER) $(DESTBIN)/se
$(CHGRP) $(GROUP) $(DESTBIN)/se
$(CHMOD) 711 $(DESTBIN)/se
$(INSTALL) scriptse $(DESTBIN)
$(CHOWN) $(OWNER) $(DESTBIN)/scriptse
$(CHGRP) $(GROUP) $(DESTBIN)/scriptse
$(CHMOD) 711 $(DESTBIN)/scriptse
$(INSTALL) se.1 /usr/man/man$(MANSEC)/se.$(MANSEC)
$(CHOWN) $(OWNER) /usr/man/man$(MANSEC)/se.$(MANSEC)
$(CHGRP) $(GROUP) /usr/man/man$(MANSEC)/se.$(MANSEC)
$(CHMOD) 644 /usr/man/man$(MANSEC)/se.$(MANSEC)
$(INSTALL) scriptse.1 /usr/man/man$(MANSEC)/scriptse.$(MANSEC)
$(CHOWN) $(OWNER) /usr/man/man$(MANSEC)/scriptse.$(MANSEC)
$(CHGRP) $(GROUP) /usr/man/man$(MANSEC)/scriptse.$(MANSEC)
$(CHMOD) 644 /usr/man/man$(MANSEC)/scriptse.$(MANSEC)
cd se_h; make install
print:
$(PR) $(HEADERS) $(SRCS) $(DOCS) $(MANS) | lpr
printman: $(MANS)
$(NROFF) -man $(MANS) | col | lpr
print2: $(HEADERS) $(SRCS) $(DOCS) $(MANS)
$(PR) $? | lpr
printall: printman print
cd pat; make print
cd libchangetty; make print
cd se_h; make print
clean:
rm -f *.o print2
cd pat; make clean
cd libchangetty; make clean
clobber: clean
rm -f se scriptse flags se.1
cd pat; make clobber
cd libchangetty; make clobber
cd se_h; make clobber
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'misc.c'" '(3315 characters)'
if test -f 'misc.c'
then
echo shar: will not over-write existing file "'misc.c'"
else
cat << \SHAR_EOF > 'misc.c'
#ifndef lint
static char RCSid[] = "$Header: misc.c,v 1.1 86/05/06 13:37:51 osadr Exp $";
#endif
/*
* $Log: misc.c,v $
* Revision 1.1 86/05/06 13:37:51 osadr
* Initial revision
*
*
*/
/*
** misc.c
**
** lots of miscellanious routines for the screen editor.
*/
#include "se.h"
#include "extern.h"
/* cprow --- copy from one row to another for append */
cprow (from, to)
register int from, to;
{
register int col;
for (col = 0; col < Ncols; col++)
load (Screen_image[from][col], to, col);
}
/* index --- return position of character in string */
int index (str, c)
register char str[], c;
{
register int i;
for (i = 0; str[i] != EOS; i++)
if (str[i] == c)
return (i);
return (-1);
}
/* strbsr --- binary search stab for an entry equal to str */
int strbsr (stab, tsize, esize, str)
char *stab, str[];
int tsize, esize;
{
/* stab should have been declared like this:
static struct {
char *s;
...
} stab[] = {
"string1", ...
"string2", ...
... ...
};
The call to strbsr should look like this:
i = strbsr (stab, sizeof (stab), sizeof (stab[0]), str);
*/
register int i, j, k, x;
int strcmp ();
i = 0;
j = tsize / esize - 1;
do {
k = (i + j) / 2;
if ((x = strcmp (str, *(char **)(stab + esize * k))) < 0)
j = k - 1; /* GREATER */
else if (x == 0)
return (k); /* EQUAL */
else
i = k + 1; /* LESS */
} while (i <= j);
return (EOF);
}
/* strmap --- map a string to upper/lower case */
int strmap (str, ul)
register char str[];
int ul;
{
register int i;
if (isupper (ul))
for (i = 0; str[i] != '0'; i++)
str[i] = islower (str[i]) ? toupper (str[i]) : str[i];
else
for (i = 0; str[i] == EOS; i++)
str[i] = isupper (str[i]) ? tolower (str[i]) : str[i];
return (i);
}
/* xindex --- invert condition returned by index */
int xindex (array, c, allbut, lastto)
char array[], c;
int allbut, lastto;
{
int index ();
if (c == EOS)
return (-1);
if (allbut == NO)
return (index (array, c));
if (index (array, c) > -1)
return (-1);
return (lastto + 1);
}
/* ctoi --- convert decimal string to a single precision integer */
int ctoi (str, i)
register char str[];
register int *i;
{
register int ret;
SKIPBL (str, *i);
for (ret = 0; isdigit (str[*i]); (*i)++)
ret = ret * 10 + (str[*i] - '0');
return (ret);
}
/* move_ --- move l bytes from here to there */
move_ (here, there, l)
register char *here, *there;
register int l;
{
while (l--)
*there++ = *here++;
}
/* twrite --- stuff characters into the terminal output buffer */
twrite (fd, buf, len)
register int fd, len;
register char *buf;
{
if ((Tobp - Tobuf) + 1 + len > MAXTOBUF)
tflush ();
if (fd != 1 || len > MAXTOBUF)
{
write (fd, buf, len);
return;
}
while (len--)
*++Tobp = *buf++;
}
/* tflush --- clear out the terminal output buffer */
tflush ()
{
write (1, Tobuf, (int)(Tobp - Tobuf + 1));
Tobp = Tobuf - 1;
}
/* basename -- return last portion of a pathname */
char *basename (str)
register char *str;
{
register char *cp;
#ifdef USG
#define rindex strrchr
#endif
char *rindex ();
if ((cp = rindex(str, '/')) == NULL)
return (str); /* no '/' found, return whole name */
else
return (++cp); /* skip over slash to name after it */
}
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
More information about the Mod.sources
mailing list