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