cleanup of unnecessarily convoluted function call
[rocksndiamonds.git] / src / libgame / misc.c
index 536d90b53816d3b4ab11e26f28ed0f54edd9842e..ed4bd5d62c991d7e94f72cb150ab904ee8c2935f 100644 (file)
@@ -620,12 +620,12 @@ static unsigned int mainCounter(int mode)
   return current_ms - base_ms;
 }
 
-void InitCounter()             // set counter back to zero
+void InitCounter(void)         // set counter back to zero
 {
   mainCounter(INIT_COUNTER);
 }
 
-unsigned int Counter() // get milliseconds since last call of InitCounter()
+unsigned int Counter(void)     // get milliseconds since last call of InitCounter()
 {
   return mainCounter(READ_COUNTER);
 }
@@ -1220,6 +1220,18 @@ char *getStringCopyNStatic(const char *s, int n)
   return s_copy;
 }
 
+char *getStringToUpper(const char *s)
+{
+  char *s_copy = checked_malloc(strlen(s) + 1);
+  char *s_ptr = s_copy;
+
+  while (*s)
+    *s_ptr++ = toupper(*s++);
+  *s_ptr = '\0';
+
+  return s_copy;
+}
+
 char *getStringToLower(const char *s)
 {
   char *s_copy = checked_malloc(strlen(s) + 1);
@@ -1232,6 +1244,55 @@ char *getStringToLower(const char *s)
   return s_copy;
 }
 
+static char *getStringVPrint(char *format, va_list ap)
+{
+  char s[MAX_LINE_LEN];
+
+  vsnprintf(s, MAX_LINE_LEN, format, ap);      // may truncate output string
+
+  return getStringCopy(s);
+}
+
+char *getStringPrint(char *format, ...)
+{
+  va_list ap;
+  char *s;
+
+  va_start(ap, format);
+  s = getStringVPrint(format, ap);
+  va_end(ap);
+
+  return s;
+}
+
+void setStringPrint(char **s, char *format, ...)
+{
+  va_list ap;
+
+  checked_free(*s);
+
+  va_start(ap, format);
+  *s = getStringVPrint(format, ap);
+  va_end(ap);
+}
+
+void appendStringPrint(char **s_old, char *format, ...)
+{
+  va_list ap;
+  char *s_new;
+
+  va_start(ap, format);
+  s_new = getStringVPrint(format, ap);
+  va_end(ap);
+
+  char *s_combined = getStringCat2(*s_old, s_new);
+
+  checked_free(*s_old);
+  checked_free(s_new);
+
+  *s_old = s_combined;
+}
+
 void setString(char **old_value, const char *new_value)
 {
   checked_free(*old_value);
@@ -1239,6 +1300,296 @@ void setString(char **old_value, const char *new_value)
   *old_value = getStringCopy(new_value);
 }
 
+char **getSplitStringArray(const char *s, const char *separators, int max_tokens)
+{
+  const char *s_ptr, *s_last = s;
+  byte separator_table[256] = { FALSE };
+  int num_tokens;
+  char **tokens = NULL;
+
+  if (s == NULL)
+    return NULL;
+
+  if (separators == NULL)
+    return NULL;
+
+  if (max_tokens < 1)
+    max_tokens = INT_MAX;
+
+  // if string is empty, return empty array
+  if (*s == '\0')
+  {
+    tokens = checked_malloc(sizeof(char *));
+    tokens[0] = NULL;
+
+    return tokens;
+  }
+
+  // initialize separator table for all characters in separators string
+  for (s_ptr = separators; *s_ptr != '\0'; s_ptr++)
+    separator_table[*(byte *)s_ptr] = TRUE;
+
+  // count number of tokens in string
+  for (num_tokens = 1, s_ptr = s; *s_ptr != '\0'; s_ptr++)
+    if (separator_table[*(byte *)s_ptr] && num_tokens < max_tokens)
+      num_tokens++;
+
+  // allocate array for determined number of tokens
+  tokens = checked_malloc((num_tokens + 1) * sizeof(char *));
+
+  // copy all but last separated sub-strings to array
+  for (num_tokens = 0, s_ptr = s; *s_ptr != '\0'; s_ptr++)
+  {
+    if (separator_table[*(byte *)s_ptr] && num_tokens + 1 < max_tokens)
+    {
+      tokens[num_tokens++] = getStringCopyN(s_last, s_ptr - s_last);
+      s_last = s_ptr + 1;
+    }
+  }
+
+  // copy last separated sub-string to array
+  tokens[num_tokens++] = getStringCopyN(s_last, s_ptr - s_last);
+
+  // terminate array
+  tokens[num_tokens] = NULL;
+
+  return tokens;
+}
+
+int getStringArrayLength(char **s_array)
+{
+  int num_strings = 0;
+
+  if (s_array == NULL)
+    return 0;
+
+  while (s_array[num_strings] != NULL)
+    num_strings++;
+
+  return num_strings;
+}
+
+void freeStringArray(char **s_array)
+{
+  int i;
+
+  if (s_array == NULL)
+    return;
+
+  for (i = 0; s_array[i] != NULL; i++)
+    checked_free(s_array[i]);
+
+  checked_free(s_array);
+}
+
+char *getEscapedString(const char *s)
+{
+  const unsigned char *s_ptr = (unsigned char *)s;
+  char *s_escaped;
+  char *s_escaped_ptr;
+
+  if (s == NULL)
+    return NULL;
+
+  /* Each source byte needs maximally four target chars (\777) */
+  s_escaped = checked_malloc(strlen(s) * 4 + 1);
+  s_escaped_ptr = s_escaped;
+
+  while (*s_ptr != '\0')
+  {
+    switch (*s_ptr)
+    {
+      case '\b':
+       *s_escaped_ptr++ = '\\';
+       *s_escaped_ptr++ = 'b';
+       break;
+
+      case '\f':
+       *s_escaped_ptr++ = '\\';
+       *s_escaped_ptr++ = 'f';
+       break;
+
+      case '\n':
+       *s_escaped_ptr++ = '\\';
+       *s_escaped_ptr++ = 'n';
+       break;
+
+      case '\r':
+       *s_escaped_ptr++ = '\\';
+       *s_escaped_ptr++ = 'r';
+       break;
+
+      case '\t':
+       *s_escaped_ptr++ = '\\';
+       *s_escaped_ptr++ = 't';
+       break;
+
+      case '\v':
+       *s_escaped_ptr++ = '\\';
+       *s_escaped_ptr++ = 'v';
+       break;
+
+      case '\\':
+       *s_escaped_ptr++ = '\\';
+       *s_escaped_ptr++ = '\\';
+       break;
+
+      case '"':
+       *s_escaped_ptr++ = '\\';
+       *s_escaped_ptr++ = '"';
+       break;
+
+      default:
+       if ((*s_ptr < ' ') || (*s_ptr >= 0177))
+       {
+         *s_escaped_ptr++ = '\\';
+         *s_escaped_ptr++ = '0' + (((*s_ptr) >> 6) & 07);
+         *s_escaped_ptr++ = '0' + (((*s_ptr) >> 3) & 07);
+         *s_escaped_ptr++ = '0' + ( (*s_ptr)       & 07);
+       }
+       else
+       {
+         *s_escaped_ptr++ = *s_ptr;
+       }
+       break;
+    }
+
+    s_ptr++;
+  }
+
+  *s_escaped_ptr = '\0';
+
+  return s_escaped;
+}
+
+char *getUnescapedString(const char *s)
+{
+  const char *s_ptr = s;
+  const char *octal_ptr;
+  char *s_unescaped;
+  char *s_unescaped_ptr;
+
+  if (s == NULL)
+    return NULL;
+
+  s_unescaped = checked_malloc(strlen(s) + 1);
+  s_unescaped_ptr = s_unescaped;
+
+  while (*s_ptr != '\0')
+  {
+    if (*s_ptr == '\\')
+    {
+      s_ptr++;
+
+      switch (*s_ptr)
+      {
+       case '\0':
+         Warn("getUnescapedString: trailing \\");
+         goto out;
+
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+         *s_unescaped_ptr = 0;
+         octal_ptr = s_ptr;
+
+         while (s_ptr < octal_ptr + 3 && *s_ptr >= '0' && *s_ptr <= '7')
+         {
+           *s_unescaped_ptr = (*s_unescaped_ptr * 8) + (*s_ptr - '0');
+           s_ptr++;
+         }
+
+         s_unescaped_ptr++;
+         s_ptr--;
+         break;
+
+       case 'b':
+         *s_unescaped_ptr++ = '\b';
+         break;
+
+       case 'f':
+         *s_unescaped_ptr++ = '\f';
+         break;
+
+       case 'n':
+         *s_unescaped_ptr++ = '\n';
+         break;
+
+       case 'r':
+         *s_unescaped_ptr++ = '\r';
+         break;
+
+       case 't':
+         *s_unescaped_ptr++ = '\t';
+         break;
+
+       case 'v':
+         *s_unescaped_ptr++ = '\v';
+         break;
+
+       default:
+         /* also handles \" and \\ */
+         *s_unescaped_ptr++ = *s_ptr;
+         break;
+      }
+    }
+    else
+    {
+      *s_unescaped_ptr++ = *s_ptr;
+    }
+
+    s_ptr++;
+  }
+
+ out:
+  *s_unescaped_ptr = '\0';
+
+  return s_unescaped;
+}
+
+char *chugString(char *s)
+{
+  if (s == NULL)
+    return NULL;
+
+  char *start;
+
+  for (start = (char *)s; *start && isspace(*start); start++)
+    ;
+
+  memmove(s, start, strlen(start) + 1);
+
+  return s;
+}
+
+char *chompString(char *s)
+{
+  if (s == NULL)
+    return NULL;
+
+  int len = strlen(s);
+
+  while (len--)
+  {
+    if (isspace(s[len]))
+      s[len] = '\0';
+    else
+      break;
+  }
+
+  return s;
+}
+
+char *stripString(char *s)
+{
+  return chugString(chompString(s));
+}
+
 boolean strEqual(const char *s1, const char *s2)
 {
   return (s1 == NULL && s2 == NULL ? TRUE  :
@@ -1353,6 +1704,7 @@ void GetOptions(int argc, char *argv[],
   options.player_name = NULL;
   options.identifier = NULL;
   options.level_nr = NULL;
+  options.drop_file = NULL;
 
   options.display_nr = 0;
 
@@ -1519,6 +1871,15 @@ void GetOptions(int argc, char *argv[],
       if (option_arg == next_option)
        options_left++;
     }
+    else if (strncmp(option, "-drop-file", option_len) == 0)
+    {
+      if (option_arg == NULL)
+       FailWithHelp("option '%s' requires an argument", option_str);
+
+      options.drop_file = getStringCopy(option_arg);
+      if (option_arg == next_option)
+       options_left++;
+    }
     else if (strncmp(option, "-verbose", option_len) == 0)
     {
       options.verbose = TRUE;
@@ -1662,6 +2023,19 @@ void clear_mem(void *ptr, unsigned int size)
 #endif
 }
 
+void *get_memcpy(const void *m, size_t size)
+{
+  void *m_copy;
+
+  if (m == NULL)
+    return NULL;
+
+  m_copy = checked_malloc(size);
+  memcpy(m_copy, m, size);
+
+  return m_copy;
+}
+
 
 // ----------------------------------------------------------------------------
 // various helper functions
@@ -2591,7 +2965,7 @@ boolean get_boolean_from_string(char *s)
   return result;
 }
 
-int get_switch3_from_string(char *s)
+int get_switch_3_state_from_string(char *s)
 {
   char *s_lower = getStringToLower(s);
   int result = FALSE;
@@ -2602,7 +2976,9 @@ int get_switch3_from_string(char *s)
       get_integer_from_string(s) == 1)
     result = TRUE;
   else if (strEqual(s_lower, "auto"))
-    result = AUTO;
+    result = STATE_AUTO;
+  else if (strEqual(s_lower, "ask"))
+    result = STATE_ASK;
 
   free(s_lower);
 
@@ -2734,7 +3110,7 @@ static void dumpList(ListNode *node_first)
 
 #define MAX_BUFFER_SIZE                        4096
 
-File *openFile(char *filename, char *mode)
+File *openFile(const char *filename, const char *mode)
 {
   File *file = checked_calloc(sizeof(File));
 
@@ -2890,7 +3266,7 @@ char *getStringFromFile(File *file, char *line, int size)
   return fgets(line, size, file->file);
 }
 
-int copyFile(char *filename_from, char *filename_to)
+int copyFile(const char *filename_from, const char *filename_to)
 {
   File *file_from, *file_to;
 
@@ -2920,7 +3296,7 @@ int copyFile(char *filename_from, char *filename_to)
   return 0;
 }
 
-boolean touchFile(char *filename)
+boolean touchFile(const char *filename)
 {
   FILE *file;