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