funcs.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  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. \**--------------------------------------------------------------------------**/
  114. /**--------------------------------------------------------------------------**\
  115. <summary>Malloc_GetSlotSize</summary>
  116. <param name="slot">Allocation unit to get the size of.</param>
  117. <returns>
  118. The size.
  119. </returns>
  120. <remarks>
  121. -
  122. </remarks>
  123. \**--------------------------------------------------------------------------**/
  124. #define Malloc_GetSlotSize(%1) \
  125. (YSI_gMallocMemory[_:(%1) - 1])
  126. /**--------------------------------------------------------------------------**\
  127. <summary>Malloc_SlotSize</summary>
  128. <param name="slot">Allocation unit to get the size of.</param>
  129. <returns>
  130. The size.
  131. </returns>
  132. <remarks>
  133. -
  134. </remarks>
  135. \**--------------------------------------------------------------------------**/
  136. #if defined YSI_MALLOC_SECURE
  137. stock Malloc_SlotSize(slot)
  138. {
  139. return Malloc_GetSlotSize(slot);
  140. }
  141. #else
  142. #define Malloc_SlotSize(%1) \
  143. Malloc_GetSlotSize(%1)
  144. #endif
  145. /**--------------------------------------------------------------------------**\
  146. <summary>Malloc_NewS</summary>
  147. <param name="string[]">The string to store.</param>
  148. <param name="pack">Whether or not the string will be packed.</param>
  149. <returns>
  150. 0 on fail or a data handle on sucess.
  151. </returns>
  152. <remarks>
  153. Allocates a new piece of memory with enough space to store the given string.
  154. </remarks>
  155. \**--------------------------------------------------------------------------**/
  156. stock Alloc:Malloc_NewS(const string[], bool:pack = false) {
  157. new
  158. size = pack ? ((strlen(string) + 1) char) : (strlen(string) + 1),
  159. Alloc:alloc = Malloc_Allocate(size, false);
  160. if (alloc)
  161. {
  162. if (pack)
  163. strpack(YSI_gMallocMemory[_:alloc], string, size);
  164. else
  165. strunpack(YSI_gMallocMemory[_:alloc], string, size);
  166. }
  167. return alloc;
  168. }
  169. /**--------------------------------------------------------------------------**\
  170. <summary>Malloc_SetSlotSize</summary>
  171. <param name="slot">The allocation unit to set the size of.</param>
  172. <param name="size">The size to set it to.</param>
  173. <returns>
  174. -
  175. </returns>
  176. <remarks>
  177. -
  178. </remarks>
  179. \**--------------------------------------------------------------------------**/
  180. #define Malloc_SetSlotSize(%1,%2) \
  181. YSI_gMallocMemory[_:(%1) - 1] = (%2)
  182. /**--------------------------------------------------------------------------**\
  183. <summary>Malloc_GetData</summary>
  184. <param name="slot">The allocation unit to get data from.</param>
  185. <param name="index">The location in the unit to get.</param>
  186. <returns>
  187. The data
  188. </returns>
  189. <remarks>
  190. Basically like Malloc_Get but used internally.
  191. </remarks>
  192. \**--------------------------------------------------------------------------**/
  193. #define Malloc_GetData(%1,%2) \
  194. (YSI_gMallocMemory[_:((%1)+Alloc:(%2))])
  195. /**--------------------------------------------------------------------------**\
  196. <summary>Malloc_SetData</summary>
  197. <param name="slot">The allocation unit to set in.</param>
  198. <param name="index">Where in the unit to set.</param>
  199. <param name="value">The value to save.</param>
  200. <returns>
  201. -
  202. </returns>
  203. <remarks>
  204. -
  205. </remarks>
  206. \**--------------------------------------------------------------------------**/
  207. #define Malloc_SetData(%1,%2,%3) \
  208. YSI_gMallocMemory[_:((%1)+Alloc:(%2))]=(%3)
  209. /**--------------------------------------------------------------------------**\
  210. <summary>mget</summary>
  211. <param name="slot">The allocation unit to get data from.</param>
  212. <param name="index">The location in the unit to get.</param>
  213. <returns>
  214. The data
  215. </returns>
  216. <remarks>
  217. Shorthand for Malloc_Get.
  218. </remarks>
  219. \**--------------------------------------------------------------------------**/
  220. #if !defined YSI_MALLOC_NO_SHORT
  221. #define mget(%1) \
  222. Malloc_Get(%1)
  223. #endif
  224. /**--------------------------------------------------------------------------**\
  225. <summary>mset</summary>
  226. <param name="slot">The allocation unit to set in.</param>
  227. <param name="index">Where in the unit to set.</param>
  228. <param name="value">The value to save.</param>
  229. <returns>
  230. -
  231. </returns>
  232. <remarks>
  233. Shorthand for Malloc_Set.
  234. </remarks>
  235. \**--------------------------------------------------------------------------**/
  236. #if !defined YSI_MALLOC_NO_SHORT
  237. #define mset(%1) \
  238. Malloc_Set(%1)
  239. #endif
  240. /**--------------------------------------------------------------------------**\
  241. <summary>mgets</summary>
  242. <param name="target[]">Target for the string.</param>
  243. <param name="len">Length of the target.</param>
  244. <param name="array">Data unit to put information in.</param>
  245. <param name="index">Index in the unit.</param>
  246. <returns>
  247. The data
  248. </returns>
  249. <remarks>
  250. Shorthand for Malloc_GetS.
  251. </remarks>
  252. \**--------------------------------------------------------------------------**/
  253. #if !defined YSI_MALLOC_NO_SHORT
  254. #define mgets(%1) \
  255. Malloc_GetS(%1)
  256. #define mgeta(%1) \
  257. Malloc_GetA(%1)
  258. #endif
  259. /**--------------------------------------------------------------------------**\
  260. <summary>msets</summary>
  261. <param name="array">Data unit to put information in.</param>
  262. <param name="index">Index in the unit.</param>
  263. <param name="str[]">String to insert</param>
  264. <returns>
  265. -
  266. </returns>
  267. <remarks>
  268. Shorthand for Malloc_SetS.
  269. </remarks>
  270. \**--------------------------------------------------------------------------**/
  271. #if !defined YSI_MALLOC_NO_SHORT
  272. #define msets(%1) \
  273. Malloc_SetS(%1)
  274. #define mseta(%1) \
  275. Malloc_SetA(%1)
  276. #endif
  277. /**--------------------------------------------------------------------------**\
  278. <summary>Malloc_NextSlot</summary>
  279. <param name="slot">The unit to get the one after of.</param>
  280. <returns>
  281. -
  282. </returns>
  283. <remarks>
  284. Gets the next free block of memory after the current one.
  285. </remarks>
  286. \**--------------------------------------------------------------------------**/
  287. #define Malloc_NextSlot(%1) \
  288. (YSI_gMallocMemory[(%1)])
  289. /**--------------------------------------------------------------------------**\
  290. <summary>Malloc_Get</summary>
  291. <param name="array">Data unit to get information from.</param>
  292. <param name="index">Index in the unit.</param>
  293. <returns>
  294. Data.
  295. </returns>
  296. <remarks>
  297. Displays errors in secure mode.
  298. </remarks>
  299. \**--------------------------------------------------------------------------**/
  300. #if defined YSI_MALLOC_SECURE
  301. stock Malloc_Get(Alloc:array, index)
  302. {
  303. if (index >= 0 && index < Malloc_GetSlotSize(_:array))
  304. {
  305. return Malloc_GetData(_:array, index);
  306. }
  307. P:C(else P:E("Array read index out of bounds: %d[%d]", _:array, index););
  308. return 0;
  309. }
  310. #else
  311. #define Malloc_Get(%1,%2) \
  312. Malloc_GetData(%1, %2)
  313. #endif
  314. /**--------------------------------------------------------------------------**\
  315. <summary>Malloc_Set</summary>
  316. <param name="array">Data unit to put information in.</param>
  317. <param name="index">Index in the unit.</param>
  318. <param name="value">Value to insert</param>
  319. <returns>
  320. -
  321. </returns>
  322. <remarks>
  323. Displays errors in secure mode.
  324. </remarks>
  325. \**--------------------------------------------------------------------------**/
  326. #if defined YSI_MALLOC_SECURE
  327. stock Malloc_Set(Alloc:array, index, value)
  328. {
  329. if (index >= 0 && index < Malloc_GetSlotSize(_:array))
  330. {
  331. return Malloc_SetData(_:array, index, value);
  332. }
  333. P:C(else P:E("Array write index out of bounds: %d[%d]", _:array, index););
  334. return 0;
  335. }
  336. #else
  337. #define Malloc_Set(%1,%2,%3) \
  338. Malloc_SetData(%1, %2, %3)
  339. #endif
  340. /**--------------------------------------------------------------------------**\
  341. <summary>Malloc_GetS</summary>
  342. <param name="target[]">Target for the string.</param>
  343. <param name="len">Length of the target.</param>
  344. <param name="array">Data unit to put information in.</param>
  345. <param name="index">Index in the unit.</param>
  346. <param name="pack">Return the string packed?</param>
  347. <returns>
  348. -
  349. </returns>
  350. <remarks>
  351. Displays errors in secure mode. Gets a string.
  352. </remarks>
  353. \**--------------------------------------------------------------------------**/
  354. stock Malloc_GetS(target[], length, Alloc:array, const index, const bool:pack = false)
  355. {
  356. P:3("Malloc_GetS: array = %d, index = %d.", _:array, index);
  357. if (0 <= index < Malloc_GetSlotSize(_:array))
  358. {
  359. if (pack)
  360. {
  361. strpack(target, Malloc_GetData(array, index), length);
  362. }
  363. else
  364. {
  365. strunpack(target, Malloc_GetData(array, index), length);
  366. }
  367. }
  368. return 0;
  369. }
  370. /**--------------------------------------------------------------------------**\
  371. <summary>Malloc_SetS</summary>
  372. <param name="array">Data unit to put information in.</param>
  373. <param name="index">Index in the unit.</param>
  374. <param name="str[]">String to insert</param>
  375. <param name="pack">Should the string be packed in?</param>
  376. <returns>
  377. -
  378. </returns>
  379. <remarks>
  380. Displays errors in secure mode. Inserts a string.
  381. </remarks>
  382. \**--------------------------------------------------------------------------**/
  383. stock Malloc_SetS(Alloc:array, const index, const str[], const bool:pack = false)
  384. {
  385. P:3("Malloc_SetS called: %d, %d, %s", _:array, index, str);
  386. new
  387. len = strlen(str) + 1;
  388. if (0 <= index && index + len <= Malloc_GetSlotSize(_:array))
  389. {
  390. P:5("Malloc_SetS: In check.");
  391. if (pack)
  392. {
  393. strpack(Malloc_GetData(array, index), str, cellmax);
  394. return (len char);
  395. }
  396. else
  397. {
  398. strunpack(Malloc_GetData(array, index), str, cellmax);
  399. return (len);
  400. }
  401. }
  402. else
  403. {
  404. #if defined YSI_MALLOC_SECURE
  405. P:E("String copy failed (%s)", str);
  406. #endif
  407. return 0;
  408. }
  409. }
  410. /**--------------------------------------------------------------------------**\
  411. <summary>Malloc_SetVAS</summary>
  412. <param name="array">Data unit to put information in.</param>
  413. <param name="index">Index in the unit.</param>
  414. <param name="arg">Offset in the stack of the string to store.</param>
  415. <returns>
  416. -
  417. </returns>
  418. <remarks>
  419. Inserts a string by stack offset for use in vararg functions.
  420. </remarks>
  421. \**--------------------------------------------------------------------------**/
  422. stock Malloc_SetVAS(Alloc:array, index, arg)
  423. {
  424. P:3("Malloc_SetVAS called: %d, %d, %d", _:array, index, arg);
  425. new
  426. len;
  427. #emit LOAD.S.pri arg
  428. #emit SMUL.C 4
  429. #emit LOAD.S.alt 0
  430. #emit ADD
  431. #emit ADD.C 12
  432. #emit LOAD.I
  433. // For later reuse.
  434. #emit STOR.S.pri arg
  435. #emit PUSH.pri
  436. #emit PUSH.C 4
  437. #emit SYSREQ.C strlen
  438. #emit STACK 8
  439. #emit STOR.S.pri len
  440. if (index >= 0 && index + (++len) <= Malloc_GetSlotSize(_:array))
  441. {
  442. P:5("Malloc_SetVAS: In check.");
  443. index += _:array;
  444. YSI_gMallocMemory[index] = 0;
  445. // Blank and copy the string.
  446. //#emit LOAD.S.pri arg
  447. //#emit SMUL.C 4
  448. //#emit LOAD.S.alt 0
  449. //#emit ADD
  450. //#emit ADD.C 12
  451. //#emit LOAD.I
  452. // Skip the code above the second time now (store the true source
  453. // address in "arg" the first time).
  454. #emit PUSH.S len
  455. #emit PUSH.S arg
  456. #emit CONST.alt YSI_gMallocMemory
  457. #emit LOAD.S.pri index
  458. #emit IDXADDR
  459. #emit MOVE.alt
  460. #emit CONST.pri 0
  461. #emit STOR.I
  462. #emit PUSH.alt
  463. #emit PUSH.C 12
  464. #emit SYSREQ.C strcat
  465. #emit STACK 16
  466. //strcat(YSI_gMallocMemory[index], str, cellmax);
  467. }
  468. #if defined YSI_MALLOC_SECURE
  469. P:C(else P:E("String copy failed (%s)", str););
  470. #endif
  471. }
  472. /**--------------------------------------------------------------------------**\
  473. <summary>Malloc_GetA</summary>
  474. <param name="target[]">Target for the array.</param>
  475. <param name="len">Length of the target.</param>
  476. <param name="array">Data unit to put information in.</param>
  477. <param name="index">Index in the unit.</param>
  478. <returns>
  479. -
  480. </returns>
  481. <remarks>
  482. Displays errors in secure mode. Gets an array.
  483. </remarks>
  484. \**--------------------------------------------------------------------------**/
  485. stock Malloc_GetA(target[], length, Alloc:array, index)
  486. {
  487. P:3("Malloc_GetA called: array = %d, index = %d.", _:array, index);
  488. if (index >= 0)
  489. {
  490. new
  491. size = Malloc_GetSlotSize(_:array);
  492. P:5("Malloc_GetA: size = %d.", size);
  493. memcpy(target, YSI_gMallocMemory, index + _:array, size * 4, length);
  494. #if defined YSI_MALLOC_SECURE
  495. P:C(if(length > size)P:E("Out of buffer space."););
  496. #endif
  497. return 1;
  498. }
  499. return 0;
  500. }
  501. /**--------------------------------------------------------------------------**\
  502. <summary>Malloc_SetA</summary>
  503. <param name="array">Data unit to put information in.</param>
  504. <param name="index">Index in the unit.</param>
  505. <param name="str[]">Array to insert.</param>
  506. <param name="len">Length of the array.</param>
  507. <returns>
  508. -
  509. </returns>
  510. <remarks>
  511. Displays errors in secure mode. Inserts an array.
  512. </remarks>
  513. \**--------------------------------------------------------------------------**/
  514. stock Malloc_SetA(Alloc:array, index, const str[], len)
  515. {
  516. P:3("Malloc_SetA: array = %d, index = %d.", _:array, index);
  517. if (index >= 0)
  518. {
  519. new
  520. size = Malloc_GetSlotSize(_:array);
  521. P:5("Malloc_SetA: size = %d.", size);
  522. memcpy(YSI_gMallocMemory[index + _:array], str, 0, len * 4, size - index);
  523. #if defined YSI_MALLOC_SECURE
  524. P:C(if(len > size - index)P:E("Out of buffer space."););
  525. #endif
  526. }
  527. }
  528. /**--------------------------------------------------------------------------**\
  529. <summary>Malloc_SetVAA</summary>
  530. <param name="array">Data unit to put information in.</param>
  531. <param name="index">Index in the unit.</param>
  532. <param name="arg">Offset in the stack of the array to store.</param>
  533. <returns>
  534. -
  535. </returns>
  536. <remarks>
  537. Inserts an array by stack offset for use in vararg functions.
  538. </remarks>
  539. \**--------------------------------------------------------------------------**/
  540. stock Malloc_SetVAA(Alloc:array, index, arg)
  541. {
  542. P:3("Malloc_SetVAA called: %d, %d, %d", _:array, index, arg);
  543. new
  544. len;
  545. #emit LOAD.S.pri arg
  546. #emit ADD.C 1
  547. #emit SMUL.C 4
  548. #emit LOAD.S.alt 0
  549. #emit ADD
  550. #emit ADD.C 12
  551. #emit LOAD.I
  552. #emit LOAD.I
  553. // For later reuse.
  554. #emit STOR.S.pri len
  555. if (index >= 0 && index + len <= Malloc_GetSlotSize(_:array))
  556. {
  557. P:5("Malloc_SetVAA In check.");
  558. index += _:array;
  559. // Skip the code above the second time now (store the true source
  560. // address in "arg" the first time).
  561. #emit LOAD.S.pri len
  562. #emit PUSH.pri
  563. #emit SMUL.C 4
  564. #emit PUSH.pri
  565. #emit PUSH.C 0
  566. // Source.
  567. #emit LOAD.S.pri arg
  568. #emit SMUL.C 4
  569. #emit LOAD.S.alt 0
  570. #emit ADD
  571. #emit ADD.C 12
  572. #emit LOAD.I
  573. #emit PUSH.pri
  574. // Destination.
  575. #emit CONST.alt YSI_gMallocMemory
  576. #emit LOAD.S.pri index
  577. #emit IDXADDR
  578. #emit MOVE.alt
  579. #emit CONST.pri 0
  580. #emit STOR.I
  581. #emit PUSH.alt
  582. // GO!
  583. #emit PUSH.C 20
  584. #emit SYSREQ.C memcpy
  585. #emit STACK 24
  586. }
  587. #if defined YSI_MALLOC_SECURE
  588. P:C(else P:E("Array copy out of memory."););
  589. #endif
  590. }
  591. /**--------------------------------------------------------------------------**\
  592. <summary>malloc</summary>
  593. <param name="size">Size of memory to allocate.</param>
  594. <returns>
  595. 0 on fail or a data handle on sucess.
  596. </returns>
  597. <remarks>
  598. Displays errors in secure mode.
  599. </remarks>
  600. \**--------------------------------------------------------------------------**/
  601. #if defined YSI_MALLOC_SECURE
  602. stock Alloc:malloc(size)
  603. {
  604. new
  605. Alloc:slot = Malloc_Allocate(size);
  606. P:C(if(!slot)P:E("Allocation failed (%d)", size););
  607. return slot;
  608. }
  609. #else
  610. #define malloc(%1) \
  611. Malloc_Allocate(%1)
  612. #endif
  613. /**--------------------------------------------------------------------------**\
  614. <summary>calloc</summary>
  615. <param name="size">Size of memory to allocate.</param>
  616. <returns>
  617. 0 on fail or a data handle on sucess.
  618. </returns>
  619. <remarks>
  620. Displays errors in secure mode. Blanks allocated mmeory.
  621. </remarks>
  622. \**--------------------------------------------------------------------------**/
  623. stock Alloc:calloc(size)
  624. {
  625. new
  626. Alloc:slot = Malloc_Allocate(size);
  627. if (slot)
  628. {
  629. new
  630. temp = _:slot;
  631. while (size--)
  632. {
  633. YSI_gMallocMemory[temp++] = 0;
  634. }
  635. }
  636. #if defined YSI_MALLOC_SECURE
  637. P:C(if(!slot)P:E("Allocation failed (%d)", size););
  638. #endif
  639. return slot;
  640. }
  641. /**--------------------------------------------------------------------------**\
  642. <summary>free</summary>
  643. <param name="slot">Slot of memory to free up.</param>
  644. <returns>
  645. -
  646. </returns>
  647. <remarks>
  648. Displays errors in secure mode.
  649. </remarks>
  650. \**--------------------------------------------------------------------------**/
  651. #if defined YSI_MALLOC_SECURE
  652. stock free(Alloc:slot)
  653. {
  654. if (!slot || !Malloc_GetSlotSize(_:slot))
  655. {
  656. P:1("Free failed (%d)", _:slot);
  657. return 0;
  658. }
  659. return Malloc_Free(slot);
  660. }
  661. #else
  662. #define free(%1) \
  663. Malloc_Free(%1)
  664. #endif
  665. /**--------------------------------------------------------------------------**\
  666. <summary>Malloc_Allocate</summary>
  667. <param name="size">Ammount of memory to allocate IN CELLS.</param>
  668. <param name="cleat">Blank the memory?</param>
  669. <returns>
  670. Memory identifier.
  671. </returns>
  672. <remarks>
  673. The size check should never fail, if there's only 1 cell
  674. extra somewhere just sneak it onto the end of an array,
  675. if the user does proper bounds checking it shouldn't
  676. matter.
  677. Implementation code for malloc().
  678. This code will find an area in memory with sufficient
  679. space to store the given data and
  680. </remarks>
  681. \**--------------------------------------------------------------------------**/
  682. #if defined YSI_MALLOC_SECURE
  683. static
  684. #endif
  685. stock Alloc:Malloc_Allocate(size, const bool:clear = true)
  686. {
  687. P:2("Malloc_Allocate called: %d, %d, %d, %d", size, YSI_g_sUnusedStart, YSI_g_sHeapStart, Malloc_GetSlotSize(YSI_g_sUnusedStart));
  688. //P:0("Malloc_Allocate called: %d, %d, %d, %d", size, YSI_g_sUnusedStart, YSI_g_sHeapStart, Malloc_GetSlotSize(YSI_g_sUnusedStart));
  689. new
  690. slot = YSI_g_sUnusedStart,
  691. p = YSI_g_sHeapStart, // Was "0", now an offset to the heap.
  692. cs,
  693. nextSlot = 0;
  694. #if _DEBUG > 3
  695. #emit LCTRL 2
  696. #emit STOR.S.alt cs
  697. printf("Malloc_Allocate: heap = %d", cs);
  698. #endif
  699. while (slot)
  700. {
  701. cs = Malloc_GetSlotSize(slot);
  702. if (!cs)
  703. {
  704. return NO_ALLOC;
  705. }
  706. if (cs >= size)
  707. {
  708. break;
  709. }
  710. p = slot;
  711. slot = Malloc_NextSlot(slot);
  712. }
  713. if (slot)
  714. {
  715. nextSlot = Malloc_NextSlot(slot);
  716. if (cs == size + 1)
  717. {
  718. size++;
  719. }
  720. if (clear)
  721. {
  722. memset(Malloc_GetData(Alloc:slot, 0), 0, size);
  723. }
  724. if (cs == size)
  725. {
  726. if (p == YSI_g_sHeapStart)
  727. {
  728. YSI_g_sUnusedStart = nextSlot;
  729. }
  730. else
  731. {
  732. Malloc_SetData(Alloc:p, 0, nextSlot);
  733. }
  734. }
  735. else
  736. {
  737. Malloc_SetSlotSize(slot, size);
  738. size++;
  739. cs -= size;
  740. size += slot;
  741. if (p == YSI_g_sHeapStart)
  742. {
  743. YSI_g_sUnusedStart = size;
  744. }
  745. else
  746. {
  747. Malloc_SetData(Alloc:p, 0, size);
  748. }
  749. Malloc_SetData(Alloc:size, 0, nextSlot);
  750. Malloc_SetSlotSize(size, cs);
  751. }
  752. return Alloc:slot;
  753. }
  754. return NO_ALLOC;
  755. }
  756. /**--------------------------------------------------------------------------**\
  757. <summary>Malloc_Free</summary>
  758. <param name="slot">Memory allocation unit to release</param>
  759. <returns>
  760. -
  761. </returns>
  762. <remarks>
  763. Implementation code for free().
  764. </remarks>
  765. \**--------------------------------------------------------------------------**/
  766. #if defined YSI_MALLOC_SECURE
  767. static
  768. #endif
  769. stock Malloc_Free(Alloc:slot)
  770. {
  771. if (slot == NO_ALLOC) return 0;
  772. P:4("Malloc_Free called: %d", _:slot);
  773. new
  774. size = Malloc_GetSlotSize(_:slot),
  775. p = YSI_g_sUnusedStart,
  776. l = YSI_g_sHeapStart; // Was "0", now an offset to the heap.
  777. P:5("Malloc_Free: size = %d", size);
  778. if (p)
  779. {
  780. while (p && p < _:slot)
  781. {
  782. l = p;
  783. p = Malloc_NextSlot(p);
  784. }
  785. if (p)
  786. {
  787. if (l == YSI_g_sHeapStart)
  788. {
  789. YSI_g_sUnusedStart = _:slot;
  790. }
  791. else
  792. {
  793. new
  794. tmp = Malloc_GetSlotSize(l);
  795. if (l + tmp + 1 == _:slot)
  796. {
  797. size += tmp + 1;
  798. Malloc_SetSlotSize(l, size);
  799. slot = Alloc:l;
  800. }
  801. else
  802. {
  803. Malloc_SetData(slot, 0, p);
  804. Malloc_SetData(Alloc:l, 0, _:slot);
  805. }
  806. }
  807. if (_:slot + size + 1 == p)
  808. {
  809. Malloc_SetSlotSize(_:slot, Malloc_GetSlotSize(p) + size + 1);
  810. Malloc_SetData(slot, 0, Malloc_NextSlot(p));
  811. }
  812. else
  813. {
  814. Malloc_SetData(slot, 0, p);
  815. }
  816. }
  817. else
  818. {
  819. p = Malloc_GetSlotSize(l) + 1;
  820. if (l + p == _:slot)
  821. {
  822. Malloc_SetSlotSize(l, size + p);
  823. }
  824. else
  825. {
  826. Malloc_SetData(slot, 0, 0);
  827. Malloc_SetData(Alloc:l, 0, _:slot);
  828. }
  829. }
  830. }
  831. else
  832. {
  833. YSI_g_sUnusedStart = _:slot;
  834. Malloc_SetData(slot, 0, 0);
  835. }
  836. return 1;
  837. }