3 * Copyright (C) 2009-2011 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library 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 GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
24 public class Vala.CCodeFile {
25 public CCodeFileType file_type { get; private set; }
27 public weak SourceFile? file { get; private set; }
29 Set<string> features = new HashSet<string> (str_hash, str_equal);
30 Set<string> declarations = new HashSet<string> (str_hash, str_equal);
31 Set<string> definitions = new HashSet<string> (str_hash, str_equal);
32 Set<string> includes = new HashSet<string> (str_hash, str_equal);
33 CCodeFragment comments = new CCodeFragment ();
34 CCodeFragment feature_test_macros = new CCodeFragment ();
35 CCodeFragment define_directives = new CCodeFragment ();
36 CCodeFragment include_directives = new CCodeFragment ();
37 CCodeFragment type_declaration = new CCodeFragment ();
38 CCodeFragment type_definition = new CCodeFragment ();
39 CCodeFragment type_member_declaration = new CCodeFragment ();
40 CCodeFragment constant_declaration = new CCodeFragment ();
41 CCodeFragment type_member_definition = new CCodeFragment ();
43 public CCodeFile (CCodeFileType type = CCodeFileType.SOURCE, SourceFile? source_file = null) {
48 public bool add_declaration (string name) {
49 if (name in declarations) {
52 declarations.add (name);
56 public void add_comment (CCodeComment comment) {
57 comments.append (comment);
60 public void add_feature_test_macro (string feature_test_macro) {
61 if (!(feature_test_macro in features)) {
62 feature_test_macros.append (new CCodeDefine (feature_test_macro));
63 features.add (feature_test_macro);
67 public void add_include (string filename, bool local = false) {
68 if (!(filename in includes)) {
69 include_directives.append (new CCodeIncludeDirective (filename, local));
70 includes.add (filename);
74 public void add_define (CCodeNode node) {
75 define_directives.append (node);
78 public void add_type_declaration (CCodeNode node) {
79 type_declaration.append (node);
82 public void add_type_definition (CCodeNode node) {
83 type_definition.append (node);
86 public void add_type_member_declaration (CCodeNode node) {
87 type_member_declaration.append (node);
90 public void add_constant_declaration (CCodeNode node) {
91 constant_declaration.append (node);
94 public void add_type_member_definition (CCodeNode node) {
95 type_member_definition.append (node);
98 public void add_function_declaration (CCodeFunction func) {
99 declarations.add (func.name);
101 var decl = func.copy ();
102 decl.is_declaration = true;
103 type_member_declaration.append (decl);
106 public void add_function (CCodeFunction func) {
107 if (!definitions.add (func.name)) {
108 Report.error (null, "internal: Redefinition of `%s'", func.name);
112 type_member_definition.append (func);
115 public List<string> get_symbols () {
116 var symbols = new ArrayList<string> (str_equal);
117 get_symbols_from_fragment (symbols, type_member_declaration);
121 void get_symbols_from_fragment (List<string> symbols, CCodeFragment fragment) {
122 foreach (CCodeNode node in fragment.get_children ()) {
123 if (node is CCodeFragment) {
124 get_symbols_from_fragment (symbols, (CCodeFragment) node);
126 var func = node as CCodeFunction;
128 symbols.add (func.name);
134 static string get_define_for_filename (string filename) {
135 var define = new StringBuilder ("__");
138 while (i.length > 0) {
139 var c = i.get_char ();
140 if (c.isalnum () && c < 0x80) {
141 define.append_unichar (c.toupper ());
143 define.append_c ('_');
149 define.append ("__");
154 public bool store (string filename, string? source_filename, bool write_version, bool line_directives, string? begin_decls = null, string? end_decls = null) {
155 var writer = new CCodeWriter (filename, source_filename);
156 if (!writer.open (write_version)) {
160 if (file_type == CCodeFileType.SOURCE) {
161 writer.line_directives = line_directives;
163 comments.write (writer);
164 writer.write_newline ();
165 feature_test_macros.write (writer);
166 writer.write_newline ();
167 include_directives.write (writer);
168 writer.write_newline ();
169 define_directives.write (writer);
170 writer.write_newline ();
171 type_declaration.write_combined (writer);
172 writer.write_newline ();
173 type_definition.write_combined (writer);
174 writer.write_newline ();
175 type_member_declaration.write_declaration (writer);
176 writer.write_newline ();
177 type_member_declaration.write (writer);
178 writer.write_newline ();
179 constant_declaration.write_combined (writer);
180 writer.write_newline ();
181 type_member_definition.write (writer);
182 writer.write_newline ();
184 writer.write_newline ();
186 var once = new CCodeOnceSection (get_define_for_filename (writer.filename));
187 once.append (new CCodeNewline ());
188 once.append (include_directives);
189 once.append (new CCodeNewline ());
191 if (begin_decls != null) {
192 once.append (new CCodeIdentifier (begin_decls));
193 once.append (new CCodeNewline ());
196 once.append (new CCodeNewline ());
197 once.append (define_directives);
198 once.append (new CCodeNewline ());
199 once.append (type_declaration);
200 once.append (new CCodeNewline ());
201 once.append (type_definition);
202 once.append (new CCodeNewline ());
203 once.append (type_member_declaration);
204 once.append (new CCodeNewline ());
205 once.append (constant_declaration);
206 once.append (new CCodeNewline ());
208 if (end_decls != null) {
209 once.append (new CCodeIdentifier (end_decls));
210 once.append (new CCodeNewline ());
213 once.append (new CCodeNewline ());
224 public enum CCodeFileType {
228 HEADER = PUBLIC_HEADER | INTERNAL_HEADER