change run to use meson/ninja and then exec. - remove libvala code from application...
[roobuilder] / src / ccode / valaccodefile.vala
1 /* valaccodefile.vala
2  *
3  * Copyright (C) 2009-2011  Jürg Billeter
4  *
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.
9
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.
14
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
18  *
19  * Author:
20  *      Jürg Billeter <j@bitron.ch>
21  */
22
23
24 public class Vala.CCodeFile {
25         public CCodeFileType file_type { get; private set; }
26
27         public weak SourceFile? file { get; private set; }
28
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 ();
42
43         public CCodeFile (CCodeFileType type = CCodeFileType.SOURCE, SourceFile? source_file = null) {
44                 file = source_file;
45                 file_type = type;
46         }
47
48         public bool add_declaration (string name) {
49                 if (name in declarations) {
50                         return true;
51                 }
52                 declarations.add (name);
53                 return false;
54         }
55
56         public void add_comment (CCodeComment comment) {
57                 comments.append (comment);
58         }
59
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);
64                 }
65         }
66
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);
71                 }
72         }
73
74         public void add_define (CCodeNode node) {
75                 define_directives.append (node);
76         }
77
78         public void add_type_declaration (CCodeNode node) {
79                 type_declaration.append (node);
80         }
81
82         public void add_type_definition (CCodeNode node) {
83                 type_definition.append (node);
84         }
85
86         public void add_type_member_declaration (CCodeNode node) {
87                 type_member_declaration.append (node);
88         }
89
90         public void add_constant_declaration (CCodeNode node) {
91                 constant_declaration.append (node);
92         }
93
94         public void add_type_member_definition (CCodeNode node) {
95                 type_member_definition.append (node);
96         }
97
98         public void add_function_declaration (CCodeFunction func) {
99                 declarations.add (func.name);
100
101                 var decl = func.copy ();
102                 decl.is_declaration = true;
103                 type_member_declaration.append (decl);
104         }
105
106         public void add_function (CCodeFunction func) {
107                 if (!definitions.add (func.name)) {
108                         Report.error (null, "internal: Redefinition of `%s'", func.name);
109                         return;
110                 }
111
112                 type_member_definition.append (func);
113         }
114
115         public List<string> get_symbols () {
116                 var symbols = new ArrayList<string> (str_equal);
117                 get_symbols_from_fragment (symbols, type_member_declaration);
118                 return symbols;
119         }
120
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);
125                         } else {
126                                 var func = node as CCodeFunction;
127                                 if (func != null) {
128                                         symbols.add (func.name);
129                                 }
130                         }
131                 }
132         }
133
134         static string get_define_for_filename (string filename) {
135                 var define = new StringBuilder ("__");
136
137                 var i = filename;
138                 while (i.length > 0) {
139                         var c = i.get_char ();
140                         if (c.isalnum  () && c < 0x80) {
141                                 define.append_unichar (c.toupper ());
142                         } else {
143                                 define.append_c ('_');
144                         }
145
146                         i = i.next_char ();
147                 }
148
149                 define.append ("__");
150
151                 return define.str;
152         }
153
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)) {
157                         return false;
158                 }
159
160                 if (file_type == CCodeFileType.SOURCE) {
161                         writer.line_directives = line_directives;
162
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 ();
183                 } else {
184                         writer.write_newline ();
185
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 ());
190
191                         if (begin_decls != null) {
192                                 once.append (new CCodeIdentifier (begin_decls));
193                                 once.append (new CCodeNewline ());
194                         }
195
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 ());
207
208                         if (end_decls != null) {
209                                 once.append (new CCodeIdentifier (end_decls));
210                                 once.append (new CCodeNewline ());
211                         }
212
213                         once.append (new CCodeNewline ());
214                         once.write (writer);
215                 }
216
217                 writer.close ();
218
219                 return true;
220         }
221 }
222
223 [Flags]
224 public enum CCodeFileType {
225         SOURCE,
226         PUBLIC_HEADER,
227         INTERNAL_HEADER,
228         HEADER = PUBLIC_HEADER | INTERNAL_HEADER
229 }