1169689Skan#  Copyright (C) 2003,2004,2005,2006 Free Software Foundation, Inc.
2169689Skan#  Contributed by Kelley Cook, June 2004.
3169689Skan#  Original code from Neil Booth, May 2003.
4169689Skan#
5169689Skan# This program is free software; you can redistribute it and/or modify it
6169689Skan# under the terms of the GNU General Public License as published by the
7169689Skan# Free Software Foundation; either version 2, or (at your option) any
8169689Skan# later version.
9169689Skan# 
10169689Skan# This program is distributed in the hope that it will be useful,
11169689Skan# but WITHOUT ANY WARRANTY; without even the implied warranty of
12169689Skan# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13169689Skan# GNU General Public License for more details.
14169689Skan# 
15169689Skan# You should have received a copy of the GNU General Public License
16169689Skan# along with this program; if not, write to the Free Software
17169689Skan# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18169689Skan
19169689Skan# This Awk script reads in the option records generated from 
20169689Skan# opt-gather.awk, combines the flags of duplicate options and generates a
21169689Skan# C header file.
22169689Skan#
23169689Skan# This program uses functions from opt-functions.awk
24169689Skan# Usage: awk -f opt-functions.awk -f opth-gen.awk < inputfile > options.h
25169689Skan
26169689SkanBEGIN {
27169689Skan	n_opts = 0
28169689Skan	n_langs = 0
29169689Skan	n_extra_masks = 0
30169689Skan	quote = "\042"
31169689Skan	comma = ","
32169689Skan	FS=SUBSEP
33169689Skan}
34169689Skan
35169689Skan# Collect the text and flags of each option into an array
36169689Skan	{
37169689Skan		if ($1 == "Language") {
38169689Skan			langs[n_langs] = $2
39169689Skan			n_langs++;
40169689Skan		}
41169689Skan		else {
42169689Skan			name = opt_args("Mask", $1)
43169689Skan			if (name == "") {
44169689Skan				opts[n_opts]  = $1
45169689Skan				flags[n_opts] = $2
46169689Skan				help[n_opts]  = $3
47169689Skan				n_opts++;
48169689Skan			}
49169689Skan			else {
50169689Skan				extra_masks[n_extra_masks++] = name
51169689Skan			}
52169689Skan		}
53169689Skan	}
54169689Skan
55169689Skan# Dump out an enumeration into a .h file.
56169689Skan# Combine the flags of duplicate options.
57169689SkanEND {
58169689Skanprint "/* This file is auto-generated by opts.sh.  */"
59169689Skanprint ""
60169689Skanprint "#ifndef OPTIONS_H"
61169689Skanprint "#define OPTIONS_H"
62169689Skanprint ""
63169689Skanprint "extern int target_flags;"
64169689Skanprint ""
65169689Skan
66169689Skanfor (i = 0; i < n_opts; i++) {
67169689Skan	name = var_name(flags[i]);
68169689Skan	if (name == "")
69169689Skan		continue;
70169689Skan
71169689Skan	print "extern " var_type(flags[i]) name ";"
72169689Skan}
73169689Skanprint ""
74169689Skan
75169689Skanfor (i = 0; i < n_opts; i++) {
76169689Skan	name = opt_args("Mask", flags[i])
77169689Skan	vname = var_name(flags[i])
78169689Skan	mask = "MASK_"
79169689Skan	if (vname != "") {
80169689Skan		mask = "OPTION_MASK_"
81169689Skan	}
82169689Skan	if (name != "" && !flag_set_p("MaskExists", flags[i]))
83169689Skan		print "#define " mask name " (1 << " masknum[vname]++ ")"
84169689Skan}
85169689Skanfor (i = 0; i < n_extra_masks; i++) {
86169689Skan	print "#define MASK_" extra_masks[i] " (1 << " masknum[""]++ ")"
87169689Skan}
88169689Skan
89169689Skanfor (var in masknum) {
90255185Sjmg	if (masknum[var] > 32) {
91169689Skan		if (var == "")
92169689Skan			print "#error too many target masks"
93169689Skan		else
94169689Skan			print "#error too many masks for " var
95169689Skan	}
96169689Skan}
97169689Skanprint ""
98169689Skan
99169689Skanfor (i = 0; i < n_opts; i++) {
100169689Skan	name = opt_args("Mask", flags[i])
101169689Skan	vname = var_name(flags[i])
102169689Skan	macro = "OPTION_"
103169689Skan	mask = "OPTION_MASK_"
104169689Skan	if (vname == "") {
105169689Skan		vname = "target_flags"
106169689Skan		macro = "TARGET_"
107169689Skan		mask = "MASK_"
108169689Skan	}
109169689Skan	if (name != "" && !flag_set_p("MaskExists", flags[i]))
110169689Skan		print "#define " macro name \
111169689Skan		      " ((" vname " & " mask name ") != 0)"
112169689Skan}
113169689Skanfor (i = 0; i < n_extra_masks; i++) {
114169689Skan	print "#define TARGET_" extra_masks[i] \
115169689Skan	      " ((target_flags & MASK_" extra_masks[i] ") != 0)"
116169689Skan}
117169689Skanprint ""
118169689Skan
119169689Skanfor (i = 0; i < n_opts; i++) {
120169689Skan	opt = opt_args("InverseMask", flags[i])
121169689Skan	if (opt ~ ",") {
122169689Skan		vname = var_name(flags[i])
123169689Skan		macro = "OPTION_"
124169689Skan		mask = "OPTION_MASK_"
125169689Skan		if (vname == "") {
126169689Skan			vname = "target_flags"
127169689Skan			macro = "TARGET_"
128169689Skan			mask = "MASK_"
129169689Skan		}
130169689Skan		print "#define " macro nth_arg(1, opt) \
131169689Skan		      " ((" vname " & " mask nth_arg(0, opt) ") == 0)"
132169689Skan	}
133169689Skan}
134169689Skanprint ""
135169689Skan
136169689Skanfor (i = 0; i < n_langs; i++) {
137169689Skan	macros[i] = "CL_" langs[i]
138169689Skan	gsub( "[^A-Za-z0-9_]", "X", macros[i] )
139169689Skan	s = substr("            ", length (macros[i]))
140169689Skan	print "#define " macros[i] s " (1 << " i ")"
141169689Skan    }
142169689Skan
143169689Skanprint ""
144169689Skanprint "enum opt_code"
145169689Skanprint "{"
146169689Skan	
147169689Skanfor (i = 0; i < n_opts; i++)
148169689Skan	back_chain[i] = "N_OPTS";
149169689Skan
150169689Skanfor (i = 0; i < n_opts; i++) {
151169689Skan	# Combine the flags of identical switches.  Switches
152169689Skan	# appear many times if they are handled by many front
153169689Skan	# ends, for example.
154169689Skan	while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
155169689Skan		flags[i + 1] = flags[i] " " flags[i + 1];
156169689Skan		i++;
157169689Skan	}
158169689Skan
159169689Skan	len = length (opts[i]);
160169689Skan	enum = "OPT_" opts[i]
161169689Skan	if (opts[i] == "finline-limit=")
162169689Skan		enum = enum "eq"
163169689Skan	gsub ("[^A-Za-z0-9]", "_", enum)
164169689Skan
165169689Skan	# If this switch takes joined arguments, back-chain all
166169689Skan	# subsequent switches to it for which it is a prefix.  If
167169689Skan	# a later switch S is a longer prefix of a switch T, T
168169689Skan	# will be back-chained to S in a later iteration of this
169169689Skan	# for() loop, which is what we want.
170169689Skan	if (flag_set_p("Joined.*", flags[i])) {
171169689Skan		for (j = i + 1; j < n_opts; j++) {
172169689Skan			if (substr (opts[j], 1, len) != opts[i])
173169689Skan				break;
174169689Skan			back_chain[j] = enum;
175169689Skan		}
176169689Skan	}
177169689Skan
178169689Skan	s = substr("                                     ", length (opts[i]))
179169689Skan	if (i + 1 == n_opts)
180169689Skan		comma = ""
181169689Skan
182169689Skan	if (help[i] == "")
183169689Skan		hlp = "0"
184169689Skan	else
185169689Skan		hlp = "N_(\"" help[i] "\")";
186169689Skan
187169689Skan	print "  " enum "," s "/* -" opts[i] " */"
188169689Skan}
189169689Skan
190169689Skanprint "  N_OPTS"
191169689Skanprint "};"
192169689Skanprint ""
193169689Skanprint "#endif /* OPTIONS_H */"
194169689Skan}
195