<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