glibcconform.py 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #!/usr/bin/python
  2. # Shared code for glibc conformance tests.
  3. # Copyright (C) 2018-2019 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. # <http://www.gnu.org/licenses/>.
  19. import os.path
  20. import re
  21. import subprocess
  22. import tempfile
  23. # Compiler options for each standard.
  24. CFLAGS = {'ISO': '-ansi',
  25. 'ISO99': '-std=c99',
  26. 'ISO11': '-std=c11',
  27. 'POSIX': '-D_POSIX_C_SOURCE=199506L -ansi',
  28. 'XPG4': '-ansi -D_XOPEN_SOURCE',
  29. 'XPG42': '-ansi -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED',
  30. 'UNIX98': '-ansi -D_XOPEN_SOURCE=500',
  31. 'XOPEN2K': '-std=c99 -D_XOPEN_SOURCE=600',
  32. 'XOPEN2K8': '-std=c99 -D_XOPEN_SOURCE=700',
  33. 'POSIX2008': '-std=c99 -D_POSIX_C_SOURCE=200809L'}
  34. # ISO C90 keywords.
  35. KEYWORDS_C90 = {'auto', 'break', 'case', 'char', 'const', 'continue',
  36. 'default', 'do', 'double', 'else', 'enum', 'extern', 'float',
  37. 'for', 'goto', 'if', 'int', 'long', 'register', 'return',
  38. 'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
  39. 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'}
  40. # ISO C99 keywords.
  41. KEYWORDS_C99 = KEYWORDS_C90 | {'inline', 'restrict'}
  42. # Keywords for each standard.
  43. KEYWORDS = {'ISO': KEYWORDS_C90,
  44. 'ISO99': KEYWORDS_C99,
  45. 'ISO11': KEYWORDS_C99,
  46. 'POSIX': KEYWORDS_C90,
  47. 'XPG4': KEYWORDS_C90,
  48. 'XPG42': KEYWORDS_C90,
  49. 'UNIX98': KEYWORDS_C90,
  50. 'XOPEN2K': KEYWORDS_C99,
  51. 'XOPEN2K8': KEYWORDS_C99,
  52. 'POSIX2008': KEYWORDS_C99}
  53. def list_exported_functions(cc, standard, header):
  54. """Return the set of functions exported by a header, empty if an
  55. include of the header does not compile.
  56. """
  57. cc_all = '%s -D_ISOMAC %s' % (cc, CFLAGS[standard])
  58. with tempfile.TemporaryDirectory() as temp_dir:
  59. c_file_name = os.path.join(temp_dir, 'test.c')
  60. aux_file_name = os.path.join(temp_dir, 'test.c.aux')
  61. with open(c_file_name, 'w') as c_file:
  62. c_file.write('#include <%s>\n' % header)
  63. fns = set()
  64. cmd = ('%s -c %s -o /dev/null -aux-info %s'
  65. % (cc_all, c_file_name, aux_file_name))
  66. try:
  67. subprocess.check_call(cmd, shell=True)
  68. except subprocess.CalledProcessError:
  69. return fns
  70. with open(aux_file_name, 'r') as aux_file:
  71. for line in aux_file:
  72. line = re.sub(r'/\*.*?\*/', '', line)
  73. line = line.strip()
  74. if line:
  75. # The word before a '(' that isn't '(*' is the
  76. # function name before the argument list (not
  77. # fully general, but sufficient for -aux-info
  78. # output on standard headers).
  79. m = re.search(r'([A-Za-z0-9_]+) *\([^*]', line)
  80. if m:
  81. fns.add(m.group(1))
  82. else:
  83. raise ValueError("couldn't parse -aux-info output: %s"
  84. % line)
  85. return fns