change section name in gdb/NEWS for changes in GDB 8.3
[external/binutils.git] / gdb / producer.c
1 /* Producer string parsers for GDB.
2
3    Copyright (C) 2012-2019 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 "common/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 #if defined GDB_SELF_TEST
129 namespace selftests {
130 namespace producer {
131
132 static void
133 producer_parsing_tests ()
134 {
135   {
136     /* Check that we don't crash if "Version" is not found in what
137        looks like an ICC producer string.  */
138     static const char icc_no_version[] = "Intel(R) foo bar";
139
140     int major = 0, minor = 0;
141     SELF_CHECK (!producer_is_icc (icc_no_version, &major, &minor));
142     SELF_CHECK (!producer_is_gcc (icc_no_version, &major, &minor));
143   }
144
145   {
146     static const char extern_f_14_1[] = "\
147 Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on \
148 Intel(R) 64, \
149 Version 14.0.1.074 Build 20130716";
150
151     int major = 0, minor = 0;
152     SELF_CHECK (producer_is_icc (extern_f_14_1, &major, &minor)
153                 && major == 14 && minor == 1);
154     SELF_CHECK (!producer_is_gcc (extern_f_14_1, &major, &minor));
155   }
156
157   {
158     static const char intern_f_14[] = "\
159 Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on \
160 Intel(R) 64, \
161 Version 14.0";
162
163     int major = 0, minor = 0;
164     SELF_CHECK (producer_is_icc (intern_f_14, &major, &minor)
165                 && major == 14 && minor == 0);
166     SELF_CHECK (!producer_is_gcc (intern_f_14, &major, &minor));
167   }
168
169   {
170     static const char intern_c_14[] = "\
171 Intel(R) C++ Intel(R) 64 Compiler XE for applications running on \
172 Intel(R) 64, \
173 Version 14.0";
174     int major = 0, minor = 0;
175     SELF_CHECK (producer_is_icc (intern_c_14, &major, &minor)
176                 && major == 14 && minor == 0);
177     SELF_CHECK (!producer_is_gcc (intern_c_14, &major, &minor));
178   }
179
180   {
181     static const char intern_c_18[] = "\
182 Intel(R) C++ Intel(R) 64 Compiler for applications running on \
183 Intel(R) 64, \
184 Version 18.0 Beta";
185     int major = 0, minor = 0;
186     SELF_CHECK (producer_is_icc (intern_c_18, &major, &minor)
187                 && major == 18 && minor == 0);
188   }
189
190   {
191     static const char gnu[] = "GNU C 4.7.2";
192     SELF_CHECK (!producer_is_icc (gnu, NULL, NULL));
193
194     int major = 0, minor = 0;
195     SELF_CHECK (producer_is_gcc (gnu, &major, &minor)
196                 && major == 4 && minor == 7);
197   }
198
199   {
200     static const char gnu_exp[] = "GNU C++14 5.0.0 20150123 (experimental)";
201     int major = 0, minor = 0;
202     SELF_CHECK (!producer_is_icc (gnu_exp, NULL, NULL));
203     SELF_CHECK (producer_is_gcc (gnu_exp, &major, &minor)
204                 && major == 5 && minor == 0);
205   }
206 }
207 }
208 }
209 #endif
210
211 void
212 _initialize_producer ()
213 {
214 #if defined GDB_SELF_TEST
215   selftests::register_test
216     ("producer-parser", selftests::producer::producer_parsing_tests);
217 #endif
218 }