]>
Commit | Line | Data |
---|---|---|
8d9254fc | 1 | # Copyright (C) 2003-2020 Free Software Foundation, Inc. |
776dc15d KC |
2 | # Contributed by Kelley Cook, June 2004. |
3 | # Original code from Neil Booth, May 2003. | |
4 | # | |
5 | # This program is free software; you can redistribute it and/or modify it | |
6 | # under the terms of the GNU General Public License as published by the | |
9dcd6f09 | 7 | # Free Software Foundation; either version 3, or (at your option) any |
776dc15d KC |
8 | # later version. |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
16 | # along with this program; see the file COPYING3. If not see |
17 | # <http://www.gnu.org/licenses/>. | |
776dc15d KC |
18 | |
19 | # Some common subroutines for use by opt[ch]-gen.awk. | |
20 | ||
e4590d63 RW |
21 | # Define some helpful character classes, for portability. |
22 | BEGIN { | |
23 | lower = "abcdefghijklmnopqrstuvwxyz" | |
24 | upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
25 | digit = "0123456789" | |
26 | alnum = lower "" upper "" digit | |
27 | } | |
28 | ||
a56a0779 RS |
29 | # Return nonzero if FLAGS contains a flag matching REGEX. |
30 | function flag_set_p(regex, flags) | |
31 | { | |
f2bc201f MLI |
32 | # Ignore the arguments of flags with arguments. |
33 | gsub ("\\([^)]+\\)", "", flags); | |
34 | return (" " flags " ") ~ (" " regex " ") | |
a56a0779 RS |
35 | } |
36 | ||
37 | # Return STRING if FLAGS contains a flag matching regexp REGEX, | |
38 | # otherwise return the empty string. | |
39 | function test_flag(regex, flags, string) | |
40 | { | |
41 | if (flag_set_p(regex, flags)) | |
42 | return string | |
43 | return "" | |
44 | } | |
45 | ||
300d83d9 JM |
46 | # Return a field initializer, with trailing comma, for a field that is |
47 | # 1 if FLAGS contains a flag matching REGEX and 0 otherwise. | |
48 | function flag_init(regex, flags) | |
49 | { | |
50 | if (flag_set_p(regex, flags)) | |
51 | return "1 /* " regex " */, " | |
52 | else | |
53 | return "0, " | |
54 | } | |
55 | ||
75685792 RS |
56 | # If FLAGS contains a "NAME(...argument...)" flag, return the value |
57 | # of the argument. Return the empty string otherwise. | |
58 | function opt_args(name, flags) | |
59 | { | |
60 | flags = " " flags | |
61 | if (flags !~ " " name "\\(") | |
62 | return "" | |
63 | sub(".* " name "\\(", "", flags) | |
27ec2266 | 64 | if (flags ~ "^[{]") |
88c2fd3d | 65 | { |
27ec2266 JJ |
66 | sub ("^[{]", "", flags) |
67 | sub ("}\\).*", "", flags) | |
88c2fd3d DK |
68 | } |
69 | else | |
70 | sub("\\).*", "", flags) | |
75685792 RS |
71 | |
72 | return flags | |
73 | } | |
74 | ||
2d8a60a6 ML |
75 | # If FLAGS contains a "NAME(...argument...)" flag, return the value |
76 | # of the argument. Print error message otherwise. | |
77 | function opt_args_non_empty(name, flags, description) | |
78 | { | |
79 | args = opt_args(name, flags) | |
80 | if (args == "") | |
81 | print "#error Empty option argument '" name "' during parsing of: " flags | |
82 | return args | |
83 | } | |
84 | ||
75685792 RS |
85 | # Return the Nth comma-separated element of S. Return the empty string |
86 | # if S does not contain N elements. | |
87 | function nth_arg(n, s) | |
88 | { | |
89 | while (n-- > 0) { | |
90 | if (s !~ ",") | |
91 | return "" | |
92 | sub("[^,]*, *", "", s) | |
93 | } | |
94 | sub(",.*", "", s) | |
95 | return s | |
96 | } | |
97 | ||
98 | # Return a bitmask of CL_* values for option flags FLAGS. | |
776dc15d KC |
99 | function switch_flags (flags) |
100 | { | |
776dc15d KC |
101 | result = "0" |
102 | for (j = 0; j < n_langs; j++) { | |
a56a0779 | 103 | regex = langs[j] |
776dc15d | 104 | gsub ( "\\+", "\\+", regex ) |
a56a0779 | 105 | result = result test_flag(regex, flags, " | " macros[j]) |
776dc15d | 106 | } |
a56a0779 RS |
107 | result = result \ |
108 | test_flag("Common", flags, " | CL_COMMON") \ | |
109 | test_flag("Target", flags, " | CL_TARGET") \ | |
212bfe71 | 110 | test_flag("PchIgnore", flags, " | CL_PCH_IGNORE") \ |
603349bf | 111 | test_flag("Driver", flags, " | CL_DRIVER") \ |
a56a0779 | 112 | test_flag("Joined", flags, " | CL_JOINED") \ |
300d83d9 | 113 | test_flag("JoinedOrMissing", flags, " | CL_JOINED") \ |
a56a0779 | 114 | test_flag("Separate", flags, " | CL_SEPARATE") \ |
a56a0779 | 115 | test_flag("Undocumented", flags, " | CL_UNDOCUMENTED") \ |
77ee7190 | 116 | test_flag("NoDWARFRecord", flags, " | CL_NO_DWARF_RECORD") \ |
c662432e | 117 | test_flag("Warning", flags, " | CL_WARNING") \ |
76c26af9 ML |
118 | test_flag("(Optimization|PerFunction)", flags, " | CL_OPTIMIZATION") \ |
119 | test_flag("Param", flags, " | CL_PARAMS") | |
300d83d9 JM |
120 | sub( "^0 \\| ", "", result ) |
121 | return result | |
122 | } | |
123 | ||
124 | # Return bit-field initializers for option flags FLAGS. | |
125 | function switch_bit_fields (flags) | |
126 | { | |
00abf86c | 127 | uinteger_flag = "" |
99114bbf L |
128 | vn = var_name(flags); |
129 | if (host_wide_int[vn] == "yes") | |
130 | hwi = "Host_Wide_Int" | |
00abf86c MS |
131 | else if (flag_set_p("Host_Wide_Int", flags)) { |
132 | hwi = "Host_Wide_Int" | |
133 | uinteger_flag = flag_init("UInteger", flags) | |
134 | } | |
99114bbf L |
135 | else |
136 | hwi = "" | |
300d83d9 | 137 | result = "" |
c243beb0 | 138 | sep_args = opt_args("Args", flags) |
300d83d9 JM |
139 | if (sep_args == "") |
140 | sep_args = 0 | |
141 | else | |
c243beb0 | 142 | sep_args-- |
300d83d9 JM |
143 | result = result sep_args ", " |
144 | ||
00abf86c MS |
145 | if (uinteger_flag == "") |
146 | uinteger_flag = flag_init("UInteger", flags) | |
147 | ||
148 | hwi_flag = flag_init("Host_Wide_Int", hwi) | |
149 | byte_size_flag = flag_init("ByteSize", flags) | |
150 | ||
151 | if (substr(byte_size_flag, 1, 1) != "0" \ | |
152 | && substr(uinteger_flag, 1, 1) == "0" \ | |
153 | && substr(hwi_flag, 1, 1) == "0") | |
154 | print "#error only UInteger amd Host_Wide_Int options can specify a ByteSize suffix" | |
155 | ||
156 | # The following flags need to be in the same order as | |
157 | # the corresponding members of struct cl_option defined | |
158 | # in gcc/opts.h. | |
300d83d9 JM |
159 | result = result \ |
160 | flag_init("SeparateAlias", flags) \ | |
161 | flag_init("NegativeAlias", flags) \ | |
162 | flag_init("NoDriverArg", flags) \ | |
163 | flag_init("RejectDriver", flags) \ | |
164 | flag_init("RejectNegative", flags) \ | |
165 | flag_init("JoinedOrMissing", flags) \ | |
00abf86c MS |
166 | uinteger_flag \ |
167 | hwi_flag \ | |
413519ae | 168 | flag_init("ToLower", flags) \ |
3713f2e2 | 169 | flag_init("Report", flags) \ |
00abf86c | 170 | byte_size_flag |
300d83d9 JM |
171 | |
172 | sub(", $", "", result) | |
776dc15d KC |
173 | return result |
174 | } | |
175 | ||
75685792 RS |
176 | # If FLAGS includes a Var flag, return the name of the variable it specifies. |
177 | # Return the empty string otherwise. | |
776dc15d KC |
178 | function var_name(flags) |
179 | { | |
75685792 | 180 | return nth_arg(0, opt_args("Var", flags)) |
776dc15d | 181 | } |
75685792 | 182 | |
99114bbf L |
183 | # Return the name of the variable if FLAGS has a HOST_WIDE_INT variable. |
184 | # Return the empty string otherwise. | |
185 | function host_wide_int_var_name(flags) | |
186 | { | |
187 | split (flags, array, "[ \t]+") | |
188 | if (array[1] == "HOST_WIDE_INT") | |
189 | return array[2] | |
190 | else | |
191 | return "" | |
192 | } | |
193 | ||
ee133b69 RS |
194 | # Return true if the option described by FLAGS has a globally-visible state. |
195 | function global_state_p(flags) | |
196 | { | |
197 | return (var_name(flags) != "" \ | |
198 | || opt_args("Mask", flags) != "" \ | |
199 | || opt_args("InverseMask", flags) != "") | |
200 | } | |
201 | ||
202 | # Return true if the option described by FLAGS must have some state | |
203 | # associated with it. | |
204 | function needs_state_p(flags) | |
205 | { | |
2d2bd949 JM |
206 | return (flag_set_p("Target", flags) \ |
207 | && !flag_set_p("Alias.*", flags) \ | |
208 | && !flag_set_p("Ignore", flags)) | |
ee133b69 RS |
209 | } |
210 | ||
46625112 JM |
211 | # If FLAGS describes an option that needs state without a public |
212 | # variable name, return the name of that field, minus the initial | |
213 | # "x_", otherwise return "". NAME is the name of the option. | |
ee133b69 RS |
214 | function static_var(name, flags) |
215 | { | |
216 | if (global_state_p(flags) || !needs_state_p(flags)) | |
217 | return "" | |
e4590d63 | 218 | gsub ("[^" alnum "]", "_", name) |
ee133b69 RS |
219 | return "VAR_" name |
220 | } | |
221 | ||
55bea00a RS |
222 | # Return the type of variable that should be associated with the given flags. |
223 | function var_type(flags) | |
224 | { | |
21bf1558 JM |
225 | if (flag_set_p("Defer", flags)) |
226 | return "void *" | |
e6d4b984 JM |
227 | else if (flag_set_p("Enum.*", flags)) { |
228 | en = opt_args("Enum", flags); | |
229 | return enum_type[en] " " | |
230 | } | |
21bf1558 | 231 | else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) |
55bea00a | 232 | return "int " |
00abf86c MS |
233 | else if (flag_set_p("Host_Wide_Int", flags)) |
234 | return "HOST_WIDE_INT " | |
55bea00a RS |
235 | else if (flag_set_p("UInteger", flags)) |
236 | return "int " | |
237 | else | |
238 | return "const char *" | |
239 | } | |
240 | ||
ab442df7 | 241 | # Return the type of variable that should be associated with the given flags |
a3f410a2 | 242 | # for use within a structure. Simple variables are changed to signed char |
ab442df7 MM |
243 | # type instead of int to save space. |
244 | function var_type_struct(flags) | |
245 | { | |
00abf86c MS |
246 | if (flag_set_p("UInteger", flags)) { |
247 | if (host_wide_int[var_name(flags)] == "yes") | |
248 | return "HOST_WIDE_INT "; | |
249 | if (flag_set_p("ByteSize", flags)) | |
250 | return "HOST_WIDE_INT " | |
251 | return "int " | |
252 | } | |
c860fe8c JM |
253 | else if (flag_set_p("Enum.*", flags)) { |
254 | en = opt_args("Enum", flags); | |
255 | return enum_type[en] " " | |
256 | } | |
603349bf | 257 | else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) { |
99114bbf L |
258 | if (flag_set_p(".*Mask.*", flags)) { |
259 | if (host_wide_int[var_name(flags)] == "yes") | |
260 | return "HOST_WIDE_INT " | |
261 | else | |
00abf86c | 262 | return "/* - */ int " |
99114bbf | 263 | } |
ab442df7 | 264 | else |
a3f410a2 | 265 | return "signed char " |
ab442df7 MM |
266 | } |
267 | else | |
268 | return "const char *" | |
269 | } | |
270 | ||
75685792 | 271 | # Given that an option has flags FLAGS, return an initializer for the |
e6d4b984 | 272 | # "var_enum", "var_type" and "var_value" fields of its cl_options[] entry. |
776dc15d KC |
273 | function var_set(flags) |
274 | { | |
21bf1558 | 275 | if (flag_set_p("Defer", flags)) |
e6d4b984 | 276 | return "0, CLVC_DEFER, 0" |
75685792 RS |
277 | s = nth_arg(1, opt_args("Var", flags)) |
278 | if (s != "") | |
e6d4b984 | 279 | return "0, CLVC_EQUAL, " s |
75685792 | 280 | s = opt_args("Mask", flags); |
a45505d8 DD |
281 | if (s != "") { |
282 | vn = var_name(flags); | |
283 | if (vn) | |
e6d4b984 | 284 | return "0, CLVC_BIT_SET, OPTION_MASK_" s |
a45505d8 | 285 | else |
e6d4b984 | 286 | return "0, CLVC_BIT_SET, MASK_" s |
a45505d8 | 287 | } |
75685792 | 288 | s = nth_arg(0, opt_args("InverseMask", flags)); |
c1630cc5 DE |
289 | if (s != "") { |
290 | vn = var_name(flags); | |
291 | if (vn) | |
e6d4b984 | 292 | return "0, CLVC_BIT_CLEAR, OPTION_MASK_" s |
55bea00a | 293 | else |
e6d4b984 JM |
294 | return "0, CLVC_BIT_CLEAR, MASK_" s |
295 | } | |
296 | if (flag_set_p("Enum.*", flags)) { | |
297 | en = opt_args("Enum", flags); | |
298 | return enum_index[en] ", CLVC_ENUM, 0" | |
c1630cc5 | 299 | } |
55bea00a | 300 | if (var_type(flags) == "const char *") |
e6d4b984 | 301 | return "0, CLVC_STRING, 0" |
00abf86c MS |
302 | if (flag_set_p("ByteSize", flags)) |
303 | return "0, CLVC_SIZE, 0" | |
e6d4b984 | 304 | return "0, CLVC_BOOLEAN, 0" |
776dc15d | 305 | } |
75685792 | 306 | |
ee133b69 RS |
307 | # Given that an option called NAME has flags FLAGS, return an initializer |
308 | # for the "flag_var" field of its cl_options[] entry. | |
309 | function var_ref(name, flags) | |
776dc15d | 310 | { |
ee133b69 | 311 | name = var_name(flags) static_var(name, flags) |
75685792 | 312 | if (name != "") |
46625112 | 313 | return "offsetof (struct gcc_options, x_" name ")" |
75685792 | 314 | if (opt_args("Mask", flags) != "") |
46625112 | 315 | return "offsetof (struct gcc_options, x_target_flags)" |
75685792 | 316 | if (opt_args("InverseMask", flags) != "") |
46625112 | 317 | return "offsetof (struct gcc_options, x_target_flags)" |
f6b3ca5a | 318 | return "(unsigned short) -1" |
776dc15d | 319 | } |
9db94baa MLI |
320 | |
321 | # Given the option called NAME return a sanitized version of its name. | |
322 | function opt_sanitized_name(name) | |
323 | { | |
e4590d63 | 324 | gsub ("[^" alnum "]", "_", name) |
9db94baa MLI |
325 | return name |
326 | } | |
327 | ||
328 | # Given the option called NAME return the appropriate enum for it. | |
329 | function opt_enum(name) | |
330 | { | |
331 | return "OPT_" opt_sanitized_name(name) | |
332 | } | |
f2bc201f MLI |
333 | |
334 | # Given the language called NAME return a sanitized version of its name. | |
335 | function lang_sanitized_name(name) | |
336 | { | |
337 | gsub( "[^" alnum "_]", "X", name ) | |
338 | return name | |
339 | } | |
d919140b MLI |
340 | |
341 | # Search for a valid var_name among all OPTS equal to option NAME. | |
342 | # If not found, return "". | |
343 | function search_var_name(name, opt_numbers, opts, flags, n_opts) | |
344 | { | |
345 | opt_var_name = var_name(flags[opt_numbers[name]]); | |
346 | if (opt_var_name != "") { | |
347 | return opt_var_name; | |
348 | } | |
349 | for (k = 0; k < n_opts; k++) { | |
350 | if (opts[k] == name && var_name(flags[k]) != "") { | |
351 | return var_name(flags[k]); | |
352 | } | |
353 | } | |
354 | return "" | |
355 | } | |
0829c7f7 | 356 | |
e88a9384 | 357 | function integer_range_info(range_option, init, option) |
63010089 ML |
358 | { |
359 | if (range_option != "") { | |
4bc8aadf JM |
360 | ival = init + 0; |
361 | start = nth_arg(0, range_option) + 0; | |
362 | end = nth_arg(1, range_option) + 0; | |
363 | if (init != "" && init != "-1" && (ival < start || ival > end)) | |
e88a9384 | 364 | print "#error initial value " init " of '" option "' must be in range [" start "," end "]" |
63010089 ML |
365 | return start ", " end |
366 | } | |
367 | else | |
368 | return "-1, -1" | |
369 | } | |
370 | ||
0829c7f7 MLI |
371 | # Handle LangEnabledBy(ENABLED_BY_LANGS, ENABLEDBY_NAME, ENABLEDBY_POSARG, |
372 | # ENABLEDBY_NEGARG). This function does not return anything. | |
373 | function lang_enabled_by(enabledby_langs, enabledby_name, enabledby_posarg, enabledby_negarg) | |
374 | { | |
375 | n_enabledby_arg_langs = split(enabledby_langs, enabledby_arg_langs, " "); | |
27e51192 TB |
376 | if (enabledby_posarg != "" && enabledby_negarg != "") { |
377 | with_args = "," enabledby_posarg "," enabledby_negarg | |
378 | } else if (enabledby_posarg == "" && enabledby_negarg == "") { | |
379 | with_args = "" | |
0829c7f7 | 380 | } else { |
c2d89095 | 381 | print "#error " opts[i] " LangEnabledBy("enabledby_langs","enabledby_name", " \ |
27e51192 TB |
382 | enabledby_posarg", " enabledby_negargs \ |
383 | ") with three arguments, it should have either 2 or 4" | |
384 | } | |
385 | ||
386 | n_enabledby_array = split(enabledby_name, enabledby_array, " \\|\\| "); | |
387 | for (k = 1; k <= n_enabledby_array; k++) { | |
388 | enabledby_index = opt_numbers[enabledby_array[k]]; | |
389 | if (enabledby_index == "") { | |
c2d89095 MLI |
390 | print "#error " opts[i] " LangEnabledBy("enabledby_langs","enabledby_name", " \ |
391 | enabledby_posarg", " enabledby_negargs"), unknown option '" enabledby_name "'" | |
0829c7f7 | 392 | } else { |
27e51192 TB |
393 | for (j = 1; j <= n_enabledby_arg_langs; j++) { |
394 | lang_name = lang_sanitized_name(enabledby_arg_langs[j]); | |
395 | lang_index = lang_numbers[enabledby_arg_langs[j]]; | |
396 | if (enables[lang_name,enabledby_array[k]] == "") { | |
397 | enabledby[lang_name,n_enabledby_lang[lang_index]] = enabledby_array[k]; | |
398 | n_enabledby_lang[lang_index]++; | |
399 | } | |
400 | enables[lang_name,enabledby_array[k]] \ | |
401 | = enables[lang_name,enabledby_array[k]] opts[i] with_args ";"; | |
0829c7f7 | 402 | } |
0829c7f7 MLI |
403 | } |
404 | } | |
405 | } |