Damn strlen() crashes when NULL is passed. Fixed.
[supertux.git] / src / lispreader.cpp
index 51ff97c..e9a150d 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-
 #include <iostream>
+#include <vector>
 #include <string>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cctype>
+#include <cstdlib>
+#include <cstring>
+
 #include "setup.h"
 #include "lispreader.h"
 
@@ -43,7 +44,7 @@
 #define TOKEN_FALSE                   10
 
 
-#define MAX_TOKEN_LENGTH           1024
+#define MAX_TOKEN_LENGTH           4096
 
 static char token_string[MAX_TOKEN_LENGTH + 1] = "";
 static int token_length = 0;
@@ -505,30 +506,43 @@ lisp_free (lisp_object_t *obj)
   if (obj == 0)
     return;
 
-  switch (obj->type)
-    {
-    case LISP_TYPE_INTERNAL :
-    case LISP_TYPE_PARSE_ERROR :
-    case LISP_TYPE_EOF :
-      return;
-
-    case LISP_TYPE_SYMBOL :
-    case LISP_TYPE_STRING :
-      free(obj->v.string);
-      break;
-
-    case LISP_TYPE_CONS :
-    case LISP_TYPE_PATTERN_CONS :
-      lisp_free(obj->v.cons.car);
-      lisp_free(obj->v.cons.cdr);
-      break;
-
-    case LISP_TYPE_PATTERN_VAR :
-      lisp_free(obj->v.pattern.sub);
-      break;
+  /** We have to use this iterative code, because the recursive function
+   * produces a stack overflow and crashs on OSX 10.2
+   */
+  std::vector<lisp_object_t*> objs;
+  objs.push_back(obj);
+
+  while(!objs.empty()) {
+    lisp_object_t* obj = objs.back();
+    objs.pop_back();
+        
+    switch (obj->type) {
+      case LISP_TYPE_INTERNAL :
+      case LISP_TYPE_PARSE_ERROR :
+      case LISP_TYPE_EOF :
+        return;
+
+      case LISP_TYPE_SYMBOL :
+      case LISP_TYPE_STRING :
+        free(obj->v.string);
+        break;
+
+      case LISP_TYPE_CONS :
+      case LISP_TYPE_PATTERN_CONS :
+        if(obj->v.cons.car)
+          objs.push_back(obj->v.cons.car);
+        if(obj->v.cons.cdr)
+          objs.push_back(obj->v.cons.cdr);
+        break;
+
+      case LISP_TYPE_PATTERN_VAR :
+        if(obj->v.pattern.sub)
+          objs.push_back(obj->v.pattern.sub);
+        break;
     }
 
-  free(obj);
+    free(obj);
+  }
 }
 
 lisp_object_t*
@@ -1101,14 +1115,10 @@ LispReader::read_lisp(const char* name, lisp_object_t*& b)
   return true;
 }
 
-LispReader*
+lisp_object_t*
 LispReader::read_lisp(const char* name)
 {
-  lisp_object_t* obj = search_for(name);
-  if(!obj)
-    return 0;
-
-  return new LispReader(obj);
+  return search_for(name);
 }
 
 bool
@@ -1196,9 +1206,46 @@ LispReader::read_char_vector (const char* name, std::vector<char>& vec)
 }
 
 bool
-LispReader::read_string (const char* name, std::string& str)
+LispReader::read_string (const char* name, std::string& str, bool translatable)
 {
-  lisp_object_t* obj = search_for (name);
+  lisp_object_t* obj;
+  if(translatable)
+    {
+  /* Internationalization support: check for the suffix: str + "-" + $LANG variable.
+     If not found, use the regular string.
+     So, translating a string in a Lisp file would result in something like:
+     (text "Hello World!")
+     (text-fr "Bonjour Monde!")
+     being fr the value of LANG (echo $LANG) for the language we want to translate to */
+
+    char* lang = getenv("tt");
+
+    char str_[1024];  // check, for instance, for (title-fr_FR "Bonjour")
+    sprintf(str_, "%s-%s", name, lang);
+
+    obj = search_for (str_);
+
+    if(!obj)  // check, for instance, for (title-fr "Bonjour")
+      {
+      if(lang != NULL && strlen(lang) >= 2)
+        {
+        char lang_[3];
+        strncpy(lang_, lang, 2);
+        lang_[2] = '\0';
+        sprintf(str_, "%s-%s", name, lang_);
+
+        obj = search_for (str_);
+        }
+      else
+        obj = 0;
+      }
+
+    if(!obj)  // check, for instance, for (title "Hello")
+      obj = search_for (name);
+    }
+  else
+    obj = search_for (name);
+
   if (!obj)
     return false;