2003-02-07 Patrik Torstensson
[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                 Console.WriteLine ("Mono Resource Generator version 0.1");
46                 Console.WriteLine ("Usage:");
47                 Console.WriteLine ("\tmonoresgen source.ext [dest.ext]");
48                 Console.WriteLine ();
49                 Console.WriteLine ("Convert a resource file from one format to another.");
50                 Console.WriteLine ("The currently supported formats are: '.txt' '.resources' '.resx'.");
51                 Console.WriteLine ("If the destination file is not specified, source.resources will be used.");
52         }
53         
54         static IResourceReader GetReader (Stream stream, string name) {
55                 string format = Path.GetExtension (name);
56                 switch (format.ToLower ()) {
57                 case ".txt":
58                 case ".text":
59                         return new TxtResourceReader (stream);
60                 case ".resources":
61                         return new ResourceReader (stream);
62                 case ".resx":
63                         LoadResX ();
64                         return (IResourceReader)Activator.CreateInstance (resxr, new object[] {stream});
65                 default:
66                         throw new Exception ("Unknown format in file " + name);
67                 }
68         }
69         
70         static IResourceWriter GetWriter (Stream stream, string name) {
71                 string format = Path.GetExtension (name);
72                 switch (format.ToLower ()) {
73                 case ".txt":
74                 case ".text":
75                         return new TxtResourceWriter (stream);
76                 case ".resources":
77                         return new ResourceWriter (stream);
78                 case ".resx":
79                         LoadResX ();
80                         return (IResourceWriter)Activator.CreateInstance (resxw, new object[] {stream});
81                 default:
82                         throw new Exception ("Unknown format in file " + name);
83                 }
84         }
85         
86         static int Main (string[] args) {
87                 FileStream source, dest;
88                 string sname, dname;
89                 IResourceReader reader;
90                 IResourceWriter writer;
91
92                 if (args.Length == 1) {
93                         sname = args [0];
94                         dname = Path.ChangeExtension (sname, "resources");
95                 } else if (args.Length != 2) {
96                         Usage ();
97                         return 1;
98                 } else {
99                         sname = args [0];
100                         dname = args [1];
101                 }
102
103                 try {
104                         source = new FileStream (sname, FileMode.Open, FileAccess.Read);
105                         dest = new FileStream (dname, FileMode.OpenOrCreate, FileAccess.Write);
106
107                         reader = GetReader (source, sname);
108                         writer = GetWriter (dest, dname);
109
110                         foreach (DictionaryEntry e in reader) {
111                                 object val = e.Value;
112                                 if (val is string)
113                                         writer.AddResource ((string)e.Key, (string)e.Value);
114                                 else
115                                         writer.AddResource ((string)e.Key, e.Value);
116                         }
117
118                         reader.Close ();
119                         writer.Close ();
120                 } catch (Exception e) {
121                         Console.WriteLine ("Error: {0}", e.Message);
122                         return 1;
123                 }
124                 return 0;
125         }
126 }
127
128 class TxtResourceWriter : IResourceWriter {
129         StreamWriter s;
130         
131         public TxtResourceWriter (Stream stream) {
132                 s = new StreamWriter (stream);
133         }
134         
135         public void AddResource (string name, byte[] value) {
136                 throw new Exception ("Binary data not valid in a text resource file");
137         }
138         
139         public void AddResource (string name, object value) {
140                 if (value is string) {
141                         AddResource (name, (string)value);
142                         return;
143                 }
144                 throw new Exception ("Objects not valid in a text resource file");
145         }
146         
147         /* FIXME: handle newlines */
148         public void AddResource (string name, string value) {
149                 s.WriteLine ("{0}={1}", name, value);
150         }
151         
152         public void Close () {
153                 s.Close ();
154         }
155         
156         public void Dispose () {}
157         
158         public void Generate () {}
159 }
160
161 class TxtResourceReader : IResourceReader {
162         Hashtable data;
163         Stream s;
164         
165         public TxtResourceReader (Stream stream) {
166                 data = new Hashtable ();
167                 s = stream;
168                 Load ();
169         }
170         
171         public virtual void Close () {
172         }
173         
174         public IDictionaryEnumerator GetEnumerator() {
175                 return data.GetEnumerator ();
176         }
177         
178         void Load () {
179                 StreamReader reader = new StreamReader (s);
180                 string line, key, val;
181                 int epos, line_num = 0;
182                 while ((line = reader.ReadLine ()) != null) {
183                         line_num++;
184                         line = line.Trim ();
185                         if (line.Length == 0 || line [0] == '#' ||
186                             line [0] == ';')
187                                 continue;
188                         epos = line.IndexOf ('=');
189                         if (epos < 0) 
190                                 throw new Exception ("Invalid format at line " + line_num);
191                         key = line.Substring (0, epos);
192                         val = line.Substring (epos + 1);
193                         key = key.Trim ();
194                         val = val.Trim ();
195                         if (key.Length == 0) 
196                                 throw new Exception ("Key is empty at line " + line_num);
197                         data.Add (key, val);
198                 }
199         }
200         
201         IEnumerator IEnumerable.GetEnumerator () {
202                 return ((IResourceReader) this).GetEnumerator();
203         }
204
205         void IDisposable.Dispose () {}
206 }
207