00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
00055 static int alisp_include_file(struct alisp_instance *instance, const char *filename);
00056
00057
00058
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
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
00558 while ((c = xgetc(instance)) != '\n' && c != EOF)
00559 ;
00560 if (c != EOF)
00561 ++instance->lineno;
00562 break;
00563
00564 case '?':
00565
00566 c = xgetc(instance);
00567 sprintf(instance->token_buffer, "%d", c);
00568 return instance->thistoken = ALISP_INTEGER;
00569
00570 case '-':
00571
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
01609
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
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
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
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
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
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
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
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
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
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
01949
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
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
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
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
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
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
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
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
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
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
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
02199
02200
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
02231
02232
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
02252
02253
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
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
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
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
02378 return &alsa_lisp_t;
02379 }
02380
02381
02382
02383
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
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
02426
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
02448
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
02555
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
02648
02649
02650
02651
02652
02653
02654
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
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
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
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
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
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
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
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 }