xref: /Universal-ctags/dsl/es.c (revision 46162f0c2114e4c37ccf3e23c3158bcb606b14cd)
1e475a54fSMasatake YAMATO /*
2e475a54fSMasatake YAMATO   Copyright (c) 2009 Masatake YAMATO
3e475a54fSMasatake YAMATO 
4e475a54fSMasatake YAMATO   Permission is hereby granted, free of charge, to any person obtaining a copy
5e475a54fSMasatake YAMATO   of this software and associated documentation files (the "Software"), to deal
6e475a54fSMasatake YAMATO   in the Software without restriction, including without limitation the rights
7e475a54fSMasatake YAMATO   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8e475a54fSMasatake YAMATO   copies of the Software, and to permit persons to whom the Software is
9e475a54fSMasatake YAMATO   furnished to do so, subject to the following conditions:
10e475a54fSMasatake YAMATO 
11e475a54fSMasatake YAMATO   The above copyright notice and this permission notice shall be included in
12e475a54fSMasatake YAMATO   all copies or substantial portions of the Software.
13e475a54fSMasatake YAMATO 
14e475a54fSMasatake YAMATO   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15e475a54fSMasatake YAMATO   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16e475a54fSMasatake YAMATO   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17e475a54fSMasatake YAMATO   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18e475a54fSMasatake YAMATO   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19e475a54fSMasatake YAMATO   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20e475a54fSMasatake YAMATO   THE SOFTWARE. */
21e475a54fSMasatake YAMATO 
22e475a54fSMasatake YAMATO #if defined (HAVE_CONFIG_H)
23e475a54fSMasatake YAMATO # include <config.h>
24e475a54fSMasatake YAMATO #endif
25e475a54fSMasatake YAMATO 
26e475a54fSMasatake YAMATO #include "es.h"
27e475a54fSMasatake YAMATO 
28e475a54fSMasatake YAMATO 
29e475a54fSMasatake YAMATO #include <stdlib.h>
30e475a54fSMasatake YAMATO #include <string.h>
31e475a54fSMasatake YAMATO #include <errno.h>
32e475a54fSMasatake YAMATO #include <limits.h>
33e475a54fSMasatake YAMATO 
34e475a54fSMasatake YAMATO #include <regex.h>
35e475a54fSMasatake YAMATO 
36e475a54fSMasatake YAMATO static int es_debug = 0;
37e475a54fSMasatake YAMATO 
38e475a54fSMasatake YAMATO typedef struct _EsInteger EsInteger;
39e475a54fSMasatake YAMATO typedef struct _EsReal EsReal;
40e475a54fSMasatake YAMATO typedef struct _EsBoolean EsBoolean;
41e475a54fSMasatake YAMATO typedef struct _EsString EsString;
42e475a54fSMasatake YAMATO typedef struct _EsSingleton EsSingleton;
43e475a54fSMasatake YAMATO typedef struct _EsSymbol EsSymbol;
44e475a54fSMasatake YAMATO typedef struct _EsError EsError;
45e475a54fSMasatake YAMATO typedef struct _EsCons EsCons;
46e475a54fSMasatake YAMATO typedef struct _EsRegex EsRegex;
47e475a54fSMasatake YAMATO typedef struct _EsPointer EsPointer;
48e475a54fSMasatake YAMATO 
49e475a54fSMasatake YAMATO struct _EsObject
50e475a54fSMasatake YAMATO {
51e475a54fSMasatake YAMATO 	EsType  type;
52e475a54fSMasatake YAMATO 	union
53e475a54fSMasatake YAMATO 	{
54e475a54fSMasatake YAMATO 		int     ref_count;
55e475a54fSMasatake YAMATO 		EsSingleton* next;
56e475a54fSMasatake YAMATO 	};
57e475a54fSMasatake YAMATO };
58e475a54fSMasatake YAMATO 
59e475a54fSMasatake YAMATO struct _EsInteger
60e475a54fSMasatake YAMATO {
61e475a54fSMasatake YAMATO 	EsObject base;
62e475a54fSMasatake YAMATO 	int      value;
63e475a54fSMasatake YAMATO };
64e475a54fSMasatake YAMATO 
65e475a54fSMasatake YAMATO struct _EsReal
66e475a54fSMasatake YAMATO {
67e475a54fSMasatake YAMATO 	EsObject base;
68e475a54fSMasatake YAMATO 	double   value;
69e475a54fSMasatake YAMATO };
70e475a54fSMasatake YAMATO 
71e475a54fSMasatake YAMATO struct _EsBoolean
72e475a54fSMasatake YAMATO {
73e475a54fSMasatake YAMATO 	EsObject base;
74e475a54fSMasatake YAMATO 	int      value;
75e475a54fSMasatake YAMATO };
76e475a54fSMasatake YAMATO 
77e475a54fSMasatake YAMATO struct _EsString
78e475a54fSMasatake YAMATO {
79e475a54fSMasatake YAMATO 	EsObject    base;
80e475a54fSMasatake YAMATO 	char*       value;
81e475a54fSMasatake YAMATO };
82e475a54fSMasatake YAMATO 
83e475a54fSMasatake YAMATO struct _EsSingleton
84e475a54fSMasatake YAMATO {
85e475a54fSMasatake YAMATO 	EsObject     base;
86e475a54fSMasatake YAMATO 	char*        quark;
87e475a54fSMasatake YAMATO };
88e475a54fSMasatake YAMATO 
89e475a54fSMasatake YAMATO struct _EsSymbol
90e475a54fSMasatake YAMATO {
91e475a54fSMasatake YAMATO 	EsSingleton base;
92e475a54fSMasatake YAMATO 	void       *data;
93e475a54fSMasatake YAMATO };
94e475a54fSMasatake YAMATO 
95e475a54fSMasatake YAMATO struct _EsError
96e475a54fSMasatake YAMATO {
97e475a54fSMasatake YAMATO 	EsSingleton base;
98e475a54fSMasatake YAMATO 	EsObject   *object;
99e475a54fSMasatake YAMATO };
100e475a54fSMasatake YAMATO 
101e475a54fSMasatake YAMATO struct _EsCons
102e475a54fSMasatake YAMATO {
103e475a54fSMasatake YAMATO 	EsObject base;
104e475a54fSMasatake YAMATO 	EsObject* car;
105e475a54fSMasatake YAMATO 	EsObject* cdr;
106e475a54fSMasatake YAMATO };
107e475a54fSMasatake YAMATO 
108e475a54fSMasatake YAMATO struct _EsRegex
109e475a54fSMasatake YAMATO {
110e475a54fSMasatake YAMATO 	EsObject base;
111e475a54fSMasatake YAMATO 	regex_t *code;
112e475a54fSMasatake YAMATO 	char* literal;
113e475a54fSMasatake YAMATO 	int   case_insensitive;
114e475a54fSMasatake YAMATO };
115e475a54fSMasatake YAMATO 
116e475a54fSMasatake YAMATO struct _EsPointer
117e475a54fSMasatake YAMATO {
118e475a54fSMasatake YAMATO 	EsObject base;
119e475a54fSMasatake YAMATO 	void *ptr;
120e7dc9661SMasatake YAMATO 	char  fat [];
121e475a54fSMasatake YAMATO };
122e475a54fSMasatake YAMATO 
123e475a54fSMasatake YAMATO enum EsObjectFlag
124e475a54fSMasatake YAMATO {
125e475a54fSMasatake YAMATO 	ES_OBJECT_FLAG_ATOM = 1 << 0,
126e475a54fSMasatake YAMATO };
127e475a54fSMasatake YAMATO 
128e475a54fSMasatake YAMATO typedef struct _EsObjectClass EsObjectClass;
129e475a54fSMasatake YAMATO struct _EsObjectClass
130e475a54fSMasatake YAMATO {
131e475a54fSMasatake YAMATO 	size_t         size;
132e475a54fSMasatake YAMATO 	void           (* free)  (EsObject* object);
133e475a54fSMasatake YAMATO 	int            (* equal) (const EsObject* self, const EsObject* other);
134e475a54fSMasatake YAMATO 	void           (* print) (const EsObject* object, MIO* fp);
135e475a54fSMasatake YAMATO 	unsigned       flags;
136e475a54fSMasatake YAMATO 	EsSingleton  **obarray;
137e475a54fSMasatake YAMATO 	const char*    name;
138e475a54fSMasatake YAMATO };
139e475a54fSMasatake YAMATO 
140e475a54fSMasatake YAMATO 
141e475a54fSMasatake YAMATO static void es_nil_free(EsObject* object);
142e475a54fSMasatake YAMATO static int  es_nil_equal(const EsObject* self, const EsObject* other);
143e475a54fSMasatake YAMATO static void es_nil_print(const EsObject* object, MIO* fp);
144e475a54fSMasatake YAMATO 
145e475a54fSMasatake YAMATO static void es_integer_free(EsObject* object);
146e475a54fSMasatake YAMATO static int  es_integer_equal(const EsObject* self, const EsObject* other);
147e475a54fSMasatake YAMATO static void es_integer_print(const EsObject* object, MIO* fp);
148e475a54fSMasatake YAMATO 
149e475a54fSMasatake YAMATO static void es_real_free(EsObject* object);
150e475a54fSMasatake YAMATO static int  es_real_equal(const EsObject* self, const EsObject* other);
151e475a54fSMasatake YAMATO static void es_real_print(const EsObject* object, MIO* fp);
152e475a54fSMasatake YAMATO 
153e475a54fSMasatake YAMATO static void es_boolean_free(EsObject* object);
154e475a54fSMasatake YAMATO static int  es_boolean_equal(const EsObject* self, const EsObject* other);
155e475a54fSMasatake YAMATO static void es_boolean_print(const EsObject* object, MIO* fp);
156e475a54fSMasatake YAMATO 
157e475a54fSMasatake YAMATO static void es_string_free(EsObject* object);
158e475a54fSMasatake YAMATO static int  es_string_equal(const EsObject* self, const EsObject* other);
159e475a54fSMasatake YAMATO static void es_string_print(const EsObject* self, MIO* fp);
160e475a54fSMasatake YAMATO 
161e475a54fSMasatake YAMATO static void es_symbol_free(EsObject* object);
162e475a54fSMasatake YAMATO static int  es_symbol_equal(const EsObject* self, const EsObject* other);
163e475a54fSMasatake YAMATO static void es_symbol_print(const EsObject* object, MIO* fp);
164e475a54fSMasatake YAMATO 
165e475a54fSMasatake YAMATO static void es_cons_free(EsObject* object);
166e475a54fSMasatake YAMATO static int  es_cons_equal(const EsObject* self, const EsObject* other);
167e475a54fSMasatake YAMATO static void es_cons_print(const EsObject* object, MIO* fp);
168e475a54fSMasatake YAMATO 
169e475a54fSMasatake YAMATO static void es_regex_free(EsObject* object);
170e475a54fSMasatake YAMATO static int  es_regex_equal(const EsObject* self, const EsObject* other);
171e475a54fSMasatake YAMATO static void es_regex_print(const EsObject* object, MIO* fp);
172e475a54fSMasatake YAMATO 
173e475a54fSMasatake YAMATO static void es_error_free(EsObject* object);
174e475a54fSMasatake YAMATO static int  es_error_equal(const EsObject* self, const EsObject* other);
175e475a54fSMasatake YAMATO static void es_error_print(const EsObject* object, MIO* fp);
176e475a54fSMasatake YAMATO 
177e475a54fSMasatake YAMATO static void es_pointer_free(EsObject* object);
178e475a54fSMasatake YAMATO static int  es_pointer_equal(const EsObject* self, const EsObject* other);
179e475a54fSMasatake YAMATO static void es_pointer_print(const EsObject* object, MIO* fp);
180e475a54fSMasatake YAMATO 
181e475a54fSMasatake YAMATO static EsSingleton* es_obarray_intern(EsType type, const char* name);
182e475a54fSMasatake YAMATO static const char*  es_singleton_get   (EsSingleton *singleton);
183e475a54fSMasatake YAMATO static unsigned int hash(const char* keyarg);
184e475a54fSMasatake YAMATO #define OBARRAY_SIZE    83
185e475a54fSMasatake YAMATO static EsSingleton  *symbol_obarray[OBARRAY_SIZE];
186e475a54fSMasatake YAMATO static EsSingleton  *error_obarray [OBARRAY_SIZE];
187e475a54fSMasatake YAMATO 
188e475a54fSMasatake YAMATO static EsObjectClass es_nil_class = {
189e475a54fSMasatake YAMATO 	.size    = 0,
190e475a54fSMasatake YAMATO 	.free    = es_nil_free,
191e475a54fSMasatake YAMATO 	.equal   = es_nil_equal,
192e475a54fSMasatake YAMATO 	.print   = es_nil_print,
193e475a54fSMasatake YAMATO 	.flags   = ES_OBJECT_FLAG_ATOM,
194e475a54fSMasatake YAMATO 	.obarray = NULL,
195e475a54fSMasatake YAMATO 	.name    = "nil",
196e475a54fSMasatake YAMATO };
197e475a54fSMasatake YAMATO 
198e475a54fSMasatake YAMATO static EsObjectClass es_integer_class = {
199e475a54fSMasatake YAMATO 	.size    = sizeof(EsInteger),
200e475a54fSMasatake YAMATO 	.free    = es_integer_free,
201e475a54fSMasatake YAMATO 	.equal   = es_integer_equal,
202e475a54fSMasatake YAMATO 	.print   = es_integer_print,
203e475a54fSMasatake YAMATO 	.flags   = ES_OBJECT_FLAG_ATOM,
204e475a54fSMasatake YAMATO 	.obarray = NULL,
205e475a54fSMasatake YAMATO 	.name    = "integer",
206e475a54fSMasatake YAMATO };
207e475a54fSMasatake YAMATO 
208e475a54fSMasatake YAMATO static EsObjectClass es_real_class = {
209e475a54fSMasatake YAMATO 	.size    = sizeof(EsReal),
210e475a54fSMasatake YAMATO 	.free    = es_real_free,
211e475a54fSMasatake YAMATO 	.equal   = es_real_equal,
212e475a54fSMasatake YAMATO 	.print   = es_real_print,
213e475a54fSMasatake YAMATO 	.flags   = ES_OBJECT_FLAG_ATOM,
214e475a54fSMasatake YAMATO 	.obarray = NULL,
215e475a54fSMasatake YAMATO 	.name    = "real",
216e475a54fSMasatake YAMATO };
217e475a54fSMasatake YAMATO 
218e475a54fSMasatake YAMATO static EsObjectClass es_boolean_class = {
219e475a54fSMasatake YAMATO 	.size    = sizeof(EsBoolean),
220e475a54fSMasatake YAMATO 	.free    = es_boolean_free,
221e475a54fSMasatake YAMATO 	.equal   = es_boolean_equal,
222e475a54fSMasatake YAMATO 	.print   = es_boolean_print,
223e475a54fSMasatake YAMATO 	.flags   = ES_OBJECT_FLAG_ATOM,
224e475a54fSMasatake YAMATO 	.obarray = (void*)1,
225e475a54fSMasatake YAMATO 	.name    = "boolean",
226e475a54fSMasatake YAMATO };
227e475a54fSMasatake YAMATO 
228e475a54fSMasatake YAMATO static EsObjectClass es_symbol_class = {
229e475a54fSMasatake YAMATO 	.size    = sizeof(EsSymbol),
230e475a54fSMasatake YAMATO 	.free    = es_symbol_free,
231e475a54fSMasatake YAMATO 	.equal   = es_symbol_equal,
232e475a54fSMasatake YAMATO 	.print   = es_symbol_print,
233e475a54fSMasatake YAMATO 	.flags   = ES_OBJECT_FLAG_ATOM,
234e475a54fSMasatake YAMATO 	.obarray = symbol_obarray,
235e475a54fSMasatake YAMATO 	.name    = "symbol",
236e475a54fSMasatake YAMATO };
237e475a54fSMasatake YAMATO 
238e475a54fSMasatake YAMATO static EsObjectClass es_string_class = {
239e475a54fSMasatake YAMATO 	.size    = sizeof(EsString),
240e475a54fSMasatake YAMATO 	.free    = es_string_free,
241e475a54fSMasatake YAMATO 	.equal   = es_string_equal,
242e475a54fSMasatake YAMATO 	.print   = es_string_print,
243e475a54fSMasatake YAMATO 	.flags   = ES_OBJECT_FLAG_ATOM,
244e475a54fSMasatake YAMATO 	.obarray = NULL,
245e475a54fSMasatake YAMATO 	.name    = "string",
246e475a54fSMasatake YAMATO };
247e475a54fSMasatake YAMATO 
248e475a54fSMasatake YAMATO static EsObjectClass es_cons_class = {
249e475a54fSMasatake YAMATO 	.size    = sizeof(EsCons),
250e475a54fSMasatake YAMATO 	.free    = es_cons_free,
251e475a54fSMasatake YAMATO 	.equal   = es_cons_equal,
252e475a54fSMasatake YAMATO 	.print   = es_cons_print,
253e475a54fSMasatake YAMATO 	.flags   = 0,
254e475a54fSMasatake YAMATO 	.obarray = NULL,
255e475a54fSMasatake YAMATO 	.name    = "cons",
256e475a54fSMasatake YAMATO };
257e475a54fSMasatake YAMATO 
258e475a54fSMasatake YAMATO static EsObjectClass es_regex_class = {
259e475a54fSMasatake YAMATO 	.size    = sizeof(EsRegex),
260e475a54fSMasatake YAMATO 	.free    = es_regex_free,
261e475a54fSMasatake YAMATO 	.equal   = es_regex_equal,
262e475a54fSMasatake YAMATO 	.print   = es_regex_print,
263e475a54fSMasatake YAMATO 	.flags   = ES_OBJECT_FLAG_ATOM,
264e475a54fSMasatake YAMATO 	.obarray = NULL,
265e475a54fSMasatake YAMATO 	.name    = "regex",
266e475a54fSMasatake YAMATO };
267e475a54fSMasatake YAMATO 
268e475a54fSMasatake YAMATO static EsObjectClass es_error_class = {
269e475a54fSMasatake YAMATO 	.size    = sizeof(EsError),
270e475a54fSMasatake YAMATO 	.free    = es_error_free,
271e475a54fSMasatake YAMATO 	.equal   = es_error_equal,
272e475a54fSMasatake YAMATO 	.print   = es_error_print,
273e475a54fSMasatake YAMATO 	.flags   = ES_OBJECT_FLAG_ATOM,
274e475a54fSMasatake YAMATO 	.obarray = error_obarray,
275e475a54fSMasatake YAMATO 	.name    = "error",
276e475a54fSMasatake YAMATO };
277e475a54fSMasatake YAMATO 
278e475a54fSMasatake YAMATO 
279e475a54fSMasatake YAMATO #define ES_TYPE_CLASS_MAX 32
280e475a54fSMasatake YAMATO static int classes_count = ES_TYPE_FOREIGNER_START;
281e475a54fSMasatake YAMATO static EsObjectClass *classes[ES_TYPE_CLASS_MAX] = {
282e475a54fSMasatake YAMATO 	[ES_TYPE_NIL]     = &es_nil_class,
283e475a54fSMasatake YAMATO 	[ES_TYPE_INTEGER] = &es_integer_class,
284e475a54fSMasatake YAMATO 	[ES_TYPE_REAL]    = &es_real_class,
285e475a54fSMasatake YAMATO 	[ES_TYPE_BOOLEAN] = &es_boolean_class,
286e475a54fSMasatake YAMATO 	[ES_TYPE_SYMBOL]  = &es_symbol_class,
287e475a54fSMasatake YAMATO 	[ES_TYPE_STRING]  = &es_string_class,
288e475a54fSMasatake YAMATO 	[ES_TYPE_CONS]    = &es_cons_class,
289e475a54fSMasatake YAMATO 	[ES_TYPE_REGEX]   = &es_regex_class,
290e475a54fSMasatake YAMATO 	[ES_TYPE_ERROR]   = &es_error_class,
291e475a54fSMasatake YAMATO };
292e475a54fSMasatake YAMATO 
293e475a54fSMasatake YAMATO 
294e475a54fSMasatake YAMATO 
mio_stdout(void)295e475a54fSMasatake YAMATO static MIO *mio_stdout (void)
296e475a54fSMasatake YAMATO {
297e475a54fSMasatake YAMATO 	static MIO  *out;
298e475a54fSMasatake YAMATO 
299e475a54fSMasatake YAMATO 	if (out == NULL)
300e475a54fSMasatake YAMATO 		out = mio_new_fp (stdout, NULL);
301e475a54fSMasatake YAMATO 
302e475a54fSMasatake YAMATO 	return out;
303e475a54fSMasatake YAMATO }
304e475a54fSMasatake YAMATO 
mio_stdin(void)305e475a54fSMasatake YAMATO static MIO *mio_stdin (void)
306e475a54fSMasatake YAMATO {
307e475a54fSMasatake YAMATO 	static MIO  *out;
308e475a54fSMasatake YAMATO 
309e475a54fSMasatake YAMATO 	if (out == NULL)
310e475a54fSMasatake YAMATO 		out = mio_new_fp (stdin, NULL);
311e475a54fSMasatake YAMATO 
312e475a54fSMasatake YAMATO 	return out;
313e475a54fSMasatake YAMATO }
314e475a54fSMasatake YAMATO 
mio_stderr(void)315e475a54fSMasatake YAMATO static MIO *mio_stderr (void)
316e475a54fSMasatake YAMATO {
317e475a54fSMasatake YAMATO 	static MIO  *out;
318e475a54fSMasatake YAMATO 
319e475a54fSMasatake YAMATO 	if (out == NULL)
320e475a54fSMasatake YAMATO 		out = mio_new_fp (stderr, NULL);
321e475a54fSMasatake YAMATO 
322e475a54fSMasatake YAMATO 	return out;
323e475a54fSMasatake YAMATO }
324e475a54fSMasatake YAMATO 
325e475a54fSMasatake YAMATO 
326e475a54fSMasatake YAMATO 
327e475a54fSMasatake YAMATO static EsObjectClass*
class_of(const EsObject * object)328e475a54fSMasatake YAMATO class_of(const EsObject* object)
329e475a54fSMasatake YAMATO {
330e475a54fSMasatake YAMATO 	return (classes[es_object_get_type(object)]);
331e475a54fSMasatake YAMATO }
332e475a54fSMasatake YAMATO 
333e475a54fSMasatake YAMATO static EsObject*
es_object_new(EsType type)334e475a54fSMasatake YAMATO es_object_new(EsType type)
335e475a54fSMasatake YAMATO {
336e475a54fSMasatake YAMATO 	EsObject* r;
337e475a54fSMasatake YAMATO 
338e475a54fSMasatake YAMATO 
339e475a54fSMasatake YAMATO 	r = calloc(1, (classes[type])->size);
340e475a54fSMasatake YAMATO 	if (r == NULL)
341e475a54fSMasatake YAMATO 		return ES_ERROR_MEMORY;
342e475a54fSMasatake YAMATO 	r->type = type;
343e475a54fSMasatake YAMATO 	r->ref_count = 1;
344e475a54fSMasatake YAMATO 
345e475a54fSMasatake YAMATO 	if (es_debug)
346e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; new{%s}: 0x%p\n",
347e475a54fSMasatake YAMATO 				   (classes[type])->name,
348e475a54fSMasatake YAMATO 				   r);
349e475a54fSMasatake YAMATO 
350e475a54fSMasatake YAMATO 	return r;
351e475a54fSMasatake YAMATO }
352e475a54fSMasatake YAMATO 
353e475a54fSMasatake YAMATO static void
es_object_free(EsObject * object)354e475a54fSMasatake YAMATO es_object_free(EsObject* object)
355e475a54fSMasatake YAMATO {
356e475a54fSMasatake YAMATO 	memset(object, 0, class_of(object)->size);
357e475a54fSMasatake YAMATO 	free(object);
358e475a54fSMasatake YAMATO }
359e475a54fSMasatake YAMATO 
360e475a54fSMasatake YAMATO static int
es_object_type_p(const EsObject * object,EsType type)361e475a54fSMasatake YAMATO es_object_type_p(const EsObject* object, EsType type)
362e475a54fSMasatake YAMATO {
363e475a54fSMasatake YAMATO 	return es_object_get_type(object) == type;
364e475a54fSMasatake YAMATO }
365e475a54fSMasatake YAMATO 
es_type_get_name(int t)366b73e7385SMasatake YAMATO const char* es_type_get_name        (int t)
367b73e7385SMasatake YAMATO {
368b73e7385SMasatake YAMATO 	return (classes[t]->name);
369b73e7385SMasatake YAMATO }
370b73e7385SMasatake YAMATO 
371e475a54fSMasatake YAMATO EsType
es_object_get_type(const EsObject * object)372e475a54fSMasatake YAMATO es_object_get_type      (const EsObject*      object)
373e475a54fSMasatake YAMATO {
374e475a54fSMasatake YAMATO 	return object? object->type: ES_TYPE_NIL;
375e475a54fSMasatake YAMATO }
376e475a54fSMasatake YAMATO 
377e475a54fSMasatake YAMATO EsObject*
es_object_ref(EsObject * object)378e475a54fSMasatake YAMATO es_object_ref           (EsObject*       object)
379e475a54fSMasatake YAMATO {
380e475a54fSMasatake YAMATO 	if (object)
381e475a54fSMasatake YAMATO     {
382e475a54fSMasatake YAMATO 		if (class_of(object)->obarray)
383e475a54fSMasatake YAMATO 			return object;
384e475a54fSMasatake YAMATO 
385e475a54fSMasatake YAMATO 		if (es_debug)
386e475a54fSMasatake YAMATO 			mio_printf(mio_stderr(), ";; ref{%s}: [%d]0x%p\n",
387e475a54fSMasatake YAMATO 					   class_of(object)->name,
388e475a54fSMasatake YAMATO 					   object->ref_count,
389e475a54fSMasatake YAMATO 					   object);
390e475a54fSMasatake YAMATO 		object->ref_count++;
391e475a54fSMasatake YAMATO     }
392e475a54fSMasatake YAMATO 	return object;
393e475a54fSMasatake YAMATO }
394e475a54fSMasatake YAMATO 
395e475a54fSMasatake YAMATO void
es_object_unref(EsObject * object)396e475a54fSMasatake YAMATO es_object_unref         (EsObject*       object)
397e475a54fSMasatake YAMATO {
398e475a54fSMasatake YAMATO 
399e475a54fSMasatake YAMATO 	if (object)
400e475a54fSMasatake YAMATO     {
401e475a54fSMasatake YAMATO 		if (class_of(object)->obarray)
402e475a54fSMasatake YAMATO 			return;
403e475a54fSMasatake YAMATO 
404e475a54fSMasatake YAMATO 		if (object->ref_count == 0)
405e475a54fSMasatake YAMATO 			if ((1 || es_debug))
406e475a54fSMasatake YAMATO 			{
407e475a54fSMasatake YAMATO 				mio_printf(mio_stderr(), "*** ref_count < 0: 0x%p ***\n", object);
408e475a54fSMasatake YAMATO 				mio_printf(mio_stderr(), "*** BOOSTING while(1). ***\n");
409e475a54fSMasatake YAMATO 				while (1);
410e475a54fSMasatake YAMATO 			}
411e475a54fSMasatake YAMATO 
412e475a54fSMasatake YAMATO 		object->ref_count--;
413e475a54fSMasatake YAMATO 		if (es_debug)
414e475a54fSMasatake YAMATO 			mio_printf(mio_stderr(), ";; unref{%s}: [%d]0x%p\n",
415e475a54fSMasatake YAMATO 					   class_of(object)->name,
416e475a54fSMasatake YAMATO 					   object->ref_count, object);
417e475a54fSMasatake YAMATO 		if (object->ref_count == 0)
418e475a54fSMasatake YAMATO 		{
419e475a54fSMasatake YAMATO 			if (es_debug)
420e475a54fSMasatake YAMATO 				mio_printf(mio_stderr(), ";; free{%s}: 0x%p\n",
421e475a54fSMasatake YAMATO 						   class_of(object)->name,
422e475a54fSMasatake YAMATO 						   object);
423e475a54fSMasatake YAMATO 			class_of(object)->free(object);
424e475a54fSMasatake YAMATO 		}
425e475a54fSMasatake YAMATO     }
426e475a54fSMasatake YAMATO }
427e475a54fSMasatake YAMATO 
428e475a54fSMasatake YAMATO void
es_object_unref_batch(EsObject * array[],unsigned int count)429e475a54fSMasatake YAMATO es_object_unref_batch (EsObject*       array[],
430e475a54fSMasatake YAMATO 					   unsigned int    count)
431e475a54fSMasatake YAMATO {
432e475a54fSMasatake YAMATO 	unsigned int i;
433e475a54fSMasatake YAMATO 
434e475a54fSMasatake YAMATO 	for (i = 0; i < count; i++)
435e475a54fSMasatake YAMATO     {
436e475a54fSMasatake YAMATO 		es_object_unref(array[i]);
437e475a54fSMasatake YAMATO 		array[i] = es_nil;
438e475a54fSMasatake YAMATO     }
439e475a54fSMasatake YAMATO }
440e475a54fSMasatake YAMATO 
441e475a54fSMasatake YAMATO int
es_object_equal(const EsObject * self,const EsObject * other)442e475a54fSMasatake YAMATO es_object_equal         (const EsObject* self,
443e475a54fSMasatake YAMATO 						 const EsObject* other)
444e475a54fSMasatake YAMATO {
445e475a54fSMasatake YAMATO 	if (self == other)
446e475a54fSMasatake YAMATO 		return 1;
447e475a54fSMasatake YAMATO 
448e475a54fSMasatake YAMATO 	return class_of(self)->equal(self, other);
449e475a54fSMasatake YAMATO }
450e475a54fSMasatake YAMATO 
451e475a54fSMasatake YAMATO 
452e475a54fSMasatake YAMATO int
es_atom(const EsObject * object)453e475a54fSMasatake YAMATO es_atom         (const EsObject* object)
454e475a54fSMasatake YAMATO {
455e475a54fSMasatake YAMATO 	return class_of(object)->flags  & ES_OBJECT_FLAG_ATOM;
456e475a54fSMasatake YAMATO }
457e475a54fSMasatake YAMATO 
458e475a54fSMasatake YAMATO 
459e475a54fSMasatake YAMATO /*
460e475a54fSMasatake YAMATO  * Nil
461e475a54fSMasatake YAMATO  */
462e475a54fSMasatake YAMATO int
es_null(const EsObject * object)463e475a54fSMasatake YAMATO es_null(const EsObject* object)
464e475a54fSMasatake YAMATO {
465e475a54fSMasatake YAMATO 	return (object == es_nil)? 1: 0;
466e475a54fSMasatake YAMATO }
467e475a54fSMasatake YAMATO 
468e475a54fSMasatake YAMATO static void
es_nil_free(EsObject * object)469e475a54fSMasatake YAMATO es_nil_free(EsObject* object)
470e475a54fSMasatake YAMATO {
471e475a54fSMasatake YAMATO 	/* DO NOTHING */
472e475a54fSMasatake YAMATO }
473e475a54fSMasatake YAMATO 
474e475a54fSMasatake YAMATO static int
es_nil_equal(const EsObject * self,const EsObject * other)475e475a54fSMasatake YAMATO es_nil_equal(const EsObject* self, const EsObject* other)
476e475a54fSMasatake YAMATO {
477e475a54fSMasatake YAMATO 	return es_null(other);
478e475a54fSMasatake YAMATO }
479e475a54fSMasatake YAMATO 
480e475a54fSMasatake YAMATO static void
es_nil_print(const EsObject * object,MIO * fp)481e475a54fSMasatake YAMATO es_nil_print(const EsObject* object, MIO* fp)
482e475a54fSMasatake YAMATO {
483e475a54fSMasatake YAMATO 	mio_puts(fp, "()");
484e475a54fSMasatake YAMATO }
485e475a54fSMasatake YAMATO 
486e475a54fSMasatake YAMATO /*
487e475a54fSMasatake YAMATO  * Integer
488e475a54fSMasatake YAMATO  */
489e475a54fSMasatake YAMATO EsObject*
es_integer_new(int value)490e475a54fSMasatake YAMATO es_integer_new (int                value)
491e475a54fSMasatake YAMATO {
492e475a54fSMasatake YAMATO 	EsObject* r;
493e475a54fSMasatake YAMATO 
494e475a54fSMasatake YAMATO 	r = es_object_new(ES_TYPE_INTEGER);
495e475a54fSMasatake YAMATO 	((EsInteger*)r)->value = value;
496e475a54fSMasatake YAMATO 	return r;
497e475a54fSMasatake YAMATO }
498e475a54fSMasatake YAMATO 
499e475a54fSMasatake YAMATO int
es_integer_p(const EsObject * object)500e475a54fSMasatake YAMATO es_integer_p   (const EsObject*   object)
501e475a54fSMasatake YAMATO {
502e475a54fSMasatake YAMATO 	return es_object_type_p(object, ES_TYPE_INTEGER);
503e475a54fSMasatake YAMATO }
504e475a54fSMasatake YAMATO 
505e475a54fSMasatake YAMATO int
es_integer_get(const EsObject * object)506e475a54fSMasatake YAMATO es_integer_get (const EsObject*   object)
507e475a54fSMasatake YAMATO {
508e475a54fSMasatake YAMATO 	if (es_integer_p(object))
509e475a54fSMasatake YAMATO 		return ((EsInteger *)object)->value;
510e475a54fSMasatake YAMATO 	else
511e475a54fSMasatake YAMATO     {
512e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_integer_get, Wrong type argument: ");
513e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
514e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
515e475a54fSMasatake YAMATO 		return -1;
516e475a54fSMasatake YAMATO     }
517e475a54fSMasatake YAMATO }
518e475a54fSMasatake YAMATO 
519e475a54fSMasatake YAMATO static void
es_integer_free(EsObject * object)520e475a54fSMasatake YAMATO es_integer_free(EsObject* object)
521e475a54fSMasatake YAMATO {
522e475a54fSMasatake YAMATO 	es_object_free(object);
523e475a54fSMasatake YAMATO }
524e475a54fSMasatake YAMATO 
525e475a54fSMasatake YAMATO static int
es_integer_equal(const EsObject * self,const EsObject * other)526e475a54fSMasatake YAMATO es_integer_equal(const EsObject* self, const EsObject* other)
527e475a54fSMasatake YAMATO {
528e475a54fSMasatake YAMATO 	return ((es_integer_p(other))
529e475a54fSMasatake YAMATO 			&& (es_integer_get(self) == es_integer_get(other)))? 1: 0;
530e475a54fSMasatake YAMATO }
531e475a54fSMasatake YAMATO 
532e475a54fSMasatake YAMATO static void
es_integer_print(const EsObject * object,MIO * fp)533e475a54fSMasatake YAMATO es_integer_print(const EsObject* object, MIO* fp)
534e475a54fSMasatake YAMATO {
535e475a54fSMasatake YAMATO 	mio_printf(fp, "%d", es_integer_get(object));
536e475a54fSMasatake YAMATO }
537e475a54fSMasatake YAMATO 
538e475a54fSMasatake YAMATO 
539e475a54fSMasatake YAMATO /*
540e475a54fSMasatake YAMATO  * Real
541e475a54fSMasatake YAMATO  */
542e475a54fSMasatake YAMATO EsObject*
es_real_new(double value)543e475a54fSMasatake YAMATO es_real_new (double                value)
544e475a54fSMasatake YAMATO {
545e475a54fSMasatake YAMATO 	EsObject* r;
546e475a54fSMasatake YAMATO 
547e475a54fSMasatake YAMATO 	r = es_object_new(ES_TYPE_REAL);
548e475a54fSMasatake YAMATO 	((EsReal*)r)->value = value;
549e475a54fSMasatake YAMATO 	return r;
550e475a54fSMasatake YAMATO }
551e475a54fSMasatake YAMATO 
552e475a54fSMasatake YAMATO int
es_real_p(const EsObject * object)553e475a54fSMasatake YAMATO es_real_p   (const EsObject*   object)
554e475a54fSMasatake YAMATO {
555e475a54fSMasatake YAMATO 	return es_object_type_p(object, ES_TYPE_REAL);
556e475a54fSMasatake YAMATO }
557e475a54fSMasatake YAMATO 
558e475a54fSMasatake YAMATO double
es_real_get(const EsObject * object)559e475a54fSMasatake YAMATO es_real_get (const EsObject*   object)
560e475a54fSMasatake YAMATO {
561e475a54fSMasatake YAMATO 	if (es_real_p(object))
562e475a54fSMasatake YAMATO 		return ((EsReal *)object)->value;
563e475a54fSMasatake YAMATO 	else
564e475a54fSMasatake YAMATO     {
565e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_real_get, Wrong type argument: ");
566e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
567e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
568e475a54fSMasatake YAMATO 		return -1;
569e475a54fSMasatake YAMATO     }
570e475a54fSMasatake YAMATO }
571e475a54fSMasatake YAMATO 
572e475a54fSMasatake YAMATO static void
es_real_free(EsObject * object)573e475a54fSMasatake YAMATO es_real_free(EsObject* object)
574e475a54fSMasatake YAMATO {
575e475a54fSMasatake YAMATO 	es_object_free(object);
576e475a54fSMasatake YAMATO }
577e475a54fSMasatake YAMATO 
578e475a54fSMasatake YAMATO static int
es_real_equal(const EsObject * self,const EsObject * other)579e475a54fSMasatake YAMATO es_real_equal(const EsObject* self, const EsObject* other)
580e475a54fSMasatake YAMATO {
581e475a54fSMasatake YAMATO 	return ((es_real_p(other))
582e475a54fSMasatake YAMATO 			/* TODO: Too restricted? */
583e475a54fSMasatake YAMATO 			&& (es_real_get(self) == es_real_get(other)))? 1: 0;
584e475a54fSMasatake YAMATO }
585e475a54fSMasatake YAMATO 
586e475a54fSMasatake YAMATO static void
es_real_print(const EsObject * object,MIO * fp)587e475a54fSMasatake YAMATO es_real_print(const EsObject* object, MIO* fp)
588e475a54fSMasatake YAMATO {
589e475a54fSMasatake YAMATO 	mio_printf(fp, "%f", es_real_get(object));
590e475a54fSMasatake YAMATO }
591e475a54fSMasatake YAMATO 
592e475a54fSMasatake YAMATO /*
593e475a54fSMasatake YAMATO  * Use Integer as Real
594e475a54fSMasatake YAMATO  */
595e475a54fSMasatake YAMATO int
es_number_p(const EsObject * object)596e475a54fSMasatake YAMATO es_number_p    (const EsObject*   object)
597e475a54fSMasatake YAMATO {
598e475a54fSMasatake YAMATO 	return (es_integer_p(object) || es_real_p(object))? 1: 0;
599e475a54fSMasatake YAMATO }
600e475a54fSMasatake YAMATO 
601e475a54fSMasatake YAMATO double
es_number_get(const EsObject * object)602e475a54fSMasatake YAMATO es_number_get  (const EsObject*   object)
603e475a54fSMasatake YAMATO {
604e475a54fSMasatake YAMATO 	double r;
605e475a54fSMasatake YAMATO 
606e475a54fSMasatake YAMATO 	switch(es_object_get_type(object))
607e475a54fSMasatake YAMATO     {
608e475a54fSMasatake YAMATO     case ES_TYPE_INTEGER:
609e475a54fSMasatake YAMATO 		r = (double)es_integer_get(object);
610e475a54fSMasatake YAMATO 		break;
611e475a54fSMasatake YAMATO     case ES_TYPE_REAL:
612e475a54fSMasatake YAMATO 		r = es_real_get(object);
613e475a54fSMasatake YAMATO 		break;
614e475a54fSMasatake YAMATO     default:
615e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_number_get, Wrong type argument: ");
616e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
617e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
618e475a54fSMasatake YAMATO 		r = -1.0;
619e475a54fSMasatake YAMATO 		break;
620e475a54fSMasatake YAMATO     }
621e475a54fSMasatake YAMATO 	return r;
622e475a54fSMasatake YAMATO }
623e475a54fSMasatake YAMATO 
624e475a54fSMasatake YAMATO 
625e475a54fSMasatake YAMATO /*
626e475a54fSMasatake YAMATO  * Boolean
627e475a54fSMasatake YAMATO  */
628e475a54fSMasatake YAMATO EsObject*
es_boolean_new(int value)629e475a54fSMasatake YAMATO es_boolean_new (int                value)
630e475a54fSMasatake YAMATO {
631e475a54fSMasatake YAMATO 	static EsObject* T;
632e475a54fSMasatake YAMATO 	static EsObject* F;
633e475a54fSMasatake YAMATO 
634e475a54fSMasatake YAMATO 	if (!T)
635e475a54fSMasatake YAMATO     {
636e475a54fSMasatake YAMATO 		T = es_object_new(ES_TYPE_BOOLEAN);
637e475a54fSMasatake YAMATO 		((EsBoolean*)T)->value = 1;
638e475a54fSMasatake YAMATO     }
639e475a54fSMasatake YAMATO 	if (!F)
640e475a54fSMasatake YAMATO     {
641e475a54fSMasatake YAMATO 		F = es_object_new(ES_TYPE_BOOLEAN);
642e475a54fSMasatake YAMATO 		((EsBoolean*)F)->value = 0;
643e475a54fSMasatake YAMATO     }
644e475a54fSMasatake YAMATO 
645e475a54fSMasatake YAMATO 	return value? T: F;
646e475a54fSMasatake YAMATO }
647e475a54fSMasatake YAMATO 
648e475a54fSMasatake YAMATO int
es_boolean_p(const EsObject * object)649e475a54fSMasatake YAMATO es_boolean_p   (const EsObject*   object)
650e475a54fSMasatake YAMATO {
651e475a54fSMasatake YAMATO 	return es_object_type_p(object, ES_TYPE_BOOLEAN);
652e475a54fSMasatake YAMATO }
653e475a54fSMasatake YAMATO 
654e475a54fSMasatake YAMATO int
es_boolean_get(const EsObject * object)655e475a54fSMasatake YAMATO es_boolean_get (const EsObject*   object)
656e475a54fSMasatake YAMATO {
657e475a54fSMasatake YAMATO 	if (es_boolean_p(object))
658e475a54fSMasatake YAMATO 		return ((EsBoolean *)object)->value;
659e475a54fSMasatake YAMATO 	else
660e475a54fSMasatake YAMATO     {
661e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_boolean_get, Wrong type argument: ");
662e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
663e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
664e475a54fSMasatake YAMATO 		return -1;
665e475a54fSMasatake YAMATO     }
666e475a54fSMasatake YAMATO }
667e475a54fSMasatake YAMATO 
668e475a54fSMasatake YAMATO static void
es_boolean_free(EsObject * object)669e475a54fSMasatake YAMATO es_boolean_free(EsObject* object)
670e475a54fSMasatake YAMATO {
671e475a54fSMasatake YAMATO 	/* Do nothing */
672e475a54fSMasatake YAMATO }
673e475a54fSMasatake YAMATO 
674e475a54fSMasatake YAMATO static int
es_boolean_equal(const EsObject * self,const EsObject * other)675e475a54fSMasatake YAMATO es_boolean_equal(const EsObject* self, const EsObject* other)
676e475a54fSMasatake YAMATO {
677e475a54fSMasatake YAMATO 	return (self == other)? 1: 0;
678e475a54fSMasatake YAMATO }
679e475a54fSMasatake YAMATO 
680e475a54fSMasatake YAMATO static void
es_boolean_print(const EsObject * object,MIO * fp)681e475a54fSMasatake YAMATO es_boolean_print(const EsObject* object, MIO* fp)
682e475a54fSMasatake YAMATO {
683e475a54fSMasatake YAMATO 	mio_printf(fp, "#%c", (es_boolean_get(object)? 't': 'f'));
684e475a54fSMasatake YAMATO }
685e475a54fSMasatake YAMATO 
686e475a54fSMasatake YAMATO /*
687e475a54fSMasatake YAMATO  * Singleton
688e475a54fSMasatake YAMATO  */
689e475a54fSMasatake YAMATO static EsSingleton*
es_obarray_intern(EsType type,const char * name)690e475a54fSMasatake YAMATO es_obarray_intern(EsType type, const char* name)
691e475a54fSMasatake YAMATO {
692e475a54fSMasatake YAMATO 	unsigned int hv;
693e475a54fSMasatake YAMATO 	EsSingleton** obarray;
694e475a54fSMasatake YAMATO 	EsSingleton* s;
695e475a54fSMasatake YAMATO 	EsSingleton* tmp;
696e475a54fSMasatake YAMATO 
697e475a54fSMasatake YAMATO 
698e475a54fSMasatake YAMATO 	obarray = (classes[type])->obarray;
699e475a54fSMasatake YAMATO 	if (!obarray)
700e475a54fSMasatake YAMATO 		return NULL;
701e475a54fSMasatake YAMATO 
702e475a54fSMasatake YAMATO 	hv = hash(name);
703e475a54fSMasatake YAMATO 	tmp = obarray[hv];
704e475a54fSMasatake YAMATO 
705e475a54fSMasatake YAMATO 	s = NULL;
706e475a54fSMasatake YAMATO 	while (tmp)
707e475a54fSMasatake YAMATO     {
708e475a54fSMasatake YAMATO 		if (!strcmp(tmp->quark, name))
709e475a54fSMasatake YAMATO 		{
710e475a54fSMasatake YAMATO 			s = tmp;
711e475a54fSMasatake YAMATO 			break;
712e475a54fSMasatake YAMATO 		}
713e475a54fSMasatake YAMATO 		else
714e475a54fSMasatake YAMATO 			tmp = ((EsObject *)tmp)->next;
715e475a54fSMasatake YAMATO     }
716e475a54fSMasatake YAMATO 
717e475a54fSMasatake YAMATO 	if (!s)
718e475a54fSMasatake YAMATO     {
719e475a54fSMasatake YAMATO 		s = (EsSingleton*) es_object_new(type);
720e475a54fSMasatake YAMATO 		s->quark = strdup(name);
721e475a54fSMasatake YAMATO 		tmp = obarray[hv];
722e475a54fSMasatake YAMATO 		obarray[hv] = s;
723e475a54fSMasatake YAMATO 		((EsObject *)s)->next = tmp;
724e475a54fSMasatake YAMATO     }
725e475a54fSMasatake YAMATO 
726e475a54fSMasatake YAMATO 	return s;
727e475a54fSMasatake YAMATO 
728e475a54fSMasatake YAMATO }
729e475a54fSMasatake YAMATO 
730e475a54fSMasatake YAMATO static const char*
es_singleton_get(EsSingleton * singleton)731e475a54fSMasatake YAMATO es_singleton_get   (EsSingleton *singleton)
732e475a54fSMasatake YAMATO {
733e475a54fSMasatake YAMATO 	return singleton->quark;
734e475a54fSMasatake YAMATO }
735e475a54fSMasatake YAMATO 
736e475a54fSMasatake YAMATO 
737e475a54fSMasatake YAMATO /*
738e475a54fSMasatake YAMATO  * Symbol
739e475a54fSMasatake YAMATO  */
740e475a54fSMasatake YAMATO static unsigned char get_char_class(int c);
741e475a54fSMasatake YAMATO 
742e475a54fSMasatake YAMATO 
743e475a54fSMasatake YAMATO EsObject*
es_symbol_intern(const char * name)744e475a54fSMasatake YAMATO es_symbol_intern  (const char*       name)
745e475a54fSMasatake YAMATO {
746e475a54fSMasatake YAMATO 	EsSingleton* r;
747e475a54fSMasatake YAMATO 
748e475a54fSMasatake YAMATO 	r = es_obarray_intern(ES_TYPE_SYMBOL, name);
749e475a54fSMasatake YAMATO 	return (EsObject*)r;
750e475a54fSMasatake YAMATO }
751e475a54fSMasatake YAMATO 
752e475a54fSMasatake YAMATO int
es_symbol_p(const EsObject * object)753e475a54fSMasatake YAMATO es_symbol_p    (const EsObject*   object)
754e475a54fSMasatake YAMATO {
755e475a54fSMasatake YAMATO 	return es_object_type_p(object, ES_TYPE_SYMBOL);
756e475a54fSMasatake YAMATO }
757e475a54fSMasatake YAMATO 
758e475a54fSMasatake YAMATO const char*
es_symbol_get(const EsObject * object)759e475a54fSMasatake YAMATO es_symbol_get  (const EsObject*   object)
760e475a54fSMasatake YAMATO {
761e475a54fSMasatake YAMATO 	if (es_symbol_p(object))
762e475a54fSMasatake YAMATO 		return es_singleton_get((EsSingleton*)object);
763e475a54fSMasatake YAMATO 	else
764e475a54fSMasatake YAMATO     {
765e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_symbol_get, Wrong type argument: ");
766e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
767e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
768e475a54fSMasatake YAMATO 		return NULL;
769e475a54fSMasatake YAMATO     }
770e475a54fSMasatake YAMATO }
771e475a54fSMasatake YAMATO 
es_symbol_set_data(const EsObject * object,void * data)772e475a54fSMasatake YAMATO void*        es_symbol_set_data (const EsObject*   object, void *data)
773e475a54fSMasatake YAMATO {
774e475a54fSMasatake YAMATO 	if (es_symbol_p(object))
775e475a54fSMasatake YAMATO     {
776e475a54fSMasatake YAMATO 		void* old_data;
777e475a54fSMasatake YAMATO 
778e475a54fSMasatake YAMATO 		old_data = ((EsSymbol*)object)->data;
779e475a54fSMasatake YAMATO 		((EsSymbol*)object)->data = data;
780e475a54fSMasatake YAMATO 		return  old_data;
781e475a54fSMasatake YAMATO     }
782e475a54fSMasatake YAMATO 	else
783e475a54fSMasatake YAMATO     {
784e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_symbol_set_data, Wrong type argument: ");
785e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
786e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
787e475a54fSMasatake YAMATO 		return NULL;
788e475a54fSMasatake YAMATO     }
789e475a54fSMasatake YAMATO }
790e475a54fSMasatake YAMATO 
es_symbol_get_data(const EsObject * object)791e475a54fSMasatake YAMATO void*        es_symbol_get_data (const EsObject*   object)
792e475a54fSMasatake YAMATO {
793e475a54fSMasatake YAMATO 	if (es_symbol_p(object))
794e475a54fSMasatake YAMATO 		return ((EsSymbol*)object)->data;
795e475a54fSMasatake YAMATO 	else
796e475a54fSMasatake YAMATO     {
797e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_symbol_get_data, Wrong type argument: ");
798e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
799e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
800e475a54fSMasatake YAMATO 		return NULL;
801e475a54fSMasatake YAMATO     }
802e475a54fSMasatake YAMATO }
803e475a54fSMasatake YAMATO 
804e475a54fSMasatake YAMATO static void
es_symbol_free(EsObject * object)805e475a54fSMasatake YAMATO es_symbol_free(EsObject* object)
806e475a54fSMasatake YAMATO {
807e475a54fSMasatake YAMATO 	/* DO NOTHING */
808e475a54fSMasatake YAMATO }
809e475a54fSMasatake YAMATO 
810e475a54fSMasatake YAMATO static int
es_symbol_equal(const EsObject * self,const EsObject * other)811e475a54fSMasatake YAMATO es_symbol_equal(const EsObject* self, const EsObject* other)
812e475a54fSMasatake YAMATO {
813e475a54fSMasatake YAMATO 	return (self == other)? 1: 0;
814e475a54fSMasatake YAMATO }
815e475a54fSMasatake YAMATO 
816e475a54fSMasatake YAMATO static void
es_symbol_print(const EsObject * object,MIO * fp)817e475a54fSMasatake YAMATO es_symbol_print(const EsObject* object, MIO* fp)
818e475a54fSMasatake YAMATO {
819e475a54fSMasatake YAMATO 	const char* string;
820e475a54fSMasatake YAMATO 	size_t len;
821e475a54fSMasatake YAMATO 	char c;
822e475a54fSMasatake YAMATO 	unsigned char cc;
823e475a54fSMasatake YAMATO 	unsigned char mask;
824e475a54fSMasatake YAMATO 	int needs_bar;
825e475a54fSMasatake YAMATO 	int i;
826e475a54fSMasatake YAMATO 
827e475a54fSMasatake YAMATO 	string = es_symbol_get(object);
828e475a54fSMasatake YAMATO 	if (!string)
829e475a54fSMasatake YAMATO 		return;
830e475a54fSMasatake YAMATO 
831e475a54fSMasatake YAMATO 	len = strlen(string);
832e475a54fSMasatake YAMATO 	if (len == 0)
833e475a54fSMasatake YAMATO 		needs_bar = 1;
834e475a54fSMasatake YAMATO 
835e475a54fSMasatake YAMATO 	c = string[0];
836e475a54fSMasatake YAMATO 	cc = get_char_class(c);
837e475a54fSMasatake YAMATO 	mask = 0x1;
838e475a54fSMasatake YAMATO 	needs_bar = (cc & mask)? 1: 0;
839e475a54fSMasatake YAMATO 	if (!needs_bar)
840e475a54fSMasatake YAMATO     {
841e475a54fSMasatake YAMATO 		/* 0 => 1? */
842e475a54fSMasatake YAMATO 		mask = 0x2;
843e475a54fSMasatake YAMATO 		for (i = 0; i< len; i++)
844e475a54fSMasatake YAMATO 		{
845e475a54fSMasatake YAMATO 			c = string[i];
846e475a54fSMasatake YAMATO 			cc = get_char_class(c);
847e475a54fSMasatake YAMATO 			needs_bar = (cc & mask)? 1: 0;
848e475a54fSMasatake YAMATO 			if (needs_bar)
849e475a54fSMasatake YAMATO 				break;
850e475a54fSMasatake YAMATO 		}
851e475a54fSMasatake YAMATO 
852e475a54fSMasatake YAMATO     }
853e475a54fSMasatake YAMATO 
854e475a54fSMasatake YAMATO 	if (needs_bar)
855e475a54fSMasatake YAMATO 		mio_printf(fp, "|");
856e475a54fSMasatake YAMATO 
857e475a54fSMasatake YAMATO 	for (i = 0; i < len; i++)
858e475a54fSMasatake YAMATO     {
859e475a54fSMasatake YAMATO 		c = string[i];
860e475a54fSMasatake YAMATO 		if (c == '\\' || c == '|')
861e475a54fSMasatake YAMATO 			mio_printf(fp, "\\");
862e475a54fSMasatake YAMATO 		mio_printf(fp, "%c", c);
863e475a54fSMasatake YAMATO     }
864e475a54fSMasatake YAMATO 
865e475a54fSMasatake YAMATO 	if (needs_bar)
866e475a54fSMasatake YAMATO 		mio_printf(fp, "|");
867e475a54fSMasatake YAMATO }
868e475a54fSMasatake YAMATO 
869e475a54fSMasatake YAMATO 
870e475a54fSMasatake YAMATO /*
871e475a54fSMasatake YAMATO  * symbol.c - symbol implementation
872e475a54fSMasatake YAMATO  *
873e475a54fSMasatake YAMATO  *   Copyright (c) 2000-2007  Shiro Kawai  <shiro@acm.org>
874e475a54fSMasatake YAMATO  *
875e475a54fSMasatake YAMATO  *   Redistribution and use in source and binary forms, with or without
876e475a54fSMasatake YAMATO  *   modification, are permitted provided that the following conditions
877e475a54fSMasatake YAMATO  *   are met:
878e475a54fSMasatake YAMATO  *
879e475a54fSMasatake YAMATO  *   1. Redistributions of source code must retain the above copyright
880e475a54fSMasatake YAMATO  *      notice, this list of conditions and the following disclaimer.
881e475a54fSMasatake YAMATO  *
882e475a54fSMasatake YAMATO  *   2. Redistributions in binary form must reproduce the above copyright
883e475a54fSMasatake YAMATO  *      notice, this list of conditions and the following disclaimer in the
884e475a54fSMasatake YAMATO  *      documentation and/or other materials provided with the distribution.
885e475a54fSMasatake YAMATO  *
886e475a54fSMasatake YAMATO  *   3. Neither the name of the authors nor the names of its contributors
887e475a54fSMasatake YAMATO  *      may be used to endorse or promote products derived from this
888e475a54fSMasatake YAMATO  *      software without specific prior written permission.
889e475a54fSMasatake YAMATO  *
890e475a54fSMasatake YAMATO  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
891e475a54fSMasatake YAMATO  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
892e475a54fSMasatake YAMATO  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
893e475a54fSMasatake YAMATO  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
894e475a54fSMasatake YAMATO  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
895e475a54fSMasatake YAMATO  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
896e475a54fSMasatake YAMATO  *   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
897e475a54fSMasatake YAMATO  *   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
898e475a54fSMasatake YAMATO  *   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
899e475a54fSMasatake YAMATO  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
900e475a54fSMasatake YAMATO  *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
901e475a54fSMasatake YAMATO  *
902e475a54fSMasatake YAMATO  *  $Id: symbol.c,v 1.40 2007/09/13 12:30:28 shirok Exp $
903e475a54fSMasatake YAMATO  */
904e475a54fSMasatake YAMATO /* table of special chars.
905e475a54fSMasatake YAMATO    bit 0: bad char for symbol to begin with
906e475a54fSMasatake YAMATO    bit 1: bad char for symbol to contain
907e475a54fSMasatake YAMATO    bit 2: bad char for symbol, and should be written as \nnn
908e475a54fSMasatake YAMATO    bit 3: bad char for symbol, and should be written as \c
909e475a54fSMasatake YAMATO    bit 4: may be escaped when case fold mode
910e475a54fSMasatake YAMATO */
911e475a54fSMasatake YAMATO static char symbol_special[] = {
912e475a54fSMasatake YAMATO 	/* NUL .... */
913e475a54fSMasatake YAMATO 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
914e475a54fSMasatake YAMATO 	/* .... */
915e475a54fSMasatake YAMATO 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
916e475a54fSMasatake YAMATO 	/*    !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /  */
917e475a54fSMasatake YAMATO 	3, 0, 3, 3, 0, 0, 0, 3, 3, 3, 0, 1, 3, 1, 1, 0,
918e475a54fSMasatake YAMATO 	/* 0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?  */
919e475a54fSMasatake YAMATO 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 0, 0, 0, 0,
920e475a54fSMasatake YAMATO 	/* @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  */
921e475a54fSMasatake YAMATO 	1, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
922e475a54fSMasatake YAMATO 	/* P  Q  R  S  T  U  V  W  X  Y  Z  [  \  ]  ^  _  */
923e475a54fSMasatake YAMATO 	16,16,16,16,16,16,16,16,16,16,16,3, 11,3, 0, 0,
924e475a54fSMasatake YAMATO 	/* `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  */
925e475a54fSMasatake YAMATO 	3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
926e475a54fSMasatake YAMATO 	/* p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~  ^? */
927e475a54fSMasatake YAMATO 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 11,3, 0, 7
928e475a54fSMasatake YAMATO };
929e475a54fSMasatake YAMATO 
930e475a54fSMasatake YAMATO /* symbol_special[':'] was 1 in the symbol.c of Gauche.
931e475a54fSMasatake YAMATO    However I modified it to 0.
932e475a54fSMasatake YAMATO    Because a keyword is a just a symbol started from `:'
933e475a54fSMasatake YAMATO    in Es. */
934e475a54fSMasatake YAMATO static unsigned char
get_char_class(int c)935e475a54fSMasatake YAMATO get_char_class(int c)
936e475a54fSMasatake YAMATO {
937e475a54fSMasatake YAMATO 	return (c < 0)? 0xff: symbol_special[c];
938e475a54fSMasatake YAMATO }
939e475a54fSMasatake YAMATO 
940e475a54fSMasatake YAMATO /*
941e475a54fSMasatake YAMATO  * String
942e475a54fSMasatake YAMATO  */
943e475a54fSMasatake YAMATO EsObject*
es_string_new(const char * value)944e475a54fSMasatake YAMATO es_string_new  (const char*        value)
945e475a54fSMasatake YAMATO {
946e475a54fSMasatake YAMATO 	EsObject* r;
947e475a54fSMasatake YAMATO 
948e475a54fSMasatake YAMATO 	r = es_object_new(ES_TYPE_STRING);
949e475a54fSMasatake YAMATO 	((EsString*)r)->value = strdup(value);
950e475a54fSMasatake YAMATO 	return r;
951e475a54fSMasatake YAMATO }
952e475a54fSMasatake YAMATO 
953e475a54fSMasatake YAMATO EsObject*
es_string_newL(const char * value,size_t len)954e475a54fSMasatake YAMATO es_string_newL (const char* value, size_t len)
955e475a54fSMasatake YAMATO {
956e475a54fSMasatake YAMATO 	EsObject* r;
957e475a54fSMasatake YAMATO 
958e475a54fSMasatake YAMATO 	r = es_object_new(ES_TYPE_STRING);
959e475a54fSMasatake YAMATO 	if (es_error_p (r))
960e475a54fSMasatake YAMATO 		return r;
961e475a54fSMasatake YAMATO 
962e475a54fSMasatake YAMATO 	void * v = malloc (len + 1);
963e475a54fSMasatake YAMATO 	if (v == NULL)
964e475a54fSMasatake YAMATO 	{
965e475a54fSMasatake YAMATO 		((EsString*)r)->value = NULL;
966e475a54fSMasatake YAMATO 		es_object_free (r);
967e475a54fSMasatake YAMATO 		return ES_ERROR_MEMORY;
968e475a54fSMasatake YAMATO 	}
969e475a54fSMasatake YAMATO 	memcpy (v, value, len);
970e475a54fSMasatake YAMATO 	((char *)v)[len] = '\0';
971e475a54fSMasatake YAMATO 	((EsString*)r)->value = v;
972e475a54fSMasatake YAMATO 	return r;
973e475a54fSMasatake YAMATO }
974e475a54fSMasatake YAMATO 
975e475a54fSMasatake YAMATO int
es_string_p(const EsObject * object)976e475a54fSMasatake YAMATO es_string_p    (const EsObject*   object)
977e475a54fSMasatake YAMATO {
978e475a54fSMasatake YAMATO 	return es_object_type_p(object, ES_TYPE_STRING);
979e475a54fSMasatake YAMATO }
980e475a54fSMasatake YAMATO 
981e475a54fSMasatake YAMATO const char*
es_string_get(const EsObject * object)982e475a54fSMasatake YAMATO es_string_get  (const EsObject*   object)
983e475a54fSMasatake YAMATO {
984e475a54fSMasatake YAMATO 	if (es_string_p(object))
985e475a54fSMasatake YAMATO 		return ((EsString *)object)->value;
986e475a54fSMasatake YAMATO 	else
987e475a54fSMasatake YAMATO     {
988e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_string_get, Wrong type argument: ");
989e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
990e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
991e475a54fSMasatake YAMATO 		return NULL;
992e475a54fSMasatake YAMATO     }
993e475a54fSMasatake YAMATO }
994e475a54fSMasatake YAMATO 
995e475a54fSMasatake YAMATO static void
es_string_free(EsObject * object)996e475a54fSMasatake YAMATO es_string_free(EsObject* object)
997e475a54fSMasatake YAMATO {
998e475a54fSMasatake YAMATO 	if (es_string_p(object))
999e475a54fSMasatake YAMATO     {
1000e475a54fSMasatake YAMATO 		free(((EsString*) object)->value);
1001e475a54fSMasatake YAMATO 		((EsString*) object)->value = NULL;
1002e475a54fSMasatake YAMATO 		es_object_free(object);
1003e475a54fSMasatake YAMATO     }
1004e475a54fSMasatake YAMATO 	else
1005e475a54fSMasatake YAMATO     {
1006e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; Internal error: \n");
1007e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";;es_string_free, Wrong type argument: ");
1008e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
1009e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
1010e475a54fSMasatake YAMATO     }
1011e475a54fSMasatake YAMATO }
1012e475a54fSMasatake YAMATO 
1013e475a54fSMasatake YAMATO 
1014e475a54fSMasatake YAMATO static int
es_string_equal(const EsObject * self,const EsObject * other)1015e475a54fSMasatake YAMATO es_string_equal(const EsObject* self, const EsObject* other)
1016e475a54fSMasatake YAMATO {
1017e475a54fSMasatake YAMATO 	if (es_string_p(other))
1018e475a54fSMasatake YAMATO     {
1019e475a54fSMasatake YAMATO 		return (!strcmp(es_string_get(self), es_string_get(other)));
1020e475a54fSMasatake YAMATO     }
1021e475a54fSMasatake YAMATO 	else
1022e475a54fSMasatake YAMATO 		return 0;
1023e475a54fSMasatake YAMATO }
1024e475a54fSMasatake YAMATO 
1025e475a54fSMasatake YAMATO static void
es_string_print(const EsObject * object,MIO * fp)1026e475a54fSMasatake YAMATO es_string_print(const EsObject* object, MIO* fp)
1027e475a54fSMasatake YAMATO {
1028e475a54fSMasatake YAMATO 	const char* string;
1029e475a54fSMasatake YAMATO 	char  c;
1030e475a54fSMasatake YAMATO 	size_t len;
1031e475a54fSMasatake YAMATO 	int      i;
1032e475a54fSMasatake YAMATO 
1033e475a54fSMasatake YAMATO 
1034e475a54fSMasatake YAMATO 	string = es_string_get(object);
1035e475a54fSMasatake YAMATO 	len    = strlen(string);
1036e475a54fSMasatake YAMATO 
1037e475a54fSMasatake YAMATO 	mio_printf(fp, "\"");
1038e475a54fSMasatake YAMATO 
1039e475a54fSMasatake YAMATO 	for (i = 0; i < len; i++)
1040e475a54fSMasatake YAMATO     {
1041e475a54fSMasatake YAMATO 		char cc;
1042e475a54fSMasatake YAMATO 
1043e475a54fSMasatake YAMATO 		c = string[i];
1044e475a54fSMasatake YAMATO 		switch (c)
1045e475a54fSMasatake YAMATO 		{
1046e475a54fSMasatake YAMATO 		case '\n':
1047e475a54fSMasatake YAMATO 			cc = 'n';
1048e475a54fSMasatake YAMATO 			break;
1049e475a54fSMasatake YAMATO 		case '\t':
1050e475a54fSMasatake YAMATO 			cc = 't';
1051e475a54fSMasatake YAMATO 			break;
1052e475a54fSMasatake YAMATO 		case '\r':
1053e475a54fSMasatake YAMATO 			cc = 'r';
1054e475a54fSMasatake YAMATO 			break;
1055e475a54fSMasatake YAMATO 		case '\f':
1056e475a54fSMasatake YAMATO 			cc = 'f';
1057e475a54fSMasatake YAMATO 			break;
1058e475a54fSMasatake YAMATO 		default:
1059e475a54fSMasatake YAMATO 			cc = 0;
1060e475a54fSMasatake YAMATO 			break;
1061e475a54fSMasatake YAMATO 		}
1062e475a54fSMasatake YAMATO 		if (cc)
1063e475a54fSMasatake YAMATO 		{
1064e475a54fSMasatake YAMATO 			mio_printf(fp, "\\");
1065e475a54fSMasatake YAMATO 			mio_printf(fp, "%c", cc);
1066e475a54fSMasatake YAMATO 			continue;
1067e475a54fSMasatake YAMATO 		}
1068e475a54fSMasatake YAMATO 
1069e475a54fSMasatake YAMATO 		if (c == '\\' || c == '"')
1070e475a54fSMasatake YAMATO 			mio_printf(fp, "\\");
1071e475a54fSMasatake YAMATO 		mio_printf(fp, "%c", c);
1072e475a54fSMasatake YAMATO     }
1073e475a54fSMasatake YAMATO 
1074e475a54fSMasatake YAMATO 	mio_printf(fp, "\"");
1075e475a54fSMasatake YAMATO }
1076e475a54fSMasatake YAMATO 
1077e475a54fSMasatake YAMATO /*
1078e475a54fSMasatake YAMATO  * Cons
1079e475a54fSMasatake YAMATO  */
1080e475a54fSMasatake YAMATO EsObject*
es_cons(EsObject * car,EsObject * cdr)1081e475a54fSMasatake YAMATO es_cons        (EsObject* car, EsObject* cdr)
1082e475a54fSMasatake YAMATO {
1083e475a54fSMasatake YAMATO 	EsObject* r;
1084e475a54fSMasatake YAMATO 
1085e475a54fSMasatake YAMATO 	if (!es_list_p(cdr))
1086e475a54fSMasatake YAMATO     {
1087e475a54fSMasatake YAMATO 		/* This library doesn't permit to dotted list. */
1088e475a54fSMasatake YAMATO 		return es_nil;
1089e475a54fSMasatake YAMATO     }
1090e475a54fSMasatake YAMATO 
1091e475a54fSMasatake YAMATO 
1092e475a54fSMasatake YAMATO 	r = es_object_new(ES_TYPE_CONS);
1093e475a54fSMasatake YAMATO 	if (es_error_p (r))
1094e475a54fSMasatake YAMATO 		return r;
1095e475a54fSMasatake YAMATO 	if (es_debug)
1096e475a54fSMasatake YAMATO     {
1097e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; cons[0x%p] = (0x%p . 0x%p)\n", r, car, cdr);
1098e475a54fSMasatake YAMATO 		/* es_print(car, mio_stderr());
1099e475a54fSMasatake YAMATO 		   mio_putc('\n', mio_stderr());
1100e475a54fSMasatake YAMATO 		   es_print(cdr, mio_stderr());
1101e475a54fSMasatake YAMATO 		   mio_putc('\n', mio_stderr()); */
1102e475a54fSMasatake YAMATO     }
1103e475a54fSMasatake YAMATO 	((EsCons*)r)->car = es_object_ref(car);
1104e475a54fSMasatake YAMATO 	((EsCons*)r)->cdr = es_object_ref(cdr);
1105e475a54fSMasatake YAMATO 
1106e475a54fSMasatake YAMATO 	return r;
1107e475a54fSMasatake YAMATO }
1108e475a54fSMasatake YAMATO 
1109e475a54fSMasatake YAMATO int
es_cons_p(const EsObject * object)1110e475a54fSMasatake YAMATO es_cons_p      (const EsObject* object)
1111e475a54fSMasatake YAMATO {
1112e475a54fSMasatake YAMATO 	return es_object_type_p(object, ES_TYPE_CONS);
1113e475a54fSMasatake YAMATO }
1114e475a54fSMasatake YAMATO 
1115e475a54fSMasatake YAMATO int
es_list_p(const EsObject * object)1116e475a54fSMasatake YAMATO es_list_p      (const EsObject* object)
1117e475a54fSMasatake YAMATO {
1118e475a54fSMasatake YAMATO 	EsType t;
1119e475a54fSMasatake YAMATO 
1120e475a54fSMasatake YAMATO 	t = es_object_get_type(object);
1121e475a54fSMasatake YAMATO 	return (t == ES_TYPE_NIL || t == ES_TYPE_CONS);
1122e475a54fSMasatake YAMATO }
1123e475a54fSMasatake YAMATO 
1124e475a54fSMasatake YAMATO EsObject*
es_car(const EsObject * object)1125e475a54fSMasatake YAMATO es_car         (const EsObject* object)
1126e475a54fSMasatake YAMATO {
1127e475a54fSMasatake YAMATO 	if (es_cons_p(object))
1128e475a54fSMasatake YAMATO 		return ((EsCons*)object)->car;
1129e475a54fSMasatake YAMATO 	else if (es_null(object))
1130e475a54fSMasatake YAMATO 		return es_nil;
1131e475a54fSMasatake YAMATO 	else
1132e475a54fSMasatake YAMATO     {
1133e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_car, Wrong type argument: ");
1134e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
1135e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
1136e475a54fSMasatake YAMATO 		return es_nil;
1137e475a54fSMasatake YAMATO     }
1138e475a54fSMasatake YAMATO }
1139e475a54fSMasatake YAMATO 
1140e475a54fSMasatake YAMATO EsObject*
es_cdr(const EsObject * object)1141e475a54fSMasatake YAMATO es_cdr         (const EsObject* object)
1142e475a54fSMasatake YAMATO {
1143e475a54fSMasatake YAMATO 	if (es_cons_p(object))
1144e475a54fSMasatake YAMATO 		return ((EsCons*)object)->cdr;
1145e475a54fSMasatake YAMATO 	else if (es_null(object))
1146e475a54fSMasatake YAMATO 		return es_nil;
1147e475a54fSMasatake YAMATO 	else
1148e475a54fSMasatake YAMATO     {
1149e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_cdr, Wrong type argument: ");
1150e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
1151e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
1152e475a54fSMasatake YAMATO 		return es_nil;
1153e475a54fSMasatake YAMATO     }
1154e475a54fSMasatake YAMATO }
1155e475a54fSMasatake YAMATO 
1156e475a54fSMasatake YAMATO static void
es_cons_free(EsObject * object)1157e475a54fSMasatake YAMATO es_cons_free(EsObject* object)
1158e475a54fSMasatake YAMATO {
1159e475a54fSMasatake YAMATO 	EsCons* cons;
1160e475a54fSMasatake YAMATO 
1161e475a54fSMasatake YAMATO 	if (es_cons_p(object))
1162e475a54fSMasatake YAMATO     {
1163e475a54fSMasatake YAMATO 		cons = ((EsCons*)object);
1164e475a54fSMasatake YAMATO 
1165e475a54fSMasatake YAMATO 		es_object_unref(cons->car);
1166e475a54fSMasatake YAMATO 		cons->car = NULL;
1167e475a54fSMasatake YAMATO 
1168e475a54fSMasatake YAMATO 		es_object_unref(cons->cdr);
1169e475a54fSMasatake YAMATO 		cons->cdr = NULL;
1170e475a54fSMasatake YAMATO 		es_object_free(object);
1171e475a54fSMasatake YAMATO     }
1172e475a54fSMasatake YAMATO 	else if (es_null(object))
1173e475a54fSMasatake YAMATO 		;				/* DO NOTHING */
1174e475a54fSMasatake YAMATO 	else
1175e475a54fSMasatake YAMATO     {
1176e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; Internal error: \n");
1177e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_cons_free, Wrong type argument: ");
1178e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
1179e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
1180e475a54fSMasatake YAMATO     }
1181e475a54fSMasatake YAMATO }
1182e475a54fSMasatake YAMATO 
1183e475a54fSMasatake YAMATO static int
es_cons_equal(const EsObject * self,const EsObject * other)1184e475a54fSMasatake YAMATO es_cons_equal(const EsObject* self, const EsObject* other)
1185e475a54fSMasatake YAMATO {
1186e475a54fSMasatake YAMATO 	return (es_null(other)
1187e475a54fSMasatake YAMATO 			|| (!es_cons_p(other))
1188e475a54fSMasatake YAMATO 			|| (!es_object_equal(es_car(self), es_car(other)))
1189e475a54fSMasatake YAMATO 			|| (!es_object_equal(es_cdr(self), es_cdr(other))))
1190e475a54fSMasatake YAMATO 		? 0
1191e475a54fSMasatake YAMATO 		: 1;
1192e475a54fSMasatake YAMATO }
1193e475a54fSMasatake YAMATO 
1194e475a54fSMasatake YAMATO static void
es_cons_print(const EsObject * object,MIO * fp)1195e475a54fSMasatake YAMATO es_cons_print(const EsObject* object, MIO* fp)
1196e475a54fSMasatake YAMATO {
1197e475a54fSMasatake YAMATO 	EsObject* car;
1198e475a54fSMasatake YAMATO 	EsObject* cdr;
1199e475a54fSMasatake YAMATO 
1200e475a54fSMasatake YAMATO 	mio_printf(fp, "(");
1201e475a54fSMasatake YAMATO 	while(!es_null(object))
1202e475a54fSMasatake YAMATO     {
1203e475a54fSMasatake YAMATO 		car = es_car(object);
1204e475a54fSMasatake YAMATO 		cdr = es_cdr(object);
1205e475a54fSMasatake YAMATO 
1206e475a54fSMasatake YAMATO 		es_print(car, fp);
1207e475a54fSMasatake YAMATO 		if (es_cons_p(cdr))
1208e475a54fSMasatake YAMATO 			mio_putc(fp, ' ');
1209e475a54fSMasatake YAMATO 		else if (!es_null(cdr))
1210e475a54fSMasatake YAMATO 		{
1211e475a54fSMasatake YAMATO 			mio_printf(mio_stderr(), ";; es_cons_print, dotted list given: ");
1212e475a54fSMasatake YAMATO 			mio_putc(mio_stderr(), '\n');
1213e475a54fSMasatake YAMATO 		}
1214e475a54fSMasatake YAMATO 		object = cdr;
1215e475a54fSMasatake YAMATO     }
1216e475a54fSMasatake YAMATO 	mio_printf(fp, ")");
1217e475a54fSMasatake YAMATO }
1218e475a54fSMasatake YAMATO 
1219e475a54fSMasatake YAMATO static EsObject* es_cons_reverse_rec(EsObject* cdr,
1220e475a54fSMasatake YAMATO 									 EsObject* car,
1221e475a54fSMasatake YAMATO 									 EsObject* gathered);
1222e475a54fSMasatake YAMATO 
1223e475a54fSMasatake YAMATO static EsObject*
es_cons_reverse(EsObject * cons)1224e475a54fSMasatake YAMATO es_cons_reverse  (EsObject*        cons)
1225e475a54fSMasatake YAMATO {
1226e475a54fSMasatake YAMATO 	/* g_return_val_if_fail (es_null(cons) || es_cons_p(cons), es_nil);
1227e475a54fSMasatake YAMATO 	   g_return_val_if_fail (!es_cproc_dotted_p(cons), es_nil); */
1228e475a54fSMasatake YAMATO 
1229e475a54fSMasatake YAMATO 	if (es_null(cons))
1230e475a54fSMasatake YAMATO 		return es_nil;
1231e475a54fSMasatake YAMATO 	else
1232e475a54fSMasatake YAMATO 		return es_cons_reverse_rec(es_cdr(cons),
1233e475a54fSMasatake YAMATO 								   es_car(cons),
1234e475a54fSMasatake YAMATO 								   es_nil);
1235e475a54fSMasatake YAMATO }
1236e475a54fSMasatake YAMATO 
1237e475a54fSMasatake YAMATO EsObject*
es_reverse(EsObject * cons)1238e475a54fSMasatake YAMATO es_reverse  (EsObject* cons)
1239e475a54fSMasatake YAMATO {
1240e475a54fSMasatake YAMATO 	return es_cons_reverse(cons);
1241e475a54fSMasatake YAMATO }
1242e475a54fSMasatake YAMATO 
1243e475a54fSMasatake YAMATO static EsObject*
es_cons_reverse_rec(EsObject * cdr,EsObject * car,EsObject * gathered)1244e475a54fSMasatake YAMATO es_cons_reverse_rec(EsObject* cdr,
1245e475a54fSMasatake YAMATO 					EsObject* car,
1246e475a54fSMasatake YAMATO 					EsObject* gathered)
1247e475a54fSMasatake YAMATO {
1248e475a54fSMasatake YAMATO 	EsObject* cons;
1249e475a54fSMasatake YAMATO 	EsObject* o;
1250e475a54fSMasatake YAMATO 
1251e475a54fSMasatake YAMATO 	cons = es_cons(car, o = gathered);
1252e475a54fSMasatake YAMATO 	es_object_unref(o);
1253e475a54fSMasatake YAMATO 
1254e475a54fSMasatake YAMATO 	if (es_null(cdr))
1255e475a54fSMasatake YAMATO 		return cons;
1256e475a54fSMasatake YAMATO 	else
1257e475a54fSMasatake YAMATO 		return es_cons_reverse_rec(es_cdr(cdr),
1258e475a54fSMasatake YAMATO 								   es_car(cdr),
1259e475a54fSMasatake YAMATO 								   cons);
1260e475a54fSMasatake YAMATO }
1261e475a54fSMasatake YAMATO 
1262e475a54fSMasatake YAMATO /*
1263e475a54fSMasatake YAMATO  * Regex
1264e475a54fSMasatake YAMATO  */
1265e475a54fSMasatake YAMATO EsObject*
es_regex_compile(const char * pattern_literal,int case_insensitive)1266e475a54fSMasatake YAMATO es_regex_compile   (const char* pattern_literal, int case_insensitive)
1267e475a54fSMasatake YAMATO {
1268e475a54fSMasatake YAMATO 	EsObject* r;
1269e475a54fSMasatake YAMATO 	regex_t *code;
1270e475a54fSMasatake YAMATO 	int err;
1271e475a54fSMasatake YAMATO 	int flag = REG_EXTENDED | REG_NEWLINE
1272e475a54fSMasatake YAMATO 		| (case_insensitive? REG_ICASE: 0);
1273e475a54fSMasatake YAMATO 
1274e475a54fSMasatake YAMATO 	code = malloc(sizeof(regex_t));
1275e475a54fSMasatake YAMATO 	if (!code)
1276e475a54fSMasatake YAMATO 		return ES_ERROR_MEMORY;
1277e475a54fSMasatake YAMATO 
1278e475a54fSMasatake YAMATO 	err = regcomp(code, pattern_literal,
1279e475a54fSMasatake YAMATO 				  flag);
1280e475a54fSMasatake YAMATO 	if (err)
1281e475a54fSMasatake YAMATO 	{
1282e475a54fSMasatake YAMATO #if 0
1283e475a54fSMasatake YAMATO /* TODO: This should be reported to caller. */
1284e475a54fSMasatake YAMATO 		char errmsg [256];
1285e475a54fSMasatake YAMATO 		regerror (err, code, errmsg, 256);
1286e475a54fSMasatake YAMATO #endif
1287e475a54fSMasatake YAMATO 		regfree (code);
1288e475a54fSMasatake YAMATO 		free (code);
1289e475a54fSMasatake YAMATO 		return ES_ERROR_REGEX;
1290e475a54fSMasatake YAMATO 	}
1291e475a54fSMasatake YAMATO 
1292e475a54fSMasatake YAMATO 	r = es_object_new(ES_TYPE_REGEX);
1293e475a54fSMasatake YAMATO 	((EsRegex*)r)->code = code;
1294e475a54fSMasatake YAMATO 	((EsRegex*)r)->literal = strdup(pattern_literal);
1295e475a54fSMasatake YAMATO 	if (!((EsRegex*)r)->literal)
1296e475a54fSMasatake YAMATO 	{
1297e475a54fSMasatake YAMATO 		regfree(((EsRegex*)r)->code);
1298e475a54fSMasatake YAMATO 		free(((EsRegex*)r)->code);
1299e475a54fSMasatake YAMATO 		es_object_free(r);
1300e475a54fSMasatake YAMATO 		return ES_ERROR_MEMORY;
1301e475a54fSMasatake YAMATO 	}
1302e475a54fSMasatake YAMATO 	((EsRegex*)r)->case_insensitive = case_insensitive;
1303e475a54fSMasatake YAMATO 	return r;
1304e475a54fSMasatake YAMATO }
1305e475a54fSMasatake YAMATO 
1306e475a54fSMasatake YAMATO int
es_regex_p(const EsObject * object)1307e475a54fSMasatake YAMATO es_regex_p   (const EsObject*   object)
1308e475a54fSMasatake YAMATO {
1309e475a54fSMasatake YAMATO 	return es_object_type_p(object, ES_TYPE_REGEX);
1310e475a54fSMasatake YAMATO }
1311e475a54fSMasatake YAMATO 
es_regex_free(EsObject * object)1312e475a54fSMasatake YAMATO static void es_regex_free(EsObject* object)
1313e475a54fSMasatake YAMATO {
1314e475a54fSMasatake YAMATO 	free(((EsRegex*)object)->literal);
1315e475a54fSMasatake YAMATO 	regfree(((EsRegex*)object)->code);
1316e475a54fSMasatake YAMATO 	free(((EsRegex*)object)->code);
1317e475a54fSMasatake YAMATO 	es_object_free(object);
1318e475a54fSMasatake YAMATO }
1319e475a54fSMasatake YAMATO 
1320e475a54fSMasatake YAMATO static int
es_regex_equal(const EsObject * self,const EsObject * other)1321e475a54fSMasatake YAMATO es_regex_equal(const EsObject* self, const EsObject* other)
1322e475a54fSMasatake YAMATO {
1323e475a54fSMasatake YAMATO 	return (es_regex_p (other)
1324e475a54fSMasatake YAMATO 			&& (strcmp (((EsRegex*)self)->literal,
1325e475a54fSMasatake YAMATO 						((EsRegex*)other)->literal) == 0)
1326e475a54fSMasatake YAMATO 			&& (((EsRegex*)self)->case_insensitive ==
1327e475a54fSMasatake YAMATO 				((EsRegex*)other)->case_insensitive));
1328e475a54fSMasatake YAMATO }
1329e475a54fSMasatake YAMATO 
1330e475a54fSMasatake YAMATO static void
es_regex_print(const EsObject * object,MIO * fp)1331e475a54fSMasatake YAMATO es_regex_print(const EsObject* object, MIO* fp)
1332e475a54fSMasatake YAMATO {
1333e475a54fSMasatake YAMATO 	mio_puts(fp, "#/");
1334e475a54fSMasatake YAMATO 	const char *s = ((EsRegex*)object)->literal;
1335e475a54fSMasatake YAMATO 	while (*s)
1336e475a54fSMasatake YAMATO 	{
1337e475a54fSMasatake YAMATO 		if (*s == '/')
1338e475a54fSMasatake YAMATO 			mio_putc(fp, '\\');
1339e475a54fSMasatake YAMATO 		mio_putc(fp, *s);
1340e475a54fSMasatake YAMATO 		s++;
1341e475a54fSMasatake YAMATO 	}
1342e475a54fSMasatake YAMATO 	mio_putc(fp, '/');
1343e475a54fSMasatake YAMATO 	if (((EsRegex*)object)->case_insensitive)
1344e475a54fSMasatake YAMATO 		mio_putc(fp, 'i');
1345e475a54fSMasatake YAMATO }
1346e475a54fSMasatake YAMATO 
1347e475a54fSMasatake YAMATO EsObject*
es_regex_exec(const EsObject * regex,const EsObject * str)1348e475a54fSMasatake YAMATO es_regex_exec    (const EsObject* regex,
1349e475a54fSMasatake YAMATO 				  const EsObject* str)
1350e475a54fSMasatake YAMATO {
1351e475a54fSMasatake YAMATO 	return regexec (((EsRegex*)regex)->code, es_string_get (str),
1352e475a54fSMasatake YAMATO 					0, NULL, 0)? es_false: es_true;
1353e475a54fSMasatake YAMATO }
1354e475a54fSMasatake YAMATO 
1355e475a54fSMasatake YAMATO /*
1356e475a54fSMasatake YAMATO  * Error
1357e475a54fSMasatake YAMATO  */
1358e475a54fSMasatake YAMATO EsObject*
es_error_intern(const char * name)1359e475a54fSMasatake YAMATO es_error_intern  (const char*       name)
1360e475a54fSMasatake YAMATO {
1361e475a54fSMasatake YAMATO 	EsSingleton* r;
1362e475a54fSMasatake YAMATO 
1363e475a54fSMasatake YAMATO 	r = es_obarray_intern(ES_TYPE_ERROR, name);
1364e475a54fSMasatake YAMATO 	return (EsObject*)r;
1365e475a54fSMasatake YAMATO }
1366e475a54fSMasatake YAMATO 
1367e475a54fSMasatake YAMATO int
es_error_p(const EsObject * object)1368e475a54fSMasatake YAMATO es_error_p    (const EsObject*   object)
1369e475a54fSMasatake YAMATO {
1370e475a54fSMasatake YAMATO 	return es_object_type_p(object, ES_TYPE_ERROR);
1371e475a54fSMasatake YAMATO }
1372e475a54fSMasatake YAMATO 
1373e475a54fSMasatake YAMATO const char*
es_error_name(const EsObject * object)1374e475a54fSMasatake YAMATO es_error_name  (const EsObject*   object)
1375e475a54fSMasatake YAMATO {
1376e475a54fSMasatake YAMATO 	if (es_error_p(object))
1377e475a54fSMasatake YAMATO 		return es_singleton_get((EsSingleton *)object);
1378e475a54fSMasatake YAMATO 	else
1379e475a54fSMasatake YAMATO     {
1380e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; es_error_name, Wrong type argument: ");
1381e475a54fSMasatake YAMATO 		es_print(object, mio_stderr());
1382e475a54fSMasatake YAMATO 		mio_putc(mio_stderr(), '\n');
1383e475a54fSMasatake YAMATO 		return NULL;
1384e475a54fSMasatake YAMATO     }
1385e475a54fSMasatake YAMATO }
1386e475a54fSMasatake YAMATO 
1387e475a54fSMasatake YAMATO EsObject*
es_error_set_object(EsObject * error,EsObject * object)1388e475a54fSMasatake YAMATO es_error_set_object (EsObject*   error, EsObject*   object)
1389e475a54fSMasatake YAMATO {
1390e475a54fSMasatake YAMATO 	EsError *e = (EsError *)error;
1391e475a54fSMasatake YAMATO 	if (e->object)
1392e475a54fSMasatake YAMATO 		es_object_unref (e->object);
1393e475a54fSMasatake YAMATO 
1394e475a54fSMasatake YAMATO 	e->object = es_object_ref (object);
1395e475a54fSMasatake YAMATO 	return error;
1396e475a54fSMasatake YAMATO }
1397e475a54fSMasatake YAMATO 
1398e475a54fSMasatake YAMATO EsObject*
es_error_get_object(const EsObject * error)1399e475a54fSMasatake YAMATO es_error_get_object (const EsObject*   error)
1400e475a54fSMasatake YAMATO {
1401e475a54fSMasatake YAMATO 	EsError *e = (EsError *)error;
1402e475a54fSMasatake YAMATO 	return e->object;
1403e475a54fSMasatake YAMATO }
1404e475a54fSMasatake YAMATO 
1405e475a54fSMasatake YAMATO static void
es_error_free(EsObject * object)1406e475a54fSMasatake YAMATO es_error_free(EsObject* object)
1407e475a54fSMasatake YAMATO {
1408e475a54fSMasatake YAMATO 	/* DO NOTHING */
1409e475a54fSMasatake YAMATO }
1410e475a54fSMasatake YAMATO 
1411e475a54fSMasatake YAMATO static int
es_error_equal(const EsObject * self,const EsObject * other)1412e475a54fSMasatake YAMATO es_error_equal(const EsObject* self, const EsObject* other)
1413e475a54fSMasatake YAMATO {
1414e475a54fSMasatake YAMATO 	return (self == other)? 1: 0;
1415e475a54fSMasatake YAMATO }
1416e475a54fSMasatake YAMATO 
1417e475a54fSMasatake YAMATO static void
es_error_print(const EsObject * object,MIO * fp)1418e475a54fSMasatake YAMATO es_error_print(const EsObject* object, MIO* fp)
1419e475a54fSMasatake YAMATO {
1420e475a54fSMasatake YAMATO 	const char* string;
1421e475a54fSMasatake YAMATO 	EsError *e = (EsError *)object;
1422e475a54fSMasatake YAMATO 
1423e475a54fSMasatake YAMATO 	string = es_error_name(object);
1424e475a54fSMasatake YAMATO 	mio_printf(fp, "#%s:", string);
1425e475a54fSMasatake YAMATO 	es_print (e->object, fp);
1426e475a54fSMasatake YAMATO }
1427e475a54fSMasatake YAMATO 
1428e475a54fSMasatake YAMATO /*
1429e475a54fSMasatake YAMATO  * Foreigner
1430e475a54fSMasatake YAMATO  */
1431e475a54fSMasatake YAMATO typedef struct _EsPointerClass EsPointerClass;
1432e475a54fSMasatake YAMATO struct _EsPointerClass
1433e475a54fSMasatake YAMATO {
1434e475a54fSMasatake YAMATO 	EsObjectClass base;
1435e7dc9661SMasatake YAMATO 
1436e7dc9661SMasatake YAMATO 	size_t fat_size;
1437e7dc9661SMasatake YAMATO 	EsObject *(* init_fat) (void *fat, void * ptr, void *extra);
1438e7dc9661SMasatake YAMATO 
1439e475a54fSMasatake YAMATO 	void (* free_ptr) (void *);
1440e475a54fSMasatake YAMATO 	int  (* equal_ptr) (const void*, const void*);
1441e475a54fSMasatake YAMATO 	void (* print_ptr) (const void*, MIO *);
1442e7dc9661SMasatake YAMATO 
1443e7dc9661SMasatake YAMATO 
1444e7dc9661SMasatake YAMATO 	void (* free_fatptr) (void *, void *);
1445e7dc9661SMasatake YAMATO 	int  (* equal_fatptr) (const void*, const void*,
1446e7dc9661SMasatake YAMATO 						   const void*, const void*);
1447e7dc9661SMasatake YAMATO 	void (* print_fatptr) (const void*, const void*, MIO *);
1448e475a54fSMasatake YAMATO };
1449e475a54fSMasatake YAMATO 
1450e7dc9661SMasatake YAMATO static EsType
es_type_define_pointer_full(const char * name,size_t fat_size,EsObject * (* initfat_fn)(void * fat,void * ptr,void * extra),void (* freefn)(void *),int (* equalfn)(const void *,const void *),void (* printfn)(const void *,MIO *),void (* freefn_fat)(void * ptr,void * fat),int (* equalfn_fat)(const void * ptr_a,const void * fat_a,const void * ptr_b,const void * fat_b),void (* printfn_fat)(const void * ptr,const void * fat,MIO *))1451e1e0f0f5SMasatake YAMATO es_type_define_pointer_full(const char *name,
1452e7dc9661SMasatake YAMATO 							size_t fat_size,
1453e7dc9661SMasatake YAMATO 							EsObject *(* initfat_fn) (void *fat, void * ptr, void *extra),
1454e475a54fSMasatake YAMATO 							void (* freefn) (void *),
1455e475a54fSMasatake YAMATO 							int  (* equalfn) (const void*, const void*),
1456e7dc9661SMasatake YAMATO 							void (* printfn) (const void*, MIO *),
1457e7dc9661SMasatake YAMATO 							void (* freefn_fat)  (void * ptr, void *fat),
1458e7dc9661SMasatake YAMATO 							int  (* equalfn_fat) (const void* ptr_a, const void* fat_a,
1459e7dc9661SMasatake YAMATO 												  const void* ptr_b, const void* fat_b),
1460e7dc9661SMasatake YAMATO 							void (* printfn_fat) (const void* ptr, const void *fat, MIO *))
1461e475a54fSMasatake YAMATO {
1462e475a54fSMasatake YAMATO 	EsType t = ES_TYPE_NIL;
1463e475a54fSMasatake YAMATO 	if (classes_count >= ES_TYPE_CLASS_MAX)
1464e475a54fSMasatake YAMATO 		return t;
1465e475a54fSMasatake YAMATO 
1466e475a54fSMasatake YAMATO 	EsPointerClass *c = calloc (1, sizeof (EsPointerClass));
1467e475a54fSMasatake YAMATO 	if (c == NULL)
1468e475a54fSMasatake YAMATO 		return t;
1469e475a54fSMasatake YAMATO 
1470e7dc9661SMasatake YAMATO 	c->fat_size  = fat_size;
1471e7dc9661SMasatake YAMATO 	c->init_fat = initfat_fn;
1472e7dc9661SMasatake YAMATO 	c->free_ptr  = freefn;
1473e7dc9661SMasatake YAMATO 	c->equal_ptr = equalfn;
1474e7dc9661SMasatake YAMATO 	c->print_ptr = printfn;
1475e7dc9661SMasatake YAMATO 	c->free_fatptr  = freefn_fat;
1476e7dc9661SMasatake YAMATO 	c->equal_fatptr = equalfn_fat;
1477e7dc9661SMasatake YAMATO 	c->print_fatptr = printfn_fat;
1478e7dc9661SMasatake YAMATO 
1479e7dc9661SMasatake YAMATO 	c->base.size  = sizeof (EsPointer) + c->fat_size;
1480e475a54fSMasatake YAMATO 	c->base.free  = es_pointer_free;
1481e475a54fSMasatake YAMATO 	c->base.equal = es_pointer_equal;
1482e475a54fSMasatake YAMATO 	c->base.print = es_pointer_print;
1483e475a54fSMasatake YAMATO 	c->base.flags = ES_OBJECT_FLAG_ATOM;
1484e475a54fSMasatake YAMATO 	c->base.name  = strdup (name);
1485e475a54fSMasatake YAMATO 	if (c->base.name == NULL)
1486e475a54fSMasatake YAMATO 	{
1487e475a54fSMasatake YAMATO 		free (c);
1488e475a54fSMasatake YAMATO 		return t;
1489e475a54fSMasatake YAMATO 	}
1490e475a54fSMasatake YAMATO 
1491e475a54fSMasatake YAMATO 	t = classes_count++;
1492e475a54fSMasatake YAMATO 	classes [t] = (EsObjectClass *)c;
1493e7dc9661SMasatake YAMATO 
1494e475a54fSMasatake YAMATO 	return t;
1495e475a54fSMasatake YAMATO }
1496e475a54fSMasatake YAMATO 
1497e7dc9661SMasatake YAMATO EsType
es_type_define_pointer(const char * name,void (* freefn)(void *),int (* equalfn)(const void *,const void *),void (* printfn)(const void *,MIO *))1498e1e0f0f5SMasatake YAMATO es_type_define_pointer(const char *name,
1499e7dc9661SMasatake YAMATO 					   void (* freefn) (void *),
1500e7dc9661SMasatake YAMATO 					   int  (* equalfn) (const void*, const void*),
1501e7dc9661SMasatake YAMATO 					   void (* printfn) (const void*, MIO *))
1502e7dc9661SMasatake YAMATO {
1503e7dc9661SMasatake YAMATO 
1504e1e0f0f5SMasatake YAMATO 	return es_type_define_pointer_full (name, 0, NULL,
1505e7dc9661SMasatake YAMATO 										freefn, equalfn, printfn,
1506e7dc9661SMasatake YAMATO 										NULL, NULL, NULL);
1507e7dc9661SMasatake YAMATO }
1508e7dc9661SMasatake YAMATO 
1509e7dc9661SMasatake YAMATO EsType
es_type_define_fatptr(const char * name,size_t fat_size,EsObject * (* initfat_fn)(void * fat,void * ptr,void * extra),void (* freefn)(void * ptr,void * fat),int (* equalfn)(const void * ptr_a,const void * fat_a,const void * ptr_b,const void * fat_b),void (* printfn)(const void * ptr,const void * fat,MIO *))1510e1e0f0f5SMasatake YAMATO es_type_define_fatptr    (const char *name,
1511e7dc9661SMasatake YAMATO 						  size_t fat_size,
1512e7dc9661SMasatake YAMATO 						  EsObject *(* initfat_fn) (void *fat, void * ptr, void *extra),
1513e7dc9661SMasatake YAMATO 						  void (* freefn) (void * ptr, void *fat),
1514e7dc9661SMasatake YAMATO 						  int  (* equalfn) (const void* ptr_a, const void* fat_a,
1515e7dc9661SMasatake YAMATO 											const void* ptr_b, const void* fat_b),
1516e7dc9661SMasatake YAMATO 						  void (* printfn) (const void* ptr, const void *fat, MIO *))
1517e7dc9661SMasatake YAMATO {
1518e1e0f0f5SMasatake YAMATO 	return es_type_define_pointer_full (name, fat_size, initfat_fn,
1519e7dc9661SMasatake YAMATO 										NULL, NULL, NULL,
1520e7dc9661SMasatake YAMATO 										freefn, equalfn, printfn);
1521e7dc9661SMasatake YAMATO }
1522e7dc9661SMasatake YAMATO 
es_pointer_free(EsObject * object)1523e475a54fSMasatake YAMATO static void es_pointer_free(EsObject* object)
1524e475a54fSMasatake YAMATO {
1525e475a54fSMasatake YAMATO 	EsObjectClass *c = class_of(object);
1526e475a54fSMasatake YAMATO 	if (((EsPointer*)object)->ptr)
1527e475a54fSMasatake YAMATO 	{
1528e7dc9661SMasatake YAMATO 		if (((EsPointerClass *)c)->free_fatptr)
1529e7dc9661SMasatake YAMATO 			((EsPointerClass *)c)->free_fatptr (((EsPointer*)object)->ptr,
1530e7dc9661SMasatake YAMATO 												((EsPointer*)object)->fat);
1531e7dc9661SMasatake YAMATO 		else if (((EsPointerClass *)c)->free_ptr)
1532e475a54fSMasatake YAMATO 			((EsPointerClass *)c)->free_ptr (((EsPointer*)object)->ptr);
1533e475a54fSMasatake YAMATO 	}
1534e475a54fSMasatake YAMATO 	es_object_free (object);
1535e475a54fSMasatake YAMATO }
1536e475a54fSMasatake YAMATO 
es_pointer_equal(const EsObject * self,const EsObject * other)1537e475a54fSMasatake YAMATO static int  es_pointer_equal(const EsObject* self, const EsObject* other)
1538e475a54fSMasatake YAMATO {
1539e475a54fSMasatake YAMATO 	if (es_object_get_type (self) != es_object_get_type (other))
1540e475a54fSMasatake YAMATO 		return 0;
1541e475a54fSMasatake YAMATO 
1542e7dc9661SMasatake YAMATO 	EsPointerClass *c = (EsPointerClass *)class_of(self);
1543e475a54fSMasatake YAMATO 	void *self_ptr  = ((EsPointer *)self)->ptr;
1544e475a54fSMasatake YAMATO 	void *other_ptr = ((EsPointer *)other)->ptr;
1545e475a54fSMasatake YAMATO 
1546e7dc9661SMasatake YAMATO 	if (c->fat_size == 0 && self_ptr == other_ptr)
1547e475a54fSMasatake YAMATO 		return 1;
1548e475a54fSMasatake YAMATO 
1549e475a54fSMasatake YAMATO 	if (self_ptr == NULL)
1550e475a54fSMasatake YAMATO 		return 0;
1551e475a54fSMasatake YAMATO 
1552e7dc9661SMasatake YAMATO 	if (c->equal_fatptr)
1553e7dc9661SMasatake YAMATO 		return c->equal_fatptr (self_ptr, ((EsPointer*)self)->fat,
1554e7dc9661SMasatake YAMATO 								other_ptr, ((EsPointer*)other)->fat);
1555e7dc9661SMasatake YAMATO 	else if (c->equal_ptr)
1556e7dc9661SMasatake YAMATO 		return c->equal_ptr (self_ptr, other_ptr);
1557e475a54fSMasatake YAMATO 	return 0;
1558e475a54fSMasatake YAMATO }
1559e475a54fSMasatake YAMATO 
es_pointer_print(const EsObject * object,MIO * fp)1560e475a54fSMasatake YAMATO static void es_pointer_print(const EsObject* object, MIO* fp)
1561e475a54fSMasatake YAMATO {
1562e475a54fSMasatake YAMATO 	EsObjectClass *c = class_of(object);
1563e7dc9661SMasatake YAMATO 	if (((EsPointerClass *)c)->print_fatptr)
1564e7dc9661SMasatake YAMATO 	{
1565e7dc9661SMasatake YAMATO 		((EsPointerClass *)c)->print_fatptr (((EsPointer *)object)->ptr,
1566e7dc9661SMasatake YAMATO 											 ((EsPointer *)object)->fat,
1567e7dc9661SMasatake YAMATO 											 fp);
1568e7dc9661SMasatake YAMATO 	}
1569e7dc9661SMasatake YAMATO 	else if (((EsPointerClass *)c)->print_ptr)
1570e475a54fSMasatake YAMATO 	{
1571e475a54fSMasatake YAMATO 		((EsPointerClass *)c)->print_ptr (((EsPointer *)object)->ptr, fp);
1572e475a54fSMasatake YAMATO 	}
1573b2774beeSMasatake YAMATO 	else
1574b2774beeSMasatake YAMATO 	{
1575b2774beeSMasatake YAMATO 		mio_puts(fp, "#<");
1576b2774beeSMasatake YAMATO 		mio_puts(fp, c->name);
1577b2774beeSMasatake YAMATO 		mio_putc(fp, ' ');
1578b2774beeSMasatake YAMATO 		mio_printf(fp, "(%p, %p)", object, ((EsPointer *)object)->ptr);
1579e475a54fSMasatake YAMATO 		mio_putc(fp, '>');
1580e475a54fSMasatake YAMATO 	}
1581b2774beeSMasatake YAMATO }
1582e475a54fSMasatake YAMATO 
1583e7dc9661SMasatake YAMATO static EsObject*
es_pointer_new_common(EsType type,void * ptr)1584e7dc9661SMasatake YAMATO es_pointer_new_common (EsType type, void *ptr)
1585e475a54fSMasatake YAMATO {
1586e475a54fSMasatake YAMATO 	EsObject *r;
1587e475a54fSMasatake YAMATO 
1588e475a54fSMasatake YAMATO 	r = es_object_new (type);
1589e475a54fSMasatake YAMATO 	if (es_error_p (r))
1590e475a54fSMasatake YAMATO 		return r;
1591e475a54fSMasatake YAMATO 
1592e475a54fSMasatake YAMATO 	((EsPointer *)r)->ptr = ptr;
1593e475a54fSMasatake YAMATO 	return r;
1594e475a54fSMasatake YAMATO }
1595e475a54fSMasatake YAMATO 
1596e7dc9661SMasatake YAMATO /*
1597e7dc9661SMasatake YAMATO  * Pointer
1598e7dc9661SMasatake YAMATO  */
1599e7dc9661SMasatake YAMATO EsObject*
es_pointer_new(EsType type,void * ptr)1600e7dc9661SMasatake YAMATO es_pointer_new (EsType type, void *ptr)
1601e7dc9661SMasatake YAMATO {
1602e7dc9661SMasatake YAMATO 	EsObject *r = es_pointer_new_common (type, ptr);
1603e7dc9661SMasatake YAMATO 	if (es_error_p (r))
1604e7dc9661SMasatake YAMATO 		return r;
1605e7dc9661SMasatake YAMATO 
1606e7dc9661SMasatake YAMATO 	if (((EsPointerClass *) (classes [type]))->fat_size > 0)
1607e7dc9661SMasatake YAMATO 		memset(((EsPointer *)r)->fat, 0,
1608e7dc9661SMasatake YAMATO 			   ((EsPointerClass *) (classes [type]))->fat_size);
1609e7dc9661SMasatake YAMATO 	return r;
1610e7dc9661SMasatake YAMATO }
1611e7dc9661SMasatake YAMATO 
1612e475a54fSMasatake YAMATO void*
es_pointer_get(const EsObject * object)1613e475a54fSMasatake YAMATO es_pointer_get    (const EsObject *object)
1614e475a54fSMasatake YAMATO {
1615e475a54fSMasatake YAMATO 	return ((EsPointer *)object)->ptr;
1616e475a54fSMasatake YAMATO }
1617e475a54fSMasatake YAMATO 
1618e475a54fSMasatake YAMATO void*
es_pointer_take(EsObject * object)1619e475a54fSMasatake YAMATO es_pointer_take    (EsObject *object)
1620e475a54fSMasatake YAMATO {
1621e475a54fSMasatake YAMATO 	void *r = ((EsPointer *)object)->ptr;
1622e475a54fSMasatake YAMATO 	((EsPointer *)object)->ptr = NULL;
1623e475a54fSMasatake YAMATO 	return r;
1624e475a54fSMasatake YAMATO }
1625e475a54fSMasatake YAMATO 
1626e7dc9661SMasatake YAMATO /*
1627e7dc9661SMasatake YAMATO  * Fat pointer
1628e7dc9661SMasatake YAMATO  */
1629e7dc9661SMasatake YAMATO EsObject*
es_fatptr_new(EsType type,void * ptr,void * extra)1630e7dc9661SMasatake YAMATO es_fatptr_new (EsType type, void *ptr, void *extra)
1631e7dc9661SMasatake YAMATO {
1632e7dc9661SMasatake YAMATO 	EsObject *r = es_pointer_new_common (type, ptr);
1633e7dc9661SMasatake YAMATO 	if (es_error_p (r))
1634e7dc9661SMasatake YAMATO 		return r;
1635e7dc9661SMasatake YAMATO 
1636e7dc9661SMasatake YAMATO 	if (((EsPointerClass *) (classes [type]))->fat_size > 0)
1637e7dc9661SMasatake YAMATO 	{
1638e7dc9661SMasatake YAMATO 		if (((EsPointerClass *) (classes [type]))->init_fat)
1639e7dc9661SMasatake YAMATO 		{
1640e7dc9661SMasatake YAMATO 			EsObject *f = (* ((EsPointerClass *) (classes [type]))->init_fat)
1641e7dc9661SMasatake YAMATO 				(((EsPointer *)r)->fat, ptr, extra);
1642e7dc9661SMasatake YAMATO 			if (es_error_p (f))
1643e7dc9661SMasatake YAMATO 			{
1644e7dc9661SMasatake YAMATO 				es_object_free (r);
1645e7dc9661SMasatake YAMATO 				return f;
1646e7dc9661SMasatake YAMATO 			}
1647e7dc9661SMasatake YAMATO 		}
1648e7dc9661SMasatake YAMATO 		else if (extra)
1649e7dc9661SMasatake YAMATO 			memcpy (((EsPointer *)r)->fat, extra,
1650e7dc9661SMasatake YAMATO 					((EsPointerClass *) (classes [type]))->fat_size);
1651e7dc9661SMasatake YAMATO 		else
1652e7dc9661SMasatake YAMATO 			memset(((EsPointer *)r)->fat, 0,
1653e7dc9661SMasatake YAMATO 				   ((EsPointerClass *) (classes [type]))->fat_size);
1654e7dc9661SMasatake YAMATO 	}
1655e7dc9661SMasatake YAMATO 	return r;
1656e7dc9661SMasatake YAMATO }
1657e7dc9661SMasatake YAMATO 
1658e7dc9661SMasatake YAMATO void*
es_fatptr_get(const EsObject * object)1659e7dc9661SMasatake YAMATO es_fatptr_get     (const EsObject *object)
1660e7dc9661SMasatake YAMATO {
1661e7dc9661SMasatake YAMATO 	EsObjectClass *c = class_of(object);
1662e7dc9661SMasatake YAMATO 	if (((EsPointerClass *)c)->fat_size == 0)
1663e7dc9661SMasatake YAMATO 		return NULL;
1664e7dc9661SMasatake YAMATO 
1665e7dc9661SMasatake YAMATO 	return ((EsPointer *)object)->fat;
1666e7dc9661SMasatake YAMATO }
1667e475a54fSMasatake YAMATO 
1668e475a54fSMasatake YAMATO 
1669e475a54fSMasatake YAMATO 
1670e475a54fSMasatake YAMATO /* http://www.cse.yorku.ca/~oz/hash.html */
1671e475a54fSMasatake YAMATO static unsigned long
djb2(unsigned char * str)1672e475a54fSMasatake YAMATO djb2(unsigned char *str)
1673e475a54fSMasatake YAMATO {
1674e475a54fSMasatake YAMATO 	unsigned long hash = 5381;
1675e475a54fSMasatake YAMATO 	int c;
1676e475a54fSMasatake YAMATO 
1677e475a54fSMasatake YAMATO 	while ((c = *str++))
1678e475a54fSMasatake YAMATO 		hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
1679e475a54fSMasatake YAMATO 
1680e475a54fSMasatake YAMATO 	return hash;
1681e475a54fSMasatake YAMATO }
1682e475a54fSMasatake YAMATO 
hash(const char * keyarg)1683e475a54fSMasatake YAMATO static unsigned int hash(const char* keyarg)
1684e475a54fSMasatake YAMATO {
1685e475a54fSMasatake YAMATO 	return ((unsigned int)djb2((unsigned char *)keyarg)) % OBARRAY_SIZE;
1686e475a54fSMasatake YAMATO }
1687e475a54fSMasatake YAMATO 
1688e475a54fSMasatake YAMATO /*
1689e475a54fSMasatake YAMATO  * Print
1690e475a54fSMasatake YAMATO  */
1691e475a54fSMasatake YAMATO void
es_print(const EsObject * object,MIO * out)1692e475a54fSMasatake YAMATO es_print           (const EsObject* object,
1693e475a54fSMasatake YAMATO 					MIO*           out)
1694e475a54fSMasatake YAMATO {
1695e475a54fSMasatake YAMATO 	class_of(object)->print(object, out? out: mio_stdout());
1696e475a54fSMasatake YAMATO }
1697e475a54fSMasatake YAMATO 
1698e475a54fSMasatake YAMATO 
1699e475a54fSMasatake YAMATO char*
es_print_to_string(EsObject * object)1700e475a54fSMasatake YAMATO es_print_to_string (EsObject*        object)
1701e475a54fSMasatake YAMATO {
1702e475a54fSMasatake YAMATO 	char *bp;
1703e475a54fSMasatake YAMATO 	size_t size;
1704e475a54fSMasatake YAMATO 	MIO* out;
1705e475a54fSMasatake YAMATO 
1706e475a54fSMasatake YAMATO 
1707e475a54fSMasatake YAMATO 	out = mio_new_memory (NULL, 0, realloc, NULL);
1708e475a54fSMasatake YAMATO 	if (!out)
1709e475a54fSMasatake YAMATO     {
1710e475a54fSMasatake YAMATO 		/* TODO: Report error */
1711e475a54fSMasatake YAMATO 		return NULL;
1712e475a54fSMasatake YAMATO     }
1713e475a54fSMasatake YAMATO 
1714e475a54fSMasatake YAMATO 	es_print(object, out);
1715e475a54fSMasatake YAMATO 	bp = (char *)mio_memory_get_data (out, &size);
1716e475a54fSMasatake YAMATO 	mio_unref(out);
1717e475a54fSMasatake YAMATO 
1718e475a54fSMasatake YAMATO 	return bp;
1719e475a54fSMasatake YAMATO }
1720e475a54fSMasatake YAMATO 
1721e475a54fSMasatake YAMATO static const char* comment_prefix = ";; ";
1722e475a54fSMasatake YAMATO void
es_comment(const char * comment,MIO * out)1723e475a54fSMasatake YAMATO es_comment (const char* comment, MIO* out)
1724e475a54fSMasatake YAMATO {
1725e475a54fSMasatake YAMATO 	const char* p;
1726e475a54fSMasatake YAMATO 	const char* c;
1727e475a54fSMasatake YAMATO 
1728e475a54fSMasatake YAMATO 	p = comment_prefix? comment_prefix: ";; ";
1729e475a54fSMasatake YAMATO 	c = comment? comment: "";
1730e475a54fSMasatake YAMATO 	out = out? out: mio_stdout();
1731e475a54fSMasatake YAMATO 
1732e475a54fSMasatake YAMATO 	/* ""
1733e475a54fSMasatake YAMATO 	   => ;;
1734e475a54fSMasatake YAMATO 
1735e475a54fSMasatake YAMATO 	   "a"
1736e475a54fSMasatake YAMATO 	   => ;; a
1737e475a54fSMasatake YAMATO 
1738e475a54fSMasatake YAMATO 	   "a\n"
1739e475a54fSMasatake YAMATO 	   => ;; a
1740e475a54fSMasatake YAMATO 
1741e475a54fSMasatake YAMATO 
1742e475a54fSMasatake YAMATO 	   "a\nb"
1743e475a54fSMasatake YAMATO 	   => ;; a
1744e475a54fSMasatake YAMATO 	   ;; b
1745e475a54fSMasatake YAMATO 
1746e475a54fSMasatake YAMATO 	   "a\nb\n"
1747e475a54fSMasatake YAMATO 	   => ;; a
1748e475a54fSMasatake YAMATO 	   ;;b
1749e475a54fSMasatake YAMATO 
1750e475a54fSMasatake YAMATO 
1751e475a54fSMasatake YAMATO 	*/
1752e475a54fSMasatake YAMATO 	while (1)
1753e475a54fSMasatake YAMATO     {
1754e475a54fSMasatake YAMATO 		mio_puts(out, p);
1755e475a54fSMasatake YAMATO 
1756e475a54fSMasatake YAMATO 		while(1)
1757e475a54fSMasatake YAMATO 		{
1758e475a54fSMasatake YAMATO 			if (*c == '\0')
1759e475a54fSMasatake YAMATO 			{
1760e475a54fSMasatake YAMATO 				mio_putc(out, '\n');
1761e475a54fSMasatake YAMATO 				return;
1762e475a54fSMasatake YAMATO 			}
1763e475a54fSMasatake YAMATO 			else
1764e475a54fSMasatake YAMATO 			{
1765e475a54fSMasatake YAMATO 				mio_putc(out, *c++);
1766e475a54fSMasatake YAMATO 				if (*(c - 1) == '\n')
1767e475a54fSMasatake YAMATO 					break;
1768e475a54fSMasatake YAMATO 			}
1769e475a54fSMasatake YAMATO 		}
1770e475a54fSMasatake YAMATO     }
1771e475a54fSMasatake YAMATO }
1772e475a54fSMasatake YAMATO 
1773e475a54fSMasatake YAMATO char*
es_comment_to_string(const char * comment)1774e475a54fSMasatake YAMATO es_comment_to_string (const char* comment)
1775e475a54fSMasatake YAMATO {
1776e475a54fSMasatake YAMATO 	char *bp;
1777e475a54fSMasatake YAMATO 	size_t size;
1778e475a54fSMasatake YAMATO 	MIO* out;
1779e475a54fSMasatake YAMATO 
1780e475a54fSMasatake YAMATO 	out = mio_new_memory (NULL, 0, realloc, NULL);
1781e475a54fSMasatake YAMATO 	if (!out)
1782e475a54fSMasatake YAMATO     {
1783e475a54fSMasatake YAMATO 		/* TODO: Report error */
1784e475a54fSMasatake YAMATO 		return NULL;
1785e475a54fSMasatake YAMATO     }
1786e475a54fSMasatake YAMATO 
1787e475a54fSMasatake YAMATO 	es_comment(comment, out);
1788e475a54fSMasatake YAMATO 	bp = (char *)mio_memory_get_data (out, &size);
1789e475a54fSMasatake YAMATO 	mio_unref(out);
1790e475a54fSMasatake YAMATO 
1791e475a54fSMasatake YAMATO 	return bp;
1792e475a54fSMasatake YAMATO }
1793e475a54fSMasatake YAMATO 
1794e475a54fSMasatake YAMATO 
1795e475a54fSMasatake YAMATO 
1796e475a54fSMasatake YAMATO 
1797e475a54fSMasatake YAMATO /*
1798e475a54fSMasatake YAMATO  * Read
1799e475a54fSMasatake YAMATO  */
1800e475a54fSMasatake YAMATO typedef struct _Token Token;
1801e475a54fSMasatake YAMATO struct _Token
1802e475a54fSMasatake YAMATO {
1803e475a54fSMasatake YAMATO 	char*  buffer;
1804e475a54fSMasatake YAMATO 	size_t filled;
1805e475a54fSMasatake YAMATO 	size_t allocated;
1806e475a54fSMasatake YAMATO };
1807e475a54fSMasatake YAMATO static Token* token_new   (char seed);
1808e475a54fSMasatake YAMATO static void   token_free  (Token* token);
1809e475a54fSMasatake YAMATO static Token* token_append(Token* token, char c);
1810e475a54fSMasatake YAMATO 
1811e475a54fSMasatake YAMATO static Token  eof_token;
1812e475a54fSMasatake YAMATO #define EOF_TOKEN         (&eof_token)
1813e475a54fSMasatake YAMATO static Token  open_paren_token;
1814e475a54fSMasatake YAMATO #define OPEN_PAREN_TOKEN  (&open_paren_token)
1815e475a54fSMasatake YAMATO static Token  close_paren_token;
1816e475a54fSMasatake YAMATO #define CLOSE_PAREN_TOKEN (&close_paren_token)
1817e475a54fSMasatake YAMATO 
1818e475a54fSMasatake YAMATO static Token*   get_token      (MIO* in);
1819e475a54fSMasatake YAMATO static void     skip_to_newline(MIO* in);
1820e475a54fSMasatake YAMATO static int      is_whitespace    (char c);
1821e475a54fSMasatake YAMATO static int      is_paren_open    (char c);
1822e475a54fSMasatake YAMATO static int      is_paren_close   (char c);
1823e475a54fSMasatake YAMATO static int      is_comment_start (char c);
1824e475a54fSMasatake YAMATO static int      is_string_start  (char c);
1825e475a54fSMasatake YAMATO static int      is_fence_start   (char c);
1826e475a54fSMasatake YAMATO static int      is_reader_macro_prefix(char c);
1827e475a54fSMasatake YAMATO 
1828e475a54fSMasatake YAMATO typedef
1829e475a54fSMasatake YAMATO int (*TerminalDetector) (int c);
1830e475a54fSMasatake YAMATO 
1831e475a54fSMasatake YAMATO static int is_string_end       (int c);
1832e475a54fSMasatake YAMATO static int is_fence_end        (int c);
1833e475a54fSMasatake YAMATO static int is_separator        (int c);
1834e475a54fSMasatake YAMATO 
1835e475a54fSMasatake YAMATO static Token* get_sequence      (MIO* fp,
1836e475a54fSMasatake YAMATO 								 Token* seed,
1837e475a54fSMasatake YAMATO 								 TerminalDetector is_terminator,
1838e475a54fSMasatake YAMATO 								 int              include_terminator);
1839e475a54fSMasatake YAMATO static Token* get_string        (MIO* fp, char seed);
1840e475a54fSMasatake YAMATO static Token* get_escaped_symbol(MIO* fp, char seed);
1841e475a54fSMasatake YAMATO static Token* get_symbol        (MIO* fp, char seed);
1842e475a54fSMasatake YAMATO static Token* get_regex         (MIO* fp);
1843e475a54fSMasatake YAMATO static void   inject_regex_flag (Token* t, char c);
1844e475a54fSMasatake YAMATO 
1845e475a54fSMasatake YAMATO static EsObject* fill_list    (MIO*  fp);
1846e475a54fSMasatake YAMATO static EsObject* make_atom    (Token* token);
1847e475a54fSMasatake YAMATO static EsObject* make_string  (char* t);
1848e475a54fSMasatake YAMATO static EsObject* make_symbol  (char* t,
1849e475a54fSMasatake YAMATO 							   int is_wrapped);
1850e475a54fSMasatake YAMATO static EsObject* make_boolean (int b);
1851e475a54fSMasatake YAMATO static int  is_integer   (const char* t,
1852e475a54fSMasatake YAMATO 						  int* i);
1853e475a54fSMasatake YAMATO static EsObject* make_integer (int  i);
1854e475a54fSMasatake YAMATO static int  is_real      (const char* t,
1855e475a54fSMasatake YAMATO 						  double* d);
1856e475a54fSMasatake YAMATO static EsObject* make_real    (double d);
1857e475a54fSMasatake YAMATO static EsObject* make_regex (const char *pat,
1858e475a54fSMasatake YAMATO 							 int case_insensitive);
1859e475a54fSMasatake YAMATO 
1860e475a54fSMasatake YAMATO 
1861e475a54fSMasatake YAMATO EsObject*
es_read(MIO * in)1862e475a54fSMasatake YAMATO es_read            (MIO* in)
1863e475a54fSMasatake YAMATO {
1864e475a54fSMasatake YAMATO 	Token* t;
1865e475a54fSMasatake YAMATO 	EsObject* r;
1866e475a54fSMasatake YAMATO 
1867e475a54fSMasatake YAMATO 
1868e475a54fSMasatake YAMATO 	in = in? in: mio_stdin();
1869e475a54fSMasatake YAMATO 
1870e475a54fSMasatake YAMATO 	t = get_token(in);
1871e475a54fSMasatake YAMATO 
1872e475a54fSMasatake YAMATO 	if (t == NULL)
1873e475a54fSMasatake YAMATO 		return ES_READER_ERROR;
1874e475a54fSMasatake YAMATO 	else if (t == EOF_TOKEN)
1875e475a54fSMasatake YAMATO 		return ES_READER_EOF;
1876e475a54fSMasatake YAMATO 	else if (t == OPEN_PAREN_TOKEN)
1877e475a54fSMasatake YAMATO 		r = fill_list(in);
1878e475a54fSMasatake YAMATO 	else if (t == CLOSE_PAREN_TOKEN)
1879e475a54fSMasatake YAMATO 		return ES_READER_ERROR;
1880e475a54fSMasatake YAMATO 	else
1881e475a54fSMasatake YAMATO 		r = make_atom(t);
1882e475a54fSMasatake YAMATO 
1883e475a54fSMasatake YAMATO 	token_free(t);
1884e475a54fSMasatake YAMATO 
1885e475a54fSMasatake YAMATO 	return r;
1886e475a54fSMasatake YAMATO }
1887e475a54fSMasatake YAMATO 
1888e475a54fSMasatake YAMATO 
1889e475a54fSMasatake YAMATO static Token*
get_token(MIO * in)1890e475a54fSMasatake YAMATO get_token(MIO* in)
1891e475a54fSMasatake YAMATO {
1892e475a54fSMasatake YAMATO 	Token* t;
1893e475a54fSMasatake YAMATO 
1894e475a54fSMasatake YAMATO 	int c;
1895e475a54fSMasatake YAMATO 	while (1)
1896e475a54fSMasatake YAMATO     {
1897e475a54fSMasatake YAMATO 		c = mio_getc(in);
1898e475a54fSMasatake YAMATO 
1899e475a54fSMasatake YAMATO 		if (c == EOF)
1900e475a54fSMasatake YAMATO 		{
1901e475a54fSMasatake YAMATO 			t = EOF_TOKEN;
1902e475a54fSMasatake YAMATO 			break;
1903e475a54fSMasatake YAMATO 		}
1904e475a54fSMasatake YAMATO 		else
1905e475a54fSMasatake YAMATO 		{
1906e475a54fSMasatake YAMATO 			char c0;
1907e475a54fSMasatake YAMATO 
1908e475a54fSMasatake YAMATO 			c0 = (char)c;
1909e475a54fSMasatake YAMATO 
1910e475a54fSMasatake YAMATO 			if (is_whitespace(c0))
1911e475a54fSMasatake YAMATO 				continue;
1912e475a54fSMasatake YAMATO 			else if (is_comment_start(c0))
1913e475a54fSMasatake YAMATO 			{
1914e475a54fSMasatake YAMATO 				skip_to_newline(in);
1915e475a54fSMasatake YAMATO 				/* TODO */
1916e475a54fSMasatake YAMATO 				continue;
1917e475a54fSMasatake YAMATO 			}
1918e475a54fSMasatake YAMATO 			else if (is_paren_open(c0))
1919e475a54fSMasatake YAMATO 			{
1920e475a54fSMasatake YAMATO 				t = OPEN_PAREN_TOKEN;
1921e475a54fSMasatake YAMATO 				break;
1922e475a54fSMasatake YAMATO 			}
1923e475a54fSMasatake YAMATO 			else if (is_paren_close(c0))
1924e475a54fSMasatake YAMATO 			{
1925e475a54fSMasatake YAMATO 				t = CLOSE_PAREN_TOKEN;
1926e475a54fSMasatake YAMATO 				break;
1927e475a54fSMasatake YAMATO 			}
1928e475a54fSMasatake YAMATO 			else if (is_string_start(c0))
1929e475a54fSMasatake YAMATO 			{
1930e475a54fSMasatake YAMATO 				t = get_string(in, c0);
1931e475a54fSMasatake YAMATO 				break;
1932e475a54fSMasatake YAMATO 			}
1933e475a54fSMasatake YAMATO 			else if (is_fence_start(c0))
1934e475a54fSMasatake YAMATO 			{
1935e475a54fSMasatake YAMATO 				t = get_escaped_symbol(in, c0);
1936e475a54fSMasatake YAMATO 				break;
1937e475a54fSMasatake YAMATO 			}
1938e475a54fSMasatake YAMATO 			else if (is_reader_macro_prefix(c0))
1939e475a54fSMasatake YAMATO 			{
1940e475a54fSMasatake YAMATO 				c = mio_getc(in);
1941e475a54fSMasatake YAMATO 				if (c == EOF)
1942e475a54fSMasatake YAMATO 				{
1943e475a54fSMasatake YAMATO 					t = get_symbol(in, c0);
1944e475a54fSMasatake YAMATO 					break;
1945e475a54fSMasatake YAMATO 				}
1946e475a54fSMasatake YAMATO 				else if (c == '/')
1947e475a54fSMasatake YAMATO 				{
1948e475a54fSMasatake YAMATO 					t = get_regex(in);
1949e475a54fSMasatake YAMATO 					break;
1950e475a54fSMasatake YAMATO 				}
1951e475a54fSMasatake YAMATO 				else
1952e475a54fSMasatake YAMATO 				{
1953e475a54fSMasatake YAMATO 					mio_ungetc (in, c);
1954e475a54fSMasatake YAMATO 					t = get_symbol(in, c0);
1955e475a54fSMasatake YAMATO 					break;
1956e475a54fSMasatake YAMATO 				}
1957e475a54fSMasatake YAMATO 			}
1958e475a54fSMasatake YAMATO 			else
1959e475a54fSMasatake YAMATO 			{
1960e475a54fSMasatake YAMATO 				t = get_symbol(in, c0);
1961e475a54fSMasatake YAMATO 				break;
1962e475a54fSMasatake YAMATO 			}
1963e475a54fSMasatake YAMATO 		}
1964e475a54fSMasatake YAMATO     }
1965e475a54fSMasatake YAMATO 
1966e475a54fSMasatake YAMATO 	return t;
1967e475a54fSMasatake YAMATO }
1968e475a54fSMasatake YAMATO 
1969e475a54fSMasatake YAMATO static int
is_whitespace(char c)1970e475a54fSMasatake YAMATO is_whitespace    (char c)
1971e475a54fSMasatake YAMATO {
1972e475a54fSMasatake YAMATO 	static const char* const whitespace_chars = " \t\n\r\f";
1973e475a54fSMasatake YAMATO 
1974e475a54fSMasatake YAMATO 	return strchr(whitespace_chars, c)? 1: 0;
1975e475a54fSMasatake YAMATO }
1976e475a54fSMasatake YAMATO 
1977e475a54fSMasatake YAMATO static int
is_paren_open(char c)1978e475a54fSMasatake YAMATO is_paren_open    (char c)
1979e475a54fSMasatake YAMATO {
1980e475a54fSMasatake YAMATO 	return (c == '(')? 1: 0;
1981e475a54fSMasatake YAMATO }
1982e475a54fSMasatake YAMATO 
1983e475a54fSMasatake YAMATO static int
is_paren_close(char c)1984e475a54fSMasatake YAMATO is_paren_close   (char c)
1985e475a54fSMasatake YAMATO {
1986e475a54fSMasatake YAMATO 	return (c == ')')? 1: 0;
1987e475a54fSMasatake YAMATO }
1988e475a54fSMasatake YAMATO 
1989e475a54fSMasatake YAMATO static int
is_comment_start(char c)1990e475a54fSMasatake YAMATO is_comment_start (char c)
1991e475a54fSMasatake YAMATO {
1992e475a54fSMasatake YAMATO 	return (c == ';')? 1: 0;
1993e475a54fSMasatake YAMATO }
1994e475a54fSMasatake YAMATO 
1995e475a54fSMasatake YAMATO static int
is_string_start(char c)1996e475a54fSMasatake YAMATO is_string_start  (char c)
1997e475a54fSMasatake YAMATO {
1998e475a54fSMasatake YAMATO 	return (c == '"')? 1: 0;
1999e475a54fSMasatake YAMATO }
2000e475a54fSMasatake YAMATO 
2001e475a54fSMasatake YAMATO static int
is_fence_start(char c)2002e475a54fSMasatake YAMATO is_fence_start  (char c)
2003e475a54fSMasatake YAMATO {
2004e475a54fSMasatake YAMATO 	return (c == '|')? 1: 0;
2005e475a54fSMasatake YAMATO }
2006e475a54fSMasatake YAMATO 
2007e475a54fSMasatake YAMATO static int
is_reader_macro_prefix(char c)2008e475a54fSMasatake YAMATO is_reader_macro_prefix(char c)
2009e475a54fSMasatake YAMATO {
2010e475a54fSMasatake YAMATO 	return (c == '#')? 1: 0;
2011e475a54fSMasatake YAMATO }
2012e475a54fSMasatake YAMATO 
2013e475a54fSMasatake YAMATO static void
skip_to_newline(MIO * fp)2014e475a54fSMasatake YAMATO skip_to_newline  (MIO* fp)
2015e475a54fSMasatake YAMATO {
2016e475a54fSMasatake YAMATO 	int c;
2017e475a54fSMasatake YAMATO 
2018e475a54fSMasatake YAMATO 
2019e475a54fSMasatake YAMATO 	while (1)
2020e475a54fSMasatake YAMATO     {
2021e475a54fSMasatake YAMATO 		char c0;
2022e475a54fSMasatake YAMATO 
2023e475a54fSMasatake YAMATO 
2024e475a54fSMasatake YAMATO 		c = mio_getc(fp);
2025e475a54fSMasatake YAMATO 		if (c == EOF)
2026e475a54fSMasatake YAMATO 			break;
2027e475a54fSMasatake YAMATO 
2028e475a54fSMasatake YAMATO 		c0 = (char)c;
2029e475a54fSMasatake YAMATO 		if (c0 == '\n')
2030e475a54fSMasatake YAMATO 			break;
2031e475a54fSMasatake YAMATO     }
2032e475a54fSMasatake YAMATO }
2033e475a54fSMasatake YAMATO 
2034e475a54fSMasatake YAMATO static int
is_string_end(int c)2035e475a54fSMasatake YAMATO is_string_end    (int c)
2036e475a54fSMasatake YAMATO {
2037e475a54fSMasatake YAMATO 	return ((char)(c) == '"')? 1: 0;
2038e475a54fSMasatake YAMATO }
2039e475a54fSMasatake YAMATO 
2040e475a54fSMasatake YAMATO static int
is_fence_end(int c)2041e475a54fSMasatake YAMATO is_fence_end     (int c)
2042e475a54fSMasatake YAMATO {
2043e475a54fSMasatake YAMATO 	return ((char)(c) == '|')? 1: 0;
2044e475a54fSMasatake YAMATO }
2045e475a54fSMasatake YAMATO 
2046e475a54fSMasatake YAMATO static int
is_separator(int c)2047e475a54fSMasatake YAMATO is_separator     (int c)
2048e475a54fSMasatake YAMATO {
2049e475a54fSMasatake YAMATO 	if (c == EOF)
2050e475a54fSMasatake YAMATO 		return 1;
2051e475a54fSMasatake YAMATO 	else
2052e475a54fSMasatake YAMATO     {
2053e475a54fSMasatake YAMATO 		char c0;
2054e475a54fSMasatake YAMATO 
2055e475a54fSMasatake YAMATO 
2056e475a54fSMasatake YAMATO 		c0 = (char)(c);
2057e475a54fSMasatake YAMATO 		if (is_whitespace(c0)
2058e475a54fSMasatake YAMATO 			|| is_comment_start(c0)
2059e475a54fSMasatake YAMATO 			|| is_paren_open(c0)
2060e475a54fSMasatake YAMATO 			|| is_paren_close(c0)
2061e475a54fSMasatake YAMATO 			|| is_string_start(c0)
2062e475a54fSMasatake YAMATO 			|| is_fence_start(c0))
2063e475a54fSMasatake YAMATO 			return 1;
2064e475a54fSMasatake YAMATO     }
2065e475a54fSMasatake YAMATO 
2066e475a54fSMasatake YAMATO 	return 0;
2067e475a54fSMasatake YAMATO }
2068e475a54fSMasatake YAMATO 
2069e475a54fSMasatake YAMATO static Token*
get_string(MIO * fp,char seed)2070e475a54fSMasatake YAMATO get_string         (MIO* fp,
2071e475a54fSMasatake YAMATO 					char seed)
2072e475a54fSMasatake YAMATO {
2073e475a54fSMasatake YAMATO 	Token* t;
2074e475a54fSMasatake YAMATO 
2075e475a54fSMasatake YAMATO 	t = token_new(seed);
2076e475a54fSMasatake YAMATO 	return get_sequence(fp, t, is_string_end, 1);
2077e475a54fSMasatake YAMATO }
2078e475a54fSMasatake YAMATO 
2079e475a54fSMasatake YAMATO static Token*
get_escaped_symbol(MIO * fp,char seed)2080e475a54fSMasatake YAMATO get_escaped_symbol (MIO* fp,
2081e475a54fSMasatake YAMATO 					char seed)
2082e475a54fSMasatake YAMATO {
2083e475a54fSMasatake YAMATO 	Token* t;
2084e475a54fSMasatake YAMATO 
2085e475a54fSMasatake YAMATO 	t = token_new(seed);
2086e475a54fSMasatake YAMATO 	return get_sequence(fp, t, is_fence_end, 1);
2087e475a54fSMasatake YAMATO }
2088e475a54fSMasatake YAMATO 
2089e475a54fSMasatake YAMATO static Token*
get_symbol(MIO * fp,char seed)2090e475a54fSMasatake YAMATO get_symbol         (MIO* fp,
2091e475a54fSMasatake YAMATO 					char seed)
2092e475a54fSMasatake YAMATO {
2093e475a54fSMasatake YAMATO 	Token* t;
2094e475a54fSMasatake YAMATO 
2095e475a54fSMasatake YAMATO 	t = token_new(seed);
2096e475a54fSMasatake YAMATO 	return get_sequence(fp, t, is_separator, 0);
2097e475a54fSMasatake YAMATO }
2098e475a54fSMasatake YAMATO 
2099e475a54fSMasatake YAMATO static Token*
get_regex(MIO * fp)2100e475a54fSMasatake YAMATO get_regex (MIO* fp)
2101e475a54fSMasatake YAMATO {
2102e475a54fSMasatake YAMATO 	Token *t;
2103e475a54fSMasatake YAMATO 	t = token_new('#');
2104e475a54fSMasatake YAMATO 	if (!t)
2105e475a54fSMasatake YAMATO 		return NULL;
2106e475a54fSMasatake YAMATO 
2107e475a54fSMasatake YAMATO 	if (!token_append(t, '/'))
2108e475a54fSMasatake YAMATO 		return NULL;
2109e475a54fSMasatake YAMATO 
2110e475a54fSMasatake YAMATO 	/* Inject a placeholder representing
2111e475a54fSMasatake YAMATO 	 * case-{in}sesitive. */
2112e475a54fSMasatake YAMATO 	if (!token_append(t, ' '))
2113e475a54fSMasatake YAMATO 		return NULL;
2114e475a54fSMasatake YAMATO 
2115e475a54fSMasatake YAMATO 	int c;
2116e475a54fSMasatake YAMATO 	int in_escape = 0;
2117e475a54fSMasatake YAMATO 	while (1)
2118e475a54fSMasatake YAMATO 	{
2119e475a54fSMasatake YAMATO 		c = mio_getc(fp);
2120e475a54fSMasatake YAMATO 		if (EOF == c)
2121e475a54fSMasatake YAMATO 		{
2122e475a54fSMasatake YAMATO 			/* TODO: Propagate the error to upper layer. */
2123e475a54fSMasatake YAMATO 			mio_printf(mio_stderr(),
2124e475a54fSMasatake YAMATO 					   ";; unexpected termination during parsing regex pattern\n");
2125e475a54fSMasatake YAMATO 			token_free (t);
2126e475a54fSMasatake YAMATO 			return NULL;
2127e475a54fSMasatake YAMATO 		}
2128e475a54fSMasatake YAMATO 
2129e475a54fSMasatake YAMATO 		char c0 = c;
2130e475a54fSMasatake YAMATO 		if (in_escape)
2131e475a54fSMasatake YAMATO 		{
2132e475a54fSMasatake YAMATO 			in_escape = 0;
2133e475a54fSMasatake YAMATO 
2134e475a54fSMasatake YAMATO 			if (c0 == 'n')
2135e475a54fSMasatake YAMATO 				c0 = '\n';
2136e475a54fSMasatake YAMATO 			else if (c0 == 't')
2137e475a54fSMasatake YAMATO 				c0 = '\t';
2138e475a54fSMasatake YAMATO 			else if (c0 != '/')
2139e475a54fSMasatake YAMATO 			{
2140e475a54fSMasatake YAMATO 				if (!token_append(t, '\\'))
2141e475a54fSMasatake YAMATO 					return NULL;
2142e475a54fSMasatake YAMATO 			}
2143e475a54fSMasatake YAMATO 
2144e475a54fSMasatake YAMATO 			if (!token_append(t, c0))
2145e475a54fSMasatake YAMATO 				return NULL;
2146e475a54fSMasatake YAMATO 		}
2147e475a54fSMasatake YAMATO 		else if (c0 == '\\')
2148e475a54fSMasatake YAMATO 			in_escape = 1;
2149e475a54fSMasatake YAMATO 		else if (c0 == '/')
2150e475a54fSMasatake YAMATO 		{
2151e475a54fSMasatake YAMATO 			c = mio_getc(fp);
2152e475a54fSMasatake YAMATO 			if (c == 'i')
2153e475a54fSMasatake YAMATO 				/* Refill the placeholder. */
2154e475a54fSMasatake YAMATO 				inject_regex_flag (t, 'i');
2155e475a54fSMasatake YAMATO 			else if (c != EOF)
2156e475a54fSMasatake YAMATO 				mio_ungetc (fp, c);
2157e475a54fSMasatake YAMATO 			break;
2158e475a54fSMasatake YAMATO 		}
2159e475a54fSMasatake YAMATO 		else
2160e475a54fSMasatake YAMATO 			if (!token_append(t, c0))
2161e475a54fSMasatake YAMATO 				return NULL;
2162e475a54fSMasatake YAMATO 	}
2163e475a54fSMasatake YAMATO 	return t;
2164e475a54fSMasatake YAMATO }
2165e475a54fSMasatake YAMATO 
2166e475a54fSMasatake YAMATO static void
dump_token(MIO * stream,const char * prefix,Token * seed)2167e475a54fSMasatake YAMATO dump_token (MIO* stream, const char* prefix, Token* seed)
2168e475a54fSMasatake YAMATO {
2169e475a54fSMasatake YAMATO 	const char* buf;
2170e475a54fSMasatake YAMATO 	int i;
2171e475a54fSMasatake YAMATO 	char  c;
2172e475a54fSMasatake YAMATO 
2173e475a54fSMasatake YAMATO 
2174e475a54fSMasatake YAMATO 	buf = seed->buffer;
2175e475a54fSMasatake YAMATO 	mio_printf(stream, "%s", prefix);
2176e475a54fSMasatake YAMATO 	for (i = 0; i < ( seed->filled - 1 ); i++)
2177e475a54fSMasatake YAMATO     {
2178e475a54fSMasatake YAMATO 		c = buf[i];
2179e475a54fSMasatake YAMATO 		mio_putc(stream, c);
2180e475a54fSMasatake YAMATO 		if (buf[i] == '\n')
2181e475a54fSMasatake YAMATO 			mio_printf(stream, "%s", prefix);
2182e475a54fSMasatake YAMATO     }
2183e475a54fSMasatake YAMATO 	mio_putc(mio_stderr(), '\n');
2184e475a54fSMasatake YAMATO }
2185e475a54fSMasatake YAMATO 
2186e475a54fSMasatake YAMATO static Token*
get_sequence(MIO * fp,Token * seed,TerminalDetector is_terminator,int include_terminator)2187e475a54fSMasatake YAMATO get_sequence       (MIO* fp,
2188e475a54fSMasatake YAMATO 					Token* seed,
2189e475a54fSMasatake YAMATO 					TerminalDetector     is_terminator,
2190e475a54fSMasatake YAMATO 					int             include_terminator)
2191e475a54fSMasatake YAMATO {
2192e475a54fSMasatake YAMATO 	int c;
2193e475a54fSMasatake YAMATO 	int in_escape;
2194e475a54fSMasatake YAMATO 
2195e475a54fSMasatake YAMATO 	in_escape = 0;
2196e475a54fSMasatake YAMATO 	while (1)
2197e475a54fSMasatake YAMATO     {
2198e475a54fSMasatake YAMATO 		c = mio_getc(fp);
2199e475a54fSMasatake YAMATO 		if (EOF == c)
2200e475a54fSMasatake YAMATO 		{
2201e475a54fSMasatake YAMATO 			if (in_escape)
2202e475a54fSMasatake YAMATO 			{
2203e475a54fSMasatake YAMATO 				/*
2204e475a54fSMasatake YAMATO 				  throw ReadError("no character after escape character: " + seed);
2205e475a54fSMasatake YAMATO 				*/
2206e475a54fSMasatake YAMATO 				mio_printf(mio_stderr(), ";; no character after escape character:\n");
2207e475a54fSMasatake YAMATO 				{
2208e475a54fSMasatake YAMATO 					seed = token_append(seed, '\\');
2209e475a54fSMasatake YAMATO 					dump_token(mio_stderr(), "; ", seed);
2210e475a54fSMasatake YAMATO 				}
2211e475a54fSMasatake YAMATO 				token_free(seed);
2212e475a54fSMasatake YAMATO 				return NULL;
2213e475a54fSMasatake YAMATO 			}
2214e475a54fSMasatake YAMATO 			else if (is_terminator(c))
2215e475a54fSMasatake YAMATO 				break;
2216e475a54fSMasatake YAMATO 			else
2217e475a54fSMasatake YAMATO 			{
2218e475a54fSMasatake YAMATO 				/*
2219e475a54fSMasatake YAMATO 				  throw ReadError("got EOF during reading a sequence: " + seed);
2220e475a54fSMasatake YAMATO 				*/
2221e475a54fSMasatake YAMATO 				mio_printf(mio_stderr(), ";; got EOF during reading a sequence: \n");
2222e475a54fSMasatake YAMATO 				dump_token(mio_stderr(), "; ", seed);
2223e475a54fSMasatake YAMATO 				token_free(seed);
2224e475a54fSMasatake YAMATO 				return NULL;
2225e475a54fSMasatake YAMATO 			}
2226e475a54fSMasatake YAMATO 		}
2227e475a54fSMasatake YAMATO 		else
2228e475a54fSMasatake YAMATO 		{
2229e475a54fSMasatake YAMATO 			char c0;
2230e475a54fSMasatake YAMATO 
2231e475a54fSMasatake YAMATO 
2232e475a54fSMasatake YAMATO 			c0 = (char)(c);
2233e475a54fSMasatake YAMATO 			if (in_escape)
2234e475a54fSMasatake YAMATO 			{
2235e475a54fSMasatake YAMATO 				switch (c0)
2236e475a54fSMasatake YAMATO 				{
2237e475a54fSMasatake YAMATO 				case 'n': c0 = '\n'; break;
2238e475a54fSMasatake YAMATO 				case 't': c0 = '\t'; break;
2239e475a54fSMasatake YAMATO 				case 'r': c0 = '\r'; break;
2240e475a54fSMasatake YAMATO 				case 'f': c0 = '\f'; break;
2241*46162f0cSAvinash Sonawane 				default:  break;
2242e475a54fSMasatake YAMATO 				}
2243e475a54fSMasatake YAMATO 				seed = token_append(seed, c0);
2244e475a54fSMasatake YAMATO 				in_escape = 0;
2245e475a54fSMasatake YAMATO 				continue;
2246e475a54fSMasatake YAMATO 			}
2247e475a54fSMasatake YAMATO 			else if (c0 == '\\')
2248e475a54fSMasatake YAMATO 			{
2249e475a54fSMasatake YAMATO 				in_escape = 1;
2250e475a54fSMasatake YAMATO 				continue;
2251e475a54fSMasatake YAMATO 			}
2252e475a54fSMasatake YAMATO 			else if (is_terminator(c))
2253e475a54fSMasatake YAMATO 			{
2254e475a54fSMasatake YAMATO 				if (include_terminator)
2255e475a54fSMasatake YAMATO 					seed = token_append(seed, c0);
2256e475a54fSMasatake YAMATO 				else
2257e475a54fSMasatake YAMATO 				{
2258e475a54fSMasatake YAMATO 					if (mio_ungetc(fp, c) == EOF)
2259e475a54fSMasatake YAMATO 					{
2260e475a54fSMasatake YAMATO 						token_free(seed);
2261e475a54fSMasatake YAMATO 						return NULL;
2262e475a54fSMasatake YAMATO 					}
2263e475a54fSMasatake YAMATO 				}
2264e475a54fSMasatake YAMATO 				break;
2265e475a54fSMasatake YAMATO 			}
2266e475a54fSMasatake YAMATO 			else
2267e475a54fSMasatake YAMATO 			{
2268e475a54fSMasatake YAMATO 				seed = token_append(seed, c0);
2269e475a54fSMasatake YAMATO 				in_escape = 0;
2270e475a54fSMasatake YAMATO 				continue;
2271e475a54fSMasatake YAMATO 			}
2272e475a54fSMasatake YAMATO 		}
2273e475a54fSMasatake YAMATO     }
2274e475a54fSMasatake YAMATO 	return seed;
2275e475a54fSMasatake YAMATO }
2276e475a54fSMasatake YAMATO 
2277e475a54fSMasatake YAMATO 
2278e475a54fSMasatake YAMATO /*
2279e475a54fSMasatake YAMATO   (let ((total-length 0)
2280e475a54fSMasatake YAMATO   (count-symbol 0))
2281e475a54fSMasatake YAMATO   (mapatoms (lambda (s) (setq total-length (+ total-length (length (symbol-name s)))
2282e475a54fSMasatake YAMATO   count-symbol (+ 1 count-symbol)
2283e475a54fSMasatake YAMATO   )))
2284e475a54fSMasatake YAMATO   (/ total-length count-symbol)) => 15
2285e475a54fSMasatake YAMATO */
2286e475a54fSMasatake YAMATO #define DEFAULT_TOKEN_LENGHT 16
2287e475a54fSMasatake YAMATO static Token*
token_new(char seed)2288e475a54fSMasatake YAMATO token_new   (char seed)
2289e475a54fSMasatake YAMATO {
2290e475a54fSMasatake YAMATO 	Token *t;
2291e475a54fSMasatake YAMATO 
2292e475a54fSMasatake YAMATO 
2293e475a54fSMasatake YAMATO 	t = malloc(sizeof(Token));
2294e475a54fSMasatake YAMATO 	if (!t)
2295e475a54fSMasatake YAMATO 		return NULL;
2296e475a54fSMasatake YAMATO 
2297e475a54fSMasatake YAMATO 	t->buffer = calloc(1, sizeof(char) * DEFAULT_TOKEN_LENGHT);
2298e475a54fSMasatake YAMATO 	if (!t->buffer)
2299e475a54fSMasatake YAMATO     {
2300e475a54fSMasatake YAMATO 		free(t);
2301e475a54fSMasatake YAMATO 		return NULL;
2302e475a54fSMasatake YAMATO     }
2303e475a54fSMasatake YAMATO 
2304e475a54fSMasatake YAMATO 	t->filled = 0;
2305e475a54fSMasatake YAMATO 	t->buffer[t->filled++] = seed;
2306e475a54fSMasatake YAMATO 	t->buffer[t->filled++]   = '\0';
2307e475a54fSMasatake YAMATO 	t->allocated = DEFAULT_TOKEN_LENGHT;
2308e475a54fSMasatake YAMATO 
2309e475a54fSMasatake YAMATO 	return t;
2310e475a54fSMasatake YAMATO }
2311e475a54fSMasatake YAMATO 
2312e475a54fSMasatake YAMATO static void
token_free(Token * token)2313e475a54fSMasatake YAMATO token_free  (Token* token)
2314e475a54fSMasatake YAMATO {
2315e475a54fSMasatake YAMATO 	if ((token == NULL)
2316e475a54fSMasatake YAMATO 		|| (token == EOF_TOKEN)
2317e475a54fSMasatake YAMATO 		|| (token == OPEN_PAREN_TOKEN)
2318e475a54fSMasatake YAMATO 		|| (token == CLOSE_PAREN_TOKEN))
2319e475a54fSMasatake YAMATO 		return;
2320e475a54fSMasatake YAMATO 
2321e475a54fSMasatake YAMATO 
2322e475a54fSMasatake YAMATO 	free(token->buffer);
2323e475a54fSMasatake YAMATO 	token->buffer = NULL;
2324e475a54fSMasatake YAMATO 	free(token);
2325e475a54fSMasatake YAMATO }
2326e475a54fSMasatake YAMATO 
2327e475a54fSMasatake YAMATO static Token*
token_append(Token * t,char c)2328e475a54fSMasatake YAMATO token_append(Token* t, char c)
2329e475a54fSMasatake YAMATO {
2330e475a54fSMasatake YAMATO 	size_t d;
2331e475a54fSMasatake YAMATO 
2332e475a54fSMasatake YAMATO 
2333e475a54fSMasatake YAMATO 	d = t->allocated - t->filled;
2334e475a54fSMasatake YAMATO 	if (d < 1)
2335e475a54fSMasatake YAMATO     {
2336e475a54fSMasatake YAMATO 		char* tmp;
2337e475a54fSMasatake YAMATO 
2338e475a54fSMasatake YAMATO 		tmp = t->buffer;
2339e475a54fSMasatake YAMATO 		t->buffer = realloc(t->buffer, t->allocated *= 2);
2340e475a54fSMasatake YAMATO 		if (!t->buffer)
2341e475a54fSMasatake YAMATO 		{
2342e475a54fSMasatake YAMATO 			t->buffer = tmp;
2343e475a54fSMasatake YAMATO 			token_free(t);
2344e475a54fSMasatake YAMATO 			return NULL;
2345e475a54fSMasatake YAMATO 		}
2346e475a54fSMasatake YAMATO     }
2347e475a54fSMasatake YAMATO 
2348e475a54fSMasatake YAMATO 	t->buffer[t->filled - 1] = c;
2349e475a54fSMasatake YAMATO 	t->buffer[t->filled++]   = '\0';
2350e475a54fSMasatake YAMATO 
2351e475a54fSMasatake YAMATO 	return t;
2352e475a54fSMasatake YAMATO }
2353e475a54fSMasatake YAMATO 
2354e475a54fSMasatake YAMATO /* We use the third character of buffer
2355e475a54fSMasatake YAMATO  * as a flag representing an option for
2356e475a54fSMasatake YAMATO  * regex pattern.
2357e475a54fSMasatake YAMATO  *
2358e475a54fSMasatake YAMATO  * 'i': case_insensitive
2359e475a54fSMasatake YAMATO  */
2360e475a54fSMasatake YAMATO static void
inject_regex_flag(Token * t,char c)2361e475a54fSMasatake YAMATO inject_regex_flag(Token* t, char c)
2362e475a54fSMasatake YAMATO {
2363e475a54fSMasatake YAMATO 	t->buffer [2] = c;
2364e475a54fSMasatake YAMATO }
2365e475a54fSMasatake YAMATO 
2366e475a54fSMasatake YAMATO static EsObject*
fill_list(MIO * fp)2367e475a54fSMasatake YAMATO fill_list (MIO* fp)
2368e475a54fSMasatake YAMATO {
2369e475a54fSMasatake YAMATO 	EsObject* r;
2370e475a54fSMasatake YAMATO 	Token*    t;
2371e475a54fSMasatake YAMATO 
2372e475a54fSMasatake YAMATO 	r = es_nil;
2373e475a54fSMasatake YAMATO 	while(1)
2374e475a54fSMasatake YAMATO     {
2375e475a54fSMasatake YAMATO 		t = get_token(fp);
2376e475a54fSMasatake YAMATO 		if (t == NULL)
2377e475a54fSMasatake YAMATO 		{
2378e475a54fSMasatake YAMATO 			es_object_unref(r);
2379e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
2380e475a54fSMasatake YAMATO 		}
2381e475a54fSMasatake YAMATO 		else if (t == EOF_TOKEN)
2382e475a54fSMasatake YAMATO 		{
2383e475a54fSMasatake YAMATO 			es_object_unref(r);
2384e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
2385e475a54fSMasatake YAMATO 		}
2386e475a54fSMasatake YAMATO 		else if (t == CLOSE_PAREN_TOKEN)
2387e475a54fSMasatake YAMATO 		{
2388e475a54fSMasatake YAMATO 			EsObject* tmp;
2389e475a54fSMasatake YAMATO 
2390e475a54fSMasatake YAMATO 			tmp = es_cons_reverse(r);
2391e475a54fSMasatake YAMATO 			es_object_unref(r);
2392e475a54fSMasatake YAMATO 			r = tmp;
2393e475a54fSMasatake YAMATO 			break;
2394e475a54fSMasatake YAMATO 		}
2395e475a54fSMasatake YAMATO 		else if (t == OPEN_PAREN_TOKEN)
2396e475a54fSMasatake YAMATO 		{
2397e475a54fSMasatake YAMATO 			EsObject* car;
2398e475a54fSMasatake YAMATO 			EsObject* cdr;
2399e475a54fSMasatake YAMATO 
2400e475a54fSMasatake YAMATO 			car = fill_list(fp);
2401e475a54fSMasatake YAMATO 			if (es_error_p(car))
2402e475a54fSMasatake YAMATO 			{
2403e475a54fSMasatake YAMATO 				es_object_unref(r);
2404e475a54fSMasatake YAMATO 				r = car;
2405e475a54fSMasatake YAMATO 				break;
2406e475a54fSMasatake YAMATO 			}
2407e475a54fSMasatake YAMATO 
2408e475a54fSMasatake YAMATO 			cdr = r;
2409e475a54fSMasatake YAMATO 			r = es_cons(car, cdr);
2410e475a54fSMasatake YAMATO 			es_object_unref(car);
2411e475a54fSMasatake YAMATO 			es_object_unref(cdr);
2412e475a54fSMasatake YAMATO 
2413e475a54fSMasatake YAMATO 			continue;
2414e475a54fSMasatake YAMATO 		}
2415e475a54fSMasatake YAMATO 		else
2416e475a54fSMasatake YAMATO 		{
2417e475a54fSMasatake YAMATO 			EsObject* car;
2418e475a54fSMasatake YAMATO 			EsObject* cdr;
2419e475a54fSMasatake YAMATO 
2420e475a54fSMasatake YAMATO 			car = make_atom(t);
2421e475a54fSMasatake YAMATO 			token_free(t);
2422e475a54fSMasatake YAMATO 
2423e475a54fSMasatake YAMATO 			if (es_error_p (car))
2424e475a54fSMasatake YAMATO 			{
2425e475a54fSMasatake YAMATO 				es_object_unref(r);
2426e475a54fSMasatake YAMATO 				r = car;
2427e475a54fSMasatake YAMATO 				break;
2428e475a54fSMasatake YAMATO 			}
2429e475a54fSMasatake YAMATO 
2430e475a54fSMasatake YAMATO 			cdr = r;
2431e475a54fSMasatake YAMATO 			r = es_cons(car, cdr);
2432e475a54fSMasatake YAMATO 			es_object_unref(car);
2433e475a54fSMasatake YAMATO 			es_object_unref(cdr);
2434e475a54fSMasatake YAMATO 
2435e475a54fSMasatake YAMATO 			continue;
2436e475a54fSMasatake YAMATO 		}
2437e475a54fSMasatake YAMATO     }
2438e475a54fSMasatake YAMATO 
2439e475a54fSMasatake YAMATO 	return r;
2440e475a54fSMasatake YAMATO }
2441e475a54fSMasatake YAMATO 
2442e475a54fSMasatake YAMATO 
2443e475a54fSMasatake YAMATO static EsObject*
make_atom(Token * token)2444e475a54fSMasatake YAMATO make_atom          (Token*   token)
2445e475a54fSMasatake YAMATO {
2446e475a54fSMasatake YAMATO 	EsObject* r;
2447e475a54fSMasatake YAMATO 	char* t;
2448e475a54fSMasatake YAMATO 
2449e475a54fSMasatake YAMATO 	int i;
2450e475a54fSMasatake YAMATO 	double d;
2451e475a54fSMasatake YAMATO 
2452e475a54fSMasatake YAMATO 
2453e475a54fSMasatake YAMATO 	t = token->buffer;
2454e475a54fSMasatake YAMATO 
2455e475a54fSMasatake YAMATO 	if (t[0] == '"')
2456e475a54fSMasatake YAMATO 		r = make_string(t);
2457e475a54fSMasatake YAMATO 	else if (t[0] == '|')
2458e475a54fSMasatake YAMATO 		r = make_symbol(t, 1);
2459e475a54fSMasatake YAMATO 	else if (strcmp(t, "#t") == 0)
2460e475a54fSMasatake YAMATO 		r = make_boolean(1);
2461e475a54fSMasatake YAMATO 	else if (strcmp(t, "#f") == 0)
2462e475a54fSMasatake YAMATO 		r = make_boolean(0);
2463e475a54fSMasatake YAMATO 	else if ((strncmp(t, "#/", 2) == 0)
2464e475a54fSMasatake YAMATO 			 && t[2] != '\0')
2465e475a54fSMasatake YAMATO 		r = make_regex (t + 3, (t[2] == 'i'));
2466e475a54fSMasatake YAMATO 	else if (is_integer(t, &i))
2467e475a54fSMasatake YAMATO     {
2468e475a54fSMasatake YAMATO 		r = make_integer(i);
2469e475a54fSMasatake YAMATO     }
2470e475a54fSMasatake YAMATO 	else if (is_real(t, &d))
2471e475a54fSMasatake YAMATO     {
2472e475a54fSMasatake YAMATO 		r = make_real(d);
2473e475a54fSMasatake YAMATO     }
2474e475a54fSMasatake YAMATO 	else
2475e475a54fSMasatake YAMATO 		r = make_symbol(t, 0);
2476e475a54fSMasatake YAMATO 
2477e475a54fSMasatake YAMATO 	return r;
2478e475a54fSMasatake YAMATO }
2479e475a54fSMasatake YAMATO 
2480e475a54fSMasatake YAMATO static EsObject*
make_string(char * t)2481e475a54fSMasatake YAMATO make_string  (char* t)
2482e475a54fSMasatake YAMATO {
2483e475a54fSMasatake YAMATO 	size_t len;
2484e475a54fSMasatake YAMATO 
2485e475a54fSMasatake YAMATO 
2486e475a54fSMasatake YAMATO 	len = strlen(t);
2487e475a54fSMasatake YAMATO 	t[(len - 1)] = '\0';
2488e475a54fSMasatake YAMATO 	return es_string_new(t + 1);
2489e475a54fSMasatake YAMATO }
2490e475a54fSMasatake YAMATO 
2491e475a54fSMasatake YAMATO static EsObject*
make_symbol(char * t,int is_wrapped)2492e475a54fSMasatake YAMATO make_symbol  (char* t,
2493e475a54fSMasatake YAMATO 			  int is_wrapped)
2494e475a54fSMasatake YAMATO {
2495e475a54fSMasatake YAMATO 	if (is_wrapped)
2496e475a54fSMasatake YAMATO     {
2497e475a54fSMasatake YAMATO 		size_t len;
2498e475a54fSMasatake YAMATO 
2499e475a54fSMasatake YAMATO 		len = strlen(t);
2500e475a54fSMasatake YAMATO 		t[(len - 1)] = '\0';
2501e475a54fSMasatake YAMATO 		t = t + 1;
2502e475a54fSMasatake YAMATO     }
2503e475a54fSMasatake YAMATO 
2504e475a54fSMasatake YAMATO 	return es_symbol_intern(t);
2505e475a54fSMasatake YAMATO }
2506e475a54fSMasatake YAMATO 
2507e475a54fSMasatake YAMATO 
2508e475a54fSMasatake YAMATO static EsObject*
make_boolean(int b)2509e475a54fSMasatake YAMATO make_boolean (int b)
2510e475a54fSMasatake YAMATO {
2511e475a54fSMasatake YAMATO 	return es_boolean_new(b);
2512e475a54fSMasatake YAMATO }
2513e475a54fSMasatake YAMATO 
2514e475a54fSMasatake YAMATO static int
is_integer(const char * cstr,int * i)2515e475a54fSMasatake YAMATO is_integer   (const char* cstr,
2516e475a54fSMasatake YAMATO 			  int* i)
2517e475a54fSMasatake YAMATO {
2518e475a54fSMasatake YAMATO 	char* endptr;
2519e475a54fSMasatake YAMATO 	long  r;
2520e475a54fSMasatake YAMATO 
2521e475a54fSMasatake YAMATO 	endptr = NULL;
2522e475a54fSMasatake YAMATO 	errno = 0;
2523e475a54fSMasatake YAMATO 	r = strtol(cstr, &endptr, 10);
2524e475a54fSMasatake YAMATO 
2525e475a54fSMasatake YAMATO 	if (errno || (endptr == cstr))
2526e475a54fSMasatake YAMATO 		return 0;
2527e475a54fSMasatake YAMATO 	else if (*endptr != '\0')
2528e475a54fSMasatake YAMATO 		return 0;
2529e475a54fSMasatake YAMATO 
2530e475a54fSMasatake YAMATO 	if ((r > INT_MAX) || r < INT_MIN)
2531e475a54fSMasatake YAMATO     {
2532e475a54fSMasatake YAMATO 		/* TODO: What I should do?
2533e475a54fSMasatake YAMATO 		   TODO: Set error */
2534e475a54fSMasatake YAMATO 		/*
2535e475a54fSMasatake YAMATO 		  throw ReadError("Too large integer for `int': " + r);
2536e475a54fSMasatake YAMATO 		*/
2537e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), ";; is_integer, Integer out of range: %s\n", cstr);
2538e475a54fSMasatake YAMATO 		return 0;
2539e475a54fSMasatake YAMATO     }
2540e475a54fSMasatake YAMATO 
2541e475a54fSMasatake YAMATO 	*i = r;
2542e475a54fSMasatake YAMATO 	return 1;
2543e475a54fSMasatake YAMATO }
2544e475a54fSMasatake YAMATO 
2545e475a54fSMasatake YAMATO static EsObject*
make_integer(int i)2546e475a54fSMasatake YAMATO make_integer (int  i)
2547e475a54fSMasatake YAMATO {
2548e475a54fSMasatake YAMATO 	return es_integer_new(i);
2549e475a54fSMasatake YAMATO }
2550e475a54fSMasatake YAMATO 
2551e475a54fSMasatake YAMATO static int
is_real(const char * cstr,double * d)2552e475a54fSMasatake YAMATO is_real      (const char* cstr,
2553e475a54fSMasatake YAMATO 			  double* d)
2554e475a54fSMasatake YAMATO {
2555e475a54fSMasatake YAMATO 	char* endptr;
2556e475a54fSMasatake YAMATO 
2557e475a54fSMasatake YAMATO 	endptr = NULL;
2558e475a54fSMasatake YAMATO 	errno = 0;
2559e475a54fSMasatake YAMATO 	*d = strtod(cstr, &endptr);
2560e475a54fSMasatake YAMATO 
2561e475a54fSMasatake YAMATO 	if (errno || (endptr == cstr))
2562e475a54fSMasatake YAMATO 		return 0;
2563e475a54fSMasatake YAMATO 	else if (*endptr != '\0')
2564e475a54fSMasatake YAMATO 		return 0;
2565e475a54fSMasatake YAMATO 
2566e475a54fSMasatake YAMATO 	/* TODO: INF, NAN... */
2567e475a54fSMasatake YAMATO 	return 1;
2568e475a54fSMasatake YAMATO }
2569e475a54fSMasatake YAMATO 
2570e475a54fSMasatake YAMATO static EsObject*
make_real(double d)2571e475a54fSMasatake YAMATO make_real (double d)
2572e475a54fSMasatake YAMATO {
2573e475a54fSMasatake YAMATO 	return es_real_new(d);
2574e475a54fSMasatake YAMATO }
2575e475a54fSMasatake YAMATO 
2576e475a54fSMasatake YAMATO static EsObject*
make_regex(const char * pat,int case_insensitive)2577e475a54fSMasatake YAMATO make_regex (const char *pat,
2578e475a54fSMasatake YAMATO 			int case_insensitive)
2579e475a54fSMasatake YAMATO {
2580e475a54fSMasatake YAMATO 	return es_regex_compile(pat, case_insensitive);
2581e475a54fSMasatake YAMATO }
2582e475a54fSMasatake YAMATO 
2583e475a54fSMasatake YAMATO EsObject*
es_read_from_string(const char * buf,const char ** saveptr)2584e475a54fSMasatake YAMATO es_read_from_string(const char* buf,
2585e475a54fSMasatake YAMATO 					const char** saveptr)
2586e475a54fSMasatake YAMATO {
2587e475a54fSMasatake YAMATO 	MIO* in;
2588e475a54fSMasatake YAMATO 	EsObject* o;
2589e475a54fSMasatake YAMATO 
2590e475a54fSMasatake YAMATO 
2591e475a54fSMasatake YAMATO 	/* IN is opend in "r" mode and the stream pointed by
2592e475a54fSMasatake YAMATO 	   IN is short-lived here. */
2593e475a54fSMasatake YAMATO 	in = mio_new_memory((void *)buf, strlen(buf), NULL, NULL);
2594e475a54fSMasatake YAMATO 	o = es_read(in);
2595e475a54fSMasatake YAMATO 	if (saveptr)
2596e475a54fSMasatake YAMATO 		*saveptr = buf + mio_tell(in);
2597e475a54fSMasatake YAMATO 	mio_unref(in);
2598e475a54fSMasatake YAMATO 
2599e475a54fSMasatake YAMATO 	return o;
2600e475a54fSMasatake YAMATO }
2601e475a54fSMasatake YAMATO 
2602e475a54fSMasatake YAMATO 
2603e475a54fSMasatake YAMATO 
2604e475a54fSMasatake YAMATO typedef struct _EsAutounrefPool EsAutounrefPool;
2605e475a54fSMasatake YAMATO typedef struct _EsChain EsChain;
2606e475a54fSMasatake YAMATO 
2607e475a54fSMasatake YAMATO struct _EsChain
2608e475a54fSMasatake YAMATO {
2609e475a54fSMasatake YAMATO 	EsObject* object;
2610e475a54fSMasatake YAMATO 	EsChain*  next;
2611e475a54fSMasatake YAMATO };
2612e475a54fSMasatake YAMATO 
2613e475a54fSMasatake YAMATO struct _EsAutounrefPool
2614e475a54fSMasatake YAMATO {
2615e475a54fSMasatake YAMATO 	EsAutounrefPool * parent_pool;
2616e475a54fSMasatake YAMATO 	EsChain*          chain;
2617e475a54fSMasatake YAMATO };
2618e475a54fSMasatake YAMATO 
2619e475a54fSMasatake YAMATO static EsAutounrefPool * currrent_pool;
2620e475a54fSMasatake YAMATO 
2621e475a54fSMasatake YAMATO static EsAutounrefPool* es_autounref_pool_new(void);
2622e475a54fSMasatake YAMATO static void             es_autounref_pool_free(EsAutounrefPool* pool);
2623e475a54fSMasatake YAMATO static EsChain*         es_chain_new(EsObject* object);
2624e475a54fSMasatake YAMATO static void             es_chain_free(EsChain* chain);
2625e475a54fSMasatake YAMATO 
2626e475a54fSMasatake YAMATO 
2627e475a54fSMasatake YAMATO void
es_autounref_pool_push(void)2628e475a54fSMasatake YAMATO es_autounref_pool_push(void)
2629e475a54fSMasatake YAMATO {
2630e475a54fSMasatake YAMATO 	EsAutounrefPool* r;
2631e475a54fSMasatake YAMATO 
2632e475a54fSMasatake YAMATO 	r = es_autounref_pool_new();
2633e475a54fSMasatake YAMATO 	r->parent_pool = currrent_pool;
2634e475a54fSMasatake YAMATO 	currrent_pool = r;
2635e475a54fSMasatake YAMATO }
2636e475a54fSMasatake YAMATO 
2637e475a54fSMasatake YAMATO void
es_autounref_pool_pop(void)2638e475a54fSMasatake YAMATO es_autounref_pool_pop (void)
2639e475a54fSMasatake YAMATO {
2640e475a54fSMasatake YAMATO 	EsAutounrefPool *tmp;
2641e475a54fSMasatake YAMATO 
2642e475a54fSMasatake YAMATO 	tmp = currrent_pool;
2643e475a54fSMasatake YAMATO 	currrent_pool = tmp->parent_pool;
2644e475a54fSMasatake YAMATO 
2645e475a54fSMasatake YAMATO 	es_autounref_pool_free(tmp);
2646e475a54fSMasatake YAMATO }
2647e475a54fSMasatake YAMATO 
2648e475a54fSMasatake YAMATO static void
es_autounref_pool_free(EsAutounrefPool * pool)2649e475a54fSMasatake YAMATO es_autounref_pool_free(EsAutounrefPool* pool)
2650e475a54fSMasatake YAMATO {
2651e475a54fSMasatake YAMATO 	pool->parent_pool = NULL;
2652e475a54fSMasatake YAMATO 	es_chain_free(pool->chain);
2653e475a54fSMasatake YAMATO 	pool->chain = NULL;
2654e475a54fSMasatake YAMATO 
2655e475a54fSMasatake YAMATO 	free(pool);
2656e475a54fSMasatake YAMATO }
2657e475a54fSMasatake YAMATO 
2658e475a54fSMasatake YAMATO EsObject*
es_object_autounref(EsObject * object)2659e475a54fSMasatake YAMATO es_object_autounref   (EsObject* object)
2660e475a54fSMasatake YAMATO {
2661e475a54fSMasatake YAMATO 	EsChain* r;
2662e475a54fSMasatake YAMATO 
2663e475a54fSMasatake YAMATO 	r = es_chain_new(object);
2664e475a54fSMasatake YAMATO 	r->next = currrent_pool->chain;
2665e475a54fSMasatake YAMATO 	currrent_pool->chain = r;
2666e475a54fSMasatake YAMATO 
2667e475a54fSMasatake YAMATO 	return object;
2668e475a54fSMasatake YAMATO }
2669e475a54fSMasatake YAMATO 
2670e475a54fSMasatake YAMATO static EsAutounrefPool*
es_autounref_pool_new(void)2671e475a54fSMasatake YAMATO es_autounref_pool_new(void)
2672e475a54fSMasatake YAMATO {
2673e475a54fSMasatake YAMATO 	EsAutounrefPool* r;
2674e475a54fSMasatake YAMATO 
2675e475a54fSMasatake YAMATO 	r = calloc(1, sizeof(EsAutounrefPool));
2676e475a54fSMasatake YAMATO 	return r;
2677e475a54fSMasatake YAMATO }
2678e475a54fSMasatake YAMATO 
2679e475a54fSMasatake YAMATO static EsChain*
es_chain_new(EsObject * object)2680e475a54fSMasatake YAMATO es_chain_new(EsObject *object)
2681e475a54fSMasatake YAMATO {
2682e475a54fSMasatake YAMATO 	EsChain* r;
2683e475a54fSMasatake YAMATO 
2684e475a54fSMasatake YAMATO 	r = calloc(1, sizeof(EsChain));
2685e475a54fSMasatake YAMATO 	r->object = object;
2686e475a54fSMasatake YAMATO 	return r;
2687e475a54fSMasatake YAMATO }
2688e475a54fSMasatake YAMATO 
2689e475a54fSMasatake YAMATO static void
es_chain_free(EsChain * chain)2690e475a54fSMasatake YAMATO es_chain_free(EsChain *chain)
2691e475a54fSMasatake YAMATO {
2692e475a54fSMasatake YAMATO 	EsChain *tmp;
2693e475a54fSMasatake YAMATO 
2694e475a54fSMasatake YAMATO 	while(chain)
2695e475a54fSMasatake YAMATO     {
2696e475a54fSMasatake YAMATO 		tmp = chain;
2697e475a54fSMasatake YAMATO 		chain = chain->next;
2698e475a54fSMasatake YAMATO 
2699e475a54fSMasatake YAMATO 		es_object_unref(tmp->object);
2700e475a54fSMasatake YAMATO 		tmp->object = NULL;
2701e475a54fSMasatake YAMATO 		tmp->next = NULL;
2702e475a54fSMasatake YAMATO 		free(tmp);
2703e475a54fSMasatake YAMATO     }
2704e475a54fSMasatake YAMATO }
2705e475a54fSMasatake YAMATO 
2706e475a54fSMasatake YAMATO 
2707e475a54fSMasatake YAMATO #include <stdarg.h>
2708e475a54fSMasatake YAMATO static EsObject* es_list_va(EsObject* object, va_list *ap);
2709e475a54fSMasatake YAMATO 
2710e475a54fSMasatake YAMATO EsObject*
es_list(EsObject * object,...)2711e475a54fSMasatake YAMATO es_list(EsObject* object,...)
2712e475a54fSMasatake YAMATO {
2713e475a54fSMasatake YAMATO 	EsObject* r;
2714e475a54fSMasatake YAMATO 	va_list ap;
2715e475a54fSMasatake YAMATO 
2716e475a54fSMasatake YAMATO 	va_start(ap, object);
2717e475a54fSMasatake YAMATO 	r = es_list_va(object, &ap);
2718e475a54fSMasatake YAMATO 	va_end(ap);
2719e475a54fSMasatake YAMATO 
2720e475a54fSMasatake YAMATO 	return r;
2721e475a54fSMasatake YAMATO }
2722e475a54fSMasatake YAMATO 
2723e475a54fSMasatake YAMATO static EsObject*
es_list_va(EsObject * object,va_list * ap)2724e475a54fSMasatake YAMATO es_list_va(EsObject* object, va_list *ap)
2725e475a54fSMasatake YAMATO {
2726e475a54fSMasatake YAMATO 	EsObject* r;
2727e475a54fSMasatake YAMATO 	EsObject* p;
2728e475a54fSMasatake YAMATO 	EsObject* tmp;
2729e475a54fSMasatake YAMATO 
2730e475a54fSMasatake YAMATO 	r = es_nil;
2731e475a54fSMasatake YAMATO 	p = object;
2732e475a54fSMasatake YAMATO 	es_autounref_pool_push();
2733e475a54fSMasatake YAMATO 	do {
2734e475a54fSMasatake YAMATO 		if (p == ES_READER_EOF)
2735e475a54fSMasatake YAMATO 			break;
2736e475a54fSMasatake YAMATO 
2737e475a54fSMasatake YAMATO 		r = es_cons((p), es_object_autounref(r));
2738e475a54fSMasatake YAMATO 		p = va_arg(*ap, EsObject *);
2739e475a54fSMasatake YAMATO 	} while(1);
2740e475a54fSMasatake YAMATO 	es_autounref_pool_pop();
2741e475a54fSMasatake YAMATO 
2742e475a54fSMasatake YAMATO 	tmp = r;
2743e475a54fSMasatake YAMATO 	r = es_cons_reverse(r);
2744e475a54fSMasatake YAMATO 	es_object_unref(tmp);
2745e475a54fSMasatake YAMATO 
2746e475a54fSMasatake YAMATO 	return r;
2747e475a54fSMasatake YAMATO }
2748e475a54fSMasatake YAMATO 
2749e475a54fSMasatake YAMATO 
2750e475a54fSMasatake YAMATO static EsObject* es_append0(EsObject* tail, EsObject* body);
2751e475a54fSMasatake YAMATO static EsObject* es_append1(EsObject* tail, EsObject* body0);
2752e475a54fSMasatake YAMATO 
2753e475a54fSMasatake YAMATO EsObject*
es_append(EsObject * list,...)2754e475a54fSMasatake YAMATO es_append(EsObject* list,...)
2755e475a54fSMasatake YAMATO {
2756e475a54fSMasatake YAMATO 	EsObject *r;
2757e475a54fSMasatake YAMATO 	EsObject *tmp;
2758e475a54fSMasatake YAMATO 	EsObject *tail;
2759e475a54fSMasatake YAMATO 	EsObject *body;
2760e475a54fSMasatake YAMATO 	va_list ap;
2761e475a54fSMasatake YAMATO 
2762e475a54fSMasatake YAMATO 
2763e475a54fSMasatake YAMATO 	va_start(ap, list);
2764e475a54fSMasatake YAMATO 	r = es_list_va(list, &ap);
2765e475a54fSMasatake YAMATO 	va_end(ap);
2766e475a54fSMasatake YAMATO 
2767e475a54fSMasatake YAMATO 	tmp = r;
2768e475a54fSMasatake YAMATO 	r = es_cons_reverse(r);
2769e475a54fSMasatake YAMATO 	es_object_unref(tmp);
2770e475a54fSMasatake YAMATO 
2771e475a54fSMasatake YAMATO 	/* r */
2772e475a54fSMasatake YAMATO 	tail = es_car(r);
2773e475a54fSMasatake YAMATO 	body = es_cdr(r);
2774e475a54fSMasatake YAMATO 	tmp  = r;
2775e475a54fSMasatake YAMATO 	r = es_append0(tail, body);
2776e475a54fSMasatake YAMATO 	es_object_unref(tmp);
2777e475a54fSMasatake YAMATO 
2778e475a54fSMasatake YAMATO 	return r;
2779e475a54fSMasatake YAMATO }
2780e475a54fSMasatake YAMATO 
2781e475a54fSMasatake YAMATO static EsObject*
es_append0(EsObject * tail,EsObject * body)2782e475a54fSMasatake YAMATO es_append0(EsObject* tail, EsObject* body)
2783e475a54fSMasatake YAMATO {
2784e475a54fSMasatake YAMATO 	if (es_null(body))
2785e475a54fSMasatake YAMATO 		return tail;
2786e475a54fSMasatake YAMATO 	else
2787e475a54fSMasatake YAMATO     {
2788e475a54fSMasatake YAMATO 		EsObject* car;
2789e475a54fSMasatake YAMATO 
2790e475a54fSMasatake YAMATO 		car = es_cons_reverse(es_car(body));
2791e475a54fSMasatake YAMATO 		tail = es_append1(tail, car);
2792e475a54fSMasatake YAMATO 		es_object_unref(car);
2793e475a54fSMasatake YAMATO 		body = es_cdr(body);
2794e475a54fSMasatake YAMATO 		return es_append0(tail, body);
2795e475a54fSMasatake YAMATO     }
2796e475a54fSMasatake YAMATO }
2797e475a54fSMasatake YAMATO 
2798e475a54fSMasatake YAMATO static EsObject*
es_append1(EsObject * tail,EsObject * body0)2799e475a54fSMasatake YAMATO es_append1(EsObject* tail, EsObject* body0)
2800e475a54fSMasatake YAMATO {
2801e475a54fSMasatake YAMATO 	if (es_null(body0))
2802e475a54fSMasatake YAMATO 		return es_object_ref(tail);
2803e475a54fSMasatake YAMATO 	else
2804e475a54fSMasatake YAMATO     {
2805e475a54fSMasatake YAMATO 		EsObject* car;
2806e475a54fSMasatake YAMATO 		EsObject* r;
2807e475a54fSMasatake YAMATO 
2808e475a54fSMasatake YAMATO 		car  = es_car(body0);
2809e475a54fSMasatake YAMATO 		tail = es_cons(car, tail);
2810e475a54fSMasatake YAMATO 
2811e475a54fSMasatake YAMATO 		r = es_append1(tail, es_cdr(body0));
2812e475a54fSMasatake YAMATO 		es_object_unref(tail);
2813e475a54fSMasatake YAMATO 		return r;
2814e475a54fSMasatake YAMATO     }
2815e475a54fSMasatake YAMATO }
2816e475a54fSMasatake YAMATO 
2817e475a54fSMasatake YAMATO 
2818e475a54fSMasatake YAMATO 
2819e475a54fSMasatake YAMATO static EsObject* pattern_d         = NULL;
2820e475a54fSMasatake YAMATO static EsObject* pattern_f         = NULL;
2821e475a54fSMasatake YAMATO static EsObject* pattern_F         = NULL;
2822e475a54fSMasatake YAMATO static EsObject* pattern_s         = NULL;
2823e475a54fSMasatake YAMATO static EsObject* pattern_S         = NULL;
2824e475a54fSMasatake YAMATO static EsObject* pattern_b         = NULL;
2825e475a54fSMasatake YAMATO static EsObject* pattern_rest      = NULL;
2826e475a54fSMasatake YAMATO static EsObject* pattern_unquote   = NULL;
2827e475a54fSMasatake YAMATO static EsObject* pattern_splice    = NULL;
2828e475a54fSMasatake YAMATO 
2829e475a54fSMasatake YAMATO static EsObject* pattern_i_d       = NULL;
2830e475a54fSMasatake YAMATO static EsObject* pattern_i_f       = NULL;
2831e475a54fSMasatake YAMATO static EsObject* pattern_i_F       = NULL;
2832e475a54fSMasatake YAMATO static EsObject* pattern_i_s       = NULL;
2833e475a54fSMasatake YAMATO static EsObject* pattern_i_S       = NULL;
2834e475a54fSMasatake YAMATO static EsObject* pattern_i_b       = NULL;
2835e475a54fSMasatake YAMATO static EsObject* pattern_i_rest    = NULL;
2836e475a54fSMasatake YAMATO static EsObject* pattern_i_unquote = NULL;
2837e475a54fSMasatake YAMATO 
2838e475a54fSMasatake YAMATO static void
pattern_init(void)2839e475a54fSMasatake YAMATO pattern_init(void)
2840e475a54fSMasatake YAMATO {
2841e475a54fSMasatake YAMATO 	if (!pattern_d) (pattern_d = es_symbol_intern("%d"));
2842e475a54fSMasatake YAMATO 	if (!pattern_f) (pattern_f = es_symbol_intern("%f"));
2843e475a54fSMasatake YAMATO 	if (!pattern_F) (pattern_F = es_symbol_intern("%F"));
2844e475a54fSMasatake YAMATO 	if (!pattern_s) (pattern_s = es_symbol_intern("%s"));
2845e475a54fSMasatake YAMATO 	if (!pattern_S) (pattern_S = es_symbol_intern("%S"));
2846e475a54fSMasatake YAMATO 	if (!pattern_b) (pattern_b = es_symbol_intern("%b"));
2847e475a54fSMasatake YAMATO 	if (!pattern_rest) (pattern_rest = es_symbol_intern("%@"));
2848e475a54fSMasatake YAMATO 	if (!pattern_unquote) (pattern_unquote = es_symbol_intern("%,"));
2849e475a54fSMasatake YAMATO 	if (!pattern_splice) (pattern_splice = es_symbol_intern("%,@"));
2850e475a54fSMasatake YAMATO 
2851e475a54fSMasatake YAMATO 	if (!pattern_i_d) (pattern_i_d = es_symbol_intern("%_d"));
2852e475a54fSMasatake YAMATO 	if (!pattern_i_f) (pattern_i_f = es_symbol_intern("%_f"));
2853e475a54fSMasatake YAMATO 	if (!pattern_i_F) (pattern_i_F = es_symbol_intern("%_F"));
2854e475a54fSMasatake YAMATO 	if (!pattern_i_s) (pattern_i_s = es_symbol_intern("%_s"));
2855e475a54fSMasatake YAMATO 	if (!pattern_i_S) (pattern_i_S = es_symbol_intern("%_S"));
2856e475a54fSMasatake YAMATO 	if (!pattern_i_b) (pattern_i_b = es_symbol_intern("%_b"));
2857e475a54fSMasatake YAMATO 	if (!pattern_i_rest) (pattern_i_rest = es_symbol_intern("%_@"));
2858e475a54fSMasatake YAMATO 	if (!pattern_i_unquote) (pattern_i_unquote = es_symbol_intern("%_,"));
2859e475a54fSMasatake YAMATO }
2860e475a54fSMasatake YAMATO 
2861e475a54fSMasatake YAMATO static EsObject*
es_vrealize_atom(EsObject * fmt_object,va_list * ap)2862e475a54fSMasatake YAMATO es_vrealize_atom(EsObject* fmt_object, va_list *ap)
2863e475a54fSMasatake YAMATO {
2864e475a54fSMasatake YAMATO 	if (fmt_object == pattern_d)
2865e475a54fSMasatake YAMATO 		return es_integer_new(va_arg(*ap, int));
2866e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_f)
2867e475a54fSMasatake YAMATO     {
2868e475a54fSMasatake YAMATO 		double x = va_arg(*ap, double);
2869e475a54fSMasatake YAMATO 		mio_printf(mio_stderr(), "=>%f\n", x);
2870e475a54fSMasatake YAMATO 		return es_real_new(x);
2871e475a54fSMasatake YAMATO     }
2872e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_s)
2873e475a54fSMasatake YAMATO 		return es_string_new(va_arg(*ap, char *));
2874e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_S)
2875e475a54fSMasatake YAMATO 		return es_symbol_intern(va_arg(*ap, char *));
2876e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_b)
2877e475a54fSMasatake YAMATO 		return es_boolean_new(va_arg(*ap, int));
2878e475a54fSMasatake YAMATO 	else if ((fmt_object == pattern_unquote)
2879e475a54fSMasatake YAMATO 			 || (fmt_object == pattern_splice))
2880e475a54fSMasatake YAMATO 		return es_object_ref(va_arg(*ap, EsObject*));
2881e475a54fSMasatake YAMATO 	else
2882e475a54fSMasatake YAMATO 		return es_object_ref(fmt_object);
2883e475a54fSMasatake YAMATO }
2884e475a54fSMasatake YAMATO 
2885e475a54fSMasatake YAMATO static EsObject*
es_vrealize(EsObject * fmt_object,va_list * ap)2886e475a54fSMasatake YAMATO es_vrealize(EsObject* fmt_object, va_list *ap)
2887e475a54fSMasatake YAMATO {
2888e475a54fSMasatake YAMATO 	pattern_init();
2889e475a54fSMasatake YAMATO 
2890e475a54fSMasatake YAMATO 	if (es_cons_p(fmt_object))
2891e475a54fSMasatake YAMATO     {
2892e475a54fSMasatake YAMATO 		EsObject* car;
2893e475a54fSMasatake YAMATO 		EsObject* cdr;
2894e475a54fSMasatake YAMATO 		EsObject* kar;
2895e475a54fSMasatake YAMATO 		EsObject* kdr;
2896e475a54fSMasatake YAMATO 		EsObject* r;
2897e475a54fSMasatake YAMATO 
2898e475a54fSMasatake YAMATO 		car = es_car(fmt_object);
2899e475a54fSMasatake YAMATO 
2900e475a54fSMasatake YAMATO 		if (car == pattern_rest)
2901e475a54fSMasatake YAMATO 			r = es_object_ref(va_arg(*ap, EsObject*));
2902e475a54fSMasatake YAMATO 		else
2903e475a54fSMasatake YAMATO 		{
2904e475a54fSMasatake YAMATO 			cdr = es_cdr(fmt_object);
2905e475a54fSMasatake YAMATO 
2906e475a54fSMasatake YAMATO 			kar = es_vrealize(car, ap);
2907e475a54fSMasatake YAMATO 			kdr = es_vrealize(cdr, ap);
2908e475a54fSMasatake YAMATO 
2909e475a54fSMasatake YAMATO 			if (car == pattern_splice)
2910e475a54fSMasatake YAMATO 			{
2911e475a54fSMasatake YAMATO 				if (es_cons_p(kar))
2912e475a54fSMasatake YAMATO 					r = es_append(kar, kdr, ES_READER_EOF);
2913e475a54fSMasatake YAMATO 				else
2914e475a54fSMasatake YAMATO 				{
2915e475a54fSMasatake YAMATO 					/* TODO: error */
2916e475a54fSMasatake YAMATO 					char *fmt;
2917e475a54fSMasatake YAMATO 
2918e475a54fSMasatake YAMATO 					mio_printf(mio_stderr(),
2919e475a54fSMasatake YAMATO 							   ";; an atom is passed for splice format:\n");
2920e475a54fSMasatake YAMATO 					fmt = es_print_to_string(fmt_object);
2921e475a54fSMasatake YAMATO 					mio_printf(mio_stderr(), ";; => %s\n", fmt);
2922e475a54fSMasatake YAMATO 					free(fmt);
2923e475a54fSMasatake YAMATO 					r = es_nil;
2924e475a54fSMasatake YAMATO 				}
2925e475a54fSMasatake YAMATO 			}
2926e475a54fSMasatake YAMATO 			else
2927e475a54fSMasatake YAMATO 				r = es_cons(kar, kdr);
2928e475a54fSMasatake YAMATO 
2929e475a54fSMasatake YAMATO 			es_object_unref(kar);
2930e475a54fSMasatake YAMATO 			es_object_unref(kdr);
2931e475a54fSMasatake YAMATO 		}
2932e475a54fSMasatake YAMATO 		return r;
2933e475a54fSMasatake YAMATO     }
2934e475a54fSMasatake YAMATO 	else
2935e475a54fSMasatake YAMATO 		return es_vrealize_atom(fmt_object, ap);
2936e475a54fSMasatake YAMATO }
2937e475a54fSMasatake YAMATO 
2938e475a54fSMasatake YAMATO EsObject*
es_realize(EsObject * fmt_object,...)2939e475a54fSMasatake YAMATO es_realize   (EsObject* fmt_object,...)
2940e475a54fSMasatake YAMATO {
2941e475a54fSMasatake YAMATO 	EsObject* object;
2942e475a54fSMasatake YAMATO 	va_list ap;
2943e475a54fSMasatake YAMATO 
2944e475a54fSMasatake YAMATO 	if (es_error_p(fmt_object))
2945e475a54fSMasatake YAMATO 		return es_object_ref(fmt_object);
2946e475a54fSMasatake YAMATO 
2947e475a54fSMasatake YAMATO 	va_start(ap, fmt_object);
2948e475a54fSMasatake YAMATO 	object = es_vrealize(fmt_object, &ap);
2949e475a54fSMasatake YAMATO 	va_end(ap);
2950e475a54fSMasatake YAMATO 
2951e475a54fSMasatake YAMATO 	return object;
2952e475a54fSMasatake YAMATO }
2953e475a54fSMasatake YAMATO 
2954e475a54fSMasatake YAMATO EsObject*
es_srealize(const char * fmt,...)2955e475a54fSMasatake YAMATO es_srealize  (const char* fmt,...)
2956e475a54fSMasatake YAMATO {
2957e475a54fSMasatake YAMATO 	EsObject* fmt_object;
2958e475a54fSMasatake YAMATO 	EsObject* object;
2959e475a54fSMasatake YAMATO 	va_list ap;
2960e475a54fSMasatake YAMATO 
2961e475a54fSMasatake YAMATO 	fmt_object = es_read_from_string(fmt, NULL);
2962e475a54fSMasatake YAMATO 	if (es_error_p(fmt_object))
2963e475a54fSMasatake YAMATO 		return fmt_object;
2964e475a54fSMasatake YAMATO 
2965e475a54fSMasatake YAMATO 	va_start(ap, fmt);
2966e475a54fSMasatake YAMATO 	object = es_vrealize(fmt_object, &ap);
2967e475a54fSMasatake YAMATO 	va_end(ap);
2968e475a54fSMasatake YAMATO 
2969e475a54fSMasatake YAMATO 	es_object_unref(fmt_object);
2970e475a54fSMasatake YAMATO 
2971e475a54fSMasatake YAMATO 	return object;
2972e475a54fSMasatake YAMATO }
2973e475a54fSMasatake YAMATO 
es_map(EsObject * (* fn)(EsObject *,void *),EsObject * list,void * user_data)2974e475a54fSMasatake YAMATO EsObject* es_map   (EsObject * (*fn) (EsObject *, void *),
2975e475a54fSMasatake YAMATO 					EsObject *list, void *user_data)
2976e475a54fSMasatake YAMATO {
2977e475a54fSMasatake YAMATO 	if (es_null (list))
2978e475a54fSMasatake YAMATO 		return list;
2979e475a54fSMasatake YAMATO 
2980e475a54fSMasatake YAMATO 	EsObject *c = es_car (list);
2981e475a54fSMasatake YAMATO 	c = fn (c, user_data);
2982e475a54fSMasatake YAMATO 	if (es_error_p (c))
2983e475a54fSMasatake YAMATO 		return c;
2984e475a54fSMasatake YAMATO 
2985e475a54fSMasatake YAMATO 	EsObject *r = es_map (fn, es_cdr (list), user_data);
2986e475a54fSMasatake YAMATO 	if (es_error_p (r))
2987e475a54fSMasatake YAMATO 	{
2988e475a54fSMasatake YAMATO 		es_object_unref (c);
2989e475a54fSMasatake YAMATO 		return r;
2990e475a54fSMasatake YAMATO 	}
2991e475a54fSMasatake YAMATO 
2992e475a54fSMasatake YAMATO 	EsObject *o = es_cons (c, r);
2993e475a54fSMasatake YAMATO 	es_object_unref (r);
2994e475a54fSMasatake YAMATO 	es_object_unref (c);
2995e475a54fSMasatake YAMATO 
2996e475a54fSMasatake YAMATO 	return o;
2997e475a54fSMasatake YAMATO }
2998e475a54fSMasatake YAMATO 
es_foreach(EsObject * (* fn)(EsObject *,void *),EsObject * list,void * user_data)2999e76e59c9SMasatake YAMATO EsObject* es_foreach (EsObject * (*fn) (EsObject *, void *),
3000e76e59c9SMasatake YAMATO 					  EsObject *list, void *user_data)
3001e76e59c9SMasatake YAMATO {
3002e76e59c9SMasatake YAMATO 	if (es_null (list))
3003e76e59c9SMasatake YAMATO 		return es_false;
3004e76e59c9SMasatake YAMATO 
3005e76e59c9SMasatake YAMATO 	for (EsObject *c = list; !es_null (c); c = es_cdr (c))
3006e76e59c9SMasatake YAMATO 	{
3007e76e59c9SMasatake YAMATO 		EsObject *r = fn (es_car (c), user_data);
3008e76e59c9SMasatake YAMATO 		if (!es_object_equal (r, es_false))
3009e76e59c9SMasatake YAMATO 			return r;
3010e76e59c9SMasatake YAMATO 	}
3011e76e59c9SMasatake YAMATO 
3012e76e59c9SMasatake YAMATO 	return es_false;
3013e76e59c9SMasatake YAMATO }
3014e76e59c9SMasatake YAMATO 
es_fold(EsObject * (* kons)(EsObject *,EsObject *,void *),EsObject * knil,EsObject * list,void * user_data)301519118124SMasatake YAMATO EsObject* es_fold (EsObject * (*kons) (EsObject *, EsObject *, void *),
301619118124SMasatake YAMATO 				   EsObject * knil, EsObject * list, void *user_data)
301719118124SMasatake YAMATO {
301819118124SMasatake YAMATO 	EsObject *r = knil;
301919118124SMasatake YAMATO 
302019118124SMasatake YAMATO 	es_autounref_pool_push();
302119118124SMasatake YAMATO 	while (!es_null (list))
302219118124SMasatake YAMATO 	{
302319118124SMasatake YAMATO 		EsObject *e = es_car (list);
302419118124SMasatake YAMATO 		list = es_cdr (list);
302519118124SMasatake YAMATO 
302619118124SMasatake YAMATO 		r = (* kons) (e, (r == knil) ? r : es_object_autounref (r),
302719118124SMasatake YAMATO 					  user_data);
302819118124SMasatake YAMATO 		if (es_error_p (r))
302919118124SMasatake YAMATO 			break;
303019118124SMasatake YAMATO 	}
303119118124SMasatake YAMATO 	es_autounref_pool_pop();
303219118124SMasatake YAMATO 
303319118124SMasatake YAMATO 	return r;
303419118124SMasatake YAMATO }
303519118124SMasatake YAMATO 
3036e475a54fSMasatake YAMATO static EsObject*
es_vmatch_atom_input(EsObject * input,EsObject * fmt_object,va_list * ap)3037e475a54fSMasatake YAMATO es_vmatch_atom_input(EsObject* input, EsObject* fmt_object, va_list *ap)
3038e475a54fSMasatake YAMATO {
3039e475a54fSMasatake YAMATO 	return ES_READER_ERROR;
3040e475a54fSMasatake YAMATO }
3041e475a54fSMasatake YAMATO 
3042e475a54fSMasatake YAMATO static EsObject*
es_vmatch_atom_fmt(EsObject * input,EsObject * fmt_object,va_list * ap)3043e475a54fSMasatake YAMATO es_vmatch_atom_fmt(EsObject* input, EsObject* fmt_object, va_list *ap)
3044e475a54fSMasatake YAMATO {
3045e475a54fSMasatake YAMATO 	if (fmt_object == pattern_unquote)
3046e475a54fSMasatake YAMATO 		*(va_arg(*ap, EsObject**)) = /* es_object_ref */(input);
3047e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_i_unquote)
3048e475a54fSMasatake YAMATO 		;
3049e475a54fSMasatake YAMATO 	else
3050e475a54fSMasatake YAMATO 		return ES_READER_ERROR;
3051e475a54fSMasatake YAMATO 
3052e475a54fSMasatake YAMATO 	return fmt_object;
3053e475a54fSMasatake YAMATO }
3054e475a54fSMasatake YAMATO 
3055e475a54fSMasatake YAMATO static EsObject*
es_vmatch_atom(EsObject * input,EsObject * fmt_object,va_list * ap)3056e475a54fSMasatake YAMATO es_vmatch_atom(EsObject* input, EsObject* fmt_object, va_list *ap)
3057e475a54fSMasatake YAMATO {
3058e475a54fSMasatake YAMATO 	if (fmt_object == pattern_d)
3059e475a54fSMasatake YAMATO     {
3060e475a54fSMasatake YAMATO 		if (es_integer_p(input))
3061e475a54fSMasatake YAMATO 			*(va_arg(*ap, int*)) = es_integer_get(input);
3062e475a54fSMasatake YAMATO 		else
3063e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3064e475a54fSMasatake YAMATO     }
3065e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_i_d)
3066e475a54fSMasatake YAMATO     {
3067e475a54fSMasatake YAMATO 		if (es_integer_p(input))
3068e475a54fSMasatake YAMATO 			;
3069e475a54fSMasatake YAMATO 		else
3070e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3071e475a54fSMasatake YAMATO     }
3072e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_f)
3073e475a54fSMasatake YAMATO     {
3074e475a54fSMasatake YAMATO 		if (es_real_p(input))
3075e475a54fSMasatake YAMATO 			*(va_arg(*ap, double*)) = es_real_get(input);
3076e475a54fSMasatake YAMATO 		else
3077e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3078e475a54fSMasatake YAMATO     }
3079e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_i_f)
3080e475a54fSMasatake YAMATO     {
3081e475a54fSMasatake YAMATO 		if (es_real_p(input))
3082e475a54fSMasatake YAMATO 			;
3083e475a54fSMasatake YAMATO 		else
3084e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3085e475a54fSMasatake YAMATO     }
3086e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_F)
3087e475a54fSMasatake YAMATO     {
3088e475a54fSMasatake YAMATO 		if (es_integer_p(input))
3089e475a54fSMasatake YAMATO 		{
3090e475a54fSMasatake YAMATO 			int i;
3091e475a54fSMasatake YAMATO 
3092e475a54fSMasatake YAMATO 			i = es_integer_get(input);
3093e475a54fSMasatake YAMATO 			*(va_arg(*ap, double*)) = (double)i;
3094e475a54fSMasatake YAMATO 		}
3095e475a54fSMasatake YAMATO 		else if (es_real_p(input))
3096e475a54fSMasatake YAMATO 		{
3097e475a54fSMasatake YAMATO 			*(va_arg(*ap, double*)) = es_real_get(input);
3098e475a54fSMasatake YAMATO 		}
3099e475a54fSMasatake YAMATO 		else
3100e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3101e475a54fSMasatake YAMATO     }
3102e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_i_F)
3103e475a54fSMasatake YAMATO     {
3104e475a54fSMasatake YAMATO 		if (es_integer_p(input) || es_real_p(input))
3105e475a54fSMasatake YAMATO 			;
3106e475a54fSMasatake YAMATO 		else
3107e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3108e475a54fSMasatake YAMATO     }
3109e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_s)
3110e475a54fSMasatake YAMATO     {
3111e475a54fSMasatake YAMATO 		if (es_string_p(input))
3112e475a54fSMasatake YAMATO 			*(va_arg(*ap, const char**)) = /* strdup */(es_string_get(input));
3113e475a54fSMasatake YAMATO 		else
3114e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3115e475a54fSMasatake YAMATO     }
3116e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_i_s)
3117e475a54fSMasatake YAMATO     {
3118e475a54fSMasatake YAMATO 		if (es_string_p(input))
3119e475a54fSMasatake YAMATO 			;
3120e475a54fSMasatake YAMATO 		else
3121e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3122e475a54fSMasatake YAMATO     }
3123e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_S)
3124e475a54fSMasatake YAMATO     {
3125e475a54fSMasatake YAMATO 		if (es_symbol_p(input))
3126e475a54fSMasatake YAMATO 			*(va_arg(*ap, const char**)) = /* strdup */(es_symbol_get(input));
3127e475a54fSMasatake YAMATO 		else
3128e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3129e475a54fSMasatake YAMATO     }
3130e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_i_S)
3131e475a54fSMasatake YAMATO     {
3132e475a54fSMasatake YAMATO 		if (es_symbol_p(input))
3133e475a54fSMasatake YAMATO 			;
3134e475a54fSMasatake YAMATO 		else
3135e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3136e475a54fSMasatake YAMATO     }
3137e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_b)
3138e475a54fSMasatake YAMATO     {
3139e475a54fSMasatake YAMATO 		if (es_boolean_p(input))
3140e475a54fSMasatake YAMATO 			*(va_arg(*ap, int*)) = es_boolean_get(input);
3141e475a54fSMasatake YAMATO 		else
3142e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3143e475a54fSMasatake YAMATO     }
3144e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_i_b)
3145e475a54fSMasatake YAMATO     {
3146e475a54fSMasatake YAMATO 		if (es_boolean_p(input))
3147e475a54fSMasatake YAMATO 			;
3148e475a54fSMasatake YAMATO 		else
3149e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3150e475a54fSMasatake YAMATO     }
3151e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_unquote)
3152e475a54fSMasatake YAMATO 		*(va_arg(*ap, EsObject**)) = /* es_object_ref */(input);
3153e475a54fSMasatake YAMATO 	else if (fmt_object == pattern_i_unquote)
3154e475a54fSMasatake YAMATO 		;
3155e475a54fSMasatake YAMATO 	else if (es_object_equal(fmt_object, input))
3156e475a54fSMasatake YAMATO 		;
3157e475a54fSMasatake YAMATO 	else
3158e475a54fSMasatake YAMATO 		return ES_READER_ERROR;
3159e475a54fSMasatake YAMATO 
3160e475a54fSMasatake YAMATO 	return fmt_object;
3161e475a54fSMasatake YAMATO }
3162e475a54fSMasatake YAMATO 
3163e475a54fSMasatake YAMATO static void
recover(EsObject * fmt_object,va_list * aq)3164e475a54fSMasatake YAMATO recover(EsObject* fmt_object, va_list *aq)
3165e475a54fSMasatake YAMATO {
3166e475a54fSMasatake YAMATO 	if (es_cons_p(fmt_object))
3167e475a54fSMasatake YAMATO     {
3168e475a54fSMasatake YAMATO 		recover(es_car(fmt_object), aq);
3169e475a54fSMasatake YAMATO 		recover(es_cdr(fmt_object), aq);
3170e475a54fSMasatake YAMATO     }
3171e475a54fSMasatake YAMATO 	else
3172e475a54fSMasatake YAMATO     {
3173e475a54fSMasatake YAMATO 		if (fmt_object == pattern_s
3174e475a54fSMasatake YAMATO 			|| fmt_object == pattern_S)
3175e475a54fSMasatake YAMATO 		{
3176e475a54fSMasatake YAMATO 			char **s;
3177e475a54fSMasatake YAMATO 
3178e475a54fSMasatake YAMATO 			s = va_arg(*aq, char **);
3179e475a54fSMasatake YAMATO 			(void)/* free */(*s);
3180e475a54fSMasatake YAMATO 
3181e475a54fSMasatake YAMATO 			*s = NULL;
3182e475a54fSMasatake YAMATO 		}
3183e475a54fSMasatake YAMATO 		else if (fmt_object == pattern_rest
3184e475a54fSMasatake YAMATO 				 || fmt_object == pattern_unquote)
3185e475a54fSMasatake YAMATO 		{
3186e475a54fSMasatake YAMATO 			EsObject** o;
3187e475a54fSMasatake YAMATO 
3188e475a54fSMasatake YAMATO 			o = va_arg(*aq, EsObject**);
3189e475a54fSMasatake YAMATO 			(void)/* es_object_unref */(*o);
3190e475a54fSMasatake YAMATO 			*o = NULL;
3191e475a54fSMasatake YAMATO 		}
3192e475a54fSMasatake YAMATO     }
3193e475a54fSMasatake YAMATO }
3194e475a54fSMasatake YAMATO 
3195e475a54fSMasatake YAMATO static EsObject*
es_vmatch(EsObject * input,EsObject * fmt_object,va_list * ap)3196e475a54fSMasatake YAMATO es_vmatch(EsObject* input, EsObject* fmt_object, va_list *ap)
3197e475a54fSMasatake YAMATO {
3198e475a54fSMasatake YAMATO 	pattern_init();
3199e475a54fSMasatake YAMATO 
3200e475a54fSMasatake YAMATO 	if (es_cons_p(fmt_object) && es_cons_p(input))
3201e475a54fSMasatake YAMATO     {
3202e475a54fSMasatake YAMATO 		EsObject* fmt_car;
3203e475a54fSMasatake YAMATO 		EsObject* fmt_cdr;
3204e475a54fSMasatake YAMATO 		EsObject* i_car;
3205e475a54fSMasatake YAMATO 		EsObject* i_cdr;
3206e475a54fSMasatake YAMATO 
3207e475a54fSMasatake YAMATO 		EsObject* r_car;
3208e475a54fSMasatake YAMATO 		EsObject* r_cdr;
3209e475a54fSMasatake YAMATO 
3210e475a54fSMasatake YAMATO 		va_list   aq;
3211e475a54fSMasatake YAMATO 
3212e475a54fSMasatake YAMATO 		fmt_car = es_car(fmt_object);
3213e475a54fSMasatake YAMATO 
3214e475a54fSMasatake YAMATO 		if (fmt_car == pattern_rest)
3215e475a54fSMasatake YAMATO 		{
3216e475a54fSMasatake YAMATO 			*(va_arg(*ap, EsObject**)) = /* es_object_ref */(input);
3217e475a54fSMasatake YAMATO 			return fmt_car;
3218e475a54fSMasatake YAMATO 		}
3219e475a54fSMasatake YAMATO 		else if (fmt_car == pattern_i_rest)
3220e475a54fSMasatake YAMATO 		{
3221e475a54fSMasatake YAMATO 			return fmt_car;
3222e475a54fSMasatake YAMATO 		}
3223e475a54fSMasatake YAMATO 
3224e475a54fSMasatake YAMATO 		fmt_cdr = es_cdr(fmt_object);
3225e475a54fSMasatake YAMATO 
3226e475a54fSMasatake YAMATO 		i_car   = es_car(input);
3227e475a54fSMasatake YAMATO 		i_cdr   = es_cdr(input);
3228e475a54fSMasatake YAMATO 
3229e475a54fSMasatake YAMATO 		va_copy(aq, *ap);
3230e475a54fSMasatake YAMATO 		r_car = es_vmatch(i_car, fmt_car, ap);
3231e475a54fSMasatake YAMATO 		if (es_error_p(r_car))
3232e475a54fSMasatake YAMATO 		{
3233e475a54fSMasatake YAMATO 			va_end(aq);
3234e475a54fSMasatake YAMATO 			return r_car;
3235e475a54fSMasatake YAMATO 		}
3236e475a54fSMasatake YAMATO 
3237e475a54fSMasatake YAMATO 		r_cdr = es_vmatch(i_cdr, fmt_cdr, ap);
3238e475a54fSMasatake YAMATO 		if (es_error_p(r_cdr))
3239e475a54fSMasatake YAMATO 		{
3240e475a54fSMasatake YAMATO 			recover(fmt_car, &aq);
3241e475a54fSMasatake YAMATO 			va_end(aq);
3242e475a54fSMasatake YAMATO 			return r_cdr;
3243e475a54fSMasatake YAMATO 		}
3244e475a54fSMasatake YAMATO 		va_end(aq);
3245e475a54fSMasatake YAMATO 		return r_cdr;
3246e475a54fSMasatake YAMATO     }
3247e475a54fSMasatake YAMATO 	else if (es_cons_p(fmt_object))
3248e475a54fSMasatake YAMATO     {
3249e475a54fSMasatake YAMATO 		return es_vmatch_atom_input(input, fmt_object, ap);
3250e475a54fSMasatake YAMATO     }
3251e475a54fSMasatake YAMATO 	else if (es_cons_p(input))
3252e475a54fSMasatake YAMATO     {
3253e475a54fSMasatake YAMATO 		if (fmt_object == pattern_rest)
3254e475a54fSMasatake YAMATO 		{
3255e475a54fSMasatake YAMATO 			*(va_arg(*ap, EsObject**)) = /* es_object_ref */(input);
3256e475a54fSMasatake YAMATO 			return fmt_object;
3257e475a54fSMasatake YAMATO 		}
3258e475a54fSMasatake YAMATO 		else if (fmt_object == pattern_i_rest)
3259e475a54fSMasatake YAMATO 			return fmt_object;
3260e475a54fSMasatake YAMATO 		else
3261e475a54fSMasatake YAMATO 			return es_vmatch_atom_fmt(input, fmt_object, ap);
3262e475a54fSMasatake YAMATO     }
3263e475a54fSMasatake YAMATO 	else
3264e475a54fSMasatake YAMATO     {
3265e475a54fSMasatake YAMATO 		return es_vmatch_atom(input, fmt_object, ap);
3266e475a54fSMasatake YAMATO     }
3267e475a54fSMasatake YAMATO }
3268e475a54fSMasatake YAMATO 
3269e475a54fSMasatake YAMATO int
es_match(EsObject * input,EsObject * fmt_object,...)3270e475a54fSMasatake YAMATO es_match(EsObject* input, EsObject* fmt_object,...)
3271e475a54fSMasatake YAMATO {
3272e475a54fSMasatake YAMATO 	EsObject* object;
3273e475a54fSMasatake YAMATO 	va_list ap;
3274e475a54fSMasatake YAMATO 
3275e475a54fSMasatake YAMATO 	va_start(ap, fmt_object);
3276e475a54fSMasatake YAMATO 	object = es_vmatch(input, fmt_object, &ap);
3277e475a54fSMasatake YAMATO 	va_end(ap);
3278e475a54fSMasatake YAMATO 
3279e475a54fSMasatake YAMATO 	return !(es_error_p(object));
3280e475a54fSMasatake YAMATO }
3281e475a54fSMasatake YAMATO 
3282e475a54fSMasatake YAMATO int
es_smatch(EsObject * input,const char * fmt,...)3283e475a54fSMasatake YAMATO es_smatch   (EsObject* input, const char* fmt,...)
3284e475a54fSMasatake YAMATO {
3285e475a54fSMasatake YAMATO 	int r;
3286e475a54fSMasatake YAMATO 	EsObject* object;
3287e475a54fSMasatake YAMATO 	EsObject* fmt_object;
3288e475a54fSMasatake YAMATO 	va_list ap;
3289e475a54fSMasatake YAMATO 
3290e475a54fSMasatake YAMATO 	fmt_object = es_read_from_string(fmt, NULL);
3291e475a54fSMasatake YAMATO 	if (es_error_p(fmt_object))
3292e475a54fSMasatake YAMATO 		return 0;
3293e475a54fSMasatake YAMATO 
3294e475a54fSMasatake YAMATO 	va_start(ap, fmt);
3295e475a54fSMasatake YAMATO 	object = es_vmatch(input, fmt_object, &ap);
3296e475a54fSMasatake YAMATO 	va_end(ap);
3297e475a54fSMasatake YAMATO 
3298e475a54fSMasatake YAMATO 	r = !(es_error_p(object));
3299e475a54fSMasatake YAMATO 	es_object_unref(fmt_object);
3300e475a54fSMasatake YAMATO 
3301e475a54fSMasatake YAMATO 	return r;
3302e475a54fSMasatake YAMATO }
3303e475a54fSMasatake YAMATO 
3304e475a54fSMasatake YAMATO EsObject*
es_pget(EsObject * plist,EsObject * key,EsObject * default_value)3305e475a54fSMasatake YAMATO es_pget (EsObject* plist, EsObject* key, EsObject* default_value)
3306e475a54fSMasatake YAMATO {
3307e475a54fSMasatake YAMATO 	if (es_cons_p(plist))
3308e475a54fSMasatake YAMATO     {
3309e475a54fSMasatake YAMATO 		EsObject* car;
3310e475a54fSMasatake YAMATO 		EsObject* cdr;
3311e475a54fSMasatake YAMATO 		EsObject* cadr;
3312e475a54fSMasatake YAMATO 		EsObject* cddr;
3313e475a54fSMasatake YAMATO 
3314e475a54fSMasatake YAMATO 		car = es_car(plist);
3315e475a54fSMasatake YAMATO 		cdr = es_cdr(plist);
3316e475a54fSMasatake YAMATO 
3317e475a54fSMasatake YAMATO 		if (es_cons_p(cdr))
3318e475a54fSMasatake YAMATO 		{
3319e475a54fSMasatake YAMATO 			cadr = es_car(cdr);
3320e475a54fSMasatake YAMATO 			cddr = es_cdr(cdr);
3321e475a54fSMasatake YAMATO 
3322e475a54fSMasatake YAMATO 			if (es_object_equal(car, key))
3323e475a54fSMasatake YAMATO 				return cadr;
3324e475a54fSMasatake YAMATO 			else
3325e475a54fSMasatake YAMATO 				return es_pget(cddr, key, default_value);
3326e475a54fSMasatake YAMATO 		}
3327e475a54fSMasatake YAMATO 		else
3328e475a54fSMasatake YAMATO 			return ES_READER_ERROR;
3329e475a54fSMasatake YAMATO     }
3330e475a54fSMasatake YAMATO 	else
3331e475a54fSMasatake YAMATO 		return default_value;
3332e475a54fSMasatake YAMATO }
3333