Format ElfObj64

include "../include/prog.h" "../include/prog.oh"
include "../include/throw.h" "../include/throw.oh"

#multithread unsafe
vstrx acod#1
vstrx apointer#1
vstr orig=NULL
vstr memorig=NULL
value dcode#1
value format_file=NULL

importx "_snprintf" snprintf

#win32 with _
importx "memcpy" memcpy
importx "sprintf" sprintf
Importx "realloc" realloc
Importx "malloc" malloc
Importx "free" free
importx "strlen" strlen
importx "strcpy" strcpy

^import "spaces" spaces 1 #full return

#strings

function debug_code()
	return #globalu.dcode
end

#0 yes  1 no
function row_termination(sv p_ac,sv p_row)
	ss ac;set ac p_ac#
	if ac#=(text_nl)
		inc p_row#
		return 0
	endif
	if ac#=(text_cr)
		inc ac;if ac#=(text_nl);set p_ac# ac;endif
		inc p_row#
		return 0
	endif
	return 1
endfunction
function row_termination_endcom(ss ac)
	if ac#=(text_nl)
		inc ac
	elseif ac#=(text_cr)
		inc ac
		if ac#=(text_nl);inc ac;end
	end
	return ac
end

function endcom(ss c,ss p)
	set globalu.acod c;set globalu.apointer p
end

import "debug_phase_init" debug_phase_init
#error_row
function escape_action(ss ac,ss pointer,ss stop_pointer,ss line_term)
    sd row=1
    #sd loop1=1
    sd error_row=0
    #
	sd ?comments=0
	char lines_com_c1=Asterisk;char lines_com_c2=Slash;ss test
    const line_comment=1
    const multiLine_comment=2
    #
    whiletrue
	sd ?loop2=1
        setcall ac spaces(ac)
        #
        if comments!=(multiLine_comment)
            set comments 0
            if ac#=(Slash)
                set test ac
                inc test
                if test#=(Slash)
                    set comments (line_comment)
                    add ac 2
                elseif test#=lines_com_c1
                    set comments (multiLine_comment)
                    add ac 2
                endelseif
            endif
        endif
        #
        while loop2=1
		setcall loop2 row_termination(#ac,#row)
		if loop2=1
			if ac#=0
				if stop_pointer!=(NULL)
					return error_row
				end
				set pointer# 0
				call debug_phase_init(pointer)
				return pointer
			endif
			if comments=0
				if pointer=stop_pointer
					set error_row row
				elseif line_term!=(NULL)
					if line_term=pointer
						whiletrue
							inc ac;inc pointer
							ss c;set c row_termination_endcom(ac)
							if c=ac
								if ac#=0
									break
								end
							else
								set globalu.acod ac
								set globalu.apointer pointer
								break
							end
						end
						return pointer
					end
				else
					set pointer# ac#
				endelse
				inc pointer
			elseif comments=(multiLine_comment)
				if ac#=lines_com_c1
					set test ac;inc test;if test#=lines_com_c2;set comments 0;inc ac;endif
				endif
			endelseif
		elseif stop_pointer=(NULL)
			if line_term=(NULL) #not wainting this at end com
				call debug_phase_init(pointer)
			end
		endelseif
		inc ac
        endwhile
	if error_row!=0
		set pointer# 0
		return error_row
	endif
    endwhile
end
#ac
function escape_action_endcom(ss pointer)
	callret escape_action(globalu.acod,globalu.apointer,(NULL),pointer)
end

#debug

import "mem_free" mem_free
function action_debug_orig()
	return #globalu.orig
endfunction
function action_debug_memorig()
	return #globalu.memorig
end
function action_debug_free_macro()
	set globalu.orig (NULL)
	if globalu.memorig!=(NULL);call mem_free(#globalu.memorig);endif
endfunction

import "printEr" printEr
import "string_nl_print" string_nl_print
function action_error()
	if globalu.orig=(NULL)
		ret
	endif

	call printEr("Row: ")

	# ac and mem is not ok at arm c code can be 16 bit aligned
	#vstr stack#2
	#sv st^stack  #can do more with only at c sign !
	#call memcpy(st,p_action_errors,(2*:))
	#sv mem=:;add mem st
	sd row
	setcall row escape_action(globalu.orig,globalu.memorig,globalu.dcode,(NULL))
	#a small reserve for a number like 2 000 000 000
	char a#dword_to_string_char
	ss row_nr^a
	call sprintf(row_nr,"%u",row)
	call string_nl_print(row_nr)
	call string_nl_print(globalu.dcode)
endfunction

import "block_get_size" block_get_size
#size
function action_size(sd id)
    sd block
    setcall block struct_ids_action((ids_get),id)
    sd ?size
    setcall size block_get_size(block)
    addcall size pool_size(id)
    #add termination
    add size 1
    return size
endfunction

^import "block_get_mem" block_get_mem 1

#these ids are get only, is safe at throwless
^import "struct_ids_action" struct_ids_action 2 #full
^import "struct_ids_actionpool" struct_ids_actionpool 2 #full

#size
function pool_size(sd id)
    sd poolblock
    setcall poolblock struct_ids_actionpool((ids_get),id)
    sd ?poolsize
    setcall poolsize block_get_size(poolblock)
    #detected at button actions="", swfdump giving error without "if poolsize!=0"
    if poolsize=0;return 0;endif
    #add header
    add poolsize (1+2)
    return poolsize
endfunction

import "f_close" f_close
function format_free()
	if globalu.format_file!=(NULL)
		call f_close(#globalu.format_file)
	end
end

import "swf_actionblock_change_back" swf_actionblock_change_back
import "file_get_content__resources_free" file_get_content__resources_free

^import "action_code_get_pointer" action_code_get_pointer 1 #full
^import "action_code_values_index" action_code_values_index
^import "action_code_get" action_code_get #full

import "ebase" ebase
^import "erbool" erbool

#aftercallimport ebool

import "swf_actionblock_change" swf_actionblock_change
import "swf_actionblock_add" swf_actionblock_add
import "action_push" action_push

#tags

import "actionpush" actionpush
import "debug_phase_code_add_if" debug_phase_code_add_if
function action_one(sd tag)
	call actionpush()
	call swf_actionblock_add(#tag,(actionrecordheader_tag_size))
	callg debug_phase_code_add_if((FALSE),(xlog_act))
endfunction

^import "action_code_right_util" action_code_right_util 1 #full
import "debug_x_preexpand_inter" debug_x_preexpand_inter
import "debug_x_expand" debug_x_expand
#codepointer
function action_caller(ss member,sv pfname,sd codepointer)
	set codepointer action_caller_right(pfname,codepointer)

	call debug_x_preexpand_inter(codepointer)
	if member!=0
		sd ?currentnr
		sd p_currentnr
		setcall p_currentnr action_code_values_index()
		set currentnr p_currentnr#
		sv values
		setcall values action_code_get()

		call action_code_member(member,0)
		call action_member_loop_right(values)

		call debug_x_expand(values)

		set p_currentnr# currentnr
	else
		call debug_x_expand((NULL))
	end
	return codepointer
endfunction
#codepointer
function action_caller_right(sv pfname,sd codepointer)
	set pfname# action_code_get_pointer(#codepointer)
	sd ?nrargs=0
	while codepointer#!=(args_end)
		setcall codepointer action_code_right_util(codepointer)
		inc nrargs
	endwhile
	add codepointer (DWORD)
	call action_push((ap_Integer),nrargs)
	return codepointer
end

#member

import "action_get_one" action_get_one
#the position where the mathpointer reachs
function action_member_loop_left(sv mathpointer)  #set, ex get_member_pointer, let the string
	sd name
	set name action_code_get_pointer(#mathpointer)
	call action_get_one(name)

	#at first is something
	if mathpointer#!=(no_pointer)
		set name action_code_get_pointer(#mathpointer)
		call action_push((ap_Constant8),name)
	else
		add mathpointer :+DWORD  #to pass the pointer   + square_bracket_start
		setcall mathpointer action_code_right_util(mathpointer)
	end

	whiletrue
		if mathpointer#=(no_pointer)
			add mathpointer :  #to pass the pointer
			if mathpointer#d=(member_end)
				add mathpointer (DWORD)
				return mathpointer
			end
			call action_one((ActionGetMember))

			#square_bracket_start
			add mathpointer (DWORD)
			setcall mathpointer action_code_right_util(mathpointer)
		else
			call action_one((ActionGetMember))

			set name action_code_get_pointer(#mathpointer)
			call action_push((ap_Constant8),name)
		end
	end
end
function action_member_loop_right(sv mathpointer) #get, ex get_member, get the object
	sd name
	set name action_code_get_pointer(#mathpointer)
	call action_get_one(name)
	whiletrue # member_end can be right from the start at CallMethod
		if mathpointer#!=(no_pointer)
			set name action_code_get_pointer(#mathpointer)
			call action_push((ap_Constant8),name)
		else
			add mathpointer :  #to pass the pointer
			if mathpointer#d=(square_bracket_start)
				add mathpointer (DWORD)
				setcall mathpointer action_code_right_util(mathpointer)
			else #member_end
				add mathpointer (DWORD)
				return mathpointer
			end
		end
		call action_one((ActionGetMember))
	end
end

import "action_code_member" action_code_member
#import "error" error
#function action_member_write(ss member)
#   const dup_member=256
#    charx dup_data#dup_member  #was dup, escape, parse on values append, code. maybe the expression string to be passed as is, but is not necessary now
#    vstr code^dup_data
#    sd len
#    setcall len strlen(member)
#    inc len
#    if len>(dup_member)
#        call error("actionscript code limit exceeded")
#    endif
#    call memcpy(code,member,len)
#    call forward_values_expand(action_member_write_tool,code)
#endfunction

#action

import "swf_actionrecordheader" swf_actionrecordheader
import "swf_mem_add" swf_mem_add
function write_action_base(sd id)
	sd block
	setcall block struct_ids_action((ids_get),id)
	sd mem
	setcall mem block_get_mem(block)
	sd size
	setcall size block_get_size(block)
	call pool_wr(id)
	call swf_mem_add(mem,size)
	#this is ActionEndFlag after ACTIONRECORD [zero or more]
	data end=0
	callg swf_mem_add(#end,1)
end
import "pool_done" pool_done
function write_action(sd id,sd frame)
	call write_action_base(id)
	callg pool_done(id,frame)
endfunction
import "pool_done_one" pool_done_one
function write_action_one(sd id)
	call write_action_base(id)
	callg pool_done_one(id)
endfunction
#void
function pool_wr(sd id)
    sd poolblock
    setcall poolblock struct_ids_actionpool((ids_get),id)
    sd ?poolsize
    setcall poolsize block_get_size(poolblock)
    #detected at button actions="", swfdump giving error without "if poolsize!=0"
    if poolsize=0;return 0;endif
    sd poolmem
    setcall poolmem block_get_mem(poolblock)
	if poolsize>^(maxuint16)
		call error("error at pool size")
	end
	call swf_actionrecordheader((ActionConstantPool),poolsize)
	callg swf_mem_add(poolmem,poolsize)
endfunction

#format and alt

import "action_base" action_base

function action_format(ss buffer,sv %the_va_list)
	if buffer!=(NULL)
		call sprintf_manual(buffer,the_va_list)
	else
		callret sprintf_manual((NULL),the_va_list)
	end
	call format_store(buffer)
	callg action_base(buffer)
endfunction
function action_format_wrap(sv %the_va_list)
	base globalu.jmp_data;call ebase(globalu.jmp_data)
	callret action_format((NULL),the_va_list)
end
function actions_format(svu psize,sv pbuf,sv %the_va_list)
	ss buf
	set buf pbuf#
	if psize=(NULL)
		callret action_format(buf,the_va_list)
	end
	sdu size
	%&a_va_list
	set size action_format_wrap(the_va_list) #here at c will replace with a_va_list
	%>
	ss p;setcall p erbool();if p#=0
		vstr er="malloc error at actionsf"
		if buf=(NULL)
			set buf malloc(size)
			if buf=(NULL)
				call error(er)
			end
			set pbuf# buf
			set psize# size
		elseif size>^psize#
			set buf realloc(buf,size)
			if buf=(NULL)
				call error(er)
			end
			set pbuf# buf
			set psize# size
		end
		callg action_format(buf,the_va_list)
	end
end

import "debug_base" debug_base
^import "alt_action_base" alt_action_base 3 #full return

function action_sprite_base(sd sprite,ss actions,ss ?has_frames)
	sd alt_ac;set alt_ac alt_action_base(actions,sprite,has_frames)
	if alt_ac!=(NULL)
		call debug_base(sprite)
		call swf_actionblock_change(sprite)
		call action_base(alt_ac)
		if alt_ac!=actions
			call file_get_content__resources_free()
		end
		call swf_actionblock_change_back()
	end
endfunction

import "error" error

function sprintf_manual(ss string,sv %the_va_list)
	ss format
	%|format
	!set format the_va_list#
	!add the_va_list :

	ss pointer;set pointer format
	ss ?has_element=FALSE
	ss ?escaped=0
	svu writable_size=1
	ss writable;set writable malloc(1) #this approach is not checking the format style: 0 or more flags, width, precision, modifiers, conversion
	vstr er="malloc error at manual sprintf"
	if writable=(NULL)
		call error(er)
	end
	sd ?n ; # for snprintf int return
	vstr err="unsafe action"
	sdu total_size
	if string=(NULL)
		set total_size 0
	end
	sv ?el
	while pointer#!=(Nullchar)
		if pointer#=(Percent)
			xor escaped 1
		elseif escaped=1
			set escaped 0
			#this is not working nowadays, printf is searching for floats on xmm registers. extract floats
			#char l="l";if pointer#=l;char f="f";ss double_test=1;add double_test pointer;if double_test#=f;inc nr;endif;endif

			if has_element=(FALSE)
				set has_element (TRUE)
			else
				valueu size#1;set size pointer;sub size format
				if size>^writable_size
					ss mem;set mem realloc(writable,size)
					if mem=(NULL)
						call free(writable)
						call error(er)
					end
					set writable mem
					set writable_size size
				end

				dec pointer
				#c is giving no write access to strings #set pointer# (Nullchar)
				dec size
				call memcpy(writable,format,size)
				ss marker;set marker writable;add marker size;set marker# (Nullchar)

				%|el
				!set el the_va_list#
				if string!=(NULL)
					add string sprintf(string,writable,el)
				else
					set n snprintf((NULL),0,writable,el)
					if n<0
						call error(err)
					end
					add total_size n
				end
				!incst the_va_list

				set format pointer
				#set pointer# (Percent)
				inc pointer ##not adding 2 here and continue? or let for a pointer# >= unicode start condition?
			end
		endelseif
		inc pointer
	endwhile
	call free(writable)
	if has_element=(TRUE)
		%|el
		!set el the_va_list#
		if string!=(NULL)
			call sprintf(string,format,el)
		else
			set n snprintf((NULL),0,format,el)
			if n<0
				callg error(err)
			end
			add total_size n
			inc total_size
			return total_size
		end
	else
		if string!=(NULL)
			call strcpy(string,format)
		else
			sdu m=1;add m strlen(format)
			return m
		end
	end
endfunction

^import "strlen_of" strlen_of 2
^import "memalloc" memalloc 1
^import "f_open_mem" f_open_mem 2
function format_init(sd ?flags,ss path)
	if globalu.format_file!=(NULL)
		call error("swf started, format file not closed")
	end
	and flags (flag_format)
	if flags=(flag_format)
		sd size;setcall size strlen_of(path,7+1) #8+not_gigantic
		sd a;setcall a memalloc(size)
		call sprintf(a,"%s.format",path)
		setcall globalu.format_file f_open_mem(a,"wb")
	end
end

import "f_write" f_write
function format_store(ss ac)
	if globalu.format_file!=(NULL)
		sd sz=1;add sz strlen(ac)
		callg f_write(globalu.format_file,ac,sz)
	end
end

entryraw globalu()
