Menu

#479 land.c: add -d output directory flag, fix implicit declarations, fix main() signature

None
closed
None
5
2026-06-03
2026-06-02
Rick Tanner
No

I was working on the idea of using land.c to generate a Gridarta tutorial map - basically, a somewhat small island off the coast. But. land.c had problems trying compile on Ubuntu Resolute - and the map file output could not be saved in to a specified directory. So, Claude came up with the following:

So, now a command syntax like this works as desired:

./land -x 200 -y 200 -s 42 -n 40 -l 300000 -p 50 -w 50000 -d ~/test_output -m


Patch Summary — land.c

1. Added #include <time.h>

Why: time() is called in main() to generate a default random seed when -s is not supplied. Modern GCC requires the header to be explicitly included; older compilers silently assumed it. Without it, GCC raises an implicit function declaration error and refuses to compile.

2. Added #include <unistd.h>

Why: getopt() is declared in <unistd.h>. The original code relied on the compiler implicitly knowing about it — behaviour that is no longer permitted under C99 and later. Without this header, GCC cannot find the declaration and raises an implicit function declaration error.

3. Added #include <string.h>

Why: Required for snprintf(), which is used throughout the patch to safely build output file paths. Strictly speaking snprintf is declared in <stdio.h> on most systems, but explicitly including <string.h> makes the dependency clear and is correct portable practice.

4. Fixed main() return type

Why: The original declaration was main(int argc, char *argv) — missing both the int return type and the correct argv declaration. Modern GCC rejects the implicit int return type as an error. The correct form is int main(int argc, char *argv[]).

5. Fixed argv declaration

Why: The original char *argv declares argv as a pointer to a single character, not an array of string pointers. The correct type is char *argv[] (array of pointers to char). This was a latent bug in the original that happened to work on the original target platform due to calling convention coincidences.

6. Added global char *outdir

Why: All output filenames were hardcoded without any path prefix, forcing the user to cd into the target directory before running. A global outdir variable (defaulting to ".") holds the user-supplied path and is accessible by both write_crossfire_maps() and the lmap/pmap block in main() without requiring a function signature change.

7. Added -d <directory> option to getopt()

Why: There was no way to specify where output files should be written. The new -d flag accepts a directory path and stores it in outdir. Adding "d:" to the getopt format string (the colon meaning the flag takes an argument) follows the existing pattern used by all other flags. Default behaviour when -d is omitted is unchanged.

8. Replaced sprintf with snprintf for all filename construction

Why: The original used sprintf(name, MAP_FORMAT, nx, ny) with a fixed 512-byte buffer. Once a directory path prefix is prepended this is insufficient and potentially unsafe. snprintf with a 4128-byte buffer (PATH_MAX 4096 + filename slack) prevents buffer overflow for any realistic path length.

9. Added bare_name for map file headers

Why: The Crossfire map header name field must contain the logical map name (world_NNN_NNN), not a filesystem path. When -d is used the full tile path includes the directory prefix, so a separate bare_name buffer is formatted using just MAP_FORMAT to keep the in-game identifier correct.

10. Added NULL checks on all fopen() calls

Why: The original checked for a failed open on tile files but not on cmap, lmap, or pmap. A failed fopen() returns NULL; passing NULL to fprintf() is undefined behaviour and typically produces a segfault with no diagnostic. All four open sites now check for NULL and exit with a descriptive error message pointing to the likely cause (directory missing or not writable).

11. Added stderr confirmation of output directory

Why: The existing code already prints a summary of all generation parameters to stderr at startup. Adding the effective output directory to that summary lets the user confirm where files will land before a potentially long generation run completes.

1 Attachments

Discussion

  • Kevin Zheng

    Kevin Zheng - 2026-06-03

    Feedback regarding the AI patch:

    • The inline explanations "PATCH: do whatever" or "Original code" are very annoying
    • The added code does not match the conventions in the server code
    • There are unrelated formatting/indentation changes that make this hard to review

    In short the effort to review what AI did here took longer than just fixing the compile myself. So I did that and pushed in ebc9cb799.

     
  • Kevin Zheng

    Kevin Zheng - 2026-06-03
    • status: open --> closed
    • assigned_to: Kevin Zheng
    • Group: -->
     

Log in to post a comment.

Auth0 Logo