1 /* Basic type operations for S-Lang */
2 /*
3 Copyright (C) 2004-2017,2018 John E. Davis
4
5 This file is part of the S-Lang Library.
6
7 The S-Lang Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The S-Lang Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 USA.
21 */
22
23 #include "slinclud.h"
24
25 #if SLANG_HAS_FLOAT
26 # include <math.h>
27 #endif
28
29 /* #define SL_APP_WANTS_FOREACH */ /* for String_Type */
30 #include "slang.h"
31 #include "_slang.h"
32
SLpop_string(char ** s)33 int SLpop_string (char **s) /*{{{*/
34 {
35 char *sls;
36
37 *s = NULL;
38
39 if (-1 == SLang_pop_slstring (&sls))
40 return -1;
41
42 if (NULL == (*s = SLmake_string (sls)))
43 {
44 SLang_free_slstring (sls);
45 return -1;
46 }
47
48 SLang_free_slstring (sls);
49 return 0;
50 }
51
52 /*}}}*/
53
SLang_pop_slstring(char ** s)54 int SLang_pop_slstring (char **s) /*{{{*/
55 {
56 return SLclass_pop_ptr_obj (SLANG_STRING_TYPE, (VOID_STAR *)s);
57 }
58
59 /*}}}*/
60
_pSLang_push_slstring(char * s)61 int _pSLang_push_slstring (char *s)
62 {
63 if (0 == SLclass_push_ptr_obj (SLANG_STRING_TYPE, (VOID_STAR)s))
64 return 0;
65
66 SLang_free_slstring (s);
67 return -1;
68 }
69
70 /* Frees s upon error */
_pSLpush_alloced_slstring(char * s,size_t len)71 int _pSLpush_alloced_slstring (char *s, size_t len)
72 {
73 if (NULL == (s = _pSLcreate_via_alloced_slstring (s, len)))
74 return -1;
75
76 return _pSLang_push_slstring (s);
77 }
78
SLang_push_string(SLFUTURE_CONST char * t)79 int SLang_push_string (SLFUTURE_CONST char *t) /*{{{*/
80 {
81 if (t == NULL)
82 return SLang_push_null ();
83
84 if (NULL == (t = SLang_create_slstring (t)))
85 return -1;
86
87 return _pSLang_push_slstring ((char *) t);
88 }
89
90 /*}}}*/
91
_pSLang_dup_and_push_slstring(SLCONST char * s)92 int _pSLang_dup_and_push_slstring (SLCONST char *s)
93 {
94 if (NULL == (s = _pSLstring_dup_slstring (s)))
95 return SLang_push_null ();
96
97 return _pSLang_push_slstring ((char *) s);
98 }
99
100 /* This function _always_ frees the malloced string */
SLang_push_malloced_string(char * c)101 int SLang_push_malloced_string (char *c) /*{{{*/
102 {
103 int ret;
104
105 ret = SLang_push_string (c);
106 SLfree (c);
107
108 return ret;
109 }
110
111 /*}}}*/
112
113 #if 0
114 static int int_int_power (int a, int b)
115 {
116 int r, s;
117
118 if (a == 0) return 0;
119 if (b < 0) return 0;
120 if (b == 0) return 1;
121
122 s = 1;
123 if (a < 0)
124 {
125 if ((b % 2) == 1) s = -1;
126 a = -a;
127 }
128
129 /* FIXME: Priority=low
130 * This needs optimized
131 */
132 r = 1;
133 while (b)
134 {
135 r = r * a;
136 b--;
137 }
138 return r * s;
139 }
140 #endif
141
142 static int
string_string_bin_op_result(int op,SLtype a,SLtype b,SLtype * c)143 string_string_bin_op_result (int op, SLtype a, SLtype b,
144 SLtype *c)
145 {
146 (void) a;
147 (void) b;
148 switch (op)
149 {
150 default:
151 return 0;
152
153 case SLANG_PLUS:
154 *c = SLANG_STRING_TYPE;
155 break;
156
157 case SLANG_GT:
158 case SLANG_GE:
159 case SLANG_LT:
160 case SLANG_LE:
161 case SLANG_EQ:
162 case SLANG_NE:
163 *c = SLANG_CHAR_TYPE;
164 break;
165 }
166 return 1;
167 }
168
169 static int
string_string_bin_op(int op,SLtype a_type,VOID_STAR ap,SLuindex_Type na,SLtype b_type,VOID_STAR bp,SLuindex_Type nb,VOID_STAR cp)170 string_string_bin_op (int op,
171 SLtype a_type, VOID_STAR ap, SLuindex_Type na,
172 SLtype b_type, VOID_STAR bp, SLuindex_Type nb,
173 VOID_STAR cp)
174 {
175 char *ic;
176 char **a, **b, **c;
177 SLuindex_Type n, n_max;
178 unsigned int da, db;
179
180 (void) a_type;
181 (void) b_type;
182
183 if (na == 1) da = 0; else da = 1;
184 if (nb == 1) db = 0; else db = 1;
185
186 if (na > nb) n_max = na; else n_max = nb;
187
188 a = (char **) ap;
189 b = (char **) bp;
190
191 if ((op != SLANG_NE) && (op != SLANG_EQ))
192 for (n = 0; n < n_max; n++)
193 {
194 if ((*a == NULL) || (*b == NULL))
195 {
196 _pSLang_verror (SL_VARIABLE_UNINITIALIZED, "String element[%lu] not initialized for binary operation", (unsigned long)n);
197 return -1;
198 }
199 a += da; b += db;
200 }
201
202 a = (char **) ap;
203 b = (char **) bp;
204 ic = (char *) cp;
205 c = NULL;
206
207 switch (op)
208 {
209 case SLANG_DIVIDE:
210 case SLANG_MINUS:
211 default:
212 return 0;
213
214 case SLANG_PLUS:
215 /* Concat */
216 c = (char **) cp;
217 for (n = 0; n < n_max; n++)
218 {
219 if (NULL == (c[n] = SLang_concat_slstrings (*a, *b)))
220 goto return_error;
221
222 a += da; b += db;
223 }
224 break;
225
226 case SLANG_NE:
227 for (n = 0; n < n_max; n++)
228 {
229 if ((*a == NULL) || (*b == NULL))
230 ic [n] = (*a != *b);
231 else
232 ic [n] = (*a != *b) && (0 != strcmp (*a, *b));
233
234 a += da;
235 b += db;
236 }
237 break;
238 case SLANG_GT:
239 for (n = 0; n < n_max; n++)
240 {
241 ic [n] = (strcmp (*a, *b) > 0);
242 a += da;
243 b += db;
244 }
245 break;
246 case SLANG_GE:
247 for (n = 0; n < n_max; n++)
248 {
249 ic [n] = (strcmp (*a, *b) >= 0);
250 a += da;
251 b += db;
252 }
253 break;
254 case SLANG_LT:
255 for (n = 0; n < n_max; n++)
256 {
257 ic [n] = (strcmp (*a, *b) < 0);
258 a += da;
259 b += db;
260 }
261 break;
262 case SLANG_LE:
263 for (n = 0; n < n_max; n++)
264 {
265 ic [n] = (strcmp (*a, *b) <= 0);
266 a += da;
267 b += db;
268 }
269 break;
270 case SLANG_EQ:
271 for (n = 0; n < n_max; n++)
272 {
273 if ((*a == NULL) || (*b == NULL))
274 ic[n] = (*a == *b);
275 else
276 ic [n] = (*a == *b) || (strcmp (*a, *b) == 0);
277 a += da;
278 b += db;
279 }
280 break;
281 }
282 return 1;
283
284 return_error:
285 if (c != NULL)
286 {
287 SLuindex_Type nn;
288 for (nn = 0; nn < n; nn++)
289 {
290 SLang_free_slstring (c[nn]);
291 c[nn] = NULL;
292 }
293 for (nn = n; nn < n_max; nn++)
294 c[nn] = NULL;
295 }
296 return -1;
297 }
298
string_destroy(SLtype unused,VOID_STAR s)299 static void string_destroy (SLtype unused, VOID_STAR s)
300 {
301 (void) unused;
302 SLang_free_slstring (*(char **) s);
303 }
304
string_push(SLtype unused,VOID_STAR sptr)305 static int string_push (SLtype unused, VOID_STAR sptr)
306 {
307 (void) unused;
308 return SLang_push_string (*(char **) sptr);
309 }
310
string_cmp(SLtype unused,VOID_STAR ap,VOID_STAR bp,int * c)311 static int string_cmp (SLtype unused, VOID_STAR ap, VOID_STAR bp, int *c)
312 {
313 char *a, *b;
314 (void) unused;
315
316 a = *(char **) ap;
317 b = *(char **) bp;
318 if (a != b)
319 {
320 if (a == NULL) *c = -1;
321 else if (b == NULL) *c = 1;
322 else *c = strcmp (a, b);
323 return 0;
324 }
325 *c = 0;
326 return 0;
327 }
328
string_to_int(SLtype a_type,VOID_STAR ap,SLuindex_Type na,SLtype b_type,VOID_STAR bp)329 static int string_to_int (SLtype a_type, VOID_STAR ap, SLuindex_Type na,
330 SLtype b_type, VOID_STAR bp)
331 {
332 char **s;
333 unsigned int i;
334 int *b;
335
336 (void) a_type;
337 (void) b_type;
338
339 s = (char **) ap;
340 b = (int *) bp;
341 for (i = 0; i < na; i++)
342 {
343 if (s[i] == NULL) b[i] = 0;
344 else b[i] = s[i][0];
345 }
346 return 1;
347 }
348
string_acopy(SLtype unused,VOID_STAR src_sptr,VOID_STAR dest_sptr)349 static int string_acopy (SLtype unused, VOID_STAR src_sptr, VOID_STAR dest_sptr)
350 {
351 char *s;
352 (void) unused;
353 if (NULL == (s = SLang_create_slstring (*(char **)src_sptr)))
354 return -1;
355 *(char **)dest_sptr = s;
356 return 0;
357 }
358
_pSLstrings_to_array(char ** strs,unsigned int n)359 SLang_Array_Type *_pSLstrings_to_array (char **strs, unsigned int n)
360 {
361 char **data;
362 SLindex_Type i, inum;
363 SLang_Array_Type *at;
364
365 inum = (SLindex_Type) n;
366
367 if (NULL == (at = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &inum, 1)))
368 return NULL;
369
370 data = (char **)at->data;
371 for (i = 0; i < inum; i++)
372 {
373 if (strs[i] == NULL)
374 {
375 data[i] = NULL;
376 continue;
377 }
378
379 if (NULL == (data[i] = SLang_create_slstring (strs[i])))
380 {
381 SLang_free_array (at);
382 return NULL;
383 }
384 }
385 return at;
386 }
387
string_list_to_array(_pSLString_List_Type * p,int delete_list)388 static SLang_Array_Type *string_list_to_array (_pSLString_List_Type *p, int delete_list)
389 {
390 unsigned int num;
391 SLindex_Type inum;
392 SLang_Array_Type *at;
393 char **buf;
394
395 buf = p->buf;
396 num = p->num;
397
398 if (delete_list == 0)
399 return _pSLstrings_to_array (buf, num);
400
401 inum = (SLindex_Type) num;
402 if (num == 0) num++; /* so realloc succeeds */
403
404 /* Since the list is to be deleted, we can steal the buffer */
405 if ((num != p->max_num)
406 && (NULL == (buf = (char **)SLrealloc ((char *) buf, sizeof (char *) * num))))
407 {
408 _pSLstring_list_delete (p);
409 return NULL;
410 }
411 p->max_num = num;
412 p->buf = buf;
413
414 if (NULL == (at = SLang_create_array (SLANG_STRING_TYPE, 0, (VOID_STAR) buf, &inum, 1)))
415 {
416 _pSLstring_list_delete (p);
417 return NULL;
418 }
419 p->buf = NULL;
420 _pSLstring_list_delete (p);
421 return at;
422 }
423
_pSLstring_list_push(_pSLString_List_Type * p,int delete_list)424 int _pSLstring_list_push (_pSLString_List_Type *p, int delete_list)
425 {
426 SLang_Array_Type *at;
427
428 if ((p == NULL)
429 || (p->buf == NULL))
430 {
431 int ret = SLang_push_null ();
432 if (delete_list)
433 _pSLstring_list_delete (p);
434 return ret;
435 }
436
437 if (NULL == (at = string_list_to_array (p, delete_list)))
438 return -1;
439
440 return SLang_push_array (at, 1);
441 }
442
_pSLstring_list_init(_pSLString_List_Type * p,unsigned int max_num,unsigned int delta_num)443 int _pSLstring_list_init (_pSLString_List_Type *p, unsigned int max_num, unsigned int delta_num)
444 {
445 if (NULL == (p->buf = (char **) _SLcalloc (max_num, sizeof (char *))))
446 return -1;
447
448 p->max_num = max_num;
449 p->num = 0;
450 p->delta_num = delta_num;
451 p->is_malloced = 0;
452 return 0;
453 }
454
_pSLstring_list_append(_pSLString_List_Type * p,char * s)455 int _pSLstring_list_append (_pSLString_List_Type *p, char *s)
456 {
457 if (s == NULL)
458 return -1;
459
460 if (p->max_num == p->num)
461 {
462 char **b;
463 unsigned int max_num = p->num + p->delta_num;
464 b = (char **)SLrealloc ((char *)p->buf, max_num * sizeof (char *));
465 if (b == NULL)
466 return -1;
467 p->buf = b;
468 p->max_num = max_num;
469 }
470
471 p->buf[p->num] = s;
472 p->num++;
473 return 0;
474 }
475
_pSLstring_list_append_copy(_pSLString_List_Type * p,char * s)476 int _pSLstring_list_append_copy (_pSLString_List_Type *p, char *s)
477 {
478 s = SLang_create_slstring (s);
479 if (s == NULL)
480 return -1;
481 if (-1 == _pSLstring_list_append (p, s))
482 {
483 SLang_free_slstring (s);
484 return -1;
485 }
486 return 0;
487 }
488
_pSLstring_list_delete(_pSLString_List_Type * p)489 void _pSLstring_list_delete (_pSLString_List_Type *p)
490 {
491 if (p == NULL)
492 return;
493
494 if (p->buf != NULL)
495 {
496 unsigned int i, imax;
497 char **buf = p->buf;
498 imax = p->num;
499 for (i = 0; i < imax; i++)
500 SLang_free_slstring (buf[i]);
501 SLfree ((char *)buf);
502 p->buf = NULL;
503 }
504 if (p->is_malloced)
505 SLfree ((char *) p);
506 }
507
_pSLstring_list_new(unsigned int max_num,unsigned int delta_num)508 _pSLString_List_Type *_pSLstring_list_new (unsigned int max_num, unsigned int delta_num)
509 {
510 _pSLString_List_Type *p;
511
512 p = (_pSLString_List_Type *)SLmalloc (sizeof (_pSLString_List_Type));
513 if (p == NULL)
514 return NULL;
515
516 if (-1 == _pSLstring_list_init (p, max_num, delta_num))
517 {
518 SLfree ((char *) p);
519 return NULL;
520 }
521 p->is_malloced = 1;
522 return p;
523 }
524
525 /* Ref type */
526
_pSLang_deref_assign(SLang_Ref_Type * ref)527 int _pSLang_deref_assign (SLang_Ref_Type *ref)
528 {
529 return ref->deref_assign (ref->data);
530 }
531
SLang_pop_ref(SLang_Ref_Type ** ref)532 int SLang_pop_ref (SLang_Ref_Type **ref)
533 {
534 return SLclass_pop_ptr_obj (SLANG_REF_TYPE, (VOID_STAR *)ref);
535 }
536
SLang_push_ref(SLang_Ref_Type * ref)537 int SLang_push_ref (SLang_Ref_Type *ref)
538 {
539 ref->num_refs++;
540 if (0 == SLclass_push_ptr_obj (SLANG_REF_TYPE, (VOID_STAR) ref))
541 return 0;
542 ref->num_refs--;
543 return -1;
544 }
545
SLang_free_ref(SLang_Ref_Type * ref)546 void SLang_free_ref (SLang_Ref_Type *ref)
547 {
548 if (ref == NULL)
549 return;
550
551 if (ref->num_refs > 1)
552 {
553 ref->num_refs--;
554 return;
555 }
556
557 if (ref->destroy != NULL)
558 (*ref->destroy)(ref->data);
559 SLfree ((char *)ref->data);
560 SLfree ((char *)ref);
561 }
562
_pSLang_new_ref(unsigned int sizeof_data)563 SLang_Ref_Type *_pSLang_new_ref (unsigned int sizeof_data)
564 {
565 SLang_Ref_Type *ref;
566
567 if (NULL == (ref = (SLang_Ref_Type *)SLcalloc (1, sizeof (SLang_Ref_Type))))
568 return NULL;
569 if (NULL == (ref->data = (VOID_STAR)SLcalloc (1, sizeof_data)))
570 {
571 SLfree ((char *)ref);
572 return NULL;
573 }
574 ref->num_refs = 1;
575 ref->sizeof_data = sizeof_data;
576 return ref;
577 }
578
ref_destroy(SLtype type,VOID_STAR ptr)579 static void ref_destroy (SLtype type, VOID_STAR ptr)
580 {
581 (void) type;
582 SLang_free_ref (*(SLang_Ref_Type **)ptr);
583 }
584
ref_push(SLtype type,VOID_STAR ptr)585 static int ref_push (SLtype type, VOID_STAR ptr)
586 {
587 SLang_Ref_Type *ref;
588
589 (void) type;
590
591 ref = *(SLang_Ref_Type **) ptr;
592
593 if (ref == NULL)
594 return SLang_push_null ();
595
596 return SLang_push_ref (ref);
597 }
598
SLang_assign_to_ref(SLang_Ref_Type * ref,SLtype type,VOID_STAR v)599 int SLang_assign_to_ref (SLang_Ref_Type *ref, SLtype type, VOID_STAR v)
600 {
601 SLang_Object_Type *stkptr;
602 SLang_Class_Type *cl;
603
604 cl = _pSLclass_get_class (type);
605
606 /* Use apush since this function is passing ``array'' bytes rather than the
607 * address of the data. I need to somehow make this more consistent. To
608 * see what I mean, consider:
609 *
610 * double z[2];
611 * char *s = "silly";
612 * char bytes[10]; BAD--- Don't do this
613 * int i;
614 *
615 * SLang_assign_to_ref (ref, SLANG_INT_TYPE, &i);
616 * SLang_assign_to_ref (ref, SLANG_STRING_TYPE, &s);
617 * SLang_assign_to_ref (ref, SLANG_COMPLEX_TYPE, z);
618 *
619 * That is, all external routines that take a VOID_STAR argument need to
620 * be documented such that how the function should be called with the
621 * various class_types.
622 */
623 if (-1 == (*cl->cl_apush) (type, v))
624 return -1;
625
626 stkptr = _pSLang_get_run_stack_pointer ();
627 if (0 == _pSLang_deref_assign (ref))
628 return 0;
629
630 if (stkptr != _pSLang_get_run_stack_pointer ())
631 SLdo_pop ();
632
633 return -1;
634 }
635
ref_string(SLtype type,VOID_STAR ptr)636 static char *ref_string (SLtype type, VOID_STAR ptr)
637 {
638 SLang_Ref_Type *ref;
639
640 (void) type;
641 ref = *(SLang_Ref_Type **) ptr;
642 if (ref->string != NULL)
643 return ref->string (ref->data);
644 return SLmake_string ("Ref_Type");
645 }
646
ref_dereference(SLtype unused,VOID_STAR ptr)647 static int ref_dereference (SLtype unused, VOID_STAR ptr)
648 {
649 (void) unused;
650 return _pSLang_dereference_ref (*(SLang_Ref_Type **) ptr);
651 }
652
ref_cmp(SLtype type,VOID_STAR a,VOID_STAR b,int * c)653 static int ref_cmp (SLtype type, VOID_STAR a, VOID_STAR b, int *c)
654 {
655 SLang_Ref_Type *ra, *rb;
656
657 (void) type;
658
659 ra = *(SLang_Ref_Type **)a;
660 rb = *(SLang_Ref_Type **)b;
661
662 if (ra == NULL)
663 {
664 if (rb == NULL) *c = 0;
665 else *c = -1;
666 return 0;
667 }
668 if (rb == NULL)
669 {
670 *c = 1;
671 return 0;
672 }
673 if (ra->sizeof_data != rb->sizeof_data)
674 {
675 *c = (int)ra->sizeof_data - (int)rb->sizeof_data;
676 return 0;
677 }
678
679 *c = memcmp (ra->data, rb->data, ra->sizeof_data);
680 return 0;
681 }
682
683 /* NULL is permitted here */
SLang_push_function(SLang_Name_Type * nt)684 int SLang_push_function (SLang_Name_Type *nt)
685 {
686 return _pSLang_push_nt_as_ref (nt);
687 }
688
SLang_pop_function(void)689 SLang_Name_Type *SLang_pop_function (void)
690 {
691 SLang_Ref_Type *ref;
692 SLang_Name_Type *f;
693
694 if (SLang_peek_at_stack () == SLANG_STRING_TYPE)
695 {
696 char *name;
697
698 if (-1 == SLang_pop_slstring (&name))
699 return NULL;
700
701 if (NULL == (f = SLang_get_function (name)))
702 {
703 _pSLang_verror (SL_UNDEFINED_NAME, "Function %s does not exist", name);
704 SLang_free_slstring (name);
705 return NULL;
706 }
707 SLang_free_slstring (name);
708 return f;
709 }
710
711 if (-1 == SLang_pop_ref (&ref))
712 return NULL;
713
714 f = SLang_get_fun_from_ref (ref);
715 SLang_free_ref (ref);
716 return f;
717 }
718
719 /* This is a placeholder for version 3 --- NULL assumed to be ok */
SLang_free_function(SLang_Name_Type * f)720 void SLang_free_function (SLang_Name_Type *f)
721 {
722 (void) f;
723 }
724
SLang_copy_function(SLang_Name_Type * f)725 SLang_Name_Type *SLang_copy_function (SLang_Name_Type *f)
726 {
727 /* Add ref-count here */
728 return f;
729 }
730
731 /* NULL type */
SLang_push_null(void)732 int SLang_push_null (void)
733 {
734 return SLclass_push_ptr_obj (SLANG_NULL_TYPE, NULL);
735 }
736
SLang_pop_null(void)737 int SLang_pop_null (void)
738 {
739 SLang_Object_Type obj;
740 return _pSLang_pop_object_of_type (SLANG_NULL_TYPE, &obj, 0);
741 }
742
null_push(SLtype unused,VOID_STAR ptr_unused)743 static int null_push (SLtype unused, VOID_STAR ptr_unused)
744 {
745 (void) unused; (void) ptr_unused;
746 return SLang_push_null ();
747 }
748
null_pop(SLtype type,VOID_STAR ptr)749 static int null_pop (SLtype type, VOID_STAR ptr)
750 {
751 (void) type;
752
753 if (-1 == SLang_pop_null ())
754 return -1;
755
756 *(char **) ptr = NULL;
757 return 0;
758 }
759
null_dereference(SLtype unused,VOID_STAR ptr)760 static int null_dereference (SLtype unused, VOID_STAR ptr)
761 {
762 (void) unused; (void) ptr;
763 return SLang_push_null ();
764 }
765
766 /* Implement foreach (NULL) using (whatever) to do nothing. This is useful
767 * because suppose that X is a list but is NULL in some situations. Then
768 * when it is NULL, we want foreach(X) to do nothing.
769 */
770 static SLang_Foreach_Context_Type *
null_foreach_open(SLtype type,unsigned int num)771 null_foreach_open (SLtype type, unsigned int num)
772 {
773 (void) type;
774 SLdo_pop_n (num + 1);
775 return (SLang_Foreach_Context_Type *)1;
776 }
777
null_foreach_close(SLtype type,SLang_Foreach_Context_Type * c)778 static void null_foreach_close (SLtype type, SLang_Foreach_Context_Type *c)
779 {
780 (void) type;
781 (void) c;
782 }
783
null_foreach(SLtype type,SLang_Foreach_Context_Type * c)784 static int null_foreach (SLtype type, SLang_Foreach_Context_Type *c)
785 {
786 (void) type;
787 (void) c;
788 return 0;
789 }
790
null_to_bool(SLtype type,int * t)791 static int null_to_bool (SLtype type, int *t)
792 {
793 (void) type;
794 *t = 0;
795 return SLang_pop_null ();
796 }
797
798 /* AnyType */
_pSLanytype_typecast(SLtype a_type,VOID_STAR ap,SLuindex_Type na,SLtype b_type,VOID_STAR bp)799 int _pSLanytype_typecast (SLtype a_type, VOID_STAR ap, SLuindex_Type na,
800 SLtype b_type, VOID_STAR bp)
801 {
802 SLang_Class_Type *cl;
803 SLang_Any_Type **any;
804 SLuindex_Type i;
805 size_t sizeof_type;
806
807 (void) b_type;
808
809 any = (SLang_Any_Type **) bp;
810
811 cl = _pSLclass_get_class (a_type);
812 sizeof_type = cl->cl_sizeof_type;
813
814 for (i = 0; i < na; i++)
815 {
816 if ((-1 == (*cl->cl_apush) (a_type, ap))
817 || (-1 == SLang_pop_anytype (&any[i])))
818 {
819 while (i != 0)
820 {
821 i--;
822 SLang_free_anytype (any[i]);
823 any[i] = NULL;
824 }
825 return -1;
826 }
827 ap = (VOID_STAR)((char *)ap + sizeof_type);
828 }
829
830 return 1;
831 }
832
SLang_pop_anytype(SLang_Any_Type ** any)833 int SLang_pop_anytype (SLang_Any_Type **any)
834 {
835 SLang_Object_Type *obj;
836
837 if (NULL == (obj = (SLang_Object_Type *) SLmalloc (sizeof (SLang_Object_Type))))
838 {
839 *any = NULL;
840 return -1;
841 }
842
843 if (-1 == SLang_pop (obj))
844 {
845 *any = NULL;
846 SLfree ((char *) obj);
847 return -1;
848 }
849 *any = (SLang_Any_Type *)obj;
850 return 0;
851 }
852
853 /* This function will result in an object that is represented by the
854 * anytype object.
855 */
SLang_push_anytype(SLang_Any_Type * any)856 int SLang_push_anytype (SLang_Any_Type *any)
857 {
858 return _pSLpush_slang_obj ((SLang_Object_Type *)any);
859 }
860
861 /* After this call, the stack will contain an Any_Type object */
anytype_push(SLtype type,VOID_STAR ptr)862 static int anytype_push (SLtype type, VOID_STAR ptr)
863 {
864 SLang_Any_Type *obj;
865
866 /* Push the object onto the stack, then pop it back off into our anytype
867 * container. That way, any memory managing associated with the type
868 * will be performed automatically. Another way to think of it is that
869 * pushing an Any_Type onto the stack will create another copy of the
870 * object represented by it.
871 */
872 if (-1 == _pSLpush_slang_obj (*(SLang_Object_Type **)ptr))
873 return -1;
874
875 if (-1 == SLang_pop_anytype (&obj))
876 return -1;
877
878 /* There is no need to reference count the anytype objects since every
879 * push results in a new anytype container.
880 */
881 if (-1 == SLclass_push_ptr_obj (type, (VOID_STAR) obj))
882 {
883 SLang_free_anytype (obj);
884 return -1;
885 }
886
887 return 0;
888 }
889
anytype_destroy(SLtype type,VOID_STAR ptr)890 static void anytype_destroy (SLtype type, VOID_STAR ptr)
891 {
892 SLang_Object_Type *obj;
893
894 (void) type;
895 obj = *(SLang_Object_Type **)ptr;
896 SLang_free_object (obj);
897 SLfree ((char *) obj);
898 }
899
SLang_free_anytype(SLang_Any_Type * any)900 void SLang_free_anytype (SLang_Any_Type *any)
901 {
902 if (any != NULL)
903 anytype_destroy (SLANG_ANY_TYPE, (VOID_STAR) &any);
904 }
905
anytype_dereference(SLtype unused,VOID_STAR ptr)906 static int anytype_dereference (SLtype unused, VOID_STAR ptr)
907 {
908 (void) unused;
909 return _pSLpush_slang_obj (*(SLang_Object_Type **) ptr);
910 }
911
912 #if 0
913 /* This function performs a deref since we may want the symmetry
914 * a = Any_Type[1]; a[x] = "foo"; bar = a[x]; ==> bar == "foo"
915 * That is, we do not want bar to be an Any_Type.
916 *
917 * Unfortunately, this does not work because of the use of the transfer
918 * buffer by both slarray.c and sltypecast.c. I can work around that
919 * but I am not sure that I like typeof(Any_Type[0]) != Any_Type.
920 */
921 static int anytype_apush (SLtype type, VOID_STAR ptr)
922 {
923 (void) type;
924 return _pSLpush_slang_obj (*(SLang_Object_Type **)ptr);
925 }
926 #endif
927
928 /* SLANG_INTP_TYPE */
intp_push(SLtype unused,VOID_STAR ptr)929 static int intp_push (SLtype unused, VOID_STAR ptr)
930 {
931 int *addr;
932 (void) unused;
933 addr = *(int **)ptr;
934 if (addr == NULL)
935 return SLclass_push_int_obj (SLANG_INT_TYPE, 0);
936 return SLclass_push_int_obj (SLANG_INT_TYPE, *addr);
937 }
938
intp_pop(SLtype unused,VOID_STAR ptr)939 static int intp_pop (SLtype unused, VOID_STAR ptr)
940 {
941 int *addr;
942
943 (void) unused;
944 addr = *(int **)ptr;
945 if (addr == NULL)
946 {
947 SLang_verror (SL_VariableUninitialized_Error, "_IntegerP_Type: integer pointer address is NULL");
948 return -1;
949 }
950 return SLang_pop_integer (addr);
951 }
952
_pSLang_pop_wchar(SLwchar_Type * wcp)953 int _pSLang_pop_wchar (SLwchar_Type *wcp)
954 {
955 /* FIXME: This bit of code will be merged into the SLang_pop_wchar function
956 * for the next major version. Currently, SLang_pop_wchar is a macro.
957 */
958 if (SLang_peek_at_stack () == SLANG_CHAR_TYPE)
959 {
960 char ch;
961 if (-1 == SLang_pop_char (&ch))
962 return -1;
963 *wcp = (unsigned char)ch;
964 return 0;
965 }
966 return SLang_pop_wchar (wcp);
967 }
968
undefined_method(SLtype t,VOID_STAR p)969 static int undefined_method (SLtype t, VOID_STAR p)
970 {
971 (void) t; (void) p;
972 SLang_set_error (SL_VARIABLE_UNINITIALIZED);
973 return -1;
974 }
void_undefined_method(SLtype t,VOID_STAR p)975 static void void_undefined_method (SLtype t, VOID_STAR p)
976 {
977 (void) t; (void) p;
978 }
979
check_sizeof(size_t c,size_t s,const char * obj,int * errp)980 static void check_sizeof (size_t c, size_t s, const char *obj, int *errp)
981 {
982 if (c == s) return;
983 (void) fprintf (stderr, "C sizeof (%s) is %d, configured to be %d\n",
984 obj, (int)c, (int)s);
985 *errp = 1;
986 }
987
_pSLregister_types(void)988 int _pSLregister_types (void)
989 {
990 SLang_Class_Type *cl;
991 int err = 0;
992
993 check_sizeof (sizeof(short), SIZEOF_SHORT, "short", &err);
994 check_sizeof (sizeof(int), SIZEOF_INT, "int", &err);
995 check_sizeof (sizeof(long), SIZEOF_LONG, "long", &err);
996 check_sizeof (sizeof(float), SIZEOF_FLOAT, "float", &err);
997 check_sizeof (sizeof(double), SIZEOF_DOUBLE, "double", &err);
998 check_sizeof (sizeof(size_t), SIZEOF_SIZE_T, "size_t", &err);
999 check_sizeof (sizeof(off_t), SIZEOF_OFF_T, "off_t", &err);
1000
1001 if (err)
1002 SLang_exit_error ("S-Lang Library not built properly. Fix SIZEOF_* in config.h and recompile");
1003
1004 if (-1 == _pSLclass_init ())
1005 return -1;
1006
1007 /* Undefined Type */
1008 if (NULL == (cl = SLclass_allocate_class ("Undefined_Type")))
1009 return -1;
1010 (void) SLclass_set_push_function (cl, undefined_method);
1011 (void) SLclass_set_pop_function (cl, undefined_method);
1012 (void) SLclass_set_destroy_function (cl, void_undefined_method);
1013 if (-1 == SLclass_register_class (cl, SLANG_UNDEFINED_TYPE, sizeof (int),
1014 SLANG_CLASS_TYPE_SCALAR))
1015 return -1;
1016 /* Make Void_Type a synonym for Undefined_Type. Note that this does
1017 * not mean that Void_Type represents SLANG_VOID_TYPE. Void_Type is
1018 * used by array_map to indicate no array is to be created.
1019 */
1020 if (-1 == SLclass_create_synonym ("Void_Type", SLANG_UNDEFINED_TYPE))
1021 return -1;
1022
1023 if (-1 == _pSLarith_register_types ())
1024 return -1;
1025
1026 /* SLANG_INTP_TYPE -- not used within the interpreter */
1027 if (NULL == (cl = SLclass_allocate_class ("_IntegerP_Type")))
1028 return -1;
1029 (void) SLclass_set_push_function (cl, intp_push);
1030 (void) SLclass_set_pop_function (cl, intp_pop);
1031 if (-1 == SLclass_register_class (cl, SLANG_INTP_TYPE, sizeof (int *),
1032 SLANG_CLASS_TYPE_SCALAR))
1033 return -1;
1034
1035 /* String Type */
1036
1037 if (NULL == (cl = SLclass_allocate_class ("String_Type")))
1038 return -1;
1039 (void) SLclass_set_destroy_function (cl, string_destroy);
1040 (void) SLclass_set_push_function (cl, string_push);
1041 (void) SLclass_set_acopy_function (cl, string_acopy);
1042 cl->cl_foreach_open = _pSLbstring_foreach_open;
1043 cl->cl_foreach_close = _pSLbstring_foreach_close;
1044 cl->cl_foreach = _pSLbstring_foreach;
1045 cl->cl_cmp = string_cmp;
1046 if (-1 == SLclass_register_class (cl, SLANG_STRING_TYPE, sizeof (char *),
1047 SLANG_CLASS_TYPE_PTR))
1048 return -1;
1049
1050 /* ref Type */
1051 if (NULL == (cl = SLclass_allocate_class ("Ref_Type")))
1052 return -1;
1053 cl->cl_dereference = ref_dereference;
1054 cl->cl_push = ref_push;
1055 cl->cl_destroy = ref_destroy;
1056 cl->cl_string = ref_string;
1057 cl->cl_cmp = ref_cmp;
1058 if (-1 == SLclass_register_class (cl, SLANG_REF_TYPE,
1059 sizeof (SLang_Ref_Type *),
1060 SLANG_CLASS_TYPE_PTR))
1061 return -1;
1062
1063 /* NULL Type */
1064
1065 if (NULL == (cl = SLclass_allocate_class ("Null_Type")))
1066 return -1;
1067 cl->cl_dereference = null_dereference,
1068 cl->cl_push = null_push;
1069 cl->cl_pop = null_pop;
1070 cl->cl_foreach_open = null_foreach_open;
1071 cl->cl_foreach_close = null_foreach_close;
1072 cl->cl_foreach = null_foreach;
1073 cl->cl_to_bool = null_to_bool;
1074 if (-1 == SLclass_register_class (cl, SLANG_NULL_TYPE, sizeof (char *),
1075 SLANG_CLASS_TYPE_SCALAR))
1076 return -1;
1077
1078 /* AnyType */
1079 if (NULL == (cl = SLclass_allocate_class ("Any_Type")))
1080 return -1;
1081 (void) SLclass_set_push_function (cl, anytype_push);
1082 (void) SLclass_set_destroy_function (cl, anytype_destroy);
1083 #if 0
1084 (void) SLclass_set_apush_function (cl, anytype_apush);
1085 #endif
1086 cl->cl_dereference = anytype_dereference;
1087 if (-1 == SLclass_register_class (cl, SLANG_ANY_TYPE, sizeof (VOID_STAR),
1088 SLANG_CLASS_TYPE_PTR))
1089 return -1;
1090
1091 if (-1 == _pSLang_init_bstring ())
1092 return -1;
1093
1094 if ((-1 == SLclass_add_typecast (SLANG_STRING_TYPE, SLANG_INT_TYPE, string_to_int, 0))
1095 || (-1 == SLclass_add_binary_op (SLANG_STRING_TYPE, SLANG_STRING_TYPE, string_string_bin_op, string_string_bin_op_result)))
1096 return -1;
1097
1098 return 0;
1099 }
1100
1101