|
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); } }