version 1.4.44b
[polyglot.git] / main.c
diff --git a/main.c b/main.c
index e49f51d..8bd6276 100644 (file)
--- a/main.c
+++ b/main.c
 #include "util.h"\r
 #include "xboard2uci.h"\r
 #include "uci2uci.h"\r
+#include "ini.h"\r
 \r
 // constants\r
 \r
 \r
-static const char * const Version = "1.4.36b";\r
+static const char * const Version = "1.4.44b";\r
 static const char * const HelpMessage = "\\r
 SYNTAX\n\\r
-* polyglot [configfile]\n\\r
-* polyglot -ec enginecommand\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
 * polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game games] [-min-score score] [-only-white] [-only-black] [-uniform]\n\\r
 * polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\\r
 * polyglot info-book [-bin inputfile] [-exact]\n\\r
 * polyglot dump-book [-bin inputfile] -color color [-out outputfile]\n\\r
-* polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-min-time time] [-max-time time] [-depth-delta delta]\n\\r
+* polyglot [configfile] epd-test [engineoptions] [-epd inputfile] [-min-depth depth] [-max-depth depth] [-min-time time] [-max-time time] [-depth-delta delta]\n\\r
 * polyglot perft [-fen fen] [-max-depth depth]\\r
 ";\r
 \r
@@ -58,17 +58,112 @@ static bool Init;
 \r
 // prototypes\r
 \r
-static void parse_option ();\r
 static void init_book ();\r
-static bool parse_line   (char line[], char * * name_ptr, char * * value_ptr);\r
 static void stop_search  ();\r
 \r
 // functions\r
 \r
+// arg_shift_left()\r
+\r
+static void arg_shift_left(char **argv, int index){\r
+    int i;\r
+    for(i=index; argv[i]!=NULL; i++){\r
+        argv[i]=argv[i+1];\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
+    char tmp[StringSize];\r
+    FILE *f;\r
+    f=fopen(filename,"w");\r
+    if(!f){\r
+        my_fatal("write_ini(): 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
+    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
+           !IS_BUTTON(opt) &&\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
+    }\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
+           !IS_BUTTON(opt)){\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
+    }\r
+    fclose(f);\r
+}\r
+\r
+// write_ini_ex()\r
+\r
+static void write_ini_ex(const char *filename,\r
+                        ini_t *ini){\r
+    ini_entry_t *entry;\r
+    char tmp[StringSize];\r
+    FILE *f;\r
+    f=fopen(filename,"w");\r
+    if(!f){\r
+        my_fatal("write_ini_ex(): 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
+    fprintf(f,"[PolyGlot]\n");\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
+    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
+\r
+\r
 // main()\r
 \r
 int main(int argc, char * argv[]) {\r
-\r
+    ini_t ini[1],ini_save[1];\r
+    ini_entry_t *entry;\r
+    char *arg;\r
+    int arg_index;\r
+    bool NoIni, Persist;\r
\r
     if(!DEBUG){\r
         printf("PolyGlot %s by Fabien Letouzey.\n",Version);\r
     }else{\r
@@ -92,10 +187,13 @@ int main(int argc, char * argv[]) {
     attack_init();\r
     \r
     hash_init();\r
-    \r
+\r
     my_random_init();\r
 \r
-        // build book\r
+    ini_init(ini);\r
+    ini_init(ini_save);\r
+\r
+        // book utilities\r
     \r
     if (argc >= 2 && my_string_equal(argv[1],"make-book")) {\r
         book_make(argc,argv);\r
@@ -107,72 +205,330 @@ int main(int argc, char * argv[]) {
         return EXIT_SUCCESS;\r
     }\r
 \r
-       if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
-      book_merge(argc,argv);\r
-      return EXIT_SUCCESS;\r
-   }\r
-\r
-   if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {\r
-      book_dump(argc,argv);\r
-      return EXIT_SUCCESS;\r
-   }\r
+    if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {\r
+        book_dump(argc,argv);\r
+        return EXIT_SUCCESS;\r
+    }\r
+    \r
+    if (argc >= 2 && my_string_equal(argv[1],"info-book")) {\r
+        book_info(argc,argv);\r
+        return EXIT_SUCCESS;\r
+    }\r
 \r
-   if (argc >= 2 && my_string_equal(argv[1],"info-book")) {\r
-      book_info(argc,argv);\r
-      return EXIT_SUCCESS;\r
-   }\r
+        // perft\r
     \r
     if (argc >= 2 && my_string_equal(argv[1],"perft")) {\r
         do_perft(argc,argv);\r
         return EXIT_SUCCESS;\r
     }\r
+\r
+        // TODO: If logging is enabled on the command line turn it on NOW\r
+        // and do not allow it to be overridden later. \r
     \r
-    if (argc >= 3 && my_string_equal(argv[1],"-ec")) {\r
-        option_set(Option,"EngineCommand",argv[2]);\r
-        engine_open(Engine);\r
-        if(!engine_active(Engine)){\r
-            my_fatal("Could not start \"%s\"\n",\r
-                     option_get(Option,"EngineCommand"));\r
+        // What is the config file? This is very hacky right now.\r
+\r
+        // Do we want a config file at all?\r
+\r
+    arg_index=0;\r
+    NoIni=FALSE;\r
+    while((arg=argv[arg_index++])){\r
+        if(my_string_equal(arg,"-noini")){\r
+            NoIni=TRUE;\r
+            break;\r
         }\r
-        Init=TRUE;\r
-        gui_init(GUI);\r
-        uci_open(Uci,Engine);\r
-        if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {\r
-            option_set(Option,"EngineName",Uci->name);\r
+    }\r
+    arg_shift_left(argv,arg_index-1);\r
+    if(NoIni){\r
+        option_set(Option,"OptionFile","<empty>");\r
+    }\r
+\r
+        // Ok see if first argument looks like config file\r
+    \r
+    if(argv[1] && !my_string_equal(argv[1],"epd-test") && !(argv[1][0]=='-')){\r
+                // first argument must be  config file\r
+        if(!NoIni){\r
+            option_set(Option,"OptionFile",argv[1]);\r
+        }else{\r
+                // ignore\r
         }\r
-        mainloop();\r
-        return EXIT_SUCCESS; \r
+        arg_shift_left(argv,1);\r
+    }else{\r
+            // Config file is the default.\r
+            // This has already been set above or in "option_init_pg()"\r
     }\r
     \r
-        // read options\r
 \r
+        // if we use a config file: load it!\r
+    \r
+    if(!my_string_equal(option_get_string(Option,"OptionFile"),"<empty>")){\r
+        if(ini_parse(ini,option_get_string(Option,"OptionFile"))){\r
+            my_fatal("main(): Can't open file \"%s\": %s\n",\r
+                   option_get_string(Option,"OptionFile"),\r
+                   strerror(errno));\r
+        }\r
+    }\r
+        // remind the reader of what options are in effect\r
+\r
+    my_log("POLYGLOG Options from ini file\n");\r
+    ini_disp(ini);\r
+\r
+        // extract PG options\r
+    \r
+    ini_start_iter(ini);\r
+    while((entry=ini_next(ini))){\r
+        if(my_string_case_equal(entry->section,"polyglot")){\r
+            option_set(Option,entry->name,entry->value);\r
+            option_set_default(Option,entry->name,entry->value);\r
+        }\r
+    }\r
+\r
+        // start logging if required\r
+    \r
+    if (option_get_bool(Option,"Log")) {\r
+        my_log_open(option_get_string(Option,"LogFile"));\r
+    }\r
+\r
+        // log welcome stuff\r
+    \r
+    if(!DEBUG){\r
+        my_log("PolyGlot %s by Fabien Letouzey\n",Version);\r
+    }else{\r
+        my_log("PolyGlot %s by Fabien Letouzey (debug build)\n",Version);\r
+    }    \r
+    my_log("POLYGLOT *** START ***\n");\r
+    my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"OptionFile"));\r
+\r
+        // open book (presumably this should go else where)\r
+    \r
+    init_book();\r
+\r
+        // scavenge command line for options necessary to start the engine\r
+    \r
+    arg_index=1;\r
+    while((arg=argv[arg_index])){\r
+        if(my_string_equal(arg,"-ec") && argv[arg_index+1]){\r
+            option_set(Option,"EngineCommand",argv[arg_index+1]);\r
+            arg_shift_left(argv,arg_index);\r
+            arg_shift_left(argv,arg_index);\r
+            continue;\r
+        }\r
+        if(my_string_equal(arg,"-ed") && argv[arg_index+1]){\r
+            option_set(Option,"EngineDir",argv[arg_index+1]);\r
+            arg_shift_left(argv,arg_index);\r
+            arg_shift_left(argv,arg_index);\r
+            continue;\r
+        }\r
+        if(my_string_equal(arg,"-en") && argv[arg_index+1]){\r
+            option_set(Option,"EngineName",argv[arg_index+1]);\r
+            arg_shift_left(argv,arg_index);\r
+            arg_shift_left(argv,arg_index);\r
+            continue;\r
+        }\r
+        arg_index++;\r
+    }\r
+\r
+        // start engine\r
+    \r
+    engine_open(Engine);\r
+    if(!engine_active(Engine)){\r
+        my_fatal("Could not start \"%s\"\n",option_get(Option,"EngineCommand"));\r
+    }\r
+\r
+        // switch to UCI mode if necessary\r
+    \r
+    if (option_get_bool(Option,"UCI")) {\r
+        my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
+    }\r
+\r
+        // initialize uci parsing and send uci command. \r
+        // Parse options and wait for uciok\r
+    \r
+    uci_open(Uci,Engine);\r
+\r
+        // get engine name from engine if not supplied in config file\r
+    \r
+    if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {\r
+        option_set(Option,"EngineName",Uci->name);\r
+    }\r
+\r
+        // what is the name of the persist file?\r
+\r
+    if(my_string_equal(option_get_string(Option,"PersistFile"),"<empty>")){\r
+        char tmp[StringSize];\r
+        snprintf(tmp,sizeof(tmp),"PG_%s.ini",\r
+                 option_get_string(Option,"EngineName"));\r
+        tmp[sizeof(tmp)-1]='\0';\r
+        option_set(Option,"PersistFile",tmp);\r
+    }\r
+\r
+    // Load the persist file\r
+\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
+\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
+        if(my_string_equal(arg,"-log")){\r
+            ini_insert_ex(ini_save,"PolyGlot","Log","true");\r
+            arg_shift_left(argv,arg_index);\r
+            continue;\r
+        }\r
+        if(my_string_equal(arg,"-lf") && argv[arg_index+1]){\r
+            ini_insert_ex(ini_save,"PolyGlot","LogFile",argv[arg_index+1]);\r
+            arg_shift_left(argv,arg_index);\r
+            arg_shift_left(argv,arg_index);\r
+            continue;\r
+        }\r
+        if(my_string_equal(arg,"-hash") && argv[arg_index+1]){\r
+            ini_insert_ex(ini_save,"Engine","Hash",argv[arg_index+1]);\r
+            arg_shift_left(argv,arg_index);\r
+            arg_shift_left(argv,arg_index);\r
+            continue;\r
+        }\r
+        if(my_string_equal(arg,"-bk") && argv[arg_index+1]){\r
+            ini_insert_ex(ini_save,"PolyGlot","Book","true");\r
+            ini_insert_ex(ini_save,"PolyGlot","BookFile",argv[arg_index+1]);\r
+            arg_shift_left(argv,arg_index);\r
+            arg_shift_left(argv,arg_index);\r
+            continue;\r
+        }\r
+        if((my_string_equal(arg,"-pg")||my_string_equal(arg,"-uci")) &&\r
+           argv[arg_index]){\r
+            int ret;\r
+            char section[StringSize];\r
+            char name[StringSize];\r
+            char value[StringSize];\r
+            ret=ini_line_parse(argv[arg_index++],section,name,value);\r
+            if(ret==NAME_VALUE){\r
+                if(my_string_equal(arg,"-pg")){\r
+                    ini_insert_ex(ini_save,"PolyGlot",name,value);\r
+                }else{\r
+                    ini_insert_ex(ini_save,"Engine",name,value);\r
+                }\r
+            }\r
+            arg_shift_left(argv,arg_index);\r
+            arg_shift_left(argv,arg_index);\r
+            continue;\r
+        }\r
+        arg_index++;\r
+    }\r
+\r
+        // remind the reader once again about options\r
+\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
+        // polyglot_set_option() performs the necessary actions such\r
+        // as opening the log file/opening book etcetera.\r
     \r
-    if (argc == 2) option_set(Option,"OptionFile",argv[1]); // HACK for compatibility\r
+    ini_start_iter(ini_save);\r
+    while((entry=ini_next(ini_save))){\r
+        if(my_string_case_equal(entry->section,"polyglot")){\r
+            polyglot_set_option(entry->name,entry->value);\r
+        }\r
+    }\r
 \r
-    parse_option(); // HACK: also launches the engine\r
+        // done initializing\r
+    \r
+    Init = TRUE;\r
+    \r
+        // collect engine options from config file(s) and send to engine\r
+    \r
+    ini_start_iter(ini);\r
+    while((entry=ini_next(ini))){\r
+        if(my_string_case_equal(entry->section,"engine")){\r
+                // also updates value in Uci->option\r
+            uci_send_option(Uci,entry->name,"%s",entry->value);\r
+                // since this comes from the ini file, also update default\r
+            option_set_default(Uci->option,entry->name,entry->value);\r
+                // this is inherited, it probably does not work correctly\r
+           if(my_string_case_equal(entry->name,"MultiPV") &&\r
+              atoi(entry->value)>1){\r
+               Uci->multipv_mode=TRUE;\r
+           }\r
+        }\r
+    }\r
+    ini_start_iter(ini_save);\r
+    while((entry=ini_next(ini_save))){\r
+        if(my_string_case_equal(entry->section,"engine")){\r
+                // also updates value in Uci->option\r
+            uci_send_option(Uci,entry->name,"%s",entry->value);\r
+                // this is inherited, it probably does not work correctly\r
+            if(my_string_case_equal(entry->name,"MultiPV") &&\r
+               atoi(entry->value)>1){\r
+                Uci->multipv_mode=TRUE;\r
+            }\r
+        }\r
+    }\r
+   \r
     \r
         // EPD test\r
     \r
-    if (argc >= 2 && my_string_equal(argv[1],"epd-test")){\r
-        epd_test(argc,argv);\r
-        return EXIT_SUCCESS;\r
-    }else if(argc >= 3 && my_string_equal(argv[2],"epd-test")){\r
-        epd_test(argc-1,argv+1);\r
+    if (argv[1] && my_string_equal(argv[1],"epd-test")){\r
+        argc=0;\r
+        while((arg=argv[argc++]));\r
+        epd_test(argc-1,argv);\r
         return EXIT_SUCCESS;\r
     }\r
     \r
-    if (argc >= 3) my_fatal("Too many arguments\n");\r
+        // Anything that hasn't been parsed yet is a syntax error\r
+\r
+    if(argv[1]){\r
+        my_fatal("main(): Unknown option: %s\n",argv[1]);\r
+    }\r
 \r
 \r
-    init_book();\r
     gui_init(GUI);\r
     mainloop();\r
     return EXIT_SUCCESS; \r
 }\r
 \r
-// polyglot_set_option\r
-\r
-void polyglot_set_option(char *name, char *value){ // this must be cleaned up!\r
+// 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)){\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)){\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
@@ -184,7 +540,7 @@ void polyglot_set_option(char *name, char *value){ // this must be cleaned up!
             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
@@ -219,135 +575,15 @@ static void init_book(){
     }\r
 }\r
 \r
-// parse_option()\r
-\r
-static void parse_option() {\r
-\r
-    const char * file_name;\r
-    FILE * file;\r
-    char line[256];\r
-    char * name, * value;\r
-    file_name = option_get_string(Option,"OptionFile");\r
-    \r
-    file = fopen(file_name,"r");\r
-    if (file == NULL) {\r
-        my_fatal("Can't open file \"%s\": %s\n",file_name,strerror(errno));\r
-    }\r
-    \r
-        // PolyGlot options (assumed first)\r
-    \r
-   while (TRUE) {\r
-       \r
-       if (!my_file_read_line(file,line,256)) {\r
-           my_fatal("parse_option(): missing [Engine] section\n");\r
-       }\r
-       \r
-       if (my_string_case_equal(line,"[engine]")) break;\r
-       \r
-       if (parse_line(line,&name,&value)) {\r
-           option_set(Option,name,value);\r
-           option_set_default(Option,name,value);\r
-       }\r
-   }\r
-   \r
-   if (option_get_bool(Option,"Log")) {\r
-       my_log_open(option_get_string(Option,"LogFile"));\r
-   }\r
-   \r
-   if(!DEBUG){\r
-       my_log("PolyGlot %s by Fabien Letouzey\n",Version);\r
-   }else{\r
-       my_log("PolyGlot %s by Fabien Letouzey (debug build)\n",Version);\r
-   }\r
-\r
-   my_log("POLYGLOT *** START ***\n");\r
-   my_log("POLYGLOT INI file \"%s\"\n",file_name);\r
-   engine_open(Engine);\r
-   if(!engine_active(Engine)){\r
-       my_fatal("Could not start \"%s\"\n",option_get(Option,"EngineCommand"));\r
-   }\r
-\r
-   if (option_get_bool(Option,"UCI")) {\r
-       my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
-   }\r
-   uci_open(Uci,Engine);\r
-   Init = TRUE;\r
-   while (my_file_read_line(file,line,256)) {\r
-       if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line);\r
-       if (parse_line(line,&name,&value)) {\r
-           uci_send_option(Uci,name,"%s",value);\r
-               //to get a decent display in winboard_x we need to now if an engine really is doing multipv analysis\r
-               // "multipv 1" in the pv is meaningless,f.i. toga sends that all the time\r
-               //therefore check if MultiPV is set to a decent value in the polyglot ini file\r
-           if(my_string_case_equal(name,"MultiPV") && atoi(value)>1)  Uci->multipv_mode=TRUE;\r
-       }\r
-   }\r
-   if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {\r
-       option_set(Option,"EngineName",Uci->name);\r
-   }\r
-   \r
-   fclose(file);\r
-}\r
-\r
-// parse_line()\r
-\r
-static bool parse_line(char line[], char * * name_ptr, char * * value_ptr) {\r
-    \r
-    char * ptr;\r
-    char * name, * value;\r
-    \r
-    ASSERT(line!=NULL);\r
-    ASSERT(name_ptr!=NULL);\r
-    ASSERT(value_ptr!=NULL);\r
-    \r
-        // remove comments\r
-    \r
-    ptr = strchr(line,';');\r
-    if (ptr != NULL) *ptr = '\0';\r
-    \r
-    ptr = strchr(line,'#');\r
-    if (ptr != NULL) *ptr = '\0';\r
-    \r
-        // split at '='\r
-    \r
-    ptr = strchr(line,'=');\r
-    if (ptr == NULL) return FALSE;\r
-    \r
-    name = line;\r
-    value = ptr+1;\r
-   \r
-        // cleanup name\r
-    \r
-    while (*name == ' ') name++; // remove leading spaces\r
-    \r
-    while (ptr > name && ptr[-1] == ' ') ptr--; // remove trailing spaces\r
-    *ptr = '\0';\r
-    \r
-    if (*name == '\0') return FALSE;\r
-    \r
-        // cleanup value\r
-    \r
-    ptr = &value[strlen(value)]; // pointer to string terminator\r
-    \r
-    while (*value == ' ') value++; // remove leading spaces\r
-    \r
-    while (ptr > value && ptr[-1] == ' ') ptr--; // remove trailing spaces\r
-    *ptr = '\0';\r
-    \r
-    if (*value == '\0') return FALSE;\r
-   \r
-        // end\r
-    \r
-    *name_ptr = name;\r
-    *value_ptr = value;\r
-    \r
-    return TRUE;\r
-}\r
 \r
 // quit()\r
 \r
 void quit() {\r
 \r
+    ini_t empty[1];\r
+\r
+    ini_init(empty);\r
+\r
     my_log("POLYGLOT *** QUIT ***\n");\r
     \r
     if (Init) {\r
@@ -358,6 +594,18 @@ void quit() {
         engine_close(Engine);\r
         \r
     }\r
+    //    printf("def=%s val=%s\n",option_get_default(Option,"Persist"),option_get_string(Option,"Persist"));\r
+    if(option_get_bool(Option,"Persist")){\r
+        write_ini(option_get_string(Option,"PersistFile"),\r
+                  Option,Uci->option);\r
+    }else if(!my_string_case_equal(option_get_default(Option,"Persist"),\r
+                                 option_get_string(Option,"Persist"))){\r
+      // Hack\r
+      ini_insert_ex(empty,"PolyGlot","Persist","false");\r
+      write_ini_ex(option_get_string(Option,"PersistFile"),empty);\r
+    }else{\r
+      write_ini_ex(option_get_string(Option,"PersistFile"),empty);\r
+    }\r
     my_log("POLYGLOT Calling exit\n");\r
     exit(EXIT_SUCCESS);\r
 }\r