Updated Danish translation
[banshee.git] / build / DllMapVerifier.cs
blob9acccb68fb6c2b0d6baa76ba444f9c9a70de7986
1 using System;
2 using System.IO;
3 using System.Xml;
4 using System.Text;
5 using System.Collections.Generic;
7 public static class DllMapVerifier
9 private struct DllImportRef
11 public DllImportRef (string name, int line, int column)
13 Name = name;
14 Line = line;
15 Column = column;
18 public string Name;
19 public int Line;
20 public int Column;
23 private static Dictionary<string, List<DllImportRef>> dll_imports
24 = new Dictionary<string, List<DllImportRef>> ();
25 private static List<string> ignore_dlls = new List<string> ();
26 private static List<string> config_dlls = null;
28 public static int Main (string [] args)
30 LoadConfigDlls (args[0]);
31 foreach (string file in args) {
32 LoadDllImports (file);
35 return VerifyDllImports (args[0]) ? 0 : 1;
38 private static bool VerifyDllImports (string configFile)
40 int total_unmapped_count = 0;
42 foreach (KeyValuePair<string, List<DllImportRef>> dll_import in dll_imports) {
43 int file_unmapped_count = 0;
44 foreach (DllImportRef dll_import_ref in dll_import.Value) {
45 if (config_dlls != null && config_dlls.Contains (dll_import_ref.Name)) {
46 continue;
49 if (file_unmapped_count++ == 0) {
50 Console.Error.WriteLine ("Unmapped DLLs in file: {0}", dll_import.Key);
53 Console.Error.WriteLine (" + {0} : {1},{2}", dll_import_ref.Name,
54 dll_import_ref.Line, dll_import_ref.Column);
57 total_unmapped_count += file_unmapped_count;
60 if (total_unmapped_count > 0) {
61 Console.Error.WriteLine ();
62 Console.Error.WriteLine (" If any DllImport above is explicitly allowed to be unmapped,");
63 Console.Error.WriteLine (" add an 'willfully unmapped' comment to the inside of the attribute:");
64 Console.Error.WriteLine ();
65 Console.Error.WriteLine (" [DllImport (\"libX11.so.6\") /* willfully unmapped */]");
66 Console.Error.WriteLine ();
69 if (total_unmapped_count > 0 && config_dlls == null) {
70 Console.Error.WriteLine ("No config file for DLL mapping was found ({0})", configFile);
73 return total_unmapped_count == 0;
76 private static void LoadDllImports (string csFile)
78 if (csFile.StartsWith ("-i")) {
79 ignore_dlls.Add (csFile.Substring (2));
80 return;
83 if (Path.GetExtension (csFile) == ".cs" && File.Exists (csFile)) {
84 List<DllImportRef> dll_import_refs = null;
86 foreach (DllImportRef dll_import in ParseFileForDllImports (csFile)) {
87 if (ignore_dlls.Contains (dll_import.Name)) {
88 continue;
91 if (dll_import_refs == null) {
92 dll_import_refs = new List<DllImportRef> ();
95 dll_import_refs.Add (dll_import);
98 if (dll_import_refs != null) {
99 dll_imports.Add (csFile, dll_import_refs);
104 private static void LoadConfigDlls (string configFile)
106 try {
107 XmlTextReader config = new XmlTextReader (configFile);
108 config_dlls = new List<string> ();
109 while (config.Read ()) {
110 if (config.NodeType == XmlNodeType.Element &&
111 config.Name == "dllmap") {
112 string dll = config.GetAttribute ("dll");
113 if (!config_dlls.Contains (dll)) {
114 config_dlls.Add (dll);
118 } catch {
122 #region DllImport parser
124 private static StreamReader reader;
125 private static int reader_line;
126 private static int reader_col;
128 private static IEnumerable<DllImportRef> ParseFileForDllImports (string file)
130 reader_line = 1;
131 reader_col = 1;
133 using (reader = new StreamReader (file)) {
134 char c;
135 bool in_paren = false;
136 bool in_attr = false;
137 bool in_dll_attr = false;
138 bool in_string = false;
139 bool in_comment = false;
140 int dll_line = 1, dll_col = 1;
141 string dll_string = null;
142 string dll_comment = null;
144 while ((c = (char)reader.Peek ()) != Char.MaxValue) {
145 switch (c) {
146 case ' ':
147 case '\t': Read (); break;
148 case '[':
149 in_attr = true;
150 dll_string = null;
151 dll_comment = null;
152 dll_line = reader_line;
153 dll_col = reader_col;
154 Read ();
155 break;
156 case '(': Read (); in_paren = true; break;
157 case ')': Read (); in_paren = false; break;
158 case '"':
159 Read ();
160 if (dll_string == null && in_dll_attr && in_paren && !in_string) {
161 in_string = true;
163 break;
164 case '/':
165 Read ();
166 if ((char)reader.Peek () == '*') {
167 Read ();
168 if (in_dll_attr && !in_comment) {
169 in_comment = true;
172 break;
173 case ']':
174 if (in_dll_attr && dll_string != null && dll_comment != "willfully unmapped") {
175 yield return new DllImportRef (dll_string, dll_line, dll_col);
177 in_attr = false;
178 in_dll_attr = false;
179 Read ();
180 break;
181 default:
182 if (!in_dll_attr && in_attr && ReadDllAttribute ()) {
183 in_dll_attr = true;
184 } else if (in_dll_attr && in_string) {
185 dll_string = ReadDllString ();
186 in_string = false;
187 } else if (in_dll_attr && in_comment) {
188 dll_comment = ReadDllComment ();
189 in_comment = false;
190 } else {
191 Read ();
193 break;
199 private static bool ReadDllAttribute ()
201 return
202 Read () == 'D' &&
203 Read () == 'l' &&
204 Read () == 'l' &&
205 Read () == 'I' &&
206 Read () == 'm' &&
207 Read () == 'p' &&
208 Read () == 'o' &&
209 Read () == 'r' &&
210 Read () == 't';
213 private static string ReadDllString ()
215 StringBuilder builder = new StringBuilder (32);
216 while (true) {
217 char c = Read ();
218 if (Char.IsLetterOrDigit (c) || c == '.' || c == '-' || c == '_') {
219 builder.Append (c);
220 } else {
221 break;
224 return builder.ToString ();
227 private static string ReadDllComment ()
229 StringBuilder builder = new StringBuilder ();
230 char lc = Char.MaxValue;
231 while (true) {
232 char c = Read ();
233 if (c == Char.MaxValue || (c == '/' && lc == '*')) {
234 break;
235 } else if (lc != Char.MaxValue) {
236 builder.Append (lc);
238 lc = c;
240 return builder.ToString ().Trim ();
243 private static char Read ()
245 char c = (char)reader.Read ();
246 if (c == '\n') {
247 reader_line++;
248 reader_col = 1;
249 } else {
250 reader_col++;
252 return c;
255 #endregion