1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  ALSA lisp implementation
3d5ac70f0Sopenharmony_ci *  Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
4d5ac70f0Sopenharmony_ci *
5d5ac70f0Sopenharmony_ci *  Based on work of Sandro Sigala (slisp-1.2)
6d5ac70f0Sopenharmony_ci *
7d5ac70f0Sopenharmony_ci *
8d5ac70f0Sopenharmony_ci *   This library is free software; you can redistribute it and/or modify
9d5ac70f0Sopenharmony_ci *   it under the terms of the GNU Lesser General Public License as
10d5ac70f0Sopenharmony_ci *   published by the Free Software Foundation; either version 2.1 of
11d5ac70f0Sopenharmony_ci *   the License, or (at your option) any later version.
12d5ac70f0Sopenharmony_ci *
13d5ac70f0Sopenharmony_ci *   This program is distributed in the hope that it will be useful,
14d5ac70f0Sopenharmony_ci *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15d5ac70f0Sopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16d5ac70f0Sopenharmony_ci *   GNU Lesser General Public License for more details.
17d5ac70f0Sopenharmony_ci *
18d5ac70f0Sopenharmony_ci *   You should have received a copy of the GNU Lesser General Public
19d5ac70f0Sopenharmony_ci *   License along with this library; if not, write to the Free Software
20d5ac70f0Sopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21d5ac70f0Sopenharmony_ci *
22d5ac70f0Sopenharmony_ci */
23d5ac70f0Sopenharmony_ci
24d5ac70f0Sopenharmony_ci#include "list.h"
25d5ac70f0Sopenharmony_ci
26d5ac70f0Sopenharmony_cienum alisp_tokens {
27d5ac70f0Sopenharmony_ci	ALISP_IDENTIFIER,
28d5ac70f0Sopenharmony_ci	ALISP_INTEGER,
29d5ac70f0Sopenharmony_ci	ALISP_FLOAT,
30d5ac70f0Sopenharmony_ci	ALISP_FLOATE,
31d5ac70f0Sopenharmony_ci	ALISP_STRING
32d5ac70f0Sopenharmony_ci};
33d5ac70f0Sopenharmony_ci
34d5ac70f0Sopenharmony_cienum alisp_objects {
35d5ac70f0Sopenharmony_ci	ALISP_OBJ_INTEGER,
36d5ac70f0Sopenharmony_ci	ALISP_OBJ_FLOAT,
37d5ac70f0Sopenharmony_ci	ALISP_OBJ_IDENTIFIER,
38d5ac70f0Sopenharmony_ci	ALISP_OBJ_STRING,
39d5ac70f0Sopenharmony_ci	ALISP_OBJ_POINTER,
40d5ac70f0Sopenharmony_ci	ALISP_OBJ_CONS,
41d5ac70f0Sopenharmony_ci	ALISP_OBJ_LAST_SEARCH = ALISP_OBJ_CONS,
42d5ac70f0Sopenharmony_ci	ALISP_OBJ_NIL,
43d5ac70f0Sopenharmony_ci	ALISP_OBJ_T,
44d5ac70f0Sopenharmony_ci};
45d5ac70f0Sopenharmony_ci
46d5ac70f0Sopenharmony_cistruct alisp_object;
47d5ac70f0Sopenharmony_ci
48d5ac70f0Sopenharmony_ci#define ALISP_TYPE_MASK	0xf0000000
49d5ac70f0Sopenharmony_ci#define ALISP_TYPE_SHIFT 28
50d5ac70f0Sopenharmony_ci#define ALISP_REFS_MASK 0x0fffffff
51d5ac70f0Sopenharmony_ci#define ALISP_REFS_SHIFT 0
52d5ac70f0Sopenharmony_ci#define ALISP_MAX_REFS (ALISP_REFS_MASK>>ALISP_REFS_SHIFT)
53d5ac70f0Sopenharmony_ci#define ALISP_MAX_REFS_LIMIT ((ALISP_MAX_REFS + 1) / 2)
54d5ac70f0Sopenharmony_ci
55d5ac70f0Sopenharmony_cistruct alisp_object {
56d5ac70f0Sopenharmony_ci	struct list_head list;
57d5ac70f0Sopenharmony_ci	unsigned int	type_refs;	/* type and count of references */
58d5ac70f0Sopenharmony_ci	union {
59d5ac70f0Sopenharmony_ci		char	*s;
60d5ac70f0Sopenharmony_ci		long	i;
61d5ac70f0Sopenharmony_ci		double	f;
62d5ac70f0Sopenharmony_ci		const void *ptr;
63d5ac70f0Sopenharmony_ci		struct {
64d5ac70f0Sopenharmony_ci			struct alisp_object *car;
65d5ac70f0Sopenharmony_ci			struct alisp_object *cdr;
66d5ac70f0Sopenharmony_ci		} c;
67d5ac70f0Sopenharmony_ci	} value;
68d5ac70f0Sopenharmony_ci};
69d5ac70f0Sopenharmony_ci
70d5ac70f0Sopenharmony_cistatic inline enum alisp_objects alisp_get_type(struct alisp_object *p)
71d5ac70f0Sopenharmony_ci{
72d5ac70f0Sopenharmony_ci	return (p->type_refs >> ALISP_TYPE_SHIFT);
73d5ac70f0Sopenharmony_ci}
74d5ac70f0Sopenharmony_ci
75d5ac70f0Sopenharmony_cistatic inline void alisp_set_type(struct alisp_object *p, enum alisp_objects type)
76d5ac70f0Sopenharmony_ci{
77d5ac70f0Sopenharmony_ci	p->type_refs &= ~ALISP_TYPE_MASK;
78d5ac70f0Sopenharmony_ci	p->type_refs |= (unsigned int)type << ALISP_TYPE_SHIFT;
79d5ac70f0Sopenharmony_ci}
80d5ac70f0Sopenharmony_ci
81d5ac70f0Sopenharmony_cistatic inline int alisp_compare_type(struct alisp_object *p, enum alisp_objects type)
82d5ac70f0Sopenharmony_ci{
83d5ac70f0Sopenharmony_ci	return ((unsigned int)type << ALISP_TYPE_SHIFT) ==
84d5ac70f0Sopenharmony_ci	       (p->type_refs & ALISP_TYPE_MASK);
85d5ac70f0Sopenharmony_ci}
86d5ac70f0Sopenharmony_ci
87d5ac70f0Sopenharmony_cistatic inline void alisp_set_refs(struct alisp_object *p, unsigned int refs)
88d5ac70f0Sopenharmony_ci{
89d5ac70f0Sopenharmony_ci	p->type_refs &= ~ALISP_REFS_MASK;
90d5ac70f0Sopenharmony_ci	p->type_refs |= refs & ALISP_REFS_MASK;
91d5ac70f0Sopenharmony_ci}
92d5ac70f0Sopenharmony_ci
93d5ac70f0Sopenharmony_cistatic inline unsigned int alisp_get_refs(struct alisp_object *p)
94d5ac70f0Sopenharmony_ci{
95d5ac70f0Sopenharmony_ci	return p->type_refs & ALISP_REFS_MASK;
96d5ac70f0Sopenharmony_ci}
97d5ac70f0Sopenharmony_ci
98d5ac70f0Sopenharmony_cistatic inline unsigned int alisp_inc_refs(struct alisp_object *p)
99d5ac70f0Sopenharmony_ci{
100d5ac70f0Sopenharmony_ci	unsigned r = alisp_get_refs(p) + 1;
101d5ac70f0Sopenharmony_ci	alisp_set_refs(p, r);
102d5ac70f0Sopenharmony_ci	return r;
103d5ac70f0Sopenharmony_ci}
104d5ac70f0Sopenharmony_ci
105d5ac70f0Sopenharmony_cistatic inline unsigned int alisp_dec_refs(struct alisp_object *p)
106d5ac70f0Sopenharmony_ci{
107d5ac70f0Sopenharmony_ci	unsigned r = alisp_get_refs(p) - 1;
108d5ac70f0Sopenharmony_ci	alisp_set_refs(p, r);
109d5ac70f0Sopenharmony_ci	return r;
110d5ac70f0Sopenharmony_ci}
111d5ac70f0Sopenharmony_ci
112d5ac70f0Sopenharmony_cistruct alisp_object_pair {
113d5ac70f0Sopenharmony_ci	struct list_head list;
114d5ac70f0Sopenharmony_ci	const char *name;
115d5ac70f0Sopenharmony_ci 	struct alisp_object *value;
116d5ac70f0Sopenharmony_ci};
117d5ac70f0Sopenharmony_ci
118d5ac70f0Sopenharmony_ci#define ALISP_LEX_BUF_MAX	16
119d5ac70f0Sopenharmony_ci#define ALISP_OBJ_PAIR_HASH_SHIFT 4
120d5ac70f0Sopenharmony_ci#define ALISP_OBJ_PAIR_HASH_SIZE (1<<ALISP_OBJ_PAIR_HASH_SHIFT)
121d5ac70f0Sopenharmony_ci#define ALISP_OBJ_PAIR_HASH_MASK (ALISP_OBJ_PAIR_HASH_SIZE-1)
122d5ac70f0Sopenharmony_ci#define ALISP_FREE_OBJ_POOL	512	/* free objects above this pool */
123d5ac70f0Sopenharmony_ci
124d5ac70f0Sopenharmony_cistruct alisp_instance {
125d5ac70f0Sopenharmony_ci	int verbose: 1,
126d5ac70f0Sopenharmony_ci	    warning: 1,
127d5ac70f0Sopenharmony_ci	    debug: 1;
128d5ac70f0Sopenharmony_ci	/* i/o */
129d5ac70f0Sopenharmony_ci	snd_input_t *in;
130d5ac70f0Sopenharmony_ci	snd_output_t *out;
131d5ac70f0Sopenharmony_ci	snd_output_t *eout;	/* error output */
132d5ac70f0Sopenharmony_ci	snd_output_t *vout;	/* verbose output */
133d5ac70f0Sopenharmony_ci	snd_output_t *wout;	/* warning output */
134d5ac70f0Sopenharmony_ci	snd_output_t *dout;	/* debug output */
135d5ac70f0Sopenharmony_ci	/* lexer */
136d5ac70f0Sopenharmony_ci	int charno;
137d5ac70f0Sopenharmony_ci	int lineno;
138d5ac70f0Sopenharmony_ci	int lex_buf[ALISP_LEX_BUF_MAX];
139d5ac70f0Sopenharmony_ci	int *lex_bufp;
140d5ac70f0Sopenharmony_ci	char *token_buffer;
141d5ac70f0Sopenharmony_ci	int token_buffer_max;
142d5ac70f0Sopenharmony_ci	int thistoken;
143d5ac70f0Sopenharmony_ci	/* object allocator / storage */
144d5ac70f0Sopenharmony_ci	long free_objs;
145d5ac70f0Sopenharmony_ci	long used_objs;
146d5ac70f0Sopenharmony_ci	long max_objs;
147d5ac70f0Sopenharmony_ci	struct list_head free_objs_list;
148d5ac70f0Sopenharmony_ci	struct list_head used_objs_list[ALISP_OBJ_PAIR_HASH_SIZE][ALISP_OBJ_LAST_SEARCH + 1];
149d5ac70f0Sopenharmony_ci	/* set object */
150d5ac70f0Sopenharmony_ci	struct list_head setobjs_list[ALISP_OBJ_PAIR_HASH_SIZE];
151d5ac70f0Sopenharmony_ci};
152