y_malloc.inc 22 KB

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