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