// logging functions
// ----------------------------------------------------------------------------
-#define DUPLICATE_LOG_OUT_TO_STDOUT TRUE
-#define DUPLICATE_LOG_ERR_TO_STDERR TRUE
+#define DUPLICATE_LOGGING_TO_STDOUT TRUE
#if defined(PLATFORM_ANDROID)
static void vprintf_log_nonewline(char *format, va_list ap)
{
- FILE *file = program.log_file[LOG_ERR_ID];
+ FILE *file = program.log_file;
-#if DUPLICATE_LOG_ERR_TO_STDERR
- if (file != program.log_file_default[LOG_ERR_ID])
+#if DUPLICATE_LOGGING_TO_STDOUT
+ if (file != program.log_file_default)
{
va_list ap2;
va_copy(ap2, ap);
- vfprintf(program.log_file_default[LOG_ERR_ID], format, ap2);
+ vfprintf(program.log_file_default, format, ap2);
va_end(ap2);
}
static void vprintf_log(char *format, va_list ap)
{
- FILE *file = program.log_file[LOG_ERR_ID];
+ FILE *file = program.log_file;
char *newline = STRING_NEWLINE;
-#if DUPLICATE_LOG_ERR_TO_STDERR
- if (file != program.log_file_default[LOG_ERR_ID])
+#if DUPLICATE_LOGGING_TO_STDOUT
+ if (file != program.log_file_default)
{
va_list ap2;
va_copy(ap2, ap);
- vfprintf(program.log_file_default[LOG_ERR_ID], format, ap2);
- fprintf(program.log_file_default[LOG_ERR_ID], "%s", newline);
+ vfprintf(program.log_file_default, format, ap2);
+ fprintf(program.log_file_default, "%s", newline);
va_end(ap2);
}
static void vPrint(char *format, va_list ap)
{
- FILE *file = program.log_file[LOG_OUT_ID];
+ FILE *file = program.log_file;
-#if DUPLICATE_LOG_OUT_TO_STDOUT
- if (file != program.log_file_default[LOG_OUT_ID])
+#if DUPLICATE_LOGGING_TO_STDOUT
+ if (file != program.log_file_default)
{
va_list ap2;
va_copy(ap2, ap);
- vfprintf(program.log_file_default[LOG_OUT_ID], format, ap2);
+ vfprintf(program.log_file_default, format, ap2);
va_end(ap2);
}
void PrintNoLog(char *format, ...)
{
- FILE *file = program.log_file_default[LOG_OUT_ID];
+ FILE *file = program.log_file_default;
va_list ap;
va_start(ap, format);
// various string functions
// ----------------------------------------------------------------------------
-char *getStringCat2WithSeparator(char *s1, char *s2, char *sep)
+char *getStringCat2WithSeparator(const char *s1,
+ const char *s2,
+ const char *sep)
{
if (s1 == NULL || s2 == NULL || sep == NULL)
return NULL;
return complete_string;
}
-char *getStringCat3WithSeparator(char *s1, char *s2, char *s3, char *sep)
+char *getStringCat3WithSeparator(const char *s1,
+ const char *s2,
+ const char *s3,
+ const char *sep)
{
if (s1 == NULL || s2 == NULL || s3 == NULL || sep == NULL)
return NULL;
return complete_string;
}
-char *getStringCat2(char *s1, char *s2)
+char *getStringCat2(const char *s1, const char *s2)
{
return getStringCat2WithSeparator(s1, s2, "");
}
-char *getStringCat3(char *s1, char *s2, char *s3)
+char *getStringCat3(const char *s1, const char *s2, const char *s3)
{
return getStringCat3WithSeparator(s1, s2, s3, "");
}
-char *getPath2(char *path1, char *path2)
+char *getPath2(const char *path1, const char *path2)
{
#if defined(PLATFORM_ANDROID)
// workaround for reading from assets directory -- skip "." subdirs in path
return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR);
}
-char *getPath3(char *path1, char *path2, char *path3)
+char *getPath3(const char *path1, const char *path2, const char *path3)
{
#if defined(PLATFORM_ANDROID)
// workaround for reading from assets directory -- skip "." subdirs in path
return filename;
}
-char *getImg2(char *path1, char *path2)
+char *getImg2(const char *path1, const char *path2)
{
return getPngOrPcxIfNotExists(getPath2(path1, path2));
}
-char *getImg3(char *path1, char *path2, char *path3)
+char *getImg3(const char *path1, const char *path2, const char *path3)
{
return getPngOrPcxIfNotExists(getPath3(path1, path2, path3));
}
return s_copy;
}
-void setString(char **old_value, char *new_value)
+void setString(char **old_value, const char *new_value)
{
checked_free(*old_value);
*old_value = getStringCopy(new_value);
}
-boolean strEqual(char *s1, char *s2)
+boolean strEqual(const char *s1, const char *s2)
{
return (s1 == NULL && s2 == NULL ? TRUE :
s1 == NULL && s2 != NULL ? FALSE :
strcmp(s1, s2) == 0);
}
-boolean strEqualN(char *s1, char *s2, int n)
+boolean strEqualN(const char *s1, const char *s2, int n)
{
return (s1 == NULL && s2 == NULL ? TRUE :
s1 == NULL && s2 != NULL ? FALSE :
strncmp(s1, s2, n) == 0);
}
-boolean strEqualCase(char *s1, char *s2)
+boolean strEqualCase(const char *s1, const char *s2)
{
return (s1 == NULL && s2 == NULL ? TRUE :
s1 == NULL && s2 != NULL ? FALSE :
strcasecmp(s1, s2) == 0);
}
-boolean strEqualCaseN(char *s1, char *s2, int n)
+boolean strEqualCaseN(const char *s1, const char *s2, int n)
{
return (s1 == NULL && s2 == NULL ? TRUE :
s1 == NULL && s2 != NULL ? FALSE :
strncasecmp(s1, s2, n) == 0);
}
-boolean strPrefix(char *s, char *prefix)
+boolean strPrefix(const char *s, const char *prefix)
{
return (s == NULL && prefix == NULL ? TRUE :
s == NULL && prefix != NULL ? FALSE :
strncmp(s, prefix, strlen(prefix)) == 0);
}
-boolean strSuffix(char *s, char *suffix)
+boolean strSuffix(const char *s, const char *suffix)
{
return (s == NULL && suffix == NULL ? TRUE :
s == NULL && suffix != NULL ? FALSE :
strcmp(&s[strlen(s) - strlen(suffix)], suffix) == 0);
}
-boolean strPrefixLower(char *s, char *prefix)
+boolean strPrefixLower(const char *s, const char *prefix)
{
char *s_lower = getStringToLower(s);
boolean match = strPrefix(s_lower, prefix);
return match;
}
-boolean strSuffixLower(char *s, char *suffix)
+boolean strSuffixLower(const char *s, const char *suffix)
{
char *s_lower = getStringToLower(s);
boolean match = strSuffix(s_lower, suffix);
return match;
}
-boolean isURL(char *s)
+boolean isURL(const char *s)
{
while (*s && *s >= 'a' && *s <= 'z')
s++;
int display_nr = atoi(option_arg);
+#if 1
+ // dirty hack: SDL_GetNumVideoDisplays() seems broken on some systems
+ options.display_nr = display_nr;
+#else
options.display_nr =
MAX(0, MIN(display_nr, SDL_GetNumVideoDisplays() - 1));
if (display_nr != options.display_nr)
Warn("invalid display %d -- using display %d",
display_nr, options.display_nr);
+#endif
}
#if defined(PLATFORM_MAC)
else if (strPrefix(option, "-psn"))
*y2 = help_y;
}
+int get_number_of_bits(int bits)
+{
+ /*
+ Counting bits set, Brian Kernighan's way
+
+ Brian Kernighan's method goes through as many iterations as there are set
+ bits. So if we have a 32-bit word with only the high bit set, then it will
+ only go once through the loop.
+
+ Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan
+ and Dennis M. Ritchie) mentions this in exercise 2-9.
+ First published by Peter Wegner in CACM 3 (1960), 322.
+ */
+
+ int num_bits = 0;
+
+ while (bits)
+ {
+ bits &= bits - 1; // clear the least significant bit set
+ num_bits++;
+ }
+
+ return num_bits;
+}
+
/* the "put" variants of the following file access functions check for the file
pointer being != NULL and return the number of bytes they have or would have
written; this allows for chunk writing functions to first determine the size
// functions for checking files and filenames
// ----------------------------------------------------------------------------
-boolean directoryExists(char *dir_name)
+boolean directoryExists(const char *dir_name)
{
if (dir_name == NULL)
return FALSE;
return success;
}
-boolean fileExists(char *filename)
+boolean fileExists(const char *filename)
{
if (filename == NULL)
return FALSE;
}
#if 0
-static boolean fileHasPrefix(char *basename, char *prefix)
+static boolean fileHasPrefix(const char *basename, const char *prefix)
{
static char *basename_lower = NULL;
int basename_length, prefix_length;
}
#endif
-static boolean fileHasSuffix(char *basename, char *suffix)
+static boolean fileHasSuffix(const char *basename, const char *suffix)
{
static char *basename_lower = NULL;
int basename_length, suffix_length;
// (now also added for Windows, to create files in user data directory)
// ----------------------------------------------------------------------------
+char *getLogBasename(char *basename)
+{
+ return getStringCat2(basename, ".log");
+}
+
char *getLogFilename(char *basename)
{
return getPath2(getMainUserGameDataDir(), basename);
}
-void OpenLogFiles(void)
+void OpenLogFile(void)
{
- int i;
-
InitMainUserDataDirectory();
- for (i = 0; i < NUM_LOGS; i++)
+ if ((program.log_file = fopen(program.log_filename, MODE_WRITE)) == NULL)
{
- if ((program.log_file[i] = fopen(program.log_filename[i], MODE_WRITE))
- == NULL)
- {
- program.log_file[i] = program.log_file_default[i]; // reset to default
-
- Warn("cannot open file '%s' for writing: %s",
- program.log_filename[i], strerror(errno));
- }
+ program.log_file = program.log_file_default; // reset to default
- // output should be unbuffered so it is not truncated in a crash
- setbuf(program.log_file[i], NULL);
+ Warn("cannot open file '%s' for writing: %s",
+ program.log_filename, strerror(errno));
}
+
+ // output should be unbuffered so it is not truncated in a crash
+ setbuf(program.log_file, NULL);
}
-void CloseLogFiles(void)
+void CloseLogFile(void)
{
- int i;
-
- for (i = 0; i < NUM_LOGS; i++)
- if (program.log_file[i] != program.log_file_default[i])
- fclose(program.log_file[i]);
+ if (program.log_file != program.log_file_default)
+ fclose(program.log_file);
}
-void DumpLogFile(int nr)
+void DumpLogFile(void)
{
- FILE *log_file = fopen(program.log_filename[nr], MODE_READ);
+ FILE *log_file = fopen(program.log_filename, MODE_READ);
if (log_file == NULL)
return;
char *error_text = getStringCat2("The program was aborted due to an error; "
"for details, see the following error file:"
STRING_NEWLINE,
- program.log_filename[LOG_ERR_ID]);
+ program.log_filename);
MessageBox(NULL, error_text, title_text, MB_OK);
#endif