From be3167c9e0220a4ee3e8b5c5f813fb2627d1ce55 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 13 Dec 2014 00:57:41 +0100 Subject: [PATCH] Support scanning only a range of the file. --- argsfile.c | 8 ++++++++ grammar.c | 18 ++++++++++++------ lex.c | 32 ++++++++++++++++++++++++++++++++ lex.h | 2 ++ main.c | 3 +++ typedef.h | 6 ++++++ 6 files changed, 63 insertions(+), 6 deletions(-) diff --git a/argsfile.c b/argsfile.c index e2caa07..7bba901 100644 --- a/argsfile.c +++ b/argsfile.c @@ -1078,6 +1078,14 @@ process_long_form_argument(const char *argument, const char *associated_value) GlobalState.output_total_plycount = TRUE; return 1; } + else if(stringcompare(argument, "startpos") == 0) { + GlobalState.start_position = atol(associated_value); + return 2; + } + else if(stringcompare(argument, "endpos") == 0) { + GlobalState.end_position = atol(associated_value); + return 2; + } else if(stringcompare(argument, "version") == 0) { fprintf(GlobalState.logfile, "pgn-extract %s\n", CURRENT_VERSION); exit(0); diff --git a/grammar.c b/grammar.c index ab22783..133947e 100644 --- a/grammar.c +++ b/grammar.c @@ -83,7 +83,7 @@ static void check_result(char **Tags,const char *terminating_result); static void free_comment_list(CommentList *comment_list); static void DealWithEcoLine(Move *move_list); static void DealWithGame(Move *move_list); -static Boolean finished_processing(void); +static Boolean finished_processing(SourceFileType file_type); /* Initialise the game header structure to contain * space for the default number of tags. @@ -236,17 +236,18 @@ select_output_file(StateInfo *GameState,const char *eco) * Conditions for finishing processing, other than all the input * having been processed. */ -static Boolean finished_processing(void) +static Boolean finished_processing(SourceFileType file_type) { - return (GlobalState.matching_game_number > 0 && - GlobalState.num_games_matched == GlobalState.matching_game_number); + return ((file_type != ECOFILE && at_end_of_input()) || + (GlobalState.matching_game_number > 0 && + GlobalState.num_games_matched == GlobalState.matching_game_number)); } static void ParseOptGameList(SourceFileType file_type) { Move *move_list = NULL; - while(ParseGame(&move_list) && !finished_processing()){ + while(ParseGame(&move_list) && !finished_processing(file_type)){ if(file_type == NORMALFILE){ DealWithGame(move_list); } @@ -997,6 +998,11 @@ DealWithEcoLine(Move *move_list) int yyparse(SourceFileType file_type) { + if(file_type != ECOFILE) { + if(!seek_to_begin()) { + return 1; + } + } setup_for_new_game(); current_symbol = skip_to_next_game(NO_TOKEN); ParseOptGameList(file_type); @@ -1004,7 +1010,7 @@ yyparse(SourceFileType file_type) /* Ok -- EOF. */ return 0; } - else if(finished_processing()) { + else if(finished_processing(file_type)) { /* Ok -- done all we need to. */ return 0; } diff --git a/lex.c b/lex.c index 0c8d26f..23d6131 100644 --- a/lex.c +++ b/lex.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #if defined(__BORLANDC__) || defined(_MSC_VER) #include @@ -1101,6 +1102,37 @@ open_input(const char *infile) return yyin != NULL; } +Boolean +seek_to_begin(void) +{ + if(GlobalState.start_position <= 0) { + return TRUE; + } + if(fseek(yyin, GlobalState.start_position, SEEK_SET) != 0) { + fprintf(GlobalState.logfile,"Cannot seek to position %ld in %s\n", + GlobalState.start_position, + GlobalState.current_input_file); + return FALSE; + } + return TRUE; +} + +Boolean +at_end_of_input(void) +{ + long pos; + if(GlobalState.end_position >= LONG_MAX) { + return FALSE; + } + pos = ftell(yyin); + if(pos == -1) { + fprintf(GlobalState.logfile,"Cannot find position in %s\n", + GlobalState.current_input_file); + return TRUE; + } + return pos >= GlobalState.end_position; +} + /* Simple interface to open_input for the ECO file. */ Boolean open_eco_file(const char *eco_file) diff --git a/lex.h b/lex.h index e0cb4dc..a310e9d 100644 --- a/lex.h +++ b/lex.h @@ -78,6 +78,8 @@ const char *tag_header_string(TagName tag); Boolean open_first_file(void); const char *input_file_name(unsigned file_number); unsigned current_file_number(void); +Boolean seek_to_begin(void); +Boolean at_end_of_input(void); Boolean open_eco_file(const char *eco_file); int yywrap(void); void add_filename_to_source_list(const char *filename,SourceFileType file_type); diff --git a/main.c b/main.c index 218793a..ec4df57 100644 --- a/main.c +++ b/main.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "bool.h" #include "mymalloc.h" #include "defs.h" @@ -106,6 +107,8 @@ StateInfo GlobalState = { "MATCH", /* position_match_comment (--markpositionmatches) */ (char *)NULL, /* current_input_file */ NORMALFILE, /* current_file_type */ + 0, /* start_position */ + LONG_MAX, /* end_position */ DEFAULT_ECO_FILE, /* eco_file (-e) */ (FILE *)NULL, /* outputfile (-o, -a). Default is stdout */ (char *)NULL, /* output_filename (-o, -a) */ diff --git a/typedef.h b/typedef.h index 65c93b5..cf7be10 100644 --- a/typedef.h +++ b/typedef.h @@ -279,6 +279,12 @@ typedef struct { const char *current_input_file; /* Whether this is a CHECKFILE or a NORMALFILE. */ SourceFileType current_file_type; + /* Byte positions to scan to and from in the PGN file. + * Starting in the middle of a game will yield unexpected + * results. + */ + long start_position; + long end_position; /* File of ECO lines. */ const char *eco_file; /* Where to write the extracted games. */ -- 2.39.2