version 1.4.34b
authorH.G. Muller <h.g.muller@hccnet.nl>
Thu, 9 Jun 2011 07:57:41 +0000 (09:57 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Thu, 9 Jun 2011 07:57:41 +0000 (09:57 +0200)
30 files changed:
ChangeLog
README
TODO
book.c
config.h
configure
configure.ac
engine.c
engine.h
epd.c
fen.c
gui.c
io.c
main.c
mainloop.c
move.c
option.c
option.h
pipex.h
pipex_posix.c
pipex_win32.c
polyglot.man
polyglot.pod
polyglot.spec
uci.c
uci.h
uci2uci.c
util.c
util.h
xboard2uci.c

index 070eeb7..b63a77a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+=========1.4.34b================\r
+- Warning: this release is less well tested as usual\r
+- Allow spaces around "=" in "option =" commands.\r
+- WbWorkArounds is now true by default.\r
+- Trying to set a non existent UCI option gives an error. \r
+- PG will now resign in case of an illegal engine move. \r
+- More code has been put in "pipex".\r
+- info strings and unrecognized info lines are relayed to the GUI.\r
 =========1.4.33b================\r
 - New option: "WbWorkArounds". Currently it blocks options which contain "Draw" in their name from being sent to the GUI. Engines that have such options are Rybka and HIARCS. \r
 - Bugfix for ASSERT failure in bright. Now another ASSERT failure has appeared which seems to be bright's fault however. \r
diff --git a/README b/README
index f36abee..df31a94 100644 (file)
--- a/README
+++ b/README
@@ -399,12 +399,11 @@ CONFIG FILE FORMAT
 
        Work arounds are identical to options except that they should be used
        only when necessary.  Their purpose is to try to hide problems with
-       various software (not just engines).  The default value is always cor-
-       rect for bug-free software.
+       various software (not just engines).
 
-       IMPORTANT: Any of these work arounds might be removed in future ver-
-       sions of PolyGlot.  You are strongly recommended to contact the author
-       of faulty software and truly fix the problem.
+       IMPORTANT: Any of these work arounds might be removed in future
+       versions of PolyGlot.  You are strongly recommended to contact the
+       author of faulty software and truly fix the problem.
 
        PolyGlot supports the following work arounds:
 
@@ -440,13 +439,12 @@ CONFIG FILE FORMAT
            to the way kibitzing is implemented, KibitzMove is disabled in that
            case.
 
-       WbWorkArounds (default: false)
+       WbWorkArounds (default: true)
            The intention of this option is to provide work arounds for
-           xboard/winboard bugs should they arise.  Currently it only prevents
-           "feature option=" commands which contain "Draw" in their name from
-           being sent to the GUI. Some versions of xboard/winboard contain a
-           bug which causes such options to be interpreted as draw claims by
-           the engine.
+           xboard/winboard bugs should they arise.  Currently it decapitalizes
+           the word Draw in options that contain this word. Some versions of
+           xboard/winboard contain a bug which causes such options to be
+           interpreted as draw claims by the engine.
 
            Engines that send options with "Draw" in their name are Rybka and
            HIARCS.
@@ -523,4 +521,4 @@ SEE ALSO
 
 
 
-                                  2009-08-06                       POLYGLOT(6)
+                                  2009-08-07                       POLYGLOT(6)
diff --git a/TODO b/TODO
index 4791f92..d01fa69 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,2 +1,9 @@
-Better check for legality of arguments (i.e. stuff after [configfile]). 
-Implementation of Marc Lacrosse's utility
+Move static queue for engine writing to engine struct
+Continue refactoring of option stuff (search for option_nb)
+Make _ex versions the default (more object oriented).
+Remove most uci option commands. Refer directly to Uci->option. It will make the code more 
+readable.
+Replace "append_option" by "insert_option".
+Inifile handling. 
+Refactor removinging of trailing EOL and white space from string (see util.c and ini file parsing). 
+ML's utility
diff --git a/book.c b/book.c
index 73fb2d2..5821451 100644 (file)
--- a/book.c
+++ b/book.c
@@ -60,7 +60,7 @@ bool book_is_open(){
 void book_open(const char file_name[]) {\r
 \r
    ASSERT(file_name!=NULL);\r
-   if(option_get_bool("BookLearn")){\r
+   if(option_get_bool(Option,"BookLearn")){\r
        BookFile = fopen(file_name,"rb+");\r
    }else{\r
        BookFile = fopen(file_name,"rb");\r
index 47ea08c..10f758d 100644 (file)
--- a/config.h
+++ b/config.h
 #define PACKAGE_NAME "polyglot"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "polyglot 1.4.33b"
+#define PACKAGE_STRING "polyglot 1.4.34b"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "polyglot"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "1.4.33b"
+#define PACKAGE_VERSION "1.4.34b"
 
 /* Define to 1 if the C compiler supports function prototypes. */
 #define PROTOTYPES 1
 #define TIME_WITH_SYS_TIME 1
 
 /* Version number of package */
-#define VERSION "1.4.33b"
+#define VERSION "1.4.34b"
 
 /* Define like PROTOTYPES; this can be used by system headers. */
 #define __PROTOTYPES 1
index 264d016..e4d62f1 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for polyglot 1.4.33b.
+# Generated by GNU Autoconf 2.61 for polyglot 1.4.34b.
 #
 # Report bugs to <michel.vandenbergh@uhasselt.be>.
 #
@@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='polyglot'
 PACKAGE_TARNAME='polyglot'
-PACKAGE_VERSION='1.4.33b'
-PACKAGE_STRING='polyglot 1.4.33b'
+PACKAGE_VERSION='1.4.34b'
+PACKAGE_STRING='polyglot 1.4.34b'
 PACKAGE_BUGREPORT='michel.vandenbergh@uhasselt.be'
 
 ac_unique_file="mainloop.c"
@@ -1207,7 +1207,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures polyglot 1.4.33b to adapt to many kinds of systems.
+\`configure' configures polyglot 1.4.34b to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1273,7 +1273,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of polyglot 1.4.33b:";;
+     short | recursive ) echo "Configuration of polyglot 1.4.34b:";;
    esac
   cat <<\_ACEOF
 
@@ -1357,7 +1357,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-polyglot configure 1.4.33b
+polyglot configure 1.4.34b
 generated by GNU Autoconf 2.61
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1371,7 +1371,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by polyglot $as_me 1.4.33b, which was
+It was created by polyglot $as_me 1.4.34b, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   $ $0 $@
@@ -2061,7 +2061,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='polyglot'
- VERSION='1.4.33b'
+ VERSION='1.4.34b'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6848,7 +6848,7 @@ exec 6>&1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by polyglot $as_me 1.4.33b, which was
+This file was extended by polyglot $as_me 1.4.34b, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -6901,7 +6901,7 @@ Report bugs to <bug-autoconf@gnu.org>."
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-polyglot config.status 1.4.33b
+polyglot config.status 1.4.34b
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
index 91b66f3..5cec935 100644 (file)
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT([polyglot], [1.4.33b], [michel.vandenbergh@uhasselt.be])
+AC_INIT([polyglot], [1.4.34b], [michel.vandenbergh@uhasselt.be])
 AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([mainloop.c])
 AC_CONFIG_HEADER([config.h])
index bf7bd49..a42c36e 100644 (file)
--- a/engine.c
+++ b/engine.c
@@ -7,21 +7,15 @@
 #include <string.h>\r
 #include <errno.h>\r
 \r
-\r
 #include "engine.h"\r
 #include "option.h"\r
 #include "pipex.h"\r
 #include "util.h"\r
 \r
-// defines\r
-\r
-#define StringSize 4096\r
-\r
 // variables\r
 \r
-static int write_index = 0;\r
-static char write_buffer[StringSize];\r
 engine_t Engine[1];\r
+static const int StringSize=4096;\r
 \r
 // functions\r
 \r
@@ -40,33 +34,17 @@ void engine_set_nice_value(engine_t *engine, int value){
 // engine_send_queue()\r
 \r
 void engine_send_queue(engine_t * engine, const char *format, ...) {\r
-    va_list arg_list;\r
-    if(write_index>=StringSize){\r
-        my_fatal("engine_send_queue(): write_buffer overflow\n");\r
-    }\r
-    va_start(arg_list,format);\r
-    write_index += vsnprintf(write_buffer + write_index,\r
-                             StringSize-write_index,\r
-                             format,\r
-                             arg_list);\r
-    va_end(arg_list);\r
+    char buf[FormatBufferSize];\r
+    CONSTRUCT_ARG_STRING(format,buf);\r
+    pipex_write(engine->pipex,buf);\r
 }\r
 \r
 // engine_send()\r
 \r
 void engine_send(engine_t * engine, const char *format, ...) {\r
-    va_list arg_list;\r
-    if(write_index>=StringSize){\r
-        my_fatal("engine_send(): write_buffer overflow\n");\r
-    }\r
-    va_start(arg_list,format);\r
-    vsnprintf(write_buffer + write_index,\r
-              StringSize-write_index,\r
-              format,\r
-              arg_list);\r
-    va_end(arg_list);\r
-    pipex_writeln(engine->pipex,write_buffer);\r
-    write_index = 0;\r
+    char buf[FormatBufferSize];\r
+    CONSTRUCT_ARG_STRING(format,buf);\r
+    pipex_writeln(engine->pipex,buf);\r
 }\r
 \r
 // engine_close()\r
@@ -76,7 +54,7 @@ void engine_close(engine_t * engine){
     pipex_send_eof(engine->pipex);\r
         // TODO: Timeout\r
     while (!engine_eof(engine)) { \r
-      engine_get(Engine,string);\r
+      engine_get(engine,string);\r
     }\r
     pipex_exit(engine->pipex);\r
 }\r
@@ -85,23 +63,18 @@ void engine_close(engine_t * engine){
 \r
 void engine_open(engine_t * engine){\r
     int affinity;\r
-    char *my_dir;\r
-    if( (my_dir = my_getcwd( NULL, 0 )) == NULL )\r
-        my_fatal("engine_open(): no current directory: %s\n",strerror(errno));\r
-    if(my_chdir(option_get_string("EngineDir"))){\r
-        my_fatal("engine_open(): cannot change directory: %s\n",strerror(errno));\r
-    }\r
-    pipex_open(engine->pipex,"Engine",option_get_string("EngineCommand"));\r
+    pipex_open(engine->pipex,\r
+               "Engine",\r
+               option_get_string(Option,"EngineDir"),\r
+               option_get_string(Option,"EngineCommand"));\r
     if(pipex_active(engine->pipex)){\r
             //play with affinity (bad idea)\r
-        affinity=option_get_int("Affinity");\r
+        affinity=option_get_int(Option,"Affinity");\r
         if(affinity!=-1) set_affinity(engine,affinity); //AAA\r
-            //lets go back\r
-        my_chdir(my_dir);\r
             // set a low priority\r
-        if (option_get_bool("UseNice")){\r
+        if (option_get_bool(Option,"UseNice")){\r
             my_log("POLYGLOT Adjust Engine Piority\n");\r
-            engine_set_nice_value(engine, option_get_int("NiceValue"));\r
+            engine_set_nice_value(engine, option_get_int(Option,"NiceValue"));\r
         }\r
     }\r
     \r
index 2a408e3..70e366b 100644 (file)
--- a/engine.h
+++ b/engine.h
@@ -5,7 +5,6 @@
 \r
 // includes\r
 \r
-#include "io.h"\r
 #include "util.h"\r
 #include "pipex.h"\r
 \r
diff --git a/epd.c b/epd.c
index c79c399..af427ad 100644 (file)
--- a/epd.c
+++ b/epd.c
 #include "uci.h"\r
 #include "util.h"\r
 \r
+\r
+// macros\r
+\r
+#define  StringSize 4096\r
+\r
 // constants\r
 \r
 static const bool UseDebug = FALSE;\r
 static const bool UseTrace = FALSE;\r
 \r
-static const int StringSize = 4096;\r
-\r
 // variables\r
 \r
 static int MinDepth;\r
@@ -179,7 +182,7 @@ static void epd_test_file(const char file_name[]) {
    time_tot = 0.0;\r
    node_tot = 0.0;\r
 \r
-   printf("\nEngineName=%s\n",option_get_string("EngineName"));\r
+   printf("\nEngineName=%s\n",option_get_string(Option,"EngineName"));\r
 \r
    printf("\n[Search parameters: MaxDepth=%d   MaxTime=%.1f   DepthDelta=%d   MinDepth=%d   MinTime=%.1f]\n\n",MaxDepth,MaxTime,DepthDelta,MinDepth,MinTime);\r
 \r
diff --git a/fen.c b/fen.c
index be3ec17..180bdf3 100644 (file)
--- a/fen.c
+++ b/fen.c
@@ -336,7 +336,7 @@ bool board_to_fen(const board_t * board, char string[], int size) {
 \r
    old_pos = pos;\r
 \r
-   if (option_get_bool("Chess960")) {\r
+   if (option_get_bool(Option,"Chess960")) {\r
 \r
       // FEN-960\r
 \r
diff --git a/gui.c b/gui.c
index 9dbe6f5..44abc37 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -52,7 +52,7 @@ void gui_init(gui_t *gui){
 #ifdef SIGPIPE
     signal(SIGPIPE,sig_pipe);
 #endif
-    pipex_open(gui->pipex,"GUI",NULL);
+    pipex_open(gui->pipex,"GUI",NULL,NULL);
 }
 
 
@@ -84,17 +84,14 @@ void gui_get(gui_t * gui, char *string) {
 
 void gui_send(gui_t * gui, const char format[], ...) {
 
-   va_list arg_list;
-   char string[StringSize];
+   char string[FormatBufferSize];
 
    ASSERT(gui!=NULL);
    ASSERT(format!=NULL);
 
    // format
 
-   va_start(arg_list,format);
-   vsprintf(string,format,arg_list);
-   va_end(arg_list);
+   CONSTRUCT_ARG_STRING(format,string);
 
    // send
 
diff --git a/io.c b/io.c
index 88eb045..92d1518 100644 (file)
--- a/io.c
+++ b/io.c
@@ -196,8 +196,7 @@ bool io_get_line(io_t * io, char string[], int size) {
 
 void io_send(io_t * io, const char format[], ...) {
 
-   va_list arg_list;
-   char string[StringSize];
+   char string[FormatBufferSize];
    int len;
 
    ASSERT(io_is_ok(io));
@@ -207,9 +206,7 @@ void io_send(io_t * io, const char format[], ...) {
 
    // format
 
-   va_start(arg_list,format);
-   vsprintf(string,format,arg_list);
-   va_end(arg_list);
+   CONSTRUCT_ARG_STRING(format,string);
 
    // append string to buffer
 
@@ -245,8 +242,7 @@ void io_send(io_t * io, const char format[], ...) {
 
 void io_send_queue(io_t * io, const char format[], ...) {
 
-   va_list arg_list;
-   char string[StringSize];
+   char string[FormatBufferSize];
    int len;
 
    ASSERT(io_is_ok(io));
@@ -256,9 +252,7 @@ void io_send_queue(io_t * io, const char format[], ...) {
 
    // format
 
-   va_start(arg_list,format);
-   vsprintf(string,format,arg_list);
-   va_end(arg_list);
+   CONSTRUCT_ARG_STRING(format,string);
 
    // append string to buffer
 
diff --git a/main.c b/main.c
index 3dc5c20..e2f4c64 100644 (file)
--- a/main.c
+++ b/main.c
@@ -35,7 +35,7 @@
 // constants\r
 \r
 \r
-static const char * const Version = "1.4.33b";\r
+static const char * const Version = "1.4.34b";\r
 static const char * const HelpMessage = "\\r
 SYNTAX\n\\r
 * polyglot [configfile]\n\\r
@@ -85,7 +85,7 @@ int main(int argc, char * argv[]) {
     Init = FALSE;\r
 \r
     util_init();\r
-    option_init();\r
+    option_init_pg();\r
     \r
     square_init();\r
     piece_init();\r
@@ -128,24 +128,26 @@ int main(int argc, char * argv[]) {
     }\r
     \r
     if (argc >= 3 && my_string_equal(argv[1],"-ec")) {\r
-        option_set("EngineCommand",argv[2]);\r
+        option_set(Option,"EngineCommand",argv[2]);\r
         engine_open(Engine);\r
         if(!engine_active(Engine)){\r
-            my_fatal("Could not start \"%s\"\n",option_get("EngineCommand"));\r
+            my_fatal("Could not start \"%s\"\n",\r
+                     option_get(Option,"EngineCommand"));\r
         }\r
         Init=TRUE;\r
         gui_init(GUI);\r
         uci_open(Uci,Engine);\r
-        if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
-            option_set("EngineName",Uci->name);\r
+        if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {\r
+            option_set(Option,"EngineName",Uci->name);\r
         }\r
         mainloop();\r
         return EXIT_SUCCESS; \r
     }\r
     \r
         // read options\r
+\r
     \r
-    if (argc == 2) option_set("OptionFile",argv[1]); // HACK for compatibility\r
+    if (argc == 2) option_set(Option,"OptionFile",argv[1]); // HACK for compatibility\r
 \r
     parse_option(); // HACK: also launches the engine\r
     \r
@@ -171,31 +173,31 @@ int main(int argc, char * argv[]) {
 // polyglot_set_option\r
 \r
 void polyglot_set_option(char *name, char *value){ // this must be cleaned up!\r
-    option_set(name,value);\r
-    if(option_get_bool("Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){\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
-        my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile"));\r
+        my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));\r
         book_close();\r
         book_clear();\r
-        book_open(option_get_string("BookFile"));\r
+        book_open(option_get_string(Option,"BookFile"));\r
         if(!book_is_open()){\r
-            my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string("BookFile"));\r
+            my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string(Option,"BookFile"));\r
         }\r
-    }else if(option_get_bool("Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){\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 LOGFILE \"%s\"\n",option_get_string("LogFile"));\r
+        my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string(Option,"LogFile"));\r
         my_log_close();\r
-        my_log_open(option_get_string("LogFile"));\r
-    }else if(option_get_bool("UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){\r
+        my_log_open(option_get_string(Option,"LogFile"));\r
+    }else if(option_get_bool(Option,"UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){\r
         my_log("POLYGLOT Adjust Engine Piority\n");\r
-        engine_set_nice_value(Engine,atoi(option_get_string("NiceValue")));\r
-    }else if(my_string_case_equal(name,"Book") && !option_get_bool("Book")){\r
+        engine_set_nice_value(Engine,atoi(option_get_string(Option,"NiceValue")));\r
+    }else if(my_string_case_equal(name,"Book") && !option_get_bool(Option,"Book")){\r
         book_close();\r
         book_clear();\r
-    }else if(my_string_case_equal(name,"UseNice") && !option_get_bool("UseNice")){\r
+    }else if(my_string_case_equal(name,"UseNice") && !option_get_bool(Option,"UseNice")){\r
         my_log("POLYGLOT Adjust Engine Piority\n");\r
         engine_set_nice_value(Engine,0);\r
-    }else if(my_string_case_equal(name,"Log") && !option_get_bool("Log")){\r
+    }else if(my_string_case_equal(name,"Log") && !option_get_bool(Option,"Log")){\r
         my_log("POLYGLOT QUIT LOGGING\n");\r
         my_log_close();\r
     }\r
@@ -206,13 +208,13 @@ void polyglot_set_option(char *name, char *value){ // this must be cleaned up!
 \r
 static void init_book(){\r
     book_clear();\r
-    if (option_get_bool("Book")){\r
+    if (option_get_bool(Option,"Book")){\r
         my_log("POLYGLOT *** SETTING BOOK ***\n");\r
-        my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile"));\r
-        book_open(option_get_string("BookFile"));\r
+        my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));\r
+        book_open(option_get_string(Option,"BookFile"));\r
         if(!book_is_open()){\r
             my_log("POLYGLOT Unable to open book \"%s\"\n",\r
-                   option_get_string("BookFile"));\r
+                   option_get_string(Option,"BookFile"));\r
         }\r
     }\r
 }\r
@@ -225,7 +227,7 @@ static void parse_option() {
     FILE * file;\r
     char line[256];\r
     char * name, * value;\r
-    file_name = option_get_string("OptionFile");\r
+    file_name = option_get_string(Option,"OptionFile");\r
     \r
     file = fopen(file_name,"r");\r
     if (file == NULL) {\r
@@ -243,13 +245,13 @@ static void parse_option() {
        if (my_string_case_equal(line,"[engine]")) break;\r
        \r
        if (parse_line(line,&name,&value)) {\r
-           option_set(name,value);\r
-           option_set_default(name,value);\r
+           option_set(Option,name,value);\r
+           option_set_default(Option,name,value);\r
        }\r
    }\r
    \r
-   if (option_get_bool("Log")) {\r
-       my_log_open(option_get_string("LogFile"));\r
+   if (option_get_bool(Option,"Log")) {\r
+       my_log_open(option_get_string(Option,"LogFile"));\r
    }\r
    \r
    if(!DEBUG){\r
@@ -262,10 +264,10 @@ static void parse_option() {
    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("EngineCommand"));\r
+       my_fatal("Could not start \"%s\"\n",option_get(Option,"EngineCommand"));\r
    }\r
 \r
-   if (option_get_bool("UCI")) {\r
+   if (option_get_bool(Option,"UCI")) {\r
        my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
    }\r
    uci_open(Uci,Engine);\r
@@ -280,8 +282,8 @@ static void parse_option() {
            if(my_string_case_equal(name,"MultiPV") && atoi(value)>1)  Uci->multipv_mode=TRUE;\r
        }\r
    }\r
-   if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
-       option_set("EngineName",Uci->name);\r
+   if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {\r
+       option_set(Option,"EngineName",Uci->name);\r
    }\r
    \r
    fclose(file);\r
@@ -371,7 +373,7 @@ static void stop_search() {
         \r
         my_log("POLYGLOT STOP SEARCH\n");\r
         \r
-        if (option_get_bool("SyncStop")) {\r
+        if (option_get_bool(Option,"SyncStop")) {\r
             uci_send_stop_sync(Uci);\r
         } else {\r
             uci_send_stop(Uci);\r
index de590cc..1fc4c1b 100644 (file)
@@ -30,7 +30,7 @@ static void mainloop_gui_step(char * string);
 // mainloop_init()\r
     \r
 static void mainloop_init(){\r
-    if(!option_get_bool("UCI")){\r
+    if(!option_get_bool(Option,"UCI")){\r
         xboard2uci_init();  // the default\r
     }\r
 }\r
@@ -38,7 +38,7 @@ static void mainloop_init(){
 // mainloop_engine_step()\r
 \r
 static void mainloop_engine_step(char * string){\r
-    if(option_get_bool("UCI")){\r
+    if(option_get_bool(Option,"UCI")){\r
         uci2uci_engine_step(string); \r
     }else{\r
         xboard2uci_engine_step(string);\r
@@ -48,11 +48,11 @@ static void mainloop_engine_step(char * string){
 // mainloop_gui_step()\r
 \r
 static void mainloop_gui_step(char * string){\r
-    if(option_get_bool("UCI")){\r
+    if(option_get_bool(Option,"UCI")){\r
         uci2uci_gui_step(string); \r
     }else if(my_string_equal(string,"uci")){ // mode auto detection\r
         my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
-        option_set("UCI","true");\r
+        option_set(Option,"UCI","true");\r
         uci2uci_gui_step(string);\r
     }else{\r
         xboard2uci_gui_step(string);\r
diff --git a/move.c b/move.c
index 8d5699f..116f11d 100644 (file)
--- a/move.c
+++ b/move.c
@@ -239,7 +239,7 @@ bool move_to_can(int move, const board_t * board, char string[], int size) {
 \r
    // king-slide castling\r
 \r
-   if (move_is_castle(move,board) && !option_get_bool("Chess960")) {\r
+   if (move_is_castle(move,board) && !option_get_bool(Option,"Chess960")) {\r
       if (FALSE) {\r
       } else if (from == E1 && to == H1) {\r
          to = G1;\r
@@ -320,7 +320,7 @@ int move_from_can(const char string[], const board_t * board) {
    case '\0': // not a promotion\r
       if (piece_is_pawn(board->square[from])\r
        && square_side_rank(to,board->turn) == Rank8\r
-       && option_get_bool("PromoteWorkAround")) {\r
+          && option_get_bool(Option,"PromoteWorkAround")) {\r
          move |= MovePromoteQueen;\r
       }\r
       break;\r
index 07b36cf..8d067b8 100644 (file)
--- a/option.c
+++ b/option.c
@@ -17,8 +17,10 @@ static const bool UseDebug = FALSE;
 // variables\r
 \r
 #define NNB { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL }\r
-option_t Option[] = {\r
 \r
+option_list_t Option[1];\r
+\r
+option_t DefaultOptions[] = {    \r
     { "OptionFile",       "string","0","0",     "polyglot.ini", NULL,0,NNB,  PG}, \r
 \r
    // options\r
@@ -68,38 +70,94 @@ option_t Option[] = {
     { "RepeatPV",        "check","0","0",      "true"     , NULL,0,NNB,  PG|XBOARD},\r
     { "PromoteWorkAround","check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
 \r
-    { "WbWorkArounds",    "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
+    { "WbWorkArounds",    "check","0","0",      "true"     , NULL,0,NNB,  PG|XBOARD}, \r
     { NULL,               NULL,"0","0",         NULL        , NULL,0,NNB,  0},\r
-};\r
 \r
-// prototypes\r
+};\r
 \r
-static option_t * option_find (const char var[]);\r
 \r
 // functions\r
 \r
-// option_init()\r
-\r
-void option_init() {\r
+// option_is_ok()\r
 \r
-    option_t *p=Option;\r
-    const char * name;\r
+bool option_is_ok(const option_list_t *option) {\r
+    if(option->option_nb<0 || option->option_nb>=OptionNb){\r
+        return FALSE;\r
+    }\r
+    return TRUE;\r
+}\r
 \r
-    while((name=(p++)->name)){\r
-        option_set(name,option_get_default(name));\r
+// option_init_pg()\r
+\r
+void option_init_pg() {\r
+\r
+    int i;\r
+    option_t *p=DefaultOptions;\r
+    \r
+    option_init(Option);\r
+    while(p){\r
+        if(p->name){\r
+            option_insert(Option,p);\r
+            p++;\r
+        }else{\r
+            break;\r
+        }\r
+    }\r
+    for(i=0;i<Option->option_nb;i++){\r
+        Option->options[i].value=my_strdup(Option->options[i].default_);\r
     }\r
 }\r
 \r
+// option_init()\r
+\r
+void option_init(option_list_t *option){\r
+    ASSERT(option!=NULL);\r
+    option->option_nb=0;\r
+    option->iter=0;\r
+    memset(option->options,0,sizeof(option->options));\r
+}\r
+\r
+// option_insert()\r
+\r
+void option_insert(option_list_t *option, option_t *new_option){\r
+    ASSERT(option!=NULL);\r
+    ASSERT(new_option!=NULL);\r
+    ASSERT(new_option->name!=NULL);\r
+    option_t *opt;\r
+    opt=option_find(option,new_option->name);\r
+    if(!opt){\r
+        opt=&option->options[option->option_nb];\r
+        option->option_nb++;\r
+    }\r
+    int i;\r
+    if(option->option_nb>=OptionNb){\r
+        my_fatal("option_insert(): option list overflow\n");\r
+    }\r
+    if(new_option->name)     my_string_set(&opt->name,     new_option->name);\r
+    if(new_option->value)    my_string_set(&opt->value,    new_option->value);\r
+    if(new_option->min)      my_string_set(&opt->min,      new_option->min);\r
+    if(new_option->max)      my_string_set(&opt->max,      new_option->max);\r
+    if(new_option->default_) my_string_set(&opt->default_, new_option->default_);\r
+    if(new_option->type)     my_string_set(&opt->type,     new_option->type);\r
+    opt->var_nb=new_option->var_nb;\r
+    for(i=0;i<new_option->var_nb;i++){\r
+        my_string_set(&opt->var[i], new_option->var[i]);\r
+    }\r
+    opt->mode=new_option->mode;\r
+}\r
 \r
 // option_set()\r
 \r
-bool option_set(const char name[], const char value[]) {\r
+bool option_set(option_list_t *option, \r
+                const char name[], \r
+                const char value[]) {\r
 \r
    option_t * opt;\r
+   ASSERT(option!=NULL);\r
    ASSERT(name!=NULL);\r
    ASSERT(value!=NULL);\r
 \r
-   opt = option_find(name);\r
+   opt = option_find(option,name);\r
    if (opt == NULL) return FALSE;\r
 \r
    my_string_set(&opt->value,value);\r
@@ -108,15 +166,18 @@ bool option_set(const char name[], const char value[]) {
 \r
    return TRUE;\r
 }\r
-// option_set()\r
 \r
-bool option_set_default(const char name[], const char value[]) {\r
+// option_set_default()\r
+\r
+bool option_set_default(option_list_t *option,\r
+                           const char name[], \r
+                           const char value[]) {\r
 \r
    option_t * opt;\r
    ASSERT(name!=NULL);\r
    ASSERT(value!=NULL);\r
 \r
-   opt = option_find(name);\r
+   opt = option_find(option,name);\r
    if (opt == NULL) return FALSE;\r
 \r
    opt->default_=my_strdup(value);\r
@@ -128,15 +189,14 @@ bool option_set_default(const char name[], const char value[]) {
 \r
 // option_get()\r
 \r
-const char * option_get(const char name[]) {\r
+const char * option_get(option_list_t *option, const char name[]) {\r
 \r
    option_t * opt;\r
 \r
    ASSERT(name!=NULL);\r
 \r
-   opt = option_find(name);\r
+   opt = option_find(option,name);\r
    if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",name);\r
-\r
    if (UseDebug) my_log("POLYGLOT OPTION GET \"%s\" -> \"%s\"\n",opt->name,opt->value);\r
 \r
    return opt->value;\r
@@ -144,13 +204,13 @@ const char * option_get(const char name[]) {
 \r
 // option_get_default()\r
 \r
-const char * option_get_default(const char name[]) {\r
+const char * option_get_default(option_list_t *option, const char name[]) {\r
 \r
    option_t * opt;\r
 \r
    ASSERT(name!=NULL);\r
 \r
-   opt = option_find(name);\r
+   opt = option_find(option,name);\r
    if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",name);\r
 \r
    if (UseDebug) my_log("POLYGLOT OPTION GET \"%s\" -> \"%s\"\n",opt->name,opt->value);\r
@@ -160,11 +220,11 @@ const char * option_get_default(const char name[]) {
 \r
 // option_get_bool()\r
 \r
-bool option_get_bool(const char name[]) {\r
+bool option_get_bool(option_list_t *option, const char name[]) {\r
 \r
    const char * value;\r
 \r
-   value = option_get(name);\r
+   value = option_get(option,name);\r
 \r
    if (FALSE) {\r
    } else if (my_string_case_equal(value,"true") || my_string_case_equal(value,"yes") || my_string_equal(value,"1")) {\r
@@ -178,53 +238,92 @@ bool option_get_bool(const char name[]) {
    return FALSE;\r
 }\r
 \r
+\r
 // option_get_double()\r
 \r
-double option_get_double(const char name[]) {\r
+double option_get_double(option_list_t *option, const char name[]) {\r
 \r
    const char * value;\r
 \r
-   value = option_get(name);\r
+   value = option_get(option,name);\r
 \r
    return atof(value);\r
 }\r
 \r
 // option_get_int()\r
 \r
-int option_get_int(const char name[]) {\r
+int option_get_int(option_list_t *option, const char name[]) {\r
 \r
    const char * value;\r
 \r
-   value = option_get(name);\r
+   value = option_get(option,name);\r
 \r
    return atoi(value);\r
 }\r
 \r
 // option_get_string()\r
 \r
-const char * option_get_string(const char name[]) {\r
+const char * option_get_string(option_list_t *option, const char name[]) {\r
 \r
    const char * value;\r
 \r
-   value = option_get(name);\r
+   value = option_get(option,name);\r
 \r
    return value;\r
 }\r
 \r
 // option_find()\r
 \r
-static option_t * option_find(const char name[]) {\r
+option_t * option_find(option_list_t *option, const char name[]) {\r
 \r
    option_t * opt;\r
+   int i;\r
 \r
    ASSERT(name!=NULL);\r
+   for (i=0; i<option->option_nb; i++){\r
+       opt=option->options+i;\r
+       if (my_string_case_equal(opt->name,name)){\r
+           return opt;\r
+       }\r
+   }\r
+   \r
+   return NULL;\r
+}\r
 \r
+void option_start_iter(option_list_t *option){\r
+    option->iter=0;\r
+}\r
 \r
-   for (opt = &Option[0]; opt->name != NULL; opt++) {\r
-      if (my_string_case_equal(opt->name,name)) return opt;\r
-   }\r
+option_t * option_next(option_list_t *option){\r
+    ASSERT(option->iter<=option->option_nb);\r
+    if(option->iter==option->option_nb){\r
+        return NULL;\r
+    }\r
+    return &option->options[option->iter++];\r
+        \r
+}\r
 \r
-   return NULL;\r
+void option_free(option_t *option){\r
+      int i;\r
+      my_string_clear(&option->name);\r
+      my_string_clear(&option->type);\r
+      my_string_clear(&option->min);\r
+      my_string_clear(&option->max);\r
+      my_string_clear(&option->default_);\r
+      my_string_clear(&option->value);\r
+      for(i=0;i<option->var_nb;i++){\r
+         my_string_clear(&option->var[i]);\r
+      }\r
+      option->var_nb=0;\r
+      option->mode=0;\r
+}\r
+\r
+void option_clear(option_list_t *option){\r
+    int i;\r
+    for (i = 0; i < option->option_nb; i++) {\r
+        option_free(option->options+i);\r
+   }\r
+   option->option_nb=0;\r
 }\r
 \r
 // end of option.cpp\r
index 050ae0e..1d5eab0 100644 (file)
--- a/option.h
+++ b/option.h
 \r
 // defines\r
 \r
-#define VarNb  16\r
-#define XBOARD (1<<0)\r
-#define UCI    (1<<1)\r
-#define PG     (1<<2)\r
+#define VarNb    16\r
+#define XBOARD   (1<<0)\r
+#define UCI      (1<<1)\r
+#define PG       (1<<2)\r
+#define OptionNb 256\r
 \r
 // types\r
 \r
@@ -29,23 +30,50 @@ typedef struct {   // TODO: put back in more logical order
     int mode;\r
 } option_t;\r
 \r
+// all non NULL data in an option_list_t should be malloc'ed\r
+// use "my_string_set" to fill it. \r
+\r
+typedef struct {\r
+    option_t options[OptionNb];\r
+    int option_nb;\r
+    int iter;\r
+} option_list_t;\r
+\r
 // variables\r
 \r
-extern option_t Option[];\r
+extern option_list_t Option[1];\r
 \r
 // functions\r
 \r
-extern void         option_init       ();\r
 \r
-extern bool         option_set        (const char var[], const char val[]);\r
-extern bool         option_set_default(const char var[], const char val[]);\r
-extern const char * option_get        (const char var[]);\r
-extern const char * option_get_default(const char var[]);\r
+extern void         option_init         (option_list_t *option);\r
+\r
+extern void         option_init_pg      ();\r
+\r
+extern bool         option_set          (option_list_t *option,\r
+                                         const char var[],\r
+                                         const char val[]);\r
+extern bool         option_set_default  (option_list_t *option,\r
+                                         const char var[],\r
+                                         const char val[]);\r
+\r
+extern const char * option_get          (option_list_t *option, const char var[]);\r
+extern const char * option_get_default  (option_list_t *option, const char var[]);\r
+\r
+extern bool         option_get_bool     (option_list_t *option, const char var[]);\r
+extern double       option_get_double   (option_list_t *option, const char var[]);\r
+extern int          option_get_int      (option_list_t *option, const char var[]);\r
+extern const char * option_get_string   (option_list_t *option, const char var[]);\r
+\r
+extern bool         option_is_ok        (const option_list_t *option);\r
+extern option_t *   option_find         (option_list_t *option, const char var[]);\r
+extern void         option_clear        (option_list_t *option);\r
+extern void         option_insert       (option_list_t *option, option_t *new_option);\r
+\r
+extern void         option_start_iter   (option_list_t *option);\r
+extern option_t *   option_next         (option_list_t *option);\r
 \r
-extern bool         option_get_bool   (const char var[]);\r
-extern double       option_get_double (const char var[]);\r
-extern int          option_get_int    (const char var[]);\r
-extern const char * option_get_string (const char var[]);\r
+extern void         option_free         (option_t *option);\r
 \r
 #endif // !defined OPTION_H\r
 \r
diff --git a/pipex.h b/pipex.h
index e96457f..e1a3618 100644 (file)
--- a/pipex.h
+++ b/pipex.h
@@ -36,6 +36,8 @@ typedef struct {
     volatile int nReadEnd;
     char lpBuffer[LINE_INPUT_MAX_CHAR];
     char lpReadBuffer[LINE_INPUT_MAX_CHAR];
+    char szWriteBuffer[LINE_INPUT_MAX_CHAR];
+    DWORD dwWriteIndex;
     const char *name;
 
 } pipex_t;
@@ -76,11 +78,13 @@ typedef struct {
 
 extern void pipex_open         (pipex_t *pipex, 
                                 const char *name,
+                                const char *working_dir,
                                 const char *command);
 extern bool pipex_active       (pipex_t *pipex);
 extern bool pipex_readln       (pipex_t *pipex, char *string);
 extern bool pipex_readln_nb    (pipex_t *pipex, char *string);
 extern void pipex_writeln      (pipex_t *pipex, const char *string);
+extern void pipex_write        (pipex_t *pipex, const char *string);
 extern bool pipex_eof          (pipex_t *pipex);
 extern void pipex_send_eof     (pipex_t *pipex);
 extern void pipex_exit         (pipex_t *pipex);
index 5d2edfa..34b32cc 100644 (file)
@@ -19,7 +19,10 @@ static void my_dup2(int old_fd, int new_fd) ;
 
 // pipex_open()
 
-void pipex_open(pipex_t *pipex, const char *name, const char *command){
+void pipex_open(pipex_t *pipex,
+                const char *name,
+                const char *working_dir,
+                const char *command){
     char string[StringSize];
     int argc;
     char * ptr;
@@ -93,8 +96,13 @@ void pipex_open(pipex_t *pipex, const char *name, const char *command){
             
            /* my_dup2(STDOUT_FILENO,STDERR_FILENO); */
             
-                // launch the new executable file
+            if(chdir(working_dir)){
+                my_fatal("pipex_open(): cannot change directory: %s\n",
+                         strerror(errno));
+            }
             
+            // launch the new executable file
+
             execvp(argv[0],&argv[0]);
             
                 // execvp() only returns when an error has occured
@@ -226,6 +234,13 @@ bool pipex_readln_nb(pipex_t *pipex, char *string){
     }
 }
 
+// pipex_write()
+
+void pipex_write(pipex_t *pipex, const char *string){
+       io_send_queue(pipex->io,"%s",string);
+}
+
+
 // pipex_writeln()
 
 void pipex_writeln(pipex_t *pipex, const char *string){
index 13adfeb..3f9ed90 100644 (file)
@@ -59,13 +59,17 @@ static DWORD WINAPI ThreadProc(LPVOID lpParam){
 
 // pipex_open()
 
-void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) {
+void pipex_open(pipex_t *pipex,
+                const char *szName,
+                const char *szWorkingDir,
+                const char *szProcFile) {
     DWORD dwMode, dwThreadId;
     HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite, hThread;
     SECURITY_ATTRIBUTES sa;
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
     int fdInput;
+    char *szCurrentDir;
     pipex->state=0;
     pipex->name=szName;
     pipex->hProcess=NULL;
@@ -88,6 +92,13 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) {
         si.hStdInput = hStdinRead;
         si.hStdOutput = hStdoutWrite;
         si.hStdError = hStdoutWrite;
+        if((szCurrentDir = _getcwd( NULL, 0 )) == NULL )
+            my_fatal("pipex_open(): no current directory: %s\n",
+                     strerror(errno));
+        if(_chdir(szWorkingDir)){
+            my_fatal("pipex_open(): cannot change directory: %s\n",
+                     strerror(errno));
+        }
         if(CreateProcess(NULL,
                          (LPSTR) szProcFile,
                          NULL,
@@ -109,6 +120,7 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) {
         }else{
             my_fatal("pipex_open(): %s",win32_error());
         }
+        _chdir(szCurrentDir);
     }
     if (pipex->bConsole) {
         SetConsoleMode(pipex->hInput,
@@ -144,9 +156,11 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) {
     if(!hThread){
         my_fatal("pipex_open(): %s",win32_error());
     }
+    pipex->dwWriteIndex=0;
     pipex_set_active(pipex);
 }
 
+
 // pipex_wait_event(pipex)
 
 void pipex_wait_event(pipex_t *pipex[]){
@@ -167,7 +181,6 @@ void pipex_wait_event(pipex_t *pipex[]){
                            );
 }
 
-
 // pipex_send_eof()
 
 void pipex_send_eof(pipex_t *pipex)  {
@@ -435,22 +448,50 @@ void pipex_set_affinity(pipex_t *pipex, int value){
     }
 }
 
+// pipex_write()
+
+void pipex_write(pipex_t *pipex, const char *szLineStr) {
+    int size,written;
+    size=sizeof(pipex->szWriteBuffer)-pipex->dwWriteIndex;
+    written=snprintf(pipex->szWriteBuffer + pipex->dwWriteIndex,
+                     size,
+                     "%s",
+                     szLineStr);
+        // snprintf returns how many bytes should have been written
+        // (not including the trailing zero)
+        // old versions of glibc and msvcrt return -1 in
+        // case of truncated output.
+    if(written>=size || written<0){
+        my_fatal("engine_send(): write_buffer overflow\n");
+    }
+    pipex->dwWriteIndex+=written;
+    
+}
+
+
 // pipex_writeln()
 
 void pipex_writeln(pipex_t *pipex, const char *szLineStr) {
   DWORD dwBytes;
-  int nStrLen;
-  char szWriteBuffer[LINE_INPUT_MAX_CHAR];
-  my_log("Adapter->%s: %s\n",pipex->name,szLineStr);
+  DWORD dwLengthWriteBuffer;
+  my_log("Adapter->%s: %s\n",pipex->name,pipex->szWriteBuffer);
+  pipex_write(pipex, szLineStr);
   if(pipex->bPipe){
-      nStrLen = strlen(szLineStr);
-      memcpy(szWriteBuffer, szLineStr, nStrLen);
-      szWriteBuffer[nStrLen] = '\r';
-      szWriteBuffer[nStrLen + 1] = '\n';
-      WriteFile(pipex->hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
+      dwLengthWriteBuffer = strlen(pipex->szWriteBuffer);
+      if(dwLengthWriteBuffer>=sizeof(pipex->szWriteBuffer)-3){
+          my_fatal("pipex_writeln(): write buffer overflow\n");
+      }
+      pipex->szWriteBuffer[dwLengthWriteBuffer] = '\r';
+      pipex->szWriteBuffer[dwLengthWriteBuffer + 1] = '\n';
+          // for easy debugging
+      pipex->szWriteBuffer[dwLengthWriteBuffer + 2] = '\0';  
+      WriteFile(pipex->hOutput, pipex->szWriteBuffer,
+                dwLengthWriteBuffer + 2,
+                &dwBytes, NULL);
   }else{
-      printf("%s\n",szLineStr);
+      printf("%s\n",pipex->szWriteBuffer);
       fflush(stdout);
   }
+  pipex->dwWriteIndex = 0;
 }
 #endif
index db0bd7e..c6f8e49 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "POLYGLOT 6"
-.TH POLYGLOT 6 "2009-08-06" "" ""
+.TH POLYGLOT 6 "2009-08-07" "" ""
 .SH "NAME"
 PolyGlot \-  Winboard protocol to UCI protocol adapter
          \-  book engine for Polyglot books 
@@ -515,8 +515,7 @@ process is allowed to run on. This option works only on Windows.
 .IX Subsection "Work arounds"
 Work arounds are identical to options except that they should be used
 only when necessary.  Their purpose is to try to hide problems with
-various software (not just engines).  The default value is always
-correct for bug-free software.
+various software (not just engines).  
 .PP
 \&\s-1IMPORTANT:\s0 Any of these work arounds might be removed in future
 versions of PolyGlot.  You are strongly recommended to contact the
@@ -553,14 +552,13 @@ however do not send a new pv string just before sending the move.
 In that case the output of PolyGlot would be inconsistent. 
 When RepeatPV is false PolyGlot does not repeat the last pv string.
 Due to the way kibitzing is implemented, KibitzMove is disabled in that case. 
-.IP "\fBWbWorkArounds\fR (default: false)" 4
-.IX Item "WbWorkArounds (default: false)"
+.IP "\fBWbWorkArounds\fR (default: true)" 4
+.IX Item "WbWorkArounds (default: true)"
 The intention of this option is to provide work arounds for
-xboard/winboard bugs should they arise.  Currently it only prevents
-\&\*(L"feature option=\*(R" commands which contain \*(L"Draw\*(R" in their name from
-being sent to the \s-1GUI\s0. Some versions of xboard/winboard contain a bug
-which causes such options to be interpreted as draw claims by the
-engine.
+xboard/winboard bugs should they arise.  Currently it decapitalizes
+the word Draw in options that contain this word. Some versions of
+xboard/winboard contain a bug which causes such options to be
+interpreted as draw claims by the engine.
 .Sp
 Engines that send options with \*(L"Draw\*(R" in their name are Rybka and \s-1HIARCS\s0. 
 .Sh "[Engine] section"
index 0465ce6..285e9b1 100644 (file)
@@ -473,8 +473,7 @@ process is allowed to run on. This option works only on Windows.
 
 Work arounds are identical to options except that they should be used
 only when necessary.  Their purpose is to try to hide problems with
-various software (not just engines).  The default value is always
-correct for bug-free software.
+various software (not just engines).  
 
 IMPORTANT: Any of these work arounds might be removed in future
 versions of PolyGlot.  You are strongly recommended to contact the
@@ -519,14 +518,13 @@ In that case the output of PolyGlot would be inconsistent.
 When RepeatPV is false PolyGlot does not repeat the last pv string.
 Due to the way kibitzing is implemented, KibitzMove is disabled in that case. 
 
-=item B<WbWorkArounds> (default: false)
+=item B<WbWorkArounds> (default: true)
 
 The intention of this option is to provide work arounds for
-xboard/winboard bugs should they arise.  Currently it only prevents
-"feature option=" commands which contain "Draw" in their name from
-being sent to the GUI. Some versions of xboard/winboard contain a bug
-which causes such options to be interpreted as draw claims by the
-engine.
+xboard/winboard bugs should they arise.  Currently it decapitalizes
+the word Draw in options that contain this word. Some versions of
+xboard/winboard contain a bug which causes such options to be
+interpreted as draw claims by the engine.
 
 Engines that send options with "Draw" in their name are Rybka and HIARCS. 
 
index ea33c64..e3f1504 100644 (file)
@@ -1,6 +1,6 @@
 Summary: A Winboard protocol to UCI protocol adapter
 Name: polyglot
-Version: 1.4.33b
+Version: 1.4.34b
 Release: 1
 License: GPL
 Group: Amusement/Games
diff --git a/uci.c b/uci.c
index 21c36e9..f8537e2 100644 (file)
--- a/uci.c
+++ b/uci.c
@@ -36,7 +36,7 @@ const char * thread_options[]={
   "number of threads",        // toga\r
   "number threads",           // Deep Learning Toga\r
   "threads",                  // glaurung, zappa, cyclone, grapefruit,\r
-                              // Deep Shredder, Deep Junior\r
+                              // Deep Shredder, Deep Junior, bright\r
   "core threads",             // HIARCS\r
   "max cpus",                 // rybka\r
   "cpus",                     // Deep Sjeng, Fruit2.3.5\r
@@ -61,33 +61,21 @@ static int  mate_score     (int dist);
 // uci_set_threads()\r
 \r
 void uci_set_threads(uci_t * uci, int n) {\r
-    const char **thread_options_copy = thread_options;\r
-    const char *thread_option;\r
     ASSERT(n>=1);\r
-    while((thread_option = *(thread_options_copy++))){\r
-        uci_send_option(uci,thread_option,"%d",n); // checks also for existence\r
+    const char *thread_option=uci_thread_option(uci);\r
+    if(thread_option){\r
+        uci_send_option(uci,thread_option,"%d",n);\r
     }\r
 }\r
 \r
-// uci_thread_option_exists()\r
-\r
-bool uci_thread_option_exist(uci_t * uci) {\r
-    const char **thread_options_copy = thread_options;\r
-    const char *thread_option;\r
-    while((thread_option = *(thread_options_copy++))){\r
-        if(uci_option_exist(uci,thread_option)) return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
 \r
 const char * uci_thread_option(uci_t * uci){\r
-    const char **thread_options_copy = thread_options;\r
+    const char **p = thread_options;\r
     const char *thread_option;\r
-    int i;\r
-    while((thread_option = *(thread_options_copy++))){\r
-        i=uci_get_option(uci,thread_option);\r
-        if(i>=0){\r
-            return Uci->option[i].name;\r
+    option_t *opt;\r
+    while((thread_option = *(p++))){\r
+        if((opt=option_find(uci->option,thread_option))){\r
+            return opt->name;\r
             break;\r
         }\r
     }\r
@@ -100,8 +88,7 @@ static bool uci_is_ok(const uci_t * uci) {
 \r
    if (uci == NULL) return FALSE;\r
    if (uci->engine == NULL) return FALSE;\r
-   if (uci->option_nb < 0 || uci->option_nb >= OptionNb) return FALSE;\r
-\r
+   if (!option_is_ok(uci->option)) return FALSE;\r
    return TRUE;\r
 }\r
 \r
@@ -123,7 +110,7 @@ void uci_open(uci_t * uci, engine_t * engine) {
    my_string_set(&uci->name,"<empty>");\r
    uci->author = NULL;\r
    my_string_set(&uci->author,"<empty>");\r
-   uci->option_nb = 0;\r
+   option_init(uci->option);\r
 \r
    uci->ready_nb = 0;\r
    uci->searching = 0;\r
@@ -146,22 +133,13 @@ void uci_open(uci_t * uci, engine_t * engine) {
 \r
 void uci_close(uci_t * uci) {\r
 \r
-   int i;\r
-   option_t * opt;\r
-\r
    ASSERT(uci_is_ok(uci));\r
    engine_close(uci->engine);\r
    uci->engine = NULL;\r
    my_string_clear(&uci->name);\r
    my_string_clear(&uci->author);\r
 \r
-   for (i = 0; i < uci->option_nb; i++) {\r
-      opt = &uci->option[i];\r
-      my_string_clear(&opt->name);\r
-      my_string_clear(&opt->default_);\r
-   }\r
-\r
-   uci->option_nb = 0;\r
+   option_clear(uci->option);\r
 }\r
 \r
 // uci_clear()\r
@@ -267,39 +245,18 @@ void uci_send_ucinewgame(uci_t * uci) {
 \r
    ASSERT(uci!=NULL);\r
 \r
-   if (option_get_int("UCIVersion") >= 2) {\r
+   if (option_get_int(Option,"UCIVersion") >= 2) {\r
       engine_send(uci->engine,"ucinewgame");\r
    }\r
 }\r
 \r
-// uci_option_exist()\r
-\r
-bool uci_option_exist(uci_t * uci, const char option[]) {\r
-\r
-   int i;\r
-   option_t * opt;\r
-\r
-   ASSERT(uci_is_ok(uci));\r
-   ASSERT(option!=NULL);\r
-\r
-   // scan options\r
-\r
-   for (i = 0; i < uci->option_nb; i++) {\r
-      opt = &uci->option[i];\r
-      if (my_string_case_equal(opt->name,option)) return TRUE;\r
-   }\r
-\r
-   return FALSE;\r
-}\r
-\r
 // uci_send_option()\r
 \r
-void uci_send_option(uci_t * uci, const char option[], const char format[], ...) {\r
+bool uci_send_option(uci_t * uci, const char option[], const char format[], ...) {\r
 \r
-   va_list arg_list;\r
-   char value[StringSize];\r
-   int i;\r
+   char value[FormatBufferSize];\r
    option_t * opt;\r
+   bool found=FALSE;\r
 \r
    ASSERT(uci_is_ok(uci));\r
    ASSERT(option!=NULL);\r
@@ -307,24 +264,27 @@ void uci_send_option(uci_t * uci, const char option[], const char format[], ...)
 \r
    // format\r
 \r
-   va_start(arg_list,format);\r
-   vsprintf(value,format,arg_list);\r
-   va_end(arg_list);\r
+   CONSTRUCT_ARG_STRING(format,value);\r
 \r
    if (UseDebug) my_log("POLYGLOT OPTION %s VALUE %s\n",option,value);\r
 \r
-   // scan options\r
-\r
-   for (i = 0; i < uci->option_nb; i++) {\r
-\r
-      opt = &uci->option[i];\r
-\r
-      if (my_string_case_equal(opt->name,option) && !my_string_equal(opt->default_,value)) {\r
-         engine_send(uci->engine,"setoption name %s value %s",opt->name,value);\r
-         my_string_set(&opt->default_,value);\r
-         break;\r
-      }\r
+   opt=option_find(uci->option,option);\r
+   if(opt){\r
+       found=TRUE;\r
+       if(!my_string_case_equal(opt->type,"button")){\r
+           if(!my_string_equal(opt->value,value)){\r
+               engine_send(uci->engine,"setoption name %s value %s",\r
+                           opt->name,value);\r
+               my_string_set(&opt->value,value);\r
+           }else{\r
+               my_log("POLYGLOT Not sending option \"%s\" since it "\r
+                      "already has the correct value.\n",opt->name);\r
+           }\r
+       }else{\r
+           engine_send(uci->engine,"setoption name %s",opt->name);\r
+       }\r
    }\r
+   return found;\r
 }\r
 \r
 // uci_parse()\r
@@ -387,9 +347,9 @@ int uci_parse(uci_t * uci, const char string[]) {
 \r
          // search information\r
 \r
-         if (uci->searching && uci->pending_nb == 1) { // current search\r
-            event = parse_info(uci,argument);\r
-         }\r
+              if (uci->searching && uci->pending_nb == 1) { // current search\r
+                  event = parse_info(uci,argument);\r
+               }\r
 \r
       } else if (my_string_equal(command,"option")) {\r
 \r
@@ -444,12 +404,19 @@ static int parse_bestmove(uci_t * uci, const char string[]) {
    // bestmove\r
 \r
    if (!parse_get_string(parse,argument,StringSize)) {\r
-      my_fatal("parse_bestmove(): missing argument\n");\r
+       return EVENT_ILLEGAL_MOVE;\r
+//      my_fatal("parse_bestmove(): missing argument\n");\r
    }\r
 \r
    uci->best_move = move_from_can(argument,uci->board);\r
-   if (uci->best_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
+   if (uci->best_move == MoveNone) {\r
+       return EVENT_ILLEGAL_MOVE;\r
+//       my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
+   }\r
 \r
+   if(!move_is_legal(uci->best_move,uci->board)){\r
+       return EVENT_ILLEGAL_MOVE;\r
+   }\r
    ASSERT(uci->best_move!=MoveNone);\r
    ASSERT(move_is_legal(uci->best_move,uci->board));\r
 \r
@@ -544,6 +511,8 @@ static int parse_info(uci_t * uci, const char string[]) {
    int multipvline=0;\r
    sint64 ln;\r
 \r
+\r
+   \r
    ASSERT(uci_is_ok(uci));\r
    ASSERT(string!=NULL);\r
 \r
@@ -691,12 +660,15 @@ static int parse_info(uci_t * uci, const char string[]) {
 \r
          if (n >= 0) uci->sel_depth = n;\r
 \r
-      } else if (my_string_equal(option,"string")) {\r
-                 if(!strncmp(argument,"DrawOffer",9))\r
+      } else  if (my_string_equal(option,"string")) {\r
+                 if(my_string_case_equal(argument,"DrawOffer")){\r
                          event |= EVENT_DRAW;\r
-                 if(!strncmp(argument,"Resign",6))\r
+          }else if(my_string_case_equal(argument,"Resign")){\r
                          event |= EVENT_RESIGN;\r
-\r
+          }else{\r
+              strcpy(uci->info,argument);\r
+              event|=EVENT_INFO;\r
+          }\r
          // TODO: argument to EOS\r
 \r
          ASSERT(!my_string_empty(argument));\r
@@ -720,6 +692,12 @@ static int parse_info(uci_t * uci, const char string[]) {
       } else {\r
 \r
          my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
+             // this is for buggy engines; it should probably be protected\r
+             // by a "WorkAround" option.\r
+         strcpy(uci->info,option);\r
+         strcat(uci->info," ");\r
+         strcat(uci->info,argument);\r
+         event|=EVENT_INFO;\r
       }\r
    }\r
 \r
@@ -738,55 +716,11 @@ static int parse_info(uci_t * uci, const char string[]) {
    return event;\r
 }\r
 \r
-int uci_get_option(uci_t * uci, const char * name){\r
-    int i;\r
-    for(i=0;i<Uci->option_nb;i++){\r
-        if(my_string_case_equal(Uci->option[i].name,name)){\r
-            return i;\r
-        }\r
-    }\r
-    return -1;\r
-}\r
-\r
-\r
-\r
-// uci_set_option()\r
-\r
-void uci_set_option(uci_t * uci,\r
-                    const char * name,\r
-                    const char * default_,\r
-                    const char * type,\r
-                    const char * max,\r
-                    const char * min,\r
-                    int var_nb,\r
-                    const char * var[]){\r
-    int i,j;\r
-    for(i=0;i<Uci->option_nb;i++){\r
-        if(my_string_equal(Uci->option[i].name,name)){\r
-            break;\r
-       }\r
-   }\r
-   if(i<OptionNb){\r
-       my_string_set(&(Uci->option[i].name),name);\r
-       my_string_set(&(Uci->option[i].default_),default_);\r
-       my_string_set(&(Uci->option[i].type),type);\r
-       my_string_set(&(Uci->option[i].min),min);\r
-       my_string_set(&(Uci->option[i].max),max);\r
-       Uci->option[i].var_nb=var_nb;\r
-       for(j=0;j<var_nb;j++){\r
-           my_string_set(&(Uci->option[i].var[j]),var[j]);\r
-       }\r
-       if(i==Uci->option_nb){\r
-           Uci->option_nb++;\r
-       }\r
-   }\r
-}\r
-\r
 // parse_option()\r
 \r
 static void parse_option(uci_t * uci, const char string[]) {\r
 \r
-   option_t * opt;\r
+   option_t opt[1];\r
    parse_t parse[1];\r
    char command[StringSize];\r
    char option[StringSize];\r
@@ -799,32 +733,16 @@ static void parse_option(uci_t * uci, const char string[]) {
 \r
    strcpy(command,"option");\r
 \r
-   if (uci->option_nb >= OptionNb) return;\r
-\r
-   opt = &uci->option[uci->option_nb];\r
-   uci->option_nb++;\r
-\r
-   opt->value=NULL;\r
+   memset(opt,0,sizeof(option_t));\r
+   \r
    my_string_set(&opt->value,"<empty>");\r
-   opt->mode=0;\r
-\r
-   opt->name = NULL;\r
    my_string_set(&opt->name,"<empty>");\r
-\r
-   \r
-   opt->default_ = NULL;\r
    my_string_set(&opt->default_,"<empty>");\r
-\r
-   opt->max = NULL;\r
    my_string_set(&opt->max,"<empty>");\r
-\r
-   opt->min = NULL;\r
    my_string_set(&opt->min,"<empty>");\r
-\r
-   opt->type = NULL;\r
    my_string_set(&opt->type,"<empty>");\r
-\r
    opt->var_nb=0;\r
+   opt->mode=0;\r
    \r
    parse_open(parse,string);\r
    parse_add_keyword(parse,"default");\r
@@ -887,6 +805,8 @@ static void parse_option(uci_t * uci, const char string[]) {
    }\r
 \r
    parse_close(parse);\r
+   option_insert(uci->option,opt);\r
+   option_free(opt);\r
 \r
    if (UseDebug) my_log("POLYGLOT option name \"%s\" default \"%s\"\n",opt->name,opt->default_);\r
 }\r
@@ -966,9 +886,9 @@ static int mate_score(int dist) {
 \r
    if (FALSE) {\r
    } else if (dist > 0) {\r
-      return +option_get_int("MateScore") - (+dist) * 2 + 1;\r
+       return +option_get_int(Option,"MateScore") - (+dist) * 2 + 1;\r
    } else if (dist < 0) {\r
-      return -option_get_int("MateScore") + (-dist) * 2;\r
+       return -option_get_int(Option,"MateScore") + (-dist) * 2;\r
    }\r
 \r
    return 0;\r
diff --git a/uci.h b/uci.h
index 0ac4f30..0a471fd 100644 (file)
--- a/uci.h
+++ b/uci.h
 #include "option.h"\r
 #include "util.h"\r
 \r
-// defines\r
+// macros\r
 \r
-#define OptionNb 256\r
+// I need to make a uniform string type.\r
+\r
+#define UciStringSize 4096\r
 \r
 // types\r
 \r
@@ -26,8 +28,7 @@ typedef struct {
    const char * name;\r
    const char * author;\r
 \r
-   int option_nb;\r
-   option_t option[OptionNb];\r
+   option_list_t option[1];\r
 \r
    bool ready;\r
    int ready_nb;\r
@@ -61,18 +62,21 @@ typedef struct {
    int root_move_pos;\r
    int root_move_nb;\r
    bool multipv_mode;\r
+   char info[UciStringSize];\r
 } uci_t;\r
 \r
 typedef enum {\r
-   EVENT_NONE  = 0,\r
-   EVENT_UCI   = 1 << 0,\r
-   EVENT_READY = 1 << 1,\r
-   EVENT_STOP  = 1 << 2,\r
-   EVENT_MOVE  = 1 << 3,\r
-   EVENT_PV    = 1 << 4,\r
-   EVENT_DEPTH = 1 << 5,\r
-   EVENT_DRAW  = 1 << 6,\r
-   EVENT_RESIGN= 1 << 7\r
+   EVENT_NONE         = 0,\r
+   EVENT_UCI          = 1 << 0,\r
+   EVENT_READY        = 1 << 1,\r
+   EVENT_STOP         = 1 << 2,\r
+   EVENT_MOVE         = 1 << 3,\r
+   EVENT_PV           = 1 << 4,\r
+   EVENT_DEPTH        = 1 << 5,\r
+   EVENT_DRAW         = 1 << 6,\r
+   EVENT_RESIGN       = 1 << 7,\r
+   EVENT_ILLEGAL_MOVE = 1 << 8,\r
+   EVENT_INFO         = 1 << 9\r
 } dummy_event_t;\r
 \r
 // variables\r
@@ -88,27 +92,11 @@ extern void uci_send_stop         (uci_t * uci);
 extern void uci_send_stop_sync    (uci_t * uci);\r
 extern void uci_send_ucinewgame   (uci_t * uci);\r
 extern void uci_set_threads       (uci_t * uci, int n);\r
-extern bool uci_thread_option_exist(uci_t * uci);\r
 extern const char * uci_thread_option(uci_t * uci);\r
-extern int uci_get_option          (uci_t * uci, const char * name);\r
-\r
-extern bool uci_option_exist      (uci_t * uci, const char option[]);\r
-extern void uci_send_option       (uci_t * uci, const char option[], const char format[], ...);\r
-\r
-extern void uci_close           (uci_t * uci);\r
-\r
-extern void uci_clear           (uci_t * uci);\r
-\r
-extern int  uci_parse           (uci_t * uci, const char string[]);\r
-\r
-void uci_set_option(uci_t * uci,\r
-                    const char * name,\r
-                    const char * default_,\r
-                    const char * type,\r
-                    const char * max,\r
-                    const char * min,\r
-                    int var_nb,\r
-                    const char * var[]);\r
+extern bool uci_send_option       (uci_t * uci, const char option[], const char format[], ...);\r
+extern void uci_close             (uci_t * uci);\r
+extern void uci_clear             (uci_t * uci);\r
+extern int  uci_parse             (uci_t * uci, const char string[]);\r
 \r
 #endif // !defined UCI_H\r
 \r
index 611697a..1c13d0f 100644 (file)
--- a/uci2uci.c
+++ b/uci2uci.c
@@ -121,6 +121,7 @@ static void format_uci_option_line(char * option_line,option_t *opt){
     char option_string[StringSize];
     int j;
     strcpy(option_line,"");
+        // buffer overflow alert
     strcat(option_line,"option name");
     if(opt->mode&PG){
         strcat(option_line," Polyglot");
@@ -150,21 +151,22 @@ static void format_uci_option_line(char * option_line,option_t *opt){
 // send_uci_options()
 
 static void send_uci_options() {
-    int i;
-    option_t *p=Option;
+
+    option_t * opt;
     char option_line[StringSize]="";
     gui_send(GUI,"id name %s", Uci->name);
     gui_send(GUI,"id author %s", Uci->author);
-    for(i=0;i<Uci->option_nb;i++){
-        format_uci_option_line(option_line,Uci->option+i);
-         gui_send(GUI,"%s",option_line);
+    option_start_iter(Uci->option);
+    while((opt=option_next(Uci->option))){
+        format_uci_option_line(option_line,opt);
+        gui_send(GUI,"%s",option_line);
     }
-    while(p->name){
-        if(p->mode &UCI){
-            format_uci_option_line(option_line,p);
+    option_start_iter(Option);
+    while((opt=option_next(Option))){
+        if(opt->mode &UCI){
+            format_uci_option_line(option_line,opt);
             gui_send(GUI,"%s",option_line);
         }
-        p++;
     }   
     gui_send(GUI,"uciok");
 }
@@ -216,7 +218,7 @@ void uci2uci_gui_step(char string[]) {
          }
          SavedMove=MoveNone;
          if(!strstr(string,"infinite")){
-             move=book_move(UCIboard,option_get_bool("BookRandom"));
+             move=book_move(UCIboard,option_get_bool(Option,"BookRandom"));
              if (move != MoveNone && move_is_legal(move,UCIboard)) {
                  if(strstr(string,"ponder")){
                      SavedMove=move;
diff --git a/util.c b/util.c
index 8551aca..0d75adf 100644 (file)
--- a/util.c
+++ b/util.c
@@ -29,7 +29,6 @@ static bool Error;
 \r
 FILE * LogFile=NULL;\r
 \r
-\r
 // functions\r
 \r
 // util_init()\r
@@ -158,45 +157,47 @@ void my_log_close() {
 // my_log()\r
 \r
 void my_log(const char format[], ...) {\r
+    \r
+    char string[FormatBufferSize];\r
+    \r
+    ASSERT(format!=NULL);\r
 \r
-   va_list ap;\r
-\r
-   ASSERT(format!=NULL);\r
+//  format\r
 \r
-   if (LogFile != NULL) {\r
-      fprintf(LogFile,"%.3f ",now_real());\r
-      va_start(ap,format);\r
+    CONSTRUCT_ARG_STRING(format,string);\r
+    \r
 \r
-      vfprintf(LogFile,format,ap);\r
-      va_end(ap);\r
+    if (LogFile != NULL) {\r
+        fprintf(LogFile,"%.3f %s",now_real(),string);\r
 #ifdef _WIN32\r
-      fflush(LogFile);\r
+        fflush(LogFile);\r
 #endif\r
-   }\r
+    }\r
 }\r
 \r
 // my_fatal()\r
 \r
 void my_fatal(const char format[], ...) {\r
 \r
-   va_list ap;\r
+    char string[FormatBufferSize];\r
 \r
-   ASSERT(format!=NULL);\r
+    ASSERT(format!=NULL);\r
 \r
-   va_start(ap,format);\r
+// format\r
 \r
-   vfprintf(stderr,format,ap);\r
-   if (LogFile != NULL) vfprintf(LogFile,format,ap);\r
+    CONSTRUCT_ARG_STRING(format,string);\r
+    \r
+    fprintf(stderr,format,string);\r
+    if (LogFile != NULL) fprintf(LogFile,format,&string);\r
 \r
-   va_end(ap);\r
-   if (Error) { // recursive error\r
-      my_log("POLYGLOT *** RECURSIVE ERROR ***\n");\r
-      exit(EXIT_FAILURE);\r
-      // abort();\r
-   } else {\r
-      Error = TRUE;\r
-      quit();\r
-   }\r
+    if (Error) { // recursive error\r
+        my_log("POLYGLOT *** RECURSIVE ERROR ***\n");\r
+        exit(EXIT_FAILURE);\r
+            // abort();\r
+    } else {\r
+        Error = TRUE;\r
+        quit();\r
+    }\r
 }\r
 \r
 // my_file_read_line()\r
@@ -394,19 +395,4 @@ double my_timer_elapsed_real(const my_timer_t * timer) {
 }\r
 \r
 \r
-char * my_getcwd(char *buf, size_t size){\r
-#ifdef _WIN32\r
-    return _getcwd(buf,size);\r
-#else\r
-    return getcwd(buf,size);\r
-#endif\r
-}\r
 \r
-int my_chdir (const char *path){\r
-    ASSERT(path!=NULL);\r
-#ifdef _WIN32\r
-    return _chdir(path);\r
-#else\r
-    return chdir(path);\r
-#endif\r
-}\r
diff --git a/util.h b/util.h
index cf197fe..2b0886c 100644 (file)
--- a/util.h
+++ b/util.h
 #define snprintf _snprintf\r
 #endif\r
 \r
+#define FormatBufferSize 4096\r
+\r
+#define CONSTRUCT_ARG_STRING(format,buf)                                 \\r
+    {                                                                    \\r
+        va_list arg_list;                                                \\r
+        int written;                                                     \\r
+        va_start(arg_list,format);                                       \\r
+        written=vsnprintf(buf,                                           \\r
+                          sizeof(buf),                                   \\r
+                          format,                                        \\r
+                          arg_list);                                     \\r
+        va_end(arg_list);                                                \\r
+        buf[sizeof(buf)]='\0';                                           \\r
+        if(written>=sizeof(buf) || written<0){                           \\r
+           my_fatal("write_buffer overflow: file \"%s\", line %d\n",     \\r
+                   __FILE__,__LINE__);                                   \\r
+        }                                                                \\r
+    }                                                                    \\r
+\r
 // types\r
 \r
 typedef signed char sint8;\r
@@ -92,6 +111,7 @@ typedef struct {
    bool running;\r
 } my_timer_t;\r
 \r
+\r
 // functions\r
 \r
 extern void   util_init             ();\r
@@ -135,9 +155,6 @@ extern double my_timer_elapsed_real (const my_timer_t * timer);
 \r
 extern char * my_error();\r
 \r
-extern char * my_getcwd             (char *buf, size_t size);\r
-extern int    my_chdir              (const char *path);\r
-\r
 #endif // !defined UTIL_H\r
 \r
 // end of util.h\r
index d255d6f..97c7b73 100644 (file)
@@ -108,6 +108,7 @@ static void stop_search    ();
 \r
 static void send_board     (int extra_move);\r
 static void send_pv        ();\r
+static void send_info      ();\r
 \r
 static void send_xboard_options ();\r
 \r
@@ -135,10 +136,10 @@ void xboard2uci_init() {
    my_timer_reset(State->timer);\r
 \r
    // yes there are engines that do not have the "Hash" option....\r
-   XB->has_feature_memory= uci_option_exist(Uci,"Hash");\r
-   XB->has_feature_smp = uci_thread_option_exist(Uci);\r
+   XB->has_feature_memory= (option_find(Uci->option,"Hash")!=NULL);\r
+   XB->has_feature_smp = (uci_thread_option(Uci)!=NULL);\r
    // TODO: support for other types of table bases\r
-   XB->has_feature_egt = uci_option_exist(Uci,"NalimovPath");\r
+   XB->has_feature_egt = (option_find(Uci->option,"NalimovPath")!=NULL);\r
    XB->analyse = FALSE;\r
    XB->computer = FALSE;\r
    XB->name = NULL;\r
@@ -193,7 +194,7 @@ void xboard2uci_gui_step(char string[]) {
 \r
                } else if (match(string,"bk")) {\r
 \r
-                       if (option_get_bool("Book")) {\r
+                       if (option_get_bool(Option,"Book")) {\r
                                game_get_board(Game,board);\r
                                book_disp(board);\r
                        }\r
@@ -216,7 +217,7 @@ void xboard2uci_gui_step(char string[]) {
                        XB->computer = TRUE;\r
 \r
                } else if (match(string,"draw")) {\r
-                       if(uci_option_exist(Uci,"UCI_DrawOffers")){\r
+                       if(option_find(Uci->option,"UCI_DrawOffers")){\r
                            my_log("POLYGLOT draw from XB received");\r
                                uci_send_option(Uci,"DrawOffer","%s","draw");}\r
                } else if (match(string,"easy")) {\r
@@ -266,7 +267,7 @@ void xboard2uci_gui_step(char string[]) {
 \r
                } else if (match(string,"hint")) {\r
 \r
-                       if (option_get_bool("Book")) {\r
+                       if (option_get_bool(Option,"Book")) {\r
 \r
                                game_get_board(Game,board);\r
                                move = book_move(board,FALSE);\r
@@ -302,7 +303,7 @@ void xboard2uci_gui_step(char string[]) {
             uci_send_isready(Uci);\r
                        my_log("POLYGLOT NEW GAME\n");\r
 \r
-                       option_set("Chess960","false");\r
+                       option_set(Option,"Chess960","false");\r
 \r
                        game_clear(Game);\r
 \r
@@ -371,7 +372,8 @@ void xboard2uci_gui_step(char string[]) {
                        XB->post = TRUE;\r
 \r
                } else if (match(string,"protover *")) {\r
-\r
+            XB->proto_ver = atoi(Star[0]);\r
+            ASSERT(XB->proto_ver>=2);\r
             send_xboard_options();\r
 \r
                } else if (match(string,"quit")) {\r
@@ -423,7 +425,8 @@ void xboard2uci_gui_step(char string[]) {
 \r
                                // book learning\r
 \r
-                               if (option_get_bool("Book") && option_get_bool("BookLearn")) {\r
+                               if (option_get_bool(Option,"Book") &&\r
+                    option_get_bool(Option,"BookLearn")) {\r
 \r
                                        if (FALSE) {\r
                                        } else if (my_string_equal(Star[0],"1-0")) {\r
@@ -440,7 +443,11 @@ void xboard2uci_gui_step(char string[]) {
 \r
                        gui_send(GUI,"Error (unknown command): %s",string);\r
 \r
-        } else if (match(string,"option *=*")){\r
+        } else if (match(string,"option *=*")   ||\r
+                   match(string,"option * =*") ||\r
+                   match(string,"option *= *") ||\r
+                   match(string,"option * = *")\r
+                   ){\r
             char *name=Star[0];\r
             char *value=Star[1];\r
             if(match(name, "Polyglot *")){\r
@@ -448,13 +455,18 @@ void xboard2uci_gui_step(char string[]) {
                 polyglot_set_option(pg_name,value);\r
             }else{\r
                 start_protected_command();\r
-                engine_send(Engine,"setoption name %s value %s",name,value);\r
+                if(!uci_send_option(Uci, name, "%s", value)){\r
+                    gui_send(GUI,"Error (unknown option): %s",name); \r
+                }\r
                 end_protected_command();\r
             }\r
         } else if (match(string,"option *")){\r
             char *name=Star[0];\r
             start_protected_command();\r
-            engine_send(Engine,"setoption name %s",name);\r
+                // value is ignored\r
+            if(!uci_send_option(Uci, name, "%s", "<empty>")){\r
+               gui_send(GUI,"Error (unknown option): %s",name); \r
+            }; \r
             end_protected_command();\r
         } else if (XB->has_feature_smp && match(string,"cores *")){\r
                 int cores=atoi(Star[0]);\r
@@ -490,9 +502,10 @@ void xboard2uci_gui_step(char string[]) {
             int real_memory;\r
             if(memory>=1){\r
                 // updating the available memory\r
+                option_t *opt;\r
                 my_log("POLYGLOT setting the amount of memory to %dMb\n",memory);\r
-                if(uci_get_option(Uci,"NalimovCache")>=0){\r
-                    nalimov_cache=atoi(Uci->option[uci_get_option(Uci,"NalimovCache")].value);\r
+                if((opt=option_find(Uci->option,"NalimovCache"))){\r
+                    nalimov_cache=atoi(opt->value);\r
                 }else{\r
                     nalimov_cache=0;\r
                 }\r
@@ -574,9 +587,9 @@ void xboard2uci_gui_step(char string[]) {
                } else if (match(string,"variant *")) {\r
 \r
                        if (my_string_equal(Star[0],"fischerandom")) {\r
-                               option_set("Chess960","true");\r
+                               option_set(Option,"Chess960","true");\r
                        } else {\r
-                               option_set("Chess960","false");\r
+                               option_set(Option,"Chess960","false");\r
                        }\r
 \r
                } else if (match(string,"white")) {\r
@@ -658,6 +671,7 @@ void xboard2uci_gui_step(char string[]) {
 void xboard2uci_engine_step(char string[]) {\r
 \r
        int event;\r
+    board_t board[1];\r
                event = uci_parse(Uci,string);\r
 \r
                // react to events\r
@@ -702,15 +716,33 @@ void xboard2uci_engine_step(char string[]) {
 \r
                        send_pv();\r
                }\r
+               if ((event & EVENT_INFO) != 0) {\r
+\r
+                       // the engine has sent info\r
+\r
+                       send_info();\r
+               }\r
                if((event & (EVENT_DRAW|EVENT_RESIGN))!=0){\r
                        my_log("POYGLOT draw offer/resign from engine\n");\r
-                       if(uci_option_exist(Uci,"UCI_DrawOffers")){\r
+                       if(option_find(Uci->option,"UCI_DrawOffers")){\r
                                if(event & EVENT_DRAW)\r
                                        gui_send(GUI,"offer draw");\r
                                else\r
                                        gui_send(GUI,"resign");\r
                        }\r
                }\r
+               if(((event & EVENT_ILLEGAL_MOVE)!=0) && (State->state == THINK)){\r
+            game_get_board(Game,board);\r
+            if(board->turn==White){\r
+                gui_send(GUI,"0-1 {polyglot: resign"\r
+                            " (illegal engine move white)}");\r
+            }else{\r
+                gui_send(GUI,"1-0 {polyglot: resign"\r
+                         " (illegal engine move black)}");\r
+            }\r
+            XB->result = TRUE;\r
+            mess();\r
+        }\r
 }\r
 \r
 // format_xboard_option_line\r
@@ -718,7 +750,9 @@ void xboard2uci_engine_step(char string[]) {
 void format_xboard_option_line(char * option_line, option_t *opt){\r
     int j;\r
     char option_string[StringSize];\r
+    char *tmp;\r
     strcpy(option_line,"");\r
+        // buffer overflow alert\r
     strcat(option_line,"feature option=\"");\r
     if(opt->mode&PG){\r
         strcat(option_line,"Polyglot ");\r
@@ -756,17 +790,21 @@ void format_xboard_option_line(char * option_line, option_t *opt){
         }\r
     }\r
     strcat(option_line,"\"");\r
+    if(option_get_bool(Option,"WbWorkArounds") &&\r
+       (tmp=strstr(option_line,"Draw"))){\r
+        *tmp='d';\r
+        my_log("POLYGLOT Decapitalizing \"Draw\" in option \"%s\"\n",\r
+               opt->name);\r
+    }\r
 }\r
 \r
-// send_xboard_options\r
+// send_xboard_options()\r
 \r
 static void send_xboard_options(){\r
-    int i;\r
+\r
     char option_line[StringSize]="";\r
-    option_t *p=Option;\r
     const char * name;\r
-    XB->proto_ver = atoi(Star[0]);\r
-    ASSERT(XB->proto_ver>=2);\r
+    option_t *opt;\r
     \r
     gui_send(GUI,"feature done=0");\r
     \r
@@ -774,7 +812,8 @@ static void send_xboard_options(){
     gui_send(GUI,"feature colors=0");\r
     gui_send(GUI,"feature draw=1");\r
     gui_send(GUI,"feature ics=1");\r
-    gui_send(GUI,"feature myname=\"%s\"",option_get_string("EngineName"));\r
+    gui_send(GUI,"feature myname=\"%s\"",\r
+             option_get_string(Option,"EngineName"));\r
     gui_send(GUI,"feature name=1");\r
     gui_send(GUI,"feature pause=0");\r
     gui_send(GUI,"feature ping=1");\r
@@ -803,34 +842,33 @@ static void send_xboard_options(){
         gui_send(GUI,"feature egt=\"\"");\r
     }\r
     \r
-    if (uci_option_exist(Uci,"UCI_Chess960")) {\r
+    if (option_find(Uci->option,"UCI_Chess960")) {\r
         gui_send(GUI,"feature variants=\"normal,fischerandom\"");\r
     } else {\r
         gui_send(GUI,"feature variants=\"normal\"");\r
     }\r
-    \r
-    for(i=0;i<Uci->option_nb;i++){\r
-        if(my_string_case_equal(Uci->option[i].name,"UCI_AnalyseMode")) continue;\r
-        if(my_string_case_equal(Uci->option[i].name,"Ponder")) continue;\r
-        if(my_string_case_equal(Uci->option[i].name,"Hash")) continue;\r
-        if(my_string_case_equal(Uci->option[i].name,"NalimovPath")) continue;\r
-        if((name=uci_thread_option(Uci))!=NULL && my_string_case_equal(Uci->option[i].name,name)) continue;\r
-        if(option_get_bool("WbWorkArounds") &&\r
-           strstr(Uci->option[i].name,"Draw")){\r
-            my_log("POLYGLOT Dropping option \"%s\" because it contains \"Draw\"\n",Uci->option[i].name);\r
-            continue;\r
-        }\r
-        format_xboard_option_line(option_line,Uci->option+i);\r
 \r
+    option_start_iter(Uci->option);\r
+    while((opt=option_next(Uci->option))){\r
+        if(my_string_case_equal(opt->name,"UCI_AnalyseMode")) continue;\r
+        if(my_string_case_equal(opt->name,"Ponder")) continue;\r
+        if(my_string_case_equal(opt->name,"Hash")) continue;\r
+        if(my_string_case_equal(opt->name,"NalimovPath")) continue;\r
+        if((name=uci_thread_option(Uci))!=NULL &&\r
+           my_string_case_equal(opt->name,name)) continue;\r
+        \r
+        format_xboard_option_line(option_line,opt);\r
+        \r
         gui_send(GUI,"%s",option_line);\r
-\r
     }\r
-    while(p->name){\r
-        if(p->mode &XBOARD){\r
-            format_xboard_option_line(option_line,p);\r
+\r
+\r
+    option_start_iter(Option);\r
+    while((opt=option_next(Option))){\r
+        if(opt->mode &XBOARD){\r
+            format_xboard_option_line(option_line,opt);\r
             gui_send(GUI,"%s",option_line);\r
         }\r
-        p++;\r
     }       \r
     gui_send(GUI,"feature done=1"); \r
     \r
@@ -839,7 +877,8 @@ static void send_xboard_options(){
 // report_best_score()\r
 \r
 static int report_best_score(){\r
-    if(!option_get_bool("ScoreWhite") || colour_is_white(Uci->board->turn)){\r
+    if(!option_get_bool(Option,"ScoreWhite") ||\r
+       colour_is_white(Uci->board->turn)){\r
         return Uci->best_score;\r
     }else{\r
         return -Uci->best_score;\r
@@ -858,14 +897,14 @@ static void comp_move(int move) {
    ASSERT(State->state==THINK);\r
    ASSERT(!XB->analyse);\r
 \r
-   if(option_get_bool("RepeatPV"))\r
+   if(option_get_bool(Option,"RepeatPV"))\r
           send_pv(); // to update time and nodes\r
 \r
    // send the move\r
 \r
    game_get_board(Game,board);\r
 \r
-   if (move_is_castle(move,board) && option_get_bool("Chess960")) {\r
+   if (move_is_castle(move,board) && option_get_bool(Option,"Chess960")) {\r
       if (!move_to_san(move,board,string,256)) my_fatal("comp_move(): move_to_san() failed\n"); // O-O/O-O-O\r
    } else {\r
       if (!move_to_can(move,board,string,256)) my_fatal("comp_move(): move_to_can() failed\n");\r
@@ -875,14 +914,14 @@ static void comp_move(int move) {
 \r
    // resign?\r
 \r
-   if (option_get_bool("Resign") && Uci->root_move_nb > 1) {\r
+   if (option_get_bool(Option,"Resign") && Uci->root_move_nb > 1) {\r
 \r
-      if (Uci->best_score <= -abs(option_get_int("ResignScore"))) {\r
+       if (Uci->best_score <= -abs(option_get_int(Option,"ResignScore"))) {\r
 \r
          State->resign_nb++;\r
          my_log("POLYGLOT %d move%s with resign score\n",State->resign_nb,(State->resign_nb>1)?"s":"");\r
 \r
-         if (State->resign_nb >= option_get_int("ResignMoves")) {\r
+         if (State->resign_nb >= option_get_int(Option,"ResignMoves")) {\r
             my_log("POLYGLOT *** RESIGN ***\n");\r
             gui_send(GUI,"resign");\r
          }\r
@@ -1153,11 +1192,11 @@ static void search_update() {
 \r
       // opening book\r
 \r
-      if (State->state == THINK && option_get_bool("Book")) {\r
+       if (State->state == THINK && option_get_bool(Option,"Book")) {\r
 \r
          game_get_board(Game,Uci->board);\r
 \r
-         move = book_move(Uci->board,option_get_bool("BookRandom"));\r
+         move = book_move(Uci->board,option_get_bool(Option,"BookRandom"));\r
 \r
          if (move != MoveNone && move_is_legal(move,Uci->board)) {\r
 \r
@@ -1186,9 +1225,10 @@ static void search_update() {
 \r
       // options\r
 \r
-      uci_send_option(Uci,"UCI_Chess960","%s",option_get_bool("Chess960")?"true":"false");\r
+      uci_send_option(Uci,"UCI_Chess960","%s",\r
+                      option_get_bool(Option,"Chess960")?"true":"false");\r
 \r
-      if (option_get_int("UCIVersion") >= 2) {\r
+      if (option_get_int(Option,"UCIVersion") >= 2) {\r
          uci_send_option(Uci,"UCI_Opponent","none none %s %s",(XB->computer)?"computer":"human",XB->name);\r
          uci_send_option(Uci,"UCI_AnalyseMode","%s",(XB->analyse)?"true":"false");\r
       }\r
@@ -1291,7 +1331,8 @@ static bool active() {
 \r
 static bool ponder() {\r
 \r
-   return XB->ponder && (option_get_bool("CanPonder") || uci_option_exist(Uci,"Ponder"));\r
+    return XB->ponder && (option_get_bool(Option,"CanPonder") ||\r
+                          option_find(Uci->option,"Ponder"));\r
 }\r
 // ponder_ok()\r
 \r
@@ -1319,7 +1360,7 @@ static bool ponder_ok(int move) {
 \r
    if (status != PLAYING) return FALSE; // game ended\r
 \r
-   if (option_get_bool("Book") && is_in_book(board)) {\r
+   if (option_get_bool(Option,"Book") && is_in_book(board)) {\r
       return FALSE;\r
    }\r
 \r
@@ -1342,7 +1383,7 @@ static void stop_search() {
       Uci->searching = FALSE;\r
 */\r
 \r
-      if (option_get_bool("SyncStop")) {\r
+      if (option_get_bool(Option,"SyncStop")) {\r
          uci_send_stop_sync(Uci);\r
       } else {\r
          uci_send_stop(Uci);\r
@@ -1418,6 +1459,15 @@ static void send_board(int extra_move) {
    engine_send(Engine,""); // newline\r
 }\r
 \r
+// send_info()\r
+\r
+static void send_info() {\r
+    if (XB->post) {\r
+        gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth>0?Uci->best_depth:1,\r
+                 0,0,0.0,0,Uci->info);  \r
+    }  \r
+}\r
+\r
 // send_pv()\r
 \r
 static void send_pv() {\r
@@ -1444,7 +1494,8 @@ static void send_pv() {
 \r
                 gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth,report_best_score(),Uci->time*100.0,Uci->node_nb,pv_string);\r
 \r
-      } else if (State->state == PONDER && option_get_bool("ShowPonder")) {\r
+      } else if (State->state == PONDER &&\r
+                 option_get_bool(Option,"ShowPonder")) {\r
 \r
          game_get_board(Game,board);\r
          move = State->exp_move;\r
@@ -1459,14 +1510,16 @@ static void send_pv() {
 \r
    // kibitz\r
 \r
-   if ((Uci->searching && option_get_bool("KibitzPV") && Uci->time >= option_get_double("KibitzDelay"))\r
-    || (!Uci->searching && option_get_bool("KibitzMove"))) {\r
+   if ((Uci->searching &&\r
+        option_get_bool(Option,"KibitzPV") &&\r
+        Uci->time >= option_get_double(Option,"KibitzDelay"))\r
+       || (!Uci->searching && option_get_bool(Option,"KibitzMove"))) {\r
 \r
       if (State->state == THINK || State->state == ANALYSE) {\r
 \r
          line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
          if(kibitz_throttle(Uci->searching)){\r
-             gui_send(GUI,"%s depth=%d time=%.2f node="S64_FORMAT" speed=%.0f score=%+.2f pv=\"%s\"",option_get_string("KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,((double)report_best_score())/100.0,pv_string);\r
+             gui_send(GUI,"%s depth=%d time=%.2f node="S64_FORMAT" speed=%.0f score=%+.2f pv=\"%s\"",option_get_string(Option,"KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,((double)report_best_score())/100.0,pv_string);\r
          }\r
       } else if (State->state == PONDER) {\r
 \r
@@ -1477,7 +1530,7 @@ static void send_pv() {
             move_to_san(move,board,move_string,256);\r
             line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
             if(kibitz_throttle(Uci->searching)){\r
-                gui_send(GUI,"%s depth=%d time=%.2f node="S64_FORMAT" speed=%.0f score=%+.2f pv=\"(%s) %s\"",option_get_string("KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,((double)report_best_score())/100.0,move_string,pv_string);\r
+                gui_send(GUI,"%s depth=%d time=%.2f node="S64_FORMAT" speed=%.0f score=%+.2f pv=\"(%s) %s\"",option_get_string(Option,"KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,((double)report_best_score())/100.0,move_string,pv_string);\r
             }\r
          }\r
       }\r
@@ -1492,12 +1545,14 @@ static bool kibitz_throttle(bool searching){
     static time_t lastKibitzPV=0;\r
     curr_time = time(NULL);\r
     if(searching){   // KibitzPV\r
-        if(curr_time >= (option_get_int("KibitzInterval") + lastKibitzPV)){\r
+        if(curr_time >=\r
+           (option_get_int(Option,"KibitzInterval") + lastKibitzPV)){\r
             lastKibitzPV=curr_time;\r
             return TRUE;\r
         }\r
     }else{       // KibitzMove\r
-        if(curr_time >= (option_get_int("KibitzInterval") + lastKibitzMove)){\r
+        if(curr_time >=\r
+           (option_get_int(Option,"KibitzInterval") + lastKibitzMove)){\r
             lastKibitzPV=curr_time;\r
             lastKibitzMove=curr_time;\r
             return TRUE;\r
@@ -1555,4 +1610,4 @@ static void learn(int result) {
    book_flush();\r
 }\r
 \r
-// end of adapter.cpp\r
+// end of xboard2uci.c\r