(root)/
Python-3.12.0/
Tools/
c-analyzer/
c_analyzer/
match.py
       1  import os.path
       2  
       3  from 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?
      13  SYSTEM_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  
      46  def is_system_type(typespec):
      47      return typespec in SYSTEM_TYPES
      48  
      49  
      50  ##################################
      51  # decl matchers
      52  
      53  def 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  
      61  def 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  
      75  def 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  
      97  def 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  
     107  def 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  
     118  def 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  
     129  def 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  
     140  def 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  
     147  def 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  
     158  def 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  
     184  def 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)