1# Copyright (C) 2003-2022 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# If FLAGS contains a "NAME(...argument...)" flag, return the value 76# of the argument. Print error message otherwise. 77function 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 85# Return the number of comma-separated element of S. 86function n_args(s) 87{ 88 n = 1 89 while (s ~ ",") { 90 n++ 91 sub("[^,]*, *", "", s) 92 } 93 return n 94} 95 96# Return the Nth comma-separated element of S. Return the empty string 97# if S does not contain N elements. 98function 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. 110function switch_flags (flags) 111{ 112 result = "0" 113 for (j = 0; j < n_langs; j++) { 114 regex = langs[j] 115 gsub ( "\\+", "\\+", regex ) 116 result = result test_flag(regex, flags, " | " macros[j]) 117 } 118 result = result \ 119 test_flag("Common", flags, " | CL_COMMON") \ 120 test_flag("Target", flags, " | CL_TARGET") \ 121 test_flag("PchIgnore", flags, " | CL_PCH_IGNORE") \ 122 test_flag("Driver", flags, " | CL_DRIVER") \ 123 test_flag("Joined", flags, " | CL_JOINED") \ 124 test_flag("JoinedOrMissing", flags, " | CL_JOINED") \ 125 test_flag("Separate", flags, " | CL_SEPARATE") \ 126 test_flag("Undocumented", flags, " | CL_UNDOCUMENTED") \ 127 test_flag("NoDWARFRecord", flags, " | CL_NO_DWARF_RECORD") \ 128 test_flag("Warning", flags, " | CL_WARNING") \ 129 test_flag("(Optimization|PerFunction)", flags, " | CL_OPTIMIZATION") \ 130 test_flag("Param", flags, " | CL_PARAMS") 131 sub( "^0 \\| ", "", result ) 132 return result 133} 134 135# Return bit-field initializers for option flags FLAGS. 136function switch_bit_fields (flags) 137{ 138 uinteger_flag = "" 139 vn = var_name(flags); 140 if (host_wide_int[vn] == "yes") 141 hwi = "Host_Wide_Int" 142 else if (flag_set_p("Host_Wide_Int", flags)) { 143 hwi = "Host_Wide_Int" 144 uinteger_flag = flag_init("UInteger", flags) 145 } 146 else 147 hwi = "" 148 result = "" 149 sep_args = opt_args("Args", flags) 150 if (sep_args == "") 151 sep_args = 0 152 else 153 sep_args-- 154 result = result sep_args ", " 155 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. 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) \ 177 uinteger_flag \ 178 hwi_flag \ 179 flag_init("ToLower", flags) \ 180 byte_size_flag 181 182 if (flag_set_p("Report", flags)) 183 print "#error Report option property is dropped" 184 185 sub(", $", "", result) 186 return result 187} 188 189# If FLAGS includes a Var flag, return the name of the variable it specifies. 190# Return the empty string otherwise. 191function var_name(flags) 192{ 193 return nth_arg(0, opt_args("Var", flags)) 194} 195 196# Return the name of the variable if FLAGS has a HOST_WIDE_INT variable. 197# Return the empty string otherwise. 198function 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 207# Return true if the option described by FLAGS has a globally-visible state. 208function 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. 217function needs_state_p(flags) 218{ 219 return (flag_set_p("Target", flags) \ 220 && !flag_set_p("Alias.*", flags) \ 221 && !flag_set_p("Ignore", flags)) 222} 223 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. 227function static_var(name, flags) 228{ 229 if (global_state_p(flags) || !needs_state_p(flags)) 230 return "" 231 gsub ("[^" alnum "]", "_", name) 232 return "VAR_" name 233} 234 235# Return the type of variable that should be associated with the given flags. 236function var_type(flags) 237{ 238 if (flag_set_p("Defer", flags)) 239 return "void *" 240 else if (flag_set_p("Enum.*", flags)) { 241 en = opt_args("Enum", flags); 242 return enum_type[en] " " 243 } 244 else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) 245 return "int " 246 else if (flag_set_p("Host_Wide_Int", flags)) 247 return "HOST_WIDE_INT " 248 else if (flag_set_p("UInteger", flags)) 249 return "int " 250 else 251 return "const char *" 252} 253 254# Return the type of variable that should be associated with the given flags 255# for use within a structure. Simple variables are changed to signed char 256# type instead of int to save space. 257function var_type_struct(flags) 258{ 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 } 266 else if (flag_set_p("Enum.*", flags)) { 267 en = opt_args("Enum", flags); 268 return enum_type[en] " " 269 } 270 else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) { 271 if (flag_set_p(".*Mask.*", flags)) { 272 if (host_wide_int[var_name(flags)] == "yes") 273 return "HOST_WIDE_INT " 274 else 275 return "/* - */ int " 276 } 277 else 278 return "signed char " 279 } 280 else 281 return "const char *" 282} 283 284# Given that an option has flags FLAGS, return an initializer for the 285# "var_enum", "var_type" and "var_value" fields of its cl_options[] entry. 286function var_set(flags) 287{ 288 if (flag_set_p("Defer", flags)) 289 return "0, CLVC_DEFER, 0" 290 s = nth_arg(1, opt_args("Var", flags)) 291 if (s != "") 292 return "0, CLVC_EQUAL, " s 293 s = opt_args("Mask", flags); 294 if (s != "") { 295 vn = var_name(flags); 296 if (vn) 297 return "0, CLVC_BIT_SET, OPTION_MASK_" s 298 else 299 return "0, CLVC_BIT_SET, MASK_" s 300 } 301 s = nth_arg(0, opt_args("InverseMask", flags)); 302 if (s != "") { 303 vn = var_name(flags); 304 if (vn) 305 return "0, CLVC_BIT_CLEAR, OPTION_MASK_" s 306 else 307 return "0, CLVC_BIT_CLEAR, MASK_" s 308 } 309 if (flag_set_p("Enum.*", flags)) { 310 en = opt_args("Enum", flags); 311 if (flag_set_p("EnumSet", flags)) 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" 315 else 316 return enum_index[en] ", CLVC_ENUM, CLEV_NORMAL" 317 } 318 if (var_type(flags) == "const char *") 319 return "0, CLVC_STRING, 0" 320 if (flag_set_p("ByteSize", flags)) 321 return "0, CLVC_SIZE, 0" 322 return "0, CLVC_INTEGER, 0" 323} 324 325# Given that an option called NAME has flags FLAGS, return an initializer 326# for the "flag_var" field of its cl_options[] entry. 327function var_ref(name, flags) 328{ 329 name = var_name(flags) static_var(name, flags) 330 if (name != "") 331 return "offsetof (struct gcc_options, x_" name ")" 332 if (opt_args("Mask", flags) != "") 333 return "offsetof (struct gcc_options, x_target_flags)" 334 if (opt_args("InverseMask", flags) != "") 335 return "offsetof (struct gcc_options, x_target_flags)" 336 return "(unsigned short) -1" 337} 338 339# Given the option called NAME return a sanitized version of its name. 340function opt_sanitized_name(name) 341{ 342 gsub ("[^" alnum "]", "_", name) 343 return name 344} 345 346# Given the option called NAME return the appropriate enum for it. 347function opt_enum(name) 348{ 349 return "OPT_" opt_sanitized_name(name) 350} 351 352# Given the language called NAME return a sanitized version of its name. 353function lang_sanitized_name(name) 354{ 355 gsub( "[^" alnum "_]", "X", name ) 356 return name 357} 358 359# Search for a valid var_name among all OPTS equal to option NAME. 360# If not found, return "". 361function 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} 374 375function integer_range_info(range_option, init, option, uinteger_used) 376{ 377 if (range_option != "") { 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)) 382 print "#error initial value " init " of '" option "' must be in range [" start "," end "]" 383 if (uinteger_used && start < 0) 384 print "#error '" option"': negative IntegerRange (" start ", " end ") cannot be combined with UInteger" 385 return start ", " end 386 } 387 else 388 return "-1, -1" 389} 390