+ if (s1 == NULL || s2 == NULL || sep == NULL)
+ return NULL;
+
+ char *complete_string = checked_malloc(strlen(s1) + strlen(sep) +
+ strlen(s2) + 1);
+
+ sprintf(complete_string, "%s%s%s", s1, sep, s2);
+
+ return complete_string;
+}
+
+char *getStringCat3WithSeparator(char *s1, char *s2, char *s3, char *sep)
+{
+ if (s1 == NULL || s2 == NULL || s3 == NULL || sep == NULL)
+ return NULL;
+
+ char *complete_string = checked_malloc(strlen(s1) + strlen(sep) +
+ strlen(s2) + strlen(sep) +
+ strlen(s3) + 1);
+
+ sprintf(complete_string, "%s%s%s%s%s", s1, sep, s2, sep, s3);
+
+ return complete_string;
+}
+
+char *getStringCat2(char *s1, char *s2)
+{
+ return getStringCat2WithSeparator(s1, s2, "");
+}
+
+char *getStringCat3(char *s1, char *s2, char *s3)
+{
+ return getStringCat3WithSeparator(s1, s2, s3, "");
+}
+
+char *getPath2(char *path1, char *path2)
+{
+#if defined(PLATFORM_ANDROID)
+ // workaround for reading from assets directory -- skip "." subdirs in path
+ if (strEqual(path1, "."))
+ return getStringCopy(path2);
+ else if (strEqual(path2, "."))
+ return getStringCopy(path1);
+#endif
+
+ return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR);
+}
+
+char *getPath3(char *path1, char *path2, char *path3)
+{
+#if defined(PLATFORM_ANDROID)
+ // workaround for reading from assets directory -- skip "." subdirs in path
+ if (strEqual(path1, "."))
+ return getStringCat2WithSeparator(path2, path3, STRING_PATH_SEPARATOR);
+ else if (strEqual(path2, "."))
+ return getStringCat2WithSeparator(path1, path3, STRING_PATH_SEPARATOR);
+ else if (strEqual(path3, "."))
+ return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR);
+#endif
+
+ return getStringCat3WithSeparator(path1, path2, path3, STRING_PATH_SEPARATOR);
+}
+
+char *getImg2(char *path1, char *path2)
+{
+ char *filename = getPath2(path1, path2);
+
+ if (!fileExists(filename) && strSuffix(path2, ".png"))
+ {
+ // backward compatibility: if PNG file not found, check for PCX file
+ char *path2pcx = getStringCopy(path2);
+
+ strcpy(&path2pcx[strlen(path2pcx) - 3], "pcx");
+
+ free(filename);
+
+ filename = getPath2(path1, path2pcx);
+
+ free(path2pcx);
+ }
+
+ return filename;
+}
+
+char *getImg3(char *path1, char *path2, char *path3)
+{
+ char *filename = getPath3(path1, path2, path3);
+
+ if (!fileExists(filename) && strSuffix(path3, ".png"))
+ {
+ // backward compatibility: if PNG file not found, check for PCX file
+ char *path3pcx = getStringCopy(path3);
+
+ strcpy(&path3pcx[strlen(path3pcx) - 3], "pcx");
+
+ free(filename);
+
+ filename = getPath3(path1, path2, path3pcx);
+
+ free(path3pcx);
+ }
+
+ return filename;
+}
+
+char *getStringCopy(const char *s)
+{
+ char *s_copy;
+
+ if (s == NULL)
+ return NULL;
+
+ s_copy = checked_malloc(strlen(s) + 1);
+ strcpy(s_copy, s);
+
+ return s_copy;
+}
+
+char *getStringCopyN(const char *s, int n)
+{
+ char *s_copy;
+ int s_len = MAX(0, n);
+
+ if (s == NULL)
+ return NULL;
+
+ s_copy = checked_malloc(s_len + 1);
+ strncpy(s_copy, s, s_len);
+ s_copy[s_len] = '\0';
+
+ return s_copy;
+}
+
+char *getStringCopyNStatic(const char *s, int n)
+{
+ static char *s_copy = NULL;
+
+ checked_free(s_copy);
+
+ s_copy = getStringCopyN(s, n);
+
+ return s_copy;
+}
+
+char *getStringToLower(const char *s)
+{
+ char *s_copy = checked_malloc(strlen(s) + 1);
+ char *s_ptr = s_copy;
+
+ while (*s)
+ *s_ptr++ = tolower(*s++);
+ *s_ptr = '\0';
+
+ return s_copy;
+}
+
+void setString(char **old_value, char *new_value)
+{
+ checked_free(*old_value);
+
+ *old_value = getStringCopy(new_value);
+}
+
+boolean strEqual(char *s1, char *s2)
+{
+ return (s1 == NULL && s2 == NULL ? TRUE :
+ s1 == NULL && s2 != NULL ? FALSE :
+ s1 != NULL && s2 == NULL ? FALSE :
+ strcmp(s1, s2) == 0);
+}
+
+boolean strEqualN(char *s1, char *s2, int n)
+{
+ return (s1 == NULL && s2 == NULL ? TRUE :
+ s1 == NULL && s2 != NULL ? FALSE :
+ s1 != NULL && s2 == NULL ? FALSE :
+ strncmp(s1, s2, n) == 0);
+}
+
+boolean strPrefix(char *s, char *prefix)
+{
+ return (s == NULL && prefix == NULL ? TRUE :
+ s == NULL && prefix != NULL ? FALSE :
+ s != NULL && prefix == NULL ? FALSE :
+ strncmp(s, prefix, strlen(prefix)) == 0);
+}
+
+boolean strSuffix(char *s, char *suffix)
+{
+ return (s == NULL && suffix == NULL ? TRUE :
+ s == NULL && suffix != NULL ? FALSE :
+ s != NULL && suffix == NULL ? FALSE :
+ strlen(s) < strlen(suffix) ? FALSE :
+ strncmp(&s[strlen(s) - strlen(suffix)], suffix, strlen(suffix)) == 0);
+}
+
+boolean strPrefixLower(char *s, char *prefix)
+{
+ char *s_lower = getStringToLower(s);
+ boolean match = strPrefix(s_lower, prefix);
+
+ free(s_lower);
+
+ return match;
+}
+
+boolean strSuffixLower(char *s, char *suffix)
+{
+ char *s_lower = getStringToLower(s);
+ boolean match = strSuffix(s_lower, suffix);
+
+ free(s_lower);
+
+ return match;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* command line option handling functions */
+/* ------------------------------------------------------------------------- */
+
+void GetOptions(char *argv[],
+ void (*print_usage_function)(void),
+ void (*print_version_function)(void))
+{
+ char *ro_base_path = RO_BASE_PATH;
+ char *rw_base_path = RW_BASE_PATH;