@@ -162,9 +162,15 @@ def _complex_member_type(self, ri):
162162 def free_needs_iter (self ):
163163 return False
164164
165- def free (self , ri , var , ref ):
165+ def _free_lines (self , ri , var , ref ):
166166 if self .is_multi_val () or self .presence_type () == 'len' :
167- ri .cw .p (f'free({ var } ->{ ref } { self .c_name } );' )
167+ return [f'free({ var } ->{ ref } { self .c_name } );' ]
168+ return []
169+
170+ def free (self , ri , var , ref ):
171+ lines = self ._free_lines (ri , var , ref )
172+ for line in lines :
173+ ri .cw .p (line )
168174
169175 def arg_member (self , ri ):
170176 member = self ._complex_member_type (ri )
@@ -263,6 +269,10 @@ def setter(self, ri, space, direction, deref=False, ref=None):
263269 var = "req"
264270 member = f"{ var } ->{ '.' .join (ref )} "
265271
272+ local_vars = []
273+ if self .free_needs_iter ():
274+ local_vars += ['unsigned int i;' ]
275+
266276 code = []
267277 presence = ''
268278 for i in range (0 , len (ref )):
@@ -272,14 +282,19 @@ def setter(self, ri, space, direction, deref=False, ref=None):
272282 if i == len (ref ) - 1 and self .presence_type () != 'bit' :
273283 continue
274284 code .append (presence + ' = 1;' )
285+ ref_path = '.' .join (ref [:- 1 ])
286+ if ref_path :
287+ ref_path += '.'
288+ code += self ._free_lines (ri , var , ref_path )
275289 code += self ._setter_lines (ri , member , presence )
276290
277291 func_name = f"{ op_prefix (ri , direction , deref = deref )} _set_{ '_' .join (ref )} "
278292 free = bool ([x for x in code if 'free(' in x ])
279293 alloc = bool ([x for x in code if 'alloc(' in x ])
280294 if free and not alloc :
281295 func_name = '__' + func_name
282- ri .cw .write_func ('static inline void' , func_name , body = code ,
296+ ri .cw .write_func ('static inline void' , func_name , local_vars = local_vars ,
297+ body = code ,
283298 args = [f'{ type_name (ri , direction , deref = deref )} *{ var } ' ] + self .arg_member (ri ))
284299
285300
@@ -482,8 +497,7 @@ def _attr_get(self, ri, var):
482497 ['unsigned int len;' ]
483498
484499 def _setter_lines (self , ri , member , presence ):
485- return [f"free({ member } );" ,
486- f"{ presence } _len = strlen({ self .c_name } );" ,
500+ return [f"{ presence } _len = strlen({ self .c_name } );" ,
487501 f"{ member } = malloc({ presence } _len + 1);" ,
488502 f'memcpy({ member } , { self .c_name } , { presence } _len);' ,
489503 f'{ member } [{ presence } _len] = 0;' ]
@@ -536,8 +550,7 @@ def _attr_get(self, ri, var):
536550 ['unsigned int len;' ]
537551
538552 def _setter_lines (self , ri , member , presence ):
539- return [f"free({ member } );" ,
540- f"{ presence } _len = len;" ,
553+ return [f"{ presence } _len = len;" ,
541554 f"{ member } = malloc({ presence } _len);" ,
542555 f'memcpy({ member } , { self .c_name } , { presence } _len);' ]
543556
@@ -574,12 +587,14 @@ def is_recursive(self):
574587 def _complex_member_type (self , ri ):
575588 return self .nested_struct_type
576589
577- def free (self , ri , var , ref ):
590+ def _free_lines (self , ri , var , ref ):
591+ lines = []
578592 at = '&'
579593 if self .is_recursive_for_op (ri ):
580594 at = ''
581- ri .cw .p (f'if ({ var } ->{ ref } { self .c_name } )' )
582- ri .cw .p (f'{ self .nested_render_name } _free({ at } { var } ->{ ref } { self .c_name } );' )
595+ lines += [f'if ({ var } ->{ ref } { self .c_name } )' ]
596+ lines += [f'{ self .nested_render_name } _free({ at } { var } ->{ ref } { self .c_name } );' ]
597+ return lines
583598
584599 def _attr_typol (self ):
585600 return f'.type = YNL_PT_NEST, .nest = &{ self .nested_render_name } _nest, '
@@ -632,15 +647,19 @@ def _complex_member_type(self, ri):
632647 def free_needs_iter (self ):
633648 return 'type' not in self .attr or self .attr ['type' ] == 'nest'
634649
635- def free (self , ri , var , ref ):
650+ def _free_lines (self , ri , var , ref ):
651+ lines = []
636652 if self .attr ['type' ] in scalars :
637- ri . cw . p ( f"free({ var } ->{ ref } { self .c_name } );" )
653+ lines += [ f"free({ var } ->{ ref } { self .c_name } );" ]
638654 elif 'type' not in self .attr or self .attr ['type' ] == 'nest' :
639- ri .cw .p (f"for (i = 0; i < { var } ->{ ref } n_{ self .c_name } ; i++)" )
640- ri .cw .p (f'{ self .nested_render_name } _free(&{ var } ->{ ref } { self .c_name } [i]);' )
641- ri .cw .p (f"free({ var } ->{ ref } { self .c_name } );" )
655+ lines += [
656+ f"for (i = 0; i < { var } ->{ ref } n_{ self .c_name } ; i++)" ,
657+ f'{ self .nested_render_name } _free(&{ var } ->{ ref } { self .c_name } [i]);' ,
658+ f"free({ var } ->{ ref } { self .c_name } );" ,
659+ ]
642660 else :
643661 raise Exception (f"Free of MultiAttr sub-type { self .attr ['type' ]} not supported yet" )
662+ return lines
644663
645664 def _attr_policy (self , policy ):
646665 return self .base_type ._attr_policy (policy )
@@ -654,10 +673,10 @@ def _attr_get(self, ri, var):
654673 def attr_put (self , ri , var ):
655674 if self .attr ['type' ] in scalars :
656675 put_type = self .type
657- ri .cw .p (f"for (unsigned int i = 0; i < { var } ->n_{ self .c_name } ; i++)" )
676+ ri .cw .p (f"for (i = 0; i < { var } ->n_{ self .c_name } ; i++)" )
658677 ri .cw .p (f"ynl_attr_put_{ put_type } (nlh, { self .enum_name } , { var } ->{ self .c_name } [i]);" )
659678 elif 'type' not in self .attr or self .attr ['type' ] == 'nest' :
660- ri .cw .p (f"for (unsigned int i = 0; i < { var } ->n_{ self .c_name } ; i++)" )
679+ ri .cw .p (f"for (i = 0; i < { var } ->n_{ self .c_name } ; i++)" )
661680 self ._attr_put_line (ri , var , f"{ self .nested_render_name } _put(nlh, " +
662681 f"{ self .enum_name } , &{ var } ->{ self .c_name } [i])" )
663682 else :
@@ -666,8 +685,7 @@ def attr_put(self, ri, var):
666685 def _setter_lines (self , ri , member , presence ):
667686 # For multi-attr we have a count, not presence, hack up the presence
668687 presence = presence [:- (len ('_present.' ) + len (self .c_name ))] + "n_" + self .c_name
669- return [f"free({ member } );" ,
670- f"{ member } = { self .c_name } ;" ,
688+ return [f"{ member } = { self .c_name } ;" ,
671689 f"{ presence } = n_{ self .c_name } ;" ]
672690
673691
@@ -696,8 +714,11 @@ def _attr_typol(self):
696714 def _attr_get (self , ri , var ):
697715 local_vars = ['const struct nlattr *attr2;' ]
698716 get_lines = [f'attr_{ self .c_name } = attr;' ,
699- 'ynl_attr_for_each_nested(attr2, attr)' ,
700- f'\t { var } ->n_{ self .c_name } ++;' ]
717+ 'ynl_attr_for_each_nested(attr2, attr) {' ,
718+ '\t if (ynl_attr_validate(yarg, attr2))' ,
719+ '\t \t return YNL_PARSE_CB_ERROR;' ,
720+ f'\t { var } ->n_{ self .c_name } ++;' ,
721+ '}' ]
701722 return get_lines , None , local_vars
702723
703724
@@ -755,6 +776,7 @@ def __init__(self, family, space_name, type_list=None, inherited=None):
755776 self .request = False
756777 self .reply = False
757778 self .recursive = False
779+ self .in_multi_val = False # used by a MultiAttr or and legacy arrays
758780
759781 self .attr_list = []
760782 self .attrs = dict ()
@@ -1122,6 +1144,10 @@ def _load_nested_sets(self):
11221144 if attr in rs_members ['reply' ]:
11231145 self .pure_nested_structs [nested ].reply = True
11241146
1147+ if spec .is_multi_val ():
1148+ child = self .pure_nested_structs .get (nested )
1149+ child .in_multi_val = True
1150+
11251151 self ._sort_pure_types ()
11261152
11271153 # Propagate the request / reply / recursive
@@ -1136,6 +1162,8 @@ def _load_nested_sets(self):
11361162 struct .child_nests .update (child .child_nests )
11371163 child .request |= struct .request
11381164 child .reply |= struct .reply
1165+ if spec .is_multi_val ():
1166+ child .in_multi_val = True
11391167 if attr_set in struct .child_nests :
11401168 struct .recursive = True
11411169
@@ -1399,9 +1427,9 @@ def write_func_lvar(self, local_vars):
13991427
14001428 def write_func (self , qual_ret , name , body , args = None , local_vars = None ):
14011429 self .write_func_prot (qual_ret = qual_ret , name = name , args = args )
1430+ self .block_start ()
14021431 self .write_func_lvar (local_vars = local_vars )
14031432
1404- self .block_start ()
14051433 for line in body :
14061434 self .p (line )
14071435 self .block_end ()
@@ -1644,11 +1672,23 @@ def put_req_nested_prototype(ri, struct, suffix=';'):
16441672
16451673
16461674def put_req_nested (ri , struct ):
1675+ local_vars = []
1676+ init_lines = []
1677+
1678+ local_vars .append ('struct nlattr *nest;' )
1679+ init_lines .append ("nest = ynl_attr_nest_start(nlh, attr_type);" )
1680+
1681+ for _ , arg in struct .member_list ():
1682+ if arg .presence_type () == 'count' :
1683+ local_vars .append ('unsigned int i;' )
1684+ break
1685+
16471686 put_req_nested_prototype (ri , struct , suffix = '' )
16481687 ri .cw .block_start ()
1649- ri .cw .write_func_lvar ('struct nlattr *nest;' )
1688+ ri .cw .write_func_lvar (local_vars )
16501689
1651- ri .cw .p ("nest = ynl_attr_nest_start(nlh, attr_type);" )
1690+ for line in init_lines :
1691+ ri .cw .p (line )
16521692
16531693 for _ , arg in struct .member_list ():
16541694 arg .attr_put (ri , "obj" )
@@ -1850,6 +1890,11 @@ def print_req(ri):
18501890 local_vars += ['size_t hdr_len;' ,
18511891 'void *hdr;' ]
18521892
1893+ for _ , attr in ri .struct ["request" ].member_list ():
1894+ if attr .presence_type () == 'count' :
1895+ local_vars += ['unsigned int i;' ]
1896+ break
1897+
18531898 print_prototype (ri , direction , terminate = False )
18541899 ri .cw .block_start ()
18551900 ri .cw .write_func_lvar (local_vars )
@@ -2941,6 +2986,9 @@ def main():
29412986 for attr_set , struct in parsed .pure_nested_structs .items ():
29422987 ri = RenderInfo (cw , parsed , args .mode , "" , "" , attr_set )
29432988 print_type_full (ri , struct )
2989+ if struct .request and struct .in_multi_val :
2990+ free_rsp_nested_prototype (ri )
2991+ cw .nl ()
29442992
29452993 for op_name , op in parsed .ops .items ():
29462994 cw .p (f"/* ============== { op .enum_name } ============== */" )
0 commit comments