<URL: http://bugs.freeciv.org/Ticket/Display.html?id=39442 >

Patch that applies to S2_1 and trunk r13075 attached.

Make escaped an attribute of entry so that it can be carried over from
load to save; change moutstr so that it takes a full_escapes argument
just like minstr. Also changed moutstr to return a string with
delimiters (either " " for escaped or $ $ for unescaped), to simplify
the code throughout.

Add secfile_insert_str_noescape so that noescaped strings (script.code
and script.vars) can be inserted.

Refactor slightly. introduce entry_init(struct *entry) so that all
entries are inited to good null values properly (removed various
duplicated NULL and 0-setting throughout other functions)

Make script.code and script.vars use the noescape function so that they
are saved back with $..$ delimiters. Now they can load correctly and are
easy to edit (good for scenario/.sav hand-editors)

Now tutorial script works from savegames!

We need to commit this to the 2.1 branch if we seriously want lua and
the tutorial to work, even if it is a bit intrusive to the registry, it
should be safe.
Index: utility/registry.c
===================================================================
--- utility/registry.c	(revision 13075)
+++ utility/registry.c	(arbetskopia)
@@ -186,6 +186,7 @@
   int dim;			/* vector's size */
   int  used;			/* number of times entry looked up */
   char *comment;                /* comment, may be NULL */
+  bool escaped;                 /* " or $. Usually TRUE */
 };
 
 /* create a 'struct entry_list' and related functions: */
@@ -228,7 +229,7 @@
 
 static char *minstrdup(struct sbuffer *sb, const char *str,
                        bool full_escapes);
-static char *moutstr(char *str);
+static char *moutstr(char *str, bool full_escapes);
 
 static struct entry*
 section_file_lookup_internal(struct section_file *my_section_file,  
@@ -356,6 +357,21 @@
 }
 
 /**************************************************************************
+  Initialize the entry struct and set to default (empty) values.
+**************************************************************************/
+static void entry_init(struct entry *pentry)
+{
+  pentry->name = NULL;
+  pentry->svalue = NULL;
+  pentry->ivalue = 0;
+  pentry->used = 0;
+  pentry->dim = 0;
+  pentry->vec_values = NULL;
+  pentry->comment = NULL;
+  pentry->escaped = TRUE;
+}
+
+/**************************************************************************
   Return a new entry struct, allocated from sb, with given name,
   and where tok is a "value" return token from inputfile.
   The entry value has any escaped double-quotes etc removed.
@@ -366,20 +382,18 @@
   struct entry *pentry;
 
   pentry = sbuf_malloc(sb, sizeof(struct entry));
+  entry_init(pentry);
   pentry->name = sbuf_strdup(sb, name);
-  pentry->comment = NULL;
   if (tok[0] != '-' && !my_isdigit(tok[0])) {
     /* It is not integer, but string with some border character. */
-    bool escapes = (tok[0] != '$'); /* Border character '$' means no escapes */
+    pentry->escaped = (tok[0] != '$'); /* Border character '$' means no escapes */
 
     /* minstrdup() starting after border character */
-    pentry->svalue = minstrdup(sb, tok+1, escapes);
-    pentry->ivalue = 0;
+    pentry->svalue = minstrdup(sb, tok+1, pentry->escaped);
     if (SECF_DEBUG_ENTRIES) {
       freelog(LOG_DEBUG, "entry %s '%s'", name, pentry->svalue);
     }
   } else {
-    pentry->svalue = NULL;
     if (sscanf(tok, "%d", &pentry->ivalue) != 1) {
       freelog(LOG_ERROR, "'%s' isn't an integer", tok);
     }
@@ -387,7 +401,6 @@
       freelog(LOG_DEBUG, "entry %s %d", name, pentry->ivalue);
     }
   }
-  pentry->used = FALSE;
   return pentry;
 }
 
@@ -821,8 +834,8 @@
 
 	  if(icol>0)
 	    fz_fprintf(fs, ",");
-	  if(pentry->svalue) 
-	    fz_fprintf(fs, "\"%s\"", moutstr(pentry->svalue));
+	  if(pentry->svalue)
+	    fz_fprintf(fs, "%s", moutstr(pentry->svalue, pentry->escaped));
 	  else
 	    fz_fprintf(fs, "%d", pentry->ivalue);
 	  
@@ -842,13 +855,13 @@
       if(!pentry) break;
       
       if (pentry->vec_values) {
-        fz_fprintf(fs, "%s=\"%s\"", pentry->name,
-	           moutstr(pentry->vec_values[0]));
+        fz_fprintf(fs, "%s=%s", pentry->name,
+	           moutstr(pentry->vec_values[0], pentry->escaped));
 	for (i = 1; i < pentry->dim; i++) {
-	  fz_fprintf(fs, ", \"%s\"", moutstr(pentry->vec_values[i]));
+	  fz_fprintf(fs, ", %s", moutstr(pentry->vec_values[i], pentry->escaped));
 	}
       } else if (pentry->svalue) {
-	fz_fprintf(fs, "%s=\"%s\"", pentry->name, moutstr(pentry->svalue));
+	fz_fprintf(fs, "%s=%s", pentry->name, moutstr(pentry->svalue, pentry->escaped));
       } else {
 	fz_fprintf(fs, "%s=%d", pentry->name, pentry->ivalue);
       }
@@ -862,7 +875,7 @@
   }
   section_list_iterate_end;
   
-  (void) moutstr(NULL);		/* free internal buffer */
+  (void) moutstr(NULL, TRUE);		/* free internal buffer */
 
   if (fz_ferror(fs) != 0) {
     freelog(LOG_ERROR, "Error before closing %s: %s", real_filename,
@@ -954,10 +967,6 @@
   pentry=section_file_insert_internal(my_section_file, buf);
 
   pentry->ivalue=val;
-  pentry->svalue = NULL;
-  pentry->vec_values = NULL;
-  pentry->dim = 0;
-  pentry->comment = NULL;
 }
 
 /**************************************************************************
@@ -978,9 +987,6 @@
   pentry = section_file_insert_internal(my_section_file, buf);
 
   pentry->ivalue = val;
-  pentry->svalue = NULL;
-  pentry->vec_values = NULL;
-  pentry->dim = 0;
   pentry->comment = sbuf_strdup(my_section_file->sb, comment);
 }
 
@@ -1007,10 +1013,6 @@
   }
 
   pentry->ivalue = val ? 1 : 0;
-  pentry->svalue = NULL;
-  pentry->vec_values = NULL;
-  pentry->dim = 0;
-  pentry->comment = NULL;
 }
 
 /**************************************************************************
@@ -1029,14 +1031,32 @@
 
   pentry = section_file_insert_internal(my_section_file, buf);
   pentry->svalue = sbuf_strdup(my_section_file->sb, sval);
-  pentry->vec_values = NULL;
-  pentry->dim = 0;
-  pentry->comment = NULL;
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
+void secfile_insert_str_noescape(struct section_file *my_section_file,
+			const char *sval, const char *path, ...)
+{
+  struct entry *pentry;
+  char buf[MAX_LEN_BUFFER];
+  va_list ap;
+
+  va_start(ap, path);
+  my_vsnprintf(buf, sizeof(buf), path, ap);
+  va_end(ap);
+
+  pentry = section_file_insert_internal(my_section_file, buf);
+  pentry->svalue = sbuf_strdup(my_section_file->sb, sval);
+  pentry->escaped = FALSE;
+}
+
+
+
+/**************************************************************************
+...
+**************************************************************************/
 void secfile_insert_str_comment(struct section_file *my_section_file,
 				char *sval, const char *const comment,
 				const char *path, ...)
@@ -1051,8 +1071,6 @@
 
   pentry = section_file_insert_internal(my_section_file, buf);
   pentry->svalue = sbuf_strdup(my_section_file->sb, sval);
-  pentry->vec_values = NULL;
-  pentry->dim = 0;
   pentry->comment = sbuf_strdup(my_section_file->sb, comment);
 }
 
@@ -1087,9 +1105,6 @@
   for (i = 0; i < dim; i++) {
     pentry->vec_values[i] = sbuf_strdup(my_section_file->sb, values[i]);
   }
-				 
-  pentry->svalue = NULL;
-  pentry->comment = NULL;
 }
 
 /**************************************************************************
@@ -1361,6 +1376,7 @@
      * the section, to avoid O(N^2) behaviour.
      */
     pentry = sbuf_malloc(sb, sizeof(struct entry));
+    entry_init(pentry);
     pentry->name = sbuf_strdup(sb, ent_name);
     entry_list_append(psection->entries, pentry);
     return pentry;
@@ -1369,6 +1385,7 @@
   psection = section_file_append_section(my_section_file, sec_name);
 
   pentry = sbuf_malloc(sb, sizeof(struct entry));
+  entry_init(pentry);
   pentry->name = sbuf_strdup(sb, ent_name);
   entry_list_append(psection->entries, pentry);
 
@@ -1600,11 +1617,12 @@
  string at a time) with str escaped the opposite of minstrdup.
  Specifically, any newline, backslash, or double quote is
  escaped with a backslash.
+ Adds appropriate delimiters: "" if escaped, $$ unescaped.
  The internal buffer is grown as necessary, and not normally
  freed (since this will be called frequently.)  A call with
  str=NULL frees the buffer and does nothing else (returns NULL).
 ***************************************************************/
-static char *moutstr(char *str)
+static char *moutstr(char *str, bool full_escapes)
 {
   static char *buf = NULL;
   static int nalloc = 0;
@@ -1620,10 +1638,12 @@
     return NULL;
   }
   
-  len = strlen(str)+1;
-  for(c=str; *c != '\0'; c++) {
-    if (*c == '\n' || *c == '\\' || *c == '\"') {
-      len++;
+  len = strlen(str)+3;
+  if (full_escapes) {
+    for(c=str; *c != '\0'; c++) {
+      if (*c == '\n' || *c == '\\' || *c == '\"') {
+        len++;
+      }
     }
   }
   if (len > nalloc) {
@@ -1632,8 +1652,9 @@
   }
   
   dest = buf;
+  *dest++ = (full_escapes ? '\"' : '$');
   while(*str != '\0') {
-    if (*str == '\n' || *str == '\\' || *str == '\"') {
+    if (full_escapes && (*str == '\n' || *str == '\\' || *str == '\"')) {
       *dest++ = '\\';
       if (*str == '\n') {
 	*dest++ = 'n';
@@ -1645,6 +1666,7 @@
       *dest++ = *str++;
     }
   }
+  *dest++ = (full_escapes ? '\"' : '$');
   *dest = '\0';
   return buf;
 }
Index: utility/registry.h
===================================================================
--- utility/registry.h	(revision 13075)
+++ utility/registry.h	(arbetskopia)
@@ -59,6 +59,11 @@
 void secfile_insert_str(struct section_file *my_section_file, 
 			const char *sval, const char *path, ...)
                         fc__attribute((__format__ (__printf__, 3, 4)));
+
+void secfile_insert_str_noescape(struct section_file *my_section_file, 
+			const char *sval, const char *path, ...)
+                        fc__attribute((__format__ (__printf__, 3, 4)));
+
 void secfile_insert_str_comment(struct section_file *my_section_file,
 				char *sval, const char *const comment,
 				const char *path, ...)
Index: server/scripting/script.c
===================================================================
--- server/scripting/script.c	(revision 13075)
+++ server/scripting/script.c	(arbetskopia)
@@ -307,7 +307,7 @@
       lua_pop(state, 1);
 
       if (vars) {
-	secfile_insert_str(file, vars, "script.vars");
+	secfile_insert_str_noescape(file, vars, "script.vars");
       }
     } else {
       /* _freeciv_state_dump in api.pkg is busted */
@@ -356,7 +356,7 @@
 static void script_code_save(struct section_file *file)
 {
   if (script_code) {
-    secfile_insert_str(file, script_code, "script.code");
+    secfile_insert_str_noescape(file, script_code, "script.code");
   }
 }
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to