home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume23
/
trn
/
part12
/
rthreads.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-22
|
7KB
|
286 lines
/* $Header: rthreads.c,v 4.3.3.3 91/01/16 03:28:53 davison Trn $
**
** $Log: rthreads.c,v $
** Revision 4.3.3.3 91/01/16 03:28:53 davison
** Changed Free to safefree. Tweaked fopen for possible binary open mode.
**
** Revision 4.3.3.2 90/08/20 16:58:14 davison
** Added message for missing/bad db.init file.
**
** Revision 4.3.3.1 90/06/20 23:00:28 davison
** Initial Trn Release
**
*/
#include "EXTERN.h"
#include "common.h"
#include "intrp.h"
#ifdef USETHREADS
#include "INTERN.h"
#include "rthreads.h"
static FILE *fp_in;
static char *strings = Nullch;
static int read_item();
static void wp_bmap(), lp_bmap();
static void safefree();
/* Initialize our thread code by determining the byte-order of the thread
** files and our own current byte-order. If they differ, set flags to let
** the read code know what we'll need to translate.
*/
void
thread_init()
{
char *filename;
int i;
word_same = long_same = TRUE;
filename = filexp( "%X/db.init" );
if( (fp_in = fopen( filename, FOPEN_RB )) != Nullfp ) {
if( fread( &mt_bmap, 1, sizeof (BMAP), fp_in ) >= sizeof (BMAP)-1 ) {
if( mt_bmap.version != DB_VERSION ) {
printf( "\nThread database is the wrong version -- ignoring it.\n" ) FLUSH;
use_threads = FALSE;
}
mybytemap( &my_bmap );
for( i = 0; i < sizeof (LONG); i++ ) {
if( i < sizeof (WORD) ) {
if( my_bmap.w[i] != mt_bmap.w[i] ) {
word_same = FALSE;
}
}
if( my_bmap.l[i] != mt_bmap.l[i] ) {
long_same = FALSE;
}
}
} else {
goto no_db_init;
}
fclose( fp_in );
} else {
no_db_init:
printf( "\ndb.init read failed -- assuming no byte-order translations.\n\n" ) FLUSH;
}
}
/* Open a thread file for the sole purpose of using it in a newsreader-
** style application. Everything is read into arrays in chunks and some
** useful massaging of the data is performed to make the newsreader's life
** easier. Be sure to call unuse_data() before calling this a second time.
*/
int
use_data( threadname )
char *threadname;
{
register int i, j, k;
register char *ptr;
if( (fp_in = fopen( threadname, FOPEN_RB )) == Nullfp ) {
if (errno != ENOENT) {
printf( "\n\nOpen failed for thread data -- continuing unthreaded.\n" );
}
bzero( &total, sizeof (TOTAL) );
return 0;
}
if( fread( &total, 1, sizeof (TOTAL), fp_in ) < sizeof (TOTAL) ) {
printf( "\n\nRead failed for thread data -- continuing unthreaded.\n" );
fclose( fp_in );
bzero( &total, sizeof (TOTAL) );
return 0;
}
lp_bmap( &total.first, 4 );
wp_bmap( &total.root, 5 );
if( !read_item( &author_cnts, (MEM_SIZE)total.author * sizeof (WORD) )
|| !read_item( &strings, (MEM_SIZE)total.string1 )
|| !read_item( &subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD) )
|| !read_item( &p_roots, (MEM_SIZE)total.root * sizeof (PACKED_ROOT) )
|| !read_item( &p_articles, (MEM_SIZE)total.article * sizeof (PACKED_ARTICLE) ) ) {
printf( "\n\nRead failed for thread data -- continuing unthreaded.\n" );
fclose( fp_in );
unuse_data( 0 );
return 0;
}
fclose( fp_in );
if( !word_same || !long_same ) {
wp_bmap( author_cnts, total.author );
wp_bmap( subject_cnts, total.subject );
for( i = 0; i < total.root; i++ ) {
lp_bmap( &p_roots[i].root_num, 1 );
wp_bmap( &p_roots[i].articles, 3 );
}
for( i = 0; i < total.article; i++ ) {
lp_bmap( &p_articles[i].num, 2 );
wp_bmap( &p_articles[i].subject, 8 );
}
}
#ifndef lint
author_ptrs = (char **)safemalloc( total.author * sizeof (char **) );
subject_ptrs = (char **)safemalloc( total.subject * sizeof (char **) );
root_subjects = (WORD *)safemalloc( total.root * sizeof (WORD) );
root_article_cnts = (WORD *)safemalloc( total.root * sizeof (WORD) );
#endif
selected_roots = safemalloc( total.root * sizeof (char) );
bzero( root_article_cnts, total.root * sizeof (WORD) );
bzero( selected_roots, total.root * sizeof (char) );
for( i = 0, ptr = strings; i < total.author; i++ ) {
author_ptrs[i] = ptr;
ptr += strlen( ptr ) + 1;
}
for( i = 0, j = 0; i < total.root; i++ ) {
root_subjects[i] = j;
k = p_roots[i].subject_cnt;
while( k-- ) {
root_article_cnts[i] += subject_cnts[j];
subject_ptrs[j++] = ptr;
ptr += strlen( ptr ) + 1;
}
if( saved_selections ) {
for( k = 0; k < selected_root_cnt; k++ ) {
if( p_roots[i].root_num == saved_selections[k] ) {
selected_roots[i] = 1;
}
}
}
}
count_roots( !saved_selections );
safefree( &saved_selections );
select_page = 0;
return 1;
}
/* A short-hand for reading a chunk of the file into a malloced array.
*/
static int
read_item( dest, len )
char **dest;
MEM_SIZE len;
{
int ret;
*dest = safemalloc( len );
ret = fread( *dest, 1, (int)len, fp_in );
if( ret != len ) {
free( *dest );
*dest = Nullch;
return 0;
}
return 1;
}
/* Free some memory if it hasn't already been freed.
*/
static void
safefree( pp )
char **pp;
{
if( *pp ) {
free( *pp );
*pp = Nullch;
}
}
/* Discard the thread data that we received through the use_data() call.
** If "save_selections" is non-zero, we'll try to remember which roots
** are currently selected long enough for the use_data() call to re-use
** them. Only do this when you are going to re-open the same data file
** immediately with use_data() (presumably because the data has been
** updated while we were using it).
*/
void
unuse_data( save_selections )
bool save_selections;
{
int i, j;
if( save_selections ) {
#ifndef lint
saved_selections
= (ART_NUM *)safemalloc( selected_root_cnt * sizeof (ART_NUM) );
#endif
for( i = 0, j = 0; i < total.root; i++ ) {
if( selected_roots[i] && root_article_cnts[i] ) {
saved_selections[j++] = p_roots[i].root_num;
}
}
} else {
selected_root_cnt = selected_count = 0;
}
safefree( &p_roots );
safefree( &root_subjects );
safefree( &author_cnts );
safefree( &subject_cnts );
safefree( &author_ptrs );
safefree( &subject_ptrs );
safefree( &root_article_cnts );
safefree( &selected_roots );
safefree( &p_articles );
safefree( &strings );
p_art = curr_p_art = Nullart;
init_tree(); /* free any tree lines */
bzero( &total, sizeof (TOTAL) );
}
/* Transform each WORD's byte-ordering in a buffer of the designated length.
*/
static void
wp_bmap( buf, len )
WORD *buf;
int len;
{
union {
BYTE b[sizeof (WORD)];
WORD w;
} in, out;
register int i;
if( word_same ) {
return;
}
while( len-- ) {
in.w = *buf;
for( i = 0; i < sizeof (WORD); i++ ) {
out.b[my_bmap.w[i]] = in.b[mt_bmap.w[i]];
}
*buf++ = out.w;
}
}
/* Transform each LONG's byte-ordering in a buffer of the designated length.
*/
static void
lp_bmap( buf, len )
LONG *buf;
int len;
{
union {
BYTE b[sizeof (LONG)];
LONG l;
} in, out;
register int i;
if( long_same ) {
return;
}
while( len-- ) {
in.l = *buf;
for( i = 0; i < sizeof (LONG); i++ ) {
out.b[my_bmap.l[i]] = in.b[mt_bmap.l[i]];
}
*buf++ = out.l;
}
}
#endif /* USETHREADS */