@@ -72,6 +72,7 @@ def detach_and_modify_auxillary_c_functions_from_statements
7272 if stmt . name == ALLOC_FUNC_NAME
7373 @auxillary_c_functions [ ALLOC_FUNC_NAME ] = stmt
7474 @user_defined_alloc = true
75+ modify_alloc_func stmt
7576 indexes << idx
7677 elsif stmt . name == DEALLOC_FUNC_NAME
7778 @auxillary_c_functions [ DEALLOC_FUNC_NAME ] = stmt
@@ -90,8 +91,8 @@ def detach_and_modify_auxillary_c_functions_from_statements
9091 end
9192 end
9293
93- indexes . each do |idx |
94- @statements . delete_at idx
94+ @statements . delete_if . with_index do |s , i |
95+ indexes . include? i
9596 end
9697 end
9798
@@ -100,10 +101,22 @@ def write_auxillary_c_functions(code)
100101 write_memcount_c_function code
101102 end
102103
104+ # FIXME : change this. its too ugly.
105+ def ugly_code_mod_hack code
106+ ret = ""
107+ ret << 'return TypedData_Wrap_Struct('
108+ ret << "#{ @alloc_c_func . type . arg_list [ 0 ] . entry . c_name } ,"
109+ ret << "&#{ @data_type_t } , #{ Rubex ::POINTER_PREFIX } data);\n "
110+
111+ c = code . instance_variable_get ( :@code )
112+ c . insert -4 , ret
113+ end
114+
103115 # Actually write the alloc function into C code.
104- def write_alloc_c_function ( code )
116+ def write_alloc_c_function ( code )
105117 if user_defined_alloc?
106118 @auxillary_c_functions [ ALLOC_FUNC_NAME ] . generate_code code
119+ ugly_code_mod_hack code
107120 else
108121 code . write_c_method_header (
109122 type : @alloc_c_func . type . type . to_s ,
@@ -122,7 +135,7 @@ def write_alloc_c_function(code)
122135 lines << 'return TypedData_Wrap_Struct('
123136 lines << "#{ @alloc_c_func . type . arg_list [ 0 ] . entry . c_name } ,"
124137 lines << "&#{ @data_type_t } , data);\n "
125-
138+
126139 code << lines
127140 end
128141 end
@@ -368,6 +381,71 @@ def prepare_get_struct_c_function
368381 end
369382 end
370383
384+ # In case of user supplied allocate function, add a statement at the
385+ # beginning to declare and obtain the data variable and also add a
386+ # return statement involving TypedDataStruct at the end so that the
387+ # user is freed from needing to write these.
388+ def modify_alloc_func ( func )
389+ stmts = [ ]
390+ stmts << data_var_cptr_decl ( nil )
391+ stmts . concat data_struct_allocations
392+ stmts . reverse . each do |s |
393+ func . statements . unshift s
394+ end
395+ end
396+
397+ # declare a pointer to a data struct.
398+ def data_var_cptr_decl ( value = nil )
399+ Statement ::CPtrDecl . new (
400+ @data_struct . entry . name , 'data' , value , '*' , @location )
401+ end
402+
403+ def data_struct_allocations
404+ stmts = [ ]
405+ # assign malloc for top level data struct
406+ rhs = Expression ::CommandCall . new (
407+ nil , 'xmalloc' ,
408+ Expression ::ActualArgList . new (
409+ [
410+ Expression ::SizeOf . new ( @data_struct . entry . name , '' )
411+ ] )
412+ )
413+ rhs . typecast = Expression ::Typecast . new ( @data_struct . entry . name , '*' )
414+ assign_data_struct = Statement ::Assign . new (
415+ Expression ::Name . new ( 'data' ) , rhs , @location
416+ )
417+
418+ stmts << assign_data_struct
419+ stmts << xmalloc_inner_struct_member
420+ stmts
421+ end
422+
423+ def xmalloc_inner_struct_member
424+ t = @scope . find ( @attached_type ) . name
425+ lhs = Expression ::CommandCall . new (
426+ Expression ::ElementRef . new (
427+ 'data' ,
428+ Expression ::ActualArgList . new (
429+ [
430+ Expression ::Literal ::Int . new ( '0' )
431+ ]
432+ )
433+ ) ,
434+ t ,
435+ nil
436+ )
437+ rhs = Expression ::CommandCall . new (
438+ nil , 'xmalloc' ,
439+ Expression ::ActualArgList . new (
440+ [
441+ Expression ::SizeOf . new ( t , '' )
442+ ]
443+ )
444+ )
445+ rhs . typecast = Expression ::Typecast . new ( t , '*' )
446+ Statement ::Assign . new ( lhs , rhs , @location )
447+ end
448+
371449 # Modify the dealloc function by adding an argument of type void* so
372450 # that it is compatible with what Ruby expects. This is done so that
373451 # the user is not burdened with additional knowledge of knowing the
0 commit comments