using System.Text;
using System.IO;
using System.Collections;
+using System.Collections.Generic;
using System.Resources;
using System.Reflection;
+using System.Xml;
class ResGen {
static Assembly swf;
static Type resxr;
static Type resxw;
+ static HashSet<string> symbols = new HashSet<string> ();
/*
* We load the ResX format stuff on demand, since the classes are in
}
static void Usage () {
-#if NET_2_0
- string Usage = @"Mono Resource Generator version 1.2 for the 2.0 profile
-Usage:
- resgen2 source.ext [dest.ext]
- resgen2 [options] /compile source.ext[,dest.resources] [...]";
-#else
- string Usage = @"Mono Resource Generator version 1.2 for the 1.0 profile
+
+ string Usage = @"Mono Resource Generator version " + Consts.MonoVersion +
+ @"
Usage:
resgen source.ext [dest.ext]
- resgen /compile source.ext[,dest.resources] [...]";
-#endif
+ resgen [options] /compile source.ext[,dest.resources] [...]";
Usage += @"
Convert a resource file from one format to another.
The currently supported formats are: '.txt' '.resources' '.resx' '.po'.
If the destination file is not specified, source.resources will be used.";
-#if NET_2_0
+
Usage += @"
Options:
output file name (if not set).
-usesourcepath, /useSourcePath
to resolve relative file paths, use the directory of the resource
- file as current directory.";
-#else
- Usage += @"
-The /compile option takes a list of .resX or .txt files to convert to
-.resources files in one bulk operation, replacing .ext with .resources for
-the output file name (if not set).";
-#endif
+ file as current directory.
+-define, /define:SYMBOL1,SYMBOL2
+ takes a comma-separated list of symbols that control conditional
+ inclusion of resources file. The source file needs to be in
+ the '.txt' format.
+
+ Resources enclosed with #ifdef SYMBOL1 ... #endif directives
+ will be included in the destination file when SYMBOL1 has
+ been specified using /define option.
+
+ Resources enclosed with #if ! SYMBOL2 ... #endif directives
+ will be included only if SYMBOL2 has NOT been specified.";
Usage += @"
";
Console.WriteLine( Usage );
return new PoResourceReader (stream);
case ".txt":
case ".text":
- return new TxtResourceReader (stream);
+ return new TxtResourceReader (stream, symbols);
case ".resources":
return new ResourceReader (stream);
case ".resx":
} catch (Exception e) {
Console.WriteLine ("Error: {0}", e.Message);
Exception inner = e.InnerException;
+
+ // under 2.0 ResXResourceReader can wrap an exception into an XmlException
+ // and this hides some helpful message from the original exception
+ XmlException xex = (inner as XmlException);
+ if (xex != null) {
+ // message is identical to the inner exception (from MWF ResXResourceReader)
+ Console.WriteLine ("Position: Line {0}, Column {1}.", xex.LineNumber, xex.LinePosition);
+ inner = inner.InnerException;
+ }
+
if (inner is TargetInvocationException && inner.InnerException != null)
inner = inner.InnerException;
if (inner != null)
}
compileMultiple = true;
break;
-#if NET_2_0
+
case "/usesourcepath":
case "-usesourcepath":
if (compileMultiple) {
}
useSourcePath = true;
break;
-#endif
+
default:
+ if (args [i].StartsWith ("/d:") ||
+ args [i].StartsWith ("-d:") ||
+ args [i].StartsWith ("/define:") ||
+ args [i].StartsWith ("-define:") ||
+ args [i].StartsWith ("/D:") ||
+ args [i].StartsWith ("-D:") ||
+ args [i].StartsWith ("/DEFINE:") ||
+ args [i].StartsWith ("-DEFINE:")) {
+
+ string defines = args [i].Substring (args [i].IndexOf (':') + 1);
+ foreach (string s in defines.Split (',') ) {
+ symbols.Add(s);
+ }
+ break;
+ }
+
if (!IsFileArgument (args [i])) {
Usage ();
return 1;
// check for Unix platforms - see FAQ for more details
// http://www.mono-project.com/FAQ:_Technical#How_to_detect_the_execution_platform_.3F
int platform = (int) Environment.OSVersion.Platform;
- return ((platform == 4) || (platform == 128));
+ return ((platform == 4) || (platform == 128) || (platform == 6));
}
}
class TxtResourceReader : IResourceReader {
Hashtable data;
Stream s;
+ HashSet <String> defines;
- public TxtResourceReader (Stream stream) {
+ public TxtResourceReader (Stream stream, IEnumerable<string> symbols) {
data = new Hashtable ();
s = stream;
+
+ defines = new HashSet<String> (symbols);
Load ();
}
public IDictionaryEnumerator GetEnumerator() {
return data.GetEnumerator ();
}
-
+
+ static string NextWord(ref string line) {
+ int i, j;
+ string keywd;
+ line = line.TrimStart ();
+ for (i = 0; i < line.Length && !Char.IsWhiteSpace (line [i]) && line [i] != ';'; i++ );
+
+ if (i < line.Length) {
+ for (j = i; j < line.Length && Char.IsWhiteSpace (line [j]) && line [j] != ';'; j++ );
+
+ keywd = line.Substring (0, i);
+ line = line.Substring (j).TrimStart ();
+ } else {
+ keywd = line;
+ line = "";
+ }
+ return keywd;
+ }
+
void Load () {
StreamReader reader = new StreamReader (s);
string line, key, val;
+ Stack<bool> conditional = new Stack<bool> (5);
int epos, line_num = 0;
+
+ conditional.Push(true);
while ((line = reader.ReadLine ()) != null) {
line_num++;
line = line.Trim ();
- if (line.Length == 0 || line [0] == '#' ||
- line [0] == ';')
+
+ if (line.Length == 0 || line [0] == ';')
continue;
+
+ if (line [0] == '#') {
+ bool stat;
+ bool neg = false;
+ string keywd, symbol;
+
+ line = line.Substring (1);
+ keywd = NextWord (ref line).ToLower ();
+ symbol = "";
+
+ if (line.Length > 0) {
+ if (line[0] == '!') {
+ line = line.Substring (1);
+ neg = true;
+ }
+ symbol = NextWord (ref line);
+ }
+
+ switch (keywd) {
+ case "endif":
+ case "else":
+ stat = conditional.Pop ();
+ if (conditional.Count < 1)
+ throw new Exception (String.Format ("Found an #{0} without matching #ifdef", keywd));
+
+ if (keywd == "else")
+ conditional.Push (conditional.Peek () && !stat);
+ break;
+
+ case "ifdef":
+ case "if":
+ if (symbol.Length == 0)
+ throw new Exception (String.Format ("Missing symbol after {0}", keywd));
+ stat = defines.Contains (symbol);
+ if (neg)
+ stat = !stat;
+
+ conditional.Push (conditional.Peek () && stat);
+ break;
+
+ }
+ continue;
+ }
+ if (conditional.Peek () == false)
+ continue;
+
epos = line.IndexOf ('=');
if (epos < 0)
throw new Exception ("Invalid format at line " + line_num);
data.Add (key, val);
}
+ if (conditional.Count > 1)
+ throw new Exception ("Found an #ifdef but not a matching #endif before reaching the end of the file.");
}
// \\n -> \n ...
case 't':
b.Append ('\t');
break;
-#if NET_2_0
case 'u':
int ch = int.Parse (value.Substring (++i, 4), NumberStyles.HexNumber);
b.Append (char.ConvertFromUtf32 (ch));
i += 3;
break;
-#endif
case '\\':
b.Append ('\\');
break;