glib-2.0: Add missing return of Queue.remove*() and add HashTable.foreach_steal()
[vala-gnome.git] / vapigen / valavapigen.vala
blob9fe8ea6f003a13b67dfb8a6236b024b06be1bc5c
1 /* valavapigen.vala
3 * Copyright (C) 2006-2010 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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 class Vala.VAPIGen {
26 static string directory;
27 static bool version;
28 static bool quiet_mode;
29 static bool disable_warnings;
30 [CCode (array_length = false, array_null_terminated = true)]
31 static string[] sources;
32 [CCode (array_length = false, array_null_terminated = true)]
33 static string[] vapi_directories;
34 [CCode (array_length = false, array_null_terminated = true)]
35 static string[] gir_directories;
36 [CCode (array_length = false, array_null_terminated = true)]
37 static string[] metadata_directories;
38 static string library;
39 [CCode (array_length = false, array_null_terminated = true)]
40 static string[] packages;
41 static bool nostdpkg;
43 CodeContext context;
45 const OptionEntry[] options = {
46 { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." },
47 { "girdir", 0, 0, OptionArg.FILENAME_ARRAY, ref gir_directories, "Look for GIR bindings in DIRECTORY", "DIRECTORY..." },
48 { "metadatadir", 0, 0, OptionArg.FILENAME_ARRAY, ref metadata_directories, "Look for GIR .metadata files in DIRECTORY", "DIRECTORY..." },
49 { "nostdpkg", 0, 0, OptionArg.NONE, ref nostdpkg, "Do not include standard packages", null },
50 { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." },
51 { "library", 0, 0, OptionArg.STRING, ref library, "Library name", "NAME" },
52 { "directory", 'd', 0, OptionArg.FILENAME, ref directory, "Output directory", "DIRECTORY" },
53 { "disable-warnings", 0, 0, OptionArg.NONE, ref disable_warnings, "Disable warnings", null },
54 { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null },
55 { "quiet", 'q', 0, OptionArg.NONE, ref quiet_mode, "Do not print messages to the console", null },
56 { OPTION_REMAINING, 0, 0, OptionArg.FILENAME_ARRAY, ref sources, null, "FILE..." },
57 { null }
60 private int quit () {
61 if (context.report.get_errors () == 0) {
62 if (!quiet_mode) {
63 stdout.printf ("Generation succeeded - %d warning(s)\n", context.report.get_warnings ());
65 return 0;
66 } else {
67 if (!quiet_mode) {
68 stdout.printf ("Generation failed: %d error(s), %d warning(s)\n", context.report.get_errors (), context.report.get_warnings ());
70 return 1;
74 private int run () {
75 context = new CodeContext ();
76 context.profile = Profile.GOBJECT;
77 context.vapi_directories = vapi_directories;
78 context.gir_directories = gir_directories;
79 context.metadata_directories = metadata_directories;
80 context.report.enable_warnings = !disable_warnings;
81 context.report.set_verbose_errors (!quiet_mode);
82 CodeContext.push (context);
83 context.nostdpkg = nostdpkg;
85 if (!nostdpkg) {
86 /* default package */
87 context.add_external_package ("glib-2.0");
88 context.add_external_package ("gobject-2.0");
91 if (context.report.get_errors () > 0) {
92 return quit ();
95 /* load packages from .deps file */
96 foreach (string source in sources) {
97 if (!source.has_suffix (".gi")) {
98 continue;
101 var depsfile = source.substring (0, source.length - "gi".length) + "deps";
102 context.add_packages_from_file (depsfile);
105 if (context.report.get_errors () > 0) {
106 return quit ();
109 // depsfile for gir case
110 if (library != null) {
111 var depsfile = library + ".deps";
112 context.add_packages_from_file (depsfile);
113 } else {
114 Report.error (null, "--library option must be specified");
117 if (context.report.get_errors () > 0) {
118 return quit ();
121 if (packages != null) {
122 foreach (string package in packages) {
123 context.add_external_package (package);
125 packages = null;
128 if (context.report.get_errors () > 0) {
129 return quit ();
132 foreach (string source in sources) {
133 if (FileUtils.test (source, FileTest.EXISTS)) {
134 var source_file = new SourceFile (context, SourceFileType.PACKAGE, source);
135 source_file.explicit = true;
136 context.add_source_file (source_file);
137 } else {
138 Report.error (null, "%s not found".printf (source));
142 if (context.report.get_errors () > 0) {
143 return quit ();
146 var parser = new Parser ();
147 parser.parse (context);
149 if (context.report.get_errors () > 0) {
150 return quit ();
153 var girparser = new GirParser ();
154 girparser.parse (context);
156 if (context.report.get_errors () > 0) {
157 return quit ();
160 var gidlparser = new GIdlParser ();
161 gidlparser.parse (context);
163 if (context.report.get_errors () > 0) {
164 return quit ();
167 context.check ();
169 if (context.report.get_errors () > 0) {
170 return quit ();
173 // interface writer ignores external packages
174 foreach (SourceFile file in context.get_source_files ()) {
175 if (file.filename.has_suffix (".vapi")) {
176 continue;
178 if (file.filename in sources) {
179 file.file_type = SourceFileType.SOURCE;
180 if (file.filename.has_suffix (".gir")) {
181 // mark relative metadata as source
182 string? metadata_filename = context.get_metadata_path (file.filename);
183 if (metadata_filename != null) {
184 foreach (SourceFile metadata_file in context.get_source_files ()) {
185 if (metadata_file.filename == metadata_filename) {
186 metadata_file.file_type = SourceFileType.SOURCE;
194 var interface_writer = new CodeWriter (CodeWriterType.VAPIGEN);
195 var vapi_filename = "%s.vapi".printf (library);
196 if (directory != null) {
197 vapi_filename = Path.build_path ("/", directory, vapi_filename);
200 interface_writer.write_file (context, vapi_filename);
202 library = null;
204 return quit ();
207 static int main (string[] args) {
208 Intl.setlocale (LocaleCategory.ALL, "");
209 try {
210 var opt_context = new OptionContext ("- Vala API Generator");
211 opt_context.set_help_enabled (true);
212 opt_context.add_main_entries (options, null);
213 opt_context.parse (ref args);
214 } catch (OptionError e) {
215 stdout.printf ("%s\n", e.message);
216 stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]);
217 return 1;
220 if (version) {
221 stdout.printf ("Vala API Generator %s\n", Vala.BUILD_VERSION);
222 return 0;
225 if (sources == null) {
226 stderr.printf ("No source file specified.\n");
227 return 1;
230 var vapigen = new VAPIGen ();
231 return vapigen.run ();