producer.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /* Producer string parsers for GDB.
  2. Copyright (C) 2012-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #include "defs.h"
  15. #include "producer.h"
  16. #include "gdbsupport/selftest.h"
  17. #include "gdbsupport/gdb_regex.h"
  18. /* See producer.h. */
  19. int
  20. producer_is_gcc_ge_4 (const char *producer)
  21. {
  22. int major, minor;
  23. if (! producer_is_gcc (producer, &major, &minor))
  24. return -1;
  25. if (major < 4)
  26. return -1;
  27. if (major > 4)
  28. return INT_MAX;
  29. return minor;
  30. }
  31. /* See producer.h. */
  32. int
  33. producer_is_gcc (const char *producer, int *major, int *minor)
  34. {
  35. const char *cs;
  36. if (producer != NULL && startswith (producer, "GNU "))
  37. {
  38. int maj, min;
  39. if (major == NULL)
  40. major = &maj;
  41. if (minor == NULL)
  42. minor = &min;
  43. /* Skip any identifier after "GNU " - such as "C11" "C++" or "Java".
  44. A full producer string might look like:
  45. "GNU C 4.7.2"
  46. "GNU Fortran 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic ..."
  47. "GNU C++14 5.0.0 20150123 (experimental)"
  48. */
  49. cs = &producer[strlen ("GNU ")];
  50. while (*cs && !isspace (*cs))
  51. cs++;
  52. if (*cs && isspace (*cs))
  53. cs++;
  54. if (sscanf (cs, "%d.%d", major, minor) == 2)
  55. return 1;
  56. }
  57. /* Not recognized as GCC. */
  58. return 0;
  59. }
  60. /* See producer.h. */
  61. bool
  62. producer_is_icc_ge_19 (const char *producer)
  63. {
  64. int major, minor;
  65. if (! producer_is_icc (producer, &major, &minor))
  66. return false;
  67. return major >= 19;
  68. }
  69. /* See producer.h. */
  70. bool
  71. producer_is_icc (const char *producer, int *major, int *minor)
  72. {
  73. compiled_regex i_re ("Intel(R)", 0, "producer_is_icc");
  74. if (producer == nullptr || i_re.exec (producer, 0, nullptr, 0) != 0)
  75. return false;
  76. /* Prepare the used fields. */
  77. int maj, min;
  78. if (major == nullptr)
  79. major = &maj;
  80. if (minor == nullptr)
  81. minor = &min;
  82. *minor = 0;
  83. *major = 0;
  84. compiled_regex re ("[0-9]+\\.[0-9]+", REG_EXTENDED, "producer_is_icc");
  85. regmatch_t version[1];
  86. if (re.exec (producer, ARRAY_SIZE (version), version, 0) == 0
  87. && version[0].rm_so != -1)
  88. {
  89. const char *version_str = producer + version[0].rm_so;
  90. sscanf (version_str, "%d.%d", major, minor);
  91. return true;
  92. }
  93. return false;
  94. }
  95. /* See producer.h. */
  96. bool
  97. producer_is_llvm (const char *producer)
  98. {
  99. return ((producer != NULL) && (startswith (producer, "clang ")
  100. || startswith (producer, " F90 Flang ")));
  101. }
  102. #if defined GDB_SELF_TEST
  103. namespace selftests {
  104. namespace producer {
  105. static void
  106. producer_parsing_tests ()
  107. {
  108. {
  109. /* Check that we don't crash if "Version" is not found in what
  110. looks like an ICC producer string. */
  111. static const char icc_no_version[] = "Intel(R) foo bar";
  112. int major = 0, minor = 0;
  113. SELF_CHECK (!producer_is_icc (icc_no_version, &major, &minor));
  114. SELF_CHECK (!producer_is_gcc (icc_no_version, &major, &minor));
  115. }
  116. {
  117. static const char extern_f_14_0[] = "\
  118. Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on \
  119. Intel(R) 64, \
  120. Version 14.0.1.074 Build 20130716";
  121. int major = 0, minor = 0;
  122. SELF_CHECK (producer_is_icc (extern_f_14_0, &major, &minor)
  123. && major == 14 && minor == 0);
  124. SELF_CHECK (!producer_is_gcc (extern_f_14_0, &major, &minor));
  125. }
  126. {
  127. static const char intern_f_14[] = "\
  128. Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on \
  129. Intel(R) 64, \
  130. Version 14.0";
  131. int major = 0, minor = 0;
  132. SELF_CHECK (producer_is_icc (intern_f_14, &major, &minor)
  133. && major == 14 && minor == 0);
  134. SELF_CHECK (!producer_is_gcc (intern_f_14, &major, &minor));
  135. }
  136. {
  137. static const char intern_c_14[] = "\
  138. Intel(R) C++ Intel(R) 64 Compiler XE for applications running on \
  139. Intel(R) 64, \
  140. Version 14.0";
  141. int major = 0, minor = 0;
  142. SELF_CHECK (producer_is_icc (intern_c_14, &major, &minor)
  143. && major == 14 && minor == 0);
  144. SELF_CHECK (!producer_is_gcc (intern_c_14, &major, &minor));
  145. }
  146. {
  147. static const char intern_c_18[] = "\
  148. Intel(R) C++ Intel(R) 64 Compiler for applications running on \
  149. Intel(R) 64, \
  150. Version 18.0 Beta";
  151. int major = 0, minor = 0;
  152. SELF_CHECK (producer_is_icc (intern_c_18, &major, &minor)
  153. && major == 18 && minor == 0);
  154. }
  155. {
  156. static const char gnu[] = "GNU C 4.7.2";
  157. SELF_CHECK (!producer_is_icc (gnu, NULL, NULL));
  158. int major = 0, minor = 0;
  159. SELF_CHECK (producer_is_gcc (gnu, &major, &minor)
  160. && major == 4 && minor == 7);
  161. }
  162. {
  163. static const char gnu_exp[] = "GNU C++14 5.0.0 20150123 (experimental)";
  164. int major = 0, minor = 0;
  165. SELF_CHECK (!producer_is_icc (gnu_exp, NULL, NULL));
  166. SELF_CHECK (producer_is_gcc (gnu_exp, &major, &minor)
  167. && major == 5 && minor == 0);
  168. }
  169. {
  170. static const char clang_llvm_exp[] = "clang version 12.0.0 (CLANG: bld#8)";
  171. int major = 0, minor = 0;
  172. SELF_CHECK (!producer_is_icc (clang_llvm_exp, NULL, NULL));
  173. SELF_CHECK (!producer_is_gcc (clang_llvm_exp, &major, &minor));
  174. SELF_CHECK (producer_is_llvm (clang_llvm_exp));
  175. }
  176. {
  177. static const char flang_llvm_exp[] = " F90 Flang - 1.5 2017-05-01";
  178. int major = 0, minor = 0;
  179. SELF_CHECK (!producer_is_icc (flang_llvm_exp, NULL, NULL));
  180. SELF_CHECK (!producer_is_gcc (flang_llvm_exp, &major, &minor));
  181. SELF_CHECK (producer_is_llvm (flang_llvm_exp));
  182. }
  183. }
  184. }
  185. }
  186. #endif
  187. void _initialize_producer ();
  188. void
  189. _initialize_producer ()
  190. {
  191. #if defined GDB_SELF_TEST
  192. selftests::register_test
  193. ("producer-parser", selftests::producer::producer_parsing_tests);
  194. #endif
  195. }