1 #!/usr/bin/env python3 1 #!/usr/bin/env python3 2 # SPDX-License-Identifier: ((GPL-2.0 WITH Linu 2 # SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 3 3 4 import argparse 4 import argparse 5 import collections 5 import collections 6 import filecmp << 7 import os 6 import os 8 import re << 9 import shutil << 10 import tempfile << 11 import yaml 7 import yaml 12 8 13 from lib import SpecFamily, SpecAttrSet, SpecA 9 from lib import SpecFamily, SpecAttrSet, SpecAttr, SpecOperation, SpecEnumSet, SpecEnumEntry 14 10 15 11 16 def c_upper(name): 12 def c_upper(name): 17 return name.upper().replace('-', '_') 13 return name.upper().replace('-', '_') 18 14 19 15 20 def c_lower(name): 16 def c_lower(name): 21 return name.lower().replace('-', '_') 17 return name.lower().replace('-', '_') 22 18 23 19 24 def limit_to_number(name): << 25 """ << 26 Turn a string limit like u32-max or s64-mi << 27 """ << 28 if name[0] == 'u' and name.endswith('-min' << 29 return 0 << 30 width = int(name[1:-4]) << 31 if name[0] == 's': << 32 width -= 1 << 33 value = (1 << width) - 1 << 34 if name[0] == 's' and name.endswith('-min' << 35 value = -value - 1 << 36 return value << 37 << 38 << 39 class BaseNlLib: 20 class BaseNlLib: 40 def get_family_id(self): 21 def get_family_id(self): 41 return 'ys->family_id' 22 return 'ys->family_id' 42 23 >> 24 def parse_cb_run(self, cb, data, is_dump=False, indent=1): >> 25 ind = '\n\t\t' + '\t' * indent + ' ' >> 26 if is_dump: >> 27 return f"mnl_cb_run2(ys->rx_buf, len, 0, 0, {cb}, {data},{ind}ynl_cb_array, NLMSG_MIN_TYPE)" >> 28 else: >> 29 return f"mnl_cb_run2(ys->rx_buf, len, ys->seq, ys->portid,{ind}{cb}, {data},{ind}" + \ >> 30 "ynl_cb_array, NLMSG_MIN_TYPE)" >> 31 43 32 44 class Type(SpecAttr): 33 class Type(SpecAttr): 45 def __init__(self, family, attr_set, attr, 34 def __init__(self, family, attr_set, attr, value): 46 super().__init__(family, attr_set, att 35 super().__init__(family, attr_set, attr, value) 47 36 48 self.attr = attr 37 self.attr = attr 49 self.attr_set = attr_set 38 self.attr_set = attr_set 50 self.type = attr['type'] 39 self.type = attr['type'] 51 self.checks = attr.get('checks', {}) 40 self.checks = attr.get('checks', {}) 52 41 53 self.request = False << 54 self.reply = False << 55 << 56 if 'len' in attr: 42 if 'len' in attr: 57 self.len = attr['len'] 43 self.len = attr['len'] 58 << 59 if 'nested-attributes' in attr: 44 if 'nested-attributes' in attr: 60 self.nested_attrs = attr['nested-a 45 self.nested_attrs = attr['nested-attributes'] 61 if self.nested_attrs == family.nam 46 if self.nested_attrs == family.name: 62 self.nested_render_name = c_lo !! 47 self.nested_render_name = f"{family.name}" 63 else: << 64 self.nested_render_name = c_lo << 65 << 66 if self.nested_attrs in self.famil << 67 self.nested_struct_type = 'str << 68 else: 48 else: 69 self.nested_struct_type = 'str !! 49 self.nested_render_name = f"{family.name}_{c_lower(self.nested_attrs)}" 70 50 71 self.c_name = c_lower(self.name) 51 self.c_name = c_lower(self.name) 72 if self.c_name in _C_KW: 52 if self.c_name in _C_KW: 73 self.c_name += '_' 53 self.c_name += '_' 74 54 75 # Added by resolve(): 55 # Added by resolve(): 76 self.enum_name = None 56 self.enum_name = None 77 delattr(self, "enum_name") 57 delattr(self, "enum_name") 78 58 79 def get_limit(self, limit, default=None): << 80 value = self.checks.get(limit, default << 81 if value is None: << 82 return value << 83 elif value in self.family.consts: << 84 return c_upper(f"{self.family['nam << 85 if not isinstance(value, int): << 86 value = limit_to_number(value) << 87 return value << 88 << 89 def resolve(self): 59 def resolve(self): 90 if 'name-prefix' in self.attr: !! 60 self.enum_name = f"{self.attr_set.name_prefix}{self.name}" 91 enum_name = f"{self.attr['name-pre !! 61 self.enum_name = c_upper(self.enum_name) 92 else: << 93 enum_name = f"{self.attr_set.name_ << 94 self.enum_name = c_upper(enum_name) << 95 62 96 def is_multi_val(self): 63 def is_multi_val(self): 97 return None 64 return None 98 65 99 def is_scalar(self): 66 def is_scalar(self): 100 return self.type in {'u8', 'u16', 'u32 67 return self.type in {'u8', 'u16', 'u32', 'u64', 's32', 's64'} 101 68 102 def is_recursive(self): << 103 return False << 104 << 105 def is_recursive_for_op(self, ri): << 106 return self.is_recursive() and not ri. << 107 << 108 def presence_type(self): 69 def presence_type(self): 109 return 'bit' 70 return 'bit' 110 71 111 def presence_member(self, space, type_filt 72 def presence_member(self, space, type_filter): 112 if self.presence_type() != type_filter 73 if self.presence_type() != type_filter: 113 return 74 return 114 75 115 if self.presence_type() == 'bit': 76 if self.presence_type() == 'bit': 116 pfx = '__' if space == 'user' else 77 pfx = '__' if space == 'user' else '' 117 return f"{pfx}u32 {self.c_name}:1; 78 return f"{pfx}u32 {self.c_name}:1;" 118 79 119 if self.presence_type() == 'len': 80 if self.presence_type() == 'len': 120 pfx = '__' if space == 'user' else 81 pfx = '__' if space == 'user' else '' 121 return f"{pfx}u32 {self.c_name}_le 82 return f"{pfx}u32 {self.c_name}_len;" 122 83 123 def _complex_member_type(self, ri): 84 def _complex_member_type(self, ri): 124 return None 85 return None 125 86 126 def free_needs_iter(self): 87 def free_needs_iter(self): 127 return False 88 return False 128 89 129 def free(self, ri, var, ref): 90 def free(self, ri, var, ref): 130 if self.is_multi_val() or self.presenc 91 if self.is_multi_val() or self.presence_type() == 'len': 131 ri.cw.p(f'free({var}->{ref}{self.c 92 ri.cw.p(f'free({var}->{ref}{self.c_name});') 132 93 133 def arg_member(self, ri): 94 def arg_member(self, ri): 134 member = self._complex_member_type(ri) 95 member = self._complex_member_type(ri) 135 if member: 96 if member: 136 arg = [member + ' *' + self.c_name !! 97 return [member + ' *' + self.c_name] 137 if self.presence_type() == 'count' << 138 arg += ['unsigned int n_' + se << 139 return arg << 140 raise Exception(f"Struct member not im 98 raise Exception(f"Struct member not implemented for class type {self.type}") 141 99 142 def struct_member(self, ri): 100 def struct_member(self, ri): 143 if self.is_multi_val(): 101 if self.is_multi_val(): 144 ri.cw.p(f"unsigned int n_{self.c_n 102 ri.cw.p(f"unsigned int n_{self.c_name};") 145 member = self._complex_member_type(ri) 103 member = self._complex_member_type(ri) 146 if member: 104 if member: 147 ptr = '*' if self.is_multi_val() e 105 ptr = '*' if self.is_multi_val() else '' 148 if self.is_recursive_for_op(ri): << 149 ptr = '*' << 150 ri.cw.p(f"{member} {ptr}{self.c_na 106 ri.cw.p(f"{member} {ptr}{self.c_name};") 151 return 107 return 152 members = self.arg_member(ri) 108 members = self.arg_member(ri) 153 for one in members: 109 for one in members: 154 ri.cw.p(one + ';') 110 ri.cw.p(one + ';') 155 111 156 def _attr_policy(self, policy): 112 def _attr_policy(self, policy): 157 return '{ .type = ' + policy + ', }' 113 return '{ .type = ' + policy + ', }' 158 114 159 def attr_policy(self, cw): 115 def attr_policy(self, cw): 160 policy = c_upper('nla-' + self.attr['t 116 policy = c_upper('nla-' + self.attr['type']) 161 117 162 spec = self._attr_policy(policy) 118 spec = self._attr_policy(policy) 163 cw.p(f"\t[{self.enum_name}] = {spec}," 119 cw.p(f"\t[{self.enum_name}] = {spec},") 164 120 165 def _attr_typol(self): 121 def _attr_typol(self): 166 raise Exception(f"Type policy not impl 122 raise Exception(f"Type policy not implemented for class type {self.type}") 167 123 168 def attr_typol(self, cw): 124 def attr_typol(self, cw): 169 typol = self._attr_typol() 125 typol = self._attr_typol() 170 cw.p(f'[{self.enum_name}] = {"{"} .nam 126 cw.p(f'[{self.enum_name}] = {"{"} .name = "{self.name}", {typol}{"}"},') 171 127 172 def _attr_put_line(self, ri, var, line): 128 def _attr_put_line(self, ri, var, line): 173 if self.presence_type() == 'bit': 129 if self.presence_type() == 'bit': 174 ri.cw.p(f"if ({var}->_present.{sel 130 ri.cw.p(f"if ({var}->_present.{self.c_name})") 175 elif self.presence_type() == 'len': 131 elif self.presence_type() == 'len': 176 ri.cw.p(f"if ({var}->_present.{sel 132 ri.cw.p(f"if ({var}->_present.{self.c_name}_len)") 177 ri.cw.p(f"{line};") 133 ri.cw.p(f"{line};") 178 134 179 def _attr_put_simple(self, ri, var, put_ty 135 def _attr_put_simple(self, ri, var, put_type): 180 line = f"ynl_attr_put_{put_type}(nlh, !! 136 line = f"mnl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name})" 181 self._attr_put_line(ri, var, line) 137 self._attr_put_line(ri, var, line) 182 138 183 def attr_put(self, ri, var): 139 def attr_put(self, ri, var): 184 raise Exception(f"Put not implemented 140 raise Exception(f"Put not implemented for class type {self.type}") 185 141 186 def _attr_get(self, ri, var): 142 def _attr_get(self, ri, var): 187 raise Exception(f"Attr get not impleme 143 raise Exception(f"Attr get not implemented for class type {self.type}") 188 144 189 def attr_get(self, ri, var, first): 145 def attr_get(self, ri, var, first): 190 lines, init_lines, local_vars = self._ 146 lines, init_lines, local_vars = self._attr_get(ri, var) 191 if type(lines) is str: 147 if type(lines) is str: 192 lines = [lines] 148 lines = [lines] 193 if type(init_lines) is str: 149 if type(init_lines) is str: 194 init_lines = [init_lines] 150 init_lines = [init_lines] 195 151 196 kw = 'if' if first else 'else if' 152 kw = 'if' if first else 'else if' 197 ri.cw.block_start(line=f"{kw} (type == !! 153 ri.cw.block_start(line=f"{kw} (mnl_attr_get_type(attr) == {self.enum_name})") 198 if local_vars: 154 if local_vars: 199 for local in local_vars: 155 for local in local_vars: 200 ri.cw.p(local) 156 ri.cw.p(local) 201 ri.cw.nl() 157 ri.cw.nl() 202 158 203 if not self.is_multi_val(): 159 if not self.is_multi_val(): 204 ri.cw.p("if (ynl_attr_validate(yar 160 ri.cw.p("if (ynl_attr_validate(yarg, attr))") 205 ri.cw.p("return YNL_PARSE_CB_ERROR !! 161 ri.cw.p("return MNL_CB_ERROR;") 206 if self.presence_type() == 'bit': 162 if self.presence_type() == 'bit': 207 ri.cw.p(f"{var}->_present.{sel 163 ri.cw.p(f"{var}->_present.{self.c_name} = 1;") 208 164 209 if init_lines: 165 if init_lines: 210 ri.cw.nl() 166 ri.cw.nl() 211 for line in init_lines: 167 for line in init_lines: 212 ri.cw.p(line) 168 ri.cw.p(line) 213 169 214 for line in lines: 170 for line in lines: 215 ri.cw.p(line) 171 ri.cw.p(line) 216 ri.cw.block_end() 172 ri.cw.block_end() 217 return True << 218 173 219 def _setter_lines(self, ri, member, presen 174 def _setter_lines(self, ri, member, presence): 220 raise Exception(f"Setter not implement 175 raise Exception(f"Setter not implemented for class type {self.type}") 221 176 222 def setter(self, ri, space, direction, der 177 def setter(self, ri, space, direction, deref=False, ref=None): 223 ref = (ref if ref else []) + [self.c_n 178 ref = (ref if ref else []) + [self.c_name] 224 var = "req" 179 var = "req" 225 member = f"{var}->{'.'.join(ref)}" 180 member = f"{var}->{'.'.join(ref)}" 226 181 227 code = [] 182 code = [] 228 presence = '' 183 presence = '' 229 for i in range(0, len(ref)): 184 for i in range(0, len(ref)): 230 presence = f"{var}->{'.'.join(ref[ 185 presence = f"{var}->{'.'.join(ref[:i] + [''])}_present.{ref[i]}" 231 # Every layer below last is a nest !! 186 if self.presence_type() == 'bit': 232 # last layer is "self" and may be !! 187 code.append(presence + ' = 1;') 233 if i == len(ref) - 1 and self.pres << 234 continue << 235 code.append(presence + ' = 1;') << 236 code += self._setter_lines(ri, member, 188 code += self._setter_lines(ri, member, presence) 237 189 238 func_name = f"{op_prefix(ri, direction !! 190 ri.cw.write_func('static inline void', 239 free = bool([x for x in code if 'free( !! 191 f"{op_prefix(ri, direction, deref=deref)}_set_{'_'.join(ref)}", 240 alloc = bool([x for x in code if 'allo !! 192 body=code, 241 if free and not alloc: << 242 func_name = '__' + func_name << 243 ri.cw.write_func('static inline void', << 244 args=[f'{type_name(ri 193 args=[f'{type_name(ri, direction, deref=deref)} *{var}'] + self.arg_member(ri)) 245 194 246 195 247 class TypeUnused(Type): 196 class TypeUnused(Type): 248 def presence_type(self): 197 def presence_type(self): 249 return '' 198 return '' 250 199 251 def arg_member(self, ri): << 252 return [] << 253 << 254 def _attr_get(self, ri, var): << 255 return ['return YNL_PARSE_CB_ERROR;'], << 256 << 257 def _attr_typol(self): 200 def _attr_typol(self): 258 return '.type = YNL_PT_REJECT, ' 201 return '.type = YNL_PT_REJECT, ' 259 202 260 def attr_policy(self, cw): 203 def attr_policy(self, cw): 261 pass 204 pass 262 205 263 def attr_put(self, ri, var): << 264 pass << 265 << 266 def attr_get(self, ri, var, first): << 267 pass << 268 << 269 def setter(self, ri, space, direction, der << 270 pass << 271 << 272 206 273 class TypePad(Type): 207 class TypePad(Type): 274 def presence_type(self): 208 def presence_type(self): 275 return '' 209 return '' 276 210 277 def arg_member(self, ri): << 278 return [] << 279 << 280 def _attr_typol(self): 211 def _attr_typol(self): 281 return '.type = YNL_PT_IGNORE, ' !! 212 return '.type = YNL_PT_REJECT, ' 282 << 283 def attr_put(self, ri, var): << 284 pass << 285 << 286 def attr_get(self, ri, var, first): << 287 pass << 288 213 289 def attr_policy(self, cw): 214 def attr_policy(self, cw): 290 pass 215 pass 291 216 292 def setter(self, ri, space, direction, der << 293 pass << 294 << 295 217 296 class TypeScalar(Type): 218 class TypeScalar(Type): 297 def __init__(self, family, attr_set, attr, 219 def __init__(self, family, attr_set, attr, value): 298 super().__init__(family, attr_set, att 220 super().__init__(family, attr_set, attr, value) 299 221 300 self.byte_order_comment = '' 222 self.byte_order_comment = '' 301 if 'byte-order' in attr: 223 if 'byte-order' in attr: 302 self.byte_order_comment = f" /* {a 224 self.byte_order_comment = f" /* {attr['byte-order']} */" 303 225 304 if 'enum' in self.attr: << 305 enum = self.family.consts[self.att << 306 low, high = enum.value_range() << 307 if 'min' not in self.checks: << 308 if low != 0 or self.type[0] == << 309 self.checks['min'] = low << 310 if 'max' not in self.checks: << 311 self.checks['max'] = high << 312 << 313 if 'min' in self.checks and 'max' in s << 314 if self.get_limit('min') > self.ge << 315 raise Exception(f'Invalid limi << 316 self.checks['range'] = True << 317 << 318 low = min(self.get_limit('min', 0), se << 319 high = max(self.get_limit('min', 0), s << 320 if low < 0 and self.type[0] == 'u': << 321 raise Exception(f'Invalid limit fo << 322 if low < -32768 or high > 32767: << 323 self.checks['full-range'] = True << 324 << 325 # Added by resolve(): 226 # Added by resolve(): 326 self.is_bitfield = None 227 self.is_bitfield = None 327 delattr(self, "is_bitfield") 228 delattr(self, "is_bitfield") 328 self.type_name = None 229 self.type_name = None 329 delattr(self, "type_name") 230 delattr(self, "type_name") 330 231 331 def resolve(self): 232 def resolve(self): 332 self.resolve_up(super()) 233 self.resolve_up(super()) 333 234 334 if 'enum-as-flags' in self.attr and se 235 if 'enum-as-flags' in self.attr and self.attr['enum-as-flags']: 335 self.is_bitfield = True 236 self.is_bitfield = True 336 elif 'enum' in self.attr: 237 elif 'enum' in self.attr: 337 self.is_bitfield = self.family.con 238 self.is_bitfield = self.family.consts[self.attr['enum']]['type'] == 'flags' 338 else: 239 else: 339 self.is_bitfield = False 240 self.is_bitfield = False 340 241 341 if not self.is_bitfield and 'enum' in !! 242 if 'enum' in self.attr and not self.is_bitfield: 342 self.type_name = self.family.const !! 243 self.type_name = f"enum {self.family.name}_{c_lower(self.attr['enum'])}" 343 elif self.is_auto_scalar: << 344 self.type_name = '__' + self.type[ << 345 else: 244 else: 346 self.type_name = '__' + self.type 245 self.type_name = '__' + self.type 347 246 >> 247 def _mnl_type(self): >> 248 t = self.type >> 249 # mnl does not have a helper for signed types >> 250 if t[0] == 's': >> 251 t = 'u' + t[1:] >> 252 return t >> 253 348 def _attr_policy(self, policy): 254 def _attr_policy(self, policy): 349 if 'flags-mask' in self.checks or self 255 if 'flags-mask' in self.checks or self.is_bitfield: 350 if self.is_bitfield: 256 if self.is_bitfield: 351 enum = self.family.consts[self 257 enum = self.family.consts[self.attr['enum']] 352 mask = enum.get_mask(as_flags= 258 mask = enum.get_mask(as_flags=True) 353 else: 259 else: 354 flags = self.family.consts[sel 260 flags = self.family.consts[self.checks['flags-mask']] 355 flag_cnt = len(flags['entries' 261 flag_cnt = len(flags['entries']) 356 mask = (1 << flag_cnt) - 1 262 mask = (1 << flag_cnt) - 1 357 return f"NLA_POLICY_MASK({policy}, 263 return f"NLA_POLICY_MASK({policy}, 0x{mask:x})" 358 elif 'full-range' in self.checks: << 359 return f"NLA_POLICY_FULL_RANGE({po << 360 elif 'range' in self.checks: << 361 return f"NLA_POLICY_RANGE({policy} << 362 elif 'min' in self.checks: 264 elif 'min' in self.checks: 363 return f"NLA_POLICY_MIN({policy}, !! 265 return f"NLA_POLICY_MIN({policy}, {self.checks['min']})" 364 elif 'max' in self.checks: !! 266 elif 'enum' in self.attr: 365 return f"NLA_POLICY_MAX({policy}, !! 267 enum = self.family.consts[self.attr['enum']] >> 268 cnt = len(enum['entries']) >> 269 return f"NLA_POLICY_MAX({policy}, {cnt - 1})" 366 return super()._attr_policy(policy) 270 return super()._attr_policy(policy) 367 271 368 def _attr_typol(self): 272 def _attr_typol(self): 369 return f'.type = YNL_PT_U{c_upper(self !! 273 return f'.type = YNL_PT_U{self.type[1:]}, ' 370 274 371 def arg_member(self, ri): 275 def arg_member(self, ri): 372 return [f'{self.type_name} {self.c_nam 276 return [f'{self.type_name} {self.c_name}{self.byte_order_comment}'] 373 277 374 def attr_put(self, ri, var): 278 def attr_put(self, ri, var): 375 self._attr_put_simple(ri, var, self.ty !! 279 self._attr_put_simple(ri, var, self._mnl_type()) 376 280 377 def _attr_get(self, ri, var): 281 def _attr_get(self, ri, var): 378 return f"{var}->{self.c_name} = ynl_at !! 282 return f"{var}->{self.c_name} = mnl_attr_get_{self._mnl_type()}(attr);", None, None 379 283 380 def _setter_lines(self, ri, member, presen 284 def _setter_lines(self, ri, member, presence): 381 return [f"{member} = {self.c_name};"] 285 return [f"{member} = {self.c_name};"] 382 286 383 287 384 class TypeFlag(Type): 288 class TypeFlag(Type): 385 def arg_member(self, ri): 289 def arg_member(self, ri): 386 return [] 290 return [] 387 291 388 def _attr_typol(self): 292 def _attr_typol(self): 389 return '.type = YNL_PT_FLAG, ' 293 return '.type = YNL_PT_FLAG, ' 390 294 391 def attr_put(self, ri, var): 295 def attr_put(self, ri, var): 392 self._attr_put_line(ri, var, f"ynl_att !! 296 self._attr_put_line(ri, var, f"mnl_attr_put(nlh, {self.enum_name}, 0, NULL)") 393 297 394 def _attr_get(self, ri, var): 298 def _attr_get(self, ri, var): 395 return [], None, None 299 return [], None, None 396 300 397 def _setter_lines(self, ri, member, presen 301 def _setter_lines(self, ri, member, presence): 398 return [] 302 return [] 399 303 400 304 401 class TypeString(Type): 305 class TypeString(Type): 402 def arg_member(self, ri): 306 def arg_member(self, ri): 403 return [f"const char *{self.c_name}"] 307 return [f"const char *{self.c_name}"] 404 308 405 def presence_type(self): 309 def presence_type(self): 406 return 'len' 310 return 'len' 407 311 408 def struct_member(self, ri): 312 def struct_member(self, ri): 409 ri.cw.p(f"char *{self.c_name};") 313 ri.cw.p(f"char *{self.c_name};") 410 314 411 def _attr_typol(self): 315 def _attr_typol(self): 412 return f'.type = YNL_PT_NUL_STR, ' 316 return f'.type = YNL_PT_NUL_STR, ' 413 317 414 def _attr_policy(self, policy): 318 def _attr_policy(self, policy): 415 if 'exact-len' in self.checks: !! 319 mem = '{ .type = ' + policy 416 mem = 'NLA_POLICY_EXACT_LEN(' + st !! 320 if 'max-len' in self.checks: 417 else: !! 321 mem += ', .len = ' + str(self.checks['max-len']) 418 mem = '{ .type = ' + policy !! 322 mem += ', }' 419 if 'max-len' in self.checks: << 420 mem += ', .len = ' + str(self. << 421 mem += ', }' << 422 return mem 323 return mem 423 324 424 def attr_policy(self, cw): 325 def attr_policy(self, cw): 425 if self.checks.get('unterminated-ok', 326 if self.checks.get('unterminated-ok', False): 426 policy = 'NLA_STRING' 327 policy = 'NLA_STRING' 427 else: 328 else: 428 policy = 'NLA_NUL_STRING' 329 policy = 'NLA_NUL_STRING' 429 330 430 spec = self._attr_policy(policy) 331 spec = self._attr_policy(policy) 431 cw.p(f"\t[{self.enum_name}] = {spec}," 332 cw.p(f"\t[{self.enum_name}] = {spec},") 432 333 433 def attr_put(self, ri, var): 334 def attr_put(self, ri, var): 434 self._attr_put_simple(ri, var, 'str') !! 335 self._attr_put_simple(ri, var, 'strz') 435 336 436 def _attr_get(self, ri, var): 337 def _attr_get(self, ri, var): 437 len_mem = var + '->_present.' + self.c 338 len_mem = var + '->_present.' + self.c_name + '_len' 438 return [f"{len_mem} = len;", 339 return [f"{len_mem} = len;", 439 f"{var}->{self.c_name} = mallo 340 f"{var}->{self.c_name} = malloc(len + 1);", 440 f"memcpy({var}->{self.c_name}, !! 341 f"memcpy({var}->{self.c_name}, mnl_attr_get_str(attr), len);", 441 f"{var}->{self.c_name}[len] = 342 f"{var}->{self.c_name}[len] = 0;"], \ 442 ['len = strnlen(ynl_attr_get_st !! 343 ['len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));'], \ 443 ['unsigned int len;'] 344 ['unsigned int len;'] 444 345 445 def _setter_lines(self, ri, member, presen 346 def _setter_lines(self, ri, member, presence): 446 return [f"free({member});", 347 return [f"free({member});", 447 f"{presence}_len = strlen({sel 348 f"{presence}_len = strlen({self.c_name});", 448 f"{member} = malloc({presence} 349 f"{member} = malloc({presence}_len + 1);", 449 f'memcpy({member}, {self.c_nam 350 f'memcpy({member}, {self.c_name}, {presence}_len);', 450 f'{member}[{presence}_len] = 0 351 f'{member}[{presence}_len] = 0;'] 451 352 452 353 453 class TypeBinary(Type): 354 class TypeBinary(Type): 454 def arg_member(self, ri): 355 def arg_member(self, ri): 455 return [f"const void *{self.c_name}", 356 return [f"const void *{self.c_name}", 'size_t len'] 456 357 457 def presence_type(self): 358 def presence_type(self): 458 return 'len' 359 return 'len' 459 360 460 def struct_member(self, ri): 361 def struct_member(self, ri): 461 ri.cw.p(f"void *{self.c_name};") 362 ri.cw.p(f"void *{self.c_name};") 462 363 463 def _attr_typol(self): 364 def _attr_typol(self): 464 return f'.type = YNL_PT_BINARY,' 365 return f'.type = YNL_PT_BINARY,' 465 366 466 def _attr_policy(self, policy): 367 def _attr_policy(self, policy): 467 if 'exact-len' in self.checks: !! 368 mem = '{ ' 468 mem = 'NLA_POLICY_EXACT_LEN(' + st !! 369 if len(self.checks) == 1 and 'min-len' in self.checks: >> 370 mem += '.len = ' + str(self.checks['min-len']) >> 371 elif len(self.checks) == 0: >> 372 mem += '.type = NLA_BINARY' 469 else: 373 else: 470 mem = '{ ' !! 374 raise Exception('One or more of binary type checks not implemented, yet') 471 if len(self.checks) == 1 and 'min- !! 375 mem += ', }' 472 mem += '.len = ' + str(self.ge << 473 elif len(self.checks) == 0: << 474 mem += '.type = NLA_BINARY' << 475 else: << 476 raise Exception('One or more o << 477 mem += ', }' << 478 return mem 376 return mem 479 377 480 def attr_put(self, ri, var): 378 def attr_put(self, ri, var): 481 self._attr_put_line(ri, var, f"ynl_att !! 379 self._attr_put_line(ri, var, f"mnl_attr_put(nlh, {self.enum_name}, " + 482 f"{var}->{self.c_n !! 380 f"{var}->_present.{self.c_name}_len, {var}->{self.c_name})") 483 381 484 def _attr_get(self, ri, var): 382 def _attr_get(self, ri, var): 485 len_mem = var + '->_present.' + self.c 383 len_mem = var + '->_present.' + self.c_name + '_len' 486 return [f"{len_mem} = len;", 384 return [f"{len_mem} = len;", 487 f"{var}->{self.c_name} = mallo 385 f"{var}->{self.c_name} = malloc(len);", 488 f"memcpy({var}->{self.c_name}, !! 386 f"memcpy({var}->{self.c_name}, mnl_attr_get_payload(attr), len);"], \ 489 ['len = ynl_attr_data_len(attr) !! 387 ['len = mnl_attr_get_payload_len(attr);'], \ 490 ['unsigned int len;'] 388 ['unsigned int len;'] 491 389 492 def _setter_lines(self, ri, member, presen 390 def _setter_lines(self, ri, member, presence): 493 return [f"free({member});", 391 return [f"free({member});", 494 f"{presence}_len = len;", << 495 f"{member} = malloc({presence} 392 f"{member} = malloc({presence}_len);", 496 f'memcpy({member}, {self.c_nam 393 f'memcpy({member}, {self.c_name}, {presence}_len);'] 497 394 498 395 499 class TypeBitfield32(Type): << 500 def _complex_member_type(self, ri): << 501 return "struct nla_bitfield32" << 502 << 503 def _attr_typol(self): << 504 return f'.type = YNL_PT_BITFIELD32, ' << 505 << 506 def _attr_policy(self, policy): << 507 if not 'enum' in self.attr: << 508 raise Exception('Enum required for << 509 enum = self.family.consts[self.attr['e << 510 mask = enum.get_mask(as_flags=True) << 511 return f"NLA_POLICY_BITFIELD32({mask}) << 512 << 513 def attr_put(self, ri, var): << 514 line = f"ynl_attr_put(nlh, {self.enum_ << 515 self._attr_put_line(ri, var, line) << 516 << 517 def _attr_get(self, ri, var): << 518 return f"memcpy(&{var}->{self.c_name}, << 519 << 520 def _setter_lines(self, ri, member, presen << 521 return [f"memcpy(&{member}, {self.c_na << 522 << 523 << 524 class TypeNest(Type): 396 class TypeNest(Type): 525 def is_recursive(self): << 526 return self.family.pure_nested_structs << 527 << 528 def _complex_member_type(self, ri): 397 def _complex_member_type(self, ri): 529 return self.nested_struct_type !! 398 return f"struct {self.nested_render_name}" 530 399 531 def free(self, ri, var, ref): 400 def free(self, ri, var, ref): 532 at = '&' !! 401 ri.cw.p(f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name});') 533 if self.is_recursive_for_op(ri): << 534 at = '' << 535 ri.cw.p(f'if ({var}->{ref}{self.c_ << 536 ri.cw.p(f'{self.nested_render_name}_fr << 537 402 538 def _attr_typol(self): 403 def _attr_typol(self): 539 return f'.type = YNL_PT_NEST, .nest = 404 return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, ' 540 405 541 def _attr_policy(self, policy): 406 def _attr_policy(self, policy): 542 return 'NLA_POLICY_NESTED(' + self.nes 407 return 'NLA_POLICY_NESTED(' + self.nested_render_name + '_nl_policy)' 543 408 544 def attr_put(self, ri, var): 409 def attr_put(self, ri, var): 545 at = '' if self.is_recursive_for_op(ri << 546 self._attr_put_line(ri, var, f"{self.n 410 self._attr_put_line(ri, var, f"{self.nested_render_name}_put(nlh, " + 547 f"{self.enum_name} !! 411 f"{self.enum_name}, &{var}->{self.c_name})") 548 412 549 def _attr_get(self, ri, var): 413 def _attr_get(self, ri, var): 550 get_lines = [f"if ({self.nested_render !! 414 get_lines = [f"{self.nested_render_name}_parse(&parg, attr);"] 551 "return YNL_PARSE_CB_ERRO << 552 init_lines = [f"parg.rsp_policy = &{se 415 init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;", 553 f"parg.data = &{var}->{s 416 f"parg.data = &{var}->{self.c_name};"] 554 return get_lines, init_lines, None 417 return get_lines, init_lines, None 555 418 556 def setter(self, ri, space, direction, der 419 def setter(self, ri, space, direction, deref=False, ref=None): 557 ref = (ref if ref else []) + [self.c_n 420 ref = (ref if ref else []) + [self.c_name] 558 421 559 for _, attr in ri.family.pure_nested_s 422 for _, attr in ri.family.pure_nested_structs[self.nested_attrs].member_list(): 560 if attr.is_recursive(): << 561 continue << 562 attr.setter(ri, self.nested_attrs, 423 attr.setter(ri, self.nested_attrs, direction, deref=deref, ref=ref) 563 424 564 425 565 class TypeMultiAttr(Type): 426 class TypeMultiAttr(Type): 566 def __init__(self, family, attr_set, attr, << 567 super().__init__(family, attr_set, att << 568 << 569 self.base_type = base_type << 570 << 571 def is_multi_val(self): 427 def is_multi_val(self): 572 return True 428 return True 573 429 574 def presence_type(self): 430 def presence_type(self): 575 return 'count' 431 return 'count' 576 432 577 def _complex_member_type(self, ri): 433 def _complex_member_type(self, ri): 578 if 'type' not in self.attr or self.att 434 if 'type' not in self.attr or self.attr['type'] == 'nest': 579 return self.nested_struct_type !! 435 return f"struct {self.nested_render_name}" 580 elif self.attr['type'] in scalars: 436 elif self.attr['type'] in scalars: 581 scalar_pfx = '__' if ri.ku_space = 437 scalar_pfx = '__' if ri.ku_space == 'user' else '' 582 return scalar_pfx + self.attr['typ 438 return scalar_pfx + self.attr['type'] 583 else: 439 else: 584 raise Exception(f"Sub-type {self.a 440 raise Exception(f"Sub-type {self.attr['type']} not supported yet") 585 441 586 def free_needs_iter(self): 442 def free_needs_iter(self): 587 return 'type' not in self.attr or self 443 return 'type' not in self.attr or self.attr['type'] == 'nest' 588 444 589 def free(self, ri, var, ref): 445 def free(self, ri, var, ref): 590 if self.attr['type'] in scalars: !! 446 if 'type' not in self.attr or self.attr['type'] == 'nest': 591 ri.cw.p(f"free({var}->{ref}{self.c << 592 elif 'type' not in self.attr or self.a << 593 ri.cw.p(f"for (i = 0; i < {var}->{ 447 ri.cw.p(f"for (i = 0; i < {var}->{ref}n_{self.c_name}; i++)") 594 ri.cw.p(f'{self.nested_render_name 448 ri.cw.p(f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);') 595 ri.cw.p(f"free({var}->{ref}{self.c << 596 else: << 597 raise Exception(f"Free of MultiAtt << 598 << 599 def _attr_policy(self, policy): << 600 return self.base_type._attr_policy(pol << 601 449 602 def _attr_typol(self): 450 def _attr_typol(self): 603 return self.base_type._attr_typol() !! 451 if 'type' not in self.attr or self.attr['type'] == 'nest': 604 !! 452 return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, ' 605 def _attr_get(self, ri, var): !! 453 elif self.attr['type'] in scalars: 606 return f'n_{self.c_name}++;', None, No !! 454 return f".type = YNL_PT_U{self.attr['type'][1:]}, " 607 << 608 def attr_put(self, ri, var): << 609 if self.attr['type'] in scalars: << 610 put_type = self.type << 611 ri.cw.p(f"for (unsigned int i = 0; << 612 ri.cw.p(f"ynl_attr_put_{put_type}( << 613 elif 'type' not in self.attr or self.a << 614 ri.cw.p(f"for (unsigned int i = 0; << 615 self._attr_put_line(ri, var, f"{se << 616 f"{self.enum_n << 617 else: 455 else: 618 raise Exception(f"Put of MultiAttr !! 456 raise Exception(f"Sub-type {self.attr['type']} not supported yet") 619 457 620 def _setter_lines(self, ri, member, presen !! 458 def _attr_get(self, ri, var): 621 # For multi-attr we have a count, not !! 459 return f'{var}->n_{self.c_name}++;', None, None 622 presence = presence[:-(len('_present.' << 623 return [f"free({member});", << 624 f"{member} = {self.c_name};", << 625 f"{presence} = n_{self.c_name} << 626 460 627 461 628 class TypeArrayNest(Type): 462 class TypeArrayNest(Type): 629 def is_multi_val(self): 463 def is_multi_val(self): 630 return True 464 return True 631 465 632 def presence_type(self): 466 def presence_type(self): 633 return 'count' 467 return 'count' 634 468 635 def _complex_member_type(self, ri): 469 def _complex_member_type(self, ri): 636 if 'sub-type' not in self.attr or self 470 if 'sub-type' not in self.attr or self.attr['sub-type'] == 'nest': 637 return self.nested_struct_type !! 471 return f"struct {self.nested_render_name}" 638 elif self.attr['sub-type'] in scalars: 472 elif self.attr['sub-type'] in scalars: 639 scalar_pfx = '__' if ri.ku_space = 473 scalar_pfx = '__' if ri.ku_space == 'user' else '' 640 return scalar_pfx + self.attr['sub 474 return scalar_pfx + self.attr['sub-type'] 641 else: 475 else: 642 raise Exception(f"Sub-type {self.a 476 raise Exception(f"Sub-type {self.attr['sub-type']} not supported yet") 643 477 644 def _attr_typol(self): 478 def _attr_typol(self): 645 return f'.type = YNL_PT_NEST, .nest = 479 return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, ' 646 480 647 def _attr_get(self, ri, var): 481 def _attr_get(self, ri, var): 648 local_vars = ['const struct nlattr *at 482 local_vars = ['const struct nlattr *attr2;'] 649 get_lines = [f'attr_{self.c_name} = at 483 get_lines = [f'attr_{self.c_name} = attr;', 650 'ynl_attr_for_each_nested !! 484 'mnl_attr_for_each_nested(attr2, attr)', 651 f'\t{var}->n_{self.c_name 485 f'\t{var}->n_{self.c_name}++;'] 652 return get_lines, None, local_vars 486 return get_lines, None, local_vars 653 487 654 488 655 class TypeNestTypeValue(Type): 489 class TypeNestTypeValue(Type): 656 def _complex_member_type(self, ri): 490 def _complex_member_type(self, ri): 657 return self.nested_struct_type !! 491 return f"struct {self.nested_render_name}" 658 492 659 def _attr_typol(self): 493 def _attr_typol(self): 660 return f'.type = YNL_PT_NEST, .nest = 494 return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, ' 661 495 662 def _attr_get(self, ri, var): 496 def _attr_get(self, ri, var): 663 prev = 'attr' 497 prev = 'attr' 664 tv_args = '' 498 tv_args = '' 665 get_lines = [] 499 get_lines = [] 666 local_vars = [] 500 local_vars = [] 667 init_lines = [f"parg.rsp_policy = &{se 501 init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;", 668 f"parg.data = &{var}->{s 502 f"parg.data = &{var}->{self.c_name};"] 669 if 'type-value' in self.attr: 503 if 'type-value' in self.attr: 670 tv_names = [c_lower(x) for x in se 504 tv_names = [c_lower(x) for x in self.attr["type-value"]] 671 local_vars += [f'const struct nlat 505 local_vars += [f'const struct nlattr *attr_{", *attr_".join(tv_names)};'] 672 local_vars += [f'__u32 {", ".join( 506 local_vars += [f'__u32 {", ".join(tv_names)};'] 673 for level in self.attr["type-value 507 for level in self.attr["type-value"]: 674 level = c_lower(level) 508 level = c_lower(level) 675 get_lines += [f'attr_{level} = !! 509 get_lines += [f'attr_{level} = mnl_attr_get_payload({prev});'] 676 get_lines += [f'{level} = ynl_ !! 510 get_lines += [f'{level} = mnl_attr_get_type(attr_{level});'] 677 prev = 'attr_' + level 511 prev = 'attr_' + level 678 512 679 tv_args = f", {', '.join(tv_names) 513 tv_args = f", {', '.join(tv_names)}" 680 514 681 get_lines += [f"{self.nested_render_na 515 get_lines += [f"{self.nested_render_name}_parse(&parg, {prev}{tv_args});"] 682 return get_lines, init_lines, local_va 516 return get_lines, init_lines, local_vars 683 517 684 518 685 class Struct: 519 class Struct: 686 def __init__(self, family, space_name, typ 520 def __init__(self, family, space_name, type_list=None, inherited=None): 687 self.family = family 521 self.family = family 688 self.space_name = space_name 522 self.space_name = space_name 689 self.attr_set = family.attr_sets[space 523 self.attr_set = family.attr_sets[space_name] 690 # Use list to catch comparisons with e 524 # Use list to catch comparisons with empty sets 691 self._inherited = inherited if inherit 525 self._inherited = inherited if inherited is not None else [] 692 self.inherited = [] 526 self.inherited = [] 693 527 694 self.nested = type_list is None 528 self.nested = type_list is None 695 if family.name == c_lower(space_name): 529 if family.name == c_lower(space_name): 696 self.render_name = c_lower(family. !! 530 self.render_name = f"{family.name}" 697 else: 531 else: 698 self.render_name = c_lower(family. !! 532 self.render_name = f"{family.name}_{c_lower(space_name)}" 699 self.struct_name = 'struct ' + self.re 533 self.struct_name = 'struct ' + self.render_name 700 if self.nested and space_name in famil << 701 self.struct_name += '_' << 702 self.ptr_name = self.struct_name + ' * 534 self.ptr_name = self.struct_name + ' *' 703 # All attr sets this one contains, dir << 704 self.child_nests = set() << 705 535 706 self.request = False 536 self.request = False 707 self.reply = False 537 self.reply = False 708 self.recursive = False << 709 538 710 self.attr_list = [] 539 self.attr_list = [] 711 self.attrs = dict() 540 self.attrs = dict() 712 if type_list is not None: !! 541 if type_list: 713 for t in type_list: 542 for t in type_list: 714 self.attr_list.append((t, self 543 self.attr_list.append((t, self.attr_set[t]),) 715 else: 544 else: 716 for t in self.attr_set: 545 for t in self.attr_set: 717 self.attr_list.append((t, self 546 self.attr_list.append((t, self.attr_set[t]),) 718 547 719 max_val = 0 548 max_val = 0 720 self.attr_max_val = None 549 self.attr_max_val = None 721 for name, attr in self.attr_list: 550 for name, attr in self.attr_list: 722 if attr.value >= max_val: 551 if attr.value >= max_val: 723 max_val = attr.value 552 max_val = attr.value 724 self.attr_max_val = attr 553 self.attr_max_val = attr 725 self.attrs[name] = attr 554 self.attrs[name] = attr 726 555 727 def __iter__(self): 556 def __iter__(self): 728 yield from self.attrs 557 yield from self.attrs 729 558 730 def __getitem__(self, key): 559 def __getitem__(self, key): 731 return self.attrs[key] 560 return self.attrs[key] 732 561 733 def member_list(self): 562 def member_list(self): 734 return self.attr_list 563 return self.attr_list 735 564 736 def set_inherited(self, new_inherited): 565 def set_inherited(self, new_inherited): 737 if self._inherited != new_inherited: 566 if self._inherited != new_inherited: 738 raise Exception("Inheriting differ 567 raise Exception("Inheriting different members not supported") 739 self.inherited = [c_lower(x) for x in 568 self.inherited = [c_lower(x) for x in sorted(self._inherited)] 740 569 741 570 742 class EnumEntry(SpecEnumEntry): 571 class EnumEntry(SpecEnumEntry): 743 def __init__(self, enum_set, yaml, prev, v 572 def __init__(self, enum_set, yaml, prev, value_start): 744 super().__init__(enum_set, yaml, prev, 573 super().__init__(enum_set, yaml, prev, value_start) 745 574 746 if prev: 575 if prev: 747 self.value_change = (self.value != 576 self.value_change = (self.value != prev.value + 1) 748 else: 577 else: 749 self.value_change = (self.value != 578 self.value_change = (self.value != 0) 750 self.value_change = self.value_change 579 self.value_change = self.value_change or self.enum_set['type'] == 'flags' 751 580 752 # Added by resolve: 581 # Added by resolve: 753 self.c_name = None 582 self.c_name = None 754 delattr(self, "c_name") 583 delattr(self, "c_name") 755 584 756 def resolve(self): 585 def resolve(self): 757 self.resolve_up(super()) 586 self.resolve_up(super()) 758 587 759 self.c_name = c_upper(self.enum_set.va 588 self.c_name = c_upper(self.enum_set.value_pfx + self.name) 760 589 761 590 762 class EnumSet(SpecEnumSet): 591 class EnumSet(SpecEnumSet): 763 def __init__(self, family, yaml): 592 def __init__(self, family, yaml): 764 self.render_name = c_lower(family.iden !! 593 self.render_name = c_lower(family.name + '-' + yaml['name']) 765 !! 594 self.enum_name = 'enum ' + self.render_name 766 if 'enum-name' in yaml: << 767 if yaml['enum-name']: << 768 self.enum_name = 'enum ' + c_l << 769 self.user_type = self.enum_nam << 770 else: << 771 self.enum_name = None << 772 else: << 773 self.enum_name = 'enum ' + self.re << 774 595 775 if self.enum_name: !! 596 self.value_pfx = yaml.get('name-prefix', f"{family.name}-{yaml['name']}-") 776 self.user_type = self.enum_name << 777 else: << 778 self.user_type = 'int' << 779 << 780 self.value_pfx = yaml.get('name-prefix << 781 597 782 super().__init__(family, yaml) 598 super().__init__(family, yaml) 783 599 784 def new_entry(self, entry, prev_entry, val 600 def new_entry(self, entry, prev_entry, value_start): 785 return EnumEntry(self, entry, prev_ent 601 return EnumEntry(self, entry, prev_entry, value_start) 786 602 787 def value_range(self): << 788 low = min([x.value for x in self.entri << 789 high = max([x.value for x in self.entr << 790 << 791 if high - low + 1 != len(self.entries) << 792 raise Exception("Can't get value r << 793 << 794 return low, high << 795 << 796 603 797 class AttrSet(SpecAttrSet): 604 class AttrSet(SpecAttrSet): 798 def __init__(self, family, yaml): 605 def __init__(self, family, yaml): 799 super().__init__(family, yaml) 606 super().__init__(family, yaml) 800 607 801 if self.subset_of is None: 608 if self.subset_of is None: 802 if 'name-prefix' in yaml: 609 if 'name-prefix' in yaml: 803 pfx = yaml['name-prefix'] 610 pfx = yaml['name-prefix'] 804 elif self.name == family.name: 611 elif self.name == family.name: 805 pfx = family.ident_name + '-a- !! 612 pfx = family.name + '-a-' 806 else: 613 else: 807 pfx = f"{family.ident_name}-a- !! 614 pfx = f"{family.name}-a-{self.name}-" 808 self.name_prefix = c_upper(pfx) 615 self.name_prefix = c_upper(pfx) 809 self.max_name = c_upper(self.yaml. 616 self.max_name = c_upper(self.yaml.get('attr-max-name', f"{self.name_prefix}max")) 810 self.cnt_name = c_upper(self.yaml. << 811 else: 617 else: 812 self.name_prefix = family.attr_set 618 self.name_prefix = family.attr_sets[self.subset_of].name_prefix 813 self.max_name = family.attr_sets[s 619 self.max_name = family.attr_sets[self.subset_of].max_name 814 self.cnt_name = family.attr_sets[s << 815 620 816 # Added by resolve: 621 # Added by resolve: 817 self.c_name = None 622 self.c_name = None 818 delattr(self, "c_name") 623 delattr(self, "c_name") 819 624 820 def resolve(self): 625 def resolve(self): 821 self.c_name = c_lower(self.name) 626 self.c_name = c_lower(self.name) 822 if self.c_name in _C_KW: 627 if self.c_name in _C_KW: 823 self.c_name += '_' 628 self.c_name += '_' 824 if self.c_name == self.family.c_name: 629 if self.c_name == self.family.c_name: 825 self.c_name = '' 630 self.c_name = '' 826 631 827 def new_attr(self, elem, value): 632 def new_attr(self, elem, value): 828 if elem['type'] in scalars: !! 633 if 'multi-attr' in elem and elem['multi-attr']: 829 t = TypeScalar(self.family, self, !! 634 return TypeMultiAttr(self.family, self, elem, value) >> 635 elif elem['type'] in scalars: >> 636 return TypeScalar(self.family, self, elem, value) 830 elif elem['type'] == 'unused': 637 elif elem['type'] == 'unused': 831 t = TypeUnused(self.family, self, !! 638 return TypeUnused(self.family, self, elem, value) 832 elif elem['type'] == 'pad': 639 elif elem['type'] == 'pad': 833 t = TypePad(self.family, self, ele !! 640 return TypePad(self.family, self, elem, value) 834 elif elem['type'] == 'flag': 641 elif elem['type'] == 'flag': 835 t = TypeFlag(self.family, self, el !! 642 return TypeFlag(self.family, self, elem, value) 836 elif elem['type'] == 'string': 643 elif elem['type'] == 'string': 837 t = TypeString(self.family, self, !! 644 return TypeString(self.family, self, elem, value) 838 elif elem['type'] == 'binary': 645 elif elem['type'] == 'binary': 839 t = TypeBinary(self.family, self, !! 646 return TypeBinary(self.family, self, elem, value) 840 elif elem['type'] == 'bitfield32': << 841 t = TypeBitfield32(self.family, se << 842 elif elem['type'] == 'nest': 647 elif elem['type'] == 'nest': 843 t = TypeNest(self.family, self, el !! 648 return TypeNest(self.family, self, elem, value) 844 elif elem['type'] == 'indexed-array' a !! 649 elif elem['type'] == 'array-nest': 845 if elem["sub-type"] == 'nest': !! 650 return TypeArrayNest(self.family, self, elem, value) 846 t = TypeArrayNest(self.family, << 847 else: << 848 raise Exception(f'new_attr: un << 849 elif elem['type'] == 'nest-type-value' 651 elif elem['type'] == 'nest-type-value': 850 t = TypeNestTypeValue(self.family, !! 652 return TypeNestTypeValue(self.family, self, elem, value) 851 else: 653 else: 852 raise Exception(f"No typed class f 654 raise Exception(f"No typed class for type {elem['type']}") 853 655 854 if 'multi-attr' in elem and elem['mult << 855 t = TypeMultiAttr(self.family, sel << 856 << 857 return t << 858 << 859 656 860 class Operation(SpecOperation): 657 class Operation(SpecOperation): 861 def __init__(self, family, yaml, req_value 658 def __init__(self, family, yaml, req_value, rsp_value): 862 super().__init__(family, yaml, req_val 659 super().__init__(family, yaml, req_value, rsp_value) 863 660 864 self.render_name = c_lower(family.iden !! 661 if req_value != rsp_value: >> 662 raise Exception("Directional messages not supported by codegen") >> 663 >> 664 self.render_name = family.name + '_' + c_lower(self.name) 865 665 866 self.dual_policy = ('do' in yaml and ' 666 self.dual_policy = ('do' in yaml and 'request' in yaml['do']) and \ 867 ('dump' in yaml and ' 667 ('dump' in yaml and 'request' in yaml['dump']) 868 668 869 self.has_ntf = False << 870 << 871 # Added by resolve: 669 # Added by resolve: 872 self.enum_name = None 670 self.enum_name = None 873 delattr(self, "enum_name") 671 delattr(self, "enum_name") 874 672 875 def resolve(self): 673 def resolve(self): 876 self.resolve_up(super()) 674 self.resolve_up(super()) 877 675 878 if not self.is_async: 676 if not self.is_async: 879 self.enum_name = self.family.op_pr 677 self.enum_name = self.family.op_prefix + c_upper(self.name) 880 else: 678 else: 881 self.enum_name = self.family.async 679 self.enum_name = self.family.async_op_prefix + c_upper(self.name) 882 680 883 def mark_has_ntf(self): !! 681 def add_notification(self, op): 884 self.has_ntf = True !! 682 if 'notify' not in self.yaml: >> 683 self.yaml['notify'] = dict() >> 684 self.yaml['notify']['reply'] = self.yaml['do']['reply'] >> 685 self.yaml['notify']['cmds'] = [] >> 686 self.yaml['notify']['cmds'].append(op) 885 687 886 688 887 class Family(SpecFamily): 689 class Family(SpecFamily): 888 def __init__(self, file_name, exclude_ops) !! 690 def __init__(self, file_name): 889 # Added by resolve: 691 # Added by resolve: 890 self.c_name = None 692 self.c_name = None 891 delattr(self, "c_name") 693 delattr(self, "c_name") 892 self.op_prefix = None 694 self.op_prefix = None 893 delattr(self, "op_prefix") 695 delattr(self, "op_prefix") 894 self.async_op_prefix = None 696 self.async_op_prefix = None 895 delattr(self, "async_op_prefix") 697 delattr(self, "async_op_prefix") 896 self.mcgrps = None 698 self.mcgrps = None 897 delattr(self, "mcgrps") 699 delattr(self, "mcgrps") 898 self.consts = None 700 self.consts = None 899 delattr(self, "consts") 701 delattr(self, "consts") 900 self.hooks = None 702 self.hooks = None 901 delattr(self, "hooks") 703 delattr(self, "hooks") 902 704 903 super().__init__(file_name, exclude_op !! 705 super().__init__(file_name) 904 706 905 self.fam_key = c_upper(self.yaml.get(' 707 self.fam_key = c_upper(self.yaml.get('c-family-name', self.yaml["name"] + '_FAMILY_NAME')) 906 self.ver_key = c_upper(self.yaml.get(' 708 self.ver_key = c_upper(self.yaml.get('c-version-name', self.yaml["name"] + '_FAMILY_VERSION')) 907 709 908 if 'definitions' not in self.yaml: 710 if 'definitions' not in self.yaml: 909 self.yaml['definitions'] = [] 711 self.yaml['definitions'] = [] 910 712 911 if 'uapi-header' in self.yaml: 713 if 'uapi-header' in self.yaml: 912 self.uapi_header = self.yaml['uapi 714 self.uapi_header = self.yaml['uapi-header'] 913 else: 715 else: 914 self.uapi_header = f"linux/{self.i !! 716 self.uapi_header = f"linux/{self.name}.h" 915 if self.uapi_header.startswith("linux/ << 916 self.uapi_header_name = self.uapi_ << 917 else: << 918 self.uapi_header_name = self.ident << 919 717 920 def resolve(self): 718 def resolve(self): 921 self.resolve_up(super()) 719 self.resolve_up(super()) 922 720 923 if self.yaml.get('protocol', 'genetlin 721 if self.yaml.get('protocol', 'genetlink') not in {'genetlink', 'genetlink-c', 'genetlink-legacy'}: 924 raise Exception("Codegen only supp 722 raise Exception("Codegen only supported for genetlink") 925 723 926 self.c_name = c_lower(self.ident_name) !! 724 self.c_name = c_lower(self.name) 927 if 'name-prefix' in self.yaml['operati 725 if 'name-prefix' in self.yaml['operations']: 928 self.op_prefix = c_upper(self.yaml 726 self.op_prefix = c_upper(self.yaml['operations']['name-prefix']) 929 else: 727 else: 930 self.op_prefix = c_upper(self.yaml 728 self.op_prefix = c_upper(self.yaml['name'] + '-cmd-') 931 if 'async-prefix' in self.yaml['operat 729 if 'async-prefix' in self.yaml['operations']: 932 self.async_op_prefix = c_upper(sel 730 self.async_op_prefix = c_upper(self.yaml['operations']['async-prefix']) 933 else: 731 else: 934 self.async_op_prefix = self.op_pre 732 self.async_op_prefix = self.op_prefix 935 733 936 self.mcgrps = self.yaml.get('mcast-gro 734 self.mcgrps = self.yaml.get('mcast-groups', {'list': []}) 937 735 938 self.hooks = dict() 736 self.hooks = dict() 939 for when in ['pre', 'post']: 737 for when in ['pre', 'post']: 940 self.hooks[when] = dict() 738 self.hooks[when] = dict() 941 for op_mode in ['do', 'dump']: 739 for op_mode in ['do', 'dump']: 942 self.hooks[when][op_mode] = di 740 self.hooks[when][op_mode] = dict() 943 self.hooks[when][op_mode]['set 741 self.hooks[when][op_mode]['set'] = set() 944 self.hooks[when][op_mode]['lis 742 self.hooks[when][op_mode]['list'] = [] 945 743 946 # dict space-name -> 'request': set(at 744 # dict space-name -> 'request': set(attrs), 'reply': set(attrs) 947 self.root_sets = dict() 745 self.root_sets = dict() 948 # dict space-name -> set('request', 'r 746 # dict space-name -> set('request', 'reply') 949 self.pure_nested_structs = dict() 747 self.pure_nested_structs = dict() >> 748 self.all_notify = dict() 950 749 951 self._mark_notify() << 952 self._mock_up_events() 750 self._mock_up_events() 953 751 >> 752 self._dictify() 954 self._load_root_sets() 753 self._load_root_sets() 955 self._load_nested_sets() 754 self._load_nested_sets() 956 self._load_attr_use() !! 755 self._load_all_notify() 957 self._load_hooks() 756 self._load_hooks() 958 757 959 self.kernel_policy = self.yaml.get('ke 758 self.kernel_policy = self.yaml.get('kernel-policy', 'split') 960 if self.kernel_policy == 'global': 759 if self.kernel_policy == 'global': 961 self._load_global_policy() 760 self._load_global_policy() 962 761 963 def new_enum(self, elem): 762 def new_enum(self, elem): 964 return EnumSet(self, elem) 763 return EnumSet(self, elem) 965 764 966 def new_attr_set(self, elem): 765 def new_attr_set(self, elem): 967 return AttrSet(self, elem) 766 return AttrSet(self, elem) 968 767 969 def new_operation(self, elem, req_value, r 768 def new_operation(self, elem, req_value, rsp_value): 970 return Operation(self, elem, req_value 769 return Operation(self, elem, req_value, rsp_value) 971 770 972 def _mark_notify(self): << 973 for op in self.msgs.values(): << 974 if 'notify' in op: << 975 self.ops[op['notify']].mark_ha << 976 << 977 # Fake a 'do' equivalent of all events, so 771 # Fake a 'do' equivalent of all events, so that we can render their response parsing 978 def _mock_up_events(self): 772 def _mock_up_events(self): 979 for op in self.yaml['operations']['lis 773 for op in self.yaml['operations']['list']: 980 if 'event' in op: 774 if 'event' in op: 981 op['do'] = { 775 op['do'] = { 982 'reply': { 776 'reply': { 983 'attributes': op['even 777 'attributes': op['event']['attributes'] 984 } 778 } 985 } 779 } 986 780 >> 781 def _dictify(self): >> 782 ntf = [] >> 783 for msg in self.msgs.values(): >> 784 if 'notify' in msg: >> 785 ntf.append(msg) >> 786 for n in ntf: >> 787 self.ops[n['notify']].add_notification(n) >> 788 987 def _load_root_sets(self): 789 def _load_root_sets(self): 988 for op_name, op in self.msgs.items(): !! 790 for op_name, op in self.ops.items(): 989 if 'attribute-set' not in op: 791 if 'attribute-set' not in op: 990 continue 792 continue 991 793 992 req_attrs = set() 794 req_attrs = set() 993 rsp_attrs = set() 795 rsp_attrs = set() 994 for op_mode in ['do', 'dump']: 796 for op_mode in ['do', 'dump']: 995 if op_mode in op and 'request' 797 if op_mode in op and 'request' in op[op_mode]: 996 req_attrs.update(set(op[op 798 req_attrs.update(set(op[op_mode]['request']['attributes'])) 997 if op_mode in op and 'reply' i 799 if op_mode in op and 'reply' in op[op_mode]: 998 rsp_attrs.update(set(op[op 800 rsp_attrs.update(set(op[op_mode]['reply']['attributes'])) 999 if 'event' in op: << 1000 rsp_attrs.update(set(op['even << 1001 801 1002 if op['attribute-set'] not in sel 802 if op['attribute-set'] not in self.root_sets: 1003 self.root_sets[op['attribute- 803 self.root_sets[op['attribute-set']] = {'request': req_attrs, 'reply': rsp_attrs} 1004 else: 804 else: 1005 self.root_sets[op['attribute- 805 self.root_sets[op['attribute-set']]['request'].update(req_attrs) 1006 self.root_sets[op['attribute- 806 self.root_sets[op['attribute-set']]['reply'].update(rsp_attrs) 1007 807 1008 def _sort_pure_types(self): << 1009 # Try to reorder according to depende << 1010 pns_key_list = list(self.pure_nested_ << 1011 pns_key_seen = set() << 1012 rounds = len(pns_key_list) ** 2 # it << 1013 for _ in range(rounds): << 1014 if len(pns_key_list) == 0: << 1015 break << 1016 name = pns_key_list.pop(0) << 1017 finished = True << 1018 for _, spec in self.attr_sets[nam << 1019 if 'nested-attributes' in spe << 1020 nested = spec['nested-att << 1021 # If the unknown nest we << 1022 if self.pure_nested_struc << 1023 continue << 1024 if nested not in pns_key_ << 1025 # Dicts are sorted, t << 1026 struct = self.pure_ne << 1027 self.pure_nested_stru << 1028 finished = False << 1029 break << 1030 if finished: << 1031 pns_key_seen.add(name) << 1032 else: << 1033 pns_key_list.append(name) << 1034 << 1035 def _load_nested_sets(self): 808 def _load_nested_sets(self): 1036 attr_set_queue = list(self.root_sets. << 1037 attr_set_seen = set(self.root_sets.ke << 1038 << 1039 while len(attr_set_queue): << 1040 a_set = attr_set_queue.pop(0) << 1041 for attr, spec in self.attr_sets[ << 1042 if 'nested-attributes' not in << 1043 continue << 1044 << 1045 nested = spec['nested-attribu << 1046 if nested not in attr_set_see << 1047 attr_set_queue.append(nes << 1048 attr_set_seen.add(nested) << 1049 << 1050 inherit = set() << 1051 if nested not in self.root_se << 1052 if nested not in self.pur << 1053 self.pure_nested_stru << 1054 else: << 1055 raise Exception(f'Using a << 1056 << 1057 if 'type-value' in spec: << 1058 if nested in self.root_se << 1059 raise Exception("Inhe << 1060 inherit.update(set(spec[' << 1061 elif spec['type'] == 'indexed << 1062 inherit.add('idx') << 1063 self.pure_nested_structs[nest << 1064 << 1065 for root_set, rs_members in self.root 809 for root_set, rs_members in self.root_sets.items(): 1066 for attr, spec in self.attr_sets[ 810 for attr, spec in self.attr_sets[root_set].items(): 1067 if 'nested-attributes' in spe 811 if 'nested-attributes' in spec: >> 812 inherit = set() 1068 nested = spec['nested-att 813 nested = spec['nested-attributes'] >> 814 if nested not in self.root_sets: >> 815 self.pure_nested_structs[nested] = Struct(self, nested, inherited=inherit) 1069 if attr in rs_members['re 816 if attr in rs_members['request']: 1070 self.pure_nested_stru 817 self.pure_nested_structs[nested].request = True 1071 if attr in rs_members['re 818 if attr in rs_members['reply']: 1072 self.pure_nested_stru 819 self.pure_nested_structs[nested].reply = True 1073 820 1074 self._sort_pure_types() !! 821 if 'type-value' in spec: >> 822 if nested in self.root_sets: >> 823 raise Exception("Inheriting members to a space used as root not supported") >> 824 inherit.update(set(spec['type-value'])) >> 825 elif spec['type'] == 'array-nest': >> 826 inherit.add('idx') >> 827 self.pure_nested_structs[nested].set_inherited(inherit) 1075 828 1076 # Propagate the request / reply / rec !! 829 def _load_all_notify(self): 1077 for attr_set, struct in reversed(self !! 830 for op_name, op in self.ops.items(): 1078 for _, spec in self.attr_sets[att !! 831 if not op: 1079 if 'nested-attributes' in spe !! 832 continue 1080 child_name = spec['nested << 1081 struct.child_nests.add(ch << 1082 child = self.pure_nested_ << 1083 if child: << 1084 if not child.recursiv << 1085 struct.child_nest << 1086 child.request |= stru << 1087 child.reply |= struct << 1088 if attr_set in struct.child_n << 1089 struct.recursive = True << 1090 << 1091 self._sort_pure_types() << 1092 << 1093 def _load_attr_use(self): << 1094 for _, struct in self.pure_nested_str << 1095 if struct.request: << 1096 for _, arg in struct.member_l << 1097 arg.request = True << 1098 if struct.reply: << 1099 for _, arg in struct.member_l << 1100 arg.reply = True << 1101 833 1102 for root_set, rs_members in self.root !! 834 if 'notify' in op: 1103 for attr, spec in self.attr_sets[ !! 835 self.all_notify[op_name] = op['notify']['cmds'] 1104 if attr in rs_members['reques << 1105 spec.request = True << 1106 if attr in rs_members['reply' << 1107 spec.reply = True << 1108 836 1109 def _load_global_policy(self): 837 def _load_global_policy(self): 1110 global_set = set() 838 global_set = set() 1111 attr_set_name = None 839 attr_set_name = None 1112 for op_name, op in self.ops.items(): 840 for op_name, op in self.ops.items(): 1113 if not op: 841 if not op: 1114 continue 842 continue 1115 if 'attribute-set' not in op: 843 if 'attribute-set' not in op: 1116 continue 844 continue 1117 845 1118 if attr_set_name is None: 846 if attr_set_name is None: 1119 attr_set_name = op['attribute 847 attr_set_name = op['attribute-set'] 1120 if attr_set_name != op['attribute 848 if attr_set_name != op['attribute-set']: 1121 raise Exception('For a global 849 raise Exception('For a global policy all ops must use the same set') 1122 850 1123 for op_mode in ['do', 'dump']: 851 for op_mode in ['do', 'dump']: 1124 if op_mode in op: 852 if op_mode in op: 1125 req = op[op_mode].get('re !! 853 global_set.update(op[op_mode].get('request', [])) 1126 if req: << 1127 global_set.update(req << 1128 854 1129 self.global_policy = [] 855 self.global_policy = [] 1130 self.global_policy_set = attr_set_nam 856 self.global_policy_set = attr_set_name 1131 for attr in self.attr_sets[attr_set_n 857 for attr in self.attr_sets[attr_set_name]: 1132 if attr in global_set: 858 if attr in global_set: 1133 self.global_policy.append(att 859 self.global_policy.append(attr) 1134 860 1135 def _load_hooks(self): 861 def _load_hooks(self): 1136 for op in self.ops.values(): 862 for op in self.ops.values(): 1137 for op_mode in ['do', 'dump']: 863 for op_mode in ['do', 'dump']: 1138 if op_mode not in op: 864 if op_mode not in op: 1139 continue 865 continue 1140 for when in ['pre', 'post']: 866 for when in ['pre', 'post']: 1141 if when not in op[op_mode 867 if when not in op[op_mode]: 1142 continue 868 continue 1143 name = op[op_mode][when] 869 name = op[op_mode][when] 1144 if name in self.hooks[whe 870 if name in self.hooks[when][op_mode]['set']: 1145 continue 871 continue 1146 self.hooks[when][op_mode] 872 self.hooks[when][op_mode]['set'].add(name) 1147 self.hooks[when][op_mode] 873 self.hooks[when][op_mode]['list'].append(name) 1148 874 1149 875 1150 class RenderInfo: 876 class RenderInfo: 1151 def __init__(self, cw, family, ku_space, !! 877 def __init__(self, cw, family, ku_space, op, op_name, op_mode, attr_set=None): 1152 self.family = family 878 self.family = family 1153 self.nl = cw.nlib 879 self.nl = cw.nlib 1154 self.ku_space = ku_space 880 self.ku_space = ku_space 1155 self.op_mode = op_mode << 1156 self.op = op 881 self.op = op 1157 !! 882 self.op_name = op_name 1158 self.fixed_hdr = None !! 883 self.op_mode = op_mode 1159 if op and op.fixed_header: << 1160 self.fixed_hdr = 'struct ' + c_lo << 1161 884 1162 # 'do' and 'dump' response parsing is 885 # 'do' and 'dump' response parsing is identical 1163 self.type_consistent = True !! 886 if op_mode != 'do' and 'dump' in op and 'do' in op and 'reply' in op['do'] and \ 1164 if op_mode != 'do' and 'dump' in op: !! 887 op["do"]["reply"] == op["dump"]["reply"]: 1165 if 'do' in op: !! 888 self.type_consistent = True 1166 if ('reply' in op['do']) != ( !! 889 else: 1167 self.type_consistent = Fa !! 890 self.type_consistent = op_mode == 'event' 1168 elif 'reply' in op['do'] and << 1169 self.type_consistent = Fa << 1170 else: << 1171 self.type_consistent = False << 1172 891 1173 self.attr_set = attr_set 892 self.attr_set = attr_set 1174 if not self.attr_set: 893 if not self.attr_set: 1175 self.attr_set = op['attribute-set 894 self.attr_set = op['attribute-set'] 1176 895 1177 self.type_name_conflict = False << 1178 if op: 896 if op: 1179 self.type_name = c_lower(op.name) !! 897 self.type_name = c_lower(op_name) 1180 else: 898 else: 1181 self.type_name = c_lower(attr_set 899 self.type_name = c_lower(attr_set) 1182 if attr_set in family.consts: << 1183 self.type_name_conflict = Tru << 1184 900 1185 self.cw = cw 901 self.cw = cw 1186 902 1187 self.struct = dict() 903 self.struct = dict() 1188 if op_mode == 'notify': << 1189 op_mode = 'do' << 1190 for op_dir in ['request', 'reply']: 904 for op_dir in ['request', 'reply']: 1191 if op: !! 905 if op and op_dir in op[op_mode]: 1192 type_list = [] !! 906 self.struct[op_dir] = Struct(family, self.attr_set, 1193 if op_dir in op[op_mode]: !! 907 type_list=op[op_mode][op_dir]['attributes']) 1194 type_list = op[op_mode][o << 1195 self.struct[op_dir] = Struct( << 1196 if op_mode == 'event': 908 if op_mode == 'event': 1197 self.struct['reply'] = Struct(fam 909 self.struct['reply'] = Struct(family, self.attr_set, type_list=op['event']['attributes']) 1198 910 1199 911 1200 class CodeWriter: 912 class CodeWriter: 1201 def __init__(self, nlib, out_file=None, o !! 913 def __init__(self, nlib, out_file): 1202 self.nlib = nlib 914 self.nlib = nlib 1203 self._overwrite = overwrite << 1204 915 1205 self._nl = False 916 self._nl = False 1206 self._block_end = False << 1207 self._silent_block = False 917 self._silent_block = False 1208 self._ind = 0 918 self._ind = 0 1209 self._ifdef_block = None !! 919 self._out = out_file 1210 if out_file is None: << 1211 self._out = os.sys.stdout << 1212 else: << 1213 self._out = tempfile.NamedTempora << 1214 self._out_file = out_file << 1215 << 1216 def __del__(self): << 1217 self.close_out_file() << 1218 << 1219 def close_out_file(self): << 1220 if self._out == os.sys.stdout: << 1221 return << 1222 # Avoid modifying the file if content << 1223 self._out.flush() << 1224 if not self._overwrite and os.path.is << 1225 if filecmp.cmp(self._out.name, se << 1226 return << 1227 with open(self._out_file, 'w+') as ou << 1228 self._out.seek(0) << 1229 shutil.copyfileobj(self._out, out << 1230 self._out.close() << 1231 self._out = os.sys.stdout << 1232 920 1233 @classmethod 921 @classmethod 1234 def _is_cond(cls, line): 922 def _is_cond(cls, line): 1235 return line.startswith('if') or line. 923 return line.startswith('if') or line.startswith('while') or line.startswith('for') 1236 924 1237 def p(self, line, add_ind=0): 925 def p(self, line, add_ind=0): 1238 if self._block_end: << 1239 self._block_end = False << 1240 if line.startswith('else'): << 1241 line = '} ' + line << 1242 else: << 1243 self._out.write('\t' * self._ << 1244 << 1245 if self._nl: 926 if self._nl: 1246 self._out.write('\n') 927 self._out.write('\n') 1247 self._nl = False 928 self._nl = False 1248 << 1249 ind = self._ind 929 ind = self._ind 1250 if line[-1] == ':': 930 if line[-1] == ':': 1251 ind -= 1 931 ind -= 1 1252 if self._silent_block: 932 if self._silent_block: 1253 ind += 1 933 ind += 1 1254 self._silent_block = line.endswith(') 934 self._silent_block = line.endswith(')') and CodeWriter._is_cond(line) 1255 if line[0] == '#': << 1256 ind = 0 << 1257 if add_ind: 935 if add_ind: 1258 ind += add_ind 936 ind += add_ind 1259 self._out.write('\t' * ind + line + ' 937 self._out.write('\t' * ind + line + '\n') 1260 938 1261 def nl(self): 939 def nl(self): 1262 self._nl = True 940 self._nl = True 1263 941 1264 def block_start(self, line=''): 942 def block_start(self, line=''): 1265 if line: 943 if line: 1266 line = line + ' ' 944 line = line + ' ' 1267 self.p(line + '{') 945 self.p(line + '{') 1268 self._ind += 1 946 self._ind += 1 1269 947 1270 def block_end(self, line=''): 948 def block_end(self, line=''): 1271 if line and line[0] not in {';', ','} 949 if line and line[0] not in {';', ','}: 1272 line = ' ' + line 950 line = ' ' + line 1273 self._ind -= 1 951 self._ind -= 1 1274 self._nl = False !! 952 self.p('}' + line) 1275 if not line: << 1276 # Delay printing closing bracket << 1277 if self._block_end: << 1278 self._out.write('\t' * (self. << 1279 self._block_end = True << 1280 else: << 1281 self.p('}' + line) << 1282 953 1283 def write_doc_line(self, doc, indent=True 954 def write_doc_line(self, doc, indent=True): 1284 words = doc.split() 955 words = doc.split() 1285 line = ' *' 956 line = ' *' 1286 for word in words: 957 for word in words: 1287 if len(line) + len(word) >= 79: 958 if len(line) + len(word) >= 79: 1288 self.p(line) 959 self.p(line) 1289 line = ' *' 960 line = ' *' 1290 if indent: 961 if indent: 1291 line += ' ' 962 line += ' ' 1292 line += ' ' + word 963 line += ' ' + word 1293 self.p(line) 964 self.p(line) 1294 965 1295 def write_func_prot(self, qual_ret, name, 966 def write_func_prot(self, qual_ret, name, args=None, doc=None, suffix=''): 1296 if not args: 967 if not args: 1297 args = ['void'] 968 args = ['void'] 1298 969 1299 if doc: 970 if doc: 1300 self.p('/*') 971 self.p('/*') 1301 self.p(' * ' + doc) 972 self.p(' * ' + doc) 1302 self.p(' */') 973 self.p(' */') 1303 974 1304 oneline = qual_ret 975 oneline = qual_ret 1305 if qual_ret[-1] != '*': 976 if qual_ret[-1] != '*': 1306 oneline += ' ' 977 oneline += ' ' 1307 oneline += f"{name}({', '.join(args)} 978 oneline += f"{name}({', '.join(args)}){suffix}" 1308 979 1309 if len(oneline) < 80: 980 if len(oneline) < 80: 1310 self.p(oneline) 981 self.p(oneline) 1311 return 982 return 1312 983 1313 v = qual_ret 984 v = qual_ret 1314 if len(v) > 3: 985 if len(v) > 3: 1315 self.p(v) 986 self.p(v) 1316 v = '' 987 v = '' 1317 elif qual_ret[-1] != '*': 988 elif qual_ret[-1] != '*': 1318 v += ' ' 989 v += ' ' 1319 v += name + '(' 990 v += name + '(' 1320 ind = '\t' * (len(v) // 8) + ' ' * (l 991 ind = '\t' * (len(v) // 8) + ' ' * (len(v) % 8) 1321 delta_ind = len(v) - len(ind) 992 delta_ind = len(v) - len(ind) 1322 v += args[0] 993 v += args[0] 1323 i = 1 994 i = 1 1324 while i < len(args): 995 while i < len(args): 1325 next_len = len(v) + len(args[i]) 996 next_len = len(v) + len(args[i]) 1326 if v[0] == '\t': 997 if v[0] == '\t': 1327 next_len += delta_ind 998 next_len += delta_ind 1328 if next_len > 76: 999 if next_len > 76: 1329 self.p(v + ',') 1000 self.p(v + ',') 1330 v = ind 1001 v = ind 1331 else: 1002 else: 1332 v += ', ' 1003 v += ', ' 1333 v += args[i] 1004 v += args[i] 1334 i += 1 1005 i += 1 1335 self.p(v + ')' + suffix) 1006 self.p(v + ')' + suffix) 1336 1007 1337 def write_func_lvar(self, local_vars): 1008 def write_func_lvar(self, local_vars): 1338 if not local_vars: 1009 if not local_vars: 1339 return 1010 return 1340 1011 1341 if type(local_vars) is str: 1012 if type(local_vars) is str: 1342 local_vars = [local_vars] 1013 local_vars = [local_vars] 1343 1014 1344 local_vars.sort(key=len, reverse=True 1015 local_vars.sort(key=len, reverse=True) 1345 for var in local_vars: 1016 for var in local_vars: 1346 self.p(var) 1017 self.p(var) 1347 self.nl() 1018 self.nl() 1348 1019 1349 def write_func(self, qual_ret, name, body 1020 def write_func(self, qual_ret, name, body, args=None, local_vars=None): 1350 self.write_func_prot(qual_ret=qual_re 1021 self.write_func_prot(qual_ret=qual_ret, name=name, args=args) 1351 self.write_func_lvar(local_vars=local 1022 self.write_func_lvar(local_vars=local_vars) 1352 1023 1353 self.block_start() 1024 self.block_start() 1354 for line in body: 1025 for line in body: 1355 self.p(line) 1026 self.p(line) 1356 self.block_end() 1027 self.block_end() 1357 1028 1358 def writes_defines(self, defines): 1029 def writes_defines(self, defines): 1359 longest = 0 1030 longest = 0 1360 for define in defines: 1031 for define in defines: 1361 if len(define[0]) > longest: 1032 if len(define[0]) > longest: 1362 longest = len(define[0]) 1033 longest = len(define[0]) 1363 longest = ((longest + 8) // 8) * 8 1034 longest = ((longest + 8) // 8) * 8 1364 for define in defines: 1035 for define in defines: 1365 line = '#define ' + define[0] 1036 line = '#define ' + define[0] 1366 line += '\t' * ((longest - len(de 1037 line += '\t' * ((longest - len(define[0]) + 7) // 8) 1367 if type(define[1]) is int: 1038 if type(define[1]) is int: 1368 line += str(define[1]) 1039 line += str(define[1]) 1369 elif type(define[1]) is str: 1040 elif type(define[1]) is str: 1370 line += '"' + define[1] + '"' 1041 line += '"' + define[1] + '"' 1371 self.p(line) 1042 self.p(line) 1372 1043 1373 def write_struct_init(self, members): 1044 def write_struct_init(self, members): 1374 longest = max([len(x[0]) for x in mem 1045 longest = max([len(x[0]) for x in members]) 1375 longest += 1 # because we prepend a 1046 longest += 1 # because we prepend a . 1376 longest = ((longest + 8) // 8) * 8 1047 longest = ((longest + 8) // 8) * 8 1377 for one in members: 1048 for one in members: 1378 line = '.' + one[0] 1049 line = '.' + one[0] 1379 line += '\t' * ((longest - len(on 1050 line += '\t' * ((longest - len(one[0]) - 1 + 7) // 8) 1380 line += '= ' + str(one[1]) + ',' !! 1051 line += '= ' + one[1] + ',' 1381 self.p(line) 1052 self.p(line) 1382 1053 1383 def ifdef_block(self, config): << 1384 config_option = None << 1385 if config: << 1386 config_option = 'CONFIG_' + c_upp << 1387 if self._ifdef_block == config_option << 1388 return << 1389 << 1390 if self._ifdef_block: << 1391 self.p('#endif /* ' + self._ifdef << 1392 if config_option: << 1393 self.p('#ifdef ' + config_option) << 1394 self._ifdef_block = config_option << 1395 << 1396 1054 1397 scalars = {'u8', 'u16', 'u32', 'u64', 's32', !! 1055 scalars = {'u8', 'u16', 'u32', 'u64', 's32', 's64'} 1398 1056 1399 direction_to_suffix = { 1057 direction_to_suffix = { 1400 'reply': '_rsp', 1058 'reply': '_rsp', 1401 'request': '_req', 1059 'request': '_req', 1402 '': '' 1060 '': '' 1403 } 1061 } 1404 1062 1405 op_mode_to_wrapper = { 1063 op_mode_to_wrapper = { 1406 'do': '', 1064 'do': '', 1407 'dump': '_list', 1065 'dump': '_list', 1408 'notify': '_ntf', 1066 'notify': '_ntf', 1409 'event': '', 1067 'event': '', 1410 } 1068 } 1411 1069 1412 _C_KW = { 1070 _C_KW = { 1413 'auto', !! 1071 'do' 1414 'bool', << 1415 'break', << 1416 'case', << 1417 'char', << 1418 'const', << 1419 'continue', << 1420 'default', << 1421 'do', << 1422 'double', << 1423 'else', << 1424 'enum', << 1425 'extern', << 1426 'float', << 1427 'for', << 1428 'goto', << 1429 'if', << 1430 'inline', << 1431 'int', << 1432 'long', << 1433 'register', << 1434 'return', << 1435 'short', << 1436 'signed', << 1437 'sizeof', << 1438 'static', << 1439 'struct', << 1440 'switch', << 1441 'typedef', << 1442 'union', << 1443 'unsigned', << 1444 'void', << 1445 'volatile', << 1446 'while' << 1447 } 1072 } 1448 1073 1449 1074 1450 def rdir(direction): 1075 def rdir(direction): 1451 if direction == 'reply': 1076 if direction == 'reply': 1452 return 'request' 1077 return 'request' 1453 if direction == 'request': 1078 if direction == 'request': 1454 return 'reply' 1079 return 'reply' 1455 return direction 1080 return direction 1456 1081 1457 1082 1458 def op_prefix(ri, direction, deref=False): 1083 def op_prefix(ri, direction, deref=False): 1459 suffix = f"_{ri.type_name}" 1084 suffix = f"_{ri.type_name}" 1460 1085 1461 if not ri.op_mode or ri.op_mode == 'do': 1086 if not ri.op_mode or ri.op_mode == 'do': 1462 suffix += f"{direction_to_suffix[dire 1087 suffix += f"{direction_to_suffix[direction]}" 1463 else: 1088 else: 1464 if direction == 'request': 1089 if direction == 'request': 1465 suffix += '_req_dump' 1090 suffix += '_req_dump' 1466 else: 1091 else: 1467 if ri.type_consistent: 1092 if ri.type_consistent: 1468 if deref: 1093 if deref: 1469 suffix += f"{direction_to 1094 suffix += f"{direction_to_suffix[direction]}" 1470 else: 1095 else: 1471 suffix += op_mode_to_wrap 1096 suffix += op_mode_to_wrapper[ri.op_mode] 1472 else: 1097 else: 1473 suffix += '_rsp' 1098 suffix += '_rsp' 1474 suffix += '_dump' if deref el 1099 suffix += '_dump' if deref else '_list' 1475 1100 1476 return f"{ri.family.c_name}{suffix}" !! 1101 return f"{ri.family['name']}{suffix}" 1477 1102 1478 1103 1479 def type_name(ri, direction, deref=False): 1104 def type_name(ri, direction, deref=False): 1480 return f"struct {op_prefix(ri, direction, 1105 return f"struct {op_prefix(ri, direction, deref=deref)}" 1481 1106 1482 1107 1483 def print_prototype(ri, direction, terminate= 1108 def print_prototype(ri, direction, terminate=True, doc=None): 1484 suffix = ';' if terminate else '' 1109 suffix = ';' if terminate else '' 1485 1110 1486 fname = ri.op.render_name 1111 fname = ri.op.render_name 1487 if ri.op_mode == 'dump': 1112 if ri.op_mode == 'dump': 1488 fname += '_dump' 1113 fname += '_dump' 1489 1114 1490 args = ['struct ynl_sock *ys'] 1115 args = ['struct ynl_sock *ys'] 1491 if 'request' in ri.op[ri.op_mode]: 1116 if 'request' in ri.op[ri.op_mode]: 1492 args.append(f"{type_name(ri, directio 1117 args.append(f"{type_name(ri, direction)} *" + f"{direction_to_suffix[direction][1:]}") 1493 1118 1494 ret = 'int' 1119 ret = 'int' 1495 if 'reply' in ri.op[ri.op_mode]: 1120 if 'reply' in ri.op[ri.op_mode]: 1496 ret = f"{type_name(ri, rdir(direction 1121 ret = f"{type_name(ri, rdir(direction))} *" 1497 1122 1498 ri.cw.write_func_prot(ret, fname, args, d 1123 ri.cw.write_func_prot(ret, fname, args, doc=doc, suffix=suffix) 1499 1124 1500 1125 1501 def print_req_prototype(ri): 1126 def print_req_prototype(ri): 1502 print_prototype(ri, "request", doc=ri.op[ 1127 print_prototype(ri, "request", doc=ri.op['doc']) 1503 1128 1504 1129 1505 def print_dump_prototype(ri): 1130 def print_dump_prototype(ri): 1506 print_prototype(ri, "request") 1131 print_prototype(ri, "request") 1507 1132 1508 1133 1509 def put_typol_fwd(cw, struct): 1134 def put_typol_fwd(cw, struct): 1510 cw.p(f'extern const struct ynl_policy_nes !! 1135 cw.p(f'extern struct ynl_policy_nest {struct.render_name}_nest;') 1511 1136 1512 1137 1513 def put_typol(cw, struct): 1138 def put_typol(cw, struct): 1514 type_max = struct.attr_set.max_name 1139 type_max = struct.attr_set.max_name 1515 cw.block_start(line=f'const struct ynl_po !! 1140 cw.block_start(line=f'struct ynl_policy_attr {struct.render_name}_policy[{type_max} + 1] =') 1516 1141 1517 for _, arg in struct.member_list(): 1142 for _, arg in struct.member_list(): 1518 arg.attr_typol(cw) 1143 arg.attr_typol(cw) 1519 1144 1520 cw.block_end(line=';') 1145 cw.block_end(line=';') 1521 cw.nl() 1146 cw.nl() 1522 1147 1523 cw.block_start(line=f'const struct ynl_po !! 1148 cw.block_start(line=f'struct ynl_policy_nest {struct.render_name}_nest =') 1524 cw.p(f'.max_attr = {type_max},') 1149 cw.p(f'.max_attr = {type_max},') 1525 cw.p(f'.table = {struct.render_name}_poli 1150 cw.p(f'.table = {struct.render_name}_policy,') 1526 cw.block_end(line=';') 1151 cw.block_end(line=';') 1527 cw.nl() 1152 cw.nl() 1528 1153 1529 1154 1530 def _put_enum_to_str_helper(cw, render_name, !! 1155 def put_req_nested(ri, struct): 1531 args = [f'int {arg_name}'] << 1532 if enum: << 1533 args = [enum.user_type + ' ' + arg_na << 1534 cw.write_func_prot('const char *', f'{ren << 1535 cw.block_start() << 1536 if enum and enum.type == 'flags': << 1537 cw.p(f'{arg_name} = ffs({arg_name}) - << 1538 cw.p(f'if ({arg_name} < 0 || {arg_name} > << 1539 cw.p('return NULL;') << 1540 cw.p(f'return {map_name}[{arg_name}];') << 1541 cw.block_end() << 1542 cw.nl() << 1543 << 1544 << 1545 def put_op_name_fwd(family, cw): << 1546 cw.write_func_prot('const char *', f'{fam << 1547 << 1548 << 1549 def put_op_name(family, cw): << 1550 map_name = f'{family.c_name}_op_strmap' << 1551 cw.block_start(line=f"static const char * << 1552 for op_name, op in family.msgs.items(): << 1553 if op.rsp_value: << 1554 # Make sure we don't add duplicat << 1555 # produce the same response in le << 1556 if family.rsp_by_value[op.rsp_val << 1557 cw.p(f'// skip "{op_name}", d << 1558 continue << 1559 << 1560 if op.req_value == op.rsp_value: << 1561 cw.p(f'[{op.enum_name}] = "{o << 1562 else: << 1563 cw.p(f'[{op.rsp_value}] = "{o << 1564 cw.block_end(line=';') << 1565 cw.nl() << 1566 << 1567 _put_enum_to_str_helper(cw, family.c_name << 1568 << 1569 << 1570 def put_enum_to_str_fwd(family, cw, enum): << 1571 args = [enum.user_type + ' value'] << 1572 cw.write_func_prot('const char *', f'{enu << 1573 << 1574 << 1575 def put_enum_to_str(family, cw, enum): << 1576 map_name = f'{enum.render_name}_strmap' << 1577 cw.block_start(line=f"static const char * << 1578 for entry in enum.entries.values(): << 1579 cw.p(f'[{entry.value}] = "{entry.name << 1580 cw.block_end(line=';') << 1581 cw.nl() << 1582 << 1583 _put_enum_to_str_helper(cw, enum.render_n << 1584 << 1585 << 1586 def put_req_nested_prototype(ri, struct, suff << 1587 func_args = ['struct nlmsghdr *nlh', 1156 func_args = ['struct nlmsghdr *nlh', 1588 'unsigned int attr_type', 1157 'unsigned int attr_type', 1589 f'{struct.ptr_name}obj'] 1158 f'{struct.ptr_name}obj'] 1590 1159 1591 ri.cw.write_func_prot('int', f'{struct.re !! 1160 ri.cw.write_func_prot('int', f'{struct.render_name}_put', func_args) 1592 suffix=suffix) << 1593 << 1594 << 1595 def put_req_nested(ri, struct): << 1596 put_req_nested_prototype(ri, struct, suff << 1597 ri.cw.block_start() 1161 ri.cw.block_start() 1598 ri.cw.write_func_lvar('struct nlattr *nes 1162 ri.cw.write_func_lvar('struct nlattr *nest;') 1599 1163 1600 ri.cw.p("nest = ynl_attr_nest_start(nlh, !! 1164 ri.cw.p("nest = mnl_attr_nest_start(nlh, attr_type);") 1601 1165 1602 for _, arg in struct.member_list(): 1166 for _, arg in struct.member_list(): 1603 arg.attr_put(ri, "obj") 1167 arg.attr_put(ri, "obj") 1604 1168 1605 ri.cw.p("ynl_attr_nest_end(nlh, nest);") !! 1169 ri.cw.p("mnl_attr_nest_end(nlh, nest);") 1606 1170 1607 ri.cw.nl() 1171 ri.cw.nl() 1608 ri.cw.p('return 0;') 1172 ri.cw.p('return 0;') 1609 ri.cw.block_end() 1173 ri.cw.block_end() 1610 ri.cw.nl() 1174 ri.cw.nl() 1611 1175 1612 1176 1613 def _multi_parse(ri, struct, init_lines, loca 1177 def _multi_parse(ri, struct, init_lines, local_vars): 1614 if struct.nested: 1178 if struct.nested: 1615 iter_line = "ynl_attr_for_each_nested !! 1179 iter_line = "mnl_attr_for_each_nested(attr, nested)" 1616 else: 1180 else: 1617 if ri.fixed_hdr: !! 1181 iter_line = "mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr))" 1618 local_vars += ['void *hdr;'] << 1619 iter_line = "ynl_attr_for_each(attr, << 1620 1182 1621 array_nests = set() 1183 array_nests = set() 1622 multi_attrs = set() 1184 multi_attrs = set() 1623 needs_parg = False 1185 needs_parg = False 1624 for arg, aspec in struct.member_list(): 1186 for arg, aspec in struct.member_list(): 1625 if aspec['type'] == 'indexed-array' a !! 1187 if aspec['type'] == 'array-nest': 1626 if aspec["sub-type"] == 'nest': !! 1188 local_vars.append(f'const struct nlattr *attr_{aspec.c_name};') 1627 local_vars.append(f'const str !! 1189 array_nests.add(arg) 1628 array_nests.add(arg) << 1629 else: << 1630 raise Exception(f'Not support << 1631 if 'multi-attr' in aspec: 1190 if 'multi-attr' in aspec: 1632 multi_attrs.add(arg) 1191 multi_attrs.add(arg) 1633 needs_parg |= 'nested-attributes' in 1192 needs_parg |= 'nested-attributes' in aspec 1634 if array_nests or multi_attrs: 1193 if array_nests or multi_attrs: 1635 local_vars.append('int i;') 1194 local_vars.append('int i;') 1636 if needs_parg: 1195 if needs_parg: 1637 local_vars.append('struct ynl_parse_a 1196 local_vars.append('struct ynl_parse_arg parg;') 1638 init_lines.append('parg.ys = yarg->ys 1197 init_lines.append('parg.ys = yarg->ys;') 1639 1198 1640 all_multi = array_nests | multi_attrs << 1641 << 1642 for anest in sorted(all_multi): << 1643 local_vars.append(f"unsigned int n_{s << 1644 << 1645 ri.cw.block_start() 1199 ri.cw.block_start() 1646 ri.cw.write_func_lvar(local_vars) 1200 ri.cw.write_func_lvar(local_vars) 1647 1201 1648 for line in init_lines: 1202 for line in init_lines: 1649 ri.cw.p(line) 1203 ri.cw.p(line) 1650 ri.cw.nl() 1204 ri.cw.nl() 1651 1205 1652 for arg in struct.inherited: 1206 for arg in struct.inherited: 1653 ri.cw.p(f'dst->{arg} = {arg};') 1207 ri.cw.p(f'dst->{arg} = {arg};') 1654 1208 1655 if ri.fixed_hdr: << 1656 ri.cw.p('hdr = ynl_nlmsg_data_offset( << 1657 ri.cw.p(f"memcpy(&dst->_hdr, hdr, siz << 1658 for anest in sorted(all_multi): << 1659 aspec = struct[anest] << 1660 ri.cw.p(f"if (dst->{aspec.c_name})") << 1661 ri.cw.p(f'return ynl_error_parse(yarg << 1662 << 1663 ri.cw.nl() 1209 ri.cw.nl() 1664 ri.cw.block_start(line=iter_line) 1210 ri.cw.block_start(line=iter_line) 1665 ri.cw.p('unsigned int type = ynl_attr_typ << 1666 ri.cw.nl() << 1667 1211 1668 first = True 1212 first = True 1669 for _, arg in struct.member_list(): 1213 for _, arg in struct.member_list(): 1670 good = arg.attr_get(ri, 'dst', first= !! 1214 arg.attr_get(ri, 'dst', first=first) 1671 # First may be 'unused' or 'pad', ign !! 1215 first = False 1672 first &= not good << 1673 1216 1674 ri.cw.block_end() 1217 ri.cw.block_end() 1675 ri.cw.nl() 1218 ri.cw.nl() 1676 1219 1677 for anest in sorted(array_nests): 1220 for anest in sorted(array_nests): 1678 aspec = struct[anest] 1221 aspec = struct[anest] 1679 1222 1680 ri.cw.block_start(line=f"if (n_{aspec !! 1223 ri.cw.block_start(line=f"if (dst->n_{aspec.c_name})") 1681 ri.cw.p(f"dst->{aspec.c_name} = callo !! 1224 ri.cw.p(f"dst->{aspec.c_name} = calloc(dst->n_{aspec.c_name}, sizeof(*dst->{aspec.c_name}));") 1682 ri.cw.p(f"dst->n_{aspec.c_name} = n_{ << 1683 ri.cw.p('i = 0;') 1225 ri.cw.p('i = 0;') 1684 ri.cw.p(f"parg.rsp_policy = &{aspec.n 1226 ri.cw.p(f"parg.rsp_policy = &{aspec.nested_render_name}_nest;") 1685 ri.cw.block_start(line=f"ynl_attr_for !! 1227 ri.cw.block_start(line=f"mnl_attr_for_each_nested(attr, attr_{aspec.c_name})") 1686 ri.cw.p(f"parg.data = &dst->{aspec.c_ 1228 ri.cw.p(f"parg.data = &dst->{aspec.c_name}[i];") 1687 ri.cw.p(f"if ({aspec.nested_render_na !! 1229 ri.cw.p(f"if ({aspec.nested_render_name}_parse(&parg, attr, mnl_attr_get_type(attr)))") 1688 ri.cw.p('return YNL_PARSE_CB_ERROR;') !! 1230 ri.cw.p('return MNL_CB_ERROR;') 1689 ri.cw.p('i++;') 1231 ri.cw.p('i++;') 1690 ri.cw.block_end() 1232 ri.cw.block_end() 1691 ri.cw.block_end() 1233 ri.cw.block_end() 1692 ri.cw.nl() 1234 ri.cw.nl() 1693 1235 1694 for anest in sorted(multi_attrs): 1236 for anest in sorted(multi_attrs): 1695 aspec = struct[anest] 1237 aspec = struct[anest] 1696 ri.cw.block_start(line=f"if (n_{aspec !! 1238 ri.cw.block_start(line=f"if (dst->n_{aspec.c_name})") 1697 ri.cw.p(f"dst->{aspec.c_name} = callo !! 1239 ri.cw.p(f"dst->{aspec.c_name} = calloc(dst->n_{aspec.c_name}, sizeof(*dst->{aspec.c_name}));") 1698 ri.cw.p(f"dst->n_{aspec.c_name} = n_{ << 1699 ri.cw.p('i = 0;') 1240 ri.cw.p('i = 0;') 1700 if 'nested-attributes' in aspec: 1241 if 'nested-attributes' in aspec: 1701 ri.cw.p(f"parg.rsp_policy = &{asp 1242 ri.cw.p(f"parg.rsp_policy = &{aspec.nested_render_name}_nest;") 1702 ri.cw.block_start(line=iter_line) 1243 ri.cw.block_start(line=iter_line) 1703 ri.cw.block_start(line=f"if (ynl_attr !! 1244 ri.cw.block_start(line=f"if (mnl_attr_get_type(attr) == {aspec.enum_name})") 1704 if 'nested-attributes' in aspec: 1245 if 'nested-attributes' in aspec: 1705 ri.cw.p(f"parg.data = &dst->{aspe 1246 ri.cw.p(f"parg.data = &dst->{aspec.c_name}[i];") 1706 ri.cw.p(f"if ({aspec.nested_rende 1247 ri.cw.p(f"if ({aspec.nested_render_name}_parse(&parg, attr))") 1707 ri.cw.p('return YNL_PARSE_CB_ERRO !! 1248 ri.cw.p('return MNL_CB_ERROR;') 1708 elif aspec.type in scalars: !! 1249 elif aspec['type'] in scalars: 1709 ri.cw.p(f"dst->{aspec.c_name}[i] !! 1250 t = aspec['type'] >> 1251 if t[0] == 's': >> 1252 t = 'u' + t[1:] >> 1253 ri.cw.p(f"dst->{aspec.c_name}[i] = mnl_attr_get_{t}(attr);") 1710 else: 1254 else: 1711 raise Exception('Nest parsing typ 1255 raise Exception('Nest parsing type not supported yet') 1712 ri.cw.p('i++;') 1256 ri.cw.p('i++;') 1713 ri.cw.block_end() 1257 ri.cw.block_end() 1714 ri.cw.block_end() 1258 ri.cw.block_end() 1715 ri.cw.block_end() 1259 ri.cw.block_end() 1716 ri.cw.nl() 1260 ri.cw.nl() 1717 1261 1718 if struct.nested: 1262 if struct.nested: 1719 ri.cw.p('return 0;') 1263 ri.cw.p('return 0;') 1720 else: 1264 else: 1721 ri.cw.p('return YNL_PARSE_CB_OK;') !! 1265 ri.cw.p('return MNL_CB_OK;') 1722 ri.cw.block_end() 1266 ri.cw.block_end() 1723 ri.cw.nl() 1267 ri.cw.nl() 1724 1268 1725 1269 1726 def parse_rsp_nested_prototype(ri, struct, su !! 1270 def parse_rsp_nested(ri, struct): 1727 func_args = ['struct ynl_parse_arg *yarg' 1271 func_args = ['struct ynl_parse_arg *yarg', 1728 'const struct nlattr *nested 1272 'const struct nlattr *nested'] 1729 for arg in struct.inherited: 1273 for arg in struct.inherited: 1730 func_args.append('__u32 ' + arg) 1274 func_args.append('__u32 ' + arg) 1731 1275 1732 ri.cw.write_func_prot('int', f'{struct.re << 1733 suffix=suffix) << 1734 << 1735 << 1736 def parse_rsp_nested(ri, struct): << 1737 parse_rsp_nested_prototype(ri, struct, su << 1738 << 1739 local_vars = ['const struct nlattr *attr; 1276 local_vars = ['const struct nlattr *attr;', 1740 f'{struct.ptr_name}dst = ya 1277 f'{struct.ptr_name}dst = yarg->data;'] 1741 init_lines = [] 1278 init_lines = [] 1742 1279 >> 1280 ri.cw.write_func_prot('int', f'{struct.render_name}_parse', func_args) >> 1281 1743 _multi_parse(ri, struct, init_lines, loca 1282 _multi_parse(ri, struct, init_lines, local_vars) 1744 1283 1745 1284 1746 def parse_rsp_msg(ri, deref=False): 1285 def parse_rsp_msg(ri, deref=False): 1747 if 'reply' not in ri.op[ri.op_mode] and r 1286 if 'reply' not in ri.op[ri.op_mode] and ri.op_mode != 'event': 1748 return 1287 return 1749 1288 1750 func_args = ['const struct nlmsghdr *nlh' 1289 func_args = ['const struct nlmsghdr *nlh', 1751 'struct ynl_parse_arg *yarg' !! 1290 'void *data'] 1752 1291 1753 local_vars = [f'{type_name(ri, "reply", d 1292 local_vars = [f'{type_name(ri, "reply", deref=deref)} *dst;', >> 1293 'struct ynl_parse_arg *yarg = data;', 1754 'const struct nlattr *attr; 1294 'const struct nlattr *attr;'] 1755 init_lines = ['dst = yarg->data;'] 1295 init_lines = ['dst = yarg->data;'] 1756 1296 1757 ri.cw.write_func_prot('int', f'{op_prefix 1297 ri.cw.write_func_prot('int', f'{op_prefix(ri, "reply", deref=deref)}_parse', func_args) 1758 1298 1759 if ri.struct["reply"].member_list(): !! 1299 _multi_parse(ri, ri.struct["reply"], init_lines, local_vars) 1760 _multi_parse(ri, ri.struct["reply"], << 1761 else: << 1762 # Empty reply << 1763 ri.cw.block_start() << 1764 ri.cw.p('return YNL_PARSE_CB_OK;') << 1765 ri.cw.block_end() << 1766 ri.cw.nl() << 1767 1300 1768 1301 1769 def print_req(ri): 1302 def print_req(ri): 1770 ret_ok = '0' 1303 ret_ok = '0' 1771 ret_err = '-1' 1304 ret_err = '-1' 1772 direction = "request" 1305 direction = "request" 1773 local_vars = ['struct ynl_req_state yrs = !! 1306 local_vars = ['struct nlmsghdr *nlh;', 1774 'struct nlmsghdr *nlh;', !! 1307 'int len, err;'] 1775 'int err;'] << 1776 1308 1777 if 'reply' in ri.op[ri.op_mode]: 1309 if 'reply' in ri.op[ri.op_mode]: 1778 ret_ok = 'rsp' 1310 ret_ok = 'rsp' 1779 ret_err = 'NULL' 1311 ret_err = 'NULL' 1780 local_vars += [f'{type_name(ri, rdir( !! 1312 local_vars += [f'{type_name(ri, rdir(direction))} *rsp;', 1781 !! 1313 'struct ynl_parse_arg yarg = { .ys = ys, };'] 1782 if ri.fixed_hdr: << 1783 local_vars += ['size_t hdr_len;', << 1784 'void *hdr;'] << 1785 1314 1786 print_prototype(ri, direction, terminate= 1315 print_prototype(ri, direction, terminate=False) 1787 ri.cw.block_start() 1316 ri.cw.block_start() 1788 ri.cw.write_func_lvar(local_vars) 1317 ri.cw.write_func_lvar(local_vars) 1789 1318 1790 ri.cw.p(f"nlh = ynl_gemsg_start_req(ys, { 1319 ri.cw.p(f"nlh = ynl_gemsg_start_req(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);") 1791 1320 1792 ri.cw.p(f"ys->req_policy = &{ri.struct['r 1321 ri.cw.p(f"ys->req_policy = &{ri.struct['request'].render_name}_nest;") 1793 if 'reply' in ri.op[ri.op_mode]: 1322 if 'reply' in ri.op[ri.op_mode]: 1794 ri.cw.p(f"yrs.yarg.rsp_policy = &{ri. !! 1323 ri.cw.p(f"yarg.rsp_policy = &{ri.struct['reply'].render_name}_nest;") 1795 ri.cw.nl() 1324 ri.cw.nl() 1796 << 1797 if ri.fixed_hdr: << 1798 ri.cw.p("hdr_len = sizeof(req->_hdr); << 1799 ri.cw.p("hdr = ynl_nlmsg_put_extra_he << 1800 ri.cw.p("memcpy(hdr, &req->_hdr, hdr_ << 1801 ri.cw.nl() << 1802 << 1803 for _, attr in ri.struct["request"].membe 1325 for _, attr in ri.struct["request"].member_list(): 1804 attr.attr_put(ri, "req") 1326 attr.attr_put(ri, "req") 1805 ri.cw.nl() 1327 ri.cw.nl() 1806 1328 >> 1329 ri.cw.p('err = mnl_socket_sendto(ys->sock, nlh, nlh->nlmsg_len);') >> 1330 ri.cw.p('if (err < 0)') >> 1331 ri.cw.p(f"return {ret_err};") >> 1332 ri.cw.nl() >> 1333 ri.cw.p('len = mnl_socket_recvfrom(ys->sock, ys->rx_buf, MNL_SOCKET_BUFFER_SIZE);') >> 1334 ri.cw.p('if (len < 0)') >> 1335 ri.cw.p(f"return {ret_err};") >> 1336 ri.cw.nl() >> 1337 1807 if 'reply' in ri.op[ri.op_mode]: 1338 if 'reply' in ri.op[ri.op_mode]: 1808 ri.cw.p('rsp = calloc(1, sizeof(*rsp) 1339 ri.cw.p('rsp = calloc(1, sizeof(*rsp));') 1809 ri.cw.p('yrs.yarg.data = rsp;') !! 1340 ri.cw.p('yarg.data = rsp;') 1810 ri.cw.p(f"yrs.cb = {op_prefix(ri, 're << 1811 if ri.op.value is not None: << 1812 ri.cw.p(f'yrs.rsp_cmd = {ri.op.en << 1813 else: << 1814 ri.cw.p(f'yrs.rsp_cmd = {ri.op.rs << 1815 ri.cw.nl() 1341 ri.cw.nl() 1816 ri.cw.p("err = ynl_exec(ys, nlh, &yrs);") !! 1342 ri.cw.p(f"err = {ri.nl.parse_cb_run(op_prefix(ri, 'reply') + '_parse', '&yarg', False)};") 1817 ri.cw.p('if (err < 0)') !! 1343 ri.cw.p('if (err < 0)') 1818 if 'reply' in ri.op[ri.op_mode]: << 1819 ri.cw.p('goto err_free;') 1344 ri.cw.p('goto err_free;') 1820 else: !! 1345 ri.cw.nl() 1821 ri.cw.p('return -1;') << 1822 ri.cw.nl() << 1823 1346 >> 1347 ri.cw.p('err = ynl_recv_ack(ys, err);') >> 1348 ri.cw.p('if (err)') >> 1349 ri.cw.p('goto err_free;') >> 1350 ri.cw.nl() 1824 ri.cw.p(f"return {ret_ok};") 1351 ri.cw.p(f"return {ret_ok};") 1825 ri.cw.nl() 1352 ri.cw.nl() >> 1353 ri.cw.p('err_free:') 1826 1354 1827 if 'reply' in ri.op[ri.op_mode]: 1355 if 'reply' in ri.op[ri.op_mode]: 1828 ri.cw.p('err_free:') << 1829 ri.cw.p(f"{call_free(ri, rdir(directi 1356 ri.cw.p(f"{call_free(ri, rdir(direction), 'rsp')}") 1830 ri.cw.p(f"return {ret_err};") !! 1357 ri.cw.p(f"return {ret_err};") 1831 << 1832 ri.cw.block_end() 1358 ri.cw.block_end() 1833 1359 1834 1360 1835 def print_dump(ri): 1361 def print_dump(ri): 1836 direction = "request" 1362 direction = "request" 1837 print_prototype(ri, direction, terminate= 1363 print_prototype(ri, direction, terminate=False) 1838 ri.cw.block_start() 1364 ri.cw.block_start() 1839 local_vars = ['struct ynl_dump_state yds 1365 local_vars = ['struct ynl_dump_state yds = {};', 1840 'struct nlmsghdr *nlh;', 1366 'struct nlmsghdr *nlh;', 1841 'int err;'] !! 1367 'int len, err;'] 1842 << 1843 if ri.fixed_hdr: << 1844 local_vars += ['size_t hdr_len;', << 1845 'void *hdr;'] << 1846 1368 1847 ri.cw.write_func_lvar(local_vars) !! 1369 for var in local_vars: >> 1370 ri.cw.p(f'{var}') >> 1371 ri.cw.nl() 1848 1372 1849 ri.cw.p('yds.yarg.ys = ys;') !! 1373 ri.cw.p('yds.ys = ys;') 1850 ri.cw.p(f"yds.yarg.rsp_policy = &{ri.stru << 1851 ri.cw.p("yds.yarg.data = NULL;") << 1852 ri.cw.p(f"yds.alloc_sz = sizeof({type_nam 1374 ri.cw.p(f"yds.alloc_sz = sizeof({type_name(ri, rdir(direction))});") 1853 ri.cw.p(f"yds.cb = {op_prefix(ri, 'reply' 1375 ri.cw.p(f"yds.cb = {op_prefix(ri, 'reply', deref=True)}_parse;") 1854 if ri.op.value is not None: !! 1376 ri.cw.p(f"yds.rsp_policy = &{ri.struct['reply'].render_name}_nest;") 1855 ri.cw.p(f'yds.rsp_cmd = {ri.op.enum_n << 1856 else: << 1857 ri.cw.p(f'yds.rsp_cmd = {ri.op.rsp_va << 1858 ri.cw.nl() 1377 ri.cw.nl() 1859 ri.cw.p(f"nlh = ynl_gemsg_start_dump(ys, 1378 ri.cw.p(f"nlh = ynl_gemsg_start_dump(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);") 1860 1379 1861 if ri.fixed_hdr: << 1862 ri.cw.p("hdr_len = sizeof(req->_hdr); << 1863 ri.cw.p("hdr = ynl_nlmsg_put_extra_he << 1864 ri.cw.p("memcpy(hdr, &req->_hdr, hdr_ << 1865 ri.cw.nl() << 1866 << 1867 if "request" in ri.op[ri.op_mode]: 1380 if "request" in ri.op[ri.op_mode]: 1868 ri.cw.p(f"ys->req_policy = &{ri.struc 1381 ri.cw.p(f"ys->req_policy = &{ri.struct['request'].render_name}_nest;") 1869 ri.cw.nl() 1382 ri.cw.nl() 1870 for _, attr in ri.struct["request"].m 1383 for _, attr in ri.struct["request"].member_list(): 1871 attr.attr_put(ri, "req") 1384 attr.attr_put(ri, "req") 1872 ri.cw.nl() 1385 ri.cw.nl() 1873 1386 1874 ri.cw.p('err = ynl_exec_dump(ys, nlh, &yd !! 1387 ri.cw.p('err = mnl_socket_sendto(ys->sock, nlh, nlh->nlmsg_len);') >> 1388 ri.cw.p('if (err < 0)') >> 1389 ri.cw.p('return NULL;') >> 1390 ri.cw.nl() >> 1391 >> 1392 ri.cw.block_start(line='do') >> 1393 ri.cw.p('len = mnl_socket_recvfrom(ys->sock, ys->rx_buf, MNL_SOCKET_BUFFER_SIZE);') >> 1394 ri.cw.p('if (len < 0)') >> 1395 ri.cw.p('goto free_list;') >> 1396 ri.cw.nl() >> 1397 ri.cw.p(f"err = {ri.nl.parse_cb_run('ynl_dump_trampoline', '&yds', False, indent=2)};") 1875 ri.cw.p('if (err < 0)') 1398 ri.cw.p('if (err < 0)') 1876 ri.cw.p('goto free_list;') 1399 ri.cw.p('goto free_list;') >> 1400 ri.cw.block_end(line='while (err > 0);') 1877 ri.cw.nl() 1401 ri.cw.nl() 1878 1402 1879 ri.cw.p('return yds.first;') 1403 ri.cw.p('return yds.first;') 1880 ri.cw.nl() 1404 ri.cw.nl() 1881 ri.cw.p('free_list:') 1405 ri.cw.p('free_list:') 1882 ri.cw.p(call_free(ri, rdir(direction), 'y 1406 ri.cw.p(call_free(ri, rdir(direction), 'yds.first')) 1883 ri.cw.p('return NULL;') 1407 ri.cw.p('return NULL;') 1884 ri.cw.block_end() 1408 ri.cw.block_end() 1885 1409 1886 1410 1887 def call_free(ri, direction, var): 1411 def call_free(ri, direction, var): 1888 return f"{op_prefix(ri, direction)}_free( 1412 return f"{op_prefix(ri, direction)}_free({var});" 1889 1413 1890 1414 1891 def free_arg_name(direction): 1415 def free_arg_name(direction): 1892 if direction: 1416 if direction: 1893 return direction_to_suffix[direction] 1417 return direction_to_suffix[direction][1:] 1894 return 'obj' 1418 return 'obj' 1895 1419 1896 1420 1897 def print_alloc_wrapper(ri, direction): << 1898 name = op_prefix(ri, direction) << 1899 ri.cw.write_func_prot(f'static inline str << 1900 ri.cw.block_start() << 1901 ri.cw.p(f'return calloc(1, sizeof(struct << 1902 ri.cw.block_end() << 1903 << 1904 << 1905 def print_free_prototype(ri, direction, suffi 1421 def print_free_prototype(ri, direction, suffix=';'): 1906 name = op_prefix(ri, direction) 1422 name = op_prefix(ri, direction) 1907 struct_name = name << 1908 if ri.type_name_conflict: << 1909 struct_name += '_' << 1910 arg = free_arg_name(direction) 1423 arg = free_arg_name(direction) 1911 ri.cw.write_func_prot('void', f"{name}_fr !! 1424 ri.cw.write_func_prot('void', f"{name}_free", [f"struct {name} *{arg}"], suffix=suffix) 1912 1425 1913 1426 1914 def _print_type(ri, direction, struct): 1427 def _print_type(ri, direction, struct): 1915 suffix = f'_{ri.type_name}{direction_to_s 1428 suffix = f'_{ri.type_name}{direction_to_suffix[direction]}' 1916 if not direction and ri.type_name_conflic << 1917 suffix += '_' << 1918 1429 1919 if ri.op_mode == 'dump': 1430 if ri.op_mode == 'dump': 1920 suffix += '_dump' 1431 suffix += '_dump' 1921 1432 1922 ri.cw.block_start(line=f"struct {ri.famil !! 1433 ri.cw.block_start(line=f"struct {ri.family['name']}{suffix}") 1923 << 1924 if ri.fixed_hdr: << 1925 ri.cw.p(ri.fixed_hdr + ' _hdr;') << 1926 ri.cw.nl() << 1927 1434 1928 meta_started = False 1435 meta_started = False 1929 for _, attr in struct.member_list(): 1436 for _, attr in struct.member_list(): 1930 for type_filter in ['len', 'bit']: 1437 for type_filter in ['len', 'bit']: 1931 line = attr.presence_member(ri.ku 1438 line = attr.presence_member(ri.ku_space, type_filter) 1932 if line: 1439 if line: 1933 if not meta_started: 1440 if not meta_started: 1934 ri.cw.block_start(line=f" 1441 ri.cw.block_start(line=f"struct") 1935 meta_started = True 1442 meta_started = True 1936 ri.cw.p(line) 1443 ri.cw.p(line) 1937 if meta_started: 1444 if meta_started: 1938 ri.cw.block_end(line='_present;') 1445 ri.cw.block_end(line='_present;') 1939 ri.cw.nl() 1446 ri.cw.nl() 1940 1447 1941 for arg in struct.inherited: 1448 for arg in struct.inherited: 1942 ri.cw.p(f"__u32 {arg};") 1449 ri.cw.p(f"__u32 {arg};") 1943 1450 1944 for _, attr in struct.member_list(): 1451 for _, attr in struct.member_list(): 1945 attr.struct_member(ri) 1452 attr.struct_member(ri) 1946 1453 1947 ri.cw.block_end(line=';') 1454 ri.cw.block_end(line=';') 1948 ri.cw.nl() 1455 ri.cw.nl() 1949 1456 1950 1457 1951 def print_type(ri, direction): 1458 def print_type(ri, direction): 1952 _print_type(ri, direction, ri.struct[dire 1459 _print_type(ri, direction, ri.struct[direction]) 1953 1460 1954 1461 1955 def print_type_full(ri, struct): 1462 def print_type_full(ri, struct): 1956 _print_type(ri, "", struct) 1463 _print_type(ri, "", struct) 1957 1464 1958 1465 1959 def print_type_helpers(ri, direction, deref=F 1466 def print_type_helpers(ri, direction, deref=False): 1960 print_free_prototype(ri, direction) 1467 print_free_prototype(ri, direction) 1961 ri.cw.nl() << 1962 1468 1963 if ri.ku_space == 'user' and direction == 1469 if ri.ku_space == 'user' and direction == 'request': 1964 for _, attr in ri.struct[direction].m 1470 for _, attr in ri.struct[direction].member_list(): 1965 attr.setter(ri, ri.attr_set, dire 1471 attr.setter(ri, ri.attr_set, direction, deref=deref) 1966 ri.cw.nl() 1472 ri.cw.nl() 1967 1473 1968 1474 1969 def print_req_type_helpers(ri): 1475 def print_req_type_helpers(ri): 1970 if len(ri.struct["request"].attr_list) == << 1971 return << 1972 print_alloc_wrapper(ri, "request") << 1973 print_type_helpers(ri, "request") 1476 print_type_helpers(ri, "request") 1974 1477 1975 1478 1976 def print_rsp_type_helpers(ri): 1479 def print_rsp_type_helpers(ri): 1977 if 'reply' not in ri.op[ri.op_mode]: 1480 if 'reply' not in ri.op[ri.op_mode]: 1978 return 1481 return 1979 print_type_helpers(ri, "reply") 1482 print_type_helpers(ri, "reply") 1980 1483 1981 1484 1982 def print_parse_prototype(ri, direction, term 1485 def print_parse_prototype(ri, direction, terminate=True): 1983 suffix = "_rsp" if direction == "reply" e 1486 suffix = "_rsp" if direction == "reply" else "_req" 1984 term = ';' if terminate else '' 1487 term = ';' if terminate else '' 1985 1488 1986 ri.cw.write_func_prot('void', f"{ri.op.re 1489 ri.cw.write_func_prot('void', f"{ri.op.render_name}{suffix}_parse", 1987 ['const struct nlat 1490 ['const struct nlattr **tb', 1988 f"struct {ri.op.re 1491 f"struct {ri.op.render_name}{suffix} *req"], 1989 suffix=term) 1492 suffix=term) 1990 1493 1991 1494 1992 def print_req_type(ri): 1495 def print_req_type(ri): 1993 if len(ri.struct["request"].attr_list) == << 1994 return << 1995 print_type(ri, "request") 1496 print_type(ri, "request") 1996 1497 1997 1498 1998 def print_req_free(ri): << 1999 if 'request' not in ri.op[ri.op_mode]: << 2000 return << 2001 _free_type(ri, 'request', ri.struct['requ << 2002 << 2003 << 2004 def print_rsp_type(ri): 1499 def print_rsp_type(ri): 2005 if (ri.op_mode == 'do' or ri.op_mode == ' 1500 if (ri.op_mode == 'do' or ri.op_mode == 'dump') and 'reply' in ri.op[ri.op_mode]: 2006 direction = 'reply' 1501 direction = 'reply' 2007 elif ri.op_mode == 'event': 1502 elif ri.op_mode == 'event': 2008 direction = 'reply' 1503 direction = 'reply' 2009 else: 1504 else: 2010 return 1505 return 2011 print_type(ri, direction) 1506 print_type(ri, direction) 2012 1507 2013 1508 2014 def print_wrapped_type(ri): 1509 def print_wrapped_type(ri): 2015 ri.cw.block_start(line=f"{type_name(ri, ' 1510 ri.cw.block_start(line=f"{type_name(ri, 'reply')}") 2016 if ri.op_mode == 'dump': 1511 if ri.op_mode == 'dump': 2017 ri.cw.p(f"{type_name(ri, 'reply')} *n 1512 ri.cw.p(f"{type_name(ri, 'reply')} *next;") 2018 elif ri.op_mode == 'notify' or ri.op_mode 1513 elif ri.op_mode == 'notify' or ri.op_mode == 'event': 2019 ri.cw.p('__u16 family;') 1514 ri.cw.p('__u16 family;') 2020 ri.cw.p('__u8 cmd;') 1515 ri.cw.p('__u8 cmd;') 2021 ri.cw.p('struct ynl_ntf_base_type *ne << 2022 ri.cw.p(f"void (*free)({type_name(ri, 1516 ri.cw.p(f"void (*free)({type_name(ri, 'reply')} *ntf);") 2023 ri.cw.p(f"{type_name(ri, 'reply', deref=T !! 1517 ri.cw.p(f"{type_name(ri, 'reply', deref=True)} obj __attribute__ ((aligned (8)));") 2024 ri.cw.block_end(line=';') 1518 ri.cw.block_end(line=';') 2025 ri.cw.nl() 1519 ri.cw.nl() 2026 print_free_prototype(ri, 'reply') 1520 print_free_prototype(ri, 'reply') 2027 ri.cw.nl() 1521 ri.cw.nl() 2028 1522 2029 1523 2030 def _free_type_members_iter(ri, struct): 1524 def _free_type_members_iter(ri, struct): 2031 for _, attr in struct.member_list(): 1525 for _, attr in struct.member_list(): 2032 if attr.free_needs_iter(): 1526 if attr.free_needs_iter(): 2033 ri.cw.p('unsigned int i;') 1527 ri.cw.p('unsigned int i;') 2034 ri.cw.nl() 1528 ri.cw.nl() 2035 break 1529 break 2036 1530 2037 1531 2038 def _free_type_members(ri, var, struct, ref=' 1532 def _free_type_members(ri, var, struct, ref=''): 2039 for _, attr in struct.member_list(): 1533 for _, attr in struct.member_list(): 2040 attr.free(ri, var, ref) 1534 attr.free(ri, var, ref) 2041 1535 2042 1536 2043 def _free_type(ri, direction, struct): 1537 def _free_type(ri, direction, struct): 2044 var = free_arg_name(direction) 1538 var = free_arg_name(direction) 2045 1539 2046 print_free_prototype(ri, direction, suffi 1540 print_free_prototype(ri, direction, suffix='') 2047 ri.cw.block_start() 1541 ri.cw.block_start() 2048 _free_type_members_iter(ri, struct) 1542 _free_type_members_iter(ri, struct) 2049 _free_type_members(ri, var, struct) 1543 _free_type_members(ri, var, struct) 2050 if direction: 1544 if direction: 2051 ri.cw.p(f'free({var});') 1545 ri.cw.p(f'free({var});') 2052 ri.cw.block_end() 1546 ri.cw.block_end() 2053 ri.cw.nl() 1547 ri.cw.nl() 2054 1548 2055 1549 2056 def free_rsp_nested_prototype(ri): << 2057 print_free_prototype(ri, "") << 2058 << 2059 << 2060 def free_rsp_nested(ri, struct): 1550 def free_rsp_nested(ri, struct): 2061 _free_type(ri, "", struct) 1551 _free_type(ri, "", struct) 2062 1552 2063 1553 2064 def print_rsp_free(ri): 1554 def print_rsp_free(ri): 2065 if 'reply' not in ri.op[ri.op_mode]: 1555 if 'reply' not in ri.op[ri.op_mode]: 2066 return 1556 return 2067 _free_type(ri, 'reply', ri.struct['reply' 1557 _free_type(ri, 'reply', ri.struct['reply']) 2068 1558 2069 1559 2070 def print_dump_type_free(ri): 1560 def print_dump_type_free(ri): 2071 sub_type = type_name(ri, 'reply') 1561 sub_type = type_name(ri, 'reply') 2072 1562 2073 print_free_prototype(ri, 'reply', suffix= 1563 print_free_prototype(ri, 'reply', suffix='') 2074 ri.cw.block_start() 1564 ri.cw.block_start() 2075 ri.cw.p(f"{sub_type} *next = rsp;") 1565 ri.cw.p(f"{sub_type} *next = rsp;") 2076 ri.cw.nl() 1566 ri.cw.nl() 2077 ri.cw.block_start(line='while ((void *)ne !! 1567 ri.cw.block_start(line='while (next)') 2078 _free_type_members_iter(ri, ri.struct['re 1568 _free_type_members_iter(ri, ri.struct['reply']) 2079 ri.cw.p('rsp = next;') 1569 ri.cw.p('rsp = next;') 2080 ri.cw.p('next = rsp->next;') 1570 ri.cw.p('next = rsp->next;') 2081 ri.cw.nl() 1571 ri.cw.nl() 2082 1572 2083 _free_type_members(ri, 'rsp', ri.struct[' 1573 _free_type_members(ri, 'rsp', ri.struct['reply'], ref='obj.') 2084 ri.cw.p(f'free(rsp);') 1574 ri.cw.p(f'free(rsp);') 2085 ri.cw.block_end() 1575 ri.cw.block_end() 2086 ri.cw.block_end() 1576 ri.cw.block_end() 2087 ri.cw.nl() 1577 ri.cw.nl() 2088 1578 2089 1579 2090 def print_ntf_type_free(ri): 1580 def print_ntf_type_free(ri): 2091 print_free_prototype(ri, 'reply', suffix= 1581 print_free_prototype(ri, 'reply', suffix='') 2092 ri.cw.block_start() 1582 ri.cw.block_start() 2093 _free_type_members_iter(ri, ri.struct['re 1583 _free_type_members_iter(ri, ri.struct['reply']) 2094 _free_type_members(ri, 'rsp', ri.struct[' 1584 _free_type_members(ri, 'rsp', ri.struct['reply'], ref='obj.') 2095 ri.cw.p(f'free(rsp);') 1585 ri.cw.p(f'free(rsp);') 2096 ri.cw.block_end() 1586 ri.cw.block_end() 2097 ri.cw.nl() 1587 ri.cw.nl() 2098 1588 2099 1589 >> 1590 def print_ntf_parse_prototype(family, cw, suffix=';'): >> 1591 cw.write_func_prot('struct ynl_ntf_base_type *', f"{family['name']}_ntf_parse", >> 1592 ['struct ynl_sock *ys'], suffix=suffix) >> 1593 >> 1594 >> 1595 def print_ntf_type_parse(family, cw, ku_mode): >> 1596 print_ntf_parse_prototype(family, cw, suffix='') >> 1597 cw.block_start() >> 1598 cw.write_func_lvar(['struct genlmsghdr *genlh;', >> 1599 'struct nlmsghdr *nlh;', >> 1600 'struct ynl_parse_arg yarg = { .ys = ys, };', >> 1601 'struct ynl_ntf_base_type *rsp;', >> 1602 'int len, err;', >> 1603 'mnl_cb_t parse;']) >> 1604 cw.p('len = mnl_socket_recvfrom(ys->sock, ys->rx_buf, MNL_SOCKET_BUFFER_SIZE);') >> 1605 cw.p('if (len < (ssize_t)(sizeof(*nlh) + sizeof(*genlh)))') >> 1606 cw.p('return NULL;') >> 1607 cw.nl() >> 1608 cw.p('nlh = (struct nlmsghdr *)ys->rx_buf;') >> 1609 cw.p('genlh = mnl_nlmsg_get_payload(nlh);') >> 1610 cw.nl() >> 1611 cw.block_start(line='switch (genlh->cmd)') >> 1612 for ntf_op in sorted(family.all_notify.keys()): >> 1613 op = family.ops[ntf_op] >> 1614 ri = RenderInfo(cw, family, ku_mode, op, ntf_op, "notify") >> 1615 for ntf in op['notify']['cmds']: >> 1616 cw.p(f"case {ntf.enum_name}:") >> 1617 cw.p(f"rsp = calloc(1, sizeof({type_name(ri, 'notify')}));") >> 1618 cw.p(f"parse = {op_prefix(ri, 'reply', deref=True)}_parse;") >> 1619 cw.p(f"yarg.rsp_policy = &{ri.struct['reply'].render_name}_nest;") >> 1620 cw.p(f"rsp->free = (void *){op_prefix(ri, 'notify')}_free;") >> 1621 cw.p('break;') >> 1622 for op_name, op in family.ops.items(): >> 1623 if 'event' not in op: >> 1624 continue >> 1625 ri = RenderInfo(cw, family, ku_mode, op, op_name, "event") >> 1626 cw.p(f"case {op.enum_name}:") >> 1627 cw.p(f"rsp = calloc(1, sizeof({type_name(ri, 'event')}));") >> 1628 cw.p(f"parse = {op_prefix(ri, 'reply', deref=True)}_parse;") >> 1629 cw.p(f"yarg.rsp_policy = &{ri.struct['reply'].render_name}_nest;") >> 1630 cw.p(f"rsp->free = (void *){op_prefix(ri, 'notify')}_free;") >> 1631 cw.p('break;') >> 1632 cw.p('default:') >> 1633 cw.p('ynl_error_unknown_notification(ys, genlh->cmd);') >> 1634 cw.p('return NULL;') >> 1635 cw.block_end() >> 1636 cw.nl() >> 1637 cw.p('yarg.data = rsp->data;') >> 1638 cw.nl() >> 1639 cw.p(f"err = {cw.nlib.parse_cb_run('parse', '&yarg', True)};") >> 1640 cw.p('if (err < 0)') >> 1641 cw.p('goto err_free;') >> 1642 cw.nl() >> 1643 cw.p('rsp->family = nlh->nlmsg_type;') >> 1644 cw.p('rsp->cmd = genlh->cmd;') >> 1645 cw.p('return rsp;') >> 1646 cw.nl() >> 1647 cw.p('err_free:') >> 1648 cw.p('free(rsp);') >> 1649 cw.p('return NULL;') >> 1650 cw.block_end() >> 1651 cw.nl() >> 1652 >> 1653 2100 def print_req_policy_fwd(cw, struct, ri=None, 1654 def print_req_policy_fwd(cw, struct, ri=None, terminate=True): 2101 if terminate and ri and policy_should_be_ !! 1655 if terminate and ri and kernel_can_gen_family_struct(struct.family): 2102 return 1656 return 2103 1657 2104 if terminate: 1658 if terminate: 2105 prefix = 'extern ' 1659 prefix = 'extern ' 2106 else: 1660 else: 2107 if ri and policy_should_be_static(str !! 1661 if kernel_can_gen_family_struct(struct.family) and ri: 2108 prefix = 'static ' 1662 prefix = 'static ' 2109 else: 1663 else: 2110 prefix = '' 1664 prefix = '' 2111 1665 2112 suffix = ';' if terminate else ' = {' 1666 suffix = ';' if terminate else ' = {' 2113 1667 2114 max_attr = struct.attr_max_val 1668 max_attr = struct.attr_max_val 2115 if ri: 1669 if ri: 2116 name = ri.op.render_name 1670 name = ri.op.render_name 2117 if ri.op.dual_policy: 1671 if ri.op.dual_policy: 2118 name += '_' + ri.op_mode 1672 name += '_' + ri.op_mode 2119 else: 1673 else: 2120 name = struct.render_name 1674 name = struct.render_name 2121 cw.p(f"{prefix}const struct nla_policy {n 1675 cw.p(f"{prefix}const struct nla_policy {name}_nl_policy[{max_attr.enum_name} + 1]{suffix}") 2122 1676 2123 1677 2124 def print_req_policy(cw, struct, ri=None): 1678 def print_req_policy(cw, struct, ri=None): 2125 if ri and ri.op: << 2126 cw.ifdef_block(ri.op.get('config-cond << 2127 print_req_policy_fwd(cw, struct, ri=ri, t 1679 print_req_policy_fwd(cw, struct, ri=ri, terminate=False) 2128 for _, arg in struct.member_list(): 1680 for _, arg in struct.member_list(): 2129 arg.attr_policy(cw) 1681 arg.attr_policy(cw) 2130 cw.p("};") 1682 cw.p("};") 2131 cw.ifdef_block(None) << 2132 cw.nl() << 2133 1683 2134 1684 2135 def kernel_can_gen_family_struct(family): 1685 def kernel_can_gen_family_struct(family): 2136 return family.proto == 'genetlink' 1686 return family.proto == 'genetlink' 2137 1687 2138 1688 2139 def policy_should_be_static(family): << 2140 return family.kernel_policy == 'split' or << 2141 << 2142 << 2143 def print_kernel_policy_ranges(family, cw): << 2144 first = True << 2145 for _, attr_set in family.attr_sets.items << 2146 if attr_set.subset_of: << 2147 continue << 2148 << 2149 for _, attr in attr_set.items(): << 2150 if not attr.request: << 2151 continue << 2152 if 'full-range' not in attr.check << 2153 continue << 2154 << 2155 if first: << 2156 cw.p('/* Integer value ranges << 2157 first = False << 2158 << 2159 sign = '' if attr.type[0] == 'u' << 2160 suffix = 'ULL' if attr.type[0] == << 2161 cw.block_start(line=f'static cons << 2162 members = [] << 2163 if 'min' in attr.checks: << 2164 members.append(('min', str(at << 2165 if 'max' in attr.checks: << 2166 members.append(('max', str(at << 2167 cw.write_struct_init(members) << 2168 cw.block_end(line=';') << 2169 cw.nl() << 2170 << 2171 << 2172 def print_kernel_op_table_fwd(family, cw, ter 1689 def print_kernel_op_table_fwd(family, cw, terminate): 2173 exported = not kernel_can_gen_family_stru 1690 exported = not kernel_can_gen_family_struct(family) 2174 1691 2175 if not terminate or exported: 1692 if not terminate or exported: 2176 cw.p(f"/* Ops table for {family.ident !! 1693 cw.p(f"/* Ops table for {family.name} */") 2177 1694 2178 pol_to_struct = {'global': 'genl_smal 1695 pol_to_struct = {'global': 'genl_small_ops', 2179 'per-op': 'genl_ops' 1696 'per-op': 'genl_ops', 2180 'split': 'genl_split 1697 'split': 'genl_split_ops'} 2181 struct_type = pol_to_struct[family.ke 1698 struct_type = pol_to_struct[family.kernel_policy] 2182 1699 2183 if not exported: 1700 if not exported: 2184 cnt = "" 1701 cnt = "" 2185 elif family.kernel_policy == 'split': 1702 elif family.kernel_policy == 'split': 2186 cnt = 0 1703 cnt = 0 2187 for op in family.ops.values(): 1704 for op in family.ops.values(): 2188 if 'do' in op: 1705 if 'do' in op: 2189 cnt += 1 1706 cnt += 1 2190 if 'dump' in op: 1707 if 'dump' in op: 2191 cnt += 1 1708 cnt += 1 2192 else: 1709 else: 2193 cnt = len(family.ops) 1710 cnt = len(family.ops) 2194 1711 2195 qual = 'static const' if not exported 1712 qual = 'static const' if not exported else 'const' 2196 line = f"{qual} struct {struct_type} !! 1713 line = f"{qual} struct {struct_type} {family.name}_nl_ops[{cnt}]" 2197 if terminate: 1714 if terminate: 2198 cw.p(f"extern {line};") 1715 cw.p(f"extern {line};") 2199 else: 1716 else: 2200 cw.block_start(line=line + ' =') 1717 cw.block_start(line=line + ' =') 2201 1718 2202 if not terminate: 1719 if not terminate: 2203 return 1720 return 2204 1721 2205 cw.nl() 1722 cw.nl() 2206 for name in family.hooks['pre']['do']['li 1723 for name in family.hooks['pre']['do']['list']: 2207 cw.write_func_prot('int', c_lower(nam 1724 cw.write_func_prot('int', c_lower(name), 2208 ['const struct gen 1725 ['const struct genl_split_ops *ops', 2209 'struct sk_buff * 1726 'struct sk_buff *skb', 'struct genl_info *info'], suffix=';') 2210 for name in family.hooks['post']['do']['l 1727 for name in family.hooks['post']['do']['list']: 2211 cw.write_func_prot('void', c_lower(na 1728 cw.write_func_prot('void', c_lower(name), 2212 ['const struct gen 1729 ['const struct genl_split_ops *ops', 2213 'struct sk_buff * 1730 'struct sk_buff *skb', 'struct genl_info *info'], suffix=';') 2214 for name in family.hooks['pre']['dump'][' 1731 for name in family.hooks['pre']['dump']['list']: 2215 cw.write_func_prot('int', c_lower(nam 1732 cw.write_func_prot('int', c_lower(name), 2216 ['struct netlink_c 1733 ['struct netlink_callback *cb'], suffix=';') 2217 for name in family.hooks['post']['dump'][ 1734 for name in family.hooks['post']['dump']['list']: 2218 cw.write_func_prot('int', c_lower(nam 1735 cw.write_func_prot('int', c_lower(name), 2219 ['struct netlink_c 1736 ['struct netlink_callback *cb'], suffix=';') 2220 1737 2221 cw.nl() 1738 cw.nl() 2222 1739 2223 for op_name, op in family.ops.items(): 1740 for op_name, op in family.ops.items(): 2224 if op.is_async: 1741 if op.is_async: 2225 continue 1742 continue 2226 1743 2227 if 'do' in op: 1744 if 'do' in op: 2228 name = c_lower(f"{family.ident_na !! 1745 name = c_lower(f"{family.name}-nl-{op_name}-doit") 2229 cw.write_func_prot('int', name, 1746 cw.write_func_prot('int', name, 2230 ['struct sk_bu 1747 ['struct sk_buff *skb', 'struct genl_info *info'], suffix=';') 2231 1748 2232 if 'dump' in op: 1749 if 'dump' in op: 2233 name = c_lower(f"{family.ident_na !! 1750 name = c_lower(f"{family.name}-nl-{op_name}-dumpit") 2234 cw.write_func_prot('int', name, 1751 cw.write_func_prot('int', name, 2235 ['struct sk_bu 1752 ['struct sk_buff *skb', 'struct netlink_callback *cb'], suffix=';') 2236 cw.nl() 1753 cw.nl() 2237 1754 2238 1755 2239 def print_kernel_op_table_hdr(family, cw): 1756 def print_kernel_op_table_hdr(family, cw): 2240 print_kernel_op_table_fwd(family, cw, ter 1757 print_kernel_op_table_fwd(family, cw, terminate=True) 2241 1758 2242 1759 2243 def print_kernel_op_table(family, cw): 1760 def print_kernel_op_table(family, cw): 2244 print_kernel_op_table_fwd(family, cw, ter 1761 print_kernel_op_table_fwd(family, cw, terminate=False) 2245 if family.kernel_policy == 'global' or fa 1762 if family.kernel_policy == 'global' or family.kernel_policy == 'per-op': 2246 for op_name, op in family.ops.items() 1763 for op_name, op in family.ops.items(): 2247 if op.is_async: 1764 if op.is_async: 2248 continue 1765 continue 2249 1766 2250 cw.ifdef_block(op.get('config-con << 2251 cw.block_start() 1767 cw.block_start() 2252 members = [('cmd', op.enum_name)] 1768 members = [('cmd', op.enum_name)] 2253 if 'dont-validate' in op: 1769 if 'dont-validate' in op: 2254 members.append(('validate', 1770 members.append(('validate', 2255 ' | '.join([c 1771 ' | '.join([c_upper('genl-dont-validate-' + x) 2256 f 1772 for x in op['dont-validate']])), ) 2257 for op_mode in ['do', 'dump']: 1773 for op_mode in ['do', 'dump']: 2258 if op_mode in op: 1774 if op_mode in op: 2259 name = c_lower(f"{family. !! 1775 name = c_lower(f"{family.name}-nl-{op_name}-{op_mode}it") 2260 members.append((op_mode + 1776 members.append((op_mode + 'it', name)) 2261 if family.kernel_policy == 'per-o 1777 if family.kernel_policy == 'per-op': 2262 struct = Struct(family, op['a 1778 struct = Struct(family, op['attribute-set'], 2263 type_list=op[ 1779 type_list=op['do']['request']['attributes']) 2264 1780 2265 name = c_lower(f"{family.iden !! 1781 name = c_lower(f"{family.name}-{op_name}-nl-policy") 2266 members.append(('policy', nam 1782 members.append(('policy', name)) 2267 members.append(('maxattr', st 1783 members.append(('maxattr', struct.attr_max_val.enum_name)) 2268 if 'flags' in op: 1784 if 'flags' in op: 2269 members.append(('flags', ' | 1785 members.append(('flags', ' | '.join([c_upper('genl-' + x) for x in op['flags']]))) 2270 cw.write_struct_init(members) 1786 cw.write_struct_init(members) 2271 cw.block_end(line=',') 1787 cw.block_end(line=',') 2272 elif family.kernel_policy == 'split': 1788 elif family.kernel_policy == 'split': 2273 cb_names = {'do': {'pre': 'pre_doit 1789 cb_names = {'do': {'pre': 'pre_doit', 'post': 'post_doit'}, 2274 'dump': {'pre': 'start', 1790 'dump': {'pre': 'start', 'post': 'done'}} 2275 1791 2276 for op_name, op in family.ops.items() 1792 for op_name, op in family.ops.items(): 2277 for op_mode in ['do', 'dump']: 1793 for op_mode in ['do', 'dump']: 2278 if op.is_async or op_mode not 1794 if op.is_async or op_mode not in op: 2279 continue 1795 continue 2280 1796 2281 cw.ifdef_block(op.get('config << 2282 cw.block_start() 1797 cw.block_start() 2283 members = [('cmd', op.enum_na 1798 members = [('cmd', op.enum_name)] 2284 if 'dont-validate' in op: 1799 if 'dont-validate' in op: 2285 dont_validate = [] !! 1800 members.append(('validate', 2286 for x in op['dont-validat !! 1801 ' | '.join([c_upper('genl-dont-validate-' + x) 2287 if op_mode == 'do' an !! 1802 for x in op['dont-validate']])), ) 2288 continue !! 1803 name = c_lower(f"{family.name}-nl-{op_name}-{op_mode}it") 2289 if op_mode == "dump" << 2290 continue << 2291 dont_validate.append( << 2292 << 2293 if dont_validate: << 2294 members.append(('vali << 2295 ' | ' << 2296 << 2297 name = c_lower(f"{family.iden << 2298 if 'pre' in op[op_mode]: 1804 if 'pre' in op[op_mode]: 2299 members.append((cb_names[ 1805 members.append((cb_names[op_mode]['pre'], c_lower(op[op_mode]['pre']))) 2300 members.append((op_mode + 'it 1806 members.append((op_mode + 'it', name)) 2301 if 'post' in op[op_mode]: 1807 if 'post' in op[op_mode]: 2302 members.append((cb_names[ 1808 members.append((cb_names[op_mode]['post'], c_lower(op[op_mode]['post']))) 2303 if 'request' in op[op_mode]: 1809 if 'request' in op[op_mode]: 2304 struct = Struct(family, o 1810 struct = Struct(family, op['attribute-set'], 2305 type_list 1811 type_list=op[op_mode]['request']['attributes']) 2306 1812 2307 if op.dual_policy: 1813 if op.dual_policy: 2308 name = c_lower(f"{fam !! 1814 name = c_lower(f"{family.name}-{op_name}-{op_mode}-nl-policy") 2309 else: 1815 else: 2310 name = c_lower(f"{fam !! 1816 name = c_lower(f"{family.name}-{op_name}-nl-policy") 2311 members.append(('policy', 1817 members.append(('policy', name)) 2312 members.append(('maxattr' 1818 members.append(('maxattr', struct.attr_max_val.enum_name)) 2313 flags = (op['flags'] if 'flag 1819 flags = (op['flags'] if 'flags' in op else []) + ['cmd-cap-' + op_mode] 2314 members.append(('flags', ' | 1820 members.append(('flags', ' | '.join([c_upper('genl-' + x) for x in flags]))) 2315 cw.write_struct_init(members) 1821 cw.write_struct_init(members) 2316 cw.block_end(line=',') 1822 cw.block_end(line=',') 2317 cw.ifdef_block(None) << 2318 1823 2319 cw.block_end(line=';') 1824 cw.block_end(line=';') 2320 cw.nl() 1825 cw.nl() 2321 1826 2322 1827 2323 def print_kernel_mcgrp_hdr(family, cw): 1828 def print_kernel_mcgrp_hdr(family, cw): 2324 if not family.mcgrps['list']: 1829 if not family.mcgrps['list']: 2325 return 1830 return 2326 1831 2327 cw.block_start('enum') 1832 cw.block_start('enum') 2328 for grp in family.mcgrps['list']: 1833 for grp in family.mcgrps['list']: 2329 grp_id = c_upper(f"{family.ident_name !! 1834 grp_id = c_upper(f"{family.name}-nlgrp-{grp['name']},") 2330 cw.p(grp_id) 1835 cw.p(grp_id) 2331 cw.block_end(';') 1836 cw.block_end(';') 2332 cw.nl() 1837 cw.nl() 2333 1838 2334 1839 2335 def print_kernel_mcgrp_src(family, cw): 1840 def print_kernel_mcgrp_src(family, cw): 2336 if not family.mcgrps['list']: 1841 if not family.mcgrps['list']: 2337 return 1842 return 2338 1843 2339 cw.block_start('static const struct genl_ !! 1844 cw.block_start('static const struct genl_multicast_group ' + family.name + '_nl_mcgrps[] =') 2340 for grp in family.mcgrps['list']: 1845 for grp in family.mcgrps['list']: 2341 name = grp['name'] 1846 name = grp['name'] 2342 grp_id = c_upper(f"{family.ident_name !! 1847 grp_id = c_upper(f"{family.name}-nlgrp-{name}") 2343 cw.p('[' + grp_id + '] = { "' + name 1848 cw.p('[' + grp_id + '] = { "' + name + '", },') 2344 cw.block_end(';') 1849 cw.block_end(';') 2345 cw.nl() 1850 cw.nl() 2346 1851 2347 1852 2348 def print_kernel_family_struct_hdr(family, cw 1853 def print_kernel_family_struct_hdr(family, cw): 2349 if not kernel_can_gen_family_struct(famil 1854 if not kernel_can_gen_family_struct(family): 2350 return 1855 return 2351 1856 2352 cw.p(f"extern struct genl_family {family. !! 1857 cw.p(f"extern struct genl_family {family.name}_nl_family;") 2353 cw.nl() 1858 cw.nl() 2354 if 'sock-priv' in family.kernel_family: << 2355 cw.p(f'void {family.c_name}_nl_sock_p << 2356 cw.p(f'void {family.c_name}_nl_sock_p << 2357 cw.nl() << 2358 1859 2359 1860 2360 def print_kernel_family_struct_src(family, cw 1861 def print_kernel_family_struct_src(family, cw): 2361 if not kernel_can_gen_family_struct(famil 1862 if not kernel_can_gen_family_struct(family): 2362 return 1863 return 2363 1864 2364 cw.block_start(f"struct genl_family {fami !! 1865 cw.block_start(f"struct genl_family {family.name}_nl_family __ro_after_init =") 2365 cw.p('.name\t\t= ' + family.fam_key + ',' 1866 cw.p('.name\t\t= ' + family.fam_key + ',') 2366 cw.p('.version\t= ' + family.ver_key + ', 1867 cw.p('.version\t= ' + family.ver_key + ',') 2367 cw.p('.netnsok\t= true,') 1868 cw.p('.netnsok\t= true,') 2368 cw.p('.parallel_ops\t= true,') 1869 cw.p('.parallel_ops\t= true,') 2369 cw.p('.module\t\t= THIS_MODULE,') 1870 cw.p('.module\t\t= THIS_MODULE,') 2370 if family.kernel_policy == 'per-op': 1871 if family.kernel_policy == 'per-op': 2371 cw.p(f'.ops\t\t= {family.c_name}_nl_o !! 1872 cw.p(f'.ops\t\t= {family.name}_nl_ops,') 2372 cw.p(f'.n_ops\t\t= ARRAY_SIZE({family !! 1873 cw.p(f'.n_ops\t\t= ARRAY_SIZE({family.name}_nl_ops),') 2373 elif family.kernel_policy == 'split': 1874 elif family.kernel_policy == 'split': 2374 cw.p(f'.split_ops\t= {family.c_name}_ !! 1875 cw.p(f'.split_ops\t= {family.name}_nl_ops,') 2375 cw.p(f'.n_split_ops\t= ARRAY_SIZE({fa !! 1876 cw.p(f'.n_split_ops\t= ARRAY_SIZE({family.name}_nl_ops),') 2376 if family.mcgrps['list']: 1877 if family.mcgrps['list']: 2377 cw.p(f'.mcgrps\t\t= {family.c_name}_n !! 1878 cw.p(f'.mcgrps\t\t= {family.name}_nl_mcgrps,') 2378 cw.p(f'.n_mcgrps\t= ARRAY_SIZE({famil !! 1879 cw.p(f'.n_mcgrps\t= ARRAY_SIZE({family.name}_nl_mcgrps),') 2379 if 'sock-priv' in family.kernel_family: << 2380 cw.p(f'.sock_priv_size\t= sizeof({fam << 2381 # Force cast here, actual helpers tak << 2382 cw.p(f'.sock_priv_init\t= (void *){fa << 2383 cw.p(f'.sock_priv_destroy = (void *){ << 2384 cw.block_end(';') 1880 cw.block_end(';') 2385 1881 2386 1882 2387 def uapi_enum_start(family, cw, obj, ckey='', 1883 def uapi_enum_start(family, cw, obj, ckey='', enum_name='enum-name'): 2388 start_line = 'enum' 1884 start_line = 'enum' 2389 if enum_name in obj: 1885 if enum_name in obj: 2390 if obj[enum_name]: 1886 if obj[enum_name]: 2391 start_line = 'enum ' + c_lower(ob 1887 start_line = 'enum ' + c_lower(obj[enum_name]) 2392 elif ckey and ckey in obj: 1888 elif ckey and ckey in obj: 2393 start_line = 'enum ' + family.c_name !! 1889 start_line = 'enum ' + family.name + '_' + c_lower(obj[ckey]) 2394 cw.block_start(line=start_line) 1890 cw.block_start(line=start_line) 2395 1891 2396 1892 2397 def render_uapi(family, cw): 1893 def render_uapi(family, cw): 2398 hdr_prot = f"_UAPI_LINUX_{c_upper(family. !! 1894 hdr_prot = f"_UAPI_LINUX_{family.name.upper()}_H" 2399 cw.p('#ifndef ' + hdr_prot) 1895 cw.p('#ifndef ' + hdr_prot) 2400 cw.p('#define ' + hdr_prot) 1896 cw.p('#define ' + hdr_prot) 2401 cw.nl() 1897 cw.nl() 2402 1898 2403 defines = [(family.fam_key, family["name" 1899 defines = [(family.fam_key, family["name"]), 2404 (family.ver_key, family.get('v 1900 (family.ver_key, family.get('version', 1))] 2405 cw.writes_defines(defines) 1901 cw.writes_defines(defines) 2406 cw.nl() 1902 cw.nl() 2407 1903 2408 defines = [] 1904 defines = [] 2409 for const in family['definitions']: 1905 for const in family['definitions']: 2410 if const['type'] != 'const': 1906 if const['type'] != 'const': 2411 cw.writes_defines(defines) 1907 cw.writes_defines(defines) 2412 defines = [] 1908 defines = [] 2413 cw.nl() 1909 cw.nl() 2414 1910 2415 # Write kdoc for enum and flags (one 1911 # Write kdoc for enum and flags (one day maybe also structs) 2416 if const['type'] == 'enum' or const[' 1912 if const['type'] == 'enum' or const['type'] == 'flags': 2417 enum = family.consts[const['name' 1913 enum = family.consts[const['name']] 2418 1914 2419 if enum.has_doc(): 1915 if enum.has_doc(): 2420 cw.p('/**') 1916 cw.p('/**') 2421 doc = '' 1917 doc = '' 2422 if 'doc' in enum: 1918 if 'doc' in enum: 2423 doc = ' - ' + enum['doc'] 1919 doc = ' - ' + enum['doc'] 2424 cw.write_doc_line(enum.enum_n 1920 cw.write_doc_line(enum.enum_name + doc) 2425 for entry in enum.entries.val 1921 for entry in enum.entries.values(): 2426 if entry.has_doc(): 1922 if entry.has_doc(): 2427 doc = '@' + entry.c_n 1923 doc = '@' + entry.c_name + ': ' + entry['doc'] 2428 cw.write_doc_line(doc 1924 cw.write_doc_line(doc) 2429 cw.p(' */') 1925 cw.p(' */') 2430 1926 2431 uapi_enum_start(family, cw, const 1927 uapi_enum_start(family, cw, const, 'name') 2432 name_pfx = const.get('name-prefix !! 1928 name_pfx = const.get('name-prefix', f"{family.name}-{const['name']}-") 2433 for entry in enum.entries.values( 1929 for entry in enum.entries.values(): 2434 suffix = ',' 1930 suffix = ',' 2435 if entry.value_change: 1931 if entry.value_change: 2436 suffix = f" = {entry.user 1932 suffix = f" = {entry.user_value()}" + suffix 2437 cw.p(entry.c_name + suffix) 1933 cw.p(entry.c_name + suffix) 2438 1934 2439 if const.get('render-max', False) 1935 if const.get('render-max', False): 2440 cw.nl() 1936 cw.nl() 2441 cw.p('/* private: */') << 2442 if const['type'] == 'flags': 1937 if const['type'] == 'flags': 2443 max_name = c_upper(name_p 1938 max_name = c_upper(name_pfx + 'mask') 2444 max_val = f' = {enum.get_ 1939 max_val = f' = {enum.get_mask()},' 2445 cw.p(max_name + max_val) 1940 cw.p(max_name + max_val) 2446 else: 1941 else: 2447 max_name = c_upper(name_p 1942 max_name = c_upper(name_pfx + 'max') 2448 cw.p('__' + max_name + ', 1943 cw.p('__' + max_name + ',') 2449 cw.p(max_name + ' = (__' 1944 cw.p(max_name + ' = (__' + max_name + ' - 1)') 2450 cw.block_end(line=';') 1945 cw.block_end(line=';') 2451 cw.nl() 1946 cw.nl() 2452 elif const['type'] == 'const': 1947 elif const['type'] == 'const': 2453 defines.append([c_upper(family.ge 1948 defines.append([c_upper(family.get('c-define-name', 2454 !! 1949 f"{family.name}-{const['name']}")), 2455 const['value']]) 1950 const['value']]) 2456 1951 2457 if defines: 1952 if defines: 2458 cw.writes_defines(defines) 1953 cw.writes_defines(defines) 2459 cw.nl() 1954 cw.nl() 2460 1955 2461 max_by_define = family.get('max-by-define 1956 max_by_define = family.get('max-by-define', False) 2462 1957 2463 for _, attr_set in family.attr_sets.items 1958 for _, attr_set in family.attr_sets.items(): 2464 if attr_set.subset_of: 1959 if attr_set.subset_of: 2465 continue 1960 continue 2466 1961 2467 max_value = f"({attr_set.cnt_name} - !! 1962 cnt_name = c_upper(family.get('attr-cnt-name', f"__{attr_set.name_prefix}MAX")) >> 1963 max_value = f"({cnt_name} - 1)" 2468 1964 2469 val = 0 1965 val = 0 2470 uapi_enum_start(family, cw, attr_set. 1966 uapi_enum_start(family, cw, attr_set.yaml, 'enum-name') 2471 for _, attr in attr_set.items(): 1967 for _, attr in attr_set.items(): 2472 suffix = ',' 1968 suffix = ',' 2473 if attr.value != val: 1969 if attr.value != val: 2474 suffix = f" = {attr.value}," 1970 suffix = f" = {attr.value}," 2475 val = attr.value 1971 val = attr.value 2476 val += 1 1972 val += 1 2477 cw.p(attr.enum_name + suffix) 1973 cw.p(attr.enum_name + suffix) 2478 cw.nl() 1974 cw.nl() 2479 cw.p(attr_set.cnt_name + ('' if max_b !! 1975 cw.p(cnt_name + ('' if max_by_define else ',')) 2480 if not max_by_define: 1976 if not max_by_define: 2481 cw.p(f"{attr_set.max_name} = {max 1977 cw.p(f"{attr_set.max_name} = {max_value}") 2482 cw.block_end(line=';') 1978 cw.block_end(line=';') 2483 if max_by_define: 1979 if max_by_define: 2484 cw.p(f"#define {attr_set.max_name 1980 cw.p(f"#define {attr_set.max_name} {max_value}") 2485 cw.nl() 1981 cw.nl() 2486 1982 2487 # Commands 1983 # Commands 2488 separate_ntf = 'async-prefix' in family[' 1984 separate_ntf = 'async-prefix' in family['operations'] 2489 1985 2490 max_name = c_upper(family.get('cmd-max-na 1986 max_name = c_upper(family.get('cmd-max-name', f"{family.op_prefix}MAX")) 2491 cnt_name = c_upper(family.get('cmd-cnt-na 1987 cnt_name = c_upper(family.get('cmd-cnt-name', f"__{family.op_prefix}MAX")) 2492 max_value = f"({cnt_name} - 1)" 1988 max_value = f"({cnt_name} - 1)" 2493 1989 2494 uapi_enum_start(family, cw, family['opera 1990 uapi_enum_start(family, cw, family['operations'], 'enum-name') 2495 val = 0 1991 val = 0 2496 for op in family.msgs.values(): 1992 for op in family.msgs.values(): 2497 if separate_ntf and ('notify' in op o 1993 if separate_ntf and ('notify' in op or 'event' in op): 2498 continue 1994 continue 2499 1995 2500 suffix = ',' 1996 suffix = ',' 2501 if op.value != val: 1997 if op.value != val: 2502 suffix = f" = {op.value}," 1998 suffix = f" = {op.value}," 2503 val = op.value 1999 val = op.value 2504 cw.p(op.enum_name + suffix) 2000 cw.p(op.enum_name + suffix) 2505 val += 1 2001 val += 1 2506 cw.nl() 2002 cw.nl() 2507 cw.p(cnt_name + ('' if max_by_define else 2003 cw.p(cnt_name + ('' if max_by_define else ',')) 2508 if not max_by_define: 2004 if not max_by_define: 2509 cw.p(f"{max_name} = {max_value}") 2005 cw.p(f"{max_name} = {max_value}") 2510 cw.block_end(line=';') 2006 cw.block_end(line=';') 2511 if max_by_define: 2007 if max_by_define: 2512 cw.p(f"#define {max_name} {max_value} 2008 cw.p(f"#define {max_name} {max_value}") 2513 cw.nl() 2009 cw.nl() 2514 2010 2515 if separate_ntf: 2011 if separate_ntf: 2516 uapi_enum_start(family, cw, family['o 2012 uapi_enum_start(family, cw, family['operations'], enum_name='async-enum') 2517 for op in family.msgs.values(): 2013 for op in family.msgs.values(): 2518 if separate_ntf and not ('notify' 2014 if separate_ntf and not ('notify' in op or 'event' in op): 2519 continue 2015 continue 2520 2016 2521 suffix = ',' 2017 suffix = ',' 2522 if 'value' in op: 2018 if 'value' in op: 2523 suffix = f" = {op['value']}," 2019 suffix = f" = {op['value']}," 2524 cw.p(op.enum_name + suffix) 2020 cw.p(op.enum_name + suffix) 2525 cw.block_end(line=';') 2021 cw.block_end(line=';') 2526 cw.nl() 2022 cw.nl() 2527 2023 2528 # Multicast 2024 # Multicast 2529 defines = [] 2025 defines = [] 2530 for grp in family.mcgrps['list']: 2026 for grp in family.mcgrps['list']: 2531 name = grp['name'] 2027 name = grp['name'] 2532 defines.append([c_upper(grp.get('c-de !! 2028 defines.append([c_upper(grp.get('c-define-name', f"{family.name}-mcgrp-{name}")), 2533 f'{name}']) 2029 f'{name}']) 2534 cw.nl() 2030 cw.nl() 2535 if defines: 2031 if defines: 2536 cw.writes_defines(defines) 2032 cw.writes_defines(defines) 2537 cw.nl() 2033 cw.nl() 2538 2034 2539 cw.p(f'#endif /* {hdr_prot} */') 2035 cw.p(f'#endif /* {hdr_prot} */') 2540 2036 2541 2037 2542 def _render_user_ntf_entry(ri, op): << 2543 ri.cw.block_start(line=f"[{op.enum_name}] << 2544 ri.cw.p(f".alloc_sz\t= sizeof({type_name( << 2545 ri.cw.p(f".cb\t\t= {op_prefix(ri, 'reply' << 2546 ri.cw.p(f".policy\t\t= &{ri.struct['reply << 2547 ri.cw.p(f".free\t\t= (void *){op_prefix(r << 2548 ri.cw.block_end(line=',') << 2549 << 2550 << 2551 def render_user_family(family, cw, prototype) << 2552 symbol = f'const struct ynl_family ynl_{f << 2553 if prototype: << 2554 cw.p(f'extern {symbol};') << 2555 return << 2556 << 2557 if family.ntfs: << 2558 cw.block_start(line=f"static const st << 2559 for ntf_op_name, ntf_op in family.ntf << 2560 if 'notify' in ntf_op: << 2561 op = family.ops[ntf_op['notif << 2562 ri = RenderInfo(cw, family, " << 2563 elif 'event' in ntf_op: << 2564 ri = RenderInfo(cw, family, " << 2565 else: << 2566 raise Exception('Invalid noti << 2567 _render_user_ntf_entry(ri, ntf_op << 2568 for op_name, op in family.ops.items() << 2569 if 'event' not in op: << 2570 continue << 2571 ri = RenderInfo(cw, family, "user << 2572 _render_user_ntf_entry(ri, op) << 2573 cw.block_end(line=";") << 2574 cw.nl() << 2575 << 2576 cw.block_start(f'{symbol} = ') << 2577 cw.p(f'.name\t\t= "{family.c_name}",') << 2578 if family.fixed_header: << 2579 cw.p(f'.hdr_len\t= sizeof(struct genl << 2580 else: << 2581 cw.p('.hdr_len\t= sizeof(struct genlm << 2582 if family.ntfs: << 2583 cw.p(f".ntf_info\t= {family['name']}_ << 2584 cw.p(f".ntf_info_size\t= YNL_ARRAY_SI << 2585 cw.block_end(line=';') << 2586 << 2587 << 2588 def family_contains_bitfield32(family): << 2589 for _, attr_set in family.attr_sets.items << 2590 if attr_set.subset_of: << 2591 continue << 2592 for _, attr in attr_set.items(): << 2593 if attr.type == "bitfield32": << 2594 return True << 2595 return False << 2596 << 2597 << 2598 def find_kernel_root(full_path): 2038 def find_kernel_root(full_path): 2599 sub_path = '' 2039 sub_path = '' 2600 while True: 2040 while True: 2601 sub_path = os.path.join(os.path.basen 2041 sub_path = os.path.join(os.path.basename(full_path), sub_path) 2602 full_path = os.path.dirname(full_path 2042 full_path = os.path.dirname(full_path) 2603 maintainers = os.path.join(full_path, 2043 maintainers = os.path.join(full_path, "MAINTAINERS") 2604 if os.path.exists(maintainers): 2044 if os.path.exists(maintainers): 2605 return full_path, sub_path[:-1] 2045 return full_path, sub_path[:-1] 2606 2046 2607 2047 2608 def main(): 2048 def main(): 2609 parser = argparse.ArgumentParser(descript 2049 parser = argparse.ArgumentParser(description='Netlink simple parsing generator') 2610 parser.add_argument('--mode', dest='mode' 2050 parser.add_argument('--mode', dest='mode', type=str, required=True) 2611 parser.add_argument('--spec', dest='spec' 2051 parser.add_argument('--spec', dest='spec', type=str, required=True) 2612 parser.add_argument('--header', dest='hea 2052 parser.add_argument('--header', dest='header', action='store_true', default=None) 2613 parser.add_argument('--source', dest='hea 2053 parser.add_argument('--source', dest='header', action='store_false') 2614 parser.add_argument('--user-header', narg 2054 parser.add_argument('--user-header', nargs='+', default=[]) 2615 parser.add_argument('--cmp-out', action=' !! 2055 parser.add_argument('-o', dest='out_file', type=str) 2616 help='Do not overwrit << 2617 parser.add_argument('--exclude-op', actio << 2618 parser.add_argument('-o', dest='out_file' << 2619 args = parser.parse_args() 2056 args = parser.parse_args() 2620 2057 >> 2058 out_file = open(args.out_file, 'w+') if args.out_file else os.sys.stdout >> 2059 2621 if args.header is None: 2060 if args.header is None: 2622 parser.error("--header or --source is 2061 parser.error("--header or --source is required") 2623 2062 2624 exclude_ops = [re.compile(expr) for expr << 2625 << 2626 try: 2063 try: 2627 parsed = Family(args.spec, exclude_op !! 2064 parsed = Family(args.spec) 2628 if parsed.license != '((GPL-2.0 WITH 2065 if parsed.license != '((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)': 2629 print('Spec license:', parsed.lic 2066 print('Spec license:', parsed.license) 2630 print('License must be: ((GPL-2.0 2067 print('License must be: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)') 2631 os.sys.exit(1) 2068 os.sys.exit(1) 2632 except yaml.YAMLError as exc: 2069 except yaml.YAMLError as exc: 2633 print(exc) 2070 print(exc) 2634 os.sys.exit(1) 2071 os.sys.exit(1) 2635 return 2072 return 2636 2073 2637 supported_models = ['unified'] !! 2074 cw = CodeWriter(BaseNlLib(), out_file) 2638 if args.mode in ['user', 'kernel']: << 2639 supported_models += ['directional'] << 2640 if parsed.msg_id_model not in supported_m << 2641 print(f'Message enum-model {parsed.ms << 2642 os.sys.exit(1) << 2643 << 2644 cw = CodeWriter(BaseNlLib(), args.out_fil << 2645 2075 2646 _, spec_kernel = find_kernel_root(args.sp 2076 _, spec_kernel = find_kernel_root(args.spec) 2647 if args.mode == 'uapi' or args.header: 2077 if args.mode == 'uapi' or args.header: 2648 cw.p(f'/* SPDX-License-Identifier: {p 2078 cw.p(f'/* SPDX-License-Identifier: {parsed.license} */') 2649 else: 2079 else: 2650 cw.p(f'// SPDX-License-Identifier: {p 2080 cw.p(f'// SPDX-License-Identifier: {parsed.license}') 2651 cw.p("/* Do not edit directly, auto-gener 2081 cw.p("/* Do not edit directly, auto-generated from: */") 2652 cw.p(f"/*\t{spec_kernel} */") 2082 cw.p(f"/*\t{spec_kernel} */") 2653 cw.p(f"/* YNL-GEN {args.mode} {'header' i 2083 cw.p(f"/* YNL-GEN {args.mode} {'header' if args.header else 'source'} */") 2654 if args.exclude_op or args.user_header: << 2655 line = '' << 2656 line += ' --user-header '.join([''] + << 2657 line += ' --exclude-op '.join([''] + << 2658 cw.p(f'/* YNL-ARG{line} */') << 2659 cw.nl() 2084 cw.nl() 2660 2085 2661 if args.mode == 'uapi': 2086 if args.mode == 'uapi': 2662 render_uapi(parsed, cw) 2087 render_uapi(parsed, cw) 2663 return 2088 return 2664 2089 2665 hdr_prot = f"_LINUX_{parsed.c_name.upper( !! 2090 hdr_prot = f"_LINUX_{parsed.name.upper()}_GEN_H" 2666 if args.header: 2091 if args.header: 2667 cw.p('#ifndef ' + hdr_prot) 2092 cw.p('#ifndef ' + hdr_prot) 2668 cw.p('#define ' + hdr_prot) 2093 cw.p('#define ' + hdr_prot) 2669 cw.nl() 2094 cw.nl() 2670 2095 2671 hdr_file=os.path.basename(args.out_file[: << 2672 << 2673 if args.mode == 'kernel': 2096 if args.mode == 'kernel': 2674 cw.p('#include <net/netlink.h>') 2097 cw.p('#include <net/netlink.h>') 2675 cw.p('#include <net/genetlink.h>') 2098 cw.p('#include <net/genetlink.h>') 2676 cw.nl() 2099 cw.nl() 2677 if not args.header: 2100 if not args.header: 2678 if args.out_file: 2101 if args.out_file: 2679 cw.p(f'#include "{hdr_file}"' !! 2102 cw.p(f'#include "{os.path.basename(args.out_file[:-2])}.h"') 2680 cw.nl() 2103 cw.nl() 2681 headers = ['uapi/' + parsed.uapi_head !! 2104 headers = [parsed.uapi_header] 2682 headers += parsed.kernel_family.get(' << 2683 else: << 2684 cw.p('#include <stdlib.h>') << 2685 cw.p('#include <string.h>') << 2686 if args.header: << 2687 cw.p('#include <linux/types.h>') << 2688 if family_contains_bitfield32(par << 2689 cw.p('#include <linux/netlink << 2690 else: << 2691 cw.p(f'#include "{hdr_file}"') << 2692 cw.p('#include "ynl.h"') << 2693 headers = [parsed.uapi_header] << 2694 for definition in parsed['definitions']: 2105 for definition in parsed['definitions']: 2695 if 'header' in definition: 2106 if 'header' in definition: 2696 headers.append(definition['header 2107 headers.append(definition['header']) 2697 for one in headers: 2108 for one in headers: 2698 cw.p(f"#include <{one}>") 2109 cw.p(f"#include <{one}>") 2699 cw.nl() 2110 cw.nl() 2700 2111 2701 if args.mode == "user": 2112 if args.mode == "user": 2702 if not args.header: 2113 if not args.header: >> 2114 cw.p("#include <stdlib.h>") >> 2115 cw.p("#include <stdio.h>") >> 2116 cw.p("#include <string.h>") >> 2117 cw.p("#include <libmnl/libmnl.h>") 2703 cw.p("#include <linux/genetlink.h 2118 cw.p("#include <linux/genetlink.h>") 2704 cw.nl() 2119 cw.nl() 2705 for one in args.user_header: 2120 for one in args.user_header: 2706 cw.p(f'#include "{one}"') 2121 cw.p(f'#include "{one}"') 2707 else: 2122 else: 2708 cw.p('struct ynl_sock;') 2123 cw.p('struct ynl_sock;') 2709 cw.nl() << 2710 render_user_family(parsed, cw, Tr << 2711 cw.nl() 2124 cw.nl() 2712 2125 2713 if args.mode == "kernel": 2126 if args.mode == "kernel": 2714 if args.header: 2127 if args.header: 2715 for _, struct in sorted(parsed.pu 2128 for _, struct in sorted(parsed.pure_nested_structs.items()): 2716 if struct.request: 2129 if struct.request: 2717 cw.p('/* Common nested ty 2130 cw.p('/* Common nested types */') 2718 break 2131 break 2719 for attr_set, struct in sorted(pa 2132 for attr_set, struct in sorted(parsed.pure_nested_structs.items()): 2720 if struct.request: 2133 if struct.request: 2721 print_req_policy_fwd(cw, 2134 print_req_policy_fwd(cw, struct) 2722 cw.nl() 2135 cw.nl() 2723 2136 2724 if parsed.kernel_policy == 'globa 2137 if parsed.kernel_policy == 'global': 2725 cw.p(f"/* Global operation po 2138 cw.p(f"/* Global operation policy for {parsed.name} */") 2726 2139 2727 struct = Struct(parsed, parse 2140 struct = Struct(parsed, parsed.global_policy_set, type_list=parsed.global_policy) 2728 print_req_policy_fwd(cw, stru 2141 print_req_policy_fwd(cw, struct) 2729 cw.nl() 2142 cw.nl() 2730 2143 2731 if parsed.kernel_policy in {'per- 2144 if parsed.kernel_policy in {'per-op', 'split'}: 2732 for op_name, op in parsed.ops 2145 for op_name, op in parsed.ops.items(): 2733 if 'do' in op and 'event' 2146 if 'do' in op and 'event' not in op: 2734 ri = RenderInfo(cw, p !! 2147 ri = RenderInfo(cw, parsed, args.mode, op, op_name, "do") 2735 print_req_policy_fwd( 2148 print_req_policy_fwd(cw, ri.struct['request'], ri=ri) 2736 cw.nl() 2149 cw.nl() 2737 2150 2738 print_kernel_op_table_hdr(parsed, 2151 print_kernel_op_table_hdr(parsed, cw) 2739 print_kernel_mcgrp_hdr(parsed, cw 2152 print_kernel_mcgrp_hdr(parsed, cw) 2740 print_kernel_family_struct_hdr(pa 2153 print_kernel_family_struct_hdr(parsed, cw) 2741 else: 2154 else: 2742 print_kernel_policy_ranges(parsed << 2743 << 2744 for _, struct in sorted(parsed.pu 2155 for _, struct in sorted(parsed.pure_nested_structs.items()): 2745 if struct.request: 2156 if struct.request: 2746 cw.p('/* Common nested ty 2157 cw.p('/* Common nested types */') 2747 break 2158 break 2748 for attr_set, struct in sorted(pa 2159 for attr_set, struct in sorted(parsed.pure_nested_structs.items()): 2749 if struct.request: 2160 if struct.request: 2750 print_req_policy(cw, stru 2161 print_req_policy(cw, struct) 2751 cw.nl() 2162 cw.nl() 2752 2163 2753 if parsed.kernel_policy == 'globa 2164 if parsed.kernel_policy == 'global': 2754 cw.p(f"/* Global operation po 2165 cw.p(f"/* Global operation policy for {parsed.name} */") 2755 2166 2756 struct = Struct(parsed, parse 2167 struct = Struct(parsed, parsed.global_policy_set, type_list=parsed.global_policy) 2757 print_req_policy(cw, struct) 2168 print_req_policy(cw, struct) 2758 cw.nl() 2169 cw.nl() 2759 2170 2760 for op_name, op in parsed.ops.ite 2171 for op_name, op in parsed.ops.items(): 2761 if parsed.kernel_policy in {' 2172 if parsed.kernel_policy in {'per-op', 'split'}: 2762 for op_mode in ['do', 'du 2173 for op_mode in ['do', 'dump']: 2763 if op_mode in op and 2174 if op_mode in op and 'request' in op[op_mode]: 2764 cw.p(f"/* {op.enu 2175 cw.p(f"/* {op.enum_name} - {op_mode} */") 2765 ri = RenderInfo(c !! 2176 ri = RenderInfo(cw, parsed, args.mode, op, op_name, op_mode) 2766 print_req_policy( 2177 print_req_policy(cw, ri.struct['request'], ri=ri) 2767 cw.nl() 2178 cw.nl() 2768 2179 2769 print_kernel_op_table(parsed, cw) 2180 print_kernel_op_table(parsed, cw) 2770 print_kernel_mcgrp_src(parsed, cw 2181 print_kernel_mcgrp_src(parsed, cw) 2771 print_kernel_family_struct_src(pa 2182 print_kernel_family_struct_src(parsed, cw) 2772 2183 2773 if args.mode == "user": 2184 if args.mode == "user": >> 2185 has_ntf = False 2774 if args.header: 2186 if args.header: 2775 cw.p('/* Enums */') << 2776 put_op_name_fwd(parsed, cw) << 2777 << 2778 for name, const in parsed.consts. << 2779 if isinstance(const, EnumSet) << 2780 put_enum_to_str_fwd(parse << 2781 cw.nl() << 2782 << 2783 cw.p('/* Common nested types */') 2187 cw.p('/* Common nested types */') 2784 for attr_set, struct in parsed.pu !! 2188 for attr_set, struct in sorted(parsed.pure_nested_structs.items()): 2785 ri = RenderInfo(cw, parsed, a !! 2189 ri = RenderInfo(cw, parsed, args.mode, "", "", "", attr_set) 2786 print_type_full(ri, struct) 2190 print_type_full(ri, struct) 2787 2191 2788 for op_name, op in parsed.ops.ite 2192 for op_name, op in parsed.ops.items(): 2789 cw.p(f"/* ============== {op. 2193 cw.p(f"/* ============== {op.enum_name} ============== */") 2790 2194 2791 if 'do' in op and 'event' not 2195 if 'do' in op and 'event' not in op: 2792 cw.p(f"/* {op.enum_name} 2196 cw.p(f"/* {op.enum_name} - do */") 2793 ri = RenderInfo(cw, parse !! 2197 ri = RenderInfo(cw, parsed, args.mode, op, op_name, "do") 2794 print_req_type(ri) 2198 print_req_type(ri) 2795 print_req_type_helpers(ri 2199 print_req_type_helpers(ri) 2796 cw.nl() 2200 cw.nl() 2797 print_rsp_type(ri) 2201 print_rsp_type(ri) 2798 print_rsp_type_helpers(ri 2202 print_rsp_type_helpers(ri) 2799 cw.nl() 2203 cw.nl() 2800 print_req_prototype(ri) 2204 print_req_prototype(ri) 2801 cw.nl() 2205 cw.nl() 2802 2206 2803 if 'dump' in op: 2207 if 'dump' in op: 2804 cw.p(f"/* {op.enum_name} 2208 cw.p(f"/* {op.enum_name} - dump */") 2805 ri = RenderInfo(cw, parse !! 2209 ri = RenderInfo(cw, parsed, args.mode, op, op_name, 'dump') 2806 print_req_type(ri) !! 2210 if 'request' in op['dump']: 2807 print_req_type_helpers(ri !! 2211 print_req_type(ri) >> 2212 print_req_type_helpers(ri) 2808 if not ri.type_consistent 2213 if not ri.type_consistent: 2809 print_rsp_type(ri) 2214 print_rsp_type(ri) 2810 print_wrapped_type(ri) 2215 print_wrapped_type(ri) 2811 print_dump_prototype(ri) 2216 print_dump_prototype(ri) 2812 cw.nl() 2217 cw.nl() 2813 2218 2814 if op.has_ntf: !! 2219 if 'notify' in op: 2815 cw.p(f"/* {op.enum_name} 2220 cw.p(f"/* {op.enum_name} - notify */") 2816 ri = RenderInfo(cw, parse !! 2221 ri = RenderInfo(cw, parsed, args.mode, op, op_name, 'notify') >> 2222 has_ntf = True 2817 if not ri.type_consistent 2223 if not ri.type_consistent: 2818 raise Exception(f'Onl !! 2224 raise Exception('Only notifications with consistent types supported') 2819 print_wrapped_type(ri) 2225 print_wrapped_type(ri) 2820 2226 2821 for op_name, op in parsed.ntfs.it << 2822 if 'event' in op: 2227 if 'event' in op: 2823 ri = RenderInfo(cw, parse !! 2228 ri = RenderInfo(cw, parsed, args.mode, op, op_name, 'event') 2824 cw.p(f"/* {op.enum_name} 2229 cw.p(f"/* {op.enum_name} - event */") 2825 print_rsp_type(ri) 2230 print_rsp_type(ri) 2826 cw.nl() 2231 cw.nl() 2827 print_wrapped_type(ri) 2232 print_wrapped_type(ri) 2828 cw.nl() << 2829 else: << 2830 cw.p('/* Enums */') << 2831 put_op_name(parsed, cw) << 2832 2233 2833 for name, const in parsed.consts. !! 2234 if has_ntf: 2834 if isinstance(const, EnumSet) !! 2235 cw.p('/* --------------- Common notification parsing --------------- */') 2835 put_enum_to_str(parsed, c !! 2236 print_ntf_parse_prototype(parsed, cw) 2836 cw.nl() 2237 cw.nl() 2837 !! 2238 else: 2838 has_recursive_nests = False << 2839 cw.p('/* Policies */') 2239 cw.p('/* Policies */') 2840 for struct in parsed.pure_nested_ !! 2240 for name, _ in parsed.attr_sets.items(): 2841 if struct.recursive: << 2842 put_typol_fwd(cw, struct) << 2843 has_recursive_nests = Tru << 2844 if has_recursive_nests: << 2845 cw.nl() << 2846 for name in parsed.pure_nested_st << 2847 struct = Struct(parsed, name) 2241 struct = Struct(parsed, name) 2848 put_typol(cw, struct) !! 2242 put_typol_fwd(cw, struct) 2849 for name in parsed.root_sets: !! 2243 cw.nl() >> 2244 >> 2245 for name, _ in parsed.attr_sets.items(): 2850 struct = Struct(parsed, name) 2246 struct = Struct(parsed, name) 2851 put_typol(cw, struct) 2247 put_typol(cw, struct) 2852 2248 2853 cw.p('/* Common nested types */') 2249 cw.p('/* Common nested types */') 2854 if has_recursive_nests: !! 2250 for attr_set, struct in sorted(parsed.pure_nested_structs.items()): 2855 for attr_set, struct in parse !! 2251 ri = RenderInfo(cw, parsed, args.mode, "", "", "", attr_set) 2856 ri = RenderInfo(cw, parse << 2857 free_rsp_nested_prototype << 2858 if struct.request: << 2859 put_req_nested_protot << 2860 if struct.reply: << 2861 parse_rsp_nested_prot << 2862 cw.nl() << 2863 for attr_set, struct in parsed.pu << 2864 ri = RenderInfo(cw, parsed, a << 2865 2252 2866 free_rsp_nested(ri, struct) 2253 free_rsp_nested(ri, struct) 2867 if struct.request: 2254 if struct.request: 2868 put_req_nested(ri, struct 2255 put_req_nested(ri, struct) 2869 if struct.reply: 2256 if struct.reply: 2870 parse_rsp_nested(ri, stru 2257 parse_rsp_nested(ri, struct) 2871 2258 2872 for op_name, op in parsed.ops.ite 2259 for op_name, op in parsed.ops.items(): 2873 cw.p(f"/* ============== {op. 2260 cw.p(f"/* ============== {op.enum_name} ============== */") 2874 if 'do' in op and 'event' not 2261 if 'do' in op and 'event' not in op: 2875 cw.p(f"/* {op.enum_name} 2262 cw.p(f"/* {op.enum_name} - do */") 2876 ri = RenderInfo(cw, parse !! 2263 ri = RenderInfo(cw, parsed, args.mode, op, op_name, "do") 2877 print_req_free(ri) << 2878 print_rsp_free(ri) 2264 print_rsp_free(ri) 2879 parse_rsp_msg(ri) 2265 parse_rsp_msg(ri) 2880 print_req(ri) 2266 print_req(ri) 2881 cw.nl() 2267 cw.nl() 2882 2268 2883 if 'dump' in op: 2269 if 'dump' in op: 2884 cw.p(f"/* {op.enum_name} 2270 cw.p(f"/* {op.enum_name} - dump */") 2885 ri = RenderInfo(cw, parse !! 2271 ri = RenderInfo(cw, parsed, args.mode, op, op_name, "dump") 2886 if not ri.type_consistent 2272 if not ri.type_consistent: 2887 parse_rsp_msg(ri, der 2273 parse_rsp_msg(ri, deref=True) 2888 print_req_free(ri) << 2889 print_dump_type_free(ri) 2274 print_dump_type_free(ri) 2890 print_dump(ri) 2275 print_dump(ri) 2891 cw.nl() 2276 cw.nl() 2892 2277 2893 if op.has_ntf: !! 2278 if 'notify' in op: 2894 cw.p(f"/* {op.enum_name} 2279 cw.p(f"/* {op.enum_name} - notify */") 2895 ri = RenderInfo(cw, parse !! 2280 ri = RenderInfo(cw, parsed, args.mode, op, op_name, 'notify') >> 2281 has_ntf = True 2896 if not ri.type_consistent 2282 if not ri.type_consistent: 2897 raise Exception(f'Onl !! 2283 raise Exception('Only notifications with consistent types supported') 2898 print_ntf_type_free(ri) 2284 print_ntf_type_free(ri) 2899 2285 2900 for op_name, op in parsed.ntfs.it << 2901 if 'event' in op: 2286 if 'event' in op: 2902 cw.p(f"/* {op.enum_name} 2287 cw.p(f"/* {op.enum_name} - event */") >> 2288 has_ntf = True 2903 2289 2904 ri = RenderInfo(cw, parse !! 2290 ri = RenderInfo(cw, parsed, args.mode, op, op_name, "do") 2905 parse_rsp_msg(ri) 2291 parse_rsp_msg(ri) 2906 2292 2907 ri = RenderInfo(cw, parse !! 2293 ri = RenderInfo(cw, parsed, args.mode, op, op_name, "event") 2908 print_ntf_type_free(ri) 2294 print_ntf_type_free(ri) 2909 cw.nl() !! 2295 2910 render_user_family(parsed, cw, Fa !! 2296 if has_ntf: >> 2297 cw.p('/* --------------- Common notification parsing --------------- */') >> 2298 print_ntf_type_parse(parsed, cw, args.mode) 2911 2299 2912 if args.header: 2300 if args.header: 2913 cw.p(f'#endif /* {hdr_prot} */') 2301 cw.p(f'#endif /* {hdr_prot} */') 2914 2302 2915 2303 2916 if __name__ == "__main__": 2304 if __name__ == "__main__": 2917 main() 2305 main()
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.