[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271]
/* * Routines for reading VMS library modules using C fgets semantics. * The lbr_read_directory routine will return index 1 module names over * successive calls. * * int lbr_open ( char *name, char *defname, lbr_index *new ); * int lbr_close ( lbr_index lptr ); * int lbr_set_module ( lbr_index lptr, char *module ); * int lbr_fgets ( char *str, int maxchar, lbr_index lptr ); * int lbr_read_directory ( char *name, int maxchar, lbr_index lptr ); * * Author: David Jones * Date: 7-MAY-1994 * Revised: 10-MAY-1994 Ported to AXP, cleanup up bugs. */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <descrip.h> #include <lbrdef.h> #include <lhidef.h> #include "lbrio.h" /* * Include file doe not define the system routine entry points. */ int LBR$INI_CONTROL(), LBR$OPEN(), LBR$OPEN(), LBR$CLOSE(), LBR$GET_HEADER(); int LBR$LOOKUP_KEY(), LBR$SET_LOCATE(), LBR$GET_RECORD(), LBR$GET_INDEX(); /**************************************************************************/ /* Open help library for access given name and index. * Input: * name Char *. Library name to open. * defname Char *. Default filespec for open (e.g. SYS$HELP:.HLB). * output: * new lbr_index *. Receives pointer to control structure for * library access. * Return value: * Value returned in VMS condition value (odd == success). */ int lbr_open ( char *name, char *defname, lbr_index *new ) { int status, func, type; lbr_index lptr; $DESCRIPTOR (fns,""); $DESCRIPTOR (dns,"sys$help:*.hlb"); /* * Allocate control block and zero it. */ lptr = (lbr_index) malloc ( sizeof(struct lbr_control) ); *new = lptr; if ( !lptr ) return 12; lptr->index = (void *) 0; lptr->rfa[0] = lptr->rfa[1] = 0; lptr->dir_alloc = 0; /* * Initialize control index. Put constants in variables so we * can properly pass the arguments by reference. */ func = LBR$C_READ; type = LBR$C_TYP_UNK; status = LBR$INI_CONTROL ( &lptr->index, &func, &type ); #ifdef DEBUG if ( (status&1)==0) printf("init_control status: %d %d\n", status,lptr->index ); #endif if ( (status&1) == 0 ) { free ( lptr ); return status; } /* * Open the library. */ fns.dsc$w_length = strlen(name); fns.dsc$a_pointer = name; dns.dsc$w_length = strlen(defname); dns.dsc$a_pointer = defname; status = LBR$OPEN ( &lptr->index, &fns, 0, &dns, 0, 0, 0 ); #ifdef DEBUG printf("status of lbr open: %d, index=%d\n", status, lptr->index ); #endif /* * Use locate mode to read records (high performance). */ if ( (status&1) == 0 ) free ( lptr ); else { status = LBR$SET_LOCATE ( &lptr->index ); if ( (status&1) == 0 ) free ( lptr ); } return status; } /**************************************************************************/ /* Close library openned by lbr_open. Free allocated memory. */ int lbr_close ( lbr_index lptr ) { int status; if ( !lptr ) return 12; /* bad pointer */ status = LBR$CLOSE ( &lptr->index ); if ( lptr->dir_alloc > 0 ) free ( lptr->dir_names ); free ( lptr ); return status; } /**************************************************************************/ /* Lookup module key in library and save RFA address. This routine * must be called prior to lbr_fgets. * * input: * lptr lbr_index. Pointer returned by lbr_open. * module char *. Module name to read. * * Return value: * VMS condition code returned by LBR$LOOKUP_KEY(). */ int lbr_set_module ( lbr_index lptr, char *module ) { int status, one, LBR$SET_INDEX(); $DESCRIPTOR ( key, "" ); lptr->used = 0; lptr->cur_length = 0; key.dsc$w_length = strlen ( module ); key.dsc$a_pointer = module; status = LBR$LOOKUP_KEY ( &lptr->index, &key, &lptr->rfa ); #ifdef DEBUG printf("Status of module %s lookup: %d %d\n", module, status, lptr->rfa); #endif return status; } /**************************************************************************/ /* Read record from library. Emulate fgets call, append linefeed to each * record. Note that function value is a VMS status, not a character pointer * however. * * input: * maxchar int. Length of str output array. * lptr lbr_index. Pointer returned by lbr_open; * output: * str Char *. Buffer to receive record read. * Return value: * VMS condition code returned by LBR$GET_RECORD(). */ int lbr_fgets ( char *str, int maxchar, lbr_index lptr ) { int status, length; struct dsc$descriptor cur_rec; length = lptr->cur_length - lptr->used; if ( length <= 0 ) { /* * Get next record. */ status = LBR$GET_RECORD ( &lptr->index, 0, &cur_rec ); if ( (status&1) == 0 ) { *str = 0; lptr->cur_length = 0; return status; } length = cur_rec.dsc$w_length; lptr->cur_length = length + 1; /* implied line feed */ lptr->cur_rec = cur_rec.dsc$a_pointer; lptr->used = 0; } else if ( length == 1 ) { /* * Only implied linefeed left in buffer. */ if ( maxchar > 1 ) *str++ = '\n'; *str = '\0'; lptr->used = lptr->cur_length; return 1; } else { /* * Set cur_rec. */ cur_rec.dsc$w_length = length - 1; cur_rec.dsc$a_pointer = &lptr->cur_rec[lptr->used]; length = cur_rec.dsc$w_length; } /* * Copy to user buffer. */ if ( length >= maxchar ) length = maxchar - 1; memcpy ( str, cur_rec.dsc$a_pointer, length ); if ( length < (maxchar - 1) ) str[length++] = '\n'; lptr->used += length; str[length++] = 0; #ifdef DEBUG printf("status of get_record: %d, length: %d '%s", status, lptr->cur_length, str ); #endif return status; } /**************************************************************************/ /* Internal routine for getting library module directory with LBR$GET_INDEX. * A bizarre oversight in LBR$GET_INDEX's design means we have to use * a module-wide variable (load_tmp) to pass context information to this * routine. */ static lbr_index load_tmp; static int lbr_fill_dir ( struct dsc$descriptor *name, long *rfa, lbr_index tptr ) { int length; lbr_index lptr; lptr = load_tmp; length = name->dsc$w_length; while ( length + lptr->dir_size + 1 >= lptr->dir_alloc ) { #ifdef DEBUG printf("Reallocating directory\n"); #endif lptr->dir_names = realloc ( lptr->dir_names, (lptr->dir_alloc+length+1)*2 ); lptr->dir_alloc *= 2; } memcpy ( &lptr->dir_names[lptr->dir_size], name->dsc$a_pointer, length ); lptr->dir_names[lptr->dir_size+length] = '\0'; lptr->dir_size += length + 1; return 1; } /**************************************************************************/ /* Return next module name in libraries directory. * * input: * maxchar Int. Size of output name array. * lptr lbr_index. Pointer returned by lbr_open(). * output: * name char *. Module name. * return value: * VMS condition code returned by LBR$GET_INDEX(). */ int lbr_read_directory ( char *name, int maxchar, lbr_index lptr ) { int status, count, inum, length; /* * Initialize. */ if ( lptr->dir_alloc <= 0 ) { struct lhidef header; status = LBR$GET_HEADER ( &lptr->index, &header ); count = header.lhi$l_modcnt; lptr->dir_alloc = count * 20; lptr->dir_size = lptr->dir_pos = 0; lptr->dir_names = malloc ( lptr->dir_alloc ); load_tmp = lptr; /* bogus */ inum = 1; status = LBR$GET_INDEX ( &lptr->index, &inum, lbr_fill_dir, lptr ); } else status = 1; if ( lptr->dir_pos >= lptr->dir_size ) return 2160; length = strlen ( &lptr->dir_names[lptr->dir_pos] ); if ( length < maxchar ) { strcpy ( name, &lptr->dir_names[lptr->dir_pos] ); } else { strncpy ( name, &lptr->dir_names[lptr->dir_pos], maxchar-1 ); name[maxchar-1] = '\0'; } #ifdef DEBUG printf("read dir pos: %d, name: '%s'\n", lptr->dir_pos, name ); #endif lptr->dir_pos += length + 1; return status; }