ALISP update

- function names are more emacs-like
 - implemented (format) function
 - fixed numerous memory-leaks (valgrind is now happy)
Ordinary mixer
 - added the global view (using hdsp names only)
This commit is contained in:
Jaroslav Kysela 2003-12-23 16:42:55 +00:00
parent beb837bcf7
commit d0facfde2b
10 changed files with 628 additions and 250 deletions

View file

@ -3,7 +3,7 @@
; The test is indended to find memory leaks.
;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
; License: GPL
; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
;
;
@ -120,7 +120,7 @@
(atom "one") (&check-memory)
(atom "one" 'two) (&check-memory)
(call) (&check-memory)
(funcall) (&check-memory)
(car) (&check-memory)
(car '(one . two)) (&check-memory)
@ -128,6 +128,13 @@
(cdr) (&check-memory)
(cdr '(one . two)) (&check-memory)
(concat) (&check-memory)
(concat 'aaaa) (&check-memory)
(concat 'aaaa 'bbbb) (&check-memory)
(concat "aaaa") (&check-memory)
(concat "aaaa" "bbbb") (&check-memory)
(concat "aaaa" "bbbb" "cccc") (&check-memory)
(cond) (&check-memory)
(cond 0) (&check-memory)
(cond 0 1) (&check-memory)
@ -160,11 +167,17 @@
(exfun 'abcd) (&check-memory)
(exfun 'abcd 'ijkl) (&check-memory)
(float) (&check-memory)
(float 1) (&check-memory)
(float 'a) (&check-memory)
(float "a" "b" "c") (&check-memory)
(float "1.2") (&check-memory)
(format) (&check-memory)
(format 1) (&check-memory)
(format 'a) (&check-memory)
(format "a" "b" "c") (&check-memory)
(format "1.2") (&check-memory)
(format "%c" 43) (&check-memory)
(format "%d" 12) (&check-memory)
(format "%i" 12) (&check-memory)
(format "%f" 12.1) (&check-memory)
(format "%s" "abcd") (&check-memory)
(format "%s %i %i" "abcd" 1 2) (&check-memory)
(garbage-collect) (&check-memory)
(gc) (&check-memory)
@ -179,12 +192,6 @@
(include "itest.lisp") (&check-memory)
(int) (&check-memory)
(int 1) (&check-memory)
(int 'a) (&check-memory)
(int "a" "b" "c") (&check-memory)
(int "1.2") (&check-memory)
(list) (&check-memory)
(list "a") (&check-memory)
(list "a" "b") (&check-memory)
@ -267,10 +274,28 @@
(setq a 1) (unsetq a) (&check-memory)
(setq a 1 2) (unsetq a) (&check-memory)
(str) (&check-memory)
(str 1) (&check-memory)
(str 1 2 3) (&check-memory)
(str 1.2 1.3) (&check-memory)
(string-equal) (&check-memory)
(string-equal 1) (&check-memory)
(string-equal "a") (&check-memory)
(string-equal "a" "a") (&check-memory)
(string-equal "a" "b") (&check-memory)
(string-equal "a" "b" "c") (&check-memory)
(string-to-integer) (&check-memory)
(string-to-integer 1) (&check-memory)
(string-to-integer 1.5) (&check-memory)
(string-to-integer "a") (&check-memory)
(string-to-integer "a" "a") (&check-memory)
(string-to-integer "a" "b") (&check-memory)
(string-to-integer "a" "b" "c") (&check-memory)
(string-to-float) (&check-memory)
(string-to-float 1) (&check-memory)
(string-to-float 1.5) (&check-memory)
(string-to-float "a") (&check-memory)
(string-to-float "a" "a") (&check-memory)
(string-to-float "a" "b") (&check-memory)
(string-to-float "a" "b" "c") (&check-memory)
(string=) (&check-memory)
(string= 1) (&check-memory)
@ -279,13 +304,6 @@
(string= "a" "b") (&check-memory)
(string= "a" "b" "c") (&check-memory)
(string-equal) (&check-memory)
(string-equal 1) (&check-memory)
(string-equal "a") (&check-memory)
(string-equal "a" "a") (&check-memory)
(string-equal "a" "b") (&check-memory)
(string-equal "a" "b" "c") (&check-memory)
(unless) (&check-memory)
(unless 1) (&check-memory)
(unless 0 1 2) (&check-memory)
@ -322,27 +340,31 @@
(unsetq abcd)
(&check-memory)
(setq abcd (("abcd" . "efgh") ("1234" . "5678")))
(unsetq abcd)
(&check-memory)
(defun myfun () (princ "a\n"))
(exfun 'myfun)
(unsetq myfun)
(&check-memory)
(defun myfun () (princ "a\n"))
(call 'myfun)
(call 'myfun 'aaaaa)
(funcall 'myfun)
(funcall 'myfun 'aaaaa)
(unsetq myfun)
(&check-memory)
(defun myfun (o) (princ o "a\n"))
(call 'myfun)
(call 'myfun 'aaaaa)
(funcall 'myfun)
(funcall 'myfun 'aaaaa)
(unsetq myfun)
(&check-memory)
(defun myfun (o p) (princ o p "\n"))
(call 'myfun)
(call 'myfun 'aaaaa)
(call 'myfun 'aaaaa 'bbbbb)
(funcall 'myfun)
(funcall 'myfun 'aaaaa)
(funcall 'myfun 'aaaaa 'bbbbb)
(unsetq myfun)
(&check-memory)

View file

@ -45,6 +45,8 @@ int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterato
__attribute__ ((format (printf, 4, 5)))
#endif
;
void alsa_lisp_result_free(struct alisp_instance *instance,
struct alisp_seq_iterator *result);
int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
struct alisp_seq_iterator **seq);
int alsa_lisp_seq_next(struct alisp_seq_iterator **seq);

View file

@ -195,7 +195,8 @@ extern "C" {
* \{
*/
int sndo_mixer_open(sndo_mixer_t **pmixer, snd_pcm_t *playback_pcm, snd_pcm_t *capture_pcm, struct alisp_cfg *lconf);
int sndo_mixer_open(sndo_mixer_t **pmixer, const char *playback_name, const char *capture_name, struct alisp_cfg *lconf);
int sndo_mixer_open_pcm(sndo_mixer_t **pmixer, snd_pcm_t *playback_pcm, snd_pcm_t *capture_pcm, struct alisp_cfg *lconf);
int sndo_mixer_close(sndo_mixer_t *mixer);
int sndo_mixer_poll_descriptors_count(sndo_mixer_t *mixer);
int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space);

View file

@ -46,11 +46,11 @@ static struct alisp_object * parse_object(struct alisp_instance *instance, int h
static void princ_cons(snd_output_t *out, struct alisp_object * p);
static void princ_object(snd_output_t *out, struct alisp_object * p);
static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p);
static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2);
/* functions */
static struct alisp_object *F_eval(struct alisp_instance *instance, struct alisp_object *);
static struct alisp_object *F_progn(struct alisp_instance *instance, struct alisp_object *);
static struct alisp_object *F_funcall(struct alisp_instance *instance, struct alisp_object *);
/* others */
static int alisp_include_file(struct alisp_instance *instance, const char *filename);
@ -176,9 +176,7 @@ static void free_object(struct alisp_object * p)
static void delete_object(struct alisp_instance *instance, struct alisp_object * p)
{
if (p == NULL)
return;
if (p == &alsa_lisp_nil || p == &alsa_lisp_t)
if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
return;
if (alisp_compare_type(p, ALISP_OBJ_NIL) ||
alisp_compare_type(p, ALISP_OBJ_T))
@ -215,8 +213,8 @@ static void delete_tree(struct alisp_instance *instance, struct alisp_object * p
static struct alisp_object * incref_object(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * p)
{
if (p == NULL)
return NULL;
if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
return p;
if (alisp_get_refs(p) == ALISP_MAX_REFS) {
assert(0);
fprintf(stderr, "OOPS: alsa lisp: incref fatal error\n");
@ -259,12 +257,30 @@ static void free_objects(struct alisp_instance *instance)
{
struct list_head *pos, *pos1;
struct alisp_object * p;
struct alisp_object_pair * pair;
int i, j;
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
list_for_each_safe(pos, pos1, &instance->setobjs_list[i]) {
pair = list_entry(pos, struct alisp_object_pair, list);
lisp_debug(instance, "freeing pair: '%s' -> %p", pair->name, pair->value);
delete_tree(instance, pair->value);
free((void *)pair->name);
free(pair);
}
}
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++) {
list_for_each_safe(pos, pos1, &instance->used_objs_list[i][j]) {
p = list_entry(pos, struct alisp_object, list);
lisp_warn(instance, "object %p is still referenced %i times!", p, alisp_get_refs(p));
#if 0
snd_output_printf(instance->wout, ">>>> ");
princ_object(instance->wout, p);
snd_output_printf(instance->wout, " <<<<\n");
#endif
if (alisp_get_refs(p) > 0)
alisp_set_refs(p, 1);
delete_object(instance, p);
}
}
@ -575,7 +591,7 @@ static int gettoken(struct alisp_instance *instance)
instance->thistoken = ALISP_INTEGER;
do {
__ok:
if (p - instance->token_buffer >= instance->token_buffer_max) {
if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p);
if (p == NULL)
return instance->thistoken = EOF;
@ -620,7 +636,7 @@ static int gettoken(struct alisp_instance *instance)
/* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */
p = instance->token_buffer;
do {
if (p - instance->token_buffer >= instance->token_buffer_max) {
if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p);
if (p == NULL)
return instance->thistoken = EOF;
@ -636,7 +652,7 @@ static int gettoken(struct alisp_instance *instance)
/* String: "\""([^"]|"\\".)*"\"" */
p = instance->token_buffer;
while ((c = xgetc(instance)) != '"' && c != EOF) {
if (p - instance->token_buffer >= instance->token_buffer_max) {
if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p);
if (p == NULL)
return instance->thistoken = EOF;
@ -683,24 +699,26 @@ static struct alisp_object * parse_form(struct alisp_instance *instance)
* Parse a dotted pair notation.
*/
if (thistoken == '.') {
thistoken = gettoken(instance);
gettoken(instance);
if (prev == NULL) {
lisp_error(instance, "unexpected `.'");
lisp_error(instance, "unexpected '.'");
__err:
delete_tree(instance, first);
return NULL;
}
prev->value.c.cdr = parse_object(instance, 1);
if (prev->value.c.cdr == NULL)
return NULL;
goto __err;
if ((thistoken = gettoken(instance)) != ')') {
lisp_error(instance, "expected `)'");
return NULL;
lisp_error(instance, "expected ')'");
goto __err;
}
break;
}
p = new_object(instance, ALISP_OBJ_CONS);
if (p == NULL)
return NULL;
goto __err;
if (first == NULL)
first = p;
@ -709,7 +727,8 @@ static struct alisp_object * parse_form(struct alisp_instance *instance)
p->value.c.car = parse_object(instance, 1);
if (p->value.c.car == NULL)
return NULL;
goto __err;
prev = p;
}
@ -724,11 +743,11 @@ static struct alisp_object * quote_object(struct alisp_instance *instance, struc
struct alisp_object * p;
if (obj == NULL)
return NULL;
goto __end1;
p = new_object(instance, ALISP_OBJ_CONS);
if (p == NULL)
return NULL;
goto __end1;
p->value.c.car = new_identifier(instance, "quote");
if (p->value.c.car == NULL)
@ -737,8 +756,9 @@ static struct alisp_object * quote_object(struct alisp_instance *instance, struc
if (p->value.c.cdr == NULL) {
delete_object(instance, p->value.c.car);
__end:
delete_object(instance, obj);
delete_object(instance, p);
__end1:
delete_tree(instance, obj);
return NULL;
}
@ -898,6 +918,7 @@ static struct alisp_object * unset_object(struct alisp_instance *instance, struc
if (!strcmp(p->name, id)) {
list_del(&p->list);
res = p->value;
free((void *)p->name);
free(p);
return res;
}
@ -1117,13 +1138,11 @@ static struct alisp_object * F_cdr(struct alisp_instance *instance, struct alisp
static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = args, * p1, * n;
p1 = eval(instance, car(p));
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
long v = 0;
double f = 0;
int type = ALISP_OBJ_INTEGER;
p1 = eval(instance, car(p));
for (;;) {
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
if (type == ALISP_OBJ_FLOAT)
@ -1149,8 +1168,17 @@ static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp
} else {
return new_float(instance, f);
}
} else if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
}
/*
* Syntax: (concat expr...)
*/
static struct alisp_object * F_concat(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = args, * p1, * n;
char *str = NULL, *str1;
p1 = eval(instance, car(p));
for (;;) {
if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
str1 = realloc(str, (str ? strlen(str) : 0) + strlen(p1->value.s) + 1);
@ -1175,16 +1203,13 @@ static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp
break;
p1 = eval(instance, car(p));
}
if (str) {
p = new_string(instance, str);
free(str);
return p;
} else {
lisp_warn(instance, "sum/concat with non-integer or string operand");
delete_tree(instance, cdr(p));
delete_object(instance, p);
delete_tree(instance, p1);
p = &alsa_lisp_nil;
}
return &alsa_lisp_nil;
return p;
}
/*
@ -2218,6 +2243,7 @@ static struct alisp_object * F_unsetq(struct alisp_instance *instance, struct al
if (p1)
delete_tree(instance, p1);
p1 = unset_object(instance, car(p));
delete_tree(instance, car(p));
p = cdr(n = p);
delete_object(instance, n);
} while (p != &alsa_lisp_nil);
@ -2269,7 +2295,7 @@ static struct alisp_object * F_defun(struct alisp_instance *instance, struct ali
static struct alisp_object * eval_func(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * args)
{
struct alisp_object * p1, * p2, * p3, * p4, * p5;
struct alisp_object * p1, * p2, * p3, * p4;
struct alisp_object ** eval_objs, ** save_objs;
int i;
@ -2297,9 +2323,8 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
i = 0;
while (p3 != &alsa_lisp_nil) {
eval_objs[i++] = eval(instance, car(p3));
p4 = cdr(p3);
delete_object(instance, p3);
p3 = p4;
p3 = cdr(p4 = p3);
delete_object(instance, p4);
}
/*
@ -2307,48 +2332,49 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
*/
i = 0;
while (p2 != &alsa_lisp_nil) {
p4 = car(p2);
save_objs[i] = replace_object(instance, p4, eval_objs[i]);
p3 = car(p2);
save_objs[i] = replace_object(instance, p3, eval_objs[i]);
if (save_objs[i] == NULL &&
set_object_direct(instance, p4, eval_objs[i]) == NULL)
set_object_direct(instance, p3, eval_objs[i]) == NULL) {
p4 = NULL;
goto _end;
}
p2 = cdr(p2);
++i;
}
p5 = F_progn(instance, incref_tree(instance, cdr(cdr(p))));
p4 = F_progn(instance, cdr(incref_tree(instance, p3 = cdr(p))));
/*
* Restore the old variable values.
*/
p2 = car(cdr(p));
p2 = car(p3);
delete_object(instance, p3);
i = 0;
while (p2 != &alsa_lisp_nil) {
p4 = car(p2);
p3 = car(p2);
if (save_objs[i] == NULL) {
p4 = unset_object(instance, p4);
p3 = unset_object(instance, p3);
} else {
p4 = replace_object(instance, p4, save_objs[i]);
p3 = replace_object(instance, p3, save_objs[i]);
}
i++;
delete_tree(instance, p4);
p2 = cdr(p2);
delete_tree(instance, p3);
delete_tree(instance, car(p2));
p2 = cdr(p3 = p2);
delete_object(instance, p3);
}
_end:
if (eval_objs)
free(eval_objs);
return p5;
return p4;
} else {
_delete:
delete_tree(instance, args);
}
return &alsa_lisp_nil;
_end:
if (eval_objs)
free(eval_objs);
return NULL;
}
struct alisp_object * F_gc(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args ATTRIBUTE_UNUSED)
@ -2401,30 +2427,10 @@ struct alisp_object * F_include(struct alisp_instance *instance, struct alisp_ob
}
/*
* Syntax: (call function args...)
*/
struct alisp_object * F_call(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
!alisp_compare_type(p, ALISP_OBJ_STRING)) {
lisp_warn(instance, "expected an function name");
delete_tree(instance, p);
delete_tree(instance, cdr(args));
delete_object(instance, args);
return &alsa_lisp_nil;
}
p1 = cdr(args);
delete_object(instance, args);
return eval_cons1(instance, p, p1);
}
/*
* Syntax: (int value)
* Syntax: (string-to-integer value)
* 'value' can be integer or float type
*/
struct alisp_object * F_int(struct alisp_instance *instance, struct alisp_object * args)
struct alisp_object * F_string_to_integer(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
@ -2443,10 +2449,10 @@ struct alisp_object * F_int(struct alisp_instance *instance, struct alisp_object
}
/*
* Syntax: (float value)
* Syntax: (string-to-float value)
* 'value' can be integer or float type
*/
struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_object * args)
struct alisp_object * F_string_to_float(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
@ -2464,38 +2470,278 @@ struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_obje
return p1;
}
/*
* Syntax: (str value)
* 'value' can be integer, float or string type
*/
struct alisp_object * F_str(struct alisp_instance *instance, struct alisp_object * args)
static int append_to_string(char **s, int *len, char *from, int size)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
delete_tree(instance, cdr(args));
delete_object(instance, args);
if (alisp_compare_type(p, ALISP_OBJ_STRING))
return p;
if (alisp_compare_type(p, ALISP_OBJ_INTEGER) ||
alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
char *buf = malloc(64);
if (buf == NULL) {
delete_tree(instance, p);
if (*len == 0) {
*s = malloc(*len = size + 1);
if (*s == NULL) {
nomem();
return -ENOMEM;
}
memcpy(*s, from, size);
} else {
*len += size;
*s = realloc(*s, *len);
if (*s == NULL) {
nomem();
return -ENOMEM;
}
memcpy(*s + strlen(*s), from, size);
}
(*s)[*len - 1] = '\0';
return 0;
}
static int format_parse_char(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
{
char b;
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "format: expected integer\n");
return 0;
}
b = p->value.i;
return append_to_string(s, len, &b, 1);
}
static int format_parse_integer(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
{
int res;
char *s1;
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
!alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
lisp_warn(instance, "format: expected integer or float\n");
return 0;
}
s1 = malloc(64);
if (s1 == NULL) {
nomem();
return -ENOMEM;
}
sprintf(s1, "%li", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? (long)floor(p->value.f) : p->value.i);
res = append_to_string(s, len, s1, strlen(s1));
free(s1);
return res;
}
static int format_parse_float(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
{
int res;
char *s1;
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
!alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
lisp_warn(instance, "format: expected integer or float\n");
return 0;
}
s1 = malloc(64);
if (s1 == NULL) {
nomem();
return -ENOMEM;
}
sprintf(s1, "%f", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? p->value.f : (double)p->value.i);
res = append_to_string(s, len, s1, strlen(s1));
free(s1);
return res;
}
static int format_parse_string(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
{
if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
lisp_warn(instance, "format: expected string\n");
return 0;
}
return append_to_string(s, len, p->value.s, strlen(p->value.s));
}
/*
* Syntax: (format format value...)
* 'format' is C-like format string
*/
struct alisp_object * F_format(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1 = cdr(args), * n;
char *s, *s1, *s2;
int len;
delete_object(instance, args);
if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
delete_tree(instance, p1);
delete_tree(instance, p);
lisp_warn(instance, "format: expected an format string");
return &alsa_lisp_nil;
}
s = p->value.s;
s1 = NULL;
len = 0;
n = eval(instance, car(p1));
do {
while (1) {
s2 = s;
while (*s2 && *s2 != '%')
s2++;
if (s2 != s) {
if (append_to_string(&s1, &len, s, s2 - s) < 0) {
__error:
delete_tree(instance, n);
delete_tree(instance, cdr(p1));
delete_object(instance, p1);
delete_tree(instance, p);
return NULL;
}
if (alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
snprintf(buf, sizeof(buf), "%ld", p->value.i);
} else {
snprintf(buf, sizeof(buf), "%.f", p->value.f);
}
p1 = new_string(instance, buf);
free(buf);
if (*s2 == '%')
s2++;
switch (*s2) {
case '%':
if (append_to_string(&s1, &len, s2, 1) < 0)
goto __error;
s = s2 + 1;
break;
case 'c':
if (format_parse_char(instance, &s1, &len, n) < 0)
goto __error;
s = s2 + 1;
goto __next;
case 'd':
case 'i':
if (format_parse_integer(instance, &s1, &len, n) < 0)
goto __error;
s = s2 + 1;
goto __next;
case 'f':
if (format_parse_float(instance, &s1, &len, n) < 0)
goto __error;
s = s2 + 1;
goto __next;
case 's':
if (format_parse_string(instance, &s1, &len, n) < 0)
goto __error;
s = s2 + 1;
goto __next;
case '\0':
goto __end;
default:
lisp_warn(instance, "unknown format char '%c'", *s2);
s = s2 + 1;
goto __next;
}
}
__next:
delete_tree(instance, n);
p1 = cdr(n = p1);
delete_object(instance, n);
n = eval(instance, car(p1));
} while (*s);
__end:
delete_tree(instance, n);
delete_tree(instance, cdr(p1));
delete_object(instance, p1);
delete_tree(instance, p);
if (len > 0) {
p1 = new_string(instance, s1);
free(s1);
} else {
lisp_warn(instance, "expected an integer or float for integer conversion");
p1 = &alsa_lisp_nil;
}
delete_tree(instance, p);
return p1;
}
/*
* Syntax: (compare-strings str1 start1 end1 str2 start2 end2 /opt-case-insensitive)
* 'str1' is first compared string
* 'start1' is first char (0..)
* 'end1' is last char (0..)
* 'str2' is second compared string
* 'start2' is first char (0..)
* 'end2' is last char (0..)
* /opt-case-insensitive true - case insensitive match
*/
struct alisp_object * F_compare_strings(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p1 = args, * n, * p[7];
char *s1, *s2;
int start1, end1, start2, end2;
for (start1 = 0; start1 < 7; start1++) {
p[start1] = eval(instance, car(p1));
p1 = cdr(n = p1);
delete_object(instance, n);
}
delete_tree(instance, p1);
if (alisp_compare_type(p[0], ALISP_OBJ_STRING)) {
lisp_warn(instance, "compare-strings: first argument must be string\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (alisp_compare_type(p[1], ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "compare-strings: second argument must be integer\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (alisp_compare_type(p[2], ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "compare-strings: third argument must be integer\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (alisp_compare_type(p[3], ALISP_OBJ_STRING)) {
lisp_warn(instance, "compare-strings: fifth argument must be string\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (!alisp_compare_type(p[4], ALISP_OBJ_NIL) &&
!alisp_compare_type(p[4], ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "compare-strings: fourth argument must be integer\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (!alisp_compare_type(p[5], ALISP_OBJ_NIL) &&
!alisp_compare_type(p[5], ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "compare-strings: sixth argument must be integer\n");
p1 = &alsa_lisp_nil;
goto __err;
}
s1 = p[0]->value.s;
start1 = p[1]->value.i;
end1 = p[2]->value.i;
s2 = p[3]->value.s;
start2 = alisp_compare_type(p[4], ALISP_OBJ_NIL) ? 0 : p[4]->value.i;
end2 = alisp_compare_type(p[5], ALISP_OBJ_NIL) ? start2 + (end1 - start1) : p[5]->value.i;
if (start1 < 0 || start2 < 0 || end1 < 0 || end2 < 0 ||
start1 >= (int)strlen(s1) || start2 >= (int)strlen(s2) ||
(end1 - start1) != (end2 - start2)) {
p1 = &alsa_lisp_nil;
goto __err;
}
if (p[6] != &alsa_lisp_nil) {
while (start1 < end1) {
if (s1[start1] == '\0' ||
s2[start2] == '\0' ||
tolower(s1[start1]) != tolower(s2[start2])) {
p1 = &alsa_lisp_nil;
goto __err;
}
start1++;
start2++;
}
} else {
while (start1 < end1) {
if (s1[start1] == '\0' ||
s2[start2] == '\0' ||
s1[start1] != s2[start2]) {
p1 = &alsa_lisp_nil;
goto __err;
}
start1++;
start2++;
}
}
p1 = &alsa_lisp_t;
__err:
for (start1 = 0; start1 < 7; start1++)
delete_tree(instance, p[start1]);
return p1;
}
@ -2744,9 +2990,10 @@ static struct intrinsic intrinsics[] = {
{ "assoc", F_assoc },
{ "assq", F_assq },
{ "atom", F_atom },
{ "call", F_call },
{ "car", F_car },
{ "cdr", F_cdr },
{ "compare-strings", F_compare_strings },
{ "concat", F_concat },
{ "cond", F_cond },
{ "cons", F_cons },
{ "defun", F_defun },
@ -2754,12 +3001,12 @@ static struct intrinsic intrinsics[] = {
{ "equal", F_equal },
{ "eval", F_eval },
{ "exfun", F_exfun },
{ "float", F_float },
{ "format", F_format },
{ "funcall", F_funcall },
{ "garbage-collect", F_gc },
{ "gc", F_gc },
{ "if", F_if },
{ "include", F_include },
{ "int", F_int },
{ "list", F_list },
{ "not", F_not },
{ "nth", F_nth },
@ -2776,9 +3023,11 @@ static struct intrinsic intrinsics[] = {
{ "set", F_set },
{ "setf", F_setq },
{ "setq", F_setq },
{ "str", F_str },
{ "string=", F_equal },
{ "string-equal", F_equal },
{ "string-to-float", F_string_to_float },
{ "string-to-integer", F_string_to_integer },
{ "string-to-number", F_string_to_float },
{ "string=", F_equal },
{ "unless", F_unless },
{ "unset", F_unset },
{ "unsetf", F_unsetq },
@ -2795,7 +3044,7 @@ static int compar(const void *p1, const void *p2)
((struct intrinsic *)p2)->name);
}
static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
static inline struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
{
struct alisp_object * p3;
struct intrinsic key, *item;
@ -2828,6 +3077,26 @@ static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct
return &alsa_lisp_nil;
}
/*
* Syntax: (funcall function args...)
*/
static struct alisp_object * F_funcall(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
!alisp_compare_type(p, ALISP_OBJ_STRING)) {
lisp_warn(instance, "expected an function name");
delete_tree(instance, p);
delete_tree(instance, cdr(args));
delete_object(instance, args);
return &alsa_lisp_nil;
}
p1 = cdr(args);
delete_object(instance, args);
return eval_cons1(instance, p, p1);
}
static inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p)
{
struct alisp_object * p1 = car(p), * p2;
@ -2839,6 +3108,8 @@ static inline struct alisp_object * eval_cons(struct alisp_instance *instance, s
p2 = cdr(p);
delete_object(instance, p);
return eval_cons1(instance, p1, p2);
} else {
delete_tree(instance, p);
}
return &alsa_lisp_nil;
@ -2919,6 +3190,7 @@ static int alisp_include_file(struct alisp_instance *instance, const char *filen
}
}
snd_input_close(instance->in);
_err:
free(name);
instance->in = old_in;
@ -3141,12 +3413,21 @@ int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterato
}
if (res == NULL)
err = -ENOMEM;
if (err == 0 && result)
if (err == 0 && result) {
*result = res;
} else {
delete_tree(instance, res);
}
return 0;
}
void alsa_lisp_result_free(struct alisp_instance *instance,
struct alisp_seq_iterator *result)
{
delete_tree(instance, result);
}
int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
struct alisp_seq_iterator **seq)
{

View file

@ -1,4 +1,11 @@
(defun sndoc_mixer_open (hctl)
(princ "sndoc_mixer_open\n")
;
; SiS SI7018 mixer abstract layer
;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
;
(defun sndoc_mixer_open (hctl pcm)
(princ "sndoc_mixer_open: hctl=" hctl " pcm=" pcm "\n")
0
)

View file

@ -1,4 +1,11 @@
(defun sndop_mixer_open (hctl)
(princ "sndop_mixer_open\n")
;
; SiS SI7018 mixer abstract layer
;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
;
(defun sndop_mixer_open (hctl pcm)
(princ "sndop_mixer_open: hctl=" hctl " pcm=" pcm "\n")
0
)

View file

@ -1,6 +1,9 @@
;
; Toplevel configuration for the ALSA Ordinary Mixer Interface
;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
;
(defun sndo_include (hctl stream)
(setq info (Acall "ctl_card_info" (Acall "hctl_ctl" hctl)))
@ -8,7 +11,7 @@
(progn
(setq info (Aresult info))
(setq driver (cdr (assq "driver" (unsetq info))))
(setq file (+ (path "data") "/alsa/cards/" (snd_card_alias driver) "/sndo" stream "-mixer.alisp"))
(setq file (concat (path "data") "/alsa/cards/" (snd_card_alias driver) "/sndo" stream "-mixer.alisp"))
(setq r (include file))
(when (= r -2) (Asyserr "unable to find file " file))
)
@ -17,36 +20,55 @@
(unsetq info driver file r)
)
(defun sndo_mixer_open_fcn (stream)
(setq fcn (+ "sndo" stream "_mixer_open"))
(setq r (if (exfun fcn) (call fcn hctl) 0))
(defun sndo_mixer_open_fcn (hctl stream pcm)
(setq fcn (concat "sndo" stream "_mixer_open"))
(setq r (if (exfun fcn) (funcall fcn hctl pcm) 0))
(when (= r 0)
(setq hctls (if hctls (cons hctls (cons hctl)) hctl))
)
(unsetq fcn r)
)
(defun sndo_mixer_open_hctl (card stream)
(setq hctl (Acall "hctl_open" (+ "hw:" (str card)) nil))
(defun sndo_mixer_open_hctl (name stream pcm)
(setq hctl (Acall "hctl_open" name nil))
(setq r (Aerror hctl))
(when (= r 0)
(setq hctl (Aresult hctl))
(setq r (sndo_include hctl stream))
(when (= r 0) (setq r (sndo_mixer_open_fcn stream)))
(if (= r 0)
(setq r (sndo_mixer_open_fcn hctl stream pcm))
(Acall "hctl_close" hctl)
)
)
(unsetq hctl r)
)
(defun sndo_mixer_open_virtual (pcm stream)
(setq name (Acall "pcm_name" pcm))
(setq file (+ (path "data") "/alsa/virtual/" name "/sndo" stream "-mixer.alisp"))
(defun sndo_mixer_open_virtual (name stream pcm)
(setq file (concat (path "data") "/alsa/virtual/" name "/sndo" stream "-mixer.alisp"))
(setq r (include file))
(when (= r -2) (Asyserr "unable to find file " file))
(when (= r 0) (setq r (sndo_mixer_open_fcn stream)))
(unsetq name file r)
(when (= r 0) (setq r (sndo_mixer_open_fcn nil stream pcm)))
(unsetq file r)
)
(defun sndo_mixer_open1 (pcm stream)
(defun sndo_mixer_open1 (name stream)
(if (compare-strings name 0 2 "hw:" 0 2)
(sndo_mixer_open_hctl name stream nil)
(sndo_mixer_open_virtual name stream nil)
)
)
(defun sndo_mixer_open (pname cname)
(setq r (sndo_mixer_open1 pname "p"))
(when (= r 0) (setq r (sndo_mixer_open1 cname "c")))
(when (!= r 0) (sndo_mixer_close))
(unsetq sndo_mixer_open
sndo_mixer_open_pcm sndo_mixer_open_pcm1
sndo_mixer_open_virtual sndo_mixer_open_fcn
sndo_include r)
)
(defun sndo_mixer_open_pcm1 (pcm stream)
(setq info (Acall "pcm_info" pcm))
(setq r (Aerror info))
(when (= r 0)
@ -54,19 +76,20 @@
(setq card (cdr (assq "card" info)))
(setq r
(if (< card 0)
(sndo_mixer_open_virtual pcm stream)
(sndo_mixer_open_hctl card stream)
(sndo_mixer_open_virtual (Acall "pcm_name" pcm) stream pcm)
(sndo_mixer_open_hctl (format "hw:%i" card) stream pcm)
)
)
)
(unsetq info card r)
)
(defun sndo_mixer_open (ppcm cpcm)
(setq r (sndo_mixer_open1 ppcm "p"))
(when (= r 0) (setq r (sndo_mixer_open1 cpcm "c")))
(defun sndo_mixer_open_pcm (ppcm cpcm)
(setq r (sndo_mixer_open_pcm1 ppcm "p"))
(when (= r 0) (setq r (sndo_mixer_open_pcm1 cpcm "c")))
(when (!= r 0) (sndo_mixer_close))
(unsetq sndo_mixer_open sndo_mixer_open1
(unsetq sndo_mixer_open
sndo_mixer_open_pcm sndo_mixer_open_pcm1
sndo_mixer_open_virtual sndo_mixer_open_fcn
sndo_include r)
)
@ -74,8 +97,8 @@
(defun sndo_mixer_close1 (hctl stream)
(when hctl
(progn
(setq fcn (+ "sndo" stream "_mixer_close"))
(when (exfun fcn) (call fcn hctl))
(setq fcn (concat "sndo" stream "_mixer_close"))
(when (exfun fcn) (funcall fcn hctl))
(unsetq fcn)
(Acall "hctl_close" hctl)
)
@ -88,4 +111,4 @@
(unsetq hctls)
)
(include (+ (path "data") "/alsa/cards/aliases.alisp"))
(include (concat (path "data") "/alsa/cards/aliases.alisp"))

View file

@ -67,17 +67,11 @@ struct sndo_mixer {
int _free_cfg;
};
/**
* \brief Opens a ordinary mixer instance
* \param pmixer Returned ordinary mixer handle
* \param playback_pcm handle of the playback PCM
* \param capture_pcm handle of the capture PCM
* \param lconf Local configuration (might be NULL - use global configuration)
* \return 0 on success otherwise a negative error code
*/
int sndo_mixer_open(sndo_mixer_t **pmixer,
snd_pcm_t *playback_pcm,
snd_pcm_t *capture_pcm,
int sndo_mixer_open1(sndo_mixer_t **pmixer,
const char *lisp_fcn,
const char *lisp_fmt,
const void *parg,
const void *carg,
struct alisp_cfg *lconf)
{
struct alisp_cfg *cfg = lconf;
@ -101,16 +95,16 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
cfg = alsa_lisp_default_cfg(input);
if (cfg == NULL)
return -ENOMEM;
cfg->warning = 1;
#if 0
cfg->debug = 1;
cfg->verbose = 1;
cfg->warning = 1;
#endif
}
err = alsa_lisp(cfg, &alisp);
if (err < 0)
goto __error;
err = alsa_lisp_function(alisp, &iterator, "sndo_mixer_open", "%ppcm%ppcm", playback_pcm, capture_pcm);
err = alsa_lisp_function(alisp, &iterator, lisp_fcn, lisp_fmt, parg, carg);
if (err < 0) {
alsa_lisp_free(alisp);
goto __error;
@ -118,6 +112,7 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
err = alsa_lisp_seq_integer(iterator, &val);
if (err == 0 && val < 0)
err = val;
alsa_lisp_result_free(alisp, iterator);
if (err < 0) {
alsa_lisp_free(alisp);
goto __error;
@ -157,6 +152,39 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
return err;
}
/**
* \brief Opens a ordinary mixer instance
* \param pmixer Returned ordinary mixer handle
* \param playback_name name for playback HCTL communication
* \param capture_name name for capture HCTL communication
* \param lconf Local configuration (might be NULL - use global configuration)
* \return 0 on success otherwise a negative error code
*/
int sndo_mixer_open(sndo_mixer_t **pmixer,
const char *playback_name,
const char *capture_name,
struct alisp_cfg *lconf)
{
return sndo_mixer_open1(pmixer, "sndo_mixer_open", "%s%s", playback_name, capture_name, lconf);
}
/**
* \brief Opens a ordinary mixer instance
* \param pmixer Returned ordinary mixer handle
* \param playback_pcm handle of the playback PCM
* \param capture_pcm handle of the capture PCM
* \param lconf Local configuration (might be NULL - use global configuration)
* \return 0 on success otherwise a negative error code
*/
int sndo_mixer_open_pcm(sndo_mixer_t **pmixer,
snd_pcm_t *playback_pcm,
snd_pcm_t *capture_pcm,
struct alisp_cfg *lconf)
{
return sndo_mixer_open1(pmixer, "sndo_mixer_open_pcm", "%ppcm%ppcm", playback_pcm, capture_pcm, lconf);
}
/**
* \brief Closes a ordinary mixer instance
* \param mixer Ordinary mixer handle to close

View file

@ -27,7 +27,7 @@ int main(int argc, char *argv[])
{"cname", 1, NULL, 'C'},
{NULL, 0, NULL, 0},
};
int err, morehelp;
int err, morehelp, result = EXIT_SUCCESS;
char *pname = "default", *cname = "default";
snd_pcm_t *phandle = NULL, *chandle = NULL;
sndo_mixer_t *handle;
@ -59,7 +59,8 @@ int main(int argc, char *argv[])
err = snd_pcm_open(&phandle, pname, SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
fprintf(stderr, "Playback PCM open error: %s\n", snd_strerror(err));
return EXIT_FAILURE;
result = EXIT_FAILURE;
goto __end;
}
}
@ -69,17 +70,23 @@ int main(int argc, char *argv[])
if (phandle)
snd_pcm_close(phandle);
fprintf(stderr, "Capture PCM open error: %s\n", snd_strerror(err));
return EXIT_FAILURE;
result = EXIT_FAILURE;
goto __end;
}
}
err = sndo_mixer_open(&handle, phandle, chandle, NULL);
err = sndo_mixer_open_pcm(&handle, phandle, chandle, NULL);
if (err < 0) {
fprintf(stderr, "mixer open error: %s\n", snd_strerror(err));
return EXIT_FAILURE;
}
result = EXIT_FAILURE;
} else {
sndo_mixer_close(handle);
}
__end:
if (chandle)
snd_pcm_close(chandle);
if (phandle)
snd_pcm_close(phandle);
return EXIT_SUCCESS;
snd_config_update_free_global(); /* to keep valgrind happy */
return result;
}