1# Copyright (C) 2003-2015 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# This Awk script reads in the option records generated from 20# opt-gather.awk, combines the flags of duplicate options and generates a 21# C file. 22# 23 24# This program uses functions from opt-functions.awk and code from 25# opt-read.awk. 26# 27# Usage: awk -f opt-functions.awk -f opt-read.awk -f optc-gen.awk \ 28# [-v header_name=header.h] < inputfile > options.c 29 30# Dump that array of options into a C file. 31END { 32 33# Record first EnabledBy and LangEnabledBy uses. 34n_enabledby = 0; 35for (i = 0; i < n_langs; i++) { 36 n_enabledby_lang[i] = 0; 37} 38for (i = 0; i < n_opts; i++) { 39 enabledby_arg = opt_args("EnabledBy", flags[i]); 40 if (enabledby_arg != "") { 41 logical_and = index(enabledby_arg, " && "); 42 if (logical_and != 0) { 43 # EnabledBy(arg1 && arg2) 44 split_sep = " && "; 45 } else { 46 # EnabledBy(arg) or EnabledBy(arg1 || arg2 || arg3) 47 split_sep = " \\|\\| "; 48 } 49 n_enabledby_names = split(enabledby_arg, enabledby_names, split_sep); 50 if (logical_and != 0 && n_enabledby_names > 2) { 51 print "#error EnabledBy (Wfoo && Wbar && Wbaz) not currently supported" 52 } 53 for (j = 1; j <= n_enabledby_names; j++) { 54 enabledby_name = enabledby_names[j]; 55 enabledby_index = opt_numbers[enabledby_name]; 56 if (enabledby_index == "") { 57 print "#error Enabledby: " enabledby_name 58 } else { 59 condition = ""; 60 if (logical_and != 0) { 61 opt_var_name_1 = search_var_name(enabledby_names[1], opt_numbers, opts, flags, n_opts); 62 opt_var_name_2 = search_var_name(enabledby_names[2], opt_numbers, opts, flags, n_opts); 63 if (opt_var_name_1 == "") { 64 print "#error " enabledby_names[1] " does not have a Var() flag" 65 } 66 if (opt_var_name_2 == "") { 67 print "#error " enabledby_names[2] " does not have a Var() flag" 68 } 69 condition = "opts->x_" opt_var_name_1 " && opts->x_" opt_var_name_2; 70 } 71 if (enables[enabledby_name] == "") { 72 enabledby[n_enabledby] = enabledby_name; 73 n_enabledby++; 74 } 75 enables[enabledby_name] = enables[enabledby_name] opts[i] ";"; 76 enablesif[enabledby_name] = enablesif[enabledby_name] condition ";"; 77 } 78 } 79 } 80 81 enabledby_arg = opt_args("LangEnabledBy", flags[i]); 82 if (enabledby_arg != "") { 83 enabledby_langs = nth_arg(0, enabledby_arg); 84 enabledby_name = nth_arg(1, enabledby_arg); 85 enabledby_posarg = nth_arg(2, enabledby_arg); 86 enabledby_negarg = nth_arg(3, enabledby_arg); 87 lang_enabled_by(enabledby_langs, enabledby_name, enabledby_posarg, enabledby_negarg); 88 } 89} 90 91 92print "/* This file is auto-generated by optc-gen.awk. */" 93print "" 94n_headers = split(header_name, headers, " ") 95for (i = 1; i <= n_headers; i++) 96 print "#include " quote headers[i] quote 97print "#include " quote "opts.h" quote 98print "#include " quote "intl.h" quote 99print "#include " quote "insn-attr-common.h" quote 100print "" 101 102if (n_extra_c_includes > 0) { 103 for (i = 0; i < n_extra_c_includes; i++) { 104 print "#include " quote extra_c_includes[i] quote 105 } 106 print "" 107} 108 109for (i = 0; i < n_enums; i++) { 110 name = enum_names[i] 111 type = enum_type[name] 112 print "static const struct cl_enum_arg cl_enum_" name \ 113 "_data[] = " 114 print "{" 115 print enum_data[name] " { NULL, 0, 0 }" 116 print "};" 117 print "" 118 print "static void" 119 print "cl_enum_" name "_set (void *var, int value)" 120 print "{" 121 print " *((" type " *) var) = (" type ") value;" 122 print "}" 123 print "" 124 print "static int" 125 print "cl_enum_" name "_get (const void *var)" 126 print "{" 127 print " return (int) *((const " type " *) var);" 128 print "}" 129 print "" 130} 131 132print "const struct cl_enum cl_enums[] =" 133print "{" 134for (i = 0; i < n_enums; i++) { 135 name = enum_names[i] 136 ehelp = enum_help[name] 137 if (ehelp == "") 138 ehelp = "NULL" 139 else 140 ehelp = quote ehelp quote 141 unknown_error = enum_unknown_error[name] 142 if (unknown_error == "") 143 unknown_error = "NULL" 144 else 145 unknown_error = quote unknown_error quote 146 print " {" 147 print " " ehelp "," 148 print " " unknown_error "," 149 print " cl_enum_" name "_data," 150 print " sizeof (" enum_type[name] ")," 151 print " cl_enum_" name "_set," 152 print " cl_enum_" name "_get" 153 print " }," 154} 155print "};" 156print "const unsigned int cl_enums_count = " n_enums ";" 157print "" 158 159print "const struct gcc_options global_options_init =\n{" 160for (i = 0; i < n_extra_vars; i++) { 161 var = extra_vars[i] 162 init = extra_vars[i] 163 if (var ~ "=" ) { 164 sub(".*= *", "", init) 165 } else { 166 init = "0" 167 } 168 sub(" *=.*", "", var) 169 name = var 170 sub("^.*[ *]", "", name) 171 sub("\\[.*\\]$", "", name) 172 var_seen[name] = 1 173 print " " init ", /* " name " */" 174} 175for (i = 0; i < n_opts; i++) { 176 name = var_name(flags[i]); 177 if (name == "") 178 continue; 179 180 init = opt_args("Init", flags[i]) 181 if (init != "") { 182 if (name in var_init && var_init[name] != init) 183 print "#error multiple initializers for " name 184 var_init[name] = init 185 } 186} 187for (i = 0; i < n_opts; i++) { 188 name = var_name(flags[i]); 189 if (name == "") 190 continue; 191 192 if (name in var_seen) 193 continue; 194 195 if (name in var_init) 196 init = var_init[name] 197 else 198 init = "0" 199 200 print " " init ", /* " name " */" 201 202 var_seen[name] = 1; 203} 204for (i = 0; i < n_opts; i++) { 205 name = static_var(opts[i], flags[i]); 206 if (name != "") { 207 print " 0, /* " name " (private state) */" 208 print "#undef x_" name 209 } 210} 211for (i = 0; i < n_opts; i++) { 212 if (flag_set_p("SetByCombined", flags[i])) 213 print " false, /* frontend_set_" var_name(flags[i]) " */" 214} 215print "};" 216print "" 217print "struct gcc_options global_options;" 218print "struct gcc_options global_options_set;" 219print "" 220 221print "const char * const lang_names[] =\n{" 222for (i = 0; i < n_langs; i++) { 223 macros[i] = "CL_" lang_sanitized_name(langs[i]) 224 s = substr(" ", length (macros[i])) 225 print " " quote langs[i] quote "," 226 } 227 228print " 0\n};\n" 229print "const unsigned int cl_options_count = N_OPTS;\n" 230print "#if (1U << " n_langs ") > CL_MIN_OPTION_CLASS" 231print " #error the number of languages exceeds the implementation limit" 232print "#endif" 233print "const unsigned int cl_lang_count = " n_langs ";\n" 234 235print "const struct cl_option cl_options[] =\n{" 236 237j = 0 238for (i = 0; i < n_opts; i++) { 239 back_chain[i] = "N_OPTS"; 240 indices[opts[i]] = j; 241 # Combine the flags of identical switches. Switches 242 # appear many times if they are handled by many front 243 # ends, for example. 244 while( i + 1 != n_opts && opts[i] == opts[i + 1] ) { 245 flags[i + 1] = flags[i] " " flags[i + 1]; 246 if (help[i + 1] == "") 247 help[i + 1] = help[i] 248 else if (help[i] != "" && help[i + 1] != help[i]) 249 print "#error Multiple different help strings for " \ 250 opts[i] ":\n\t" help[i] "\n\t" help[i + 1] 251 252 i++; 253 back_chain[i] = "N_OPTS"; 254 indices[opts[i]] = j; 255 } 256 j++; 257} 258 259for (i = 0; i < n_opts; i++) { 260 # With identical flags, pick only the last one. The 261 # earlier loop ensured that it has all flags merged, 262 # and a nonempty help text if one of the texts was nonempty. 263 while( i + 1 != n_opts && opts[i] == opts[i + 1] ) { 264 i++; 265 } 266 267 len = length (opts[i]); 268 enum = opt_enum(opts[i]) 269 270 # If this switch takes joined arguments, back-chain all 271 # subsequent switches to it for which it is a prefix. If 272 # a later switch S is a longer prefix of a switch T, T 273 # will be back-chained to S in a later iteration of this 274 # for() loop, which is what we want. 275 if (flag_set_p("Joined.*", flags[i])) { 276 for (j = i + 1; j < n_opts; j++) { 277 if (substr (opts[j], 1, len) != opts[i]) 278 break; 279 back_chain[j] = enum; 280 } 281 } 282 283 s = substr(" ", length (opts[i])) 284 if (i + 1 == n_opts) 285 comma = "" 286 287 if (help[i] == "") 288 hlp = "0" 289 else 290 hlp = quote help[i] quote; 291 292 missing_arg_error = opt_args("MissingArgError", flags[i]) 293 if (missing_arg_error == "") 294 missing_arg_error = "0" 295 else 296 missing_arg_error = quote missing_arg_error quote 297 298 299 warn_message = opt_args("Warn", flags[i]) 300 if (warn_message == "") 301 warn_message = "0" 302 else 303 warn_message = quote warn_message quote 304 305 alias_arg = opt_args("Alias", flags[i]) 306 if (alias_arg == "") { 307 if (flag_set_p("Ignore", flags[i])) 308 alias_data = "NULL, NULL, OPT_SPECIAL_ignore" 309 else 310 alias_data = "NULL, NULL, N_OPTS" 311 } else { 312 alias_opt = nth_arg(0, alias_arg) 313 alias_posarg = nth_arg(1, alias_arg) 314 alias_negarg = nth_arg(2, alias_arg) 315 316 if (var_ref(opts[i], flags[i]) != "-1") 317 print "#error Alias setting variable" 318 319 if (alias_posarg != "" && alias_negarg == "") { 320 if (!flag_set_p("RejectNegative", flags[i]) \ 321 && opts[i] ~ "^[Wfm]") 322 print "#error Alias with single argument " \ 323 "allowing negative form" 324 } 325 if (alias_posarg != "" \ 326 && flag_set_p("NegativeAlias", flags[i])) { 327 print "#error Alias with multiple arguments " \ 328 "used with NegativeAlias" 329 } 330 331 alias_opt = opt_enum(alias_opt) 332 if (alias_posarg == "") 333 alias_posarg = "NULL" 334 else 335 alias_posarg = quote alias_posarg quote 336 if (alias_negarg == "") 337 alias_negarg = "NULL" 338 else 339 alias_negarg = quote alias_negarg quote 340 alias_data = alias_posarg ", " alias_negarg ", " alias_opt 341 } 342 343 neg = opt_args("Negative", flags[i]); 344 if (neg != "") 345 idx = indices[neg] 346 else { 347 if (flag_set_p("RejectNegative", flags[i])) 348 idx = -1; 349 else { 350 if (opts[i] ~ "^[Wfm]") 351 idx = indices[opts[i]]; 352 else 353 idx = -1; 354 } 355 } 356 # Split the printf after %u to work around an ia64-hp-hpux11.23 357 # awk bug. 358 printf(" { %c-%s%c,\n %s,\n %s,\n %s,\n %s, %s, %u,", 359 quote, opts[i], quote, hlp, missing_arg_error, warn_message, 360 alias_data, back_chain[i], len) 361 printf(" %d,\n", idx) 362 condition = opt_args("Condition", flags[i]) 363 cl_flags = switch_flags(flags[i]) 364 cl_bit_fields = switch_bit_fields(flags[i]) 365 cl_zero_bit_fields = switch_bit_fields("") 366 if (condition != "") 367 printf("#if %s\n" \ 368 " %s,\n" \ 369 " 0, %s,\n" \ 370 "#else\n" \ 371 " 0,\n" \ 372 " 1 /* Disabled. */, %s,\n" \ 373 "#endif\n", 374 condition, cl_flags, cl_bit_fields, cl_zero_bit_fields) 375 else 376 printf(" %s,\n" \ 377 " 0, %s,\n", 378 cl_flags, cl_bit_fields) 379 printf(" %s, %s }%s\n", var_ref(opts[i], flags[i]), 380 var_set(flags[i]), comma) 381} 382 383print "};" 384 385print "\n\n" 386print "bool " 387print "common_handle_option_auto (struct gcc_options *opts, " 388print " struct gcc_options *opts_set, " 389print " const struct cl_decoded_option *decoded, " 390print " unsigned int lang_mask, int kind, " 391print " location_t loc, " 392print " const struct cl_option_handlers *handlers, " 393print " diagnostic_context *dc) " 394print "{ " 395print " size_t scode = decoded->opt_index; " 396print " int value = decoded->value; " 397print " enum opt_code code = (enum opt_code) scode; " 398print " " 399print " gcc_assert (decoded->canonical_option_num_elements <= 2); " 400print " " 401print " switch (code) " 402print " { " 403# Handle EnabledBy 404for (i = 0; i < n_enabledby; i++) { 405 enabledby_name = enabledby[i]; 406 print " case " opt_enum(enabledby_name) ":" 407 n_enables = split(enables[enabledby_name], thisenable, ";"); 408 n_enablesif = split(enablesif[enabledby_name], thisenableif, ";"); 409 if (n_enables != n_enablesif) { 410 print "#error n_enables != n_enablesif: Something went wrong!" 411 } 412 for (j = 1; j < n_enables; j++) { 413 opt_var_name = var_name(flags[opt_numbers[thisenable[j]]]); 414 if (opt_var_name != "") { 415 condition = "!opts_set->x_" opt_var_name 416 if (thisenableif[j] != "") { 417 value = "(" thisenableif[j] ")" 418 } else { 419 value = "value" 420 } 421 print " if (" condition ")" 422 print " handle_generated_option (opts, opts_set," 423 print " " opt_enum(thisenable[j]) ", NULL, " value "," 424 print " lang_mask, kind, loc, handlers, dc);" 425 } else { 426 print "#error " thisenable[j] " does not have a Var() flag" 427 } 428 } 429 print " break;\n" 430} 431print " default: " 432print " break; " 433print " } " 434print " return true; " 435print "} " 436 437# Handle LangEnabledBy 438for (i = 0; i < n_langs; i++) { 439 lang_name = lang_sanitized_name(langs[i]); 440 mark_unused = " ATTRIBUTE_UNUSED"; 441 442 print "\n\n" 443 print "bool " 444 print lang_name "_handle_option_auto (struct gcc_options *opts" mark_unused ", " 445 print " struct gcc_options *opts_set" mark_unused ", " 446 print " size_t scode" mark_unused ", const char *arg" mark_unused ", int value" mark_unused ", " 447 print " unsigned int lang_mask" mark_unused ", int kind" mark_unused ", " 448 print " location_t loc" mark_unused ", " 449 print " const struct cl_option_handlers *handlers" mark_unused ", " 450 print " diagnostic_context *dc" mark_unused ") " 451 print "{ " 452 print " enum opt_code code = (enum opt_code) scode; " 453 print " " 454 print " switch (code) " 455 print " { " 456 457 for (k = 0; k < n_enabledby_lang[i]; k++) { 458 enabledby_name = enabledby[lang_name,k]; 459 print " case " opt_enum(enabledby_name) ":" 460 n_thisenable = split(enables[lang_name,enabledby_name], thisenable, ";"); 461 for (j = 1; j < n_thisenable; j++) { 462 n_thisenable_args = split(thisenable[j], thisenable_args, ","); 463 if (n_thisenable_args == 1) { 464 thisenable_opt = thisenable[j]; 465 value = "value"; 466 } else { 467 thisenable_opt = thisenable_args[1]; 468 with_posarg = thisenable_args[2]; 469 with_negarg = thisenable_args[3]; 470 value = "value ? " with_posarg " : " with_negarg; 471 } 472 opt_var_name = var_name(flags[opt_numbers[thisenable_opt]]); 473 if (opt_var_name != "") { 474 print " if (!opts_set->x_" opt_var_name ")" 475 print " handle_generated_option (opts, opts_set," 476 print " " opt_enum(thisenable_opt) ", NULL, " value "," 477 print " lang_mask, kind, loc, handlers, dc);" 478 } else { 479 print "#error " thisenable_opt " does not have a Var() flag" 480 } 481 } 482 print " break;\n" 483 } 484 print " default: " 485 print " break; " 486 print " } " 487 print " return true; " 488 print "} " 489} 490 491#Handle CPP() 492print "\n" 493print "#include " quote "cpplib.h" quote; 494print "void" 495print "cpp_handle_option_auto (const struct gcc_options * opts, " 496print " size_t scode, struct cpp_options * cpp_opts)" 497print "{ " 498print " enum opt_code code = (enum opt_code) scode; " 499print " " 500print " switch (code) " 501print " { " 502for (i = 0; i < n_opts; i++) { 503 # With identical flags, pick only the last one. The 504 # earlier loop ensured that it has all flags merged, 505 # and a nonempty help text if one of the texts was nonempty. 506 while( i + 1 != n_opts && opts[i] == opts[i + 1] ) { 507 i++; 508 } 509 510 cpp_option = nth_arg(0, opt_args("CPP", flags[i])); 511 if (cpp_option != "") { 512 opt_var_name = var_name(flags[i]); 513 init = opt_args("Init", flags[i]) 514 if (opt_var_name != "" && init != "") { 515 print " case " opt_enum(opts[i]) ":" 516 print " cpp_opts->" cpp_option " = opts->x_" opt_var_name ";" 517 print " break;" 518 } else if (opt_var_name == "" && init == "") { 519 print "#error CPP() requires setting Init() and Var() for " opts[i] 520 } else if (opt_var_name != "") { 521 print "#error CPP() requires setting Init() for " opts[i] 522 } else { 523 print "#error CPP() requires setting Var() for " opts[i] 524 } 525 } 526} 527print " default: " 528print " break; " 529print " } " 530print "}\n" 531print "void" 532print "init_global_opts_from_cpp(struct gcc_options * opts, " 533print " const struct cpp_options * cpp_opts)" 534print "{ " 535for (i = 0; i < n_opts; i++) { 536 # With identical flags, pick only the last one. The 537 # earlier loop ensured that it has all flags merged, 538 # and a nonempty help text if one of the texts was nonempty. 539 while( i + 1 != n_opts && opts[i] == opts[i + 1] ) { 540 i++; 541 } 542 cpp_option = nth_arg(0, opt_args("CPP", flags[i])); 543 opt_var_name = var_name(flags[i]); 544 if (cpp_option != "" && opt_var_name != "") { 545 print " opts->x_" opt_var_name " = cpp_opts->" cpp_option ";" 546 } 547} 548print "} " 549 550} 551 552