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