merge.c File Reference

#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_linkmerge_in_head = NULL
str_linkmerge_in_tail = NULL
str_linkmerge_in_cl_last = NULL
int merge_in_num = 0
int merge_er_value = MERGE_ER_NONE

Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
11/29/2001

Function Documentation

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.

Parameters:
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]
Returns:
Returns TRUE if the help option was parsed.
Exceptions:
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.

Parameters:
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 }


Variable Documentation

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.

Array of database pointers storing all currently loaded databases.

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().

Pointer to last input name from command-line.

Pointer to head of list containing names of the input CDD files.

int merge_in_num = 0

Specifies the number of merged CDD files.

Pointer to tail of list containing names of the input CDD files.

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.

Generated on Sun Nov 21 00:55:40 2010 for Covered by  doxygen 1.6.3