libs/alsa-lib-1.0.13/src/alisp/alisp.c

Go to the documentation of this file.
00001 /*
00002  *  ALSA lisp implementation
00003  *  Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
00004  *
00005  *  Based on work of Sandro Sigala (slisp-1.2)
00006  *
00007  *
00008  *   This library is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU Lesser General Public License as
00010  *   published by the Free Software Foundation; either version 2.1 of
00011  *   the License, or (at your option) any later version.
00012  *
00013  *   This program is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU Lesser General Public License for more details.
00017  *
00018  *   You should have received a copy of the GNU Lesser General Public
00019  *   License along with this library; if not, write to the Free Software
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00021  *
00022  */
00023 
00024 #include <assert.h>
00025 
00026 #include <limits.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <ctype.h>
00031 #include <math.h>
00032 #include <err.h>
00033 
00034 #define alisp_seq_iterator alisp_object
00035 
00036 #include "local.h"
00037 #include "alisp.h"
00038 #include "alisp_local.h"
00039 
00040 struct alisp_object alsa_lisp_nil;
00041 struct alisp_object alsa_lisp_t;
00042 
00043 /* parser prototypes */
00044 static struct alisp_object * parse_object(struct alisp_instance *instance, int havetoken);
00045 static void princ_cons(snd_output_t *out, struct alisp_object * p);
00046 static void princ_object(snd_output_t *out, struct alisp_object * p);
00047 static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p);
00048 
00049 /* functions */
00050 static struct alisp_object *F_eval(struct alisp_instance *instance, struct alisp_object *);
00051 static struct alisp_object *F_progn(struct alisp_instance *instance, struct alisp_object *);
00052 static struct alisp_object *F_funcall(struct alisp_instance *instance, struct alisp_object *);
00053 
00054 /* others */
00055 static int alisp_include_file(struct alisp_instance *instance, const char *filename);
00056 
00057 /*
00058  *  object handling
00059  */
00060 
00061 static int get_string_hash(const char *s)
00062 {
00063         int val = 0;
00064         if (s == NULL)
00065                 return val;
00066         while (*s)
00067                 val += *s++;
00068         return val & ALISP_OBJ_PAIR_HASH_MASK;
00069 }
00070 
00071 static void nomem(void)
00072 {
00073         SNDERR("alisp: no enough memory");
00074 }
00075 
00076 static void lisp_verbose(struct alisp_instance *instance, const char *fmt, ...)
00077 {
00078         va_list ap;
00079 
00080         if (!instance->verbose)
00081                 return;
00082         va_start(ap, fmt);
00083         snd_output_printf(instance->vout, "alisp: ");
00084         snd_output_vprintf(instance->vout, fmt, ap);
00085         snd_output_putc(instance->vout, '\n');
00086         va_end(ap);
00087 }
00088 
00089 static void lisp_error(struct alisp_instance *instance, const char *fmt, ...)
00090 {
00091         va_list ap;
00092 
00093         if (!instance->warning)
00094                 return;
00095         va_start(ap, fmt);
00096         snd_output_printf(instance->eout, "alisp error: ");
00097         snd_output_vprintf(instance->eout, fmt, ap);
00098         snd_output_putc(instance->eout, '\n');
00099         va_end(ap);
00100 }
00101 
00102 static void lisp_warn(struct alisp_instance *instance, const char *fmt, ...)
00103 {
00104         va_list ap;
00105 
00106         if (!instance->warning)
00107                 return;
00108         va_start(ap, fmt);
00109         snd_output_printf(instance->wout, "alisp warning: ");
00110         snd_output_vprintf(instance->wout, fmt, ap);
00111         snd_output_putc(instance->wout, '\n');
00112         va_end(ap);
00113 }
00114 
00115 static void lisp_debug(struct alisp_instance *instance, const char *fmt, ...)
00116 {
00117         va_list ap;
00118 
00119         if (!instance->debug)
00120                 return;
00121         va_start(ap, fmt);
00122         snd_output_printf(instance->dout, "alisp debug: ");
00123         snd_output_vprintf(instance->dout, fmt, ap);
00124         snd_output_putc(instance->dout, '\n');
00125         va_end(ap);
00126 }
00127 
00128 static struct alisp_object * new_object(struct alisp_instance *instance, int type)
00129 {
00130         struct alisp_object * p;
00131 
00132         if (list_empty(&instance->free_objs_list)) {
00133                 p = (struct alisp_object *)malloc(sizeof(struct alisp_object));
00134                 if (p == NULL) {
00135                         nomem();
00136                         return NULL;
00137                 }
00138                 lisp_debug(instance, "allocating cons %p", p);
00139         } else {
00140                 p = (struct alisp_object *)instance->free_objs_list.next;
00141                 list_del(&p->list);
00142                 instance->free_objs--;
00143                 lisp_debug(instance, "recycling cons %p", p);
00144         }
00145 
00146         instance->used_objs++;
00147 
00148         alisp_set_type(p, type);
00149         alisp_set_refs(p, 1);
00150         if (type == ALISP_OBJ_CONS) {
00151                 p->value.c.car = &alsa_lisp_nil;
00152                 p->value.c.cdr = &alsa_lisp_nil;
00153                 list_add(&p->list, &instance->used_objs_list[0][ALISP_OBJ_CONS]);
00154         }
00155 
00156         if (instance->used_objs + instance->free_objs > instance->max_objs)
00157                 instance->max_objs = instance->used_objs + instance->free_objs;
00158 
00159         return p;
00160 }
00161 
00162 static void free_object(struct alisp_object * p)
00163 {
00164         switch (alisp_get_type(p)) {
00165         case ALISP_OBJ_STRING:
00166         case ALISP_OBJ_IDENTIFIER:
00167                 free(p->value.s);
00168                 alisp_set_type(p, ALISP_OBJ_INTEGER);
00169                 break;
00170         default:
00171                 break;
00172         }
00173 }
00174 
00175 static void delete_object(struct alisp_instance *instance, struct alisp_object * p)
00176 {
00177         if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
00178                 return;
00179         if (alisp_compare_type(p, ALISP_OBJ_NIL) ||
00180             alisp_compare_type(p, ALISP_OBJ_T))
00181                 return;
00182         assert(alisp_get_refs(p) > 0);
00183         lisp_debug(instance, "delete cons %p (type = %i, refs = %i) (s = '%s')", p, alisp_get_type(p), alisp_get_refs(p),
00184                         alisp_compare_type(p, ALISP_OBJ_STRING) ||
00185                         alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) ? p->value.s : "???");
00186         if (alisp_dec_refs(p))
00187                 return;
00188         list_del(&p->list);
00189         instance->used_objs--;
00190         free_object(p);
00191         if (instance->free_objs >= ALISP_FREE_OBJ_POOL) {
00192                 lisp_debug(instance, "freed cons %p", p);
00193                 free(p);
00194                 return;
00195         }
00196         lisp_debug(instance, "moved cons %p to free list", p);
00197         list_add(&p->list, &instance->free_objs_list);
00198         instance->free_objs++;
00199 }
00200 
00201 static void delete_tree(struct alisp_instance *instance, struct alisp_object * p)
00202 {
00203         if (p == NULL)
00204                 return;
00205         if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
00206                 delete_tree(instance, p->value.c.car);
00207                 delete_tree(instance, p->value.c.cdr);
00208         }
00209         delete_object(instance, p);
00210 }
00211 
00212 static struct alisp_object * incref_object(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * p)
00213 {
00214         if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
00215                 return p;
00216         if (alisp_get_refs(p) == ALISP_MAX_REFS) {
00217                 assert(0);
00218                 fprintf(stderr, "OOPS: alsa lisp: incref fatal error\n");
00219                 exit(EXIT_FAILURE);
00220         }
00221         alisp_inc_refs(p);
00222         return p;
00223 }
00224 
00225 static struct alisp_object * incref_tree(struct alisp_instance *instance, struct alisp_object * p)
00226 {
00227         if (p == NULL)
00228                 return NULL;
00229         if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
00230                 incref_tree(instance, p->value.c.car);
00231                 incref_tree(instance, p->value.c.cdr);
00232         }
00233         return incref_object(instance, p);
00234 }
00235 
00236 static struct alisp_object * incref_tree_explicit(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * e)
00237 {
00238         if (p == NULL)
00239                 return NULL;
00240         if (alisp_compare_type(p, ALISP_OBJ_CONS)) {
00241                 if (e == p) {
00242                         incref_tree(instance, p->value.c.car);
00243                         incref_tree(instance, p->value.c.cdr);
00244                 } else {
00245                         incref_tree_explicit(instance, p->value.c.car, e);
00246                         incref_tree_explicit(instance, p->value.c.cdr, e);
00247                 }
00248         }
00249         if (e == p)
00250                 return incref_object(instance, p);
00251         return p;
00252 }
00253 
00254 static void free_objects(struct alisp_instance *instance)
00255 {
00256         struct list_head *pos, *pos1;
00257         struct alisp_object * p;
00258         struct alisp_object_pair * pair;
00259         int i, j;
00260 
00261         for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
00262                 list_for_each_safe(pos, pos1, &instance->setobjs_list[i]) {
00263                         pair = list_entry(pos, struct alisp_object_pair, list);
00264                         lisp_debug(instance, "freeing pair: '%s' -> %p", pair->name, pair->value);
00265                         delete_tree(instance, pair->value);
00266                         free((void *)pair->name);
00267                         free(pair);
00268                 }
00269         }
00270         for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
00271                 for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++) {
00272                         list_for_each_safe(pos, pos1, &instance->used_objs_list[i][j]) {
00273                                 p = list_entry(pos, struct alisp_object, list);
00274                                 lisp_warn(instance, "object %p is still referenced %i times!", p, alisp_get_refs(p));
00275 #if 0
00276                                 snd_output_printf(instance->wout, ">>>> ");
00277                                 princ_object(instance->wout, p);
00278                                 snd_output_printf(instance->wout, " <<<<\n");
00279 #endif
00280                                 if (alisp_get_refs(p) > 0)
00281                                         alisp_set_refs(p, 1);
00282                                 delete_object(instance, p);
00283                         }
00284                 }
00285         list_for_each_safe(pos, pos1, &instance->free_objs_list) {
00286                 p = list_entry(pos, struct alisp_object, list);
00287                 list_del(&p->list);
00288                 free(p);
00289                 lisp_debug(instance, "freed (all) cons %p", p);
00290         }
00291 }
00292 
00293 static struct alisp_object * search_object_identifier(struct alisp_instance *instance, const char *s)
00294 {
00295         struct list_head * pos;
00296         struct alisp_object * p;
00297 
00298         list_for_each(pos, &instance->used_objs_list[get_string_hash(s)][ALISP_OBJ_IDENTIFIER]) {
00299                 p = list_entry(pos, struct alisp_object, list);
00300                 if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
00301                         continue;
00302                 if (!strcmp(p->value.s, s))
00303                         return incref_object(instance, p);
00304         }
00305 
00306         return NULL;
00307 }
00308 
00309 static struct alisp_object * search_object_string(struct alisp_instance *instance, const char *s)
00310 {
00311         struct list_head * pos;
00312         struct alisp_object * p;
00313 
00314         list_for_each(pos, &instance->used_objs_list[get_string_hash(s)][ALISP_OBJ_STRING]) {
00315                 p = list_entry(pos, struct alisp_object, list);
00316                 if (!strcmp(p->value.s, s)) {
00317                         if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
00318                                 continue;
00319                         return incref_object(instance, p);
00320                 }
00321         }
00322 
00323         return NULL;
00324 }
00325 
00326 static struct alisp_object * search_object_integer(struct alisp_instance *instance, long in)
00327 {
00328         struct list_head * pos;
00329         struct alisp_object * p;
00330 
00331         list_for_each(pos, &instance->used_objs_list[in & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_INTEGER]) {
00332                 p = list_entry(pos, struct alisp_object, list);
00333                 if (p->value.i == in) {
00334                         if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
00335                                 continue;
00336                         return incref_object(instance, p);
00337                 }
00338         }
00339 
00340         return NULL;
00341 }
00342 
00343 static struct alisp_object * search_object_float(struct alisp_instance *instance, double in)
00344 {
00345         struct list_head * pos;
00346         struct alisp_object * p;
00347 
00348         list_for_each(pos, &instance->used_objs_list[(long)in & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_FLOAT]) {
00349                 p = list_entry(pos, struct alisp_object, list);
00350                 if (p->value.i == in) {
00351                         if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
00352                                 continue;
00353                         return incref_object(instance, p);
00354                 }
00355         }
00356 
00357         return NULL;
00358 }
00359 
00360 static struct alisp_object * search_object_pointer(struct alisp_instance *instance, const void *ptr)
00361 {
00362         struct list_head * pos;
00363         struct alisp_object * p;
00364 
00365         list_for_each(pos, &instance->used_objs_list[(long)ptr & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_POINTER]) {
00366                 p = list_entry(pos, struct alisp_object, list);
00367                 if (p->value.ptr == ptr) {
00368                         if (alisp_get_refs(p) > ALISP_MAX_REFS_LIMIT)
00369                                 continue;
00370                         return incref_object(instance, p);
00371                 }
00372         }
00373 
00374         return NULL;
00375 }
00376 
00377 static struct alisp_object * new_integer(struct alisp_instance *instance, long value)
00378 {
00379         struct alisp_object * obj;
00380         
00381         obj = search_object_integer(instance, value);
00382         if (obj != NULL)
00383                 return obj;
00384         obj = new_object(instance, ALISP_OBJ_INTEGER);
00385         if (obj) {
00386                 list_add(&obj->list, &instance->used_objs_list[value & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_INTEGER]);
00387                 obj->value.i = value;
00388         }
00389         return obj;
00390 }
00391 
00392 static struct alisp_object * new_float(struct alisp_instance *instance, double value)
00393 {
00394         struct alisp_object * obj;
00395         
00396         obj = search_object_float(instance, value);
00397         if (obj != NULL)
00398                 return obj;
00399         obj = new_object(instance, ALISP_OBJ_FLOAT);
00400         if (obj) {
00401                 list_add(&obj->list, &instance->used_objs_list[(long)value & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_FLOAT]);
00402                 obj->value.f = value;
00403         }
00404         return obj;
00405 }
00406 
00407 static struct alisp_object * new_string(struct alisp_instance *instance, const char *str)
00408 {
00409         struct alisp_object * obj;
00410         
00411         obj = search_object_string(instance, str);
00412         if (obj != NULL)
00413                 return obj;
00414         obj = new_object(instance, ALISP_OBJ_STRING);
00415         if (obj)
00416                 list_add(&obj->list, &instance->used_objs_list[get_string_hash(str)][ALISP_OBJ_STRING]);
00417         if (obj && (obj->value.s = strdup(str)) == NULL) {
00418                 delete_object(instance, obj);
00419                 nomem();
00420                 return NULL;
00421         }
00422         return obj;
00423 }
00424 
00425 static struct alisp_object * new_identifier(struct alisp_instance *instance, const char *id)
00426 {
00427         struct alisp_object * obj;
00428         
00429         obj = search_object_identifier(instance, id);
00430         if (obj != NULL)
00431                 return obj;
00432         obj = new_object(instance, ALISP_OBJ_IDENTIFIER);
00433         if (obj)
00434                 list_add(&obj->list, &instance->used_objs_list[get_string_hash(id)][ALISP_OBJ_IDENTIFIER]);
00435         if (obj && (obj->value.s = strdup(id)) == NULL) {
00436                 delete_object(instance, obj);
00437                 nomem();
00438                 return NULL;
00439         }
00440         return obj;
00441 }
00442 
00443 static struct alisp_object * new_pointer(struct alisp_instance *instance, const void *ptr)
00444 {
00445         struct alisp_object * obj;
00446         
00447         obj = search_object_pointer(instance, ptr);
00448         if (obj != NULL)
00449                 return obj;
00450         obj = new_object(instance, ALISP_OBJ_POINTER);
00451         if (obj) {
00452                 list_add(&obj->list, &instance->used_objs_list[(long)ptr & ALISP_OBJ_PAIR_HASH_MASK][ALISP_OBJ_POINTER]);
00453                 obj->value.ptr = ptr;
00454         }
00455         return obj;
00456 }
00457 
00458 static struct alisp_object * new_cons_pointer(struct alisp_instance * instance, const char *ptr_id, void *ptr)
00459 {
00460         struct alisp_object * lexpr;
00461 
00462         if (ptr == NULL)
00463                 return &alsa_lisp_nil;
00464         lexpr = new_object(instance, ALISP_OBJ_CONS);
00465         if (lexpr == NULL)
00466                 return NULL;
00467         lexpr->value.c.car = new_string(instance, ptr_id);
00468         if (lexpr->value.c.car == NULL)
00469                 goto __end;
00470         lexpr->value.c.cdr = new_pointer(instance, ptr);
00471         if (lexpr->value.c.cdr == NULL) {
00472                 delete_object(instance, lexpr->value.c.car);
00473               __end:
00474                 delete_object(instance, lexpr);
00475                 return NULL;
00476         }
00477         return lexpr;
00478 }
00479 
00480 void alsa_lisp_init_objects(void) __attribute__ ((constructor));
00481 
00482 void alsa_lisp_init_objects(void)
00483 {
00484         memset(&alsa_lisp_nil, 0, sizeof(alsa_lisp_nil));
00485         alisp_set_type(&alsa_lisp_nil, ALISP_OBJ_NIL);
00486         INIT_LIST_HEAD(&alsa_lisp_nil.list);
00487         memset(&alsa_lisp_t, 0, sizeof(alsa_lisp_t));
00488         alisp_set_type(&alsa_lisp_t, ALISP_OBJ_T);
00489         INIT_LIST_HEAD(&alsa_lisp_t.list);
00490 }
00491 
00492 /*
00493  * lexer
00494  */ 
00495 
00496 static int xgetc(struct alisp_instance *instance)
00497 {
00498         instance->charno++;
00499         if (instance->lex_bufp > instance->lex_buf)
00500                 return *--(instance->lex_bufp);
00501         return snd_input_getc(instance->in);
00502 }
00503 
00504 static inline void xungetc(struct alisp_instance *instance, int c)
00505 {
00506         *(instance->lex_bufp)++ = c;
00507         instance->charno--;
00508 }
00509 
00510 static int init_lex(struct alisp_instance *instance)
00511 {
00512         instance->charno = instance->lineno = 1;
00513         instance->token_buffer_max = 10;
00514         if ((instance->token_buffer = (char *)malloc(instance->token_buffer_max)) == NULL) {
00515                 nomem();
00516                 return -ENOMEM;
00517         }
00518         instance->lex_bufp = instance->lex_buf;
00519         return 0;
00520 }
00521 
00522 static void done_lex(struct alisp_instance *instance)
00523 {
00524         free(instance->token_buffer);
00525 }
00526 
00527 static char * extend_buf(struct alisp_instance *instance, char *p)
00528 {
00529         int off = p - instance->token_buffer;
00530 
00531         instance->token_buffer_max += 10;
00532         instance->token_buffer = (char *)realloc(instance->token_buffer, instance->token_buffer_max);
00533         if (instance->token_buffer == NULL) {
00534                 nomem();
00535                 return NULL;
00536         }
00537 
00538         return instance->token_buffer + off;
00539 }
00540 
00541 static int gettoken(struct alisp_instance *instance)
00542 {
00543         char *p;
00544         int c;
00545 
00546         for (;;) {
00547                 c = xgetc(instance);
00548                 switch (c) {
00549                 case '\n':
00550                         ++instance->lineno;
00551                         break;
00552 
00553                 case ' ': case '\f': case '\t': case '\v': case '\r':
00554                         break;
00555 
00556                 case ';':
00557                         /* Comment: ";".*"\n" */
00558                         while ((c = xgetc(instance)) != '\n' && c != EOF)
00559                                 ;
00560                         if (c != EOF)
00561                                 ++instance->lineno;
00562                         break;
00563 
00564                 case '?':
00565                         /* Character: "?". */
00566                         c = xgetc(instance);
00567                         sprintf(instance->token_buffer, "%d", c);
00568                         return instance->thistoken = ALISP_INTEGER;
00569 
00570                 case '-':
00571                         /* Minus sign: "-". */
00572                         c = xgetc(instance);
00573                         if (!isdigit(c)) {
00574                                 xungetc(instance, c);
00575                                 c = '-';
00576                                 goto got_id;
00577                         }
00578                         xungetc(instance, c);
00579                         c = '-';
00580                         /* FALLTRHU */
00581 
00582                 case '0':
00583                 case '1': case '2': case '3':
00584                 case '4': case '5': case '6':
00585                 case '7': case '8': case '9':
00586                         /* Integer: [0-9]+ */
00587                         p = instance->token_buffer;
00588                         instance->thistoken = ALISP_INTEGER;
00589                         do {
00590                               __ok:
00591                                 if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
00592                                         p = extend_buf(instance, p);
00593                                         if (p == NULL)
00594                                                 return instance->thistoken = EOF;
00595                                 }
00596                                 *p++ = c;
00597                                 c = xgetc(instance);
00598                                 if (c == '.' && instance->thistoken == ALISP_INTEGER) {
00599                                         c = xgetc(instance);
00600                                         xungetc(instance, c);
00601                                         if (isdigit(c)) {
00602                                                 instance->thistoken = ALISP_FLOAT;
00603                                                 c = '.';
00604                                                 goto __ok;
00605                                         } else {
00606                                                 c = '.';
00607                                         }
00608                                 } else if (c == 'e' && instance->thistoken == ALISP_FLOAT) {
00609                                         c = xgetc(instance);
00610                                         if (isdigit(c)) {
00611                                                 instance->thistoken = ALISP_FLOATE;
00612                                                 goto __ok;
00613                                         }
00614                                 }
00615                         } while (isdigit(c));
00616                         xungetc(instance, c);
00617                         *p = '\0';
00618                         return instance->thistoken;
00619 
00620                 got_id:
00621                 case '!': case '_': case '+': case '*': case '/': case '%':
00622                 case '<': case '>': case '=': case '&':
00623                 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
00624                 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
00625                 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
00626                 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
00627                 case 'y': case 'z':
00628                 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00629                 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
00630                 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
00631                 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
00632                 case 'Y': case 'Z':
00633                         /* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */
00634                         p = instance->token_buffer;
00635                         do {
00636                                 if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
00637                                         p = extend_buf(instance, p);
00638                                         if (p == NULL)
00639                                                 return instance->thistoken = EOF;
00640                                 }
00641                                 *p++ = c;
00642                                 c = xgetc(instance);
00643                         } while (isalnum(c) || strchr("!_-+*/%<>=&", c) != NULL);
00644                         xungetc(instance, c);
00645                         *p = '\0';
00646                         return instance->thistoken = ALISP_IDENTIFIER;
00647 
00648                 case '"':
00649                         /* String: "\""([^"]|"\\".)*"\"" */
00650                         p = instance->token_buffer;
00651                         while ((c = xgetc(instance)) != '"' && c != EOF) {
00652                                 if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
00653                                         p = extend_buf(instance, p);
00654                                         if (p == NULL)
00655                                                 return instance->thistoken = EOF;
00656                                 }
00657                                 if (c == '\\') {
00658                                         c = xgetc(instance);
00659                                         switch (c) {
00660                                         case '\n': ++instance->lineno; break;
00661                                         case 'a': *p++ = '\a'; break;
00662                                         case 'b': *p++ = '\b'; break;
00663                                         case 'f': *p++ = '\f'; break;
00664                                         case 'n': *p++ = '\n'; break;
00665                                         case 'r': *p++ = '\r'; break;
00666                                         case 't': *p++ = '\t'; break;
00667                                         case 'v': *p++ = '\v'; break;
00668                                         default: *p++ = c;
00669                                         }
00670                                 } else {
00671                                         if (c == '\n')
00672                                                 ++instance->lineno;
00673                                         *p++ = c;
00674                                 }
00675                         }
00676                         *p = '\0';
00677                         return instance->thistoken = ALISP_STRING;
00678 
00679                 default:
00680                         return instance->thistoken = c;
00681                 }
00682         }
00683 }
00684 
00685 /*
00686  *  parser
00687  */
00688 
00689 static struct alisp_object * parse_form(struct alisp_instance *instance)
00690 {
00691         int thistoken;
00692         struct alisp_object * p, * first = NULL, * prev = NULL;
00693 
00694         while ((thistoken = gettoken(instance)) != ')' && thistoken != EOF) {
00695                 /*
00696                  * Parse a dotted pair notation.
00697                  */
00698                 if (thistoken == '.') {
00699                         gettoken(instance);
00700                         if (prev == NULL) {
00701                                 lisp_error(instance, "unexpected '.'");
00702                               __err:
00703                                 delete_tree(instance, first);
00704                                 return NULL;
00705                         }
00706                         prev->value.c.cdr = parse_object(instance, 1);
00707                         if (prev->value.c.cdr == NULL)
00708                                 goto __err;
00709                         if ((thistoken = gettoken(instance)) != ')') {
00710                                 lisp_error(instance, "expected ')'");
00711                                 goto __err;
00712                         }
00713                         break;
00714                 }
00715 
00716                 p = new_object(instance, ALISP_OBJ_CONS);
00717                 if (p == NULL)
00718                         goto __err;
00719 
00720                 if (first == NULL)
00721                         first = p;
00722                 if (prev != NULL)
00723                         prev->value.c.cdr = p;
00724 
00725                 p->value.c.car = parse_object(instance, 1);
00726                 if (p->value.c.car == NULL)
00727                         goto __err;
00728 
00729                 prev = p;
00730         }
00731 
00732         if (first == NULL)
00733                 return &alsa_lisp_nil;
00734         else
00735                 return first;
00736 }
00737 
00738 static struct alisp_object * quote_object(struct alisp_instance *instance, struct alisp_object * obj)
00739 {
00740         struct alisp_object * p;
00741 
00742         if (obj == NULL)
00743                 goto __end1;
00744 
00745         p = new_object(instance, ALISP_OBJ_CONS);
00746         if (p == NULL)
00747                 goto __end1;
00748 
00749         p->value.c.car = new_identifier(instance, "quote");
00750         if (p->value.c.car == NULL)
00751                 goto __end;
00752         p->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
00753         if (p->value.c.cdr == NULL) {
00754                 delete_object(instance, p->value.c.car);
00755               __end:
00756                 delete_object(instance, p);
00757               __end1:
00758                 delete_tree(instance, obj);
00759                 return NULL;
00760         }
00761 
00762         p->value.c.cdr->value.c.car = obj;
00763         return p;
00764 }
00765 
00766 static inline struct alisp_object * parse_quote(struct alisp_instance *instance)
00767 {
00768         return quote_object(instance, parse_object(instance, 0));
00769 }
00770 
00771 static struct alisp_object * parse_object(struct alisp_instance *instance, int havetoken)
00772 {
00773         int thistoken;
00774         struct alisp_object * p = NULL;
00775 
00776         if (!havetoken)
00777                 thistoken = gettoken(instance);
00778         else
00779                 thistoken = instance->thistoken;
00780 
00781         switch (thistoken) {
00782         case EOF:
00783                 break;
00784         case '(':
00785                 p = parse_form(instance);
00786                 break;
00787         case '\'':
00788                 p = parse_quote(instance);
00789                 break;
00790         case ALISP_IDENTIFIER:
00791                 if (!strcmp(instance->token_buffer, "t"))
00792                         p = &alsa_lisp_t;
00793                 else if (!strcmp(instance->token_buffer, "nil"))
00794                         p = &alsa_lisp_nil;
00795                 else {
00796                         p = new_identifier(instance, instance->token_buffer);
00797                 }
00798                 break;
00799         case ALISP_INTEGER: {
00800                 p = new_integer(instance, atol(instance->token_buffer));
00801                 break;
00802         }
00803         case ALISP_FLOAT:
00804         case ALISP_FLOATE: {
00805                 p = new_float(instance, atof(instance->token_buffer));
00806                 break;
00807         }
00808         case ALISP_STRING:
00809                 p = new_string(instance, instance->token_buffer);
00810                 break;
00811         default:
00812                 lisp_warn(instance, "%d:%d: unexpected character `%c'", instance->lineno, instance->charno, thistoken);
00813                 break;
00814         }
00815 
00816         return p;
00817 }
00818 
00819 /*
00820  *  object manipulation
00821  */
00822 
00823 static struct alisp_object_pair * set_object_direct(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * value)
00824 {
00825         struct alisp_object_pair *p;
00826         const char *id;
00827 
00828         id = name->value.s;
00829         p = (struct alisp_object_pair *)malloc(sizeof(struct alisp_object_pair));
00830         if (p == NULL) {
00831                 nomem();
00832                 return NULL;
00833         }
00834         p->name = strdup(id);
00835         if (p->name == NULL) {
00836                 delete_tree(instance, value);
00837                 free(p);
00838                 return NULL;
00839         }
00840         list_add(&p->list, &instance->setobjs_list[get_string_hash(id)]);
00841         p->value = value;
00842         return p;
00843 }
00844 
00845 static int check_set_object(struct alisp_instance * instance, struct alisp_object * name)
00846 {
00847         if (name == &alsa_lisp_nil) {
00848                 lisp_warn(instance, "setting the value of a nil object");
00849                 return 0;
00850         }
00851         if (name == &alsa_lisp_t) {
00852                 lisp_warn(instance, "setting the value of a t object");
00853                 return 0;
00854         }
00855         if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
00856             !alisp_compare_type(name, ALISP_OBJ_STRING)) {
00857                 lisp_warn(instance, "setting the value of an object with non-indentifier");
00858                 return 0;
00859         }
00860         return 1;
00861 }
00862 
00863 static struct alisp_object_pair * set_object(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * value)
00864 {
00865         struct list_head *pos;
00866         struct alisp_object_pair *p;
00867         const char *id;
00868 
00869         if (name == NULL || value == NULL)
00870                 return NULL;
00871 
00872         id = name->value.s;
00873 
00874         list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
00875                 p = list_entry(pos, struct alisp_object_pair, list);
00876                 if (!strcmp(p->name, id)) {
00877                         delete_tree(instance, p->value);
00878                         p->value = value;
00879                         return p;
00880                 }
00881         }
00882 
00883         p = (struct alisp_object_pair *)malloc(sizeof(struct alisp_object_pair));
00884         if (p == NULL) {
00885                 nomem();
00886                 return NULL;
00887         }
00888         p->name = strdup(id);
00889         if (p->name == NULL) {
00890                 delete_tree(instance, value);
00891                 free(p);
00892                 return NULL;
00893         }
00894         list_add(&p->list, &instance->setobjs_list[get_string_hash(id)]);
00895         p->value = value;
00896         return p;
00897 }
00898 
00899 static struct alisp_object * unset_object(struct alisp_instance *instance, struct alisp_object * name)
00900 {
00901         struct list_head *pos;
00902         struct alisp_object *res;
00903         struct alisp_object_pair *p;
00904         const char *id;
00905         
00906         if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
00907             !alisp_compare_type(name, ALISP_OBJ_STRING)) {
00908                 lisp_warn(instance, "unset object with a non-indentifier");
00909                 return &alsa_lisp_nil;
00910         }
00911         id = name->value.s;
00912 
00913         list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
00914                 p = list_entry(pos, struct alisp_object_pair, list);
00915                 if (!strcmp(p->name, id)) {
00916                         list_del(&p->list);
00917                         res = p->value;
00918                         free((void *)p->name);
00919                         free(p);
00920                         return res;
00921                 }
00922         }
00923         
00924         return &alsa_lisp_nil;
00925 }
00926 
00927 static struct alisp_object * get_object1(struct alisp_instance *instance, const char *id)
00928 {
00929         struct alisp_object_pair *p;
00930         struct list_head *pos;
00931 
00932         list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
00933                 p = list_entry(pos, struct alisp_object_pair, list);
00934                 if (!strcmp(p->name, id))
00935                         return p->value;
00936         }
00937 
00938         return &alsa_lisp_nil;
00939 }
00940 
00941 static struct alisp_object * get_object(struct alisp_instance *instance, struct alisp_object * name)
00942 {
00943         if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
00944             !alisp_compare_type(name, ALISP_OBJ_STRING)) {
00945                 delete_tree(instance, name);
00946                 return &alsa_lisp_nil;
00947         }
00948         return get_object1(instance, name->value.s);
00949 }
00950 
00951 static struct alisp_object * replace_object(struct alisp_instance *instance, struct alisp_object * name, struct alisp_object * onew)
00952 {
00953         struct alisp_object_pair *p;
00954         struct alisp_object *r;
00955         struct list_head *pos;
00956         const char *id;
00957 
00958         if (!alisp_compare_type(name, ALISP_OBJ_IDENTIFIER) &&
00959             !alisp_compare_type(name, ALISP_OBJ_STRING)) {
00960                 delete_tree(instance, name);
00961                 return &alsa_lisp_nil;
00962         }
00963         id = name->value.s;
00964         list_for_each(pos, &instance->setobjs_list[get_string_hash(id)]) {
00965                 p = list_entry(pos, struct alisp_object_pair, list);
00966                 if (!strcmp(p->name, id)) {
00967                         r = p->value;
00968                         p->value = onew;
00969                         return r;
00970                 }
00971         }
00972 
00973         return NULL;
00974 }
00975 
00976 static void dump_objects(struct alisp_instance *instance, const char *fname)
00977 {
00978         struct alisp_object_pair *p;
00979         snd_output_t *out;
00980         struct list_head *pos;
00981         int i, err;
00982 
00983         if (!strcmp(fname, "-"))
00984                 err = snd_output_stdio_attach(&out, stdout, 0);
00985         else
00986                 err = snd_output_stdio_open(&out, fname, "w+");
00987         if (err < 0) {
00988                 SNDERR("alisp: cannot open file '%s' for writting (%s)", fname, snd_strerror(errno));
00989                 return;
00990         }
00991 
00992         for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
00993                 list_for_each(pos, &instance->setobjs_list[i]) {
00994                         p = list_entry(pos, struct alisp_object_pair, list);
00995                         if (alisp_compare_type(p->value, ALISP_OBJ_CONS) &&
00996                             alisp_compare_type(p->value->value.c.car, ALISP_OBJ_IDENTIFIER) &&
00997                             !strcmp(p->value->value.c.car->value.s, "lambda")) {
00998                                 snd_output_printf(out, "(defun %s ", p->name);
00999                                 princ_cons(out, p->value->value.c.cdr);
01000                                 snd_output_printf(out, ")\n");
01001                                 continue;
01002                         }
01003                         snd_output_printf(out, "(setq %s '", p->name);
01004                         princ_object(out, p->value);
01005                         snd_output_printf(out, ")\n");
01006                 }
01007         }
01008         snd_output_close(out);
01009 }
01010 
01011 static const char *obj_type_str(struct alisp_object * p)
01012 {
01013         switch (alisp_get_type(p)) {
01014         case ALISP_OBJ_NIL: return "nil";
01015         case ALISP_OBJ_T: return "t";
01016         case ALISP_OBJ_INTEGER: return "integer";
01017         case ALISP_OBJ_FLOAT: return "float";
01018         case ALISP_OBJ_IDENTIFIER: return "identifier";
01019         case ALISP_OBJ_STRING: return "string";
01020         case ALISP_OBJ_POINTER: return "pointer";
01021         case ALISP_OBJ_CONS: return "cons";
01022         default: assert(0);
01023         }
01024 }
01025 
01026 static void print_obj_lists(struct alisp_instance *instance, snd_output_t *out)
01027 {
01028         struct list_head *pos;
01029         struct alisp_object * p;
01030         int i, j;
01031 
01032         snd_output_printf(out, "** used objects\n");
01033         for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
01034                 for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++)
01035                         list_for_each(pos, &instance->used_objs_list[i][j]) {
01036                                 p = list_entry(pos, struct alisp_object, list);
01037                                 snd_output_printf(out, "**   %p (%s) (", p, obj_type_str(p));
01038                                 if (!alisp_compare_type(p, ALISP_OBJ_CONS))
01039                                         princ_object(out, p);
01040                                 else
01041                                         snd_output_printf(out, "cons");
01042                                 snd_output_printf(out, ") refs=%i\n", alisp_get_refs(p));
01043                         }
01044         snd_output_printf(out, "** free objects\n");
01045         list_for_each(pos, &instance->free_objs_list) {
01046                 p = list_entry(pos, struct alisp_object, list);
01047                 snd_output_printf(out, "**   %p\n", p);
01048         }
01049 }
01050 
01051 static void dump_obj_lists(struct alisp_instance *instance, const char *fname)
01052 {
01053         snd_output_t *out;
01054         int err;
01055 
01056         if (!strcmp(fname, "-"))
01057                 err = snd_output_stdio_attach(&out, stdout, 0);
01058         else
01059                 err = snd_output_stdio_open(&out, fname, "w+");
01060         if (err < 0) {
01061                 SNDERR("alisp: cannot open file '%s' for writting (%s)", fname, snd_strerror(errno));
01062                 return;
01063         }
01064 
01065         print_obj_lists(instance, out);
01066 
01067         snd_output_close(out);
01068 }
01069 
01070 /*
01071  *  functions
01072  */
01073 
01074 static int count_list(struct alisp_object * p)
01075 {
01076         int i = 0;
01077 
01078         while (p != &alsa_lisp_nil && alisp_compare_type(p, ALISP_OBJ_CONS)) {
01079                 p = p->value.c.cdr;
01080                 ++i;
01081         }
01082 
01083         return i;
01084 }
01085 
01086 static inline struct alisp_object * car(struct alisp_object * p)
01087 {
01088         if (alisp_compare_type(p, ALISP_OBJ_CONS))
01089                 return p->value.c.car;
01090 
01091         return &alsa_lisp_nil;
01092 }
01093 
01094 static inline struct alisp_object * cdr(struct alisp_object * p)
01095 {
01096         if (alisp_compare_type(p, ALISP_OBJ_CONS))
01097                 return p->value.c.cdr;
01098 
01099         return &alsa_lisp_nil;
01100 }
01101 
01102 /*
01103  * Syntax: (car expr)
01104  */
01105 static struct alisp_object * F_car(struct alisp_instance *instance, struct alisp_object * args)
01106 {
01107         struct alisp_object *p1 = car(args), *p2;
01108         delete_tree(instance, cdr(args));
01109         delete_object(instance, args);
01110         p1 = eval(instance, p1);
01111         delete_tree(instance, cdr(p1));
01112         p2 = car(p1);
01113         delete_object(instance, p1);
01114         return p2;
01115 }
01116 
01117 /*
01118  * Syntax: (cdr expr)
01119  */
01120 static struct alisp_object * F_cdr(struct alisp_instance *instance, struct alisp_object * args)
01121 {
01122         struct alisp_object *p1 = car(args), *p2;
01123         delete_tree(instance, cdr(args));
01124         delete_object(instance, args);
01125         p1 = eval(instance, p1);
01126         delete_tree(instance, car(p1));
01127         p2 = cdr(p1);
01128         delete_object(instance, p1);
01129         return p2;
01130 }
01131 
01132 /*
01133  * Syntax: (+ expr...)
01134  */
01135 static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args)
01136 {
01137         struct alisp_object * p = args, * p1, * n;
01138         long v = 0;
01139         double f = 0;
01140         int type = ALISP_OBJ_INTEGER;
01141 
01142         p1 = eval(instance, car(p));
01143         for (;;) {
01144                 if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
01145                         if (type == ALISP_OBJ_FLOAT)
01146                                 f += p1->value.i;
01147                         else
01148                                 v += p1->value.i;
01149                 } else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
01150                         f += p1->value.f + v;
01151                         v = 0;
01152                         type = ALISP_OBJ_FLOAT;
01153                 } else {
01154                         lisp_warn(instance, "sum with a non integer or float operand");
01155                 }
01156                 delete_tree(instance, p1);
01157                 p = cdr(n = p);
01158                 delete_object(instance, n);
01159                 if (p == &alsa_lisp_nil)
01160                         break;
01161                 p1 = eval(instance, car(p));
01162         }
01163         if (type == ALISP_OBJ_INTEGER) {
01164                 return new_integer(instance, v);
01165         } else {
01166                 return new_float(instance, f);
01167         }
01168 }
01169 
01170 /*
01171  * Syntax: (concat expr...)
01172  */
01173 static struct alisp_object * F_concat(struct alisp_instance *instance, struct alisp_object * args)
01174 {
01175         struct alisp_object * p = args, * p1, * n;
01176         char *str = NULL, *str1;
01177         
01178         p1 = eval(instance, car(p));
01179         for (;;) {
01180                 if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
01181                         str1 = realloc(str, (str ? strlen(str) : 0) + strlen(p1->value.s) + 1);
01182                         if (str1 == NULL) {
01183                                 nomem();
01184                                 free(str);
01185                                 return NULL;
01186                         }
01187                         if (str == NULL)
01188                                 strcpy(str1, p1->value.s);
01189                         else
01190                                 strcat(str1, p1->value.s);
01191                         str = str1;
01192                 } else {
01193                         lisp_warn(instance, "concat with a non string or identifier operand");
01194                 }
01195                 delete_tree(instance, p1);
01196                 p = cdr(n = p);
01197                 delete_object(instance, n);
01198                 if (p == &alsa_lisp_nil)
01199                         break;
01200                 p1 = eval(instance, car(p));
01201         }
01202         if (str) {
01203                 p = new_string(instance, str);
01204                 free(str);
01205         } else {
01206                 p = &alsa_lisp_nil;
01207         }
01208         return p;
01209 }
01210 
01211 /*
01212  * Syntax: (- expr...)
01213  */
01214 static struct alisp_object * F_sub(struct alisp_instance *instance, struct alisp_object * args)
01215 {
01216         struct alisp_object * p = args, * p1, * n;
01217         long v = 0;
01218         double f = 0;
01219         int type = ALISP_OBJ_INTEGER;
01220 
01221         do {
01222                 p1 = eval(instance, car(p));
01223                 if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
01224                         if (p == args && cdr(p) != &alsa_lisp_nil) {
01225                                 v = p1->value.i;
01226                         } else {
01227                                 if (type == ALISP_OBJ_FLOAT)
01228                                         f -= p1->value.i;
01229                                 else
01230                                         v -= p1->value.i;
01231                         }
01232                 } else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
01233                         if (type == ALISP_OBJ_INTEGER) {
01234                                 f = v;
01235                                 type = ALISP_OBJ_FLOAT;
01236                         }
01237                         if (p == args && cdr(p) != &alsa_lisp_nil)
01238                                 f = p1->value.f;
01239                         else {
01240                                 f -= p1->value.f;
01241                         }
01242                 } else
01243                         lisp_warn(instance, "difference with a non integer or float operand");
01244                 delete_tree(instance, p1);
01245                 n = cdr(p);
01246                 delete_object(instance, p);
01247                 p = n;
01248         } while (p != &alsa_lisp_nil);
01249 
01250         if (type == ALISP_OBJ_INTEGER) {
01251                 return new_integer(instance, v);
01252         } else {
01253                 return new_float(instance, f);
01254         }
01255 }
01256 
01257 /*
01258  * Syntax: (* expr...)
01259  */
01260 static struct alisp_object * F_mul(struct alisp_instance *instance, struct alisp_object * args)
01261 {
01262         struct alisp_object * p = args, * p1, * n;
01263         long v = 1;
01264         double f = 1;
01265         int type = ALISP_OBJ_INTEGER;
01266 
01267         do {
01268                 p1 = eval(instance, car(p));
01269                 if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
01270                         if (type == ALISP_OBJ_FLOAT)
01271                                 f *= p1->value.i;
01272                         else
01273                                 v *= p1->value.i;
01274                 } else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
01275                         f *= p1->value.f * v; v = 1;
01276                         type = ALISP_OBJ_FLOAT;
01277                 } else {
01278                         lisp_warn(instance, "product with a non integer or float operand");
01279                 }
01280                 delete_tree(instance, p1);
01281                 n = cdr(p);
01282                 delete_object(instance, p);
01283                 p = n;
01284         } while (p != &alsa_lisp_nil);
01285 
01286         if (type == ALISP_OBJ_INTEGER) {
01287                 return new_integer(instance, v);
01288         } else {
01289                 return new_float(instance, f);
01290         }
01291 }
01292 
01293 /*
01294  * Syntax: (/ expr...)
01295  */
01296 static struct alisp_object * F_div(struct alisp_instance *instance, struct alisp_object * args)
01297 {
01298         struct alisp_object * p = args, * p1, * n;
01299         long v = 0;
01300         double f = 0;
01301         int type = ALISP_OBJ_INTEGER;
01302 
01303         do {
01304                 p1 = eval(instance, car(p));
01305                 if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
01306                         if (p == args && cdr(p) != &alsa_lisp_nil) {
01307                                 v = p1->value.i;
01308                         } else {
01309                                 if (p1->value.i == 0) {
01310                                         lisp_warn(instance, "division by zero");
01311                                         v = 0;
01312                                         f = 0;
01313                                         break;
01314                                 } else {
01315                                         if (type == ALISP_OBJ_FLOAT)
01316                                                 f /= p1->value.i;
01317                                         else
01318                                                 v /= p1->value.i;
01319                                 }
01320                         }
01321                 } else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
01322                         if (type == ALISP_OBJ_INTEGER) {
01323                                 f = v;
01324                                 type = ALISP_OBJ_FLOAT;
01325                         }
01326                         if (p == args && cdr(p) != &alsa_lisp_nil) {
01327                                 f = p1->value.f;
01328                         } else {
01329                                 if (p1->value.f == 0) {
01330                                         lisp_warn(instance, "division by zero");
01331                                         f = 0;
01332                                         break;
01333                                 } else {
01334                                         f /= p1->value.i;
01335                                 }
01336                         }
01337                 } else
01338                         lisp_warn(instance, "quotient with a non integer or float operand");
01339                 delete_tree(instance, p1);
01340                 n = cdr(p);
01341                 delete_object(instance, p);
01342                 p = n;
01343         } while (p != &alsa_lisp_nil);
01344 
01345         if (type == ALISP_OBJ_INTEGER) {
01346                 return new_integer(instance, v);
01347         } else {
01348                 return new_float(instance, f);
01349         }
01350 }
01351 
01352 /*
01353  * Syntax: (% expr1 expr2)
01354  */
01355 static struct alisp_object * F_mod(struct alisp_instance *instance, struct alisp_object * args)
01356 {
01357         struct alisp_object * p1, * p2, * p3;
01358 
01359         p1 = eval(instance, car(args));
01360         p2 = eval(instance, car(cdr(args)));
01361         delete_tree(instance, cdr(cdr(args)));
01362         delete_object(instance, cdr(args));
01363         delete_object(instance, args);
01364 
01365         if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
01366             alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
01367                 if (p2->value.i == 0) {
01368                         lisp_warn(instance, "module by zero");
01369                         p3 = new_integer(instance, 0);
01370                 } else {
01371                         p3 = new_integer(instance, p1->value.i % p2->value.i);
01372                 }
01373         } else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) || 
01374                     alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
01375                    (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
01376                     alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
01377                 double f1, f2;
01378                 f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
01379                 f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
01380                 f1 = fmod(f1, f2);
01381                 if (f1 == EDOM) {
01382                         lisp_warn(instance, "module by zero");
01383                         p3 = new_float(instance, 0);
01384                 } else {
01385                         p3 = new_float(instance, f1);
01386                 }
01387         } else {
01388                 lisp_warn(instance, "module with a non integer or float operand");
01389                 delete_tree(instance, p1);
01390                 delete_tree(instance, p2);
01391                 return &alsa_lisp_nil;
01392         }
01393 
01394         delete_tree(instance, p1);
01395         delete_tree(instance, p2);
01396         return p3;
01397 }
01398 
01399 /*
01400  * Syntax: (< expr1 expr2)
01401  */
01402 static struct alisp_object * F_lt(struct alisp_instance *instance, struct alisp_object * args)
01403 {
01404         struct alisp_object * p1, * p2;
01405 
01406         p1 = eval(instance, car(args));
01407         p2 = eval(instance, car(cdr(args)));
01408         delete_tree(instance, cdr(cdr(args)));
01409         delete_object(instance, cdr(args));
01410         delete_object(instance, args);
01411 
01412         if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
01413             alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
01414                 if (p1->value.i < p2->value.i) {
01415                       __true:
01416                         delete_tree(instance, p1);
01417                         delete_tree(instance, p2);
01418                         return &alsa_lisp_t;
01419                 }
01420         } else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
01421                     alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
01422                    (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
01423                     alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
01424                 double f1, f2;
01425                 f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
01426                 f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
01427                 if (f1 < f2)
01428                         goto __true;
01429         } else {
01430                 lisp_warn(instance, "comparison with a non integer or float operand");
01431         }
01432 
01433         delete_tree(instance, p1);
01434         delete_tree(instance, p2);
01435         return &alsa_lisp_nil;
01436 }
01437 
01438 /*
01439  * Syntax: (> expr1 expr2)
01440  */
01441 static struct alisp_object * F_gt(struct alisp_instance *instance, struct alisp_object * args)
01442 {
01443         struct alisp_object * p1, * p2;
01444 
01445         p1 = eval(instance, car(args));
01446         p2 = eval(instance, car(cdr(args)));
01447         delete_tree(instance, cdr(cdr(args)));
01448         delete_object(instance, cdr(args));
01449         delete_object(instance, args);
01450 
01451         if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
01452             alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
01453                 if (p1->value.i > p2->value.i) {
01454                       __true:
01455                         delete_tree(instance, p1);
01456                         delete_tree(instance, p2);
01457                         return &alsa_lisp_t;
01458                 }
01459         } else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
01460                     alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
01461                    (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
01462                     alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
01463                 double f1, f2;
01464                 f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
01465                 f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
01466                 if (f1 > f2)
01467                         goto __true;
01468         } else {
01469                 lisp_warn(instance, "comparison with a non integer or float operand");
01470         }
01471 
01472         delete_tree(instance, p1);
01473         delete_tree(instance, p2);
01474         return &alsa_lisp_nil;
01475 }
01476 
01477 /*
01478  * Syntax: (<= expr1 expr2)
01479  */
01480 static struct alisp_object * F_le(struct alisp_instance *instance, struct alisp_object * args)
01481 {
01482         struct alisp_object * p1, * p2;
01483 
01484         p1 = eval(instance, car(args));
01485         p2 = eval(instance, car(cdr(args)));
01486         delete_tree(instance, cdr(cdr(args)));
01487         delete_object(instance, cdr(args));
01488         delete_object(instance, args);
01489 
01490         if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
01491             alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
01492                 if (p1->value.i <= p2->value.i) {
01493                       __true:
01494                         delete_tree(instance, p1);
01495                         delete_tree(instance, p2);
01496                         return &alsa_lisp_t;
01497                 }
01498         } else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
01499                     alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
01500                    (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
01501                     alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
01502                 double f1, f2;
01503                 f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
01504                 f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
01505                 if (f1 <= f2)
01506                         goto __true;
01507         } else {
01508                 lisp_warn(instance, "comparison with a non integer or float operand");
01509         }
01510 
01511         delete_tree(instance, p1);
01512         delete_tree(instance, p2);
01513         return &alsa_lisp_nil;
01514 }
01515 
01516 /*
01517  * Syntax: (>= expr1 expr2)
01518  */
01519 static struct alisp_object * F_ge(struct alisp_instance *instance, struct alisp_object * args)
01520 {
01521         struct alisp_object * p1, * p2;
01522 
01523         p1 = eval(instance, car(args));
01524         p2 = eval(instance, car(cdr(args)));
01525         delete_tree(instance, cdr(cdr(args)));
01526         delete_object(instance, cdr(args));
01527         delete_object(instance, args);
01528 
01529         if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
01530             alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
01531                 if (p1->value.i >= p2->value.i) {
01532                       __true:
01533                         delete_tree(instance, p1);
01534                         delete_tree(instance, p2);
01535                         return &alsa_lisp_t;
01536                 }
01537         } else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
01538                     alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
01539                    (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
01540                     alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
01541                 double f1, f2;
01542                 f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
01543                 f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
01544                 if (f1 >= f2)
01545                         goto __true;
01546         } else {
01547                 lisp_warn(instance, "comparison with a non integer or float operand");
01548         }
01549 
01550         delete_tree(instance, p1);
01551         delete_tree(instance, p2);
01552         return &alsa_lisp_nil;
01553 }
01554 
01555 /*
01556  * Syntax: (= expr1 expr2)
01557  */
01558 static struct alisp_object * F_numeq(struct alisp_instance *instance, struct alisp_object * args)
01559 {
01560         struct alisp_object * p1, * p2;
01561 
01562         p1 = eval(instance, car(args));
01563         p2 = eval(instance, car(cdr(args)));
01564         delete_tree(instance, cdr(cdr(args)));
01565         delete_object(instance, cdr(args));
01566         delete_object(instance, args);
01567 
01568         if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) &&
01569             alisp_compare_type(p2, ALISP_OBJ_INTEGER)) {
01570                 if (p1->value.i == p2->value.i) {
01571                       __true:
01572                         delete_tree(instance, p1);
01573                         delete_tree(instance, p2);
01574                         return &alsa_lisp_t;
01575                 }
01576         } else if ((alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
01577                     alisp_compare_type(p1, ALISP_OBJ_FLOAT)) &&
01578                    (alisp_compare_type(p2, ALISP_OBJ_INTEGER) ||
01579                     alisp_compare_type(p2, ALISP_OBJ_FLOAT))) {
01580                 double f1, f2;
01581                 f1 = alisp_compare_type(p1, ALISP_OBJ_INTEGER) ? p1->value.i : p1->value.f;
01582                 f2 = alisp_compare_type(p2, ALISP_OBJ_INTEGER) ? p2->value.i : p2->value.f;
01583                 if (f1 == f2)
01584                         goto __true;
01585         } else {
01586                 lisp_warn(instance, "comparison with a non integer or float operand");
01587         }
01588 
01589         delete_tree(instance, p1);
01590         delete_tree(instance, p2);
01591         return &alsa_lisp_nil;
01592 }
01593 
01594 /*
01595  * Syntax: (!= expr1 expr2)
01596  */
01597 static struct alisp_object * F_numneq(struct alisp_instance *instance, struct alisp_object * args)
01598 {
01599         struct alisp_object * p;
01600         
01601         p = F_numeq(instance, args);
01602         if (p == &alsa_lisp_nil)
01603                 return &alsa_lisp_t;
01604         return &alsa_lisp_nil;
01605 }
01606 
01607 /*
01608  * Syntax: (exfun name)
01609  * Test, if a function exists
01610  */
01611 static struct alisp_object * F_exfun(struct alisp_instance *instance, struct alisp_object * args)
01612 {
01613         struct alisp_object * p1, * p2;
01614 
01615         p1 = eval(instance, car(args));
01616         delete_tree(instance, cdr(args));
01617         delete_object(instance, args);
01618         p2 = get_object(instance, p1);
01619         if (p2 == &alsa_lisp_nil) {
01620                 delete_tree(instance, p1);
01621                 return &alsa_lisp_nil;
01622         }
01623         p2 = car(p2);
01624         if (alisp_compare_type(p2, ALISP_OBJ_IDENTIFIER) &&
01625             !strcmp(p2->value.s, "lambda")) {
01626                 delete_tree(instance, p1);
01627                 return &alsa_lisp_t;
01628         }
01629         delete_tree(instance, p1);
01630         return &alsa_lisp_nil;
01631 }
01632 
01633 static void princ_string(snd_output_t *out, char *s)
01634 {
01635         char *p;
01636 
01637         snd_output_putc(out, '"');
01638         for (p = s; *p != '\0'; ++p)
01639                 switch (*p) {
01640                 case '\a': snd_output_putc(out, '\\'); snd_output_putc(out, 'a'); break;
01641                 case '\b': snd_output_putc(out, '\\'); snd_output_putc(out, 'b'); break;
01642                 case '\f': snd_output_putc(out, '\\'); snd_output_putc(out, 'f'); break;
01643                 case '\n': snd_output_putc(out, '\\'); snd_output_putc(out, 'n'); break;
01644                 case '\r': snd_output_putc(out, '\\'); snd_output_putc(out, 'r'); break;
01645                 case '\t': snd_output_putc(out, '\\'); snd_output_putc(out, 't'); break;
01646                 case '\v': snd_output_putc(out, '\\'); snd_output_putc(out, 'v'); break;
01647                 case '"': snd_output_putc(out, '\\'); snd_output_putc(out, '"'); break;
01648                 default: snd_output_putc(out, *p);
01649                 }
01650         snd_output_putc(out, '"');
01651 }
01652 
01653 static void princ_cons(snd_output_t *out, struct alisp_object * p)
01654 {
01655         do {
01656                 princ_object(out, p->value.c.car);
01657                 p = p->value.c.cdr;
01658                 if (p != &alsa_lisp_nil) {
01659                         snd_output_putc(out, ' ');
01660                         if (!alisp_compare_type(p, ALISP_OBJ_CONS)) {
01661                                 snd_output_printf(out, ". ");
01662                                 princ_object(out, p);
01663                         }
01664                 }
01665         } while (p != &alsa_lisp_nil && alisp_compare_type(p, ALISP_OBJ_CONS));
01666 }
01667 
01668 static void princ_object(snd_output_t *out, struct alisp_object * p)
01669 {
01670         switch (alisp_get_type(p)) {
01671         case ALISP_OBJ_NIL:
01672                 snd_output_printf(out, "nil");
01673                 break;
01674         case ALISP_OBJ_T:
01675                 snd_output_putc(out, 't');
01676                 break;
01677         case ALISP_OBJ_IDENTIFIER:
01678                 snd_output_printf(out, "%s", p->value.s);
01679                 break;
01680         case ALISP_OBJ_STRING:
01681                 princ_string(out, p->value.s);
01682                 break;
01683         case ALISP_OBJ_INTEGER:
01684                 snd_output_printf(out, "%ld", p->value.i);
01685                 break;
01686         case ALISP_OBJ_FLOAT:
01687                 snd_output_printf(out, "%f", p->value.f);
01688                 break;
01689         case ALISP_OBJ_POINTER:
01690                 snd_output_printf(out, "<%p>", p->value.ptr);
01691                 break;
01692         case ALISP_OBJ_CONS:
01693                 snd_output_putc(out, '(');
01694                 princ_cons(out, p);
01695                 snd_output_putc(out, ')');
01696         }
01697 }
01698 
01699 /*
01700  * Syntax: (princ expr...)
01701  */
01702 static struct alisp_object * F_princ(struct alisp_instance *instance, struct alisp_object * args)
01703 {
01704         struct alisp_object * p = args, * p1 = NULL, * n;
01705 
01706         do {
01707                 if (p1)
01708                         delete_tree(instance, p1);
01709                 p1 = eval(instance, car(p));
01710                 if (alisp_compare_type(p1, ALISP_OBJ_STRING))
01711                         snd_output_printf(instance->out, p1->value.s);
01712                 else
01713                         princ_object(instance->out, p1);
01714                 n = cdr(p);
01715                 delete_object(instance, p);
01716                 p = n;
01717         } while (p != &alsa_lisp_nil);
01718 
01719         return p1;
01720 }
01721 
01722 /*
01723  * Syntax: (atom expr)
01724  */
01725 static struct alisp_object * F_atom(struct alisp_instance *instance, struct alisp_object * args)
01726 {
01727         struct alisp_object * p;
01728 
01729         p = eval(instance, car(args));
01730         delete_tree(instance, cdr(args));
01731         delete_object(instance, args);
01732         if (p == NULL)
01733                 return NULL;
01734 
01735         switch (alisp_get_type(p)) {
01736         case ALISP_OBJ_T:
01737         case ALISP_OBJ_NIL:
01738         case ALISP_OBJ_INTEGER:
01739         case ALISP_OBJ_FLOAT:
01740         case ALISP_OBJ_STRING:
01741         case ALISP_OBJ_IDENTIFIER:
01742         case ALISP_OBJ_POINTER:
01743                 delete_tree(instance, p);
01744                 return &alsa_lisp_t;
01745         default:
01746                 break;
01747         }
01748 
01749         delete_tree(instance, p);
01750         return &alsa_lisp_nil;
01751 }
01752 
01753 /*
01754  * Syntax: (cons expr1 expr2)
01755  */
01756 static struct alisp_object * F_cons(struct alisp_instance *instance, struct alisp_object * args)
01757 {
01758         struct alisp_object * p;
01759 
01760         p = new_object(instance, ALISP_OBJ_CONS);
01761         if (p) {
01762                 p->value.c.car = eval(instance, car(args));
01763                 p->value.c.cdr = eval(instance, car(cdr(args)));
01764                 delete_tree(instance, cdr(cdr(args)));
01765                 delete_object(instance, cdr(args));
01766                 delete_object(instance, args);
01767         } else {
01768                 delete_tree(instance, args);
01769         }
01770 
01771         return p;
01772 }
01773 
01774 /*
01775  * Syntax: (list expr1...)
01776  */
01777 static struct alisp_object * F_list(struct alisp_instance *instance, struct alisp_object * args)
01778 {
01779         struct alisp_object * p = args, * first = NULL, * prev = NULL, * p1;
01780 
01781         if (p == &alsa_lisp_nil)
01782                 return &alsa_lisp_nil;
01783 
01784         do {
01785                 p1 = new_object(instance, ALISP_OBJ_CONS);
01786                 if (p1 == NULL) {
01787                         delete_tree(instance, p);
01788                         delete_tree(instance, first);
01789                         return NULL;
01790                 }
01791                 p1->value.c.car = eval(instance, car(p));
01792                 if (p1->value.c.car == NULL) {
01793                         delete_tree(instance, first);
01794                         delete_tree(instance, cdr(p));
01795                         delete_object(instance, p);
01796                         return NULL;
01797                 }
01798                 if (first == NULL)
01799                         first = p1;
01800                 if (prev != NULL)
01801                         prev->value.c.cdr = p1;
01802                 prev = p1;
01803                 p = cdr(p1 = p);
01804                 delete_object(instance, p1);
01805         } while (p != &alsa_lisp_nil);
01806 
01807         return first;
01808 }
01809 
01810 static inline int eq(struct alisp_object * p1, struct alisp_object * p2)
01811 {
01812         return p1 == p2;
01813 }
01814 
01815 static int equal(struct alisp_object * p1, struct alisp_object * p2)
01816 {
01817         int type1, type2;
01818 
01819         if (eq(p1, p2))
01820                 return 1;
01821 
01822         type1 = alisp_get_type(p1);
01823         type2 = alisp_get_type(p2);
01824 
01825         if (type1 == ALISP_OBJ_CONS || type2 == ALISP_OBJ_CONS)
01826                 return 0;
01827 
01828         if (type1 == type2) {
01829                 switch (type1) {
01830                 case ALISP_OBJ_STRING:
01831                         return !strcmp(p1->value.s, p2->value.s);
01832                 case ALISP_OBJ_INTEGER:
01833                         return p1->value.i == p2->value.i;
01834                 case ALISP_OBJ_FLOAT:
01835                         return p1->value.i == p2->value.i;
01836                 }
01837         }
01838 
01839         return 0;
01840 }
01841 
01842 /*
01843  * Syntax: (eq expr1 expr2)
01844  */
01845 static struct alisp_object * F_eq(struct alisp_instance *instance, struct alisp_object * args)
01846 {
01847         struct alisp_object * p1, * p2;
01848 
01849         p1 = eval(instance, car(args));
01850         p2 = eval(instance, car(cdr(args)));
01851         delete_tree(instance, cdr(cdr(args)));
01852         delete_object(instance, cdr(args));
01853         delete_object(instance, args);
01854 
01855         if (eq(p1, p2)) {
01856                 delete_tree(instance, p1);
01857                 delete_tree(instance, p2);
01858                 return &alsa_lisp_t;
01859         }
01860         delete_tree(instance, p1);
01861         delete_tree(instance, p2);
01862         return &alsa_lisp_nil;
01863 }
01864 
01865 /*
01866  * Syntax: (equal expr1 expr2)
01867  */
01868 static struct alisp_object * F_equal(struct alisp_instance *instance, struct alisp_object * args)
01869 {
01870         struct alisp_object * p1, * p2;
01871 
01872         p1 = eval(instance, car(args));
01873         p2 = eval(instance, car(cdr(args)));
01874         delete_tree(instance, cdr(cdr(args)));
01875         delete_object(instance, cdr(args));
01876         delete_object(instance, args);
01877 
01878         if (equal(p1, p2)) {
01879                 delete_tree(instance, p1);
01880                 delete_tree(instance, p2);
01881                 return &alsa_lisp_t;
01882         }
01883         delete_tree(instance, p1);
01884         delete_tree(instance, p2);
01885         return &alsa_lisp_nil;
01886 }
01887 
01888 /*
01889  * Syntax: (quote expr)
01890  */
01891 static struct alisp_object * F_quote(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args)
01892 {
01893         struct alisp_object *p = car(args);
01894         
01895         delete_tree(instance, cdr(args));
01896         delete_object(instance, args);
01897         return p;
01898 }
01899 
01900 /*
01901  * Syntax: (and expr...)
01902  */
01903 static struct alisp_object * F_and(struct alisp_instance *instance, struct alisp_object * args)
01904 {
01905         struct alisp_object * p = args, * p1 = NULL, * n;
01906 
01907         do {
01908                 if (p1)
01909                         delete_tree(instance, p1);
01910                 p1 = eval(instance, car(p));
01911                 if (p1 == &alsa_lisp_nil) {
01912                         delete_tree(instance, p1);
01913                         delete_tree(instance, cdr(p));
01914                         delete_object(instance, p);
01915                         return &alsa_lisp_nil;
01916                 }
01917                 p = cdr(n = p);
01918                 delete_object(instance, n);
01919         } while (p != &alsa_lisp_nil);
01920 
01921         return p1;
01922 }
01923 
01924 /*
01925  * Syntax: (or expr...)
01926  */
01927 static struct alisp_object * F_or(struct alisp_instance *instance, struct alisp_object * args)
01928 {
01929         struct alisp_object * p = args, * p1 = NULL, * n;
01930 
01931         do {
01932                 if (p1)
01933                         delete_tree(instance, p1);
01934                 p1 = eval(instance, car(p));
01935                 if (p1 != &alsa_lisp_nil) {
01936                         delete_tree(instance, cdr(p));
01937                         delete_object(instance, p);
01938                         return p1;
01939                 }
01940                 p = cdr(n = p);
01941                 delete_object(instance, n);
01942         } while (p != &alsa_lisp_nil);
01943 
01944         return &alsa_lisp_nil;
01945 }
01946 
01947 /*
01948  * Syntax: (not expr)
01949  * Syntax: (null expr)
01950  */
01951 static struct alisp_object * F_not(struct alisp_instance *instance, struct alisp_object * args)
01952 {
01953         struct alisp_object * p = eval(instance, car(args));
01954 
01955         delete_tree(instance, cdr(args));
01956         delete_object(instance, args);
01957         if (p != &alsa_lisp_nil) {
01958                 delete_tree(instance, p);
01959                 return &alsa_lisp_nil;
01960         }
01961 
01962         delete_tree(instance, p);
01963         return &alsa_lisp_t;
01964 }
01965 
01966 /*
01967  * Syntax: (cond (expr1 [expr2])...)
01968  */
01969 static struct alisp_object * F_cond(struct alisp_instance *instance, struct alisp_object * args)
01970 {
01971         struct alisp_object * p = args, * p1, * p2, * p3;
01972 
01973         do {
01974                 p1 = car(p);
01975                 if ((p2 = eval(instance, car(p1))) != &alsa_lisp_nil) {
01976                         p3 = cdr(p1);
01977                         delete_object(instance, p1);
01978                         delete_tree(instance, cdr(p));
01979                         delete_object(instance, p);
01980                         if (p3 != &alsa_lisp_nil) {
01981                                 delete_tree(instance, p2);
01982                                 return F_progn(instance, p3);
01983                         } else {
01984                                 delete_tree(instance, p3);
01985                                 return p2;
01986                         }
01987                 } else {
01988                         delete_tree(instance, p2);
01989                         delete_tree(instance, cdr(p1));
01990                         delete_object(instance, p1);
01991                 }
01992                 p = cdr(p2 = p);
01993                 delete_object(instance, p2);
01994         } while (p != &alsa_lisp_nil);
01995 
01996         return &alsa_lisp_nil;
01997 }
01998 
01999 /*
02000  * Syntax: (if expr then-expr else-expr...)
02001  */
02002 static struct alisp_object * F_if(struct alisp_instance *instance, struct alisp_object * args)
02003 {
02004         struct alisp_object * p1, * p2, * p3;
02005 
02006         p1 = car(args);
02007         p2 = car(cdr(args));
02008         p3 = cdr(cdr(args));
02009         delete_object(instance, cdr(args));
02010         delete_object(instance, args);
02011 
02012         p1 = eval(instance, p1);
02013         if (p1 != &alsa_lisp_nil) {
02014                 delete_tree(instance, p1);
02015                 delete_tree(instance, p3);
02016                 return eval(instance, p2);
02017         }
02018 
02019         delete_tree(instance, p1);
02020         delete_tree(instance, p2);
02021         return F_progn(instance, p3);
02022 }
02023 
02024 /*
02025  * Syntax: (when expr then-expr...)
02026  */
02027 static struct alisp_object * F_when(struct alisp_instance *instance, struct alisp_object * args)
02028 {
02029         struct alisp_object * p1, * p2;
02030 
02031         p1 = car(args);
02032         p2 = cdr(args);
02033         delete_object(instance, args);
02034         if ((p1 = eval(instance, p1)) != &alsa_lisp_nil) {
02035                 delete_tree(instance, p1);
02036                 return F_progn(instance, p2);
02037         } else {
02038                 delete_tree(instance, p1);
02039                 delete_tree(instance, p2);
02040         }
02041 
02042         return &alsa_lisp_nil;
02043 }
02044 
02045 /*
02046  * Syntax: (unless expr else-expr...)
02047  */
02048 static struct alisp_object * F_unless(struct alisp_instance *instance, struct alisp_object * args)
02049 {
02050         struct alisp_object * p1, * p2;
02051 
02052         p1 = car(args);
02053         p2 = cdr(args);
02054         delete_object(instance, args);
02055         if ((p1 = eval(instance, p1)) == &alsa_lisp_nil) {
02056                 return F_progn(instance, p2);
02057         } else {
02058                 delete_tree(instance, p1);
02059                 delete_tree(instance, p2);
02060         }
02061 
02062         return &alsa_lisp_nil;
02063 }
02064 
02065 /*
02066  * Syntax: (while expr exprs...)
02067  */
02068 static struct alisp_object * F_while(struct alisp_instance *instance, struct alisp_object * args)
02069 {
02070         struct alisp_object * p1, * p2, * p3;
02071 
02072         p1 = car(args);
02073         p2 = cdr(args);
02074 
02075         delete_object(instance, args);
02076         while (1) {
02077                 incref_tree(instance, p1);
02078                 if ((p3 = eval(instance, p1)) == &alsa_lisp_nil)
02079                         break;
02080                 delete_tree(instance, p3);
02081                 incref_tree(instance, p2);
02082                 delete_tree(instance, F_progn(instance, p2));
02083         }
02084 
02085         delete_tree(instance, p1);
02086         delete_tree(instance, p2);
02087         return &alsa_lisp_nil;
02088 }
02089 
02090 /*
02091  * Syntax: (progn expr...)
02092  */
02093 static struct alisp_object * F_progn(struct alisp_instance *instance, struct alisp_object * args)
02094 {
02095         struct alisp_object * p = args, * p1 = NULL, * n;
02096 
02097         do {
02098                 if (p1)
02099                         delete_tree(instance, p1);
02100                 p1 = eval(instance, car(p));
02101                 n = cdr(p);
02102                 delete_object(instance, p);
02103                 p = n;
02104         } while (p != &alsa_lisp_nil);
02105 
02106         return p1;
02107 }
02108 
02109 /*
02110  * Syntax: (prog1 expr...)
02111  */
02112 static struct alisp_object * F_prog1(struct alisp_instance *instance, struct alisp_object * args)
02113 {
02114         struct alisp_object * p = args, * first = NULL, * p1;
02115 
02116         do {
02117                 p1 = eval(instance, car(p));
02118                 if (first == NULL)
02119                         first = p1;
02120                 else
02121                         delete_tree(instance, p1);
02122                 p1 = cdr(p);
02123                 delete_object(instance, p);
02124                 p = p1;
02125         } while (p != &alsa_lisp_nil);
02126 
02127         if (first == NULL)
02128                 first = &alsa_lisp_nil;
02129 
02130         return first;
02131 }
02132 
02133 /*
02134  * Syntax: (prog2 expr...)
02135  */
02136 static struct alisp_object * F_prog2(struct alisp_instance *instance, struct alisp_object * args)
02137 {
02138         struct alisp_object * p = args, * second = NULL, * p1;
02139         int i = 0;
02140 
02141         do {
02142                 ++i;
02143                 p1 = eval(instance, car(p));
02144                 if (i == 2)
02145                         second = p1;
02146                 else
02147                         delete_tree(instance, p1);
02148                 p1 = cdr(p);
02149                 delete_object(instance, p);
02150                 p = p1;
02151         } while (p != &alsa_lisp_nil);
02152 
02153         if (second == NULL)
02154                 second = &alsa_lisp_nil;
02155 
02156         return second;
02157 }
02158 
02159 /*
02160  * Syntax: (set name value)
02161  */
02162 static struct alisp_object * F_set(struct alisp_instance *instance, struct alisp_object * args)
02163 {
02164         struct alisp_object * p1 = eval(instance, car(args)),
02165                             * p2 = eval(instance, car(cdr(args)));
02166 
02167         delete_tree(instance, cdr(cdr(args)));
02168         delete_object(instance, cdr(args));
02169         delete_object(instance, args);
02170         if (!check_set_object(instance, p1)) {
02171                 delete_tree(instance, p2);
02172                 p2 = &alsa_lisp_nil;
02173         } else {
02174                 if (set_object(instance, p1, p2) == NULL) {
02175                         delete_tree(instance, p1);
02176                         delete_tree(instance, p2);
02177                         return NULL;
02178                 }
02179         }
02180         delete_tree(instance, p1);
02181         return incref_tree(instance, p2);
02182 }
02183 
02184 /*
02185  * Syntax: (unset name)
02186  */
02187 static struct alisp_object * F_unset(struct alisp_instance *instance, struct alisp_object * args)
02188 {
02189         struct alisp_object * p1 = eval(instance, car(args));
02190 
02191         delete_tree(instance, unset_object(instance, p1));
02192         delete_tree(instance, cdr(args));
02193         delete_object(instance, args);
02194         return p1;
02195 }
02196 
02197 /*
02198  * Syntax: (setq name value...)
02199  * Syntax: (setf name value...)
02200  * `name' is not evalled
02201  */
02202 static struct alisp_object * F_setq(struct alisp_instance *instance, struct alisp_object * args)
02203 {
02204         struct alisp_object * p = args, * p1, * p2 = NULL, *n;
02205 
02206         do {
02207                 p1 = car(p);
02208                 p2 = eval(instance, car(cdr(p)));
02209                 n = cdr(cdr(p));
02210                 delete_object(instance, cdr(p));
02211                 delete_object(instance, p);
02212                 if (!check_set_object(instance, p1)) {
02213                         delete_tree(instance, p2);
02214                         p2 = &alsa_lisp_nil;
02215                 } else {
02216                         if (set_object(instance, p1, p2) == NULL) {
02217                                 delete_tree(instance, p1);
02218                                 delete_tree(instance, p2);
02219                                 return NULL;
02220                         }
02221                 }
02222                 delete_tree(instance, p1);
02223                 p = n;
02224         } while (p != &alsa_lisp_nil);
02225 
02226         return incref_tree(instance, p2);
02227 }
02228 
02229 /*
02230  * Syntax: (unsetq name...)
02231  * Syntax: (unsetf name...)
02232  * `name' is not evalled
02233  */
02234 static struct alisp_object * F_unsetq(struct alisp_instance *instance, struct alisp_object * args)
02235 {
02236         struct alisp_object * p = args, * p1 = NULL, * n;
02237 
02238         do {
02239                 if (p1)
02240                         delete_tree(instance, p1);
02241                 p1 = unset_object(instance, car(p));
02242                 delete_tree(instance, car(p));
02243                 p = cdr(n = p);
02244                 delete_object(instance, n);
02245         } while (p != &alsa_lisp_nil);
02246 
02247         return p1;
02248 }
02249 
02250 /*
02251  * Syntax: (defun name arglist expr...)
02252  * `name' is not evalled
02253  * `arglist' is not evalled
02254  */
02255 static struct alisp_object * F_defun(struct alisp_instance *instance, struct alisp_object * args)
02256 {
02257         struct alisp_object * p1 = car(args),
02258                             * p2 = car(cdr(args)),
02259                             * p3 = cdr(cdr(args));
02260         struct alisp_object * lexpr;
02261 
02262         lexpr = new_object(instance, ALISP_OBJ_CONS);
02263         if (lexpr) {
02264                 lexpr->value.c.car = new_identifier(instance, "lambda");
02265                 if (lexpr->value.c.car == NULL) {
02266                         delete_object(instance, lexpr);
02267                         delete_tree(instance, args);
02268                         return NULL;
02269                 }
02270                 if ((lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS)) == NULL) {
02271                         delete_object(instance, lexpr->value.c.car);
02272                         delete_object(instance, lexpr);
02273                         delete_tree(instance, args);
02274                         return NULL;
02275                 }
02276                 lexpr->value.c.cdr->value.c.car = p2;
02277                 lexpr->value.c.cdr->value.c.cdr = p3;
02278                 delete_object(instance, cdr(args));
02279                 delete_object(instance, args);
02280                 if (set_object(instance, p1, lexpr) == NULL) {
02281                         delete_tree(instance, p1);
02282                         delete_tree(instance, lexpr);
02283                         return NULL;
02284                 }
02285                 delete_tree(instance, p1);
02286         } else {
02287                 delete_tree(instance, args);
02288         }
02289         return &alsa_lisp_nil;
02290 }
02291 
02292 static struct alisp_object * eval_func(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * args)
02293 {
02294         struct alisp_object * p1, * p2, * p3, * p4;
02295         struct alisp_object ** eval_objs, ** save_objs;
02296         int i;
02297 
02298         p1 = car(p);
02299         if (alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER) &&
02300             !strcmp(p1->value.s, "lambda")) {
02301                 p2 = car(cdr(p));
02302                 p3 = args;
02303 
02304                 if ((i = count_list(p2)) != count_list(p3)) {
02305                         lisp_warn(instance, "wrong number of parameters");
02306                         goto _delete;
02307                 }
02308 
02309                 eval_objs = malloc(2 * i * sizeof(struct alisp_object *));
02310                 if (eval_objs == NULL) {
02311                         nomem();
02312                         goto _delete;
02313                 }
02314                 save_objs = eval_objs + i;
02315                 
02316                 /*
02317                  * Save the new variable values.
02318                  */
02319                 i = 0;
02320                 while (p3 != &alsa_lisp_nil) {
02321                         eval_objs[i++] = eval(instance, car(p3));
02322                         p3 = cdr(p4 = p3);
02323                         delete_object(instance, p4);
02324                 }
02325 
02326                 /*
02327                  * Save the old variable values and set the new ones.
02328                  */
02329                 i = 0;
02330                 while (p2 != &alsa_lisp_nil) {
02331                         p3 = car(p2);
02332                         save_objs[i] = replace_object(instance, p3, eval_objs[i]);
02333                         if (save_objs[i] == NULL &&
02334                             set_object_direct(instance, p3, eval_objs[i]) == NULL) {
02335                                 p4 = NULL;
02336                                 goto _end;
02337                         }
02338                         p2 = cdr(p2);
02339                         ++i;
02340                 }
02341 
02342                 p4 = F_progn(instance, cdr(incref_tree(instance, p3 = cdr(p))));
02343 
02344                 /*
02345                  * Restore the old variable values.
02346                  */
02347                 p2 = car(p3);
02348                 delete_object(instance, p3);
02349                 i = 0;
02350                 while (p2 != &alsa_lisp_nil) {
02351                         p3 = car(p2);
02352                         if (save_objs[i] == NULL) {
02353                                 p3 = unset_object(instance, p3);
02354                         } else {
02355                                 p3 = replace_object(instance, p3, save_objs[i]);
02356                         }
02357                         i++;
02358                         delete_tree(instance, p3);
02359                         delete_tree(instance, car(p2));
02360                         p2 = cdr(p3 = p2);
02361                         delete_object(instance, p3);
02362                 }
02363 
02364                _end:
02365                 free(eval_objs);
02366 
02367                 return p4;
02368         } else {
02369                _delete:
02370                 delete_tree(instance, args);
02371         }
02372         return &alsa_lisp_nil;
02373 }
02374 
02375 struct alisp_object * F_gc(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args ATTRIBUTE_UNUSED)
02376 {
02377         /* improved: no more traditional gc */
02378         return &alsa_lisp_t;
02379 }
02380 
02381 /*
02382  * Syntax: (path what)
02383  * what is string ('data')
02384  */
02385 struct alisp_object * F_path(struct alisp_instance *instance, struct alisp_object * args)
02386 {
02387         struct alisp_object * p1;
02388 
02389         p1 = eval(instance, car(args));
02390         delete_tree(instance, cdr(args));
02391         delete_object(instance, args);
02392         if (!alisp_compare_type(p1, ALISP_OBJ_STRING)) {
02393                 delete_tree(instance, p1);
02394                 return &alsa_lisp_nil;
02395         }
02396         if (!strcmp(p1->value.s, "data")) {
02397                 delete_tree(instance, p1);
02398                 return new_string(instance, "/share");
02399         }
02400         delete_tree(instance, p1);
02401         return &alsa_lisp_nil;
02402 }
02403 
02404 /*
02405  * Syntax: (include filename...)
02406  */
02407 struct alisp_object * F_include(struct alisp_instance *instance, struct alisp_object * args)
02408 {
02409         struct alisp_object * p = args, * p1;
02410         int res = -ENOENT;
02411 
02412         do {
02413                 p1 = eval(instance, car(p));
02414                 if (alisp_compare_type(p1, ALISP_OBJ_STRING))
02415                         res = alisp_include_file(instance, p1->value.s);
02416                 delete_tree(instance, p1);
02417                 p = cdr(p1 = p);
02418                 delete_object(instance, p1);
02419         } while (p != &alsa_lisp_nil);
02420 
02421         return new_integer(instance, res);
02422 }
02423 
02424 /*
02425  * Syntax: (string-to-integer value)
02426  * 'value' can be integer or float type
02427  */
02428 struct alisp_object * F_string_to_integer(struct alisp_instance *instance, struct alisp_object * args)
02429 {
02430         struct alisp_object * p = eval(instance, car(args)), * p1;
02431 
02432         delete_tree(instance, cdr(args));
02433         delete_object(instance, args);
02434         if (alisp_compare_type(p, ALISP_OBJ_INTEGER))
02435                 return p;
02436         if (alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
02437                 p1 = new_integer(instance, floor(p->value.f));
02438         } else {
02439                 lisp_warn(instance, "expected an integer or float for integer conversion");
02440                 p1 = &alsa_lisp_nil;
02441         }
02442         delete_tree(instance, p);
02443         return p1;
02444 }
02445 
02446 /*
02447  * Syntax: (string-to-float value)
02448  * 'value' can be integer or float type
02449  */
02450 struct alisp_object * F_string_to_float(struct alisp_instance *instance, struct alisp_object * args)
02451 {
02452         struct alisp_object * p = eval(instance, car(args)), * p1;
02453 
02454         delete_tree(instance, cdr(args));
02455         delete_object(instance, args);
02456         if (alisp_compare_type(p, ALISP_OBJ_FLOAT))
02457                 return p;
02458         if (alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
02459                 p1 = new_float(instance, p->value.i);
02460         } else {
02461                 lisp_warn(instance, "expected an integer or float for integer conversion");
02462                 p1 = &alsa_lisp_nil;
02463         }
02464         delete_tree(instance, p);
02465         return p1;
02466 }
02467 
02468 static int append_to_string(char **s, int *len, char *from, int size)
02469 {
02470         if (*len == 0) {
02471                 *s = malloc(*len = size + 1);
02472                 if (*s == NULL) {
02473                         nomem();
02474                         return -ENOMEM;
02475                 }
02476                 memcpy(*s, from, size);
02477         } else {
02478                 *len += size;
02479                 *s = realloc(*s, *len);
02480                 if (*s == NULL) {
02481                         nomem();
02482                         return -ENOMEM;
02483                 }
02484                 memcpy(*s + strlen(*s), from, size);
02485         }
02486         (*s)[*len - 1] = '\0';
02487         return 0;
02488 }
02489 
02490 static int format_parse_char(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
02491 {
02492         char b;
02493 
02494         if (!alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
02495                 lisp_warn(instance, "format: expected integer\n");
02496                 return 0;
02497         }
02498         b = p->value.i;
02499         return append_to_string(s, len, &b, 1);
02500 }
02501 
02502 static int format_parse_integer(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
02503 {
02504         int res;
02505         char *s1;
02506 
02507         if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
02508             !alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
02509                 lisp_warn(instance, "format: expected integer or float\n");
02510                 return 0;
02511         }
02512         s1 = malloc(64);
02513         if (s1 == NULL) {
02514                 nomem();
02515                 return -ENOMEM;
02516         }
02517         sprintf(s1, "%li", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? (long)floor(p->value.f) : p->value.i);
02518         res = append_to_string(s, len, s1, strlen(s1));
02519         free(s1);
02520         return res;
02521 }
02522 
02523 static int format_parse_float(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
02524 {
02525         int res;
02526         char *s1;
02527 
02528         if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
02529             !alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
02530                 lisp_warn(instance, "format: expected integer or float\n");
02531                 return 0;
02532         }
02533         s1 = malloc(64);
02534         if (s1 == NULL) {
02535                 nomem();
02536                 return -ENOMEM;
02537         }
02538         sprintf(s1, "%f", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? p->value.f : (double)p->value.i);
02539         res = append_to_string(s, len, s1, strlen(s1));
02540         free(s1);
02541         return res;
02542 }
02543 
02544 static int format_parse_string(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
02545 {
02546         if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
02547                 lisp_warn(instance, "format: expected string\n");
02548                 return 0;
02549         }
02550         return append_to_string(s, len, p->value.s, strlen(p->value.s));
02551 }
02552 
02553 /*
02554  * Syntax: (format format value...)
02555  * 'format' is C-like format string
02556  */
02557 struct alisp_object * F_format(struct alisp_instance *instance, struct alisp_object * args)
02558 {
02559         struct alisp_object * p = eval(instance, car(args)), * p1 = cdr(args), * n;
02560         char *s, *s1, *s2;
02561         int len;
02562 
02563         delete_object(instance, args);
02564         if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
02565                 delete_tree(instance, p1);
02566                 delete_tree(instance, p);
02567                 lisp_warn(instance, "format: expected an format string");
02568                 return &alsa_lisp_nil;
02569         }
02570         s = p->value.s;
02571         s1 = NULL;
02572         len = 0;
02573         n = eval(instance, car(p1));
02574         do {
02575                 while (1) {
02576                         s2 = s;
02577                         while (*s2 && *s2 != '%')
02578                                 s2++;
02579                         if (s2 != s) {
02580                                 if (append_to_string(&s1, &len, s, s2 - s) < 0) {
02581                                       __error:
02582                                         delete_tree(instance, n);
02583                                         delete_tree(instance, cdr(p1));
02584                                         delete_object(instance, p1);
02585                                         delete_tree(instance, p);
02586                                         return NULL;
02587                                 }
02588                         }
02589                         if (*s2 == '%')
02590                                 s2++;
02591                         switch (*s2) {
02592                         case '%':
02593                                 if (append_to_string(&s1, &len, s2, 1) < 0)
02594                                         goto __error;
02595                                 s = s2 + 1;
02596                                 break;
02597                         case 'c':
02598                                 if (format_parse_char(instance, &s1, &len, n) < 0)
02599                                         goto __error;
02600                                 s = s2 + 1;
02601                                 goto __next;
02602                         case 'd':
02603                         case 'i':
02604                                 if (format_parse_integer(instance, &s1, &len, n) < 0)
02605                                         goto __error;
02606                                 s = s2 + 1;
02607                                 goto __next;
02608                         case 'f':
02609                                 if (format_parse_float(instance, &s1, &len, n) < 0)
02610                                         goto __error;
02611                                 s = s2 + 1;
02612                                 goto __next;
02613                         case 's':
02614                                 if (format_parse_string(instance, &s1, &len, n) < 0)
02615                                         goto __error;
02616                                 s = s2 + 1;
02617                                 goto __next;
02618                         case '\0':
02619                                 goto __end;
02620                         default:
02621                                 lisp_warn(instance, "unknown format char '%c'", *s2);
02622                                 s = s2 + 1;
02623                                 goto __next;
02624                         }
02625                 }
02626               __next:
02627                 delete_tree(instance, n);
02628                 p1 = cdr(n = p1);
02629                 delete_object(instance, n);
02630                 n = eval(instance, car(p1));
02631         } while (*s);
02632       __end:
02633         delete_tree(instance, n);
02634         delete_tree(instance, cdr(p1));
02635         delete_object(instance, p1);
02636         delete_tree(instance, p);
02637         if (len > 0) {
02638                 p1 = new_string(instance, s1);
02639                 free(s1);
02640         } else {
02641                 p1 = &alsa_lisp_nil;
02642         }
02643         return p1;
02644 }
02645 
02646 /*
02647  * Syntax: (compare-strings str1 start1 end1 str2 start2 end2 /opt-case-insensitive)
02648  * 'str1' is first compared string
02649  * 'start1' is first char (0..)
02650  * 'end1' is last char (0..)
02651  * 'str2' is second compared string
02652  * 'start2' is first char (0..)
02653  * 'end2' is last char (0..)
02654  * /opt-case-insensitive true - case insensitive match
02655  */
02656 struct alisp_object * F_compare_strings(struct alisp_instance *instance, struct alisp_object * args)
02657 {
02658         struct alisp_object * p1 = args, * n, * p[7];
02659         char *s1, *s2;
02660         int start1, end1, start2, end2;
02661         
02662         for (start1 = 0; start1 < 7; start1++) {
02663                 p[start1] = eval(instance, car(p1));
02664                 p1 = cdr(n = p1);
02665                 delete_object(instance, n);
02666         }
02667         delete_tree(instance, p1);
02668         if (alisp_compare_type(p[0], ALISP_OBJ_STRING)) {
02669                 lisp_warn(instance, "compare-strings: first argument must be string\n");
02670                 p1 = &alsa_lisp_nil;
02671                 goto __err;
02672         }
02673         if (alisp_compare_type(p[1], ALISP_OBJ_INTEGER)) {
02674                 lisp_warn(instance, "compare-strings: second argument must be integer\n");
02675                 p1 = &alsa_lisp_nil;
02676                 goto __err;
02677         }
02678         if (alisp_compare_type(p[2], ALISP_OBJ_INTEGER)) {
02679                 lisp_warn(instance, "compare-strings: third argument must be integer\n");
02680                 p1 = &alsa_lisp_nil;
02681                 goto __err;
02682         }
02683         if (alisp_compare_type(p[3], ALISP_OBJ_STRING)) {
02684                 lisp_warn(instance, "compare-strings: fifth argument must be string\n");
02685                 p1 = &alsa_lisp_nil;
02686                 goto __err;
02687         }
02688         if (!alisp_compare_type(p[4], ALISP_OBJ_NIL) &&
02689             !alisp_compare_type(p[4], ALISP_OBJ_INTEGER)) {
02690                 lisp_warn(instance, "compare-strings: fourth argument must be integer\n");
02691                 p1 = &alsa_lisp_nil;
02692                 goto __err;
02693         }
02694         if (!alisp_compare_type(p[5], ALISP_OBJ_NIL) &&
02695             !alisp_compare_type(p[5], ALISP_OBJ_INTEGER)) {
02696                 lisp_warn(instance, "compare-strings: sixth argument must be integer\n");
02697                 p1 = &alsa_lisp_nil;
02698                 goto __err;
02699         }
02700         s1 = p[0]->value.s;
02701         start1 = p[1]->value.i;
02702         end1 = p[2]->value.i;
02703         s2 = p[3]->value.s;
02704         start2 = alisp_compare_type(p[4], ALISP_OBJ_NIL) ? 0 : p[4]->value.i;
02705         end2 = alisp_compare_type(p[5], ALISP_OBJ_NIL) ? start2 + (end1 - start1) : p[5]->value.i;
02706         if (start1 < 0 || start2 < 0 || end1 < 0 || end2 < 0 ||
02707             start1 >= (int)strlen(s1) || start2 >= (int)strlen(s2) ||
02708             (end1 - start1) != (end2 - start2)) {
02709                 p1 = &alsa_lisp_nil;
02710                 goto __err;
02711         }
02712         if (p[6] != &alsa_lisp_nil) {
02713                 while (start1 < end1) {
02714                         if (s1[start1] == '\0' ||
02715                             s2[start2] == '\0' ||
02716                             tolower(s1[start1]) != tolower(s2[start2])) {
02717                                 p1 = &alsa_lisp_nil;
02718                                 goto __err;
02719                         }
02720                         start1++;
02721                         start2++;
02722                 }
02723         } else {
02724                 while (start1 < end1) {
02725                         if (s1[start1] == '\0' ||
02726                             s2[start2] == '\0' ||
02727                             s1[start1] != s2[start2]) {
02728                                 p1 = &alsa_lisp_nil;
02729                                 goto __err;
02730                         }
02731                         start1++;
02732                         start2++;
02733                 }
02734         }
02735         p1 = &alsa_lisp_t;
02736         
02737       __err:
02738         for (start1 = 0; start1 < 7; start1++)
02739                 delete_tree(instance, p[start1]);
02740         return p1;      
02741 }
02742 
02743 /*
02744  *  Syntax: (assoc key alist)
02745  */
02746 struct alisp_object * F_assoc(struct alisp_instance *instance, struct alisp_object * args)
02747 {
02748         struct alisp_object * p1, * p2, * n;
02749 
02750         p1 = eval(instance, car(args));
02751         p2 = eval(instance, car(cdr(args)));
02752         delete_tree(instance, cdr(cdr(args)));
02753         delete_object(instance, cdr(args));
02754         delete_object(instance, args);
02755 
02756         do {
02757                 if (eq(p1, car(car(p2)))) {
02758                         n = car(p2);
02759                         delete_tree(instance, p1);
02760                         delete_tree(instance, cdr(p2));
02761                         delete_object(instance, p2);
02762                         return n;
02763                 }
02764                 delete_tree(instance, car(p2));
02765                 p2 = cdr(n = p2);
02766                 delete_object(instance, n);
02767         } while (p2 != &alsa_lisp_nil);
02768 
02769         delete_tree(instance, p1);
02770         return &alsa_lisp_nil;  
02771 }
02772 
02773 /*
02774  *  Syntax: (rassoc value alist)
02775  */
02776 struct alisp_object * F_rassoc(struct alisp_instance *instance, struct alisp_object * args)
02777 {
02778         struct alisp_object * p1, *p2, * n;
02779 
02780         p1 = eval(instance, car(args));
02781         p2 = eval(instance, car(cdr(args)));
02782         delete_tree(instance, cdr(cdr(args)));
02783         delete_object(instance, cdr(args));
02784         delete_object(instance, args);
02785 
02786         do {
02787                 if (eq(p1, cdr(car(p2)))) {
02788                         n = car(p2);
02789                         delete_tree(instance, p1);
02790                         delete_tree(instance, cdr(p2));
02791                         delete_object(instance, p2);
02792                         return n;
02793                 }
02794                 delete_tree(instance, car(p2));
02795                 p2 = cdr(n = p2);
02796                 delete_object(instance, n);
02797         } while (p2 != &alsa_lisp_nil);
02798 
02799         delete_tree(instance, p1);
02800         return &alsa_lisp_nil;  
02801 }
02802 
02803 /*
02804  *  Syntax: (assq key alist)
02805  */
02806 struct alisp_object * F_assq(struct alisp_instance *instance, struct alisp_object * args)
02807 {
02808         struct alisp_object * p1, * p2, * n;
02809 
02810         p1 = eval(instance, car(args));
02811         p2 = eval(instance, car(cdr(args)));
02812         delete_tree(instance, cdr(cdr(args)));
02813         delete_object(instance, cdr(args));
02814         delete_object(instance, args);
02815 
02816         do {
02817                 if (equal(p1, car(car(p2)))) {
02818                         n = car(p2);
02819                         delete_tree(instance, p1);
02820                         delete_tree(instance, cdr(p2));
02821                         delete_object(instance, p2);
02822                         return n;
02823                 }
02824                 delete_tree(instance, car(p2));
02825                 p2 = cdr(n = p2);
02826                 delete_object(instance, n);
02827         } while (p2 != &alsa_lisp_nil);
02828 
02829         delete_tree(instance, p1);
02830         return &alsa_lisp_nil;  
02831 }
02832 
02833 /*
02834  *  Syntax: (nth index alist)
02835  */
02836 struct alisp_object * F_nth(struct alisp_instance *instance, struct alisp_object * args)
02837 {
02838         struct alisp_object * p1, * p2, * n;
02839         long idx;
02840 
02841         p1 = eval(instance, car(args));
02842         p2 = eval(instance, car(cdr(args)));
02843         delete_tree(instance, cdr(cdr(args)));
02844         delete_object(instance, cdr(args));
02845         delete_object(instance, args);
02846 
02847         if (!alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
02848                 delete_tree(instance, p1);
02849                 delete_tree(instance, p2);
02850                 return &alsa_lisp_nil;
02851         }
02852         if (!alisp_compare_type(p2, ALISP_OBJ_CONS)) {
02853                 delete_object(instance, p1);
02854                 delete_tree(instance, p2);
02855                 return &alsa_lisp_nil;
02856         }
02857         idx = p1->value.i;
02858         delete_object(instance, p1);
02859         while (idx-- > 0) {
02860                 delete_tree(instance, car(p2));
02861                 p2 = cdr(n = p2);
02862                 delete_object(instance, n);
02863         }
02864         n = car(p2);
02865         delete_tree(instance, cdr(p2));
02866         delete_object(instance, p2);
02867         return n;
02868 }
02869 
02870 /*
02871  *  Syntax: (rassq value alist)
02872  */
02873 struct alisp_object * F_rassq(struct alisp_instance *instance, struct alisp_object * args)
02874 {
02875         struct alisp_object * p1, * p2, * n;
02876 
02877         p1 = eval(instance, car(args));
02878         p2 = eval(instance, car(cdr(args)));
02879         delete_tree(instance, cdr(cdr(args)));
02880         delete_object(instance, cdr(args));
02881         delete_object(instance, args);
02882 
02883         do {
02884                 if (equal(p1, cdr(car(p2)))) {
02885                         n = car(p2);
02886                         delete_tree(instance, p1);
02887                         delete_tree(instance, cdr(p2));
02888                         delete_object(instance, p2);
02889                         return n;
02890                 }
02891                 delete_tree(instance, car(p2));
02892                 p2 = cdr(n = p2);
02893                 delete_object(instance, n);
02894         } while (p2 != &alsa_lisp_nil);
02895 
02896         delete_tree(instance, p1);
02897         return &alsa_lisp_nil;  
02898 }
02899 
02900 static struct alisp_object * F_dump_memory(struct alisp_instance *instance, struct alisp_object * args)
02901 {
02902         struct alisp_object * p = car(args);
02903 
02904         if (p != &alsa_lisp_nil && cdr(args) == &alsa_lisp_nil &&
02905             alisp_compare_type(p, ALISP_OBJ_STRING)) {
02906                 if (strlen(p->value.s) > 0) {
02907                         dump_objects(instance, p->value.s);
02908                         delete_tree(instance, args);
02909                         return &alsa_lisp_t;
02910                 } else
02911                         lisp_warn(instance, "expected filename");
02912         } else
02913                 lisp_warn(instance, "wrong number of parameters (expected string)");
02914 
02915         delete_tree(instance, args);
02916         return &alsa_lisp_nil;
02917 }
02918 
02919 static struct alisp_object * F_stat_memory(struct alisp_instance *instance, struct alisp_object * args)
02920 {
02921         snd_output_printf(instance->out, "*** Memory stats\n");
02922         snd_output_printf(instance->out, "  used_objs = %li, free_objs = %li, max_objs = %li, obj_size = %i (total bytes = %li, max bytes = %li)\n",
02923                           instance->used_objs,
02924                           instance->free_objs,
02925                           instance->max_objs,
02926                           (int)sizeof(struct alisp_object),
02927                           (long)((instance->used_objs + instance->free_objs) * sizeof(struct alisp_object)),
02928                           (long)(instance->max_objs * sizeof(struct alisp_object)));
02929         delete_tree(instance, args);
02930         return &alsa_lisp_nil;
02931 }
02932 
02933 static struct alisp_object * F_check_memory(struct alisp_instance *instance, struct alisp_object * args)
02934 {
02935         delete_tree(instance, args);
02936         if (instance->used_objs > 0) {
02937                 fprintf(stderr, "!!!alsa lisp - check memory failed!!!\n");
02938                 F_stat_memory(instance, &alsa_lisp_nil);
02939                 exit(EXIT_FAILURE);
02940         }
02941         return &alsa_lisp_t;
02942 }
02943 
02944 static struct alisp_object * F_dump_objects(struct alisp_instance *instance, struct alisp_object * args)
02945 {
02946         struct alisp_object * p = car(args);
02947 
02948         if (p != &alsa_lisp_nil && cdr(args) == &alsa_lisp_nil &&
02949             alisp_compare_type(p, ALISP_OBJ_STRING)) {
02950                 if (strlen(p->value.s) > 0) {
02951                         dump_obj_lists(instance, p->value.s);
02952                         delete_tree(instance, args);
02953                         return &alsa_lisp_t;
02954                 } else
02955                         lisp_warn(instance, "expected filename");
02956         } else
02957                 lisp_warn(instance, "wrong number of parameters (expected string)");
02958 
02959         delete_tree(instance, args);
02960         return &alsa_lisp_nil;
02961 }
02962 
02963 struct intrinsic {
02964         const char *name;
02965         struct alisp_object * (*func)(struct alisp_instance *instance, struct alisp_object * args);
02966 };
02967 
02968 static struct intrinsic intrinsics[] = {
02969         { "!=", F_numneq },
02970         { "%", F_mod },
02971         { "&check-memory", F_check_memory },
02972         { "&dump-memory", F_dump_memory },
02973         { "&dump-objects", F_dump_objects },
02974         { "&stat-memory", F_stat_memory },
02975         { "*", F_mul },
02976         { "+", F_add },
02977         { "-", F_sub },
02978         { "/", F_div },
02979         { "<", F_lt },
02980         { "<=", F_le },
02981         { "=", F_numeq },
02982         { ">", F_gt },
02983         { ">=", F_ge },
02984         { "and", F_and },
02985         { "assoc", F_assoc },
02986         { "assq", F_assq },
02987         { "atom", F_atom },
02988         { "car", F_car },
02989         { "cdr", F_cdr },
02990         { "compare-strings", F_compare_strings },
02991         { "concat", F_concat },
02992         { "cond", F_cond },
02993         { "cons", F_cons },
02994         { "defun", F_defun },
02995         { "eq", F_eq },
02996         { "equal", F_equal },
02997         { "eval", F_eval },
02998         { "exfun", F_exfun },
02999         { "format", F_format },
03000         { "funcall", F_funcall },
03001         { "garbage-collect", F_gc },
03002         { "gc", F_gc },
03003         { "if", F_if },
03004         { "include", F_include },
03005         { "list", F_list },
03006         { "not", F_not },
03007         { "nth", F_nth },
03008         { "null", F_not },
03009         { "or", F_or },
03010         { "path", F_path },
03011         { "princ", F_princ },
03012         { "prog1", F_prog1 },
03013         { "prog2", F_prog2 },
03014         { "progn", F_progn },
03015         { "quote", F_quote },
03016         { "rassoc", F_rassoc },
03017         { "rassq", F_rassq },
03018         { "set", F_set },
03019         { "setf", F_setq },
03020         { "setq", F_setq },
03021         { "string-equal", F_equal },
03022         { "string-to-float", F_string_to_float },
03023         { "string-to-integer", F_string_to_integer },
03024         { "string-to-number", F_string_to_float },
03025         { "string=", F_equal },
03026         { "unless", F_unless },
03027         { "unset", F_unset },
03028         { "unsetf", F_unsetq },
03029         { "unsetq", F_unsetq },
03030         { "when", F_when },
03031         { "while", F_while },
03032 };
03033 
03034 #include "alisp_snd.c"
03035 
03036 static int compar(const void *p1, const void *p2)
03037 {
03038         return strcmp(((struct intrinsic *)p1)->name,
03039                       ((struct intrinsic *)p2)->name);
03040 }
03041 
03042 static inline struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
03043 {
03044         struct alisp_object * p3;
03045         struct intrinsic key, *item;
03046 
03047         key.name = p1->value.s;
03048 
03049         if ((item = bsearch(&key, intrinsics,
03050                             sizeof intrinsics / sizeof intrinsics[0],
03051                             sizeof intrinsics[0], compar)) != NULL) {
03052                 delete_object(instance, p1);
03053                 return item->func(instance, p2);
03054         }
03055 
03056         if ((item = bsearch(&key, snd_intrinsics,
03057                             sizeof snd_intrinsics / sizeof snd_intrinsics[0],
03058                             sizeof snd_intrinsics[0], compar)) != NULL) {
03059                 delete_object(instance, p1);
03060                 return item->func(instance, p2);
03061         }
03062 
03063         if ((p3 = get_object(instance, p1)) != &alsa_lisp_nil) {
03064                 delete_object(instance, p1);
03065                 return eval_func(instance, p3, p2);
03066         } else {
03067                 lisp_warn(instance, "function `%s' is undefined", p1->value.s);
03068                 delete_object(instance, p1);
03069                 delete_tree(instance, p2);
03070         }
03071 
03072         return &alsa_lisp_nil;
03073 }
03074 
03075 /*
03076  * Syntax: (funcall function args...)
03077  */
03078 static struct alisp_object * F_funcall(struct alisp_instance *instance, struct alisp_object * args)
03079 {
03080         struct alisp_object * p = eval(instance, car(args)), * p1;
03081 
03082         if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
03083             !alisp_compare_type(p, ALISP_OBJ_STRING)) {
03084                 lisp_warn(instance, "expected an function name");
03085                 delete_tree(instance, p);
03086                 delete_tree(instance, cdr(args));
03087                 delete_object(instance, args);
03088                 return &alsa_lisp_nil;
03089         }
03090         p1 = cdr(args);
03091         delete_object(instance, args);
03092         return eval_cons1(instance, p, p1);
03093 }
03094 
03095 static inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p)
03096 {
03097         struct alisp_object * p1 = car(p), * p2;
03098 
03099         if (p1 != &alsa_lisp_nil && alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER)) {
03100                 if (!strcmp(p1->value.s, "lambda"))
03101                         return p;
03102 
03103                 p2 = cdr(p);
03104                 delete_object(instance, p);
03105                 return eval_cons1(instance, p1, p2);
03106         } else {
03107                 delete_tree(instance, p);
03108         }
03109 
03110         return &alsa_lisp_nil;
03111 }
03112 
03113 static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p)
03114 {
03115         switch (alisp_get_type(p)) {
03116         case ALISP_OBJ_IDENTIFIER: {
03117                 struct alisp_object *r = incref_tree(instance, get_object(instance, p));
03118                 delete_object(instance, p);
03119                 return r;
03120         }
03121         case ALISP_OBJ_INTEGER:
03122         case ALISP_OBJ_FLOAT:
03123         case ALISP_OBJ_STRING:
03124         case ALISP_OBJ_POINTER:
03125                 return p;
03126         case ALISP_OBJ_CONS:
03127                 return eval_cons(instance, p);
03128         default:
03129                 break;
03130         }
03131 
03132         return p;
03133 }
03134 
03135 static struct alisp_object * F_eval(struct alisp_instance *instance, struct alisp_object * args)
03136 {
03137         return eval(instance, eval(instance, car(args)));
03138 }
03139 
03140 /*
03141  *  main routine
03142  */
03143 
03144 static int alisp_include_file(struct alisp_instance *instance, const char *filename)
03145 {
03146         snd_input_t *old_in;
03147         struct alisp_object *p, *p1;
03148         char *name;
03149         int retval = 0, err;
03150 
03151         err = snd_user_file(filename, &name);
03152         if (err < 0)
03153                 return err;
03154         old_in = instance->in;
03155         err = snd_input_stdio_open(&instance->in, name, "r");
03156         if (err < 0) {
03157                 retval = err;
03158                 goto _err;
03159         }
03160         if (instance->verbose)
03161                 lisp_verbose(instance, "** include filename '%s'", name);
03162 
03163         for (;;) {
03164                 if ((p = parse_object(instance, 0)) == NULL)
03165                         break;
03166                 if (instance->verbose) {
03167                         lisp_verbose(instance, "** code");
03168                         princ_object(instance->vout, p);
03169                         snd_output_putc(instance->vout, '\n');
03170                 }
03171                 p1 = eval(instance, p);
03172                 if (p1 == NULL) {
03173                         retval = -ENOMEM;
03174                         break;
03175                 }
03176                 if (instance->verbose) {
03177                         lisp_verbose(instance, "** result");
03178                         princ_object(instance->vout, p1);
03179                         snd_output_putc(instance->vout, '\n');
03180                 }
03181                 delete_tree(instance, p1);
03182                 if (instance->debug) {
03183                         lisp_debug(instance, "** objects after operation");
03184                         print_obj_lists(instance, instance->dout);
03185                 }
03186         }       
03187 
03188         snd_input_close(instance->in);
03189        _err:
03190         free(name);
03191         instance->in = old_in;
03192         return retval;
03193 }
03194  
03195 int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
03196 {
03197         struct alisp_instance *instance;
03198         struct alisp_object *p, *p1;
03199         int i, j, retval = 0;
03200         
03201         instance = (struct alisp_instance *)malloc(sizeof(struct alisp_instance));
03202         if (instance == NULL) {
03203                 nomem();
03204                 return -ENOMEM;
03205         }
03206         memset(instance, 0, sizeof(struct alisp_instance));
03207         instance->verbose = cfg->verbose && cfg->vout;
03208         instance->warning = cfg->warning && cfg->wout;
03209         instance->debug = cfg->debug && cfg->dout;
03210         instance->in = cfg->in;
03211         instance->out = cfg->out;
03212         instance->vout = cfg->vout;
03213         instance->eout = cfg->eout;
03214         instance->wout = cfg->wout;
03215         instance->dout = cfg->dout;
03216         INIT_LIST_HEAD(&instance->free_objs_list);
03217         for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
03218                 for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++)
03219                         INIT_LIST_HEAD(&instance->used_objs_list[i][j]);
03220                 INIT_LIST_HEAD(&instance->setobjs_list[i]);
03221         }
03222         
03223         init_lex(instance);
03224 
03225         for (;;) {
03226                 if ((p = parse_object(instance, 0)) == NULL)
03227                         break;
03228                 if (instance->verbose) {
03229                         lisp_verbose(instance, "** code");
03230                         princ_object(instance->vout, p);
03231                         snd_output_putc(instance->vout, '\n');
03232                 }
03233                 p1 = eval(instance, p);
03234                 if (p1 == NULL) {
03235                         retval = -ENOMEM;
03236                         break;
03237                 }
03238                 if (instance->verbose) {
03239                         lisp_verbose(instance, "** result");
03240                         princ_object(instance->vout, p1);
03241                         snd_output_putc(instance->vout, '\n');
03242                 }
03243                 delete_tree(instance, p1);
03244                 if (instance->debug) {
03245                         lisp_debug(instance, "** objects after operation");
03246                         print_obj_lists(instance, instance->dout);
03247                 }
03248         }
03249 
03250         if (_instance)
03251                 *_instance = instance;
03252         else
03253                 alsa_lisp_free(instance); 
03254         
03255         return 0;
03256 }
03257 
03258 void alsa_lisp_free(struct alisp_instance *instance)
03259 {
03260         if (instance == NULL)
03261                 return;
03262         done_lex(instance);
03263         free_objects(instance);
03264         free(instance);
03265 }
03266 
03267 struct alisp_cfg *alsa_lisp_default_cfg(snd_input_t *input)
03268 {
03269         snd_output_t *output, *eoutput;
03270         struct alisp_cfg *cfg;
03271         int err;
03272         
03273         err = snd_output_stdio_attach(&output, stdout, 0);
03274         if (err < 0)
03275                 return NULL;
03276         err = snd_output_stdio_attach(&eoutput, stderr, 0);
03277         if (err < 0) {
03278                 snd_output_close(output);
03279                 return NULL;
03280         }
03281         cfg = calloc(1, sizeof(struct alisp_cfg));
03282         if (cfg == NULL) {
03283                 snd_output_close(eoutput);
03284                 snd_output_close(output);
03285                 return NULL;
03286         }
03287         cfg->out = output;
03288         cfg->wout = eoutput;
03289         cfg->eout = eoutput;
03290         cfg->dout = eoutput;
03291         cfg->in = input;
03292         return cfg;
03293 }
03294 
03295 void alsa_lisp_default_cfg_free(struct alisp_cfg *cfg)
03296 {
03297         snd_input_close(cfg->in);
03298         snd_output_close(cfg->out);
03299         snd_output_close(cfg->dout);
03300         free(cfg);
03301 }
03302 
03303 int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterator **result,
03304                        const char *id, const char *args, ...)
03305 {
03306         int err = 0;
03307         struct alisp_object *aargs = NULL, *obj, *res;
03308 
03309         if (args && *args != 'n') {
03310                 va_list ap;
03311                 struct alisp_object *p;
03312                 p = NULL;
03313                 va_start(ap, args);
03314                 while (*args) {
03315                         if (*args++ != '%') {
03316                                 err = -EINVAL;
03317                                 break;
03318                         }
03319                         if (*args == '\0') {
03320                                 err = -EINVAL;
03321                                 break;
03322                         }
03323                         obj = NULL;
03324                         err = 0;
03325                         switch (*args++) {
03326                         case 's':
03327                                 obj = new_string(instance, va_arg(ap, char *));
03328                                 break;
03329                         case 'i':
03330                                 obj = new_integer(instance, va_arg(ap, int));
03331                                 break;
03332                         case 'l':
03333                                 obj = new_integer(instance, va_arg(ap, long));
03334                                 break;
03335                         case 'f':
03336                         case 'd':
03337                                 obj = new_integer(instance, va_arg(ap, double));
03338                                 break;
03339                         case 'p': {
03340                                 char _ptrid[24];
03341                                 char *ptrid = _ptrid;
03342                                 while (*args && *args != '%')
03343                                         *ptrid++ = *args++;
03344                                 *ptrid = 0;
03345                                 if (ptrid == _ptrid) {
03346                                         err = -EINVAL;
03347                                         break;
03348                                 }
03349                                 obj = new_cons_pointer(instance, _ptrid, va_arg(ap, void *));
03350                                 obj = quote_object(instance, obj);
03351                                 break;
03352                         }
03353                         default:
03354                                 err = -EINVAL;
03355                                 break;
03356                         }
03357                         if (err < 0)
03358                                 goto __args_end;
03359                         if (obj == NULL) {
03360                                 err = -ENOMEM;
03361                                 goto __args_end;
03362                         }
03363                         if (p == NULL) {
03364                                 p = aargs = new_object(instance, ALISP_OBJ_CONS);
03365                         } else {
03366                                 p->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
03367                                 p = p->value.c.cdr;
03368                         }
03369                         if (p == NULL) {
03370                                 err = -ENOMEM;
03371                                 goto __args_end;
03372                         }
03373                         p->value.c.car = obj;
03374                 }
03375               __args_end:
03376                 va_end(ap);
03377                 if (err < 0)
03378                         return err;
03379 #if 0
03380                 snd_output_printf(instance->wout, ">>>");
03381                 princ_object(instance->wout, aargs);
03382                 snd_output_printf(instance->wout, "<<<\n");
03383 #endif
03384         }
03385 
03386         err = -ENOENT;
03387         if (aargs == NULL)
03388                 aargs = &alsa_lisp_nil;
03389         if ((obj = get_object1(instance, id)) != &alsa_lisp_nil) {
03390                 res = eval_func(instance, obj, aargs);
03391                 err = 0;
03392         } else {
03393                 struct intrinsic key, *item;
03394                 key.name = id;
03395                 if ((item = bsearch(&key, intrinsics,
03396                                     sizeof intrinsics / sizeof intrinsics[0],
03397                                     sizeof intrinsics[0], compar)) != NULL) {
03398                         res = item->func(instance, aargs);
03399                         err = 0;
03400                 } else if ((item = bsearch(&key, snd_intrinsics,
03401                                          sizeof snd_intrinsics / sizeof snd_intrinsics[0],
03402                                          sizeof snd_intrinsics[0], compar)) != NULL) {
03403                         res = item->func(instance, aargs);
03404                         err = 0;
03405                 } else {
03406                         res = &alsa_lisp_nil;
03407                 }
03408         }
03409         if (res == NULL)
03410                 err = -ENOMEM;
03411         if (err == 0 && result) {
03412                 *result = res;
03413         } else {
03414                 delete_tree(instance, res);
03415         }
03416 
03417         return 0;
03418 }
03419 
03420 void alsa_lisp_result_free(struct alisp_instance *instance,
03421                            struct alisp_seq_iterator *result)
03422 {
03423         delete_tree(instance, result);
03424 }
03425 
03426 int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
03427                         struct alisp_seq_iterator **seq)
03428 {
03429         struct alisp_object * p1;
03430 
03431         p1 = get_object1(instance, id);
03432         if (p1 == NULL)
03433                 return -ENOMEM;
03434         *seq = p1;
03435         return 0;
03436 }
03437 
03438 int alsa_lisp_seq_next(struct alisp_seq_iterator **seq)
03439 {
03440         struct alisp_object * p1 = *seq;
03441 
03442         p1 = cdr(p1);
03443         if (p1 == &alsa_lisp_nil)
03444                 return -ENOENT;
03445         *seq = p1;
03446         return 0;
03447 }
03448 
03449 int alsa_lisp_seq_count(struct alisp_seq_iterator *seq)
03450 {
03451         int count = 0;
03452         
03453         while (seq != &alsa_lisp_nil) {
03454                 count++;
03455                 seq = cdr(seq);
03456         }
03457         return count;
03458 }
03459 
03460 int alsa_lisp_seq_integer(struct alisp_seq_iterator *seq, long *val)
03461 {
03462         if (alisp_compare_type(seq, ALISP_OBJ_CONS))
03463                 seq = seq->value.c.cdr;
03464         if (alisp_compare_type(seq, ALISP_OBJ_INTEGER))
03465                 *val = seq->value.i;
03466         else
03467                 return -EINVAL;
03468         return 0;
03469 }
03470 
03471 int alsa_lisp_seq_pointer(struct alisp_seq_iterator *seq, const char *ptr_id, void **ptr)
03472 {
03473         struct alisp_object * p2;
03474         
03475         if (alisp_compare_type(seq, ALISP_OBJ_CONS) &&
03476             alisp_compare_type(seq->value.c.car, ALISP_OBJ_CONS))
03477                 seq = seq->value.c.car;
03478         if (alisp_compare_type(seq, ALISP_OBJ_CONS)) {
03479                 p2 = seq->value.c.car;
03480                 if (!alisp_compare_type(p2, ALISP_OBJ_STRING))
03481                         return -EINVAL;
03482                 if (strcmp(p2->value.s, ptr_id))
03483                         return -EINVAL;
03484                 p2 = seq->value.c.cdr;
03485                 if (!alisp_compare_type(p2, ALISP_OBJ_POINTER))
03486                         return -EINVAL;
03487                 *ptr = (void *)seq->value.ptr;
03488         } else
03489                 return -EINVAL;
03490         return 0;
03491 }

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1