5 * Copyright (C) 1998-2000 Mark Probst
6 * Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
30 #include "../app/globals.h"
31 #include "../app/setup.h"
32 #include "../utils/lispreader.h"
34 using namespace SuperTux;
36 #define TOKEN_ERROR -1
38 #define TOKEN_OPEN_PAREN 1
39 #define TOKEN_CLOSE_PAREN 2
40 #define TOKEN_SYMBOL 3
41 #define TOKEN_STRING 4
42 #define TOKEN_INTEGER 5
44 #define TOKEN_PATTERN_OPEN_PAREN 7
47 #define TOKEN_FALSE 10
50 #define MAX_TOKEN_LENGTH 4096
52 static char token_string[MAX_TOKEN_LENGTH + 1] = "";
53 static int token_length = 0;
55 static lisp_object_t end_marker = { LISP_TYPE_EOF, {{0, 0}} };
56 static lisp_object_t error_object = { LISP_TYPE_PARSE_ERROR , {{0,0}} };
57 static lisp_object_t close_paren_marker = { LISP_TYPE_PARSE_ERROR , {{0,0}} };
58 static lisp_object_t dot_marker = { LISP_TYPE_PARSE_ERROR , {{0,0}} };
63 token_string[0] = '\0';
68 _token_append (char c)
70 if (token_length >= MAX_TOKEN_LENGTH)
71 throw LispReaderException("_token_append()", __FILE__, __LINE__);
73 token_string[token_length++] = c;
74 token_string[token_length] = '\0';
78 _next_char (lisp_stream_t *stream)
82 case LISP_STREAM_FILE :
83 return getc(stream->v.file);
85 case LISP_STREAM_STRING :
87 char c = stream->v.string.buf[stream->v.string.pos];
92 ++stream->v.string.pos;
98 return stream->v.any.next_char(stream->v.any.data);
101 throw LispReaderException("_next_char()", __FILE__, __LINE__);
106 _unget_char (char c, lisp_stream_t *stream)
108 switch (stream->type)
110 case LISP_STREAM_FILE :
111 ungetc(c, stream->v.file);
114 case LISP_STREAM_STRING :
115 --stream->v.string.pos;
118 case LISP_STREAM_ANY:
119 stream->v.any.unget_char(c, stream->v.any.data);
123 throw LispReaderException("_unget_char()", __FILE__, __LINE__);
128 _scan (lisp_stream_t *stream)
130 static char *delims = "\"();";
138 c = _next_char(stream);
141 else if (c == ';') /* comment start */
144 c = _next_char(stream);
156 return TOKEN_OPEN_PAREN;
159 return TOKEN_CLOSE_PAREN;
164 c = _next_char(stream);
171 c = _next_char(stream);
193 c = _next_char(stream);
206 c = _next_char(stream);
211 return TOKEN_PATTERN_OPEN_PAREN;
218 if (isdigit(c) || c == '-')
220 int have_nondigits = 0;
222 int have_floating_point = 0;
229 have_floating_point++;
232 c = _next_char(stream);
234 if (c != EOF && !isdigit(c) && !isspace(c) && c != '.' && !strchr(delims, c))
237 while (c != EOF && !isspace(c) && !strchr(delims, c));
240 _unget_char(c, stream);
242 if (have_nondigits || !have_digits || have_floating_point > 1)
244 else if (have_floating_point == 1)
247 return TOKEN_INTEGER;
253 c = _next_char(stream);
254 if (c != EOF && !isspace(c) && !strchr(delims, c))
258 _unget_char(c, stream);
265 c = _next_char(stream);
267 while (c != EOF && !isspace(c) && !strchr(delims, c));
269 _unget_char(c, stream);
275 throw LispReaderException("_scan()", __FILE__, __LINE__);
279 static lisp_object_t*
280 lisp_object_alloc (int type)
282 lisp_object_t *obj = (lisp_object_t*)malloc(sizeof(lisp_object_t));
290 SuperTux::lisp_stream_init_file (lisp_stream_t *stream, FILE *file)
292 stream->type = LISP_STREAM_FILE;
293 stream->v.file = file;
299 SuperTux::lisp_stream_init_string (lisp_stream_t *stream, char *buf)
301 stream->type = LISP_STREAM_STRING;
302 stream->v.string.buf = buf;
303 stream->v.string.pos = 0;
309 SuperTux::lisp_stream_init_any (lisp_stream_t *stream, void *data,
310 int (*next_char) (void *data),
311 void (*unget_char) (char c, void *data))
313 if (next_char == 0 || unget_char == 0)
314 throw LispReaderException("lisp_stream_init_any()", __FILE__, __LINE__);
316 stream->type = LISP_STREAM_ANY;
317 stream->v.any.data = data;
318 stream->v.any.next_char= next_char;
319 stream->v.any.unget_char = unget_char;
325 SuperTux::lisp_make_integer (int value)
327 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_INTEGER);
329 obj->v.integer = value;
335 SuperTux::lisp_make_real (float value)
337 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_REAL);
345 SuperTux::lisp_make_symbol (const char *value)
347 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_SYMBOL);
349 obj->v.string = strdup(value);
355 SuperTux::lisp_make_string (const char *value)
357 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_STRING);
359 obj->v.string = strdup(value);
365 SuperTux::lisp_make_cons (lisp_object_t *car, lisp_object_t *cdr)
367 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_CONS);
369 obj->v.cons.car = car;
370 obj->v.cons.cdr = cdr;
376 SuperTux::lisp_make_boolean (int value)
378 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_BOOLEAN);
380 obj->v.integer = value ? 1 : 0;
385 static lisp_object_t*
386 lisp_make_pattern_cons (lisp_object_t *car, lisp_object_t *cdr)
388 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_CONS);
390 obj->v.cons.car = car;
391 obj->v.cons.cdr = cdr;
396 static lisp_object_t*
397 lisp_make_pattern_var (int type, int index, lisp_object_t *sub)
399 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_VAR);
401 obj->v.pattern.type = type;
402 obj->v.pattern.index = index;
403 obj->v.pattern.sub = sub;
409 SuperTux::lisp_read (lisp_stream_t *in)
411 int token = _scan(in);
412 lisp_object_t *obj = lisp_nil();
414 if (token == TOKEN_EOF)
420 return &error_object;
425 case TOKEN_OPEN_PAREN :
426 case TOKEN_PATTERN_OPEN_PAREN :
428 lisp_object_t *last = lisp_nil(), *car;
433 if (car == &error_object || car == &end_marker)
436 return &error_object;
438 else if (car == &dot_marker)
440 if (lisp_nil_p(last))
443 return &error_object;
447 if (car == &error_object || car == &end_marker)
454 last->v.cons.cdr = car;
456 if (_scan(in) != TOKEN_CLOSE_PAREN)
459 return &error_object;
462 car = &close_paren_marker;
465 else if (car != &close_paren_marker)
467 if (lisp_nil_p(last))
468 obj = last = (token == TOKEN_OPEN_PAREN ? lisp_make_cons(car, lisp_nil()) : lisp_make_pattern_cons(car, lisp_nil()));
470 last = last->v.cons.cdr = lisp_make_cons(car, lisp_nil());
473 while (car != &close_paren_marker);
477 case TOKEN_CLOSE_PAREN :
478 return &close_paren_marker;
481 return lisp_make_symbol(token_string);
484 return lisp_make_string(token_string);
487 return lisp_make_integer(atoi(token_string));
490 return lisp_make_real((float)atof(token_string));
496 return lisp_make_boolean(1);
499 return lisp_make_boolean(0);
502 throw LispReaderException("lisp_read()", __FILE__, __LINE__);
503 return &error_object;
507 SuperTux::lisp_free (lisp_object_t *obj)
512 /** We have to use this iterative code, because the recursive function
513 * produces a stack overflow and crashs on OSX 10.2
515 std::vector<lisp_object_t*> objs;
518 while(!objs.empty()) {
519 lisp_object_t* obj = objs.back();
523 case LISP_TYPE_INTERNAL :
524 case LISP_TYPE_PARSE_ERROR :
528 case LISP_TYPE_SYMBOL :
529 case LISP_TYPE_STRING :
533 case LISP_TYPE_CONS :
534 case LISP_TYPE_PATTERN_CONS :
536 objs.push_back(obj->v.cons.car);
538 objs.push_back(obj->v.cons.cdr);
541 case LISP_TYPE_PATTERN_VAR :
542 if(obj->v.pattern.sub)
543 objs.push_back(obj->v.pattern.sub);
552 SuperTux::lisp_read_from_string (const char *buf)
554 lisp_stream_t stream;
556 lisp_stream_init_string(&stream, (char*)buf);
557 return lisp_read(&stream);
561 _compile_pattern (lisp_object_t **obj, int *index)
566 switch (lisp_type(*obj))
568 case LISP_TYPE_PATTERN_CONS :
577 { "any", LISP_PATTERN_ANY },
578 { "symbol", LISP_PATTERN_SYMBOL },
579 { "string", LISP_PATTERN_STRING },
580 { "integer", LISP_PATTERN_INTEGER },
581 { "real", LISP_PATTERN_REAL },
582 { "boolean", LISP_PATTERN_BOOLEAN },
583 { "list", LISP_PATTERN_LIST },
584 { "or", LISP_PATTERN_OR },
590 lisp_object_t *pattern;
593 if (lisp_type(lisp_car(*obj)) != LISP_TYPE_SYMBOL)
596 type_name = lisp_symbol(lisp_car(*obj));
597 for (i = 0; types[i].name != 0; ++i)
599 if (strcmp(types[i].name, type_name) == 0)
601 type = types[i].type;
606 if (types[i].name == 0)
609 if (type != LISP_PATTERN_OR && lisp_cdr(*obj) != 0)
612 pattern = lisp_make_pattern_var(type, (*index)++, lisp_nil());
614 if (type == LISP_PATTERN_OR)
616 lisp_object_t *cdr = lisp_cdr(*obj);
618 if (!_compile_pattern(&cdr, index))
624 pattern->v.pattern.sub = cdr;
626 (*obj)->v.cons.cdr = lisp_nil();
635 case LISP_TYPE_CONS :
636 if (!_compile_pattern(&(*obj)->v.cons.car, index))
638 if (!_compile_pattern(&(*obj)->v.cons.cdr, index))
647 SuperTux::lisp_compile_pattern (lisp_object_t **obj, int *num_subs)
652 result = _compile_pattern(obj, &index);
654 if (result && num_subs != 0)
660 static int _match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars);
663 _match_pattern_var (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars)
665 if (lisp_type(pattern) != LISP_TYPE_PATTERN_VAR)
666 throw LispReaderException("_match_pattern_var", __FILE__, __LINE__);
668 switch (pattern->v.pattern.type)
670 case LISP_PATTERN_ANY :
673 case LISP_PATTERN_SYMBOL :
674 if (obj == 0 || lisp_type(obj) != LISP_TYPE_SYMBOL)
678 case LISP_PATTERN_STRING :
679 if (obj == 0 || lisp_type(obj) != LISP_TYPE_STRING)
683 case LISP_PATTERN_INTEGER :
684 if (obj == 0 || lisp_type(obj) != LISP_TYPE_INTEGER)
688 case LISP_PATTERN_REAL :
689 if (obj == 0 || lisp_type(obj) != LISP_TYPE_REAL)
693 case LISP_PATTERN_BOOLEAN :
694 if (obj == 0 || lisp_type(obj) != LISP_TYPE_BOOLEAN)
698 case LISP_PATTERN_LIST :
699 if (obj == 0 || lisp_type(obj) != LISP_TYPE_CONS)
703 case LISP_PATTERN_OR :
708 for (sub = pattern->v.pattern.sub; sub != 0; sub = lisp_cdr(sub))
710 if (lisp_type(sub) != LISP_TYPE_CONS)
711 throw LispReaderException("_match_pattern_var()", __FILE__, __LINE__);
713 if (_match_pattern(lisp_car(sub), obj, vars))
723 throw LispReaderException("_match_pattern_var()", __FILE__, __LINE__);
727 vars[pattern->v.pattern.index] = obj;
733 _match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars)
741 if (lisp_type(pattern) == LISP_TYPE_PATTERN_VAR)
742 return _match_pattern_var(pattern, obj, vars);
744 if (lisp_type(pattern) != lisp_type(obj))
747 switch (lisp_type(pattern))
749 case LISP_TYPE_SYMBOL :
750 return strcmp(lisp_symbol(pattern), lisp_symbol(obj)) == 0;
752 case LISP_TYPE_STRING :
753 return strcmp(lisp_string(pattern), lisp_string(obj)) == 0;
755 case LISP_TYPE_INTEGER :
756 return lisp_integer(pattern) == lisp_integer(obj);
758 case LISP_TYPE_REAL :
759 return lisp_real(pattern) == lisp_real(obj);
761 case LISP_TYPE_CONS :
763 int result1, result2;
765 result1 = _match_pattern(lisp_car(pattern), lisp_car(obj), vars);
766 result2 = _match_pattern(lisp_cdr(pattern), lisp_cdr(obj), vars);
768 return result1 && result2;
773 throw LispReaderException("_match_pattern()", __FILE__, __LINE__);
780 SuperTux::lisp_match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars, int num_subs)
785 for (i = 0; i < num_subs; ++i)
786 vars[i] = &error_object;
788 return _match_pattern(pattern, obj, vars);
792 SuperTux::lisp_match_string (const char *pattern_string, lisp_object_t *obj, lisp_object_t **vars)
794 lisp_object_t *pattern;
798 pattern = lisp_read_from_string(pattern_string);
800 if (pattern != 0 && (lisp_type(pattern) == LISP_TYPE_EOF
801 || lisp_type(pattern) == LISP_TYPE_PARSE_ERROR))
804 if (!lisp_compile_pattern(&pattern, &num_subs))
810 result = lisp_match_pattern(pattern, obj, vars, num_subs);
818 SuperTux::lisp_type (lisp_object_t *obj)
821 return LISP_TYPE_NIL;
826 SuperTux::lisp_integer (lisp_object_t *obj)
828 if (obj->type != LISP_TYPE_INTEGER)
829 throw LispReaderException("lisp_integer()", __FILE__, __LINE__);
831 return obj->v.integer;
835 SuperTux::lisp_symbol (lisp_object_t *obj)
837 if (obj->type != LISP_TYPE_SYMBOL)
838 throw LispReaderException("lisp_symbol()", __FILE__, __LINE__);
840 return obj->v.string;
844 SuperTux::lisp_string (lisp_object_t *obj)
846 if (obj->type != LISP_TYPE_STRING)
847 throw LispReaderException("lisp_string()", __FILE__, __LINE__);
849 return obj->v.string;
853 SuperTux::lisp_boolean (lisp_object_t *obj)
855 if (obj->type != LISP_TYPE_BOOLEAN)
856 throw LispReaderException("lisp_boolean()", __FILE__, __LINE__);
858 return obj->v.integer;
862 SuperTux::lisp_real (lisp_object_t *obj)
864 if (obj->type != LISP_TYPE_REAL && obj->type != LISP_TYPE_INTEGER)
865 throw LispReaderException("lisp_real()", __FILE__, __LINE__);
867 if (obj->type == LISP_TYPE_INTEGER)
868 return obj->v.integer;
873 SuperTux::lisp_car (lisp_object_t *obj)
875 if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
876 throw LispReaderException("lisp_car()", __FILE__, __LINE__);
878 return obj->v.cons.car;
882 SuperTux::lisp_cdr (lisp_object_t *obj)
884 if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
885 throw LispReaderException("lisp_cdr()", __FILE__, __LINE__);
887 return obj->v.cons.cdr;
891 SuperTux::lisp_cxr (lisp_object_t *obj, const char *x)
895 for (i = strlen(x) - 1; i >= 0; --i)
898 else if (x[i] == 'd')
901 throw LispReaderException("lisp_cxr()", __FILE__, __LINE__);
907 SuperTux::lisp_list_length (lisp_object_t *obj)
913 if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
914 throw LispReaderException("lisp_list_length()", __FILE__, __LINE__);
917 obj = obj->v.cons.cdr;
924 SuperTux::lisp_list_nth_cdr (lisp_object_t *obj, int index)
929 throw LispReaderException("lisp_list_nth_cdr()", __FILE__, __LINE__);
930 if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
931 throw LispReaderException("lisp_list_nth_cdr()", __FILE__, __LINE__);
934 obj = obj->v.cons.cdr;
941 SuperTux::lisp_list_nth (lisp_object_t *obj, int index)
943 obj = lisp_list_nth_cdr(obj, index);
946 throw LispReaderException("lisp_list_nth()", __FILE__, __LINE__);
948 return obj->v.cons.car;
952 SuperTux::lisp_dump (lisp_object_t *obj, FILE *out)
960 switch (lisp_type(obj))
963 fputs("#<eof>", out);
966 case LISP_TYPE_PARSE_ERROR :
967 fputs("#<error>", out);
970 case LISP_TYPE_INTEGER :
971 fprintf(out, "%d", lisp_integer(obj));
974 case LISP_TYPE_REAL :
975 fprintf(out, "%f", lisp_real(obj));
978 case LISP_TYPE_SYMBOL :
979 fputs(lisp_symbol(obj), out);
982 case LISP_TYPE_STRING :
987 for (p = lisp_string(obj); *p != 0; ++p)
989 if (*p == '"' || *p == '\\')
997 case LISP_TYPE_CONS :
998 case LISP_TYPE_PATTERN_CONS :
999 fputs(lisp_type(obj) == LISP_TYPE_CONS ? "(" : "#?(", out);
1002 lisp_dump(lisp_car(obj), out);
1003 obj = lisp_cdr(obj);
1006 if (lisp_type(obj) != LISP_TYPE_CONS
1007 && lisp_type(obj) != LISP_TYPE_PATTERN_CONS)
1010 lisp_dump(obj, out);
1020 case LISP_TYPE_BOOLEAN :
1021 if (lisp_boolean(obj))
1028 throw LispReaderException("lisp_dump()", __FILE__, __LINE__);
1032 using namespace std;
1034 LispReader::LispReader (lisp_object_t* l)
1039 LispReader::~LispReader()
1046 LispReader::load(const std::string& filename, const std::string& toplevellist)
1048 lisp_object_t* obj = lisp_read_from_file(filename);
1050 if(obj->type == LISP_TYPE_EOF || obj->type == LISP_TYPE_PARSE_ERROR) {
1052 throw LispReaderException("LispReader::load", __FILE__, __LINE__);
1055 if(toplevellist != lisp_symbol(lisp_car(obj))) {
1057 throw LispReaderException("LispReader::load wrong toplevel symbol",
1058 __FILE__, __LINE__);
1061 LispReader* reader = new LispReader(lisp_cdr(obj));
1062 reader->owner = obj;
1068 LispReader::search_for(const char* name)
1070 //std::cout << "LispReader::search_for(" << name << ")" << std::endl;
1071 lisp_object_t* cursor = lst;
1073 while(!lisp_nil_p(cursor))
1075 lisp_object_t* cur = lisp_car(cursor);
1077 if (!lisp_cons_p(cur) || !lisp_symbol_p (lisp_car(cur)))
1079 lisp_dump(cur, stdout);
1080 //throw ConstruoError (std::string("LispReader: Read error in search_for ") + name);
1081 printf("LispReader: Read error in search\n");
1085 if (strcmp(lisp_symbol(lisp_car(cur)), name) == 0)
1087 return lisp_cdr(cur);
1091 cursor = lisp_cdr (cursor);
1097 LispReader::read_int (const char* name, int& i)
1099 lisp_object_t* obj = search_for (name);
1103 if (!lisp_integer_p(lisp_car(obj)))
1106 i = lisp_integer(lisp_car(obj));
1111 LispReader::read_lisp(const char* name, lisp_object_t*& b)
1113 lisp_object_t* obj = search_for (name);
1122 LispReader::read_lisp(const char* name)
1124 return search_for(name);
1128 LispReader::read_float (const char* name, float& f)
1130 lisp_object_t* obj = search_for (name);
1134 if (!lisp_real_p(lisp_car(obj)) && !lisp_integer_p(lisp_car(obj)))
1135 Termination::abort("LispReader expected type real at token: ", name);
1137 f = lisp_real(lisp_car(obj));
1142 LispReader::read_string_vector (const char* name, std::vector<std::string>& vec)
1144 lisp_object_t* obj = search_for (name);
1149 while(!lisp_nil_p(obj))
1151 if (!lisp_string_p(lisp_car(obj)))
1152 Termination::abort("LispReader expected type string at token: ", name);
1153 vec.push_back(lisp_string(lisp_car(obj)));
1154 obj = lisp_cdr(obj);
1160 LispReader::read_int_vector (const char* name, std::vector<int>& vec)
1162 lisp_object_t* obj = search_for (name);
1167 while(!lisp_nil_p(obj))
1169 if (!lisp_integer_p(lisp_car(obj)))
1170 Termination::abort("LispReader expected type integer at token: ", name);
1171 vec.push_back(lisp_integer(lisp_car(obj)));
1172 obj = lisp_cdr(obj);
1178 LispReader::read_int_vector (const char* name, std::vector<unsigned int>& vec)
1180 lisp_object_t* obj = search_for (name);
1185 while(!lisp_nil_p(obj))
1187 if (!lisp_integer_p(lisp_car(obj)))
1188 Termination::abort("LispReader expected type integer at token: ", name);
1189 vec.push_back(lisp_integer(lisp_car(obj)));
1190 obj = lisp_cdr(obj);
1196 LispReader::read_char_vector (const char* name, std::vector<char>& vec)
1198 lisp_object_t* obj = search_for (name);
1203 while(!lisp_nil_p(obj))
1205 vec.push_back(*lisp_string(lisp_car(obj)));
1206 obj = lisp_cdr(obj);
1212 LispReader::read_string (const char* name, std::string& str, bool translatable)
1217 /* Internationalization support: check for the suffix: str + "-" + $LANG variable.
1218 If not found, use the regular string.
1219 So, translating a string in a Lisp file would result in something like:
1220 (text "Hello World!")
1221 (text-fr "Bonjour Monde!")
1222 being fr the value of LANG (echo $LANG) for the language we want to translate to */
1224 char* lang = getenv("LANG");
1226 char str_[1024]; // check, for instance, for (title-fr_FR "Bonjour")
1227 sprintf(str_, "%s-%s", name, lang);
1229 obj = search_for (str_);
1231 if(!obj) // check, for instance, for (title-fr "Bonjour")
1233 if(lang != NULL && strlen(lang) >= 2)
1236 strncpy(lang_, lang, 2);
1238 sprintf(str_, "%s-%s", name, lang_);
1240 obj = search_for (str_);
1246 if(!obj) // check, for instance, for (title "Hello")
1247 obj = search_for (name);
1250 obj = search_for (name);
1255 if (!lisp_string_p(lisp_car(obj)))
1256 Termination::abort("LispReader expected type string at token: ", name);
1257 str = lisp_string(lisp_car(obj));
1262 LispReader::read_bool (const char* name, bool& b)
1264 lisp_object_t* obj = search_for (name);
1268 if (!lisp_boolean_p(lisp_car(obj)))
1269 Termination::abort("LispReader expected type bool at token: ", name);
1270 b = lisp_boolean(lisp_car(obj));
1275 LispReader::get_lisp()
1280 lisp_object_t* SuperTux::lisp_read_from_file(const std::string& filename)
1282 FILE* in = fopen(filename.c_str(), "r");
1287 lisp_stream_t stream;
1288 lisp_stream_init_file(&stream, in);
1289 lisp_object_t* obj = lisp_read(&stream);