aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/lscript/lscript_library/lscript_alloc.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/lscript/lscript_library/lscript_alloc.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/lscript/lscript_library/lscript_alloc.cpp')
-rw-r--r--linden/indra/lscript/lscript_library/lscript_alloc.cpp1121
1 files changed, 1121 insertions, 0 deletions
diff --git a/linden/indra/lscript/lscript_library/lscript_alloc.cpp b/linden/indra/lscript/lscript_library/lscript_alloc.cpp
new file mode 100644
index 0000000..978d7f2
--- /dev/null
+++ b/linden/indra/lscript/lscript_library/lscript_alloc.cpp
@@ -0,0 +1,1121 @@
1/**
2 * @file lscript_alloc.cpp
3 * @brief general heap management for scripting system
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28// #define at top of file accelerates gcc compiles
29// Under gcc 2.9, the manual is unclear if comments can appear above #ifndef
30// Under gcc 3, the manual explicitly states comments can appear above the #ifndef
31
32#include "linden_common.h"
33
34#include "lscript_alloc.h"
35
36// supported data types
37
38// basic types
39// integer 4 bytes of integer data
40// float 4 bytes of float data
41// string data null terminated 1 byte string
42// key data null terminated 1 byte string
43// vector data 12 bytes of 3 floats
44// quaternion data 16 bytes of 4 floats
45
46// list type
47// list data 4 bytes of number of entries followed by pointer
48
49// string pointer 4 bytes of address of string data on the heap (only used in list data)
50// key pointer 4 bytes of address of key data on the heap (only used in list data)
51
52// heap format
53//
54// 4 byte offset to next block (in bytes)
55// 1 byte of type of variable or empty
56// 2 bytes of reference count
57// nn bytes of data
58
59void reset_hp_to_safe_spot(const U8 *buffer)
60{
61 set_register((U8 *)buffer, LREG_HP, TOP_OF_MEMORY);
62}
63
64// create a heap from the HR to TM
65BOOL lsa_create_heap(U8 *heap_start, S32 size)
66{
67 LLScriptAllocEntry entry(size, LST_NULL);
68
69 S32 position = 0;
70
71 alloc_entry2bytestream(heap_start, position, entry);
72
73 return TRUE;
74}
75
76S32 lsa_heap_top(U8 *heap_start, S32 maxtop)
77{
78 S32 offset = 0;
79 LLScriptAllocEntry entry;
80 bytestream2alloc_entry(entry, heap_start, offset);
81
82 while (offset + entry.mSize < maxtop)
83 {
84 offset += entry.mSize;
85 bytestream2alloc_entry(entry, heap_start, offset);
86 }
87 return offset + entry.mSize;
88}
89
90
91// adding to heap
92// if block is empty
93// if block is at least block size + 4 larger than data
94// split block
95// insert data into first part
96// return address
97// else
98// insert data into block
99// return address
100// else
101// if next block is >= SP
102// set Stack-Heap collision
103// return NULL
104// if next block is empty
105// merge next block with current block
106// go to start of algorithm
107// else
108// move to next block
109// go to start of algorithm
110
111S32 lsa_heap_add_data(U8 *buffer, LLScriptLibData *data, S32 heapsize, BOOL b_delete)
112{
113 if (get_register(buffer, LREG_FR))
114 return 1;
115 LLScriptAllocEntry entry, nextentry;
116 S32 hr = get_register(buffer, LREG_HR);
117 S32 hp = get_register(buffer, LREG_HP);
118 S32 current_offset, next_offset, offset = hr;
119 S32 size = 0;
120
121 switch(data->mType)
122 {
123 case LST_INTEGER:
124 size = 4;
125 break;
126 case LST_FLOATINGPOINT:
127 size = 4;
128 break;
129 case LST_KEY:
130 size = (S32)strlen(data->mKey) + 1;
131 break;
132 case LST_STRING:
133 size = (S32)strlen(data->mString) + 1;
134 break;
135 case LST_LIST:
136 // list data 4 bytes of number of entries followed by number of pointer
137 size = 4 + 4*data->getListLength();
138 if (data->checkForMultipleLists())
139 {
140 set_fault(buffer, LSRF_NESTING_LISTS);
141 }
142 break;
143 case LST_VECTOR:
144 size = 12;
145 break;
146 case LST_QUATERNION:
147 size = 16;
148 break;
149 default:
150 break;
151 }
152
153 current_offset = offset;
154 bytestream2alloc_entry(entry, buffer, offset);
155
156 do
157 {
158 hp = get_register(buffer, LREG_HP);
159 if (!entry.mType)
160 {
161 if (entry.mSize >= size + SIZEOF_SCRIPT_ALLOC_ENTRY + 4)
162 {
163 offset = current_offset;
164 lsa_split_block(buffer, offset, size, entry);
165 entry.mType = data->mType;
166 entry.mSize = size;
167 entry.mReferenceCount = 1;
168 offset = current_offset;
169 alloc_entry2bytestream(buffer, offset, entry);
170 lsa_insert_data(buffer, offset, data, entry, heapsize);
171 hp = get_register(buffer, LREG_HP);
172 S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;
173 if (new_hp >= hr + heapsize)
174 {
175 break;
176 }
177 if (new_hp > hp)
178 {
179 set_register(buffer, LREG_HP, new_hp);
180 hp = get_register(buffer, LREG_HP);
181 }
182 if (b_delete)
183 delete data;
184 // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
185 // and function clean up of ref counts isn't based on scope (a mistake, I know)
186 if (current_offset <= hp)
187 return current_offset - hr + 1;
188 else
189 return hp - hr + 1;
190 }
191 else if (entry.mSize >= size)
192 {
193 entry.mType = data->mType;
194 entry.mReferenceCount = 1;
195 offset = current_offset;
196 alloc_entry2bytestream(buffer, offset, entry);
197 lsa_insert_data(buffer, offset, data, entry, heapsize);
198 hp = get_register(buffer, LREG_HP);
199 if (b_delete)
200 delete data;
201 // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
202 // and function clean up of ref counts isn't based on scope (a mistake, I know)
203 return current_offset - hr + 1;
204 }
205 }
206 offset += entry.mSize;
207 if (offset < hr + heapsize)
208 {
209 next_offset = offset;
210 bytestream2alloc_entry(nextentry, buffer, offset);
211 if (!nextentry.mType && !entry.mType)
212 {
213 entry.mSize += nextentry.mSize + SIZEOF_SCRIPT_ALLOC_ENTRY;
214 offset = current_offset;
215 alloc_entry2bytestream(buffer, offset, entry);
216 }
217 else
218 {
219 current_offset = next_offset;
220 entry = nextentry;
221 }
222
223 // this works whether we are bumping out or coming in
224 S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;
225
226 // make sure we aren't about to be stupid
227 if (new_hp >= hr + heapsize)
228 {
229 break;
230 }
231 if (new_hp > hp)
232 {
233 set_register(buffer, LREG_HP, new_hp);
234 hp = get_register(buffer, LREG_HP);
235 }
236 }
237 else
238 {
239 break;
240 }
241 } while (1);
242 set_fault(buffer, LSRF_STACK_HEAP_COLLISION);
243 reset_hp_to_safe_spot(buffer);
244 if (b_delete)
245 delete data;
246 return 0;
247}
248
249// split block
250// set offset to point to new block
251// set offset of new block to point to original offset - block size - data size
252// set new block to empty
253// set new block reference count to 0
254void lsa_split_block(U8 *buffer, S32 &offset, S32 size, LLScriptAllocEntry &entry)
255{
256 if (get_register(buffer, LREG_FR))
257 return;
258 LLScriptAllocEntry newentry;
259
260 newentry.mSize = entry.mSize - SIZEOF_SCRIPT_ALLOC_ENTRY - size;
261 entry.mSize -= newentry.mSize + SIZEOF_SCRIPT_ALLOC_ENTRY;
262
263 alloc_entry2bytestream(buffer, offset, entry);
264 S32 orig_offset = offset + size;
265 alloc_entry2bytestream(buffer, orig_offset, newentry);
266}
267
268// insert data
269// if data is non-list type
270// set type to basic type, set reference count to 1, copy data, return address
271// else
272// set type to list data type, set reference count to 1
273// save length of list
274// for each list entry
275// insert data
276// return address
277
278void lsa_insert_data(U8 *buffer, S32 &offset, LLScriptLibData *data, LLScriptAllocEntry &entry, S32 heapsize)
279{
280 if (get_register(buffer, LREG_FR))
281 return;
282 if (data->mType != LST_LIST)
283 {
284 switch(data->mType)
285 {
286 case LST_INTEGER:
287 integer2bytestream(buffer, offset, data->mInteger);
288 break;
289 case LST_FLOATINGPOINT:
290 float2bytestream(buffer, offset, data->mFP);
291 break;
292 case LST_KEY:
293 char2bytestream(buffer, offset, data->mKey);
294 break;
295 case LST_STRING:
296 char2bytestream(buffer, offset, data->mString);
297 break;
298 case LST_VECTOR:
299 vector2bytestream(buffer, offset, data->mVec);
300 break;
301 case LST_QUATERNION:
302 quaternion2bytestream(buffer, offset, data->mQuat);
303 break;
304 default:
305 break;
306 }
307 }
308 else
309 {
310 // store length of list
311 integer2bytestream(buffer, offset, data->getListLength());
312 data = data->mListp;
313 while(data)
314 {
315 // store entry and then store address if valid
316 S32 address = lsa_heap_add_data(buffer, data, heapsize, FALSE);
317 integer2bytestream(buffer, offset, address);
318 data = data->mListp;
319 }
320 }
321}
322
323S32 lsa_create_data_block(U8 **buffer, LLScriptLibData *data, S32 base_offset)
324{
325 S32 offset = 0;
326 S32 size = 0;
327
328 LLScriptAllocEntry entry;
329
330 if (!data)
331 {
332 entry.mType = LST_NULL;
333 entry.mReferenceCount = 0;
334 entry.mSize = MAX_HEAP_SIZE;
335 size = SIZEOF_SCRIPT_ALLOC_ENTRY;
336 *buffer = new U8[size];
337 alloc_entry2bytestream(*buffer, offset, entry);
338 return size;
339 }
340
341 entry.mType = data->mType;
342 entry.mReferenceCount = 1;
343
344 if (data->mType != LST_LIST)
345 {
346 if ( (data->mType != LST_STRING)
347 &&(data->mType != LST_KEY))
348 {
349 size = LSCRIPTDataSize[data->mType];
350 }
351 else
352 {
353 if (data->mType == LST_STRING)
354 {
355 if (data->mString)
356 {
357 size = (S32)strlen(data->mString) + 1;
358 }
359 else
360 {
361 size = 1;
362 }
363 }
364 if (data->mType == LST_KEY)
365 {
366 if (data->mKey)
367 {
368 size = (S32)strlen(data->mKey) + 1;
369 }
370 else
371 {
372 size = 1;
373 }
374 }
375 }
376 entry.mSize = size;
377 size += SIZEOF_SCRIPT_ALLOC_ENTRY;
378 *buffer = new U8[size];
379 alloc_entry2bytestream(*buffer, offset, entry);
380
381 switch(data->mType)
382 {
383 case LST_INTEGER:
384 integer2bytestream(*buffer, offset, data->mInteger);
385 break;
386 case LST_FLOATINGPOINT:
387 float2bytestream(*buffer, offset, data->mFP);
388 break;
389 case LST_KEY:
390 if (data->mKey)
391 char2bytestream(*buffer, offset, data->mKey);
392 else
393 byte2bytestream(*buffer, offset, 0);
394 break;
395 case LST_STRING:
396 if (data->mString)
397 char2bytestream(*buffer, offset, data->mString);
398 else
399 byte2bytestream(*buffer, offset, 0);
400 break;
401 case LST_VECTOR:
402 vector2bytestream(*buffer, offset, data->mVec);
403 break;
404 case LST_QUATERNION:
405 quaternion2bytestream(*buffer, offset, data->mQuat);
406 break;
407 default:
408 break;
409 }
410 }
411 else
412 {
413 U8 *listbuf;
414 S32 length = data->getListLength();
415 size = 4 * length + 4;
416 entry.mSize = size;
417
418 size += SIZEOF_SCRIPT_ALLOC_ENTRY;
419 *buffer = new U8[size];
420
421 alloc_entry2bytestream(*buffer, offset, entry);
422 // store length of list
423 integer2bytestream(*buffer, offset, length);
424 data = data->mListp;
425 while(data)
426 {
427 // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
428 // and function clean up of ref counts isn't based on scope (a mistake, I know)
429 integer2bytestream(*buffer, offset, size + base_offset + 1);
430
431 S32 listsize = lsa_create_data_block(&listbuf, data, base_offset + size);
432 if (listsize)
433 {
434 U8 *tbuff = new U8[size + listsize];
435 memcpy(tbuff, *buffer, size);
436 memcpy(tbuff + size, listbuf, listsize);
437 size += listsize;
438 delete [] *buffer;
439 delete [] listbuf;
440 *buffer = tbuff;
441 }
442 data = data->mListp;
443 }
444 }
445 return size;
446}
447
448// increase reference count
449// increase reference count by 1
450
451void lsa_increase_ref_count(U8 *buffer, S32 offset)
452{
453 if (get_register(buffer, LREG_FR))
454 return;
455 // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
456 // and function clean up of ref counts isn't based on scope (a mistake, I know)
457 offset += get_register(buffer, LREG_HR) - 1;
458 if ( (offset < get_register(buffer, LREG_HR))
459 ||(offset >= get_register(buffer, LREG_HP)))
460 {
461 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
462 return;
463 }
464 S32 orig_offset = offset;
465 LLScriptAllocEntry entry;
466 bytestream2alloc_entry(entry, buffer, offset);
467
468 entry.mReferenceCount++;
469
470 alloc_entry2bytestream(buffer, orig_offset, entry);
471}
472
473// decrease reference count
474// decrease reference count by 1
475// if reference count == 0
476// set type to empty
477
478void lsa_decrease_ref_count(U8 *buffer, S32 offset)
479{
480 if (get_register(buffer, LREG_FR))
481 return;
482 // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
483 // and function clean up of ref counts isn't based on scope (a mistake, I know)
484 offset += get_register(buffer, LREG_HR) - 1;
485 if ( (offset < get_register(buffer, LREG_HR))
486 ||(offset >= get_register(buffer, LREG_HP)))
487 {
488 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
489 return;
490 }
491 S32 orig_offset = offset;
492 LLScriptAllocEntry entry;
493 bytestream2alloc_entry(entry, buffer, offset);
494
495 entry.mReferenceCount--;
496
497 if (entry.mReferenceCount < 0)
498 {
499 entry.mReferenceCount = 0;
500 set_fault(buffer, LSRF_HEAP_ERROR);
501 }
502 else if (!entry.mReferenceCount)
503 {
504 if (entry.mType == LST_LIST)
505 {
506 S32 i, num = bytestream2integer(buffer, offset);
507 for (i = 0; i < num; i++)
508 {
509 S32 list_offset = bytestream2integer(buffer, offset);
510 lsa_decrease_ref_count(buffer, list_offset);
511 }
512 }
513 entry.mType = LST_NULL;
514 }
515
516 alloc_entry2bytestream(buffer, orig_offset, entry);
517}
518
519char gLSAStringRead[16384];
520
521
522LLScriptLibData *lsa_get_data(U8 *buffer, S32 &offset, BOOL b_dec_ref)
523{
524 if (get_register(buffer, LREG_FR))
525 return (new LLScriptLibData);
526 S32 orig_offset = offset;
527 // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
528 // and function clean up of ref counts isn't based on scope (a mistake, I know)
529 offset += get_register(buffer, LREG_HR) - 1;
530 if ( (offset < get_register(buffer, LREG_HR))
531 ||(offset >= get_register(buffer, LREG_HP)))
532 {
533 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
534 return (new LLScriptLibData);
535 }
536 LLScriptAllocEntry entry;
537 bytestream2alloc_entry(entry, buffer, offset);
538
539 LLScriptLibData *retval = new LLScriptLibData;
540
541 if (!entry.mType)
542 {
543 set_fault(buffer, LSRF_HEAP_ERROR);
544 return retval;
545 }
546
547 retval->mType = (LSCRIPTType)entry.mType;
548 if (entry.mType != LST_LIST)
549 {
550 switch(entry.mType)
551 {
552 case LST_INTEGER:
553 retval->mInteger = bytestream2integer(buffer, offset);
554 break;
555 case LST_FLOATINGPOINT:
556 retval->mFP = bytestream2float(buffer, offset);
557 break;
558 case LST_KEY:
559 bytestream2char(gLSAStringRead, buffer, offset);
560 retval->mKey = new char[strlen(gLSAStringRead) + 1];
561 strcpy(retval->mKey, gLSAStringRead);
562 break;
563 case LST_STRING:
564 bytestream2char(gLSAStringRead, buffer, offset);
565 retval->mString = new char[strlen(gLSAStringRead) + 1];
566 strcpy(retval->mString, gLSAStringRead);
567 break;
568 case LST_VECTOR:
569 bytestream2vector(retval->mVec, buffer, offset);
570 break;
571 case LST_QUATERNION:
572 bytestream2quaternion(retval->mQuat, buffer, offset);
573 break;
574 default:
575 break;
576 }
577 }
578 else
579 {
580 // get length of list
581 S32 i, length = bytestream2integer(buffer, offset);
582 LLScriptLibData *tip = retval;
583
584 for (i = 0; i < length; i++)
585 {
586 S32 address = bytestream2integer(buffer, offset);
587 tip->mListp = lsa_get_data(buffer, address, FALSE);
588 tip = tip->mListp;
589 }
590 }
591 if (retval->checkForMultipleLists())
592 {
593 set_fault(buffer, LSRF_NESTING_LISTS);
594 }
595 if (b_dec_ref)
596 {
597 lsa_decrease_ref_count(buffer, orig_offset);
598 }
599 return retval;
600}
601
602LLScriptLibData *lsa_get_list_ptr(U8 *buffer, S32 &offset, BOOL b_dec_ref)
603{
604 if (get_register(buffer, LREG_FR))
605 return (new LLScriptLibData);
606 S32 orig_offset = offset;
607 // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
608 // and function clean up of ref counts isn't based on scope (a mistake, I know)
609 offset += get_register(buffer, LREG_HR) - 1;
610 if ( (offset < get_register(buffer, LREG_HR))
611 ||(offset >= get_register(buffer, LREG_HP)))
612 {
613 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
614 return (new LLScriptLibData);
615 }
616 LLScriptAllocEntry entry;
617 bytestream2alloc_entry(entry, buffer, offset);
618
619 if (!entry.mType)
620 {
621 set_fault(buffer, LSRF_HEAP_ERROR);
622 return NULL;
623 }
624
625 LLScriptLibData base, *tip = &base;
626
627 if (entry.mType != LST_LIST)
628 {
629 return NULL;
630 }
631 else
632 {
633 // get length of list
634 S32 i, length = bytestream2integer(buffer, offset);
635
636 for (i = 0; i < length; i++)
637 {
638 S32 address = bytestream2integer(buffer, offset);
639 tip->mListp = lsa_get_data(buffer, address, FALSE);
640 tip = tip->mListp;
641 }
642 }
643 if (b_dec_ref)
644 {
645 lsa_decrease_ref_count(buffer, orig_offset);
646 }
647 tip = base.mListp;
648 base.mListp = NULL;
649 return tip;
650}
651
652S32 lsa_cat_strings(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize)
653{
654 if (get_register(buffer, LREG_FR))
655 return 0;
656 LLScriptLibData *string1;
657 LLScriptLibData *string2;
658 if (offset1 != offset2)
659 {
660 string1 = lsa_get_data(buffer, offset1, TRUE);
661 string2 = lsa_get_data(buffer, offset2, TRUE);
662 }
663 else
664 {
665 string1 = lsa_get_data(buffer, offset1, TRUE);
666 string2 = lsa_get_data(buffer, offset2, TRUE);
667 }
668
669 if ( (!string1)
670 ||(!string2))
671 {
672 set_fault(buffer, LSRF_HEAP_ERROR);
673 delete string1;
674 delete string2;
675 return 0;
676 }
677
678 char *test1 = NULL, *test2 = NULL;
679
680 if (string1->mType == LST_STRING)
681 {
682 test1 = string1->mString;
683 }
684 else if (string1->mType == LST_KEY)
685 {
686 test1 = string1->mKey;
687 }
688 if (string2->mType == LST_STRING)
689 {
690 test2 = string2->mString;
691 }
692 else if (string2->mType == LST_KEY)
693 {
694 test2 = string2->mKey;
695 }
696
697 if ( (!test1)
698 ||(!test2))
699 {
700 set_fault(buffer, LSRF_HEAP_ERROR);
701 delete string1;
702 delete string2;
703 return 0;
704 }
705
706 S32 size = (S32)strlen(test1) + (S32)strlen(test2) + 1;
707
708 LLScriptLibData *string3 = new LLScriptLibData;
709 string3->mType = LST_STRING;
710 string3->mString = new char[size];
711 strcpy(string3->mString, test1);
712 strcat(string3->mString, test2);
713
714 delete string1;
715 delete string2;
716
717 return lsa_heap_add_data(buffer, string3, heapsize, TRUE);
718}
719
720S32 lsa_cmp_strings(U8 *buffer, S32 offset1, S32 offset2)
721{
722 if (get_register(buffer, LREG_FR))
723 return 0;
724 LLScriptLibData *string1;
725 LLScriptLibData *string2;
726
727 string1 = lsa_get_data(buffer, offset1, TRUE);
728 string2 = lsa_get_data(buffer, offset2, TRUE);
729
730 if ( (!string1)
731 ||(!string2))
732 {
733 set_fault(buffer, LSRF_HEAP_ERROR);
734 delete string1;
735 delete string2;
736 return 0;
737 }
738
739 char *test1 = NULL, *test2 = NULL;
740
741 if (string1->mType == LST_STRING)
742 {
743 test1 = string1->mString;
744 }
745 else if (string1->mType == LST_KEY)
746 {
747 test1 = string1->mKey;
748 }
749 if (string2->mType == LST_STRING)
750 {
751 test2 = string2->mString;
752 }
753 else if (string2->mType == LST_KEY)
754 {
755 test2 = string2->mKey;
756 }
757
758 if ( (!test1)
759 ||(!test2))
760 {
761 set_fault(buffer, LSRF_HEAP_ERROR);
762 delete string1;
763 delete string2;
764 return 0;
765 }
766 S32 retval = strcmp(test1, test2);
767
768 delete string1;
769 delete string2;
770
771 return retval;
772}
773
774void lsa_print_heap(U8 *buffer)
775{
776 S32 offset = get_register(buffer, LREG_HR);
777 S32 readoffset;
778 S32 ivalue;
779 F32 fpvalue;
780 LLVector3 vvalue;
781 LLQuaternion qvalue;
782 char string[4096];
783
784 LLScriptAllocEntry entry;
785
786 bytestream2alloc_entry(entry, buffer, offset);
787
788 printf("HP: [0x%X]\n", get_register(buffer, LREG_HP));
789 printf("==========\n");
790
791 while (offset + entry.mSize < MAX_HEAP_SIZE)
792 {
793 printf("[0x%X] ", offset);
794 printf("%s ", LSCRIPTTypeNames[entry.mType]);
795 printf("Ref Count: %d ", entry.mReferenceCount);
796 printf("Size: %d = ", entry.mSize);
797
798 readoffset = offset;
799
800 switch(entry.mType)
801 {
802 case LST_INTEGER:
803 ivalue = bytestream2integer(buffer, readoffset);
804 printf("%d\n", ivalue);
805 break;
806 case LST_FLOATINGPOINT:
807 fpvalue = bytestream2float(buffer, readoffset);
808 printf("%f\n", fpvalue);
809 break;
810 case LST_STRING:
811 bytestream2char(string, buffer, readoffset);
812 printf("%s\n", string);
813 break;
814 case LST_KEY:
815 bytestream2char(string, buffer, readoffset);
816 printf("%s\n", string);
817 break;
818 case LST_VECTOR:
819 bytestream2vector(vvalue, buffer, readoffset);
820 printf("< %f, %f, %f >\n", vvalue.mV[VX], vvalue.mV[VY], vvalue.mV[VZ]);
821 break;
822 case LST_QUATERNION:
823 bytestream2quaternion(qvalue, buffer, readoffset);
824 printf("< %f, %f, %f, %f >\n", qvalue.mQ[VX], qvalue.mQ[VY], qvalue.mQ[VZ], qvalue.mQ[VS]);
825 break;
826 case LST_LIST:
827 ivalue = bytestream2integer(buffer, readoffset);
828 printf("%d\n", ivalue);
829 break;
830 default:
831 printf("\n");
832 break;
833 }
834 offset += entry.mSize;
835 bytestream2alloc_entry(entry, buffer, offset);
836 }
837 printf("[0x%X] ", offset);
838 printf("%s ", LSCRIPTTypeNames[entry.mType]);
839 printf("Ref Count: %d ", entry.mReferenceCount);
840 printf("Size: %d\n", entry.mSize);
841 printf("==========\n");
842}
843
844void lsa_fprint_heap(U8 *buffer, FILE *fp)
845{
846 S32 offset = get_register(buffer, LREG_HR);
847 S32 readoffset;
848 S32 ivalue;
849 F32 fpvalue;
850 LLVector3 vvalue;
851 LLQuaternion qvalue;
852 char string[4096];
853
854 LLScriptAllocEntry entry;
855
856 bytestream2alloc_entry(entry, buffer, offset);
857
858 while (offset + entry.mSize < MAX_HEAP_SIZE)
859 {
860 fprintf(fp, "[0x%X] ", offset);
861 fprintf(fp, "%s ", LSCRIPTTypeNames[entry.mType]);
862 fprintf(fp, "Ref Count: %d ", entry.mReferenceCount);
863 fprintf(fp, "Size: %d = ", entry.mSize);
864
865 readoffset = offset;
866
867 switch(entry.mType)
868 {
869 case LST_INTEGER:
870 ivalue = bytestream2integer(buffer, readoffset);
871 fprintf(fp, "%d\n", ivalue);
872 break;
873 case LST_FLOATINGPOINT:
874 fpvalue = bytestream2float(buffer, readoffset);
875 fprintf(fp, "%f\n", fpvalue);
876 break;
877 case LST_STRING:
878 bytestream2char(string, buffer, readoffset);
879 fprintf(fp, "%s\n", string);
880 break;
881 case LST_KEY:
882 bytestream2char(string, buffer, readoffset);
883 fprintf(fp, "%s\n", string);
884 break;
885 case LST_VECTOR:
886 bytestream2vector(vvalue, buffer, readoffset);
887 fprintf(fp, "< %f, %f, %f >\n", vvalue.mV[VX], vvalue.mV[VY], vvalue.mV[VZ]);
888 break;
889 case LST_QUATERNION:
890 bytestream2quaternion(qvalue, buffer, readoffset);
891 fprintf(fp, "< %f, %f, %f, %f >\n", qvalue.mQ[VX], qvalue.mQ[VY], qvalue.mQ[VZ], qvalue.mQ[VS]);
892 break;
893 case LST_LIST:
894 ivalue = bytestream2integer(buffer, readoffset);
895 fprintf(fp, "%d\n", ivalue);
896 break;
897 default:
898 fprintf(fp, "\n");
899 break;
900 }
901 offset += entry.mSize;
902 bytestream2alloc_entry(entry, buffer, offset);
903 }
904 fprintf(fp, "[0x%X] ", offset);
905 fprintf(fp, "%s ", LSCRIPTTypeNames[entry.mType]);
906 fprintf(fp, "Ref Count: %d ", entry.mReferenceCount);
907 fprintf(fp, "Size: %d", entry.mSize);
908 fprintf(fp, "\n");
909}
910
911S32 lsa_cat_lists(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize)
912{
913 if (get_register(buffer, LREG_FR))
914 return 0;
915 LLScriptLibData *list1;
916 LLScriptLibData *list2;
917 if (offset1 != offset2)
918 {
919 list1 = lsa_get_data(buffer, offset1, TRUE);
920 list2 = lsa_get_data(buffer, offset2, TRUE);
921 }
922 else
923 {
924 list1 = lsa_get_data(buffer, offset1, TRUE);
925 list2 = lsa_get_data(buffer, offset2, TRUE);
926 }
927
928 if ( (!list1)
929 ||(!list2))
930 {
931 set_fault(buffer, LSRF_HEAP_ERROR);
932 delete list1;
933 delete list2;
934 return 0;
935 }
936
937 if ( (list1->mType != LST_LIST)
938 ||(list2->mType != LST_LIST))
939 {
940 set_fault(buffer, LSRF_HEAP_ERROR);
941 delete list1;
942 delete list2;
943 return 0;
944 }
945
946 LLScriptLibData *runner = list1;
947
948 while (runner->mListp)
949 {
950 runner = runner->mListp;
951 }
952
953 runner->mListp = list2->mListp;
954
955 list2->mListp = NULL;
956
957 delete list2;
958
959 return lsa_heap_add_data(buffer, list1, heapsize, TRUE);
960}
961
962
963S32 lsa_cmp_lists(U8 *buffer, S32 offset1, S32 offset2)
964{
965 if (get_register(buffer, LREG_FR))
966 return 0;
967 LLScriptLibData *list1;
968 LLScriptLibData *list2;
969 if (offset1 != offset2)
970 {
971 list1 = lsa_get_data(buffer, offset1, TRUE);
972 list2 = lsa_get_data(buffer, offset2, TRUE);
973 }
974 else
975 {
976 list1 = lsa_get_data(buffer, offset1, FALSE);
977 list2 = lsa_get_data(buffer, offset2, TRUE);
978 }
979
980 if ( (!list1)
981 ||(!list2))
982 {
983 set_fault(buffer, LSRF_HEAP_ERROR);
984 delete list1;
985 delete list2;
986 return 0;
987 }
988
989 if ( (list1->mType != LST_LIST)
990 ||(list2->mType != LST_LIST))
991 {
992 set_fault(buffer, LSRF_HEAP_ERROR);
993 delete list1;
994 delete list2;
995 return 0;
996 }
997
998 S32 length1 = list1->getListLength();
999 S32 length2 = list2->getListLength();
1000
1001 if (length1 != length2)
1002 {
1003 return length1 - length2;
1004 }
1005
1006 LLScriptLibData *runner1 = list1;
1007 LLScriptLibData *runner2 = list2;
1008
1009 S32 count = 0;
1010
1011 while (runner1)
1012 {
1013 if (runner1->mType != runner2->mType)
1014 return count;
1015
1016 switch(runner1->mType)
1017 {
1018 case LST_INTEGER:
1019 if (runner1->mInteger != runner2->mInteger)
1020 return count;
1021 break;
1022 case LST_FLOATINGPOINT:
1023 if (runner1->mFP != runner2->mFP)
1024 return count;
1025 break;
1026 case LST_KEY:
1027 if (strcmp(runner1->mKey, runner2->mKey))
1028 return count;
1029 break;
1030 case LST_STRING:
1031 if (strcmp(runner1->mString, runner2->mString))
1032 return count;
1033 break;
1034 case LST_VECTOR:
1035 if (runner1->mVec != runner2->mVec)
1036 return count;
1037 case LST_QUATERNION:
1038 if (runner1->mQuat != runner2->mQuat)
1039 return count;
1040 break;
1041 default:
1042 break;
1043 }
1044
1045 runner1 = runner1->mListp;
1046 runner2 = runner2->mListp;
1047 }
1048
1049 delete list1;
1050 delete list2;
1051 return 0;
1052}
1053
1054
1055S32 lsa_preadd_lists(U8 *buffer, LLScriptLibData *data, S32 offset2, S32 heapsize)
1056{
1057 if (get_register(buffer, LREG_FR))
1058 return 0;
1059 LLScriptLibData *list2 = lsa_get_data(buffer, offset2, TRUE);
1060
1061 if (!list2)
1062 {
1063 set_fault(buffer, LSRF_HEAP_ERROR);
1064 delete list2;
1065 return 0;
1066 }
1067
1068 if (list2->mType != LST_LIST)
1069 {
1070 set_fault(buffer, LSRF_HEAP_ERROR);
1071 delete list2;
1072 return 0;
1073 }
1074
1075 LLScriptLibData *runner = data->mListp;
1076
1077 while (runner->mListp)
1078 {
1079 runner = runner->mListp;
1080 }
1081
1082
1083 runner->mListp = list2->mListp;
1084 list2->mListp = data->mListp;
1085
1086 return lsa_heap_add_data(buffer, list2, heapsize, TRUE);
1087}
1088
1089
1090S32 lsa_postadd_lists(U8 *buffer, S32 offset1, LLScriptLibData *data, S32 heapsize)
1091{
1092 if (get_register(buffer, LREG_FR))
1093 return 0;
1094 LLScriptLibData *list1 = lsa_get_data(buffer, offset1, TRUE);
1095
1096 if (!list1)
1097 {
1098 set_fault(buffer, LSRF_HEAP_ERROR);
1099 delete list1;
1100 return 0;
1101 }
1102
1103 if (list1->mType != LST_LIST)
1104 {
1105 set_fault(buffer, LSRF_HEAP_ERROR);
1106 delete list1;
1107 return 0;
1108 }
1109
1110 LLScriptLibData *runner = list1;
1111
1112 while (runner->mListp)
1113 {
1114 runner = runner->mListp;
1115 }
1116
1117 runner->mListp = data->mListp;
1118
1119 return lsa_heap_add_data(buffer, list1, heapsize, TRUE);
1120}
1121