1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  ALSA lisp implementation
3d5ac70f0Sopenharmony_ci *  Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
4d5ac70f0Sopenharmony_ci *
5d5ac70f0Sopenharmony_ci *  Based on work of Sandro Sigala (slisp-1.2)
6d5ac70f0Sopenharmony_ci *
7d5ac70f0Sopenharmony_ci *
8d5ac70f0Sopenharmony_ci *   This library is free software; you can redistribute it and/or modify
9d5ac70f0Sopenharmony_ci *   it under the terms of the GNU Lesser General Public License as
10d5ac70f0Sopenharmony_ci *   published by the Free Software Foundation; either version 2.1 of
11d5ac70f0Sopenharmony_ci *   the License, or (at your option) any later version.
12d5ac70f0Sopenharmony_ci *
13d5ac70f0Sopenharmony_ci *   This program is distributed in the hope that it will be useful,
14d5ac70f0Sopenharmony_ci *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15d5ac70f0Sopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16d5ac70f0Sopenharmony_ci *   GNU Lesser General Public License for more details.
17d5ac70f0Sopenharmony_ci *
18d5ac70f0Sopenharmony_ci *   You should have received a copy of the GNU Lesser General Public
19d5ac70f0Sopenharmony_ci *   License along with this library; if not, write to the Free Software
20d5ac70f0Sopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21d5ac70f0Sopenharmony_ci *
22d5ac70f0Sopenharmony_ci */
23d5ac70f0Sopenharmony_ci
24d5ac70f0Sopenharmony_ci#define alisp_seq_iterator alisp_object
25d5ac70f0Sopenharmony_ci
26d5ac70f0Sopenharmony_ci#include "local.h"
27d5ac70f0Sopenharmony_ci#include "alisp.h"
28d5ac70f0Sopenharmony_ci#include "alisp_local.h"
29d5ac70f0Sopenharmony_ci
30d5ac70f0Sopenharmony_ci#include <assert.h>
31d5ac70f0Sopenharmony_ci
32d5ac70f0Sopenharmony_ci#include <limits.h>
33d5ac70f0Sopenharmony_ci#include <stdio.h>
34d5ac70f0Sopenharmony_ci#include <stdlib.h>
35d5ac70f0Sopenharmony_ci#include <string.h>
36d5ac70f0Sopenharmony_ci#include <ctype.h>
37d5ac70f0Sopenharmony_ci#include <math.h>
38d5ac70f0Sopenharmony_ci#include <err.h>
39d5ac70f0Sopenharmony_ci
40d5ac70f0Sopenharmony_ci
41d5ac70f0Sopenharmony_cistruct alisp_object alsa_lisp_nil;
42d5ac70f0Sopenharmony_cistruct alisp_object alsa_lisp_t;
43d5ac70f0Sopenharmony_ci
44d5ac70f0Sopenharmony_ci/* parser prototypes */
45d5ac70f0Sopenharmony_cistatic struct alisp_object * parse_object(struct alisp_instance *instance, int havetoken);
46d5ac70f0Sopenharmony_cistatic void princ_cons(snd_output_t *out, struct alisp_object * p);
47d5ac70f0Sopenharmony_cistatic void princ_object(snd_output_t *out, struct alisp_object * p);
48d5ac70f0Sopenharmony_cistatic struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p);
49d5ac70f0Sopenharmony_ci
50d5ac70f0Sopenharmony_ci/* functions */
51d5ac70f0Sopenharmony_cistatic struct alisp_object *F_eval(struct alisp_instance *instance, struct alisp_object *);
52d5ac70f0Sopenharmony_cistatic struct alisp_object *F_progn(struct alisp_instance *instance, struct alisp_object *);
53d5ac70f0Sopenharmony_cistatic struct alisp_object *F_funcall(struct alisp_instance *instance, struct alisp_object *);
54d5ac70f0Sopenharmony_ci
55d5ac70f0Sopenharmony_ci/* others */
56d5ac70f0Sopenharmony_cistatic int alisp_include_file(struct alisp_instance *instance, const char *filename);
57d5ac70f0Sopenharmony_ci
58d5ac70f0Sopenharmony_ci/*
59d5ac70f0Sopenharmony_ci *  object handling
60d5ac70f0Sopenharmony_ci */
61d5ac70f0Sopenharmony_ci
62d5ac70f0Sopenharmony_cistatic int get_string_hash(const char *s)
63d5ac70f0Sopenharmony_ci{
64d5ac70f0Sopenharmony_ci	int val = 0;
65d5ac70f0Sopenharmony_ci	if (s == NULL)
66d5ac70f0Sopenharmony_ci		return val;
67d5ac70f0Sopenharmony_ci	while (*s)
68d5ac70f0Sopenharmony_ci		val += *s++;
69d5ac70f0Sopenharmony_ci	return val & ALISP_OBJ_PAIR_HASH_MASK;
70d5ac70f0Sopenharmony_ci}
71d5ac70f0Sopenharmony_ci
72d5ac70f0Sopenharmony_cistatic void nomem(void)
73d5ac70f0Sopenharmony_ci{
74d5ac70f0Sopenharmony_ci	SNDERR("alisp: no enough memory");
75d5ac70f0Sopenharmony_ci}
76d5ac70f0Sopenharmony_ci
77d5ac70f0Sopenharmony_cistatic void lisp_verbose(struct alisp_instance *instance, const char *fmt, ...)
78d5ac70f0Sopenharmony_ci{
79d5ac70f0Sopenharmony_ci	va_list ap;
80d5ac70f0Sopenharmony_ci
81d5ac70f0Sopenharmony_ci	if (!instance->verbose)
82d5ac70f0Sopenharmony_ci		return;
83d5ac70f0Sopenharmony_ci	va_start(ap, fmt);
84d5ac70f0Sopenharmony_ci	snd_output_printf(instance->vout, "alisp: ");
85d5ac70f0Sopenharmony_ci	snd_output_vprintf(instance->vout, fmt, ap);
86d5ac70f0Sopenharmony_ci	snd_output_putc(instance->vout, '\n');
87d5ac70f0Sopenharmony_ci	va_end(ap);
88d5ac70f0Sopenharmony_ci}
89d5ac70f0Sopenharmony_ci
90d5ac70f0Sopenharmony_cistatic void lisp_error(struct alisp_instance *instance, const char *fmt, ...)
91d5ac70f0Sopenharmony_ci{
92d5ac70f0Sopenharmony_ci	va_list ap;
93d5ac70f0Sopenharmony_ci
94d5ac70f0Sopenharmony_ci	if (!instance->warning)
95d5ac70f0Sopenharmony_ci		return;
96d5ac70f0Sopenharmony_ci	va_start(ap, fmt);
97d5ac70f0Sopenharmony_ci	snd_output_printf(instance->eout, "alisp error: ");
98d5ac70f0Sopenharmony_ci	snd_output_vprintf(instance->eout, fmt, ap);
99d5ac70f0Sopenharmony_ci	snd_output_putc(instance->eout, '\n');
100d5ac70f0Sopenharmony_ci	va_end(ap);
101d5ac70f0Sopenharmony_ci}
102d5ac70f0Sopenharmony_ci
103d5ac70f0Sopenharmony_cistatic void lisp_warn(struct alisp_instance *instance, const char *fmt, ...)
104d5ac70f0Sopenharmony_ci{
105d5ac70f0Sopenharmony_ci	va_list ap;
106d5ac70f0Sopenharmony_ci
107d5ac70f0Sopenharmony_ci	if (!instance->warning)
108d5ac70f0Sopenharmony_ci		return;
109d5ac70f0Sopenharmony_ci	va_start(ap, fmt);
110d5ac70f0Sopenharmony_ci	snd_output_printf(instance->wout, "alisp warning: ");
111d5ac70f0Sopenharmony_ci	snd_output_vprintf(instance->wout, fmt, ap);
112d5ac70f0Sopenharmony_ci	snd_output_putc(instance->wout, '\n');
113d5ac70f0Sopenharmony_ci	va_end(ap);
114d5ac70f0Sopenharmony_ci}
115d5ac70f0Sopenharmony_ci
116d5ac70f0Sopenharmony_cistatic void lisp_debug(struct alisp_instance *instance, const char *fmt, ...)
117d5ac70f0Sopenharmony_ci{
118d5ac70f0Sopenharmony_ci	va_list ap;
119d5ac70f0Sopenharmony_ci
120d5ac70f0Sopenharmony_ci	if (!instance->debug)
121d5ac70f0Sopenharmony_ci		return;
122d5ac70f0Sopenharmony_ci	va_start(ap, fmt);
123d5ac70f0Sopenharmony_ci	snd_output_printf(instance->dout, "alisp debug: ");
124d5ac70f0Sopenharmony_ci	snd_output_vprintf(instance->dout, fmt, ap);
125d5ac70f0Sopenharmony_ci	snd_output_putc(instance->dout, '\n');
126d5ac70f0Sopenharmony_ci	va_end(ap);
127d5ac70f0Sopenharmony_ci}
128d5ac70f0Sopenharmony_ci
129d5ac70f0Sopenharmony_cistatic struct alisp_object * new_object(struct alisp_instance *instance, int type)
130d5ac70f0Sopenharmony_ci{
131d5ac70f0Sopenharmony_ci	struct alisp_object * p;
132d5ac70f0Sopenharmony_ci
133d5ac70f0Sopenharmony_ci	if (list_empty(&instance->free_objs_list)) {
134d5ac70f0Sopenharmony_ci		p = (struct alisp_object *)malloc(sizeof(struct alisp_object));
135d5ac70f0Sopenharmony_ci		if (p == NULL) {
136d5ac70f0Sopenharmony_ci			nomem();
137d5ac70f0Sopenharmony_ci			return NULL;
138d5ac70f0Sopenharmony_ci		}
139d5ac70f0Sopenharmony_ci		lisp_debug(instance, "allocating cons %p", p);
140d5ac70f0Sopenharmony_ci	} else {
141d5ac70f0Sopenharmony_ci		p = (struct alisp_object *)instance->free_objs_list.next;
142d5ac70f0Sopenharmony_ci		list_del(&p->list);
143d5ac70f0Sopenharmony_ci		instance->free_objs--;
144d5ac70f0Sopenharmony_ci		lisp_debug(instance, "recycling cons %p", p);
145d5ac70f0Sopenharmony_ci	}
146d5ac70f0Sopenharmony_ci
147d5ac70f0Sopenharmony_ci	instance->used_objs++;
148d5ac70f0Sopenharmony_ci
149d5ac70f0Sopenharmony_ci	alisp_set_type(p, type);
150d5ac70f0Sopenharmony_ci	alisp_set_refs(p, 1);
151d5ac70f0Sopenharmony_ci	if (type == ALISP_OBJ_CONS) {
152d5ac70f0Sopenharmony_ci		p->value.c.car = &alsa_lisp_nil;
153d5ac70f0Sopenharmony_ci		p->value.c.cdr = &alsa_lisp_nil;
154d5ac70f0Sopenharmony_ci		list_add(&p->list, &instance->used_objs_list[0][ALISP_OBJ_CONS]);
155d5ac70f0Sopenharmony_ci	}
156d5ac70f0Sopenharmony_ci
157d5ac70f0Sopenharmony_ci	if (instance->used_objs + instance->free_objs > instance->max_objs)
158d5ac70f0Sopenharmony_ci		instance->max_objs = instance->used_objs + instance->free_objs;
159d5ac70f0Sopenharmony_ci
160d5ac70f0Sopenharmony_ci	return p;
161d5ac70f0Sopenharmony_ci}
162d5ac70f0Sopenharmony_ci
163d5ac70f0Sopenharmony_cistatic void free_object(struct alisp_object * p)
164d5ac70f0Sopenharmony_ci{
165d5ac70f0Sopenharmony_ci	switch (alisp_get_type(p)) {
166d5ac70f0Sopenharmony_ci	case ALISP_OBJ_STRING:
167d5ac70f0Sopenharmony_ci	case ALISP_OBJ_IDENTIFIER:
168d5ac70f0Sopenharmony_ci		free(p->value.s);
169d5ac70f0Sopenharmony_ci		alisp_set_type(p, ALISP_OBJ_INTEGER);
170d5ac70f0Sopenharmony_ci		break;
171d5ac70f0Sopenharmony_ci	default:
172d5ac70f0Sopenharmony_ci		break;
173d5ac70f0Sopenharmony_ci	}
174d5ac70f0Sopenharmony_ci}
175d5ac70f0Sopenharmony_ci
176d5ac70f0Sopenharmony_cistatic void delete_object(struct alisp_instance *instance, struct alisp_object * p)
177d5ac70f0Sopenharmony_ci{
178d5ac70f0Sopenharmony_ci	if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
179d5ac70f0Sopenharmony_ci		return;
180d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_NIL) ||
181d5ac70f0Sopenharmony_ci	    alisp_compare_type(p, ALISP_OBJ_T))
182d5ac70f0Sopenharmony_ci		return;
183d5ac70f0Sopenharmony_ci	assert(alisp_get_refs(p) > 0);
184d5ac70f0Sopenharmony_ci	lisp_debug(instance, "delete cons %p (type = %i, refs = %i) (s = '%s')", p, alisp_get_type(p), alisp_get_refs(p),
185d5ac70f0Sopenharmony_ci			alisp_compare_type(p, ALISP_OBJ_STRING) ||
186d5ac70f0Sopenharmony_ci			alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) ? p->value.s : "???");
187d5ac70f0Sopenharmony_ci	if (alisp_dec_refs(p))
188d5ac70f0Sopenharmony_ci		return;
189d5ac70f0Sopenharmony_ci	list_del(&p->list);
190d5ac70f0Sopenharmony_ci	instance->used_objs--;
191d5ac70f0Sopenharmony_ci	free_object(p);
192d5ac70f0Sopenharmony_ci	if (instance->free_objs >= ALISP_FREE_OBJ_POOL) {
193d5ac70f0Sopenharmony_ci		lisp_debug(instance, "freed cons %p", p);
194d5ac70f0Sopenharmony_ci		free(p);
195d5ac70f0Sopenharmony_ci		return;
196d5ac70f0Sopenharmony_ci	}
197d5ac70f0Sopenharmony_ci	lisp_debug(instance, "moved cons %p to free list", p);
198d5ac70f0Sopenharmony_ci	list_add(&p->list, &instance->free_objs_list);
199d5ac70f0Sopenharmony_ci	instance->free_objs++;
200d5ac70f0Sopenharmony_ci}
201d5ac70f0Sopenharmony_ci
202d5ac70f0Sopenharmony_cistatic void delete_tree(struct alisp_instance *instance, struct alisp_object * p)
203d5ac70f0Sopenharmony_ci{
204d5ac70f0Sopenharmony_ci	if (p == NULL)
205d5ac70f0Sopenharmony_ci		return;
206d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
207d5ac70f0Sopenharmony_ci		delete_tree(instance, p->value.c.car);
208d5ac70f0Sopenharmony_ci		delete_tree(instance, p->value.c.cdr);
209d5ac70f0Sopenharmony_ci	}
210d5ac70f0Sopenharmony_ci	delete_object(instance, p);
211d5ac70f0Sopenharmony_ci}
212d5ac70f0Sopenharmony_ci
213d5ac70f0Sopenharmony_cistatic struct alisp_object * incref_object(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * p)
214d5ac70f0Sopenharmony_ci{
215d5ac70f0Sopenharmony_ci	if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
216d5ac70f0Sopenharmony_ci		return p;
217d5ac70f0Sopenharmony_ci	if (alisp_get_refs(p) == ALISP_MAX_REFS) {
218d5ac70f0Sopenharmony_ci		assert(0);
219d5ac70f0Sopenharmony_ci		fprintf(stderr, "OOPS: alsa lisp: incref fatal error\n");
220d5ac70f0Sopenharmony_ci		exit(EXIT_FAILURE);
221d5ac70f0Sopenharmony_ci	}
222d5ac70f0Sopenharmony_ci	alisp_inc_refs(p);
223d5ac70f0Sopenharmony_ci	return p;
224d5ac70f0Sopenharmony_ci}
225d5ac70f0Sopenharmony_ci
226d5ac70f0Sopenharmony_cistatic struct alisp_object * incref_tree(struct alisp_instance *instance, struct alisp_object * p)
227d5ac70f0Sopenharmony_ci{
228d5ac70f0Sopenharmony_ci	if (p == NULL)
229d5ac70f0Sopenharmony_ci		return NULL;
230d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
231d5ac70f0Sopenharmony_ci		incref_tree(instance, p->value.c.car);
232d5ac70f0Sopenharmony_ci		incref_tree(instance, p->value.c.cdr);
233d5ac70f0Sopenharmony_ci	}
234d5ac70f0Sopenharmony_ci	return incref_object(instance, p);
235d5ac70f0Sopenharmony_ci}
236d5ac70f0Sopenharmony_ci
237d5ac70f0Sopenharmony_ci/* Function not used yet. Leave it commented out until we actually use it to
238d5ac70f0Sopenharmony_ci * avoid compiler complaints */
239d5ac70f0Sopenharmony_ci#if 0
240d5ac70f0Sopenharmony_cistatic struct alisp_object * incref_tree_explicit(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * e)
241d5ac70f0Sopenharmony_ci{
242d5ac70f0Sopenharmony_ci	if (p == NULL)
243d5ac70f0Sopenharmony_ci		return NULL;
244d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
245d5ac70f0Sopenharmony_ci		if (e == p) {
246d5ac70f0Sopenharmony_ci			incref_tree(instance, p->value.c.car);
247d5ac70f0Sopenharmony_ci			incref_tree(instance, p->value.c.cdr);
248d5ac70f0Sopenharmony_ci		} else {
249d5ac70f0Sopenharmony_ci			incref_tree_explicit(instance, p->value.c.car, e);
250d5ac70f0Sopenharmony_ci			incref_tree_explicit(instance, p->value.c.cdr, e);
251d5ac70f0Sopenharmony_ci		}
252d5ac70f0Sopenharmony_ci	}
253d5ac70f0Sopenharmony_ci	if (e == p)
254d5ac70f0Sopenharmony_ci		return incref_object(instance, p);
255d5ac70f0Sopenharmony_ci	return p;
256d5ac70f0Sopenharmony_ci}
257d5ac70f0Sopenharmony_ci#endif
258d5ac70f0Sopenharmony_ci
259d5ac70f0Sopenharmony_cistatic void free_objects(struct alisp_instance *instance)
260d5ac70f0Sopenharmony_ci{
261d5ac70f0Sopenharmony_ci	struct list_head *pos, *pos1;
262d5ac70f0Sopenharmony_ci	struct alisp_object * p;
263d5ac70f0Sopenharmony_ci	struct alisp_object_pair * pair;
264d5ac70f0Sopenharmony_ci	int i, j;
265d5ac70f0Sopenharmony_ci
266d5ac70f0Sopenharmony_ci	for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
267d5ac70f0Sopenharmony_ci		list_for_each_safe(pos, pos1, &instance->setobjs_list[i]) {
268d5ac70f0Sopenharmony_ci			pair = list_entry(pos, struct alisp_object_pair, list);
269d5ac70f0Sopenharmony_ci			lisp_debug(instance, "freeing pair: '%s' -> %p", pair->name, pair->value);
270d5ac70f0Sopenharmony_ci			delete_tree(instance, pair->value);
271d5ac70f0Sopenharmony_ci			free((void *)pair->name);
272d5ac70f0Sopenharmony_ci			free(pair);
273d5ac70f0Sopenharmony_ci		}
274d5ac70f0Sopenharmony_ci	}
275d5ac70f0Sopenharmony_ci	for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
276d5ac70f0Sopenharmony_ci		for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++) {
277d5ac70f0Sopenharmony_ci			list_for_each_safe(pos, pos1, &instance->used_objs_list[i][j]) {
278d5ac70f0Sopenharmony_ci				p = list_entry(pos, struct alisp_object, list);
279d5ac70f0Sopenharmony_ci				lisp_warn(instance, "object %p is still referenced %i times!", p, alisp_get_refs(p));
280d5ac70f0Sopenharmony_ci#if 0
281d5ac70f0Sopenharmony_ci				snd_output_printf(instance->wout, ">>>> ");
282d5ac70f0Sopenharmony_ci				princ_object(instance->wout, p);
283d5ac70f0Sopenharmony_ci				snd_output_printf(instance->wout, " <<<<\n");
284d5ac70f0Sopenharmony_ci#endif
285d5ac70f0Sopenharmony_ci				if (alisp_get_refs(p) > 0)
286d5ac70f0Sopenharmony_ci					alisp_set_refs(p, 1);
287d5ac70f0Sopenharmony_ci				delete_object(instance, p);
288d5ac70f0Sopenharmony_ci			}
289d5ac70f0Sopenharmony_ci		}
290d5ac70f0Sopenharmony_ci	list_for_each_safe(pos, pos1, &instance->free_objs_list) {
291d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object, list);
292d5ac70f0Sopenharmony_ci		list_del(&p->list);
293d5ac70f0Sopenharmony_ci		free(p);
294d5ac70f0Sopenharmony_ci		lisp_debug(instance, "freed (all) cons %p", p);
295d5ac70f0Sopenharmony_ci	}
296d5ac70f0Sopenharmony_ci}
297d5ac70f0Sopenharmony_ci
298d5ac70f0Sopenharmony_cistatic struct alisp_object * search_object_identifier(struct alisp_instance *instance, const char *s)
299d5ac70f0Sopenharmony_ci{
300d5ac70f0Sopenharmony_ci	struct list_head * pos;
301d5ac70f0Sopenharmony_ci	struct alisp_object * p;
302d5ac70f0Sopenharmony_ci
303d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->used_objs_list[get_string_hash(s)][ALISP_OBJ_IDENTIFIER]) {
304d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object, list);
305d5ac70f0Sopenharmony_ci		if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
306d5ac70f0Sopenharmony_ci			continue;
307d5ac70f0Sopenharmony_ci		if (!strcmp(p->value.s, s))
308d5ac70f0Sopenharmony_ci			return incref_object(instance, p);
309d5ac70f0Sopenharmony_ci	}
310d5ac70f0Sopenharmony_ci
311d5ac70f0Sopenharmony_ci	return NULL;
312d5ac70f0Sopenharmony_ci}
313d5ac70f0Sopenharmony_ci
314d5ac70f0Sopenharmony_cistatic struct alisp_object * search_object_string(struct alisp_instance *instance, const char *s)
315d5ac70f0Sopenharmony_ci{
316d5ac70f0Sopenharmony_ci	struct list_head * pos;
317d5ac70f0Sopenharmony_ci	struct alisp_object * p;
318d5ac70f0Sopenharmony_ci
319d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->used_objs_list[get_string_hash(s)][ALISP_OBJ_STRING]) {
320d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object, list);
321d5ac70f0Sopenharmony_ci		if (!strcmp(p->value.s, s)) {
322d5ac70f0Sopenharmony_ci			if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
323d5ac70f0Sopenharmony_ci				continue;
324d5ac70f0Sopenharmony_ci			return incref_object(instance, p);
325d5ac70f0Sopenharmony_ci		}
326d5ac70f0Sopenharmony_ci	}
327d5ac70f0Sopenharmony_ci
328d5ac70f0Sopenharmony_ci	return NULL;
329d5ac70f0Sopenharmony_ci}
330d5ac70f0Sopenharmony_ci
331d5ac70f0Sopenharmony_cistatic struct alisp_object * search_object_integer(struct alisp_instance *instance, long in)
332d5ac70f0Sopenharmony_ci{
333d5ac70f0Sopenharmony_ci	struct list_head * pos;
334d5ac70f0Sopenharmony_ci	struct alisp_object * p;
335d5ac70f0Sopenharmony_ci
336d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->used_objs_list[in & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_INTEGER]) {
337d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object, list);
338d5ac70f0Sopenharmony_ci		if (p->value.i == in) {
339d5ac70f0Sopenharmony_ci			if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
340d5ac70f0Sopenharmony_ci				continue;
341d5ac70f0Sopenharmony_ci			return incref_object(instance, p);
342d5ac70f0Sopenharmony_ci		}
343d5ac70f0Sopenharmony_ci	}
344d5ac70f0Sopenharmony_ci
345d5ac70f0Sopenharmony_ci	return NULL;
346d5ac70f0Sopenharmony_ci}
347d5ac70f0Sopenharmony_ci
348d5ac70f0Sopenharmony_cistatic struct alisp_object * search_object_float(struct alisp_instance *instance, double in)
349d5ac70f0Sopenharmony_ci{
350d5ac70f0Sopenharmony_ci	struct list_head * pos;
351d5ac70f0Sopenharmony_ci	struct alisp_object * p;
352d5ac70f0Sopenharmony_ci
353d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->used_objs_list[(long)in & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_FLOAT]) {
354d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object, list);
355d5ac70f0Sopenharmony_ci		if (p->value.i == in) {
356d5ac70f0Sopenharmony_ci			if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
357d5ac70f0Sopenharmony_ci				continue;
358d5ac70f0Sopenharmony_ci			return incref_object(instance, p);
359d5ac70f0Sopenharmony_ci		}
360d5ac70f0Sopenharmony_ci	}
361d5ac70f0Sopenharmony_ci
362d5ac70f0Sopenharmony_ci	return NULL;
363d5ac70f0Sopenharmony_ci}
364d5ac70f0Sopenharmony_ci
365d5ac70f0Sopenharmony_cistatic struct alisp_object * search_object_pointer(struct alisp_instance *instance, const void *ptr)
366d5ac70f0Sopenharmony_ci{
367d5ac70f0Sopenharmony_ci	struct list_head * pos;
368d5ac70f0Sopenharmony_ci	struct alisp_object * p;
369d5ac70f0Sopenharmony_ci
370d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->used_objs_list[(long)ptr & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_POINTER]) {
371d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object, list);
372d5ac70f0Sopenharmony_ci		if (p->value.ptr == ptr) {
373d5ac70f0Sopenharmony_ci			if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
374d5ac70f0Sopenharmony_ci				continue;
375d5ac70f0Sopenharmony_ci			return incref_object(instance, p);
376d5ac70f0Sopenharmony_ci		}
377d5ac70f0Sopenharmony_ci	}
378d5ac70f0Sopenharmony_ci
379d5ac70f0Sopenharmony_ci	return NULL;
380d5ac70f0Sopenharmony_ci}
381d5ac70f0Sopenharmony_ci
382d5ac70f0Sopenharmony_cistatic struct alisp_object * new_integer(struct alisp_instance *instance, long value)
383d5ac70f0Sopenharmony_ci{
384d5ac70f0Sopenharmony_ci	struct alisp_object * obj;
385d5ac70f0Sopenharmony_ci
386d5ac70f0Sopenharmony_ci	obj = search_object_integer(instance, value);
387d5ac70f0Sopenharmony_ci	if (obj != NULL)
388d5ac70f0Sopenharmony_ci		return obj;
389d5ac70f0Sopenharmony_ci	obj = new_object(instance, ALISP_OBJ_INTEGER);
390d5ac70f0Sopenharmony_ci	if (obj) {
391d5ac70f0Sopenharmony_ci		list_add(&obj->list, &instance->used_objs_list[value & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_INTEGER]);
392d5ac70f0Sopenharmony_ci		obj->value.i = value;
393d5ac70f0Sopenharmony_ci	}
394d5ac70f0Sopenharmony_ci	return obj;
395d5ac70f0Sopenharmony_ci}
396d5ac70f0Sopenharmony_ci
397d5ac70f0Sopenharmony_cistatic struct alisp_object * new_float(struct alisp_instance *instance, double value)
398d5ac70f0Sopenharmony_ci{
399d5ac70f0Sopenharmony_ci	struct alisp_object * obj;
400d5ac70f0Sopenharmony_ci
401d5ac70f0Sopenharmony_ci	obj = search_object_float(instance, value);
402d5ac70f0Sopenharmony_ci	if (obj != NULL)
403d5ac70f0Sopenharmony_ci		return obj;
404d5ac70f0Sopenharmony_ci	obj = new_object(instance, ALISP_OBJ_FLOAT);
405d5ac70f0Sopenharmony_ci	if (obj) {
406d5ac70f0Sopenharmony_ci		list_add(&obj->list, &instance->used_objs_list[(long)value & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_FLOAT]);
407d5ac70f0Sopenharmony_ci		obj->value.f = value;
408d5ac70f0Sopenharmony_ci	}
409d5ac70f0Sopenharmony_ci	return obj;
410d5ac70f0Sopenharmony_ci}
411d5ac70f0Sopenharmony_ci
412d5ac70f0Sopenharmony_cistatic struct alisp_object * new_string(struct alisp_instance *instance, const char *str)
413d5ac70f0Sopenharmony_ci{
414d5ac70f0Sopenharmony_ci	struct alisp_object * obj;
415d5ac70f0Sopenharmony_ci
416d5ac70f0Sopenharmony_ci	obj = search_object_string(instance, str);
417d5ac70f0Sopenharmony_ci	if (obj != NULL)
418d5ac70f0Sopenharmony_ci		return obj;
419d5ac70f0Sopenharmony_ci	obj = new_object(instance, ALISP_OBJ_STRING);
420d5ac70f0Sopenharmony_ci	if (obj)
421d5ac70f0Sopenharmony_ci		list_add(&obj->list, &instance->used_objs_list[get_string_hash(str)][ALISP_OBJ_STRING]);
422d5ac70f0Sopenharmony_ci	if (obj && (obj->value.s = strdup(str)) == NULL) {
423d5ac70f0Sopenharmony_ci		delete_object(instance, obj);
424d5ac70f0Sopenharmony_ci		nomem();
425d5ac70f0Sopenharmony_ci		return NULL;
426d5ac70f0Sopenharmony_ci	}
427d5ac70f0Sopenharmony_ci	return obj;
428d5ac70f0Sopenharmony_ci}
429d5ac70f0Sopenharmony_ci
430d5ac70f0Sopenharmony_cistatic struct alisp_object * new_identifier(struct alisp_instance *instance, const char *id)
431d5ac70f0Sopenharmony_ci{
432d5ac70f0Sopenharmony_ci	struct alisp_object * obj;
433d5ac70f0Sopenharmony_ci
434d5ac70f0Sopenharmony_ci	obj = search_object_identifier(instance, id);
435d5ac70f0Sopenharmony_ci	if (obj != NULL)
436d5ac70f0Sopenharmony_ci		return obj;
437d5ac70f0Sopenharmony_ci	obj = new_object(instance, ALISP_OBJ_IDENTIFIER);
438d5ac70f0Sopenharmony_ci	if (obj)
439d5ac70f0Sopenharmony_ci		list_add(&obj->list, &instance->used_objs_list[get_string_hash(id)][ALISP_OBJ_IDENTIFIER]);
440d5ac70f0Sopenharmony_ci	if (obj && (obj->value.s = strdup(id)) == NULL) {
441d5ac70f0Sopenharmony_ci		delete_object(instance, obj);
442d5ac70f0Sopenharmony_ci		nomem();
443d5ac70f0Sopenharmony_ci		return NULL;
444d5ac70f0Sopenharmony_ci	}
445d5ac70f0Sopenharmony_ci	return obj;
446d5ac70f0Sopenharmony_ci}
447d5ac70f0Sopenharmony_ci
448d5ac70f0Sopenharmony_cistatic struct alisp_object * new_pointer(struct alisp_instance *instance, const void *ptr)
449d5ac70f0Sopenharmony_ci{
450d5ac70f0Sopenharmony_ci	struct alisp_object * obj;
451d5ac70f0Sopenharmony_ci
452d5ac70f0Sopenharmony_ci	obj = search_object_pointer(instance, ptr);
453d5ac70f0Sopenharmony_ci	if (obj != NULL)
454d5ac70f0Sopenharmony_ci		return obj;
455d5ac70f0Sopenharmony_ci	obj = new_object(instance, ALISP_OBJ_POINTER);
456d5ac70f0Sopenharmony_ci	if (obj) {
457d5ac70f0Sopenharmony_ci		list_add(&obj->list, &instance->used_objs_list[(long)ptr & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_POINTER]);
458d5ac70f0Sopenharmony_ci		obj->value.ptr = ptr;
459d5ac70f0Sopenharmony_ci	}
460d5ac70f0Sopenharmony_ci	return obj;
461d5ac70f0Sopenharmony_ci}
462d5ac70f0Sopenharmony_ci
463d5ac70f0Sopenharmony_cistatic struct alisp_object * new_cons_pointer(struct alisp_instance * instance, const char *ptr_id, void *ptr)
464d5ac70f0Sopenharmony_ci{
465d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr;
466d5ac70f0Sopenharmony_ci
467d5ac70f0Sopenharmony_ci	if (ptr == NULL)
468d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
469d5ac70f0Sopenharmony_ci	lexpr = new_object(instance, ALISP_OBJ_CONS);
470d5ac70f0Sopenharmony_ci	if (lexpr == NULL)
471d5ac70f0Sopenharmony_ci		return NULL;
472d5ac70f0Sopenharmony_ci	lexpr->value.c.car = new_string(instance, ptr_id);
473d5ac70f0Sopenharmony_ci	if (lexpr->value.c.car == NULL)
474d5ac70f0Sopenharmony_ci		goto __end;
475d5ac70f0Sopenharmony_ci	lexpr->value.c.cdr = new_pointer(instance, ptr);
476d5ac70f0Sopenharmony_ci	if (lexpr->value.c.cdr == NULL) {
477d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr->value.c.car);
478d5ac70f0Sopenharmony_ci	      __end:
479d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr);
480d5ac70f0Sopenharmony_ci		return NULL;
481d5ac70f0Sopenharmony_ci	}
482d5ac70f0Sopenharmony_ci	return lexpr;
483d5ac70f0Sopenharmony_ci}
484d5ac70f0Sopenharmony_ci
485d5ac70f0Sopenharmony_civoid alsa_lisp_init_objects(void) __attribute__ ((constructor));
486d5ac70f0Sopenharmony_ci
487d5ac70f0Sopenharmony_civoid alsa_lisp_init_objects(void)
488d5ac70f0Sopenharmony_ci{
489d5ac70f0Sopenharmony_ci	memset(&alsa_lisp_nil, 0, sizeof(alsa_lisp_nil));
490d5ac70f0Sopenharmony_ci	alisp_set_type(&alsa_lisp_nil, ALISP_OBJ_NIL);
491d5ac70f0Sopenharmony_ci	INIT_LIST_HEAD(&alsa_lisp_nil.list);
492d5ac70f0Sopenharmony_ci	memset(&alsa_lisp_t, 0, sizeof(alsa_lisp_t));
493d5ac70f0Sopenharmony_ci	alisp_set_type(&alsa_lisp_t, ALISP_OBJ_T);
494d5ac70f0Sopenharmony_ci	INIT_LIST_HEAD(&alsa_lisp_t.list);
495d5ac70f0Sopenharmony_ci}
496d5ac70f0Sopenharmony_ci
497d5ac70f0Sopenharmony_ci/*
498d5ac70f0Sopenharmony_ci * lexer
499d5ac70f0Sopenharmony_ci */
500d5ac70f0Sopenharmony_ci
501d5ac70f0Sopenharmony_cistatic int xgetc(struct alisp_instance *instance)
502d5ac70f0Sopenharmony_ci{
503d5ac70f0Sopenharmony_ci	instance->charno++;
504d5ac70f0Sopenharmony_ci	if (instance->lex_bufp > instance->lex_buf)
505d5ac70f0Sopenharmony_ci		return *--(instance->lex_bufp);
506d5ac70f0Sopenharmony_ci	return snd_input_getc(instance->in);
507d5ac70f0Sopenharmony_ci}
508d5ac70f0Sopenharmony_ci
509d5ac70f0Sopenharmony_cistatic inline void xungetc(struct alisp_instance *instance, int c)
510d5ac70f0Sopenharmony_ci{
511d5ac70f0Sopenharmony_ci	*(instance->lex_bufp)++ = c;
512d5ac70f0Sopenharmony_ci	instance->charno--;
513d5ac70f0Sopenharmony_ci}
514d5ac70f0Sopenharmony_ci
515d5ac70f0Sopenharmony_cistatic int init_lex(struct alisp_instance *instance)
516d5ac70f0Sopenharmony_ci{
517d5ac70f0Sopenharmony_ci	instance->charno = instance->lineno = 1;
518d5ac70f0Sopenharmony_ci	instance->token_buffer_max = 10;
519d5ac70f0Sopenharmony_ci	if ((instance->token_buffer = (char *)malloc(instance->token_buffer_max)) == NULL) {
520d5ac70f0Sopenharmony_ci		nomem();
521d5ac70f0Sopenharmony_ci		return -ENOMEM;
522d5ac70f0Sopenharmony_ci	}
523d5ac70f0Sopenharmony_ci	instance->lex_bufp = instance->lex_buf;
524d5ac70f0Sopenharmony_ci	return 0;
525d5ac70f0Sopenharmony_ci}
526d5ac70f0Sopenharmony_ci
527d5ac70f0Sopenharmony_cistatic void done_lex(struct alisp_instance *instance)
528d5ac70f0Sopenharmony_ci{
529d5ac70f0Sopenharmony_ci	free(instance->token_buffer);
530d5ac70f0Sopenharmony_ci}
531d5ac70f0Sopenharmony_ci
532d5ac70f0Sopenharmony_cistatic char * extend_buf(struct alisp_instance *instance, char *p)
533d5ac70f0Sopenharmony_ci{
534d5ac70f0Sopenharmony_ci	int off = p - instance->token_buffer;
535d5ac70f0Sopenharmony_ci
536d5ac70f0Sopenharmony_ci	instance->token_buffer_max += 10;
537d5ac70f0Sopenharmony_ci	instance->token_buffer = (char *)realloc(instance->token_buffer, instance->token_buffer_max);
538d5ac70f0Sopenharmony_ci	if (instance->token_buffer == NULL) {
539d5ac70f0Sopenharmony_ci		nomem();
540d5ac70f0Sopenharmony_ci		return NULL;
541d5ac70f0Sopenharmony_ci	}
542d5ac70f0Sopenharmony_ci
543d5ac70f0Sopenharmony_ci	return instance->token_buffer + off;
544d5ac70f0Sopenharmony_ci}
545d5ac70f0Sopenharmony_ci
546d5ac70f0Sopenharmony_cistatic int gettoken(struct alisp_instance *instance)
547d5ac70f0Sopenharmony_ci{
548d5ac70f0Sopenharmony_ci	char *p;
549d5ac70f0Sopenharmony_ci	int c;
550d5ac70f0Sopenharmony_ci
551d5ac70f0Sopenharmony_ci	for (;;) {
552d5ac70f0Sopenharmony_ci		c = xgetc(instance);
553d5ac70f0Sopenharmony_ci		switch (c) {
554d5ac70f0Sopenharmony_ci		case '\n':
555d5ac70f0Sopenharmony_ci			++instance->lineno;
556d5ac70f0Sopenharmony_ci			break;
557d5ac70f0Sopenharmony_ci
558d5ac70f0Sopenharmony_ci		case ' ': case '\f': case '\t': case '\v': case '\r':
559d5ac70f0Sopenharmony_ci			break;
560d5ac70f0Sopenharmony_ci
561d5ac70f0Sopenharmony_ci		case ';':
562d5ac70f0Sopenharmony_ci			/* Comment: ";".*"\n" */
563d5ac70f0Sopenharmony_ci			while ((c = xgetc(instance)) != '\n' && c != EOF)
564d5ac70f0Sopenharmony_ci				;
565d5ac70f0Sopenharmony_ci			if (c != EOF)
566d5ac70f0Sopenharmony_ci				++instance->lineno;
567d5ac70f0Sopenharmony_ci			break;
568d5ac70f0Sopenharmony_ci
569d5ac70f0Sopenharmony_ci		case '?':
570d5ac70f0Sopenharmony_ci			/* Character: "?". */
571d5ac70f0Sopenharmony_ci			c = xgetc(instance);
572d5ac70f0Sopenharmony_ci			sprintf(instance->token_buffer, "%d", c);
573d5ac70f0Sopenharmony_ci			return instance->thistoken = ALISP_INTEGER;
574d5ac70f0Sopenharmony_ci
575d5ac70f0Sopenharmony_ci		case '-':
576d5ac70f0Sopenharmony_ci			/* Minus sign: "-". */
577d5ac70f0Sopenharmony_ci			c = xgetc(instance);
578d5ac70f0Sopenharmony_ci			if (!isdigit(c)) {
579d5ac70f0Sopenharmony_ci				xungetc(instance, c);
580d5ac70f0Sopenharmony_ci				c = '-';
581d5ac70f0Sopenharmony_ci				goto got_id;
582d5ac70f0Sopenharmony_ci			}
583d5ac70f0Sopenharmony_ci			xungetc(instance, c);
584d5ac70f0Sopenharmony_ci			c = '-';
585d5ac70f0Sopenharmony_ci			/* FALLTRHU */
586d5ac70f0Sopenharmony_ci
587d5ac70f0Sopenharmony_ci		case '0':
588d5ac70f0Sopenharmony_ci		case '1': case '2': case '3':
589d5ac70f0Sopenharmony_ci		case '4': case '5': case '6':
590d5ac70f0Sopenharmony_ci		case '7': case '8': case '9':
591d5ac70f0Sopenharmony_ci			/* Integer: [0-9]+ */
592d5ac70f0Sopenharmony_ci			p = instance->token_buffer;
593d5ac70f0Sopenharmony_ci			instance->thistoken = ALISP_INTEGER;
594d5ac70f0Sopenharmony_ci			do {
595d5ac70f0Sopenharmony_ci			      __ok:
596d5ac70f0Sopenharmony_ci				if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
597d5ac70f0Sopenharmony_ci					p = extend_buf(instance, p);
598d5ac70f0Sopenharmony_ci					if (p == NULL)
599d5ac70f0Sopenharmony_ci						return instance->thistoken = EOF;
600d5ac70f0Sopenharmony_ci				}
601d5ac70f0Sopenharmony_ci				*p++ = c;
602d5ac70f0Sopenharmony_ci				c = xgetc(instance);
603d5ac70f0Sopenharmony_ci				if (c == '.' && instance->thistoken == ALISP_INTEGER) {
604d5ac70f0Sopenharmony_ci					c = xgetc(instance);
605d5ac70f0Sopenharmony_ci					xungetc(instance, c);
606d5ac70f0Sopenharmony_ci					if (isdigit(c)) {
607d5ac70f0Sopenharmony_ci						instance->thistoken = ALISP_FLOAT;
608d5ac70f0Sopenharmony_ci						c = '.';
609d5ac70f0Sopenharmony_ci						goto __ok;
610d5ac70f0Sopenharmony_ci					} else {
611d5ac70f0Sopenharmony_ci						c = '.';
612d5ac70f0Sopenharmony_ci					}
613d5ac70f0Sopenharmony_ci				} else if (c == 'e' && instance->thistoken == ALISP_FLOAT) {
614d5ac70f0Sopenharmony_ci					c = xgetc(instance);
615d5ac70f0Sopenharmony_ci					if (isdigit(c)) {
616d5ac70f0Sopenharmony_ci						instance->thistoken = ALISP_FLOATE;
617d5ac70f0Sopenharmony_ci						goto __ok;
618d5ac70f0Sopenharmony_ci					}
619d5ac70f0Sopenharmony_ci				}
620d5ac70f0Sopenharmony_ci			} while (isdigit(c));
621d5ac70f0Sopenharmony_ci			xungetc(instance, c);
622d5ac70f0Sopenharmony_ci			*p = '\0';
623d5ac70f0Sopenharmony_ci			return instance->thistoken;
624d5ac70f0Sopenharmony_ci
625d5ac70f0Sopenharmony_ci		got_id:
626d5ac70f0Sopenharmony_ci		case '!': case '_': case '+': case '*': case '/': case '%':
627d5ac70f0Sopenharmony_ci		case '<': case '>': case '=': case '&':
628d5ac70f0Sopenharmony_ci		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
629d5ac70f0Sopenharmony_ci		case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
630d5ac70f0Sopenharmony_ci		case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
631d5ac70f0Sopenharmony_ci		case 's': case 't': case 'u': case 'v': case 'w': case 'x':
632d5ac70f0Sopenharmony_ci		case 'y': case 'z':
633d5ac70f0Sopenharmony_ci		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
634d5ac70f0Sopenharmony_ci		case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
635d5ac70f0Sopenharmony_ci		case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
636d5ac70f0Sopenharmony_ci		case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
637d5ac70f0Sopenharmony_ci		case 'Y': case 'Z':
638d5ac70f0Sopenharmony_ci			/* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */
639d5ac70f0Sopenharmony_ci			p = instance->token_buffer;
640d5ac70f0Sopenharmony_ci			do {
641d5ac70f0Sopenharmony_ci				if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
642d5ac70f0Sopenharmony_ci					p = extend_buf(instance, p);
643d5ac70f0Sopenharmony_ci					if (p == NULL)
644d5ac70f0Sopenharmony_ci						return instance->thistoken = EOF;
645d5ac70f0Sopenharmony_ci				}
646d5ac70f0Sopenharmony_ci				*p++ = c;
647d5ac70f0Sopenharmony_ci				c = xgetc(instance);
648d5ac70f0Sopenharmony_ci			} while (isalnum(c) || strchr("!_-+*/%<>=&", c) != NULL);
649d5ac70f0Sopenharmony_ci			xungetc(instance, c);
650d5ac70f0Sopenharmony_ci			*p = '\0';
651d5ac70f0Sopenharmony_ci			return instance->thistoken = ALISP_IDENTIFIER;
652d5ac70f0Sopenharmony_ci
653d5ac70f0Sopenharmony_ci		case '"':
654d5ac70f0Sopenharmony_ci			/* String: "\""([^"]|"\\".)*"\"" */
655d5ac70f0Sopenharmony_ci			p = instance->token_buffer;
656d5ac70f0Sopenharmony_ci			while ((c = xgetc(instance)) != '"' && c != EOF) {
657d5ac70f0Sopenharmony_ci				if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
658d5ac70f0Sopenharmony_ci					p = extend_buf(instance, p);
659d5ac70f0Sopenharmony_ci					if (p == NULL)
660d5ac70f0Sopenharmony_ci						return instance->thistoken = EOF;
661d5ac70f0Sopenharmony_ci				}
662d5ac70f0Sopenharmony_ci				if (c == '\\') {
663d5ac70f0Sopenharmony_ci					c = xgetc(instance);
664d5ac70f0Sopenharmony_ci					switch (c) {
665d5ac70f0Sopenharmony_ci					case '\n': ++instance->lineno; break;
666d5ac70f0Sopenharmony_ci					case 'a': *p++ = '\a'; break;
667d5ac70f0Sopenharmony_ci					case 'b': *p++ = '\b'; break;
668d5ac70f0Sopenharmony_ci					case 'f': *p++ = '\f'; break;
669d5ac70f0Sopenharmony_ci					case 'n': *p++ = '\n'; break;
670d5ac70f0Sopenharmony_ci					case 'r': *p++ = '\r'; break;
671d5ac70f0Sopenharmony_ci					case 't': *p++ = '\t'; break;
672d5ac70f0Sopenharmony_ci					case 'v': *p++ = '\v'; break;
673d5ac70f0Sopenharmony_ci					default: *p++ = c;
674d5ac70f0Sopenharmony_ci					}
675d5ac70f0Sopenharmony_ci				} else {
676d5ac70f0Sopenharmony_ci					if (c == '\n')
677d5ac70f0Sopenharmony_ci						++instance->lineno;
678d5ac70f0Sopenharmony_ci					*p++ = c;
679d5ac70f0Sopenharmony_ci				}
680d5ac70f0Sopenharmony_ci			}
681d5ac70f0Sopenharmony_ci			*p = '\0';
682d5ac70f0Sopenharmony_ci			return instance->thistoken = ALISP_STRING;
683d5ac70f0Sopenharmony_ci
684d5ac70f0Sopenharmony_ci		default:
685d5ac70f0Sopenharmony_ci			return instance->thistoken = c;
686d5ac70f0Sopenharmony_ci		}
687d5ac70f0Sopenharmony_ci	}
688d5ac70f0Sopenharmony_ci}
689d5ac70f0Sopenharmony_ci
690d5ac70f0Sopenharmony_ci/*
691d5ac70f0Sopenharmony_ci *  parser
692d5ac70f0Sopenharmony_ci */
693d5ac70f0Sopenharmony_ci
694d5ac70f0Sopenharmony_cistatic struct alisp_object * parse_form(struct alisp_instance *instance)
695d5ac70f0Sopenharmony_ci{
696d5ac70f0Sopenharmony_ci	int thistoken;
697d5ac70f0Sopenharmony_ci	struct alisp_object * p, * first = NULL, * prev = NULL;
698d5ac70f0Sopenharmony_ci
699d5ac70f0Sopenharmony_ci	while ((thistoken = gettoken(instance)) != ')' && thistoken != EOF) {
700d5ac70f0Sopenharmony_ci		/*
701d5ac70f0Sopenharmony_ci		 * Parse a dotted pair notation.
702d5ac70f0Sopenharmony_ci		 */
703d5ac70f0Sopenharmony_ci		if (thistoken == '.') {
704d5ac70f0Sopenharmony_ci			gettoken(instance);
705d5ac70f0Sopenharmony_ci			if (prev == NULL) {
706d5ac70f0Sopenharmony_ci				lisp_error(instance, "unexpected '.'");
707d5ac70f0Sopenharmony_ci			      __err:
708d5ac70f0Sopenharmony_ci				delete_tree(instance, first);
709d5ac70f0Sopenharmony_ci				return NULL;
710d5ac70f0Sopenharmony_ci			}
711d5ac70f0Sopenharmony_ci			prev->value.c.cdr = parse_object(instance, 1);
712d5ac70f0Sopenharmony_ci			if (prev->value.c.cdr == NULL)
713d5ac70f0Sopenharmony_ci				goto __err;
714d5ac70f0Sopenharmony_ci			if ((thistoken = gettoken(instance)) != ')') {
715d5ac70f0Sopenharmony_ci				lisp_error(instance, "expected ')'");
716d5ac70f0Sopenharmony_ci				goto __err;
717d5ac70f0Sopenharmony_ci			}
718d5ac70f0Sopenharmony_ci			break;
719d5ac70f0Sopenharmony_ci		}
720d5ac70f0Sopenharmony_ci
721d5ac70f0Sopenharmony_ci		p = new_object(instance, ALISP_OBJ_CONS);
722d5ac70f0Sopenharmony_ci		if (p == NULL)
723d5ac70f0Sopenharmony_ci			goto __err;
724d5ac70f0Sopenharmony_ci
725d5ac70f0Sopenharmony_ci		if (first == NULL)
726d5ac70f0Sopenharmony_ci			first = p;
727d5ac70f0Sopenharmony_ci		if (prev != NULL)
728d5ac70f0Sopenharmony_ci			prev->value.c.cdr = p;
729d5ac70f0Sopenharmony_ci
730d5ac70f0Sopenharmony_ci		p->value.c.car = parse_object(instance, 1);
731d5ac70f0Sopenharmony_ci		if (p->value.c.car == NULL)
732d5ac70f0Sopenharmony_ci			goto __err;
733d5ac70f0Sopenharmony_ci
734d5ac70f0Sopenharmony_ci		prev = p;
735d5ac70f0Sopenharmony_ci	}
736d5ac70f0Sopenharmony_ci
737d5ac70f0Sopenharmony_ci	if (first == NULL)
738d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
739d5ac70f0Sopenharmony_ci	else
740d5ac70f0Sopenharmony_ci		return first;
741d5ac70f0Sopenharmony_ci}
742d5ac70f0Sopenharmony_ci
743d5ac70f0Sopenharmony_cistatic struct alisp_object * quote_object(struct alisp_instance *instance, struct alisp_object * obj)
744d5ac70f0Sopenharmony_ci{
745d5ac70f0Sopenharmony_ci	struct alisp_object * p;
746d5ac70f0Sopenharmony_ci
747d5ac70f0Sopenharmony_ci	if (obj == NULL)
748d5ac70f0Sopenharmony_ci		goto __end1;
749d5ac70f0Sopenharmony_ci
750d5ac70f0Sopenharmony_ci	p = new_object(instance, ALISP_OBJ_CONS);
751d5ac70f0Sopenharmony_ci	if (p == NULL)
752d5ac70f0Sopenharmony_ci		goto __end1;
753d5ac70f0Sopenharmony_ci
754d5ac70f0Sopenharmony_ci	p->value.c.car = new_identifier(instance, "quote");
755d5ac70f0Sopenharmony_ci	if (p->value.c.car == NULL)
756d5ac70f0Sopenharmony_ci		goto __end;
757d5ac70f0Sopenharmony_ci	p->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
758d5ac70f0Sopenharmony_ci	if (p->value.c.cdr == NULL) {
759d5ac70f0Sopenharmony_ci		delete_object(instance, p->value.c.car);
760d5ac70f0Sopenharmony_ci	      __end:
761d5ac70f0Sopenharmony_ci		delete_object(instance, p);
762d5ac70f0Sopenharmony_ci	      __end1:
763d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
764d5ac70f0Sopenharmony_ci		return NULL;
765d5ac70f0Sopenharmony_ci	}
766d5ac70f0Sopenharmony_ci
767d5ac70f0Sopenharmony_ci	p->value.c.cdr->value.c.car = obj;
768d5ac70f0Sopenharmony_ci	return p;
769d5ac70f0Sopenharmony_ci}
770d5ac70f0Sopenharmony_ci
771d5ac70f0Sopenharmony_cistatic inline struct alisp_object * parse_quote(struct alisp_instance *instance)
772d5ac70f0Sopenharmony_ci{
773d5ac70f0Sopenharmony_ci	return quote_object(instance, parse_object(instance, 0));
774d5ac70f0Sopenharmony_ci}
775d5ac70f0Sopenharmony_ci
776d5ac70f0Sopenharmony_cistatic struct alisp_object * parse_object(struct alisp_instance *instance, int havetoken)
777d5ac70f0Sopenharmony_ci{
778d5ac70f0Sopenharmony_ci	int thistoken;
779d5ac70f0Sopenharmony_ci	struct alisp_object * p = NULL;
780d5ac70f0Sopenharmony_ci
781d5ac70f0Sopenharmony_ci	if (!havetoken)
782d5ac70f0Sopenharmony_ci		thistoken = gettoken(instance);
783d5ac70f0Sopenharmony_ci	else
784d5ac70f0Sopenharmony_ci		thistoken = instance->thistoken;
785d5ac70f0Sopenharmony_ci
786d5ac70f0Sopenharmony_ci	switch (thistoken) {
787d5ac70f0Sopenharmony_ci	case EOF:
788d5ac70f0Sopenharmony_ci		break;
789d5ac70f0Sopenharmony_ci	case '(':
790d5ac70f0Sopenharmony_ci		p = parse_form(instance);
791d5ac70f0Sopenharmony_ci		break;
792d5ac70f0Sopenharmony_ci	case '\'':
793d5ac70f0Sopenharmony_ci		p = parse_quote(instance);
794d5ac70f0Sopenharmony_ci		break;
795d5ac70f0Sopenharmony_ci	case ALISP_IDENTIFIER:
796d5ac70f0Sopenharmony_ci		if (!strcmp(instance->token_buffer, "t"))
797d5ac70f0Sopenharmony_ci			p = &alsa_lisp_t;
798d5ac70f0Sopenharmony_ci		else if (!strcmp(instance->token_buffer, "nil"))
799d5ac70f0Sopenharmony_ci			p = &alsa_lisp_nil;
800d5ac70f0Sopenharmony_ci		else {
801d5ac70f0Sopenharmony_ci			p = new_identifier(instance, instance->token_buffer);
802d5ac70f0Sopenharmony_ci		}
803d5ac70f0Sopenharmony_ci		break;
804d5ac70f0Sopenharmony_ci	case ALISP_INTEGER: {
805d5ac70f0Sopenharmony_ci		p = new_integer(instance, atol(instance->token_buffer));
806d5ac70f0Sopenharmony_ci		break;
807d5ac70f0Sopenharmony_ci	}
808d5ac70f0Sopenharmony_ci	case ALISP_FLOAT:
809d5ac70f0Sopenharmony_ci	case ALISP_FLOATE: {
810d5ac70f0Sopenharmony_ci		p = new_float(instance, atof(instance->token_buffer));
811d5ac70f0Sopenharmony_ci		break;
812d5ac70f0Sopenharmony_ci	}
813d5ac70f0Sopenharmony_ci	case ALISP_STRING:
814d5ac70f0Sopenharmony_ci		p = new_string(instance, instance->token_buffer);
815d5ac70f0Sopenharmony_ci		break;
816d5ac70f0Sopenharmony_ci	default:
817d5ac70f0Sopenharmony_ci		lisp_warn(instance, "%d:%d: unexpected character `%c'", instance->lineno, instance->charno, thistoken);
818d5ac70f0Sopenharmony_ci		break;
819d5ac70f0Sopenharmony_ci	}
820d5ac70f0Sopenharmony_ci
821d5ac70f0Sopenharmony_ci	return p;
822d5ac70f0Sopenharmony_ci}
823d5ac70f0Sopenharmony_ci
824d5ac70f0Sopenharmony_ci/*
825d5ac70f0Sopenharmony_ci *  object manipulation
826d5ac70f0Sopenharmony_ci */
827d5ac70f0Sopenharmony_ci
828d5ac70f0Sopenharmony_cistatic struct alisp_object_pair * set_object_direct(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * value)
829d5ac70f0Sopenharmony_ci{
830d5ac70f0Sopenharmony_ci	struct alisp_object_pair *p;
831d5ac70f0Sopenharmony_ci	const char *id;
832d5ac70f0Sopenharmony_ci
833d5ac70f0Sopenharmony_ci	id = name->value.s;
834d5ac70f0Sopenharmony_ci	p = (struct alisp_object_pair *)malloc(sizeof(struct alisp_object_pair));
835d5ac70f0Sopenharmony_ci	if (p == NULL) {
836d5ac70f0Sopenharmony_ci		nomem();
837d5ac70f0Sopenharmony_ci		return NULL;
838d5ac70f0Sopenharmony_ci	}
839d5ac70f0Sopenharmony_ci	p->name = strdup(id);
840d5ac70f0Sopenharmony_ci	if (p->name == NULL) {
841d5ac70f0Sopenharmony_ci		delete_tree(instance, value);
842d5ac70f0Sopenharmony_ci		free(p);
843d5ac70f0Sopenharmony_ci		return NULL;
844d5ac70f0Sopenharmony_ci	}
845d5ac70f0Sopenharmony_ci	list_add(&p->list, &instance->setobjs_list[get_string_hash(id)]);
846d5ac70f0Sopenharmony_ci	p->value = value;
847d5ac70f0Sopenharmony_ci	return p;
848d5ac70f0Sopenharmony_ci}
849d5ac70f0Sopenharmony_ci
850d5ac70f0Sopenharmony_cistatic int check_set_object(struct alisp_instance * instance, struct alisp_object * name)
851d5ac70f0Sopenharmony_ci{
852d5ac70f0Sopenharmony_ci	if (name == &alsa_lisp_nil) {
853d5ac70f0Sopenharmony_ci		lisp_warn(instance, "setting the value of a nil object");
854d5ac70f0Sopenharmony_ci		return 0;
855d5ac70f0Sopenharmony_ci	}
856d5ac70f0Sopenharmony_ci	if (name == &alsa_lisp_t) {
857d5ac70f0Sopenharmony_ci		lisp_warn(instance, "setting the value of a t object");
858d5ac70f0Sopenharmony_ci		return 0;
859d5ac70f0Sopenharmony_ci	}
860d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
861d5ac70f0Sopenharmony_ci	    !alisp_compare_type(name, ALISP_OBJ_STRING)) {
862d5ac70f0Sopenharmony_ci		lisp_warn(instance, "setting the value of an object with non-indentifier");
863d5ac70f0Sopenharmony_ci		return 0;
864d5ac70f0Sopenharmony_ci	}
865d5ac70f0Sopenharmony_ci	return 1;
866d5ac70f0Sopenharmony_ci}
867d5ac70f0Sopenharmony_ci
868d5ac70f0Sopenharmony_cistatic struct alisp_object_pair * set_object(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * value)
869d5ac70f0Sopenharmony_ci{
870d5ac70f0Sopenharmony_ci	struct list_head *pos;
871d5ac70f0Sopenharmony_ci	struct alisp_object_pair *p;
872d5ac70f0Sopenharmony_ci	const char *id;
873d5ac70f0Sopenharmony_ci
874d5ac70f0Sopenharmony_ci	if (name == NULL || value == NULL)
875d5ac70f0Sopenharmony_ci		return NULL;
876d5ac70f0Sopenharmony_ci
877d5ac70f0Sopenharmony_ci	id = name->value.s;
878d5ac70f0Sopenharmony_ci
879d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
880d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object_pair, list);
881d5ac70f0Sopenharmony_ci		if (!strcmp(p->name, id)) {
882d5ac70f0Sopenharmony_ci			delete_tree(instance, p->value);
883d5ac70f0Sopenharmony_ci			p->value = value;
884d5ac70f0Sopenharmony_ci			return p;
885d5ac70f0Sopenharmony_ci		}
886d5ac70f0Sopenharmony_ci	}
887d5ac70f0Sopenharmony_ci
888d5ac70f0Sopenharmony_ci	p = (struct alisp_object_pair *)malloc(sizeof(struct alisp_object_pair));
889d5ac70f0Sopenharmony_ci	if (p == NULL) {
890d5ac70f0Sopenharmony_ci		nomem();
891d5ac70f0Sopenharmony_ci		return NULL;
892d5ac70f0Sopenharmony_ci	}
893d5ac70f0Sopenharmony_ci	p->name = strdup(id);
894d5ac70f0Sopenharmony_ci	if (p->name == NULL) {
895d5ac70f0Sopenharmony_ci		delete_tree(instance, value);
896d5ac70f0Sopenharmony_ci		free(p);
897d5ac70f0Sopenharmony_ci		return NULL;
898d5ac70f0Sopenharmony_ci	}
899d5ac70f0Sopenharmony_ci	list_add(&p->list, &instance->setobjs_list[get_string_hash(id)]);
900d5ac70f0Sopenharmony_ci	p->value = value;
901d5ac70f0Sopenharmony_ci	return p;
902d5ac70f0Sopenharmony_ci}
903d5ac70f0Sopenharmony_ci
904d5ac70f0Sopenharmony_cistatic struct alisp_object * unset_object(struct alisp_instance *instance, struct alisp_object * name)
905d5ac70f0Sopenharmony_ci{
906d5ac70f0Sopenharmony_ci	struct list_head *pos;
907d5ac70f0Sopenharmony_ci	struct alisp_object *res;
908d5ac70f0Sopenharmony_ci	struct alisp_object_pair *p;
909d5ac70f0Sopenharmony_ci	const char *id;
910d5ac70f0Sopenharmony_ci
911d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
912d5ac70f0Sopenharmony_ci	    !alisp_compare_type(name, ALISP_OBJ_STRING)) {
913d5ac70f0Sopenharmony_ci	    	lisp_warn(instance, "unset object with a non-indentifier");
914d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
915d5ac70f0Sopenharmony_ci	}
916d5ac70f0Sopenharmony_ci	id = name->value.s;
917d5ac70f0Sopenharmony_ci
918d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
919d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object_pair, list);
920d5ac70f0Sopenharmony_ci		if (!strcmp(p->name, id)) {
921d5ac70f0Sopenharmony_ci			list_del(&p->list);
922d5ac70f0Sopenharmony_ci			res = p->value;
923d5ac70f0Sopenharmony_ci			free((void *)p->name);
924d5ac70f0Sopenharmony_ci			free(p);
925d5ac70f0Sopenharmony_ci			return res;
926d5ac70f0Sopenharmony_ci		}
927d5ac70f0Sopenharmony_ci	}
928d5ac70f0Sopenharmony_ci
929d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
930d5ac70f0Sopenharmony_ci}
931d5ac70f0Sopenharmony_ci
932d5ac70f0Sopenharmony_cistatic struct alisp_object * get_object1(struct alisp_instance *instance, const char *id)
933d5ac70f0Sopenharmony_ci{
934d5ac70f0Sopenharmony_ci	struct alisp_object_pair *p;
935d5ac70f0Sopenharmony_ci	struct list_head *pos;
936d5ac70f0Sopenharmony_ci
937d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
938d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object_pair, list);
939d5ac70f0Sopenharmony_ci		if (!strcmp(p->name, id))
940d5ac70f0Sopenharmony_ci			return p->value;
941d5ac70f0Sopenharmony_ci	}
942d5ac70f0Sopenharmony_ci
943d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
944d5ac70f0Sopenharmony_ci}
945d5ac70f0Sopenharmony_ci
946d5ac70f0Sopenharmony_cistatic struct alisp_object * get_object(struct alisp_instance *instance, struct alisp_object * name)
947d5ac70f0Sopenharmony_ci{
948d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
949d5ac70f0Sopenharmony_ci	    !alisp_compare_type(name, ALISP_OBJ_STRING)) {
950d5ac70f0Sopenharmony_ci	    	delete_tree(instance, name);
951d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
952d5ac70f0Sopenharmony_ci	}
953d5ac70f0Sopenharmony_ci	return get_object1(instance, name->value.s);
954d5ac70f0Sopenharmony_ci}
955d5ac70f0Sopenharmony_ci
956d5ac70f0Sopenharmony_cistatic struct alisp_object * replace_object(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * onew)
957d5ac70f0Sopenharmony_ci{
958d5ac70f0Sopenharmony_ci	struct alisp_object_pair *p;
959d5ac70f0Sopenharmony_ci	struct alisp_object *r;
960d5ac70f0Sopenharmony_ci	struct list_head *pos;
961d5ac70f0Sopenharmony_ci	const char *id;
962d5ac70f0Sopenharmony_ci
963d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
964d5ac70f0Sopenharmony_ci	    !alisp_compare_type(name, ALISP_OBJ_STRING)) {
965d5ac70f0Sopenharmony_ci	    	delete_tree(instance, name);
966d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
967d5ac70f0Sopenharmony_ci	}
968d5ac70f0Sopenharmony_ci	id = name->value.s;
969d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
970d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object_pair, list);
971d5ac70f0Sopenharmony_ci		if (!strcmp(p->name, id)) {
972d5ac70f0Sopenharmony_ci			r = p->value;
973d5ac70f0Sopenharmony_ci			p->value = onew;
974d5ac70f0Sopenharmony_ci			return r;
975d5ac70f0Sopenharmony_ci		}
976d5ac70f0Sopenharmony_ci	}
977d5ac70f0Sopenharmony_ci
978d5ac70f0Sopenharmony_ci	return NULL;
979d5ac70f0Sopenharmony_ci}
980d5ac70f0Sopenharmony_ci
981d5ac70f0Sopenharmony_cistatic void dump_objects(struct alisp_instance *instance, const char *fname)
982d5ac70f0Sopenharmony_ci{
983d5ac70f0Sopenharmony_ci	struct alisp_object_pair *p;
984d5ac70f0Sopenharmony_ci	snd_output_t *out;
985d5ac70f0Sopenharmony_ci	struct list_head *pos;
986d5ac70f0Sopenharmony_ci	int i, err;
987d5ac70f0Sopenharmony_ci
988d5ac70f0Sopenharmony_ci	if (!strcmp(fname, "-"))
989d5ac70f0Sopenharmony_ci		err = snd_output_stdio_attach(&out, stdout, 0);
990d5ac70f0Sopenharmony_ci	else
991d5ac70f0Sopenharmony_ci		err = snd_output_stdio_open(&out, fname, "w+");
992d5ac70f0Sopenharmony_ci	if (err < 0) {
993d5ac70f0Sopenharmony_ci		SNDERR("alisp: cannot open file '%s' for writing (%s)", fname, snd_strerror(errno));
994d5ac70f0Sopenharmony_ci		return;
995d5ac70f0Sopenharmony_ci	}
996d5ac70f0Sopenharmony_ci
997d5ac70f0Sopenharmony_ci	for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
998d5ac70f0Sopenharmony_ci		list_for_each(pos, &instance->setobjs_list[i]) {
999d5ac70f0Sopenharmony_ci			p = list_entry(pos, struct alisp_object_pair, list);
1000d5ac70f0Sopenharmony_ci			if (alisp_compare_type(p->value, ALISP_OBJ_CONS) &&
1001d5ac70f0Sopenharmony_ci			    alisp_compare_type(p->value->value.c.car, ALISP_OBJ_IDENTIFIER) &&
1002d5ac70f0Sopenharmony_ci			    !strcmp(p->value->value.c.car->value.s, "lambda")) {
1003d5ac70f0Sopenharmony_ci			    	snd_output_printf(out, "(defun %s ", p->name);
1004d5ac70f0Sopenharmony_ci			    	princ_cons(out, p->value->value.c.cdr);
1005d5ac70f0Sopenharmony_ci			    	snd_output_printf(out, ")\n");
1006d5ac70f0Sopenharmony_ci			    	continue;
1007d5ac70f0Sopenharmony_ci			}
1008d5ac70f0Sopenharmony_ci			snd_output_printf(out, "(setq %s '", p->name);
1009d5ac70f0Sopenharmony_ci 			princ_object(out, p->value);
1010d5ac70f0Sopenharmony_ci			snd_output_printf(out, ")\n");
1011d5ac70f0Sopenharmony_ci		}
1012d5ac70f0Sopenharmony_ci	}
1013d5ac70f0Sopenharmony_ci	snd_output_close(out);
1014d5ac70f0Sopenharmony_ci}
1015d5ac70f0Sopenharmony_ci
1016d5ac70f0Sopenharmony_cistatic const char *obj_type_str(struct alisp_object * p)
1017d5ac70f0Sopenharmony_ci{
1018d5ac70f0Sopenharmony_ci	switch (alisp_get_type(p)) {
1019d5ac70f0Sopenharmony_ci	case ALISP_OBJ_NIL: return "nil";
1020d5ac70f0Sopenharmony_ci	case ALISP_OBJ_T: return "t";
1021d5ac70f0Sopenharmony_ci	case ALISP_OBJ_INTEGER: return "integer";
1022d5ac70f0Sopenharmony_ci	case ALISP_OBJ_FLOAT: return "float";
1023d5ac70f0Sopenharmony_ci	case ALISP_OBJ_IDENTIFIER: return "identifier";
1024d5ac70f0Sopenharmony_ci	case ALISP_OBJ_STRING: return "string";
1025d5ac70f0Sopenharmony_ci	case ALISP_OBJ_POINTER: return "pointer";
1026d5ac70f0Sopenharmony_ci	case ALISP_OBJ_CONS: return "cons";
1027d5ac70f0Sopenharmony_ci	default: assert(0);
1028d5ac70f0Sopenharmony_ci	}
1029d5ac70f0Sopenharmony_ci}
1030d5ac70f0Sopenharmony_ci
1031d5ac70f0Sopenharmony_cistatic void print_obj_lists(struct alisp_instance *instance, snd_output_t *out)
1032d5ac70f0Sopenharmony_ci{
1033d5ac70f0Sopenharmony_ci	struct list_head *pos;
1034d5ac70f0Sopenharmony_ci	struct alisp_object * p;
1035d5ac70f0Sopenharmony_ci	int i, j;
1036d5ac70f0Sopenharmony_ci
1037d5ac70f0Sopenharmony_ci	snd_output_printf(out, "** used objects\n");
1038d5ac70f0Sopenharmony_ci	for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
1039d5ac70f0Sopenharmony_ci		for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++)
1040d5ac70f0Sopenharmony_ci			list_for_each(pos, &instance->used_objs_list[i][j]) {
1041d5ac70f0Sopenharmony_ci				p = list_entry(pos, struct alisp_object, list);
1042d5ac70f0Sopenharmony_ci				snd_output_printf(out, "**   %p (%s) (", p, obj_type_str(p));
1043d5ac70f0Sopenharmony_ci				if (!alisp_compare_type(p, ALISP_OBJ_CONS))
1044d5ac70f0Sopenharmony_ci					princ_object(out, p);
1045d5ac70f0Sopenharmony_ci				else
1046d5ac70f0Sopenharmony_ci					snd_output_printf(out, "cons");
1047d5ac70f0Sopenharmony_ci				snd_output_printf(out, ") refs=%i\n", alisp_get_refs(p));
1048d5ac70f0Sopenharmony_ci			}
1049d5ac70f0Sopenharmony_ci	snd_output_printf(out, "** free objects\n");
1050d5ac70f0Sopenharmony_ci	list_for_each(pos, &instance->free_objs_list) {
1051d5ac70f0Sopenharmony_ci		p = list_entry(pos, struct alisp_object, list);
1052d5ac70f0Sopenharmony_ci		snd_output_printf(out, "**   %p\n", p);
1053d5ac70f0Sopenharmony_ci	}
1054d5ac70f0Sopenharmony_ci}
1055d5ac70f0Sopenharmony_ci
1056d5ac70f0Sopenharmony_cistatic void dump_obj_lists(struct alisp_instance *instance, const char *fname)
1057d5ac70f0Sopenharmony_ci{
1058d5ac70f0Sopenharmony_ci	snd_output_t *out;
1059d5ac70f0Sopenharmony_ci	int err;
1060d5ac70f0Sopenharmony_ci
1061d5ac70f0Sopenharmony_ci	if (!strcmp(fname, "-"))
1062d5ac70f0Sopenharmony_ci		err = snd_output_stdio_attach(&out, stdout, 0);
1063d5ac70f0Sopenharmony_ci	else
1064d5ac70f0Sopenharmony_ci		err = snd_output_stdio_open(&out, fname, "w+");
1065d5ac70f0Sopenharmony_ci	if (err < 0) {
1066d5ac70f0Sopenharmony_ci		SNDERR("alisp: cannot open file '%s' for writing (%s)", fname, snd_strerror(errno));
1067d5ac70f0Sopenharmony_ci		return;
1068d5ac70f0Sopenharmony_ci	}
1069d5ac70f0Sopenharmony_ci
1070d5ac70f0Sopenharmony_ci	print_obj_lists(instance, out);
1071d5ac70f0Sopenharmony_ci
1072d5ac70f0Sopenharmony_ci	snd_output_close(out);
1073d5ac70f0Sopenharmony_ci}
1074d5ac70f0Sopenharmony_ci
1075d5ac70f0Sopenharmony_ci/*
1076d5ac70f0Sopenharmony_ci *  functions
1077d5ac70f0Sopenharmony_ci */
1078d5ac70f0Sopenharmony_ci
1079d5ac70f0Sopenharmony_cistatic int count_list(struct alisp_object * p)
1080d5ac70f0Sopenharmony_ci{
1081d5ac70f0Sopenharmony_ci	int i = 0;
1082d5ac70f0Sopenharmony_ci
1083d5ac70f0Sopenharmony_ci	while (p != &alsa_lisp_nil && alisp_compare_type(p, ALISP_OBJ_CONS)) {
1084d5ac70f0Sopenharmony_ci		p = p->value.c.cdr;
1085d5ac70f0Sopenharmony_ci		++i;
1086d5ac70f0Sopenharmony_ci	}
1087d5ac70f0Sopenharmony_ci
1088d5ac70f0Sopenharmony_ci	return i;
1089d5ac70f0Sopenharmony_ci}
1090d5ac70f0Sopenharmony_ci
1091d5ac70f0Sopenharmony_cistatic inline struct alisp_object * car(struct alisp_object * p)
1092d5ac70f0Sopenharmony_ci{
1093d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_CONS))
1094d5ac70f0Sopenharmony_ci		return p->value.c.car;
1095d5ac70f0Sopenharmony_ci
1096d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1097d5ac70f0Sopenharmony_ci}
1098d5ac70f0Sopenharmony_ci
1099d5ac70f0Sopenharmony_cistatic inline struct alisp_object * cdr(struct alisp_object * p)
1100d5ac70f0Sopenharmony_ci{
1101d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_CONS))
1102d5ac70f0Sopenharmony_ci		return p->value.c.cdr;
1103d5ac70f0Sopenharmony_ci
1104d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1105d5ac70f0Sopenharmony_ci}
1106d5ac70f0Sopenharmony_ci
1107d5ac70f0Sopenharmony_ci/*
1108d5ac70f0Sopenharmony_ci * Syntax: (car expr)
1109d5ac70f0Sopenharmony_ci */
1110d5ac70f0Sopenharmony_cistatic struct alisp_object * F_car(struct alisp_instance *instance, struct alisp_object * args)
1111d5ac70f0Sopenharmony_ci{
1112d5ac70f0Sopenharmony_ci	struct alisp_object *p1 = car(args), *p2;
1113d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
1114d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1115d5ac70f0Sopenharmony_ci	p1 = eval(instance, p1);
1116d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(p1));
1117d5ac70f0Sopenharmony_ci	p2 = car(p1);
1118d5ac70f0Sopenharmony_ci	delete_object(instance, p1);
1119d5ac70f0Sopenharmony_ci	return p2;
1120d5ac70f0Sopenharmony_ci}
1121d5ac70f0Sopenharmony_ci
1122d5ac70f0Sopenharmony_ci/*
1123d5ac70f0Sopenharmony_ci * Syntax: (cdr expr)
1124d5ac70f0Sopenharmony_ci */
1125d5ac70f0Sopenharmony_cistatic struct alisp_object * F_cdr(struct alisp_instance *instance, struct alisp_object * args)
1126d5ac70f0Sopenharmony_ci{
1127d5ac70f0Sopenharmony_ci	struct alisp_object *p1 = car(args), *p2;
1128d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
1129d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1130d5ac70f0Sopenharmony_ci	p1 = eval(instance, p1);
1131d5ac70f0Sopenharmony_ci	delete_tree(instance, car(p1));
1132d5ac70f0Sopenharmony_ci	p2 = cdr(p1);
1133d5ac70f0Sopenharmony_ci	delete_object(instance, p1);
1134d5ac70f0Sopenharmony_ci	return p2;
1135d5ac70f0Sopenharmony_ci}
1136d5ac70f0Sopenharmony_ci
1137d5ac70f0Sopenharmony_ci/*
1138d5ac70f0Sopenharmony_ci * Syntax: (+ expr...)
1139d5ac70f0Sopenharmony_ci */
1140d5ac70f0Sopenharmony_cistatic struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args)
1141d5ac70f0Sopenharmony_ci{
1142d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1, * n;
1143d5ac70f0Sopenharmony_ci	long v = 0;
1144d5ac70f0Sopenharmony_ci	double f = 0;
1145d5ac70f0Sopenharmony_ci	int type = ALISP_OBJ_INTEGER;
1146d5ac70f0Sopenharmony_ci
1147d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(p));
1148d5ac70f0Sopenharmony_ci	for (;;) {
1149d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
1150d5ac70f0Sopenharmony_ci			if (type == ALISP_OBJ_FLOAT)
1151d5ac70f0Sopenharmony_ci				f += p1->value.i;
1152d5ac70f0Sopenharmony_ci			else
1153d5ac70f0Sopenharmony_ci				v += p1->value.i;
1154d5ac70f0Sopenharmony_ci		} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
1155d5ac70f0Sopenharmony_ci			f += p1->value.f + v;
1156d5ac70f0Sopenharmony_ci			v = 0;
1157d5ac70f0Sopenharmony_ci			type = ALISP_OBJ_FLOAT;
1158d5ac70f0Sopenharmony_ci		} else {
1159d5ac70f0Sopenharmony_ci			lisp_warn(instance, "sum with a non integer or float operand");
1160d5ac70f0Sopenharmony_ci		}
1161d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1162d5ac70f0Sopenharmony_ci		p = cdr(n = p);
1163d5ac70f0Sopenharmony_ci		delete_object(instance, n);
1164d5ac70f0Sopenharmony_ci		if (p == &alsa_lisp_nil)
1165d5ac70f0Sopenharmony_ci			break;
1166d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
1167d5ac70f0Sopenharmony_ci	}
1168d5ac70f0Sopenharmony_ci	if (type == ALISP_OBJ_INTEGER) {
1169d5ac70f0Sopenharmony_ci		return new_integer(instance, v);
1170d5ac70f0Sopenharmony_ci	} else {
1171d5ac70f0Sopenharmony_ci		return new_float(instance, f);
1172d5ac70f0Sopenharmony_ci	}
1173d5ac70f0Sopenharmony_ci}
1174d5ac70f0Sopenharmony_ci
1175d5ac70f0Sopenharmony_ci/*
1176d5ac70f0Sopenharmony_ci * Syntax: (concat expr...)
1177d5ac70f0Sopenharmony_ci */
1178d5ac70f0Sopenharmony_cistatic struct alisp_object * F_concat(struct alisp_instance *instance, struct alisp_object * args)
1179d5ac70f0Sopenharmony_ci{
1180d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1, * n;
1181d5ac70f0Sopenharmony_ci	char *str = NULL, *str1;
1182d5ac70f0Sopenharmony_ci
1183d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(p));
1184d5ac70f0Sopenharmony_ci	for (;;) {
1185d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
1186d5ac70f0Sopenharmony_ci			str1 = realloc(str, (str ? strlen(str) : 0) + strlen(p1->value.s) + 1);
1187d5ac70f0Sopenharmony_ci			if (str1 == NULL) {
1188d5ac70f0Sopenharmony_ci				nomem();
1189d5ac70f0Sopenharmony_ci				free(str);
1190d5ac70f0Sopenharmony_ci				return NULL;
1191d5ac70f0Sopenharmony_ci			}
1192d5ac70f0Sopenharmony_ci			if (str == NULL)
1193d5ac70f0Sopenharmony_ci				strcpy(str1, p1->value.s);
1194d5ac70f0Sopenharmony_ci			else
1195d5ac70f0Sopenharmony_ci				strcat(str1, p1->value.s);
1196d5ac70f0Sopenharmony_ci			str = str1;
1197d5ac70f0Sopenharmony_ci		} else {
1198d5ac70f0Sopenharmony_ci			lisp_warn(instance, "concat with a non string or identifier operand");
1199d5ac70f0Sopenharmony_ci		}
1200d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1201d5ac70f0Sopenharmony_ci		p = cdr(n = p);
1202d5ac70f0Sopenharmony_ci		delete_object(instance, n);
1203d5ac70f0Sopenharmony_ci		if (p == &alsa_lisp_nil)
1204d5ac70f0Sopenharmony_ci			break;
1205d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
1206d5ac70f0Sopenharmony_ci	}
1207d5ac70f0Sopenharmony_ci	if (str) {
1208d5ac70f0Sopenharmony_ci		p = new_string(instance, str);
1209d5ac70f0Sopenharmony_ci		free(str);
1210d5ac70f0Sopenharmony_ci	} else {
1211d5ac70f0Sopenharmony_ci		p = &alsa_lisp_nil;
1212d5ac70f0Sopenharmony_ci	}
1213d5ac70f0Sopenharmony_ci	return p;
1214d5ac70f0Sopenharmony_ci}
1215d5ac70f0Sopenharmony_ci
1216d5ac70f0Sopenharmony_ci/*
1217d5ac70f0Sopenharmony_ci * Syntax: (- expr...)
1218d5ac70f0Sopenharmony_ci */
1219d5ac70f0Sopenharmony_cistatic struct alisp_object * F_sub(struct alisp_instance *instance, struct alisp_object * args)
1220d5ac70f0Sopenharmony_ci{
1221d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1, * n;
1222d5ac70f0Sopenharmony_ci	long v = 0;
1223d5ac70f0Sopenharmony_ci	double f = 0;
1224d5ac70f0Sopenharmony_ci	int type = ALISP_OBJ_INTEGER;
1225d5ac70f0Sopenharmony_ci
1226d5ac70f0Sopenharmony_ci	do {
1227d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
1228d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
1229d5ac70f0Sopenharmony_ci			if (p == args && cdr(p) != &alsa_lisp_nil) {
1230d5ac70f0Sopenharmony_ci				v = p1->value.i;
1231d5ac70f0Sopenharmony_ci			} else {
1232d5ac70f0Sopenharmony_ci				if (type == ALISP_OBJ_FLOAT)
1233d5ac70f0Sopenharmony_ci					f -= p1->value.i;
1234d5ac70f0Sopenharmony_ci				else
1235d5ac70f0Sopenharmony_ci					v -= p1->value.i;
1236d5ac70f0Sopenharmony_ci			}
1237d5ac70f0Sopenharmony_ci		} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
1238d5ac70f0Sopenharmony_ci			if (type == ALISP_OBJ_INTEGER) {
1239d5ac70f0Sopenharmony_ci				f = v;
1240d5ac70f0Sopenharmony_ci				type = ALISP_OBJ_FLOAT;
1241d5ac70f0Sopenharmony_ci			}
1242d5ac70f0Sopenharmony_ci			if (p == args && cdr(p) != &alsa_lisp_nil)
1243d5ac70f0Sopenharmony_ci				f = p1->value.f;
1244d5ac70f0Sopenharmony_ci			else {
1245d5ac70f0Sopenharmony_ci				f -= p1->value.f;
1246d5ac70f0Sopenharmony_ci			}
1247d5ac70f0Sopenharmony_ci		} else
1248d5ac70f0Sopenharmony_ci			lisp_warn(instance, "difference with a non integer or float operand");
1249d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1250d5ac70f0Sopenharmony_ci		n = cdr(p);
1251d5ac70f0Sopenharmony_ci		delete_object(instance, p);
1252d5ac70f0Sopenharmony_ci		p = n;
1253d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
1254d5ac70f0Sopenharmony_ci
1255d5ac70f0Sopenharmony_ci	if (type == ALISP_OBJ_INTEGER) {
1256d5ac70f0Sopenharmony_ci		return new_integer(instance, v);
1257d5ac70f0Sopenharmony_ci	} else {
1258d5ac70f0Sopenharmony_ci		return new_float(instance, f);
1259d5ac70f0Sopenharmony_ci	}
1260d5ac70f0Sopenharmony_ci}
1261d5ac70f0Sopenharmony_ci
1262d5ac70f0Sopenharmony_ci/*
1263d5ac70f0Sopenharmony_ci * Syntax: (* expr...)
1264d5ac70f0Sopenharmony_ci */
1265d5ac70f0Sopenharmony_cistatic struct alisp_object * F_mul(struct alisp_instance *instance, struct alisp_object * args)
1266d5ac70f0Sopenharmony_ci{
1267d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1, * n;
1268d5ac70f0Sopenharmony_ci	long v = 1;
1269d5ac70f0Sopenharmony_ci	double f = 1;
1270d5ac70f0Sopenharmony_ci	int type = ALISP_OBJ_INTEGER;
1271d5ac70f0Sopenharmony_ci
1272d5ac70f0Sopenharmony_ci	do {
1273d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
1274d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
1275d5ac70f0Sopenharmony_ci			if (type == ALISP_OBJ_FLOAT)
1276d5ac70f0Sopenharmony_ci				f *= p1->value.i;
1277d5ac70f0Sopenharmony_ci			else
1278d5ac70f0Sopenharmony_ci				v *= p1->value.i;
1279d5ac70f0Sopenharmony_ci		} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
1280d5ac70f0Sopenharmony_ci			f *= p1->value.f * v; v = 1;
1281d5ac70f0Sopenharmony_ci			type = ALISP_OBJ_FLOAT;
1282d5ac70f0Sopenharmony_ci		} else {
1283d5ac70f0Sopenharmony_ci			lisp_warn(instance, "product with a non integer or float operand");
1284d5ac70f0Sopenharmony_ci		}
1285d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1286d5ac70f0Sopenharmony_ci		n = cdr(p);
1287d5ac70f0Sopenharmony_ci		delete_object(instance, p);
1288d5ac70f0Sopenharmony_ci		p = n;
1289d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
1290d5ac70f0Sopenharmony_ci
1291d5ac70f0Sopenharmony_ci	if (type == ALISP_OBJ_INTEGER) {
1292d5ac70f0Sopenharmony_ci		return new_integer(instance, v);
1293d5ac70f0Sopenharmony_ci	} else {
1294d5ac70f0Sopenharmony_ci		return new_float(instance, f);
1295d5ac70f0Sopenharmony_ci	}
1296d5ac70f0Sopenharmony_ci}
1297d5ac70f0Sopenharmony_ci
1298d5ac70f0Sopenharmony_ci/*
1299d5ac70f0Sopenharmony_ci * Syntax: (/ expr...)
1300d5ac70f0Sopenharmony_ci */
1301d5ac70f0Sopenharmony_cistatic struct alisp_object * F_div(struct alisp_instance *instance, struct alisp_object * args)
1302d5ac70f0Sopenharmony_ci{
1303d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1, * n;
1304d5ac70f0Sopenharmony_ci	long v = 0;
1305d5ac70f0Sopenharmony_ci	double f = 0;
1306d5ac70f0Sopenharmony_ci	int type = ALISP_OBJ_INTEGER;
1307d5ac70f0Sopenharmony_ci
1308d5ac70f0Sopenharmony_ci	do {
1309d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
1310d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
1311d5ac70f0Sopenharmony_ci			if (p == args && cdr(p) != &alsa_lisp_nil) {
1312d5ac70f0Sopenharmony_ci				v = p1->value.i;
1313d5ac70f0Sopenharmony_ci			} else {
1314d5ac70f0Sopenharmony_ci				if (p1->value.i == 0) {
1315d5ac70f0Sopenharmony_ci					lisp_warn(instance, "division by zero");
1316d5ac70f0Sopenharmony_ci					v = 0;
1317d5ac70f0Sopenharmony_ci					f = 0;
1318d5ac70f0Sopenharmony_ci					break;
1319d5ac70f0Sopenharmony_ci				} else {
1320d5ac70f0Sopenharmony_ci					if (type == ALISP_OBJ_FLOAT)
1321d5ac70f0Sopenharmony_ci						f /= p1->value.i;
1322d5ac70f0Sopenharmony_ci					else
1323d5ac70f0Sopenharmony_ci						v /= p1->value.i;
1324d5ac70f0Sopenharmony_ci				}
1325d5ac70f0Sopenharmony_ci			}
1326d5ac70f0Sopenharmony_ci		} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
1327d5ac70f0Sopenharmony_ci			if (type == ALISP_OBJ_INTEGER) {
1328d5ac70f0Sopenharmony_ci				f = v;
1329d5ac70f0Sopenharmony_ci				type = ALISP_OBJ_FLOAT;
1330d5ac70f0Sopenharmony_ci			}
1331d5ac70f0Sopenharmony_ci			if (p == args && cdr(p) != &alsa_lisp_nil) {
1332d5ac70f0Sopenharmony_ci				f = p1->value.f;
1333d5ac70f0Sopenharmony_ci			} else {
1334d5ac70f0Sopenharmony_ci				if (p1->value.f == 0) {
1335d5ac70f0Sopenharmony_ci					lisp_warn(instance, "division by zero");
1336d5ac70f0Sopenharmony_ci					f = 0;
1337d5ac70f0Sopenharmony_ci					break;
1338d5ac70f0Sopenharmony_ci				} else {
1339d5ac70f0Sopenharmony_ci					f /= p1->value.i;
1340d5ac70f0Sopenharmony_ci				}
1341d5ac70f0Sopenharmony_ci			}
1342d5ac70f0Sopenharmony_ci		} else
1343d5ac70f0Sopenharmony_ci			lisp_warn(instance, "quotient with a non integer or float operand");
1344d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1345d5ac70f0Sopenharmony_ci		n = cdr(p);
1346d5ac70f0Sopenharmony_ci		delete_object(instance, p);
1347d5ac70f0Sopenharmony_ci		p = n;
1348d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
1349d5ac70f0Sopenharmony_ci
1350d5ac70f0Sopenharmony_ci	if (type == ALISP_OBJ_INTEGER) {
1351d5ac70f0Sopenharmony_ci		return new_integer(instance, v);
1352d5ac70f0Sopenharmony_ci	} else {
1353d5ac70f0Sopenharmony_ci		return new_float(instance, f);
1354d5ac70f0Sopenharmony_ci	}
1355d5ac70f0Sopenharmony_ci}
1356d5ac70f0Sopenharmony_ci
1357d5ac70f0Sopenharmony_ci/*
1358d5ac70f0Sopenharmony_ci * Syntax: (% expr1 expr2)
1359d5ac70f0Sopenharmony_ci */
1360d5ac70f0Sopenharmony_cistatic struct alisp_object * F_mod(struct alisp_instance *instance, struct alisp_object * args)
1361d5ac70f0Sopenharmony_ci{
1362d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2, * p3;
1363d5ac70f0Sopenharmony_ci
1364d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1365d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
1366d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
1367d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
1368d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1369d5ac70f0Sopenharmony_ci
1370d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1371d5ac70f0Sopenharmony_ci	    alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1372d5ac70f0Sopenharmony_ci		if (p2->value.i == 0) {
1373d5ac70f0Sopenharmony_ci			lisp_warn(instance, "module by zero");
1374d5ac70f0Sopenharmony_ci			p3 = new_integer(instance, 0);
1375d5ac70f0Sopenharmony_ci		} else {
1376d5ac70f0Sopenharmony_ci			p3 = new_integer(instance, p1->value.i % p2->value.i);
1377d5ac70f0Sopenharmony_ci		}
1378d5ac70f0Sopenharmony_ci	} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1379d5ac70f0Sopenharmony_ci	            alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1380d5ac70f0Sopenharmony_ci		   (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1381d5ac70f0Sopenharmony_ci		    alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1382d5ac70f0Sopenharmony_ci		double f1, f2;
1383d5ac70f0Sopenharmony_ci		f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1384d5ac70f0Sopenharmony_ci		f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1385d5ac70f0Sopenharmony_ci		f1 = fmod(f1, f2);
1386d5ac70f0Sopenharmony_ci		if (f1 == EDOM) {
1387d5ac70f0Sopenharmony_ci			lisp_warn(instance, "module by zero");
1388d5ac70f0Sopenharmony_ci			p3 = new_float(instance, 0);
1389d5ac70f0Sopenharmony_ci		} else {
1390d5ac70f0Sopenharmony_ci			p3 = new_float(instance, f1);
1391d5ac70f0Sopenharmony_ci		}
1392d5ac70f0Sopenharmony_ci	} else {
1393d5ac70f0Sopenharmony_ci		lisp_warn(instance, "module with a non integer or float operand");
1394d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1395d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
1396d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
1397d5ac70f0Sopenharmony_ci	}
1398d5ac70f0Sopenharmony_ci
1399d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1400d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
1401d5ac70f0Sopenharmony_ci	return p3;
1402d5ac70f0Sopenharmony_ci}
1403d5ac70f0Sopenharmony_ci
1404d5ac70f0Sopenharmony_ci/*
1405d5ac70f0Sopenharmony_ci * Syntax: (< expr1 expr2)
1406d5ac70f0Sopenharmony_ci */
1407d5ac70f0Sopenharmony_cistatic struct alisp_object * F_lt(struct alisp_instance *instance, struct alisp_object * args)
1408d5ac70f0Sopenharmony_ci{
1409d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
1410d5ac70f0Sopenharmony_ci
1411d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1412d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
1413d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
1414d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
1415d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1416d5ac70f0Sopenharmony_ci
1417d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1418d5ac70f0Sopenharmony_ci	    alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1419d5ac70f0Sopenharmony_ci		if (p1->value.i < p2->value.i) {
1420d5ac70f0Sopenharmony_ci		      __true:
1421d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1422d5ac70f0Sopenharmony_ci			delete_tree(instance, p2);
1423d5ac70f0Sopenharmony_ci			return &alsa_lisp_t;
1424d5ac70f0Sopenharmony_ci		}
1425d5ac70f0Sopenharmony_ci	} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1426d5ac70f0Sopenharmony_ci	            alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1427d5ac70f0Sopenharmony_ci		   (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1428d5ac70f0Sopenharmony_ci		    alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1429d5ac70f0Sopenharmony_ci		double f1, f2;
1430d5ac70f0Sopenharmony_ci		f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1431d5ac70f0Sopenharmony_ci		f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1432d5ac70f0Sopenharmony_ci		if (f1 < f2)
1433d5ac70f0Sopenharmony_ci			goto __true;
1434d5ac70f0Sopenharmony_ci	} else {
1435d5ac70f0Sopenharmony_ci		lisp_warn(instance, "comparison with a non integer or float operand");
1436d5ac70f0Sopenharmony_ci	}
1437d5ac70f0Sopenharmony_ci
1438d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1439d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
1440d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1441d5ac70f0Sopenharmony_ci}
1442d5ac70f0Sopenharmony_ci
1443d5ac70f0Sopenharmony_ci/*
1444d5ac70f0Sopenharmony_ci * Syntax: (> expr1 expr2)
1445d5ac70f0Sopenharmony_ci */
1446d5ac70f0Sopenharmony_cistatic struct alisp_object * F_gt(struct alisp_instance *instance, struct alisp_object * args)
1447d5ac70f0Sopenharmony_ci{
1448d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
1449d5ac70f0Sopenharmony_ci
1450d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1451d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
1452d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
1453d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
1454d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1455d5ac70f0Sopenharmony_ci
1456d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1457d5ac70f0Sopenharmony_ci	    alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1458d5ac70f0Sopenharmony_ci		if (p1->value.i > p2->value.i) {
1459d5ac70f0Sopenharmony_ci		      __true:
1460d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1461d5ac70f0Sopenharmony_ci			delete_tree(instance, p2);
1462d5ac70f0Sopenharmony_ci			return &alsa_lisp_t;
1463d5ac70f0Sopenharmony_ci		}
1464d5ac70f0Sopenharmony_ci	} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1465d5ac70f0Sopenharmony_ci	            alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1466d5ac70f0Sopenharmony_ci		   (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1467d5ac70f0Sopenharmony_ci		    alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1468d5ac70f0Sopenharmony_ci		double f1, f2;
1469d5ac70f0Sopenharmony_ci		f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1470d5ac70f0Sopenharmony_ci		f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1471d5ac70f0Sopenharmony_ci		if (f1 > f2)
1472d5ac70f0Sopenharmony_ci			goto __true;
1473d5ac70f0Sopenharmony_ci	} else {
1474d5ac70f0Sopenharmony_ci		lisp_warn(instance, "comparison with a non integer or float operand");
1475d5ac70f0Sopenharmony_ci	}
1476d5ac70f0Sopenharmony_ci
1477d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1478d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
1479d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1480d5ac70f0Sopenharmony_ci}
1481d5ac70f0Sopenharmony_ci
1482d5ac70f0Sopenharmony_ci/*
1483d5ac70f0Sopenharmony_ci * Syntax: (<= expr1 expr2)
1484d5ac70f0Sopenharmony_ci */
1485d5ac70f0Sopenharmony_cistatic struct alisp_object * F_le(struct alisp_instance *instance, struct alisp_object * args)
1486d5ac70f0Sopenharmony_ci{
1487d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
1488d5ac70f0Sopenharmony_ci
1489d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1490d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
1491d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
1492d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
1493d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1494d5ac70f0Sopenharmony_ci
1495d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1496d5ac70f0Sopenharmony_ci	    alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1497d5ac70f0Sopenharmony_ci		if (p1->value.i <= p2->value.i) {
1498d5ac70f0Sopenharmony_ci		      __true:
1499d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1500d5ac70f0Sopenharmony_ci			delete_tree(instance, p2);
1501d5ac70f0Sopenharmony_ci			return &alsa_lisp_t;
1502d5ac70f0Sopenharmony_ci		}
1503d5ac70f0Sopenharmony_ci	} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1504d5ac70f0Sopenharmony_ci	            alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1505d5ac70f0Sopenharmony_ci		   (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1506d5ac70f0Sopenharmony_ci		    alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1507d5ac70f0Sopenharmony_ci		double f1, f2;
1508d5ac70f0Sopenharmony_ci		f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1509d5ac70f0Sopenharmony_ci		f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1510d5ac70f0Sopenharmony_ci		if (f1 <= f2)
1511d5ac70f0Sopenharmony_ci			goto __true;
1512d5ac70f0Sopenharmony_ci	} else {
1513d5ac70f0Sopenharmony_ci		lisp_warn(instance, "comparison with a non integer or float operand");
1514d5ac70f0Sopenharmony_ci	}
1515d5ac70f0Sopenharmony_ci
1516d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1517d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
1518d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1519d5ac70f0Sopenharmony_ci}
1520d5ac70f0Sopenharmony_ci
1521d5ac70f0Sopenharmony_ci/*
1522d5ac70f0Sopenharmony_ci * Syntax: (>= expr1 expr2)
1523d5ac70f0Sopenharmony_ci */
1524d5ac70f0Sopenharmony_cistatic struct alisp_object * F_ge(struct alisp_instance *instance, struct alisp_object * args)
1525d5ac70f0Sopenharmony_ci{
1526d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
1527d5ac70f0Sopenharmony_ci
1528d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1529d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
1530d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
1531d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
1532d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1533d5ac70f0Sopenharmony_ci
1534d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1535d5ac70f0Sopenharmony_ci	    alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1536d5ac70f0Sopenharmony_ci		if (p1->value.i >= p2->value.i) {
1537d5ac70f0Sopenharmony_ci		      __true:
1538d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1539d5ac70f0Sopenharmony_ci			delete_tree(instance, p2);
1540d5ac70f0Sopenharmony_ci			return &alsa_lisp_t;
1541d5ac70f0Sopenharmony_ci		}
1542d5ac70f0Sopenharmony_ci	} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1543d5ac70f0Sopenharmony_ci	            alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1544d5ac70f0Sopenharmony_ci		   (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1545d5ac70f0Sopenharmony_ci		    alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1546d5ac70f0Sopenharmony_ci		double f1, f2;
1547d5ac70f0Sopenharmony_ci		f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1548d5ac70f0Sopenharmony_ci		f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1549d5ac70f0Sopenharmony_ci		if (f1 >= f2)
1550d5ac70f0Sopenharmony_ci			goto __true;
1551d5ac70f0Sopenharmony_ci	} else {
1552d5ac70f0Sopenharmony_ci		lisp_warn(instance, "comparison with a non integer or float operand");
1553d5ac70f0Sopenharmony_ci	}
1554d5ac70f0Sopenharmony_ci
1555d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1556d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
1557d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1558d5ac70f0Sopenharmony_ci}
1559d5ac70f0Sopenharmony_ci
1560d5ac70f0Sopenharmony_ci/*
1561d5ac70f0Sopenharmony_ci * Syntax: (= expr1 expr2)
1562d5ac70f0Sopenharmony_ci */
1563d5ac70f0Sopenharmony_cistatic struct alisp_object * F_numeq(struct alisp_instance *instance, struct alisp_object * args)
1564d5ac70f0Sopenharmony_ci{
1565d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
1566d5ac70f0Sopenharmony_ci
1567d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1568d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
1569d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
1570d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
1571d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1572d5ac70f0Sopenharmony_ci
1573d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1574d5ac70f0Sopenharmony_ci	    alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1575d5ac70f0Sopenharmony_ci		if (p1->value.i == p2->value.i) {
1576d5ac70f0Sopenharmony_ci		      __true:
1577d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1578d5ac70f0Sopenharmony_ci			delete_tree(instance, p2);
1579d5ac70f0Sopenharmony_ci			return &alsa_lisp_t;
1580d5ac70f0Sopenharmony_ci		}
1581d5ac70f0Sopenharmony_ci	} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1582d5ac70f0Sopenharmony_ci	            alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1583d5ac70f0Sopenharmony_ci		   (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1584d5ac70f0Sopenharmony_ci		    alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1585d5ac70f0Sopenharmony_ci		double f1, f2;
1586d5ac70f0Sopenharmony_ci		f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1587d5ac70f0Sopenharmony_ci		f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1588d5ac70f0Sopenharmony_ci		if (f1 == f2)
1589d5ac70f0Sopenharmony_ci			goto __true;
1590d5ac70f0Sopenharmony_ci	} else {
1591d5ac70f0Sopenharmony_ci		lisp_warn(instance, "comparison with a non integer or float operand");
1592d5ac70f0Sopenharmony_ci	}
1593d5ac70f0Sopenharmony_ci
1594d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1595d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
1596d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1597d5ac70f0Sopenharmony_ci}
1598d5ac70f0Sopenharmony_ci
1599d5ac70f0Sopenharmony_ci/*
1600d5ac70f0Sopenharmony_ci * Syntax: (!= expr1 expr2)
1601d5ac70f0Sopenharmony_ci */
1602d5ac70f0Sopenharmony_cistatic struct alisp_object * F_numneq(struct alisp_instance *instance, struct alisp_object * args)
1603d5ac70f0Sopenharmony_ci{
1604d5ac70f0Sopenharmony_ci	struct alisp_object * p;
1605d5ac70f0Sopenharmony_ci
1606d5ac70f0Sopenharmony_ci	p = F_numeq(instance, args);
1607d5ac70f0Sopenharmony_ci	if (p == &alsa_lisp_nil)
1608d5ac70f0Sopenharmony_ci		return &alsa_lisp_t;
1609d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1610d5ac70f0Sopenharmony_ci}
1611d5ac70f0Sopenharmony_ci
1612d5ac70f0Sopenharmony_ci/*
1613d5ac70f0Sopenharmony_ci * Syntax: (exfun name)
1614d5ac70f0Sopenharmony_ci * Test, if a function exists
1615d5ac70f0Sopenharmony_ci */
1616d5ac70f0Sopenharmony_cistatic struct alisp_object * F_exfun(struct alisp_instance *instance, struct alisp_object * args)
1617d5ac70f0Sopenharmony_ci{
1618d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
1619d5ac70f0Sopenharmony_ci
1620d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1621d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
1622d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1623d5ac70f0Sopenharmony_ci	p2 = get_object(instance, p1);
1624d5ac70f0Sopenharmony_ci	if (p2 == &alsa_lisp_nil) {
1625d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1626d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
1627d5ac70f0Sopenharmony_ci	}
1628d5ac70f0Sopenharmony_ci	p2 = car(p2);
1629d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p2, ALISP_OBJ_IDENTIFIER) &&
1630d5ac70f0Sopenharmony_ci	    !strcmp(p2->value.s, "lambda")) {
1631d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1632d5ac70f0Sopenharmony_ci		return &alsa_lisp_t;
1633d5ac70f0Sopenharmony_ci	}
1634d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1635d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1636d5ac70f0Sopenharmony_ci}
1637d5ac70f0Sopenharmony_ci
1638d5ac70f0Sopenharmony_cistatic void princ_string(snd_output_t *out, char *s)
1639d5ac70f0Sopenharmony_ci{
1640d5ac70f0Sopenharmony_ci	char *p;
1641d5ac70f0Sopenharmony_ci
1642d5ac70f0Sopenharmony_ci	snd_output_putc(out, '"');
1643d5ac70f0Sopenharmony_ci	for (p = s; *p != '\0'; ++p)
1644d5ac70f0Sopenharmony_ci		switch (*p) {
1645d5ac70f0Sopenharmony_ci		case '\a': snd_output_putc(out, '\\'); snd_output_putc(out, 'a'); break;
1646d5ac70f0Sopenharmony_ci		case '\b': snd_output_putc(out, '\\'); snd_output_putc(out, 'b'); break;
1647d5ac70f0Sopenharmony_ci		case '\f': snd_output_putc(out, '\\'); snd_output_putc(out, 'f'); break;
1648d5ac70f0Sopenharmony_ci		case '\n': snd_output_putc(out, '\\'); snd_output_putc(out, 'n'); break;
1649d5ac70f0Sopenharmony_ci		case '\r': snd_output_putc(out, '\\'); snd_output_putc(out, 'r'); break;
1650d5ac70f0Sopenharmony_ci		case '\t': snd_output_putc(out, '\\'); snd_output_putc(out, 't'); break;
1651d5ac70f0Sopenharmony_ci		case '\v': snd_output_putc(out, '\\'); snd_output_putc(out, 'v'); break;
1652d5ac70f0Sopenharmony_ci		case '"': snd_output_putc(out, '\\'); snd_output_putc(out, '"'); break;
1653d5ac70f0Sopenharmony_ci		default: snd_output_putc(out, *p);
1654d5ac70f0Sopenharmony_ci		}
1655d5ac70f0Sopenharmony_ci	snd_output_putc(out, '"');
1656d5ac70f0Sopenharmony_ci}
1657d5ac70f0Sopenharmony_ci
1658d5ac70f0Sopenharmony_cistatic void princ_cons(snd_output_t *out, struct alisp_object * p)
1659d5ac70f0Sopenharmony_ci{
1660d5ac70f0Sopenharmony_ci	do {
1661d5ac70f0Sopenharmony_ci		princ_object(out, p->value.c.car);
1662d5ac70f0Sopenharmony_ci		p = p->value.c.cdr;
1663d5ac70f0Sopenharmony_ci		if (p != &alsa_lisp_nil) {
1664d5ac70f0Sopenharmony_ci			snd_output_putc(out, ' ');
1665d5ac70f0Sopenharmony_ci			if (!alisp_compare_type(p, ALISP_OBJ_CONS)) {
1666d5ac70f0Sopenharmony_ci				snd_output_printf(out, ". ");
1667d5ac70f0Sopenharmony_ci				princ_object(out, p);
1668d5ac70f0Sopenharmony_ci			}
1669d5ac70f0Sopenharmony_ci		}
1670d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil && alisp_compare_type(p, ALISP_OBJ_CONS));
1671d5ac70f0Sopenharmony_ci}
1672d5ac70f0Sopenharmony_ci
1673d5ac70f0Sopenharmony_cistatic void princ_object(snd_output_t *out, struct alisp_object * p)
1674d5ac70f0Sopenharmony_ci{
1675d5ac70f0Sopenharmony_ci	switch (alisp_get_type(p)) {
1676d5ac70f0Sopenharmony_ci	case ALISP_OBJ_NIL:
1677d5ac70f0Sopenharmony_ci		snd_output_printf(out, "nil");
1678d5ac70f0Sopenharmony_ci		break;
1679d5ac70f0Sopenharmony_ci	case ALISP_OBJ_T:
1680d5ac70f0Sopenharmony_ci		snd_output_putc(out, 't');
1681d5ac70f0Sopenharmony_ci		break;
1682d5ac70f0Sopenharmony_ci	case ALISP_OBJ_IDENTIFIER:
1683d5ac70f0Sopenharmony_ci		snd_output_printf(out, "%s", p->value.s);
1684d5ac70f0Sopenharmony_ci		break;
1685d5ac70f0Sopenharmony_ci	case ALISP_OBJ_STRING:
1686d5ac70f0Sopenharmony_ci		princ_string(out, p->value.s);
1687d5ac70f0Sopenharmony_ci		break;
1688d5ac70f0Sopenharmony_ci	case ALISP_OBJ_INTEGER:
1689d5ac70f0Sopenharmony_ci		snd_output_printf(out, "%ld", p->value.i);
1690d5ac70f0Sopenharmony_ci		break;
1691d5ac70f0Sopenharmony_ci	case ALISP_OBJ_FLOAT:
1692d5ac70f0Sopenharmony_ci		snd_output_printf(out, "%f", p->value.f);
1693d5ac70f0Sopenharmony_ci		break;
1694d5ac70f0Sopenharmony_ci	case ALISP_OBJ_POINTER:
1695d5ac70f0Sopenharmony_ci		snd_output_printf(out, "<%p>", p->value.ptr);
1696d5ac70f0Sopenharmony_ci		break;
1697d5ac70f0Sopenharmony_ci	case ALISP_OBJ_CONS:
1698d5ac70f0Sopenharmony_ci		snd_output_putc(out, '(');
1699d5ac70f0Sopenharmony_ci		princ_cons(out, p);
1700d5ac70f0Sopenharmony_ci		snd_output_putc(out, ')');
1701d5ac70f0Sopenharmony_ci	}
1702d5ac70f0Sopenharmony_ci}
1703d5ac70f0Sopenharmony_ci
1704d5ac70f0Sopenharmony_ci/*
1705d5ac70f0Sopenharmony_ci * Syntax: (princ expr...)
1706d5ac70f0Sopenharmony_ci */
1707d5ac70f0Sopenharmony_cistatic struct alisp_object * F_princ(struct alisp_instance *instance, struct alisp_object * args)
1708d5ac70f0Sopenharmony_ci{
1709d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1 = NULL, * n;
1710d5ac70f0Sopenharmony_ci
1711d5ac70f0Sopenharmony_ci	do {
1712d5ac70f0Sopenharmony_ci		if (p1)
1713d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1714d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
1715d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_STRING))
1716d5ac70f0Sopenharmony_ci			snd_output_printf(instance->out, "%s", p1->value.s);
1717d5ac70f0Sopenharmony_ci		else
1718d5ac70f0Sopenharmony_ci			princ_object(instance->out, p1);
1719d5ac70f0Sopenharmony_ci		n = cdr(p);
1720d5ac70f0Sopenharmony_ci		delete_object(instance, p);
1721d5ac70f0Sopenharmony_ci		p = n;
1722d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
1723d5ac70f0Sopenharmony_ci
1724d5ac70f0Sopenharmony_ci	return p1;
1725d5ac70f0Sopenharmony_ci}
1726d5ac70f0Sopenharmony_ci
1727d5ac70f0Sopenharmony_ci/*
1728d5ac70f0Sopenharmony_ci * Syntax: (atom expr)
1729d5ac70f0Sopenharmony_ci */
1730d5ac70f0Sopenharmony_cistatic struct alisp_object * F_atom(struct alisp_instance *instance, struct alisp_object * args)
1731d5ac70f0Sopenharmony_ci{
1732d5ac70f0Sopenharmony_ci	struct alisp_object * p;
1733d5ac70f0Sopenharmony_ci
1734d5ac70f0Sopenharmony_ci	p = eval(instance, car(args));
1735d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
1736d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1737d5ac70f0Sopenharmony_ci	if (p == NULL)
1738d5ac70f0Sopenharmony_ci		return NULL;
1739d5ac70f0Sopenharmony_ci
1740d5ac70f0Sopenharmony_ci	switch (alisp_get_type(p)) {
1741d5ac70f0Sopenharmony_ci	case ALISP_OBJ_T:
1742d5ac70f0Sopenharmony_ci	case ALISP_OBJ_NIL:
1743d5ac70f0Sopenharmony_ci	case ALISP_OBJ_INTEGER:
1744d5ac70f0Sopenharmony_ci	case ALISP_OBJ_FLOAT:
1745d5ac70f0Sopenharmony_ci	case ALISP_OBJ_STRING:
1746d5ac70f0Sopenharmony_ci	case ALISP_OBJ_IDENTIFIER:
1747d5ac70f0Sopenharmony_ci	case ALISP_OBJ_POINTER:
1748d5ac70f0Sopenharmony_ci		delete_tree(instance, p);
1749d5ac70f0Sopenharmony_ci		return &alsa_lisp_t;
1750d5ac70f0Sopenharmony_ci	default:
1751d5ac70f0Sopenharmony_ci		break;
1752d5ac70f0Sopenharmony_ci	}
1753d5ac70f0Sopenharmony_ci
1754d5ac70f0Sopenharmony_ci	delete_tree(instance, p);
1755d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1756d5ac70f0Sopenharmony_ci}
1757d5ac70f0Sopenharmony_ci
1758d5ac70f0Sopenharmony_ci/*
1759d5ac70f0Sopenharmony_ci * Syntax: (cons expr1 expr2)
1760d5ac70f0Sopenharmony_ci */
1761d5ac70f0Sopenharmony_cistatic struct alisp_object * F_cons(struct alisp_instance *instance, struct alisp_object * args)
1762d5ac70f0Sopenharmony_ci{
1763d5ac70f0Sopenharmony_ci	struct alisp_object * p;
1764d5ac70f0Sopenharmony_ci
1765d5ac70f0Sopenharmony_ci	p = new_object(instance, ALISP_OBJ_CONS);
1766d5ac70f0Sopenharmony_ci	if (p) {
1767d5ac70f0Sopenharmony_ci		p->value.c.car = eval(instance, car(args));
1768d5ac70f0Sopenharmony_ci		p->value.c.cdr = eval(instance, car(cdr(args)));
1769d5ac70f0Sopenharmony_ci		delete_tree(instance, cdr(cdr(args)));
1770d5ac70f0Sopenharmony_ci		delete_object(instance, cdr(args));
1771d5ac70f0Sopenharmony_ci		delete_object(instance, args);
1772d5ac70f0Sopenharmony_ci	} else {
1773d5ac70f0Sopenharmony_ci		delete_tree(instance, args);
1774d5ac70f0Sopenharmony_ci	}
1775d5ac70f0Sopenharmony_ci
1776d5ac70f0Sopenharmony_ci	return p;
1777d5ac70f0Sopenharmony_ci}
1778d5ac70f0Sopenharmony_ci
1779d5ac70f0Sopenharmony_ci/*
1780d5ac70f0Sopenharmony_ci * Syntax: (list expr1...)
1781d5ac70f0Sopenharmony_ci */
1782d5ac70f0Sopenharmony_cistatic struct alisp_object * F_list(struct alisp_instance *instance, struct alisp_object * args)
1783d5ac70f0Sopenharmony_ci{
1784d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * first = NULL, * prev = NULL, * p1;
1785d5ac70f0Sopenharmony_ci
1786d5ac70f0Sopenharmony_ci	if (p == &alsa_lisp_nil)
1787d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
1788d5ac70f0Sopenharmony_ci
1789d5ac70f0Sopenharmony_ci	do {
1790d5ac70f0Sopenharmony_ci		p1 = new_object(instance, ALISP_OBJ_CONS);
1791d5ac70f0Sopenharmony_ci		if (p1 == NULL) {
1792d5ac70f0Sopenharmony_ci			delete_tree(instance, p);
1793d5ac70f0Sopenharmony_ci			delete_tree(instance, first);
1794d5ac70f0Sopenharmony_ci			return NULL;
1795d5ac70f0Sopenharmony_ci		}
1796d5ac70f0Sopenharmony_ci		p1->value.c.car = eval(instance, car(p));
1797d5ac70f0Sopenharmony_ci		if (p1->value.c.car == NULL) {
1798d5ac70f0Sopenharmony_ci			delete_tree(instance, first);
1799d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p));
1800d5ac70f0Sopenharmony_ci			delete_object(instance, p);
1801d5ac70f0Sopenharmony_ci			return NULL;
1802d5ac70f0Sopenharmony_ci		}
1803d5ac70f0Sopenharmony_ci		if (first == NULL)
1804d5ac70f0Sopenharmony_ci			first = p1;
1805d5ac70f0Sopenharmony_ci		if (prev != NULL)
1806d5ac70f0Sopenharmony_ci			prev->value.c.cdr = p1;
1807d5ac70f0Sopenharmony_ci		prev = p1;
1808d5ac70f0Sopenharmony_ci		p = cdr(p1 = p);
1809d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
1810d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
1811d5ac70f0Sopenharmony_ci
1812d5ac70f0Sopenharmony_ci	return first;
1813d5ac70f0Sopenharmony_ci}
1814d5ac70f0Sopenharmony_ci
1815d5ac70f0Sopenharmony_cistatic inline int eq(struct alisp_object * p1, struct alisp_object * p2)
1816d5ac70f0Sopenharmony_ci{
1817d5ac70f0Sopenharmony_ci	return p1 == p2;
1818d5ac70f0Sopenharmony_ci}
1819d5ac70f0Sopenharmony_ci
1820d5ac70f0Sopenharmony_cistatic int equal(struct alisp_object * p1, struct alisp_object * p2)
1821d5ac70f0Sopenharmony_ci{
1822d5ac70f0Sopenharmony_ci	int type1, type2;
1823d5ac70f0Sopenharmony_ci
1824d5ac70f0Sopenharmony_ci	if (eq(p1, p2))
1825d5ac70f0Sopenharmony_ci		return 1;
1826d5ac70f0Sopenharmony_ci
1827d5ac70f0Sopenharmony_ci	type1 = alisp_get_type(p1);
1828d5ac70f0Sopenharmony_ci	type2 = alisp_get_type(p2);
1829d5ac70f0Sopenharmony_ci
1830d5ac70f0Sopenharmony_ci	if (type1 == ALISP_OBJ_CONS || type2 == ALISP_OBJ_CONS)
1831d5ac70f0Sopenharmony_ci		return 0;
1832d5ac70f0Sopenharmony_ci
1833d5ac70f0Sopenharmony_ci	if (type1 == type2) {
1834d5ac70f0Sopenharmony_ci		switch (type1) {
1835d5ac70f0Sopenharmony_ci		case ALISP_OBJ_STRING:
1836d5ac70f0Sopenharmony_ci			return !strcmp(p1->value.s, p2->value.s);
1837d5ac70f0Sopenharmony_ci		case ALISP_OBJ_INTEGER:
1838d5ac70f0Sopenharmony_ci			return p1->value.i == p2->value.i;
1839d5ac70f0Sopenharmony_ci		case ALISP_OBJ_FLOAT:
1840d5ac70f0Sopenharmony_ci			return p1->value.i == p2->value.i;
1841d5ac70f0Sopenharmony_ci		}
1842d5ac70f0Sopenharmony_ci	}
1843d5ac70f0Sopenharmony_ci
1844d5ac70f0Sopenharmony_ci	return 0;
1845d5ac70f0Sopenharmony_ci}
1846d5ac70f0Sopenharmony_ci
1847d5ac70f0Sopenharmony_ci/*
1848d5ac70f0Sopenharmony_ci * Syntax: (eq expr1 expr2)
1849d5ac70f0Sopenharmony_ci */
1850d5ac70f0Sopenharmony_cistatic struct alisp_object * F_eq(struct alisp_instance *instance, struct alisp_object * args)
1851d5ac70f0Sopenharmony_ci{
1852d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
1853d5ac70f0Sopenharmony_ci
1854d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1855d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
1856d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
1857d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
1858d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1859d5ac70f0Sopenharmony_ci
1860d5ac70f0Sopenharmony_ci	if (eq(p1, p2)) {
1861d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1862d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
1863d5ac70f0Sopenharmony_ci		return &alsa_lisp_t;
1864d5ac70f0Sopenharmony_ci	}
1865d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1866d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
1867d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1868d5ac70f0Sopenharmony_ci}
1869d5ac70f0Sopenharmony_ci
1870d5ac70f0Sopenharmony_ci/*
1871d5ac70f0Sopenharmony_ci * Syntax: (equal expr1 expr2)
1872d5ac70f0Sopenharmony_ci */
1873d5ac70f0Sopenharmony_cistatic struct alisp_object * F_equal(struct alisp_instance *instance, struct alisp_object * args)
1874d5ac70f0Sopenharmony_ci{
1875d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
1876d5ac70f0Sopenharmony_ci
1877d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
1878d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
1879d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
1880d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
1881d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1882d5ac70f0Sopenharmony_ci
1883d5ac70f0Sopenharmony_ci	if (equal(p1, p2)) {
1884d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
1885d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
1886d5ac70f0Sopenharmony_ci		return &alsa_lisp_t;
1887d5ac70f0Sopenharmony_ci	}
1888d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
1889d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
1890d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1891d5ac70f0Sopenharmony_ci}
1892d5ac70f0Sopenharmony_ci
1893d5ac70f0Sopenharmony_ci/*
1894d5ac70f0Sopenharmony_ci * Syntax: (quote expr)
1895d5ac70f0Sopenharmony_ci */
1896d5ac70f0Sopenharmony_cistatic struct alisp_object * F_quote(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args)
1897d5ac70f0Sopenharmony_ci{
1898d5ac70f0Sopenharmony_ci	struct alisp_object *p = car(args);
1899d5ac70f0Sopenharmony_ci
1900d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
1901d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1902d5ac70f0Sopenharmony_ci	return p;
1903d5ac70f0Sopenharmony_ci}
1904d5ac70f0Sopenharmony_ci
1905d5ac70f0Sopenharmony_ci/*
1906d5ac70f0Sopenharmony_ci * Syntax: (and expr...)
1907d5ac70f0Sopenharmony_ci */
1908d5ac70f0Sopenharmony_cistatic struct alisp_object * F_and(struct alisp_instance *instance, struct alisp_object * args)
1909d5ac70f0Sopenharmony_ci{
1910d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1 = NULL, * n;
1911d5ac70f0Sopenharmony_ci
1912d5ac70f0Sopenharmony_ci	do {
1913d5ac70f0Sopenharmony_ci		if (p1)
1914d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1915d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
1916d5ac70f0Sopenharmony_ci		if (p1 == &alsa_lisp_nil) {
1917d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1918d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p));
1919d5ac70f0Sopenharmony_ci			delete_object(instance, p);
1920d5ac70f0Sopenharmony_ci			return &alsa_lisp_nil;
1921d5ac70f0Sopenharmony_ci		}
1922d5ac70f0Sopenharmony_ci		p = cdr(n = p);
1923d5ac70f0Sopenharmony_ci		delete_object(instance, n);
1924d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
1925d5ac70f0Sopenharmony_ci
1926d5ac70f0Sopenharmony_ci	return p1;
1927d5ac70f0Sopenharmony_ci}
1928d5ac70f0Sopenharmony_ci
1929d5ac70f0Sopenharmony_ci/*
1930d5ac70f0Sopenharmony_ci * Syntax: (or expr...)
1931d5ac70f0Sopenharmony_ci */
1932d5ac70f0Sopenharmony_cistatic struct alisp_object * F_or(struct alisp_instance *instance, struct alisp_object * args)
1933d5ac70f0Sopenharmony_ci{
1934d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1 = NULL, * n;
1935d5ac70f0Sopenharmony_ci
1936d5ac70f0Sopenharmony_ci	do {
1937d5ac70f0Sopenharmony_ci		if (p1)
1938d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
1939d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
1940d5ac70f0Sopenharmony_ci		if (p1 != &alsa_lisp_nil) {
1941d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p));
1942d5ac70f0Sopenharmony_ci			delete_object(instance, p);
1943d5ac70f0Sopenharmony_ci			return p1;
1944d5ac70f0Sopenharmony_ci		}
1945d5ac70f0Sopenharmony_ci		p = cdr(n = p);
1946d5ac70f0Sopenharmony_ci		delete_object(instance, n);
1947d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
1948d5ac70f0Sopenharmony_ci
1949d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
1950d5ac70f0Sopenharmony_ci}
1951d5ac70f0Sopenharmony_ci
1952d5ac70f0Sopenharmony_ci/*
1953d5ac70f0Sopenharmony_ci * Syntax: (not expr)
1954d5ac70f0Sopenharmony_ci * Syntax: (null expr)
1955d5ac70f0Sopenharmony_ci */
1956d5ac70f0Sopenharmony_cistatic struct alisp_object * F_not(struct alisp_instance *instance, struct alisp_object * args)
1957d5ac70f0Sopenharmony_ci{
1958d5ac70f0Sopenharmony_ci	struct alisp_object * p = eval(instance, car(args));
1959d5ac70f0Sopenharmony_ci
1960d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
1961d5ac70f0Sopenharmony_ci	delete_object(instance, args);
1962d5ac70f0Sopenharmony_ci	if (p != &alsa_lisp_nil) {
1963d5ac70f0Sopenharmony_ci		delete_tree(instance, p);
1964d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
1965d5ac70f0Sopenharmony_ci	}
1966d5ac70f0Sopenharmony_ci
1967d5ac70f0Sopenharmony_ci	delete_tree(instance, p);
1968d5ac70f0Sopenharmony_ci	return &alsa_lisp_t;
1969d5ac70f0Sopenharmony_ci}
1970d5ac70f0Sopenharmony_ci
1971d5ac70f0Sopenharmony_ci/*
1972d5ac70f0Sopenharmony_ci * Syntax: (cond (expr1 [expr2])...)
1973d5ac70f0Sopenharmony_ci */
1974d5ac70f0Sopenharmony_cistatic struct alisp_object * F_cond(struct alisp_instance *instance, struct alisp_object * args)
1975d5ac70f0Sopenharmony_ci{
1976d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1, * p2, * p3;
1977d5ac70f0Sopenharmony_ci
1978d5ac70f0Sopenharmony_ci	do {
1979d5ac70f0Sopenharmony_ci		p1 = car(p);
1980d5ac70f0Sopenharmony_ci		if ((p2 = eval(instance, car(p1))) != &alsa_lisp_nil) {
1981d5ac70f0Sopenharmony_ci			p3 = cdr(p1);
1982d5ac70f0Sopenharmony_ci			delete_object(instance, p1);
1983d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p));
1984d5ac70f0Sopenharmony_ci			delete_object(instance, p);
1985d5ac70f0Sopenharmony_ci			if (p3 != &alsa_lisp_nil) {
1986d5ac70f0Sopenharmony_ci				delete_tree(instance, p2);
1987d5ac70f0Sopenharmony_ci				return F_progn(instance, p3);
1988d5ac70f0Sopenharmony_ci			} else {
1989d5ac70f0Sopenharmony_ci				delete_tree(instance, p3);
1990d5ac70f0Sopenharmony_ci				return p2;
1991d5ac70f0Sopenharmony_ci			}
1992d5ac70f0Sopenharmony_ci		} else {
1993d5ac70f0Sopenharmony_ci			delete_tree(instance, p2);
1994d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p1));
1995d5ac70f0Sopenharmony_ci			delete_object(instance, p1);
1996d5ac70f0Sopenharmony_ci		}
1997d5ac70f0Sopenharmony_ci		p = cdr(p2 = p);
1998d5ac70f0Sopenharmony_ci		delete_object(instance, p2);
1999d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
2000d5ac70f0Sopenharmony_ci
2001d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2002d5ac70f0Sopenharmony_ci}
2003d5ac70f0Sopenharmony_ci
2004d5ac70f0Sopenharmony_ci/*
2005d5ac70f0Sopenharmony_ci * Syntax: (if expr then-expr else-expr...)
2006d5ac70f0Sopenharmony_ci */
2007d5ac70f0Sopenharmony_cistatic struct alisp_object * F_if(struct alisp_instance *instance, struct alisp_object * args)
2008d5ac70f0Sopenharmony_ci{
2009d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2, * p3;
2010d5ac70f0Sopenharmony_ci
2011d5ac70f0Sopenharmony_ci	p1 = car(args);
2012d5ac70f0Sopenharmony_ci	p2 = car(cdr(args));
2013d5ac70f0Sopenharmony_ci	p3 = cdr(cdr(args));
2014d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
2015d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2016d5ac70f0Sopenharmony_ci
2017d5ac70f0Sopenharmony_ci	p1 = eval(instance, p1);
2018d5ac70f0Sopenharmony_ci	if (p1 != &alsa_lisp_nil) {
2019d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2020d5ac70f0Sopenharmony_ci		delete_tree(instance, p3);
2021d5ac70f0Sopenharmony_ci		return eval(instance, p2);
2022d5ac70f0Sopenharmony_ci	}
2023d5ac70f0Sopenharmony_ci
2024d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2025d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
2026d5ac70f0Sopenharmony_ci	return F_progn(instance, p3);
2027d5ac70f0Sopenharmony_ci}
2028d5ac70f0Sopenharmony_ci
2029d5ac70f0Sopenharmony_ci/*
2030d5ac70f0Sopenharmony_ci * Syntax: (when expr then-expr...)
2031d5ac70f0Sopenharmony_ci */
2032d5ac70f0Sopenharmony_cistatic struct alisp_object * F_when(struct alisp_instance *instance, struct alisp_object * args)
2033d5ac70f0Sopenharmony_ci{
2034d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
2035d5ac70f0Sopenharmony_ci
2036d5ac70f0Sopenharmony_ci	p1 = car(args);
2037d5ac70f0Sopenharmony_ci	p2 = cdr(args);
2038d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2039d5ac70f0Sopenharmony_ci	if ((p1 = eval(instance, p1)) != &alsa_lisp_nil) {
2040d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2041d5ac70f0Sopenharmony_ci		return F_progn(instance, p2);
2042d5ac70f0Sopenharmony_ci	} else {
2043d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2044d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
2045d5ac70f0Sopenharmony_ci	}
2046d5ac70f0Sopenharmony_ci
2047d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2048d5ac70f0Sopenharmony_ci}
2049d5ac70f0Sopenharmony_ci
2050d5ac70f0Sopenharmony_ci/*
2051d5ac70f0Sopenharmony_ci * Syntax: (unless expr else-expr...)
2052d5ac70f0Sopenharmony_ci */
2053d5ac70f0Sopenharmony_cistatic struct alisp_object * F_unless(struct alisp_instance *instance, struct alisp_object * args)
2054d5ac70f0Sopenharmony_ci{
2055d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
2056d5ac70f0Sopenharmony_ci
2057d5ac70f0Sopenharmony_ci	p1 = car(args);
2058d5ac70f0Sopenharmony_ci	p2 = cdr(args);
2059d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2060d5ac70f0Sopenharmony_ci	if ((p1 = eval(instance, p1)) == &alsa_lisp_nil) {
2061d5ac70f0Sopenharmony_ci		return F_progn(instance, p2);
2062d5ac70f0Sopenharmony_ci	} else {
2063d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2064d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
2065d5ac70f0Sopenharmony_ci	}
2066d5ac70f0Sopenharmony_ci
2067d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2068d5ac70f0Sopenharmony_ci}
2069d5ac70f0Sopenharmony_ci
2070d5ac70f0Sopenharmony_ci/*
2071d5ac70f0Sopenharmony_ci * Syntax: (while expr exprs...)
2072d5ac70f0Sopenharmony_ci */
2073d5ac70f0Sopenharmony_cistatic struct alisp_object * F_while(struct alisp_instance *instance, struct alisp_object * args)
2074d5ac70f0Sopenharmony_ci{
2075d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2, * p3;
2076d5ac70f0Sopenharmony_ci
2077d5ac70f0Sopenharmony_ci	p1 = car(args);
2078d5ac70f0Sopenharmony_ci	p2 = cdr(args);
2079d5ac70f0Sopenharmony_ci
2080d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2081d5ac70f0Sopenharmony_ci	while (1) {
2082d5ac70f0Sopenharmony_ci		incref_tree(instance, p1);
2083d5ac70f0Sopenharmony_ci		if ((p3 = eval(instance, p1)) == &alsa_lisp_nil)
2084d5ac70f0Sopenharmony_ci			break;
2085d5ac70f0Sopenharmony_ci		delete_tree(instance, p3);
2086d5ac70f0Sopenharmony_ci		incref_tree(instance, p2);
2087d5ac70f0Sopenharmony_ci		delete_tree(instance, F_progn(instance, p2));
2088d5ac70f0Sopenharmony_ci	}
2089d5ac70f0Sopenharmony_ci
2090d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2091d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
2092d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2093d5ac70f0Sopenharmony_ci}
2094d5ac70f0Sopenharmony_ci
2095d5ac70f0Sopenharmony_ci/*
2096d5ac70f0Sopenharmony_ci * Syntax: (progn expr...)
2097d5ac70f0Sopenharmony_ci */
2098d5ac70f0Sopenharmony_cistatic struct alisp_object * F_progn(struct alisp_instance *instance, struct alisp_object * args)
2099d5ac70f0Sopenharmony_ci{
2100d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1 = NULL, * n;
2101d5ac70f0Sopenharmony_ci
2102d5ac70f0Sopenharmony_ci	do {
2103d5ac70f0Sopenharmony_ci		if (p1)
2104d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2105d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
2106d5ac70f0Sopenharmony_ci		n = cdr(p);
2107d5ac70f0Sopenharmony_ci		delete_object(instance, p);
2108d5ac70f0Sopenharmony_ci		p = n;
2109d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
2110d5ac70f0Sopenharmony_ci
2111d5ac70f0Sopenharmony_ci	return p1;
2112d5ac70f0Sopenharmony_ci}
2113d5ac70f0Sopenharmony_ci
2114d5ac70f0Sopenharmony_ci/*
2115d5ac70f0Sopenharmony_ci * Syntax: (prog1 expr...)
2116d5ac70f0Sopenharmony_ci */
2117d5ac70f0Sopenharmony_cistatic struct alisp_object * F_prog1(struct alisp_instance *instance, struct alisp_object * args)
2118d5ac70f0Sopenharmony_ci{
2119d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * first = NULL, * p1;
2120d5ac70f0Sopenharmony_ci
2121d5ac70f0Sopenharmony_ci	do {
2122d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
2123d5ac70f0Sopenharmony_ci		if (first == NULL)
2124d5ac70f0Sopenharmony_ci			first = p1;
2125d5ac70f0Sopenharmony_ci		else
2126d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2127d5ac70f0Sopenharmony_ci		p1 = cdr(p);
2128d5ac70f0Sopenharmony_ci		delete_object(instance, p);
2129d5ac70f0Sopenharmony_ci		p = p1;
2130d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
2131d5ac70f0Sopenharmony_ci
2132d5ac70f0Sopenharmony_ci	if (first == NULL)
2133d5ac70f0Sopenharmony_ci		first = &alsa_lisp_nil;
2134d5ac70f0Sopenharmony_ci
2135d5ac70f0Sopenharmony_ci	return first;
2136d5ac70f0Sopenharmony_ci}
2137d5ac70f0Sopenharmony_ci
2138d5ac70f0Sopenharmony_ci/*
2139d5ac70f0Sopenharmony_ci * Syntax: (prog2 expr...)
2140d5ac70f0Sopenharmony_ci */
2141d5ac70f0Sopenharmony_cistatic struct alisp_object * F_prog2(struct alisp_instance *instance, struct alisp_object * args)
2142d5ac70f0Sopenharmony_ci{
2143d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * second = NULL, * p1;
2144d5ac70f0Sopenharmony_ci	int i = 0;
2145d5ac70f0Sopenharmony_ci
2146d5ac70f0Sopenharmony_ci	do {
2147d5ac70f0Sopenharmony_ci		++i;
2148d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
2149d5ac70f0Sopenharmony_ci		if (i == 2)
2150d5ac70f0Sopenharmony_ci			second = p1;
2151d5ac70f0Sopenharmony_ci		else
2152d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2153d5ac70f0Sopenharmony_ci		p1 = cdr(p);
2154d5ac70f0Sopenharmony_ci		delete_object(instance, p);
2155d5ac70f0Sopenharmony_ci		p = p1;
2156d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
2157d5ac70f0Sopenharmony_ci
2158d5ac70f0Sopenharmony_ci	if (second == NULL)
2159d5ac70f0Sopenharmony_ci		second = &alsa_lisp_nil;
2160d5ac70f0Sopenharmony_ci
2161d5ac70f0Sopenharmony_ci	return second;
2162d5ac70f0Sopenharmony_ci}
2163d5ac70f0Sopenharmony_ci
2164d5ac70f0Sopenharmony_ci/*
2165d5ac70f0Sopenharmony_ci * Syntax: (set name value)
2166d5ac70f0Sopenharmony_ci */
2167d5ac70f0Sopenharmony_cistatic struct alisp_object * F_set(struct alisp_instance *instance, struct alisp_object * args)
2168d5ac70f0Sopenharmony_ci{
2169d5ac70f0Sopenharmony_ci	struct alisp_object * p1 = eval(instance, car(args)),
2170d5ac70f0Sopenharmony_ci			    * p2 = eval(instance, car(cdr(args)));
2171d5ac70f0Sopenharmony_ci
2172d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
2173d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
2174d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2175d5ac70f0Sopenharmony_ci	if (!check_set_object(instance, p1)) {
2176d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
2177d5ac70f0Sopenharmony_ci		p2 = &alsa_lisp_nil;
2178d5ac70f0Sopenharmony_ci	} else {
2179d5ac70f0Sopenharmony_ci		if (set_object(instance, p1, p2) == NULL) {
2180d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2181d5ac70f0Sopenharmony_ci			delete_tree(instance, p2);
2182d5ac70f0Sopenharmony_ci			return NULL;
2183d5ac70f0Sopenharmony_ci		}
2184d5ac70f0Sopenharmony_ci	}
2185d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2186d5ac70f0Sopenharmony_ci	return incref_tree(instance, p2);
2187d5ac70f0Sopenharmony_ci}
2188d5ac70f0Sopenharmony_ci
2189d5ac70f0Sopenharmony_ci/*
2190d5ac70f0Sopenharmony_ci * Syntax: (unset name)
2191d5ac70f0Sopenharmony_ci */
2192d5ac70f0Sopenharmony_cistatic struct alisp_object * F_unset(struct alisp_instance *instance, struct alisp_object * args)
2193d5ac70f0Sopenharmony_ci{
2194d5ac70f0Sopenharmony_ci	struct alisp_object * p1 = eval(instance, car(args));
2195d5ac70f0Sopenharmony_ci
2196d5ac70f0Sopenharmony_ci	delete_tree(instance, unset_object(instance, p1));
2197d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
2198d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2199d5ac70f0Sopenharmony_ci	return p1;
2200d5ac70f0Sopenharmony_ci}
2201d5ac70f0Sopenharmony_ci
2202d5ac70f0Sopenharmony_ci/*
2203d5ac70f0Sopenharmony_ci * Syntax: (setq name value...)
2204d5ac70f0Sopenharmony_ci * Syntax: (setf name value...)
2205d5ac70f0Sopenharmony_ci * `name' is not evalled
2206d5ac70f0Sopenharmony_ci */
2207d5ac70f0Sopenharmony_cistatic struct alisp_object * F_setq(struct alisp_instance *instance, struct alisp_object * args)
2208d5ac70f0Sopenharmony_ci{
2209d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1, * p2 = NULL, *n;
2210d5ac70f0Sopenharmony_ci
2211d5ac70f0Sopenharmony_ci	do {
2212d5ac70f0Sopenharmony_ci		p1 = car(p);
2213d5ac70f0Sopenharmony_ci		p2 = eval(instance, car(cdr(p)));
2214d5ac70f0Sopenharmony_ci		n = cdr(cdr(p));
2215d5ac70f0Sopenharmony_ci		delete_object(instance, cdr(p));
2216d5ac70f0Sopenharmony_ci		delete_object(instance, p);
2217d5ac70f0Sopenharmony_ci		if (!check_set_object(instance, p1)) {
2218d5ac70f0Sopenharmony_ci			delete_tree(instance, p2);
2219d5ac70f0Sopenharmony_ci			p2 = &alsa_lisp_nil;
2220d5ac70f0Sopenharmony_ci		} else {
2221d5ac70f0Sopenharmony_ci			if (set_object(instance, p1, p2) == NULL) {
2222d5ac70f0Sopenharmony_ci				delete_tree(instance, p1);
2223d5ac70f0Sopenharmony_ci				delete_tree(instance, p2);
2224d5ac70f0Sopenharmony_ci				return NULL;
2225d5ac70f0Sopenharmony_ci			}
2226d5ac70f0Sopenharmony_ci		}
2227d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2228d5ac70f0Sopenharmony_ci		p = n;
2229d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
2230d5ac70f0Sopenharmony_ci
2231d5ac70f0Sopenharmony_ci	return incref_tree(instance, p2);
2232d5ac70f0Sopenharmony_ci}
2233d5ac70f0Sopenharmony_ci
2234d5ac70f0Sopenharmony_ci/*
2235d5ac70f0Sopenharmony_ci * Syntax: (unsetq name...)
2236d5ac70f0Sopenharmony_ci * Syntax: (unsetf name...)
2237d5ac70f0Sopenharmony_ci * `name' is not evalled
2238d5ac70f0Sopenharmony_ci */
2239d5ac70f0Sopenharmony_cistatic struct alisp_object * F_unsetq(struct alisp_instance *instance, struct alisp_object * args)
2240d5ac70f0Sopenharmony_ci{
2241d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1 = NULL, * n;
2242d5ac70f0Sopenharmony_ci
2243d5ac70f0Sopenharmony_ci	do {
2244d5ac70f0Sopenharmony_ci		if (p1)
2245d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2246d5ac70f0Sopenharmony_ci		p1 = unset_object(instance, car(p));
2247d5ac70f0Sopenharmony_ci		delete_tree(instance, car(p));
2248d5ac70f0Sopenharmony_ci		p = cdr(n = p);
2249d5ac70f0Sopenharmony_ci		delete_object(instance, n);
2250d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
2251d5ac70f0Sopenharmony_ci
2252d5ac70f0Sopenharmony_ci	return p1;
2253d5ac70f0Sopenharmony_ci}
2254d5ac70f0Sopenharmony_ci
2255d5ac70f0Sopenharmony_ci/*
2256d5ac70f0Sopenharmony_ci * Syntax: (defun name arglist expr...)
2257d5ac70f0Sopenharmony_ci * `name' is not evalled
2258d5ac70f0Sopenharmony_ci * `arglist' is not evalled
2259d5ac70f0Sopenharmony_ci */
2260d5ac70f0Sopenharmony_cistatic struct alisp_object * F_defun(struct alisp_instance *instance, struct alisp_object * args)
2261d5ac70f0Sopenharmony_ci{
2262d5ac70f0Sopenharmony_ci	struct alisp_object * p1 = car(args),
2263d5ac70f0Sopenharmony_ci			    * p2 = car(cdr(args)),
2264d5ac70f0Sopenharmony_ci			    * p3 = cdr(cdr(args));
2265d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr;
2266d5ac70f0Sopenharmony_ci
2267d5ac70f0Sopenharmony_ci	lexpr = new_object(instance, ALISP_OBJ_CONS);
2268d5ac70f0Sopenharmony_ci	if (lexpr) {
2269d5ac70f0Sopenharmony_ci		lexpr->value.c.car = new_identifier(instance, "lambda");
2270d5ac70f0Sopenharmony_ci		if (lexpr->value.c.car == NULL) {
2271d5ac70f0Sopenharmony_ci			delete_object(instance, lexpr);
2272d5ac70f0Sopenharmony_ci			delete_tree(instance, args);
2273d5ac70f0Sopenharmony_ci			return NULL;
2274d5ac70f0Sopenharmony_ci		}
2275d5ac70f0Sopenharmony_ci		if ((lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS)) == NULL) {
2276d5ac70f0Sopenharmony_ci			delete_object(instance, lexpr->value.c.car);
2277d5ac70f0Sopenharmony_ci			delete_object(instance, lexpr);
2278d5ac70f0Sopenharmony_ci			delete_tree(instance, args);
2279d5ac70f0Sopenharmony_ci			return NULL;
2280d5ac70f0Sopenharmony_ci		}
2281d5ac70f0Sopenharmony_ci		lexpr->value.c.cdr->value.c.car = p2;
2282d5ac70f0Sopenharmony_ci		lexpr->value.c.cdr->value.c.cdr = p3;
2283d5ac70f0Sopenharmony_ci		delete_object(instance, cdr(args));
2284d5ac70f0Sopenharmony_ci		delete_object(instance, args);
2285d5ac70f0Sopenharmony_ci		if (set_object(instance, p1, lexpr) == NULL) {
2286d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2287d5ac70f0Sopenharmony_ci			delete_tree(instance, lexpr);
2288d5ac70f0Sopenharmony_ci			return NULL;
2289d5ac70f0Sopenharmony_ci		}
2290d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2291d5ac70f0Sopenharmony_ci	} else {
2292d5ac70f0Sopenharmony_ci		delete_tree(instance, args);
2293d5ac70f0Sopenharmony_ci	}
2294d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2295d5ac70f0Sopenharmony_ci}
2296d5ac70f0Sopenharmony_ci
2297d5ac70f0Sopenharmony_cistatic struct alisp_object * eval_func(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * args)
2298d5ac70f0Sopenharmony_ci{
2299d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2, * p3, * p4;
2300d5ac70f0Sopenharmony_ci	struct alisp_object ** eval_objs, ** save_objs;
2301d5ac70f0Sopenharmony_ci	int i;
2302d5ac70f0Sopenharmony_ci
2303d5ac70f0Sopenharmony_ci	p1 = car(p);
2304d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER) &&
2305d5ac70f0Sopenharmony_ci	    !strcmp(p1->value.s, "lambda")) {
2306d5ac70f0Sopenharmony_ci		p2 = car(cdr(p));
2307d5ac70f0Sopenharmony_ci		p3 = args;
2308d5ac70f0Sopenharmony_ci
2309d5ac70f0Sopenharmony_ci		if ((i = count_list(p2)) != count_list(p3)) {
2310d5ac70f0Sopenharmony_ci			lisp_warn(instance, "wrong number of parameters");
2311d5ac70f0Sopenharmony_ci			goto _delete;
2312d5ac70f0Sopenharmony_ci		}
2313d5ac70f0Sopenharmony_ci
2314d5ac70f0Sopenharmony_ci		eval_objs = malloc(2 * i * sizeof(struct alisp_object *));
2315d5ac70f0Sopenharmony_ci		if (eval_objs == NULL) {
2316d5ac70f0Sopenharmony_ci			nomem();
2317d5ac70f0Sopenharmony_ci			goto _delete;
2318d5ac70f0Sopenharmony_ci		}
2319d5ac70f0Sopenharmony_ci		save_objs = eval_objs + i;
2320d5ac70f0Sopenharmony_ci
2321d5ac70f0Sopenharmony_ci		/*
2322d5ac70f0Sopenharmony_ci		 * Save the new variable values.
2323d5ac70f0Sopenharmony_ci		 */
2324d5ac70f0Sopenharmony_ci		i = 0;
2325d5ac70f0Sopenharmony_ci		while (p3 != &alsa_lisp_nil) {
2326d5ac70f0Sopenharmony_ci			eval_objs[i++] = eval(instance, car(p3));
2327d5ac70f0Sopenharmony_ci			p3 = cdr(p4 = p3);
2328d5ac70f0Sopenharmony_ci			delete_object(instance, p4);
2329d5ac70f0Sopenharmony_ci		}
2330d5ac70f0Sopenharmony_ci
2331d5ac70f0Sopenharmony_ci		/*
2332d5ac70f0Sopenharmony_ci		 * Save the old variable values and set the new ones.
2333d5ac70f0Sopenharmony_ci		 */
2334d5ac70f0Sopenharmony_ci		i = 0;
2335d5ac70f0Sopenharmony_ci		while (p2 != &alsa_lisp_nil) {
2336d5ac70f0Sopenharmony_ci			p3 = car(p2);
2337d5ac70f0Sopenharmony_ci			save_objs[i] = replace_object(instance, p3, eval_objs[i]);
2338d5ac70f0Sopenharmony_ci			if (save_objs[i] == NULL &&
2339d5ac70f0Sopenharmony_ci			    set_object_direct(instance, p3, eval_objs[i]) == NULL) {
2340d5ac70f0Sopenharmony_ci			    	p4 = NULL;
2341d5ac70f0Sopenharmony_ci				goto _end;
2342d5ac70f0Sopenharmony_ci			}
2343d5ac70f0Sopenharmony_ci			p2 = cdr(p2);
2344d5ac70f0Sopenharmony_ci			++i;
2345d5ac70f0Sopenharmony_ci		}
2346d5ac70f0Sopenharmony_ci
2347d5ac70f0Sopenharmony_ci		p4 = F_progn(instance, cdr(incref_tree(instance, p3 = cdr(p))));
2348d5ac70f0Sopenharmony_ci
2349d5ac70f0Sopenharmony_ci		/*
2350d5ac70f0Sopenharmony_ci		 * Restore the old variable values.
2351d5ac70f0Sopenharmony_ci		 */
2352d5ac70f0Sopenharmony_ci		p2 = car(p3);
2353d5ac70f0Sopenharmony_ci		delete_object(instance, p3);
2354d5ac70f0Sopenharmony_ci		i = 0;
2355d5ac70f0Sopenharmony_ci		while (p2 != &alsa_lisp_nil) {
2356d5ac70f0Sopenharmony_ci			p3 = car(p2);
2357d5ac70f0Sopenharmony_ci			if (save_objs[i] == NULL) {
2358d5ac70f0Sopenharmony_ci				p3 = unset_object(instance, p3);
2359d5ac70f0Sopenharmony_ci			} else {
2360d5ac70f0Sopenharmony_ci				p3 = replace_object(instance, p3, save_objs[i]);
2361d5ac70f0Sopenharmony_ci			}
2362d5ac70f0Sopenharmony_ci			i++;
2363d5ac70f0Sopenharmony_ci			delete_tree(instance, p3);
2364d5ac70f0Sopenharmony_ci			delete_tree(instance, car(p2));
2365d5ac70f0Sopenharmony_ci			p2 = cdr(p3 = p2);
2366d5ac70f0Sopenharmony_ci			delete_object(instance, p3);
2367d5ac70f0Sopenharmony_ci		}
2368d5ac70f0Sopenharmony_ci
2369d5ac70f0Sopenharmony_ci               _end:
2370d5ac70f0Sopenharmony_ci		free(eval_objs);
2371d5ac70f0Sopenharmony_ci
2372d5ac70f0Sopenharmony_ci		return p4;
2373d5ac70f0Sopenharmony_ci	} else {
2374d5ac70f0Sopenharmony_ci	       _delete:
2375d5ac70f0Sopenharmony_ci		delete_tree(instance, args);
2376d5ac70f0Sopenharmony_ci	}
2377d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2378d5ac70f0Sopenharmony_ci}
2379d5ac70f0Sopenharmony_ci
2380d5ac70f0Sopenharmony_cistruct alisp_object * F_gc(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args ATTRIBUTE_UNUSED)
2381d5ac70f0Sopenharmony_ci{
2382d5ac70f0Sopenharmony_ci	/* improved: no more traditional gc */
2383d5ac70f0Sopenharmony_ci	return &alsa_lisp_t;
2384d5ac70f0Sopenharmony_ci}
2385d5ac70f0Sopenharmony_ci
2386d5ac70f0Sopenharmony_ci/*
2387d5ac70f0Sopenharmony_ci * Syntax: (path what)
2388d5ac70f0Sopenharmony_ci * what is string ('data')
2389d5ac70f0Sopenharmony_ci */
2390d5ac70f0Sopenharmony_cistruct alisp_object * F_path(struct alisp_instance *instance, struct alisp_object * args)
2391d5ac70f0Sopenharmony_ci{
2392d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
2393d5ac70f0Sopenharmony_ci
2394d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
2395d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
2396d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2397d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p1, ALISP_OBJ_STRING)) {
2398d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2399d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
2400d5ac70f0Sopenharmony_ci	}
2401d5ac70f0Sopenharmony_ci	if (!strcmp(p1->value.s, "data")) {
2402d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2403d5ac70f0Sopenharmony_ci		return new_string(instance, snd_config_topdir());
2404d5ac70f0Sopenharmony_ci	}
2405d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2406d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2407d5ac70f0Sopenharmony_ci}
2408d5ac70f0Sopenharmony_ci
2409d5ac70f0Sopenharmony_ci/*
2410d5ac70f0Sopenharmony_ci * Syntax: (include filename...)
2411d5ac70f0Sopenharmony_ci */
2412d5ac70f0Sopenharmony_cistruct alisp_object * F_include(struct alisp_instance *instance, struct alisp_object * args)
2413d5ac70f0Sopenharmony_ci{
2414d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1;
2415d5ac70f0Sopenharmony_ci	int res = -ENOENT;
2416d5ac70f0Sopenharmony_ci
2417d5ac70f0Sopenharmony_ci	do {
2418d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
2419d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_STRING))
2420d5ac70f0Sopenharmony_ci			res = alisp_include_file(instance, p1->value.s);
2421d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2422d5ac70f0Sopenharmony_ci		p = cdr(p1 = p);
2423d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
2424d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
2425d5ac70f0Sopenharmony_ci
2426d5ac70f0Sopenharmony_ci	return new_integer(instance, res);
2427d5ac70f0Sopenharmony_ci}
2428d5ac70f0Sopenharmony_ci
2429d5ac70f0Sopenharmony_ci/*
2430d5ac70f0Sopenharmony_ci * Syntax: (string-to-integer value)
2431d5ac70f0Sopenharmony_ci * 'value' can be integer or float type
2432d5ac70f0Sopenharmony_ci */
2433d5ac70f0Sopenharmony_cistruct alisp_object * F_string_to_integer(struct alisp_instance *instance, struct alisp_object * args)
2434d5ac70f0Sopenharmony_ci{
2435d5ac70f0Sopenharmony_ci	struct alisp_object * p = eval(instance, car(args)), * p1;
2436d5ac70f0Sopenharmony_ci
2437d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
2438d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2439d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_INTEGER))
2440d5ac70f0Sopenharmony_ci		return p;
2441d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
2442d5ac70f0Sopenharmony_ci		p1 = new_integer(instance, floor(p->value.f));
2443d5ac70f0Sopenharmony_ci	} else {
2444d5ac70f0Sopenharmony_ci		lisp_warn(instance, "expected an integer or float for integer conversion");
2445d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2446d5ac70f0Sopenharmony_ci	}
2447d5ac70f0Sopenharmony_ci	delete_tree(instance, p);
2448d5ac70f0Sopenharmony_ci	return p1;
2449d5ac70f0Sopenharmony_ci}
2450d5ac70f0Sopenharmony_ci
2451d5ac70f0Sopenharmony_ci/*
2452d5ac70f0Sopenharmony_ci * Syntax: (string-to-float value)
2453d5ac70f0Sopenharmony_ci * 'value' can be integer or float type
2454d5ac70f0Sopenharmony_ci */
2455d5ac70f0Sopenharmony_cistruct alisp_object * F_string_to_float(struct alisp_instance *instance, struct alisp_object * args)
2456d5ac70f0Sopenharmony_ci{
2457d5ac70f0Sopenharmony_ci	struct alisp_object * p = eval(instance, car(args)), * p1;
2458d5ac70f0Sopenharmony_ci
2459d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
2460d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2461d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_FLOAT))
2462d5ac70f0Sopenharmony_ci		return p;
2463d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
2464d5ac70f0Sopenharmony_ci		p1 = new_float(instance, p->value.i);
2465d5ac70f0Sopenharmony_ci	} else {
2466d5ac70f0Sopenharmony_ci		lisp_warn(instance, "expected an integer or float for integer conversion");
2467d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2468d5ac70f0Sopenharmony_ci	}
2469d5ac70f0Sopenharmony_ci	delete_tree(instance, p);
2470d5ac70f0Sopenharmony_ci	return p1;
2471d5ac70f0Sopenharmony_ci}
2472d5ac70f0Sopenharmony_ci
2473d5ac70f0Sopenharmony_cistatic int append_to_string(char **s, int *len, char *from, int size)
2474d5ac70f0Sopenharmony_ci{
2475d5ac70f0Sopenharmony_ci	if (*len == 0) {
2476d5ac70f0Sopenharmony_ci		*s = malloc(*len = size + 1);
2477d5ac70f0Sopenharmony_ci		if (*s == NULL) {
2478d5ac70f0Sopenharmony_ci			nomem();
2479d5ac70f0Sopenharmony_ci			return -ENOMEM;
2480d5ac70f0Sopenharmony_ci		}
2481d5ac70f0Sopenharmony_ci		memcpy(*s, from, size);
2482d5ac70f0Sopenharmony_ci	} else {
2483d5ac70f0Sopenharmony_ci		*len += size;
2484d5ac70f0Sopenharmony_ci		*s = realloc(*s, *len);
2485d5ac70f0Sopenharmony_ci		if (*s == NULL) {
2486d5ac70f0Sopenharmony_ci			nomem();
2487d5ac70f0Sopenharmony_ci			return -ENOMEM;
2488d5ac70f0Sopenharmony_ci		}
2489d5ac70f0Sopenharmony_ci		memcpy(*s + strlen(*s), from, size);
2490d5ac70f0Sopenharmony_ci	}
2491d5ac70f0Sopenharmony_ci	(*s)[*len - 1] = '\0';
2492d5ac70f0Sopenharmony_ci	return 0;
2493d5ac70f0Sopenharmony_ci}
2494d5ac70f0Sopenharmony_ci
2495d5ac70f0Sopenharmony_cistatic int format_parse_char(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
2496d5ac70f0Sopenharmony_ci{
2497d5ac70f0Sopenharmony_ci	char b;
2498d5ac70f0Sopenharmony_ci
2499d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
2500d5ac70f0Sopenharmony_ci		lisp_warn(instance, "format: expected integer\n");
2501d5ac70f0Sopenharmony_ci		return 0;
2502d5ac70f0Sopenharmony_ci	}
2503d5ac70f0Sopenharmony_ci	b = p->value.i;
2504d5ac70f0Sopenharmony_ci	return append_to_string(s, len, &b, 1);
2505d5ac70f0Sopenharmony_ci}
2506d5ac70f0Sopenharmony_ci
2507d5ac70f0Sopenharmony_cistatic int format_parse_integer(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
2508d5ac70f0Sopenharmony_ci{
2509d5ac70f0Sopenharmony_ci	int res;
2510d5ac70f0Sopenharmony_ci	char *s1;
2511d5ac70f0Sopenharmony_ci
2512d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
2513d5ac70f0Sopenharmony_ci	    !alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
2514d5ac70f0Sopenharmony_ci		lisp_warn(instance, "format: expected integer or float\n");
2515d5ac70f0Sopenharmony_ci		return 0;
2516d5ac70f0Sopenharmony_ci	}
2517d5ac70f0Sopenharmony_ci	s1 = malloc(64);
2518d5ac70f0Sopenharmony_ci	if (s1 == NULL) {
2519d5ac70f0Sopenharmony_ci		nomem();
2520d5ac70f0Sopenharmony_ci		return -ENOMEM;
2521d5ac70f0Sopenharmony_ci	}
2522d5ac70f0Sopenharmony_ci	sprintf(s1, "%li", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? (long)floor(p->value.f) : p->value.i);
2523d5ac70f0Sopenharmony_ci	res = append_to_string(s, len, s1, strlen(s1));
2524d5ac70f0Sopenharmony_ci	free(s1);
2525d5ac70f0Sopenharmony_ci	return res;
2526d5ac70f0Sopenharmony_ci}
2527d5ac70f0Sopenharmony_ci
2528d5ac70f0Sopenharmony_cistatic int format_parse_float(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
2529d5ac70f0Sopenharmony_ci{
2530d5ac70f0Sopenharmony_ci	int res;
2531d5ac70f0Sopenharmony_ci	char *s1;
2532d5ac70f0Sopenharmony_ci
2533d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
2534d5ac70f0Sopenharmony_ci	    !alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
2535d5ac70f0Sopenharmony_ci		lisp_warn(instance, "format: expected integer or float\n");
2536d5ac70f0Sopenharmony_ci		return 0;
2537d5ac70f0Sopenharmony_ci	}
2538d5ac70f0Sopenharmony_ci	s1 = malloc(64);
2539d5ac70f0Sopenharmony_ci	if (s1 == NULL) {
2540d5ac70f0Sopenharmony_ci		nomem();
2541d5ac70f0Sopenharmony_ci		return -ENOMEM;
2542d5ac70f0Sopenharmony_ci	}
2543d5ac70f0Sopenharmony_ci	sprintf(s1, "%f", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? p->value.f : (double)p->value.i);
2544d5ac70f0Sopenharmony_ci	res = append_to_string(s, len, s1, strlen(s1));
2545d5ac70f0Sopenharmony_ci	free(s1);
2546d5ac70f0Sopenharmony_ci	return res;
2547d5ac70f0Sopenharmony_ci}
2548d5ac70f0Sopenharmony_ci
2549d5ac70f0Sopenharmony_cistatic int format_parse_string(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
2550d5ac70f0Sopenharmony_ci{
2551d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
2552d5ac70f0Sopenharmony_ci		lisp_warn(instance, "format: expected string\n");
2553d5ac70f0Sopenharmony_ci		return 0;
2554d5ac70f0Sopenharmony_ci	}
2555d5ac70f0Sopenharmony_ci	return append_to_string(s, len, p->value.s, strlen(p->value.s));
2556d5ac70f0Sopenharmony_ci}
2557d5ac70f0Sopenharmony_ci
2558d5ac70f0Sopenharmony_ci/*
2559d5ac70f0Sopenharmony_ci * Syntax: (format format value...)
2560d5ac70f0Sopenharmony_ci * 'format' is C-like format string
2561d5ac70f0Sopenharmony_ci */
2562d5ac70f0Sopenharmony_cistruct alisp_object * F_format(struct alisp_instance *instance, struct alisp_object * args)
2563d5ac70f0Sopenharmony_ci{
2564d5ac70f0Sopenharmony_ci	struct alisp_object * p = eval(instance, car(args)), * p1 = cdr(args), * n;
2565d5ac70f0Sopenharmony_ci	char *s, *s1, *s2;
2566d5ac70f0Sopenharmony_ci	int len;
2567d5ac70f0Sopenharmony_ci
2568d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2569d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
2570d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2571d5ac70f0Sopenharmony_ci		delete_tree(instance, p);
2572d5ac70f0Sopenharmony_ci		lisp_warn(instance, "format: expected an format string");
2573d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
2574d5ac70f0Sopenharmony_ci	}
2575d5ac70f0Sopenharmony_ci	s = p->value.s;
2576d5ac70f0Sopenharmony_ci	s1 = NULL;
2577d5ac70f0Sopenharmony_ci	len = 0;
2578d5ac70f0Sopenharmony_ci	n = eval(instance, car(p1));
2579d5ac70f0Sopenharmony_ci	do {
2580d5ac70f0Sopenharmony_ci		while (1) {
2581d5ac70f0Sopenharmony_ci			s2 = s;
2582d5ac70f0Sopenharmony_ci			while (*s2 && *s2 != '%')
2583d5ac70f0Sopenharmony_ci				s2++;
2584d5ac70f0Sopenharmony_ci			if (s2 != s) {
2585d5ac70f0Sopenharmony_ci				if (append_to_string(&s1, &len, s, s2 - s) < 0) {
2586d5ac70f0Sopenharmony_ci				      __error:
2587d5ac70f0Sopenharmony_ci					delete_tree(instance, n);
2588d5ac70f0Sopenharmony_ci					delete_tree(instance, cdr(p1));
2589d5ac70f0Sopenharmony_ci					delete_object(instance, p1);
2590d5ac70f0Sopenharmony_ci					delete_tree(instance, p);
2591d5ac70f0Sopenharmony_ci					return NULL;
2592d5ac70f0Sopenharmony_ci				}
2593d5ac70f0Sopenharmony_ci			}
2594d5ac70f0Sopenharmony_ci			if (*s2 == '%')
2595d5ac70f0Sopenharmony_ci				s2++;
2596d5ac70f0Sopenharmony_ci			switch (*s2) {
2597d5ac70f0Sopenharmony_ci			case '%':
2598d5ac70f0Sopenharmony_ci				if (append_to_string(&s1, &len, s2, 1) < 0)
2599d5ac70f0Sopenharmony_ci					goto __error;
2600d5ac70f0Sopenharmony_ci				s = s2 + 1;
2601d5ac70f0Sopenharmony_ci				break;
2602d5ac70f0Sopenharmony_ci			case 'c':
2603d5ac70f0Sopenharmony_ci				if (format_parse_char(instance, &s1, &len, n) < 0)
2604d5ac70f0Sopenharmony_ci					goto __error;
2605d5ac70f0Sopenharmony_ci				s = s2 + 1;
2606d5ac70f0Sopenharmony_ci				goto __next;
2607d5ac70f0Sopenharmony_ci			case 'd':
2608d5ac70f0Sopenharmony_ci			case 'i':
2609d5ac70f0Sopenharmony_ci				if (format_parse_integer(instance, &s1, &len, n) < 0)
2610d5ac70f0Sopenharmony_ci					goto __error;
2611d5ac70f0Sopenharmony_ci				s = s2 + 1;
2612d5ac70f0Sopenharmony_ci				goto __next;
2613d5ac70f0Sopenharmony_ci			case 'f':
2614d5ac70f0Sopenharmony_ci				if (format_parse_float(instance, &s1, &len, n) < 0)
2615d5ac70f0Sopenharmony_ci					goto __error;
2616d5ac70f0Sopenharmony_ci				s = s2 + 1;
2617d5ac70f0Sopenharmony_ci				goto __next;
2618d5ac70f0Sopenharmony_ci			case 's':
2619d5ac70f0Sopenharmony_ci				if (format_parse_string(instance, &s1, &len, n) < 0)
2620d5ac70f0Sopenharmony_ci					goto __error;
2621d5ac70f0Sopenharmony_ci				s = s2 + 1;
2622d5ac70f0Sopenharmony_ci				goto __next;
2623d5ac70f0Sopenharmony_ci			case '\0':
2624d5ac70f0Sopenharmony_ci				goto __end;
2625d5ac70f0Sopenharmony_ci			default:
2626d5ac70f0Sopenharmony_ci				lisp_warn(instance, "unknown format char '%c'", *s2);
2627d5ac70f0Sopenharmony_ci				s = s2 + 1;
2628d5ac70f0Sopenharmony_ci				goto __next;
2629d5ac70f0Sopenharmony_ci			}
2630d5ac70f0Sopenharmony_ci		}
2631d5ac70f0Sopenharmony_ci	      __next:
2632d5ac70f0Sopenharmony_ci		delete_tree(instance, n);
2633d5ac70f0Sopenharmony_ci		p1 = cdr(n = p1);
2634d5ac70f0Sopenharmony_ci		delete_object(instance, n);
2635d5ac70f0Sopenharmony_ci		n = eval(instance, car(p1));
2636d5ac70f0Sopenharmony_ci	} while (*s);
2637d5ac70f0Sopenharmony_ci      __end:
2638d5ac70f0Sopenharmony_ci	delete_tree(instance, n);
2639d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(p1));
2640d5ac70f0Sopenharmony_ci	delete_object(instance, p1);
2641d5ac70f0Sopenharmony_ci	delete_tree(instance, p);
2642d5ac70f0Sopenharmony_ci	if (len > 0) {
2643d5ac70f0Sopenharmony_ci		p1 = new_string(instance, s1);
2644d5ac70f0Sopenharmony_ci		free(s1);
2645d5ac70f0Sopenharmony_ci	} else {
2646d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2647d5ac70f0Sopenharmony_ci	}
2648d5ac70f0Sopenharmony_ci	return p1;
2649d5ac70f0Sopenharmony_ci}
2650d5ac70f0Sopenharmony_ci
2651d5ac70f0Sopenharmony_ci/*
2652d5ac70f0Sopenharmony_ci * Syntax: (compare-strings str1 start1 end1 str2 start2 end2 /opt-case-insensitive)
2653d5ac70f0Sopenharmony_ci * 'str1' is first compared string
2654d5ac70f0Sopenharmony_ci * 'start1' is first char (0..)
2655d5ac70f0Sopenharmony_ci * 'end1' is last char (0..)
2656d5ac70f0Sopenharmony_ci * 'str2' is second compared string
2657d5ac70f0Sopenharmony_ci * 'start2' is first char (0..)
2658d5ac70f0Sopenharmony_ci * 'end2' is last char (0..)
2659d5ac70f0Sopenharmony_ci * /opt-case-insensitive true - case insensitive match
2660d5ac70f0Sopenharmony_ci */
2661d5ac70f0Sopenharmony_cistruct alisp_object * F_compare_strings(struct alisp_instance *instance, struct alisp_object * args)
2662d5ac70f0Sopenharmony_ci{
2663d5ac70f0Sopenharmony_ci	struct alisp_object * p1 = args, * n, * p[7];
2664d5ac70f0Sopenharmony_ci	char *s1, *s2;
2665d5ac70f0Sopenharmony_ci	int start1, end1, start2, end2;
2666d5ac70f0Sopenharmony_ci
2667d5ac70f0Sopenharmony_ci	for (start1 = 0; start1 < 7; start1++) {
2668d5ac70f0Sopenharmony_ci		p[start1] = eval(instance, car(p1));
2669d5ac70f0Sopenharmony_ci		p1 = cdr(n = p1);
2670d5ac70f0Sopenharmony_ci		delete_object(instance, n);
2671d5ac70f0Sopenharmony_ci	}
2672d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2673d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p[0], ALISP_OBJ_STRING)) {
2674d5ac70f0Sopenharmony_ci		lisp_warn(instance, "compare-strings: first argument must be string\n");
2675d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2676d5ac70f0Sopenharmony_ci		goto __err;
2677d5ac70f0Sopenharmony_ci	}
2678d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p[1], ALISP_OBJ_INTEGER)) {
2679d5ac70f0Sopenharmony_ci		lisp_warn(instance, "compare-strings: second argument must be integer\n");
2680d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2681d5ac70f0Sopenharmony_ci		goto __err;
2682d5ac70f0Sopenharmony_ci	}
2683d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p[2], ALISP_OBJ_INTEGER)) {
2684d5ac70f0Sopenharmony_ci		lisp_warn(instance, "compare-strings: third argument must be integer\n");
2685d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2686d5ac70f0Sopenharmony_ci		goto __err;
2687d5ac70f0Sopenharmony_ci	}
2688d5ac70f0Sopenharmony_ci	if (alisp_compare_type(p[3], ALISP_OBJ_STRING)) {
2689d5ac70f0Sopenharmony_ci		lisp_warn(instance, "compare-strings: fifth argument must be string\n");
2690d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2691d5ac70f0Sopenharmony_ci		goto __err;
2692d5ac70f0Sopenharmony_ci	}
2693d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p[4], ALISP_OBJ_NIL) &&
2694d5ac70f0Sopenharmony_ci	    !alisp_compare_type(p[4], ALISP_OBJ_INTEGER)) {
2695d5ac70f0Sopenharmony_ci		lisp_warn(instance, "compare-strings: fourth argument must be integer\n");
2696d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2697d5ac70f0Sopenharmony_ci		goto __err;
2698d5ac70f0Sopenharmony_ci	}
2699d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p[5], ALISP_OBJ_NIL) &&
2700d5ac70f0Sopenharmony_ci	    !alisp_compare_type(p[5], ALISP_OBJ_INTEGER)) {
2701d5ac70f0Sopenharmony_ci		lisp_warn(instance, "compare-strings: sixth argument must be integer\n");
2702d5ac70f0Sopenharmony_ci		p1 = &alsa_lisp_nil;
2703d5ac70f0Sopenharmony_ci		goto __err;
2704d5ac70f0Sopenharmony_ci	}
2705d5ac70f0Sopenharmony_ci	s1 = p[0]->value.s;
2706d5ac70f0Sopenharmony_ci	start1 = p[1]->value.i;
2707d5ac70f0Sopenharmony_ci	end1 = p[2]->value.i;
2708d5ac70f0Sopenharmony_ci	s2 = p[3]->value.s;
2709d5ac70f0Sopenharmony_ci	start2 = alisp_compare_type(p[4], ALISP_OBJ_NIL) ? 0 : p[4]->value.i;
2710d5ac70f0Sopenharmony_ci	end2 = alisp_compare_type(p[5], ALISP_OBJ_NIL) ? start2 + (end1 - start1) : p[5]->value.i;
2711d5ac70f0Sopenharmony_ci	if (start1 < 0 || start2 < 0 || end1 < 0 || end2 < 0 ||
2712d5ac70f0Sopenharmony_ci	    start1 >= (int)strlen(s1) || start2 >= (int)strlen(s2) ||
2713d5ac70f0Sopenharmony_ci	    (end1 - start1) != (end2 - start2)) {
2714d5ac70f0Sopenharmony_ci	    	p1 = &alsa_lisp_nil;
2715d5ac70f0Sopenharmony_ci	    	goto __err;
2716d5ac70f0Sopenharmony_ci	}
2717d5ac70f0Sopenharmony_ci	if (p[6] != &alsa_lisp_nil) {
2718d5ac70f0Sopenharmony_ci		while (start1 < end1) {
2719d5ac70f0Sopenharmony_ci			if (s1[start1] == '\0' ||
2720d5ac70f0Sopenharmony_ci			    s2[start2] == '\0' ||
2721d5ac70f0Sopenharmony_ci			    tolower(s1[start1]) != tolower(s2[start2])) {
2722d5ac70f0Sopenharmony_ci				p1 = &alsa_lisp_nil;
2723d5ac70f0Sopenharmony_ci				goto __err;
2724d5ac70f0Sopenharmony_ci			}
2725d5ac70f0Sopenharmony_ci			start1++;
2726d5ac70f0Sopenharmony_ci			start2++;
2727d5ac70f0Sopenharmony_ci		}
2728d5ac70f0Sopenharmony_ci	} else {
2729d5ac70f0Sopenharmony_ci		while (start1 < end1) {
2730d5ac70f0Sopenharmony_ci			if (s1[start1] == '\0' ||
2731d5ac70f0Sopenharmony_ci			    s2[start2] == '\0' ||
2732d5ac70f0Sopenharmony_ci			    s1[start1] != s2[start2]) {
2733d5ac70f0Sopenharmony_ci				p1 = &alsa_lisp_nil;
2734d5ac70f0Sopenharmony_ci				goto __err;
2735d5ac70f0Sopenharmony_ci			}
2736d5ac70f0Sopenharmony_ci			start1++;
2737d5ac70f0Sopenharmony_ci			start2++;
2738d5ac70f0Sopenharmony_ci		}
2739d5ac70f0Sopenharmony_ci	}
2740d5ac70f0Sopenharmony_ci	p1 = &alsa_lisp_t;
2741d5ac70f0Sopenharmony_ci
2742d5ac70f0Sopenharmony_ci      __err:
2743d5ac70f0Sopenharmony_ci      	for (start1 = 0; start1 < 7; start1++)
2744d5ac70f0Sopenharmony_ci      		delete_tree(instance, p[start1]);
2745d5ac70f0Sopenharmony_ci      	return p1;
2746d5ac70f0Sopenharmony_ci}
2747d5ac70f0Sopenharmony_ci
2748d5ac70f0Sopenharmony_ci/*
2749d5ac70f0Sopenharmony_ci *  Syntax: (assoc key alist)
2750d5ac70f0Sopenharmony_ci */
2751d5ac70f0Sopenharmony_cistruct alisp_object * F_assoc(struct alisp_instance *instance, struct alisp_object * args)
2752d5ac70f0Sopenharmony_ci{
2753d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2, * n;
2754d5ac70f0Sopenharmony_ci
2755d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
2756d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
2757d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
2758d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
2759d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2760d5ac70f0Sopenharmony_ci
2761d5ac70f0Sopenharmony_ci	do {
2762d5ac70f0Sopenharmony_ci		if (eq(p1, car(car(p2)))) {
2763d5ac70f0Sopenharmony_ci			n = car(p2);
2764d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2765d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p2));
2766d5ac70f0Sopenharmony_ci			delete_object(instance, p2);
2767d5ac70f0Sopenharmony_ci			return n;
2768d5ac70f0Sopenharmony_ci		}
2769d5ac70f0Sopenharmony_ci		delete_tree(instance, car(p2));
2770d5ac70f0Sopenharmony_ci		p2 = cdr(n = p2);
2771d5ac70f0Sopenharmony_ci		delete_object(instance, n);
2772d5ac70f0Sopenharmony_ci	} while (p2 != &alsa_lisp_nil);
2773d5ac70f0Sopenharmony_ci
2774d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2775d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2776d5ac70f0Sopenharmony_ci}
2777d5ac70f0Sopenharmony_ci
2778d5ac70f0Sopenharmony_ci/*
2779d5ac70f0Sopenharmony_ci *  Syntax: (rassoc value alist)
2780d5ac70f0Sopenharmony_ci */
2781d5ac70f0Sopenharmony_cistruct alisp_object * F_rassoc(struct alisp_instance *instance, struct alisp_object * args)
2782d5ac70f0Sopenharmony_ci{
2783d5ac70f0Sopenharmony_ci	struct alisp_object * p1, *p2, * n;
2784d5ac70f0Sopenharmony_ci
2785d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
2786d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
2787d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
2788d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
2789d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2790d5ac70f0Sopenharmony_ci
2791d5ac70f0Sopenharmony_ci	do {
2792d5ac70f0Sopenharmony_ci		if (eq(p1, cdr(car(p2)))) {
2793d5ac70f0Sopenharmony_ci			n = car(p2);
2794d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2795d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p2));
2796d5ac70f0Sopenharmony_ci			delete_object(instance, p2);
2797d5ac70f0Sopenharmony_ci			return n;
2798d5ac70f0Sopenharmony_ci		}
2799d5ac70f0Sopenharmony_ci		delete_tree(instance, car(p2));
2800d5ac70f0Sopenharmony_ci		p2 = cdr(n = p2);
2801d5ac70f0Sopenharmony_ci		delete_object(instance, n);
2802d5ac70f0Sopenharmony_ci	} while (p2 != &alsa_lisp_nil);
2803d5ac70f0Sopenharmony_ci
2804d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2805d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2806d5ac70f0Sopenharmony_ci}
2807d5ac70f0Sopenharmony_ci
2808d5ac70f0Sopenharmony_ci/*
2809d5ac70f0Sopenharmony_ci *  Syntax: (assq key alist)
2810d5ac70f0Sopenharmony_ci */
2811d5ac70f0Sopenharmony_cistruct alisp_object * F_assq(struct alisp_instance *instance, struct alisp_object * args)
2812d5ac70f0Sopenharmony_ci{
2813d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2, * n;
2814d5ac70f0Sopenharmony_ci
2815d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
2816d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
2817d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
2818d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
2819d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2820d5ac70f0Sopenharmony_ci
2821d5ac70f0Sopenharmony_ci	do {
2822d5ac70f0Sopenharmony_ci		if (equal(p1, car(car(p2)))) {
2823d5ac70f0Sopenharmony_ci			n = car(p2);
2824d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2825d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p2));
2826d5ac70f0Sopenharmony_ci			delete_object(instance, p2);
2827d5ac70f0Sopenharmony_ci			return n;
2828d5ac70f0Sopenharmony_ci		}
2829d5ac70f0Sopenharmony_ci		delete_tree(instance, car(p2));
2830d5ac70f0Sopenharmony_ci		p2 = cdr(n = p2);
2831d5ac70f0Sopenharmony_ci		delete_object(instance, n);
2832d5ac70f0Sopenharmony_ci	} while (p2 != &alsa_lisp_nil);
2833d5ac70f0Sopenharmony_ci
2834d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2835d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2836d5ac70f0Sopenharmony_ci}
2837d5ac70f0Sopenharmony_ci
2838d5ac70f0Sopenharmony_ci/*
2839d5ac70f0Sopenharmony_ci *  Syntax: (nth index alist)
2840d5ac70f0Sopenharmony_ci */
2841d5ac70f0Sopenharmony_cistruct alisp_object * F_nth(struct alisp_instance *instance, struct alisp_object * args)
2842d5ac70f0Sopenharmony_ci{
2843d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2, * n;
2844d5ac70f0Sopenharmony_ci	long idx;
2845d5ac70f0Sopenharmony_ci
2846d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
2847d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
2848d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
2849d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
2850d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2851d5ac70f0Sopenharmony_ci
2852d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
2853d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
2854d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
2855d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
2856d5ac70f0Sopenharmony_ci	}
2857d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p2, ALISP_OBJ_CONS)) {
2858d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
2859d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
2860d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
2861d5ac70f0Sopenharmony_ci	}
2862d5ac70f0Sopenharmony_ci	idx = p1->value.i;
2863d5ac70f0Sopenharmony_ci	delete_object(instance, p1);
2864d5ac70f0Sopenharmony_ci	while (idx-- > 0) {
2865d5ac70f0Sopenharmony_ci		delete_tree(instance, car(p2));
2866d5ac70f0Sopenharmony_ci		p2 = cdr(n = p2);
2867d5ac70f0Sopenharmony_ci		delete_object(instance, n);
2868d5ac70f0Sopenharmony_ci	}
2869d5ac70f0Sopenharmony_ci	n = car(p2);
2870d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(p2));
2871d5ac70f0Sopenharmony_ci	delete_object(instance, p2);
2872d5ac70f0Sopenharmony_ci	return n;
2873d5ac70f0Sopenharmony_ci}
2874d5ac70f0Sopenharmony_ci
2875d5ac70f0Sopenharmony_ci/*
2876d5ac70f0Sopenharmony_ci *  Syntax: (rassq value alist)
2877d5ac70f0Sopenharmony_ci */
2878d5ac70f0Sopenharmony_cistruct alisp_object * F_rassq(struct alisp_instance *instance, struct alisp_object * args)
2879d5ac70f0Sopenharmony_ci{
2880d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2, * n;
2881d5ac70f0Sopenharmony_ci
2882d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
2883d5ac70f0Sopenharmony_ci	p2 = eval(instance, car(cdr(args)));
2884d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
2885d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
2886d5ac70f0Sopenharmony_ci	delete_object(instance, args);
2887d5ac70f0Sopenharmony_ci
2888d5ac70f0Sopenharmony_ci	do {
2889d5ac70f0Sopenharmony_ci		if (equal(p1, cdr(car(p2)))) {
2890d5ac70f0Sopenharmony_ci			n = car(p2);
2891d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
2892d5ac70f0Sopenharmony_ci			delete_tree(instance, cdr(p2));
2893d5ac70f0Sopenharmony_ci			delete_object(instance, p2);
2894d5ac70f0Sopenharmony_ci			return n;
2895d5ac70f0Sopenharmony_ci		}
2896d5ac70f0Sopenharmony_ci		delete_tree(instance, car(p2));
2897d5ac70f0Sopenharmony_ci		p2 = cdr(n = p2);
2898d5ac70f0Sopenharmony_ci		delete_object(instance, n);
2899d5ac70f0Sopenharmony_ci	} while (p2 != &alsa_lisp_nil);
2900d5ac70f0Sopenharmony_ci
2901d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
2902d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2903d5ac70f0Sopenharmony_ci}
2904d5ac70f0Sopenharmony_ci
2905d5ac70f0Sopenharmony_cistatic struct alisp_object * F_dump_memory(struct alisp_instance *instance, struct alisp_object * args)
2906d5ac70f0Sopenharmony_ci{
2907d5ac70f0Sopenharmony_ci	struct alisp_object * p = car(args);
2908d5ac70f0Sopenharmony_ci
2909d5ac70f0Sopenharmony_ci	if (p != &alsa_lisp_nil && cdr(args) == &alsa_lisp_nil &&
2910d5ac70f0Sopenharmony_ci	    alisp_compare_type(p, ALISP_OBJ_STRING)) {
2911d5ac70f0Sopenharmony_ci		if (strlen(p->value.s) > 0) {
2912d5ac70f0Sopenharmony_ci			dump_objects(instance, p->value.s);
2913d5ac70f0Sopenharmony_ci			delete_tree(instance, args);
2914d5ac70f0Sopenharmony_ci			return &alsa_lisp_t;
2915d5ac70f0Sopenharmony_ci		} else
2916d5ac70f0Sopenharmony_ci			lisp_warn(instance, "expected filename");
2917d5ac70f0Sopenharmony_ci	} else
2918d5ac70f0Sopenharmony_ci		lisp_warn(instance, "wrong number of parameters (expected string)");
2919d5ac70f0Sopenharmony_ci
2920d5ac70f0Sopenharmony_ci	delete_tree(instance, args);
2921d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2922d5ac70f0Sopenharmony_ci}
2923d5ac70f0Sopenharmony_ci
2924d5ac70f0Sopenharmony_cistatic struct alisp_object * F_stat_memory(struct alisp_instance *instance, struct alisp_object * args)
2925d5ac70f0Sopenharmony_ci{
2926d5ac70f0Sopenharmony_ci	snd_output_printf(instance->out, "*** Memory stats\n");
2927d5ac70f0Sopenharmony_ci	snd_output_printf(instance->out, "  used_objs = %li, free_objs = %li, max_objs = %li, obj_size = %i (total bytes = %li, max bytes = %li)\n",
2928d5ac70f0Sopenharmony_ci			  instance->used_objs,
2929d5ac70f0Sopenharmony_ci			  instance->free_objs,
2930d5ac70f0Sopenharmony_ci			  instance->max_objs,
2931d5ac70f0Sopenharmony_ci			  (int)sizeof(struct alisp_object),
2932d5ac70f0Sopenharmony_ci			  (long)((instance->used_objs + instance->free_objs) * sizeof(struct alisp_object)),
2933d5ac70f0Sopenharmony_ci			  (long)(instance->max_objs * sizeof(struct alisp_object)));
2934d5ac70f0Sopenharmony_ci	delete_tree(instance, args);
2935d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2936d5ac70f0Sopenharmony_ci}
2937d5ac70f0Sopenharmony_ci
2938d5ac70f0Sopenharmony_cistatic struct alisp_object * F_check_memory(struct alisp_instance *instance, struct alisp_object * args)
2939d5ac70f0Sopenharmony_ci{
2940d5ac70f0Sopenharmony_ci	delete_tree(instance, args);
2941d5ac70f0Sopenharmony_ci	if (instance->used_objs > 0) {
2942d5ac70f0Sopenharmony_ci		fprintf(stderr, "!!!alsa lisp - check memory failed!!!\n");
2943d5ac70f0Sopenharmony_ci		F_stat_memory(instance, &alsa_lisp_nil);
2944d5ac70f0Sopenharmony_ci		exit(EXIT_FAILURE);
2945d5ac70f0Sopenharmony_ci	}
2946d5ac70f0Sopenharmony_ci	return &alsa_lisp_t;
2947d5ac70f0Sopenharmony_ci}
2948d5ac70f0Sopenharmony_ci
2949d5ac70f0Sopenharmony_cistatic struct alisp_object * F_dump_objects(struct alisp_instance *instance, struct alisp_object * args)
2950d5ac70f0Sopenharmony_ci{
2951d5ac70f0Sopenharmony_ci	struct alisp_object * p = car(args);
2952d5ac70f0Sopenharmony_ci
2953d5ac70f0Sopenharmony_ci	if (p != &alsa_lisp_nil && cdr(args) == &alsa_lisp_nil &&
2954d5ac70f0Sopenharmony_ci	    alisp_compare_type(p, ALISP_OBJ_STRING)) {
2955d5ac70f0Sopenharmony_ci		if (strlen(p->value.s) > 0) {
2956d5ac70f0Sopenharmony_ci			dump_obj_lists(instance, p->value.s);
2957d5ac70f0Sopenharmony_ci			delete_tree(instance, args);
2958d5ac70f0Sopenharmony_ci			return &alsa_lisp_t;
2959d5ac70f0Sopenharmony_ci		} else
2960d5ac70f0Sopenharmony_ci			lisp_warn(instance, "expected filename");
2961d5ac70f0Sopenharmony_ci	} else
2962d5ac70f0Sopenharmony_ci		lisp_warn(instance, "wrong number of parameters (expected string)");
2963d5ac70f0Sopenharmony_ci
2964d5ac70f0Sopenharmony_ci	delete_tree(instance, args);
2965d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
2966d5ac70f0Sopenharmony_ci}
2967d5ac70f0Sopenharmony_ci
2968d5ac70f0Sopenharmony_cistruct intrinsic {
2969d5ac70f0Sopenharmony_ci	const char *name;
2970d5ac70f0Sopenharmony_ci	struct alisp_object * (*func)(struct alisp_instance *instance, struct alisp_object * args);
2971d5ac70f0Sopenharmony_ci};
2972d5ac70f0Sopenharmony_ci
2973d5ac70f0Sopenharmony_cistatic const struct intrinsic intrinsics[] = {
2974d5ac70f0Sopenharmony_ci	{ "!=", F_numneq },
2975d5ac70f0Sopenharmony_ci	{ "%", F_mod },
2976d5ac70f0Sopenharmony_ci	{ "&check-memory", F_check_memory },
2977d5ac70f0Sopenharmony_ci	{ "&dump-memory", F_dump_memory },
2978d5ac70f0Sopenharmony_ci	{ "&dump-objects", F_dump_objects },
2979d5ac70f0Sopenharmony_ci	{ "&stat-memory", F_stat_memory },
2980d5ac70f0Sopenharmony_ci	{ "*", F_mul },
2981d5ac70f0Sopenharmony_ci	{ "+", F_add },
2982d5ac70f0Sopenharmony_ci	{ "-", F_sub },
2983d5ac70f0Sopenharmony_ci	{ "/", F_div },
2984d5ac70f0Sopenharmony_ci	{ "<", F_lt },
2985d5ac70f0Sopenharmony_ci	{ "<=", F_le },
2986d5ac70f0Sopenharmony_ci	{ "=", F_numeq },
2987d5ac70f0Sopenharmony_ci	{ ">", F_gt },
2988d5ac70f0Sopenharmony_ci	{ ">=", F_ge },
2989d5ac70f0Sopenharmony_ci	{ "and", F_and },
2990d5ac70f0Sopenharmony_ci	{ "assoc", F_assoc },
2991d5ac70f0Sopenharmony_ci	{ "assq", F_assq },
2992d5ac70f0Sopenharmony_ci	{ "atom", F_atom },
2993d5ac70f0Sopenharmony_ci	{ "car", F_car },
2994d5ac70f0Sopenharmony_ci	{ "cdr", F_cdr },
2995d5ac70f0Sopenharmony_ci	{ "compare-strings", F_compare_strings },
2996d5ac70f0Sopenharmony_ci	{ "concat", F_concat },
2997d5ac70f0Sopenharmony_ci	{ "cond", F_cond },
2998d5ac70f0Sopenharmony_ci	{ "cons", F_cons },
2999d5ac70f0Sopenharmony_ci	{ "defun", F_defun },
3000d5ac70f0Sopenharmony_ci	{ "eq", F_eq },
3001d5ac70f0Sopenharmony_ci	{ "equal", F_equal },
3002d5ac70f0Sopenharmony_ci	{ "eval", F_eval },
3003d5ac70f0Sopenharmony_ci	{ "exfun", F_exfun },
3004d5ac70f0Sopenharmony_ci	{ "format", F_format },
3005d5ac70f0Sopenharmony_ci	{ "funcall", F_funcall },
3006d5ac70f0Sopenharmony_ci	{ "garbage-collect", F_gc },
3007d5ac70f0Sopenharmony_ci	{ "gc", F_gc },
3008d5ac70f0Sopenharmony_ci	{ "if", F_if },
3009d5ac70f0Sopenharmony_ci	{ "include", F_include },
3010d5ac70f0Sopenharmony_ci	{ "list", F_list },
3011d5ac70f0Sopenharmony_ci	{ "not", F_not },
3012d5ac70f0Sopenharmony_ci	{ "nth", F_nth },
3013d5ac70f0Sopenharmony_ci	{ "null", F_not },
3014d5ac70f0Sopenharmony_ci	{ "or", F_or },
3015d5ac70f0Sopenharmony_ci	{ "path", F_path },
3016d5ac70f0Sopenharmony_ci	{ "princ", F_princ },
3017d5ac70f0Sopenharmony_ci	{ "prog1", F_prog1 },
3018d5ac70f0Sopenharmony_ci	{ "prog2", F_prog2 },
3019d5ac70f0Sopenharmony_ci	{ "progn", F_progn },
3020d5ac70f0Sopenharmony_ci	{ "quote", F_quote },
3021d5ac70f0Sopenharmony_ci	{ "rassoc", F_rassoc },
3022d5ac70f0Sopenharmony_ci	{ "rassq", F_rassq },
3023d5ac70f0Sopenharmony_ci	{ "set", F_set },
3024d5ac70f0Sopenharmony_ci	{ "setf", F_setq },
3025d5ac70f0Sopenharmony_ci	{ "setq", F_setq },
3026d5ac70f0Sopenharmony_ci	{ "string-equal", F_equal },
3027d5ac70f0Sopenharmony_ci	{ "string-to-float", F_string_to_float },
3028d5ac70f0Sopenharmony_ci	{ "string-to-integer", F_string_to_integer },
3029d5ac70f0Sopenharmony_ci	{ "string-to-number", F_string_to_float },
3030d5ac70f0Sopenharmony_ci	{ "string=", F_equal },
3031d5ac70f0Sopenharmony_ci	{ "unless", F_unless },
3032d5ac70f0Sopenharmony_ci	{ "unset", F_unset },
3033d5ac70f0Sopenharmony_ci	{ "unsetf", F_unsetq },
3034d5ac70f0Sopenharmony_ci	{ "unsetq", F_unsetq },
3035d5ac70f0Sopenharmony_ci	{ "when", F_when },
3036d5ac70f0Sopenharmony_ci	{ "while", F_while },
3037d5ac70f0Sopenharmony_ci};
3038d5ac70f0Sopenharmony_ci
3039d5ac70f0Sopenharmony_ci#include "alisp_snd.c"
3040d5ac70f0Sopenharmony_ci
3041d5ac70f0Sopenharmony_cistatic int compar(const void *p1, const void *p2)
3042d5ac70f0Sopenharmony_ci{
3043d5ac70f0Sopenharmony_ci	return strcmp(((struct intrinsic *)p1)->name,
3044d5ac70f0Sopenharmony_ci		      ((struct intrinsic *)p2)->name);
3045d5ac70f0Sopenharmony_ci}
3046d5ac70f0Sopenharmony_ci
3047d5ac70f0Sopenharmony_cistatic inline struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
3048d5ac70f0Sopenharmony_ci{
3049d5ac70f0Sopenharmony_ci	struct alisp_object * p3;
3050d5ac70f0Sopenharmony_ci	struct intrinsic key, *item;
3051d5ac70f0Sopenharmony_ci
3052d5ac70f0Sopenharmony_ci	key.name = p1->value.s;
3053d5ac70f0Sopenharmony_ci
3054d5ac70f0Sopenharmony_ci	if ((item = bsearch(&key, intrinsics,
3055d5ac70f0Sopenharmony_ci			    sizeof intrinsics / sizeof intrinsics[0],
3056d5ac70f0Sopenharmony_ci			    sizeof intrinsics[0], compar)) != NULL) {
3057d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
3058d5ac70f0Sopenharmony_ci		return item->func(instance, p2);
3059d5ac70f0Sopenharmony_ci	}
3060d5ac70f0Sopenharmony_ci
3061d5ac70f0Sopenharmony_ci	if ((item = bsearch(&key, snd_intrinsics,
3062d5ac70f0Sopenharmony_ci			    sizeof snd_intrinsics / sizeof snd_intrinsics[0],
3063d5ac70f0Sopenharmony_ci			    sizeof snd_intrinsics[0], compar)) != NULL) {
3064d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
3065d5ac70f0Sopenharmony_ci		return item->func(instance, p2);
3066d5ac70f0Sopenharmony_ci	}
3067d5ac70f0Sopenharmony_ci
3068d5ac70f0Sopenharmony_ci	if ((p3 = get_object(instance, p1)) != &alsa_lisp_nil) {
3069d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
3070d5ac70f0Sopenharmony_ci		return eval_func(instance, p3, p2);
3071d5ac70f0Sopenharmony_ci	} else {
3072d5ac70f0Sopenharmony_ci		lisp_warn(instance, "function `%s' is undefined", p1->value.s);
3073d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
3074d5ac70f0Sopenharmony_ci		delete_tree(instance, p2);
3075d5ac70f0Sopenharmony_ci	}
3076d5ac70f0Sopenharmony_ci
3077d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
3078d5ac70f0Sopenharmony_ci}
3079d5ac70f0Sopenharmony_ci
3080d5ac70f0Sopenharmony_ci/*
3081d5ac70f0Sopenharmony_ci * Syntax: (funcall function args...)
3082d5ac70f0Sopenharmony_ci */
3083d5ac70f0Sopenharmony_cistatic struct alisp_object * F_funcall(struct alisp_instance *instance, struct alisp_object * args)
3084d5ac70f0Sopenharmony_ci{
3085d5ac70f0Sopenharmony_ci	struct alisp_object * p = eval(instance, car(args)), * p1;
3086d5ac70f0Sopenharmony_ci
3087d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
3088d5ac70f0Sopenharmony_ci	    !alisp_compare_type(p, ALISP_OBJ_STRING)) {
3089d5ac70f0Sopenharmony_ci		lisp_warn(instance, "expected an function name");
3090d5ac70f0Sopenharmony_ci		delete_tree(instance, p);
3091d5ac70f0Sopenharmony_ci		delete_tree(instance, cdr(args));
3092d5ac70f0Sopenharmony_ci		delete_object(instance, args);
3093d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
3094d5ac70f0Sopenharmony_ci	}
3095d5ac70f0Sopenharmony_ci	p1 = cdr(args);
3096d5ac70f0Sopenharmony_ci	delete_object(instance, args);
3097d5ac70f0Sopenharmony_ci	return eval_cons1(instance, p, p1);
3098d5ac70f0Sopenharmony_ci}
3099d5ac70f0Sopenharmony_ci
3100d5ac70f0Sopenharmony_cistatic inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p)
3101d5ac70f0Sopenharmony_ci{
3102d5ac70f0Sopenharmony_ci	struct alisp_object * p1 = car(p), * p2;
3103d5ac70f0Sopenharmony_ci
3104d5ac70f0Sopenharmony_ci	if (p1 != &alsa_lisp_nil && alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER)) {
3105d5ac70f0Sopenharmony_ci		if (!strcmp(p1->value.s, "lambda"))
3106d5ac70f0Sopenharmony_ci			return p;
3107d5ac70f0Sopenharmony_ci
3108d5ac70f0Sopenharmony_ci		p2 = cdr(p);
3109d5ac70f0Sopenharmony_ci		delete_object(instance, p);
3110d5ac70f0Sopenharmony_ci		return eval_cons1(instance, p1, p2);
3111d5ac70f0Sopenharmony_ci	} else {
3112d5ac70f0Sopenharmony_ci		delete_tree(instance, p);
3113d5ac70f0Sopenharmony_ci	}
3114d5ac70f0Sopenharmony_ci
3115d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
3116d5ac70f0Sopenharmony_ci}
3117d5ac70f0Sopenharmony_ci
3118d5ac70f0Sopenharmony_cistatic struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p)
3119d5ac70f0Sopenharmony_ci{
3120d5ac70f0Sopenharmony_ci	switch (alisp_get_type(p)) {
3121d5ac70f0Sopenharmony_ci	case ALISP_OBJ_IDENTIFIER: {
3122d5ac70f0Sopenharmony_ci		struct alisp_object *r = incref_tree(instance, get_object(instance, p));
3123d5ac70f0Sopenharmony_ci		delete_object(instance, p);
3124d5ac70f0Sopenharmony_ci		return r;
3125d5ac70f0Sopenharmony_ci	}
3126d5ac70f0Sopenharmony_ci	case ALISP_OBJ_INTEGER:
3127d5ac70f0Sopenharmony_ci	case ALISP_OBJ_FLOAT:
3128d5ac70f0Sopenharmony_ci	case ALISP_OBJ_STRING:
3129d5ac70f0Sopenharmony_ci	case ALISP_OBJ_POINTER:
3130d5ac70f0Sopenharmony_ci		return p;
3131d5ac70f0Sopenharmony_ci	case ALISP_OBJ_CONS:
3132d5ac70f0Sopenharmony_ci		return eval_cons(instance, p);
3133d5ac70f0Sopenharmony_ci	default:
3134d5ac70f0Sopenharmony_ci		break;
3135d5ac70f0Sopenharmony_ci	}
3136d5ac70f0Sopenharmony_ci
3137d5ac70f0Sopenharmony_ci	return p;
3138d5ac70f0Sopenharmony_ci}
3139d5ac70f0Sopenharmony_ci
3140d5ac70f0Sopenharmony_cistatic struct alisp_object * F_eval(struct alisp_instance *instance, struct alisp_object * args)
3141d5ac70f0Sopenharmony_ci{
3142d5ac70f0Sopenharmony_ci	return eval(instance, eval(instance, car(args)));
3143d5ac70f0Sopenharmony_ci}
3144d5ac70f0Sopenharmony_ci
3145d5ac70f0Sopenharmony_ci/*
3146d5ac70f0Sopenharmony_ci *  main routine
3147d5ac70f0Sopenharmony_ci */
3148d5ac70f0Sopenharmony_ci
3149d5ac70f0Sopenharmony_cistatic int alisp_include_file(struct alisp_instance *instance, const char *filename)
3150d5ac70f0Sopenharmony_ci{
3151d5ac70f0Sopenharmony_ci	snd_input_t *old_in;
3152d5ac70f0Sopenharmony_ci	struct alisp_object *p, *p1;
3153d5ac70f0Sopenharmony_ci	char *name;
3154d5ac70f0Sopenharmony_ci	int retval = 0, err;
3155d5ac70f0Sopenharmony_ci
3156d5ac70f0Sopenharmony_ci	err = snd_user_file(filename, &name);
3157d5ac70f0Sopenharmony_ci	if (err < 0)
3158d5ac70f0Sopenharmony_ci		return err;
3159d5ac70f0Sopenharmony_ci	old_in = instance->in;
3160d5ac70f0Sopenharmony_ci	err = snd_input_stdio_open(&instance->in, name, "r");
3161d5ac70f0Sopenharmony_ci	if (err < 0) {
3162d5ac70f0Sopenharmony_ci		retval = err;
3163d5ac70f0Sopenharmony_ci		goto _err;
3164d5ac70f0Sopenharmony_ci	}
3165d5ac70f0Sopenharmony_ci	if (instance->verbose)
3166d5ac70f0Sopenharmony_ci		lisp_verbose(instance, "** include filename '%s'", name);
3167d5ac70f0Sopenharmony_ci
3168d5ac70f0Sopenharmony_ci	for (;;) {
3169d5ac70f0Sopenharmony_ci		if ((p = parse_object(instance, 0)) == NULL)
3170d5ac70f0Sopenharmony_ci			break;
3171d5ac70f0Sopenharmony_ci		if (instance->verbose) {
3172d5ac70f0Sopenharmony_ci			lisp_verbose(instance, "** code");
3173d5ac70f0Sopenharmony_ci			princ_object(instance->vout, p);
3174d5ac70f0Sopenharmony_ci			snd_output_putc(instance->vout, '\n');
3175d5ac70f0Sopenharmony_ci		}
3176d5ac70f0Sopenharmony_ci		p1 = eval(instance, p);
3177d5ac70f0Sopenharmony_ci		if (p1 == NULL) {
3178d5ac70f0Sopenharmony_ci			retval = -ENOMEM;
3179d5ac70f0Sopenharmony_ci			break;
3180d5ac70f0Sopenharmony_ci		}
3181d5ac70f0Sopenharmony_ci		if (instance->verbose) {
3182d5ac70f0Sopenharmony_ci			lisp_verbose(instance, "** result");
3183d5ac70f0Sopenharmony_ci			princ_object(instance->vout, p1);
3184d5ac70f0Sopenharmony_ci			snd_output_putc(instance->vout, '\n');
3185d5ac70f0Sopenharmony_ci		}
3186d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
3187d5ac70f0Sopenharmony_ci		if (instance->debug) {
3188d5ac70f0Sopenharmony_ci			lisp_debug(instance, "** objects after operation");
3189d5ac70f0Sopenharmony_ci			print_obj_lists(instance, instance->dout);
3190d5ac70f0Sopenharmony_ci		}
3191d5ac70f0Sopenharmony_ci	}
3192d5ac70f0Sopenharmony_ci
3193d5ac70f0Sopenharmony_ci	snd_input_close(instance->in);
3194d5ac70f0Sopenharmony_ci       _err:
3195d5ac70f0Sopenharmony_ci	free(name);
3196d5ac70f0Sopenharmony_ci	instance->in = old_in;
3197d5ac70f0Sopenharmony_ci	return retval;
3198d5ac70f0Sopenharmony_ci}
3199d5ac70f0Sopenharmony_ci
3200d5ac70f0Sopenharmony_ciint alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
3201d5ac70f0Sopenharmony_ci{
3202d5ac70f0Sopenharmony_ci	struct alisp_instance *instance;
3203d5ac70f0Sopenharmony_ci	struct alisp_object *p, *p1;
3204d5ac70f0Sopenharmony_ci	int i, j, retval = 0;
3205d5ac70f0Sopenharmony_ci
3206d5ac70f0Sopenharmony_ci	instance = (struct alisp_instance *)calloc(1, sizeof(struct alisp_instance));
3207d5ac70f0Sopenharmony_ci	if (instance == NULL) {
3208d5ac70f0Sopenharmony_ci		nomem();
3209d5ac70f0Sopenharmony_ci		return -ENOMEM;
3210d5ac70f0Sopenharmony_ci	}
3211d5ac70f0Sopenharmony_ci	instance->verbose = cfg->verbose && cfg->vout;
3212d5ac70f0Sopenharmony_ci	instance->warning = cfg->warning && cfg->wout;
3213d5ac70f0Sopenharmony_ci	instance->debug = cfg->debug && cfg->dout;
3214d5ac70f0Sopenharmony_ci	instance->in = cfg->in;
3215d5ac70f0Sopenharmony_ci	instance->out = cfg->out;
3216d5ac70f0Sopenharmony_ci	instance->vout = cfg->vout;
3217d5ac70f0Sopenharmony_ci	instance->eout = cfg->eout;
3218d5ac70f0Sopenharmony_ci	instance->wout = cfg->wout;
3219d5ac70f0Sopenharmony_ci	instance->dout = cfg->dout;
3220d5ac70f0Sopenharmony_ci	INIT_LIST_HEAD(&instance->free_objs_list);
3221d5ac70f0Sopenharmony_ci	for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
3222d5ac70f0Sopenharmony_ci		for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++)
3223d5ac70f0Sopenharmony_ci			INIT_LIST_HEAD(&instance->used_objs_list[i][j]);
3224d5ac70f0Sopenharmony_ci		INIT_LIST_HEAD(&instance->setobjs_list[i]);
3225d5ac70f0Sopenharmony_ci	}
3226d5ac70f0Sopenharmony_ci
3227d5ac70f0Sopenharmony_ci	init_lex(instance);
3228d5ac70f0Sopenharmony_ci
3229d5ac70f0Sopenharmony_ci	for (;;) {
3230d5ac70f0Sopenharmony_ci		if ((p = parse_object(instance, 0)) == NULL)
3231d5ac70f0Sopenharmony_ci			break;
3232d5ac70f0Sopenharmony_ci		if (instance->verbose) {
3233d5ac70f0Sopenharmony_ci			lisp_verbose(instance, "** code");
3234d5ac70f0Sopenharmony_ci			princ_object(instance->vout, p);
3235d5ac70f0Sopenharmony_ci			snd_output_putc(instance->vout, '\n');
3236d5ac70f0Sopenharmony_ci		}
3237d5ac70f0Sopenharmony_ci		p1 = eval(instance, p);
3238d5ac70f0Sopenharmony_ci		if (p1 == NULL) {
3239d5ac70f0Sopenharmony_ci			retval = -ENOMEM;
3240d5ac70f0Sopenharmony_ci			break;
3241d5ac70f0Sopenharmony_ci		}
3242d5ac70f0Sopenharmony_ci		if (instance->verbose) {
3243d5ac70f0Sopenharmony_ci			lisp_verbose(instance, "** result");
3244d5ac70f0Sopenharmony_ci			princ_object(instance->vout, p1);
3245d5ac70f0Sopenharmony_ci			snd_output_putc(instance->vout, '\n');
3246d5ac70f0Sopenharmony_ci		}
3247d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
3248d5ac70f0Sopenharmony_ci		if (instance->debug) {
3249d5ac70f0Sopenharmony_ci			lisp_debug(instance, "** objects after operation");
3250d5ac70f0Sopenharmony_ci			print_obj_lists(instance, instance->dout);
3251d5ac70f0Sopenharmony_ci		}
3252d5ac70f0Sopenharmony_ci	}
3253d5ac70f0Sopenharmony_ci
3254d5ac70f0Sopenharmony_ci	if (_instance)
3255d5ac70f0Sopenharmony_ci		*_instance = instance;
3256d5ac70f0Sopenharmony_ci	else
3257d5ac70f0Sopenharmony_ci		alsa_lisp_free(instance);
3258d5ac70f0Sopenharmony_ci
3259d5ac70f0Sopenharmony_ci	return retval;
3260d5ac70f0Sopenharmony_ci}
3261d5ac70f0Sopenharmony_ci
3262d5ac70f0Sopenharmony_civoid alsa_lisp_free(struct alisp_instance *instance)
3263d5ac70f0Sopenharmony_ci{
3264d5ac70f0Sopenharmony_ci	if (instance == NULL)
3265d5ac70f0Sopenharmony_ci		return;
3266d5ac70f0Sopenharmony_ci	done_lex(instance);
3267d5ac70f0Sopenharmony_ci	free_objects(instance);
3268d5ac70f0Sopenharmony_ci	free(instance);
3269d5ac70f0Sopenharmony_ci}
3270d5ac70f0Sopenharmony_ci
3271d5ac70f0Sopenharmony_cistruct alisp_cfg *alsa_lisp_default_cfg(snd_input_t *input)
3272d5ac70f0Sopenharmony_ci{
3273d5ac70f0Sopenharmony_ci	snd_output_t *output, *eoutput;
3274d5ac70f0Sopenharmony_ci	struct alisp_cfg *cfg;
3275d5ac70f0Sopenharmony_ci	int err;
3276d5ac70f0Sopenharmony_ci
3277d5ac70f0Sopenharmony_ci	err = snd_output_stdio_attach(&output, stdout, 0);
3278d5ac70f0Sopenharmony_ci	if (err < 0)
3279d5ac70f0Sopenharmony_ci		return NULL;
3280d5ac70f0Sopenharmony_ci	err = snd_output_stdio_attach(&eoutput, stderr, 0);
3281d5ac70f0Sopenharmony_ci	if (err < 0) {
3282d5ac70f0Sopenharmony_ci		snd_output_close(output);
3283d5ac70f0Sopenharmony_ci		return NULL;
3284d5ac70f0Sopenharmony_ci	}
3285d5ac70f0Sopenharmony_ci	cfg = calloc(1, sizeof(struct alisp_cfg));
3286d5ac70f0Sopenharmony_ci	if (cfg == NULL) {
3287d5ac70f0Sopenharmony_ci		snd_output_close(eoutput);
3288d5ac70f0Sopenharmony_ci		snd_output_close(output);
3289d5ac70f0Sopenharmony_ci		return NULL;
3290d5ac70f0Sopenharmony_ci	}
3291d5ac70f0Sopenharmony_ci	cfg->out = output;
3292d5ac70f0Sopenharmony_ci	cfg->wout = eoutput;
3293d5ac70f0Sopenharmony_ci	cfg->eout = eoutput;
3294d5ac70f0Sopenharmony_ci	cfg->dout = eoutput;
3295d5ac70f0Sopenharmony_ci	cfg->in = input;
3296d5ac70f0Sopenharmony_ci	return cfg;
3297d5ac70f0Sopenharmony_ci}
3298d5ac70f0Sopenharmony_ci
3299d5ac70f0Sopenharmony_civoid alsa_lisp_default_cfg_free(struct alisp_cfg *cfg)
3300d5ac70f0Sopenharmony_ci{
3301d5ac70f0Sopenharmony_ci	snd_input_close(cfg->in);
3302d5ac70f0Sopenharmony_ci	snd_output_close(cfg->out);
3303d5ac70f0Sopenharmony_ci	snd_output_close(cfg->dout);
3304d5ac70f0Sopenharmony_ci	free(cfg);
3305d5ac70f0Sopenharmony_ci}
3306d5ac70f0Sopenharmony_ci
3307d5ac70f0Sopenharmony_ciint alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterator **result,
3308d5ac70f0Sopenharmony_ci		       const char *id, const char *args, ...)
3309d5ac70f0Sopenharmony_ci{
3310d5ac70f0Sopenharmony_ci	int err = 0;
3311d5ac70f0Sopenharmony_ci	struct alisp_object *aargs = NULL, *obj, *res;
3312d5ac70f0Sopenharmony_ci
3313d5ac70f0Sopenharmony_ci	if (args && *args != 'n') {
3314d5ac70f0Sopenharmony_ci		va_list ap;
3315d5ac70f0Sopenharmony_ci		struct alisp_object *p;
3316d5ac70f0Sopenharmony_ci		p = NULL;
3317d5ac70f0Sopenharmony_ci		va_start(ap, args);
3318d5ac70f0Sopenharmony_ci		while (*args) {
3319d5ac70f0Sopenharmony_ci			if (*args++ != '%') {
3320d5ac70f0Sopenharmony_ci				err = -EINVAL;
3321d5ac70f0Sopenharmony_ci				break;
3322d5ac70f0Sopenharmony_ci			}
3323d5ac70f0Sopenharmony_ci			if (*args == '\0') {
3324d5ac70f0Sopenharmony_ci				err = -EINVAL;
3325d5ac70f0Sopenharmony_ci				break;
3326d5ac70f0Sopenharmony_ci			}
3327d5ac70f0Sopenharmony_ci			obj = NULL;
3328d5ac70f0Sopenharmony_ci			err = 0;
3329d5ac70f0Sopenharmony_ci			switch (*args++) {
3330d5ac70f0Sopenharmony_ci			case 's':
3331d5ac70f0Sopenharmony_ci				obj = new_string(instance, va_arg(ap, char *));
3332d5ac70f0Sopenharmony_ci				break;
3333d5ac70f0Sopenharmony_ci			case 'i':
3334d5ac70f0Sopenharmony_ci				obj = new_integer(instance, va_arg(ap, int));
3335d5ac70f0Sopenharmony_ci				break;
3336d5ac70f0Sopenharmony_ci			case 'l':
3337d5ac70f0Sopenharmony_ci				obj = new_integer(instance, va_arg(ap, long));
3338d5ac70f0Sopenharmony_ci				break;
3339d5ac70f0Sopenharmony_ci			case 'f':
3340d5ac70f0Sopenharmony_ci			case 'd':
3341d5ac70f0Sopenharmony_ci				obj = new_integer(instance, va_arg(ap, double));
3342d5ac70f0Sopenharmony_ci				break;
3343d5ac70f0Sopenharmony_ci			case 'p': {
3344d5ac70f0Sopenharmony_ci				char _ptrid[24];
3345d5ac70f0Sopenharmony_ci				char *ptrid = _ptrid;
3346d5ac70f0Sopenharmony_ci				while (*args && *args != '%')
3347d5ac70f0Sopenharmony_ci					*ptrid++ = *args++;
3348d5ac70f0Sopenharmony_ci				*ptrid = 0;
3349d5ac70f0Sopenharmony_ci				if (ptrid == _ptrid) {
3350d5ac70f0Sopenharmony_ci					err = -EINVAL;
3351d5ac70f0Sopenharmony_ci					break;
3352d5ac70f0Sopenharmony_ci				}
3353d5ac70f0Sopenharmony_ci				obj = new_cons_pointer(instance, _ptrid, va_arg(ap, void *));
3354d5ac70f0Sopenharmony_ci				obj = quote_object(instance, obj);
3355d5ac70f0Sopenharmony_ci				break;
3356d5ac70f0Sopenharmony_ci			}
3357d5ac70f0Sopenharmony_ci			default:
3358d5ac70f0Sopenharmony_ci				err = -EINVAL;
3359d5ac70f0Sopenharmony_ci				break;
3360d5ac70f0Sopenharmony_ci			}
3361d5ac70f0Sopenharmony_ci			if (err < 0)
3362d5ac70f0Sopenharmony_ci				goto __args_end;
3363d5ac70f0Sopenharmony_ci			if (obj == NULL) {
3364d5ac70f0Sopenharmony_ci				err = -ENOMEM;
3365d5ac70f0Sopenharmony_ci				goto __args_end;
3366d5ac70f0Sopenharmony_ci			}
3367d5ac70f0Sopenharmony_ci			if (p == NULL) {
3368d5ac70f0Sopenharmony_ci				p = aargs = new_object(instance, ALISP_OBJ_CONS);
3369d5ac70f0Sopenharmony_ci			} else {
3370d5ac70f0Sopenharmony_ci				p->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
3371d5ac70f0Sopenharmony_ci				p = p->value.c.cdr;
3372d5ac70f0Sopenharmony_ci			}
3373d5ac70f0Sopenharmony_ci			if (p == NULL) {
3374d5ac70f0Sopenharmony_ci				err = -ENOMEM;
3375d5ac70f0Sopenharmony_ci				goto __args_end;
3376d5ac70f0Sopenharmony_ci			}
3377d5ac70f0Sopenharmony_ci			p->value.c.car = obj;
3378d5ac70f0Sopenharmony_ci		}
3379d5ac70f0Sopenharmony_ci	      __args_end:
3380d5ac70f0Sopenharmony_ci		va_end(ap);
3381d5ac70f0Sopenharmony_ci		if (err < 0)
3382d5ac70f0Sopenharmony_ci			return err;
3383d5ac70f0Sopenharmony_ci#if 0
3384d5ac70f0Sopenharmony_ci		snd_output_printf(instance->wout, ">>>");
3385d5ac70f0Sopenharmony_ci		princ_object(instance->wout, aargs);
3386d5ac70f0Sopenharmony_ci		snd_output_printf(instance->wout, "<<<\n");
3387d5ac70f0Sopenharmony_ci#endif
3388d5ac70f0Sopenharmony_ci	}
3389d5ac70f0Sopenharmony_ci
3390d5ac70f0Sopenharmony_ci	err = -ENOENT;
3391d5ac70f0Sopenharmony_ci	if (aargs == NULL)
3392d5ac70f0Sopenharmony_ci		aargs = &alsa_lisp_nil;
3393d5ac70f0Sopenharmony_ci	if ((obj = get_object1(instance, id)) != &alsa_lisp_nil) {
3394d5ac70f0Sopenharmony_ci		res = eval_func(instance, obj, aargs);
3395d5ac70f0Sopenharmony_ci		err = 0;
3396d5ac70f0Sopenharmony_ci	} else {
3397d5ac70f0Sopenharmony_ci		struct intrinsic key, *item;
3398d5ac70f0Sopenharmony_ci		key.name = id;
3399d5ac70f0Sopenharmony_ci		if ((item = bsearch(&key, intrinsics,
3400d5ac70f0Sopenharmony_ci				    sizeof intrinsics / sizeof intrinsics[0],
3401d5ac70f0Sopenharmony_ci				    sizeof intrinsics[0], compar)) != NULL) {
3402d5ac70f0Sopenharmony_ci			res = item->func(instance, aargs);
3403d5ac70f0Sopenharmony_ci			err = 0;
3404d5ac70f0Sopenharmony_ci		} else if ((item = bsearch(&key, snd_intrinsics,
3405d5ac70f0Sopenharmony_ci				         sizeof snd_intrinsics / sizeof snd_intrinsics[0],
3406d5ac70f0Sopenharmony_ci					 sizeof snd_intrinsics[0], compar)) != NULL) {
3407d5ac70f0Sopenharmony_ci			res = item->func(instance, aargs);
3408d5ac70f0Sopenharmony_ci			err = 0;
3409d5ac70f0Sopenharmony_ci		} else {
3410d5ac70f0Sopenharmony_ci			res = &alsa_lisp_nil;
3411d5ac70f0Sopenharmony_ci		}
3412d5ac70f0Sopenharmony_ci	}
3413d5ac70f0Sopenharmony_ci	if (res == NULL)
3414d5ac70f0Sopenharmony_ci		err = -ENOMEM;
3415d5ac70f0Sopenharmony_ci	if (err == 0 && result) {
3416d5ac70f0Sopenharmony_ci		*result = res;
3417d5ac70f0Sopenharmony_ci	} else {
3418d5ac70f0Sopenharmony_ci		delete_tree(instance, res);
3419d5ac70f0Sopenharmony_ci	}
3420d5ac70f0Sopenharmony_ci
3421d5ac70f0Sopenharmony_ci	return 0;
3422d5ac70f0Sopenharmony_ci}
3423d5ac70f0Sopenharmony_ci
3424d5ac70f0Sopenharmony_civoid alsa_lisp_result_free(struct alisp_instance *instance,
3425d5ac70f0Sopenharmony_ci			   struct alisp_seq_iterator *result)
3426d5ac70f0Sopenharmony_ci{
3427d5ac70f0Sopenharmony_ci	delete_tree(instance, result);
3428d5ac70f0Sopenharmony_ci}
3429d5ac70f0Sopenharmony_ci
3430d5ac70f0Sopenharmony_ciint alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
3431d5ac70f0Sopenharmony_ci			struct alisp_seq_iterator **seq)
3432d5ac70f0Sopenharmony_ci{
3433d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
3434d5ac70f0Sopenharmony_ci
3435d5ac70f0Sopenharmony_ci	p1 = get_object1(instance, id);
3436d5ac70f0Sopenharmony_ci	if (p1 == NULL)
3437d5ac70f0Sopenharmony_ci		return -ENOMEM;
3438d5ac70f0Sopenharmony_ci	*seq = p1;
3439d5ac70f0Sopenharmony_ci	return 0;
3440d5ac70f0Sopenharmony_ci}
3441d5ac70f0Sopenharmony_ci
3442d5ac70f0Sopenharmony_ciint alsa_lisp_seq_next(struct alisp_seq_iterator **seq)
3443d5ac70f0Sopenharmony_ci{
3444d5ac70f0Sopenharmony_ci	struct alisp_object * p1 = *seq;
3445d5ac70f0Sopenharmony_ci
3446d5ac70f0Sopenharmony_ci	p1 = cdr(p1);
3447d5ac70f0Sopenharmony_ci	if (p1 == &alsa_lisp_nil)
3448d5ac70f0Sopenharmony_ci		return -ENOENT;
3449d5ac70f0Sopenharmony_ci	*seq = p1;
3450d5ac70f0Sopenharmony_ci	return 0;
3451d5ac70f0Sopenharmony_ci}
3452d5ac70f0Sopenharmony_ci
3453d5ac70f0Sopenharmony_ciint alsa_lisp_seq_count(struct alisp_seq_iterator *seq)
3454d5ac70f0Sopenharmony_ci{
3455d5ac70f0Sopenharmony_ci	int count = 0;
3456d5ac70f0Sopenharmony_ci
3457d5ac70f0Sopenharmony_ci	while (seq != &alsa_lisp_nil) {
3458d5ac70f0Sopenharmony_ci		count++;
3459d5ac70f0Sopenharmony_ci		seq = cdr(seq);
3460d5ac70f0Sopenharmony_ci	}
3461d5ac70f0Sopenharmony_ci	return count;
3462d5ac70f0Sopenharmony_ci}
3463d5ac70f0Sopenharmony_ci
3464d5ac70f0Sopenharmony_ciint alsa_lisp_seq_integer(struct alisp_seq_iterator *seq, long *val)
3465d5ac70f0Sopenharmony_ci{
3466d5ac70f0Sopenharmony_ci	if (alisp_compare_type(seq, ALISP_OBJ_CONS))
3467d5ac70f0Sopenharmony_ci		seq = seq->value.c.cdr;
3468d5ac70f0Sopenharmony_ci	if (alisp_compare_type(seq, ALISP_OBJ_INTEGER))
3469d5ac70f0Sopenharmony_ci		*val = seq->value.i;
3470d5ac70f0Sopenharmony_ci	else
3471d5ac70f0Sopenharmony_ci		return -EINVAL;
3472d5ac70f0Sopenharmony_ci	return 0;
3473d5ac70f0Sopenharmony_ci}
3474d5ac70f0Sopenharmony_ci
3475d5ac70f0Sopenharmony_ciint alsa_lisp_seq_pointer(struct alisp_seq_iterator *seq, const char *ptr_id, void **ptr)
3476d5ac70f0Sopenharmony_ci{
3477d5ac70f0Sopenharmony_ci	struct alisp_object * p2;
3478d5ac70f0Sopenharmony_ci
3479d5ac70f0Sopenharmony_ci	if (alisp_compare_type(seq, ALISP_OBJ_CONS) &&
3480d5ac70f0Sopenharmony_ci	    alisp_compare_type(seq->value.c.car, ALISP_OBJ_CONS))
3481d5ac70f0Sopenharmony_ci		seq = seq->value.c.car;
3482d5ac70f0Sopenharmony_ci	if (alisp_compare_type(seq, ALISP_OBJ_CONS)) {
3483d5ac70f0Sopenharmony_ci		p2 = seq->value.c.car;
3484d5ac70f0Sopenharmony_ci		if (!alisp_compare_type(p2, ALISP_OBJ_STRING))
3485d5ac70f0Sopenharmony_ci			return -EINVAL;
3486d5ac70f0Sopenharmony_ci		if (strcmp(p2->value.s, ptr_id))
3487d5ac70f0Sopenharmony_ci			return -EINVAL;
3488d5ac70f0Sopenharmony_ci		p2 = seq->value.c.cdr;
3489d5ac70f0Sopenharmony_ci		if (!alisp_compare_type(p2, ALISP_OBJ_POINTER))
3490d5ac70f0Sopenharmony_ci			return -EINVAL;
3491d5ac70f0Sopenharmony_ci		*ptr = (void *)seq->value.ptr;
3492d5ac70f0Sopenharmony_ci	} else
3493d5ac70f0Sopenharmony_ci		return -EINVAL;
3494d5ac70f0Sopenharmony_ci	return 0;
3495d5ac70f0Sopenharmony_ci}
3496