187 lines
4.8 KiB
PHP
187 lines
4.8 KiB
PHP
|
; Platform-specific procedures for Linux.
|
||
|
|
||
|
; Reallocate memory at pointer [start.buf] and size [start.allocated],
|
||
|
; new size is in eax.
|
||
|
realloc:
|
||
|
push ebx esi edi
|
||
|
mov ecx, eax
|
||
|
push ebp
|
||
|
kercall __NR_mmap2, 0, , PROT_READ+PROT_WRITE, MAP_PRIVATE+MAP_ANONYMOUS, -1, 0
|
||
|
pop ebp
|
||
|
cmp eax, 0xFFFFF000
|
||
|
ja nomemory
|
||
|
add [start.free], ecx
|
||
|
xchg ecx, [start.allocated]
|
||
|
sub [start.free], ecx
|
||
|
mov edi, eax
|
||
|
xchg eax, [start.buf]
|
||
|
shr ecx, 2
|
||
|
jz .nothing
|
||
|
push ecx
|
||
|
mov esi, eax
|
||
|
rep movsd
|
||
|
pop ecx
|
||
|
shl ecx, 2
|
||
|
call free_eax_ecx
|
||
|
.nothing:
|
||
|
pop edi esi ebx
|
||
|
ret
|
||
|
|
||
|
; Read the next portion of input data to [start.buf].
|
||
|
read:
|
||
|
mov ecx, [start.buf]
|
||
|
add ecx, [start.allocated]
|
||
|
mov edx, [start.free]
|
||
|
sub ecx, edx
|
||
|
kercall __NR_read, [start.in], ,
|
||
|
test eax, eax
|
||
|
js readerr
|
||
|
ret
|
||
|
|
||
|
; Write output data: eax=pointer, edi=size.
|
||
|
write:
|
||
|
mov ecx, eax
|
||
|
kercall __NR_write, [start.out], , edi
|
||
|
cmp eax, edi
|
||
|
jnz writeerr
|
||
|
ret
|
||
|
|
||
|
; Parse command line, open input and output files.
|
||
|
get_params:
|
||
|
; 1. Initialize default streams: 0 for stdin, 1 for stdout.
|
||
|
inc [start.out]
|
||
|
; 2. Prepare for scanning, skipping argv[0].
|
||
|
mov ebx, [start.argc]
|
||
|
cmp ebx, 1
|
||
|
jbe .noargs
|
||
|
dec ebx
|
||
|
lea esi, [start.argv+4] ; skip argv[0]
|
||
|
xor edi, edi ; no args parsed yet
|
||
|
; 3. Parse loop.
|
||
|
.parse:
|
||
|
; 3a. Get the next argument.
|
||
|
lodsd
|
||
|
; 3b. Check whether it is a known option.
|
||
|
cmp word [eax], '-e'
|
||
|
jnz @f
|
||
|
cmp byte [eax+2], 0
|
||
|
jnz @f
|
||
|
; 3c. If it is, modify flags and continue the loop.
|
||
|
mov [start.flags], 1 ; '-e' is given
|
||
|
jmp .nextarg
|
||
|
@@:
|
||
|
; 3d. Otherwise, it is a name of input or output file.
|
||
|
; edi keeps the count of names encountered before;
|
||
|
; edi = 0 means this is input file, edi = 1 - output file,
|
||
|
; otherwise this is third arg, which is an error
|
||
|
cmp edi, 1
|
||
|
ja information
|
||
|
; 3e. Some parameters of __NR_open differ for input and output. Setup them.
|
||
|
mov ecx, O_WRONLY+O_CREAT+O_TRUNC
|
||
|
mov edx, 0644o
|
||
|
jz @f
|
||
|
mov ecx, O_RDONLY
|
||
|
@@:
|
||
|
; 3f. Open/create the file, save the handle.
|
||
|
push ebx
|
||
|
mov ebx, eax
|
||
|
kercall __NR_open
|
||
|
pop ebx
|
||
|
test eax, eax
|
||
|
js .fileerr
|
||
|
mov [start.in+edi*4], eax
|
||
|
inc edi
|
||
|
.nextarg:
|
||
|
dec ebx
|
||
|
jnz .parse
|
||
|
.noargs:
|
||
|
; 4. End of command line reached. Return.
|
||
|
ret
|
||
|
.fileerr:
|
||
|
test edi, edi
|
||
|
jz in_openerr
|
||
|
jmp out_openerr
|
||
|
|
||
|
; Exit, return code is in al.
|
||
|
exit:
|
||
|
movzx ebx, al
|
||
|
push ebx
|
||
|
mov eax, [start.buf]
|
||
|
test eax, eax
|
||
|
jz @f
|
||
|
mov ecx, [start.allocated]
|
||
|
call free_eax_ecx
|
||
|
@@:
|
||
|
kercall __NR_close, [start.in]
|
||
|
kercall __NR_close, [start.out]
|
||
|
pop ebx
|
||
|
kercall __NR_exit
|
||
|
|
||
|
; Helper procedure for realloc and exit.
|
||
|
free_eax_ecx:
|
||
|
mov ebx, eax
|
||
|
kercall __NR_munmap
|
||
|
ret
|
||
|
|
||
|
; Output the message given in esi to stderr.
|
||
|
sayerr:
|
||
|
movzx edx, byte [esi-1]
|
||
|
kercall __NR_write, 2, esi,
|
||
|
ret
|
||
|
|
||
|
; Get environment variable esi (ebx-relative pointer) to the buffer,
|
||
|
; expanding it if needed.
|
||
|
get_environment_variable:
|
||
|
mov ecx, [start.argc]
|
||
|
lea ecx, [start.argv+ecx*4+4]
|
||
|
.findvar:
|
||
|
mov edx, [ecx]
|
||
|
add ecx, 4
|
||
|
test edx, edx
|
||
|
jz .notfound
|
||
|
push esi
|
||
|
add esi, ebx
|
||
|
.comparename:
|
||
|
lodsb
|
||
|
cmp al, [edx]
|
||
|
jnz @f
|
||
|
inc edx
|
||
|
jmp .comparename
|
||
|
@@:
|
||
|
pop esi
|
||
|
test al, al
|
||
|
jnz .findvar
|
||
|
cmp byte [edx], '='
|
||
|
jnz .findvar
|
||
|
inc edx
|
||
|
xor eax, eax
|
||
|
@@:
|
||
|
inc eax
|
||
|
cmp byte [edx+eax-1], 0
|
||
|
jnz @b
|
||
|
stdcall alloc_in_buf, eax
|
||
|
@@:
|
||
|
mov al, [edx]
|
||
|
inc edx
|
||
|
mov [edi+ebx], al
|
||
|
inc edi
|
||
|
test al, al
|
||
|
jnz @b
|
||
|
ret
|
||
|
.notfound:
|
||
|
stdcall alloc_in_buf, 1
|
||
|
mov byte [edi+ebx], 0
|
||
|
inc edi
|
||
|
ret
|
||
|
|
||
|
; Test whether a file with name [.testname] exists.
|
||
|
; Returns eax<0 if not, nonzero otherwise.
|
||
|
test_file_exists:
|
||
|
push ebx
|
||
|
add ebx, [start.testname]
|
||
|
sub esp, 800h
|
||
|
kercall __NR_stat, , esp
|
||
|
add esp, 800h
|
||
|
pop ebx
|
||
|
ret
|