Exemplo n.º 1
0
static FILE *
select_output_file(StateInfo *GameState,const char *eco)
{
    if(GameState->games_per_file > 0) {
        if(GameState->games_per_file == 1 || (GameState->num_games_matched % GameState->games_per_file) == 1) {
            /* Time to open the next one. */
            char filename[50];

            if(GameState->outputfile != NULL) {
                (void) fclose(GameState->outputfile);
            }
            sprintf(filename,"%u%s",
                    GameState->next_file_number,
                    output_file_suffix(GameState->output_format));
            GameState->outputfile = must_open_file(filename,"w");
            GameState->next_file_number++;
        }
    }
    else if(GameState->ECO_level > DONT_DIVIDE) {
        /* Open a file of the appropriate name. */
        if(GameState->outputfile != NULL) {
            /* @@@ In practice, this might need refinement.
             * Repeated opening and closing may prove inefficient.
             */
            (void) fclose(GameState->outputfile);
            GameState->outputfile = open_eco_output_file(
                                        GameState->ECO_level,
                                        eco);
        }
    }
    else {
    }
    return GameState->outputfile;
}
Exemplo n.º 2
0
    /* Process the argument character and its associated value.
     * This function processes arguments from the command line and
     * from an argument file associated with the -A argument.
     *
     * An argument -ofile.pgn would be passed in as:
     *                'o' and "file.pgn".
     * A zero-length string for associated_value is not necessarily
     * an error, e.g. -e has an optional following filename.
     * NB: If the associated_value is to be used beyond this function,
     * it must be copied.
     */
void
process_argument(char arg_letter,const char *associated_value)
{   /* Provide an alias for associated_value because it will
     * often represent a file name.
     */
    const char *filename = skip_leading_spaces(associated_value);

    switch(arg_letter){
        case WRITE_TO_OUTPUT_FILE_ARGUMENT:
        case APPEND_TO_OUTPUT_FILE_ARGUMENT:
          if(GlobalState.ECO_level > 0){
              fprintf(GlobalState.logfile,"-%c conflicts with -E\n",
                      arg_letter);
          }
          else if(GlobalState.games_per_file > 0){
              fprintf(GlobalState.logfile,"-%c conflicts with -#\n",
                      arg_letter);
          }
          else if(GlobalState.output_filename != NULL){
              fprintf(GlobalState.logfile,
                      "-%c: File %s has already been selected for output.\n",
                      arg_letter,GlobalState.output_filename);
              exit(1);
          }
          else if(*filename == '\0'){
              fprintf(GlobalState.logfile,"Usage: -%cfilename.\n",arg_letter);
              exit(1);
          }
          else{
              if(GlobalState.outputfile != NULL){
                  (void) fclose(GlobalState.outputfile);
              }
              if(arg_letter == WRITE_TO_OUTPUT_FILE_ARGUMENT){
                  GlobalState.outputfile = must_open_file(filename,"w");
              }
              else{
                  GlobalState.outputfile = must_open_file(filename,"a");
              }
              GlobalState.output_filename = filename;
          }
          break;
        case WRITE_TO_LOG_FILE_ARGUMENT:
        case APPEND_TO_LOG_FILE_ARGUMENT:
          /* Take precautions against multiple log files. */
          if((GlobalState.logfile != stderr) && (GlobalState.logfile != NULL)){
                (void) fclose(GlobalState.logfile);
          }
          if(arg_letter == WRITE_TO_LOG_FILE_ARGUMENT){
                GlobalState.logfile = fopen(filename,"w");
          }
          else{
                GlobalState.logfile = fopen(filename,"a");
          }
          if(GlobalState.logfile == NULL){
                fprintf(stderr,"Unable to open %s for writing.\n",filename);
                GlobalState.logfile = stderr;
          }
          break;
        case DUPLICATES_FILE_ARGUMENT:
          if(*filename == '\0'){
              fprintf(GlobalState.logfile,"Usage: -%cfilename.\n",arg_letter);
              exit(1);
          }
          else if(GlobalState.suppress_duplicates){
              fprintf(GlobalState.logfile,
                      "-%c clashes with the -%c flag.\n",arg_letter,
                      DONT_KEEP_DUPLICATES_ARGUMENT);
              exit(1);
          }
          else{
              GlobalState.duplicate_file = must_open_file(filename,"w");
          }
          break;
        case USE_ECO_FILE_ARGUMENT:
          GlobalState.add_ECO = TRUE;
          if(*filename != '\0'){
              GlobalState.eco_file = copy_string(filename);
          }
          else if((filename = getenv("ECO_FILE")) != NULL){
              GlobalState.eco_file = filename;
          }
          else{
              /* Use the default which is already set up. */
          }
          initEcoTable();
          break;
        case ECO_OUTPUT_LEVEL_ARGUMENT:
          {   unsigned level;

              if(GlobalState.output_filename != NULL){
                  fprintf(GlobalState.logfile,
                          "-%c: File %s has already been selected for output.\n",
                          arg_letter,
                          GlobalState.output_filename);
                  exit(1);
              }
              else if(GlobalState.games_per_file > 0){
                  fprintf(GlobalState.logfile,
                            "-%c conflicts with -#.\n",
                            arg_letter);
                  exit(1);
              }
              else if(sscanf(associated_value,"%u",&level) != 1){
                    fprintf(GlobalState.logfile,
                            "-%c requires a number attached, e.g., -%c1.\n",
                            arg_letter,arg_letter);
                     exit(1);
              }
              else if((level < MIN_ECO_LEVEL) || (level > MAX_ECO_LEVEL)){
                    fprintf(GlobalState.logfile,
                            "-%c level should be between %u and %u.\n",
                            MIN_ECO_LEVEL,MAX_ECO_LEVEL,arg_letter);
                    exit(1);
              }
              else{
                    GlobalState.ECO_level = level;
              }
          }
          break;
        case CHECK_FILE_ARGUMENT:
          if(*filename != '\0'){
              /* See if it is a single PGN file, or a list
               * of files.
               */
              size_t len = strlen(filename);
              /* Check for a .PGN suffix. */
              const char *suffix = output_file_suffix(SAN);

              if((len > strlen(suffix)) &&
                    (stringcompare(&filename[len-strlen(suffix)],
                                            suffix) == 0)){
                  add_filename_to_source_list(filename,CHECKFILE);
              }
              else{
                  FILE *fp = must_open_file(filename,"r");
                  add_filename_list_from_file(fp,CHECKFILE);
                  (void) fclose(fp);
              }
          }
          break;
        case FILE_OF_FILES_ARGUMENT:
          if(*filename != '\0'){
              FILE *fp = must_open_file(filename,"r");
              add_filename_list_from_file(fp,NORMALFILE);
              (void) fclose(fp);
          }
          else{
              fprintf(GlobalState.logfile,"Filename expected with -%c\n",
                      arg_letter);
          }
          break;
        case BOUNDS_ARGUMENT:
          {
              /* Bounds on the number of moves are to be found.
               * "l#" means less-than-or-equal-to.
               * "g#" means greater-than-or-equal-to.
               * Otherwise "#" (or "e#") means that number.
               */
              /* Equal by default. */
              char which = 'e';
              unsigned value;
              Boolean Ok = TRUE;
              const char *bound = associated_value;

              switch(*bound){
                case 'l':
                case 'u':
                case 'e':
                  which = *bound;
                  bound++;
                  break;
                default:
                  if(!isdigit((int) *bound)){
                      fprintf(GlobalState.logfile,
                              "-%c must be followed by e, l, or u.\n",
                              arg_letter);
                      Ok = FALSE;
                  }
                  break;
              }
              if(Ok && (sscanf(bound,"%u",&value) == 1)){
                GlobalState.check_move_bounds = TRUE;
                switch(which){
                  case 'e':
                        GlobalState.lower_move_bound = value; 
                        GlobalState.upper_move_bound = value; 
                        break;
                  case 'l':
                    if(value <= GlobalState.upper_move_bound){
                        GlobalState.lower_move_bound = value; 
                    }
                    else{
                        fprintf(GlobalState.logfile,
                           "Lower bound is greater than the upper bound; -%c ignored.\n",
                           arg_letter);
                        Ok = FALSE;
                    }
                    break;
                  case 'u':
                    if(value >= GlobalState.lower_move_bound){
                        GlobalState.upper_move_bound = value; 
                    }
                    else{
                        fprintf(GlobalState.logfile,
                           "Upper bound is smaller than the lower bound; -%c ignored.\n",
                           arg_letter);
                        Ok = FALSE;
                    }
                    break;
                }
             }
             else{
               fprintf(GlobalState.logfile,
                       "-%c should be in the form -%c[elu]number.\n",
                       arg_letter,arg_letter);
               Ok = FALSE;
             }
             if(!Ok){
                exit(1);
             }
         }
         break;
        case GAMES_PER_FILE_ARGUMENT:
          if(GlobalState.ECO_level > 0){
              fprintf(GlobalState.logfile,
                      "-%c conflicts with -E.\n",arg_letter);
              exit(1);
          }
          else if(GlobalState.output_filename != NULL){
              fprintf(GlobalState.logfile,
                        "-%c: File %s has already been selected for output.\n",
                        arg_letter,
                        GlobalState.output_filename);
              exit(1);
          }
          else if(sscanf(associated_value,"%u",
                       &GlobalState.games_per_file) != 1){
            fprintf(GlobalState.logfile,
                    "-%c should be followed by an unsigned integer.\n",
                    arg_letter);
            exit(1);
          }
          else{
            /* Value set. */
          }
          break;
        case FILE_OF_ARGUMENTS_ARGUMENT:
          if(*filename != '\0'){
              /* @@@ Potentially recursive call. Is this safe? */
              read_args_file(filename);
          }
          else{
              fprintf(GlobalState.logfile,"Usage: -%cfilename.\n",
                      arg_letter);
          }
          break;
        case NON_MATCHING_GAMES_ARGUMENT:
          if(*filename != '\0'){
              if(GlobalState.non_matching_file != NULL){
                  (void) fclose(GlobalState.non_matching_file);
              }
              GlobalState.non_matching_file = must_open_file(filename,"w");
          }
          else{
              fprintf(GlobalState.logfile,"Usage: -%cfilename.\n",arg_letter);
              exit(1);
          }
          break;
        case TAG_EXTRACTION_ARGUMENT:
            /* A single tag extraction criterion. */
            extract_tag_argument(associated_value);
            break;
        case LINE_WIDTH_ARGUMENT:
            { /* Specify an output line width. */
              unsigned length;

              if(sscanf(associated_value,"%u",&length) > 0){
                  set_output_line_length(length);
              }
              else{
                  fprintf(GlobalState.logfile,
                          "-%c should be followed by an unsigned integer.\n",
                          arg_letter);
                  exit(1);
              }
            }
            break;
        case HELP_ARGUMENT:
            usage_and_exit();
            break;
        case OUTPUT_FORMAT_ARGUMENT:
            /* Whether to use the source form of moves or
             * rewrite them into another format.
             */
	    {
		OutputFormat format = which_output_format(associated_value);
		if(format == UCI) {
		    /* Rewrite the game in a format suitable for input to
		     * a UCI-compatible engine.
		     * This is actually LALG but involves adjusting a lot of
		     * the other statuses, too.
		     */
		    GlobalState.keep_NAGs = FALSE;
		    GlobalState.keep_comments = FALSE;
		    GlobalState.keep_move_numbers = FALSE;
		    GlobalState.keep_checks = FALSE;
		    GlobalState.keep_variations = FALSE;
		    set_output_line_length(5000);
		    format = LALG;
		}
		GlobalState.output_format = format;
	    }
            break;
        case SEVEN_TAG_ROSTER_ARGUMENT:
            if(GlobalState.tag_output_format == ALL_TAGS ||
               GlobalState.tag_output_format == SEVEN_TAG_ROSTER) {
                GlobalState.tag_output_format = SEVEN_TAG_ROSTER;
            }
            else {
                fprintf(GlobalState.logfile,
                        "-%c clashes with another argument.\n",
                        SEVEN_TAG_ROSTER_ARGUMENT);
                exit(1);
            }
            break;
        case DONT_KEEP_COMMENTS_ARGUMENT:
            GlobalState.keep_comments = FALSE;
            break;
        case DONT_KEEP_DUPLICATES_ARGUMENT:
            /* Make sure that this doesn't clash with -d. */
            if(GlobalState.duplicate_file == NULL){
                GlobalState.suppress_duplicates = TRUE;
            }
            else{
                fprintf(GlobalState.logfile,
                            "-%c clashes with -%c flag.\n",
                            DONT_KEEP_DUPLICATES_ARGUMENT,
                            DUPLICATES_FILE_ARGUMENT);
                exit(1);
            }
            break;
        case DONT_MATCH_PERMUTATIONS_ARGUMENT:
            GlobalState.match_permutations = FALSE;
            break;
        case DONT_KEEP_NAGS_ARGUMENT:
            GlobalState.keep_NAGs = FALSE;
            break;
        case OUTPUT_FEN_STRING_ARGUMENT:
            /* Output a FEN string of the final position.
             * This is displayed in a comment.
             */
	    if(GlobalState.add_FEN_comments) {
		/* Already implied. */
	        GlobalState.output_FEN_string = FALSE;
	    }
	    else {
		GlobalState.output_FEN_string = TRUE;
	    }
            break;
        case CHECK_ONLY_ARGUMENT:
            /* Report errors, but don't convert. */
            GlobalState.check_only = TRUE;
            break;
        case KEEP_SILENT_ARGUMENT:
            /* Turn off progress reporting. */
            GlobalState.verbose = FALSE;
            break;
        case USE_SOUNDEX_ARGUMENT:
            /* Use soundex matches for player tags. */
            GlobalState.use_soundex = TRUE;
            break;
        case MATCH_CHECKMATE_ARGUMENT:
            /* Match only games that end in checkmate. */
            GlobalState.match_only_checkmate = TRUE;
            break;
        case SUPPRESS_ORIGINALS_ARGUMENT:
            GlobalState.suppress_originals = TRUE;
            break;
        case DONT_KEEP_VARIATIONS_ARGUMENT:
            GlobalState.keep_variations = FALSE;
            break;
        case USE_VIRTUAL_HASH_TABLE_ARGUMENT:
            GlobalState.use_virtual_hash_table = TRUE;
            break;

        case TAGS_ARGUMENT:
            if(*filename != '\0'){
                read_tag_file(filename);
            }
            break;
        case TAG_ROSTER_ARGUMENT:
            if(*filename != '\0'){
                read_tag_roster_file(filename);
            }
            break;
        case MOVES_ARGUMENT:
            if(*filename != '\0'){
                /* Where the list of variations of interest are kept. */
                FILE *variation_file = must_open_file(filename,"r");
                /* We wish to search for particular variations. */
                add_textual_variations_from_file(variation_file);
                fclose(variation_file);
            }
            break;
        case POSITIONS_ARGUMENT:
            if(*filename != '\0'){
                FILE *variation_file = must_open_file(filename,"r");
                /* We wish to search for positional variations. */
                add_positional_variations_from_file(variation_file);
                fclose(variation_file);
            }
            break;
        case ENDINGS_ARGUMENT:
            if(*filename != '\0'){
                if(!build_endings(filename)){
                    exit(1);
                }
            }
            break;
        default:
            fprintf(GlobalState.logfile,
                    "Unrecognized argument -%c\n", arg_letter);
    }
}