lscript_alloc.cpp

Go to the documentation of this file.
00001 
00032 // #define at top of file accelerates gcc compiles
00033 // Under gcc 2.9, the manual is unclear if comments can appear above #ifndef
00034 // Under gcc 3, the manual explicitly states comments can appear above the #ifndef
00035 
00036 #include "linden_common.h"
00037 #include "lscript_alloc.h"
00038 #include "llrand.h"
00039 
00040 // supported data types
00041 
00042 //      basic types
00043 //      integer                 4 bytes of integer data
00044 //      float                   4 bytes of float data
00045 //      string data             null terminated 1 byte string
00046 //      key data                null terminated 1 byte string
00047 //      vector data             12 bytes of 3 floats
00048 //      quaternion data 16 bytes of 4 floats
00049 
00050 //      list type
00051 //      list data               4 bytes of number of entries followed by pointer
00052 
00053 //      string pointer          4 bytes of address of string data on the heap (only used in list data)
00054 //  key pointer                 4 bytes of address of key data on the heap (only used in list data)
00055 
00056 // heap format
00057 // 
00058 // 4 byte offset to next block (in bytes)
00059 // 1 byte of type of variable or empty
00060 // 2 bytes of reference count
00061 // nn bytes of data
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 // create a heap from the HR to TM
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 // adding to heap
00096 //      if block is empty
00097 //              if block is at least block size + 4 larger than data
00098 //                      split block
00099 //                      insert data into first part
00100 //                      return address
00101 //              else
00102 //                      insert data into block
00103 //                      return address
00104 //      else
00105 //              if next block is >= SP 
00106 //                      set Stack-Heap collision
00107 //                      return NULL
00108 //              if next block is empty
00109 //                      merge next block with current block
00110 //                      go to start of algorithm
00111 //              else
00112 //                      move to next block
00113 //                      go to start of algorithm
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                 // NOTE: babbage: defensive as some library calls set data to NULL
00135                 size = data->mKey ? (S32)strlen(data->mKey) + 1 : 1; /*Flawfinder: ignore*/
00136                 break;
00137         case LST_STRING:
00138                 // NOTE: babbage: defensive as some library calls set data to NULL
00139                 size = data->mString ? (S32)strlen(data->mString) + 1 : 1; /*Flawfinder: ignore*/
00140                 break;
00141         case LST_LIST:
00142                 //      list data               4 bytes of number of entries followed by number of pointer
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         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00191         // and function clean up of ref counts isn't based on scope (a mistake, I know)
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         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00208         // and function clean up of ref counts isn't based on scope (a mistake, I know)
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                         // this works whether we are bumping out or coming in
00230                         S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;
00231 
00232                         // make sure we aren't about to be stupid
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 // split block
00256 //      set offset to point to new block
00257 //      set offset of new block to point to original offset - block size - data size
00258 //      set new block to empty
00259 //      set new block reference count to 0
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 // insert data
00275 //      if data is non-list type
00276 //              set type to basic type, set reference count to 1, copy data, return address
00277 //      else
00278 //              set type to list data type, set reference count to 1
00279 //              save length of list
00280 //              for each list entry
00281 //                      insert data
00282 //                      return address
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                 // store length of list
00317                 integer2bytestream(buffer, offset, data->getListLength());
00318                 data = data->mListp;
00319                 while(data)
00320                 {
00321                         // store entry and then store address if valid
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;          /*Flawfinder: ignore*/
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;             /*Flawfinder: ignore*/
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                 // store length of list
00429                 integer2bytestream(*buffer, offset, length);
00430                 data = data->mListp;
00431                 while(data)
00432                 {
00433         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00434         // and function clean up of ref counts isn't based on scope (a mistake, I know)
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);   /*Flawfinder: ignore*/
00446                                 memcpy(tbuff + size, listbuf, listsize);                /*Flawfinder: ignore*/
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 // increase reference count
00459 //      increase reference count by 1
00460 
00461 void lsa_increase_ref_count(U8 *buffer, S32 offset)
00462 {
00463         if (get_register(buffer, LREG_FR))
00464                 return;
00465         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00466         // and function clean up of ref counts isn't based on scope (a mistake, I know)
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 // decrease reference count
00484 //              decrease reference count by 1
00485 //              if reference count == 0
00486 //                      set type to empty
00487 
00488 void lsa_decrease_ref_count(U8 *buffer, S32 offset)
00489 {
00490         if (get_register(buffer, LREG_FR))
00491                 return;
00492         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00493         // and function clean up of ref counts isn't based on scope (a mistake, I know)
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];             /*Flawfinder: ignore*/
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         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00538         // and function clean up of ref counts isn't based on scope (a mistake, I know)
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)); // global sring buffer? for real? :(
00570                         retval->mKey = new char[strlen(gLSAStringRead) + 1];            /*Flawfinder: ignore*/
00571                         strcpy(retval->mKey, gLSAStringRead);                   /*Flawfinder: ignore*/
00572                         break;
00573                 case LST_STRING:
00574                         bytestream2char(gLSAStringRead, buffer, offset, sizeof(gLSAStringRead));
00575                         retval->mString = new char[strlen(gLSAStringRead) + 1];         /*Flawfinder: ignore*/
00576                         strcpy(retval->mString, gLSAStringRead);                        /*Flawfinder: ignore*/
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                 // get length of list
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         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00618         // and function clean up of ref counts isn't based on scope (a mistake, I know)
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                 // get length of list
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;                 /*Flawfinder: ignore*/
00717 
00718         LLScriptLibData *string3 = new LLScriptLibData;
00719         string3->mType = LST_STRING;
00720         string3->mString = new char[size];
00721         strcpy(string3->mString, test1);                        /*Flawfinder: ignore*/
00722         strcat(string3->mString, test2);                        /*Flawfinder: ignore*/
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];           /*Flawfinder: ignore*/
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];           /*Flawfinder: ignore*/
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         // Copy everything into a special vector for sorting;
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         // We cannot simply call random_shuffle or similar algorithm since
01114         // we need to obey the stride. So, we iterate over what we have
01115         // and swap each with a random other segment.
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         // copy the pointers back out
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 }

Generated on Fri May 16 08:33:06 2008 for SecondLife by  doxygen 1.5.5