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