2 // It is not used to provide our collation tailoring sources, but generates
3 // easy-to-read summary of LDML tailorings for ASCII-based developers (us).
5 // The actual tailoring source is mono-tailoring-source.txt.
9 using System.Collections;
11 using System.Globalization;
13 using Commons.Xml.Relaxng;
15 namespace Mono.Globalization.Unicode
21 public readonly int Level;
22 public readonly string Value;
24 public Mapping (int level, string value)
31 public class TailoringComparer : IComparer
33 public static TailoringComparer Instance =
34 new TailoringComparer ();
36 public int Compare (object o1, object o2)
38 Tailoring t1 = (Tailoring) o1;
39 Tailoring t2 = (Tailoring) o2;
40 return String.CompareOrdinal (t1.TargetString, t2.TargetString);
46 public readonly int Before;
49 ArrayList tailored = new ArrayList ();
51 public Tailoring (string value, int before)
57 public string TargetString {
58 get { return targetString; }
61 public IList Tailored {
62 get { return tailored; }
66 public void Contraction (int level, string value, string additional)
68 targetString += additional;
69 tailored.Add (new Mapping (level, value));
72 // <p> <s> <t> <q> <i>
73 public void Add (int level, string value)
75 tailored.Add (new Mapping (level, value));
78 // <pc> <sc> <tc> <qc> <ic>
79 public void AddRange (int level, string value)
81 foreach (char c in value)
82 tailored.Add (new Mapping (level, new string (c, 1)));
85 public void Serialize (TextWriter w)
87 w.Write (" // Target: '{0}' {{", TargetString);
88 foreach (char c in TargetString)
89 w.Write ("{0:X04},", (int) c);
90 w.WriteLine ("}} {0}",
91 TargetString.Length > 1 ? "!" : "");
93 w.WriteLine (" // Before: {0}", Before);
94 foreach (Mapping m in tailored) {
95 w.Write (" // {0}:'{1}' {{", m.Level, m.Value);
96 foreach (char c in m.Value)
97 w.Write ("{0:X04},", (int) c);
103 public class TailoringStoreComparer : IComparer
105 public static TailoringStoreComparer Instance =
106 new TailoringStoreComparer ();
108 public int Compare (object o1, object o2)
110 TailoringStore t1 = (TailoringStore) o1;
111 TailoringStore t2 = (TailoringStore) o2;
112 return t1.Culture.LCID - t2.Culture.LCID;
119 ArrayList tailorings = new ArrayList ();
123 public TailoringStore (string name)
125 culture = new CultureInfo (name);
128 public CultureInfo Culture {
129 get { return culture; }
132 public bool FrenchSort {
133 get { return frenchSort; }
134 set { frenchSort = value; }
137 public string Alias {
138 get { return alias; }
139 set { alias = value; }
142 public void Add (Tailoring t)
148 get { return tailorings.Count; }
151 public void Serialize (TextWriter w)
153 w.WriteLine ("// Culture: {0} ({1})", culture.LCID, culture.Name);
155 w.WriteLine ("// FrenchSort.");
157 w.WriteLine ("// Alias: {0}", Alias);
159 tailorings.Sort (TailoringComparer.Instance);
161 foreach (Tailoring t in tailorings)
166 class CultureSpecificLdmlReader
168 ArrayList ignoredFiles = new ArrayList ();
169 ArrayList tailorings = new ArrayList ();
171 public static void Main (string [] args)
173 new CultureSpecificLdmlReader ().Run (args);
176 void Run (string [] args)
178 if (args.Length < 2) {
179 Console.WriteLine ("specify arguments: path_to_ldml_files config_file");
182 string dirname = args [0];
183 string configFileName = args [1];
184 string config = null;
185 using (StreamReader sr = new StreamReader (configFileName)) {
186 config = sr.ReadToEnd ();
188 foreach (string configLine in config.Split ('\n')) {
189 int idx = configLine.IndexOf ('#');
190 string line = idx < 0 ? configLine : configLine.Substring (0, idx);
191 if (line.StartsWith ("ignore: "))
192 ignoredFiles.Add (line.Substring (8).Trim ());
195 XmlTextReader rng = new XmlTextReader ("ldml-limited.rng");
196 RelaxngPattern p = RelaxngPattern.Read (rng);
199 foreach (FileInfo fi in new DirectoryInfo (dirname).GetFiles ("*.xml")) {
200 if (ignoredFiles.Contains (fi.Name))
202 XmlTextReader inst = null;
204 inst = new XmlTextReader (fi.FullName);
205 inst.XmlResolver = null;
206 RelaxngValidatingReader rvr = new
207 RelaxngValidatingReader (inst, p);
208 rvr.ReportDetails = true;
209 XmlDocument doc = new XmlDocument ();
210 doc.XmlResolver = null;
212 TailoringStore ts = ProcessLdml (doc);
221 tailorings.Sort (TailoringStoreComparer.Instance);
223 using (TextWriter tw = new StreamWriter ("create-tailoring.out", false, System.Text.Encoding.UTF8)) {
228 void Serialize (TextWriter output)
230 output.WriteLine ("static char [] tailorings = new char [] {");
231 foreach (TailoringStore ts in tailorings)
232 ts.Serialize (output);
233 output.WriteLine ("};");
235 int [] tailoringIndex = new int [0x80];
236 int [] tailoringCount = new int [0x80];
237 bool [] frenchSort = new bool [0x80];
239 foreach (TailoringStore ts in tailorings) {
240 int lcid = ts.Culture.LCID;
241 tailoringIndex [lcid] = current;
242 tailoringCount [lcid] = ts.Count;
243 frenchSort [lcid] = ts.FrenchSort;
247 foreach (TailoringStore ts in tailorings) {
248 if (ts.Alias == null)
250 int lcid = ts.Culture.LCID;
251 int target = new CultureInfo (ts.Alias).LCID;
252 tailoringIndex [lcid] = tailoringIndex [target];
253 tailoringCount [lcid] = tailoringCount [target];
254 frenchSort [lcid] = frenchSort [target];
258 /*typedef*/ struct TailoringInfo {
259 public TailoringInfo (ushort lcid, uint idx, ushort count, bool french) { Lcid = lcid; TailoringIndex = idx; TailoringCount = count; FrenchSort = french; }
260 public readonly ushort Lcid;
261 /*guint32*/ public readonly uint TailoringIndex;
262 /*guint16*/ public readonly ushort TailoringCount;
263 /*gboolean*/ public readonly bool FrenchSort;
264 }/* TailoringInfo;*/");
266 output.WriteLine ("static TailoringInfo [] tailoringIndexes = new TailoringInfo [] {");
267 for (int i = 0; i < tailoringIndex.Length; i++)
268 output.WriteLine ("new TailoringInfo ({0}, {1}, {2}, {3}), ",
273 output.WriteLine ("};");
278 TailoringStore ProcessLdml (XmlDocument doc)
280 XmlElement langElem = doc.SelectSingleNode (
281 "/ldml/identity/language") as XmlElement;
282 string lang = langElem.GetAttribute ("type");
283 XmlElement terr = doc.SelectSingleNode (
284 "/ldml/identity/territory") as XmlElement;
285 string lcid = lang + (terr != null ?
286 "-" + terr.GetAttribute ("type") : null);
287 TailoringStore ts = null;
289 ts = new TailoringStore (lcid);
290 } catch (ArgumentException) {
291 Console.Error.WriteLine ("WARNING: culture " + lcid + " is not supported in the runtime.");
294 // Console.Error.WriteLine ("Processing " + lcid);
296 XmlNode vn = doc.SelectSingleNode ("/ldml/collations/alias/@source");
302 XmlElement collation = doc.SelectSingleNode ("/ldml/collations/collation[@type='standard']") as XmlElement;
303 XmlElement settings = collation.SelectSingleNode ("settings") as XmlElement;
304 if (settings != null)
305 ts.FrenchSort = settings.GetAttribute ("backwards") == "on";
309 string contraction = null;
311 foreach (XmlNode n in collation.SelectNodes ("rules/*")) {
312 XmlElement el = n as XmlElement;
316 switch (el.LocalName) {
318 switch (el.GetAttribute ("before")) {
319 case "primary": before = 1; break;
320 case "secondary": before = 2; break;
323 switch (el.FirstChild.LocalName) {
324 case "last_primary_ignorable":
325 case "last_secondary_ignorable":
326 Console.Error.WriteLine ("WARNING: {0} is not supported for now.", el.FirstChild.LocalName);
329 XmlElement cpElem = el.SelectSingleNode ("cp") as XmlElement;
332 v = new string ((char) (int.Parse (
333 cpElem.GetAttribute ("hex"),
334 NumberStyles.HexNumber)), 1);
336 v = el.FirstChild.Value;
337 t = new Tailoring (v, before);
344 t.Add (1, el.InnerText);
348 t.Add (2, el.InnerText);
352 t.Add (3, el.InnerText);
356 t.Add (4, el.InnerText);
360 t.Add (5, el.InnerText);
364 switch (el.FirstChild.LocalName) {
366 contLevel = 2; break;
368 contLevel = 3; break;
370 throw new Exception ("Not expected first child of 'x': " + el.Name);
372 if (contraction != null && el.LastChild.InnerText != contraction)
373 throw new Exception ("When there are sequential 'x' elements for single tailoring, those 'extend' text must be identical.");
374 bool exists = contraction != null;
375 contraction = el.LastChild.InnerText;
376 t.Contraction (contLevel,
377 el.FirstChild.InnerText,
378 exists ? "" : contraction);
381 throw new Exception ("Support this element: " + el.Name);