version 1.4.46b
[polyglot.git] / main.c
diff --git a/main.c b/main.c
index fad2ed8..aaadc82 100644 (file)
--- a/main.c
+++ b/main.c
@@ -7,6 +7,7 @@
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
+#include <time.h>\r
 \r
 #include "attack.h"\r
 #include "board.h"\r
 #include "xboard2uci.h"\r
 #include "uci2uci.h"\r
 #include "ini.h"\r
+#include "util.h"\r
+\r
 \r
 // constants\r
 \r
 \r
-static const char * const Version = "1.4.42b";\r
+static const char * const Version = "1.4.46b";\r
 static const char * const HelpMessage = "\\r
 SYNTAX\n\\r
 * polyglot [configfile] [-noini] [-ec engine] [-ed enginedirectory] [-en enginename] [-log] [-lf logfile] [-hash value] [-bk book] [-pg <name>=<value>]* [-uci <name>=<value>]*\n\\r
@@ -52,6 +55,22 @@ static const int SearchDepth = 63;
 static const double SearchTime = 3600.0;\r
 static const int StringSize = 4096;\r
 \r
+static const char * const IniIntro=\r
+              "; This ini file is used internally by PolyGlot\n"\r
+              "; to remember the settings for the UCI engine\n"\r
+              "; whose name is \"%s\".\n"\r
+              "\n"\r
+              "; The values for these settings would be typicallly\n"\r
+              "; obtained from the engine settings dialog\n"\r
+              "; in WinBoard/xboard 4.4.0 and higher.\n"\r
+              "\n" \r
+              "; If the value of the option \"Persist\" is false\n"\r
+              "; then the content of this file is ignored.\n"\r
+              "\n"\r
+              "; It is allowed to manually edit this file\n"\r
+              "; and you may safely delete it as well.\n"\r
+              "\n";\r
+\r
 // variables\r
 \r
 static bool Init;\r
@@ -72,43 +91,78 @@ static void arg_shift_left(char **argv, int index){
     }\r
 }\r
 \r
+\r
+// make_ini()\r
+\r
+static void make_ini(ini_t *ini){\r
+    option_t *opt;\r
+    char tmp[StringSize];\r
+    ini_insert_ex(ini,"polyglot",\r
+                 "EngineName",\r
+                 option_get_string(Option,"EngineName"));\r
+    ini_insert_ex(ini,"polyglot",\r
+                 "EngineCommand",\r
+                 option_get_string(Option,"EngineCommand"));\r
+    ini_insert_ex(ini,"polyglot",\r
+                 "EngineDir",\r
+                 option_get_string(Option,"EngineDir"));\r
+    option_start_iter(Option);\r
+    while((opt=option_next(Option))){\r
+        if(!my_string_equal(opt->value,opt->default_)&&\r
+           !IS_BUTTON(opt->type) &&\r
+           (opt->mode & XBOARD)){\r
+         ini_insert_ex(ini,"polyglot",opt->name,opt->value);\r
+        }\r
+    }\r
+    option_start_iter(Uci->option);\r
+    while((opt=option_next(Uci->option))){\r
+        if(!my_string_equal(opt->value,opt->default_)&&\r
+           !IS_BUTTON(opt->type)){\r
+         ini_insert_ex(ini,"engine",opt->name,opt->value);\r
+        }\r
+    }\r
+}\r
+\r
+\r
 // write_ini()\r
 \r
 static void write_ini(const char *filename,\r
-                      option_list_t *pg_options,\r
-                      option_list_t *uci_options){\r
-    option_t *opt;\r
+                        ini_t *ini){\r
+    ini_entry_t *entry;\r
     char tmp[StringSize];\r
     FILE *f;\r
+    time_t t=time(NULL);\r
     f=fopen(filename,"w");\r
     if(!f){\r
-        my_fatal("ini_create_pg(): Cannot open %s for writing.\n",filename);\r
-    }\r
-    fprintf(f,"; You may edit this file to set options for the\n"\r
-              "; UCI engine whose PolyGlot name is %s.\n"\r
-              "; You may also safely delete this file\n"\r
-              "; to restore the default options.\n",\r
-            option_get_string(Option,"EngineName"));\r
+      // alas this does nothing....\r
+      gui_send(GUI,"tellusererror write_ini(): %s: %s.",filename,strerror(errno));\r
+      // but at least we log the error\r
+      my_log("POLYGLOT write_ini(): %s: %s.\n",filename,strerror(errno));\r
+      return;\r
+    }\r
+    fprintf(f,"; %s\n",ctime(&t));\r
+    fprintf(f,IniIntro,option_get_string(Option,"EngineName"));\r
     fprintf(f,"[PolyGlot]\n");\r
-    option_start_iter(pg_options);\r
-    while((opt=option_next(pg_options))){\r
-        if(!my_string_equal(opt->value,opt->default_)&&\r
-           !my_string_case_equal(opt->type,"button") &&\r
-           (opt->mode & XBOARD)){\r
-            snprintf(tmp,sizeof(tmp),"%s=%s\n",opt->name,opt->value);\r
-            tmp[sizeof(tmp)-1]='\0';\r
-            fprintf(f,"%s",tmp);\r
-        }\r
+    ini_start_iter(ini);\r
+    while((entry=ini_next(ini))){\r
+      if(my_string_case_equal(entry->section,"polyglot")){\r
+       snprintf(tmp,sizeof(tmp),"%s=%s\n",\r
+                entry->name,\r
+                entry->value);\r
+       tmp[sizeof(tmp)-1]='\0';\r
+       fprintf(f,"%s",tmp);\r
+      }\r
     }\r
     fprintf(f,"[Engine]\n");\r
-    option_start_iter(uci_options);\r
-    while((opt=option_next(uci_options))){\r
-        if(!my_string_equal(opt->value,opt->default_)&&\r
-           !my_string_case_equal(opt->type,"button")){\r
-            snprintf(tmp,sizeof(tmp),"%s=%s\n",opt->name,opt->value);\r
-            tmp[sizeof(tmp)-1]='\0';\r
-            fprintf(f,"%s",tmp);\r
-        }\r
+    ini_start_iter(ini);\r
+    while((entry=ini_next(ini))){\r
+      if(my_string_case_equal(entry->section,"engine")){\r
+       snprintf(tmp,sizeof(tmp),"%s=%s\n",\r
+                entry->name,\r
+                entry->value);\r
+       tmp[sizeof(tmp)-1]='\0';\r
+       fprintf(f,"%s",tmp);\r
+      }\r
     }\r
     fclose(f);\r
 }\r
@@ -121,7 +175,8 @@ int main(int argc, char * argv[]) {
     ini_entry_t *entry;\r
     char *arg;\r
     int arg_index;\r
-    bool NoIni;\r
+    bool NoIni, Persist;\r
+    char persist_path[StringSize];\r
  \r
     if(!DEBUG){\r
         printf("PolyGlot %s by Fabien Letouzey.\n",Version);\r
@@ -299,8 +354,8 @@ int main(int argc, char * argv[]) {
         my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
     }\r
 \r
-        // initialize uci parsing and send uci command. Parse options and wait\r
-        // for uciok\r
+        // initialize uci parsing and send uci command. \r
+        // Parse options and wait for uciok\r
     \r
     uci_open(Uci,Engine);\r
 \r
@@ -314,22 +369,50 @@ int main(int argc, char * argv[]) {
 \r
     if(my_string_equal(option_get_string(Option,"PersistFile"),"<empty>")){\r
         char tmp[StringSize];\r
-        snprintf(tmp,sizeof(tmp),"PG_%s.ini",\r
+       int i;\r
+        snprintf(tmp,sizeof(tmp),"%s.ini",\r
                  option_get_string(Option,"EngineName"));\r
         tmp[sizeof(tmp)-1]='\0';\r
+       for(i=0;i<strlen(tmp);i++){\r
+         if(tmp[i]==' '){\r
+           tmp[i]='_';\r
+         }\r
+       }\r
         option_set(Option,"PersistFile",tmp);\r
     }\r
 \r
-        // if "Persist" is true, load the persist file!\r
-    \r
-    if(option_get_bool(Option,"Persist")){\r
-        my_log("POLYGLOT PersistFile=%s\n",option_get_string(Option,"PersistFile"));\r
-        if(ini_parse(ini_save,option_get_string(Option,"PersistFile"))){\r
-            my_log("POLYGLOT Unable to open PersistFile\n"); \r
-        }\r
+    // Load the persist file\r
+\r
+    my_path_join(persist_path,\r
+                 option_get_string(Option,"PersistDir"),\r
+                 option_get_string(Option,"PersistFile"));\r
+\r
+    my_log("POLYGLOT PersistFile=%s\n",persist_path);   \r
+    if(ini_parse(ini_save,persist_path)){\r
+      my_log("POLYGLOT Unable to open PersistFile\n"); \r
     }\r
-    \r
-        // parse the command line and merge remaining options\r
+\r
+    // Do we want to use the persist file?\r
+\r
+    entry=ini_find(ini_save,"polyglot","Persist");\r
+    if(!entry){\r
+      Persist=option_get_bool(Option,"Persist");\r
+    }else{\r
+      Persist=(my_string_case_equal(entry->value,"false") || \r
+              my_string_equal(entry->value,"0"))?FALSE:TRUE;\r
+    }\r
+\r
+    // if "Persist" now happens to be false, forget about the\r
+    // persist file    \r
+\r
+    if(!Persist){\r
+      my_log("POLYGLOT Ignoring PersistFile");\r
+      ini_clear(ini_save);\r
+    }\r
+\r
+    option_set(Option,"Persist",Persist?"true":"false");\r
+\r
+    // parse the command line and merge remaining options\r
 \r
     arg_index=1;\r
     while((arg=argv[arg_index])){\r
@@ -380,16 +463,24 @@ int main(int argc, char * argv[]) {
 \r
         // remind the reader once again about options\r
 \r
-    my_log("POLYGLOG Options from save file and command line\n");\r
+    my_log("POLYGLOG Options from PersistFile and command line\n");\r
     ini_disp(ini_save);\r
 \r
-        // extract PG options; this time do not set the default\r
+        // Extract PG options; this time do not set the default.\r
         // polyglot_set_option() performs the necessary actions such\r
         // as opening the log file/opening book etcetera.\r
+        // Ignore EngineName, EngineCommand and EngineDir\r
+        // as these are really meant as comments.\r
     \r
     ini_start_iter(ini_save);\r
     while((entry=ini_next(ini_save))){\r
         if(my_string_case_equal(entry->section,"polyglot")){\r
+           if(my_string_case_equal(entry->value,"EngineName")) \r
+              continue;\r
+           if(my_string_case_equal(entry->value,"EngineCommand")) \r
+              continue;\r
+           if(my_string_case_equal(entry->value,"EngineDir")) \r
+              continue;\r
             polyglot_set_option(entry->name,entry->value);\r
         }\r
     }\r
@@ -452,7 +543,24 @@ int main(int argc, char * argv[]) {
 // polyglot_set_option()\r
 \r
 void polyglot_set_option(const char *name, const char *value){ // this must be cleaned up!\r
+    option_t *opt;\r
     my_log("POLYGLOT Setting PolyGlot option %s=\"%s\"\n",name,value);\r
+    if(my_string_case_equal(name,"Defaults")){\r
+      option_start_iter(Uci->option);\r
+      while((opt=option_next(Uci->option))){\r
+       if(!IS_BUTTON(opt->type)){\r
+       // also sets opt->value\r
+         uci_send_option(Uci,opt->name,opt->default_);\r
+       }\r
+      }\r
+      option_start_iter(Option);\r
+      while((opt=option_next(Option))){\r
+       if(!IS_BUTTON(opt->type)){\r
+         polyglot_set_option(opt->name,opt->default_);\r
+       }\r
+      }\r
+      xboard2uci_send_options();\r
+    }\r
     option_set(Option,name,value);\r
     if(option_get_bool(Option,"Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){\r
         my_log("POLYGLOT *** SETTING BOOK ***\n");\r
@@ -464,7 +572,7 @@ void polyglot_set_option(const char *name, const char *value){ // this must be c
             my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string(Option,"BookFile"));\r
         }\r
     }else if(option_get_bool(Option,"Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){\r
-        my_log("POLYGLOT *** SETTING LOGFILE ***\n");\r
+        my_log("POLYGLOT *** SWITCHING LOGFILE ***\n");\r
         my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string(Option,"LogFile"));\r
         my_log_close();\r
         my_log_open(option_get_string(Option,"LogFile"));\r
@@ -504,6 +612,12 @@ static void init_book(){
 \r
 void quit() {\r
 \r
+    ini_t ini[1];\r
+    char persist_path[StringSize];\r
+    int ret;\r
+\r
+    ini_init(ini);\r
+\r
     my_log("POLYGLOT *** QUIT ***\n");\r
     \r
     if (Init) {\r
@@ -514,11 +628,34 @@ void quit() {
         engine_close(Engine);\r
         \r
     }\r
-    if(option_get_bool(Option,"Persist")){\r
-        write_ini(option_get_string(Option,"PersistFile"),\r
-                  Option,Uci->option);\r
+    ret=my_mkdir(option_get(Option,"PersistDir"));\r
+    if(ret){\r
+      my_log("POLYGLOT quit(): %s: %s\n",option_get(Option,"PersistDir"),strerror(errno));\r
+    }\r
+    // PersistFile can be named "<empty>" in case of a crash before the\r
+    // engine is started. \r
+    if(!my_string_case_equal(option_get(Option,"PersistFile"),\r
+                            "<empty>")){\r
+      // Persistence should only work in XBOARD mode.\r
+      // In UCI mode the GUI is responsible for remembering options.\r
+      if(!option_get_bool(Option,"UCI")){\r
+       my_path_join(persist_path,\r
+                    option_get(Option,"PersistDir"),\r
+                    option_get(Option,"PersistFile"));\r
+       make_ini(ini);\r
+       if(option_get_bool(Option,"Persist")){\r
+         write_ini(persist_path,ini);\r
+       }else if(!my_string_case_equal(option_get_default(Option,"Persist"),\r
+                                      option_get_string(Option,"Persist"))){\r
+         // Hack\r
+         ini_insert_ex(ini,"polyglot","Persist","false");\r
+         write_ini(persist_path,ini);\r
+       }else{\r
+         write_ini(persist_path,ini);\r
+       }\r
+       my_log("POLYGLOT Calling exit\n");\r
+      }\r
     }\r
-    my_log("POLYGLOT Calling exit\n");\r
     exit(EXIT_SUCCESS);\r
 }\r
 \r