Project

General

Profile

Actions

Feature #1903

open

improve format of output from ruledit/ruleup

Added by Dean Brown 8 months ago. Updated 1 day ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
Ruledit and ruleup
Target version:
Start date:
01/12/2026
Due date:
% Done:

0%

Estimated time:

Description

Don't you just hate it when there's a long helptext (like for a government), nicely formatted with newlines (like in the standard supplied rulesets), and then ruledit/ruleup turns it into a single line hundreds of chars long. And you're viewing it in a text editor that doesn't wrap long lines, cause you don't want wrapping when you're looking at C code. Let's do better.


Files

1903_S3_3&Main.patch (12.1 KB) 1903_S3_3&Main.patch Dean Brown, 08/29/2026 06:26 AM
Actions #1

Updated by Dean Brown 8 months ago

  • File 1903.patch added

This doesn't do everything possible to keep line lengths < LINE_BREAK, but does deal with "helptext=..." and long lists of "...","...", like the lists of actions in actions.ruleset and lists of "flags=" in units.ruleset. Not dealt with are "helptxt" strings within

flags={"name","helptxt"
class_flags={"name","helptxt"

in units.ruleset - there is only 1 instance in the supplied rulesets of a lengthy string. Also the Achievements in game.ruleset have strings for first_msg and cons_msg that could be long but there are no instances in the supplied rulesets.

The routine make_escapes() needed to be changed because as written it messed up the added new line chars. It was only called from entry_to_file() in registry_ini.c so I moved it from support.c/h to registry_ini.c and rewrote and renamed it.

Did a lot of testing - made sure running supplied rulesets thru new ruledit doesn't change appearance of helptext in the client help viewer. Also tested hacked input with edge cases and perverse strings. A token > 70 chars and no delimiters doesn't get split.

I discovered issue #1893 while testing, that issue and this one are independent and there's no need for a block.

Actions #2

Updated by Marko Lindqvist 8 months ago

Without reading the patch too carefully: Does it handle UTF-8 correctly? (i.e. not injecting newlines in the middle of a character)

You seem to have dropped backslash handling ('\\') from make_escapes(). Is that intentional?

The other secfiles we write in addition to rulesets are the savegames and client options files. I suppose you have tested that there's no changes to how they turn out with this patch?

Actions #3

Updated by Dean Brown 8 months ago

  • File 1903.patch added

Good catch on UTF-8, testing with "Agōgē of Sparta" shows a problem. Fixed the patch to test for high bit.

Yes backslash handling ('\\') is intentional. Otherwise inserting "\n\0x0A" doesn't work.

Yes tested savegames and client options files - the latter are unchanged, savegames wind up a little easier to read and still work OK.

Actions #4

Updated by Dean Brown 8 months ago

  • File deleted (1903.patch)
Actions #5

Updated by Dean Brown 7 months ago

  • File 1903_S3_3&Main.patch added
  • File 1903_S3_2.patch added

Need different patches for different branches.

Actions #6

Updated by Dean Brown 7 months ago

  • File deleted (1903.patch)
Actions #7

Updated by Marko Lindqvist 7 months ago

  • Blocks Bug #1893: ruledit and ruleup output has issues with _() added
Actions #8

Updated by Marko Lindqvist 3 months ago

The main problem I have with this patch is how it selects the low-level behavior based on what the high-level entry name happens to be. That's not a good API. It's mostly a coincidence that entry name "helptext" maps to the wanted behavior (and actually it does not - like you already point out yourself, there's also "first_msg" and "cons_msg" entry names in achievements.ruleset that should match).

I don't really see why the word wrap with \n\ cannot be applied unconditionally to all strings. It shouldn't matter to high-level what the low-level's internal format is as long as thigs get returned to the high-level properly formatted. But if there IS a reason to have different behavior for different entries, then the hugh-level should have control over the behavior in a way other than selecting specific entry names.


There are a number of cases where function's starting '{' is not on a line of its own.

Actions #9

Updated by Marko Lindqvist 25 days ago

Any progress with this? Or can we stop blocking #1893 with this, and get at least it going?

Actions #10

Updated by Dean Brown 7 days ago

  • File deleted (1903_S3_3&Main.patch)
Actions #11

Updated by Dean Brown 7 days ago

  • File deleted (1903_S3_2.patch)
Actions #12

Updated by Dean Brown 7 days ago

  • File 1903_S3_2.patch added
  • File 1903_S3_3&Main.patch added

I was being overly cautious by limiting my changes to just some strings, now reworked to do all strings and not test for e.g. "helptext". Now does the "first_msg" and "cons_msg", and "helptxt" strings within tables too. Much better!

I think #1893 is independent of this and doesn't need to be blocked.

Actions #13

Updated by Marko Lindqvist 1 day ago

Still haven't looked into details of this patch, but noticed that you are including fc_types.h from common/ to under utility/. That's not allowed. The whole point of separation between utility/ and common/ is that utility is independent from common. Common is freeciv specific code, utility contains utility functions that could be usable for other projects too.

Actions #14

Updated by Marko Lindqvist 1 day ago

  • Target version set to 3.4.0
Actions #15

Updated by Marko Lindqvist 1 day ago

  • Blocks deleted (Bug #1893: ruledit and ruleup output has issues with _() )
Actions #16

Updated by Dean Brown 1 day ago

  • File deleted (1903_S3_2.patch)
Actions #17

Updated by Dean Brown 1 day ago

  • File deleted (1903_S3_3&Main.patch)
Actions #18

Updated by Dean Brown 1 day ago

Fixed.

Actions #19

Updated by Marko Lindqvist 1 day ago

There's plenty of possibilities of buffer overflow in word_wrap_helptext()
You get an static char array with 8192 characters, and write to it without ever checking if you're still within the bounds. For all we know, even the input string might already be longer than 8192.

make_escapes_quotes() has a chance of buffer overflow, and more often also chance of underusing the buffer (it will abort even if three would be space left)
The original make_escapes() reserved two bytes of extra space so that even if the very last write expand from one to two bytes there would still be space for the terminating '\0'. You add only one byte. That you decrease 'max' inside the loop does not help when we are in the last character anyway.
The decrease of 'max' inside the loop seems completely wrong in any case. You do it in addition to increasing dest, so the net effect is that for one character added you decrease the space lest by two.


The comment

  /* We free() old value only after we've placed the new one, to
   * support secfile_replace_str_vec() calls that want to keep some of
   * the entries from the old vector in the new one. We don't want
   * to lose the entry in between. */

seems wrong in the context (I assume it's just copypasted)

Actions

Also available in: Atom PDF