]>
Commit | Line | Data |
---|---|---|
7adcbafe | 1 | # Copyright (C) 2003-2022 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 | ||
d8e91994 TS |
85 | # Return the number of comma-separated element of S. |
86 | function n_args(s) | |
87 | { | |
88 | n = 1 | |
89 | while (s ~ ",") { | |
90 | n++ | |
91 | sub("[^,]*, *", "", s) | |
92 | } | |
93 | return n | |
94 | } | |
95 | ||
75685792 RS |
96 | # Return the Nth comma-separated element of S. Return the empty string |
97 | # if S does not contain N elements. | |
98 | function nth_arg(n, s) | |
99 | { | |
100 | while (n-- > 0) { | |
101 | if (s !~ ",") | |
102 | return "" | |
103 | sub("[^,]*, *", "", s) | |
104 | } | |
105 | sub(",.*", "", s) | |
106 | return s | |
107 | } | |
108 | ||
109 | # Return a bitmask of CL_* values for option flags FLAGS. | |
776dc15d KC |
110 | function switch_flags (flags) |
111 | { | |
776dc15d KC |
112 | result = "0" |
113 | for (j = 0; j < n_langs; j++) { | |
a56a0779 | 114 | regex = langs[j] |
776dc15d | 115 | gsub ( "\\+", "\\+", regex ) |
a56a0779 | 116 | result = result test_flag(regex, flags, " | " macros[j]) |
776dc15d | 117 | } |
a56a0779 RS |
118 | result = result \ |
119 | test_flag("Common", flags, " | CL_COMMON") \ | |
120 | test_flag("Target", flags, " | CL_TARGET") \ | |
212bfe71 | 121 | test_flag("PchIgnore", flags, " | CL_PCH_IGNORE") \ |
603349bf | 122 | test_flag("Driver", flags, " | CL_DRIVER") \ |
a56a0779 | 123 | test_flag("Joined", flags, " | CL_JOINED") \ |
300d83d9 | 124 | test_flag("JoinedOrMissing", flags, " | CL_JOINED") \ |
a56a0779 | 125 | test_flag("Separate", flags, " | CL_SEPARATE") \ |
a56a0779 | 126 | test_flag("Undocumented", flags, " | CL_UNDOCUMENTED") \ |
77ee7190 | 127 | test_flag("NoDWARFRecord", flags, " | CL_NO_DWARF_RECORD") \ |
c662432e | 128 | test_flag("Warning", flags, " | CL_WARNING") \ |
76c26af9 ML |
129 | test_flag("(Optimization|PerFunction)", flags, " | CL_OPTIMIZATION") \ |
130 | test_flag("Param", flags, " | CL_PARAMS") | |
300d83d9 JM |
131 | sub( "^0 \\| ", "", result ) |
132 | return result | |
133 | } | |
134 | ||
135 | # Return bit-field initializers for option flags FLAGS. | |
136 | function switch_bit_fields (flags) | |
137 | { | |
00abf86c | 138 | uinteger_flag = "" |
99114bbf L |
139 | vn = var_name(flags); |
140 | if (host_wide_int[vn] == "yes") | |
141 | hwi = "Host_Wide_Int" | |
00abf86c MS |
142 | else if (flag_set_p("Host_Wide_Int", flags)) { |
143 | hwi = "Host_Wide_Int" | |
144 | uinteger_flag = flag_init("UInteger", flags) | |
145 | } | |
99114bbf L |
146 | else |
147 | hwi = "" | |
300d83d9 | 148 | result = "" |
c243beb0 | 149 | sep_args = opt_args("Args", flags) |
300d83d9 JM |
150 | if (sep_args == "") |
151 | sep_args = 0 | |
152 | else | |
c243beb0 | 153 | sep_args-- |
300d83d9 JM |
154 | result = result sep_args ", " |
155 | ||
00abf86c MS |
156 | if (uinteger_flag == "") |
157 | uinteger_flag = flag_init("UInteger", flags) | |
158 | ||
159 | hwi_flag = flag_init("Host_Wide_Int", hwi) | |
160 | byte_size_flag = flag_init("ByteSize", flags) | |
161 | ||
162 | if (substr(byte_size_flag, 1, 1) != "0" \ | |
163 | && substr(uinteger_flag, 1, 1) == "0" \ | |
164 | && substr(hwi_flag, 1, 1) == "0") | |
165 | print "#error only UInteger amd Host_Wide_Int options can specify a ByteSize suffix" | |
166 | ||
167 | # The following flags need to be in the same order as | |
168 | # the corresponding members of struct cl_option defined | |
169 | # in gcc/opts.h. | |
300d83d9 JM |
170 | result = result \ |
171 | flag_init("SeparateAlias", flags) \ | |
172 | flag_init("NegativeAlias", flags) \ | |
173 | flag_init("NoDriverArg", flags) \ | |
174 | flag_init("RejectDriver", flags) \ | |
175 | flag_init("RejectNegative", flags) \ | |
176 | flag_init("JoinedOrMissing", flags) \ | |
00abf86c MS |
177 | uinteger_flag \ |
178 | hwi_flag \ | |
413519ae | 179 | flag_init("ToLower", flags) \ |
00abf86c | 180 | byte_size_flag |
300d83d9 | 181 | |
5137d1ae ML |
182 | if (flag_set_p("Report", flags)) |
183 | print "#error Report option property is dropped" | |
184 | ||
300d83d9 | 185 | sub(", $", "", result) |
776dc15d KC |
186 | return result |
187 | } | |
188 | ||
75685792 RS |
189 | # If FLAGS includes a Var flag, return the name of the variable it specifies. |
190 | # Return the empty string otherwise. | |
776dc15d KC |
191 | function var_name(flags) |
192 | { | |
75685792 | 193 | return nth_arg(0, opt_args("Var", flags)) |
776dc15d | 194 | } |
75685792 | 195 | |
99114bbf L |
196 | # Return the name of the variable if FLAGS has a HOST_WIDE_INT variable. |
197 | # Return the empty string otherwise. | |
198 | function host_wide_int_var_name(flags) | |
199 | { | |
200 | split (flags, array, "[ \t]+") | |
201 | if (array[1] == "HOST_WIDE_INT") | |
202 | return array[2] | |
203 | else | |
204 | return "" | |
205 | } | |
206 | ||
ee133b69 RS |
207 | # Return true if the option described by FLAGS has a globally-visible state. |
208 | function global_state_p(flags) | |
209 | { | |
210 | return (var_name(flags) != "" \ | |
211 | || opt_args("Mask", flags) != "" \ | |
212 | || opt_args("InverseMask", flags) != "") | |
213 | } | |
214 | ||
215 | # Return true if the option described by FLAGS must have some state | |
216 | # associated with it. | |
217 | function needs_state_p(flags) | |
218 | { | |
2d2bd949 JM |
219 | return (flag_set_p("Target", flags) \ |
220 | && !flag_set_p("Alias.*", flags) \ | |
221 | && !flag_set_p("Ignore", flags)) | |
ee133b69 RS |
222 | } |
223 | ||
46625112 JM |
224 | # If FLAGS describes an option that needs state without a public |
225 | # variable name, return the name of that field, minus the initial | |
226 | # "x_", otherwise return "". NAME is the name of the option. | |
ee133b69 RS |
227 | function static_var(name, flags) |
228 | { | |
229 | if (global_state_p(flags) || !needs_state_p(flags)) | |
230 | return "" | |
e4590d63 | 231 | gsub ("[^" alnum "]", "_", name) |
ee133b69 RS |
232 | return "VAR_" name |
233 | } | |
234 | ||
55bea00a RS |
235 | # Return the type of variable that should be associated with the given flags. |
236 | function var_type(flags) | |
237 | { | |
21bf1558 JM |
238 | if (flag_set_p("Defer", flags)) |
239 | return "void *" | |
e6d4b984 JM |
240 | else if (flag_set_p("Enum.*", flags)) { |
241 | en = opt_args("Enum", flags); | |
242 | return enum_type[en] " " | |
243 | } | |
21bf1558 | 244 | else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) |
55bea00a | 245 | return "int " |
00abf86c MS |
246 | else if (flag_set_p("Host_Wide_Int", flags)) |
247 | return "HOST_WIDE_INT " | |
55bea00a RS |
248 | else if (flag_set_p("UInteger", flags)) |
249 | return "int " | |
250 | else | |
251 | return "const char *" | |
252 | } | |
253 | ||
ab442df7 | 254 | # Return the type of variable that should be associated with the given flags |
a3f410a2 | 255 | # for use within a structure. Simple variables are changed to signed char |
ab442df7 MM |
256 | # type instead of int to save space. |
257 | function var_type_struct(flags) | |
258 | { | |
00abf86c MS |
259 | if (flag_set_p("UInteger", flags)) { |
260 | if (host_wide_int[var_name(flags)] == "yes") | |
261 | return "HOST_WIDE_INT "; | |
262 | if (flag_set_p("ByteSize", flags)) | |
263 | return "HOST_WIDE_INT " | |
264 | return "int " | |
265 | } | |
c860fe8c JM |
266 | else if (flag_set_p("Enum.*", flags)) { |
267 | en = opt_args("Enum", flags); | |
268 | return enum_type[en] " " | |
269 | } | |
603349bf | 270 | else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) { |
99114bbf L |
271 | if (flag_set_p(".*Mask.*", flags)) { |
272 | if (host_wide_int[var_name(flags)] == "yes") | |
273 | return "HOST_WIDE_INT " | |
274 | else | |
00abf86c | 275 | return "/* - */ int " |
99114bbf | 276 | } |
ab442df7 | 277 | else |
a3f410a2 | 278 | return "signed char " |
ab442df7 MM |
279 | } |
280 | else | |
281 | return "const char *" | |
282 | } | |
283 | ||
75685792 | 284 | # Given that an option has flags FLAGS, return an initializer for the |
e6d4b984 | 285 | # "var_enum", "var_type" and "var_value" fields of its cl_options[] entry. |
776dc15d KC |
286 | function var_set(flags) |
287 | { | |
21bf1558 | 288 | if (flag_set_p("Defer", flags)) |
e6d4b984 | 289 | return "0, CLVC_DEFER, 0" |
75685792 RS |
290 | s = nth_arg(1, opt_args("Var", flags)) |
291 | if (s != "") | |
e6d4b984 | 292 | return "0, CLVC_EQUAL, " s |
75685792 | 293 | s = opt_args("Mask", flags); |
a45505d8 DD |
294 | if (s != "") { |
295 | vn = var_name(flags); | |
296 | if (vn) | |
e6d4b984 | 297 | return "0, CLVC_BIT_SET, OPTION_MASK_" s |
a45505d8 | 298 | else |
e6d4b984 | 299 | return "0, CLVC_BIT_SET, MASK_" s |
a45505d8 | 300 | } |
75685792 | 301 | s = nth_arg(0, opt_args("InverseMask", flags)); |
c1630cc5 DE |
302 | if (s != "") { |
303 | vn = var_name(flags); | |
304 | if (vn) | |
e6d4b984 | 305 | return "0, CLVC_BIT_CLEAR, OPTION_MASK_" s |
55bea00a | 306 | else |
e6d4b984 JM |
307 | return "0, CLVC_BIT_CLEAR, MASK_" s |
308 | } | |
309 | if (flag_set_p("Enum.*", flags)) { | |
310 | en = opt_args("Enum", flags); | |
385196ad | 311 | if (flag_set_p("EnumSet", flags)) |
0ebb09f5 JJ |
312 | return enum_index[en] ", CLVC_ENUM, CLEV_SET" |
313 | else if (flag_set_p("EnumBitSet", flags)) | |
314 | return enum_index[en] ", CLVC_ENUM, CLEV_BITSET" | |
385196ad | 315 | else |
0ebb09f5 | 316 | return enum_index[en] ", CLVC_ENUM, CLEV_NORMAL" |
c1630cc5 | 317 | } |
55bea00a | 318 | if (var_type(flags) == "const char *") |
e6d4b984 | 319 | return "0, CLVC_STRING, 0" |
00abf86c MS |
320 | if (flag_set_p("ByteSize", flags)) |
321 | return "0, CLVC_SIZE, 0" | |
8e836af6 | 322 | return "0, CLVC_INTEGER, 0" |
776dc15d | 323 | } |
75685792 | 324 | |
ee133b69 RS |
325 | # Given that an option called NAME has flags FLAGS, return an initializer |
326 | # for the "flag_var" field of its cl_options[] entry. | |
327 | function var_ref(name, flags) | |
776dc15d | 328 | { |
ee133b69 | 329 | name = var_name(flags) static_var(name, flags) |
75685792 | 330 | if (name != "") |
46625112 | 331 | return "offsetof (struct gcc_options, x_" name ")" |
75685792 | 332 | if (opt_args("Mask", flags) != "") |
46625112 | 333 | return "offsetof (struct gcc_options, x_target_flags)" |
75685792 | 334 | if (opt_args("InverseMask", flags) != "") |
46625112 | 335 | return "offsetof (struct gcc_options, x_target_flags)" |
f6b3ca5a | 336 | return "(unsigned short) -1" |
776dc15d | 337 | } |
9db94baa MLI |
338 | |
339 | # Given the option called NAME return a sanitized version of its name. | |
340 | function opt_sanitized_name(name) | |
341 | { | |
e4590d63 | 342 | gsub ("[^" alnum "]", "_", name) |
9db94baa MLI |
343 | return name |
344 | } | |
345 | ||
346 | # Given the option called NAME return the appropriate enum for it. | |
347 | function opt_enum(name) | |
348 | { | |
349 | return "OPT_" opt_sanitized_name(name) | |
350 | } | |
f2bc201f MLI |
351 | |
352 | # Given the language called NAME return a sanitized version of its name. | |
353 | function lang_sanitized_name(name) | |
354 | { | |
355 | gsub( "[^" alnum "_]", "X", name ) | |
356 | return name | |
357 | } | |
d919140b MLI |
358 | |
359 | # Search for a valid var_name among all OPTS equal to option NAME. | |
360 | # If not found, return "". | |
361 | function search_var_name(name, opt_numbers, opts, flags, n_opts) | |
362 | { | |
363 | opt_var_name = var_name(flags[opt_numbers[name]]); | |
364 | if (opt_var_name != "") { | |
365 | return opt_var_name; | |
366 | } | |
367 | for (k = 0; k < n_opts; k++) { | |
368 | if (opts[k] == name && var_name(flags[k]) != "") { | |
369 | return var_name(flags[k]); | |
370 | } | |
371 | } | |
372 | return "" | |
373 | } | |
0829c7f7 | 374 | |
679652a7 | 375 | function integer_range_info(range_option, init, option, uinteger_used) |
63010089 ML |
376 | { |
377 | if (range_option != "") { | |
4bc8aadf JM |
378 | ival = init + 0; |
379 | start = nth_arg(0, range_option) + 0; | |
380 | end = nth_arg(1, range_option) + 0; | |
381 | if (init != "" && init != "-1" && (ival < start || ival > end)) | |
e88a9384 | 382 | print "#error initial value " init " of '" option "' must be in range [" start "," end "]" |
679652a7 ML |
383 | if (uinteger_used && start < 0) |
384 | print "#error '" option"': negative IntegerRange (" start ", " end ") cannot be combined with UInteger" | |
63010089 ML |
385 | return start ", " end |
386 | } | |
387 | else | |
388 | return "-1, -1" | |
389 | } |