1# Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 2# Free Software Foundation, Inc. 3# Contributed by Kelley Cook, June 2004. 4# Original code from Neil Booth, May 2003. 5# 6# This program is free software; you can redistribute it and/or modify it 7# under the terms of the GNU General Public License as published by the 8# Free Software Foundation; either version 3, or (at your option) any 9# later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program; see the file COPYING3. If not see 18# <http://www.gnu.org/licenses/>. 19 20# This Awk script reads in the option records generated from 21# opt-gather.awk, combines the flags of duplicate options and generates a 22# C file. 23# 24 25# This program uses functions from opt-functions.awk and code from 26# opt-read.awk. 27# 28# Usage: awk -f opt-functions.awk -f opt-read.awk -f optc-gen.awk \ 29# [-v header_name=header.h] < inputfile > options.c 30 31# Dump that array of options into a C file. 32END { 33print "/* This file is auto-generated by optc-gen.awk. */" 34print "" 35n_headers = split(header_name, headers, " ") 36for (i = 1; i <= n_headers; i++) 37 print "#include " quote headers[i] quote 38print "#include " quote "opts.h" quote 39print "#include " quote "intl.h" quote 40print "#include " quote "insn-attr-common.h" quote 41print "" 42 43if (n_extra_c_includes > 0) { 44 for (i = 0; i < n_extra_c_includes; i++) { 45 print "#include " quote extra_c_includes[i] quote 46 } 47 print "" 48} 49 50for (i = 0; i < n_enums; i++) { 51 name = enum_names[i] 52 type = enum_type[name] 53 print "static const struct cl_enum_arg cl_enum_" name \ 54 "_data[] = " 55 print "{" 56 print enum_data[name] " { NULL, 0, 0 }" 57 print "};" 58 print "" 59 print "static void" 60 print "cl_enum_" name "_set (void *var, int value)" 61 print "{" 62 print " *((" type " *) var) = (" type ") value;" 63 print "}" 64 print "" 65 print "static int" 66 print "cl_enum_" name "_get (const void *var)" 67 print "{" 68 print " return (int) *((const " type " *) var);" 69 print "}" 70 print "" 71} 72 73print "const struct cl_enum cl_enums[] =" 74print "{" 75for (i = 0; i < n_enums; i++) { 76 name = enum_names[i] 77 ehelp = enum_help[name] 78 if (ehelp == "") 79 ehelp = "NULL" 80 else 81 ehelp = quote ehelp quote 82 unknown_error = enum_unknown_error[name] 83 if (unknown_error == "") 84 unknown_error = "NULL" 85 else 86 unknown_error = quote unknown_error quote 87 print " {" 88 print " " ehelp "," 89 print " " unknown_error "," 90 print " cl_enum_" name "_data," 91 print " sizeof (" enum_type[name] ")," 92 print " cl_enum_" name "_set," 93 print " cl_enum_" name "_get" 94 print " }," 95} 96print "};" 97print "const unsigned int cl_enums_count = " n_enums ";" 98print "" 99 100print "const struct gcc_options global_options_init =\n{" 101for (i = 0; i < n_extra_vars; i++) { 102 var = extra_vars[i] 103 init = extra_vars[i] 104 if (var ~ "=" ) { 105 sub(".*= *", "", init) 106 } else { 107 init = "0" 108 } 109 sub(" *=.*", "", var) 110 name = var 111 sub("^.*[ *]", "", name) 112 sub("\\[.*\\]$", "", name) 113 var_seen[name] = 1 114 print " " init ", /* " name " */" 115} 116for (i = 0; i < n_opts; i++) { 117 name = var_name(flags[i]); 118 if (name == "") 119 continue; 120 121 init = opt_args("Init", flags[i]) 122 if (init != "") { 123 if (name in var_init && var_init[name] != init) 124 print "#error multiple initializers for " name 125 var_init[name] = init 126 } 127} 128for (i = 0; i < n_opts; i++) { 129 name = var_name(flags[i]); 130 if (name == "") 131 continue; 132 133 if (name in var_seen) 134 continue; 135 136 if (name in var_init) 137 init = var_init[name] 138 else 139 init = "0" 140 141 print " " init ", /* " name " */" 142 143 var_seen[name] = 1; 144} 145for (i = 0; i < n_opts; i++) { 146 name = static_var(opts[i], flags[i]); 147 if (name != "") { 148 print " 0, /* " name " (private state) */" 149 print "#undef x_" name 150 } 151} 152for (i = 0; i < n_opts; i++) { 153 if (flag_set_p("SetByCombined", flags[i])) 154 print " false, /* frontend_set_" var_name(flags[i]) " */" 155} 156print "};" 157print "" 158print "struct gcc_options global_options;" 159print "struct gcc_options global_options_set;" 160print "" 161 162print "const char * const lang_names[] =\n{" 163for (i = 0; i < n_langs; i++) { 164 macros[i] = "CL_" langs[i] 165 gsub( "[^" alnum "_]", "X", macros[i] ) 166 s = substr(" ", length (macros[i])) 167 print " " quote langs[i] quote "," 168 } 169 170print " 0\n};\n" 171print "const unsigned int cl_options_count = N_OPTS;\n" 172print "#if (1U << " n_langs ") > CL_MIN_OPTION_CLASS" 173print " #error the number of languages exceeds the implementation limit" 174print "#endif" 175print "const unsigned int cl_lang_count = " n_langs ";\n" 176 177print "const struct cl_option cl_options[] =\n{" 178 179j = 0 180for (i = 0; i < n_opts; i++) { 181 back_chain[i] = "N_OPTS"; 182 indices[opts[i]] = j; 183 # Combine the flags of identical switches. Switches 184 # appear many times if they are handled by many front 185 # ends, for example. 186 while( i + 1 != n_opts && opts[i] == opts[i + 1] ) { 187 flags[i + 1] = flags[i] " " flags[i + 1]; 188 if (help[i + 1] == "") 189 help[i + 1] = help[i] 190 else if (help[i] != "" && help[i + 1] != help[i]) 191 print "warning: multiple different help strings for " \ 192 opts[i] ":\n\t" help[i] "\n\t" help[i + 1] \ 193 | "cat 1>&2" 194 i++; 195 back_chain[i] = "N_OPTS"; 196 indices[opts[i]] = j; 197 } 198 j++; 199} 200 201for (i = 0; i < n_opts; i++) { 202 # With identical flags, pick only the last one. The 203 # earlier loop ensured that it has all flags merged, 204 # and a nonempty help text if one of the texts was nonempty. 205 while( i + 1 != n_opts && opts[i] == opts[i + 1] ) { 206 i++; 207 } 208 209 len = length (opts[i]); 210 enum = opt_enum(opts[i]) 211 212 # If this switch takes joined arguments, back-chain all 213 # subsequent switches to it for which it is a prefix. If 214 # a later switch S is a longer prefix of a switch T, T 215 # will be back-chained to S in a later iteration of this 216 # for() loop, which is what we want. 217 if (flag_set_p("Joined.*", flags[i])) { 218 for (j = i + 1; j < n_opts; j++) { 219 if (substr (opts[j], 1, len) != opts[i]) 220 break; 221 back_chain[j] = enum; 222 } 223 } 224 225 s = substr(" ", length (opts[i])) 226 if (i + 1 == n_opts) 227 comma = "" 228 229 if (help[i] == "") 230 hlp = "0" 231 else 232 hlp = quote help[i] quote; 233 234 missing_arg_error = opt_args("MissingArgError", flags[i]) 235 if (missing_arg_error == "") 236 missing_arg_error = "0" 237 else 238 missing_arg_error = quote missing_arg_error quote 239 240 241 warn_message = opt_args("Warn", flags[i]) 242 if (warn_message == "") 243 warn_message = "0" 244 else 245 warn_message = quote warn_message quote 246 247 alias_arg = opt_args("Alias", flags[i]) 248 if (alias_arg == "") { 249 if (flag_set_p("Ignore", flags[i])) 250 alias_data = "NULL, NULL, OPT_SPECIAL_ignore" 251 else 252 alias_data = "NULL, NULL, N_OPTS" 253 } else { 254 alias_opt = nth_arg(0, alias_arg) 255 alias_posarg = nth_arg(1, alias_arg) 256 alias_negarg = nth_arg(2, alias_arg) 257 258 if (var_ref(opts[i], flags[i]) != "-1") 259 print "#error Alias setting variable" 260 261 if (alias_posarg != "" && alias_negarg == "") { 262 if (!flag_set_p("RejectNegative", flags[i]) \ 263 && opts[i] ~ "^[Wfm]") 264 print "#error Alias with single argument " \ 265 "allowing negative form" 266 } 267 if (alias_posarg != "" \ 268 && flag_set_p("NegativeAlias", flags[i])) { 269 print "#error Alias with multiple arguments " \ 270 "used with NegativeAlias" 271 } 272 273 alias_opt = opt_enum(alias_opt) 274 if (alias_posarg == "") 275 alias_posarg = "NULL" 276 else 277 alias_posarg = quote alias_posarg quote 278 if (alias_negarg == "") 279 alias_negarg = "NULL" 280 else 281 alias_negarg = quote alias_negarg quote 282 alias_data = alias_posarg ", " alias_negarg ", " alias_opt 283 } 284 285 neg = opt_args("Negative", flags[i]); 286 if (neg != "") 287 idx = indices[neg] 288 else { 289 if (flag_set_p("RejectNegative", flags[i])) 290 idx = -1; 291 else { 292 if (opts[i] ~ "^[Wfm]") 293 idx = indices[opts[i]]; 294 else 295 idx = -1; 296 } 297 } 298 # Split the printf after %u to work around an ia64-hp-hpux11.23 299 # awk bug. 300 printf(" { %c-%s%c,\n %s,\n %s,\n %s,\n %s, %s, %u,", 301 quote, opts[i], quote, hlp, missing_arg_error, warn_message, 302 alias_data, back_chain[i], len) 303 printf(" %d,\n", idx) 304 condition = opt_args("Condition", flags[i]) 305 cl_flags = switch_flags(flags[i]) 306 cl_bit_fields = switch_bit_fields(flags[i]) 307 cl_zero_bit_fields = switch_bit_fields("") 308 if (condition != "") 309 printf("#if %s\n" \ 310 " %s,\n" \ 311 " 0, %s,\n" \ 312 "#else\n" \ 313 " 0,\n" \ 314 " 1 /* Disabled. */, %s,\n" \ 315 "#endif\n", 316 condition, cl_flags, cl_bit_fields, cl_zero_bit_fields) 317 else 318 printf(" %s,\n" \ 319 " 0, %s,\n", 320 cl_flags, cl_bit_fields) 321 printf(" %s, %s }%s\n", var_ref(opts[i], flags[i]), 322 var_set(flags[i]), comma) 323} 324 325print "};" 326 327} 328