Forgot this file
[mono.git] / mcs / monoresgen / monoresgen.cs
1 /*
2  * monoresgen: convert between the resource formats (.txt, .resources, .resx).
3  *
4  * Copyright (c) 2002 Ximian, Inc
5  *
6  * Author: Paolo Molaro (lupus@ximian.com)
7  */
8
9 /*
10  * TODO:
11  * * escape/unescape in the .txt reader/writer to be able to roundtrip values with newlines
12  *   (unlike the MS ResGen utility)
13  * * add .po format to help traslators on unixy systems
14  */
15
16 using System;
17 using System.IO;
18 using System.Collections;
19 using System.Resources;
20 using System.Reflection;
21
22 class ResGen {
23
24         static Assembly swf;
25         static Type resxr;
26         static Type resxw;
27
28         /*
29          * We load the ResX format stuff on demand, since the classes are in 
30          * System.Windows.Forms (!!!) and we can't depend on that assembly in mono, yet.
31          */
32         static void LoadResX () {
33                 if (swf != null)
34                         return;
35                 try {
36                         swf = Assembly.LoadWithPartialName ("System.Windows.Forms");
37                         resxr = swf.GetType ("System.Resources.ResXResourceReader");
38                         resxw = swf.GetType ("System.Resources.ResXResourceWriter");
39                 } catch (Exception e) {
40                         throw new Exception ("Cannot load support for ResX format: " + e.Message);
41                 }
42         }
43
44         static void Usage () {
45                 string Usage = @"Mono Resource Generator version 0.1
46 Usage:
47                 monoresgen source.ext [dest.ext]
48                 monoresgen /compile source.ext[,dest.resources] [...]
49
50 Convert a resource file from one format to another.
51 The currently supported formats are: '.txt' '.resources' '.resx'.
52 If the destination file is not specified, source.resources will be used.
53 The /compile option takes a list of .resX or .txt files to convert to
54 .resources files in one bulk operation, replacing .ext with .resources for
55 the output file name.
56 ";
57                 Console.WriteLine( Usage );
58         }
59         
60         static IResourceReader GetReader (Stream stream, string name) {
61                 string format = Path.GetExtension (name);
62                 switch (format.ToLower ()) {
63                 case ".txt":
64                 case ".text":
65                         return new TxtResourceReader (stream);
66                 case ".resources":
67                         return new ResourceReader (stream);
68                 case ".resx":
69                         LoadResX ();
70                         return (IResourceReader)Activator.CreateInstance (resxr, new object[] {stream});
71                 default:
72                         throw new Exception ("Unknown format in file " + name);
73                 }
74         }
75         
76         static IResourceWriter GetWriter (Stream stream, string name) {
77                 string format = Path.GetExtension (name);
78                 switch (format.ToLower ()) {
79                 case ".txt":
80                 case ".text":
81                         return new TxtResourceWriter (stream);
82                 case ".resources":
83                         return new ResourceWriter (stream);
84                 case ".resx":
85                         LoadResX ();
86                         return (IResourceWriter)Activator.CreateInstance (resxw, new object[] {stream});
87                 default:
88                         throw new Exception ("Unknown format in file " + name);
89                 }
90         }
91         
92         static int CompileResourceFile(string sname, string dname ) {
93                 try {
94                 FileStream source, dest;
95                 IResourceReader reader;
96                 IResourceWriter writer;
97
98                         source = new FileStream (sname, FileMode.Open, FileAccess.Read);
99                         dest = new FileStream (dname, FileMode.OpenOrCreate, FileAccess.Write);
100
101                         reader = GetReader (source, sname);
102                         writer = GetWriter (dest, dname);
103
104                         int rescount = 0;
105                         foreach (DictionaryEntry e in reader) {
106                                 rescount++;
107                                 object val = e.Value;
108                                 if (val is string)
109                                         writer.AddResource ((string)e.Key, (string)e.Value);
110                                 else
111                                         writer.AddResource ((string)e.Key, e.Value);
112                         }
113                         Console.WriteLine( "Read in {0} resources from '{1}'", rescount, sname );
114
115                         reader.Close ();
116                         writer.Close ();
117                         Console.WriteLine("Writing resource file...  Done.");
118                 } catch (Exception e) {
119                         Console.WriteLine ("Error: {0}", e.Message);
120                         return 1;
121                 }
122                 return 0;
123         }
124         
125         static int Main (string[] args) {
126                 string sname = "", dname = ""; 
127                 if ((int) args.Length < 1 || args[0] == "-h" || args[0] == "-?" || args[0] == "/h" || args[0] == "/?") {
128                           Usage();
129                           return 1;
130                 }               
131                 if (args[0] == "/compile" || args[0] == "-compile") {
132                         for ( int i=1; i< args.Length; i++ ) {                          
133                                 if ( args[i].IndexOf(",") != -1 ){
134                                         string[] pair =  args[i].Split(',');
135                                         sname = pair[0]; 
136                                         dname = pair[1];
137                                         if (dname == ""){
138                                                 Console.WriteLine(@"error: You must specify an input & outfile file name like this:");
139                                                 Console.WriteLine("inFile.txt,outFile.resources." );
140                                                 Console.WriteLine("You passed in '{0}'.", args[i] );
141                                                 return 1;
142                                         }
143                                 } else {
144                                         sname = args[i]; 
145                                         dname = Path.ChangeExtension (sname, "resources");
146                                 }
147                                 int ret = CompileResourceFile( sname, dname );
148                                 if (ret != 0 ) {
149                                         return ret;
150                                 }
151                         }
152                         return 0;
153                 
154                 }
155                 else if (args.Length == 1) {
156                         sname = args [0];
157                         dname = Path.ChangeExtension (sname, "resources");
158                 } else if (args.Length != 2) {
159                         Usage ();
160                         return 1;
161                 } else {
162                         sname = args [0];
163                         dname = args [1];                       
164                 }               
165                 return CompileResourceFile( sname, dname );
166         }
167 }
168
169 class TxtResourceWriter : IResourceWriter {
170         StreamWriter s;
171         
172         public TxtResourceWriter (Stream stream) {
173                 s = new StreamWriter (stream);
174         }
175         
176         public void AddResource (string name, byte[] value) {
177                 throw new Exception ("Binary data not valid in a text resource file");
178         }
179         
180         public void AddResource (string name, object value) {
181                 if (value is string) {
182                         AddResource (name, (string)value);
183                         return;
184                 }
185                 throw new Exception ("Objects not valid in a text resource file");
186         }
187         
188         /* FIXME: handle newlines */
189         public void AddResource (string name, string value) {
190                 s.WriteLine ("{0}={1}", name, value);
191         }
192         
193         public void Close () {
194                 s.Close ();
195         }
196         
197         public void Dispose () {}
198         
199         public void Generate () {}
200 }
201
202 class TxtResourceReader : IResourceReader {
203         Hashtable data;
204         Stream s;
205         
206         public TxtResourceReader (Stream stream) {
207                 data = new Hashtable ();
208                 s = stream;
209                 Load ();
210         }
211         
212         public virtual void Close () {
213         }
214         
215         public IDictionaryEnumerator GetEnumerator() {
216                 return data.GetEnumerator ();
217         }
218         
219         void Load () {
220                 StreamReader reader = new StreamReader (s);
221                 string line, key, val;
222                 int epos, line_num = 0;
223                 while ((line = reader.ReadLine ()) != null) {
224                         line_num++;
225                         line = line.Trim ();
226                         if (line.Length == 0 || line [0] == '#' ||
227                             line [0] == ';')
228                                 continue;
229                         epos = line.IndexOf ('=');
230                         if (epos < 0) 
231                                 throw new Exception ("Invalid format at line " + line_num);
232                         key = line.Substring (0, epos);
233                         val = line.Substring (epos + 1);
234                         key = key.Trim ();
235                         val = val.Trim ();
236                         if (key.Length == 0) 
237                                 throw new Exception ("Key is empty at line " + line_num);
238                         data.Add (key, val);
239                 }
240         }
241         
242         IEnumerator IEnumerable.GetEnumerator () {
243                 return ((IResourceReader) this).GetEnumerator();
244         }
245
246         void IDisposable.Dispose () {}
247 }
248