2
* ALSA lisp implementation
3
* Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
5
* Based on work of Sandro Sigala (slisp-1.2)
8
* This library is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU Lesser General Public License as
10
* published by the Free Software Foundation; either version 2.1 of
11
* the License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34
#define alisp_seq_iterator alisp_object
38
#include "alisp_local.h"
40
struct alisp_object alsa_lisp_nil;
41
struct alisp_object alsa_lisp_t;
43
/* parser prototypes */
44
static struct alisp_object * parse_object(struct alisp_instance *instance, int havetoken);
45
static void princ_cons(snd_output_t *out, struct alisp_object * p);
46
static void princ_object(snd_output_t *out, struct alisp_object * p);
47
static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p);
50
static struct alisp_object *F_eval(struct alisp_instance *instance, struct alisp_object *);
51
static struct alisp_object *F_progn(struct alisp_instance *instance, struct alisp_object *);
52
static struct alisp_object *F_funcall(struct alisp_instance *instance, struct alisp_object *);
55
static int alisp_include_file(struct alisp_instance *instance, const char *filename);
61
static int get_string_hash(const char *s)
68
return val & ALISP_OBJ_PAIR_HASH_MASK;
71
static void nomem(void)
73
SNDERR("alisp: no enough memory");
76
static void lisp_verbose(struct alisp_instance *instance, const char *fmt, ...)
80
if (!instance->verbose)
83
snd_output_printf(instance->vout, "alisp: ");
84
snd_output_vprintf(instance->vout, fmt, ap);
85
snd_output_putc(instance->vout, '\n');
89
static void lisp_error(struct alisp_instance *instance, const char *fmt, ...)
93
if (!instance->warning)
96
snd_output_printf(instance->eout, "alisp error: ");
97
snd_output_vprintf(instance->eout, fmt, ap);
98
snd_output_putc(instance->eout, '\n');
102
static void lisp_warn(struct alisp_instance *instance, const char *fmt, ...)
106
if (!instance->warning)
109
snd_output_printf(instance->wout, "alisp warning: ");
110
snd_output_vprintf(instance->wout, fmt, ap);
111
snd_output_putc(instance->wout, '\n');
115
static void lisp_debug(struct alisp_instance *instance, const char *fmt, ...)
119
if (!instance->debug)
122
snd_output_printf(instance->dout, "alisp debug: ");
123
snd_output_vprintf(instance->dout, fmt, ap);
124
snd_output_putc(instance->dout, '\n');
128
static struct alisp_object * new_object(struct alisp_instance *instance, int type)
130
struct alisp_object * p;
132
if (list_empty(&instance->free_objs_list)) {
133
p = (struct alisp_object *)malloc(sizeof(struct alisp_object));
138
lisp_debug(instance, "allocating cons %p", p);
140
p = (struct alisp_object *)instance->free_objs_list.next;
142
instance->free_objs--;
143
lisp_debug(instance, "recycling cons %p", p);
146
instance->used_objs++;
148
alisp_set_type(p, type);
149
alisp_set_refs(p, 1);
150
if (type == ALISP_OBJ_CONS) {
151
p->value.c.car = &alsa_lisp_nil;
152
p->value.c.cdr = &alsa_lisp_nil;
153
list_add(&p->list, &instance->used_objs_list[0][ALISP_OBJ_CONS]);
156
if (instance->used_objs + instance->free_objs > instance->max_objs)
157
instance->max_objs = instance->used_objs + instance->free_objs;
162
static void free_object(struct alisp_object * p)
164
switch (alisp_get_type(p)) {
165
case ALISP_OBJ_STRING:
166
case ALISP_OBJ_IDENTIFIER:
168
alisp_set_type(p, ALISP_OBJ_INTEGER);
175
static void delete_object(struct alisp_instance *instance, struct alisp_object * p)
177
if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
179
if (alisp_compare_type(p, ALISP_OBJ_NIL) ||
180
alisp_compare_type(p, ALISP_OBJ_T))
182
assert(alisp_get_refs(p) > 0);
183
lisp_debug(instance, "delete cons %p (type = %i, refs = %i) (s = '%s')", p, alisp_get_type(p), alisp_get_refs(p),
184
alisp_compare_type(p, ALISP_OBJ_STRING) ||
185
alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) ? p->value.s : "???");
186
if (alisp_dec_refs(p))
189
instance->used_objs--;
191
if (instance->free_objs >= ALISP_FREE_OBJ_POOL) {
192
lisp_debug(instance, "freed cons %p", p);
196
lisp_debug(instance, "moved cons %p to free list", p);
197
list_add(&p->list, &instance->free_objs_list);
198
instance->free_objs++;
201
static void delete_tree(struct alisp_instance *instance, struct alisp_object * p)
205
if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
206
delete_tree(instance, p->value.c.car);
207
delete_tree(instance, p->value.c.cdr);
209
delete_object(instance, p);
212
static struct alisp_object * incref_object(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * p)
214
if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
216
if (alisp_get_refs(p) == ALISP_MAX_REFS) {
218
fprintf(stderr, "OOPS: alsa lisp: incref fatal error\n");
225
static struct alisp_object * incref_tree(struct alisp_instance *instance, struct alisp_object * p)
229
if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
230
incref_tree(instance, p->value.c.car);
231
incref_tree(instance, p->value.c.cdr);
233
return incref_object(instance, p);
236
/* Function not used yet. Leave it commented out until we actually use it to
237
* avoid compiler complaints */
239
static struct alisp_object * incref_tree_explicit(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * e)
243
if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
245
incref_tree(instance, p->value.c.car);
246
incref_tree(instance, p->value.c.cdr);
248
incref_tree_explicit(instance, p->value.c.car, e);
249
incref_tree_explicit(instance, p->value.c.cdr, e);
253
return incref_object(instance, p);
258
static void free_objects(struct alisp_instance *instance)
260
struct list_head *pos, *pos1;
261
struct alisp_object * p;
262
struct alisp_object_pair * pair;
265
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
266
list_for_each_safe(pos, pos1, &instance->setobjs_list[i]) {
267
pair = list_entry(pos, struct alisp_object_pair, list);
268
lisp_debug(instance, "freeing pair: '%s' -> %p", pair->name, pair->value);
269
delete_tree(instance, pair->value);
270
free((void *)pair->name);
274
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
275
for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++) {
276
list_for_each_safe(pos, pos1, &instance->used_objs_list[i][j]) {
277
p = list_entry(pos, struct alisp_object, list);
278
lisp_warn(instance, "object %p is still referenced %i times!", p, alisp_get_refs(p));
280
snd_output_printf(instance->wout, ">>>> ");
281
princ_object(instance->wout, p);
282
snd_output_printf(instance->wout, " <<<<\n");
284
if (alisp_get_refs(p) > 0)
285
alisp_set_refs(p, 1);
286
delete_object(instance, p);
289
list_for_each_safe(pos, pos1, &instance->free_objs_list) {
290
p = list_entry(pos, struct alisp_object, list);
293
lisp_debug(instance, "freed (all) cons %p", p);
297
static struct alisp_object * search_object_identifier(struct alisp_instance *instance, const char *s)
299
struct list_head * pos;
300
struct alisp_object * p;
302
list_for_each(pos, &instance->used_objs_list[get_string_hash(s)][ALISP_OBJ_IDENTIFIER]) {
303
p = list_entry(pos, struct alisp_object, list);
304
if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
306
if (!strcmp(p->value.s, s))
307
return incref_object(instance, p);
313
static struct alisp_object * search_object_string(struct alisp_instance *instance, const char *s)
315
struct list_head * pos;
316
struct alisp_object * p;
318
list_for_each(pos, &instance->used_objs_list[get_string_hash(s)][ALISP_OBJ_STRING]) {
319
p = list_entry(pos, struct alisp_object, list);
320
if (!strcmp(p->value.s, s)) {
321
if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
323
return incref_object(instance, p);
330
static struct alisp_object * search_object_integer(struct alisp_instance *instance, long in)
332
struct list_head * pos;
333
struct alisp_object * p;
335
list_for_each(pos, &instance->used_objs_list[in & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_INTEGER]) {
336
p = list_entry(pos, struct alisp_object, list);
337
if (p->value.i == in) {
338
if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
340
return incref_object(instance, p);
347
static struct alisp_object * search_object_float(struct alisp_instance *instance, double in)
349
struct list_head * pos;
350
struct alisp_object * p;
352
list_for_each(pos, &instance->used_objs_list[(long)in & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_FLOAT]) {
353
p = list_entry(pos, struct alisp_object, list);
354
if (p->value.i == in) {
355
if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
357
return incref_object(instance, p);
364
static struct alisp_object * search_object_pointer(struct alisp_instance *instance, const void *ptr)
366
struct list_head * pos;
367
struct alisp_object * p;
369
list_for_each(pos, &instance->used_objs_list[(long)ptr & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_POINTER]) {
370
p = list_entry(pos, struct alisp_object, list);
371
if (p->value.ptr == ptr) {
372
if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
374
return incref_object(instance, p);
381
static struct alisp_object * new_integer(struct alisp_instance *instance, long value)
383
struct alisp_object * obj;
385
obj = search_object_integer(instance, value);
388
obj = new_object(instance, ALISP_OBJ_INTEGER);
390
list_add(&obj->list, &instance->used_objs_list[value & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_INTEGER]);
391
obj->value.i = value;
396
static struct alisp_object * new_float(struct alisp_instance *instance, double value)
398
struct alisp_object * obj;
400
obj = search_object_float(instance, value);
403
obj = new_object(instance, ALISP_OBJ_FLOAT);
405
list_add(&obj->list, &instance->used_objs_list[(long)value & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_FLOAT]);
406
obj->value.f = value;
411
static struct alisp_object * new_string(struct alisp_instance *instance, const char *str)
413
struct alisp_object * obj;
415
obj = search_object_string(instance, str);
418
obj = new_object(instance, ALISP_OBJ_STRING);
420
list_add(&obj->list, &instance->used_objs_list[get_string_hash(str)][ALISP_OBJ_STRING]);
421
if (obj && (obj->value.s = strdup(str)) == NULL) {
422
delete_object(instance, obj);
429
static struct alisp_object * new_identifier(struct alisp_instance *instance, const char *id)
431
struct alisp_object * obj;
433
obj = search_object_identifier(instance, id);
436
obj = new_object(instance, ALISP_OBJ_IDENTIFIER);
438
list_add(&obj->list, &instance->used_objs_list[get_string_hash(id)][ALISP_OBJ_IDENTIFIER]);
439
if (obj && (obj->value.s = strdup(id)) == NULL) {
440
delete_object(instance, obj);
447
static struct alisp_object * new_pointer(struct alisp_instance *instance, const void *ptr)
449
struct alisp_object * obj;
451
obj = search_object_pointer(instance, ptr);
454
obj = new_object(instance, ALISP_OBJ_POINTER);
456
list_add(&obj->list, &instance->used_objs_list[(long)ptr & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_POINTER]);
457
obj->value.ptr = ptr;
462
static struct alisp_object * new_cons_pointer(struct alisp_instance * instance, const char *ptr_id, void *ptr)
464
struct alisp_object * lexpr;
467
return &alsa_lisp_nil;
468
lexpr = new_object(instance, ALISP_OBJ_CONS);
471
lexpr->value.c.car = new_string(instance, ptr_id);
472
if (lexpr->value.c.car == NULL)
474
lexpr->value.c.cdr = new_pointer(instance, ptr);
475
if (lexpr->value.c.cdr == NULL) {
476
delete_object(instance, lexpr->value.c.car);
478
delete_object(instance, lexpr);
484
void alsa_lisp_init_objects(void) __attribute__ ((constructor));
486
void alsa_lisp_init_objects(void)
488
memset(&alsa_lisp_nil, 0, sizeof(alsa_lisp_nil));
489
alisp_set_type(&alsa_lisp_nil, ALISP_OBJ_NIL);
490
INIT_LIST_HEAD(&alsa_lisp_nil.list);
491
memset(&alsa_lisp_t, 0, sizeof(alsa_lisp_t));
492
alisp_set_type(&alsa_lisp_t, ALISP_OBJ_T);
493
INIT_LIST_HEAD(&alsa_lisp_t.list);
500
static int xgetc(struct alisp_instance *instance)
503
if (instance->lex_bufp > instance->lex_buf)
504
return *--(instance->lex_bufp);
505
return snd_input_getc(instance->in);
508
static inline void xungetc(struct alisp_instance *instance, int c)
510
*(instance->lex_bufp)++ = c;
514
static int init_lex(struct alisp_instance *instance)
516
instance->charno = instance->lineno = 1;
517
instance->token_buffer_max = 10;
518
if ((instance->token_buffer = (char *)malloc(instance->token_buffer_max)) == NULL) {
522
instance->lex_bufp = instance->lex_buf;
526
static void done_lex(struct alisp_instance *instance)
528
free(instance->token_buffer);
531
static char * extend_buf(struct alisp_instance *instance, char *p)
533
int off = p - instance->token_buffer;
535
instance->token_buffer_max += 10;
536
instance->token_buffer = (char *)realloc(instance->token_buffer, instance->token_buffer_max);
537
if (instance->token_buffer == NULL) {
542
return instance->token_buffer + off;
545
static int gettoken(struct alisp_instance *instance)
557
case ' ': case '\f': case '\t': case '\v': case '\r':
561
/* Comment: ";".*"\n" */
562
while ((c = xgetc(instance)) != '\n' && c != EOF)
569
/* Character: "?". */
571
sprintf(instance->token_buffer, "%d", c);
572
return instance->thistoken = ALISP_INTEGER;
575
/* Minus sign: "-". */
578
xungetc(instance, c);
582
xungetc(instance, c);
587
case '1': case '2': case '3':
588
case '4': case '5': case '6':
589
case '7': case '8': case '9':
590
/* Integer: [0-9]+ */
591
p = instance->token_buffer;
592
instance->thistoken = ALISP_INTEGER;
595
if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
596
p = extend_buf(instance, p);
598
return instance->thistoken = EOF;
602
if (c == '.' && instance->thistoken == ALISP_INTEGER) {
604
xungetc(instance, c);
606
instance->thistoken = ALISP_FLOAT;
612
} else if (c == 'e' && instance->thistoken == ALISP_FLOAT) {
615
instance->thistoken = ALISP_FLOATE;
619
} while (isdigit(c));
620
xungetc(instance, c);
622
return instance->thistoken;
625
case '!': case '_': case '+': case '*': case '/': case '%':
626
case '<': case '>': case '=': case '&':
627
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
628
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
629
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
630
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
632
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
633
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
634
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
635
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
637
/* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */
638
p = instance->token_buffer;
640
if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
641
p = extend_buf(instance, p);
643
return instance->thistoken = EOF;
647
} while (isalnum(c) || strchr("!_-+*/%<>=&", c) != NULL);
648
xungetc(instance, c);
650
return instance->thistoken = ALISP_IDENTIFIER;
653
/* String: "\""([^"]|"\\".)*"\"" */
654
p = instance->token_buffer;
655
while ((c = xgetc(instance)) != '"' && c != EOF) {
656
if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
657
p = extend_buf(instance, p);
659
return instance->thistoken = EOF;
664
case '\n': ++instance->lineno; break;
665
case 'a': *p++ = '\a'; break;
666
case 'b': *p++ = '\b'; break;
667
case 'f': *p++ = '\f'; break;
668
case 'n': *p++ = '\n'; break;
669
case 'r': *p++ = '\r'; break;
670
case 't': *p++ = '\t'; break;
671
case 'v': *p++ = '\v'; break;
681
return instance->thistoken = ALISP_STRING;
684
return instance->thistoken = c;
693
static struct alisp_object * parse_form(struct alisp_instance *instance)
696
struct alisp_object * p, * first = NULL, * prev = NULL;
698
while ((thistoken = gettoken(instance)) != ')' && thistoken != EOF) {
700
* Parse a dotted pair notation.
702
if (thistoken == '.') {
705
lisp_error(instance, "unexpected '.'");
707
delete_tree(instance, first);
710
prev->value.c.cdr = parse_object(instance, 1);
711
if (prev->value.c.cdr == NULL)
713
if ((thistoken = gettoken(instance)) != ')') {
714
lisp_error(instance, "expected ')'");
720
p = new_object(instance, ALISP_OBJ_CONS);
727
prev->value.c.cdr = p;
729
p->value.c.car = parse_object(instance, 1);
730
if (p->value.c.car == NULL)
737
return &alsa_lisp_nil;
742
static struct alisp_object * quote_object(struct alisp_instance *instance, struct alisp_object * obj)
744
struct alisp_object * p;
749
p = new_object(instance, ALISP_OBJ_CONS);
753
p->value.c.car = new_identifier(instance, "quote");
754
if (p->value.c.car == NULL)
756
p->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
757
if (p->value.c.cdr == NULL) {
758
delete_object(instance, p->value.c.car);
760
delete_object(instance, p);
762
delete_tree(instance, obj);
766
p->value.c.cdr->value.c.car = obj;
770
static inline struct alisp_object * parse_quote(struct alisp_instance *instance)
772
return quote_object(instance, parse_object(instance, 0));
775
static struct alisp_object * parse_object(struct alisp_instance *instance, int havetoken)
778
struct alisp_object * p = NULL;
781
thistoken = gettoken(instance);
783
thistoken = instance->thistoken;
789
p = parse_form(instance);
792
p = parse_quote(instance);
794
case ALISP_IDENTIFIER:
795
if (!strcmp(instance->token_buffer, "t"))
797
else if (!strcmp(instance->token_buffer, "nil"))
800
p = new_identifier(instance, instance->token_buffer);
803
case ALISP_INTEGER: {
804
p = new_integer(instance, atol(instance->token_buffer));
809
p = new_float(instance, atof(instance->token_buffer));
813
p = new_string(instance, instance->token_buffer);
816
lisp_warn(instance, "%d:%d: unexpected character `%c'", instance->lineno, instance->charno, thistoken);
824
* object manipulation
827
static struct alisp_object_pair * set_object_direct(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * value)
829
struct alisp_object_pair *p;
833
p = (struct alisp_object_pair *)malloc(sizeof(struct alisp_object_pair));
838
p->name = strdup(id);
839
if (p->name == NULL) {
840
delete_tree(instance, value);
844
list_add(&p->list, &instance->setobjs_list[get_string_hash(id)]);
849
static int check_set_object(struct alisp_instance * instance, struct alisp_object * name)
851
if (name == &alsa_lisp_nil) {
852
lisp_warn(instance, "setting the value of a nil object");
855
if (name == &alsa_lisp_t) {
856
lisp_warn(instance, "setting the value of a t object");
859
if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
860
!alisp_compare_type(name, ALISP_OBJ_STRING)) {
861
lisp_warn(instance, "setting the value of an object with non-indentifier");
867
static struct alisp_object_pair * set_object(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * value)
869
struct list_head *pos;
870
struct alisp_object_pair *p;
873
if (name == NULL || value == NULL)
878
list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
879
p = list_entry(pos, struct alisp_object_pair, list);
880
if (!strcmp(p->name, id)) {
881
delete_tree(instance, p->value);
887
p = (struct alisp_object_pair *)malloc(sizeof(struct alisp_object_pair));
892
p->name = strdup(id);
893
if (p->name == NULL) {
894
delete_tree(instance, value);
898
list_add(&p->list, &instance->setobjs_list[get_string_hash(id)]);
903
static struct alisp_object * unset_object(struct alisp_instance *instance, struct alisp_object * name)
905
struct list_head *pos;
906
struct alisp_object *res;
907
struct alisp_object_pair *p;
910
if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
911
!alisp_compare_type(name, ALISP_OBJ_STRING)) {
912
lisp_warn(instance, "unset object with a non-indentifier");
913
return &alsa_lisp_nil;
917
list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
918
p = list_entry(pos, struct alisp_object_pair, list);
919
if (!strcmp(p->name, id)) {
922
free((void *)p->name);
928
return &alsa_lisp_nil;
931
static struct alisp_object * get_object1(struct alisp_instance *instance, const char *id)
933
struct alisp_object_pair *p;
934
struct list_head *pos;
936
list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
937
p = list_entry(pos, struct alisp_object_pair, list);
938
if (!strcmp(p->name, id))
942
return &alsa_lisp_nil;
945
static struct alisp_object * get_object(struct alisp_instance *instance, struct alisp_object * name)
947
if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
948
!alisp_compare_type(name, ALISP_OBJ_STRING)) {
949
delete_tree(instance, name);
950
return &alsa_lisp_nil;
952
return get_object1(instance, name->value.s);
955
static struct alisp_object * replace_object(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * onew)
957
struct alisp_object_pair *p;
958
struct alisp_object *r;
959
struct list_head *pos;
962
if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
963
!alisp_compare_type(name, ALISP_OBJ_STRING)) {
964
delete_tree(instance, name);
965
return &alsa_lisp_nil;
968
list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
969
p = list_entry(pos, struct alisp_object_pair, list);
970
if (!strcmp(p->name, id)) {
980
static void dump_objects(struct alisp_instance *instance, const char *fname)
982
struct alisp_object_pair *p;
984
struct list_head *pos;
987
if (!strcmp(fname, "-"))
988
err = snd_output_stdio_attach(&out, stdout, 0);
990
err = snd_output_stdio_open(&out, fname, "w+");
992
SNDERR("alisp: cannot open file '%s' for writting (%s)", fname, snd_strerror(errno));
996
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
997
list_for_each(pos, &instance->setobjs_list[i]) {
998
p = list_entry(pos, struct alisp_object_pair, list);
999
if (alisp_compare_type(p->value, ALISP_OBJ_CONS) &&
1000
alisp_compare_type(p->value->value.c.car, ALISP_OBJ_IDENTIFIER) &&
1001
!strcmp(p->value->value.c.car->value.s, "lambda")) {
1002
snd_output_printf(out, "(defun %s ", p->name);
1003
princ_cons(out, p->value->value.c.cdr);
1004
snd_output_printf(out, ")\n");
1007
snd_output_printf(out, "(setq %s '", p->name);
1008
princ_object(out, p->value);
1009
snd_output_printf(out, ")\n");
1012
snd_output_close(out);
1015
static const char *obj_type_str(struct alisp_object * p)
1017
switch (alisp_get_type(p)) {
1018
case ALISP_OBJ_NIL: return "nil";
1019
case ALISP_OBJ_T: return "t";
1020
case ALISP_OBJ_INTEGER: return "integer";
1021
case ALISP_OBJ_FLOAT: return "float";
1022
case ALISP_OBJ_IDENTIFIER: return "identifier";
1023
case ALISP_OBJ_STRING: return "string";
1024
case ALISP_OBJ_POINTER: return "pointer";
1025
case ALISP_OBJ_CONS: return "cons";
1030
static void print_obj_lists(struct alisp_instance *instance, snd_output_t *out)
1032
struct list_head *pos;
1033
struct alisp_object * p;
1036
snd_output_printf(out, "** used objects\n");
1037
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
1038
for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++)
1039
list_for_each(pos, &instance->used_objs_list[i][j]) {
1040
p = list_entry(pos, struct alisp_object, list);
1041
snd_output_printf(out, "** %p (%s) (", p, obj_type_str(p));
1042
if (!alisp_compare_type(p, ALISP_OBJ_CONS))
1043
princ_object(out, p);
1045
snd_output_printf(out, "cons");
1046
snd_output_printf(out, ") refs=%i\n", alisp_get_refs(p));
1048
snd_output_printf(out, "** free objects\n");
1049
list_for_each(pos, &instance->free_objs_list) {
1050
p = list_entry(pos, struct alisp_object, list);
1051
snd_output_printf(out, "** %p\n", p);
1055
static void dump_obj_lists(struct alisp_instance *instance, const char *fname)
1060
if (!strcmp(fname, "-"))
1061
err = snd_output_stdio_attach(&out, stdout, 0);
1063
err = snd_output_stdio_open(&out, fname, "w+");
1065
SNDERR("alisp: cannot open file '%s' for writting (%s)", fname, snd_strerror(errno));
1069
print_obj_lists(instance, out);
1071
snd_output_close(out);
1078
static int count_list(struct alisp_object * p)
1082
while (p != &alsa_lisp_nil && alisp_compare_type(p, ALISP_OBJ_CONS)) {
1090
static inline struct alisp_object * car(struct alisp_object * p)
1092
if (alisp_compare_type(p, ALISP_OBJ_CONS))
1093
return p->value.c.car;
1095
return &alsa_lisp_nil;
1098
static inline struct alisp_object * cdr(struct alisp_object * p)
1100
if (alisp_compare_type(p, ALISP_OBJ_CONS))
1101
return p->value.c.cdr;
1103
return &alsa_lisp_nil;
1107
* Syntax: (car expr)
1109
static struct alisp_object * F_car(struct alisp_instance *instance, struct alisp_object * args)
1111
struct alisp_object *p1 = car(args), *p2;
1112
delete_tree(instance, cdr(args));
1113
delete_object(instance, args);
1114
p1 = eval(instance, p1);
1115
delete_tree(instance, cdr(p1));
1117
delete_object(instance, p1);
1122
* Syntax: (cdr expr)
1124
static struct alisp_object * F_cdr(struct alisp_instance *instance, struct alisp_object * args)
1126
struct alisp_object *p1 = car(args), *p2;
1127
delete_tree(instance, cdr(args));
1128
delete_object(instance, args);
1129
p1 = eval(instance, p1);
1130
delete_tree(instance, car(p1));
1132
delete_object(instance, p1);
1137
* Syntax: (+ expr...)
1139
static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args)
1141
struct alisp_object * p = args, * p1, * n;
1144
int type = ALISP_OBJ_INTEGER;
1146
p1 = eval(instance, car(p));
1148
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
1149
if (type == ALISP_OBJ_FLOAT)
1153
} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
1154
f += p1->value.f + v;
1156
type = ALISP_OBJ_FLOAT;
1158
lisp_warn(instance, "sum with a non integer or float operand");
1160
delete_tree(instance, p1);
1162
delete_object(instance, n);
1163
if (p == &alsa_lisp_nil)
1165
p1 = eval(instance, car(p));
1167
if (type == ALISP_OBJ_INTEGER) {
1168
return new_integer(instance, v);
1170
return new_float(instance, f);
1175
* Syntax: (concat expr...)
1177
static struct alisp_object * F_concat(struct alisp_instance *instance, struct alisp_object * args)
1179
struct alisp_object * p = args, * p1, * n;
1180
char *str = NULL, *str1;
1182
p1 = eval(instance, car(p));
1184
if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
1185
str1 = realloc(str, (str ? strlen(str) : 0) + strlen(p1->value.s) + 1);
1192
strcpy(str1, p1->value.s);
1194
strcat(str1, p1->value.s);
1197
lisp_warn(instance, "concat with a non string or identifier operand");
1199
delete_tree(instance, p1);
1201
delete_object(instance, n);
1202
if (p == &alsa_lisp_nil)
1204
p1 = eval(instance, car(p));
1207
p = new_string(instance, str);
1216
* Syntax: (- expr...)
1218
static struct alisp_object * F_sub(struct alisp_instance *instance, struct alisp_object * args)
1220
struct alisp_object * p = args, * p1, * n;
1223
int type = ALISP_OBJ_INTEGER;
1226
p1 = eval(instance, car(p));
1227
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
1228
if (p == args && cdr(p) != &alsa_lisp_nil) {
1231
if (type == ALISP_OBJ_FLOAT)
1236
} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
1237
if (type == ALISP_OBJ_INTEGER) {
1239
type = ALISP_OBJ_FLOAT;
1241
if (p == args && cdr(p) != &alsa_lisp_nil)
1247
lisp_warn(instance, "difference with a non integer or float operand");
1248
delete_tree(instance, p1);
1250
delete_object(instance, p);
1252
} while (p != &alsa_lisp_nil);
1254
if (type == ALISP_OBJ_INTEGER) {
1255
return new_integer(instance, v);
1257
return new_float(instance, f);
1262
* Syntax: (* expr...)
1264
static struct alisp_object * F_mul(struct alisp_instance *instance, struct alisp_object * args)
1266
struct alisp_object * p = args, * p1, * n;
1269
int type = ALISP_OBJ_INTEGER;
1272
p1 = eval(instance, car(p));
1273
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
1274
if (type == ALISP_OBJ_FLOAT)
1278
} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
1279
f *= p1->value.f * v; v = 1;
1280
type = ALISP_OBJ_FLOAT;
1282
lisp_warn(instance, "product with a non integer or float operand");
1284
delete_tree(instance, p1);
1286
delete_object(instance, p);
1288
} while (p != &alsa_lisp_nil);
1290
if (type == ALISP_OBJ_INTEGER) {
1291
return new_integer(instance, v);
1293
return new_float(instance, f);
1298
* Syntax: (/ expr...)
1300
static struct alisp_object * F_div(struct alisp_instance *instance, struct alisp_object * args)
1302
struct alisp_object * p = args, * p1, * n;
1305
int type = ALISP_OBJ_INTEGER;
1308
p1 = eval(instance, car(p));
1309
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
1310
if (p == args && cdr(p) != &alsa_lisp_nil) {
1313
if (p1->value.i == 0) {
1314
lisp_warn(instance, "division by zero");
1319
if (type == ALISP_OBJ_FLOAT)
1325
} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
1326
if (type == ALISP_OBJ_INTEGER) {
1328
type = ALISP_OBJ_FLOAT;
1330
if (p == args && cdr(p) != &alsa_lisp_nil) {
1333
if (p1->value.f == 0) {
1334
lisp_warn(instance, "division by zero");
1342
lisp_warn(instance, "quotient with a non integer or float operand");
1343
delete_tree(instance, p1);
1345
delete_object(instance, p);
1347
} while (p != &alsa_lisp_nil);
1349
if (type == ALISP_OBJ_INTEGER) {
1350
return new_integer(instance, v);
1352
return new_float(instance, f);
1357
* Syntax: (% expr1 expr2)
1359
static struct alisp_object * F_mod(struct alisp_instance *instance, struct alisp_object * args)
1361
struct alisp_object * p1, * p2, * p3;
1363
p1 = eval(instance, car(args));
1364
p2 = eval(instance, car(cdr(args)));
1365
delete_tree(instance, cdr(cdr(args)));
1366
delete_object(instance, cdr(args));
1367
delete_object(instance, args);
1369
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1370
alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1371
if (p2->value.i == 0) {
1372
lisp_warn(instance, "module by zero");
1373
p3 = new_integer(instance, 0);
1375
p3 = new_integer(instance, p1->value.i % p2->value.i);
1377
} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1378
alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1379
(alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1380
alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1382
f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1383
f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1386
lisp_warn(instance, "module by zero");
1387
p3 = new_float(instance, 0);
1389
p3 = new_float(instance, f1);
1392
lisp_warn(instance, "module with a non integer or float operand");
1393
delete_tree(instance, p1);
1394
delete_tree(instance, p2);
1395
return &alsa_lisp_nil;
1398
delete_tree(instance, p1);
1399
delete_tree(instance, p2);
1404
* Syntax: (< expr1 expr2)
1406
static struct alisp_object * F_lt(struct alisp_instance *instance, struct alisp_object * args)
1408
struct alisp_object * p1, * p2;
1410
p1 = eval(instance, car(args));
1411
p2 = eval(instance, car(cdr(args)));
1412
delete_tree(instance, cdr(cdr(args)));
1413
delete_object(instance, cdr(args));
1414
delete_object(instance, args);
1416
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1417
alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1418
if (p1->value.i < p2->value.i) {
1420
delete_tree(instance, p1);
1421
delete_tree(instance, p2);
1422
return &alsa_lisp_t;
1424
} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1425
alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1426
(alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1427
alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1429
f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1430
f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1434
lisp_warn(instance, "comparison with a non integer or float operand");
1437
delete_tree(instance, p1);
1438
delete_tree(instance, p2);
1439
return &alsa_lisp_nil;
1443
* Syntax: (> expr1 expr2)
1445
static struct alisp_object * F_gt(struct alisp_instance *instance, struct alisp_object * args)
1447
struct alisp_object * p1, * p2;
1449
p1 = eval(instance, car(args));
1450
p2 = eval(instance, car(cdr(args)));
1451
delete_tree(instance, cdr(cdr(args)));
1452
delete_object(instance, cdr(args));
1453
delete_object(instance, args);
1455
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1456
alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1457
if (p1->value.i > p2->value.i) {
1459
delete_tree(instance, p1);
1460
delete_tree(instance, p2);
1461
return &alsa_lisp_t;
1463
} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1464
alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1465
(alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1466
alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1468
f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1469
f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1473
lisp_warn(instance, "comparison with a non integer or float operand");
1476
delete_tree(instance, p1);
1477
delete_tree(instance, p2);
1478
return &alsa_lisp_nil;
1482
* Syntax: (<= expr1 expr2)
1484
static struct alisp_object * F_le(struct alisp_instance *instance, struct alisp_object * args)
1486
struct alisp_object * p1, * p2;
1488
p1 = eval(instance, car(args));
1489
p2 = eval(instance, car(cdr(args)));
1490
delete_tree(instance, cdr(cdr(args)));
1491
delete_object(instance, cdr(args));
1492
delete_object(instance, args);
1494
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1495
alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1496
if (p1->value.i <= p2->value.i) {
1498
delete_tree(instance, p1);
1499
delete_tree(instance, p2);
1500
return &alsa_lisp_t;
1502
} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1503
alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1504
(alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1505
alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1507
f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1508
f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1512
lisp_warn(instance, "comparison with a non integer or float operand");
1515
delete_tree(instance, p1);
1516
delete_tree(instance, p2);
1517
return &alsa_lisp_nil;
1521
* Syntax: (>= expr1 expr2)
1523
static struct alisp_object * F_ge(struct alisp_instance *instance, struct alisp_object * args)
1525
struct alisp_object * p1, * p2;
1527
p1 = eval(instance, car(args));
1528
p2 = eval(instance, car(cdr(args)));
1529
delete_tree(instance, cdr(cdr(args)));
1530
delete_object(instance, cdr(args));
1531
delete_object(instance, args);
1533
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1534
alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1535
if (p1->value.i >= p2->value.i) {
1537
delete_tree(instance, p1);
1538
delete_tree(instance, p2);
1539
return &alsa_lisp_t;
1541
} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1542
alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1543
(alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1544
alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1546
f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1547
f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1551
lisp_warn(instance, "comparison with a non integer or float operand");
1554
delete_tree(instance, p1);
1555
delete_tree(instance, p2);
1556
return &alsa_lisp_nil;
1560
* Syntax: (= expr1 expr2)
1562
static struct alisp_object * F_numeq(struct alisp_instance *instance, struct alisp_object * args)
1564
struct alisp_object * p1, * p2;
1566
p1 = eval(instance, car(args));
1567
p2 = eval(instance, car(cdr(args)));
1568
delete_tree(instance, cdr(cdr(args)));
1569
delete_object(instance, cdr(args));
1570
delete_object(instance, args);
1572
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
1573
alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
1574
if (p1->value.i == p2->value.i) {
1576
delete_tree(instance, p1);
1577
delete_tree(instance, p2);
1578
return &alsa_lisp_t;
1580
} else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
1581
alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
1582
(alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
1583
alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
1585
f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
1586
f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
1590
lisp_warn(instance, "comparison with a non integer or float operand");
1593
delete_tree(instance, p1);
1594
delete_tree(instance, p2);
1595
return &alsa_lisp_nil;
1599
* Syntax: (!= expr1 expr2)
1601
static struct alisp_object * F_numneq(struct alisp_instance *instance, struct alisp_object * args)
1603
struct alisp_object * p;
1605
p = F_numeq(instance, args);
1606
if (p == &alsa_lisp_nil)
1607
return &alsa_lisp_t;
1608
return &alsa_lisp_nil;
1612
* Syntax: (exfun name)
1613
* Test, if a function exists
1615
static struct alisp_object * F_exfun(struct alisp_instance *instance, struct alisp_object * args)
1617
struct alisp_object * p1, * p2;
1619
p1 = eval(instance, car(args));
1620
delete_tree(instance, cdr(args));
1621
delete_object(instance, args);
1622
p2 = get_object(instance, p1);
1623
if (p2 == &alsa_lisp_nil) {
1624
delete_tree(instance, p1);
1625
return &alsa_lisp_nil;
1628
if (alisp_compare_type(p2, ALISP_OBJ_IDENTIFIER) &&
1629
!strcmp(p2->value.s, "lambda")) {
1630
delete_tree(instance, p1);
1631
return &alsa_lisp_t;
1633
delete_tree(instance, p1);
1634
return &alsa_lisp_nil;
1637
static void princ_string(snd_output_t *out, char *s)
1641
snd_output_putc(out, '"');
1642
for (p = s; *p != '\0'; ++p)
1644
case '\a': snd_output_putc(out, '\\'); snd_output_putc(out, 'a'); break;
1645
case '\b': snd_output_putc(out, '\\'); snd_output_putc(out, 'b'); break;
1646
case '\f': snd_output_putc(out, '\\'); snd_output_putc(out, 'f'); break;
1647
case '\n': snd_output_putc(out, '\\'); snd_output_putc(out, 'n'); break;
1648
case '\r': snd_output_putc(out, '\\'); snd_output_putc(out, 'r'); break;
1649
case '\t': snd_output_putc(out, '\\'); snd_output_putc(out, 't'); break;
1650
case '\v': snd_output_putc(out, '\\'); snd_output_putc(out, 'v'); break;
1651
case '"': snd_output_putc(out, '\\'); snd_output_putc(out, '"'); break;
1652
default: snd_output_putc(out, *p);
1654
snd_output_putc(out, '"');
1657
static void princ_cons(snd_output_t *out, struct alisp_object * p)
1660
princ_object(out, p->value.c.car);
1662
if (p != &alsa_lisp_nil) {
1663
snd_output_putc(out, ' ');
1664
if (!alisp_compare_type(p, ALISP_OBJ_CONS)) {
1665
snd_output_printf(out, ". ");
1666
princ_object(out, p);
1669
} while (p != &alsa_lisp_nil && alisp_compare_type(p, ALISP_OBJ_CONS));
1672
static void princ_object(snd_output_t *out, struct alisp_object * p)
1674
switch (alisp_get_type(p)) {
1676
snd_output_printf(out, "nil");
1679
snd_output_putc(out, 't');
1681
case ALISP_OBJ_IDENTIFIER:
1682
snd_output_printf(out, "%s", p->value.s);
1684
case ALISP_OBJ_STRING:
1685
princ_string(out, p->value.s);
1687
case ALISP_OBJ_INTEGER:
1688
snd_output_printf(out, "%ld", p->value.i);
1690
case ALISP_OBJ_FLOAT:
1691
snd_output_printf(out, "%f", p->value.f);
1693
case ALISP_OBJ_POINTER:
1694
snd_output_printf(out, "<%p>", p->value.ptr);
1696
case ALISP_OBJ_CONS:
1697
snd_output_putc(out, '(');
1699
snd_output_putc(out, ')');
1704
* Syntax: (princ expr...)
1706
static struct alisp_object * F_princ(struct alisp_instance *instance, struct alisp_object * args)
1708
struct alisp_object * p = args, * p1 = NULL, * n;
1712
delete_tree(instance, p1);
1713
p1 = eval(instance, car(p));
1714
if (alisp_compare_type(p1, ALISP_OBJ_STRING))
1715
snd_output_printf(instance->out, p1->value.s);
1717
princ_object(instance->out, p1);
1719
delete_object(instance, p);
1721
} while (p != &alsa_lisp_nil);
1727
* Syntax: (atom expr)
1729
static struct alisp_object * F_atom(struct alisp_instance *instance, struct alisp_object * args)
1731
struct alisp_object * p;
1733
p = eval(instance, car(args));
1734
delete_tree(instance, cdr(args));
1735
delete_object(instance, args);
1739
switch (alisp_get_type(p)) {
1742
case ALISP_OBJ_INTEGER:
1743
case ALISP_OBJ_FLOAT:
1744
case ALISP_OBJ_STRING:
1745
case ALISP_OBJ_IDENTIFIER:
1746
case ALISP_OBJ_POINTER:
1747
delete_tree(instance, p);
1748
return &alsa_lisp_t;
1753
delete_tree(instance, p);
1754
return &alsa_lisp_nil;
1758
* Syntax: (cons expr1 expr2)
1760
static struct alisp_object * F_cons(struct alisp_instance *instance, struct alisp_object * args)
1762
struct alisp_object * p;
1764
p = new_object(instance, ALISP_OBJ_CONS);
1766
p->value.c.car = eval(instance, car(args));
1767
p->value.c.cdr = eval(instance, car(cdr(args)));
1768
delete_tree(instance, cdr(cdr(args)));
1769
delete_object(instance, cdr(args));
1770
delete_object(instance, args);
1772
delete_tree(instance, args);
1779
* Syntax: (list expr1...)
1781
static struct alisp_object * F_list(struct alisp_instance *instance, struct alisp_object * args)
1783
struct alisp_object * p = args, * first = NULL, * prev = NULL, * p1;
1785
if (p == &alsa_lisp_nil)
1786
return &alsa_lisp_nil;
1789
p1 = new_object(instance, ALISP_OBJ_CONS);
1791
delete_tree(instance, p);
1792
delete_tree(instance, first);
1795
p1->value.c.car = eval(instance, car(p));
1796
if (p1->value.c.car == NULL) {
1797
delete_tree(instance, first);
1798
delete_tree(instance, cdr(p));
1799
delete_object(instance, p);
1805
prev->value.c.cdr = p1;
1808
delete_object(instance, p1);
1809
} while (p != &alsa_lisp_nil);
1814
static inline int eq(struct alisp_object * p1, struct alisp_object * p2)
1819
static int equal(struct alisp_object * p1, struct alisp_object * p2)
1826
type1 = alisp_get_type(p1);
1827
type2 = alisp_get_type(p2);
1829
if (type1 == ALISP_OBJ_CONS || type2 == ALISP_OBJ_CONS)
1832
if (type1 == type2) {
1834
case ALISP_OBJ_STRING:
1835
return !strcmp(p1->value.s, p2->value.s);
1836
case ALISP_OBJ_INTEGER:
1837
return p1->value.i == p2->value.i;
1838
case ALISP_OBJ_FLOAT:
1839
return p1->value.i == p2->value.i;
1847
* Syntax: (eq expr1 expr2)
1849
static struct alisp_object * F_eq(struct alisp_instance *instance, struct alisp_object * args)
1851
struct alisp_object * p1, * p2;
1853
p1 = eval(instance, car(args));
1854
p2 = eval(instance, car(cdr(args)));
1855
delete_tree(instance, cdr(cdr(args)));
1856
delete_object(instance, cdr(args));
1857
delete_object(instance, args);
1860
delete_tree(instance, p1);
1861
delete_tree(instance, p2);
1862
return &alsa_lisp_t;
1864
delete_tree(instance, p1);
1865
delete_tree(instance, p2);
1866
return &alsa_lisp_nil;
1870
* Syntax: (equal expr1 expr2)
1872
static struct alisp_object * F_equal(struct alisp_instance *instance, struct alisp_object * args)
1874
struct alisp_object * p1, * p2;
1876
p1 = eval(instance, car(args));
1877
p2 = eval(instance, car(cdr(args)));
1878
delete_tree(instance, cdr(cdr(args)));
1879
delete_object(instance, cdr(args));
1880
delete_object(instance, args);
1882
if (equal(p1, p2)) {
1883
delete_tree(instance, p1);
1884
delete_tree(instance, p2);
1885
return &alsa_lisp_t;
1887
delete_tree(instance, p1);
1888
delete_tree(instance, p2);
1889
return &alsa_lisp_nil;
1893
* Syntax: (quote expr)
1895
static struct alisp_object * F_quote(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args)
1897
struct alisp_object *p = car(args);
1899
delete_tree(instance, cdr(args));
1900
delete_object(instance, args);
1905
* Syntax: (and expr...)
1907
static struct alisp_object * F_and(struct alisp_instance *instance, struct alisp_object * args)
1909
struct alisp_object * p = args, * p1 = NULL, * n;
1913
delete_tree(instance, p1);
1914
p1 = eval(instance, car(p));
1915
if (p1 == &alsa_lisp_nil) {
1916
delete_tree(instance, p1);
1917
delete_tree(instance, cdr(p));
1918
delete_object(instance, p);
1919
return &alsa_lisp_nil;
1922
delete_object(instance, n);
1923
} while (p != &alsa_lisp_nil);
1929
* Syntax: (or expr...)
1931
static struct alisp_object * F_or(struct alisp_instance *instance, struct alisp_object * args)
1933
struct alisp_object * p = args, * p1 = NULL, * n;
1937
delete_tree(instance, p1);
1938
p1 = eval(instance, car(p));
1939
if (p1 != &alsa_lisp_nil) {
1940
delete_tree(instance, cdr(p));
1941
delete_object(instance, p);
1945
delete_object(instance, n);
1946
} while (p != &alsa_lisp_nil);
1948
return &alsa_lisp_nil;
1952
* Syntax: (not expr)
1953
* Syntax: (null expr)
1955
static struct alisp_object * F_not(struct alisp_instance *instance, struct alisp_object * args)
1957
struct alisp_object * p = eval(instance, car(args));
1959
delete_tree(instance, cdr(args));
1960
delete_object(instance, args);
1961
if (p != &alsa_lisp_nil) {
1962
delete_tree(instance, p);
1963
return &alsa_lisp_nil;
1966
delete_tree(instance, p);
1967
return &alsa_lisp_t;
1971
* Syntax: (cond (expr1 [expr2])...)
1973
static struct alisp_object * F_cond(struct alisp_instance *instance, struct alisp_object * args)
1975
struct alisp_object * p = args, * p1, * p2, * p3;
1979
if ((p2 = eval(instance, car(p1))) != &alsa_lisp_nil) {
1981
delete_object(instance, p1);
1982
delete_tree(instance, cdr(p));
1983
delete_object(instance, p);
1984
if (p3 != &alsa_lisp_nil) {
1985
delete_tree(instance, p2);
1986
return F_progn(instance, p3);
1988
delete_tree(instance, p3);
1992
delete_tree(instance, p2);
1993
delete_tree(instance, cdr(p1));
1994
delete_object(instance, p1);
1997
delete_object(instance, p2);
1998
} while (p != &alsa_lisp_nil);
2000
return &alsa_lisp_nil;
2004
* Syntax: (if expr then-expr else-expr...)
2006
static struct alisp_object * F_if(struct alisp_instance *instance, struct alisp_object * args)
2008
struct alisp_object * p1, * p2, * p3;
2011
p2 = car(cdr(args));
2012
p3 = cdr(cdr(args));
2013
delete_object(instance, cdr(args));
2014
delete_object(instance, args);
2016
p1 = eval(instance, p1);
2017
if (p1 != &alsa_lisp_nil) {
2018
delete_tree(instance, p1);
2019
delete_tree(instance, p3);
2020
return eval(instance, p2);
2023
delete_tree(instance, p1);
2024
delete_tree(instance, p2);
2025
return F_progn(instance, p3);
2029
* Syntax: (when expr then-expr...)
2031
static struct alisp_object * F_when(struct alisp_instance *instance, struct alisp_object * args)
2033
struct alisp_object * p1, * p2;
2037
delete_object(instance, args);
2038
if ((p1 = eval(instance, p1)) != &alsa_lisp_nil) {
2039
delete_tree(instance, p1);
2040
return F_progn(instance, p2);
2042
delete_tree(instance, p1);
2043
delete_tree(instance, p2);
2046
return &alsa_lisp_nil;
2050
* Syntax: (unless expr else-expr...)
2052
static struct alisp_object * F_unless(struct alisp_instance *instance, struct alisp_object * args)
2054
struct alisp_object * p1, * p2;
2058
delete_object(instance, args);
2059
if ((p1 = eval(instance, p1)) == &alsa_lisp_nil) {
2060
return F_progn(instance, p2);
2062
delete_tree(instance, p1);
2063
delete_tree(instance, p2);
2066
return &alsa_lisp_nil;
2070
* Syntax: (while expr exprs...)
2072
static struct alisp_object * F_while(struct alisp_instance *instance, struct alisp_object * args)
2074
struct alisp_object * p1, * p2, * p3;
2079
delete_object(instance, args);
2081
incref_tree(instance, p1);
2082
if ((p3 = eval(instance, p1)) == &alsa_lisp_nil)
2084
delete_tree(instance, p3);
2085
incref_tree(instance, p2);
2086
delete_tree(instance, F_progn(instance, p2));
2089
delete_tree(instance, p1);
2090
delete_tree(instance, p2);
2091
return &alsa_lisp_nil;
2095
* Syntax: (progn expr...)
2097
static struct alisp_object * F_progn(struct alisp_instance *instance, struct alisp_object * args)
2099
struct alisp_object * p = args, * p1 = NULL, * n;
2103
delete_tree(instance, p1);
2104
p1 = eval(instance, car(p));
2106
delete_object(instance, p);
2108
} while (p != &alsa_lisp_nil);
2114
* Syntax: (prog1 expr...)
2116
static struct alisp_object * F_prog1(struct alisp_instance *instance, struct alisp_object * args)
2118
struct alisp_object * p = args, * first = NULL, * p1;
2121
p1 = eval(instance, car(p));
2125
delete_tree(instance, p1);
2127
delete_object(instance, p);
2129
} while (p != &alsa_lisp_nil);
2132
first = &alsa_lisp_nil;
2138
* Syntax: (prog2 expr...)
2140
static struct alisp_object * F_prog2(struct alisp_instance *instance, struct alisp_object * args)
2142
struct alisp_object * p = args, * second = NULL, * p1;
2147
p1 = eval(instance, car(p));
2151
delete_tree(instance, p1);
2153
delete_object(instance, p);
2155
} while (p != &alsa_lisp_nil);
2158
second = &alsa_lisp_nil;
2164
* Syntax: (set name value)
2166
static struct alisp_object * F_set(struct alisp_instance *instance, struct alisp_object * args)
2168
struct alisp_object * p1 = eval(instance, car(args)),
2169
* p2 = eval(instance, car(cdr(args)));
2171
delete_tree(instance, cdr(cdr(args)));
2172
delete_object(instance, cdr(args));
2173
delete_object(instance, args);
2174
if (!check_set_object(instance, p1)) {
2175
delete_tree(instance, p2);
2176
p2 = &alsa_lisp_nil;
2178
if (set_object(instance, p1, p2) == NULL) {
2179
delete_tree(instance, p1);
2180
delete_tree(instance, p2);
2184
delete_tree(instance, p1);
2185
return incref_tree(instance, p2);
2189
* Syntax: (unset name)
2191
static struct alisp_object * F_unset(struct alisp_instance *instance, struct alisp_object * args)
2193
struct alisp_object * p1 = eval(instance, car(args));
2195
delete_tree(instance, unset_object(instance, p1));
2196
delete_tree(instance, cdr(args));
2197
delete_object(instance, args);
2202
* Syntax: (setq name value...)
2203
* Syntax: (setf name value...)
2204
* `name' is not evalled
2206
static struct alisp_object * F_setq(struct alisp_instance *instance, struct alisp_object * args)
2208
struct alisp_object * p = args, * p1, * p2 = NULL, *n;
2212
p2 = eval(instance, car(cdr(p)));
2214
delete_object(instance, cdr(p));
2215
delete_object(instance, p);
2216
if (!check_set_object(instance, p1)) {
2217
delete_tree(instance, p2);
2218
p2 = &alsa_lisp_nil;
2220
if (set_object(instance, p1, p2) == NULL) {
2221
delete_tree(instance, p1);
2222
delete_tree(instance, p2);
2226
delete_tree(instance, p1);
2228
} while (p != &alsa_lisp_nil);
2230
return incref_tree(instance, p2);
2234
* Syntax: (unsetq name...)
2235
* Syntax: (unsetf name...)
2236
* `name' is not evalled
2238
static struct alisp_object * F_unsetq(struct alisp_instance *instance, struct alisp_object * args)
2240
struct alisp_object * p = args, * p1 = NULL, * n;
2244
delete_tree(instance, p1);
2245
p1 = unset_object(instance, car(p));
2246
delete_tree(instance, car(p));
2248
delete_object(instance, n);
2249
} while (p != &alsa_lisp_nil);
2255
* Syntax: (defun name arglist expr...)
2256
* `name' is not evalled
2257
* `arglist' is not evalled
2259
static struct alisp_object * F_defun(struct alisp_instance *instance, struct alisp_object * args)
2261
struct alisp_object * p1 = car(args),
2262
* p2 = car(cdr(args)),
2263
* p3 = cdr(cdr(args));
2264
struct alisp_object * lexpr;
2266
lexpr = new_object(instance, ALISP_OBJ_CONS);
2268
lexpr->value.c.car = new_identifier(instance, "lambda");
2269
if (lexpr->value.c.car == NULL) {
2270
delete_object(instance, lexpr);
2271
delete_tree(instance, args);
2274
if ((lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS)) == NULL) {
2275
delete_object(instance, lexpr->value.c.car);
2276
delete_object(instance, lexpr);
2277
delete_tree(instance, args);
2280
lexpr->value.c.cdr->value.c.car = p2;
2281
lexpr->value.c.cdr->value.c.cdr = p3;
2282
delete_object(instance, cdr(args));
2283
delete_object(instance, args);
2284
if (set_object(instance, p1, lexpr) == NULL) {
2285
delete_tree(instance, p1);
2286
delete_tree(instance, lexpr);
2289
delete_tree(instance, p1);
2291
delete_tree(instance, args);
2293
return &alsa_lisp_nil;
2296
static struct alisp_object * eval_func(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * args)
2298
struct alisp_object * p1, * p2, * p3, * p4;
2299
struct alisp_object ** eval_objs, ** save_objs;
2303
if (alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER) &&
2304
!strcmp(p1->value.s, "lambda")) {
2308
if ((i = count_list(p2)) != count_list(p3)) {
2309
lisp_warn(instance, "wrong number of parameters");
2313
eval_objs = malloc(2 * i * sizeof(struct alisp_object *));
2314
if (eval_objs == NULL) {
2318
save_objs = eval_objs + i;
2321
* Save the new variable values.
2324
while (p3 != &alsa_lisp_nil) {
2325
eval_objs[i++] = eval(instance, car(p3));
2327
delete_object(instance, p4);
2331
* Save the old variable values and set the new ones.
2334
while (p2 != &alsa_lisp_nil) {
2336
save_objs[i] = replace_object(instance, p3, eval_objs[i]);
2337
if (save_objs[i] == NULL &&
2338
set_object_direct(instance, p3, eval_objs[i]) == NULL) {
2346
p4 = F_progn(instance, cdr(incref_tree(instance, p3 = cdr(p))));
2349
* Restore the old variable values.
2352
delete_object(instance, p3);
2354
while (p2 != &alsa_lisp_nil) {
2356
if (save_objs[i] == NULL) {
2357
p3 = unset_object(instance, p3);
2359
p3 = replace_object(instance, p3, save_objs[i]);
2362
delete_tree(instance, p3);
2363
delete_tree(instance, car(p2));
2365
delete_object(instance, p3);
2374
delete_tree(instance, args);
2376
return &alsa_lisp_nil;
2379
struct alisp_object * F_gc(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args ATTRIBUTE_UNUSED)
2381
/* improved: no more traditional gc */
2382
return &alsa_lisp_t;
2386
* Syntax: (path what)
2387
* what is string ('data')
2389
struct alisp_object * F_path(struct alisp_instance *instance, struct alisp_object * args)
2391
struct alisp_object * p1;
2393
p1 = eval(instance, car(args));
2394
delete_tree(instance, cdr(args));
2395
delete_object(instance, args);
2396
if (!alisp_compare_type(p1, ALISP_OBJ_STRING)) {
2397
delete_tree(instance, p1);
2398
return &alsa_lisp_nil;
2400
if (!strcmp(p1->value.s, "data")) {
2401
delete_tree(instance, p1);
2402
return new_string(instance, ALSA_CONFIG_DIR);
2404
delete_tree(instance, p1);
2405
return &alsa_lisp_nil;
2409
* Syntax: (include filename...)
2411
struct alisp_object * F_include(struct alisp_instance *instance, struct alisp_object * args)
2413
struct alisp_object * p = args, * p1;
2417
p1 = eval(instance, car(p));
2418
if (alisp_compare_type(p1, ALISP_OBJ_STRING))
2419
res = alisp_include_file(instance, p1->value.s);
2420
delete_tree(instance, p1);
2422
delete_object(instance, p1);
2423
} while (p != &alsa_lisp_nil);
2425
return new_integer(instance, res);
2429
* Syntax: (string-to-integer value)
2430
* 'value' can be integer or float type
2432
struct alisp_object * F_string_to_integer(struct alisp_instance *instance, struct alisp_object * args)
2434
struct alisp_object * p = eval(instance, car(args)), * p1;
2436
delete_tree(instance, cdr(args));
2437
delete_object(instance, args);
2438
if (alisp_compare_type(p, ALISP_OBJ_INTEGER))
2440
if (alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
2441
p1 = new_integer(instance, floor(p->value.f));
2443
lisp_warn(instance, "expected an integer or float for integer conversion");
2444
p1 = &alsa_lisp_nil;
2446
delete_tree(instance, p);
2451
* Syntax: (string-to-float value)
2452
* 'value' can be integer or float type
2454
struct alisp_object * F_string_to_float(struct alisp_instance *instance, struct alisp_object * args)
2456
struct alisp_object * p = eval(instance, car(args)), * p1;
2458
delete_tree(instance, cdr(args));
2459
delete_object(instance, args);
2460
if (alisp_compare_type(p, ALISP_OBJ_FLOAT))
2462
if (alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
2463
p1 = new_float(instance, p->value.i);
2465
lisp_warn(instance, "expected an integer or float for integer conversion");
2466
p1 = &alsa_lisp_nil;
2468
delete_tree(instance, p);
2472
static int append_to_string(char **s, int *len, char *from, int size)
2475
*s = malloc(*len = size + 1);
2480
memcpy(*s, from, size);
2483
*s = realloc(*s, *len);
2488
memcpy(*s + strlen(*s), from, size);
2490
(*s)[*len - 1] = '\0';
2494
static int format_parse_char(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
2498
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
2499
lisp_warn(instance, "format: expected integer\n");
2503
return append_to_string(s, len, &b, 1);
2506
static int format_parse_integer(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
2511
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
2512
!alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
2513
lisp_warn(instance, "format: expected integer or float\n");
2521
sprintf(s1, "%li", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? (long)floor(p->value.f) : p->value.i);
2522
res = append_to_string(s, len, s1, strlen(s1));
2527
static int format_parse_float(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
2532
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
2533
!alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
2534
lisp_warn(instance, "format: expected integer or float\n");
2542
sprintf(s1, "%f", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? p->value.f : (double)p->value.i);
2543
res = append_to_string(s, len, s1, strlen(s1));
2548
static int format_parse_string(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
2550
if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
2551
lisp_warn(instance, "format: expected string\n");
2554
return append_to_string(s, len, p->value.s, strlen(p->value.s));
2558
* Syntax: (format format value...)
2559
* 'format' is C-like format string
2561
struct alisp_object * F_format(struct alisp_instance *instance, struct alisp_object * args)
2563
struct alisp_object * p = eval(instance, car(args)), * p1 = cdr(args), * n;
2567
delete_object(instance, args);
2568
if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
2569
delete_tree(instance, p1);
2570
delete_tree(instance, p);
2571
lisp_warn(instance, "format: expected an format string");
2572
return &alsa_lisp_nil;
2577
n = eval(instance, car(p1));
2581
while (*s2 && *s2 != '%')
2584
if (append_to_string(&s1, &len, s, s2 - s) < 0) {
2586
delete_tree(instance, n);
2587
delete_tree(instance, cdr(p1));
2588
delete_object(instance, p1);
2589
delete_tree(instance, p);
2597
if (append_to_string(&s1, &len, s2, 1) < 0)
2602
if (format_parse_char(instance, &s1, &len, n) < 0)
2608
if (format_parse_integer(instance, &s1, &len, n) < 0)
2613
if (format_parse_float(instance, &s1, &len, n) < 0)
2618
if (format_parse_string(instance, &s1, &len, n) < 0)
2625
lisp_warn(instance, "unknown format char '%c'", *s2);
2631
delete_tree(instance, n);
2633
delete_object(instance, n);
2634
n = eval(instance, car(p1));
2637
delete_tree(instance, n);
2638
delete_tree(instance, cdr(p1));
2639
delete_object(instance, p1);
2640
delete_tree(instance, p);
2642
p1 = new_string(instance, s1);
2645
p1 = &alsa_lisp_nil;
2651
* Syntax: (compare-strings str1 start1 end1 str2 start2 end2 /opt-case-insensitive)
2652
* 'str1' is first compared string
2653
* 'start1' is first char (0..)
2654
* 'end1' is last char (0..)
2655
* 'str2' is second compared string
2656
* 'start2' is first char (0..)
2657
* 'end2' is last char (0..)
2658
* /opt-case-insensitive true - case insensitive match
2660
struct alisp_object * F_compare_strings(struct alisp_instance *instance, struct alisp_object * args)
2662
struct alisp_object * p1 = args, * n, * p[7];
2664
int start1, end1, start2, end2;
2666
for (start1 = 0; start1 < 7; start1++) {
2667
p[start1] = eval(instance, car(p1));
2669
delete_object(instance, n);
2671
delete_tree(instance, p1);
2672
if (alisp_compare_type(p[0], ALISP_OBJ_STRING)) {
2673
lisp_warn(instance, "compare-strings: first argument must be string\n");
2674
p1 = &alsa_lisp_nil;
2677
if (alisp_compare_type(p[1], ALISP_OBJ_INTEGER)) {
2678
lisp_warn(instance, "compare-strings: second argument must be integer\n");
2679
p1 = &alsa_lisp_nil;
2682
if (alisp_compare_type(p[2], ALISP_OBJ_INTEGER)) {
2683
lisp_warn(instance, "compare-strings: third argument must be integer\n");
2684
p1 = &alsa_lisp_nil;
2687
if (alisp_compare_type(p[3], ALISP_OBJ_STRING)) {
2688
lisp_warn(instance, "compare-strings: fifth argument must be string\n");
2689
p1 = &alsa_lisp_nil;
2692
if (!alisp_compare_type(p[4], ALISP_OBJ_NIL) &&
2693
!alisp_compare_type(p[4], ALISP_OBJ_INTEGER)) {
2694
lisp_warn(instance, "compare-strings: fourth argument must be integer\n");
2695
p1 = &alsa_lisp_nil;
2698
if (!alisp_compare_type(p[5], ALISP_OBJ_NIL) &&
2699
!alisp_compare_type(p[5], ALISP_OBJ_INTEGER)) {
2700
lisp_warn(instance, "compare-strings: sixth argument must be integer\n");
2701
p1 = &alsa_lisp_nil;
2705
start1 = p[1]->value.i;
2706
end1 = p[2]->value.i;
2708
start2 = alisp_compare_type(p[4], ALISP_OBJ_NIL) ? 0 : p[4]->value.i;
2709
end2 = alisp_compare_type(p[5], ALISP_OBJ_NIL) ? start2 + (end1 - start1) : p[5]->value.i;
2710
if (start1 < 0 || start2 < 0 || end1 < 0 || end2 < 0 ||
2711
start1 >= (int)strlen(s1) || start2 >= (int)strlen(s2) ||
2712
(end1 - start1) != (end2 - start2)) {
2713
p1 = &alsa_lisp_nil;
2716
if (p[6] != &alsa_lisp_nil) {
2717
while (start1 < end1) {
2718
if (s1[start1] == '\0' ||
2719
s2[start2] == '\0' ||
2720
tolower(s1[start1]) != tolower(s2[start2])) {
2721
p1 = &alsa_lisp_nil;
2728
while (start1 < end1) {
2729
if (s1[start1] == '\0' ||
2730
s2[start2] == '\0' ||
2731
s1[start1] != s2[start2]) {
2732
p1 = &alsa_lisp_nil;
2742
for (start1 = 0; start1 < 7; start1++)
2743
delete_tree(instance, p[start1]);
2748
* Syntax: (assoc key alist)
2750
struct alisp_object * F_assoc(struct alisp_instance *instance, struct alisp_object * args)
2752
struct alisp_object * p1, * p2, * n;
2754
p1 = eval(instance, car(args));
2755
p2 = eval(instance, car(cdr(args)));
2756
delete_tree(instance, cdr(cdr(args)));
2757
delete_object(instance, cdr(args));
2758
delete_object(instance, args);
2761
if (eq(p1, car(car(p2)))) {
2763
delete_tree(instance, p1);
2764
delete_tree(instance, cdr(p2));
2765
delete_object(instance, p2);
2768
delete_tree(instance, car(p2));
2770
delete_object(instance, n);
2771
} while (p2 != &alsa_lisp_nil);
2773
delete_tree(instance, p1);
2774
return &alsa_lisp_nil;
2778
* Syntax: (rassoc value alist)
2780
struct alisp_object * F_rassoc(struct alisp_instance *instance, struct alisp_object * args)
2782
struct alisp_object * p1, *p2, * n;
2784
p1 = eval(instance, car(args));
2785
p2 = eval(instance, car(cdr(args)));
2786
delete_tree(instance, cdr(cdr(args)));
2787
delete_object(instance, cdr(args));
2788
delete_object(instance, args);
2791
if (eq(p1, cdr(car(p2)))) {
2793
delete_tree(instance, p1);
2794
delete_tree(instance, cdr(p2));
2795
delete_object(instance, p2);
2798
delete_tree(instance, car(p2));
2800
delete_object(instance, n);
2801
} while (p2 != &alsa_lisp_nil);
2803
delete_tree(instance, p1);
2804
return &alsa_lisp_nil;
2808
* Syntax: (assq key alist)
2810
struct alisp_object * F_assq(struct alisp_instance *instance, struct alisp_object * args)
2812
struct alisp_object * p1, * p2, * n;
2814
p1 = eval(instance, car(args));
2815
p2 = eval(instance, car(cdr(args)));
2816
delete_tree(instance, cdr(cdr(args)));
2817
delete_object(instance, cdr(args));
2818
delete_object(instance, args);
2821
if (equal(p1, car(car(p2)))) {
2823
delete_tree(instance, p1);
2824
delete_tree(instance, cdr(p2));
2825
delete_object(instance, p2);
2828
delete_tree(instance, car(p2));
2830
delete_object(instance, n);
2831
} while (p2 != &alsa_lisp_nil);
2833
delete_tree(instance, p1);
2834
return &alsa_lisp_nil;
2838
* Syntax: (nth index alist)
2840
struct alisp_object * F_nth(struct alisp_instance *instance, struct alisp_object * args)
2842
struct alisp_object * p1, * p2, * n;
2845
p1 = eval(instance, car(args));
2846
p2 = eval(instance, car(cdr(args)));
2847
delete_tree(instance, cdr(cdr(args)));
2848
delete_object(instance, cdr(args));
2849
delete_object(instance, args);
2851
if (!alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
2852
delete_tree(instance, p1);
2853
delete_tree(instance, p2);
2854
return &alsa_lisp_nil;
2856
if (!alisp_compare_type(p2, ALISP_OBJ_CONS)) {
2857
delete_object(instance, p1);
2858
delete_tree(instance, p2);
2859
return &alsa_lisp_nil;
2862
delete_object(instance, p1);
2864
delete_tree(instance, car(p2));
2866
delete_object(instance, n);
2869
delete_tree(instance, cdr(p2));
2870
delete_object(instance, p2);
2875
* Syntax: (rassq value alist)
2877
struct alisp_object * F_rassq(struct alisp_instance *instance, struct alisp_object * args)
2879
struct alisp_object * p1, * p2, * n;
2881
p1 = eval(instance, car(args));
2882
p2 = eval(instance, car(cdr(args)));
2883
delete_tree(instance, cdr(cdr(args)));
2884
delete_object(instance, cdr(args));
2885
delete_object(instance, args);
2888
if (equal(p1, cdr(car(p2)))) {
2890
delete_tree(instance, p1);
2891
delete_tree(instance, cdr(p2));
2892
delete_object(instance, p2);
2895
delete_tree(instance, car(p2));
2897
delete_object(instance, n);
2898
} while (p2 != &alsa_lisp_nil);
2900
delete_tree(instance, p1);
2901
return &alsa_lisp_nil;
2904
static struct alisp_object * F_dump_memory(struct alisp_instance *instance, struct alisp_object * args)
2906
struct alisp_object * p = car(args);
2908
if (p != &alsa_lisp_nil && cdr(args) == &alsa_lisp_nil &&
2909
alisp_compare_type(p, ALISP_OBJ_STRING)) {
2910
if (strlen(p->value.s) > 0) {
2911
dump_objects(instance, p->value.s);
2912
delete_tree(instance, args);
2913
return &alsa_lisp_t;
2915
lisp_warn(instance, "expected filename");
2917
lisp_warn(instance, "wrong number of parameters (expected string)");
2919
delete_tree(instance, args);
2920
return &alsa_lisp_nil;
2923
static struct alisp_object * F_stat_memory(struct alisp_instance *instance, struct alisp_object * args)
2925
snd_output_printf(instance->out, "*** Memory stats\n");
2926
snd_output_printf(instance->out, " used_objs = %li, free_objs = %li, max_objs = %li, obj_size = %i (total bytes = %li, max bytes = %li)\n",
2927
instance->used_objs,
2928
instance->free_objs,
2930
(int)sizeof(struct alisp_object),
2931
(long)((instance->used_objs + instance->free_objs) * sizeof(struct alisp_object)),
2932
(long)(instance->max_objs * sizeof(struct alisp_object)));
2933
delete_tree(instance, args);
2934
return &alsa_lisp_nil;
2937
static struct alisp_object * F_check_memory(struct alisp_instance *instance, struct alisp_object * args)
2939
delete_tree(instance, args);
2940
if (instance->used_objs > 0) {
2941
fprintf(stderr, "!!!alsa lisp - check memory failed!!!\n");
2942
F_stat_memory(instance, &alsa_lisp_nil);
2945
return &alsa_lisp_t;
2948
static struct alisp_object * F_dump_objects(struct alisp_instance *instance, struct alisp_object * args)
2950
struct alisp_object * p = car(args);
2952
if (p != &alsa_lisp_nil && cdr(args) == &alsa_lisp_nil &&
2953
alisp_compare_type(p, ALISP_OBJ_STRING)) {
2954
if (strlen(p->value.s) > 0) {
2955
dump_obj_lists(instance, p->value.s);
2956
delete_tree(instance, args);
2957
return &alsa_lisp_t;
2959
lisp_warn(instance, "expected filename");
2961
lisp_warn(instance, "wrong number of parameters (expected string)");
2963
delete_tree(instance, args);
2964
return &alsa_lisp_nil;
2969
struct alisp_object * (*func)(struct alisp_instance *instance, struct alisp_object * args);
2972
static const struct intrinsic intrinsics[] = {
2975
{ "&check-memory", F_check_memory },
2976
{ "&dump-memory", F_dump_memory },
2977
{ "&dump-objects", F_dump_objects },
2978
{ "&stat-memory", F_stat_memory },
2989
{ "assoc", F_assoc },
2994
{ "compare-strings", F_compare_strings },
2995
{ "concat", F_concat },
2998
{ "defun", F_defun },
3000
{ "equal", F_equal },
3002
{ "exfun", F_exfun },
3003
{ "format", F_format },
3004
{ "funcall", F_funcall },
3005
{ "garbage-collect", F_gc },
3008
{ "include", F_include },
3015
{ "princ", F_princ },
3016
{ "prog1", F_prog1 },
3017
{ "prog2", F_prog2 },
3018
{ "progn", F_progn },
3019
{ "quote", F_quote },
3020
{ "rassoc", F_rassoc },
3021
{ "rassq", F_rassq },
3025
{ "string-equal", F_equal },
3026
{ "string-to-float", F_string_to_float },
3027
{ "string-to-integer", F_string_to_integer },
3028
{ "string-to-number", F_string_to_float },
3029
{ "string=", F_equal },
3030
{ "unless", F_unless },
3031
{ "unset", F_unset },
3032
{ "unsetf", F_unsetq },
3033
{ "unsetq", F_unsetq },
3035
{ "while", F_while },
3038
#include "alisp_snd.c"
3040
static int compar(const void *p1, const void *p2)
3042
return strcmp(((struct intrinsic *)p1)->name,
3043
((struct intrinsic *)p2)->name);
3046
static inline struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
3048
struct alisp_object * p3;
3049
struct intrinsic key, *item;
3051
key.name = p1->value.s;
3053
if ((item = bsearch(&key, intrinsics,
3054
sizeof intrinsics / sizeof intrinsics[0],
3055
sizeof intrinsics[0], compar)) != NULL) {
3056
delete_object(instance, p1);
3057
return item->func(instance, p2);
3060
if ((item = bsearch(&key, snd_intrinsics,
3061
sizeof snd_intrinsics / sizeof snd_intrinsics[0],
3062
sizeof snd_intrinsics[0], compar)) != NULL) {
3063
delete_object(instance, p1);
3064
return item->func(instance, p2);
3067
if ((p3 = get_object(instance, p1)) != &alsa_lisp_nil) {
3068
delete_object(instance, p1);
3069
return eval_func(instance, p3, p2);
3071
lisp_warn(instance, "function `%s' is undefined", p1->value.s);
3072
delete_object(instance, p1);
3073
delete_tree(instance, p2);
3076
return &alsa_lisp_nil;
3080
* Syntax: (funcall function args...)
3082
static struct alisp_object * F_funcall(struct alisp_instance *instance, struct alisp_object * args)
3084
struct alisp_object * p = eval(instance, car(args)), * p1;
3086
if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
3087
!alisp_compare_type(p, ALISP_OBJ_STRING)) {
3088
lisp_warn(instance, "expected an function name");
3089
delete_tree(instance, p);
3090
delete_tree(instance, cdr(args));
3091
delete_object(instance, args);
3092
return &alsa_lisp_nil;
3095
delete_object(instance, args);
3096
return eval_cons1(instance, p, p1);
3099
static inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p)
3101
struct alisp_object * p1 = car(p), * p2;
3103
if (p1 != &alsa_lisp_nil && alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER)) {
3104
if (!strcmp(p1->value.s, "lambda"))
3108
delete_object(instance, p);
3109
return eval_cons1(instance, p1, p2);
3111
delete_tree(instance, p);
3114
return &alsa_lisp_nil;
3117
static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p)
3119
switch (alisp_get_type(p)) {
3120
case ALISP_OBJ_IDENTIFIER: {
3121
struct alisp_object *r = incref_tree(instance, get_object(instance, p));
3122
delete_object(instance, p);
3125
case ALISP_OBJ_INTEGER:
3126
case ALISP_OBJ_FLOAT:
3127
case ALISP_OBJ_STRING:
3128
case ALISP_OBJ_POINTER:
3130
case ALISP_OBJ_CONS:
3131
return eval_cons(instance, p);
3139
static struct alisp_object * F_eval(struct alisp_instance *instance, struct alisp_object * args)
3141
return eval(instance, eval(instance, car(args)));
3148
static int alisp_include_file(struct alisp_instance *instance, const char *filename)
3150
snd_input_t *old_in;
3151
struct alisp_object *p, *p1;
3153
int retval = 0, err;
3155
err = snd_user_file(filename, &name);
3158
old_in = instance->in;
3159
err = snd_input_stdio_open(&instance->in, name, "r");
3164
if (instance->verbose)
3165
lisp_verbose(instance, "** include filename '%s'", name);
3168
if ((p = parse_object(instance, 0)) == NULL)
3170
if (instance->verbose) {
3171
lisp_verbose(instance, "** code");
3172
princ_object(instance->vout, p);
3173
snd_output_putc(instance->vout, '\n');
3175
p1 = eval(instance, p);
3180
if (instance->verbose) {
3181
lisp_verbose(instance, "** result");
3182
princ_object(instance->vout, p1);
3183
snd_output_putc(instance->vout, '\n');
3185
delete_tree(instance, p1);
3186
if (instance->debug) {
3187
lisp_debug(instance, "** objects after operation");
3188
print_obj_lists(instance, instance->dout);
3192
snd_input_close(instance->in);
3195
instance->in = old_in;
3199
int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
3201
struct alisp_instance *instance;
3202
struct alisp_object *p, *p1;
3203
int i, j, retval = 0;
3205
instance = (struct alisp_instance *)malloc(sizeof(struct alisp_instance));
3206
if (instance == NULL) {
3210
memset(instance, 0, sizeof(struct alisp_instance));
3211
instance->verbose = cfg->verbose && cfg->vout;
3212
instance->warning = cfg->warning && cfg->wout;
3213
instance->debug = cfg->debug && cfg->dout;
3214
instance->in = cfg->in;
3215
instance->out = cfg->out;
3216
instance->vout = cfg->vout;
3217
instance->eout = cfg->eout;
3218
instance->wout = cfg->wout;
3219
instance->dout = cfg->dout;
3220
INIT_LIST_HEAD(&instance->free_objs_list);
3221
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
3222
for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++)
3223
INIT_LIST_HEAD(&instance->used_objs_list[i][j]);
3224
INIT_LIST_HEAD(&instance->setobjs_list[i]);
3230
if ((p = parse_object(instance, 0)) == NULL)
3232
if (instance->verbose) {
3233
lisp_verbose(instance, "** code");
3234
princ_object(instance->vout, p);
3235
snd_output_putc(instance->vout, '\n');
3237
p1 = eval(instance, p);
3242
if (instance->verbose) {
3243
lisp_verbose(instance, "** result");
3244
princ_object(instance->vout, p1);
3245
snd_output_putc(instance->vout, '\n');
3247
delete_tree(instance, p1);
3248
if (instance->debug) {
3249
lisp_debug(instance, "** objects after operation");
3250
print_obj_lists(instance, instance->dout);
3255
*_instance = instance;
3257
alsa_lisp_free(instance);
3262
void alsa_lisp_free(struct alisp_instance *instance)
3264
if (instance == NULL)
3267
free_objects(instance);
3271
struct alisp_cfg *alsa_lisp_default_cfg(snd_input_t *input)
3273
snd_output_t *output, *eoutput;
3274
struct alisp_cfg *cfg;
3277
err = snd_output_stdio_attach(&output, stdout, 0);
3280
err = snd_output_stdio_attach(&eoutput, stderr, 0);
3282
snd_output_close(output);
3285
cfg = calloc(1, sizeof(struct alisp_cfg));
3287
snd_output_close(eoutput);
3288
snd_output_close(output);
3292
cfg->wout = eoutput;
3293
cfg->eout = eoutput;
3294
cfg->dout = eoutput;
3299
void alsa_lisp_default_cfg_free(struct alisp_cfg *cfg)
3301
snd_input_close(cfg->in);
3302
snd_output_close(cfg->out);
3303
snd_output_close(cfg->dout);
3307
int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterator **result,
3308
const char *id, const char *args, ...)
3311
struct alisp_object *aargs = NULL, *obj, *res;
3313
if (args && *args != 'n') {
3315
struct alisp_object *p;
3319
if (*args++ != '%') {
3323
if (*args == '\0') {
3331
obj = new_string(instance, va_arg(ap, char *));
3334
obj = new_integer(instance, va_arg(ap, int));
3337
obj = new_integer(instance, va_arg(ap, long));
3341
obj = new_integer(instance, va_arg(ap, double));
3345
char *ptrid = _ptrid;
3346
while (*args && *args != '%')
3349
if (ptrid == _ptrid) {
3353
obj = new_cons_pointer(instance, _ptrid, va_arg(ap, void *));
3354
obj = quote_object(instance, obj);
3368
p = aargs = new_object(instance, ALISP_OBJ_CONS);
3370
p->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
3377
p->value.c.car = obj;
3384
snd_output_printf(instance->wout, ">>>");
3385
princ_object(instance->wout, aargs);
3386
snd_output_printf(instance->wout, "<<<\n");
3392
aargs = &alsa_lisp_nil;
3393
if ((obj = get_object1(instance, id)) != &alsa_lisp_nil) {
3394
res = eval_func(instance, obj, aargs);
3397
struct intrinsic key, *item;
3399
if ((item = bsearch(&key, intrinsics,
3400
sizeof intrinsics / sizeof intrinsics[0],
3401
sizeof intrinsics[0], compar)) != NULL) {
3402
res = item->func(instance, aargs);
3404
} else if ((item = bsearch(&key, snd_intrinsics,
3405
sizeof snd_intrinsics / sizeof snd_intrinsics[0],
3406
sizeof snd_intrinsics[0], compar)) != NULL) {
3407
res = item->func(instance, aargs);
3410
res = &alsa_lisp_nil;
3415
if (err == 0 && result) {
3418
delete_tree(instance, res);
3424
void alsa_lisp_result_free(struct alisp_instance *instance,
3425
struct alisp_seq_iterator *result)
3427
delete_tree(instance, result);
3430
int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
3431
struct alisp_seq_iterator **seq)
3433
struct alisp_object * p1;
3435
p1 = get_object1(instance, id);
3442
int alsa_lisp_seq_next(struct alisp_seq_iterator **seq)
3444
struct alisp_object * p1 = *seq;
3447
if (p1 == &alsa_lisp_nil)
3453
int alsa_lisp_seq_count(struct alisp_seq_iterator *seq)
3457
while (seq != &alsa_lisp_nil) {
3464
int alsa_lisp_seq_integer(struct alisp_seq_iterator *seq, long *val)
3466
if (alisp_compare_type(seq, ALISP_OBJ_CONS))
3467
seq = seq->value.c.cdr;
3468
if (alisp_compare_type(seq, ALISP_OBJ_INTEGER))
3469
*val = seq->value.i;
3475
int alsa_lisp_seq_pointer(struct alisp_seq_iterator *seq, const char *ptr_id, void **ptr)
3477
struct alisp_object * p2;
3479
if (alisp_compare_type(seq, ALISP_OBJ_CONS) &&
3480
alisp_compare_type(seq->value.c.car, ALISP_OBJ_CONS))
3481
seq = seq->value.c.car;
3482
if (alisp_compare_type(seq, ALISP_OBJ_CONS)) {
3483
p2 = seq->value.c.car;
3484
if (!alisp_compare_type(p2, ALISP_OBJ_STRING))
3486
if (strcmp(p2->value.s, ptr_id))
3488
p2 = seq->value.c.cdr;
3489
if (!alisp_compare_type(p2, ALISP_OBJ_POINTER))
3491
*ptr = (void *)seq->value.ptr;