(root)/
glibc-2.38/
scripts/
gen-as-const.py
       1  #!/usr/bin/python3
       2  # Produce headers of assembly constants from C expressions.
       3  # Copyright (C) 2018-2023 Free Software Foundation, Inc.
       4  # This file is part of the GNU C Library.
       5  #
       6  # The GNU C Library is free software; you can redistribute it and/or
       7  # modify it under the terms of the GNU Lesser General Public
       8  # License as published by the Free Software Foundation; either
       9  # version 2.1 of the License, or (at your option) any later version.
      10  #
      11  # The GNU C Library is distributed in the hope that it will be useful,
      12  # but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14  # Lesser General Public License for more details.
      15  #
      16  # You should have received a copy of the GNU Lesser General Public
      17  # License along with the GNU C Library; if not, see
      18  # <https://www.gnu.org/licenses/>.
      19  
      20  # The input to this script looks like:
      21  #       #cpp-directive ...
      22  #       NAME1
      23  #       NAME2 expression ...
      24  # A line giving just a name implies an expression consisting of just that name.
      25  
      26  import argparse
      27  
      28  import glibcextract
      29  
      30  
      31  def gen_test(sym_data):
      32      """Generate a test for the values of some C constants.
      33  
      34      The first argument is as for glibcextract.compute_c_consts.
      35  
      36      """
      37      out_lines = []
      38      for arg in sym_data:
      39          if isinstance(arg, str):
      40              if arg == 'START':
      41                  out_lines.append('#include <stdint.h>\n'
      42                                   '#include <stdio.h>\n'
      43                                   '#include <bits/wordsize.h>\n'
      44                                   '#if __WORDSIZE == 64\n'
      45                                   'typedef uint64_t c_t;\n'
      46                                   '# define U(n) UINT64_C (n)\n'
      47                                   '#else\n'
      48                                   'typedef uint32_t c_t;\n'
      49                                   '# define U(n) UINT32_C (n)\n'
      50                                   '#endif\n'
      51                                   'static int\n'
      52                                   'do_test (void)\n'
      53                                   '{\n'
      54                                   # Compilation test only, using static
      55                                   # assertions.
      56                                   '  return 0;\n'
      57                                   '}\n'
      58                                   '#include <support/test-driver.c>')
      59              else:
      60                  out_lines.append(arg)
      61              continue
      62          name = arg[0]
      63          value = arg[1]
      64          out_lines.append('_Static_assert (U (asconst_%s) == (c_t) (%s), '
      65                           '"value of %s");'
      66                           % (name, value, name))
      67      return '\n'.join(out_lines)
      68  
      69  
      70  def main():
      71      """The main entry point."""
      72      parser = argparse.ArgumentParser(
      73          description='Produce headers of assembly constants.')
      74      parser.add_argument('--cc', metavar='CC',
      75                          help='C compiler (including options) to use')
      76      parser.add_argument('--test', action='store_true',
      77                          help='Generate test case instead of header')
      78      parser.add_argument('--python', action='store_true',
      79                          help='Generate Python file instead of header')
      80      parser.add_argument('sym_file',
      81                          help='.sym file to process')
      82      args = parser.parse_args()
      83      sym_data = []
      84      with open(args.sym_file, 'r') as sym_file:
      85          started = False
      86          for line in sym_file:
      87              line = line.strip()
      88              if line == '':
      89                  continue
      90              # Pass preprocessor directives through.
      91              if line.startswith('#'):
      92                  sym_data.append(line)
      93                  continue
      94              words = line.split(maxsplit=1)
      95              if not started:
      96                  sym_data.append('START')
      97                  started = True
      98              # Separator.
      99              if words[0] == '--':
     100                  continue
     101              name = words[0]
     102              value = words[1] if len(words) > 1 else words[0]
     103              sym_data.append((name, value))
     104          if not started:
     105              sym_data.append('START')
     106      if args.test:
     107          print(gen_test(sym_data))
     108      elif args.python:
     109          consts = glibcextract.compute_c_consts(sym_data, args.cc)
     110          print('# GENERATED FILE\n'
     111                '\n'
     112                '# Constant definitions.\n'
     113                '# See gen-as-const.py for details.\n')
     114          print(''.join('%s = %s\n' % c for c in sorted(consts.items())), end='')
     115      else:
     116          consts = glibcextract.compute_c_consts(sym_data, args.cc)
     117          print(''.join('#define %s %s\n' % c for c in sorted(consts.items())), end='')
     118  
     119  if __name__ == '__main__':
     120      main()