/**************************************************************** * * * * * Revised 11/JULY/89 by chou & cheng : * * Add function gen_rr_matrix. * * gen_path. * * gen_macros. * * store_into_matrix * * * * modify prescan * * read_and_write * * * * Revised 14/JUNE/89 by chou & cheng. * * This program modify H_GEN_BAK make it suitable for free * * format * * Function change : presacn , read_and_write , locate_comment * * * * * * * * * * * * Project : S89 DDA/main interface * * Program : H_GEN.C * * --.h file generator * * * * This program generates an output file schema.h, * * which represents a virtual network database converted from * * the Ingres internal structure according to the input schema * * definition text file. * * * * It scans the input file by two passes. In the first * * pass it scans the input file and builds up two linked list * * holding the parent-child and child-parent relations, whereas * * in the second pass the the data structure as well as the * * relation pointers are built up. * * * * parent-child/owner-member relationship is decided * * according to the following criterion : * * if a foreign key ever appears within a table, * * then this table has a parent which is a table keyed * * by this foreign key. * * * * The virtual netwrok database structure is implemented * * as in the following example : * * * * if input schema definition is as follow : * CatFurnish CF /*catalog of furnishings { CFid catalog_id c8 1 /*unique id of catalog_furnishing ftype furnishing_type c8 0 /*type(rug, mirror,picture) fstyle furnishing_style c8 0 /*style(rug ex:shag,rag,oriental) fdim1 furnishing_dimens1 f8 0 /*measurement across from LL pt fdim2 furnishing_dimens2 f8 0 /*measurement up from LL pt fprice furnishing_price f8 0 /*price of the furniture } FUrnishing FU /*furnishing relative to surfaces { FUid furnishing_id c8 1 /*unique id of this furnishing in db SUid surface_id c8 1 /*unique id of assoc. surface CFid catalog_of_furnish c8 1 /*unique id of assoc. catalog fdis1 furnishing_displace1 f8 0 /*(E-W)measurement for (n-s) see n1 fdis2 furnishing_displace2 f8 0 /*(N-S)measurement for (u-d) see n2 fcolor furnishing_color c12 0 /*furnishing color } HOuse HO /*list of houses with ids, styles, number of floors and rooms { HOid house_id c8 1 /*unique id of one house in the db hstyle house_style c12 0 /*style (colonial-cape-ranch) nfloors nfloors i2 0 /*number of floors in this house nrooms nrooms i2 0 /*number of rooms in this house hlength hlength f8 0 /*overall length(ft) of this house hwidth hwidth f8 0 /*overall width(ft) of this house } JointPoint JP /*the joint point of two conduit segment { JPid joint_point c8 1 /*unique id of joint_point jx joint_x_coord f8 0 /*joint point world x coordinate jy joint_y_coord f8 0 /*joint point world y coordinate jz joint_z_coord f8 0 /*joint point world z coordinate } OUtlet OU /* the outlet of the conduit { OUid outlet_id c8 1 /*unique id of outlet SUid surface_id c8 1 /*unique id of assoc. surface JPid joint_point_id c8 1 /*unique id of assoc. joint point odim1 outlet_dimension1 f8 0 /*measurement across from LL pt odim2 outlet_dimension2 f8 0 /*measurement up from LL pt } PArtition PA /*partition separating rooms from each other and outside { PAid partition_id c8 1 /*unique id of this partition in db HOid house_id c8 1 /*id of house containing partition porient part_orientation c1 0 /*N-S-E-W-U-D normal to surface pdim1 part_dimension1 f8 0 /*(E-W)measurement for (n-s)see n3 pdim2 part_dimension2 f8 0 /*(N-S)measurement for (u-d)see n4 px part_x_coord f8 0 /*x (E-W) coord of SW corner of PA py part_y_coord f8 0 /*y (N-S) coord of SW corner of PA } ROom RO /*list of rooms in each house with relative position and dimension { ROid room_id c8 1 /*uniue id of room in db HOid house_id c8 1 /*unique id of house containing rtype room_type c12 0 /*type of room (kitchen, bedroom) rwidth room_width f8 0 /*width of room in E-W direction rdepth room_depth f8 0 /*depth of room in N-S direction rx room_x_coord f8 0 /*x (E-W) world coord.of SW corner ry room_y_coord f8 0 /*y (N-S) world coord.of SW corner } SUrface SU /*surfaces relate partitions to rooms(min 6-room, 2-partion) { SUid surface_id c8 1 /*unique id of this surface in db ROid room_id c8 1 /*unique id of adj. room PAid partiton_id c8 1 /*unique id of adj. partition(1) scolor color_name c12 0 /*color name of the surface } We can represent the above tables by the following diagram: ----------- | H O | ----------- / \ / \ /\ /\ ------- ------- | P A | | R O | ------- ------- \ / \ / \ / /\ /\ ------------ ------ | S U | ------- | JP | ------------ | CF | ------ / \ ------- \ / \ / \ / \ / \ / \ / /\ /\ /\ /\ ------------ ----------- | O U | | F U | ------------ ------------ According to this diagram, we construct our intending output as follows: struct CF /*catalog of furnishings { char CFid[9] ; /*unique id of catalog_furnishing char ftype[9] ; /*type(rug, mirror,picture) char fstyle[9] ; /*style(rug ex:shag,rag,oriental) float fdim1 ; /*measurement across from LL pt float fdim2 ; /*measurement up from LL pt float fprice ; /*price of the furniture struct FY *FYid_fcptr ; struct FY *FYid_bcptr ; struct FU *FUid_fcptr ; struct FU *FUid_bcptr ; struct CF *prev_ptr ; struct CF *next_ptr ; } *CF = NULL , *CFcurr = NULL , *CFtemp = NULL ; struct FU /*furnishing relative to surfaces { char FUid[9] ; /*unique id of this furnishing in db char SUid[9] ; /*unique id of assoc. surface char CFid[9] ; /*unique id of assoc. catalog float fdis1 ; /*(E-W)measurement for (n-s) see n1 float fdis2 ; /*(N-S)measurement for (u-d) see n2 char fcolor[13] ; /*furnishing color struct CF *CFid_pptr ; -- pointer to parent CF struct dummy_type *CFid_fpptr ; -- pointer for building forward link list chain under same parent -- It points to either next sibling of this chain or it parent CF if it is the last sibling. struct dummy_type *CFid_bpptr ; -- pointer for building backward link list chain under same parent -- It points to either next sibling of this chain or it parent CF if it is the first sibling. struct SU *SUid_pptr ; struct dummy_type *SUid_fpptr ; struct dummy_type *SUid_bpptr ; struct FU *prev_ptr ; -- backward pointer for all the occurence of struct FU struct FU *next_ptr ; -- forward pointer for all the occurence of struct FU } *FU = NULL , *FUcurr = NULL , *FUtemp = NULL ; struct HO /*list of houses with ids, styles, number of { char HOid[9] ; /*unique id of one house in the db char hstyle[13] ; /*style (colonial-cape-ranch) int nfloors ; /*number of floors in this house int nrooms ; /*number of rooms in this house float hlength ; /*overall length(ft) of this house float hwidth ; /*overall width(ft) of this house struct UT *UTid_fcptr ; struct UT *UTid_bcptr ; struct SS *SSid_fcptr ; struct SS *SSid_bcptr ; struct RO *ROid_fcptr ; struct RO *ROid_bcptr ; struct PA *PAid_fcptr ; struct PA *PAid_bcptr ; struct HO *prev_ptr ; struct HO *next_ptr ; } *HO = NULL , *HOcurr = NULL , *HOtemp = NULL ; struct JP /*the joint point of two conduit segment { char JPid[9] ; /*unique id of joint_point float jx ; /*joint point world x coordinate float jy ; /*joint point world y coordinate float jz ; /*joint point world z coordinate struct OU *OUid_fcptr ; struct OU *OUid_bcptr ; struct CJ *CJid_fcptr ; struct CJ *CJid_bcptr ; struct JP *prev_ptr ; struct JP *next_ptr ; } *JP = NULL , *JPcurr = NULL , *JPtemp = NULL ; struct OU /* the outlet of the conduit { char OUid[9] ; /*unique id of outlet char SUid[9] ; /*unique id of assoc. surface char JPid[9] ; /*unique id of assoc. joint point float odim1 ; /*measurement across from LL pt float odim2 ; /*measurement up from LL pt struct JP *JPid_pptr ; struct dummy_type *JPid_fpptr ; struct dummy_type *JPid_bpptr ; struct SU *SUid_pptr ; struct dummy_type *SUid_fpptr ; struct dummy_type *SUid_bpptr ; struct OU *prev_ptr ; struct OU *next_ptr ; } *OU = NULL , *OUcurr = NULL , *OUtemp = NULL ; struct PA /*partition separating rooms from each other { char PAid[9] ; /*unique id of this partition in db char HOid[9] ; /*id of house containing partition char porient[2] ; /*N-S-E-W-U-D normal to surface float pdim1 ; /*(E-W)measurement for (n-s)see n3 float pdim2 ; /*(N-S)measurement for (u-d)see n4 float px ; /*x (E-W) coord of SW corner of PA float py ; /*y (N-S) coord of SW corner of PA struct HO *HOid_pptr ; struct dummy_type *HOid_fpptr ; struct dummy_type *HOid_bpptr ; struct SU *SUid_fcptr ; struct SU *SUid_bcptr ; struct CS *CSid_fcptr ; struct CS *CSid_bcptr ; struct AP *APid_fcptr ; struct AP *APid_bcptr ; struct PA *prev_ptr ; struct PA *next_ptr ; } *PA = NULL , *PAcurr = NULL , *PAtemp = NULL ; struct RO /*list of rooms in each house with relative { char ROid[9] ; /*uniue id of room in db char HOid[9] ; /*unique id of house containing room char rtype[13] ; /*type of room (kitchen, bedroom) float rwidth ; /*width of room in E-W direction float rdepth ; /*depth of room in N-S direction float rx ; /*x (E-W) world coord.of SW corner float ry ; /*y (N-S) world coord.of SW corner struct HO *HOid_pptr ; struct dummy_type *HOid_fpptr ; struct dummy_type *HOid_bpptr ; struct SU *SUid_fcptr ; -- pointer for building forward link list chain ; -- It points to it first child SU. struct SU *SUid_bcptr ; -- pointer for building backward link list chain ; -- It points to it last child SU. struct RO *prev_ptr ; struct RO *next_ptr ; } *RO = NULL , *ROcurr = NULL , *ROtemp = NULL ; struct SU /*surfaces relate partitions to rooms { char SUid[9] ; /*unique id of this surface in db char ROid[9] ; /*unique id of adj. room(exactly 1) char PAid[9] ; /*unique id of adj. partition(1) char scolor[13] ; /*color name of the surface struct PA *PAid_pptr ; struct dummy_type *PAid_fpptr ; struct dummy_type *PAid_bpptr ; struct RO *ROid_pptr ; struct dummy_type *ROid_fpptr ; struct dummy_type *ROid_bpptr ; struct OU *OUid_fcptr ; struct OU *OUid_bcptr ; struct FU *FUid_fcptr ; struct FU *FUid_bcptr ; struct SU *prev_ptr ; struct SU *next_ptr ; } *SU = NULL , *SUcurr = NULL , *SUtemp = NULL ; The input schema.txt file should follow the convention : Every comment should be complete (terminated) in one line ,i,e, exceed screen width without a new-line or in multiple line while each comment line end with " star back_slash " plus a " new_line. " /**************************************************************************/ #include #define BUFSIZE 256 /* max buffer length of */ #define NAMELENGTH 20 /* max length of name */ #define MAXFIELDNO 20 /* max no of fields within a table */ #define ABBREV_NAME_LENGTH 3 /* length of abbrev_name in the schema table */ #define SPACE ' ' #define TAB '\t' #define NEWLINE '\n' #define EOS '\0' /* end of string */ #define SCHEMA_HEADER_FILE_NAME_LENGTH 30 #define PATH_NUMBER 10 /* max number of track save */ #define MAX_TAB_NUMBER 50 /* max number of table */ #define HASHSIZE 26 /* number of A..Z */ struct rr_type /* object to hold parent-child/child-parent relation */ { char firstid[NAMELENGTH] ; char secondid[NAMELENGTH] ; struct rr_type *next_ptr ; } ; struct cell_type { int path_length[ PATH_NUMBER ] ; char path_track [ PATH_NUMBER ] [ MAX_TAB_NUMBER * 2 ] ; } rr_matrix [ MAX_TAB_NUMBER ] [MAX_TAB_NUMBER ] ; struct rr_type *pc_table = NULL ; /* parent-child table */ struct rr_type *cp_table = NULL ; /* child-parent table */ FILE *fp1, *fp2, *fp3, *fopen(); int table_seq_no ; main(argc,argv) int argc; char *argv[]; { char schema_header_file_name[SCHEMA_HEADER_FILE_NAME_LENGTH] ; int i ; /* schema_header_file_name in the begining is the same with schema.txt file name which is keyed in by the user . But sooner we change its file extention from ".txt" (or anything else ) to ".h" . */ if (argc != 2) { printf(" Lack one schema definition file name\n"); exit(1); } else { if ((fp1=fopen(argv[1],"r")) == NULL) { printf("can not open %s\n", argv[1]); exit(1); } if ( (strlen (argv[1]) > SCHEMA_HEADER_FILE_NAME_LENGTH )) { printf (" error : \n" ); printf (" input schema_file_name_length > 30 column \n"); exit(2) ; } else strcpy ( schema_header_file_name, argv[1] ) ; /* convert extension of schema_text_file_name from "txt" to "h" */ for ( i = 0 ;; i++ ) { if ( ( schema_header_file_name[ i + 1 ] == '.' ) || ( schema_header_file_name[ i + 1 ] == '\0' ) ) { schema_header_file_name[ i + 1 ] = '.' ; schema_header_file_name[ i + 2 ] = 'h' ; schema_header_file_name[ i + 3 ] = '\0' ; break ; } } if ((fp2=fopen(schema_header_file_name, "w")) == NULL ) { printf(" Can not open output file \n", schema_header_file_name); exit(3); } } /* DATA DECLARATION of .H FILE */ fprintf (fp2, "/*\n This .H file is generated by H_GEN.C from %s\n", argv[1]); fprintf (fp2, " H_GEN.C is suitable for free_format schema.txt \n"); fprintf (fp2, " While old version H_GEN_BAK is suitable only for fixed format schema.txt \n"); fprintf (fp2, " Modify by TCHENG & CCHOU 07/JULY 1989 \n*/\n\n"); fprintf (fp2, "#define schema_text_file_name %s\n", argv[1]) ; fprintf (fp2, "#define schema_header_file_name %s\n\n", schema_header_file_name ) ; fprintf(fp2, "#define BUFSIZE %d\n", BUFSIZE); fprintf(fp2, "#define NAMELENGTH %d\n", NAMELENGTH); fprintf(fp2, "#define MAXFIELDNO %d\n", MAXFIELDNO); fprintf(fp2, "#define ABBREV_NAME_LENGTH %d\n\n", ABBREV_NAME_LENGTH); fprintf(fp2, "FILE *hcg_fp1 , *hcg_fp2 ;\n\n"); fprintf(fp2, "struct dummy_type {\n\tint dummy ;\n} ;\n\n"); fprintf(fp2, "struct hcg_table_seq_list_type {\n"); fprintf(fp2, "\tchar ttabbrev[ABBREV_NAME_LENGTH] ;\n"); fprintf(fp2, "\tstruct hcg_table_seq_list_type *next_ptr ;\n"); fprintf(fp2, "} *hcg_table_seq_list = NULL, *hcg_curr_table_ptr ;\n\n"); fprintf(fp2, "static char hcg_s[ABBREV_NAME_LENGTH] = \" \" ;\n"); fprintf(fp2, "char hcg_dummy_char , hcg_buffer[BUFSIZE] , hcg_t[MAXFIELDNO][NAMELENGTH] ;\n\n"); prescan (); write_rr_table () ; gen_rr_matrix(rr_matrix) ; gen_macros (); /* close fp1 and reopen so as to reposition pointer to the beginning */ fclose(fp1); if ((fp1=fopen(argv[1],"r")) == NULL) { printf("can not open %s\n", argv[1]); exit(4); } read_and_write (); fclose(fp1); fclose(fp2); } /**************************************************************** * * * function name : write_rr_table * * * * This function writes pc_table and cp_table entries to * * schema.h as its first 2 leading comments. * * * * P.S. the two table will be need in C_GEN.C for generate * * pr_load * * * * input : none; * * output : the first part of schema.h (pc_table and cp_table * * entries; * * * ****************************************************************/ write_rr_table () { struct rr_type *tmp ; fprintf(fp2 , "/* pc_table entries : parent followed by child\n"); tmp = pc_table; while (tmp != NULL) { fprintf ( fp2 , "%s:%s\n", tmp->firstid , tmp->secondid ); tmp = tmp->next_ptr; } fprintf(fp2 , "*/\n"); fprintf(fp2 , "/* cp_table entries : child followed by parent \n"); tmp = cp_table; while (tmp != NULL) { fprintf ( fp2 , "%s:%s\n", tmp->firstid , tmp->secondid ); tmp = tmp->next_ptr; } fprintf(fp2 , "*/\n\n"); } /**************************************************************** * * * Revised 11/JULY/89 by Chou & Cheng * * Added some code to build field_list which pointed by * * fhashtab * * * * * * function name : prescan * * * * * * This function scans the input schema definition text; * * It skips anything except table fields such that they are * * foreign keys. If a foreign key is scanned, a new entry is * * inserted into the pc_table (which holds parent-child * * relations) and cp_table as well, sorted by the parent name or * * the child name, depending on which table is reffered. * * * * input : schema definition text; * * output : pc_table, cp_table; * * * ****************************************************************/ char buffer[BUFSIZE], s1[NAMELENGTH], s2[NAMELENGTH], s3[NAMELENGTH],s4[NAMELENGTH], s5[NAMELENGTH], tab_id[NAMELENGTH], tab_abbrev[ABBREV_NAME_LENGTH]; struct field_list { int tab_seq_no ; int field_seq_no ; char field_name [MAXFIELDNO][NAMELENGTH] ; }; struct field_list hashtab[HASHSIZE][HASHSIZE]; char *j ; int i, k , table_begin , field_seq_no , hash_val_1 , hash_val_2 ; prescan () { struct rr_type *obj_ptr ; read_next(); k = 1 ; table_seq_no = 0 ; field_seq_no = 0 ; table_begin = 0 ; while ( !feof ( fp1 ) ) { sscanf ( buffer , "%s %s %s %s %s" , s1, s2, s3, s4, s5 ) ; /* handle s4 .EQ. space & "id" in s1 ( added 89/7/7 by Chou & Cheng */ if( strcmp ( s4, "\0" ) == 0 ) { if ( ( s1[2] == 'i' ) && ( s1[3] == 'd' ) ) { s4[0] = '1'; s4[1] = '\0'; } } switch ( s1 [ 0 ] ) { /* case of table ends */ case '}' : k = 1 ; table_begin = 0 ; field_seq_no = 0 ; read_next(); break ; /* case of table beginnings, goes to default */ case '{' : table_begin = 1 ; /* case of comments, goes to default */ case '/' : case EOS : read_next(); break ; default : /* case of skipping line between tables */ if ( table_begin == 0 ) { read_next(); break ; } /* case of scanning table fields;, that is, scanning the things between begin of table '{' and end of table '}' */ if ( k == 1 ) /* first row of this table */ { strcpy ( tab_id, s1, 2 ) ; hash_val_1 = (int) (s1[0] - 'A' ); hash_val_2 = (int) (s1[1] - 'A' ); hashtab[hash_val_1][hash_val_2].tab_seq_no = table_seq_no ; table_seq_no++; field_seq_no = 0 ; } else if ( strcmp ( s4 , "1" ) == 0 ) /* encounter foreign key */ { obj_ptr = (struct rr_type *) make_rr_object ( s1 , tab_id ) ; pc_table = (struct rr_type *) rr_insert ( obj_ptr , pc_table ); obj_ptr = (struct rr_type *) make_rr_object ( tab_id, s1 ) ; cp_table = (struct rr_type *) rr_insert ( obj_ptr , cp_table ); } strcpy (hashtab[hash_val_1][hash_val_2]. field_name[field_seq_no], s1 ); hashtab[hash_val_1][hash_val_2].field_seq_no = field_seq_no ; field_seq_no++; read_next(); k++ ; break ; } } } /**************************************************************** * * * function name : gen_rr_matrix * * * * The function build a two dimension rr_matrix which holds * * at most ten path_track from the same child table to it * * ancestor table. * * * * ****************************************************************/ gen_rr_matrix ( rr_matrix ) struct cell_type rr_matrix[][MAX_TAB_NUMBER] ; { char parent_abbrev[ABBREV_NAME_LENGTH],child_abbrev[ABBREV_NAME_LENGTH]; char path_history[MAX_TAB_NUMBER * 2 + 1] ; /* multiply 2 because each tab_abbrev_name is two char, ex "AP" plus 1 , for the null char of path_history. struct rr_type *obj_ptr , *curr_ptr ; int i , j , x , y ; /* initialize rr_matrix */ for ( i = 0 ; i < table_seq_no ; i++) for ( j = 0 ; j < table_seq_no ; j++ ) for ( k = 0 ; k < PATH_NUMBER ; k++ ) { rr_matrix[i][j].path_length[k]=0; rr_matrix[i][j].path_track[k][0]='\0'; } curr_ptr = cp_table ; while (curr_ptr != NULL) { path_history[0] = curr_ptr->firstid[0] ; path_history[1] = curr_ptr->firstid[1] ; path_history[2] = curr_ptr->secondid[0] ; path_history[3] = curr_ptr->secondid[1] ; path_history[4] = '\0' ; /* mark the end of path history */ /* save child_name and parent_name used laterly as parameters for gen_path */ child_abbrev[0] = curr_ptr->firstid[0] ; child_abbrev[1] = curr_ptr->firstid[1] ; child_abbrev[2] = '\0' ; parent_abbrev[0] = curr_ptr->secondid[0] ; parent_abbrev[1] = curr_ptr->secondid[1] ; parent_abbrev[2] = '\0' ; /* get the matrix index x , y */ hash_val_1 = (int) (curr_ptr->firstid[0] - 'A'); hash_val_2 = (int) (curr_ptr->firstid[1] - 'A'); x = hashtab[hash_val_1][hash_val_2].tab_seq_no ; hash_val_1 = (int) (curr_ptr->secondid[0] - 'A') ; hash_val_2 = (int) (curr_ptr->secondid[1] - 'A') ; y = hashtab[hash_val_1][hash_val_2].tab_seq_no ; store_into_matrix(rr_matrix, x, y, 1, path_history); gen_path ( rr_matrix, path_history, child_abbrev, parent_abbrev ) ; curr_ptr = curr_ptr->next_ptr ; } } /**************************************************************** * * * function name : gen_path * * * ****************************************************************/ gen_path ( rr_matrix, path_history, path_head, target ) struct cell_type rr_matrix[][MAX_TAB_NUMBER] ; char path_history[]; char path_head[]; char target[]; { char child_abbrev[ABBREV_NAME_LENGTH] , parent_abbrev[ABBREV_NAME_LENGTH] ; struct rr_type *curr_ptr ; int i , j , x , y , cycle ; curr_ptr = cp_table ; while (curr_ptr != NULL) { child_abbrev[0] = curr_ptr->firstid[0] ; child_abbrev[1] = curr_ptr->firstid[1] ; child_abbrev[2] = '\0' ; parent_abbrev[0] = curr_ptr->secondid[0] ; parent_abbrev[1] = curr_ptr->secondid[1] ; parent_abbrev[2] = '\0' ; if(strcmp(target,child_abbrev)==0) { i = 0; cycle = 0; while(path_history[i]!='\0') { if((path_history[i]==parent_abbrev[0])&& (path_history[i+1]==parent_abbrev[1])) { cycle = 1; break; } i += 2; } if(!cycle) { path_history[i] = parent_abbrev[0]; path_history[i+1] = parent_abbrev[1]; path_history[i+2] = '\0'; /* get the matrix index x , y */ hash_val_1 = (int) (path_head[0] - 'A' ); hash_val_2 = (int) (path_head[1] - 'A' ); x = hashtab[hash_val_1][hash_val_2].tab_seq_no ; hash_val_1=(int)(curr_ptr->secondid[0] - 'A' ) ; hash_val_2=(int)(curr_ptr->secondid[1] - 'A' ) ; y = hashtab[hash_val_1][hash_val_2].tab_seq_no ; store_into_matrix(rr_matrix, x, y, i/2, path_history); gen_path(rr_matrix,path_history,path_head, parent_abbrev); path_history[i] = '\0' ; } } curr_ptr = curr_ptr->next_ptr ; } } /**************************************************************** * * * function name : store_into_matrix * * * ****************************************************************/ store_into_matrix(rr_matrix, x, y, length, path_history) struct cell_type rr_matrix[][MAX_TAB_NUMBER] ; int x, y, length ; char path_history[] ; { int i , j , k ; i = 0 ; /* Decide what's the path (first or second or 3rd ...10rd giong to be processed */ while( ( i < PATH_NUMBER ) && ( rr_matrix[x][y].path_length[i] != 0 ) && ( rr_matrix[x][y].path_length[i] < length ) ) i++; if ( i == PATH_NUMBER ) return ; else if ( rr_matrix[x][y].path_length[i] == 0 ) /* First path */ { rr_matrix[x][y].path_length[i] = length ; strcpy ( rr_matrix[x][y].path_track[i] , path_history ) ; } else { j = i ; while ( rr_matrix[x][y].path_length[j] != 0 ) j++ ; /* make the "hole" at the right place in the array */ for ( k = j ; k > i ; k-- ) { rr_matrix[x][y].path_length[k] = rr_matrix[x][y].path_length[k - 1] ; strcpy ( rr_matrix[x][y].path_track[k] , rr_matrix[x][y].path_track[k - 1] ) ; } rr_matrix[x][y].path_length[i] = length ; strcpy ( rr_matrix[x][y].path_track[i] , path_history ) ; } } gen_macros() { char child_abbrev[ABBREV_NAME_LENGTH], parent_abbrev[ABBREV_NAME_LENGTH]; int i, j, k, m, n ; for ( i = 0 ; i < table_seq_no + 1 ; i++ ) for ( j = 0 ; j < table_seq_no + 1 ; j++ ) for ( k = 0 ; k < PATH_NUMBER ; k++ ) { if (rr_matrix[i][j].path_length[k] == 0) break ; if (rr_matrix[i][j].path_length[k] >= 2) { strncpy ( child_abbrev, rr_matrix[i][j].path_track[k], 2 ) ; strcpy ( parent_abbrev, &(rr_matrix[i][j].path_track[k][ rr_matrix[i][j].path_length[k] * 2]) ) ; hash_val_1 = (int) ( parent_abbrev[0] - 'A' ) ; hash_val_2 = (int) ( parent_abbrev[1] - 'A' ) ; for(n = 0 ; n < hashtab[hash_val_1][hash_val_2].field_seq_no+1; n++) { fprintf ( fp2, "#define " ); fprintf ( fp2, "%c%cptr->%s\t", child_abbrev[0], child_abbrev[1], hashtab[hash_val_1][hash_val_2].field_name[n] ); m = 0 ; while ( m < 2 * rr_matrix[i][j].path_length[k] + 2 ) { fprintf ( fp2, "%c%cpptr->", rr_matrix[i][j].path_track[k][m], rr_matrix[i][j].path_track[k][m+1] ) ; m += 2 ; } fprintf ( fp2, "%s\n", hashtab[hash_val_1][hash_val_2].field_name[n] ); } } } } /**************************************************************** * * * function : read_and_write * * * * This function scans the input schema definition text * * and write corresponding output to schema.h. * * * * input : schema definition text; * * output : the second part of schema.h (the data structure * * declaration); * * * * This function has been modified by TCHENG 12 JUNE.1989 * * After modify , H_GEN is suitable for free_format schema.txt * * * * use STRCHR replace user define function LOCATE_COMMENT * * * * Modified by cchou 06/28/89. It is again portable from VMS to * * UNIX. * ****************************************************************/ read_and_write () { int dimension, index ; read_next(); k = 1 ; table_begin = 0 ; while ( !feof ( fp1 ) ) { sscanf ( buffer , "%s%s%s%s%s" , s1, s2, s3, s4, s5 ) ; /* handle s2 .EQ. space. (added 89/7/8 by Cheng & Chou) */ if ( strcmp ( s2, "\0" ) == 0 ) strcpy ( s2, s1 ) ; /* handle s3 .EQ. space. (added 89/7/8 by Cheng & Chou) */ if ( strcmp ( s3, "\0" ) == 0 ) { s3[0] = 'c'; s3[1] = '8'; s3[2] = '\0'; } /* handle s4 .EQ. space. (added 89/7/8 by Cheng & Chou) */ if( strcmp ( s4, "\0" ) == 0 ) { if ( ( s1[2] == 'i' ) && ( s1[3] == 'd' ) ) { s4[0] = '1'; s4[1] = '\0'; } } switch ( s1 [ 0 ] ) { /* case of table ends */ case '}' : make_pptr ( tab_id, cp_table) ; make_cptr ( tab_id, pc_table) ; fprintf( fp2 , "struct %c%c *prev_ptr ; \n" , tab_id[0], tab_id[1]) ; fprintf( fp2 , "struct %c%c *next_ptr ; \n" , tab_id[0],tab_id[1]) ; fprintf ( fp2 , "} *%c%c = NULL ," , tab_id[0],tab_id[1]) ; fprintf ( fp2 , " *%c%ccurr = NULL ," , tab_id[0],tab_id[1]) ; fprintf ( fp2 , " *%c%ctemp = NULL ;\n\n" , tab_id[0],tab_id[1]) ; k = 1 ; table_begin = 0 ; read_next(); break ; /* case of table beginnings */ case '{' : table_begin = 1 ; fprintf ( fp2 , "{\n" ) ; read_next(); break ; /* case of comments */ case '/' : if ( table_begin == 0 ) fprintf(fp2, "%s" , buffer ) ; else fprintf(fp2, "\t\t\t%s",buffer); case EOS : case NEWLINE : read_next(); break ; /* case of scanning table fields;, that is, scanning the things between begin of table '{' and end of table '}' */ default : if ( table_begin == 0 ) { fprintf(fp2, "struct %s", s2); if ( strlen(s3) != 0 ) { #ifdef strchr j = strchr (buffer,'/') ; if ( (j + 1) == strchr (buffer,'*')) fprintf(fp2, "\t\t\t%s", j); #else index = locate_comment(buffer) ; if( index < (BUFSIZE - 1)) fprintf(fp2, "\t\t\t%s", &(buffer[index])) ; #endif } else fprintf(fp2, "\n"); read_next(); break ; } if ( k == 1 ) /* first row of this table */ strcpy ( tab_id, s1 ) ; switch ( s3[0] ) { case 'i' : fprintf(fp2,"int %s ;",s1) ; break ; case 'f' : fprintf(fp2,"float %s ;",s1) ; break ; case 'c' : case 't' : dimension = 1 + atoi ( &(s3[1]) ) ; fprintf(fp2,"char %s[%d] ;", s1,dimension) ; break ; } if ( strlen(s5) != 0 ) { #ifdef strchr j = strchr (buffer,'/') ; if ( (j + 1) == strchr (buffer,'*')) fprintf(fp2, "\t\t\t%s", j); #else index = locate_comment(buffer) ; if( index < (BUFSIZE - 1)) fprintf(fp2, "\t\t\t%s", &(buffer[index])) ; #endif } else fprintf(fp2, "\n"); read_next(); k++ ; break ; } } } /**************************************************************** * * * This function clear input buffer and target string . * * fgets next line * * added at 8 June 1989. * *****************************************************************/ read_next() { for ( i = 0 ; i < BUFSIZE ; i++ ) buffer [i] = '\0' ; s1[0] = '\0' ; s2[0] = '\0' ; s3[0] = '\0' ; s4[0] = '\0' ; s5[0] = '\0' ; fgets ( buffer , BUFSIZE , fp1 ) ; } /**************************************************************** * * * function name : locate_comment * * * * This function returns the index of where comment starts in * * the buffer array. * * * *****************************************************************/ locate_comment(buffer) char buffer[] ; { int i ; for ( i = 0 ; i < BUFSIZE - 1 ; i++ ) { if ( ( buffer [ i ] == '/' ) && ( buffer [ i + 1 ] == '*' ) ) break ; } return i ; } /**************************************************************** * * * function name : make_rr_object * * * * This function returns an object of rr_type which hold * * the content of firstid (e.g. parent id/child id) with its * * firstid field and secondid (e.g. child id/parent id) with its * * secondid field. It also intialize the next_ptr to NULL. * * * * input : firstid, secondid; * * output : object of rr_type; * * * ****************************************************************/ make_rr_object ( firstid , secondid ) char firstid[] , secondid[] ; { struct rr_type *obj_ptr ; obj_ptr = ( struct rr_type* ) malloc ( sizeof ( struct rr_type ) ) ; strcpy (obj_ptr->firstid , firstid ) ; strcpy (obj_ptr->secondid , secondid ) ; obj_ptr->next_ptr = NULL ; return (int) obj_ptr ; } /**************************************************************** * * * function name : rr_insert * * * * This function inserts a new entry into pc_table or * * cp_table. * * * * input : object to be inserted, table to insert; * * output : table after insertion; * * * ****************************************************************/ rr_insert ( obj_ptr , table_head ) struct rr_type *obj_ptr , *table_head ; { struct rr_type *previous_ptr , *current_ptr ; current_ptr = table_head ; if ( table_head == NULL ) table_head = obj_ptr ; else { previous_ptr = current_ptr ; while ( ( current_ptr != NULL ) && ( strcmp ( current_ptr->firstid , obj_ptr->firstid ) < 0 ) ) /* traversing the link list sorted in ascending order by the 1st field of a rr_type object and searching for the right position to insert */ { previous_ptr = current_ptr ; current_ptr = current_ptr->next_ptr ; } if ( current_ptr == table_head ) /* new entry to be inserted in front of the link list */ { obj_ptr->next_ptr = current_ptr ; table_head = obj_ptr ; } else { previous_ptr->next_ptr = obj_ptr ; obj_ptr->next_ptr = current_ptr ; } } return (int) table_head ; } /**************************************************************** * * * function name : make_pptr * * * * This function writes the needed data structure * * declaration of next-child-or-parent pointer links for all * * parents of current_table. (This is done in both forward and * * backward direction) * * The data structures of direct pointers to parents are also * * declared. * * * * input : cp_table; * * output : the declaration for links to next-child or parent; * * * ****************************************************************/ make_pptr ( current_table ,cp_table ) struct rr_type *cp_table ; char current_table[] ; { struct rr_type *tmp_ptr ; /* to hold the current position */ tmp_ptr = cp_table ; while ( tmp_ptr ) /* not end of list */ if ( strcmp ( current_table , tmp_ptr->firstid ) > 0 ) tmp_ptr = tmp_ptr->next_ptr ; else if ( strcmp ( current_table , tmp_ptr->firstid ) == 0 ) { fprintf ( fp2 , "struct %c%c *%s_pptr ;\n", tmp_ptr->secondid[0], tmp_ptr->secondid[1] , tmp_ptr->secondid ) ; fprintf ( fp2 , "union {\n\tstruct %c%c *ptr0 ;\n\tstruct %c%c *ptr1 ;\n\t} *%s_fpptr ;\n", current_table[0] , current_table[1] , tmp_ptr->secondid[0], tmp_ptr->secondid[1] , tmp_ptr->secondid ) ; fprintf ( fp2 , "int %s_fpptr_border_flag ;\n", tmp_ptr->secondid ) ; fprintf ( fp2 , "union {\n\tstruct %c%c *ptr0 ;\n\tstruct %c%c *ptr1 ;\n\t} *%s_bpptr ;\n", current_table[0] , current_table[1] , tmp_ptr->secondid[0], tmp_ptr->secondid[1] , tmp_ptr->secondid ) ; fprintf ( fp2 , "int %s_bpptr_border_flag ;\n", tmp_ptr->secondid ) ; tmp_ptr = tmp_ptr->next_ptr ; } else /* no more chance have matched_name in cp_table */ break ; } /**************************************************************** * * * function name : make_cptr * * * * This function writes the needed data structure for * * pointer links to all children of current_table. (This is * * done in both forward and backward direction) * * * * input : pc_table; * * output : the declaration for links to children ; * * * ****************************************************************/ make_cptr ( current_table, pc_table ) struct rr_type *pc_table ; char current_table[] ; { struct rr_type *tmp_ptr ; /* to hold the current position */ tmp_ptr = pc_table ; while ( tmp_ptr ) /* not end of list */ if ( strcmp ( current_table , tmp_ptr->firstid ) > 0 ) tmp_ptr = tmp_ptr->next_ptr ; else if ( strcmp ( current_table , tmp_ptr->firstid ) == 0 ) { fprintf ( fp2 , "struct %c%c *%s_fcptr ;\n", tmp_ptr->secondid[0], tmp_ptr->secondid[1], tmp_ptr->secondid ) ; fprintf ( fp2 , "struct %c%c *%s_bcptr ;\n", tmp_ptr->secondid[0] , tmp_ptr->secondid[1] , tmp_ptr->secondid ) ; tmp_ptr = tmp_ptr->next_ptr ; } else /* no more chance have matched_name in the pc_table */ break ; }