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 "slinclud.h"
00025
00026
00027 #include "slang.h"
00028 #include "_slang.h"
00029
00030 typedef struct Range_Array_Type SLarray_Range_Array_Type;
00031
00032 struct Range_Array_Type
00033 {
00034 SLindex_Type first_index;
00035 SLindex_Type last_index;
00036 SLindex_Type delta;
00037 int has_first_index;
00038 int has_last_index;
00039 int (*to_linear_fun) (SLang_Array_Type *, SLarray_Range_Array_Type *, VOID_STAR);
00040 };
00041
00042 static SLang_Array_Type *inline_implicit_int_array (SLindex_Type *, SLindex_Type *, SLindex_Type *);
00043
00044
00045 static int pop_array (SLang_Array_Type **at_ptr, int convert_scalar)
00046 {
00047 SLang_Array_Type *at;
00048 SLindex_Type one = 1;
00049 int type;
00050
00051 *at_ptr = NULL;
00052 type = SLang_peek_at_stack ();
00053
00054 switch (type)
00055 {
00056 case -1:
00057 return -1;
00058
00059 case SLANG_ARRAY_TYPE:
00060 return SLclass_pop_ptr_obj (SLANG_ARRAY_TYPE, (VOID_STAR *) at_ptr);
00061
00062 case SLANG_NULL_TYPE:
00063
00064
00065 default:
00066 if (convert_scalar == 0)
00067 {
00068 SLdo_pop ();
00069 SLang_verror (SL_TYPE_MISMATCH, "Context requires an array. Scalar not converted");
00070 return -1;
00071 }
00072 break;
00073 }
00074
00075 if (NULL == (at = SLang_create_array ((SLtype) type, 0, NULL, &one, 1)))
00076 return -1;
00077
00078 if (at->flags & SLARR_DATA_VALUE_IS_POINTER)
00079 {
00080
00081
00082
00083
00084 if (*(VOID_STAR *)at->data != NULL)
00085 {
00086 at->cl->cl_destroy ((SLtype) type, at->data);
00087 *(VOID_STAR *) at->data = NULL;
00088 }
00089 }
00090
00091 if (-1 == at->cl->cl_apop ((SLtype) type, at->data))
00092 {
00093 SLang_free_array (at);
00094 return -1;
00095 }
00096
00097 *at_ptr = at;
00098
00099 return 0;
00100 }
00101
00102 static VOID_STAR linear_get_data_addr (SLang_Array_Type *at, SLindex_Type *dims)
00103 {
00104 size_t ofs;
00105
00106 if (at->num_dims == 1)
00107 {
00108 if (*dims < 0)
00109 ofs = (size_t) (*dims + at->dims[0]);
00110 else
00111 ofs = (size_t)*dims;
00112 }
00113 else
00114 {
00115 unsigned int i;
00116 SLindex_Type *max_dims = at->dims;
00117 unsigned int num_dims = at->num_dims;
00118 ofs = 0;
00119 for (i = 0; i < num_dims; i++)
00120 {
00121 SLindex_Type d = dims[i];
00122
00123 if (d < 0)
00124 d = d + max_dims[i];
00125
00126 ofs = ofs * (size_t)max_dims [i] + (size_t) d;
00127 }
00128 }
00129 if (ofs >= at->num_elements)
00130 {
00131 SLang_set_error (SL_Index_Error);
00132 return NULL;
00133 }
00134 return (VOID_STAR) ((char *)at->data + (ofs * at->sizeof_type));
00135 }
00136
00137 _INLINE_
00138 static VOID_STAR get_data_addr (SLang_Array_Type *at, SLindex_Type *dims)
00139 {
00140 VOID_STAR data;
00141
00142 data = at->data;
00143 if (data == NULL)
00144 {
00145 SLang_verror (SL_UNKNOWN_ERROR, "Array has no data");
00146 return NULL;
00147 }
00148
00149 data = (*at->index_fun) (at, dims);
00150
00151 if (data == NULL)
00152 {
00153 SLang_verror (SL_UNKNOWN_ERROR, "Unable to access array element");
00154 return NULL;
00155 }
00156
00157 return data;
00158 }
00159
00160 void _pSLarray_free_array_elements (SLang_Class_Type *cl, VOID_STAR s, SLuindex_Type num)
00161 {
00162 size_t sizeof_type;
00163 void (*f) (SLtype, VOID_STAR);
00164 char *p;
00165 SLtype type;
00166
00167 if ((cl->cl_class_type == SLANG_CLASS_TYPE_SCALAR)
00168 || (cl->cl_class_type == SLANG_CLASS_TYPE_VECTOR))
00169 return;
00170
00171 f = cl->cl_destroy;
00172 sizeof_type = cl->cl_sizeof_type;
00173 type = cl->cl_data_type;
00174
00175 p = (char *) s;
00176 while (num != 0)
00177 {
00178 if (NULL != *(VOID_STAR *)p)
00179 {
00180 (*f) (type, (VOID_STAR)p);
00181 *(VOID_STAR *) p = NULL;
00182 }
00183 p += sizeof_type;
00184 num--;
00185 }
00186 }
00187
00188 static int destroy_element (SLang_Array_Type *at,
00189 SLindex_Type *dims,
00190 VOID_STAR data)
00191 {
00192 data = get_data_addr (at, dims);
00193 if (data == NULL)
00194 return -1;
00195
00196
00197
00198
00199
00200 if (NULL != *(VOID_STAR *)data)
00201 {
00202 (*at->cl->cl_destroy) (at->data_type, data);
00203 *(VOID_STAR *) data = NULL;
00204 }
00205 return 0;
00206 }
00207
00208
00209
00210
00211 static int new_object_element (SLang_Array_Type *at,
00212 SLindex_Type *dims,
00213 VOID_STAR data)
00214 {
00215 data = get_data_addr (at, dims);
00216 if (data == NULL)
00217 return -1;
00218
00219 return (*at->cl->cl_init_array_object) (at->data_type, data);
00220 }
00221
00222 int _pSLarray_next_index (SLindex_Type *dims, SLindex_Type *max_dims, unsigned int num_dims)
00223 {
00224 while (num_dims)
00225 {
00226 SLindex_Type dims_i;
00227
00228 num_dims--;
00229
00230 dims_i = dims [num_dims] + 1;
00231 if (dims_i < (int) max_dims [num_dims])
00232 {
00233 dims [num_dims] = dims_i;
00234 return 0;
00235 }
00236 dims [num_dims] = 0;
00237 }
00238
00239 return -1;
00240 }
00241
00242 static int do_method_for_all_elements (SLang_Array_Type *at,
00243 int (*method)(SLang_Array_Type *,
00244 SLindex_Type *,
00245 VOID_STAR),
00246 VOID_STAR client_data)
00247 {
00248 SLindex_Type dims [SLARRAY_MAX_DIMS];
00249 SLindex_Type *max_dims;
00250 unsigned int num_dims;
00251
00252 if (at->num_elements == 0)
00253 return 0;
00254
00255 max_dims = at->dims;
00256 num_dims = at->num_dims;
00257
00258 SLMEMSET((char *)dims, 0, sizeof(dims));
00259
00260 do
00261 {
00262 if (-1 == (*method) (at, dims, client_data))
00263 return -1;
00264 }
00265 while (0 == _pSLarray_next_index (dims, max_dims, num_dims));
00266
00267 return 0;
00268 }
00269
00270 void SLang_free_array (SLang_Array_Type *at)
00271 {
00272 unsigned int flags;
00273
00274 if (at == NULL) return;
00275
00276 if (at->num_refs > 1)
00277 {
00278 at->num_refs -= 1;
00279 return;
00280 }
00281
00282 flags = at->flags;
00283
00284 if (flags & SLARR_DATA_VALUE_IS_INTRINSIC)
00285 return;
00286
00287 if (flags & SLARR_DATA_VALUE_IS_POINTER)
00288 (void) do_method_for_all_elements (at, destroy_element, NULL);
00289
00290 if (at->free_fun != NULL)
00291 at->free_fun (at);
00292 else
00293 SLfree ((char *) at->data);
00294
00295 SLfree ((char *) at);
00296 }
00297
00298 SLang_Array_Type *
00299 SLang_create_array1 (SLtype type, int read_only, VOID_STAR data,
00300 SLindex_Type *dims, unsigned int num_dims, int no_init)
00301 {
00302 SLang_Class_Type *cl;
00303 SLang_Array_Type *at;
00304 SLuindex_Type i, num_elements;
00305 size_t sizeof_type;
00306 size_t size;
00307
00308 if (num_dims > SLARRAY_MAX_DIMS)
00309 {
00310 SLang_verror (SL_NOT_IMPLEMENTED, "%u dimensional arrays are not supported", num_dims);
00311 return NULL;
00312 }
00313
00314 for (i = 0; i < num_dims; i++)
00315 {
00316 if (dims[i] < 0)
00317 {
00318 SLang_verror (SL_INVALID_PARM, "Size of array dim %u is less than 0", i);
00319 return NULL;
00320 }
00321 }
00322
00323 cl = _pSLclass_get_class (type);
00324
00325 at = (SLang_Array_Type *) SLmalloc (sizeof(SLang_Array_Type));
00326 if (at == NULL)
00327 return NULL;
00328
00329 memset ((char*) at, 0, sizeof(SLang_Array_Type));
00330
00331 at->data_type = type;
00332 at->cl = cl;
00333 at->num_dims = num_dims;
00334 at->num_refs = 1;
00335
00336 if (read_only) at->flags = SLARR_DATA_VALUE_IS_READ_ONLY;
00337
00338 if ((cl->cl_class_type != SLANG_CLASS_TYPE_SCALAR)
00339 && (cl->cl_class_type != SLANG_CLASS_TYPE_VECTOR))
00340 at->flags |= SLARR_DATA_VALUE_IS_POINTER;
00341
00342 num_elements = 1;
00343 for (i = 0; i < num_dims; i++)
00344 {
00345 at->dims[i] = dims[i];
00346 num_elements = dims[i] * num_elements;
00347 }
00348
00349
00350
00351
00352 while (i < SLARRAY_MAX_DIMS)
00353 at->dims[i++] = 1;
00354
00355 at->num_elements = num_elements;
00356 at->index_fun = linear_get_data_addr;
00357 at->sizeof_type = sizeof_type = cl->cl_sizeof_type;
00358
00359 if (data != NULL)
00360 {
00361 at->data = data;
00362 return at;
00363 }
00364
00365 size = (size_t) (num_elements * sizeof_type);
00366 if (size/sizeof_type != num_elements)
00367 {
00368 SLang_verror (SL_INVALID_PARM, "Unable to create array of the desired size");
00369 SLang_free_array (at);
00370 return NULL;
00371 }
00372
00373 if (size == 0) size = 1;
00374
00375 if (NULL == (data = (VOID_STAR) SLmalloc (size)))
00376 {
00377 SLang_free_array (at);
00378 return NULL;
00379 }
00380
00381 at->data = data;
00382
00383 if ((no_init == 0) || (at->flags & SLARR_DATA_VALUE_IS_POINTER))
00384 memset ((char *) data, 0, size);
00385
00386 if ((no_init == 0)
00387 && (cl->cl_init_array_object != NULL)
00388 && (-1 == do_method_for_all_elements (at, new_object_element, NULL)))
00389 {
00390 SLang_free_array (at);
00391 return NULL;
00392 }
00393
00394 return at;
00395 }
00396
00397 SLang_Array_Type *
00398 SLang_create_array (SLtype type, int read_only, VOID_STAR data,
00399 SLindex_Type *dims, unsigned int num_dims)
00400 {
00401 return SLang_create_array1 (type, read_only, data, dims, num_dims, 0);
00402 }
00403
00404 int SLang_add_intrinsic_array (char *name,
00405 SLtype type,
00406 int read_only,
00407 VOID_STAR data,
00408 unsigned int num_dims, ...)
00409 {
00410 va_list ap;
00411 unsigned int i;
00412 SLindex_Type dims[SLARRAY_MAX_DIMS];
00413 SLang_Array_Type *at;
00414
00415 if ((num_dims > SLARRAY_MAX_DIMS)
00416 || (name == NULL)
00417 || (data == NULL))
00418 {
00419 SLang_verror (SL_INVALID_PARM, "Unable to create intrinsic array");
00420 return -1;
00421 }
00422
00423 va_start (ap, num_dims);
00424 for (i = 0; i < num_dims; i++)
00425 dims [i] = va_arg (ap, int);
00426 va_end (ap);
00427
00428 at = SLang_create_array (type, read_only, data, dims, num_dims);
00429 if (at == NULL)
00430 return -1;
00431 at->flags |= SLARR_DATA_VALUE_IS_INTRINSIC;
00432
00433
00434
00435
00436 if (-1 == SLadd_intrinsic_variable (name, (VOID_STAR) at, SLANG_ARRAY_TYPE, 1))
00437 {
00438 SLang_free_array (at);
00439 return -1;
00440 }
00441 return 0;
00442 }
00443
00444 static int pop_array_indices (SLindex_Type *dims, unsigned int num_dims)
00445 {
00446 unsigned int n;
00447 int i;
00448
00449 if (num_dims > SLARRAY_MAX_DIMS)
00450 {
00451 SLang_verror (SL_INVALID_PARM, "Array size not supported");
00452 return -1;
00453 }
00454
00455 n = num_dims;
00456 while (n != 0)
00457 {
00458 n--;
00459 if (-1 == SLang_pop_integer (&i))
00460 return -1;
00461
00462 dims[n] = i;
00463 }
00464
00465 return 0;
00466 }
00467
00468 int SLang_push_array (SLang_Array_Type *at, int free_flag)
00469 {
00470 if (at == NULL)
00471 return SLang_push_null ();
00472
00473 at->num_refs += 1;
00474
00475 if (0 == SLclass_push_ptr_obj (SLANG_ARRAY_TYPE, (VOID_STAR) at))
00476 {
00477 if (free_flag)
00478 SLang_free_array (at);
00479 return 0;
00480 }
00481
00482 at->num_refs -= 1;
00483
00484 if (free_flag) SLang_free_array (at);
00485 return -1;
00486 }
00487
00488
00489
00490 static int push_create_new_array (unsigned int num_dims)
00491 {
00492 SLang_Array_Type *at;
00493 SLtype type;
00494 SLindex_Type dims [SLARRAY_MAX_DIMS];
00495 int (*anew) (SLtype, unsigned int);
00496
00497 if (-1 == SLang_pop_datatype (&type))
00498 return -1;
00499
00500 anew = (_pSLclass_get_class (type))->cl_anew;
00501 if (anew != NULL)
00502 return (*anew) (type, num_dims);
00503
00504 if (-1 == pop_array_indices (dims, num_dims))
00505 return -1;
00506
00507 if (NULL == (at = SLang_create_array (type, 0, NULL, dims, num_dims)))
00508 return -1;
00509
00510 return SLang_push_array (at, 1);
00511 }
00512
00513 static int push_element_at_addr (SLang_Array_Type *at,
00514 VOID_STAR data, int allow_null)
00515 {
00516 SLang_Class_Type *cl;
00517
00518 cl = at->cl;
00519 if ((at->flags & SLARR_DATA_VALUE_IS_POINTER)
00520 && (*(VOID_STAR *) data == NULL))
00521 {
00522 if (allow_null)
00523 return SLang_push_null ();
00524
00525 SLang_verror (SL_VARIABLE_UNINITIALIZED,
00526 "%s array has uninitialized element", cl->cl_name);
00527 return -1;
00528 }
00529
00530 return (*cl->cl_apush)(at->data_type, data);
00531 }
00532
00533 static int coerse_array_to_linear (SLang_Array_Type *at)
00534 {
00535 SLarray_Range_Array_Type *range;
00536 VOID_STAR vdata;
00537 SLuindex_Type imax;
00538
00539
00540
00541
00542 if (0 == (at->flags & SLARR_DATA_VALUE_IS_RANGE))
00543 return 0;
00544
00545 range = (SLarray_Range_Array_Type *) at->data;
00546 if ((range->has_last_index == 0) || (range->has_first_index == 0))
00547 {
00548 SLang_verror (SL_INVALID_PARM, "Invalid context for a range array of indeterminate size");
00549 return -1;
00550 }
00551
00552 imax = at->num_elements;
00553 vdata = (VOID_STAR) SLmalloc ((imax + 1) * at->sizeof_type);
00554 if (vdata == NULL)
00555 return -1;
00556 (void) (*range->to_linear_fun)(at, range, vdata);
00557 SLfree ((char *) range);
00558 at->data = (VOID_STAR) vdata;
00559 at->flags &= ~SLARR_DATA_VALUE_IS_RANGE;
00560 at->index_fun = linear_get_data_addr;
00561 return 0;
00562 }
00563
00564 static void
00565 free_index_objects (SLang_Object_Type *index_objs, unsigned int num_indices)
00566 {
00567 unsigned int i;
00568 SLang_Object_Type *obj;
00569
00570 for (i = 0; i < num_indices; i++)
00571 {
00572 obj = index_objs + i;
00573 if (obj->data_type != 0)
00574 SLang_free_object (obj);
00575 }
00576 }
00577
00578 static int
00579 pop_indices (SLang_Array_Type *at_to_index,
00580 SLang_Object_Type *index_objs, unsigned int num_indices,
00581 int *is_index_array)
00582 {
00583 unsigned int i;
00584
00585 memset((char *) index_objs, 0, num_indices * sizeof (SLang_Object_Type));
00586
00587 *is_index_array = 0;
00588
00589 if (num_indices != at_to_index->num_dims)
00590 {
00591 if (num_indices != 1)
00592 {
00593 SLang_verror (SL_INVALID_PARM, "wrong number of indices for array");
00594 return -1;
00595 }
00596 }
00597
00598 i = num_indices;
00599 while (i != 0)
00600 {
00601 SLang_Object_Type *obj;
00602 SLtype data_type;
00603 SLang_Array_Type *at;
00604
00605 i--;
00606 obj = index_objs + i;
00607 if (SLANG_ARRAY_TYPE != _pSLang_peek_at_stack2 (&data_type))
00608 {
00609 if (-1 == _pSLang_pop_object_of_type (SLANG_ARRAY_INDEX_TYPE, obj, 0))
00610 goto return_error;
00611
00612 continue;
00613 }
00614 if (data_type != SLANG_ARRAY_INDEX_TYPE)
00615 {
00616 if (-1 == SLclass_typecast (SLANG_ARRAY_INDEX_TYPE, 1, 1))
00617 return -1;
00618 }
00619 if (-1 == SLang_pop (obj))
00620 goto return_error;
00621
00622 at = obj->v.array_val;
00623 if (at->flags & SLARR_DATA_VALUE_IS_RANGE)
00624 {
00625 SLarray_Range_Array_Type *r = (SLarray_Range_Array_Type *) at->data;
00626 if ((r->has_last_index == 0) || (r->has_first_index == 0))
00627 {
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 SLang_Array_Type *new_at;
00639 SLindex_Type first_index, last_index;
00640 SLindex_Type delta = r->delta;
00641 SLindex_Type n;
00642
00643 if (num_indices == 1)
00644 n = (SLindex_Type)at_to_index->num_elements;
00645 else
00646 n = at_to_index->dims[i];
00647
00648 if (r->has_first_index)
00649 {
00650
00651 first_index = r->first_index;
00652 if (first_index < 0) first_index += n;
00653 if (delta > 0) last_index = n-1; else last_index = 0;
00654 }
00655 else if (r->has_last_index)
00656 {
00657
00658 if (delta > 0) first_index = 0; else first_index = n-1;
00659 last_index = r->last_index;
00660 if (last_index < 0)
00661 last_index += n;
00662 }
00663 else
00664 {
00665
00666 if (delta > 0)
00667 {
00668 first_index = 0;
00669 last_index = n - 1;
00670 }
00671 else
00672 {
00673 first_index = n-1;
00674 last_index = 0;
00675 }
00676 }
00677
00678 if (NULL == (new_at = inline_implicit_int_array (&first_index, &last_index, &delta)))
00679 goto return_error;
00680
00681 SLang_free_array (at);
00682 obj->v.array_val = new_at;
00683 }
00684 }
00685 if (num_indices == 1)
00686 {
00687 *is_index_array = 1;
00688 return 0;
00689 }
00690 }
00691 return 0;
00692
00693 return_error:
00694 free_index_objects (index_objs, num_indices);
00695 return -1;
00696 }
00697
00698 static void do_index_error (SLindex_Type i, SLindex_Type indx, SLindex_Type dim)
00699 {
00700 SLang_verror (SL_Index_Error, "Array index %u (value=%ld) out of allowed range 0<=index<%ld",
00701 i, (long)indx, (long)dim);
00702 }
00703
00704 static int
00705 transfer_n_elements (SLang_Array_Type *at, VOID_STAR dest_data, VOID_STAR src_data,
00706 size_t sizeof_type, SLuindex_Type n, int is_ptr)
00707 {
00708 SLtype data_type;
00709 SLang_Class_Type *cl;
00710
00711 if (is_ptr == 0)
00712 {
00713 SLMEMCPY ((char *) dest_data, (char *)src_data, n * sizeof_type);
00714 return 0;
00715 }
00716
00717 data_type = at->data_type;
00718 cl = at->cl;
00719
00720 while (n != 0)
00721 {
00722 if (*(VOID_STAR *)dest_data != NULL)
00723 {
00724 (*cl->cl_destroy) (data_type, dest_data);
00725 *(VOID_STAR *) dest_data = NULL;
00726 }
00727
00728 if (*(VOID_STAR *) src_data == NULL)
00729 *(VOID_STAR *) dest_data = NULL;
00730 else
00731 {
00732 if (-1 == (*cl->cl_acopy) (data_type, src_data, dest_data))
00733
00734 return -1;
00735 }
00736
00737 src_data = (VOID_STAR) ((char *)src_data + sizeof_type);
00738 dest_data = (VOID_STAR) ((char *)dest_data + sizeof_type);
00739
00740 n--;
00741 }
00742
00743 return 0;
00744 }
00745
00746 _INLINE_
00747 int
00748 _pSLarray_aget_transfer_elem (SLang_Array_Type *at, SLindex_Type *indices,
00749 VOID_STAR new_data, size_t sizeof_type, int is_ptr)
00750 {
00751 VOID_STAR at_data;
00752
00753
00754
00755
00756 if (NULL == (at_data = get_data_addr (at, indices)))
00757 return -1;
00758
00759 if (is_ptr == 0)
00760 {
00761 memcpy ((char *) new_data, (char *)at_data, sizeof_type);
00762 return 0;
00763 }
00764
00765 return transfer_n_elements (at, new_data, at_data, sizeof_type, 1, is_ptr);
00766 }
00767
00768
00769
00770
00771
00772 static int
00773 aget_from_index_array (SLang_Array_Type *at,
00774 SLang_Array_Type *ind_at)
00775 {
00776 SLang_Array_Type *new_at;
00777 SLindex_Type *indices, *indices_max, num_elements;
00778 unsigned char *new_data, *src_data;
00779 size_t sizeof_type;
00780 int is_ptr;
00781
00782 if (-1 == coerse_array_to_linear (at))
00783 return -1;
00784
00785 if (-1 == coerse_array_to_linear (ind_at))
00786 return -1;
00787
00788 if (NULL == (new_at = SLang_create_array (at->data_type, 0, NULL, ind_at->dims, ind_at->num_dims)))
00789 return -1;
00790
00791
00792 indices = (SLindex_Type *) ind_at->data;
00793 indices_max = indices + ind_at->num_elements;
00794
00795 src_data = (unsigned char *) at->data;
00796 new_data = (unsigned char *) new_at->data;
00797 num_elements = (SLindex_Type) at->num_elements;
00798 sizeof_type = new_at->sizeof_type;
00799 is_ptr = (new_at->flags & SLARR_DATA_VALUE_IS_POINTER);
00800
00801 while (indices < indices_max)
00802 {
00803 size_t offset;
00804 SLindex_Type i = *indices;
00805
00806 if (i < 0)
00807 {
00808 i += num_elements;
00809 if (i < 0)
00810 i = num_elements;
00811 }
00812 if (i >= num_elements)
00813 {
00814 SLang_set_error (SL_Index_Error);
00815 SLang_free_array (new_at);
00816 return -1;
00817 }
00818
00819 offset = sizeof_type * (SLuindex_Type)i;
00820 if (-1 == transfer_n_elements (at, (VOID_STAR) new_data,
00821 (VOID_STAR) (src_data + offset),
00822 sizeof_type, 1, is_ptr))
00823 {
00824 SLang_free_array (new_at);
00825 return -1;
00826 }
00827
00828 new_data += sizeof_type;
00829 indices++;
00830 }
00831
00832 return SLang_push_array (new_at, 1);
00833 }
00834
00835
00836
00837
00838
00839 static int
00840 convert_nasty_index_objs (SLang_Array_Type *at,
00841 SLang_Object_Type *index_objs,
00842 unsigned int num_indices,
00843 SLindex_Type **index_data,
00844 SLindex_Type *range_buf, SLindex_Type *range_delta_buf,
00845 SLindex_Type *max_dims,
00846 unsigned int *num_elements,
00847 int *is_array, int is_dim_array[SLARRAY_MAX_DIMS])
00848 {
00849 unsigned int i, total_num_elements;
00850 SLang_Array_Type *ind_at;
00851
00852 if (num_indices != at->num_dims)
00853 {
00854 SLang_verror (SL_INVALID_PARM, "Array requires %u indices", at->num_dims);
00855 return -1;
00856 }
00857
00858 *is_array = 0;
00859 total_num_elements = 1;
00860 for (i = 0; i < num_indices; i++)
00861 {
00862 SLang_Object_Type *obj = index_objs + i;
00863 range_delta_buf [i] = 0;
00864
00865 if (obj->data_type == SLANG_ARRAY_INDEX_TYPE)
00866 {
00867 range_buf [i] = obj->v.index_val;
00868 max_dims [i] = 1;
00869 index_data[i] = range_buf + i;
00870 is_dim_array[i] = 0;
00871 }
00872 #if SLANG_ARRAY_INDEX_TYPE != SLANG_INT_TYPE
00873 else if (obj->data_type == SLANG_INT_TYPE)
00874 {
00875 range_buf [i] = obj->v.int_val;
00876 max_dims [i] = 1;
00877 index_data[i] = range_buf + i;
00878 is_dim_array[i] = 0;
00879 }
00880 #endif
00881 else
00882 {
00883 *is_array = 1;
00884 is_dim_array[i] = 1;
00885 ind_at = obj->v.array_val;
00886
00887 if (ind_at->flags & SLARR_DATA_VALUE_IS_RANGE)
00888 {
00889 SLarray_Range_Array_Type *r;
00890
00891 r = (SLarray_Range_Array_Type *) ind_at->data;
00892 range_buf[i] = r->first_index;
00893 range_delta_buf [i] = r->delta;
00894 max_dims[i] = (SLindex_Type) ind_at->num_elements;
00895 }
00896 else
00897 {
00898 index_data [i] = (SLindex_Type *) ind_at->data;
00899 max_dims[i] = (SLindex_Type) ind_at->num_elements;
00900 }
00901 }
00902
00903 total_num_elements = total_num_elements * max_dims[i];
00904 }
00905
00906 *num_elements = total_num_elements;
00907 return 0;
00908 }
00909
00910
00911
00912
00913
00914
00915 static int
00916 aget_from_indices (SLang_Array_Type *at,
00917 SLang_Object_Type *index_objs, unsigned int num_indices)
00918 {
00919 SLindex_Type *index_data [SLARRAY_MAX_DIMS];
00920 SLindex_Type range_buf [SLARRAY_MAX_DIMS];
00921 SLindex_Type range_delta_buf [SLARRAY_MAX_DIMS];
00922 SLindex_Type max_dims [SLARRAY_MAX_DIMS];
00923 unsigned int i, num_elements;
00924 SLang_Array_Type *new_at;
00925 SLindex_Type map_indices[SLARRAY_MAX_DIMS];
00926 SLindex_Type indices [SLARRAY_MAX_DIMS];
00927 SLindex_Type *at_dims;
00928 size_t sizeof_type;
00929 int is_ptr, ret, is_array;
00930 char *new_data;
00931 SLang_Class_Type *cl;
00932 int is_dim_array[SLARRAY_MAX_DIMS];
00933
00934 if (-1 == convert_nasty_index_objs (at, index_objs, num_indices,
00935 index_data, range_buf, range_delta_buf,
00936 max_dims, &num_elements, &is_array,
00937 is_dim_array))
00938 return -1;
00939
00940 is_ptr = (at->flags & SLARR_DATA_VALUE_IS_POINTER);
00941 sizeof_type = at->sizeof_type;
00942
00943 cl = _pSLclass_get_class (at->data_type);
00944
00945 if ((is_array == 0) && (num_elements == 1))
00946 {
00947 new_data = (char *)cl->cl_transfer_buf;
00948 memset (new_data, 0, sizeof_type);
00949 new_at = NULL;
00950 }
00951 else
00952 {
00953 SLindex_Type i_num_elements = (SLindex_Type)num_elements;
00954
00955 new_at = SLang_create_array (at->data_type, 0, NULL, &i_num_elements, 1);
00956 if (NULL == new_at)
00957 return -1;
00958 if (num_elements == 0)
00959 return SLang_push_array (new_at, 1);
00960
00961 new_data = (char *)new_at->data;
00962 }
00963
00964 at_dims = at->dims;
00965 memset ((char *) map_indices, 0, sizeof(map_indices));
00966 while (1)
00967 {
00968 for (i = 0; i < num_indices; i++)
00969 {
00970 SLindex_Type j = map_indices[i];
00971 SLindex_Type indx;
00972
00973 if (0 != range_delta_buf[i])
00974 indx = range_buf[i] + j * range_delta_buf[i];
00975 else
00976 indx = index_data [i][j];
00977
00978 if (indx < 0)
00979 indx += at_dims[i];
00980
00981 if ((indx < 0) || (indx >= at_dims[i]))
00982 {
00983 do_index_error (i, indx, at_dims[i]);
00984 SLang_free_array (new_at);
00985 return -1;
00986 }
00987 indices[i] = indx;
00988 }
00989
00990 if (-1 == _pSLarray_aget_transfer_elem (at, indices, (VOID_STAR)new_data, sizeof_type, is_ptr))
00991 {
00992 SLang_free_array (new_at);
00993 return -1;
00994 }
00995 new_data += sizeof_type;
00996 if (num_indices == 1)
00997 {
00998 map_indices[0]++;
00999 if (map_indices[0] == max_dims[0])
01000 break;
01001 }
01002 else if (0 != _pSLarray_next_index (map_indices, max_dims, num_indices))
01003 break;
01004 }
01005
01006 if (new_at != NULL)
01007 {
01008 int num_dims = 0;
01009
01010 for (i = 0; i < num_indices; i++)
01011 {
01012 if (is_dim_array[i])
01013 {
01014 new_at->dims[num_dims] = max_dims[i];
01015 num_dims++;
01016 }
01017 }
01018
01019 if (num_dims != 0) new_at->num_dims = num_dims;
01020 return SLang_push_array (new_at, 1);
01021 }
01022
01023
01024 new_data -= sizeof_type;
01025 if (is_ptr && (*(VOID_STAR *)new_data == NULL))
01026 ret = SLang_push_null ();
01027 else
01028 {
01029 ret = (*cl->cl_apush) (at->data_type, (VOID_STAR)new_data);
01030 (*cl->cl_adestroy) (at->data_type, (VOID_STAR)new_data);
01031 }
01032
01033 return ret;
01034 }
01035
01036 static int push_string_as_array (unsigned char *s, unsigned int len)
01037 {
01038 SLindex_Type ilen;
01039 SLang_Array_Type *at;
01040
01041 ilen = (SLindex_Type) len;
01042
01043 at = SLang_create_array (SLANG_UCHAR_TYPE, 0, NULL, &ilen, 1);
01044 if (at == NULL)
01045 return -1;
01046
01047 memcpy ((char *)at->data, (char *)s, len);
01048 return SLang_push_array (at, 1);
01049 }
01050
01051 static int pop_array_as_string (char **sp)
01052 {
01053 SLang_Array_Type *at;
01054 int ret;
01055
01056 *sp = NULL;
01057
01058 if (-1 == SLang_pop_array_of_type (&at, SLANG_UCHAR_TYPE))
01059 return -1;
01060
01061 ret = 0;
01062
01063 if (NULL == (*sp = SLang_create_nslstring ((char *) at->data, at->num_elements)))
01064 ret = -1;
01065
01066 SLang_free_array (at);
01067 return ret;
01068 }
01069
01070 static int pop_array_as_bstring (SLang_BString_Type **bs)
01071 {
01072 SLang_Array_Type *at;
01073 int ret;
01074
01075 *bs = NULL;
01076
01077 if (-1 == SLang_pop_array_of_type (&at, SLANG_UCHAR_TYPE))
01078 return -1;
01079
01080 ret = 0;
01081
01082 if (NULL == (*bs = SLbstring_create ((unsigned char *) at->data, at->num_elements)))
01083 ret = -1;
01084
01085 SLang_free_array (at);
01086 return ret;
01087 }
01088
01089 static int aget_from_array (unsigned int num_indices)
01090 {
01091 SLang_Array_Type *at;
01092 SLang_Object_Type index_objs [SLARRAY_MAX_DIMS];
01093 int ret;
01094 int is_index_array;
01095 unsigned int i;
01096
01097 if (num_indices > SLARRAY_MAX_DIMS)
01098 {
01099 SLang_verror (SL_INVALID_PARM, "Number of dims must be less than %d", SLARRAY_MAX_DIMS);
01100 return -1;
01101 }
01102
01103 if (-1 == pop_array (&at, 1))
01104 return -1;
01105
01106 if (-1 == pop_indices (at, index_objs, num_indices, &is_index_array))
01107 {
01108 SLang_free_array (at);
01109 return -1;
01110 }
01111
01112 if (is_index_array == 0)
01113 {
01114 #if SLANG_OPTIMIZE_FOR_SPEED
01115 if ((num_indices == 1) && (index_objs[0].data_type == SLANG_INT_TYPE)
01116 && (0 == (at->flags & (SLARR_DATA_VALUE_IS_RANGE|SLARR_DATA_VALUE_IS_POINTER)))
01117 && (1 == at->num_dims)
01118 && (at->data != NULL))
01119 {
01120 SLindex_Type ofs = index_objs[0].v.int_val;
01121 if (ofs < 0) ofs += at->dims[0];
01122 if ((ofs >= at->dims[0]) || (ofs < 0))
01123 ret = aget_from_indices (at, index_objs, num_indices);
01124 else switch (at->data_type)
01125 {
01126 case SLANG_CHAR_TYPE:
01127 ret = SLclass_push_char_obj (SLANG_CHAR_TYPE, *((char *)at->data + ofs));
01128 break;
01129 case SLANG_INT_TYPE:
01130 ret = SLclass_push_int_obj (SLANG_INT_TYPE, *((int *)at->data + ofs));
01131 break;
01132 #if SLANG_HAS_FLOAT
01133 case SLANG_DOUBLE_TYPE:
01134 ret = SLclass_push_double_obj (SLANG_DOUBLE_TYPE, *((double *)at->data + ofs));
01135 break;
01136 #endif
01137 default:
01138 ret = aget_from_indices (at, index_objs, num_indices);
01139 }
01140 }
01141 else
01142 #endif
01143 ret = aget_from_indices (at, index_objs, num_indices);
01144 }
01145 else
01146 ret = aget_from_index_array (at, index_objs[0].v.array_val);
01147
01148 SLang_free_array (at);
01149 for (i = 0; i < num_indices; i++)
01150 SLang_free_object (index_objs + i);
01151
01152 return ret;
01153 }
01154
01155 static int push_string_element (SLtype type, unsigned char *s, unsigned int len)
01156 {
01157 int i;
01158
01159 if (SLang_peek_at_stack () == SLANG_ARRAY_TYPE)
01160 {
01161 char *str;
01162
01163
01164 if (-1 == push_string_as_array (s, len))
01165 return -1;
01166
01167 if (-1 == aget_from_array (1))
01168 return -1;
01169
01170 if (type == SLANG_BSTRING_TYPE)
01171 {
01172 SLang_BString_Type *bs;
01173 int ret;
01174
01175 if (-1 == pop_array_as_bstring (&bs))
01176 return -1;
01177
01178 ret = SLang_push_bstring (bs);
01179 SLbstring_free (bs);
01180 return ret;
01181 }
01182
01183 if (-1 == pop_array_as_string (&str))
01184 return -1;
01185 return _pSLang_push_slstring (str);
01186 }
01187
01188 if (-1 == SLang_pop_integer (&i))
01189 return -1;
01190
01191 if (i < 0) i = i + (int)len;
01192 if ((unsigned int) i > len)
01193 i = len;
01194
01195 return SLang_push_uchar (s[(unsigned int)i]);
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207 int _pSLarray_aget1 (unsigned int num_indices)
01208 {
01209 int type;
01210 int (*aget_fun) (SLtype, unsigned int);
01211
01212 type = SLang_peek_at_stack ();
01213 switch (type)
01214 {
01215 case -1:
01216 return -1;
01217
01218 case SLANG_DATATYPE_TYPE:
01219 return push_create_new_array (num_indices);
01220
01221 case SLANG_BSTRING_TYPE:
01222 if (1 == num_indices)
01223 {
01224 SLang_BString_Type *bs;
01225 int ret;
01226 unsigned int len;
01227 unsigned char *s;
01228
01229 if (-1 == SLang_pop_bstring (&bs))
01230 return -1;
01231
01232 if (NULL == (s = SLbstring_get_pointer (bs, &len)))
01233 ret = -1;
01234 else
01235 ret = push_string_element (type, s, len);
01236
01237 SLbstring_free (bs);
01238 return ret;
01239 }
01240 break;
01241
01242 case SLANG_STRING_TYPE:
01243 if (1 == num_indices)
01244 {
01245 char *s;
01246 int ret;
01247
01248 if (-1 == SLang_pop_slstring (&s))
01249 return -1;
01250
01251 ret = push_string_element (type, (unsigned char *)s, _pSLstring_bytelen (s));
01252 _pSLang_free_slstring (s);
01253 return ret;
01254 }
01255 break;
01256
01257 case SLANG_ARRAY_TYPE:
01258 break;
01259
01260 case SLANG_ASSOC_TYPE:
01261 return _pSLassoc_aget (type, num_indices);
01262
01263 default:
01264 aget_fun = _pSLclass_get_class (type)->cl_aget;
01265 if (NULL != aget_fun)
01266 return (*aget_fun) (type, num_indices);
01267 }
01268
01269 return aget_from_array (num_indices);
01270 }
01271
01272 int _pSLarray_aget (void)
01273 {
01274 return _pSLarray_aget1 ((unsigned int)(SLang_Num_Function_Args-1));
01275 }
01276
01277
01278
01279 _INLINE_ int
01280 _pSLarray_aput_transfer_elem (SLang_Array_Type *at, SLindex_Type *indices,
01281 VOID_STAR data_to_put, size_t sizeof_type, int is_ptr)
01282 {
01283 VOID_STAR at_data;
01284
01285
01286
01287
01288
01289 if (NULL == (at_data = get_data_addr (at, indices)))
01290 return -1;
01291
01292 if (is_ptr == 0)
01293 {
01294 memcpy ((char *) at_data, (char *)data_to_put, sizeof_type);
01295 return 0;
01296 }
01297
01298 return transfer_n_elements (at, at_data, data_to_put, sizeof_type, 1, is_ptr);
01299 }
01300
01301 static int
01302 aput_get_data_to_put (SLang_Class_Type *cl, unsigned int num_elements, int allow_array,
01303 SLang_Array_Type **at_ptr, char **data_to_put, SLuindex_Type *data_increment)
01304 {
01305 SLtype data_type;
01306 int type;
01307 SLang_Array_Type *at;
01308
01309 *at_ptr = NULL;
01310
01311 data_type = cl->cl_data_type;
01312 type = SLang_peek_at_stack ();
01313
01314 if ((SLtype)type != data_type)
01315 {
01316 if ((type != SLANG_NULL_TYPE)
01317 || ((cl->cl_class_type != SLANG_CLASS_TYPE_PTR)
01318 && (cl->cl_class_type != SLANG_CLASS_TYPE_MMT)))
01319 {
01320 if (-1 == SLclass_typecast (data_type, 1, allow_array))
01321 return -1;
01322 }
01323 else
01324 {
01325
01326 *data_increment = 0;
01327 *data_to_put = (char *) cl->cl_transfer_buf;
01328 *((char **)cl->cl_transfer_buf) = NULL;
01329 return SLdo_pop ();
01330 }
01331 }
01332
01333 if (allow_array
01334 && (data_type != SLANG_ARRAY_TYPE)
01335 && (data_type != SLANG_ANY_TYPE)
01336 && (SLANG_ARRAY_TYPE == SLang_peek_at_stack ()))
01337 {
01338 if (-1 == SLang_pop_array (&at, 0))
01339 return -1;
01340
01341 if ((at->num_elements != num_elements)
01342 #if 0
01343 || (at->num_dims != 1)
01344 #endif
01345 )
01346 {
01347 SLang_verror (SL_Index_Error, "Array size is inappropriate for use with index-array");
01348 SLang_free_array (at);
01349 return -1;
01350 }
01351
01352 *data_to_put = (char *) at->data;
01353 *data_increment = at->sizeof_type;
01354 *at_ptr = at;
01355 return 0;
01356 }
01357
01358 *data_increment = 0;
01359 *data_to_put = (char *) cl->cl_transfer_buf;
01360
01361 if (-1 == (*cl->cl_apop)(data_type, (VOID_STAR) *data_to_put))
01362 return -1;
01363
01364 return 0;
01365 }
01366
01367 static int
01368 aput_from_indices (SLang_Array_Type *at,
01369 SLang_Object_Type *index_objs, unsigned int num_indices)
01370 {
01371 SLindex_Type *index_data [SLARRAY_MAX_DIMS];
01372 SLindex_Type range_buf [SLARRAY_MAX_DIMS];
01373 SLindex_Type range_delta_buf [SLARRAY_MAX_DIMS];
01374 SLindex_Type max_dims [SLARRAY_MAX_DIMS];
01375 SLindex_Type *at_dims;
01376 unsigned int i, num_elements;
01377 SLa