COVERAGE SUMMARY
FILE SUMMARY
NameExecutedRoutines%ExecutedLines%Unexecuted
/home/matt/eu/rds/include/std/machine.e102050.00%8714958.39%62
ROUTINE SUMMARY
RoutineExecutedLinesUnexecuted
poke_string()0110.00%11
poke_wstring()090.00%9
allocate_wstring()080.00%8
allocate_data()060.00%6
peek_wstring()060.00%6
allocate_protect()232785.19%4
DEP_on()030.00%3
free()111478.57%3
allocate_pointer_array()7977.78%2
block_aligned()020.00%2
is_DEP_supported()020.00%2
is_using_DEP()020.00%2
page_aligned_address()020.00%2
allocate_string()7887.50%1
allocate_string_pointer_array()6785.71%1
allocate()77100.00%0
allocate_code()22100.00%0
free_pointer_array()1010100.00%0
std_library_address()44100.00%0
valid_memory_protection_constant()22100.00%0
LINE COVERAGE DETAIL
#Executed
1
-- (c) Copyright - See License.txt
2
--
3
namespace machine
4
5
include std/dll.e
6
include std/error.e
7
public include std/memconst.e
8
include std/types.e
9
10101
ifdef SAFE then
11
12
public include std/safe.e as memory
13
14
elsedef
15
16
public include std/memory.e as memory
17
18
end ifdef
19
20
integer FREE_ARRAY_RID
21
220
230
return remainder(a,4096)=0
24
end type
25
26
27
--****
28
-- === Memory allocation
29
--
30
31
--**
32
-- Allocate a contiguous block of data memory.
33
--
34
-- Parameters:
35
-- # ##n## : a positive integer, the size of the requested block.
36
-- # ##cleanup## : an integer, if non-zero, then the returned pointer will be
37
-- automatically freed when its reference count drops to zero, or
38
-- when passed as a parameter to [[:delete]].
39
--
40
-- Return:
41
-- An **atom**, the address of the allocated memory or 0 if the memory
42
-- can't be allocated.
43
--
44
-- Comments:
45
-- Since ##allocate_string##() allocates memory, you are responsible to
46
-- [[:free]]() the block when done with it if ##cleanup## is zero.
47
-- If ##cleanup## is non-zero, then the memory can be freed by calling
48
-- [[:delete]], or when the pointer's reference count drops to zero.
49
-- When you are finished using the block, you should pass the address of the block to
50
-- ##[[:free]]()## if ##cleanup## is zero. If ##cleanup## is non-zero, then the memory
51
-- can be freed by calling [[:delete]], or when the pointer's reference count drops to zero.
52
-- This will free the block and make the memory available for other purposes. When
53
-- your program terminates, the operating system will reclaim all memory for use with other
54
-- programs. An address returned by this function shouldn't be passed to ##[[:call]]()##.
55
-- For that purpose you may use ##[[:allocate_code]]()## instead.
56
--
57
-- The address returned will be at least 4-byte aligned.
58
--
59
-- Example 1:
60
--
61
-- buffer = allocate(100)
62
-- for i = 0 to 99 do
63
-- poke(buffer+i, 0)
64
-- end for
65
--
66
--
67
-- See Also:
68
-- [[:free]], [[:peek]], [[:poke]], [[:mem_set]], [[:allocate_code]]
69
70512
71
-- allocate memory block and add it to safe list
72
machine_addr iaddr
73
machine_addr eaddr
74512
ifdef DATA_EXECUTE then
75
-- high level call: No need to add BORDER_SPACE*2 here.
76
eaddr = machine:allocate_protect( n, 1, PAGE_READ_WRITE_EXECUTE )
77
elsedef
78512
iaddr = eu:machine_func(M_ALLOC, n+BORDER_SPACE*2)
79512
eaddr = prepare_block(iaddr, n, PAGE_READ_WRITE )
80
end ifdef
81512
if cleanup then
822
eaddr = delete_routine( eaddr, FREE_RID )
83
end if
84512
return eaddr
85
end function
86
87
--**
88
-- Allocate n bytes of memory and return the address.
89
-- Free the memory using free() below.
90
910
92
-- allocate memory block and add it to safe list
93
machine_addr a
94
bordered_address sla
950
a = eu:machine_func(M_ALLOC, n+BORDER_SPACE*2)
960
sla = prepare_block(a, n, PAGE_READ_WRITE )
970
if cleanup then
980
return delete_routine( sla, FREE_RID )
99
else
1000
return sla
101
end if
102
end function
103
104
105
--**
106
-- Allocate a NULL terminated pointer array.
107
--
108
-- Parameters:
109
-- # ##pointers## : a sequence of pointers to add to the pointer array.
110
-- # ##cleanup## : an integer, if non-zero, then the returned pointer will be
111
-- automatically freed when its reference count drops to zero, or
112
-- when passed as a parameter to [[:delete]]
113
--
114
-- Comments:
115
-- This function adds the NULL terminator.
116
--
117
-- Example 1:
118
--
119
-- atom pa = allocate_pointer_array({ allocate_string("1"), allocate_string("2") })
120
--
121
--
122
-- See Also:
123
-- [[:allocate_string_pointer_array]], [[:free_pointer_array]]
124
1252
126
atom pList
127
1282
if atom(pointers) then
1290
return 0
130
end if
131
1322
pointers &= 0
1332
pList = allocate(length(pointers) * 4)
1342
poke4(pList, pointers)
1352
if cleanup then
1360
return delete_routine( pList, FREE_ARRAY_RID )
137
end if
1382
return pList
139
end function
140
141
--**
142
-- Free a NULL terminated pointers array.
143
--
144
-- Parameters:
145
-- # ##pointers_array## : memory address of where the NULL terminated array exists at.
146
--
147
-- Comments:
148
-- This is for NULL terminated lists, such as allocated by [[:allocate_pointer_array]].
149
-- Do not call ##free_pointer_array##() for a pointer that was allocated to be cleaned
150
-- up automatically. Instead, use [[:delete]].
151
--
152
-- See Also:
153
-- [[:allocate_pointer_array]], [[:allocate_string_pointer_array]]
154
1551
1561
atom saved = pointers_array,
1571
ptr = peek4u(pointers_array)
158
1591
while ptr do
1602
deallocate(ptr)
161
1622
pointers_array+=4
1632
ptr = peek4u(pointers_array)
1642
end while
165
1661
free(saved)
1671
end procedure
168101
FREE_ARRAY_RID = routine_id("free_pointer_array")
169
170
--**
171
-- Allocate a C-style null-terminated array of strings in memory
172
--
173
-- Parameters:
174
-- # ##string_list## : sequence of strings to store in RAM.
175
-- # ##cleanup## : an integer, if non-zero, then the returned pointer will be
176
-- automatically freed when its reference count drops to zero, or
177
-- when passed as a parameter to [[:delete]]
178
--
179
-- Returns:
180
-- An **atom**, the address of the memory block where the string pointer
181
-- array was stored.
182
--
183
-- Example 1:
184
--
185
-- atom p = allocate_string_pointer_array({ "One", "Two", "Three" })
186
-- -- Same as C: char *p = { "One", "Two", "Three", NULL };
187
--
188
--
189
-- See Also:
190
-- [[:free_pointer_array]]
191
1921
1931
for i = 1 to length(string_list) do
1942
string_list[i] = allocate_string(string_list[i])
1952
end for
196
1971
if cleanup then
1980
return delete_routine( allocate_pointer_array(string_list), FREE_ARRAY_RID )
199
else
2001
return allocate_pointer_array(string_list)
201
end if
202
end function
203
204
205
--****
206
-- == Indirect Routine Calling
207
--
208
-- <>
209
--
210
-- === SAFE mode
211
--
212
-- During the development of your application, you can define the word ##SAFE## to cause
213
-- ##machine.e## to use alternative memory functions. These functions are slower but
214
-- help in the debugging stages. In general, ##SAFE## mode should not be enabled during
215
-- production phases but only for development phases.
216
--
217
-- To define the word ##SAFE## run your application with the ##-D SAFE## command line
218
-- option, or add to the top of your main file ##with define SAFE##.
219
--
220
--
221
-- === Data Execute mode
222
--
223
-- ##Data Execute mode## makes data that will be returned from allocate() executable. On some
224
-- systems allocate() will return memory that is not executable unless this mode has been enabled.
225
-- When writing software you should use allocate_code() or allocate_protect() to get memory for
226
-- execution. This is more efficient and more secure than using ##Data Execute mode##. However,
227
-- since on many systems executing memory returned from allocate() will work much software will be
228
-- written 4.0 and yet use allocate() for executable memory instead of the afore mentioned routines.
229
-- Therefore, you may use this switch when you find that your are getting Data Execute Exceptions
230
-- running some software. ##SAFE## mode will help you discover what memory should be changed to
231
-- what access level. ##Data Execute## mode will only work when the EUPHORIA program uses
232
-- std/machine.e not machine.e.
233
234
-- To enable ##Data Execute mode## define the word ##DATA_EXECUTE## using
235
-- the ##-D DATA_EXECUTE## command line option.
236
--
237
238
--****
239
-- @[dyncall|]
240
-- === Accessing Euphoria coded routines
241
--
242
243
--****
244
-- Signature:
245
-- function routine_id(sequence routine_name)
246
--
247
-- Description:
248
-- Return an integer id number for a user-defined Euphoria procedure or function.
249
--
250
-- Parameters:
251
-- # ##routine_name## : a string, the name of the procedure or function.
252
--
253
-- Returns:
254
-- An **integer**, known as a routine id, -1 if the named routine can't be found, else zero or more.
255
--
256
-- Errors:
257
-- ##routine_name## should not exceed 1,024 characters.
258
--
259
-- Comments:
260
-- The id number can be passed to [[:call_proc]]() or [[:call_func]](), to indirectly call
261
-- the routine named by ##routine_name##. This id depends on the internal process of
262
-- parsing your code, not on ##routine_name##.
263
--
264
-- The routine named ##routine_name## must be visible, i.e. callable, at the place where
265
-- ##routine_id##() is used to get the id number. If it is not, -1 is returned.
266
--
267
-- Indirect calls to the routine can appear earlier in the program than the definition of the routine,
268
-- but the id number can only be obtained in code that comes after the definition
269
-- of the routine - see example 2 below.
270
--
271
-- Once obtained, a valid routine id can be used at any place in the program to call
272
-- a routine indirectly via [[:call_proc]]()/[[:call_func]](), including at places where
273
-- the routine is no longer in scope.
274
--
275
-- Some typical uses of ##routine_id##() are:
276
--
277
-- # Creating a subroutine that takes another routine as a parameter. (See Example 2 below)
278
-- # Using a sequence of routine id's to make a case (switch) statement. Using the
279
-- [[:switch statement]] is more efficient.
280
-- # Setting up an Object-Oriented system.
281
-- # Getting a routine id so you can pass it to [[:call_back]](). (See [[:Platform-Specific Issues]])
282
-- # Getting a routine id so you can pass it to [[:task_create]](). (See [[:Multitasking in Euphoria]])
283
-- # Calling a routine that is defined later in a program. This is no longer needed from v4.0 onward.
284
--
285
-- Note that C routines, callable by Euphoria, also have ids, but they cannot be used where
286
-- routine ids are, because of the different type checking and other technical issues.
287
-- See [[:define_c_proc]]() and [[:define_c_func]]().
288
--
289
-- Example 1:
290
--
291
-- procedure foo()
292
-- puts(1, "Hello World\n")
293
-- end procedure
294
--
295
-- integer foo_num
296
-- foo_num = routine_id("foo")
297
--
298
-- call_proc(foo_num, {}) -- same as calling foo()
299
--
300
--
301
-- Example 2:
302
--
303
-- function apply_to_all(sequence s, integer f)
304
-- -- apply a function to all elements of a sequence
305
-- sequence result
306
-- result = {}
307
-- for i = 1 to length(s) do
308
-- -- we can call add1() here although it comes later in the program
309
-- result = append(result, call_func(f, {s[i]}))
310
-- end for
311
-- return result
312
-- end function
313
--
314
-- function add1(atom x)
315
-- return x + 1
316
-- end function
317
--
318
-- -- add1() is visible here, so we can ask for its routine id
319
-- ? apply_to_all({1, 2, 3}, routine_id("add1"))
320
-- -- displays {2,3,4}
321
--
322
--
323
-- See Also:
324
-- [[:call_proc]], [[:call_func]], [[:call_back]], [[:define_c_func]], [[:define_c_proc]],
325
-- [[:task_create]], [[:Platform-Specific Issues]], [[:Indirect routine calling]]
326
327
--****
328
-- Signature:
329
-- function call_func(integer id, sequence args={})
330
--
331
-- Description:
332
-- Call the user-defined Euphoria function by routine id.
333
--
334
-- Parameters:
335
-- # ##id## : an integer, the routine id of the function to call
336
-- # ##args## : a sequence, the parameters to pass to the function.
337
--
338
-- Returns:
339
-- The **value**, the called function returns.
340
--
341
-- Errors:
342
-- If ##id## is negative or otherwise unknown, an error occurs.
343
--
344
-- If the length of ##args## is not the number of parameters the function takes, an error occurs.
345
--
346
-- Comments:
347
-- ##id## must be a valid routine id returned by [[:routine_id]]().
348
--
349
-- ##args## must be a sequence of argument values of length n, where n is the number of
350
-- arguments required by the called function. Defaulted parameters currently cannot be
351
-- synthesized while making a indirect call.
352
--
353
-- If the function with id ##id## does not take any arguments then ##args## should be ##{}##.
354
--
355
-- Example 1:
356
-- Take a look at the sample program called ##demo/csort.ex##
357
--
358
-- See Also:
359
-- [[:call_proc]], [[:routine_id]], [[:c_func]]
360
--
361
362
--****
363
-- Signature:
364
-- procedure call_proc(integer id, sequence args={})
365
--
366
-- Description:
367
-- Call a user-defined Euphoria procedure by routine id.
368
--
369
-- Parameters:
370
-- # ##id## : an integer, the routine id of the procedure to call
371
-- # ##args## : a sequence, the parameters to pass to the function.
372
--
373
-- Errors:
374
-- If ##id## is negative or otherwise unknown, an error occurs.
375
--
376
-- If the length of ##args## is not the number of parameters the function takes, an error occurs.
377
--
378
-- Comments:
379
-- ##id## must be a valid routine id returned by [[:routine_id]]().
380
--
381
-- ##args## must be a sequence of argument values of length n, where n is the number of
382
-- arguments required by the called procedure. Defaulted parameters currently cannot be
383
-- synthesized while making a indirect call.
384
--
385
-- If the procedure with id ##id## does not take any arguments then ##args## should be ##{}##.
386
--
387
-- Example 1:
388
--
389
-- public integer foo_id
390
--
391
-- procedure x()
392
-- call_proc(foo_id, {1, "Hello World\n"})
393
-- end procedure
394
--
395
-- procedure foo(integer a, sequence s)
396
-- puts(a, s)
397
-- end procedure
398
--
399
-- foo_id = routine_id("foo")
400
--
401
-- x()
402
--
403
--
404
-- See Also:
405
-- [[:call_func]], [[:routine_id]], [[:c_proc]]
406
407
--****
408
-- === Accessing Euphoria internals
409
410
--****
411
-- Signature:
412
-- function machine_func(integer machine_id, object args={})
413
--
414
-- Description:
415
-- Perform a machine-specific operation that returns a value.
416
--
417
-- Returns:
418
-- Depends on the called internal facility.
419
--
420
-- Comments:
421
-- This function us mainly used by the standard library files to implement machine dependent
422
-- operations such as graphics and sound effects. This routine should normally be called
423
-- indirectly via one of the library routines in a Euphoria include file.
424
-- User programs normally do not need to call ##machine_func##.
425
--
426
-- A direct call might cause a machine exception if done incorrectly.
427
--
428
-- See Also:
429
-- [[:machine_proc]]
430
431
--****
432
-- Signature:
433
-- procedure machine_proc(integer machine_id, object args={})
434
--
435
-- Description:
436
-- Perform a machine-specific operation that does not return a value.
437
--
438
-- Comments:
439
-- This procedure us mainly used by the standard library files to implement machine dependent
440
-- operations such as graphics and sound effects. This routine should normally be called
441
-- indirectly via one of the library routines in a Euphoria include file.
442
-- User programs normally do not need to call ##machine_proc##.
443
--
444
-- A direct call might cause a machine exception if done incorrectly.
445
--
446
-- See Also:
447
-- [[:machine_func]]
448
449
450101
ifdef WIN32 then
451
452
atom kernel_dll, memDLL_id,
453
VirtualAlloc_rid,
454
-- VirtualLock_rid, VirtualUnlock_rid,
455
VirtualProtect_rid, GetLastError_rid, GetSystemInfo_rid
456
457
memDLL_id = open_dll( "kernel32.dll" )
458
kernel_dll = memDLL_id
459
VirtualAlloc_rid = define_c_func( memDLL_id, "VirtualAlloc", { C_POINTER, C_SIZE_T, C_DWORD, C_DWORD }, C_POINTER )
460
VirtualProtect_rid = define_c_func( memDLL_id, "VirtualProtect", { C_POINTER, C_SIZE_T, C_DWORD, C_POINTER }, C_BOOL )
461
VirtualFree_rid = define_c_func( kernel_dll, "VirtualFree", { C_POINTER, C_SIZE_T, C_DWORD }, C_BOOL )
462
-- VirtualLock_rid = define_c_func( memDLL_id, "VirtualLock", { C_POINTER, C_SIZE_T }, C_BOOL )
463
-- VirtualUnlock_rid = define_c_func( memDLL_id, "VirtualUnlock", { C_POINTER, C_SIZE_T }, C_BOOL )
464
GetLastError_rid = define_c_func( kernel_dll, "GetLastError", {}, C_DWORD )
465
GetSystemInfo_rid = define_c_proc( kernel_dll, "GetSystemInfo", { C_POINTER } )
466
if VirtualAlloc_rid != -1 and VirtualProtect_rid != -1
467
and GetLastError_rid != -1 and GetSystemInfo_rid != -1
468
then
469
atom vaa = VirtualAlloc( 0, 1, or_bits( MEM_RESERVE, MEM_COMMIT ), PAGE_READ_WRITE_EXECUTE ) != 0
470
if vaa then
471
DEP_really_works = 1
472
c_func( VirtualFree_rid, { vaa, 1, MEM_RELEASE } )
473
vaa = 0
474
end if
475
end if
476
477
integer page_size = 0
478
if GetSystemInfo_rid != -1 then
479
bordered_address system_info_ptr = allocate( 9 * 4 )
480
if system_info_ptr != 0 then
481
c_proc( GetSystemInfo_rid, { system_info_ptr } )
482
page_size = peek4u( system_info_ptr + 4 )
483
free( system_info_ptr )
484
end if
485
end if
486
public constant PAGE_SIZE = page_size
487
elsifdef UNIX then
488101
constant getpagesize_rid = define_c_func( -1, "getpagesize", { }, C_UINT )
489101
public constant PAGE_SIZE = c_func( getpagesize_rid, {} )
490
end ifdef
491
492101
ifdef WIN32 then
493
function VirtualAlloc( atom addr, atom size, atom allocation_type, atom protect_ )
494
atom r1
495
r1 = c_func( VirtualAlloc_rid, {addr, size, allocation_type, protect_ } )
496
return r1
497
end function
498
end ifdef
499
500
--****
501
-- == Types supporting Memory
502
503
--**
504
-- protection constants type
50560
50660
return 0 != find( x, MEMORY_PROTECTION )
507
end type
508
509
--**
510
-- page aligned address type
5110
5120
return remainder( a, PAGE_SIZE ) = 0
513
end type
514
5150
5160
return DEP_really_works
517
end function
518
5190
5200
return use_DEP
521
end function
522
5230
5240
use_DEP = value
5250
end procedure
526
527
--****
528
-- === Allocating and Writing to memory:
529
530
--**
531
-- Allocates and copies data into executable memory.
532
--
533
-- Parameters:
534
-- # ##a_sequence_of_machine_code## : is the machine code to
535
-- be put into memory to be later called with [[:call()]]
536
-- # the ##word length## : of the said code. You can specify your
537
-- code as 1-byte, 2-byte or 4-byte chunks if you wish. If your machine code is byte
538
-- code specify 1. The default is 1.
539
--
540
-- Return Value:
541
-- An **address**,
542
-- The function returns the address in memory of the code, that can be
543
-- safely executed whether DEP is enabled or not or 0 if it fails. On the
544
-- other hand, if you try to execute a code address returned by [[:allocate()]]
545
-- with DEP enabled the program will receive a machine exception.
546
--
547
-- Comments:
548
--
549
-- Use this for the machine code you want to run in memory. The copying is
550
-- done for you and when the routine returns the memory may not be readable
551
-- or writeable but it is guaranteed to be executable. If you want to also
552
-- write to this memory **after the machine code has been copied** you should
553
-- use [[:allocate_protect()]] instead and you should read about having memory
554
-- executable and writeable at the same time is a bad idea. You mustn't use
555
-- ##free()## on memory returned from this function. You may instead
556
-- use ##free_code()## but since you will probably need the code throughout
557
-- the life of your program's process this normally is not necessary.
558
-- If you want to put only data in the memory to be read and written use [[:allocate]].
559
-- See Also:
560
-- [[:allocate]], [[:free_code]], [[:allocate_protect]]
561
5621
563
5641
return allocate_protect( data, wordsize, PAGE_EXECUTE )
565
566
end function
567
568
569
570
--**
571
-- Type for memory addresses
572
--
573
-- an address returned from allocate() or allocate_protect()
574
-- or allocate_code() or the value 0.
575
--
576
-- Return Value:
577
-- An **integer**,
578
-- The type will return 1 if the parameter was returned
579
-- from one of these functions (and has not yet been freeed)
580
--
581
-- Comments:
582
-- This type is equivalent to atom unless SAFE is defined.
583
-- Only values that satisfy this type may be passed into
584
-- free or free_code.
585
--
58628
58728
ifdef not SAFE then
58810
return 1
589
elsedef
59018
return (addr = 0) or bordered_address(addr)
591
end ifdef
592
end type
593
594101
ifdef WIN32 then
595
std_library_address oldprotptr = allocate_data(4)
596
end ifdef
597
598
--**
599
-- Allocates and copies data into memory and gives it protection using
600
-- [[:Standard Library Memory Protection Constants]] or
601
-- [[:Microsoft Windows Memory Protection Constants]]. The user may only pass in one of these
602
-- constants. If you only wish to execute a sequence as machine code use ##allocate_code()##.
603
-- If you only want to read and write data into memory use ##allocate()##.
604
--
605
-- See [[http://msdn.microsoft.com/en-us/library/aa366786(VS.85).aspx "MSDN: Microsoft's Memory Protection Constants"]]
606
--
607
-- Parameters:
608
-- # ##data## : is the machine code to be put into memory.
609
-- # ##wordsize## : is the size each element of data will take in
610
-- memory. Are they 1-byte, 2-bytes or 4-bytes long? Specify here. The default is 1.
611
-- # ##protection## : is the particular Windows protection.
612
--
613
-- Returns:
614
-- An **address**,
615
-- The function returns the address to the required memory
616
-- or 0 if it fails. This function is guaranteed to return memory on
617
-- the 4 byte boundary. It also guarantees that the memory returned with
618
-- at least the protection given (but you may get more).
619
--
620
-- If you want to call ##allocate_protect( data, PAGE_READWRITE )##, you can use
621
-- [[:allocate]] instead. It is more efficient and simpler.
622
--
623
-- If you want to call ##allocate_protect( data, PAGE_EXECUTE )##, you can use
624
-- [[:allocate_code()]] instead. It is simpler.
625
--
626
-- You mustn't use [[:free()]] on memory returned from this function, instead use [[:free_code()]].
627
62818
629
-- set the actual protection for the OS to /true_protection/ in all cases
630
-- /protection/ is put into the checking system if it is there using SAFE
631
63218
atom iaddr = 0
633
std_library_address eaddr
634
integer size
635
valid_memory_protection_constant first_protection
636
63718
valid_memory_protection_constant true_protection = protection
638
639
-- when SAFE is defined /true_protection/ always allows READ so that block edges can be
640
-- checked and WRITE so that we can add leader and trailer markers in this routine.
641
-- when SAFE is not defined /true_protection/ is set to what is passed in without
642
-- modification.
64318
ifdef SAFE then
6448
if ( (not test_write(protection)) or (not test_read(protection) ) ) then
6456
if test_exec(protection) then
6461
true_protection = PAGE_READ_WRITE_EXECUTE
647
else
6485
true_protection = PAGE_READ_WRITE
649
end if
650
end if
651
end ifdef
652
65318
if atom(data) then
6543
size = data * wordsize
6553
first_protection = true_protection
656
else
65715
size = length(data) * wordsize
65815
first_protection = PAGE_READ_WRITE
659
end if
660
66118
ifdef WIN32 then
662
if dep_works() then
663
iaddr = eu:c_func(VirtualAlloc_rid,
664
{ 0, size+BORDER_SPACE*2, or_bits( MEM_RESERVE, MEM_COMMIT ), first_protection })
665
else
666
iaddr = machine_func(M_ALLOC, size+BORDER_SPACE*2)
667
end if
668
elsedef
66918
iaddr = machine_func(M_ALLOC, size+BORDER_SPACE*2)
670
end ifdef
67118
if iaddr = 0 then
6720
return 0
673
end if
674
675
-- eaddr is set here
67618
eaddr = prepare_block( iaddr, size, protection )
677
67818
if eaddr = 0 or atom( data ) then
6793
return eaddr
680
end if
681
68215
switch wordsize do
683
case 1 then
68415
eu:poke( eaddr, data )
685
686
case 2 then
6870
eu:poke2( eaddr, data )
688
689
case 4 then
6900
eu:poke4( eaddr, data )
691
692
case else
6930
crash("logic error: Wrong word size %d in allocate_protect", wordsize)
694
695
end switch
696
697
69815
ifdef WIN32 then
699
ifdef SAFE then
700
-- here we can take away write access
701
-- from true_protection if protection doesn't have it.
702
-- true_protection must have read access though.
703
switch protection do
704
case PAGE_EXECUTE then
705
true_protection = PAGE_EXECUTE_READ
706
707
case PAGE_EXECUTE_WRITECOPY then
708
true_protection = PAGE_EXECUTE_READWRITE
709
710
case PAGE_WRITECOPY, PAGE_NOACCESS then
711
true_protection = PAGE_READONLY
712
713
case else
714
true_protection = protection
715
end switch
716
end ifdef
717
if dep_works() then
718
if eu:c_func( VirtualProtect_rid, { iaddr, size, true_protection , oldprotptr } ) = 0 then
719
-- 0 indicates failure here
720
c_func(VirtualFree_rid, { iaddr, size, MEM_RELEASE })
721
return 0
722
end if
723
end if
724
end ifdef
725
72615
return eaddr
727
end function
728
729
730
731
--**
732
-- Stores a C-style null-terminated ANSI string in memory
733
--
734
-- Parameters:
735
-- # ##buffaddr##: an atom, the RAM address to to the string at.
736
-- # ##buffsize##: an integer, the number of bytes available, starting from ##buffaddr##.
737
-- # ##s## : a sequence, the string to store at address ##buffaddr##.
738
--
739
-- Comments:
740
-- * This does not allocate an RAM. You must supply the preallocated area.
741
-- * This can only be used on ANSI strings. It cannot be used for double-byte strings.
742
-- * If ##s## is not a string, nothing is stored and a zero is returned.
743
--
744
-- Returns:
745
-- An atom. If this is zero, then nothing was stored, otherwise it is the
746
-- address of the first byte after the stored string.
747
--
748
-- Example 1:
749
--
750
-- atom title
751
--
752
-- title = allocate(1000)
753
-- if poke_string(title, 1000, "The Wizard of Oz") then
754
-- -- successful
755
-- else
756
-- -- failed
757
-- end if
758
--
759
--
760
-- See Also:
761
-- [[:allocate]], [[:allocate_string]]
762
7630
764
7650
if buffaddr <= 0 then
7660
return 0
767
end if
768
7690
if not string(s) then
7700
return 0
771
end if
772
7730
if buffsize <= length(s) then
7740
return 0
775
end if
776
7770
poke(buffaddr, s)
7780
buffaddr += length(s)
7790
poke(buffaddr, 0)
780
7810
return buffaddr
782
end function
783
784
--**
785
-- Stores a C-style null-terminated Double-Byte string in memory
786
--
787
-- Parameters:
788
-- # ##buffaddr##: an atom, the RAM address to to the string at.
789
-- # ##buffsize##: an integer, the number of bytes available, starting from ##buffaddr##.
790
-- # ##s## : a sequence, the string to store at address ##buffaddr##.
791
--
792
-- Comments:
793
-- * This does not allocate an RAM. You must supply the preallocated area.
794
-- * This uses two bytes per string character. **Note** that ##buffsize##
795
-- is the number of //bytes// available in the buffer and not the number
796
-- of //characters// available.
797
-- * If ##s## is not a double-byte string, nothing is stored and a zero is returned.
798
--
799
-- Returns:
800
-- An atom. If this is zero, then nothing was stored, otherwise it is the
801
-- address of the first byte after the stored string.
802
--
803
-- Example 1:
804
--
805
-- atom title
806
--
807
-- title = allocate(1000)
808
-- if poke_wstring(title, 1000, "The Wizard of Oz") then
809
-- -- successful
810
-- else
811
-- -- failed
812
-- end if
813
--
814
--
815
-- See Also:
816
-- [[:allocate]], [[:allocate_wstring]]
817
8180
819
8200
if buffaddr <= 0 then
8210
return 0
822
end if
823
8240
if buffsize <= 2 * length(s) then
8250
return 0
826
end if
827
8280
poke2(buffaddr, s)
8290
buffaddr += 2 * length(s)
8300
poke2(buffaddr, 0)
831
8320
return buffaddr
833
end function
834
835
--**
836
-- Allocate a C-style null-terminated string in memory
837
--
838
-- Parameters:
839
-- # ##s## : a sequence, the string to store in RAM.
840
-- # ##cleanup## : an integer, if non-zero, then the returned pointer will be
841
-- automatically freed when its reference count drops to zero, or
842
-- when passed as a parameter to [[:delete]].
843
--
844
-- Returns:
845
-- An **atom**, the address of the memory block where the string was
846
-- stored, or 0 on failure.
847
--
848
-- Comments:
849
-- Only the 8 lowest bits of each atom in ##s## is stored. Use
850
-- ##allocate_wstring##() for storing double byte encoded strings.
851
--
852
-- There is no allocate_string_low() function. However, you could easily
853
-- craft one by adapting the code for ##allocate_string##.
854
--
855
-- Since ##allocate_string##() allocates memory, you are responsible to
856
-- [[:free]]() the block when done with it if ##cleanup## is zero.
857
-- If ##cleanup## is non-zero, then the memory can be freed by calling
858
-- [[:delete]], or when the pointer's reference count drops to zero.
859
--
860
-- Example 1:
861
--
862
-- atom title
863
--
864
-- title = allocate_string("The Wizard of Oz")
865
--
866
--
867
-- See Also:
868
-- [[:allocate]], [[:allocate_wstring]]
869
870169
871
atom mem
872
873169
mem = allocate( length(s) + 1) -- Thanks to Igor
874
875169
if mem then
876169
poke(mem, s)
877169
poke(mem+length(s), 0) -- Thanks to Aku
878169
if cleanup then
8790
mem = delete_routine( mem, FREE_RID )
880
end if
881
end if
882
883169
return mem
884
end function
885
886
--**
887
-- Create a C-style null-terminated wchar_t string in memory
888
--
889
-- Parameters:
890
-- # ##s## : a unicode (utf16) string
891
--
892
-- Returns:
893
-- An **atom**, the address of the allocated string, or 0 on failure.
894
--
895
-- See Also:
896
-- [[:allocate_string]]
897
--
8980
899
atom mem
900
9010
mem = allocate( 2 * (length(s) + 1) )
9020
if mem then
9030
poke2(mem, s)
9040
poke2(mem + length(s)*2, 0)
9050
if cleanup then
9060
mem = delete_routine( mem, FREE_RID )
907
end if
908
end if
909
9100
return mem
911
end function
912
913
--**
914
-- Return a unicode (utf16) string that are stored at machine address a.
915
--
916
-- Parameters:
917
-- # ##addr## : an atom, the address of the string in memory
918
--
919
-- Returns:
920
-- The **string**, at the memory position. The terminator is the null word (two bytes equal to 0).
921
--
922
-- See Also:
923
-- [[:peek_string]]
924
9250
9260
atom ptr = addr
927
9280
while peek2u(ptr) do
9290
ptr += 2
9300
end while
931
9320
return peek2u({addr, (ptr - addr) / 2})
933
end function
934
935
--****
936
-- === Memory disposal
937
--
938
939
--**
940
-- Free up a previously allocated block of memory.
941
-- @[machine:free]
942
--
943
-- Parameters:
944
-- # ##addr##, either a single atom or a sequence of atoms; these are addresses of a blocks to free.
945
--
946
-- Comments:
947
-- * Use ##free##() to return blocks of memory the during execution. This will reduce the chance of
948
-- running out of memory or getting into excessive virtual memory swapping to disk.
949
-- * Do not reference a block of memory that has been freed.
950
-- * When your program terminates, all allocated memory will be returned to the system.
951
-- * ##addr## must have been allocated previously using [[:allocate]](). You
952
-- cannot use it to relinquish part of a block. Instead, you have to allocate
953
-- a block of the new size, copy useful contents from old block there and
954
-- then ##free##() the old block.
955
-- * If the memory was allocated and automatic cleanup
956
-- was specified, then do not call ##free()## directly. Instead, use [[:delete]].
957
-- * An ##addr## of zero is simply ignored.
958
--
959
-- Example 1:
960
-- ##demo/callmach.ex##
961
--
962
-- See Also:
963
-- [[:allocate]], [[:free_code]]
964187
965187
if number_array (addr) then
96612
if ascii_string(addr) then
9670
crash("free(\"%s\") is not a valid address", {addr})
968
end if
969
97012
for i = 1 to length(addr) do
97124
deallocate(addr[i])
97224
end for
97312
return
974175
elsif sequence(addr) then
9750
crash("free() called with nested sequence")
976
end if
977
978175
if addr = 0 then
979
-- Special case, a zero address is assumed to be an uninitialized pointer,
980
-- so it is ignored.
9810
return
982
end if
983
984175
deallocate(addr)
985172
end procedure
986101
FREE_RID = routine_id("free")
987
988
989
--****
990
-- Signature:
991
-- include std/machine.e
992
-- public procedure free_code( atom addr, integer size, valid_wordsize wordsize = 1 )
993
--
994
-- Description:
995
-- Frees up allocated code memory
996
--
997
-- Parameters:
998
-- # ##addr## : must be an address returned by [[:allocate_code()]] or [[:allocate_protect()]]. Do **not** pass memory returned from [[:allocate()]] here!
999
-- # ##size## : is the length of the sequence passed to ##alllocate_code()## or the size you specified when you called allocate_protect().
1000
-- # ##wordsize##: valid_wordsize default = 1
1001
--
1002
-- Comments:
1003
-- Chances are you will not need to call this function because code allocations are typically public scope operations that you want to have available until your process exits.
1004
--
1005
-- See Also: [[:allocate_code]], [[:free]]