Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

/Users/trevorw/projects/release/covered-0.7.4/src/merge.c File Reference


Detailed Description

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

#include <stdio.h>
#include <stdlib.h>
#include "binding.h"
#include "db.h"
#include "defines.h"
#include "info.h"
#include "merge.h"
#include "sim.h"
#include "util.h"

Functions

void merge_usage ()
bool merge_parse_args (int argc, int last_arg, const char **argv)
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


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

00345   { PROFILE(COMMAND_MERGE);
00346 
00347   int          i;     /* Loop iterator */
00348   unsigned int rv;    /* Return value from snprintf calls */
00349   bool         error = FALSE;
00350 
00351   /* Output header information */
00352   rv = snprintf( user_msg, USER_MSG_LENGTH, COVERED_HEADER );
00353   assert( rv < USER_MSG_LENGTH );
00354   print_output( user_msg, NORMAL, __FILE__, __LINE__ );
00355 
00356   Try {
00357 
00358     str_link* strl;
00359     bool      stop_merging;
00360     int       curr_leading_hier_num = 0;
00361 
00362     /* Parse score command-line */
00363     if( !merge_parse_args( argc, last_arg, argv ) ) {
00364 
00365       /* Read in base database */
00366       rv = snprintf( user_msg, USER_MSG_LENGTH, "Reading CDD file \"%s\"", merge_in_head->str );
00367       assert( rv < USER_MSG_LENGTH );
00368       print_output( user_msg, NORMAL, __FILE__, __LINE__ );
00369       db_read( merge_in_head->str, READ_MODE_MERGE_NO_MERGE );
00370 
00371       /* If the currently read CDD didn't contain any merged CDDs it is a leaf CDD so mark it as such */
00372       if( (db_list[curr_db]->leading_hier_num - curr_leading_hier_num) == 1 ) {
00373         merge_in_head->suppl = 1;
00374       }
00375       curr_leading_hier_num = db_list[curr_db]->leading_hier_num;
00376 
00377       /* Read in databases to merge */
00378       strl         = merge_in_head->next;
00379       stop_merging = (strl == merge_in_head);
00380       while( (strl != NULL) && !stop_merging ) {
00381         rv = snprintf( user_msg, USER_MSG_LENGTH, "Merging CDD file \"%s\"", strl->str );
00382         assert( rv < USER_MSG_LENGTH );
00383         print_output( user_msg, NORMAL, __FILE__, __LINE__ );
00384         db_read( strl->str, READ_MODE_MERGE_NO_MERGE );
00385 
00386         /* If we have not merged any CDD files from this CDD, this is a leaf CDD so mark it as such */
00387         if( (db_list[curr_db]->leading_hier_num - curr_leading_hier_num) == 1 ) {
00388           strl->suppl = 1;
00389         }
00390         curr_leading_hier_num = db_list[curr_db]->leading_hier_num;
00391 
00392         stop_merging = (strl == merge_in_cl_last);
00393         strl         = strl->next;
00394       }
00395 
00396       /* Perform the tree merges */
00397       db_merge_instance_trees();
00398 
00399       /* Bind */
00400       bind_perform( TRUE, 0 );
00401 
00402       /* Write out new database to output file */
00403       db_write( merged_file, FALSE, TRUE, FALSE );
00404 
00405       print_output( "\n***  Merging completed successfully!  ***", NORMAL, __FILE__, __LINE__ );
00406 
00407     }
00408 
00409   } Catch_anonymous {
00410     error = TRUE;
00411   }
00412 
00413   /* Close database */
00414   db_close();
00415 
00416   /* Deallocate other memory */
00417   str_link_delete_list( merge_in_head );
00418   free_safe( merged_file, (strlen( merged_file ) + 1) );
00419 
00420   if( error ) {
00421     Throw 0;
00422   }
00423 
00424   PROFILE_END;
00425 
00426 }

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

00133   {
00134 
00135   int       i;
00136   str_link* strl;
00137   str_link* ext_head     = NULL;
00138   str_link* ext_tail     = NULL;
00139   str_link* dir_head     = NULL;
00140   str_link* dir_tail     = NULL;
00141   bool      help_found   = FALSE;
00142 
00143   i = last_arg + 1;
00144 
00145   while( (i < argc) && !help_found ) {
00146 
00147     if( strncmp( "-h", argv[i], 2 ) == 0 ) {
00148 
00149       merge_usage();
00150       help_found = TRUE;
00151 
00152     } else if( strncmp( "-o", argv[i], 2 ) == 0 ) {
00153     
00154       if( check_option_value( argc, argv, i ) ) {
00155         i++;
00156         if( is_legal_filename( argv[i] ) ) {
00157           merged_file = strdup_safe( argv[i] );
00158         } else {
00159           unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Output file \"%s\" is not writable", argv[i] );
00160           assert( rv < USER_MSG_LENGTH );
00161           print_output( user_msg, FATAL, __FILE__, __LINE__ );
00162           Throw 0;
00163         }
00164       } else {
00165         Throw 0;
00166       }
00167 
00168     } else if( strncmp( "-f", argv[i], 2 ) == 0 ) {
00169 
00170       if( check_option_value( argc, argv, i ) ) {
00171         char**       arg_list = NULL;
00172         int          arg_num  = 0;
00173         unsigned int j;
00174         i++;
00175         Try {
00176           read_command_file( argv[i], &arg_list, &arg_num );
00177           help_found = merge_parse_args( arg_num, -1, (const char**)arg_list );
00178         } Catch_anonymous {
00179           for( j=0; j<arg_num; j++ ) {
00180             free_safe( arg_list[j], (strlen( arg_list[j] ) + 1) );
00181           }
00182           free_safe( arg_list, (sizeof( char* ) * arg_num) );
00183           Throw 0;
00184         }
00185         for( j=0; j<arg_num; j++ ) {
00186           free_safe( arg_list[j], (strlen( arg_list[j] ) + 1) );
00187         }
00188         free_safe( arg_list, (sizeof( char* ) * arg_num) );
00189       } else {
00190         Throw 0;
00191       }
00192 
00193     } else if( strncmp( "-d", argv[i], 2 ) == 0 ) {
00194 
00195       if( check_option_value( argc, argv, i ) ) {
00196         i++;
00197         if( directory_exists( argv[i] ) ) {
00198           (void)str_link_add( strdup_safe( argv[i] ), &dir_head, &dir_tail );
00199         } else {
00200           unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Specified -d directory (%s) does not exist", argv[i] );
00201           assert( rv < USER_MSG_LENGTH );
00202           print_output( user_msg, FATAL, __FILE__, __LINE__ );
00203           Throw 0;
00204         }
00205       } else {
00206         Throw 0;
00207       }
00208 
00209     } else if( strncmp( "-er", argv[i], 3 ) == 0 ) {
00210 
00211       if( check_option_value( argc, argv, i ) ) {
00212         i++;
00213         if( strncmp( "first", argv[i], 5 ) == 0 ) {
00214           merge_er_value = MERGE_ER_FIRST;
00215         } else if( strncmp( "last", argv[i], 4 ) == 0 ) {
00216           merge_er_value = MERGE_ER_LAST;
00217         } else if( strncmp( "all", argv[i], 3 ) == 0 ) {
00218           merge_er_value = MERGE_ER_ALL;
00219         } else if( strncmp( "new", argv[i], 3 ) == 0 ) {
00220           merge_er_value = MERGE_ER_NEW;
00221         } else if( strncmp( "old", argv[i], 3 ) == 0 ) {
00222           merge_er_value = MERGE_ER_OLD;
00223         } else {
00224           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] );
00225           assert( rv < USER_MSG_LENGTH );
00226           print_output( user_msg, FATAL, __FILE__, __LINE__ );
00227           Throw 0;
00228         }
00229       } else {
00230         Throw 0;
00231       }
00232 
00233     } else if( strncmp( "-ext", argv[i], 4 ) == 0 ) {
00234 
00235       if( check_option_value( argc, argv, i ) ) {
00236         i++;
00237         (void)str_link_add( strdup_safe( argv[i] ), &ext_head, &ext_tail );
00238       } else {
00239         Throw 0;
00240       } 
00241 
00242     } else if( strncmp( "-m", argv[i], 2 ) == 0 ) {
00243 
00244       if( check_option_value( argc, argv, i ) ) {
00245         i++;
00246         if( cdd_message != NULL ) {
00247           print_output( "Only one -m option is allowed on the merge command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00248         } else {
00249           cdd_message = strdup_safe( argv[i] );
00250         }
00251       } else {
00252         Throw 0;
00253       }
00254 
00255     } else {
00256 
00257       /* The name of a file to merge */
00258       if( file_exists( argv[i] ) ) {
00259 
00260         /* Create absolute filename */
00261         char* file = get_absolute_path( argv[i] );
00262 
00263         /* If we have not specified a merge file explicitly, set it implicitly to the first CDD file found */
00264         if( (merge_in_head == NULL) && (merged_file == NULL) ) {
00265           merged_file = strdup_safe( file );
00266         }
00267 
00268         /* Add the specified merge file to the list */
00269         (void)str_link_add( file, &merge_in_head, &merge_in_tail );
00270 
00271       } else {
00272 
00273         unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "CDD file (%s) does not exist", argv[i] );
00274         assert( rv < USER_MSG_LENGTH );
00275         print_output( user_msg, FATAL, __FILE__, __LINE__ );
00276         Throw 0;
00277 
00278       }
00279 
00280     }
00281 
00282     i++;
00283 
00284   }
00285 
00286   if( !help_found ) {
00287 
00288     Try {
00289 
00290       /* Load any merge files found in specified directories */
00291       strl = dir_head;
00292       while( strl != NULL ) {
00293         directory_load( strl->str, ext_head, &merge_in_head, &merge_in_tail );
00294         strl = strl->next;
00295       }
00296 
00297     } Catch_anonymous {
00298       str_link_delete_list( ext_head );
00299       str_link_delete_list( dir_head );
00300       Throw 0;
00301     }
00302 
00303     /* Set the last command-line pointer to the current tail */
00304     merge_in_cl_last = merge_in_tail;
00305 
00306     /* Make sure that we have at least 2 files to merge */
00307     strl = merge_in_head;
00308     while( strl != NULL ) {
00309       merge_in_num++;
00310       strl = strl->next;
00311     }
00312 
00313     /* Check to make sure that the user specified at least two files to merge */
00314     if( merge_in_num < 2 ) {
00315       print_output( "Must specify at least two CDD files to merge", FATAL, __FILE__, __LINE__ );
00316       Throw 0;
00317     }
00318 
00319     /*
00320      If no -o option was specified and no merge files were specified, don't presume that the first file found in
00321      the directory will be that file.
00322     */
00323     if( merged_file == NULL ) {
00324       print_output( "Must specify the -o option or a specific CDD file for containing the merged results", FATAL, __FILE__, __LINE__ );
00325       Throw 0;
00326     }
00327 
00328   }
00329 
00330   /* Deallocate the temporary lists */
00331   str_link_delete_list( ext_head );
00332   str_link_delete_list( dir_head );
00333 
00334   return( help_found );
00335 
00336 }

void merge_usage  )  [static]
 

Outputs usage informaiton to standard output for merge command.

00082                           {
00083 
00084   printf( "\n" );
00085   printf( "Usage:  covered merge (-h | [<options>] <existing_database> <database_to_merge>+)\n" );
00086   printf( "\n" );
00087   printf( "   -h                         Displays this help information.\n" );
00088   printf( "\n" );
00089   printf( "   Options:\n" );
00090   printf( "      -o <filename>           File to output new database to.  If this argument is not\n" );
00091   printf( "                                specified, the <existing_database> is used as the output\n" );
00092   printf( "                                database name.\n" );
00093   printf( "      -f <filename>           Name of file containing additional arguments to parse.\n" );
00094   printf( "      -d <directory>          Directory to search for CDD files to include.  This option is used in\n" );
00095   printf( "                                conjunction with the -ext option which specifies the file extension\n" );
00096   printf( "                                to use for determining which files in the directory are CDD files.\n" );
00097   printf( "      -er <value>             Specifies how to handle exclusion reason resolution.  If two or more CDD files being\n" );
00098   printf( "                                merged have exclusion reasons specified for the same coverage point, the exclusion\n" );
00099   printf( "                                reason needs to be resolved (unless it is the same string value).  If this option\n" );
00100   printf( "                                is not specified and a conflict is found, Covered will interactively request input\n" );
00101   printf( "                                for each exclusion as to how to handle it.  If this option is specified, it tells\n" );
00102   printf( "                                Covered how to handle all exclusion reason conflicts.  The values are as follows:\n" );
00103   printf( "                                  first - CDD file that contained the first exclusion reason is used.\n" );
00104   printf( "                                  last  - CDD file that contained the last exclusion reason is used.\n" );
00105   printf( "                                  all   - All exclusion reasons are used (concatenated).\n" );
00106   printf( "                                  new   - Use the newest exclusion reason specified.\n" );
00107   printf( "                                  old   - Use the oldest exclusion reason specified.\n" );
00108   printf( "      -ext <extension>        Used in conjunction with the -d option.  If no -ext options are specified\n" );
00109   printf( "                                on the command-line, the default value of '.cdd' is used.  Note that\n" );
00110   printf( "                                a period (.) should be specified.\n" );
00111   printf( "      -m <message>            Allows the user to specify information about this CDD file.  This information\n" );
00112   printf( "                                can be anything (messages with whitespace should be surrounded by double-quotation\n" );
00113   printf( "                                marks), but may include something about the simulation arguments to more easily\n" );
00114   printf( "                                link the CDD file to its simulation for purposes of recreating the CDD file.\n" );
00115   printf( "\n" );
00116 
00117 }


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.

db** db_list
 

Array of database pointers storing all currently loaded databases.

int merge_er_value = MERGE_ER_NONE
 

Specifies the value of the -er option.

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.


Generated on Wed Jun 17 22:19:23 2009 for Covered by doxygen 1.3.4