/* #define COMPILE_MAIN */ /* * Library I/O routines for Vax-11 C * * Martin Minow * * This software is in the public-domain. * * Restrictions: * We only know about text libraries. * Only one library may be manipulated at at time. * Little attention was paid to performance. */ #ifdef COMPILE_MAIN #define TESTING #endif #include #include #define EOS 0 /* * Define vms specific structures and definitions: * descrip String descriptors * rms File system * ssdef Return status codes */ #include rms #include descrip #include ssdef /* * Home made library definitions */ #include "lbrdef.h" /* * Library status values */ globalvalue LBR$_NORMAL; /* Normal return */ /* * The following functions are defined/used * * int * lbr_update(filename) -- initialize existing file for update * char *filename; -- file name to open * Opens an existing file for update. Returns SS$_NORMAL if ok, * else the error code. * * int * lbr_create(filename, keylen, nindexes) * char *filename; * int keylen; -- maximum key length * int nindex; -- number of library indexes * Open the library for update. Create it if it wasn't found. * Return SS$_NORMAL if ok, else a vms error code. * * int * lbr_open(filename) -- initialize for read only * char *filename; * Open an existing library for input. Return SS$_NORMAL * if opened ok, else a vms error code. * * int * lbr_close() * Close the library. Returns the VMS error code. * * int * lbr_lookup(key) * char *key; * Setup to read the data associated with a key. * Return SS$_NORMAL if ok, else a vms error code. * * int * lbr_read(buffer, bufferlen) * char *buffer; * int bufferlen; * Read a record from the library -- after calling lbr_lookup. * Returns the number of bytes read for each record, or EOF * when at "end of data". * * int * lbr_write(buffer, bufferlen, command) * char *buffer; -- Data buffer or key. * int bufferlen; -- Length if data buffer. * int command; -- Request type: * 0 New entry, buffer has the key. * 1 A record to be stored under this key. * 2 Terminate input for this key. * 3 An additional key for the record just entered. * Returns SS$_NORMAL if ok. Exits to the operating system * if your calls are in the wrong order. */ typedef struct rfa { long rfa[2]; } RFA; /* * Static database for library interface */ static int lbr_index; /* VMS routines need this */ static struct lbr$credef lbr_options; /* Create options */ typedef struct dsc$descriptor_s STRING; /* VMS string descriptor */ int lbr_update(filename) char *filename; /* * Initialize an existing file for update. */ { register int errorcode; int function; int type_text; STRING string; descrip(filename, -1, &string); function = LBR$C_UPDATE; type_text = LBR$C_TYP_TXT; if (((errorcode = lbr$ini_control( &lbr_index, /* For other references */ &function, /* Assume it's there */ &type_text, /* Text library */ NULL)) /* No name block */ == LBR$_NORMAL) && ((errorcode = lbr$open( &lbr_index, /* Library index */ &string, /* File name descriptor */ &lbr_options, /* Options array */ NULL, /* No default filename */ NULL, /* No NAM block */ NULL, /* No result file name */ NULL)) /* No result file len */ == LBR$_NORMAL)) { return (SS$_NORMAL); /* Gotcha */ } #ifdef TESTING message(errorcode, "Opening for update"); #endif return (errorcode); } int lbr_create(filename, keylen, nindex) char *filename; int keylen; int nindex; { register int errorcode; int function; int type_text; STRING string; if (lbr_update(filename) == SS$_NORMAL) return (SS$_NORMAL); /* * Couldn't open the file for update. Try to create it. */ descrip(filename, -1, &string); lbr_options.cre$l_type = LBR$C_TYP_TXT; lbr_options.cre$l_keylen = keylen; /* max key length */ lbr_options.cre$l_alloc = 100; /* initial allocation */ lbr_options.cre$l_idxmax = nindex; /* number of indices */ lbr_options.cre$l_uhdmax = 0; /* extra module header */ lbr_options.cre$l_entall = 0; /* Index to preallocate */ function = LBR$C_CREATE; type_text = LBR$C_TYP_TXT; if (((errorcode = lbr$ini_control( &lbr_index, /* For other references */ &function, /* Create a new library */ &type_text, /* Text library */ NULL)) /* No name block */ == LBR$_NORMAL) && ((errorcode = lbr$open( &lbr_index, /* Library index */ &string, /* File name descriptor */ &lbr_options, /* Create options array */ NULL, /* No default filename */ NULL, /* No NAM block */ NULL, /* No result file name */ NULL)) /* No result file len */ == LBR$_NORMAL) && (errorcode = lbr_close()) == SS$_NORMAL && (errorcode = lbr_update(filename)) == SS$_NORMAL) { return (SS$_NORMAL); /* Gotcha */ } #ifdef TESTING message(errorcode, "Can't create library %s", filename); #endif return (errorcode); } int lbr_open(filename) char *filename; /* * Open an existing library */ { register int errorcode; int function; int type_text; STRING string; descrip(filename, -1, &string); function = LBR$C_READ; type_text = LBR$C_TYP_TXT; if (((errorcode = lbr$ini_control( &lbr_index, /* For other references */ &function, /* Assume it's there */ &type_text, /* Text library */ NULL)) /* No name block */ == LBR$_NORMAL) && ((errorcode = lbr$open( &lbr_index, /* Library index */ &string, /* File name descriptor */ NULL, /* No options array */ NULL, /* No default filename */ NULL, /* No NAM block */ NULL, /* No result file name */ NULL)) /* No result file len */ == LBR$_NORMAL)) { return (SS$_NORMAL); /* Gotcha */ } #ifdef TESTING message(errorcode, "Opening library %s", filename); #endif return (errorcode); } int lbr_close() /* * Close the library */ { register int errorcode; if ((errorcode = lbr$close(&lbr_index)) == LBR$_NORMAL) return (SS$_NORMAL); else { #ifdef TESTING message(errorcode, "Closing library", NULL); #endif return (errorcode); } } int lbr_lookup(key) char *key; /* * Setup to read data associated with a key. */ { register int errorcode; RFA textrfa; /* Actaully unused */ STRING string; descrip(key, -1, &string); if (((errorcode = lbr$lookup_key(&lbr_index, &string, /* Key descriptor */ &textrfa)) /* Store rfa here */ & 01) != 0) { return (SS$_NORMAL); } else { #ifdef TESTING message(errorcode, "Looking up key \"%s\"", key); #endif return (errorcode); } } int lbr_read(buffer, bufflen) char *buffer; int bufflen; /* * Read a record. return actual record length or EOF. */ { register int errorcode; struct dsc$descriptor_s bufdes = { bufflen, /* dsc$w_length = strlen(text) */ DSC$K_DTYPE_T, /* Text type */ DSC$K_CLASS_S, /* String */ buffer, /* dsc$a_pointer -> text */ }; struct dsc$descriptor_s outbufdes = { 0, /* dsc$w_length = strlen(text) */ DSC$K_DTYPE_T, /* Text type */ DSC$K_CLASS_S, /* String */ NULL, /* dsc$a_pointer -> text */ }; if (((errorcode = lbr$get_record(&lbr_index, &bufdes, /* Where to store data */ &outbufdes)) /* Gets actual datum length */ & 01) != 0) { return (outbufdes.dsc$w_length); } else if (errorcode == RMS$_EOF) return (EOF); else { #ifdef TESTING message(errorcode, "unexpected error reading text", NULL); #endif return (EOF); } } int lbr_write(buffer, bufflen, command) char *buffer; int bufflen; int command; /* * Manage update/replace of a module. * Calling sequence: * lbr_write("module", 0, 0); -- setup to enter "module" * while (more_data) -- write all data * lbr_write(datum, strlen(datum), 1); * lbr_write(NULL, 0, 2); -- terminate. * while (more_alises_for_this_module) * lbr_write(alies, 0, 3); -- write other names */ { register int errorcode; struct dsc$descriptor_s bufdes = { bufflen, /* Actual data length */ DSC$K_DTYPE_T, /* Text type */ DSC$K_CLASS_S, /* String datum */ buffer, /* Datum location */ }; /* * The following static database maintains communication between * calls of lbr_write. */ #define INIT_STATE 0 #define ENTER_STATE 1 #define END_STATE 2 static int state = INIT_STATE; int replacing; int first; static RFA old_module_rfa; static RFA new_module_rfa; static RFA first_record_rfa; static struct dsc$descriptor_s module_name = { 0, /* Actual data length */ DSC$K_DTYPE_T, /* Text type */ DSC$K_CLASS_S, /* String datum */ NULL, /* Datum location */ }; switch (command) { case 0: /* Initialize */ if (state == ENTER_STATE) { fprintf(stderr, "Bug calling lbr_write:"); fprintf(stderr, " you must terminate previous"); fprintf(stderr, " entry before entering a new module\n"); fprintf(stderr, "old library key is \"%s\",", module_name.dsc$a_pointer); fprintf(stderr, " new key is \"%s\"\n", buffer); exit(SS$_BADPARAM); } module_name.dsc$a_pointer = malloc(strlen(buffer) + 1); strcpy(module_name.dsc$a_pointer, buffer); module_name.dsc$w_length = strlen(buffer); replacing = lbr$lookup_key(&lbr_index, &module_name, /* Key to search for */ &old_module_rfa); /* Old module for deletion */ state = ENTER_STATE; first = TRUE; return (SS$_NORMAL); /* Always successful */ case 1: /* Put a record */ if (state != ENTER_STATE) { fprintf(stderr, "Bug -- lbr_write calls out of order\n"); exit(SS$_BADPARAM); } if ((errorcode = lbr$put_record(&lbr_index, &bufdes, &new_module_rfa)) & 01) { if (first) { first_record_rfa = new_module_rfa; first = FALSE; } return (SS$_NORMAL); } else { #ifdef TESTING message(errorcode, "putting a module record", NULL); #endif return (errorcode); } case 2: if (state != ENTER_STATE) { fprintf(stderr, "Bug: lbr_write calls out of order.\n"); exit(SS$_BADPARAM); } if (((errorcode = lbr$put_end(&lbr_index)) & 01) != 0 && ((errorcode = lbr$replace_key(&lbr_index, &module_name, &old_module_rfa, &new_module_rfa)) & 01) != 0 && ((replacing & 01) == 0 || ((errorcode = lbr$delete_data(&lbr_index, &old_module_rfa)) & 01) != 0)) { free(module_name.dsc$a_pointer); module_name.dsc$a_pointer = NULL; state = END_STATE; return (SS$_NORMAL); } else { #ifdef TESTING message(errorcode, "cleanup after write of \"%s\"", module_name.dsc$a_pointer); #endif return (errorcode); } case 3: if (state != END_STATE) { fprintf(stderr, "Bug: lbr_write calls out of order\n"); exit(SS$_BADPARAM); } descrip(buffer, -1, &bufdes); replacing = lbr$lookup_key(&lbr_index, &bufdes, &old_module_rfa); if (replacing & 01) { if (((errorcode = lbr$delete_data(&lbr_index, &old_module_rfa)) & 01) == 0) { #ifdef TESTING message(errorcode, "delete_data for \"%s\"", buffer); #endif return (errorcode); } if (((errorcode = lbr$delete_key(&lbr_index, &bufdes)) & 01) == 0) { #ifdef TESTING message(errorcode, "delete_key for \"%s\"", buffer); #endif return (errorcode); } } if (((errorcode = lbr$insert_key(&lbr_index, &bufdes, &first_record_rfa)) & 01) == 0) { #ifdef TESTING message(errorcode, "alternate key \"%s\"\n", buffer); #endif return (errorcode); } return (SS$_NORMAL); } } static descrip(text, len, stringp) char *text; int len; STRING *stringp; /* * Load string descriptor */ { if (len == -1) len = strlen(text); stringp->dsc$a_pointer = text; stringp->dsc$w_length = len; stringp->dsc$b_dtype = DSC$K_DTYPE_T; stringp->dsc$b_class = DSC$K_CLASS_S; } static message(errorcode, why, arg) int errorcode; char *why; char *arg; /* * Print error message */ { extern char *vms_etext(); if (why == NULL) { fprintf(stderr, "\n%s\n", vms_etext(errorcode)); } else if (arg == NULL) { fprintf(stderr, "\n%s: %s\n", why, vms_etext(errorcode)); } else { fprintf(stderr, "\n"); fprintf(stderr, why, arg); fprintf(stderr, ": %s\n", vms_etext(errorcode)); } } #ifdef COMPILE_MAIN char line[514]; char filename[514]; main() { register int readcount; while (prompt("Library file name")) { strcpy(filename, line); read_module(); enter_module(); } } read_module() { register int readcount; lbr_open(filename); fprintf(stderr, "open, index = %d\n", lbr_index); while (prompt("Module name")) { if (lbr_lookup(line) == SS$_NORMAL) { while ((readcount = lbr_read(line, sizeof line)) >= 0) { line[readcount] = EOS; fprintf(stderr, "%6d\t%s\n", readcount, line); } } else fprintf(stderr, "Couldn't find \"%s\"\n", line); } lbr_close(); } enter_module() { lbr_create(filename, 32, 1); fprintf(stderr, "open for update, index = %d\n", lbr_index); while (prompt("Module name to enter")) { if (lbr_lookup(line) == SS$_NORMAL) fprintf(stderr, "Warning, \"%s\" in library\n", line); if (lbr_write(line, 0, 0) != SS$_NORMAL) fprintf(stderr, "Entry failed\n"); else { while (prompt("data")) { if (lbr_write(line, strlen(line), 1) != SS$_NORMAL) fprintf(stderr, "Error entering data\n"); } if (lbr_write(NULL, 0, 2) != SS$_NORMAL) fprintf(stderr, "Error closing entry\n"); while (prompt("Additional module names")) { if (lbr_write(line, 0, 3) != SS$_NORMAL) fprintf(stderr, "Error entering additional name\n"); } } } lbr_close(); } prompt(text) char *text; { clearerr(stdin); fprintf(stderr, "%s: ", text); fflush(stdin); if (gets(line) == NULL || line[0] == EOS) return (FALSE); return (TRUE); } #endif