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 *header1, char *header2){
70 // Step 1: Initial malloc
72 *variants=malloc(strlen(header1)+strlen(header2)+1);
75 // Step 2: Extract variant names.
77 header1_dup=strdup(header1);
78 header2_dup=strdup(header2);
81 header=(i==0)?header1_dup:header2_dup;
83 token=strtok(header,"\n");
85 token=strtok(NULL,"\n");
87 token=strtok(NULL,"\n");
88 if(token){ // NBVARIANTS
92 variant=strtok(NULL,"\n");
93 if(!strstr(*variants,variant)){
94 if((*variants)[0]!=0){
95 strcat(*variants,",");
97 strcat(*variants,variant);
114 my_fatal("header_merge(): bad header %d. Error %d\n",i,ret);
126 void book_merge(int argc, char * argv[]) {
129 const char * in_file_1;
130 const char * in_file_2;
131 const char * out_file;
141 entry_t e1[1], e2[1];
145 my_string_clear(&in_file_1);
148 my_string_clear(&in_file_2);
151 my_string_set(&out_file,"out.bin");
153 for (i = 1; i < argc; i++) {
157 } else if (my_string_equal(argv[i],"merge-book")) {
161 } else if (my_string_equal(argv[i],"-in1")) {
164 if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");
166 my_string_set(&in_file_1,argv[i]);
168 } else if (my_string_equal(argv[i],"-in2")) {
171 if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");
173 my_string_set(&in_file_2,argv[i]);
175 } else if (my_string_equal(argv[i],"-out")) {
178 if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");
180 my_string_set(&out_file,argv[i]);
184 my_fatal("book_merge(): unknown option \"%s\"\n",argv[i]);
189 ret=pgheader_read(&header1,in_file_1);
192 case PGHEADER_NO_HEADER:
193 header1=malloc(strlen(default_header)+1);
194 strcpy(header1,default_header);
196 case PGHEADER_OS_ERROR:
197 my_fatal("book_merge(): %s: %s\n",in_file_1,strerror(errno));
199 my_fatal("book_merge(): Could not read header of %s\n",in_file_1);
202 ret=pgheader_read(&header2,in_file_2);
205 case PGHEADER_NO_HEADER:
206 header2=malloc(strlen(default_header)+1);
207 strcpy(header2,default_header);
209 case PGHEADER_OS_ERROR:
210 my_fatal("book_merge(): %s: %s\n",in_file_2,strerror(errno));
212 my_fatal("book_merge(): Could not read header of %s\n",in_file_2);
216 variants_merge(&variants,header1,header2);
220 pgheader_create(&header,variants,"Created by Polyglot.");
222 pgheader_create_raw(&raw_header,header,&size);
229 book_open(In1,in_file_1,"rb");
230 book_open(In2,in_file_2,"rb");
231 book_open(Out,out_file,"wb");
236 fputc(raw_header[i],Out->file);
250 b1 = read_entry(In1,e1,i1);
251 }while(b1 && e1->key==U64(0x0) && (++i1));
254 b2 = read_entry(In2,e2,i2);
255 }while(b2 && e2->key==U64(0x0) && (++i2));
259 } else if (!b1 && !b2) {
263 } else if (b1 && !b2) {
267 } else if (b2 && !b1) {
278 } else if (e1->key < e2->key) {
281 } else if (e1->key > e2->key) {
285 ASSERT(e1->key==e2->key);
297 printf("skipped %d entr%s.\n",skip,(skip>1)?"ies":"y");
305 static void book_clear(book_t * book) {
315 static void book_open(book_t * book, const char file_name[], const char mode[]) {
318 ASSERT(file_name!=NULL);
321 book->file = fopen(file_name,mode);
322 if (book->file == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));
324 if (fseek(book->file,0,SEEK_END) == -1) {
325 my_fatal("book_open(): fseek(): %s\n",strerror(errno));
328 book->size = ftell(book->file) / 16;
333 static void book_close(book_t * book) {
337 if (fclose(book->file) == EOF) {
338 my_fatal("book_close(): fclose(): %s\n",strerror(errno));
344 static bool read_entry(book_t * book, entry_t * entry, int n) {
349 if (n < 0 || n >= book->size) return FALSE;
351 ASSERT(n>=0&&n<book->size);
353 if (fseek(book->file,n*16,SEEK_SET) == -1) {
354 my_fatal("read_entry(): fseek(): %s\n",strerror(errno));
357 entry->key = read_integer(book->file,8);
358 entry->move = read_integer(book->file,2);
359 entry->count = read_integer(book->file,2);
360 entry->n = read_integer(book->file,2);
361 entry->sum = read_integer(book->file,2);
368 static void write_entry(book_t * book, const entry_t * entry) {
373 write_integer(book->file,8,entry->key);
374 write_integer(book->file,2,entry->move);
375 write_integer(book->file,2,entry->count);
376 write_integer(book->file,2,entry->n);
377 write_integer(book->file,2,entry->sum);
384 static uint64 read_integer(FILE * file, int size) {
391 ASSERT(size>0&&size<=8);
395 for (i = 0; i < size; i++) {
401 my_fatal("read_integer(): fgetc(): EOF reached\n");
403 my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));
416 static void write_integer(FILE * file, int size, uint64 n) {
422 ASSERT(size>0&&size<=8);
423 ASSERT(size==8||n>>(size*8)==0);
425 for (i = size-1; i >= 0; i--) {
427 b = (n >> (i*8)) & 0xFF;
430 if (fputc(b,file) == EOF) {
431 my_fatal("write_integer(): fputc(): %s\n",strerror(errno));
436 // end of book_merge.cpp