|
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 - 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