]> git.sesse.net Git - pgn-extract/blob - taglines.c
Add support for outputting positions in my own bit-packed FEN format.
[pgn-extract] / taglines.c
1 /*
2  *  Program: pgn-extract: a Portable Game Notation (PGN) extractor.
3  *  Copyright (C) 1994-2014 David Barnes
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 1, or (at your option)
7  *  any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  *  David Barnes may be contacted as D.J.Barnes@kent.ac.uk
19  *  http://www.cs.kent.ac.uk/people/staff/djb/
20  *
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "bool.h"
27 #include "defs.h"
28 #include "typedef.h"
29 #include "tokens.h"
30 #include "taglist.h"
31 #include "lex.h"
32 #include "lines.h"
33 #include "lists.h"
34 #include "moves.h"
35 #include "output.h"
36 #include "taglines.h"
37
38 static FILE *yyin = NULL;
39
40         /* Read the list of extraction criteria from TagFile.
41          * This doesn't use the normal lexical analyser before the
42          * PGN files are processed but circumvents next_token by
43          * calling get_tag() and get_string. This allows it to detect
44          * EOF before yywrap() is called.
45          * Be careful to leave lex in the right state.
46          */
47 void
48 read_tag_file(const char *TagFile)
49 {   
50     yyin = fopen(TagFile,"r");
51     if(yyin != NULL){
52         Boolean keep_reading = TRUE;
53         
54         while(keep_reading){
55             char *line = next_input_line(yyin);
56             if(line != NULL){
57                 keep_reading = process_tag_line(TagFile,line);
58             }
59             else{
60                 keep_reading = FALSE;
61             }
62         }
63         (void) fclose(yyin);
64         /* Call yywrap in order to set up for the next (first) input file. */
65         (void) yywrap();
66         yyin = NULL;
67     }
68     else{
69         fprintf(GlobalState.logfile,
70                 "Unable to open %s for reading.\n",TagFile);
71         exit(1);
72     }
73 }
74
75         /* Read the contents of a file that lists the
76          * required output ordering for tags.
77          */
78 void
79 read_tag_roster_file(const char *RosterFile)
80 {   Boolean keep_reading = TRUE;
81     yyin = must_open_file(RosterFile,"r");
82     
83     while(keep_reading){
84         char *line = next_input_line(yyin);
85         if(line != NULL){
86             keep_reading = process_roster_line(line);
87         }
88         else{
89             keep_reading = FALSE;
90         }
91     }
92     (void) fclose(yyin);
93     /* Call yywrap in order to set up for the next (first) input file. */
94     (void) yywrap();
95 }
96
97         /* Extract a tag/value pair from the given line.
98          * Return TRUE if this was successful.
99          */
100 Boolean
101 process_tag_line(const char *TagFile,char *line)
102 {
103     Boolean keep_reading = TRUE;
104     if(non_blank_line(line)){
105         unsigned char *linep = (unsigned char *) line;
106         /* We should find a tag. */
107         LinePair resulting_line = gather_tag(line,linep);
108         TokenType tag_token;
109
110         /* Pick up where we are now. */
111         line = resulting_line.line;
112         linep = resulting_line.linep;
113         tag_token = resulting_line.token;
114         if(tag_token != NO_TOKEN){
115             /* Pick up which tag it was. */
116             int tag_index = yylval.tag_index;
117             /* Allow for an optional operator. */
118             TagOperator operator = NONE;
119
120             /* Skip whitespace up to a double quote. */
121             while(is_character_class(*linep, WHITESPACE)){
122                 linep++;
123             }
124             /* Allow for an optional operator. */
125             if(is_character_class(*linep, OPERATOR)){
126                 switch(*linep){
127                   case '<':
128                     linep++;
129                     if(*linep == '='){
130                         linep++;
131                         operator = LESS_THAN_OR_EQUAL_TO;
132                     }
133                     else if(*linep == '>'){
134                         linep++;
135                         operator = NOT_EQUAL_TO;
136                     }
137                     else{
138                         operator = LESS_THAN;;
139                     }
140                     break;
141                   case '>':
142                     linep++;
143                     if(*linep == '='){
144                         linep++;
145                         operator = GREATER_THAN_OR_EQUAL_TO;
146                     }
147                     else{
148                         operator = GREATER_THAN;
149                     }
150                     break;
151                   case '=':
152                     linep++;
153                     operator = EQUAL_TO;
154                     break;
155                   default:
156                     fprintf(GlobalState.logfile,
157                         "Internal error: unknown operator in %s\n",line);
158                     linep++;
159                     break;
160                 }
161                 /* Skip whitespace up to a double quote. */
162                 while(is_character_class(*linep, WHITESPACE)){
163                     linep++;
164                 }
165             }
166
167             if(is_character_class(*linep, DOUBLE_QUOTE)){
168                 /* A string, as expected. */
169                 linep++;
170                 resulting_line = gather_string(line,linep);
171                 line = resulting_line.line;
172                 linep = resulting_line.linep;
173                 if(tag_token == TAG){
174                     /* Treat FEN* tags as a special case.
175                      * Use the position they represent to indicate
176                      * a positional match.
177                      */
178                     if(tag_index == FEN_TAG){
179                         add_fen_positional_match(yylval.token_string);
180                         (void) free((void *)yylval.token_string);
181                     }
182                     else if(tag_index == PSEUDO_FEN_PATTERN_TAG){
183                         add_fen_pattern_match(yylval.token_string);
184                         (void) free((void *)yylval.token_string);
185                     }
186                     else{
187                         add_tag_to_list(tag_index,yylval.token_string,operator);
188                         (void) free((void *)yylval.token_string);
189                     }
190                 }
191                 else{
192                     if(!GlobalState.skipping_current_game){
193                             fprintf(GlobalState.logfile,
194                                 "File %s: unrecognised tag name %s\n",
195                                         TagFile,line);
196                     }
197                     (void) free((void *)yylval.token_string);
198                 }
199             }
200             else{
201                 if(!GlobalState.skipping_current_game){
202                     fprintf(GlobalState.logfile,
203                             "File %s: missing quoted tag string in %s at %s\n",
204                             TagFile,line,linep);
205                 }
206             }
207         }
208         else{
209             /* Terminate the reading, as we have run out of tags. */
210             keep_reading = FALSE;
211         }
212     }
213     return keep_reading;
214 }
215
216         /* Extract a tag name from the given line.
217          * Return TRUE if this was successful.
218          */
219 Boolean
220 process_roster_line(char *line)
221 {
222     Boolean keep_reading = TRUE;
223     if(non_blank_line(line)){
224         unsigned char *linep = (unsigned char *) line;
225         /* We should find a tag. */
226         LinePair resulting_line = gather_tag(line,linep);
227         TokenType tag_token;
228
229         /* Pick up where we are now. */
230         line = resulting_line.line;
231         linep = resulting_line.linep;
232         tag_token = resulting_line.token;
233         if(tag_token != NO_TOKEN){
234             /* Pick up which tag it was. */
235             int tag_index = yylval.tag_index;
236             add_to_output_tag_order((TagName) tag_index);
237         }
238         else{
239             /* Terminate the reading, as we have run out of tags. */
240             keep_reading = FALSE;
241         }
242     }
243     return keep_reading;
244 }