1# Copyright (C) 2003-2019 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 sub( "^0 \\| ", "", result ) 110 return result 111} 112 113# Return bit-field initializers for option flags FLAGS. 114function switch_bit_fields (flags) 115{ 116 uinteger_flag = "" 117 vn = var_name(flags); 118 if (host_wide_int[vn] == "yes") 119 hwi = "Host_Wide_Int" 120 else if (flag_set_p("Host_Wide_Int", flags)) { 121 hwi = "Host_Wide_Int" 122 uinteger_flag = flag_init("UInteger", flags) 123 } 124 else 125 hwi = "" 126 result = "" 127 sep_args = opt_args("Args", flags) 128 if (sep_args == "") 129 sep_args = 0 130 else 131 sep_args-- 132 result = result sep_args ", " 133 134 if (uinteger_flag == "") 135 uinteger_flag = flag_init("UInteger", flags) 136 137 hwi_flag = flag_init("Host_Wide_Int", hwi) 138 byte_size_flag = flag_init("ByteSize", flags) 139 140 if (substr(byte_size_flag, 1, 1) != "0" \ 141 && substr(uinteger_flag, 1, 1) == "0" \ 142 && substr(hwi_flag, 1, 1) == "0") 143 print "#error only UInteger amd Host_Wide_Int options can specify a ByteSize suffix" 144 145 # The following flags need to be in the same order as 146 # the corresponding members of struct cl_option defined 147 # in gcc/opts.h. 148 result = result \ 149 flag_init("SeparateAlias", flags) \ 150 flag_init("NegativeAlias", flags) \ 151 flag_init("NoDriverArg", flags) \ 152 flag_init("RejectDriver", flags) \ 153 flag_init("RejectNegative", flags) \ 154 flag_init("JoinedOrMissing", flags) \ 155 uinteger_flag \ 156 hwi_flag \ 157 flag_init("ToLower", flags) \ 158 flag_init("Report", flags) \ 159 byte_size_flag 160 161 sub(", $", "", result) 162 return result 163} 164 165# If FLAGS includes a Var flag, return the name of the variable it specifies. 166# Return the empty string otherwise. 167function var_name(flags) 168{ 169 return nth_arg(0, opt_args("Var", flags)) 170} 171 172# Return the name of the variable if FLAGS has a HOST_WIDE_INT variable. 173# Return the empty string otherwise. 174function host_wide_int_var_name(flags) 175{ 176 split (flags, array, "[ \t]+") 177 if (array[1] == "HOST_WIDE_INT") 178 return array[2] 179 else 180 return "" 181} 182 183# Return true if the option described by FLAGS has a globally-visible state. 184function global_state_p(flags) 185{ 186 return (var_name(flags) != "" \ 187 || opt_args("Mask", flags) != "" \ 188 || opt_args("InverseMask", flags) != "") 189} 190 191# Return true if the option described by FLAGS must have some state 192# associated with it. 193function needs_state_p(flags) 194{ 195 return (flag_set_p("Target", flags) \ 196 && !flag_set_p("Alias.*", flags) \ 197 && !flag_set_p("Ignore", flags)) 198} 199 200# If FLAGS describes an option that needs state without a public 201# variable name, return the name of that field, minus the initial 202# "x_", otherwise return "". NAME is the name of the option. 203function static_var(name, flags) 204{ 205 if (global_state_p(flags) || !needs_state_p(flags)) 206 return "" 207 gsub ("[^" alnum "]", "_", name) 208 return "VAR_" name 209} 210 211# Return the type of variable that should be associated with the given flags. 212function var_type(flags) 213{ 214 if (flag_set_p("Defer", flags)) 215 return "void *" 216 else if (flag_set_p("Enum.*", flags)) { 217 en = opt_args("Enum", flags); 218 return enum_type[en] " " 219 } 220 else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) 221 return "int " 222 else if (flag_set_p("Host_Wide_Int", flags)) 223 return "HOST_WIDE_INT " 224 else if (flag_set_p("UInteger", flags)) 225 return "int " 226 else 227 return "const char *" 228} 229 230# Return the type of variable that should be associated with the given flags 231# for use within a structure. Simple variables are changed to signed char 232# type instead of int to save space. 233function var_type_struct(flags) 234{ 235 if (flag_set_p("UInteger", flags)) { 236 if (host_wide_int[var_name(flags)] == "yes") 237 return "HOST_WIDE_INT "; 238 if (flag_set_p("ByteSize", flags)) 239 return "HOST_WIDE_INT " 240 return "int " 241 } 242 else if (flag_set_p("Enum.*", flags)) { 243 en = opt_args("Enum", flags); 244 return enum_type[en] " " 245 } 246 else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) { 247 if (flag_set_p(".*Mask.*", flags)) { 248 if (host_wide_int[var_name(flags)] == "yes") 249 return "HOST_WIDE_INT " 250 else 251 return "/* - */ int " 252 } 253 else 254 return "signed char " 255 } 256 else 257 return "const char *" 258} 259 260# Given that an option has flags FLAGS, return an initializer for the 261# "var_enum", "var_type" and "var_value" fields of its cl_options[] entry. 262function var_set(flags) 263{ 264 if (flag_set_p("Defer", flags)) 265 return "0, CLVC_DEFER, 0" 266 s = nth_arg(1, opt_args("Var", flags)) 267 if (s != "") 268 return "0, CLVC_EQUAL, " s 269 s = opt_args("Mask", flags); 270 if (s != "") { 271 vn = var_name(flags); 272 if (vn) 273 return "0, CLVC_BIT_SET, OPTION_MASK_" s 274 else 275 return "0, CLVC_BIT_SET, MASK_" s 276 } 277 s = nth_arg(0, opt_args("InverseMask", flags)); 278 if (s != "") { 279 vn = var_name(flags); 280 if (vn) 281 return "0, CLVC_BIT_CLEAR, OPTION_MASK_" s 282 else 283 return "0, CLVC_BIT_CLEAR, MASK_" s 284 } 285 if (flag_set_p("Enum.*", flags)) { 286 en = opt_args("Enum", flags); 287 return enum_index[en] ", CLVC_ENUM, 0" 288 } 289 if (var_type(flags) == "const char *") 290 return "0, CLVC_STRING, 0" 291 if (flag_set_p("ByteSize", flags)) 292 return "0, CLVC_SIZE, 0" 293 return "0, CLVC_BOOLEAN, 0" 294} 295 296# Given that an option called NAME has flags FLAGS, return an initializer 297# for the "flag_var" field of its cl_options[] entry. 298function var_ref(name, flags) 299{ 300 name = var_name(flags) static_var(name, flags) 301 if (name != "") 302 return "offsetof (struct gcc_options, x_" name ")" 303 if (opt_args("Mask", flags) != "") 304 return "offsetof (struct gcc_options, x_target_flags)" 305 if (opt_args("InverseMask", flags) != "") 306 return "offsetof (struct gcc_options, x_target_flags)" 307 return "(unsigned short) -1" 308} 309 310# Given the option called NAME return a sanitized version of its name. 311function opt_sanitized_name(name) 312{ 313 gsub ("[^" alnum "]", "_", name) 314 return name 315} 316 317# Given the option called NAME return the appropriate enum for it. 318function opt_enum(name) 319{ 320 return "OPT_" opt_sanitized_name(name) 321} 322 323# Given the language called NAME return a sanitized version of its name. 324function lang_sanitized_name(name) 325{ 326 gsub( "[^" alnum "_]", "X", name ) 327 return name 328} 329 330# Search for a valid var_name among all OPTS equal to option NAME. 331# If not found, return "". 332function search_var_name(name, opt_numbers, opts, flags, n_opts) 333{ 334 opt_var_name = var_name(flags[opt_numbers[name]]); 335 if (opt_var_name != "") { 336 return opt_var_name; 337 } 338 for (k = 0; k < n_opts; k++) { 339 if (opts[k] == name && var_name(flags[k]) != "") { 340 return var_name(flags[k]); 341 } 342 } 343 return "" 344} 345 346function integer_range_info(range_option, init, option) 347{ 348 if (range_option != "") { 349 start = nth_arg(0, range_option); 350 end = nth_arg(1, range_option); 351 if (init != "" && init != "-1" && (init < start || init > end)) 352 print "#error initial value " init " of '" option "' must be in range [" start "," end "]" 353 return start ", " end 354 } 355 else 356 return "-1, -1" 357} 358 359# Handle LangEnabledBy(ENABLED_BY_LANGS, ENABLEDBY_NAME, ENABLEDBY_POSARG, 360# ENABLEDBY_NEGARG). This function does not return anything. 361function lang_enabled_by(enabledby_langs, enabledby_name, enabledby_posarg, enabledby_negarg) 362{ 363 n_enabledby_arg_langs = split(enabledby_langs, enabledby_arg_langs, " "); 364 if (enabledby_posarg != "" && enabledby_negarg != "") { 365 with_args = "," enabledby_posarg "," enabledby_negarg 366 } else if (enabledby_posarg == "" && enabledby_negarg == "") { 367 with_args = "" 368 } else { 369 print "#error " opts[i] " LangEnabledBy("enabledby_langs","enabledby_name", " \ 370 enabledby_posarg", " enabledby_negargs \ 371 ") with three arguments, it should have either 2 or 4" 372 } 373 374 n_enabledby_array = split(enabledby_name, enabledby_array, " \\|\\| "); 375 for (k = 1; k <= n_enabledby_array; k++) { 376 enabledby_index = opt_numbers[enabledby_array[k]]; 377 if (enabledby_index == "") { 378 print "#error " opts[i] " LangEnabledBy("enabledby_langs","enabledby_name", " \ 379 enabledby_posarg", " enabledby_negargs"), unknown option '" enabledby_name "'" 380 } else { 381 for (j = 1; j <= n_enabledby_arg_langs; j++) { 382 lang_name = lang_sanitized_name(enabledby_arg_langs[j]); 383 lang_index = lang_numbers[enabledby_arg_langs[j]]; 384 if (enables[lang_name,enabledby_array[k]] == "") { 385 enabledby[lang_name,n_enabledby_lang[lang_index]] = enabledby_array[k]; 386 n_enabledby_lang[lang_index]++; 387 } 388 enables[lang_name,enabledby_array[k]] \ 389 = enables[lang_name,enabledby_array[k]] opts[i] with_args ";"; 390 } 391 } 392 } 393} 394