y_malloc.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  1. /**--------------------------------------------------------------------------**\
  2. ===================================
  3. Y Sever Includes - Malloc Functions
  4. ===================================
  5. Description:
  6. Functions for using malloc/calloc/free type functions in PAWN.
  7. Legal:
  8. Version: MPL 1.1
  9. The contents of this file are subject to the Mozilla Public License Version
  10. 1.1 (the "License"); you may not use this file except in compliance with
  11. the License. You may obtain a copy of the License at
  12. http://www.mozilla.org/MPL/
  13. Software distributed under the License is distributed on an "AS IS" basis,
  14. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  15. for the specific language governing rights and limitations under the
  16. License.
  17. The Original Code is the YSI malloc include.
  18. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  19. Portions created by the Initial Developer are Copyright (C) 2011
  20. the Initial Developer. All Rights Reserved.
  21. Contributors:
  22. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  23. Thanks:
  24. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  25. ZeeX - Very productive conversations.
  26. koolk - IsPlayerinAreaEx code.
  27. TheAlpha - Danish translation.
  28. breadfish - German translation.
  29. Fireburn - Dutch translation.
  30. yom - French translation.
  31. 50p - Polish translation.
  32. Zamaroht - Spanish translation.
  33. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  34. for me to strive to better.
  35. Pixels^ - Running XScripters where the idea was born.
  36. Matite - Pestering me to release it and using it.
  37. Very special thanks to:
  38. Thiadmer - PAWN, whose limits continue to amaze me!
  39. Kye/Kalcor - SA:MP.
  40. SA:MP Team past, present and future - SA:MP.
  41. Version:
  42. 0.1
  43. Changelog:
  44. 02/12/11:
  45. Added variable argument functions.
  46. 22/12/08:
  47. First version.
  48. Functions:
  49. Public
  50. -
  51. Core:
  52. -
  53. Stock:
  54. malloc - Allocate a block of memory (may be inline).
  55. calloc - Allocate a block of memory and blank.
  56. free - Free an allocated block of memory (may be inline).
  57. Malloc_Set - Set a value in an allocated array (may be inline).
  58. Malloc_Get - Get a value in an allocated array (may be inline).
  59. Malloc_SetS - Set a string in an allocated array.
  60. Malloc_GetS - Get a string in an allocated array.
  61. Malloc_Allocate - Do the memory allocation (may be static).
  62. Malloc_Free - Do the memory freeing (may be static).
  63. Malloc_SlotSize - Get the size of an allocated block (may be inline).
  64. Malloc_NewS - Allocate for and store a given string.
  65. Static:
  66. Malloc_Allocate - Do the memory allocation (may be stock).
  67. Malloc_Free - Do the memory freeing (may be stock).
  68. Inline:
  69. mget - Get data from an allocation unit.
  70. mset - Set data in an allocation unit.
  71. mgets - Get a string from an allocation unit.
  72. msets - Set a string in an allocation unit.
  73. malloc - Allocate a block of memory (may be stock).
  74. free - Free an allocated block of memory (may be stock).
  75. Malloc_Set - Set a value in an allocated array (may be stock).
  76. Malloc_Get - Get a value in an allocated array (may be stock).
  77. Malloc_NextSlot - Get the next free data block.
  78. Malloc_GetSlotSize - Get the size of a slot.
  79. Malloc_SetSlotSize - Set the size of a block.
  80. Malloc_GetData - Direct data access getter.
  81. Malloc_SetData - Direct data access setter.
  82. Malloc_SlotSize - Get the size of an allocated block (may be stock).
  83. API:
  84. -
  85. Callbacks:
  86. -
  87. Definitions:
  88. MALLOC_KB_TO_CELL - Multiplication value to convert kb to cells.
  89. NO_ALLOC - A failed allocation (NULL, but YSI already has NULL).
  90. Enums:
  91. -
  92. Macros:
  93. -
  94. Tags:
  95. Alloc - An allocated block handle variable.
  96. Variables:
  97. Global:
  98. YSI_gMallocMemory - Stores the data (may be static).
  99. Static:
  100. YSI_gMallocMemory - Stores the data (may be global).
  101. YSI_g_sUnusedStart - Start of free memory.
  102. Commands:
  103. -
  104. Compile options:
  105. MALLOC_MEMORY - Number of cells to reserve.
  106. MALLOC_MEMORY_KB - Number of killobytes to reserve.
  107. MALLOC_MEMORY_B - Number of bytes to reserve.
  108. MALLOC_MEMORY_MB - Number of megabytes to reserve.
  109. YSI_MALLOC_SECURE - Use enhanced bounds checking.
  110. YSI_MALLOC_NO_SHORT - Avoid conflicts with mget/mset.
  111. Operators:
  112. -
  113. </remarks>
  114. \**--------------------------------------------------------------------------**/
  115. #include "internal\y_version"
  116. #include "y_debug"
  117. #include "internal\y_funcinc"
  118. #define MALLOC_KB_TO_CELL ((1024 * 8) / cellbits)
  119. #define NO_ALLOC (Alloc:0)
  120. #if !defined MALLOC_MEMORY
  121. #if defined MALLOC_MEMORY_KB
  122. #define MALLOC_MEMORY ((MALLOC_MEMORY_KB) * MALLOC_KB_TO_CELL)
  123. #else
  124. #if defined MALLOC_MEMORY_MB
  125. #define MALLOC_MEMORY ((MALLOC_MEMORY_MB) * 1024 * MALLOC_KB_TO_CELL)
  126. #else
  127. #if defined MALLOC_MEMORY_B
  128. #define MALLOC_MEMORY (((MALLOC_MEMORY_B) * 8) / cellbits)
  129. #else
  130. #define MALLOC_MEMORY (16 * 1024 * MALLOC_KB_TO_CELL)
  131. #endif
  132. #endif
  133. #endif
  134. #endif
  135. static
  136. YSI_g_sUnusedStart = 1;
  137. #if defined YSI_MALLOC_SECURE
  138. static
  139. #else
  140. new
  141. #endif
  142. YSI_gMallocMemory[MALLOC_MEMORY] = {MALLOC_MEMORY - 1, 0};
  143. forward Alloc:Malloc_Allocate(size);
  144. forward Alloc:calloc(size);
  145. #if defined YSI_MALLOC_SECURE
  146. forward Alloc:malloc(size);
  147. #endif
  148. /**--------------------------------------------------------------------------**\
  149. <summary>Malloc_GetSlotSize</summary>
  150. <param name="slot">Allocation unit to get the size of.</param>
  151. <returns>
  152. The size.
  153. </returns>
  154. <remarks>
  155. -
  156. </remarks>
  157. \**--------------------------------------------------------------------------**/
  158. #define Malloc_GetSlotSize(%1) \
  159. (YSI_gMallocMemory[_:(%1) - 1])
  160. /**--------------------------------------------------------------------------**\
  161. <summary>Malloc_SlotSize</summary>
  162. <param name="slot">Allocation unit to get the size of.</param>
  163. <returns>
  164. The size.
  165. </returns>
  166. <remarks>
  167. -
  168. </remarks>
  169. \**--------------------------------------------------------------------------**/
  170. #if defined YSI_MALLOC_SECURE
  171. stock Malloc_SlotSize(slot)
  172. {
  173. return Malloc_GetSlotSize(slot);
  174. }
  175. #else
  176. #define Malloc_SlotSize(%1) \
  177. Malloc_GetSlotSize(%1)
  178. #endif
  179. /**--------------------------------------------------------------------------**\
  180. <summary>Malloc_NewS</summary>
  181. <param name="string[]">The string to store.</param>
  182. <param name="pack">Whether or not the string will be packed.</param>
  183. <returns>
  184. 0 on fail or a data handle on sucess.
  185. </returns>
  186. <remarks>
  187. -
  188. </remarks>
  189. \**--------------------------------------------------------------------------**/
  190. stock Alloc:Malloc_NewS(const string[], bool:pack = false) {
  191. new
  192. size = pack ? ((strlen(string) + 1) char) : (strlen(string) + 1),
  193. Alloc:alloc = Malloc_Allocate(size)
  194. ;
  195. if (alloc) {
  196. if (pack)
  197. strpack(YSI_gMallocMemory[_:alloc], string, size);
  198. else
  199. strunpack(YSI_gMallocMemory[_:alloc], string, size);
  200. }
  201. return alloc;
  202. }
  203. /**--------------------------------------------------------------------------**\
  204. <summary>Malloc_SetSlotSize</summary>
  205. <param name="slot">The allocation unit to set the size of.</param>
  206. <param name="size">The size to set it to.</param>
  207. <returns>
  208. -
  209. </returns>
  210. <remarks>
  211. -
  212. </remarks>
  213. \**--------------------------------------------------------------------------**/
  214. #define Malloc_SetSlotSize(%1,%2) \
  215. YSI_gMallocMemory[_:(%1) - 1] = (%2)
  216. /**--------------------------------------------------------------------------**\
  217. <summary>Malloc_GetData</summary>
  218. <param name="slot">The allocation unit to get data from.</param>
  219. <param name="index">The location in the unit to get.</param>
  220. <returns>
  221. The data
  222. </returns>
  223. <remarks>
  224. Basically like Malloc_Get but used internally.
  225. </remarks>
  226. \**--------------------------------------------------------------------------**/
  227. #define Malloc_GetData(%1,%2) \
  228. (YSI_gMallocMemory[_:((%1)+Alloc:(%2))])
  229. /**--------------------------------------------------------------------------**\
  230. <summary>Malloc_SetData</summary>
  231. <param name="slot">The allocation unit to set in.</param>
  232. <param name="index">Where in the unit to set.</param>
  233. <param name="value">The value to save.</param>
  234. <returns>
  235. -
  236. </returns>
  237. <remarks>
  238. -
  239. </remarks>
  240. \**--------------------------------------------------------------------------**/
  241. #define Malloc_SetData(%1,%2,%3) \
  242. YSI_gMallocMemory[_:((%1)+Alloc:(%2))]=(%3)
  243. /**--------------------------------------------------------------------------**\
  244. <summary>mget</summary>
  245. <param name="slot">The allocation unit to get data from.</param>
  246. <param name="index">The location in the unit to get.</param>
  247. <returns>
  248. The data
  249. </returns>
  250. <remarks>
  251. Shorthand for Malloc_Get.
  252. </remarks>
  253. \**--------------------------------------------------------------------------**/
  254. #if !defined YSI_MALLOC_NO_SHORT
  255. #define mget(%1) \
  256. Malloc_Get(%1)
  257. #endif
  258. /**--------------------------------------------------------------------------**\
  259. <summary>mset</summary>
  260. <param name="slot">The allocation unit to set in.</param>
  261. <param name="index">Where in the unit to set.</param>
  262. <param name="value">The value to save.</param>
  263. <returns>
  264. -
  265. </returns>
  266. <remarks>
  267. Shorthand for Malloc_Set.
  268. </remarks>
  269. \**--------------------------------------------------------------------------**/
  270. #if !defined YSI_MALLOC_NO_SHORT
  271. #define mset(%1) \
  272. Malloc_Set(%1)
  273. #endif
  274. /**--------------------------------------------------------------------------**\
  275. <summary>mgets</summary>
  276. <param name="target[]">Target for the string.</param>
  277. <param name="len">Length of the target.</param>
  278. <param name="array">Data unit to put information in.</param>
  279. <param name="index">Index in the unit.</param>
  280. <returns>
  281. The data
  282. </returns>
  283. <remarks>
  284. Shorthand for Malloc_GetS.
  285. </remarks>
  286. \**--------------------------------------------------------------------------**/
  287. #if !defined YSI_MALLOC_NO_SHORT
  288. #define mgets(%1) \
  289. Malloc_GetS(%1)
  290. #define mgeta(%1) \
  291. Malloc_GetA(%1)
  292. #endif
  293. /**--------------------------------------------------------------------------**\
  294. <summary>msets</summary>
  295. <param name="array">Data unit to put information in.</param>
  296. <param name="index">Index in the unit.</param>
  297. <param name="str[]">String to insert</param>
  298. <returns>
  299. -
  300. </returns>
  301. <remarks>
  302. Shorthand for Malloc_SetS.
  303. </remarks>
  304. \**--------------------------------------------------------------------------**/
  305. #if !defined YSI_MALLOC_NO_SHORT
  306. #define msets(%1) \
  307. Malloc_SetS(%1)
  308. #define mseta(%1) \
  309. Malloc_SetA(%1)
  310. #endif
  311. /**--------------------------------------------------------------------------**\
  312. <summary>Malloc_NextSlot</summary>
  313. <param name="slot">The unit to get the one after of.</param>
  314. <returns>
  315. -
  316. </returns>
  317. <remarks>
  318. Gets the next free block of memory after the current one.
  319. </remarks>
  320. \**--------------------------------------------------------------------------**/
  321. #define Malloc_NextSlot(%1) \
  322. (YSI_gMallocMemory[(%1)])
  323. /**--------------------------------------------------------------------------**\
  324. <summary>Malloc_Get</summary>
  325. <param name="array">Data unit to get information from.</param>
  326. <param name="index">Index in the unit.</param>
  327. <returns>
  328. Data.
  329. </returns>
  330. <remarks>
  331. Displays errors in secure mode.
  332. </remarks>
  333. \**--------------------------------------------------------------------------**/
  334. #if defined YSI_MALLOC_SECURE
  335. stock Malloc_Get(Alloc:array, index)
  336. {
  337. if (index >= 0 && index < Malloc_GetSlotSize(_:array))
  338. {
  339. return Malloc_GetData(_:array, index);
  340. }
  341. P:C(else P:E("Array read index out of bounds: %d[%d]", _:array, index););
  342. return 0;
  343. }
  344. #else
  345. #define Malloc_Get(%1,%2) \
  346. Malloc_GetData(%1, %2)
  347. #endif
  348. /**--------------------------------------------------------------------------**\
  349. <summary>Malloc_Set</summary>
  350. <param name="array">Data unit to put information in.</param>
  351. <param name="index">Index in the unit.</param>
  352. <param name="value">Value to insert</param>
  353. <returns>
  354. -
  355. </returns>
  356. <remarks>
  357. Displays errors in secure mode.
  358. </remarks>
  359. \**--------------------------------------------------------------------------**/
  360. #if defined YSI_MALLOC_SECURE
  361. stock Malloc_Set(Alloc:array, index, value)
  362. {
  363. if (index >= 0 && index < Malloc_GetSlotSize(_:array))
  364. {
  365. return Malloc_SetData(_:array, index, value);
  366. }
  367. P:C(else P:E("Array write index out of bounds: %d[%d]", _:array, index););
  368. return 0;
  369. }
  370. #else
  371. #define Malloc_Set(%1,%2,%3) \
  372. Malloc_SetData(%1, %2, %3)
  373. #endif
  374. /**--------------------------------------------------------------------------**\
  375. <summary>Malloc_GetS</summary>
  376. <param name="target[]">Target for the string.</param>
  377. <param name="len">Length of the target.</param>
  378. <param name="array">Data unit to put information in.</param>
  379. <param name="index">Index in the unit.</param>
  380. <returns>
  381. -
  382. </returns>
  383. <remarks>
  384. Displays errors in secure mode. Gets a string.
  385. </remarks>
  386. \**--------------------------------------------------------------------------**/
  387. stock Malloc_GetS(target[], length, Alloc:array, index)
  388. {
  389. P:3("Malloc_GetS: array = %d, index = %d.", _:array, index);
  390. if (index >= 0)
  391. {
  392. new
  393. size = Malloc_GetSlotSize(_:array);
  394. P:5("Malloc_GetS: size = %d.", size);
  395. new
  396. i = 0;
  397. index += _:array;
  398. size += _:array;
  399. while (i < length && index < size)
  400. {
  401. P:6("Malloc_GetS: i = %d.", i);
  402. if (!(target[i++] = YSI_gMallocMemory[index++]))
  403. {
  404. return 1;
  405. }
  406. }
  407. #if defined YSI_MALLOC_SECURE
  408. P:C(if(index == size)P:E("Out of data (%d, %d)", _:array, index););
  409. P:C(if(i == length)P:E("Out of buffer space"););
  410. #endif
  411. }
  412. return 0;
  413. }
  414. /**--------------------------------------------------------------------------**\
  415. <summary>Malloc_SetS</summary>
  416. <param name="array">Data unit to put information in.</param>
  417. <param name="index">Index in the unit.</param>
  418. <param name="str[]">String to insert</param>
  419. <returns>
  420. -
  421. </returns>
  422. <remarks>
  423. Displays errors in secure mode. Inserts a string.
  424. </remarks>
  425. \**--------------------------------------------------------------------------**/
  426. stock Malloc_SetS(Alloc:array, index, const str[])
  427. {
  428. P:3("Malloc_SetS called: %d, %d, %s", _:array, index, str);
  429. if (index >= 0 && index + strlen(str) + 1 <= Malloc_GetSlotSize(_:array))
  430. {
  431. P:5("Malloc_SetS: In check.");
  432. index += _:array;
  433. YSI_gMallocMemory[index] = 0;
  434. strcat(YSI_gMallocMemory[index], str, cellmax);
  435. //while ((YSI_gMallocMemory[index++] = str[i++])) {}
  436. }
  437. #if defined YSI_MALLOC_SECURE
  438. P:C(else P:E("String copy failed (%s)", str););
  439. #endif
  440. }
  441. /**--------------------------------------------------------------------------**\
  442. <summary>Malloc_SetVAS</summary>
  443. <param name="array">Data unit to put information in.</param>
  444. <param name="index">Index in the unit.</param>
  445. <param name="arg">Offset in the stack of the string to store.</param>
  446. <returns>
  447. -
  448. </returns>
  449. <remarks>
  450. Inserts a string by stack offset for use in vararg functions.
  451. </remarks>
  452. \**--------------------------------------------------------------------------**/
  453. stock Malloc_SetVAS(Alloc:array, index, arg)
  454. {
  455. P:3("Malloc_SetVAS called: %d, %d, %d", _:array, index, arg);
  456. new
  457. len;
  458. #emit LOAD.S.pri arg
  459. #emit SMUL.C 4
  460. #emit LOAD.S.alt 0
  461. #emit ADD
  462. #emit ADD.C 12
  463. #emit LOAD.I
  464. // For later reuse.
  465. #emit STOR.S.pri arg
  466. #emit PUSH.pri
  467. #emit PUSH.C 4
  468. #emit SYSREQ.C strlen
  469. #emit STACK 8
  470. #emit STOR.S.pri len
  471. if (index >= 0 && index + (++len) <= Malloc_GetSlotSize(_:array))
  472. {
  473. P:5("Malloc_SetVAS: In check.");
  474. index += _:array;
  475. YSI_gMallocMemory[index] = 0;
  476. // Blank and copy the string.
  477. //#emit LOAD.S.pri arg
  478. //#emit SMUL.C 4
  479. //#emit LOAD.S.alt 0
  480. //#emit ADD
  481. //#emit ADD.C 12
  482. //#emit LOAD.I
  483. // Skip the code above the second time now (store the true source
  484. // address in "arg" the first time).
  485. #emit PUSH.S len
  486. #emit PUSH.S arg
  487. #emit CONST.alt YSI_gMallocMemory
  488. #emit LOAD.S.pri index
  489. #emit IDXADDR
  490. #emit MOVE.alt
  491. #emit CONST.pri 0
  492. #emit STOR.I
  493. #emit PUSH.alt
  494. #emit PUSH.C 12
  495. #emit SYSREQ.C strcat
  496. #emit STACK 16
  497. //strcat(YSI_gMallocMemory[index], str, cellmax);
  498. }
  499. #if defined YSI_MALLOC_SECURE
  500. P:C(else P:E("String copy failed (%s)", str););
  501. #endif
  502. }
  503. /**--------------------------------------------------------------------------**\
  504. <summary>Malloc_GetA</summary>
  505. <param name="target[]">Target for the array.</param>
  506. <param name="len">Length of the target.</param>
  507. <param name="array">Data unit to put information in.</param>
  508. <param name="index">Index in the unit.</param>
  509. <returns>
  510. -
  511. </returns>
  512. <remarks>
  513. Displays errors in secure mode. Gets an array.
  514. </remarks>
  515. \**--------------------------------------------------------------------------**/
  516. stock Malloc_GetA(target[], length, Alloc:array, index)
  517. {
  518. P:3("Malloc_GetA called: array = %d, index = %d.", _:array, index);
  519. if (index >= 0)
  520. {
  521. new
  522. size = Malloc_GetSlotSize(_:array);
  523. P:5("Malloc_GetA: size = %d.", size);
  524. memcpy(target, YSI_gMallocMemory, index + _:array, size * 4, length);
  525. #if defined YSI_MALLOC_SECURE
  526. P:C(if(length > size)P:E("Out of buffer space."););
  527. #endif
  528. return 1;
  529. }
  530. return 0;
  531. }
  532. /**--------------------------------------------------------------------------**\
  533. <summary>Malloc_SetA</summary>
  534. <param name="array">Data unit to put information in.</param>
  535. <param name="index">Index in the unit.</param>
  536. <param name="str[]">Array to insert.</param>
  537. <param name="len">Length of the array.</param>
  538. <returns>
  539. -
  540. </returns>
  541. <remarks>
  542. Displays errors in secure mode. Inserts an array.
  543. </remarks>
  544. \**--------------------------------------------------------------------------**/
  545. stock Malloc_SetA(Alloc:array, index, const str[], len)
  546. {
  547. P:3("Malloc_SetA: array = %d, index = %d.", _:array, index);
  548. if (index >= 0)
  549. {
  550. new
  551. size = Malloc_GetSlotSize(_:array);
  552. P:5("Malloc_SetA: size = %d.", size);
  553. memcpy(YSI_gMallocMemory[index + _:array], str, 0, len * 4, size - index);
  554. #if defined YSI_MALLOC_SECURE
  555. P:C(if(len > size - index)P:E("Out of buffer space."););
  556. #endif
  557. }
  558. }
  559. /**--------------------------------------------------------------------------**\
  560. <summary>Malloc_SetVAA</summary>
  561. <param name="array">Data unit to put information in.</param>
  562. <param name="index">Index in the unit.</param>
  563. <param name="arg">Offset in the stack of the array to store.</param>
  564. <returns>
  565. -
  566. </returns>
  567. <remarks>
  568. Inserts an array by stack offset for use in vararg functions.
  569. </remarks>
  570. \**--------------------------------------------------------------------------**/
  571. stock Malloc_SetVAA(Alloc:array, index, arg)
  572. {
  573. P:3("Malloc_SetVAA called: %d, %d, %d", _:array, index, arg);
  574. new
  575. len;
  576. #emit LOAD.S.pri arg
  577. #emit ADD.C 1
  578. #emit SMUL.C 4
  579. #emit LOAD.S.alt 0
  580. #emit ADD
  581. #emit ADD.C 12
  582. #emit LOAD.I
  583. #emit LOAD.I
  584. // For later reuse.
  585. #emit STOR.S.pri len
  586. printf("%d", len);
  587. if (index >= 0 && index + len <= Malloc_GetSlotSize(_:array))
  588. {
  589. P:5("Malloc_SetVAA In check.");
  590. index += _:array;
  591. // Skip the code above the second time now (store the true source
  592. // address in "arg" the first time).
  593. #emit LOAD.S.pri len
  594. #emit PUSH.pri
  595. #emit SMUL.C 4
  596. #emit PUSH.pri
  597. #emit PUSH.C 0
  598. // Source.
  599. #emit LOAD.S.pri arg
  600. #emit SMUL.C 4
  601. #emit LOAD.S.alt 0
  602. #emit ADD
  603. #emit ADD.C 12
  604. #emit LOAD.I
  605. #emit PUSH.pri
  606. // Destination.
  607. #emit CONST.alt YSI_gMallocMemory
  608. #emit LOAD.S.pri index
  609. #emit IDXADDR
  610. #emit MOVE.alt
  611. #emit CONST.pri 0
  612. #emit STOR.I
  613. #emit PUSH.alt
  614. // GO!
  615. #emit PUSH.C 20
  616. #emit SYSREQ.C memcpy
  617. #emit STACK 24
  618. //strcat(YSI_gMallocMemory[index], str, cellmax);
  619. }
  620. #if defined YSI_MALLOC_SECURE
  621. P:C(else P:E("Array copy out of memory."););
  622. #endif
  623. }
  624. /**--------------------------------------------------------------------------**\
  625. <summary>malloc</summary>
  626. <param name="size">Size of memory to allocate.</param>
  627. <returns>
  628. 0 on fail or a data handle on sucess.
  629. </returns>
  630. <remarks>
  631. Displays errors in secure mode.
  632. </remarks>
  633. \**--------------------------------------------------------------------------**/
  634. #if defined YSI_MALLOC_SECURE
  635. stock Alloc:malloc(size)
  636. {
  637. new
  638. Alloc:slot = Malloc_Allocate(size);
  639. P:C(if(!slot)P:E("Allocation failed (%d)", size););
  640. return slot;
  641. }
  642. #else
  643. #define malloc(%1) \
  644. Malloc_Allocate(%1)
  645. #endif
  646. /**--------------------------------------------------------------------------**\
  647. <summary>calloc</summary>
  648. <param name="size">Size of memory to allocate.</param>
  649. <returns>
  650. 0 on fail or a data handle on sucess.
  651. </returns>
  652. <remarks>
  653. Displays errors in secure mode. Blanks allocated mmeory.
  654. </remarks>
  655. \**--------------------------------------------------------------------------**/
  656. stock Alloc:calloc(size)
  657. {
  658. new
  659. Alloc:slot = Malloc_Allocate(size);
  660. if (slot)
  661. {
  662. new
  663. temp = _:slot;
  664. while (size--)
  665. {
  666. YSI_gMallocMemory[temp++] = 0;
  667. }
  668. }
  669. #if defined YSI_MALLOC_SECURE
  670. P:C(if(!slot)P:E("Allocation failed (%d)", size););
  671. #endif
  672. return slot;
  673. }
  674. /**--------------------------------------------------------------------------**\
  675. <summary>free</summary>
  676. <param name="slot">Slot of memory to free up.</param>
  677. <returns>
  678. -
  679. </returns>
  680. <remarks>
  681. Displays errors in secure mode.
  682. </remarks>
  683. \**--------------------------------------------------------------------------**/
  684. #if defined YSI_MALLOC_SECURE
  685. stock free(Alloc:slot)
  686. {
  687. if (!slot || !Malloc_GetSlotSize(_:slot))
  688. {
  689. P:1("Free failed (%d)", _:slot);
  690. return 0;
  691. }
  692. return Malloc_Free(slot);
  693. }
  694. #else
  695. #define free(%1) \
  696. Malloc_Free(%1)
  697. #endif
  698. /**--------------------------------------------------------------------------**\
  699. <summary>Malloc_Allocate</summary>
  700. <param name="size">Ammount of memory to allocate.</param>
  701. <returns>
  702. Memory identifier.
  703. </returns>
  704. <remarks>
  705. The size check should never fail, if there's only 1 cell
  706. extra somewhere just sneak it onto the end of an array,
  707. if the user does proper bounds checking it shouldn't
  708. matter.
  709. Implementation code for malloc().
  710. This code will find an area in memory with sufficient
  711. space to store the given data and
  712. </remarks>
  713. \**--------------------------------------------------------------------------**/
  714. #if defined YSI_MALLOC_SECURE
  715. static
  716. #endif
  717. stock Alloc:Malloc_Allocate(size)
  718. {
  719. new
  720. slot = YSI_g_sUnusedStart,
  721. p = 0,
  722. cs;
  723. while (slot)
  724. {
  725. cs = Malloc_GetSlotSize(slot);
  726. if (!cs)
  727. {
  728. return NO_ALLOC;
  729. }
  730. if (cs >= size)
  731. {
  732. break;
  733. }
  734. p = slot;
  735. slot = Malloc_NextSlot(slot);
  736. }
  737. if (slot)
  738. {
  739. if (cs == size + 1)
  740. {
  741. size++;
  742. }
  743. if (cs == size)
  744. {
  745. if (p)
  746. {
  747. Malloc_SetData(Alloc:p, 0, Malloc_NextSlot(slot));
  748. }
  749. else
  750. {
  751. YSI_g_sUnusedStart = Malloc_NextSlot(slot);
  752. }
  753. }
  754. else
  755. {
  756. Malloc_SetSlotSize(slot, size);
  757. size++;
  758. cs -= size;
  759. size += slot;
  760. if (p)
  761. {
  762. Malloc_SetData(Alloc:p, 0, size);
  763. }
  764. else
  765. {
  766. YSI_g_sUnusedStart = size;
  767. }
  768. Malloc_SetData(Alloc:size, 0, Malloc_NextSlot(slot));
  769. Malloc_SetSlotSize(size, cs);
  770. }
  771. return Alloc:slot;
  772. }
  773. return NO_ALLOC;
  774. }
  775. /**--------------------------------------------------------------------------**\
  776. <summary>Malloc_Free</summary>
  777. <param name="slot">Memory allocation unit to release</param>
  778. <returns>
  779. -
  780. </returns>
  781. <remarks>
  782. Implementation code for free().
  783. </remarks>
  784. \**--------------------------------------------------------------------------**/
  785. #if defined YSI_MALLOC_SECURE
  786. static
  787. #endif
  788. stock Malloc_Free(Alloc:slot)
  789. {
  790. P:4("Malloc_Free called: %d", _:slot);
  791. new
  792. size = Malloc_GetSlotSize(_:slot),
  793. p = YSI_g_sUnusedStart,
  794. l = 0;
  795. P:5("Malloc_Free: size = %d", size);
  796. if (p)
  797. {
  798. while (p && p < _:slot)
  799. {
  800. l = p;
  801. p = Malloc_NextSlot(p);
  802. }
  803. if (p)
  804. {
  805. if (l)
  806. {
  807. new
  808. tmp = Malloc_GetSlotSize(l);
  809. if (l + tmp + 1 == _:slot)
  810. {
  811. size += tmp + 1;
  812. Malloc_SetSlotSize(l, size);
  813. slot = Alloc:l;
  814. }
  815. else
  816. {
  817. Malloc_SetData(slot, 0, p);
  818. Malloc_SetData(Alloc:l, 0, _:slot);
  819. }
  820. }
  821. else
  822. {
  823. YSI_g_sUnusedStart = _:slot;
  824. }
  825. if (_:slot + size + 1 == p)
  826. {
  827. Malloc_SetSlotSize(_:slot, Malloc_GetSlotSize(p) + size + 1);
  828. Malloc_SetData(slot, 0, Malloc_NextSlot(p));
  829. }
  830. else
  831. {
  832. Malloc_SetData(slot, 0, p);
  833. }
  834. }
  835. else
  836. {
  837. new
  838. tmp = Malloc_GetSlotSize(l);
  839. if (l + tmp + 1 == _:slot)
  840. {
  841. Malloc_SetSlotSize(l, size + tmp + 1);
  842. }
  843. else
  844. {
  845. Malloc_SetData(slot, 0, 0);
  846. Malloc_SetData(Alloc:l, 0, _:slot);
  847. }
  848. }
  849. }
  850. else
  851. {
  852. YSI_g_sUnusedStart = _:slot;
  853. Malloc_SetData(slot, 0, 0);
  854. }
  855. return 1;
  856. }