11 #include "book_merge.h"
17 #define MAXVARIANTS 50
40 static const char *default_header="@PG@\n1.0\n1\nnormal\n";
44 static void book_clear (book_t * book);
46 static void book_open (book_t * book, const char file_name[], const char mode[]);
47 static void book_close (book_t * book);
49 static bool read_entry (book_t * book, entry_t * entry, int n);
50 static void write_entry (book_t * book, const entry_t * entry);
52 static uint64 read_integer (FILE * file, int size);
53 static void write_integer (FILE * file, int size, uint64 n);
59 static void variants_merge(char ** variants, char *variants1, char *variants2){
70 // Step 1: Initial malloc
72 *variants=malloc(strlen(variants1)+strlen(variants2)+1+1);
75 // Step 2: Loop through the variant names
77 variants1_dup=strdup(variants1);
78 variants2_dup=strdup(variants2);
81 variants_list=(i==0)?variants1_dup:variants2_dup;
82 variant=strtok(variants_list,"\x0a");
84 // TODO: this does not take into account that one variant name
85 // may be contained in another.
86 if(!strstr(*variants,variant)){
87 if((*variants)[0]!=0){
88 strcat(*variants,"\x0a");
90 strcat(*variants,variant);
92 variant=strtok(NULL,"\x0a");
103 void book_merge(int argc, char * argv[]) {
106 const char * in_file_1;
107 const char * in_file_2;
108 const char * out_file;
121 entry_t e1[1], e2[1];
125 my_string_clear(&in_file_1);
128 my_string_clear(&in_file_2);
131 my_string_set(&out_file,"out.bin");
133 for (i = 1; i < argc; i++) {
137 } else if (my_string_equal(argv[i],"merge-book")) {
141 } else if (my_string_equal(argv[i],"-in1")) {
144 if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");
146 my_string_set(&in_file_1,argv[i]);
148 } else if (my_string_equal(argv[i],"-in2")) {
151 if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");
153 my_string_set(&in_file_2,argv[i]);
155 } else if (my_string_equal(argv[i],"-out")) {
158 if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");
160 my_string_set(&out_file,argv[i]);
164 my_fatal("book_merge(): unknown option \"%s\"\n",argv[i]);
169 ret=pgheader_read(&header1,in_file_1);
172 case PGHEADER_NO_HEADER:
173 pgheader_create(&header1,"normal","");
175 case PGHEADER_OS_ERROR:
176 my_fatal("book_merge(): %s: %s\n",in_file_1,strerror(errno));
178 my_fatal("book_merge(): Could not read header of %s\n",in_file_1);
181 ret=pgheader_read(&header2,in_file_2);
184 case PGHEADER_NO_HEADER:
185 pgheader_create(&header2,"normal","");
187 case PGHEADER_OS_ERROR:
188 my_fatal("book_merge(): %s: %s\n",in_file_2,strerror(errno));
190 my_fatal("book_merge(): Could not read header of %s\n",in_file_2);
194 pgheader_parse(header1,&variants1,&comment);
197 pgheader_parse(header2,&variants2,&comment);
200 variants_merge(&variants,variants1,variants2);
204 pgheader_create(&header,variants,"Created by Polyglot.");
206 pgheader_create_raw(&raw_header,header,&size);
213 book_open(In1,in_file_1,"rb");
214 book_open(In2,in_file_2,"rb");
215 book_open(Out,out_file,"wb");
220 fputc(raw_header[i],Out->file);
234 b1 = read_entry(In1,e1,i1);
235 }while(b1 && e1->key==U64(0x0) && (++i1));
238 b2 = read_entry(In2,e2,i2);
239 }while(b2 && e2->key==U64(0x0) && (++i2));
243 } else if (!b1 && !b2) {
247 } else if (b1 && !b2) {
251 } else if (b2 && !b1) {
262 } else if (e1->key < e2->key) {
265 } else if (e1->key > e2->key) {
269 ASSERT(e1->key==e2->key);
281 printf("skipped %d entr%s.\n",skip,(skip>1)?"ies":"y");
289 static void book_clear(book_t * book) {
299 static void book_open(book_t * book, const char file_name[], const char mode[]) {
302 ASSERT(file_name!=NULL);
305 book->file = fopen(file_name,mode);
306 if (book->file == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));
308 if (fseek(book->file,0,SEEK_END) == -1) {
309 my_fatal("book_open(): fseek(): %s\n",strerror(errno));
312 book->size = ftell(book->file) / 16;
317 static void book_close(book_t * book) {
321 if (fclose(book->file) == EOF) {
322 my_fatal("book_close(): fclose(): %s\n",strerror(errno));
328 static bool read_entry(book_t * book, entry_t * entry, int n) {
333 if (n < 0 || n >= book->size) return FALSE;
335 ASSERT(n>=0&&n<book->size);
337 if (fseek(book->file,n*16,SEEK_SET) == -1) {
338 my_fatal("read_entry(): fseek(): %s\n",strerror(errno));
341 entry->key = read_integer(book->file,8);
342 entry->move = read_integer(book->file,2);
343 entry->count = read_integer(book->file,2);
344 entry->n = read_integer(book->file,2);
345 entry->sum = read_integer(book->file,2);
352 static void write_entry(book_t * book, const entry_t * entry) {
357 write_integer(book->file,8,entry->key);
358 write_integer(book->file,2,entry->move);
359 write_integer(book->file,2,entry->count);
360 write_integer(book->file,2,entry->n);
361 write_integer(book->file,2,entry->sum);
368 static uint64 read_integer(FILE * file, int size) {
375 ASSERT(size>0&&size<=8);
379 for (i = 0; i < size; i++) {
385 my_fatal("read_integer(): fgetc(): EOF reached\n");
387 my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));
400 static void write_integer(FILE * file, int size, uint64 n) {
406 ASSERT(size>0&&size<=8);
407 ASSERT(size==8||n>>(size*8)==0);
409 for (i = size-1; i >= 0; i--) {
411 b = (n >> (i*8)) & 0xFF;
414 if (fputc(b,file) == EOF) {
415 my_fatal("write_integer(): fputc(): %s\n",strerror(errno));
420 // end of book_merge.cpp