|
|
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 i
Length: 10485 (0x28f5)
Types: TextFile
Names: »info.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z«
└─⟦dcb95597f⟧
└─⟦this⟧ »info.c«
#ifndef lint
static char rcsid[] =
"$Header: info.c,v 2.9 88/01/13 19:00:56 deboor Exp $";
static char notice[] =
"This program is in the public domain and is available for unlimited \
distribution as long as this notice is enclosed.";
#endif
/*
* Routines for manipulating the lists of INFO structures attached to each
* folder.
*
* $Source: /c/support/deboor/usr/src/old/vmh/RCS/info.c,v $
* $Revision: 2.9 $
* $Author: deboor $
*
* FUNCTIONS:
* findinfo find INFO structure by linear search
* findinfoR find INFO structure relative to another
* findinfoS same but stop when it's clear INFO structure isn't there
* flushinfo write INFO list out to disk
* i_diff find # of structures between two INFO structures
* i_post return nth INFO structure after a given one
* i_pre return nth INFO structure before a given one
* linkinfo link an INFO structure into a list
* readinfo read/rebuild INFO list
* unlinkinfo unlink and INFO structure from its list
*/
# include "vmh.h"
# include <sys/file.h>
/*
* INFO *
* findinfo (mno, f) register mno; FLDR *f;
* look for mno in the info list of folder f. Starts
* at f->f_head and continues until either the message is found
* or the end of the list is reached. The final record examined
* (which is either the record or the tail of the list) is returned
*/
INFO *
findinfo (mno, f)
Reg2 int mno;
FLDR *f;
{
Reg1 INFO *ss;
for (ss = f->f_head; ss && ss->i_next && ss->i_mnum != mno; ss = ss->i_next)
;
return ss;
}
/*
* INFO *
* findinfoS (mno, f) register mno; FLDR *f;
* looks for the message mno in folder f . It does an absolute
* search starting from the head. If it finds the message, its INFO
* structure is returned. If it doesn't find the message, the INFO
* structure AFTER where it should have been is returned. The 'S' stands
* for "Stop", as in, stop when its impossible for the message to be there.
*/
INFO *
findinfoS (mno, f)
Reg2 int mno;
FLDR *f;
{
Reg1 INFO *ss;
for (ss = f->f_head; ss && ss->i_next && mno > ss->i_mnum; ss = ss->i_next)
;
return (ss);
}
/*
* INFO *
* findinfoR (mno, sp) register mno; INFO *sp;
* look for info on message number mno beginning at record *sp.
* if mno is below the number of *sp, search occurs backwards;
* if it is above it, search occurs forwards. If mno is not found,
* the final record examined is returned. If sp is NULL, NULL is returned.
*/
INFO *
findinfoR (mno, sp)
Reg2 int mno;
INFO *sp;
{
Reg1 INFO *ss;
if (!sp)
return ((INFO *) NULL);
if (mno < sp->i_mnum && sp->i_prev) {
for (ss = sp->i_prev; ss->i_prev && ss->i_mnum != mno; ss = ss->i_prev)
;
} else if (mno > sp->i_mnum && sp->i_next) {
for (ss = sp->i_next; ss->i_next && ss->i_mnum != mno; ss = ss->i_next)
;
} else
ss = sp;
return (ss);
}
/*
* INFO *
* i_pre (sp, n) INFO *sp; register n;
* returns the nth info structure before sp, or the previous-most
* (say what?) structure on the list if there aren't n structures before
* it. if n is negative, just calls i_post with -n.
* NULL is returned on an error. Note that only valid info structures
* are examined.
*/
INFO *
i_pre (sp, n)
INFO *sp;
Reg3 int n;
{
Reg1 int i;
Reg2 INFO *ss;
if (n < 0)
return (i_post(sp, -n));
if (!sp)
return (sp);
for (i = 0, ss = sp; i < n && ss->i_prev; ss = ss->i_prev)
if (!ss->i_invalid)
i++;
return (ss);
}
/*
* INFO *
* i_post(sp, n) INFO *sp; register n;
* returns the nth info record after sp. If there aren't that many,
* returns the last record on the list following sp. If n is negative,
* just calls i_pre to search before sp. Again, only valid info
* structures are counted.
* NULL is returned on any error.
*/
INFO *
i_post (sp, n)
INFO *sp;
Reg3 int n;
{
Reg1 int i;
Reg2 INFO *ss;
if (n < 0)
return (i_pre(sp, -n));
if (!sp)
return (sp);
for (i = 0, ss = sp; i < n && ss->i_next; ss = ss->i_next)
if (!ss->i_invalid)
i++;
return (ss);
}
/*
* i_diff (ss1, ss2) register INFO *ss1, *ss2;
* returns the number of valid records between ss1 and ss2.
* i.e. if ss1 == ss2, returns 0; if ss1->ss3->ss4->ss2,
* returns 3, etc.
*/
i_diff (ss1, ss2)
Reg1 INFO *ss1;
Reg3 INFO *ss2;
{
Reg2 int i;
if (!ss1 || !ss2) /* if either is null, return 0 */
return (0);
if (ss1->i_mnum < ss2->i_mnum) { /* move down the list if we're below it */
for (i = 0; ss1 != ss2; ss1 = ss1->i_next) {
if (ss1 == 0) {
break;
} else if (!ss1->i_invalid) {
i++;
}
}
} else { /* else move up the list */
for (i = 0; ss1 != ss2; ss1 = ss1->i_prev) {
if (!ss1) {
break;
} else if (!ss1->i_invalid) {
i--;
}
}
}
return (i);
}
/*
* linkinfo (sp, f) INFO *sp; FLDR *f;
* links the record *sp into the info structure list for the
* folder f . If this list is empty, the head and tail are set
* equal to sp; if sp's message number is greater than the tail's
* sp is linked after the tail and becomes the new tail (structures
* go from low numbers at the head to high numbers at the tail);
* if sp's mnum is less than the head's, sp becomes the new head;
* if it's between the head and the tail, searching begins at either
* the head or the tail depending on whether sp's mnum is less than
* or greater than the average of the two numbers, respectively.
*/
linkinfo (sp, f)
INFO *sp;
FLDR *f;
{
Reg2 INFO *tail = f->f_tail;
Reg3 INFO *head = f->f_head;
Reg1 int mno = sp->i_mnum;
INFO *r_prev, *r_next; /* save places for prev and next when replacing */
if (!tail) { /* no structures */
f->f_tail = f->f_head = sp; /* set sp as the first one */
sp->i_prev = sp->i_next = (INFO *)0;
} else if (mno > tail->i_mnum) { /* after tail */
tail->i_next = sp; /* link it to end */
sp->i_prev = tail;
sp->i_next = (INFO *) 0;
f->f_tail = sp; /* and make it the tail */
} else if (mno < head->i_mnum) { /* before head */
head->i_prev = sp; /* link sp at beginning */
sp->i_next = head;
sp->i_prev = (INFO *) 0;
f->f_head = sp; /* and make it the head */
} else { /* nowhere easy. look for the thing */
if (mno < (head->i_mnum + tail->i_mnum) / 2) {
/*
* loop terminates when it hits the end of the list (something
* is wrong), it finds itself in the list (this is a replace) or
* it finds the element before which it should be inserted.
*/
for (;head && head->i_mnum < mno; head = head->i_next)
;
} else {
for (;tail && tail->i_mnum > mno; tail = tail->i_prev)
;
if (! tail)
punt ("Couldn't link in info record!");
if (tail->i_mnum == mno) { /* if found */
head = tail; /* set the ptr app. */
goto replace; /* and do the replace */
}
head = tail->i_next; /* set ptr after where sp should be */
}
if (head && head->i_mnum == mno) { /* found itself */
replace:
r_prev = head->i_prev;
r_next = head->i_next;
*head = *sp;
head->i_prev = r_prev;
head->i_next = r_next;
} else if (!head) { /* couldn't find where to put it */
punt("Couldn't link in info record!"); /* major program bug */
} else { /* found where to stick it */
sp->i_prev = head->i_prev; /* link it to previous element */
sp->i_next = head; /* then to next */
head->i_prev->i_next = sp; /* then previous to it*/
head->i_prev = sp; /* then next to it */
}
}
f->f_modified = 1;
}
/*
* unlinkinfo (sp, f) register INFO *sp; FLDR *f;
* unlinks the structure pointed to by sp. IT DOESN'T FREE IT.
*/
unlinkinfo (sp, f)
register INFO *sp;
FLDR *f;
{
if (sp->i_prev) /* unlink from previous */
sp->i_prev->i_next = sp->i_next;
else /* must be the head of the list */
f->f_head = sp->i_next;
if (sp->i_next) /* unlink from next */
sp->i_next->i_prev = sp->i_prev;
else /* must be tail of list */
f->f_tail = sp->i_prev;
/*
* if it's any of the display pointers, advance them to next
* one, if it exists. If the next doesn't exist, move
* them to the previous one.
*/
if (sp == f->f_cur)
f->f_cur = (sp->i_next) ? sp->i_next : sp->i_prev;
if (sp == f->f_top)
f->f_top = (sp->i_next) ? sp->i_next : sp->i_prev;
if (sp == f->f_bot)
f->f_bot = (sp->i_next) ? sp->i_next : sp->i_prev;
}
/*
* readinfo (f) register FLDR *f;
* reads in the info file for the folder f. reads in an enormous
* block of records and then uses linkinfo to link them all up.
*/
readinfo (f)
Reg3 FLDR *f;
{
char infopath[PATHLENGTH];
Reg1 INFO *sp;
int nrecs;
Reg2 int i;
int ifile;
(void) strcat (strcpy (infopath, f->f_name), "/.info");
if ((ifile = open (infopath, O_RDONLY, 0)) < 0) {
makeinfo(f); /* can't find it. build new one */
return;
}
if (read (ifile, (char *) &nrecs, sizeof(nrecs)) < sizeof(nrecs)) {
errormsg ("bad .info format", 1); /* empty file */
makeinfo (f); /* build new one */
(void) close (ifile);
return;
}
sp = (INFO *) Calloc (nrecs, sizeof(INFO));
if (read (ifile, (char *)sp, sizeof(INFO) * nrecs) !=
nrecs * sizeof(INFO)) {
errormsg ("error in .info file", 1); /* munged file */
Free ((char *)sp); /* recover memory */
makeinfo (f); /* build new file */
(void) close (ifile);
return;
}
(void) close (ifile);
for (i = nrecs;i; i--,sp++)
linkinfo (sp, f);
if (checkinfo (f)) /* see if what we read was up to date */
makeinfo (f); /* no. remake it */
}
/*
* flushinfo (fd, f) int fd; register FLDR *f;
* (void) writes the info structures for the folder f out to the file
* w/descriptor fd.
*/
flushinfo (fd, f)
int fd;
register FLDR *f;
{
register INFO *ss;
(void) write (fd, (char *) &f->f_msgs.m_nummsg, sizeof(int));
for (ss = f->f_head; ss; ss = ss->i_next) {
if (!ss->i_invalid) {
(void) write (fd, (char *) ss, sizeof(INFO));
}
}
}
/*
* invalfldr (f)
* Invalidate all the info structures for the given folder. Used
* just before rebuilding so any structures which describe non-existent
* messages are prevented from being written out.
*/
invalfldr (f)
FLDR *f;
{
register INFO *ss;
for (ss = f->f_head; ss; ss = ss->i_next) {
ss->i_invalid = 1;
}
}
/*
* invalmsg (ss, f)
* invalidate the given message for the given folder. If the message
* number is listed as existing in the MSGS structure, it is removed
* and the number of messages in the folder is reduced by one.
*/
invalmsg (ss, f)
INFO *ss;
FLDR *f;
{
ss->i_invalid = 1;
if (Exists (ss->i_mnum, &f->f_msgs)) {
f->f_msgs.m_nummsg -= 1;
Del_Msg (ss->i_mnum, &f->f_msgs);
}
}