From: SMTP%"VMSSERV@kcl.ac.uk" 19-AUG-1996 18:17:23.51 To: everhart@star.zko.dec.com CC: Subj: WEBBOOK.2-OF-5 -+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+ X out_size = lz.\0E08; X code_limit = bmask`5Bout_size`5D; X X add_bits ( bs, lz.clear, out_size ); X value = *dptr++; X prefix = (value`261) ? 0 : 1;`09`09/* first bit */ X mask = 2; X for ( i = 0; i < height; i++ ) `7B X for ( j = (i==0) ? 1 : 0; j < width; j++ ) `7B X`09/* X`09 * Extract next bit from input bits. X`09 */ X`09current = ((value`26mask) != 0) ? 0 : 1; X`09mask *= 2; X`09if ( mask > 128 ) `7B\0F06= 1; value = *dptr++; `7D X`09/*`20 X`09 * Find prefix//current table entry`20 X`09 */ X`09/* hashval = (lz.max_hash`26((current< code_limit ) `7B X`09 out_size++; X`09 code_limit =\0D0B*2 + 1; X`09 `7D X`09 if ( new > 4092 ) `7B X`09`09/* Reset so we don't overflow */ X`09`09add_bits ( bs, current, out_size ); X`09`09add_bits ( bs, lz.clear, out_size ); X`09`09current = lz.clear; X`09`09initialize_lz_state ( `26lz, code_size ); X#ifdef DEBUG Xprintf("Reset code table, out_size %d, clear=%d`5Cn", lz.\1D08, lz.clear ); X#endif X`09`09out_size = lz.\0E08; X`09`09code_limit = bmask`5Bout_size`5D; X X`09`09prefix = ((value`26mask) != 0) ? 0 : 1; X`09`09mask *= 2; X`09`09if ( mask > 128 ) `7B\0F06= 1; value = *dptr++; `7D X`09`09j++; if ( j >= width ) break; X`09 `7D else `7B X`09 lz.table`5Bnew`5D.prefix = \0906; X`09 lz.table`5Bnew`5D.code = current; X`09 lz.table`5Bnew`5D.next_hash = hash_\1C06hashval`5D; X`09 lz.hash_table`5Bhashval`5D = new; X X`09`09/* prefix for next value */ X`09 prefix = current; X`09 `7D X`09 `20 X`09`7D X `7D X if ( mask != 1 ) `7B`09/* wrap to next byte at eol */ X`09mask = 1; value = *dptr++;; X `7D X `7D X /* X * Flush remaining to output. X */ X add_bits ( bs, prefix, out_size ); X if ( i >= height ) `7B add_bits ( bs, lz.eoi, out_size ); return 1; `7D X X return 1; X`7D $ call unpack [.WEBBOOK]BOOKFILE_FIGURE.C;1 - 1912650167 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 22 4 20 $! $ create 'f' Xint bkg_convert_figure_to_gif (`20 X`09long hdr`5B10`5D, `09`09`09/* Section header figure subrec */ X`09unsigned char *data, int datalen, /* data read from section */ X`09int (*output)(void*, int, char *), /* User-supplied \2E06 function */ X`09void *outarg );`09`09`09/* user-arg for output function */ $ call unpack [.WEBBOOK]BOOKFILE_FIGURE.H;1 - 673988755 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 1 5 20 $! $ create 'f' X/* X * Define routines for handling indices X * X * int bki_create_context ( void *bkfctx,\0E07*\1F08); X * int bki_delete_context ( void *ctx ); X * int bki_find_index ( void *ctx, char *pattern, int pat_type, X *`09`09char name`5B256`5D, int *type\0B07count); X * int bki_find_index_end ( void *ctx ) X * X * int bki_open_index ( void *ctx, char *name ); `20 X * int bki_read_index ( void *ctx, char name`5B256`5D ); X * int bki_close_index ( void *ctx ); X */ X#include X#include X#include X#include X X#include "bookreader_recdef.h" X#include "bookfile_io.h" X#include "bookfile_index.h"`09/* validate prototypes */ X Xstruct index_context `7B X void *bkf;`09`09`09/* bkf_open context for doing I/O */ X bkrdr_recptr root;`09`09/* pointer to root part for file */ X bkrdr_recptr cur;`09`09/* Current open index page */ X int cur_alloc;`09`09/* Allocation size of cur */ X int offset;`09`09`09/* Current read\1A07 in cur */ X int find_context;`09`09/* Offset for\1D06index */ X`7D; Xtypedef struct index_context *bkictx; Xstatic bkrdr_recptr lookup_index ( bkictx ctx, char *name );`09/* fwd ref */ Xstatic int strmatchwild ( char *cand,\0C07pattern ); X Xint bki_create_context ( void *bkf,\0B07*\1C08) X`7B X bkictx ctx; X int status, page_length, \0806; X /* X * allocate context block. X */ X ctx = (bkictx) malloc ( sizeof(struct index_context) ); X if ( !ctx ) return SS$_INSFMEM; X ctx->bkf = bkf; X ctx->cur_alloc = 0; X ctx->offset = 0; X ctx->find_context = 0; X /* X * Make local copy of pointer to root part of file (part 0). We assume X * bkf_read returns address of a static structure for part 0. X */ X status = bkf_read_page ( bkf, 0, `26page_length, `26ctx->root, `26\1506 ); V X *context = (void *) ctx; X return status; X`7D X Xint bki_delete_context ( void *\1008) X`7B X bkictx ctx; X /* X * Deallocate any structures and sub-\130C\2B07d. X */ X ctx = (bkictx) context; X X if ( ctx->cur_alloc > 0 ) `7B X`09free ( ctx->cur ); X`09ctx->cur_alloc = 0; X `7D X free ( ctx ); X return 1; X`7D X/********\0808\1010\2020\400D/ X/* Scan indexes listed in the root part for\2406 with matching name(s). X */ Xint bki_find_index ( void *context, char *pattern, int pat_type,`20 X`09char name`5B256`5D, int *type\0B07count ) X`7B X bkictx ctx; X bkrdr_recptr root, subrec; X int status, has_wild, i; X X ctx = (bkictx) context; X root = ctx->root; X /* X * See if find_index is in progress. X */ X if ( ctx->find_context == 0 ) `7B X`09/*`20 X`09 * Start new search, Examine for wildcards. X`09 */ X`09for ( i = has_wild = 0; pattern`5Bi`5D; i++ )`20 X`09`09if ( pattern`5Bi`5D == '*' `7C`7C\1510%' ) `7B X`09 has_wild = 1; X`09 break; X`09`7D X`09if ( pat_type == -1 ) has_wild = 1; X`09if ( has_wild ) `7B X`09 /* Set find_context to offset of first sub-record */ X`09 ctx->find_context = sizeof(root->first); X`09`7D else `7B X`09 /* Do direct match */ X`09 subrec = lookup_index ( ctx, name ); X`09 if ( !subrec ) return 0; X X`09 *type = subrec->table.keyid; X`09 *count = subrec->table.count; X`09 strncpy ( name, subrec->table.title\1513_len ); X`09 return 1; X`09`7D X `7D X /* X * Continue search. X */ X for ( i = ctx->find_context; i < root->gen.length; X`09`09i += subrec->gen.length ) `7B X`09subrec = (bkrdr_recptr) `26root->reloff`5Bi`5D; X`09if ( subrec->gen.length <= 0 ) break;`09/* invalid\2C07 */ X /* X`09 * Test only the table header records. X`09 */ X`09if ( subrec->gen.type == BKSBREC_TABLE ) `7B X`09 if ( pat_type >= 0 ) `09/* make sure type matches */ X`09`09`09if ( pat_type != subrec->table.keyid ) continue; X`09 if ( 0 == strmatchwild ( subrec->table.title, pattern ) ) `7B X`09`09*type = subrec->table.keyid; X`09`09*count = subrec->table.count; X`09`09strncpy ( name, subrec->table.title\1513_len ); X`09`09name`5Bsubrec->table.tit_len`5D = '`5C0'; X`09`09ctx->find_context = i + subrec->gen.length; X`09`09return 1; X`09 `7D X`09`7D X `7D X /* X * No more entires. X */ X ctx->find_context = i; X return 2; X`7D X/* X * Return pointer to matching index record. X */ Xstatic bkrdr_recptr lookup_index ( bkictx ctx, char *name ) X`7B X bkrdr_recptr subrec, root; X int i, namlen; X X root = ctx->root; X namlen = strlen ( name ) + 1; X /* X * Scan subrecords of root. X */ X for ( i = sizeof(root->first); i < \1206gen.length;`20 X`09`09i+= subrec->gen.length ) `7B X`09subrec = (bkrdr_recptr) `26root->reloff`5Bi`5D; X`09if ( subrec->gen.length <= 0 ) break; X`09/* X`09 * Check table records found for matching name. X`09 */ X`09if ( subrec->gen.type == BKSBREC_TABLE ) `7B X`09 if ( subrec->table.tit_len == namlen ) if`20 X`09`09( 0==strncmp(subrec->table.title, nam\0606len)) return \2B06; X`09`7D X `7D X return (bkrdr_recptr) 0; X`7D X/********\0808\1010\2020\400A/ X/* Reset find context. X */ Xint bki_find_index_end ( void *context ) X`7B X bkictx ctx; X X ctx = (bkictx) context; X ctx->find_context = 0; X return 1; X`7D X X/********\0808\1010\2020\4008/ X/* Emulate VMS wildcard matching routine for c strings. Algorithm obtained X * by decoding VAX version of STR$MATCH_WILD. A successful match returns X * 0 to correspond with success status of tu_strncmp() routine. X */ X#define WC_FAIL 1 X#define WC_MATCH 0 Xstatic int strmatchwild ( char *cand,\0C07pattern ) X`7B X char *save_cand,\0C07pattern; X /* X * Main loop, check each character in pattern string. X */ X for ( save_cand = (char *) 0; *pattern; \0907++ ) `7B X`09if ( *pattern == '*' ) `7B X`09 /* X`09 * Wildcard character, if it is last \1909 in pattern we know X`09 * we have match. X`09 */ X`09 if ( pattern`5B1`5D == '`5C0' ) return WC_MATCH; X`09 /* X`09 * checkpoint the current position of X`09 * both strings so we can resume at the succeeding candidate X`09 * string character if sub\1707starting at current position X`09 * fails. X`09 */ X`09 save_cand = cand;`20 X`09 save_pattern = \0A07; X X`09`7D else if ( *cand++ != *pattern )\1B07\1008!= '%' ) `7B X`09 /* X`09 * Characters did not match, if no '*'s in preceding pattern, X`09 * then strings do not match. X`09 */ X`09 if ( !save_cand ) return WC_FAIL; X`09 /* X`09 * Resume search at next candidate character, updating X`09 * the candidate checkpoint position. If no more characters, X`09 * then strings do not match. X`09 */ X`09 if ( *save_cand++ == '`5C0' ) return WC_FAIL; X`09 cand = save_cand; X`09 pattern = save_\0F07; X`09`7D X `7D X /* X * If pattern matched to this point, we succeed if candidate also at end. X */ X if ( *cand == '`5C0' ) return WC_MATCH; X return WC_FAIL; X`7D X/********\0808\1010\2020\400A/ Xint bki_open_index ( void *context, char *name ) X`7B X bkictx ctx; X bkrdr_recptr tblrec, ndxrec; X int status, page_length, \0806; X X /* X * Lookup index. X */ X ctx = (bkictx) context; X tblrec = lookup_index ( ctx, name ); X if ( !tblrec ) return 0; X /* X * read page and make copy. X */ X status = bkf_read_page ( ctx->bkf, tblrec->table.part, `26page_length, X`09`26ndxrec, `26length ); X if ( (status`261) == 0 ) return \1806; X if ( ndxrec->gen.type != BKREC_INDEX ) return SS$_BUGCHECK; X X if ( ctx->cur_alloc <= page_length ) `7B X`09/* Allocate buffer */ X`09if ( ctx->cur_alloc > 0 ) `7B X`09 ctx->cur_alloc = 0; X`09 free ( ctx->cur ); X`09`7D X`09ctx->cur = (bkrdr_recptr) malloc ( page_length + 15000 ); X`09if ( !ctx->cur ) return SS$_INSFMEM; X`09ctx->cur_alloc = page_length + 15000; X `7D X memcpy ( ctx->cur, ndxrec, page_length ); X ndxrec = ctx->cur; X /* X * Initalize offset. X */ X ctx->offset = sizeof(ndxrec->gen); X return 1; X`7D Xint bki_close_index ( void *context ) X`7B X bkictx ctx; X X ctx = (bkictx) context; X ctx->offset = 0; X return 1;`09`09/* nothing to do */ X`7D X/********\0808\1010\2020\400C/ X/* Read table index entry and current offset and return data to caller. X */ Xint bki_read_index ( void *context,`20 X`09short hdr`5B9`5D, `09`09/* Index entry attributes + hor,ver of name */ X`09unsigned char attr`5B4`5D, /* Fontno, x, y, length of name */ X`09char name`5B256`5D, `09/* Entry name */ X`09char **desc, `09`09/* Display descricption. */ X`09long *value )`09`09/* Section number or special \2606*/ X`7B X X bkictx ctx; X bkrdr_recptr ndxrec, subrec; X struct text_rec *trec; X int status, offset, i, j, sublen, namlen; X long *vptr; X /* X * Recover context and do consitency checks. X */ X ctx = (bkictx) context; X offset = ctx->\0E06; X if ( offset <= 0 ) return SS$_BADPARAM; X ndxrec = ctx->cur; X if ( offset >= ndxrec->gen.length ) return SS$_NOMOREFILES; X /* X * Look at record\0707 at current offset, update\0F07 used for X * next read. X */ X subrec = (bkrdr_recptr) `26ndxrec->reloff`5Boffset`5D; X if ( subrec->gen.type != BKSBREC_IXTXT ) return SS$_BUGCHECK; X ctx->offset = \0907+ subrec->gen.length; X /* X * Copy fixed portion of ixtxt record to caller's arguments and initialize V X * variable portion to null values. X */ X for ( i = 0; i < 7; i++ ) hdr`5Bi`5D = subrec->ixtxt.ix\1906; X hdr`5B7`5D = hdr`5B8`5D = 0; X namlen = 0; X name`5B0`5D = '`5C0'; X *desc = ""; X *value = 0; X attr`5B0`5D =\0A061\0A092\14093`5D = 0; X /* X * Scan text subrecords. X */ X for ( i = sizeof(subrec->ixtxt); i < s\1407gen.length; i += sublen ) `7B X`09trec = (struct text_rec *) `26subrec->reloff`5Bi`5D; X`09sublen = trec->reclen; X`09switch ( trec->type ) `7B X`09 case 1: X`09`09break; X`09 case 2: X`09 case 3: X`09`09/* X`09`09 * Contcatenate strings. Save attributes on first\2307 only. X`09`09 */ X`09`09j = sublen - sizeof(struct text_rec) +\1A08trec->data); X`09`09if ( namlen == 0 ) `7B X`09`09 hdr`5B7`5D = trec->hor; X`09`09 hdr`5B8`5D = trec->ver; X`09`09 attr`5B0`5D = trec->fontno; X`09`09 attr`5B1`5D = trec->x; X`09`09 attr`5B2`5D = trec->y; X`09`09`7D X`09`09if ( (namlen + j) < 254 ) `7B X`09`09 if ( namlen != 0 ) name`5B\1306++`5D = '`5C0';`09/* fake word bounda Vry */ X`09`09 memcpy ( `26name`5Bnamlen`5D, trec->data, j ); X`09`09 namlen += j; X`09`09 name`5Bnamlen`5D = '`5C0'; X`09`09`7D X`09`09attr`5B3`5D = namlen; X`09`09break; X X`09 default: X`09`09/* X`09`09 * Assume this is description following name. X`09`09 */ X`09`09*desc = `26subrec->reloff`5Bi`5D; X`09`09vptr = (long *) `26subrec->reloff`5Bi+strlen(*desc)+1`5D; X`09`09*value = *vptr; X`09`09sublen = 0; X`09`09i = subrec->gen.length;`09/* force loop exit */ X`09`09break; X`09`7D X `7D X return 1; X`7D $ call unpack [.WEBBOOK]BOOKFILE_INDEX.C;1 - 1802949894 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 22 6 20 $! $ create 'f' X/* X * Routines for accessing indices of bookreader file. X */ Xint bki_create_context ( void *bkfctx,`09\0E06*ctx ); Xint bki_delete_context ( void *ctx ); X/* X * If type is -1, matches any, otherwise both\2806and name must\2F06. X */ Xint bki_find_index ( void *ctx, char *pattern, int pat_type, X`09char name`5B256`5D, int *type\0B07count ); Xint bki_find_index_end ( void *ctx ); Xint bki_open_index ( void *ctx, char *name ); X/* X * For read_index, hdr includes 7 shorts from ixtxt record and X * 2 from first text subrecord (type 2/3). Pointers returned by read_index X * will remain valid until index is closed (only one\1A07may be X * open per context). X */ Xint bki_read_index ( void *ctx,`20 X`09short hdr`5B9`5D, `09`09/* Index entry attributes + hor,ver of name */ X`09unsigned char attr`5B4`5D, /* Fontno, x, y, length of name */ X`09char name`5B256`5D, `09/* Entry name */ X`09char **desc, `09`09/* Display descricption. */ X`09long *value );`09`09/* Section number or special \2706*/ Xint bki_close_index ( void *ctx ); $ call unpack [.WEBBOOK]BOOKFILE_INDEX.H;1 - 906102625 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 3 7 20 $! $ create 'f' X/* X * Low-level routines for accessing bookreader files via RMS. Records X * are read via rfa address. X * X * int bkf_open ( char *fname,\0D07de\0F07void **retctx ); X * int bkf_close ( void *ctx ); X * char *bkf_last_error ( void *ctx ); X * int bkf_read ( void *ctx, file_address *rfa, *bufaddr, *length ); X * int bkf_read_page ( void *ctx, id, *page_length, *bufaddr, *\1306 ); X * int bkf_lookup_section ( void *ctx, int sect-id\0D06*part ); X * int bkf_lookup_first_section ( void *ctx, int sect-id\0D06*part\0B07fsec V ); X * X * Function values returned are VMS condition codes. specifying a X * null pointer for rfa causes a sequential read. X * X * Author:`09David Jones X * Date:`0910-SEP-1995 X */ X X#include X#include X#include X#include X#include X#include X#include "bookreader_recdef.h" X#include "bookfile_io.h" `09`09`09/* verify prototypes */ Xint sys$open(), sys$connect\0F09lose\1C08get(); X Xstruct rfa_context `7B X struct FAB fab; X struct RAB rab; X struct XABFHC xabfhc;`09`09/* for setting network block count */ X struct XABITM xabitm;`09`09/* for setting mode */ X struct `7B X`09short length, code; X`09long *bufaddr, *retlen, term; X `7D xab_itemlist; X long network_block_count; X int high_id;`09`09`09/* highest allowed id */ X int superbuf_alloc; X bkrdr_recptr root;`09`09`09/* master info rec for file (1st) */ X bkrdr_recptr lrec;`09`09`09/* page id -> file_address mapping */ X bkrdr_recptr superbuf;`09`09/* Buffer for assembling large recs */ X long *secmap;`09`09`09/* Section id -> page id mapping */ X long *first_sec;`09`09`09/* First section id for page */ X char *ubuf;`09`09&0209/* buffer for I/O operations */ X int partcount, sec\0B06;`09`09/* Local, aligned copy of root page */ X`09`09&0209`09/* cells */ X char last_error`5B128`5D;`09`09/* text describing error */ X`7D; Xtypedef struct rfa_context *rfactx; X X/* X * Since opens don't have a valid context, last error for NULL ctx is global. V X */ Xstatic char *last_open_error = ""; X Xchar *bkf_last_error ( void *vctx ) X`7B X rfactx ctx; X X if ( vctx ) `7B X`09ctx = (rfactx) vctx; X`09return ctx->last_error; X `7D else return last_open_error; X`7D X/********\0808\1010\2020\400C/ X/* Utility routine to allocate new buffer and copy contents of existing X * buffer to it X */ Xstatic bkrdr_recptr duplicate_record (\200Esource, int length ) X`7B X bkrdr_recptr new; X new = (bkrdr_recptr) malloc ( length ); X if ( new ) memcpy\0F06, source, length ); X return new; X`7D X/********\0808\1010\2020\400C/ X/* Close bookreader file and deallocate context structures. X */ Xint bkf_close ( void *vctx ) X`7B X rfactx ctx; X int status; X ctx = (rfactx) vctx; X if ( !ctx ) return SS$_BADPARAM; X status = sys$close ( `26ctx->fab ); X X if ( ctx->root ) free\130E; X if ( ctx->lrec ) free\130E; X if ( ctx->secmap ) free\1510; X if ( ctx->ubuf ) free\130E; X if ( ctx->superbuf_alloc > 0 ) free\2110 ); X free ( ctx ); X return status; X`7D X/********\0808\1010\2020\400C/ X/* Open bookreader file and initialize context structures. X * Arguments: X *`09fname`09`09Name of bookreader file. X *`09defname`09`09Default file specification, if NULL, will use X *`09`09`09decw$book:.\0B09. X *`09retctx`09`09Address of opaque pointer. X */ Xint bkf_open ( char *fname,\0D07de\0F07void **retctx ) X`7B X rfactx ctx; X bkrdr_recptr currec; X int status, length; X char default_name`5B128`5D; X /* X * Allocate and initialize context structures. X */ X last_open_error = "";`09`09/* clear previous \1F06*/ X *retctx = (void *) 0; X ctx = (rfactx) malloc ( sizeof(struct rfa_context) ); X if ( !ctx ) return 0; X ctx->fab = cc$rms_fab; X ctx->rab = cc$rms_rab; X ctx->xabfhc = cc$rms_\1006; X ctx->network_block_count = 127; X ctx->high_id = 0; X ctx->partcount = 0; X ctx->sectcount = 0; X ctx->superbuf_alloc = 0; X ctx->root = (bkrdr_recptr) 0; X ctx->lrec = (bkrdr_recptr) 0; X ctx->ubuf = (char *) 0; X X ctx->fab.fab$l_fna = fname; X ctx->fab.fab$b_fns = strlen(fname); X if ( defname ) `7B X`09ctx->fab.fab$l_dna = defname; X`09ctx->fab.fab$b_dns = strlen ( defname ); X `7D else `7B X strcpy ( default_name, "DECW$BOOK:.\0B09" ); X ctx->fab.fab$l_dna = default_name; X ctx->fab.fab$b_dns = strlen(default_name); X `7D X ctx->fab.fab$b_shr = FAB$M_SHRGET; X ctx->fab.fab$l_xab = (char *) `26ctx->xabfhc; X ctx->fab.fab$b_rtv = -1;`09`09/* retrieval window size */ X X ctx->xabfhc.xab$l_nxt = (char *) `26\2208itm; X X memset ( `26ctx->xabitm, 0, sizeof(\170B) ); X ctx->xabitm.xab$b_cod = XAB$C_ITM; X ctx->xabitm.xab$b_bln = XAB$K_ITMLEN; X ctx->xabitm.xab$l_itemlist = (char *) `26\2708\1E09; X ctx->xabitm.xab$b_mode = XAB$K_SETMODE; X ctx->xab_itemlist.length = sizeof(ctx->network_block_count); X ctx->xab_itemlist.code = XAB$_NET_BLOCK_COUNT; X ctx->xab_itemlist.bufaddr = `26ctx->network_block_count; X ctx->xab_itemlist.retlen = (long *) 0; X ctx->xab_itemlist.term = 0; X X ctx->rab.rab$l_fab = `26ctx->fab; X ctx->rab.rab$b_rac = RAB$C_RFA; X ctx->rab.rab$l_rop = RAB$M_LOC `7C\0C07RAH; /* locate mode and read-ahead* V/ X ctx->rab.rab$b_mbc = 127;`09`09/* multi-block count */ X /* X * Open file and connect record stream. X */ X status = sys$open ( `26ctx->fab ); X if ( (status`261) == 1 ) `7B X`09if ( ctx->xabfhc.xab$w_lrl == 0 ) `7B X`09 ctx->rab.rab$w_usz = 32767; X`09`7D else `7B X`09 ctx->rab.rab$w_usz =\1506xabfhc.xab$w_lrl; X`09`7D X`09status = sys$connect ( `26ctx->rab ); X`09if ( (status`261) == 0 ) `7B X`09 last_open_error = "Error in SYS$CONNECT call"; X`09 sys$close ( `26ctx->fab ); X`09 free ( ctx ); X`09 ctx = (rfactx) 0; X`09`7D X `7D else `7B X`09last_open_error = "Error in SYS$OPEN call"; X`09free ( ctx ); X`09ctx = (rfactx) 0; X `7D X *retctx = (void *) ctx; X if ( !ctx ) return status; X /* X * The FHC XAB on the open retrieved the longest record length (LRL) of X * the file. Allocate a buffer. X */ X ctx->secmap = (long *) 0; X ctx->ubuf = malloc (\1506rab.rab$w_usz ); X /* X * Read the initial page, this if first record in file so read sequentiall Vy. X */ X status = bkf_read ( (void *) ctx, BKF_NEXT_REC, `26currec, `26length ); X if ( (status`261) == 1 ) `7B X`09ctx->root = duplicate_record ( currec, length ); X`09if ( !ctx->root ) return SS$_INSFMEM; X`09ctx->partcount = ctx->root->first.\1D09; X`09ctx->sectcount = ctx->root->first.sectioncount; X`09/* X`09 * Do sanity checks on root record and read las\1508. X`09 */ X X`09status = bkf_read ( (void *) ctx, `26ctx->root->first.lastptr, X`09`09`26currec, `26length ); X`09if ( (status`261) == 1 ) `7B X`09 ctx->lrec = duplicate_record ( currec, length ); X`09 /* X`09 * Do sanity checks of last record and set page id limit. X`09 */ X`09 ctx->high_id = ((length - 6) / sizeof(ctx->lrec->last.dir`5B1`5D)) - 1; V X`09`7D X `7D X return status; X`7D X/********\0808\1010\2020\400C/ X/* Read RMS record from bookreader file. X */ Xint bkf_read ( void *vctx,`20 X`09struct file_address *rfa, bkrdr_recptr *bufaddr, int *length ) X`7B X int status; X rfactx ctx; X X ctx = (rfactx) vctx; X X if ( rfa ) `7B X`09/* direct read to specified rfa */ X`09ctx->rab.rab$b_rac = RAB$C_RFA; X`09ctx->rab.rab$w_rfa`5B0`5D = rfa->wrd`5B0`5D; X`09ctx->rab.rab$w_rfa`5B1`5D = rfa->wrd`5B1`5D; X`09ctx->rab.rab$w_rfa`5B2`5D = rfa->wrd`5B2`5D; X `7D else `7B X`09/* Read sequentially */ X`09ctx->rab.rab$b_rac = RAB$C_SEQ; X `7D X X ctx->rab.rab$l_ubf = (char *)\1E06ubuf; X status = sys$get ( `26ctx->rab ); X if ( (status`261) ) `7B X`09*bufaddr = (bkrdr_recptr) ctx->rab.rab$l_rbf; X`09*length = ctx->rab.rab$w_rsz; X `7D else `7B X`09*bufaddr = (bkrdr_recptr) ""; X`09*length = 0; X `7D X return status; X`7D X/********\0808\1010\2020\4008/ Xint bkf_read_page ( void *vctx, int id\0806*page_length, X`09bkrdr_recptr *bufaddr, int *length ) X`7B X int status, i; X rfactx ctx; X ctx = (rfactx) vctx; X /* X * Do limit checks on requested ID. X */ X if ( id < 0 `7C`7C id > ctx->high_id ) `7B X`09strcpy ( ctx->last_error, "Bad page number" ); X`09return SS$_BADPARAM; X `7D X /* X * Locate record from directory in the lrec. X */ X *page_length = ctx->lrec->last.dir`5Bid`5D.size; X if ( id == 0 ) `7B X`09/* We already have a copy of the root page, return it */ X`09status = 1; X`09*length = *page_\0F06; X`09*bufaddr = ctx->root; X `7D else `7B X`09/* X`09 * Read initial record. X`09 */ X status = bkf_read ( vctx, `26ctx->lrec->last.dir`5Bid`5D.rfa, bufaddr, V`20 X`09`09length ); X`09if ( (status`261) == 0 ) return \1806; X /* X * If page is larger than requested, assemble into\2506 buffer. X`09 */ X`09if ( *length < *page_\0F07) `7B X`09 /* X`09 * Allocate oversize buffer to accomodate whole thing. X`09 */ X`09 if ( ctx->superbuf_alloc < *page_length ) `7B X`09`09if ( ctx->superbuf_alloc > 0 ) `7B X`09`09 free ( ctx->superbuf ); X`09`09 ctx->superbuf_alloc = 0; X`09`09`7D X`09`09ctx->superbuf = malloc ( *page_length + 15000 ); X`09`09if ( !ctx->superbuf ) return SS$_INSFMEM; X`09`09ctx->superbuf_alloc = *page_length + 15000; X`09 `7D X`09 /* X`09 * Copy peices into superbuf. X`09 */ X`09 memcpy ( ctx->superbuf->raw, (*bufaddr)\1107*length ); X`09 for ( i = *length; i < *page_\120A+\2009 ) `7B X`09`09/* X`09`09 * Last 10 chars of superbuf record should be rfa next \1A06. X`09`09 * Just assume sequential read will do. X`09`09 */ X`09`09status = bkf_read ( vctx, BKF_NEXT_REC, bufaddr, length ); X`09 if ( (status`261) == 0 ) return \1806; X X`09`09if ( ((*bufaddr)->gen.type == BKREC_CONT_END) `7C`7C X`09`09 ((*bufaddr)->gen.type == BKREC_CONT_MID) ) `7B X`09`09 /* X`09`09 * Adjust state to trim tail off of superbuf and header X`09`09 * off of bufaddr. X`09`09 */ X`09`09 i = i - 10; X`09`09 *length =\0A09- 6; X`09`09`7D else `7B X`09`09 break;&0209/* unexpected record type */ X`09`09`7D X`09`09memcpy ( `26ctx->superbuf->raw`5Bi`5D, (*bufaddr)->raw+6, *length ); X`09 `7D X`09 /* X`09 * update values. X`09 */ X`09 *bufaddr = ctx->superbuf; X`09 *length = ctx->superbuf->gen.\1C09*page_\2B06; X`09`7D X `7D X return status; X`7D X/********\0808\1010\2020\400B/ X/* Convert section number to part \0F06. X */ Xint bkf_lookup_section ( void *vctx, int sect_id\0D06*part ) X`7B X int status, i, j, start\0707page, \0606length\0E06_\0D06; X rfactx ctx; X bkrdr_recptr tmp; X ctx = (rfactx) vctx; X X if ( sect_id > ctx->sectcount ) return SS$_BADPARAM; X if ( sect_id < 0 ) return SS$_BADPARAM; X X if ( !ctx->secmap ) `7B`09/* do initial load */ X`09status = bkf_read_page ( vctx, ctx->root->first.index_page, X`09`09`26page_length, `26tmp, `26\0F06 ); X`09if ( (status`261) == 0 ) return \1806; X X`09if ( tmp->gen.type != BKREC_SECMAP ) return SS$_BUGCHECK; X`09i = (length - sizeof(tmp->gen)) /\140Dsecmap.map`5B1`5D); X X`09if ( i-1 != ctx->sectcount ) return SS$_BUGCHECK; X`09/* X`09 * build our own secmap aligned. Negative numbers in map X`09 * are offset to entry for first section on that page. X`09 */ X`09ctx->secmap = (long *) malloc ((i+ctx->partcount+1) * sizeof(long)); X`09if ( !ctx->secmap ) return SS$_INSFMEM; X`09ctx->first_sec = `26ctx->secmap`5Bi`5D;`09/* first sections */ X`09for ( j = 0; j <= ctx->partcount; j++ )\1606first_sec`5Bj`5D = -1; X`09for ( j = 0; j < i; j++ ) `7B X`09 page = tmp->secmap.map`5Bj`5D; X#ifdef DEBUG X`09 printf("/bki/ secmap`5B%d`5D = %d`5Cn", j, page ); X#endif X`09 ctx->secmap`5Bj`5D = page; X`09 if ( page < 0 `7C`7C\0C06> ctx->partcount ) `7B X`09`09printf("secmap`5B%d`5D = %d is out of range`5Cn", j, page ); X`09`09return SS$_BUGCHECK; X`09 `7D else if ( ctx->first_sec`5Bpage`5D < 0 ) `7B X`09`09ctx->first_sec`5Bpage`5D = j;`09/* first section of page */ X`09 `7D X`09`7D X `7D X *part = ctx->secmap`5Bsect_id`5D; X return 1; X`7D X Xint bkf_lookup_first_section ( void *vctx, int sect_id\0D06*part\0B07first ) X`7B X int status, page; X rfactx ctx; X ctx = (rfactx) vctx; X X if ( sect_id > ctx->sectcount ) return SS$_BADPARAM; X if ( sect_id < 0 ) return SS$_BADPARAM; X X if ( !ctx->secmap ) `7B`09/* do initial load */ X X`09status = bkf_lookup_section ( vctx, sect_id, part ); X`09if ( (status`261) == 0 ) return \1806; X `7D X page = ctx->secmap`5Bsect_id`5D; X *first = ctx->first_sec`5Bpage`5D; X *part = page; X return 1; X`7D Xint bkf_lookup_part_section ( void *vctx, int part_id\0D06*first ) X`7B X int status, dummy; X rfactx ctx; X ctx = (rfactx) vctx; X X if ( part_id > ctx->partcount ) return SS$_BADPARAM; X if ( part_id < 0 ) return SS$_BADPARAM; X X if ( !ctx->secmap ) `7B`09/* do initial load */ X X`09status = bkf_lookup_section ( vctx, 1, `26dummy ); X`09if ( (status`261) == 0 ) return \1806; X `7D +-+-+-+-+-+-+-+- END OF PART 2 +-+-+-+-+-+-+-+- ================== RFC 822 Headers ================== Return-Path: VMSSERV@kcl.ac.uk Received: by galaxy.zko.dec.com (UCX V4.0-10B, OpenVMS V6.2 VAX); Mon, 19 Aug 1996 18:16:54 -0400 Received: from newt.kcl.ac.uk by mail11.digital.com (8.7.5/UNX 1.2/1.0/WV) id SAA18820; Mon, 19 Aug 1996 18:03:01 -0400 (EDT) Received: from alder.cc.kcl.ac.uk by newt.kcl.ac.uk with SMTP (PP) id <23290-0@newt.kcl.ac.uk>; Mon, 19 Aug 1996 23:02:50 +0100 Received: by alder.cc.kcl.ac.uk (MX V4.2 AXP) id 731; Mon, 19 Aug 1996 23:03:11 EDT Date: Mon, 19 Aug 1996 23:02:57 BST From: Kings College London File Server To: everhart@star.zko.dec.com Message-ID: <009A71AB.068F7E20.731@alder.cc.kcl.ac.uk> Subject: WEBBOOK.2-OF-5