1import os.path 2 3from c_parser import ( 4 info as _info, 5 match as _match, 6) 7 8 9_KIND = _info.KIND 10 11 12# XXX Use known.tsv for these? 13SYSTEM_TYPES = { 14 'int8_t', 15 'uint8_t', 16 'int16_t', 17 'uint16_t', 18 'int32_t', 19 'uint32_t', 20 'int64_t', 21 'uint64_t', 22 'size_t', 23 'ssize_t', 24 'intptr_t', 25 'uintptr_t', 26 'wchar_t', 27 '', 28 # OS-specific 29 'pthread_cond_t', 30 'pthread_mutex_t', 31 'pthread_key_t', 32 'atomic_int', 33 'atomic_uintptr_t', 34 '', 35 # lib-specific 36 'WINDOW', # curses 37 'XML_LChar', 38 'XML_Size', 39 'XML_Parser', 40 'enum XML_Error', 41 'enum XML_Status', 42 '', 43} 44 45 46def is_system_type(typespec): 47 return typespec in SYSTEM_TYPES 48 49 50################################## 51# decl matchers 52 53def is_public(decl): 54 if not decl.filename.endswith('.h'): 55 return False 56 if 'Include' not in decl.filename.split(os.path.sep): 57 return False 58 return True 59 60 61def is_process_global(vardecl): 62 kind, storage, _, _, _ = _info.get_parsed_vartype(vardecl) 63 if kind is not _KIND.VARIABLE: 64 raise NotImplementedError(vardecl) 65 if 'static' in (storage or ''): 66 return True 67 68 if hasattr(vardecl, 'parent'): 69 parent = vardecl.parent 70 else: 71 parent = vardecl.get('parent') 72 return not parent 73 74 75def is_fixed_type(vardecl): 76 if not vardecl: 77 return None 78 _, _, _, typespec, abstract = _info.get_parsed_vartype(vardecl) 79 if 'typeof' in typespec: 80 raise NotImplementedError(vardecl) 81 elif not abstract: 82 return True 83 84 if '*' not in abstract: 85 # XXX What about []? 86 return True 87 elif _match._is_funcptr(abstract): 88 return True 89 else: 90 for after in abstract.split('*')[1:]: 91 if not after.lstrip().startswith('const'): 92 return False 93 else: 94 return True 95 96 97def is_immutable(vardecl): 98 if not vardecl: 99 return None 100 if not is_fixed_type(vardecl): 101 return False 102 _, _, typequal, _, _ = _info.get_parsed_vartype(vardecl) 103 # If there, it can only be "const" or "volatile". 104 return typequal == 'const' 105 106 107def is_public_api(decl): 108 if not is_public(decl): 109 return False 110 if decl.kind is _KIND.TYPEDEF: 111 return True 112 elif _match.is_type_decl(decl): 113 return not _match.is_forward_decl(decl) 114 else: 115 return _match.is_external_reference(decl) 116 117 118def is_public_declaration(decl): 119 if not is_public(decl): 120 return False 121 if decl.kind is _KIND.TYPEDEF: 122 return True 123 elif _match.is_type_decl(decl): 124 return _match.is_forward_decl(decl) 125 else: 126 return _match.is_external_reference(decl) 127 128 129def is_public_definition(decl): 130 if not is_public(decl): 131 return False 132 if decl.kind is _KIND.TYPEDEF: 133 return True 134 elif _match.is_type_decl(decl): 135 return not _match.is_forward_decl(decl) 136 else: 137 return not _match.is_external_reference(decl) 138 139 140def is_public_impl(decl): 141 if not _KIND.is_decl(decl.kind): 142 return False 143 # See filter_forward() about "is_public". 144 return getattr(decl, 'is_public', False) 145 146 147def is_module_global_decl(decl): 148 if is_public_impl(decl): 149 return False 150 if _match.is_forward_decl(decl): 151 return False 152 return not _match.is_local_var(decl) 153 154 155################################## 156# filtering with matchers 157 158def filter_forward(items, *, markpublic=False): 159 if markpublic: 160 public = set() 161 actual = [] 162 for item in items: 163 if is_public_api(item): 164 public.add(item.id) 165 elif not _match.is_forward_decl(item): 166 actual.append(item) 167 else: 168 # non-public duplicate! 169 # XXX 170 raise Exception(item) 171 for item in actual: 172 _info.set_flag(item, 'is_public', item.id in public) 173 yield item 174 else: 175 for item in items: 176 if _match.is_forward_decl(item): 177 continue 178 yield item 179 180 181################################## 182# grouping with matchers 183 184def group_by_storage(decls, **kwargs): 185 def is_module_global(decl): 186 if not is_module_global_decl(decl): 187 return False 188 if decl.kind == _KIND.VARIABLE: 189 if _info.get_effective_storage(decl) == 'static': 190 # This is covered by is_static_module_global(). 191 return False 192 return True 193 def is_static_module_global(decl): 194 if not _match.is_global_var(decl): 195 return False 196 return _info.get_effective_storage(decl) == 'static' 197 def is_static_local(decl): 198 if not _match.is_local_var(decl): 199 return False 200 return _info.get_effective_storage(decl) == 'static' 201 #def is_local(decl): 202 # if not _match.is_local_var(decl): 203 # return False 204 # return _info.get_effective_storage(decl) != 'static' 205 categories = { 206 #'extern': is_extern, 207 'published': is_public_impl, 208 'module-global': is_module_global, 209 'static-module-global': is_static_module_global, 210 'static-local': is_static_local, 211 } 212 return _match.group_by_category(decls, categories, **kwargs) 213