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 "lispreader.h"
32 #define TOKEN_ERROR -1
34 #define TOKEN_OPEN_PAREN 1
35 #define TOKEN_CLOSE_PAREN 2
36 #define TOKEN_SYMBOL 3
37 #define TOKEN_STRING 4
38 #define TOKEN_INTEGER 5
40 #define TOKEN_PATTERN_OPEN_PAREN 7
43 #define TOKEN_FALSE 10
46 #define MAX_TOKEN_LENGTH 1024
48 static char token_string[MAX_TOKEN_LENGTH + 1] = "";
49 static int token_length = 0;
51 static lisp_object_t end_marker = { LISP_TYPE_EOF, {{0, 0}} };
52 static lisp_object_t error_object = { LISP_TYPE_PARSE_ERROR , {{0,0}} };
53 static lisp_object_t close_paren_marker = { LISP_TYPE_PARSE_ERROR , {{0,0}} };
54 static lisp_object_t dot_marker = { LISP_TYPE_PARSE_ERROR , {{0,0}} };
59 token_string[0] = '\0';
64 _token_append (char c)
66 if (token_length >= MAX_TOKEN_LENGTH)
67 throw LispReaderException("_token_append()", __FILE__, __LINE__);
69 token_string[token_length++] = c;
70 token_string[token_length] = '\0';
74 _next_char (lisp_stream_t *stream)
78 case LISP_STREAM_FILE :
79 return getc(stream->v.file);
81 case LISP_STREAM_STRING :
83 char c = stream->v.string.buf[stream->v.string.pos];
88 ++stream->v.string.pos;
94 return stream->v.any.next_char(stream->v.any.data);
97 throw LispReaderException("_next_char()", __FILE__, __LINE__);
102 _unget_char (char c, lisp_stream_t *stream)
104 switch (stream->type)
106 case LISP_STREAM_FILE :
107 ungetc(c, stream->v.file);
110 case LISP_STREAM_STRING :
111 --stream->v.string.pos;
114 case LISP_STREAM_ANY:
115 stream->v.any.unget_char(c, stream->v.any.data);
119 throw LispReaderException("_unget_char()", __FILE__, __LINE__);
124 _scan (lisp_stream_t *stream)
126 static char *delims = "\"();";
134 c = _next_char(stream);
137 else if (c == ';') /* comment start */
140 c = _next_char(stream);
152 return TOKEN_OPEN_PAREN;
155 return TOKEN_CLOSE_PAREN;
160 c = _next_char(stream);
167 c = _next_char(stream);
189 c = _next_char(stream);
202 c = _next_char(stream);
207 return TOKEN_PATTERN_OPEN_PAREN;
214 if (isdigit(c) || c == '-')
216 int have_nondigits = 0;
218 int have_floating_point = 0;
225 have_floating_point++;
228 c = _next_char(stream);
230 if (c != EOF && !isdigit(c) && !isspace(c) && c != '.' && !strchr(delims, c))
233 while (c != EOF && !isspace(c) && !strchr(delims, c));
236 _unget_char(c, stream);
238 if (have_nondigits || !have_digits || have_floating_point > 1)
240 else if (have_floating_point == 1)
243 return TOKEN_INTEGER;
249 c = _next_char(stream);
250 if (c != EOF && !isspace(c) && !strchr(delims, c))
254 _unget_char(c, stream);
261 c = _next_char(stream);
263 while (c != EOF && !isspace(c) && !strchr(delims, c));
265 _unget_char(c, stream);
271 throw LispReaderException("_scan()", __FILE__, __LINE__);
275 static lisp_object_t*
276 lisp_object_alloc (int type)
278 lisp_object_t *obj = (lisp_object_t*)malloc(sizeof(lisp_object_t));
286 lisp_stream_init_file (lisp_stream_t *stream, FILE *file)
288 stream->type = LISP_STREAM_FILE;
289 stream->v.file = file;
295 lisp_stream_init_string (lisp_stream_t *stream, char *buf)
297 stream->type = LISP_STREAM_STRING;
298 stream->v.string.buf = buf;
299 stream->v.string.pos = 0;
305 lisp_stream_init_any (lisp_stream_t *stream, void *data,
306 int (*next_char) (void *data),
307 void (*unget_char) (char c, void *data))
309 if (next_char == 0 || unget_char == 0)
310 throw LispReaderException("lisp_stream_init_any()", __FILE__, __LINE__);
312 stream->type = LISP_STREAM_ANY;
313 stream->v.any.data = data;
314 stream->v.any.next_char= next_char;
315 stream->v.any.unget_char = unget_char;
321 lisp_make_integer (int value)
323 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_INTEGER);
325 obj->v.integer = value;
331 lisp_make_real (float value)
333 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_REAL);
341 lisp_make_symbol (const char *value)
343 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_SYMBOL);
345 obj->v.string = strdup(value);
351 lisp_make_string (const char *value)
353 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_STRING);
355 obj->v.string = strdup(value);
361 lisp_make_cons (lisp_object_t *car, lisp_object_t *cdr)
363 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_CONS);
365 obj->v.cons.car = car;
366 obj->v.cons.cdr = cdr;
372 lisp_make_boolean (int value)
374 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_BOOLEAN);
376 obj->v.integer = value ? 1 : 0;
381 static lisp_object_t*
382 lisp_make_pattern_cons (lisp_object_t *car, lisp_object_t *cdr)
384 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_CONS);
386 obj->v.cons.car = car;
387 obj->v.cons.cdr = cdr;
392 static lisp_object_t*
393 lisp_make_pattern_var (int type, int index, lisp_object_t *sub)
395 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_VAR);
397 obj->v.pattern.type = type;
398 obj->v.pattern.index = index;
399 obj->v.pattern.sub = sub;
405 lisp_read (lisp_stream_t *in)
407 int token = _scan(in);
408 lisp_object_t *obj = lisp_nil();
410 if (token == TOKEN_EOF)
416 return &error_object;
421 case TOKEN_OPEN_PAREN :
422 case TOKEN_PATTERN_OPEN_PAREN :
424 lisp_object_t *last = lisp_nil(), *car;
429 if (car == &error_object || car == &end_marker)
432 return &error_object;
434 else if (car == &dot_marker)
436 if (lisp_nil_p(last))
439 return &error_object;
443 if (car == &error_object || car == &end_marker)
450 last->v.cons.cdr = car;
452 if (_scan(in) != TOKEN_CLOSE_PAREN)
455 return &error_object;
458 car = &close_paren_marker;
461 else if (car != &close_paren_marker)
463 if (lisp_nil_p(last))
464 obj = last = (token == TOKEN_OPEN_PAREN ? lisp_make_cons(car, lisp_nil()) : lisp_make_pattern_cons(car, lisp_nil()));
466 last = last->v.cons.cdr = lisp_make_cons(car, lisp_nil());
469 while (car != &close_paren_marker);
473 case TOKEN_CLOSE_PAREN :
474 return &close_paren_marker;
477 return lisp_make_symbol(token_string);
480 return lisp_make_string(token_string);
483 return lisp_make_integer(atoi(token_string));
486 return lisp_make_real((float)atof(token_string));
492 return lisp_make_boolean(1);
495 return lisp_make_boolean(0);
498 throw LispReaderException("lisp_read()", __FILE__, __LINE__);
499 return &error_object;
503 lisp_free (lisp_object_t *obj)
510 case LISP_TYPE_INTERNAL :
511 case LISP_TYPE_PARSE_ERROR :
515 case LISP_TYPE_SYMBOL :
516 case LISP_TYPE_STRING :
520 case LISP_TYPE_CONS :
521 case LISP_TYPE_PATTERN_CONS :
522 lisp_free(obj->v.cons.car);
523 lisp_free(obj->v.cons.cdr);
526 case LISP_TYPE_PATTERN_VAR :
527 lisp_free(obj->v.pattern.sub);
535 lisp_read_from_string (const char *buf)
537 lisp_stream_t stream;
539 lisp_stream_init_string(&stream, (char*)buf);
540 return lisp_read(&stream);
544 _compile_pattern (lisp_object_t **obj, int *index)
549 switch (lisp_type(*obj))
551 case LISP_TYPE_PATTERN_CONS :
560 { "any", LISP_PATTERN_ANY },
561 { "symbol", LISP_PATTERN_SYMBOL },
562 { "string", LISP_PATTERN_STRING },
563 { "integer", LISP_PATTERN_INTEGER },
564 { "real", LISP_PATTERN_REAL },
565 { "boolean", LISP_PATTERN_BOOLEAN },
566 { "list", LISP_PATTERN_LIST },
567 { "or", LISP_PATTERN_OR },
573 lisp_object_t *pattern;
576 if (lisp_type(lisp_car(*obj)) != LISP_TYPE_SYMBOL)
579 type_name = lisp_symbol(lisp_car(*obj));
580 for (i = 0; types[i].name != 0; ++i)
582 if (strcmp(types[i].name, type_name) == 0)
584 type = types[i].type;
589 if (types[i].name == 0)
592 if (type != LISP_PATTERN_OR && lisp_cdr(*obj) != 0)
595 pattern = lisp_make_pattern_var(type, (*index)++, lisp_nil());
597 if (type == LISP_PATTERN_OR)
599 lisp_object_t *cdr = lisp_cdr(*obj);
601 if (!_compile_pattern(&cdr, index))
607 pattern->v.pattern.sub = cdr;
609 (*obj)->v.cons.cdr = lisp_nil();
618 case LISP_TYPE_CONS :
619 if (!_compile_pattern(&(*obj)->v.cons.car, index))
621 if (!_compile_pattern(&(*obj)->v.cons.cdr, index))
630 lisp_compile_pattern (lisp_object_t **obj, int *num_subs)
635 result = _compile_pattern(obj, &index);
637 if (result && num_subs != 0)
643 static int _match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars);
646 _match_pattern_var (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars)
648 if (lisp_type(pattern) != LISP_TYPE_PATTERN_VAR)
649 throw LispReaderException("_match_pattern_var", __FILE__, __LINE__);
651 switch (pattern->v.pattern.type)
653 case LISP_PATTERN_ANY :
656 case LISP_PATTERN_SYMBOL :
657 if (obj == 0 || lisp_type(obj) != LISP_TYPE_SYMBOL)
661 case LISP_PATTERN_STRING :
662 if (obj == 0 || lisp_type(obj) != LISP_TYPE_STRING)
666 case LISP_PATTERN_INTEGER :
667 if (obj == 0 || lisp_type(obj) != LISP_TYPE_INTEGER)
671 case LISP_PATTERN_REAL :
672 if (obj == 0 || lisp_type(obj) != LISP_TYPE_REAL)
676 case LISP_PATTERN_BOOLEAN :
677 if (obj == 0 || lisp_type(obj) != LISP_TYPE_BOOLEAN)
681 case LISP_PATTERN_LIST :
682 if (obj == 0 || lisp_type(obj) != LISP_TYPE_CONS)
686 case LISP_PATTERN_OR :
691 for (sub = pattern->v.pattern.sub; sub != 0; sub = lisp_cdr(sub))
693 if (lisp_type(sub) != LISP_TYPE_CONS)
694 throw LispReaderException("_match_pattern_var()", __FILE__, __LINE__);
696 if (_match_pattern(lisp_car(sub), obj, vars))
706 throw LispReaderException("_match_pattern_var()", __FILE__, __LINE__);
710 vars[pattern->v.pattern.index] = obj;
716 _match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars)
724 if (lisp_type(pattern) == LISP_TYPE_PATTERN_VAR)
725 return _match_pattern_var(pattern, obj, vars);
727 if (lisp_type(pattern) != lisp_type(obj))
730 switch (lisp_type(pattern))
732 case LISP_TYPE_SYMBOL :
733 return strcmp(lisp_symbol(pattern), lisp_symbol(obj)) == 0;
735 case LISP_TYPE_STRING :
736 return strcmp(lisp_string(pattern), lisp_string(obj)) == 0;
738 case LISP_TYPE_INTEGER :
739 return lisp_integer(pattern) == lisp_integer(obj);
741 case LISP_TYPE_REAL :
742 return lisp_real(pattern) == lisp_real(obj);
744 case LISP_TYPE_CONS :
746 int result1, result2;
748 result1 = _match_pattern(lisp_car(pattern), lisp_car(obj), vars);
749 result2 = _match_pattern(lisp_cdr(pattern), lisp_cdr(obj), vars);
751 return result1 && result2;
756 throw LispReaderException("_match_pattern()", __FILE__, __LINE__);
763 lisp_match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars, int num_subs)
768 for (i = 0; i < num_subs; ++i)
769 vars[i] = &error_object;
771 return _match_pattern(pattern, obj, vars);
775 lisp_match_string (const char *pattern_string, lisp_object_t *obj, lisp_object_t **vars)
777 lisp_object_t *pattern;
781 pattern = lisp_read_from_string(pattern_string);
783 if (pattern != 0 && (lisp_type(pattern) == LISP_TYPE_EOF
784 || lisp_type(pattern) == LISP_TYPE_PARSE_ERROR))
787 if (!lisp_compile_pattern(&pattern, &num_subs))
793 result = lisp_match_pattern(pattern, obj, vars, num_subs);
801 lisp_type (lisp_object_t *obj)
804 return LISP_TYPE_NIL;
809 lisp_integer (lisp_object_t *obj)
811 if (obj->type != LISP_TYPE_INTEGER)
812 throw LispReaderException("lisp_integer()", __FILE__, __LINE__);
814 return obj->v.integer;
818 lisp_symbol (lisp_object_t *obj)
820 if (obj->type != LISP_TYPE_SYMBOL)
821 throw LispReaderException("lisp_symbol()", __FILE__, __LINE__);
823 return obj->v.string;
827 lisp_string (lisp_object_t *obj)
829 if (obj->type != LISP_TYPE_STRING)
830 throw LispReaderException("lisp_string()", __FILE__, __LINE__);
832 return obj->v.string;
836 lisp_boolean (lisp_object_t *obj)
838 if (obj->type != LISP_TYPE_BOOLEAN)
839 throw LispReaderException("lisp_boolean()", __FILE__, __LINE__);
841 return obj->v.integer;
845 lisp_real (lisp_object_t *obj)
847 if (obj->type != LISP_TYPE_REAL && obj->type != LISP_TYPE_INTEGER)
848 throw LispReaderException("lisp_real()", __FILE__, __LINE__);
850 if (obj->type == LISP_TYPE_INTEGER)
851 return obj->v.integer;
856 lisp_car (lisp_object_t *obj)
858 if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
859 throw LispReaderException("lisp_car()", __FILE__, __LINE__);
861 return obj->v.cons.car;
865 lisp_cdr (lisp_object_t *obj)
867 if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
868 throw LispReaderException("lisp_cdr()", __FILE__, __LINE__);
870 return obj->v.cons.cdr;
874 lisp_cxr (lisp_object_t *obj, const char *x)
878 for (i = strlen(x) - 1; i >= 0; --i)
881 else if (x[i] == 'd')
884 throw LispReaderException("lisp_cxr()", __FILE__, __LINE__);
890 lisp_list_length (lisp_object_t *obj)
896 if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
897 throw LispReaderException("lisp_list_length()", __FILE__, __LINE__);
900 obj = obj->v.cons.cdr;
907 lisp_list_nth_cdr (lisp_object_t *obj, int index)
912 throw LispReaderException("lisp_list_nth_cdr()", __FILE__, __LINE__);
913 if (obj->type != LISP_TYPE_CONS && obj->type != LISP_TYPE_PATTERN_CONS)
914 throw LispReaderException("lisp_list_nth_cdr()", __FILE__, __LINE__);
917 obj = obj->v.cons.cdr;
924 lisp_list_nth (lisp_object_t *obj, int index)
926 obj = lisp_list_nth_cdr(obj, index);
929 throw LispReaderException("lisp_list_nth()", __FILE__, __LINE__);
931 return obj->v.cons.car;
935 lisp_dump (lisp_object_t *obj, FILE *out)
943 switch (lisp_type(obj))
946 fputs("#<eof>", out);
949 case LISP_TYPE_PARSE_ERROR :
950 fputs("#<error>", out);
953 case LISP_TYPE_INTEGER :
954 fprintf(out, "%d", lisp_integer(obj));
957 case LISP_TYPE_REAL :
958 fprintf(out, "%f", lisp_real(obj));
961 case LISP_TYPE_SYMBOL :
962 fputs(lisp_symbol(obj), out);
965 case LISP_TYPE_STRING :
970 for (p = lisp_string(obj); *p != 0; ++p)
972 if (*p == '"' || *p == '\\')
980 case LISP_TYPE_CONS :
981 case LISP_TYPE_PATTERN_CONS :
982 fputs(lisp_type(obj) == LISP_TYPE_CONS ? "(" : "#?(", out);
985 lisp_dump(lisp_car(obj), out);
989 if (lisp_type(obj) != LISP_TYPE_CONS
990 && lisp_type(obj) != LISP_TYPE_PATTERN_CONS)
1003 case LISP_TYPE_BOOLEAN :
1004 if (lisp_boolean(obj))
1011 throw LispReaderException("lisp_dump()", __FILE__, __LINE__);
1015 using namespace std;
1017 LispReader::LispReader (lisp_object_t* l)
1020 //std::cout << "LispReader: " << std::flush;
1021 //lisp_dump(lst, stdout);
1022 //std::cout << std::endl;
1026 LispReader::search_for(const char* name)
1028 //std::cout << "LispReader::search_for(" << name << ")" << std::endl;
1029 lisp_object_t* cursor = lst;
1031 while(!lisp_nil_p(cursor))
1033 lisp_object_t* cur = lisp_car(cursor);
1035 if (!lisp_cons_p(cur) || !lisp_symbol_p (lisp_car(cur)))
1037 lisp_dump(cur, stdout);
1038 //throw ConstruoError (std::string("LispReader: Read error in search_for ") + name);
1039 printf("LispReader: Read error in search\n");
1043 if (strcmp(lisp_symbol(lisp_car(cur)), name) == 0)
1045 return lisp_cdr(cur);
1049 cursor = lisp_cdr (cursor);
1055 LispReader::read_int (const char* name, int* i)
1057 lisp_object_t* obj = search_for (name);
1060 if (!lisp_integer_p(lisp_car(obj)))
1062 //st_abort("LispReader expected type integer at token: ", name); /* Instead of giving up, we return with false now. */
1065 *i = lisp_integer(lisp_car(obj));
1072 LispReader::read_lisp(const char* name, lisp_object_t** b)
1074 lisp_object_t* obj = search_for (name);
1085 LispReader::read_float (const char* name, float* f)
1087 lisp_object_t* obj = search_for (name);
1090 if (!lisp_real_p(lisp_car(obj)) && !lisp_integer_p(lisp_car(obj)))
1091 st_abort("LispReader expected type real at token: ", name);
1092 *f = lisp_real(lisp_car(obj));
1099 LispReader::read_string_vector (const char* name, std::vector<std::string>* vec)
1101 lisp_object_t* obj = search_for (name);
1104 while(!lisp_nil_p(obj))
1106 if (!lisp_string_p(lisp_car(obj)))
1107 st_abort("LispReader expected type string at token: ", name);
1108 vec->push_back(lisp_string(lisp_car(obj)));
1109 obj = lisp_cdr(obj);
1117 LispReader::read_int_vector (const char* name, std::vector<int>* vec)
1119 lisp_object_t* obj = search_for (name);
1122 while(!lisp_nil_p(obj))
1124 if (!lisp_integer_p(lisp_car(obj)))
1125 st_abort("LispReader expected type integer at token: ", name);
1126 vec->push_back(lisp_integer(lisp_car(obj)));
1127 obj = lisp_cdr(obj);
1135 LispReader::read_char_vector (const char* name, std::vector<char>* vec)
1137 lisp_object_t* obj = search_for (name);
1140 while(!lisp_nil_p(obj))
1142 vec->push_back(*lisp_string(lisp_car(obj)));
1143 obj = lisp_cdr(obj);
1151 LispReader::read_string (const char* name, std::string* str)
1153 lisp_object_t* obj = search_for (name);
1156 if (!lisp_string_p(lisp_car(obj)))
1157 st_abort("LispReader expected type string at token: ", name);
1158 *str = lisp_string(lisp_car(obj));
1165 LispReader::read_bool (const char* name, bool* b)
1167 lisp_object_t* obj = search_for (name);
1170 if (!lisp_boolean_p(lisp_car(obj)))
1171 st_abort("LispReader expected type bool at token: ", name);
1172 *b = lisp_boolean(lisp_car(obj));
1178 LispWriter::LispWriter (const char* name)
1180 lisp_objs.push_back(lisp_make_symbol (name));
1184 LispWriter::append (lisp_object_t* obj)
1186 lisp_objs.push_back(obj);
1190 LispWriter::make_list3 (lisp_object_t* a, lisp_object_t* b, lisp_object_t* c)
1192 return lisp_make_cons (a, lisp_make_cons(b, lisp_make_cons(c, lisp_nil())));
1196 LispWriter::make_list2 (lisp_object_t* a, lisp_object_t* b)
1198 return lisp_make_cons (a, lisp_make_cons(b, lisp_nil()));
1202 LispWriter::write_float (const char* name, float f)
1204 append(make_list2 (lisp_make_symbol (name),
1205 lisp_make_real(f)));
1209 LispWriter::write_int (const char* name, int i)
1211 append(make_list2 (lisp_make_symbol (name),
1212 lisp_make_integer(i)));
1216 LispWriter::write_string (const char* name, const char* str)
1218 append(make_list2 (lisp_make_symbol (name),
1219 lisp_make_string(str)));
1223 LispWriter::write_symbol (const char* name, const char* symname)
1225 append(make_list2 (lisp_make_symbol (name),
1226 lisp_make_symbol(symname)));
1230 LispWriter::write_lisp_obj(const char* name, lisp_object_t* lst)
1232 append(make_list2 (lisp_make_symbol (name),
1237 LispWriter::write_boolean (const char* name, bool b)
1239 append(make_list2 (lisp_make_symbol (name),
1240 lisp_make_boolean(b)));
1244 LispWriter::create_lisp ()
1246 lisp_object_t* lisp_obj = lisp_nil();
1248 for(std::vector<lisp_object_t*>::reverse_iterator i = lisp_objs.rbegin ();
1249 i != lisp_objs.rend (); ++i)
1251 lisp_obj = lisp_make_cons (*i, lisp_obj);
1259 void mygzungetc(char c, void* file)
1264 lisp_stream_t* lisp_stream_init_gzfile (lisp_stream_t *stream, gzFile file)
1266 return lisp_stream_init_any (stream, file, gzgetc, mygzungetc);
1270 lisp_object_t* lisp_read_from_gzfile(const char* filename)
1273 lisp_object_t* root_obj = 0;
1274 int chunk_size = 128 * 1024;
1277 char* buf = static_cast<char*>(malloc(chunk_size));
1279 throw LispReaderException("lisp_read_from_gzfile()", __FILE__, __LINE__);
1281 gzFile in = gzopen(filename, "r");
1285 int ret = gzread(in, buf + buf_pos, chunk_size);
1289 throw LispReaderException("Error while reading from file", __FILE__, __LINE__);
1291 else if (ret == chunk_size) // buffer got full, eof not yet there so resize
1293 buf_pos = chunk_size * try_number;
1295 buf = static_cast<char*>(realloc(buf, chunk_size * try_number));
1298 throw LispReaderException("lisp_read_from_gzfile()", __FILE__, __LINE__);
1302 // everything fine, encountered EOF
1307 lisp_stream_t stream;
1308 lisp_stream_init_string (&stream, buf);
1309 root_obj = lisp_read (&stream);
1317 bool has_suffix(const char* data, const char* suffix)
1319 int suffix_len = strlen(suffix);
1320 int data_len = strlen(data);
1322 const char* data_suffix = (data + data_len - suffix_len);
1324 if (data_suffix >= data)
1326 return (strcmp(data_suffix, suffix) == 0);
1334 lisp_object_t* lisp_read_from_file(const std::string& filename)
1336 lisp_stream_t stream;
1338 if (has_suffix(filename.c_str(), ".gz"))
1340 return lisp_read_from_gzfile(filename.c_str());
1344 lisp_object_t* obj = 0;
1345 FILE* in = fopen(filename.c_str(), "r");
1349 lisp_stream_init_file(&stream, in);
1350 obj = lisp_read(&stream);