Make non-existing opton in settings file non-fatal
authorH.G. Muller <h.g.muller@hccnet.nl>
Tue, 14 Jun 2011 16:47:30 +0000 (18:47 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Tue, 14 Jun 2011 16:53:56 +0000 (18:53 +0200)
It is rather difficult to recover from a situaton where the settings
file contains an unknown option (e.g. because you downgraded to a
previous version that had fewer options), especially in WinBoard, where
the user settings file is in a hidden folder, and people might not be
able to find it, let alone edit it. By just skipping the line with the
offending option, rather than generating a fatal error, when reading
from a settings file, such options will be automatically purged from the
file as soon as you save settings.
  Small problem is that the user cannot be warned, as the initialization
has not progressed far enough at this point to generate error popups. In
XBoard we can at least print to the console, but in WinBoard there is no
warning at all. But the worst thing that can happen is that new options
in a settings file of a more advanced version will revert to their
defaults.

args.h

diff --git a/args.h b/args.h
index d3909b5..60a04a5 100644 (file)
--- a/args.h
+++ b/args.h
@@ -741,7 +741,7 @@ ArgDescriptor argDescriptorIndirection =
 { "", ArgSettingsFilename, (void *) NULL, FALSE };
 
 void
 { "", ArgSettingsFilename, (void *) NULL, FALSE };
 
 void
-ExitArgError(char *msg, char *badArg)
+ExitArgError(char *msg, char *badArg, Boolean quit)
 {
   char buf[MSG_SIZ];
   int len;
 {
   char buf[MSG_SIZ];
   int len;
@@ -750,6 +750,7 @@ ExitArgError(char *msg, char *badArg)
   if( (len > MSG_SIZ) && appData.debugMode )
     fprintf(debugFP, "ExitArgError: buffer truncated. Input: msg=%s badArg=%s\n", msg, badArg);
 
   if( (len > MSG_SIZ) && appData.debugMode )
     fprintf(debugFP, "ExitArgError: buffer truncated. Input: msg=%s badArg=%s\n", msg, badArg);
 
+  if(!quit) { printf("%s in settings file\n", buf); return; } // DisplayError does not work yet at this stage...
   DisplayFatalError(buf, 0, 2);
   exit(2);
 }
   DisplayFatalError(buf, 0, 2);
   exit(2);
 }
@@ -759,7 +760,7 @@ ValidateInt(char *s)
 {
   char *p = s;
   if(*p == '-' || *p == '+') p++;
 {
   char *p = s;
   if(*p == '-' || *p == '+') p++;
-  while(*p) if(!isdigit(*p++)) ExitArgError("Bad integer value", s);
+  while(*p) if(!isdigit(*p++)) ExitArgError("Bad integer value", s, TRUE);
   return atoi(s);
 }
 
   return atoi(s);
 }
 
@@ -849,9 +850,11 @@ ParseArgs(GetFunc get, void *cl)
       *q = NULLCHAR;
       for (ad = argDescriptors; ad->argName != NULL; ad++)
        if (strcmp(ad->argName, argName + 1) == 0) break;
       *q = NULLCHAR;
       for (ad = argDescriptors; ad->argName != NULL; ad++)
        if (strcmp(ad->argName, argName + 1) == 0) break;
-      if (ad->argName == NULL)
-       ExitArgError("Unrecognized argument", argName);
-
+      if (ad->argName == NULL) {
+       ExitArgError("Unrecognized argument", argName, get != &FileGet); // [HGM] make unknown argument non-fatal
+       while (ch != '\n' && ch != NULLCHAR) ch = get(cl); // but skip rest of line it is on
+       continue; // so that when it is in a settings file, it is the only setting that will be purged from it
+      }
     } else if (ch == '@') {
       /* Indirection file */
       ad = &argDescriptorIndirection;
     } else if (ch == '@') {
       /* Indirection file */
       ad = &argDescriptorIndirection;
@@ -877,7 +880,7 @@ ParseArgs(GetFunc get, void *cl)
 
     while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
     if (ch == NULLCHAR || ch == '\n') {
 
     while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);
     if (ch == NULLCHAR || ch == '\n') {
-      ExitArgError("No value provided for argument", argName);
+      ExitArgError("No value provided for argument", argName, TRUE);
     }
     q = argValue;
     if (ch == '{') {
     }
     q = argValue;
     if (ch == '{') {
@@ -937,7 +940,7 @@ ParseArgs(GetFunc get, void *cl)
          ch = get(cl);
          switch (ch) {
          case NULLCHAR:
          ch = get(cl);
          switch (ch) {
          case NULLCHAR:
-           ExitArgError("Incomplete \\ escape in value for", argName);
+           ExitArgError("Incomplete \\ escape in value for", argName, TRUE);
            break;
          case 'n':
            *q++ = '\n';
            break;
          case 'n':
            *q++ = '\n';
@@ -1021,7 +1024,7 @@ ParseArgs(GetFunc get, void *cl)
        } else {
          if (ad->argLoc != NULL) {
          } else {
        } else {
          if (ad->argLoc != NULL) {
          } else {
-           ExitArgError("Failed to open indirection file", argValue);
+           ExitArgError("Failed to open indirection file", argValue, TRUE);
          }
        }
       }
          }
        }
       }
@@ -1038,7 +1041,7 @@ ParseArgs(GetFunc get, void *cl)
        *(Boolean *) ad->argLoc = FALSE;
        break;
       default:
        *(Boolean *) ad->argLoc = FALSE;
        break;
       default:
-       ExitArgError("Unrecognized boolean argument value", argValue);
+       ExitArgError("Unrecognized boolean argument value", argValue, TRUE);
        break;
       }
       break;
        break;
       }
       break;
@@ -1066,7 +1069,7 @@ ParseArgs(GetFunc get, void *cl)
       break;
 
     case ArgNone:
       break;
 
     case ArgNone:
-      ExitArgError("Unrecognized argument", argValue);
+      ExitArgError("Unrecognized argument", argValue, TRUE);
       break;
     case ArgTwo:
     case ArgTrue:
       break;
     case ArgTwo:
     case ArgTrue: