OpenTTD Source
1.11.0-beta2
|
Go to the documentation of this file.
10 #include "../stdafx.h"
11 #include "../string_func.h"
12 #include "../strings_type.h"
13 #include "../misc/getoptdata.h"
14 #include "../ini_type.h"
15 #include "../core/smallvec_type.hpp"
19 #if !defined(_WIN32) || defined(__CYGWIN__)
24 #include "../safeguards.h"
31 void NORETURN CDECL
error(
const char *s, ...)
38 fprintf(stderr,
"FATAL: %s\n", buf);
59 size_t Add(
const char *text,
size_t length)
64 this->
size += store_size;
74 if (fwrite(this->
data, 1, this->
size, out_fp) != this->
size) {
75 fprintf(stderr,
"Error: Cannot write output\n");
111 void Add(
const char *text,
size_t length = 0)
113 if (length == 0) length = strlen(text);
117 length -= stored_size;
123 size_t stored_size = block.
Add(text, length);
124 length -= stored_size;
136 out_data.Write(out_fp);
148 return num_blocks > 0 && this->
output_buffer[num_blocks - 1].HasRoom();
172 FILE *in = fopen(filename.c_str(),
"rb");
173 if (in ==
nullptr)
return nullptr;
175 fseek(in, 0L, SEEK_END);
178 fseek(in, 0L, SEEK_SET);
182 virtual void ReportFileError(
const char *
const pre,
const char *
const buffer,
const char *
const post)
184 error(
"%s%s%s", pre, buffer, post);
219 if (!item->name.empty()) {
237 if (item ==
nullptr && defaults !=
nullptr) item = defaults->
GetItem(name,
false);
238 if (item ==
nullptr || !item->
value.has_value())
return nullptr;
239 return item->
value->c_str();
248 static const int MAX_VAR_LENGTH = 64;
253 if (templates_grp ==
nullptr)
return;
257 const char *
const *sgn;
258 for (sgn = special_group_names; *sgn !=
nullptr; sgn++)
if (grp->name == *sgn)
break;
259 if (*sgn !=
nullptr)
continue;
261 IniItem *template_item = templates_grp->
GetItem(grp->name,
false);
262 if (template_item ==
nullptr || !template_item->
value.has_value()) {
263 fprintf(stderr,
"settingsgen: Warning: Cannot find template %s\n", grp->name.c_str());
268 static const char *
const pp_lines[] = {
"if",
"ifdef",
"ifndef",
nullptr};
270 for (
const char *
const *name = pp_lines; *name !=
nullptr; name++) {
271 const char *condition =
FindItemValue(*name, grp, default_grp);
272 if (condition !=
nullptr) {
283 const char *txt = template_item->
value->c_str();
284 while (*txt !=
'\0') {
298 char variable[MAX_VAR_LENGTH];
300 while (i < MAX_VAR_LENGTH - 1) {
301 if (!(txt[i] ==
'_' || (txt[i] >=
'a' && txt[i] <=
'z') || (txt[i] >=
'0' && txt[i] <=
'9')))
break;
302 variable[i] = txt[i];
310 const char *valitem =
FindItemValue(variable, grp, default_grp);
329 static void CopyFile(
const char *fname, FILE *out_fp)
331 if (fname ==
nullptr)
return;
333 FILE *in_fp = fopen(fname,
"r");
334 if (in_fp ==
nullptr) {
335 fprintf(stderr,
"settingsgen: Warning: Cannot open file %s for copying\n", fname);
342 length = fread(buffer, 1,
lengthof(buffer), in_fp);
343 if (fwrite(buffer, 1, length, out_fp) != length) {
344 fprintf(stderr,
"Error: Cannot copy file\n");
347 }
while (length ==
lengthof(buffer));
360 FILE *f2 = fopen(n2,
"rb");
361 if (f2 ==
nullptr)
return false;
363 FILE *f1 = fopen(n1,
"rb");
366 error(
"can't open %s", n1);
373 l1 = fread(b1, 1,
sizeof(b1), f1);
374 l2 = fread(b2, 1,
sizeof(b2), f2);
376 if (l1 != l2 || memcmp(b1, b2, l1) != 0) {
433 int CDECL
main(
int argc,
char *argv[])
435 const char *output_file =
nullptr;
436 const char *before_file =
nullptr;
437 const char *after_file =
nullptr;
450 puts(
"settingsgen - $Revision$\n"
451 "Usage: settingsgen [options] ini-file...\n"
453 " -v, --version Print version information and exit\n"
454 " -h, -?, --help Print this help message and exit\n"
455 " -b FILE, --before FILE Copy FILE before all settings\n"
456 " -a FILE, --after FILE Copy FILE after all settings\n"
457 " -o FILE, --output FILE Write output to FILE\n");
461 output_file = mgo.
opt;
465 after_file = mgo.
opt;
469 before_file = mgo.
opt;
473 fprintf(stderr,
"Invalid arguments\n");
483 if (output_file ==
nullptr) {
488 static const char *
const tmp_output =
"tmp2.xxx";
490 FILE *fp = fopen(tmp_output,
"w");
492 fprintf(stderr,
"settingsgen: Warning: Cannot open file %s\n", tmp_output);
508 if (rename(tmp_output, output_file) == -1)
error(
"rename() failed");
static void ProcessIniFile(const char *fname)
Process a single INI file.
static bool CompareFiles(const char *n1, const char *n2)
Compare two files for identity.
void Write(FILE *out_fp) const
Write all stored output to the output stream.
static IniLoadFile * LoadIniFile(const char *filename)
Load the INI file.
IniItem * next
The next item in this group.
char data[OUTPUT_BLOCK_SIZE]
Stored data.
void Clear()
Prepare buffer for use.
virtual FILE * OpenFile(const std::string &filename, Subdirectory subdir, size_t *size)
Open the INI file.
static const char * DEFAULTS_GROUP_NAME
Name of the group containing default values for the template variables.
A single "line" in an ini file.
A group within an ini file.
#define GETOPT_VALUE(shortname, longname)
Short option with value.
bool BufferHasRoom() const
Does the buffer have room without adding a new OutputBuffer block?
OutputStore _stored_output
Temporary storage of the output, until all processing is done.
static void MemCpyT(T *destination, const T *source, size_t num=1)
Type-safe version of memcpy().
size_t size
Number of bytes stored in data.
Ini file that only supports loading.
char ** argv
Remaining command line arguments.
static void DumpGroup(IniLoadFile *ifile, const char *const group_name)
Dump a IGT_SEQUENCE group into _stored_output.
static const char * POSTAMBLE_GROUP_NAME
Name of the group containing the post amble.
void Clear()
Clear the temporary storage.
static const size_t OUTPUT_BLOCK_SIZE
Block size of the buffer in OutputBuffer.
#define GETOPT_NOVAL(shortname, longname)
Short option without value.
std::optional< std::string > value
The value of this item.
#define GETOPT_END()
Option terminator.
bool HasRoom() const
Does the block have room for more data?
#define GETOPT_GENERAL(id, shortname, longname, flags)
General macro for creating an option.
OutputBufferVector output_buffer
Vector of blocks containing the stored output.
char * opt
Option value, if available (else nullptr).
int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap)
Safer implementation of vsnprintf; same as vsnprintf except:
IniGroupType type
type of group
Data storage for parsing command line options.
Derived class for loading INI files without going through Fio stuff.
void Write(FILE *out_fp) const
Dump buffer to the output stream.
Temporarily store output.
std::vector< OutputBuffer > OutputBufferVector
Vector type for output buffers.
const char *const * list_group_names
nullptr terminated list with group names that are lists
static const OptionData _opts[]
Options of settingsgen.
IniGroup * group
the first group in the ini
static const char * PREAMBLE_GROUP_NAME
Name of the group containing the pre amble.
size_t Add(const char *text, size_t length)
Add text to the output buffer.
int CDECL main(int argc, char *argv[])
And the main program (what else?)
static const char * FindItemValue(const char *name, IniGroup *grp, IniGroup *defaults)
Find the value of a template variable.
@ NO_DIRECTORY
A path without any base directory.
void NORETURN CDECL error(const char *s,...)
Report a fatal error.
@ IGT_SEQUENCE
A list of uninterpreted lines, terminated by the next group block.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
static void CopyFile(const char *fname, FILE *out_fp)
Copy a file to the output.
int GetOpt()
Find the next option.
void Add(const char *text, size_t length=0)
Add text to the output storage.
#define lengthof(x)
Return the length of an fixed size array.
IniItem * item
the first item in the group
Output buffer for a block of data.
const char *const * seq_group_names
nullptr terminated list with group names that are sequences.
static void DumpSections(IniLoadFile *ifile)
Output all non-special sections through the template / template variable expansion system.
IniItem * GetItem(const std::string &name, bool create)
Get the item with the given name, and if it doesn't exist and create is true it creates a new item.
void LoadFromDisk(const std::string &filename, Subdirectory subdir)
Load the Ini file's data from the disk.
virtual void ReportFileError(const char *const pre, const char *const buffer, const char *const post)
Report an error about the file contents.
SettingsIniFile(const char *const *list_group_names=nullptr, const char *const *seq_group_names=nullptr)
Construct a new ini loader.
#define lastof(x)
Get the last element of an fixed size array.
@ ODF_NO_VALUE
A plain option (no value attached to it).
int numleft
Number of arguments left in argv.
static const char * TEMPLATES_GROUP_NAME
Name of the group containing the templates.
IniGroup * GetGroup(const std::string &name, bool create_new=true)
Get the group with the given name.
IniGroup * next
the next group within this file