00001
00032
00033
00034
00035
00036 #include "linden_common.h"
00037 #include "lscript_alloc.h"
00038 #include "llrand.h"
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 void reset_hp_to_safe_spot(const U8 *buffer)
00064 {
00065 set_register((U8 *)buffer, LREG_HP, TOP_OF_MEMORY);
00066 }
00067
00068
00069 BOOL lsa_create_heap(U8 *heap_start, S32 size)
00070 {
00071 LLScriptAllocEntry entry(size, LST_NULL);
00072
00073 S32 position = 0;
00074
00075 alloc_entry2bytestream(heap_start, position, entry);
00076
00077 return TRUE;
00078 }
00079
00080 S32 lsa_heap_top(U8 *heap_start, S32 maxtop)
00081 {
00082 S32 offset = 0;
00083 LLScriptAllocEntry entry;
00084 bytestream2alloc_entry(entry, heap_start, offset);
00085
00086 while (offset + entry.mSize < maxtop)
00087 {
00088 offset += entry.mSize;
00089 bytestream2alloc_entry(entry, heap_start, offset);
00090 }
00091 return offset + entry.mSize;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 S32 lsa_heap_add_data(U8 *buffer, LLScriptLibData *data, S32 heapsize, BOOL b_delete)
00116 {
00117 if (get_register(buffer, LREG_FR))
00118 return 1;
00119 LLScriptAllocEntry entry, nextentry;
00120 S32 hr = get_register(buffer, LREG_HR);
00121 S32 hp = get_register(buffer, LREG_HP);
00122 S32 current_offset, next_offset, offset = hr;
00123 S32 size = 0;
00124
00125 switch(data->mType)
00126 {
00127 case LST_INTEGER:
00128 size = 4;
00129 break;
00130 case LST_FLOATINGPOINT:
00131 size = 4;
00132 break;
00133 case LST_KEY:
00134 size = (S32)strlen(data->mKey) + 1;
00135 break;
00136 case LST_STRING:
00137 size = (S32)strlen(data->mString) + 1;
00138 break;
00139 case LST_LIST:
00140
00141 size = 4 + 4*data->getListLength();
00142 if (data->checkForMultipleLists())
00143 {
00144 set_fault(buffer, LSRF_NESTING_LISTS);
00145 }
00146 break;
00147 case LST_VECTOR:
00148 size = 12;
00149 break;
00150 case LST_QUATERNION:
00151 size = 16;
00152 break;
00153 default:
00154 break;
00155 }
00156
00157 current_offset = offset;
00158 bytestream2alloc_entry(entry, buffer, offset);
00159
00160 do
00161 {
00162 hp = get_register(buffer, LREG_HP);
00163 if (!entry.mType)
00164 {
00165 if (entry.mSize >= size + SIZEOF_SCRIPT_ALLOC_ENTRY + 4)
00166 {
00167 offset = current_offset;
00168 lsa_split_block(buffer, offset, size, entry);
00169 entry.mType = data->mType;
00170 entry.mSize = size;
00171 entry.mReferenceCount = 1;
00172 offset = current_offset;
00173 alloc_entry2bytestream(buffer, offset, entry);
00174 lsa_insert_data(buffer, offset, data, entry, heapsize);
00175 hp = get_register(buffer, LREG_HP);
00176 S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;
00177 if (new_hp >= hr + heapsize)
00178 {
00179 break;
00180 }
00181 if (new_hp > hp)
00182 {
00183 set_register(buffer, LREG_HP, new_hp);
00184 hp = get_register(buffer, LREG_HP);
00185 }
00186 if (b_delete)
00187 delete data;
00188
00189
00190 if (current_offset <= hp)
00191 return current_offset - hr + 1;
00192 else
00193 return hp - hr + 1;
00194 }
00195 else if (entry.mSize >= size)
00196 {
00197 entry.mType = data->mType;
00198 entry.mReferenceCount = 1;
00199 offset = current_offset;
00200 alloc_entry2bytestream(buffer, offset, entry);
00201 lsa_insert_data(buffer, offset, data, entry, heapsize);
00202 hp = get_register(buffer, LREG_HP);
00203 if (b_delete)
00204 delete data;
00205
00206
00207 return current_offset - hr + 1;
00208 }
00209 }
00210 offset += entry.mSize;
00211 if (offset < hr + heapsize)
00212 {
00213 next_offset = offset;
00214 bytestream2alloc_entry(nextentry, buffer, offset);
00215 if (!nextentry.mType && !entry.mType)
00216 {
00217 entry.mSize += nextentry.mSize + SIZEOF_SCRIPT_ALLOC_ENTRY;
00218 offset = current_offset;
00219 alloc_entry2bytestream(buffer, offset, entry);
00220 }
00221 else
00222 {
00223 current_offset = next_offset;
00224 entry = nextentry;
00225 }
00226
00227
00228 S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;
00229
00230
00231 if (new_hp >= hr + heapsize)
00232 {
00233 break;
00234 }
00235 if (new_hp > hp)
00236 {
00237 set_register(buffer, LREG_HP, new_hp);
00238 hp = get_register(buffer, LREG_HP);
00239 }
00240 }
00241 else
00242 {
00243 break;
00244 }
00245 } while (1);
00246 set_fault(buffer, LSRF_STACK_HEAP_COLLISION);
00247 reset_hp_to_safe_spot(buffer);
00248 if (b_delete)
00249 delete data;
00250 return 0;
00251 }
00252
00253
00254
00255
00256
00257
00258 void lsa_split_block(U8 *buffer, S32 &offset, S32 size, LLScriptAllocEntry &entry)
00259 {
00260 if (get_register(buffer, LREG_FR))
00261 return;
00262 LLScriptAllocEntry newentry;
00263
00264 newentry.mSize = entry.mSize - SIZEOF_SCRIPT_ALLOC_ENTRY - size;
00265 entry.mSize -= newentry.mSize + SIZEOF_SCRIPT_ALLOC_ENTRY;
00266
00267 alloc_entry2bytestream(buffer, offset, entry);
00268 S32 orig_offset = offset + size;
00269 alloc_entry2bytestream(buffer, orig_offset, newentry);
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 void lsa_insert_data(U8 *buffer, S32 &offset, LLScriptLibData *data, LLScriptAllocEntry &entry, S32 heapsize)
00283 {
00284 if (get_register(buffer, LREG_FR))
00285 return;
00286 if (data->mType != LST_LIST)
00287 {
00288 switch(data->mType)
00289 {
00290 case LST_INTEGER:
00291 integer2bytestream(buffer, offset, data->mInteger);
00292 break;
00293 case LST_FLOATINGPOINT:
00294 float2bytestream(buffer, offset, data->mFP);
00295 break;
00296 case LST_KEY:
00297 char2bytestream(buffer, offset, data->mKey);
00298 break;
00299 case LST_STRING:
00300 char2bytestream(buffer, offset, data->mString);
00301 break;
00302 case LST_VECTOR:
00303 vector2bytestream(buffer, offset, data->mVec);
00304 break;
00305 case LST_QUATERNION:
00306 quaternion2bytestream(buffer, offset, data->mQuat);
00307 break;
00308 default:
00309 break;
00310 }
00311 }
00312 else
00313 {
00314
00315 integer2bytestream(buffer, offset, data->getListLength());
00316 data = data->mListp;
00317 while(data)
00318 {
00319
00320 S32 address = lsa_heap_add_data(buffer, data, heapsize, FALSE);
00321 integer2bytestream(buffer, offset, address);
00322 data = data->mListp;
00323 }
00324 }
00325 }
00326
00327 S32 lsa_create_data_block(U8 **buffer, LLScriptLibData *data, S32 base_offset)
00328 {
00329 S32 offset = 0;
00330 S32 size = 0;
00331
00332 LLScriptAllocEntry entry;
00333
00334 if (!data)
00335 {
00336 entry.mType = LST_NULL;
00337 entry.mReferenceCount = 0;
00338 entry.mSize = MAX_HEAP_SIZE;
00339 size = SIZEOF_SCRIPT_ALLOC_ENTRY;
00340 *buffer = new U8[size];
00341 alloc_entry2bytestream(*buffer, offset, entry);
00342 return size;
00343 }
00344
00345 entry.mType = data->mType;
00346 entry.mReferenceCount = 1;
00347
00348 if (data->mType != LST_LIST)
00349 {
00350 if ( (data->mType != LST_STRING)
00351 &&(data->mType != LST_KEY))
00352 {
00353 size = LSCRIPTDataSize[data->mType];
00354 }
00355 else
00356 {
00357 if (data->mType == LST_STRING)
00358 {
00359 if (data->mString)
00360 {
00361 size = (S32)strlen(data->mString) + 1;
00362 }
00363 else
00364 {
00365 size = 1;
00366 }
00367 }
00368 if (data->mType == LST_KEY)
00369 {
00370 if (data->mKey)
00371 {
00372 size = (S32)strlen(data->mKey) + 1;
00373 }
00374 else
00375 {
00376 size = 1;
00377 }
00378 }
00379 }
00380 entry.mSize = size;
00381 size += SIZEOF_SCRIPT_ALLOC_ENTRY;
00382 *buffer = new U8[size];
00383 alloc_entry2bytestream(*buffer, offset, entry);
00384
00385 switch(data->mType)
00386 {
00387 case LST_INTEGER:
00388 integer2bytestream(*buffer, offset, data->mInteger);
00389 break;
00390 case LST_FLOATINGPOINT:
00391 float2bytestream(*buffer, offset, data->mFP);
00392 break;
00393 case LST_KEY:
00394 if (data->mKey)
00395 char2bytestream(*buffer, offset, data->mKey);
00396 else
00397 byte2bytestream(*buffer, offset, 0);
00398 break;
00399 case LST_STRING:
00400 if (data->mString)
00401 char2bytestream(*buffer, offset, data->mString);
00402 else
00403 byte2bytestream(*buffer, offset, 0);
00404 break;
00405 case LST_VECTOR:
00406 vector2bytestream(*buffer, offset, data->mVec);
00407 break;
00408 case LST_QUATERNION:
00409 quaternion2bytestream(*buffer, offset, data->mQuat);
00410 break;
00411 default:
00412 break;
00413 }
00414 }
00415 else
00416 {
00417 U8 *listbuf;
00418 S32 length = data->getListLength();
00419 size = 4 * length + 4;
00420 entry.mSize = size;
00421
00422 size += SIZEOF_SCRIPT_ALLOC_ENTRY;
00423 *buffer = new U8[size];
00424
00425 alloc_entry2bytestream(*buffer, offset, entry);
00426
00427 integer2bytestream(*buffer, offset, length);
00428 data = data->mListp;
00429 while(data)
00430 {
00431
00432
00433 integer2bytestream(*buffer, offset, size + base_offset + 1);
00434
00435 S32 listsize = lsa_create_data_block(&listbuf, data, base_offset + size);
00436 if (listsize)
00437 {
00438 U8 *tbuff = new U8[size + listsize];
00439 if (tbuff == NULL)
00440 {
00441 llerrs << "Memory Allocation Failed" << llendl;
00442 }
00443 memcpy(tbuff, *buffer, size);
00444 memcpy(tbuff + size, listbuf, listsize);
00445 size += listsize;
00446 delete [] *buffer;
00447 delete [] listbuf;
00448 *buffer = tbuff;
00449 }
00450 data = data->mListp;
00451 }
00452 }
00453 return size;
00454 }
00455
00456
00457
00458
00459 void lsa_increase_ref_count(U8 *buffer, S32 offset)
00460 {
00461 if (get_register(buffer, LREG_FR))
00462 return;
00463
00464
00465 offset += get_register(buffer, LREG_HR) - 1;
00466 if ( (offset < get_register(buffer, LREG_HR))
00467 ||(offset >= get_register(buffer, LREG_HP)))
00468 {
00469 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
00470 return;
00471 }
00472 S32 orig_offset = offset;
00473 LLScriptAllocEntry entry;
00474 bytestream2alloc_entry(entry, buffer, offset);
00475
00476 entry.mReferenceCount++;
00477
00478 alloc_entry2bytestream(buffer, orig_offset, entry);
00479 }
00480
00481
00482
00483
00484
00485
00486 void lsa_decrease_ref_count(U8 *buffer, S32 offset)
00487 {
00488 if (get_register(buffer, LREG_FR))
00489 return;
00490
00491
00492 offset += get_register(buffer, LREG_HR) - 1;
00493 if ( (offset < get_register(buffer, LREG_HR))
00494 ||(offset >= get_register(buffer, LREG_HP)))
00495 {
00496 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
00497 return;
00498 }
00499 S32 orig_offset = offset;
00500 LLScriptAllocEntry entry;
00501 bytestream2alloc_entry(entry, buffer, offset);
00502
00503 entry.mReferenceCount--;
00504
00505 if (entry.mReferenceCount < 0)
00506 {
00507 entry.mReferenceCount = 0;
00508 set_fault(buffer, LSRF_HEAP_ERROR);
00509 }
00510 else if (!entry.mReferenceCount)
00511 {
00512 if (entry.mType == LST_LIST)
00513 {
00514 S32 i, num = bytestream2integer(buffer, offset);
00515 for (i = 0; i < num; i++)
00516 {
00517 S32 list_offset = bytestream2integer(buffer, offset);
00518 lsa_decrease_ref_count(buffer, list_offset);
00519 }
00520 }
00521 entry.mType = LST_NULL;
00522 }
00523
00524 alloc_entry2bytestream(buffer, orig_offset, entry);
00525 }
00526
00527 char gLSAStringRead[16384];
00528
00529
00530 LLScriptLibData *lsa_get_data(U8 *buffer, S32 &offset, BOOL b_dec_ref)
00531 {
00532 if (get_register(buffer, LREG_FR))
00533 return (new LLScriptLibData);
00534 S32 orig_offset = offset;
00535
00536
00537 offset += get_register(buffer, LREG_HR) - 1;
00538 if ( (offset < get_register(buffer, LREG_HR))
00539 ||(offset >= get_register(buffer, LREG_HP)))
00540 {
00541 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
00542 return (new LLScriptLibData);
00543 }
00544 LLScriptAllocEntry entry;
00545 bytestream2alloc_entry(entry, buffer, offset);
00546
00547 LLScriptLibData *retval = new LLScriptLibData;
00548
00549 if (!entry.mType)
00550 {
00551 set_fault(buffer, LSRF_HEAP_ERROR);
00552 return retval;
00553 }
00554
00555 retval->mType = (LSCRIPTType)entry.mType;
00556 if (entry.mType != LST_LIST)
00557 {
00558 switch(entry.mType)
00559 {
00560 case LST_INTEGER:
00561 retval->mInteger = bytestream2integer(buffer, offset);
00562 break;
00563 case LST_FLOATINGPOINT:
00564 retval->mFP = bytestream2float(buffer, offset);
00565 break;
00566 case LST_KEY:
00567 bytestream2char(gLSAStringRead, buffer, offset);
00568 retval->mKey = new char[strlen(gLSAStringRead) + 1];
00569 strcpy(retval->mKey, gLSAStringRead);
00570 break;
00571 case LST_STRING:
00572 bytestream2char(gLSAStringRead, buffer, offset);
00573 retval->mString = new char[strlen(gLSAStringRead) + 1];
00574 strcpy(retval->mString, gLSAStringRead);
00575 break;
00576 case LST_VECTOR:
00577 bytestream2vector(retval->mVec, buffer, offset);
00578 break;
00579 case LST_QUATERNION:
00580 bytestream2quaternion(retval->mQuat, buffer, offset);
00581 break;
00582 default:
00583 break;
00584 }
00585 }
00586 else
00587 {
00588
00589 S32 i, length = bytestream2integer(buffer, offset);
00590 LLScriptLibData *tip = retval;
00591
00592 for (i = 0; i < length; i++)
00593 {
00594 S32 address = bytestream2integer(buffer, offset);
00595 tip->mListp = lsa_get_data(buffer, address, FALSE);
00596 tip = tip->mListp;
00597 }
00598 }
00599 if (retval->checkForMultipleLists())
00600 {
00601 set_fault(buffer, LSRF_NESTING_LISTS);
00602 }
00603 if (b_dec_ref)
00604 {
00605 lsa_decrease_ref_count(buffer, orig_offset);
00606 }
00607 return retval;
00608 }
00609
00610 LLScriptLibData *lsa_get_list_ptr(U8 *buffer, S32 &offset, BOOL b_dec_ref)
00611 {
00612 if (get_register(buffer, LREG_FR))
00613 return (new LLScriptLibData);
00614 S32 orig_offset = offset;
00615
00616
00617 offset += get_register(buffer, LREG_HR) - 1;
00618 if ( (offset < get_register(buffer, LREG_HR))
00619 ||(offset >= get_register(buffer, LREG_HP)))
00620 {
00621 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
00622 return (new LLScriptLibData);
00623 }
00624 LLScriptAllocEntry entry;
00625 bytestream2alloc_entry(entry, buffer, offset);
00626
00627 if (!entry.mType)
00628 {
00629 set_fault(buffer, LSRF_HEAP_ERROR);
00630 return NULL;
00631 }
00632
00633 LLScriptLibData base, *tip = &base;
00634
00635 if (entry.mType != LST_LIST)
00636 {
00637 return NULL;
00638 }
00639 else
00640 {
00641
00642 S32 i, length = bytestream2integer(buffer, offset);
00643
00644 for (i = 0; i < length; i++)
00645 {
00646 S32 address = bytestream2integer(buffer, offset);
00647 tip->mListp = lsa_get_data(buffer, address, FALSE);
00648 tip = tip->mListp;
00649 }
00650 }
00651 if (b_dec_ref)
00652 {
00653 lsa_decrease_ref_count(buffer, orig_offset);
00654 }
00655 tip = base.mListp;
00656 base.mListp = NULL;
00657 return tip;
00658 }
00659
00660 S32 lsa_cat_strings(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize)
00661 {
00662 if (get_register(buffer, LREG_FR))
00663 return 0;
00664 LLScriptLibData *string1;
00665 LLScriptLibData *string2;
00666 if (offset1 != offset2)
00667 {
00668 string1 = lsa_get_data(buffer, offset1, TRUE);
00669 string2 = lsa_get_data(buffer, offset2, TRUE);
00670 }
00671 else
00672 {
00673 string1 = lsa_get_data(buffer, offset1, TRUE);
00674 string2 = lsa_get_data(buffer, offset2, TRUE);
00675 }
00676
00677 if ( (!string1)
00678 ||(!string2))
00679 {
00680 set_fault(buffer, LSRF_HEAP_ERROR);
00681 delete string1;
00682 delete string2;
00683 return 0;
00684 }
00685
00686 char *test1 = NULL, *test2 = NULL;
00687
00688 if (string1->mType == LST_STRING)
00689 {
00690 test1 = string1->mString;
00691 }
00692 else if (string1->mType == LST_KEY)
00693 {
00694 test1 = string1->mKey;
00695 }
00696 if (string2->mType == LST_STRING)
00697 {
00698 test2 = string2->mString;
00699 }
00700 else if (string2->mType == LST_KEY)
00701 {
00702 test2 = string2->mKey;
00703 }
00704
00705 if ( (!test1)
00706 ||(!test2))
00707 {
00708 set_fault(buffer, LSRF_HEAP_ERROR);
00709 delete string1;
00710 delete string2;
00711 return 0;
00712 }
00713
00714 S32 size = (S32)strlen(test1) + (S32)strlen(test2) + 1;
00715
00716 LLScriptLibData *string3 = new LLScriptLibData;
00717 string3->mType = LST_STRING;
00718 string3->mString = new char[size];
00719 strcpy(string3->mString, test1);
00720 strcat(string3->mString, test2);
00721
00722 delete string1;
00723 delete string2;
00724
00725 return lsa_heap_add_data(buffer, string3, heapsize, TRUE);
00726 }
00727
00728 S32 lsa_cmp_strings(U8 *buffer, S32 offset1, S32 offset2)
00729 {
00730 if (get_register(buffer, LREG_FR))
00731 return 0;
00732 LLScriptLibData *string1;
00733 LLScriptLibData *string2;
00734
00735 string1 = lsa_get_data(buffer, offset1, TRUE);
00736 string2 = lsa_get_data(buffer, offset2, TRUE);
00737
00738 if ( (!string1)
00739 ||(!string2))
00740 {
00741 set_fault(buffer, LSRF_HEAP_ERROR);
00742 delete string1;
00743 delete string2;
00744 return 0;
00745 }
00746
00747 char *test1 = NULL, *test2 = NULL;
00748
00749 if (string1->mType == LST_STRING)
00750 {
00751 test1 = string1->mString;
00752 }
00753 else if (string1->mType == LST_KEY)
00754 {
00755 test1 = string1->mKey;
00756 }
00757 if (string2->mType == LST_STRING)
00758 {
00759 test2 = string2->mString;
00760 }
00761 else if (string2->mType == LST_KEY)
00762 {
00763 test2 = string2->mKey;
00764 }
00765
00766 if ( (!test1)
00767 ||(!test2))
00768 {
00769 set_fault(buffer, LSRF_HEAP_ERROR);
00770 delete string1;
00771 delete string2;
00772 return 0;
00773 }
00774 S32 retval = strcmp(test1, test2);
00775
00776 delete string1;
00777 delete string2;
00778
00779 return retval;
00780 }
00781
00782 void lsa_print_heap(U8 *buffer)
00783 {
00784 S32 offset = get_register(buffer, LREG_HR);
00785 S32 readoffset;
00786 S32 ivalue;
00787 F32 fpvalue;
00788 LLVector3 vvalue;
00789 LLQuaternion qvalue;
00790 char string[4096];
00791
00792 LLScriptAllocEntry entry;
00793
00794 bytestream2alloc_entry(entry, buffer, offset);
00795
00796 printf("HP: [0x%X]\n", get_register(buffer, LREG_HP));
00797 printf("==========\n");
00798
00799 while (offset + entry.mSize < MAX_HEAP_SIZE)
00800 {
00801 printf("[0x%X] ", offset);
00802 printf("%s ", LSCRIPTTypeNames[entry.mType]);
00803 printf("Ref Count: %d ", entry.mReferenceCount);
00804 printf("Size: %d = ", entry.mSize);
00805
00806 readoffset = offset;
00807
00808 switch(entry.mType)
00809 {
00810 case LST_INTEGER:
00811 ivalue = bytestream2integer(buffer, readoffset);
00812 printf("%d\n", ivalue);
00813 break;
00814 case LST_FLOATINGPOINT:
00815 fpvalue = bytestream2float(buffer, readoffset);
00816 printf("%f\n", fpvalue);
00817 break;
00818 case LST_STRING:
00819 bytestream2char(string, buffer, readoffset);
00820 printf("%s\n", string);
00821 break;
00822 case LST_KEY:
00823 bytestream2char(string, buffer, readoffset);
00824 printf("%s\n", string);
00825 break;
00826 case LST_VECTOR:
00827 bytestream2vector(vvalue, buffer, readoffset);
00828 printf("< %f, %f, %f >\n", vvalue.mV[VX], vvalue.mV[VY], vvalue.mV[VZ]);
00829 break;
00830 case LST_QUATERNION:
00831 bytestream2quaternion(qvalue, buffer, readoffset);
00832 printf("< %f, %f, %f, %f >\n", qvalue.mQ[VX], qvalue.mQ[VY], qvalue.mQ[VZ], qvalue.mQ[VS]);
00833 break;
00834 case LST_LIST:
00835 ivalue = bytestream2integer(buffer, readoffset);
00836 printf("%d\n", ivalue);
00837 break;
00838 default:
00839 printf("\n");
00840 break;
00841 }
00842 offset += entry.mSize;
00843 bytestream2alloc_entry(entry, buffer, offset);
00844 }
00845 printf("[0x%X] ", offset);
00846 printf("%s ", LSCRIPTTypeNames[entry.mType]);
00847 printf("Ref Count: %d ", entry.mReferenceCount);
00848 printf("Size: %d\n", entry.mSize);
00849 printf("==========\n");
00850 }
00851
00852 void lsa_fprint_heap(U8 *buffer, FILE *fp)
00853 {
00854 S32 offset = get_register(buffer, LREG_HR);
00855 S32 readoffset;
00856 S32 ivalue;
00857 F32 fpvalue;
00858 LLVector3 vvalue;
00859 LLQuaternion qvalue;
00860 char string[4096];
00861
00862 LLScriptAllocEntry entry;
00863
00864 bytestream2alloc_entry(entry, buffer, offset);
00865
00866 while (offset + entry.mSize < MAX_HEAP_SIZE)
00867 {
00868 fprintf(fp, "[0x%X] ", offset);
00869 fprintf(fp, "%s ", LSCRIPTTypeNames[entry.mType]);
00870 fprintf(fp, "Ref Count: %d ", entry.mReferenceCount);
00871 fprintf(fp, "Size: %d = ", entry.mSize);
00872
00873 readoffset = offset;
00874
00875 switch(entry.mType)
00876 {
00877 case LST_INTEGER:
00878 ivalue = bytestream2integer(buffer, readoffset);
00879 fprintf(fp, "%d\n", ivalue);
00880 break;
00881 case LST_FLOATINGPOINT:
00882 fpvalue = bytestream2float(buffer, readoffset);
00883 fprintf(fp, "%f\n", fpvalue);
00884 break;
00885 case LST_STRING:
00886 bytestream2char(string, buffer, readoffset);
00887 fprintf(fp, "%s\n", string);
00888 break;
00889 case LST_KEY:
00890 bytestream2char(string, buffer, readoffset);
00891 fprintf(fp, "%s\n", string);
00892 break;
00893 case LST_VECTOR:
00894 bytestream2vector(vvalue, buffer, readoffset);
00895 fprintf(fp, "< %f, %f, %f >\n", vvalue.mV[VX], vvalue.mV[VY], vvalue.mV[VZ]);
00896 break;
00897 case LST_QUATERNION:
00898 bytestream2quaternion(qvalue, buffer, readoffset);
00899 fprintf(fp, "< %f, %f, %f, %f >\n", qvalue.mQ[VX], qvalue.mQ[VY], qvalue.mQ[VZ], qvalue.mQ[VS]);
00900 break;
00901 case LST_LIST:
00902 ivalue = bytestream2integer(buffer, readoffset);
00903 fprintf(fp, "%d\n", ivalue);
00904 break;
00905 default:
00906 fprintf(fp, "\n");
00907 break;
00908 }
00909 offset += entry.mSize;
00910 bytestream2alloc_entry(entry, buffer, offset);
00911 }
00912 fprintf(fp, "[0x%X] ", offset);
00913 fprintf(fp, "%s ", LSCRIPTTypeNames[entry.mType]);
00914 fprintf(fp, "Ref Count: %d ", entry.mReferenceCount);
00915 fprintf(fp, "Size: %d", entry.mSize);
00916 fprintf(fp, "\n");
00917 }
00918
00919 S32 lsa_cat_lists(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize)
00920 {
00921 if (get_register(buffer, LREG_FR))
00922 return 0;
00923 LLScriptLibData *list1;
00924 LLScriptLibData *list2;
00925 if (offset1 != offset2)
00926 {
00927 list1 = lsa_get_data(buffer, offset1, TRUE);
00928 list2 = lsa_get_data(buffer, offset2, TRUE);
00929 }
00930 else
00931 {
00932 list1 = lsa_get_data(buffer, offset1, TRUE);
00933 list2 = lsa_get_data(buffer, offset2, TRUE);
00934 }
00935
00936 if ( (!list1)
00937 ||(!list2))
00938 {
00939 set_fault(buffer, LSRF_HEAP_ERROR);
00940 delete list1;
00941 delete list2;
00942 return 0;
00943 }
00944
00945 if ( (list1->mType != LST_LIST)
00946 ||(list2->mType != LST_LIST))
00947 {
00948 set_fault(buffer, LSRF_HEAP_ERROR);
00949 delete list1;
00950 delete list2;
00951 return 0;
00952 }
00953
00954 LLScriptLibData *runner = list1;
00955
00956 while (runner->mListp)
00957 {
00958 runner = runner->mListp;
00959 }
00960
00961 runner->mListp = list2->mListp;
00962
00963 list2->mListp = NULL;
00964
00965 delete list2;
00966
00967 return lsa_heap_add_data(buffer, list1, heapsize, TRUE);
00968 }
00969
00970
00971 S32 lsa_cmp_lists(U8 *buffer, S32 offset1, S32 offset2)
00972 {
00973 if (get_register(buffer, LREG_FR))
00974 return 0;
00975 LLScriptLibData *list1;
00976 LLScriptLibData *list2;
00977 if (offset1 != offset2)
00978 {
00979 list1 = lsa_get_data(buffer, offset1, TRUE);
00980 list2 = lsa_get_data(buffer, offset2, TRUE);
00981 }
00982 else
00983 {
00984 list1 = lsa_get_data(buffer, offset1, FALSE);
00985 list2 = lsa_get_data(buffer, offset2, TRUE);
00986 }
00987
00988 if ( (!list1)
00989 ||(!list2))
00990 {
00991 set_fault(buffer, LSRF_HEAP_ERROR);
00992 delete list1;
00993 delete list2;
00994 return 0;
00995 }
00996
00997 if ( (list1->mType != LST_LIST)
00998 ||(list2->mType != LST_LIST))
00999 {
01000 set_fault(buffer, LSRF_HEAP_ERROR);
01001 delete list1;
01002 delete list2;
01003 return 0;
01004 }
01005
01006 S32 length1 = list1->getListLength();
01007 S32 length2 = list2->getListLength();
01008 delete list1;
01009 delete list2;
01010 return length1 - length2;
01011 }
01012
01013
01014 S32 lsa_preadd_lists(U8 *buffer, LLScriptLibData *data, S32 offset2, S32 heapsize)
01015 {
01016 if (get_register(buffer, LREG_FR))
01017 return 0;
01018 LLScriptLibData *list2 = lsa_get_data(buffer, offset2, TRUE);
01019
01020 if (!list2)
01021 {
01022 set_fault(buffer, LSRF_HEAP_ERROR);
01023 delete list2;
01024 return 0;
01025 }
01026
01027 if (list2->mType != LST_LIST)
01028 {
01029 set_fault(buffer, LSRF_HEAP_ERROR);
01030 delete list2;
01031 return 0;
01032 }
01033
01034 LLScriptLibData *runner = data->mListp;
01035
01036 while (runner->mListp)
01037 {
01038 runner = runner->mListp;
01039 }
01040
01041
01042 runner->mListp = list2->mListp;
01043 list2->mListp = data->mListp;
01044
01045 return lsa_heap_add_data(buffer, list2, heapsize, TRUE);
01046 }
01047
01048
01049 S32 lsa_postadd_lists(U8 *buffer, S32 offset1, LLScriptLibData *data, S32 heapsize)
01050 {
01051 if (get_register(buffer, LREG_FR))
01052 return 0;
01053 LLScriptLibData *list1 = lsa_get_data(buffer, offset1, TRUE);
01054
01055 if (!list1)
01056 {
01057 set_fault(buffer, LSRF_HEAP_ERROR);
01058 delete list1;
01059 return 0;
01060 }
01061
01062 if (list1->mType != LST_LIST)
01063 {
01064 set_fault(buffer, LSRF_HEAP_ERROR);
01065 delete list1;
01066 return 0;
01067 }
01068
01069 LLScriptLibData *runner = list1;
01070
01071 while (runner->mListp)
01072 {
01073 runner = runner->mListp;
01074 }
01075
01076 runner->mListp = data->mListp;
01077
01078 return lsa_heap_add_data(buffer, list1, heapsize, TRUE);
01079 }
01080
01081
01082 LLScriptLibData* lsa_randomize(LLScriptLibData* src, S32 stride)
01083 {
01084 S32 number = src->getListLength();
01085 if (number <= 0)
01086 {
01087 return NULL;
01088 }
01089 if (stride <= 0)
01090 {
01091 stride = 1;
01092 }
01093 if(number % stride)
01094 {
01095 LLScriptLibData* retval = src->mListp;
01096 src->mListp = NULL;
01097 return retval;
01098 }
01099 S32 buckets = number / stride;
01100
01101
01102 std::vector<LLScriptLibData*> sort_array;
01103 sort_array.reserve(number);
01104 LLScriptLibData* temp = src->mListp;
01105 while(temp)
01106 {
01107 sort_array.push_back(temp);
01108 temp = temp->mListp;
01109 }
01110
01111
01112
01113
01114 S32 index = 0;
01115 S32 ii = 0;
01116 for(; ii < number; ii += stride)
01117 {
01118 index = ll_rand(buckets) * stride;
01119 for(S32 jj = 0; jj < stride; ++jj)
01120 {
01121 std::swap(sort_array[ii + jj], sort_array[index + jj]);
01122 }
01123 }
01124
01125
01126 ii = 1;
01127 temp = sort_array[0];
01128 while (ii < number)
01129 {
01130 temp->mListp = sort_array[ii++];
01131 temp = temp->mListp;
01132 }
01133 temp->mListp = NULL;
01134
01135 src->mListp = NULL;
01136
01137 LLScriptLibData* ret_value = sort_array[0];
01138 return ret_value;
01139 }