Home | History | Annotate | Line # | Download | only in gdb
producer.c revision 1.1.1.2
      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 
     26 int
     27 producer_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 
     42 int
     43 producer_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 
     78 bool
     79 producer_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 
    130 bool
    131 producer_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
    138 namespace selftests {
    139 namespace producer {
    140 
    141 static void
    142 producer_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[] = "\
    156 Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on \
    157 Intel(R) 64, \
    158 Version 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[] = "\
    168 Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on \
    169 Intel(R) 64, \
    170 Version 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[] = "\
    180 Intel(R) C++ Intel(R) 64 Compiler XE for applications running on \
    181 Intel(R) 64, \
    182 Version 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[] = "\
    191 Intel(R) C++ Intel(R) 64 Compiler for applications running on \
    192 Intel(R) 64, \
    193 Version 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 
    236 void _initialize_producer ();
    237 void
    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