/******************************************************************************/ /* File : pr_load.c */ /* Schema : olc96fa.sch */ /* Chgen Version : v10 */ /******************************************************************************/ #include #include #ifdef __STDC__ #include #endif #include "olc96fa.h" int SMbtidx; int ACbtidx; int STbtidx; int AIbtidx; int TRbtidx; int ETbtidx; int ENbtidx; int EIbtidx; int TFbtidx; int TIbtidx; int CKbtidx; int open_file; /************************************************************/ /* This routine is similar to strcpy, except that it pads the result string */ /* with blanks (if the unpad flag is 0) out to the length specified by n. */ /* If the unpad flag is 1, then trailing blanks are removed (even any that */ /* were in the original string). */ /************************************************************/ void mystrcpy(s,t,n,unpad) char *s,*t; int n,unpad; { int i; char *s2; s2 = s; while ((*t != '\0') && (n>0)) { *s++ = *t++; n--; } for (s; n>0; n--) *s++ = ' '; *s = '\0'; s = s2; if (unpad) for (i=strlen(s)-1; (i>=0) && ((s[i] == ' ') || (s[i] == 9)); i--) s[i] = '\0'; } /*********************************************************/ /** This function is identical to the system routine **/ /** strncpy, except that it null terminates the string **/ /*********************************************************/ void strncpy_null(a,b,n) char a[]; char b[]; int n; { strncpy(a,b,n); a[n] = '\0'; return; } /******************************************************************************/ /* This routine sets a region of memory to 0 (zero). The 'standard' routine */ /* memset() could be used, but apparently, it is not supplied with some */ /* UNIX systems. */ /******************************************************************************/ void clear_mem(s,n) char *s; int n; { for (; n>0; n--) *s++ = '\0'; } /******************************************************************************/ /* This function searches the hcg_table_seq_list for the specified table */ /* abbrev (which is assumed to be the first 2 chars of the pkey param). */ /* If successful, the global hcg_tbl_idx is set to its idx, and 1 is */ /* returned. Otherwise, the hcg_tbl_idx is set to 0, and 0 is returned. */ /* This search is optimized using a form of caching. If the hcg_tbl_idx */ /* already points to the correct table, the search is avoided. */ /******************************************************************************/ int find_tbl_idx(pkey) char *pkey; { if (strncmp(pkey,hcg_table_seq_list[hcg_tbl_idx].ttabbrev,HCG_ABBR_SIZE) == 0) return(1); for (hcg_tbl_idx=0; hcg_tbl_idx < HCG_NUM_TABLES; hcg_tbl_idx++) if (strncmp(pkey,hcg_table_seq_list[hcg_tbl_idx].ttabbrev,HCG_ABBR_SIZE) == 0) return(1); hcg_tbl_idx = 0; return(0); } /******************************************************************************/ /* This function is almost identical to find_tbl_idx, except that it searches */ /* the hcg_view_list for the specified view-name, and the hcg_view_idx is */ /* used. In this case, viewnames are not restricted to any fixed length, */ /* so a regular strcmp() is used. */ /******************************************************************************/ int find_view_idx(viewname) char *viewname; { if (strcmp(viewname,hcg_view_list.view_list[hcg_view_idx].view_name) == 0) return(1); for (hcg_view_idx=0; hcg_view_idx < hcg_view_list.num_views; hcg_view_idx++) if (strcmp(viewname,hcg_view_list.view_list[hcg_view_idx].view_name) == 0) return(1); hcg_view_idx = 0; return(0); } /******************************************************************************/ /* This routine will extract a version number and row_number out of the */ /* specified key value. The results are stored in the globals hcg_version */ /* and hcg_row. */ /******************************************************************************/ /* This function will determine if the specified key value meets the */ /* proper version for that table in the specified view idx. */ /******************************************************************************/ int meets_view(tbl_idx,view_idx,pkey) int tbl_idx; int view_idx; hcg_key pkey; { return(1); } /******************************************************************************/ /* This routine simply prints a warning when a duplicate row is added to */ /* a table. While it may seem this would be better as a macro, it is used */ /* as a routine instead, to help minimize macro expansion. */ /******************************************************************************/ void dup_row_warning(pkey) hcg_key pkey; { char temp_key[HCG_KEY_SIZE+1]; if(decode(temp_key, &pkey) != 1) printf("Error: pkey %u is an ivalid key!\n",pkey); else printf("Warning: duplicate row (%s) encountered in pr_add, ignored.\n",temp_key); } /******************************************************************************/ /* Same as dup_row_warning, but a different error concept. */ /******************************************************************************/ void forward_ref_warning(pkey,fkey) hcg_key pkey, fkey; { char temp_pkey[HCG_KEY_SIZE+1], temp_fkey[HCG_KEY_SIZE+1]; if(decode(temp_pkey, &pkey) != 1) printf("Error: Invalid pkey %u !\n",pkey); if(decode(temp_fkey, &fkey) != 1) printf("Error: Invalid fkey %u !\n",fkey); printf("Warning: Record %s references a parent record %s that is not yet loaded (ie, forward reference)\n",temp_pkey,temp_fkey); } /******************************************************************************/ /* This routine is used by the various file read routines. It flushes the */ /* read buffer, reads the next line of the file, and then converts any */ /* control characters in the buffer into spaces (for example, newline). */ /******************************************************************************/ void hcg_read_next() { int i; clear_mem(hcg_buffer,BUFSIZE); fgets(hcg_buffer,BUFSIZE,hcg_ascii_fp); for (i = 0; hcg_buffer[i] != '\0'; i++) if (hcg_buffer[i] < ' ') hcg_buffer[i] = ' '; } /******************************************************************************/ /* This routine is used to parse the next word (w) out of the specified string*/ /* buffer(s). The parameter idx serves two purposes. On the way in, it */ /* marks the starting point in the string for the parse. From here, white- */ /* space is skipped. Once a word has begun, it is considered finished when */ /* more whitespace is encountered, or end of string. Finally, idx is moved */ /* along to the start of the next word. It is up to the caller to initially */ /* set idx = 0. This routine is also useful for any parsing project. */ /******************************************************************************/ void hcg_parse(s,w,idx) char *s; char *w; int *idx; { int i; i = 0; while ( (s[*idx] == ' ') || (s[*idx] == '\t') || (s[*idx] == '\n')) (*idx)++; while ( (s[*idx] != ' ') && (s[*idx] != '\t') && (s[*idx] != '\0') && (s[*idx] != '\n')) { w[i++] = s[*idx]; (*idx)++; } w[i] = '\0'; while ( (s[*idx] == ' ') || (s[*idx] == '\t') || (s[*idx] == '\n')) (*idx)++; } /******************************************************************************/ /* This routine is used to update the embedded version number of a key field. */ /* If the new version flag indicates a new version should be generated, and */ /* the mode of the view is 'w' (write), and the table corresponding to the */ /* key in question (since it may be a foreign key) is in the view, then a */ /* version update will actually occur. The version is updated to 'one higher'*/ /* than the highest version found for the base table in question (specified */ /* by tbl_idx). */ /******************************************************************************/ void hcg_update_version(pkey, tbl_idx, new_version) hcg_key *pkey; int tbl_idx; int new_version; { if ((new_version) && (hcg_view_list.view_list[hcg_view_idx].mode == 'w') ) { if(set_version(pkey, hcg_table_seq_list[tbl_idx].maxver +1) != 1) printf("Error: Can not set version of pkey %u to %d\n", *pkey, hcg_table_seq_list[tbl_idx].maxver + 1); } } ; /*----------------------------------------------------------- * * Source File : lut.c * * This file contains code for look up table * and binary tree mainipulations used by chgen and gen * developed for spring 1993 project... *----------------------------------------------------------- */ #ifndef HCG_KEY_SIZE /* used to determine context of lut */ /* code use so that includes are not*/ /* multiply defined */ #include #include #include #include "lut.h" #endif char *lut_get_name(); /* ************************************************************ * Function : is_string_null * * Abstract : function to determine if string is NULL... * * Created by : T. Cunningham * * Creation Date : 4/14/93 * * Modified : * ************************************************************ */ bool is_string_null(p_string) char *p_string; { /* local variables */ /**************************************/ if(*p_string == '\0') { return(TRUE); } return(FALSE); } /* end is_string_null */ /* ************************************************************ * Function : lut_display * * Abstract : Function to display look up table... * * Created by : T. Cunningham * * Creation Date : 4/14/93 * * Modified : * ************************************************************ */ int lut_display(p_lut, max_num) lut_st *p_lut; int max_num; { /* local variables */ int idx; char *p_str; /**************************************/ printf("\nLook Up Table Output \n"); printf( "---- -- ----- ------\n\n"); for(idx=0; idxtype = type; p_lut->p_btree_root = NULL; p_lut->num_elements = 0; for(idx=0; idxnames[idx]; *p_ch = '\0'; } return(0); } /* end lut_init */ /* ************************************************************ * Function : lut_insert_element * * Abstract : Function to insert an element into a look up table. * * Created by : T. Cunnigham * * Creation Date : 4/13/92 * * Modified : * ************************************************************ */ int lut_insert_element(p_lut, name) lut_st *p_lut; /* ptr to lut */ char name[]; /* string of element to insert */ { /* local variables */ int abbr_size, test, idx, loop, len; /**************************************/ len = strlen(name); switch(p_lut->type) { case ABBR_TBL_TYPE : if( (len != ABBR_SIZE_BIG) && (len != ABBR_SIZE_SMALL)) { printf("%s : Input character string != required abbreviation size...\n", name); return(ERROR); } else { /*************************************/ /* check if abbrv is AAA thru ZZZ */ /*************************************/ for(idx=0; idx < len; idx++) { if((name[idx] > 'Z') || (name[idx] < 'A') ) { printf("%s : Invalid abbreviation passed to insert funct...\n", name); return(ERROR); } } } break; case VER_TBL_TYPE : if(len != VER_SIZE) { printf("Input character string != required version size...\n"); return(ERROR); } else { /****************************************************/ /* check if version is between 0 and MAX_VER_NUMBER */ /****************************************************/ test = atoi(name); if((test < 0) || (test > MAX_VER_NUMBER)) { printf("%s : Invalid version number passed to insert funct. \n", name); return(ERROR); } /*************************************/ /* check to see if there are already */ /* MAX_VER_ELEMENTS in the table... */ /*************************************/ if(p_lut->num_elements >= MAX_VER_ELEMENTS) { printf("Version look up table already full...\n"); printf("Only allowed to have %d indexes...\n", MAX_VER_ELEMENTS); return(ERROR); } } break; default : printf("%s : Unknown table type input to lut_insert_element routine...\n",name); return(ERROR); break; } /**************************************/ /* check btree to see if abbrv exists */ /* if exists do not add to table */ /**************************************/ if((test = btree_does_node_exist(p_lut->p_btree_root, name)) != ERROR) { return(test); } /*************************************/ /* find next available slot in table */ /*************************************/ idx = 0; loop = TRUE; while(idx < LUT_NUM_ELEMENTS) { if(is_string_null(p_lut->names[idx])) { strcpy((char *) p_lut->names[idx], name); p_lut->num_elements++; btree_insert_node(&p_lut->p_btree_root, name, idx); return(idx); } idx++; } /* end while */ printf("No slots available for element insertion...\n"); return(ERROR); } /* end lut_insert_element */ /* ************************************************************ * Function : lut_delete_element * * Abstract : Function to delete an entry in the look up table. * * Created by : T. Cunningham * * Creation Date : 4/13/93 * * Modified : * ************************************************************ */ int lut_delete_element(p_lut, index) lut_st *p_lut; int index; { /* local variables */ int idx; char *p_ch; /**************************************/ if(index > LUT_NUM_ELEMENTS) { printf("ERROR - Requested index > look up table size...\n"); return(ERROR); } if(is_string_null(p_lut->names[index])) { printf("ERROR - Requested index to delete does not exist...\n"); return(ERROR); } printf("Deleting lut element # %d\n", index); p_ch = (char *) p_lut->names[index]; *p_ch = '\0'; p_lut->num_elements--; /* decrement number of elements in lut */ printf("Destroying binary tree\n"); btree_destroy(p_lut->p_btree_root, (btree_node_st *)NULL); printf("Recreating binary tree\n"); p_lut->p_btree_root = NULL; btree_create(p_lut); return(0); } /* end lut_delete_element */ /* ************************************************************ * Function : lut_does_node_exist * * Abstract : Function to accept a character string * and return the index of that array in the * look up table. * Return a ERROR if the string does not exist * in the table... * * Created by : T. Cunningham * * Creation Date : 5/6/93 * * Modified : * ********************************************************** int lut_does_node_exist(p_lut, name) lut_st *p_lut; char name[]; { int ret_stat; if(p_lut == NULL) { printf("Null ptr passed as lut address...\n"); return(ERROR); } ret_stat = btree_does_node_exist(p_lut->p_btree_root, name); return(ret_stat); } /* end lut_does_node_exist */ /* ************************************************************ * Function : lut_get_name * * Abstract : Function to accept an index number and return * the abbreviation name corresponding to the * index number... * * returns a character pointer. * * Created by : T. Cunningham * * Creation Date : 4/13/92 * * Modified : * ************************************************************ */ char *lut_get_name(p_lut, index) lut_st *p_lut; int index; { /* local variables */ char *p_ch; /**************************************/ if(index <= LUT_NUM_ELEMENTS) { if(is_string_null(p_lut->names[index])) { return(NULL); } else { return((char *)p_lut->names[index]); } } else { printf("Invalid index input to lut_get_name...\n"); return(NULL); } } /* end lut_get_name */ /* ************************************************************ * Function : abbr_lut_create * * Abstract : Function to create a lut from an array of * strings... * Returns ERROR if failure occurred or * returns (0) if successful.... * * Created by : T. Cunningham * * Creation Date : 5/2/93 * * Modified : * ************************************************************ */ int abbr_lut_create(p_lut, p_abbr, num_strings) lut_st *p_lut; char *p_abbr[]; int num_strings; { int ret_stat, idx; lut_init(p_lut, ABBR_TBL_TYPE); /* build the lut table and btree */ for(idx=0; idxname, p_node->num, p_node->weight); btree_print_node(p_node->p_left); btree_print_node(p_node->p_right); return(0); } /* end btree_print_node */ /* *********************************************************** * Function : btree_display_nodes * * Abstract : Function to traverse the btree and print out * each node in a depth first fashion. * * Created by : T. Cunningham * * Creation Date : 4/14/93 * * Modified : * ************************************************************ */ int btree_display_nodes(p_root) btree_node_st *p_root; { /* local variables */ /**************************************/ printf("\n\nAbbreviation Index Weight - Binary Tree Output\n"); printf( "------------ ----- ------\n\n"); btree_print_node(p_root); return(0); } /* end btree_display_nodes */ /* *********************************************************** * Function : btree_does_node_exist * * Abstract : Function to determine if abbreviation exists * in the lut binary tree. * * returns : index number of abbreviation * or ERROR if it does not exist. * * Created by : T. Cunningham * * Creation Date : 4/14/93 * * Modified : * ************************************************************ */ int btree_does_node_exist(p_node, name) btree_node_st *p_node; char name[]; { /* local variables */ int test, ret_stat; /**************************************/ if(p_node == NULL) { return(ERROR); } if( (test = strcmp(p_node->name, name)) == 0) { return(p_node->num); } ret_stat = btree_does_node_exist(p_node->p_left, name); if(ret_stat >= 0) { return(ret_stat); } ret_stat = btree_does_node_exist(p_node->p_right, name); if(ret_stat >= 0) { return(ret_stat); } else { return(ERROR); } } /* end btree_does_node_exist */ /* ************************************************************ * Function : btree_insert_node * * Abstract : Function to insert a node into an existing btree, * or if btree does not exist create a new one and * insert the node as the root. * * Created by : T. Cunningham * * Creation Date : 4/14/93 * * Modified : * ************************************************************ */ int btree_insert_node(p_new, abbr, index) btree_node_st **p_new; char abbr[]; int index; { /* local variables */ int test, loop = TRUE; /**************************************/ btree_node_st *p_temp, *p_node; /**************************************************/ /* first check if btree exists - if not create it */ /**************************************************/ if(*p_new == NULL) { p_node = (btree_node_st *) calloc(sizeof(btree_node_st), 1); strcpy(p_node->name, abbr); p_node->num = index; p_node->weight = 2; p_node->p_right = NULL; p_node->p_left = NULL; *p_new = p_node; return(0); } /* insert into existing binary tree */ p_temp = *p_new; /*******************************************/ /* check out if abbreviation already exists */ /* if so return the index of the abbrev */ /********************************************/ test = strcmp(p_temp->name, abbr); if(test == 0) { /* node exists */ printf("Node : %s Already exists...\n", p_temp->name); return(0); } else if (test < 0) /* insert into right child */ { btree_insert_node(&p_temp->p_right, abbr, index); } else if (test > 0) /* insert into left child */ { btree_insert_node(&p_temp->p_left, abbr, index); } p_temp->weight = btree_wt(p_temp->p_left) + btree_wt(p_temp->p_right); return(0); } /* end btree_insert_node */ /* ************************************************************ * Function : btree_create * * Abstract : Function to create the btree from the look up table. * * Created by : T. Cunningham * * Creation Date : 4/14/93 * * Modified : * ************************************************************ */ int btree_create(p_lut) lut_st *p_lut; { /* local variables */ int ret_stat, idx; char *p_abbr; /* ptr to abbreviation */ /**************************************/ /* traverse the lut */ for(idx=0; idx < LUT_NUM_ELEMENTS; idx++) { /* get next element in the lut */ p_abbr = lut_get_name(p_lut, idx); if(p_abbr != NULL) { /* add to btree */ btree_insert_node(&p_lut->p_btree_root, p_abbr, idx); } } /* end for */ return(0); } /* end btree_create */ /* ************************************************************ * Function : btree_destroy * * Abstract : Function to delete the binary tree and * free up the memory allocated to the tree. * * Created by : T. Cunningham * * Creation Date : 4/15/93 * * Modified : * *********************************************************** */ int btree_destroy(p_node, p_back) btree_node_st *p_node; btree_node_st *p_back; { /* local variables */ char child_dir; /**************************************/ if(p_back == NULL) { /* this is a root node */ child_dir = 'N'; } else if(p_back->p_right == p_node) { /* this is a right child of the parent */ child_dir = 'R'; } else if(p_back->p_left == p_node) { /* this is a left child of the parent */ child_dir = 'L'; } /* if leaf node */ if( (p_node->p_left == NULL) && (p_node->p_right == NULL)) { /***********************/ /* this is a leaf node */ /***********************/ /* set parent ptr to this node to NULL */ if(child_dir == 'R') { p_back->p_right = NULL; } else if(child_dir == 'L') { p_back->p_left = NULL; } else { /* node is root */ } free(p_node); return(0); } /* not a leaf node */ if(p_node->p_left == NULL) { /*****************************/ /* node has right child only */ /*****************************/ btree_destroy(p_node->p_right, p_node); } else /* left node exists */ { if(p_node->p_right == NULL) { /****************************/ /* node has left child only */ /****************************/ btree_destroy(p_node->p_left, p_node); } else { /***********************************/ /* node has two children */ /***********************************/ btree_destroy(p_node->p_left, p_node); btree_destroy(p_node->p_right, p_node); } } /*******************************************/ /* If you get here you are now a leaf node */ /* All of your subtrees have been deleted */ /*******************************************/ /* set parent ptr to this node to NULL */ if(child_dir == 'R') { p_back->p_right = NULL; } else if(child_dir == 'L') { p_back->p_left = NULL; } else { /* node is root */ } free(p_node); return(0); } /* end btree_destroy */ /* **************************************************************** * Function : btree_wt * * Abstract : Function to give a weight to each node in the tree * The weight is based on number of nodes below it. * This is used for balencing btrees - however the * the balence code was not included in this gen * version due to a lack of time to debug it... * * Created by : D. Pinkney * * Creation Date :?????? * * Modified : * ********************************************************** */ int btree_wt(t) /* returns weight of tree or 1 otherwise */ btree_node_st *t; { if (t == (btree_node_st *) NULL) { return(1); } else { return(t->weight); } } /* end btree_wt */ /********************** private functions used by the key servicing functions (not exported for general use) */ /******************************************************************* * Internally used values of character field lengths *******************************************************************/ #define OLD_KEY_LEN 8 /* for backward compatibility */ #define OLD_ABB_LEN 2 #define OLD_VER_LEN 2 #define OLD_ROW_LEN 4 #define NEW_KEY_LEN 12 #define NEW_ABB_LEN 4 #define NEW_VER_LEN 3 #define NEW_ROW_LEN 5 #define MAX_ROW 65535 /******************************************************************* * The following are masks defining bit lengths of the key field *******************************************************************/ static unsigned long abmask = 0x000000FF; /* masks 8 bit abbreviation field from 32 bit key */ static unsigned long vrmask = 0x000000FF; /* masks 8 bit version field from 32 bit key */ static unsigned long rwmask = 0x0000FFFF; /* masks 16 bit row # field from 32 bit key */ static int key_len = HCG_KEY_SIZE; static int max_row = MAX_ROW; static int max_ver = MAXVERSIONS; static int abshift = 24; /* these are the amounts to shift the 32 bit key to use the above masks */ static int vrshift = 16; static int rwshift = 0; /******************************************************************* * This is the value used to generate the NULL key. *******************************************************************/ static hcg_key null_key_p = 999999999; /******************************************************************* * The following key function sets the static key length *******************************************************************/ int set_external_key_length( klen ) int klen; { if( (klen == OLD_KEY_LEN) || (klen == NEW_KEY_LEN) ) { key_len = klen; return 1; } else { return -1; } } /******************************************************************* * Decode abbrev. encoded in key k, return in string abb *******************************************************************/ int abb_decode( k, abb ) hcg_key* k; char* abb; { char* tmp; unsigned int abi; abi = (*(unsigned long*)k >> abshift) & abmask; if( (tmp = (char *)lut_get_name(&hcg_table_abbrev_lut, abi)) != NULL ) { strcpy( abb, tmp ); return 1; } else { abb[0] = '\0'; return -1; } } /******************************************************************* * Decode the version field of key k; return string representation in ver *******************************************************************/ int ver_decode( k, ver ) hcg_key* k; char* ver; { unsigned int vri = 0; char* rval; vri = (*(unsigned long*)k >> vrshift) & vrmask; if( key_len == OLD_KEY_LEN ) { sprintf(ver,"%02d",vri); return 1; } else if( key_len == NEW_KEY_LEN ) { sprintf(ver,"%03d",vri); return 1; } else { ver[0] = '\0'; return -1; } } /******************************************************************* * Decode (convert to string) the row field of k, return in row *******************************************************************/ int row_decode( k, row ) hcg_key* k; char* row; { int rwi; rwi = (int) ((*(unsigned long*)k >> rwshift) & rwmask); if( key_len == OLD_KEY_LEN ) { sprintf(row, "%04d", rwi); } else if( key_len == NEW_KEY_LEN ) { sprintf(row, "%05d", rwi); } else { return -1; } return 1; } /******************************************************************* * Encode the table abbrev field of key k; with abbr in string t *******************************************************************/ int abb_encode( k, t ) hcg_key* k; char* t; { int ab; if( (ab = lut_insert_element( &hcg_table_abbrev_lut, t )) < 0 ) { printf("ERROR: failure to encode table abbrev: %s\n",t); return -1; } else { *(unsigned long*)k &= ~(abmask << abshift); *(unsigned long*)k |= ((unsigned long)ab & abmask) << abshift; return 1; } } /******************************************************************* * Encode version field in key k to (legal) value contained in string t *******************************************************************/ int ver_encode( k, t ) hcg_key* k; char* t; { unsigned long vr; char* unconv_stuff = NULL; if( (vr = strtoul(t, &unconv_stuff, 10)) > max_ver ) { printf("ERROR: failure to encode table version: %s; MAX allowed version: %d\n",t,max_ver); return -1; } else { *(unsigned long*)k &= ~(vrmask << vrshift); /* clear field */ *(unsigned long*)k |= (vr & vrmask) << vrshift; return 1; } } /******************************************************************* * Encode the row field of key k to (legal) value denoted in string t *******************************************************************/ int row_encode( k, t ) hcg_key* k; char* t; { unsigned long rw; char* unconv_suff = NULL; if( (rw = strtoul(t, &unconv_suff, 10)) > max_row ) { printf("ERROR: failure to encode row value: %s; MAX allowed row: %d\n",t,max_row); return -1; } else { *(unsigned long*)k |= (rw & rwmask); return 1; } } /******************************************************************* * Encode the string in external_key; return key in k *******************************************************************/ int encode( external_key, k ) hcg_key* k; char* external_key; { int ncp; /* no. of chars in field (in external key) */ int fstrt; /* start of field index in external key */ int i; int klen; char t[NEW_KEY_LEN + 1]; char field_buf[NEW_KEY_LEN + 1]; if( (lut_st*) &hcg_table_abbrev_lut == (lut_st*)NULL ) /* ensure necessary tables have been initialized */ { return -1; } if( (klen = strlen(external_key)) != key_len) { printf("Key encode: invalid character key length: %d; key: %s\n",klen,external_key); return -1; } else { for( i=0; i < klen; i++ ) t[i] = (isupper(external_key[i]) ? external_key[i] : toupper(external_key[i])); *k = 0; ncp = (klen == OLD_KEY_LEN) ? 2 : 4; strncpy(field_buf,t,ncp); field_buf[ncp] = '\0'; if( abb_encode(k,field_buf) < 0 ) { return -1; } else { fstrt = ncp; if( klen == OLD_KEY_LEN ) { ncp = OLD_VER_LEN; field_buf[0] = '0'; strncpy( &field_buf[1], &t[fstrt], ncp ); field_buf[ncp+1] = '\0'; } else { ncp = NEW_VER_LEN; strncpy( field_buf, &t[fstrt], ncp ); field_buf[ncp] = '\0'; } if( ver_encode(k, field_buf) < 0 ) { return -1; } else { fstrt += ncp; ncp = (klen == OLD_KEY_LEN) ? OLD_ROW_LEN : NEW_ROW_LEN; strncpy(field_buf, &t[fstrt], ncp); field_buf[ncp] = '\0'; return ( row_encode(k, field_buf) >= 0 ) ? 1 : -1; } } } } /******************************************************************* * Decode key k, return pointer to static buffer containing string *******************************************************************/ char* decode_retstr( k ) hcg_key* k; { static char external_key[NEW_KEY_LEN + 1]; int status; return ( (status = decode(external_key,k)) == 1 ) ? external_key : NULL; } /******************************************************************* * Decode the encoded key k, return string in external_key *******************************************************************/ int decode( external_key, k ) char* external_key; hcg_key* k; { char t[10]; int klen; external_key[0] = '\0'; if( abb_decode(k,t) < 0 ) { return -1; } else { klen = strlen(t); if( ((klen = strlen(t)) != OLD_ABB_LEN) && (klen != NEW_ABB_LEN) ) { printf("ERROR: invalid key returned in decoding; key: %s\n", t); return -1; } else { strcat( external_key, t ); if( ver_decode(k,t) < 0 ) { return -1; } else { strcat( external_key, t ); if( row_decode(k,t) < 0 ) { return -1; } else { strcat( external_key, t ); return 1; } /* row decode ok */ } /* ver decode ok */ } /* abbr of valid length */ } /* abb decode ok */ } /******************************************************************* * Compare two keys; return value as strcmp (-1,0,1) *******************************************************************/ int key_compare( k1, k2 ) hcg_key* k1; hcg_key* k2; { if( *(unsigned long*)k1 < *(unsigned long*)k2 ) return -1; if( *(unsigned long*)k1 == *(unsigned long*)k2 ) return 0; if( *(unsigned long*)k1 > *(unsigned long*)k2 ) return 1; } /******************************************************************* * Return the character abbr of the encoded key *******************************************************************/ char* get_abbr( k, ret ) hcg_key* k; char* ret; { return (abb_decode(k,ret) >= 0) ? ret : NULL; } /******************************************************************* * Return the version no. encoded in this key *******************************************************************/ int get_version( k ) hcg_key* k; { return (int) (*(unsigned long*)k >> vrshift) & vrmask; } /******************************************************************* * Return the row value of the encoded key *******************************************************************/ int get_row( k ) hcg_key* k; { return (int) (*(unsigned long*)k & rwmask ); } /******************************************************************* * Set the abbr field of an encoded key to a desired value *******************************************************************/ int set_abbr( k, ret ) hcg_key* k; char* ret; { return abb_encode(k,ret); } /******************************************************************* * Set the version field of an encoded key to a desired (legal) value *******************************************************************/ int set_version( k, r ) hcg_key* k; int r; { char vbuf[NEW_KEY_LEN]; unsigned int vri; if( r > max_ver ) { return -1; } else { sprintf(vbuf,"%03d",r); vbuf[NEW_VER_LEN] = '\0'; ver_encode( k, vbuf ); return 1; } } /******************************************************************* * Set the row field of an encoded key to the desired legal value *******************************************************************/ int set_row( k, r ) hcg_key* k; int r; { unsigned int rwi; rwi = (unsigned int) r; if( r > max_row ) { return -1; } else { *(unsigned long*)k &= ~(rwmask << rwshift); *(unsigned long*)k |= (rwi & rwmask) << rwshift; return 1; } } /******************************************************************* * This (nkey) is used as a NULL key *******************************************************************/ static hcg_key nkey; /******************************************************************* * Return a pointer to a NULL key *******************************************************************/ hcg_key* null_key() { nkey = null_key_p; return &nkey; } /******************************************************************* * The following tests a key to see if it is NULL *******************************************************************/ int is_null_key( k ) hcg_key* k; { return (*k == null_key_p); } /******************************************************************************/ /* This function initializes the contents of the virtual database, making it */ /* suitable for later calls to pr_load and pr_add. In addition, all files */ /* specified by the filelist parameter are scanned, gathering data stats */ /* (max version for each table, and highest row number value for each table). */ /* Next, the definition of all 'views' are loaded from the specified viewdef_ */ /* filename. See the CHGEN users manual for a description of the file */ /* format and syntax. */ /******************************************************************************/ void pr_init ( viewdef_filename, filelist) char viewdef_filename[]; char filelist[]; { int i,idx, ver_chars; char scan_filename[SCHEMA_HEADER_FILE_NAME_LENGTH]; char viewname[MAXVIEWNAMELEN]; char temp_mode[8],temp_command[100],table_abbrev[ABBREV_NAME_LENGTH],temp_verstring[10], error_table[ABBREV_NAME_LENGTH]; FILE filevar; open_file=1; if (hcg_initialized) { printf("Error: pr_init() called when database is already initialized.\n"); exit(1); } lut_init(&hcg_table_abbrev_lut, ABBR_TBL_TYPE); abbr_lut_create(&hcg_table_abbrev_lut, hcg_tbl_abbr, HCG_NUM_TABLES); clear_mem(hcg_ts_list,sizeof(hcg_ts_list)); for (hcg_tbl_idx = 0; hcg_tbl_idx < HCG_NUM_TABLES; hcg_tbl_idx++) hcg_table_seq_list[hcg_tbl_idx].rcount = hcg_table_seq_list[hcg_tbl_idx].maxver = 0; for(i=0; i < MAXVIEWS; i++) hcg_view_list.view_list[i].view_name[0]='\0'; i = 0; hcg_parse(filelist,scan_filename,&i); while (scan_filename[0] != '\0') { if ((hcg_ascii_fp=fopen(scan_filename,"r")) == NULL) { printf("can not open %s to find TS data\n", scan_filename); exit(2); } hcg_tbl_idx = 0; hcg_read_next(); while ( !feof(hcg_ascii_fp) ) { idx = 0; hcg_parse(hcg_buffer,hcg_t,&idx); if (!find_tbl_idx(hcg_t)) { strncpy_null(error_table, hcg_t, HCG_ABBR_SIZE); printf("Warning: unknown table (%s) found in scanned datafile %s, ignored.\n",error_table,scan_filename); hcg_read_next(); continue; } if(strlen(hcg_t) != HCG_KEY_SIZE) { printf("Warning: invalid keysize %d for key %s, must be %d, ignored.\n", strlen(hcg_t), hcg_t, HCG_KEY_SIZE); hcg_read_next(); continue; } if(HCG_KEY_SIZE == 8) ver_chars = 2; else ver_chars = 3; strncpy_null(temp_verstring, (char *)&hcg_t[HCG_ABBR_SIZE], ver_chars); if(atoi(temp_verstring) > MAXVERSIONS || atoi(temp_verstring) < 0) { printf("Warning: invalid version %d for key %s, exiting.\n", atoi(temp_verstring), hcg_t); exit(0); } if(encode(hcg_t, &hcg_k) != 1) { printf("Warning: Invalid key %s, ignored.\n", hcg_t); hcg_read_next(); continue; } hcg_row = get_row(&hcg_k); hcg_version = get_version(&hcg_k); if (hcg_row > hcg_ts_list[hcg_tbl_idx].ts_list[hcg_version].maxrow) hcg_ts_list[hcg_tbl_idx].ts_list[hcg_version].maxrow = hcg_row; if (hcg_version > hcg_table_seq_list[hcg_tbl_idx].maxver) hcg_table_seq_list[hcg_tbl_idx].maxver = hcg_version; hcg_read_next(); } /* while !feof */ close(hcg_ascii_fp); hcg_parse(filelist,scan_filename,&i); } /* while scan_filename */ hcg_view_list.num_views = 0; if ((hcg_ascii_fp=fopen(viewdef_filename,"r")) == NULL) { printf("can not open %s to find view definitions\n", viewdef_filename); exit(2); } hcg_tbl_idx = hcg_view_idx = 0; hcg_read_next(); while ( !feof(hcg_ascii_fp) ) { idx = 0; hcg_parse(hcg_buffer,temp_command,&idx); if (strcmp(temp_command,"define_view") == 0) { hcg_parse(hcg_buffer,viewname,&idx); if (find_view_idx(viewname)) { printf("Warning: view %s defined twice, ignored.\n",viewname); hcg_read_next(); continue; } hcg_parse(hcg_buffer,temp_mode,&idx); if ((strcmp(temp_mode,"read") != 0) && (strcmp(temp_mode,"write") != 0) && (strcmp(temp_mode,"update") != 0)) { printf("Error: mode %s specified for view %s is invalid.\n",temp_mode,viewname); exit(2); } if (hcg_view_list.num_views >= MAXVIEWS) { printf("Error: Too many views defined (max=%d), next view would have been %s.\n",MAXVIEWS,viewname); exit(2); } strcpy(hcg_view_list.view_list[hcg_view_list.num_views].view_name,viewname); hcg_view_list.view_list[hcg_view_list.num_views].mode = temp_mode[0]; for (i=0; i<100; i++) hcg_view_list.view_list[hcg_view_list.num_views].version_list[i] = '\0'; hcg_view_list.num_views++; } /* if define_view */ else if (strcmp(temp_command,"view_element") == 0) { hcg_parse(hcg_buffer,viewname,&idx); if (!find_view_idx(viewname)) { printf("Warning: view %s specified in view_element statement is not defined, ignored.\n",viewname); hcg_read_next(); continue; } hcg_parse(hcg_buffer,table_abbrev,&idx); if (!find_tbl_idx(table_abbrev)) { printf("Warning: unknown table (%s) specified for view %s in view_element statement, ignored.\n",table_abbrev,viewname); hcg_read_next(); continue; } hcg_parse(hcg_buffer,temp_verstring,&idx); hcg_version = atoi(temp_verstring); if ((hcg_version < -(MAXVERSIONS)) || (hcg_version > MAXVERSIONS)) { printf("Warning: version-offset %d specified for view %s in view_element statement is out of range, ignored.\n",hcg_version,viewname); hcg_read_next(); continue; } if ((hcg_table_seq_list[hcg_tbl_idx].maxver == MAXVERSIONS) && (hcg_view_list.view_list[hcg_view_list.num_views -1].mode == 'w')) { printf("Error: view %s invoked on table %s as write, MAXVERSION of %d is used\n",viewname, table_abbrev, MAXVERSIONS); exit(0); } if (hcg_version > hcg_table_seq_list[hcg_tbl_idx].maxver) { printf("Warning: absolute version-number %d specified for view %s in view_element statement is higher than current max-version (%d), ignored.\n",hcg_version,viewname,hcg_table_seq_list[hcg_tbl_idx].maxver); hcg_read_next(); continue; } if ((hcg_version < 0) && ((hcg_table_seq_list[hcg_tbl_idx].maxver+hcg_version) < 1) ) { printf("Warning: version-offset %d specified for view %s in view_element statement would lead ",hcg_version,viewname); printf("to an invalid version number (<1), current max-version (%d), ignored.\n",hcg_table_seq_list[hcg_tbl_idx].maxver); hcg_read_next(); continue; } if (hcg_version > 0) hcg_view_list.view_list[hcg_view_idx].version_list[hcg_tbl_idx] = (char) hcg_version; else hcg_view_list.view_list[hcg_view_idx].version_list[hcg_tbl_idx] = (char) hcg_table_seq_list[hcg_tbl_idx].maxver+hcg_version; } /* if view_element */ else if ((temp_command[0] != '\0') && (strncmp(temp_command,"/*",2) != 0)) { printf("Warning: unknown command (%s) found in view-definition file (%s), ignored.\n",temp_command,viewdef_filename); hcg_read_next(); continue; } hcg_read_next(); } /* while !feof */ close(hcg_ascii_fp); btree_initialized(); hcg_initialized = 1; } /******************************************************************************/ /* Description: This routine is used to reset btree. .*/ /* Input: none. */ /* Output: none.( it will reset table 's btree. */ /******************************************************************************/ btree_initialized() { if (hcg_initialized) { } SMbtidx=SEQUENCESEARCH; ACbtidx=SEQUENCESEARCH; STbtidx=SEQUENCESEARCH; AIbtidx=SEQUENCESEARCH; TRbtidx=SEQUENCESEARCH; ETbtidx=SEQUENCESEARCH; ENbtidx=SEQUENCESEARCH; EIbtidx=SEQUENCESEARCH; TFbtidx=SEQUENCESEARCH; TIbtidx=SEQUENCESEARCH; CKbtidx=SEQUENCESEARCH; } /******************************************************************************/ /* This private macro will allocate a block of memory large enough to hold the*/ /* specified table type. It also flushes the block to binary 0 (zero), so */ /* that pointer fields are pre-nulled. */ /******************************************************************************/ #define alloc_element(tbl) \ tbl##elt = (struct tbl *)malloc( sizeof(struct tbl) ); \ clear_mem(tbl##elt,sizeof(struct tbl)) /******************************************************************************/ /* This private macro will insert a row into a table. The pkey parameter is */ /* the name of the primary key field for the table in question. The row is */ /* linked into the tables row chain at the alphabetically correct location, */ /* sorted by primary key. */ /******************************************************************************/ #define insert_element(tbl,pkey) \ if (tbl == NULL) \ { \ tbl = tbl##elt; \ tbl##end = tbl##elt; \ } \ else \ if (key_compare(&tbl##end->pkey,&tbl##elt->pkey) < 0) \ { \ tbl##end->next_ptr = tbl##elt; \ tbl##elt->prev_ptr = tbl##end; \ tbl##end = tbl##elt; \ } \ else \ { \ tbl##temp = tbl; \ tbl##curr = tbl; \ while ((tbl##curr != NULL) && (key_compare(&tbl##curr->pkey,&tbl##elt->pkey) < 0)) \ { \ tbl##temp = tbl##curr; \ tbl##curr = tbl##curr->next_ptr; \ } \ if ((tbl##curr != NULL) && (key_compare(&tbl##curr->pkey,&tbl##elt->pkey) == 0)) \ { \ dup_row_warning(tbl##elt->pkey); \ free(tbl##elt); \ break; \ } \ if (tbl##curr == tbl) \ { \ tbl##elt->next_ptr = tbl; \ tbl->prev_ptr = tbl##elt; \ tbl = tbl##elt; \ } \ else \ { \ tbl##elt->next_ptr = tbl##curr; \ tbl##elt->prev_ptr = tbl##temp; \ tbl##temp->next_ptr = tbl##elt; \ if (tbl##curr != NULL) \ tbl##curr->prev_ptr = tbl##elt; \ } \ } \ tbl##curr = tbl##elt /******************************************************************************/ /* This private macro will loop over the specified child table, linking the */ /* first child it finds for this parent row. This is acceptable since it is */ /* supposed to be a singleton relationship. */ /******************************************************************************/ #define link_child_1(ca,pa,cf,pk,p,c) \ pa##curr = pa##elt; \ ca##curr2 = ca; \ while(ca##curr2) \ { \ if (key_compare(&ca##curr2->cf,&pa##curr->pk) == 0) \ { \ ca##curr2->p##_pp = pa##curr; \ pa##curr->c##_fcp = ca##curr2; \ break; \ } \ ca##curr2 = ca##curr2->next_ptr; \ } /******************************************************************************/ /* This private macro will loop over the specified child table, linking any */ /* children of this parent row. It is identical to link_child_nobp except */ /* that back pointers are also filled in. */ /******************************************************************************/ #define link_child_bp_m(ca,pa,cf,pk,p,c) \ pa##curr = pa##elt; \ ca##curr2 = ca; \ while(ca##curr2) \ { \ if (key_compare(&ca##curr2->cf,&pa##curr->pk) == 0) \ { \ ca##curr2->p##_pp = pa##curr; \ ca##temp2 = pa##curr->c##_bcp; \ pa##curr->c##_bcp = ca##curr2; \ (struct pa *) ca##curr2->p##_fpp = pa##curr; \ if (pa##curr->c##_fcp == NULL) \ { \ pa##curr->c##_fcp = ca##curr2; \ (struct pa *) ca##curr2->p##_bpp = pa##curr; \ } \ else \ { \ (struct ca *) ca##curr2->p##_bpp = ca##temp2; \ (struct ca *) ca##temp2->p##_fpp = ca##curr2; \ } \ } \ ca##curr2 = ca##curr2->next_ptr; \ } /******************************************************************************/ /* This private macro will loop over the specified child table, linking any */ /* children of this parent row. It is identical to link_child_bp except */ /* that back pointers are not filled in. Because there are no back-ptrs, */ /* the last child in the chain must be found via a search loop over the */ /* children. */ /******************************************************************************/ #define link_child_nobp_m(ca,pa,cf,pk,p,c) \ pa##curr = pa##elt; \ ca##curr2 = ca; \ while(ca##curr2) \ { \ if (key_compare(&ca##curr2->cf,&pa##curr->pk) == 0) \ { \ ca##curr2->p##_pp = pa##curr; \ (struct pa *) ca##curr2->p##_fpp = pa##curr; \ if (pa##curr->c##_fcp == NULL) \ { \ pa##curr->c##_fcp = ca##curr2; \ } \ else \ { \ for (ca##temp2 = pa##curr->c##_fcp; (struct pa *) ca##temp2->p##_fpp != pa##curr; ca##temp2 = (struct ca *)ca##temp2->p##_fpp); \ (struct ca *) ca##temp2->p##_fpp = ca##curr2; \ } \ ca##temp2 = ca##curr2; \ } \ ca##curr2 = ca##curr2->next_ptr; \ } /******************************************************************************/ /* This private macro will loop over the specified parent table, linking any */ /* parents of this child row. It is identical to link_parent_nobp except */ /* that it is assumed to be a singleton child. */ /******************************************************************************/ #define link_parent_1(ca,pa,cf,pk,p,c) \ for (pa##curr2 = pa; (pa##curr2 != NULL) && (key_compare(&pa##curr2->pk,&ca##curr->cf) < 0); pa##curr2 = pa##curr2->next_ptr); \ if ((pa##curr2 != NULL) && (key_compare(&ca##curr->cf,&pa##curr2->pk) == 0)) \ { \ ca##curr->p##_pp = pa##curr2; \ pa##curr2->c##_fcp = ca##curr; \ } /******************************************************************************/ /* This private macro will loop over the specified parent table, linking any */ /* parents of this child row. It is identical to link_parent_nobp except */ /* that back pointers are also filled in. */ /* */ /* NOTE: Since the -noforward command-line qualifier was NOT used to generate */ /* this code, no check is included to ensure that a parent row was */ /* actually found. Performance and code size are sacrificed here, since*/ /* calls to link_child_{no}bp are included in the caller (pr_add). */ /* Link child is only needed when there is a risk of forward references */ /* in the data file. */ /* */ /******************************************************************************/ #define link_parent_bp_m(ca,pa,cf,pk,p,c) \ for (pa##curr2 = pa; (pa##curr2 != NULL) && (key_compare(&pa##curr2->pk,&ca##curr->cf) < 0); pa##curr2 = pa##curr2->next_ptr); \ if ((pa##curr2 != NULL) && (key_compare(&ca##curr->cf,&pa##curr2->pk) == 0)) \ { \ ca##curr->p##_pp = pa##curr2; \ ca##temp = pa##curr2->c##_bcp; \ pa##curr2->c##_bcp = ca##curr; \ (struct pa *) ca##curr->p##_fpp = pa##curr2; \ if (pa##curr2->c##_fcp == NULL) \ { \ pa##curr2->c##_fcp = ca##curr; \ (struct pa *) ca##curr->p##_bpp = pa##curr2; \ } \ else \ { \ (struct ca *) ca##curr->p##_bpp = ca##temp; \ (struct ca *) ca##temp->p##_fpp = ca##curr; \ } \ } /******************************************************************************/ /* This private macro will loop over the specified parent table, linking any */ /* parents of this child row. It is identical to link_parent_nobp except */ /* that back pointers are not filled in. Because there are no back-ptrs, */ /* the last child in the chain must be found via a search loop over the */ /* children. */ /* */ /* NOTE: Since the -noforward command-line qualifier was NOT used to generate */ /* this code, no check is included to ensure that a parent row was */ /* actually found. Performance and code size are sacrificed here, since*/ /* calls to link_child_{no}bp are included in the caller (pr_add). */ /* Link child is only needed when there is a risk of forward references */ /* in the data file. */ /* */ /******************************************************************************/ #define link_parent_nobp_m(ca,pa,cf,pk,p,c) \ for (pa##curr2 = pa; (pa##curr2 != NULL) && (key_compare(&pa##curr2->pk,&ca##curr->cf) < 0); pa##curr2 = pa##curr2->next_ptr); \ if ((pa##curr2 != NULL) && (key_compare(&ca##curr->cf,&pa##curr2->pk) == 0)) \ { \ ca##curr->p##_pp = pa##curr2; \ (struct pa *) ca##curr->p##_fpp = pa##curr2; \ if (pa##curr2->c##_fcp == NULL) \ pa##curr2->c##_fcp = ca##curr; \ else \ { \ for (ca##temp2 = pa##curr2->c##_fcp; (struct pa *) ca##temp2->p##_fpp != pa##curr2; ca##temp2 = (struct ca *)ca##temp2->p##_fpp); \ (struct ca *) ca##temp2->p##_fpp = ca##curr; \ } \ } /******************************************************************************/ /* This routine is used to link a single row to a virtual database table. */ /******************************************************************************/ void pr_link (tbl_encoding) int tbl_encoding; { switch( tbl_encoding ) { case 0 : /* encoding of SM */ insert_element(SM,SMid); link_child_bp_m(ET,SM,SMid,SMid,SMid,ETid); link_child_bp_m(ST,SM,SMid,SMid,SMid,STid); link_child_bp_m(AC,SM,SMid,SMid,SMid,ACid); break; case 1 : /* encoding of AC */ insert_element(AC,ACid); link_child_bp_m(AI,AC,ACid,ACid,ACid,AIid); link_parent_bp_m(AC,SM,SMid,SMid,SMid,ACid); break; case 2 : /* encoding of ST */ insert_element(ST,STid); link_child_bp_m(TR,ST,STid1,STid,STid1,TRid1); link_child_bp_m(TR,ST,STid2,STid,STid2,TRid2); link_parent_bp_m(ST,SM,SMid,SMid,SMid,STid); break; case 3 : /* encoding of AI */ insert_element(AI,AIid); link_child_bp_m(TF,AI,AIid,AIid,AIid,TFid); link_child_bp_m(CK,AI,AIid1,AIid,AIid1,CKid1); link_child_bp_m(TI,AI,AIid1,AIid,AIid1,TIid1); link_child_bp_m(EI,AI,AIid1,AIid,AIid1,EIid1); link_child_bp_m(TF,AI,AIid1_source,AIid,AIid1_source,TFid1); link_child_bp_m(CK,AI,AIid2,AIid,AIid2,CKid2); link_child_bp_m(TI,AI,AIid2,AIid,AIid2,TIid2); link_child_bp_m(EI,AI,AIid2,AIid,AIid2,EIid2); link_child_bp_m(TF,AI,AIid2_reply,AIid,AIid2_reply,TFid2); link_child_bp_m(CK,AI,AIid3,AIid,AIid3,CKid3); link_child_bp_m(TI,AI,AIid3,AIid,AIid3,TIid3); link_parent_bp_m(AI,AC,ACid,ACid,ACid,AIid); break; case 4 : /* encoding of TR */ insert_element(TR,TRid); link_child_bp_m(EN,TR,TRid,TRid,TRid,ENid); link_parent_bp_m(TR,ST,STid1,STid,STid1,TRid1); link_parent_bp_m(TR,ST,STid2,STid,STid2,TRid2); break; case 5 : /* encoding of ET */ insert_element(ET,ETid); link_child_bp_m(CK,ET,ETid,ETid,ETid,CKid); link_child_bp_m(TI,ET,ETid,ETid,ETid,TIid); link_child_bp_m(EI,ET,ETid,ETid,ETid,EIid); link_child_bp_m(EN,ET,ETid,ETid,ETid,ENid); link_parent_bp_m(ET,SM,SMid,SMid,SMid,ETid); break; case 6 : /* encoding of EN */ insert_element(EN,ENid); link_parent_bp_m(EN,TR,TRid,TRid,TRid,ENid); link_parent_bp_m(EN,ET,ETid,ETid,ETid,ENid); break; case 7 : /* encoding of EI */ insert_element(EI,EIid); link_parent_bp_m(EI,ET,ETid,ETid,ETid,EIid); link_parent_bp_m(EI,AI,AIid1,AIid,AIid1,EIid1); link_parent_bp_m(EI,AI,AIid2,AIid,AIid2,EIid2); break; case 8 : /* encoding of TF */ insert_element(TF,TFid); link_parent_bp_m(TF,AI,AIid,AIid,AIid,TFid); link_parent_bp_m(TF,AI,AIid1_source,AIid,AIid1_source,TFid1); link_parent_bp_m(TF,AI,AIid2_reply,AIid,AIid2_reply,TFid2); break; case 9 : /* encoding of TI */ insert_element(TI,TIid); link_parent_bp_m(TI,ET,ETid,ETid,ETid,TIid); link_parent_bp_m(TI,AI,AIid1,AIid,AIid1,TIid1); link_parent_bp_m(TI,AI,AIid2,AIid,AIid2,TIid2); link_parent_bp_m(TI,AI,AIid3,AIid,AIid3,TIid3); break; case 10 : /* encoding of CK */ insert_element(CK,CKid); link_parent_bp_m(CK,ET,ETid,ETid,ETid,CKid); link_parent_bp_m(CK,AI,AIid1,AIid,AIid1,CKid1); link_parent_bp_m(CK,AI,AIid2,AIid,AIid2,CKid2); link_parent_bp_m(CK,AI,AIid3,AIid,AIid3,CKid3); break; } } /******************************************************************************/ /* This routine is used to create a table element and initialize it. */ /******************************************************************************/ hcg_ptr pr_gen_create ( size ) int size; { hcg_ptr ptr = (hcg_ptr) malloc(size); bzero(ptr, size); /* or memset(ptr, 0, size); */ /* This should also set all the keys to null_key() but doesn't right now -- MM */ return ptr; } /******************************************************************************/ /* This macro is used to generate the next available primary key value for the*/ /* specified table, using the specified view. */ /******************************************************************************/ #define pr_gen_key(key,tbl_abbrv,version_id,entry_id) \ (key) = *null_key();\ set_abbr(&(key), (tbl_abbrv));\ set_version(&(key), (version_id));\ set_row(&(key), (entry_id))\ #define pr_gen_pkey(viewname,tbl,pkey) \ if (find_view_idx(viewname)) \ pr_gen_key(pkey,hcg_table_seq_list[tbl##_idx].ttabbrev, \ (char) hcg_view_list.view_list[hcg_view_idx].version_list[tbl##_idx], \ hcg_ts_list[tbl##_idx].ts_list[hcg_view_list.view_list[hcg_view_idx].version_list[tbl##_idx]].maxrow+1) #define pr_check_fkey(ctbl_abbr,ctbl_ptr,ckey,ptbl_abbr,pkey,ptbl_ptr) \ if ( is_null_key(&((ctbl_ptr)->ckey)) || (ctbl_ptr)->ckey == 0 ) {\ if (!hcg_default_fkey) {\ printf("Warning: foreign key %s is not set for table %s element 0x%8.8x\n", \ #ckey, #ctbl_abbr, ctbl_ptr );\ pr_gen_key( (ctbl_ptr)->ckey,#ptbl_abbr, 0, 0);\ }\ else if ( (ptbl_ptr) && ( !is_null_key(&((ptbl_ptr)->pkey)) ) && ( (ptbl_ptr)->pkey != 0) ) {\ (ctbl_ptr)->ckey = (ptbl_ptr)->pkey;\ }\ else {\ pr_gen_key( (ctbl_ptr)->ckey, #ptbl_abbr, 0, 0);\ }\ } /******************************************************************************/ /* This macro is used set the default value of non-key fields of type cX or tX*/ /******************************************************************************/ #define pr_check_str(tbl_abbr,tbl_ptr,fld,length) \ if ( (tbl_ptr)->fld[0] == '\0' ) \ {\ int i = sizeof((tbl_ptr)->fld) - 2;\ printf("Warning: string field %s is not set for table %s element 0x%8.8x\n", \ #fld, #tbl_abbr, tbl_ptr);\ for((tbl_ptr)->fld[i] = '\0'; i>=0; (tbl_ptr)->fld[i--] = '?');\ } /******************************************************************************/ /* This routine is used to add a single row to a virtual database table. */ /* Validations for valid table-id, table is within view, and the version */ /* number is the right one for this table in this view. if all this passes, */ /* the row is added to the database, and linked in to its parents, etc... */ /******************************************************************************/ void gen_pr_add (viewname, tbl_abbrv, tbl_ptr) char viewname[]; char tbl_abbrv[]; hcg_ptr tbl_ptr; { char error_table[HCG_ABBR_SIZE+1]; char tempkey[HCG_KEY_SIZE+1]; int tbl_encoding; /* skip leading spaces (if any) from tbl_abbrv */ while( *tbl_abbrv == ' ') ++tbl_abbrv; if (!hcg_initialized) { printf("Error: pr_add() called when database is not yet initialized.\n"); exit(1); } if (!find_view_idx(viewname)) { printf("Error: view %s passed to pr_load is not defined.\n",viewname); exit(2); } if (!find_tbl_idx(tbl_abbrv)) { strncpy_null(error_table, tbl_abbrv, HCG_ABBR_SIZE); printf("Warning: unknown table (%s) passed to pr_add, ignored.\n",error_table); return; } hcg_version = hcg_view_list.view_list[hcg_view_idx].version_list[hcg_tbl_idx]; hcg_table_seq_list[hcg_tbl_idx].rcount++; hcg_ts_list[hcg_tbl_idx].ts_list[hcg_version].rcount++; tbl_encoding = encoding( hcg_table_seq_list[hcg_tbl_idx].ttabbrev ); switch( tbl_encoding ) { case 0 : /* encoding of SM */ SMelt = (struct SM *) tbl_ptr; pr_gen_pkey(viewname,SM,SMelt->SMid); pr_check_str (SM,SMelt,Abbrev,4); pr_check_str (SM,SMelt,Name,80); pr_link(tbl_encoding); break; case 1 : /* encoding of AC */ ACelt = (struct AC *) tbl_ptr; pr_gen_pkey(viewname,AC,ACelt->ACid); pr_check_fkey(AC,ACelt,SMid,SM,SMid,SMelt); pr_check_str (AC,ACelt,Name,80); pr_link(tbl_encoding); break; case 2 : /* encoding of ST */ STelt = (struct ST *) tbl_ptr; pr_gen_pkey(viewname,ST,STelt->STid); pr_check_fkey(ST,STelt,SMid,SM,SMid,SMelt); pr_check_str (ST,STelt,ActName,32); pr_check_str (ST,STelt,Name,80); pr_link(tbl_encoding); break; case 3 : /* encoding of AI */ AIelt = (struct AI *) tbl_ptr; pr_gen_pkey(viewname,AI,AIelt->AIid); pr_check_fkey(AI,AIelt,ACid,AC,ACid,ACelt); pr_check_str (AI,AIelt,State,80); pr_check_str (AI,AIelt,Name,80); pr_link(tbl_encoding); break; case 4 : /* encoding of TR */ TRelt = (struct TR *) tbl_ptr; pr_gen_pkey(viewname,TR,TRelt->TRid); pr_check_fkey(TR,TRelt,STid1,ST,STid,STelt); pr_check_fkey(TR,TRelt,STid2,ST,STid,STelt); pr_link(tbl_encoding); break; case 5 : /* encoding of ET */ ETelt = (struct ET *) tbl_ptr; pr_gen_pkey(viewname,ET,ETelt->ETid); pr_check_fkey(ET,ETelt,SMid,SM,SMid,SMelt); pr_check_str (ET,ETelt,Label,8); pr_check_str (ET,ETelt,Descrip,80); pr_link(tbl_encoding); break; case 6 : /* encoding of EN */ ENelt = (struct EN *) tbl_ptr; pr_gen_pkey(viewname,EN,ENelt->ENid); pr_check_fkey(EN,ENelt,TRid,TR,TRid,TRelt); pr_check_fkey(EN,ENelt,ETid,ET,ETid,ETelt); pr_link(tbl_encoding); break; case 7 : /* encoding of EI */ EIelt = (struct EI *) tbl_ptr; pr_gen_pkey(viewname,EI,EIelt->EIid); pr_check_fkey(EI,EIelt,ETid,ET,ETid,ETelt); pr_check_fkey(EI,EIelt,AIid1,AI,AIid,AIelt); pr_check_fkey(EI,EIelt,AIid2,AI,AIid,AIelt); pr_check_str (EI,EIelt,Text,80); pr_link(tbl_encoding); break; case 8 : /* encoding of TF */ TFelt = (struct TF *) tbl_ptr; pr_gen_pkey(viewname,TF,TFelt->TFid); pr_check_fkey(TF,TFelt,AIid,AI,AIid,AIelt); pr_check_fkey(TF,TFelt,AIid1_source,AI,AIid,AIelt); pr_check_fkey(TF,TFelt,AIid2_reply,AI,AIid,AIelt); pr_check_str (TF,TFelt,replyETLabel,8); pr_link(tbl_encoding); break; case 9 : /* encoding of TI */ TIelt = (struct TI *) tbl_ptr; pr_gen_pkey(viewname,TI,TIelt->TIid); pr_check_fkey(TI,TIelt,ETid,ET,ETid,ETelt); pr_check_fkey(TI,TIelt,AIid1,AI,AIid,AIelt); pr_check_fkey(TI,TIelt,AIid2,AI,AIid,AIelt); pr_check_fkey(TI,TIelt,AIid3,AI,AIid,AIelt); pr_link(tbl_encoding); break; case 10 : /* encoding of CK */ CKelt = (struct CK *) tbl_ptr; pr_gen_pkey(viewname,CK,CKelt->CKid); pr_check_fkey(CK,CKelt,ETid,ET,ETid,ETelt); pr_check_fkey(CK,CKelt,AIid1,AI,AIid,AIelt); pr_check_fkey(CK,CKelt,AIid2,AI,AIid,AIelt); pr_check_fkey(CK,CKelt,AIid3,AI,AIid,AIelt); pr_link(tbl_encoding); break; } hcg_ts_list[hcg_tbl_idx].ts_list[hcg_version].maxrow++; } /******************************************************************************/ /* This routine is used to read the (already open datafile) and call pr_add */ /* with each row, to add it to the database. Validations for valid table-id, */ /* table is within view, and the version number is the right one for this */ /* table in this view. if all this passes, pr_add is called. A special flag */ /* is set telling pr_add not to perform these same validations. */ /******************************************************************************/ void load_data(viewname) char viewname[]; { int idx, ver_chars; char temp_verstring[ABBREV_NAME_LENGTH]; int tbl_encoding; /* 93su523 PGEN merge */ void pr_parse(); /* 93su523 PGEN merge */ hcg_tbl_idx = 0; hcg_read_next(); while ( !feof(hcg_ascii_fp) ) { idx = 0; hcg_parse(hcg_buffer,hcg_t,&idx); if (!find_tbl_idx(hcg_t)) { strncpy_null(temp_verstring, hcg_t, HCG_ABBR_SIZE); printf("Warning: unknown table (%s) found in datafile, ignored.\n",temp_verstring); hcg_read_next(); continue; } if(strlen(hcg_t) != HCG_KEY_SIZE) { printf("Warning: invalid keysize %d for key %s, must be %d, ignored.\n", strlen(hcg_t), hcg_t, HCG_KEY_SIZE); hcg_read_next(); continue; } if(HCG_KEY_SIZE == 8) ver_chars = 2; else ver_chars = 3; strncpy_null(temp_verstring, &hcg_t[HCG_ABBR_SIZE], ver_chars); if(encode(hcg_t, &hcg_k) != 1) { printf("Warning: invalid key %s, ignored.\n", hcg_t); hcg_read_next(); continue; } hcg_row = get_row(&hcg_k); hcg_version = get_version(&hcg_k); if (((char) hcg_version) != hcg_view_list.view_list[hcg_view_idx].version_list[hcg_tbl_idx]) { hcg_read_next(); continue; } hcg_table_seq_list[hcg_tbl_idx].rcount++; hcg_ts_list[hcg_tbl_idx].ts_list[hcg_version].rcount++; if (hcg_row > hcg_ts_list[hcg_tbl_idx].ts_list[hcg_version].maxrow) hcg_ts_list[hcg_tbl_idx].ts_list[hcg_version].maxrow = hcg_row; /* 93su523 PGEN merge (BEGIN) */ tbl_encoding = encoding( hcg_table_seq_list[hcg_tbl_idx].ttabbrev ); pr_parse(viewname, hcg_buffer, tbl_encoding, idx, hcg_k); pr_link( tbl_encoding ); /* 93su523 PGEN merge (END) */ hcg_read_next(); } } /******************************************************************************/ /* This routine is used to parse a single row to a virtual database table. */ /* Validations for valid table-id, table is within view, and the version */ /* number is the right one for this table in this view. if all this passes, */ /* the row is added to the database, and linked in to its parents, etc... */ /******************************************************************************/ /*OWEN*/ typedef void (ActionRoutine)(hcg_key); void pr_parse (viewname, buffer, tbl_encoding, idx, hcg_k) char viewname[]; char buffer[]; int tbl_encoding; int idx; hcg_key hcg_k; { #ifdef DEBUG printf("Row to be added = %s\n", buffer); #endif switch( tbl_encoding ) { case 0 : /* encoding of SM */ SMelt = pr_create(SM); SMelt->SMid = hcg_k; hcg_parse(buffer,hcg_t,&idx); mystrcpy(SMelt->Abbrev,hcg_t,4,0); mystrcpy(SMelt->Name,buffer+idx,80,1); break; case 1 : /* encoding of AC */ ACelt = pr_create(AC); ACelt->ACid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); ACelt->SMid = hcg_k; mystrcpy(ACelt->Name,buffer+idx,80,1); break; case 2 : /* encoding of ST */ STelt = pr_create(ST); STelt->STid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); STelt->SMid = hcg_k; hcg_parse(buffer,hcg_t,&idx); mystrcpy(STelt->ActName,hcg_t,32,1); hcg_parse(buffer,hcg_t,&idx); /*CHANGED*/ #ifdef ORIGINAL_VERSION pr_set_int(STelt,ActFunc,atoi(hcg_t)); #else STelt->ActFunc = (ActionRoutine *)atoi(hcg_t) ; #endif mystrcpy(STelt->Name,buffer+idx,80,1); break; case 3 : /* encoding of AI */ AIelt = pr_create(AI); AIelt->AIid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); AIelt->ACid = hcg_k; hcg_parse(buffer,hcg_t,&idx); mystrcpy(AIelt->State,hcg_t,80,1); mystrcpy(AIelt->Name,buffer+idx,80,1); break; case 4 : /* encoding of TR */ TRelt = pr_create(TR); TRelt->TRid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TRelt->STid1 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TRelt->STid2 = hcg_k; break; case 5 : /* encoding of ET */ ETelt = pr_create(ET); ETelt->ETid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); ETelt->SMid = hcg_k; hcg_parse(buffer,hcg_t,&idx); mystrcpy(ETelt->Label,hcg_t,8,1); mystrcpy(ETelt->Descrip,buffer+idx,80,1); break; case 6 : /* encoding of EN */ ENelt = pr_create(EN); ENelt->ENid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); ENelt->ETid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); ENelt->TRid = hcg_k; break; case 7 : /* encoding of EI */ EIelt = pr_create(EI); EIelt->EIid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); EIelt->AIid1 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); EIelt->AIid2 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); EIelt->ETid = hcg_k; hcg_parse(buffer,hcg_t,&idx); pr_set_int(EIelt,Int1,atoi(hcg_t)); hcg_parse(buffer,hcg_t,&idx); pr_set_int(EIelt,Int2,atoi(hcg_t)); hcg_parse(buffer,hcg_t,&idx); pr_set_flt(EIelt,Flt1, atof(hcg_t)); hcg_parse(buffer,hcg_t,&idx); pr_set_flt(EIelt,Flt2, atof(hcg_t)); mystrcpy(EIelt->Text,buffer+idx,80,1); break; case 8 : /* encoding of TF */ TFelt = pr_create(TF); TFelt->TFid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TFelt->AIid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TFelt->AIid1_source = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TFelt->AIid2_reply = hcg_k; hcg_parse(buffer,hcg_t,&idx); mystrcpy(TFelt->replyETLabel,hcg_t,8,0); hcg_parse(buffer,hcg_t,&idx); pr_set_int(TFelt,bitPosition,atoi(hcg_t)); break; case 9 : /* encoding of TI */ TIelt = pr_create(TI); TIelt->TIid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TIelt->AIid1 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TIelt->AIid2 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TIelt->AIid3 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); TIelt->ETid = hcg_k; hcg_parse(buffer,hcg_t,&idx); pr_set_int(TIelt,ttg,atoi(hcg_t)); break; case 10 : /* encoding of CK */ CKelt = pr_create(CK); CKelt->CKid = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); CKelt->AIid1 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); CKelt->AIid2 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); CKelt->AIid3 = hcg_k; hcg_parse(buffer, hcg_t, &idx); encode(hcg_t, &hcg_k); CKelt->ETid = hcg_k; hcg_parse(buffer,hcg_t,&idx); pr_set_int(CKelt,period,atoi(hcg_t)); break; } } /******************************************************************************/ /* This routine is used to load the contents of the virtual database from the */ /* specified file, using the specified view. All rows from the file that */ /* meet the criteria of the view will be loaded. This routine itself really */ /* just verifys the view name, opens the file, and then calls load_data. */ /* It also closes the file. */ /******************************************************************************/ void pr_load ( viewname, file_name) char viewname[],file_name[]; { if (!hcg_initialized) { printf("Error: pr_load() called when database is not yet initialized.\n"); exit(1); } if (!find_view_idx(viewname)) { printf("Error: view %s passed to pr_load is not defined.\n",viewname); exit(2); } if ((hcg_ascii_fp=fopen(file_name,"r")) == NULL) { printf("can not open %s\n", file_name); exit(2); } load_data (viewname); close(hcg_ascii_fp); } /******************************************************************************/ /* Description: This routine is used to find the pkey location by using btree.*/ /* Input: the special table name and its pkey value. */ /* *temp1 is the table name. *temp2 is the pkey value. */ /* Output: none.( it will move table position to the specific row. */ /******************************************************************************/ void pr_find_bt(temp1,temp2) char *temp1; hcg_key *temp2; { int tbl_encoding, finish=FALSE ; hcg_key result; if (!find_tbl_idx(temp1)) { printf("Error: unknown table (%s) passed to pr_find.\n",temp1); exit(3); } tbl_encoding = encoding( hcg_table_seq_list[hcg_tbl_idx].ttabbrev ); switch( tbl_encoding ) { } }