home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume23 / trn / part12 / rthreads.c < prev    next >
C/C++ Source or Header  |  1991-08-22  |  7KB  |  286 lines

  1. /* $Header: rthreads.c,v 4.3.3.3 91/01/16 03:28:53 davison Trn $
  2. **
  3. ** $Log:    rthreads.c,v $
  4. ** Revision 4.3.3.3  91/01/16  03:28:53  davison
  5. ** Changed Free to safefree.  Tweaked fopen for possible binary open mode.
  6. ** 
  7. ** Revision 4.3.3.2  90/08/20  16:58:14  davison
  8. ** Added message for missing/bad db.init file.
  9. ** 
  10. ** Revision 4.3.3.1  90/06/20  23:00:28  davison
  11. ** Initial Trn Release
  12. ** 
  13. */
  14.  
  15. #include "EXTERN.h"
  16. #include "common.h"
  17. #include "intrp.h"
  18.  
  19. #ifdef USETHREADS
  20. #include "INTERN.h"
  21. #include "rthreads.h"
  22.  
  23. static FILE *fp_in;
  24.  
  25. static char *strings = Nullch;
  26.  
  27. static int read_item();
  28. static void wp_bmap(), lp_bmap();
  29. static void safefree();
  30.  
  31. /* Initialize our thread code by determining the byte-order of the thread
  32. ** files and our own current byte-order.  If they differ, set flags to let
  33. ** the read code know what we'll need to translate.
  34. */
  35. void
  36. thread_init()
  37. {
  38.     char *filename;
  39.     int i;
  40.  
  41.     word_same = long_same = TRUE;
  42.     filename = filexp( "%X/db.init" );
  43.     if( (fp_in = fopen( filename, FOPEN_RB )) != Nullfp ) {
  44.     if( fread( &mt_bmap, 1, sizeof (BMAP), fp_in ) >= sizeof (BMAP)-1 ) {
  45.         if( mt_bmap.version != DB_VERSION ) {
  46.         printf( "\nThread database is the wrong version -- ignoring it.\n" ) FLUSH;
  47.         use_threads = FALSE;
  48.         }
  49.         mybytemap( &my_bmap );
  50.         for( i = 0; i < sizeof (LONG); i++ ) {
  51.         if( i < sizeof (WORD) ) {
  52.             if( my_bmap.w[i] != mt_bmap.w[i] ) {
  53.             word_same = FALSE;
  54.             }
  55.         }
  56.         if( my_bmap.l[i] != mt_bmap.l[i] ) {
  57.             long_same = FALSE;
  58.         }
  59.         }
  60.     } else {
  61.         goto no_db_init;
  62.     }
  63.     fclose( fp_in );
  64.     } else {
  65.       no_db_init:
  66.     printf( "\ndb.init read failed -- assuming no byte-order translations.\n\n" ) FLUSH;
  67.     }
  68. }
  69.  
  70. /* Open a thread file for the sole purpose of using it in a newsreader-
  71. ** style application.  Everything is read into arrays in chunks and some
  72. ** useful massaging of the data is performed to make the newsreader's life
  73. ** easier.  Be sure to call unuse_data() before calling this a second time.
  74. */
  75. int
  76. use_data( threadname )
  77. char *threadname;
  78. {
  79.     register int i, j, k;
  80.     register char *ptr;
  81.  
  82.     if( (fp_in = fopen( threadname, FOPEN_RB )) == Nullfp ) {
  83.     if (errno != ENOENT) {
  84.         printf( "\n\nOpen failed for thread data -- continuing unthreaded.\n" );
  85.     }
  86.     bzero( &total, sizeof (TOTAL) );
  87.     return 0;
  88.     }
  89.     if( fread( &total, 1, sizeof (TOTAL), fp_in ) < sizeof (TOTAL) ) {
  90.     printf( "\n\nRead failed for thread data -- continuing unthreaded.\n" );
  91.     fclose( fp_in );
  92.     bzero( &total, sizeof (TOTAL) );
  93.     return 0;
  94.     }
  95.     lp_bmap( &total.first, 4 );
  96.     wp_bmap( &total.root, 5 );
  97.  
  98.     if( !read_item( &author_cnts, (MEM_SIZE)total.author * sizeof (WORD) )
  99.      || !read_item( &strings, (MEM_SIZE)total.string1 ) 
  100.      || !read_item( &subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD) )
  101.      || !read_item( &p_roots, (MEM_SIZE)total.root * sizeof (PACKED_ROOT) )
  102.      || !read_item( &p_articles, (MEM_SIZE)total.article * sizeof (PACKED_ARTICLE) ) ) {
  103.     printf( "\n\nRead failed for thread data -- continuing unthreaded.\n" );
  104.     fclose( fp_in );
  105.     unuse_data( 0 );
  106.     return 0;
  107.     }
  108.     fclose( fp_in );
  109.  
  110.     if( !word_same || !long_same ) {
  111.     wp_bmap( author_cnts, total.author );
  112.     wp_bmap( subject_cnts, total.subject );
  113.     for( i = 0; i < total.root; i++ ) {
  114.         lp_bmap( &p_roots[i].root_num, 1 );
  115.         wp_bmap( &p_roots[i].articles, 3 );
  116.     }
  117.     for( i = 0; i < total.article; i++ ) {
  118.         lp_bmap( &p_articles[i].num, 2 );
  119.         wp_bmap( &p_articles[i].subject, 8 );
  120.     }
  121.     }
  122.  
  123. #ifndef lint
  124.     author_ptrs = (char **)safemalloc( total.author * sizeof (char **) );
  125.     subject_ptrs = (char **)safemalloc( total.subject * sizeof (char **) );
  126.     root_subjects = (WORD *)safemalloc( total.root * sizeof (WORD) );
  127.     root_article_cnts = (WORD *)safemalloc( total.root * sizeof (WORD) );
  128. #endif
  129.     selected_roots = safemalloc( total.root * sizeof (char) );
  130.  
  131.     bzero( root_article_cnts, total.root * sizeof (WORD) );
  132.     bzero( selected_roots, total.root * sizeof (char) );
  133.  
  134.     for( i = 0, ptr = strings; i < total.author; i++ ) {
  135.     author_ptrs[i] = ptr;
  136.     ptr += strlen( ptr ) + 1;
  137.     }
  138.  
  139.     for( i = 0, j = 0; i < total.root; i++ ) {
  140.     root_subjects[i] = j;
  141.     k = p_roots[i].subject_cnt;
  142.     while( k-- ) {
  143.         root_article_cnts[i] += subject_cnts[j];
  144.         subject_ptrs[j++] = ptr;
  145.         ptr += strlen( ptr ) + 1;
  146.     }
  147.     if( saved_selections ) {
  148.         for( k = 0; k < selected_root_cnt; k++ ) {
  149.         if( p_roots[i].root_num == saved_selections[k] ) {
  150.             selected_roots[i] = 1;
  151.         }
  152.         }
  153.     }
  154.     }
  155.     count_roots( !saved_selections );
  156.     safefree( &saved_selections );
  157.     select_page = 0;
  158.     return 1;
  159. }
  160.  
  161. /* A short-hand for reading a chunk of the file into a malloced array.
  162. */
  163. static int
  164. read_item( dest, len )
  165. char **dest;
  166. MEM_SIZE len;
  167. {
  168.     int ret;
  169.  
  170.     *dest = safemalloc( len );
  171.     ret = fread( *dest, 1, (int)len, fp_in );
  172.     if( ret != len ) {
  173.     free( *dest );
  174.     *dest = Nullch;
  175.     return 0;
  176.     }
  177.     return 1;
  178. }
  179.  
  180. /* Free some memory if it hasn't already been freed.
  181. */
  182. static void
  183. safefree( pp )
  184. char **pp;
  185. {
  186.     if( *pp ) {
  187.     free( *pp );
  188.     *pp = Nullch;
  189.     }
  190. }
  191.  
  192. /* Discard the thread data that we received through the use_data() call.
  193. ** If "save_selections" is non-zero, we'll try to remember which roots
  194. ** are currently selected long enough for the use_data() call to re-use
  195. ** them.  Only do this when you are going to re-open the same data file
  196. ** immediately with use_data() (presumably because the data has been
  197. ** updated while we were using it).
  198. */
  199. void
  200. unuse_data( save_selections )
  201. bool save_selections;
  202. {
  203.     int i, j;
  204.  
  205.     if( save_selections ) {
  206. #ifndef lint
  207.     saved_selections
  208.       = (ART_NUM *)safemalloc( selected_root_cnt * sizeof (ART_NUM) );
  209. #endif
  210.     for( i = 0, j = 0; i < total.root; i++ ) {
  211.         if( selected_roots[i] && root_article_cnts[i] ) {
  212.         saved_selections[j++] = p_roots[i].root_num;
  213.         }
  214.     }
  215.     } else {
  216.     selected_root_cnt = selected_count = 0;
  217.     }
  218.     safefree( &p_roots );
  219.     safefree( &root_subjects );
  220.     safefree( &author_cnts );
  221.     safefree( &subject_cnts );
  222.     safefree( &author_ptrs );
  223.     safefree( &subject_ptrs );
  224.     safefree( &root_article_cnts );
  225.     safefree( &selected_roots );
  226.     safefree( &p_articles );
  227.     safefree( &strings );
  228.  
  229.     p_art = curr_p_art = Nullart;
  230.     init_tree();        /* free any tree lines */
  231.  
  232.     bzero( &total, sizeof (TOTAL) );
  233. }
  234.  
  235. /* Transform each WORD's byte-ordering in a buffer of the designated length.
  236. */
  237. static void
  238. wp_bmap( buf, len )
  239. WORD *buf;
  240. int len;
  241. {
  242.     union {
  243.     BYTE b[sizeof (WORD)];
  244.     WORD w;
  245.     } in, out;
  246.     register int i;
  247.  
  248.     if( word_same ) {
  249.     return;
  250.     }
  251.     while( len-- ) {
  252.     in.w = *buf;
  253.     for( i = 0; i < sizeof (WORD); i++ ) {
  254.         out.b[my_bmap.w[i]] = in.b[mt_bmap.w[i]];
  255.     }
  256.     *buf++ = out.w;
  257.     }
  258. }
  259.  
  260. /* Transform each LONG's byte-ordering in a buffer of the designated length.
  261. */
  262. static void
  263. lp_bmap( buf, len )
  264. LONG *buf;
  265. int len;
  266. {
  267.     union {
  268.     BYTE b[sizeof (LONG)];
  269.     LONG l;
  270.     } in, out;
  271.     register int i;
  272.  
  273.     if( long_same ) {
  274.     return;
  275.     }
  276.     while( len-- ) {
  277.     in.l = *buf;
  278.     for( i = 0; i < sizeof (LONG); i++ ) {
  279.         out.b[my_bmap.l[i]] = in.b[mt_bmap.l[i]];
  280.     }
  281.     *buf++ = out.l;
  282.     }
  283. }
  284.  
  285. #endif /* USETHREADS */
  286.