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