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 Serialize (Console.Out);
226 void Serialize (TextWriter output)
228 output.WriteLine ("static char [] tailorings = new char [] {");
229 foreach (TailoringStore ts in tailorings)
230 ts.Serialize (output);
231 output.WriteLine ("};");
233 int [] tailoringIndex = new int [0x80];
234 int [] tailoringCount = new int [0x80];
235 bool [] frenchSort = new bool [0x80];
237 foreach (TailoringStore ts in tailorings) {
238 int lcid = ts.Culture.LCID;
239 tailoringIndex [lcid] = current;
240 tailoringCount [lcid] = ts.Count;
241 frenchSort [lcid] = ts.FrenchSort;
245 foreach (TailoringStore ts in tailorings) {
246 if (ts.Alias == null)
248 int lcid = ts.Culture.LCID;
249 int target = new CultureInfo (ts.Alias).LCID;
250 tailoringIndex [lcid] = tailoringIndex [target];
251 tailoringCount [lcid] = tailoringCount [target];
252 frenchSort [lcid] = frenchSort [target];
256 /*typedef*/ struct TailoringInfo {
257 public TailoringInfo (ushort lcid, uint idx, ushort count, bool french) { Lcid = lcid; TailoringIndex = idx; TailoringCount = count; FrenchSort = french; }
258 public readonly ushort Lcid;
259 /*guint32*/ public readonly uint TailoringIndex;
260 /*guint16*/ public readonly ushort TailoringCount;
261 /*gboolean*/ public readonly bool FrenchSort;
262 }/* TailoringInfo;*/");
264 output.WriteLine ("static TailoringInfo [] tailoringIndexes = new TailoringInfo [] {");
265 for (int i = 0; i < tailoringIndex.Length; i++)
266 output.WriteLine ("new TailoringInfo ({0}, {1}, {2}, {3}), ",
271 output.WriteLine ("};");
276 TailoringStore ProcessLdml (XmlDocument doc)
278 XmlElement langElem = doc.SelectSingleNode (
279 "/ldml/identity/language") as XmlElement;
280 string lang = langElem.GetAttribute ("type");
281 XmlElement terr = doc.SelectSingleNode (
282 "/ldml/identity/territory") as XmlElement;
283 string lcid = lang + (terr != null ?
284 "-" + terr.GetAttribute ("type") : null);
285 TailoringStore ts = null;
287 ts = new TailoringStore (lcid);
288 } catch (ArgumentException) {
289 Console.Error.WriteLine ("WARNING: culture " + lcid + " is not supported in the runtime.");
292 // Console.Error.WriteLine ("Processing " + lcid);
294 XmlNode vn = doc.SelectSingleNode ("/ldml/collations/alias/@source");
300 XmlElement collation = doc.SelectSingleNode ("/ldml/collations/collation[@type='standard']") as XmlElement;
301 XmlElement settings = collation.SelectSingleNode ("settings") as XmlElement;
302 if (settings != null)
303 ts.FrenchSort = settings.GetAttribute ("backwards") == "on";
307 string contraction = null;
309 foreach (XmlNode n in collation.SelectNodes ("rules/*")) {
310 XmlElement el = n as XmlElement;
314 switch (el.LocalName) {
316 switch (el.GetAttribute ("before")) {
317 case "primary": before = 1; break;
318 case "secondary": before = 2; break;
321 switch (el.FirstChild.LocalName) {
322 case "last_primary_ignorable":
323 case "last_secondary_ignorable":
324 Console.Error.WriteLine ("WARNING: {0} is not supported for now.", el.FirstChild.LocalName);
327 XmlElement cpElem = el.SelectSingleNode ("cp") as XmlElement;
330 v = new string ((char) (int.Parse (
331 cpElem.GetAttribute ("hex"),
332 NumberStyles.HexNumber)), 1);
334 v = el.FirstChild.Value;
335 t = new Tailoring (v, before);
342 t.Add (1, el.InnerText);
346 t.Add (2, el.InnerText);
350 t.Add (3, el.InnerText);
354 t.Add (4, el.InnerText);
358 t.Add (5, el.InnerText);
362 switch (el.FirstChild.LocalName) {
364 contLevel = 2; break;
366 contLevel = 3; break;
368 throw new Exception ("Not expected first child of 'x': " + el.Name);
370 if (contraction != null && el.LastChild.InnerText != contraction)
371 throw new Exception ("When there are sequential 'x' elements for single tailoring, those 'extend' text must be identical.");
372 bool exists = contraction != null;
373 contraction = el.LastChild.InnerText;
374 t.Contraction (contLevel,
375 el.FirstChild.InnerText,
376 exists ? "" : contraction);
379 throw new Exception ("Support this element: " + el.Name);