1 /*************************************************************************/
2 /* */
3 /* Language Technologies Institute */
4 /* Carnegie Mellon University */
5 /* Copyright (c) 1999 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author: Alan W Black (awb@cs.cmu.edu) */
34 /* Date: December 1999 */
35 /*************************************************************************/
36 /* */
37 /* Typed values */
38 /* */
39 /*************************************************************************/
40
41 /* ----------------------------------------------------------------- */
42 /* The English TTS System "Flite+hts_engine" */
43 /* developed by HTS Working Group */
44 /* http://hts-engine.sourceforge.net/ */
45 /* ----------------------------------------------------------------- */
46 /* */
47 /* Copyright (c) 2005-2013 Nagoya Institute of Technology */
48 /* Department of Computer Science */
49 /* */
50 /* 2005-2008 Tokyo Institute of Technology */
51 /* Interdisciplinary Graduate School of */
52 /* Science and Engineering */
53 /* */
54 /* All rights reserved. */
55 /* */
56 /* Redistribution and use in source and binary forms, with or */
57 /* without modification, are permitted provided that the following */
58 /* conditions are met: */
59 /* */
60 /* - Redistributions of source code must retain the above copyright */
61 /* notice, this list of conditions and the following disclaimer. */
62 /* - Redistributions in binary form must reproduce the above */
63 /* copyright notice, this list of conditions and the following */
64 /* disclaimer in the documentation and/or other materials provided */
65 /* with the distribution. */
66 /* - Neither the name of the HTS working group nor the names of its */
67 /* contributors may be used to endorse or promote products derived */
68 /* from this software without specific prior written permission. */
69 /* */
70 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
71 /* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
72 /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
73 /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
74 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS */
75 /* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */
76 /* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
77 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
78 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
79 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */
80 /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY */
81 /* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
82 /* POSSIBILITY OF SUCH DAMAGE. */
83 /* ----------------------------------------------------------------- */
84
85 #include "cst_math.h"
86 #include "cst_file.h"
87 #include "cst_val.h"
88 #include "cst_string.h"
89
new_val()90 static cst_val *new_val()
91 {
92 return cst_alloc(struct cst_val_struct,1);
93 }
94
int_val(int i)95 cst_val *int_val(int i)
96 {
97 cst_val *v = new_val();
98 CST_VAL_TYPE(v) = CST_VAL_TYPE_INT;
99 CST_VAL_INT(v) = i;
100 return v;
101 }
102
float_val(float f)103 cst_val *float_val(float f)
104 {
105 cst_val *v = new_val();
106 CST_VAL_TYPE(v) = CST_VAL_TYPE_FLOAT;
107 CST_VAL_FLOAT(v) = f;
108 return v;
109 }
110
string_val(const char * s)111 cst_val *string_val(const char *s)
112 {
113 cst_val *v = new_val();
114 CST_VAL_TYPE(v) = CST_VAL_TYPE_STRING;
115 /* would be nice to note if this is a deletable string or not */
116 CST_VAL_STRING_LVAL(v) = cst_strdup(s);
117 return v;
118 }
119
cons_val(const cst_val * a,const cst_val * b)120 cst_val *cons_val(const cst_val *a, const cst_val *b)
121 {
122 cst_val *v = new_val();
123 CST_VAL_CAR(v)=((!a || cst_val_consp(a)) ?
124 (cst_val *)(void *)a:val_inc_refcount(a));
125 CST_VAL_CDR(v)=((!b || cst_val_consp(b)) ?
126 (cst_val *)(void *)b:val_inc_refcount(b));
127 return v;
128 }
129
val_new_typed(int type,void * vv)130 cst_val *val_new_typed(int type,void *vv)
131 {
132 cst_val *v = new_val();
133 CST_VAL_TYPE(v) = type;
134 CST_VAL_VOID(v) = vv;
135 return v;
136 }
137
delete_val_list(cst_val * v)138 void delete_val_list(cst_val *v)
139 {
140 if (v)
141 {
142 if (cst_val_consp(v))
143 {
144 delete_val_list(CST_VAL_CDR(v));
145 cst_free(v);
146 }
147 else
148 delete_val(v);
149 }
150 }
151
delete_val(cst_val * v)152 void delete_val(cst_val *v)
153 {
154 if (v)
155 {
156 if (cst_val_consp(v))
157 {
158 delete_val(CST_VAL_CAR(v));
159 delete_val(CST_VAL_CDR(v));
160 cst_free(v);
161 }
162 else if (val_dec_refcount(v) == 0)
163 {
164 if (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING)
165 cst_free(CST_VAL_VOID(v));
166 else if (CST_VAL_TYPE(v) >= CST_VAL_TYPE_FIRST_FREE)
167 {
168 if (cst_val_defs[CST_VAL_TYPE(v)/2].delete_function)
169 (cst_val_defs[CST_VAL_TYPE(v)/2].delete_function)
170 (CST_VAL_VOID(v));
171 }
172 cst_free(v);
173 }
174 }
175 }
176
177 /* Accessor functions */
val_int(const cst_val * v)178 int val_int(const cst_val *v)
179 {
180 if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_INT))
181 return CST_VAL_INT(v);
182 else if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_FLOAT))
183 return (int)CST_VAL_FLOAT(v);
184 else if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING))
185 return atoi(CST_VAL_STRING(v));
186 else
187 {
188 cst_errmsg("VAL: tried to access int in %d typed val\n",
189 (v ? CST_VAL_TYPE(v) : -1));
190 cst_error();
191 }
192 return 0;
193 }
194
val_float(const cst_val * v)195 float val_float(const cst_val *v)
196 {
197 if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_INT))
198 return (float)CST_VAL_INT(v);
199 else if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_FLOAT))
200 return CST_VAL_FLOAT(v);
201 else if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING))
202 return cst_atof(CST_VAL_STRING(v));
203 else
204 {
205 cst_errmsg("VAL: tried to access float in %d typed val\n",
206 (v ? CST_VAL_TYPE(v) : -1));
207 cst_error();
208 }
209 return 0;
210 }
211
val_string(const cst_val * v)212 const char *val_string(const cst_val *v)
213 {
214 if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING))
215 return CST_VAL_STRING(v);
216 else
217 {
218 cst_errmsg("VAL: tried to access string in %d typed val\n",
219 (v ? CST_VAL_TYPE(v) : -1));
220 cst_error();
221 }
222 return 0;
223 }
224
val_car(const cst_val * v)225 const cst_val *val_car(const cst_val *v)
226 {
227 if (v && cst_val_consp(v))
228 return CST_VAL_CAR(v);
229 else
230 {
231 cst_errmsg("VAL: tried to access car in %d typed val\n",
232 (v ? CST_VAL_TYPE(v) : -1));
233 cst_error();
234 }
235 return 0;
236 }
237
val_cdr(const cst_val * v)238 const cst_val *val_cdr(const cst_val *v)
239 {
240 if (v && cst_val_consp(v))
241 return CST_VAL_CDR(v);
242 else
243 {
244 cst_errmsg("VAL: tried to access cdr in %d typed val\n",
245 (v ? CST_VAL_TYPE(v) : -1));
246 cst_error();
247 }
248 return 0;
249 }
250
val_generic(const cst_val * v,int type,const char * stype)251 void *val_generic(const cst_val *v, int type, const char *stype)
252 { /* a generic access function that checks the expected type */
253 if (v && CST_VAL_TYPE(v) == type)
254 return CST_VAL_VOID(v);
255 else
256 {
257 cst_errmsg("VAL: tried to access %s in %d type val\n",
258 stype,
259 (v ? CST_VAL_TYPE(v) : -1));
260 cst_error();
261 }
262 return NULL;
263 }
264
val_void(const cst_val * v)265 void *val_void(const cst_val *v)
266 {
267 /* The scary, do anything function, this shouldn't be called by mortals */
268 if ((v == NULL) ||
269 (CST_VAL_TYPE(v) == CST_VAL_TYPE_CONS) ||
270 (CST_VAL_TYPE(v) == CST_VAL_TYPE_INT) ||
271 (CST_VAL_TYPE(v) == CST_VAL_TYPE_FLOAT))
272 {
273 cst_errmsg("VAL: tried to access void in %d typed val\n",
274 (v ? CST_VAL_TYPE(v) : -1));
275 cst_error();
276 return NULL;
277 }
278 else
279 return CST_VAL_VOID(v);
280 }
281
cst_val_consp(const cst_val * v)282 int cst_val_consp(const cst_val *v)
283 {
284 /* To keep a val cell down to 8 bytes we identify non-cons cells */
285 /* with non-zero values in the least significant bit of the first */
286 /* address in the cell (this is a standard technique used on Lisp */
287 /* machines */
288 #if 0
289 void *t;
290 int t1;
291
292 /* Hmm this still isn't right (it can be) but this isn't it */
293 t = CST_VAL_CAR(v);
294 t1 = *(int *)&t;
295
296 if ((t1&0x1) == 0)
297 return TRUE;
298 else
299 return FALSE;
300 #endif
301 const cst_val_atom *t;
302
303 t = (const cst_val_atom *)v;
304 if (t->type % 2 == 0)
305 return TRUE;
306 else
307 return FALSE;
308 }
309
set_cdr(cst_val * v1,const cst_val * v2)310 const cst_val *set_cdr(cst_val *v1, const cst_val *v2)
311 {
312 /* destructive set cdr, be careful you have a pointer to current cdr */
313
314 if (!cst_val_consp(v1))
315 {
316 cst_errmsg("VAL: tried to set cdr of non-consp cell\n");
317 cst_error();
318 return NULL;
319 }
320 else
321 {
322 val_dec_refcount(CST_VAL_CDR(v1));
323 val_inc_refcount(v1);
324 CST_VAL_CDR(v1) = (cst_val *)v2;
325 }
326 return v1;
327 }
328
set_car(cst_val * v1,const cst_val * v2)329 const cst_val *set_car(cst_val *v1, const cst_val *v2)
330 {
331 /* destructive set car, be careful you have a pointer to current cdr */
332
333 if (!cst_val_consp(v1))
334 {
335 cst_errmsg("VAL: tried to set car of non-consp cell\n");
336 cst_error();
337 return NULL;
338 }
339 else
340 {
341 val_dec_refcount(CST_VAL_CAR(v1));
342 val_inc_refcount(v1);
343 CST_VAL_CAR(v1) = (cst_val *)v2;
344 }
345 return v1;
346 }
347
348 #ifndef FLITE_PLUS_HTS_ENGINE
val_print(cst_file fd,const cst_val * v)349 void val_print(cst_file fd,const cst_val *v)
350 {
351 const cst_val *p;
352
353 if (v == NULL)
354 cst_fprintf(fd,"[null]");
355 else if (CST_VAL_TYPE(v) == CST_VAL_TYPE_INT)
356 cst_fprintf(fd,"%d",val_int(v));
357 else if (CST_VAL_TYPE(v) == CST_VAL_TYPE_FLOAT)
358 cst_fprintf(fd,"%f",val_float(v));
359 else if (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING)
360 cst_fprintf(fd,"%s",val_string(v));
361 else if (cst_val_consp(v))
362 {
363 cst_fprintf(fd,"(");
364 for (p=v; p; )
365 {
366 val_print(fd,val_car(p));
367 p=val_cdr(p);
368 if (p)
369 cst_fprintf(fd," ");
370 }
371 cst_fprintf(fd,")");
372 }
373 else
374 cst_fprintf(fd,"[Val %s 0x%p]",
375 cst_val_defs[CST_VAL_TYPE(v)/2].name,CST_VAL_VOID(v));
376 }
377 #endif /* !FLITE_PLUS_HTS_ENGINE */
378
val_reverse(cst_val * l)379 cst_val *val_reverse(cst_val *l)
380 {
381 cst_val *n,*np,*nl;
382 for (nl=0,n=l; n; nl=n,n=np)
383 {
384 np=CST_VAL_CDR(n);
385 CST_VAL_CDR(n) = nl;
386 }
387 return nl;
388 }
389
val_append(cst_val * l1,cst_val * l2)390 cst_val *val_append(cst_val *l1, cst_val *l2)
391 {
392 /* Destructively add l2 to the end of l1 return l1 */
393 cst_val *t;
394
395 if (l1 == 0)
396 return l2;
397 else
398 {
399 for (t=l1; val_cdr(t); t=CST_VAL_CDR(t));
400 CST_VAL_CDR(t) = l2;
401 return l1;
402 }
403 }
404
val_length(const cst_val * l)405 int val_length(const cst_val *l)
406 {
407 const cst_val *n;
408 int i;
409
410 for (i=0,n=l; n; n=val_cdr(n))
411 i++;
412
413 return i;
414 }
415
val_equal(const cst_val * v1,const cst_val * v2)416 int val_equal(const cst_val *v1, const cst_val *v2)
417 {
418 if (v1 == v2)
419 return TRUE; /* its eq so its equal */
420 else if (v1 == 0)
421 return FALSE;
422 else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE(v2))
423 {
424 if (cst_val_consp(v1))
425 return ((val_equal(val_car(v1),val_car(v2))) &&
426 (val_equal(val_cdr(v1),val_cdr(v2))));
427 else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_INT)
428 return (val_int(v1) == val_int(v2));
429 else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_FLOAT)
430 return (val_float(v1) == val_float(v2));
431 else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_STRING)
432 return (cst_streq(CST_VAL_STRING(v1),CST_VAL_STRING(v2)));
433 else
434 return CST_VAL_VOID(v1) == CST_VAL_VOID(v2);
435 }
436 else
437 return FALSE;
438 }
439
val_less(const cst_val * v1,const cst_val * v2)440 int val_less(const cst_val *v1, const cst_val *v2)
441 {
442 return val_float(v1) < val_float(v2);
443 }
444
val_greater(const cst_val * v1,const cst_val * v2)445 int val_greater(const cst_val *v1,const cst_val *v2)
446 {
447 return val_float(v1) > val_float(v2);
448 }
449
val_member(const cst_val * v1,const cst_val * l)450 int val_member(const cst_val *v1,const cst_val *l)
451 {
452 const cst_val *i;
453
454 for (i=l; i; i=val_cdr(i))
455 {
456 if (val_equal(val_car(i),v1))
457 return TRUE;
458 }
459 return FALSE;
460 }
461
val_member_string(const char * v1,const cst_val * l)462 int val_member_string(const char *v1,const cst_val *l)
463 {
464 const cst_val *i;
465
466 for (i=l; i; i=val_cdr(i))
467 {
468 if (cst_streq(v1,val_string(val_car(i))))
469 return TRUE;
470 }
471 return FALSE;
472 }
473
val_inc_refcount(const cst_val * b)474 cst_val *val_inc_refcount(const cst_val *b)
475 {
476 cst_val *wb;
477
478 /* Well I was lying, they're not really const, but this is the place */
479 /* where breaking const is reasonable */
480 wb = (cst_val *)(void *)b;
481
482 if (CST_VAL_REFCOUNT(wb) == -1)
483 /* or is a cons cell in the text segment, how do I do that ? */
484 return wb;
485 else if (!cst_val_consp(wb)) /* we don't ref count cons cells */
486 CST_VAL_REFCOUNT(wb) += 1;
487 return wb;
488 }
489
val_dec_refcount(const cst_val * b)490 int val_dec_refcount(const cst_val *b)
491 {
492 cst_val *wb;
493
494 wb = (cst_val *)(void *)b;
495
496 if (CST_VAL_REFCOUNT(wb) == -1)
497 /* or is a cons cell in the text segment, how do I do that ? */
498 return -1;
499 else if (cst_val_consp(wb)) /* we don't ref count cons cells */
500 return 0;
501 else if (CST_VAL_REFCOUNT(wb) == 0)
502 {
503 /* Otherwise, trying to free a val outside an
504 item/relation/etc has rather the opposite effect from what
505 you might have intended... */
506 return 0;
507 }
508 else
509 {
510 CST_VAL_REFCOUNT(wb) -= 1;
511 return CST_VAL_REFCOUNT(wb);
512 }
513 }
514
cst_utf8_explode(const cst_string * utf8string)515 cst_val *cst_utf8_explode(const cst_string *utf8string)
516 {
517 /* return a list of utf-8 characters as strings */
518 const unsigned char *xxx = (const unsigned char *)utf8string;
519 cst_val *chars=NULL;
520 int i, l=0;
521 char utf8char[5];
522
523 for (i=0; xxx[i]; i++)
524 {
525 if (xxx[i] < 0x80) /* one byte */
526 {
527 sprintf(utf8char,"%c",xxx[i]);
528 l = 1;
529 }
530 else if (xxx[i] < 0xe0) /* two bytes */
531 {
532 sprintf(utf8char,"%c%c",xxx[i],xxx[i+1]);
533 i++;
534 l = 2;
535 }
536 else if (xxx[i] < 0xff) /* three bytes */
537 {
538 sprintf(utf8char,"%c%c%c",xxx[i],xxx[i+1],xxx[i+2]);
539 i++; i++;
540 l = 3;
541 }
542 else
543 {
544 sprintf(utf8char,"%c%c%c%c",xxx[i],xxx[i+1],xxx[i+2],xxx[i+3]);
545 i++; i++; i++;
546 l = 4;
547 }
548 chars = cons_val(string_val(utf8char),chars);
549 }
550 return val_reverse(chars);
551
552 }
553
val_stringp(const cst_val * v)554 int val_stringp(const cst_val *v)
555 {
556 if (cst_val_consp(v))
557 return FALSE;
558 else if (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING)
559 return TRUE;
560 else
561 return FALSE;
562 }
563
val_assoc_string(const char * v1,const cst_val * al)564 const cst_val *val_assoc_string(const char *v1,const cst_val *al)
565 {
566 const cst_val *i;
567
568 for (i=al; i; i=val_cdr(i))
569 {
570 if (cst_streq(v1,val_string(val_car(val_car(i)))))
571 return val_car(i);
572 }
573 return NULL;
574 }
575
cst_implode(const cst_val * sl)576 cst_string *cst_implode(const cst_val *sl)
577 {
578 const cst_val *v;
579 int l=0;
580 char *s;
581
582 for (v=sl; v; v=val_cdr(v))
583 {
584 if (val_stringp(val_car(v)))
585 l += cst_strlen(val_string(val_car(v)));
586 }
587
588 s = cst_alloc(cst_string,l+1);
589
590 for (v=sl; v; v=val_cdr(v))
591 {
592 if (val_stringp(val_car(v)))
593 cst_sprintf(s,"%s%s",s,val_string(val_car(v)));
594
595 }
596
597 return s;
598 }
599