|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 11621 (0x2d65)
Types: TextFile
Names: »scratch.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/se/scratch.c«
#ifndef lint
static char RCSid[] = "$Header: scratch.c,v 1.2 86/07/17 17:21:38 arnold Exp $";
#endif
/*
* $Log: scratch.c,v $
* Revision 1.2 86/07/17 17:21:38 arnold
* Calls to error() changed to reflect whether or not to coredump.
*
* Revision 1.1 86/05/06 13:38:04 osadr
* Initial revision
*
*
*/
/*
** scratch.c
**
** scratch file handling for se screen editor.
**
** If OLD_SCRATCH is defined, then this file will contain the
** original scratch file handling, based on linked lists,
** from the ratfor version of Software Tools. This method is
** real good at moving lines around, but is poor for finding lines.
**
** If OLD_SCRATCH is not defined, which is the default, this file will use
** the line handling methodology presented in Software Tools In Pascal,
** *without* changing the way any of the routines are called.
**
** Bascially, the lines are always kept in order in the Buf array.
** Thus, lines 1 through 5 are in Buf[1] through Buf[5]. blkmove() and
** reverse() do the work of moving lines around in the buffer. The alloc()
** routine, therefore, always allocates the first empty slot, which will be
** at Lastln + 1, if there is room.
**
** Deleted lines are kept at the end of the buffer. Limbo points to the first
** line in the group of lines which were last deleted, or else Limbo == NOMORE.
**
** It is a very good idea to read the chapters on editing in BOTH editions of
** Software Tools, before trying to muck with this. It also helps to be a
** little bit off the wall....
**
** In fact, I would go as far as saying, "If you touch this, it will break.
** It is held together with chewing gum, scotch tape, and bobby pins."
** (Of course, you could always use OLD_SCRATCH, which definitely works.
** It just increases the size of the editor.) So much for the old
** "Just replace the implementation of the underlying primitives..."
*/
#include "se.h"
#include "extern.h"
/* alloc --- allocate space for a new pointer block */
static LINEDESC *alloc (ptr)
register LINEDESC **ptr;
{
#ifdef OLD_SCRATCH /* old way */
if (Free == NOMORE) /* no free list, expand into unallocated space */
{
if (Lastbf - Buf + BUFENT <= MAXBUF) /* see if there's room */
{
*ptr = Lastbf;
Lastbf += BUFENT;
}
else
*ptr = NOMORE; /* out of pointer space */
}
else /* remove a block from free list */
{
*ptr = Free;
Free = Free->Prevline;
}
#else /* new way */
int limbo_index = Limbo - Buf; /* use indices instead of pointers */
/* N.B.: this statement is meaningless if Limbo == NOMORE */
/* but if so, we don't use limbo_index anyway */
if (Limbo == NOMORE)
if (Lastln < (MAXBUF - 1) - 1) /* dumb zero based indexing! */
*ptr = &Buf[Lastln + 1];
else
*ptr = NOMORE;
else if (limbo_index - Lastln > 1)
*ptr = &Buf[Lastln + 1];
else
*ptr = NOMORE;
#endif
return (*ptr);
}
/* bump --- advance line number and corresponding index simultaneously */
bump (line, ix, way)
int *line, way;
LINEDESC **ix;
{
if (way == FORWARD) /* increment line number */
{
#ifdef OLD_SCRATCH
*ix = (*ix)->Nextline;
if (*ix == Line0)
*line = 0;
else
(*line)++;
#else
(*ix)++;
if (*ix == &Buf[Lastln+1])
{
*line = 0;
*ix = Line0;
}
else
(*line)++;
#endif
}
else /* decrement line number */
{
if (*ix == Line0)
*line = Lastln;
else
(*line)--;
#ifdef OLD_SCRATCH
*ix = (*ix)->Prevline;
#else
if (*ix == Line0)
*ix = &Buf[Lastln];
else
(*ix)--;
#endif
}
}
/* closef --- close a file */
static closef (fd)
filedes fd;
{
close (fd);
}
/* clrbuf --- purge scratch file */
clrbuf ()
{
if (Lastln > 0)
svdel (1, Lastln);
closef (Scr);
unlink (Scrname);
}
/* garbage_collect --- compress scratch file */
garbage_collect ()
{
char new_name [MAXLINE];
register int i, new_scrend;
int new_fd;
register LINEDESC *p;
makscr (&new_fd, new_name);
remark ("collecting garbage");
new_scrend = 0;
#ifdef OLD_SCRATCH
for (p = Limbo, i = 1; i <= Limcnt; p = p->Nextline, i++)
#else
for (p = Limbo, i = 1; i <= Limcnt; p++, i++)
#endif
{
gtxt (p);
seekf ((long) new_scrend * 8, new_fd);
writef (Txt, (int) p->Lineleng, new_fd);
p->Seekaddr = new_scrend;
new_scrend += (p->Lineleng + 7) / 8;
}
#ifdef OLD_SCRATCH
for (p = Line0, i = 0; i <= Lastln; p = p->Nextline, i++)
#else
for (p = Line0, i = 0; i <= Lastln; p++, i++)
#endif
{
gtxt (p);
seekf ((long) new_scrend * 8, new_fd);
writef (Txt, (int) p->Lineleng, new_fd);
p->Seekaddr = new_scrend;
new_scrend += (p->Lineleng + 7) / 8;
}
closef (Scr);
unlink (Scrname);
Scr = new_fd;
sprintf (Scrname, "%s", new_name);
Scrend = new_scrend;
Lost_lines = 0;
remark ("");
}
/* gettxt --- locate text for line, copy to txt */
LINEDESC *gettxt (line)
int line;
{
register LINEDESC *k;
LINEDESC *getind ();
k = getind (line);
gtxt (k);
return (k);
}
/* gtxt --- retrieve a line from the scratch file */
gtxt (ptr)
register LINEDESC *ptr;
{
int readf ();
seekf ((long) ptr->Seekaddr * 8, Scr); /* position to start of file */
/*
* rounded Seekaddr to 8 byte sections, giving larger
* buffer space for text (*8)
*/
return (readf (Txt, (int) ptr->Lineleng, Scr) - 1);
}
/* inject --- insert a new line after curln */
inject (lin)
register char lin [];
{
register int i;
int maklin ();
register LINEDESC *k1, *k2;
LINEDESC *k3;
LINEDESC *getind ();
for (i = 0; lin [i] != EOS; )
{
i = maklin (lin, i, &k3); /* create a single line */
if (i == ERR)
{
Errcode = ECANTINJECT;
return (ERR);
}
#ifdef OLD_SCRATCH
k1 = getind (Curln); /* get pointer to curln */
k2 = k1-> Nextline; /* get pointer to nextln */
relink (k1, k3, k3, k2); /* set pointers of new line */
relink (k3, k2, k1, k3); /* set pointers of prev, next */
svins (Curln, 1);
Lastln++; /* update Lastln */
#else
Lastln++; /* update Lastln */
blkmove (Lastln, Lastln, Curln);
svins (Curln, 1);
#endif
Curln++; /* update Curln */
}
return (OK);
}
/* maklin --- construct a new line, add to scratch file */
maklin (lin, i, newind)
register char lin [];
register int i;
LINEDESC **newind;
{
char text [MAXLINE];
register int l, n;
LINEDESC *ptr;
LINEDESC *alloc ();
if (alloc (&ptr) == NOMORE) /* get space for pointer block */
return (ERR);
for (n = i; lin [n] != EOS; n++) /* find end of line */
if (lin [n] == '\n')
{
n++;
break;
}
if (n - i >= MAXLINE ) /* can't handle more than MAXLINE chars/line */
n = i + MAXLINE - 1;
l = n - i + 1; /* length of new line (including EOS) */
move_ (&lin [i], text, l); /* move new line into text */
text [l - 1] = EOS; /* add EOS */
ptr->Seekaddr = Scrend; /* will be added to end of scratch file */
ptr->Lineleng = l; /* line length including EOS */
ptr->Globmark = NO; /* not marked for Global command */
ptr->Markname = DEFAULTNAME; /* give it default mark name */
seekf ((long) Scrend * 8, Scr); /* go to end of scratch file */
writef (text, l, Scr); /* write line on scratch file */
Scrend += (l + 7) / 8; /* update end-of-file pointer */
Buffer_changed = YES;
*newind = ptr; /* return index of new line */
return (n); /* return next char of interest in lin */
}
/* makscr --- create a new scratch file */
makscr (fd, str)
register filedes *fd;
register char str[];
{
register int i;
for (i = 0; i <= 9; i++)
{
sprintf (str, "/usr/tmp/se%d.%d", getpid(), i);
/* create str name in /usr/tmp */
if ((*fd = open (str, 0)) < 0)
{
/* if the file is not there, close it and create it */
close (*fd);
if ((*fd = creat (str, 0700)) > 0)
{
close (*fd);
if ((*fd = open (str, 2)) > 0)
return;
}
}
else
close (*fd);
}
error (YES, "can't create scratch file");
}
/* nextln --- get line after "line" */
nextln (line)
int line;
{
register int ret;
ret = line + 1;
if (ret > Lastln)
ret = 0;
return (ret);
}
/* prevln --- get line before "line" */
prevln (line)
int line;
{
register int ret;
ret = line - 1;
if (ret < 0)
ret = Lastln;
return (ret);
}
/* readf --- read count words from fd into buf */
readf (buf, count, fd)
char buf [];
int count, fd;
{
register int ret;
ret = read (fd, buf, count);
if (ret != count)
error (YES, "Fatal scratch file read error");
return (ret);
}
#ifdef OLD_SCRATCH
/* relink --- rewrite two half links */
relink (a, x, y, b)
LINEDESC *a, *b, *x, *y;
{
x->Prevline = a;
y->Nextline = b;
}
#endif
/* seekf --- position file open on fd to pos */
static seekf (pos, fd)
long pos;
filedes fd;
{
register long ret;
long lseek ();
ret = lseek (fd, pos, 0); /* abs seek */
if (ret != pos)
error (YES, "Fatal scratch file seek error");
return (OK);
}
/* mkbuf --- create scratch file, initialize line 0 */
mkbuf ()
{
LINEDESC *p;
makscr (&Scr, Scrname); /* create a scratch file */
Scrend = 0; /* initially empty */
Curln = 0;
#ifdef OLD_SCRATCH
Lastln = 0;
#else
Lastln = -1; /* alloc depends on this... */
#endif
#ifdef OLD_SCRATCH
Lastbf = &Buf[0]; /* next word available for allocation ?? */
Free = NOMORE; /* free list initially empty */
#endif
Limbo = NOMORE; /* no lines in limbo */
Limcnt = 0;
Lost_lines = 0; /* no garbage in scratch file yet */
maklin ("", 0, &p); /* create an empty line */
#ifdef OLD_SCRATCH
relink (p, p, p, p); /* establish initial linked list */
#endif
p->Markname = EOS; /* give it an illegal mark name */
Line0 = p; /* henceforth and forevermore */
#ifndef OLD_SCRATCH
Lastln = 0;
#endif
}
/* sp_inject --- special inject for reading files */
LINEDESC *sp_inject (lin, len, line)
char lin[];
int len;
LINEDESC *line;
{
register LINEDESC *k, *ret;
LINEDESC *ptr;
LINEDESC *alloc ();
ret = alloc (&ptr);
if (ptr == NOMORE)
{
Errcode = ECANTINJECT;
return (ret);
}
ptr->Seekaddr = Scrend;
ptr->Lineleng = len + 1;
ptr->Globmark = NO;
ptr->Markname = DEFAULTNAME;
seekf ((long) Scrend * 8, Scr);
writef (lin, len + 1, Scr);
Scrend += ((len + 1) + 7) / 8; /* fudge for larger buffer */
Lastln++;
Buffer_changed = YES;
#ifdef OLD_SCRATCH
k = line->Nextline;
relink (line, ptr, ptr, k);
relink (ptr, k, line, ptr);
#else
/*
* this part dependant on the fact that we set
* Curln = line in the routine do_read.
*/
blkmove (ptr - Buf, ptr - Buf, Curln); /* need line no's */
Curln++;
#endif
return (ret);
}
/* writef --- write count words from buf onto fd */
writef (buf, count, fd)
char buf[];
int count;
filedes fd;
{
register int ret;
ret = write (fd, buf, count);
if (ret != count)
error (YES, "Fatal scratch file write error");
return (ret);
}
/* getind --- locate line index in buffer */
LINEDESC *getind (line)
register int line;
{
#ifdef OLD_SCRATCH
register LINEDESC *k;
k = Line0;
line++;
while (--line)
k = k->Nextline;
return (k);
#else
return (&Buf[line]);
#endif
}
#ifndef OLD_SCRATCH
/* blkmove -- use SWT in Pascal line handling */
blkmove (n1, n2, n3) /* move block of lines n1..n2 to after n3 */
int n1, n2, n3;
{
if (n3 < n1 -1)
{
reverse (n3 + 1, n1 - 1);
reverse (n1, n2);
reverse (n3 + 1, n2);
}
else if (n3 > n2)
{
reverse (n1, n2);
reverse (n2 + 1, n3);
reverse (n1, n3);
}
}
/* reverse -- reverse buf[n1]..buf[n2] */
reverse (n1, n2)
register int n1, n2;
{
LINEDESC temp;
while (n1 < n2)
{
temp = Buf[n1];
Buf[n1] = Buf[n2];
Buf[n2] = temp;
n1++;
n2--;
}
}
#endif