#include <stdio.h>
#include <stdlib.h>
#include "binding.h"
#include "db.h"
#include "defines.h"
#include "info.h"
#include "link.h"
#include "merge.h"
#include "sim.h"
#include "util.h"
Functions | |
static void | merge_usage () |
static bool | merge_parse_args (int argc, int last_arg, const char **argv) |
void | merge_check () |
void | command_merge (int argc, int last_arg, const char **argv) |
Parses command-line for merge options and performs merge command. | |
Variables | |
db ** | db_list |
unsigned int | curr_db |
int | merged_code |
char | user_msg [USER_MSG_LENGTH] |
char * | cdd_message |
char * | merged_file = NULL |
str_link * | merge_in_head = NULL |
str_link * | merge_in_tail = NULL |
str_link * | merge_in_cl_last = NULL |
int | merge_in_num = 0 |
int | merge_er_value = MERGE_ER_NONE |
void command_merge | ( | int | argc, | |
int | last_arg, | |||
const char ** | argv | |||
) |
Parses command-line for merge options and performs merge command.
Performs merge command functionality.
argc | Number of arguments in command-line to parse | |
last_arg | Index of last parsed argument from list | |
argv | List of arguments from command-line to parse |
References bind_perform(), Catch_anonymous, COVERED_HEADER, curr_db, db_close(), db_merge_instance_trees(), db_read(), db_write(), FALSE, free_safe, HEADER, db_s::leading_hier_num, merge_check(), merge_parse_args(), merged_file, str_link_s::next, NORMAL, print_output(), PROFILE, PROFILE_END, READ_MODE_MERGE_NO_MERGE, str_link_s::str, str_link_delete_list(), str_link_s::suppl, Throw, TRUE, Try, user_msg, and USER_MSG_LENGTH.
Referenced by main().
00355 { PROFILE(COMMAND_MERGE); 00356 00357 int i; /* Loop iterator */ 00358 unsigned int rv; /* Return value from snprintf calls */ 00359 bool error = FALSE; 00360 00361 /* Output header information */ 00362 rv = snprintf( user_msg, USER_MSG_LENGTH, COVERED_HEADER ); 00363 assert( rv < USER_MSG_LENGTH ); 00364 print_output( user_msg, HEADER, __FILE__, __LINE__ ); 00365 00366 Try { 00367 00368 str_link* strl; 00369 bool stop_merging; 00370 int curr_leading_hier_num = 0; 00371 00372 /* Parse score command-line */ 00373 if( !merge_parse_args( argc, last_arg, argv ) ) { 00374 00375 /* Check if merge could be executed */ 00376 merge_check(); 00377 00378 /* Read in base database */ 00379 rv = snprintf( user_msg, USER_MSG_LENGTH, "Reading CDD file \"%s\"", merge_in_head->str ); 00380 assert( rv < USER_MSG_LENGTH ); 00381 print_output( user_msg, NORMAL, __FILE__, __LINE__ ); 00382 if( !db_read( merge_in_head->str, READ_MODE_MERGE_NO_MERGE ) ) { 00383 00384 /* The read in CDD was empty so mark it as such */ 00385 merge_in_head->suppl = 2; 00386 00387 } else { 00388 00389 /* If the currently read CDD didn't contain any merged CDDs it is a leaf CDD so mark it as such */ 00390 if( (db_list[curr_db]->leading_hier_num - curr_leading_hier_num) == 1 ) { 00391 merge_in_head->suppl = 1; 00392 } 00393 curr_leading_hier_num = db_list[curr_db]->leading_hier_num; 00394 00395 } 00396 00397 /* Read in databases to merge */ 00398 strl = merge_in_head->next; 00399 stop_merging = (strl == merge_in_head); 00400 while( (strl != NULL) && !stop_merging ) { 00401 rv = snprintf( user_msg, USER_MSG_LENGTH, "Merging CDD file \"%s\"", strl->str ); 00402 assert( rv < USER_MSG_LENGTH ); 00403 print_output( user_msg, NORMAL, __FILE__, __LINE__ ); 00404 if( !db_read( strl->str, READ_MODE_MERGE_NO_MERGE ) ) { 00405 00406 /* The read in CDD was empty so mark it as such */ 00407 merge_in_head->suppl = 2; 00408 00409 } else { 00410 00411 /* If we have not merged any CDD files from this CDD, this is a leaf CDD so mark it as such */ 00412 if( (db_list[curr_db]->leading_hier_num - curr_leading_hier_num) == 1 ) { 00413 strl->suppl = 1; 00414 } 00415 curr_leading_hier_num = db_list[curr_db]->leading_hier_num; 00416 00417 } 00418 00419 stop_merging = (strl == merge_in_cl_last); 00420 strl = strl->next; 00421 } 00422 00423 /* Perform the tree merges */ 00424 db_merge_instance_trees(); 00425 00426 /* Bind */ 00427 bind_perform( TRUE, 0 ); 00428 00429 /* Write out new database to output file */ 00430 db_write( merged_file, FALSE, TRUE ); 00431 00432 print_output( "\n*** Merging completed successfully! ***", NORMAL, __FILE__, __LINE__ ); 00433 00434 } 00435 00436 } Catch_anonymous { 00437 error = TRUE; 00438 } 00439 00440 /* Close database */ 00441 db_close(); 00442 00443 /* Deallocate other memory */ 00444 str_link_delete_list( merge_in_head ); 00445 free_safe( merged_file, (strlen( merged_file ) + 1) ); 00446 00447 if( error ) { 00448 Throw 0; 00449 } 00450 00451 PROFILE_END; 00452 00453 }
void merge_check | ( | ) |
Check number of merged files.
References FATAL, merge_in_num, merged_file, str_link_s::next, print_output(), PROFILE, PROFILE_END, and Throw.
Referenced by command_merge().
00318 { PROFILE(MERGE_CHECK); 00319 00320 str_link* strl; 00321 00322 /* Make sure that we have at least 2 files to merge */ 00323 strl = merge_in_head; 00324 while( strl != NULL ) { 00325 merge_in_num++; 00326 strl = strl->next; 00327 } 00328 00329 /* Check to make sure that the user specified at least two files to merge */ 00330 if( merge_in_num < 2 ) { 00331 print_output( "Must specify at least two CDD files to merge", FATAL, __FILE__, __LINE__ ); 00332 Throw 0; 00333 } 00334 00335 /* 00336 If no -o option was specified and no merge files were specified, don't presume that the first file found in 00337 the directory will be that file. 00338 */ 00339 if( merged_file == NULL ) { 00340 print_output( "Must specify the -o option or a specific CDD file for containing the merged results", FATAL, __FILE__, __LINE__ ); 00341 Throw 0; 00342 } 00343 00344 PROFILE_END; 00345 00346 }
static bool merge_parse_args | ( | int | argc, | |
int | last_arg, | |||
const char ** | argv | |||
) | [static] |
anonymous | Throw Throw Throw |
Parses the merge argument list, placing all parsed values into global variables. If an argument is found that is not valid for the merge operation, an error message is displayed to the user.
argc | Number of arguments in argument list argv | |
last_arg | Index of last parsed argument from list | |
argv | Argument list passed to this program |
References Catch_anonymous, cdd_message, check_option_value(), directory_exists(), directory_load(), FALSE, FATAL, file_exists(), free_safe, get_absolute_path(), is_legal_filename(), MERGE_ER_ALL, MERGE_ER_FIRST, MERGE_ER_LAST, MERGE_ER_NEW, MERGE_ER_OLD, merge_er_value, merge_usage(), merged_file, str_link_s::next, print_output(), read_command_file(), str_link_s::str, str_link_add(), str_link_delete_list(), strdup_safe, Throw, TRUE, Try, user_msg, USER_MSG_LENGTH, and WARNING.
Referenced by command_merge().
00134 { 00135 00136 int i; 00137 str_link* strl; 00138 str_link* ext_head = NULL; 00139 str_link* ext_tail = NULL; 00140 str_link* dir_head = NULL; 00141 str_link* dir_tail = NULL; 00142 bool help_found = FALSE; 00143 00144 i = last_arg + 1; 00145 00146 while( (i < argc) && !help_found ) { 00147 00148 if( strncmp( "-h", argv[i], 2 ) == 0 ) { 00149 00150 merge_usage(); 00151 help_found = TRUE; 00152 00153 } else if( strncmp( "-o", argv[i], 2 ) == 0 ) { 00154 00155 if( check_option_value( argc, argv, i ) ) { 00156 i++; 00157 if( is_legal_filename( argv[i] ) ) { 00158 merged_file = strdup_safe( argv[i] ); 00159 } else { 00160 unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Output file \"%s\" is not writable", argv[i] ); 00161 assert( rv < USER_MSG_LENGTH ); 00162 print_output( user_msg, FATAL, __FILE__, __LINE__ ); 00163 Throw 0; 00164 } 00165 } else { 00166 Throw 0; 00167 } 00168 00169 } else if( strncmp( "-f", argv[i], 2 ) == 0 ) { 00170 00171 if( check_option_value( argc, argv, i ) ) { 00172 char** arg_list = NULL; 00173 int arg_num = 0; 00174 unsigned int j; 00175 i++; 00176 Try { 00177 read_command_file( argv[i], &arg_list, &arg_num ); 00178 help_found = merge_parse_args( arg_num, -1, (const char**)arg_list ); 00179 } Catch_anonymous { 00180 for( j=0; j<arg_num; j++ ) { 00181 free_safe( arg_list[j], (strlen( arg_list[j] ) + 1) ); 00182 } 00183 free_safe( arg_list, (sizeof( char* ) * arg_num) ); 00184 Throw 0; 00185 } 00186 for( j=0; j<arg_num; j++ ) { 00187 free_safe( arg_list[j], (strlen( arg_list[j] ) + 1) ); 00188 } 00189 free_safe( arg_list, (sizeof( char* ) * arg_num) ); 00190 } else { 00191 Throw 0; 00192 } 00193 00194 } else if( strncmp( "-d", argv[i], 2 ) == 0 ) { 00195 00196 if( check_option_value( argc, argv, i ) ) { 00197 i++; 00198 if( directory_exists( argv[i] ) ) { 00199 (void)str_link_add( strdup_safe( argv[i] ), &dir_head, &dir_tail ); 00200 } else { 00201 unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Specified -d directory (%s) does not exist", argv[i] ); 00202 assert( rv < USER_MSG_LENGTH ); 00203 print_output( user_msg, FATAL, __FILE__, __LINE__ ); 00204 Throw 0; 00205 } 00206 } else { 00207 Throw 0; 00208 } 00209 00210 } else if( strncmp( "-er", argv[i], 3 ) == 0 ) { 00211 00212 if( check_option_value( argc, argv, i ) ) { 00213 i++; 00214 if( strncmp( "first", argv[i], 5 ) == 0 ) { 00215 merge_er_value = MERGE_ER_FIRST; 00216 } else if( strncmp( "last", argv[i], 4 ) == 0 ) { 00217 merge_er_value = MERGE_ER_LAST; 00218 } else if( strncmp( "all", argv[i], 3 ) == 0 ) { 00219 merge_er_value = MERGE_ER_ALL; 00220 } else if( strncmp( "new", argv[i], 3 ) == 0 ) { 00221 merge_er_value = MERGE_ER_NEW; 00222 } else if( strncmp( "old", argv[i], 3 ) == 0 ) { 00223 merge_er_value = MERGE_ER_OLD; 00224 } else { 00225 unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Illegal value to use for the -er option (%s). Valid values are: first, last, all, new, old", argv[i] ); 00226 assert( rv < USER_MSG_LENGTH ); 00227 print_output( user_msg, FATAL, __FILE__, __LINE__ ); 00228 Throw 0; 00229 } 00230 } else { 00231 Throw 0; 00232 } 00233 00234 } else if( strncmp( "-ext", argv[i], 4 ) == 0 ) { 00235 00236 if( check_option_value( argc, argv, i ) ) { 00237 i++; 00238 (void)str_link_add( strdup_safe( argv[i] ), &ext_head, &ext_tail ); 00239 } else { 00240 Throw 0; 00241 } 00242 00243 } else if( strncmp( "-m", argv[i], 2 ) == 0 ) { 00244 00245 if( check_option_value( argc, argv, i ) ) { 00246 i++; 00247 if( cdd_message != NULL ) { 00248 print_output( "Only one -m option is allowed on the merge command-line. Using first value...", WARNING, __FILE__, __LINE__ ); 00249 } else { 00250 cdd_message = strdup_safe( argv[i] ); 00251 } 00252 } else { 00253 Throw 0; 00254 } 00255 00256 } else { 00257 00258 /* The name of a file to merge */ 00259 if( file_exists( argv[i] ) ) { 00260 00261 /* Create absolute filename */ 00262 char* file = get_absolute_path( argv[i] ); 00263 00264 /* If we have not specified a merge file explicitly, set it implicitly to the first CDD file found */ 00265 if( (merge_in_head == NULL) && (merged_file == NULL) ) { 00266 merged_file = strdup_safe( file ); 00267 } 00268 00269 /* Add the specified merge file to the list */ 00270 (void)str_link_add( file, &merge_in_head, &merge_in_tail ); 00271 00272 } else { 00273 00274 unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "CDD file (%s) does not exist", argv[i] ); 00275 assert( rv < USER_MSG_LENGTH ); 00276 print_output( user_msg, FATAL, __FILE__, __LINE__ ); 00277 Throw 0; 00278 00279 } 00280 00281 } 00282 00283 i++; 00284 00285 } 00286 00287 if( !help_found ) { 00288 00289 Try { 00290 00291 /* Load any merge files found in specified directories */ 00292 strl = dir_head; 00293 while( strl != NULL ) { 00294 directory_load( strl->str, ext_head, &merge_in_head, &merge_in_tail ); 00295 strl = strl->next; 00296 } 00297 00298 } Catch_anonymous { 00299 str_link_delete_list( ext_head ); 00300 str_link_delete_list( dir_head ); 00301 Throw 0; 00302 } 00303 00304 /* Set the last command-line pointer to the current tail */ 00305 merge_in_cl_last = merge_in_tail; 00306 } 00307 00308 /* Deallocate the temporary lists */ 00309 str_link_delete_list( ext_head ); 00310 str_link_delete_list( dir_head ); 00311 00312 return( help_found ); 00313 }
static void merge_usage | ( | ) | [static] |
Outputs usage informaiton to standard output for merge command.
Referenced by merge_parse_args().
00083 { 00084 00085 printf( "\n" ); 00086 printf( "Usage: covered merge (-h | [<options>] <existing_database> <database_to_merge>+)\n" ); 00087 printf( "\n" ); 00088 printf( " -h Displays this help information.\n" ); 00089 printf( "\n" ); 00090 printf( " Options:\n" ); 00091 printf( " -o <filename> File to output new database to. If this argument is not\n" ); 00092 printf( " specified, the <existing_database> is used as the output\n" ); 00093 printf( " database name.\n" ); 00094 printf( " -f <filename> Name of file containing additional arguments to parse.\n" ); 00095 printf( " -d <directory> Directory to search for CDD files to include. This option is used in\n" ); 00096 printf( " conjunction with the -ext option which specifies the file extension\n" ); 00097 printf( " to use for determining which files in the directory are CDD files.\n" ); 00098 printf( " -er <value> Specifies how to handle exclusion reason resolution. If two or more CDD files being\n" ); 00099 printf( " merged have exclusion reasons specified for the same coverage point, the exclusion\n" ); 00100 printf( " reason needs to be resolved (unless it is the same string value). If this option\n" ); 00101 printf( " is not specified and a conflict is found, Covered will interactively request input\n" ); 00102 printf( " for each exclusion as to how to handle it. If this option is specified, it tells\n" ); 00103 printf( " Covered how to handle all exclusion reason conflicts. The values are as follows:\n" ); 00104 printf( " first - CDD file that contained the first exclusion reason is used.\n" ); 00105 printf( " last - CDD file that contained the last exclusion reason is used.\n" ); 00106 printf( " all - All exclusion reasons are used (concatenated).\n" ); 00107 printf( " new - Use the newest exclusion reason specified.\n" ); 00108 printf( " old - Use the oldest exclusion reason specified.\n" ); 00109 printf( " -ext <extension> Used in conjunction with the -d option. If no -ext options are specified\n" ); 00110 printf( " on the command-line, the default value of '.cdd' is used. Note that\n" ); 00111 printf( " a period (.) should be specified.\n" ); 00112 printf( " -m <message> Allows the user to specify information about this CDD file. This information\n" ); 00113 printf( " can be anything (messages with whitespace should be surrounded by double-quotation\n" ); 00114 printf( " marks), but may include something about the simulation arguments to more easily\n" ); 00115 printf( " link the CDD file to its simulation for purposes of recreating the CDD file.\n" ); 00116 printf( "\n" ); 00117 00118 }
char* cdd_message |
User-supplied message to include in the CDD database
unsigned int curr_db |
Index of current database in db_list array that is being handled.
int merge_er_value = MERGE_ER_NONE |
Specifies the value of the -er option.
Referenced by exclude_db_merge(), exclude_merge(), and merge_parse_args().
str_link* merge_in_cl_last = NULL |
Pointer to last input name from command-line.
str_link* merge_in_head = NULL |
Pointer to head of list containing names of the input CDD files.
int merge_in_num = 0 |
Specifies the number of merged CDD files.
str_link* merge_in_tail = NULL |
Pointer to tail of list containing names of the input CDD files.
int merged_code |
char* merged_file = NULL |
Specifies the output filename of the CDD file that contains the merged data.
char user_msg[USER_MSG_LENGTH] |
Holds some output that will be displayed via the print_output command. This is created globally so that memory does not need to be reallocated for each function that wishes to use it.