| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /* |
| * |
| * errorGen.as |
| * |
| * "errorGen" is an AS3 script which reads an |
| * XML file containing all (localized) compiler |
| * error messages and creates .cpp, .h and |
| * .java files which describe the same data. |
| * |
| * Chris Nuuja |
| * Jan 20, 2004 |
| * |
| */ |
| import avmplus.* |
| const CONFIG_FILE:String = "errorConfig.xml"; |
| const SCRIPT_NAME:String = "errorGen"; |
| |
| var config:XML = XML(File.read(CONFIG_FILE)); |
| |
| var IFDEF:String = String(config.Ifdef); |
| var XML_INPUT_BASE:String = String(config.InputFileBase); |
| var XML_INPUT_FILE:String = String(config.XmlInputFile); |
| var OUTPUT_CPP_FILE:String = String(config.OutputCppFile); |
| var OUTPUT_JAVA_FILE:String = String(config.OutputJavaFile); |
| var OUTPUT_H_FILE:String = String(config.OutputHFile); |
| var ARRAY_NAME:String = String(config.ArrayName); |
| var LANG_COUNT_NAME:String = String(config.LangCountName); |
| var COUNT_NAME:String = String(config.CountName); |
| var STRUCT_NAME:String = String(config.NamespaceName); |
| var MAIN_INCLUDE:String = String(config.MainInclude); |
| |
| class LocalizedLanguage // one of these per localzed .xml file |
| { |
| public var language:String; // language name |
| public var sourceXML:XML; // original .xml file |
| public var messages:Array; // array of ErrorMessages, indexed by the ErrorMessage's id. |
| } |
| |
| class ErrorMessage // one of these per message in the an .xml file |
| { |
| public var id:Number; |
| public var label:String; |
| public var message:String; |
| public var language:String; |
| } |
| |
| var localizedMessages:Object = new Object(); // holds all LocalizedLanguages, indexed by the LocalizedLanguage's language (i.e. localizedMessages["EN"] for english) |
| var languageNames:Array = []; // holds all language names, indexed from 0 to numLanguages-1 |
| var numLanguages:int; |
| var numErrors:int; // The number of ErrorMessages in the master "EN" LocalizedLanguage |
| |
| var maxStringLength:int=0; // maximum length of any error string. Used when generating padding white space for pretty output |
| |
| function compare(a:Object, b:Object):Number |
| { |
| if (a.id < b.id) { |
| return -1; |
| } else if (a.id > b.id) { |
| return 1; |
| } else { |
| return 0; |
| } |
| } |
| |
| for each ( var language:XML in config..Language ) |
| { |
| var languageRec:LocalizedLanguage = new LocalizedLanguage(); |
| var languageName:String = String(language); |
| languageRec.language = languageName; |
| languageRec.sourceXML = XML(File.read(XML_INPUT_BASE + language + XML_INPUT_FILE)); |
| languageRec.messages = []; |
| |
| for each (var error:XML in (languageRec.sourceXML)..error) |
| { |
| // Remove IMD's <description> elements |
| delete error.description; |
| if (error.@removed == true) |
| continue; |
| |
| var message:ErrorMessage = new ErrorMessage(); |
| //print("About to dump id: " + error.@id + " = " + error); |
| message.id = Number(error.@id); |
| message.language= languageName; |
| message.label = String(error.@label); |
| message.message = String(error); |
| |
| languageRec.messages[message.id] = message; |
| |
| maxStringLength = Math.max(maxStringLength, message.label.length); |
| |
| // english is the reference language |
| if (languageName == "EN") |
| numErrors++; |
| } |
| //languageRec.messages = languageRec.messages.sort(compare); |
| |
| languageNames.push(languageName); |
| localizedMessages[languageName] = languageRec; |
| } |
| numLanguages = languageNames.length; |
| |
| var s:String; |
| |
| s = "\ |
| /*\n\ |
| *\n\ |
| * THIS FILE IS AUTO-GENERATED. DO NOT EDIT THIS FILE.\n\ |
| * Use the script '" + SCRIPT_NAME + "' to generate this file.\n\ |
| */\n\ |
| \n\ |
| /*\n\ |
| *\n\ |
| * Licensed to the Apache Software Foundation (ASF) under one or more\n\ |
| * contributor license agreements. See the NOTICE file distributed with\n\ |
| * this work for additional information regarding copyright ownership.\n\ |
| * The ASF licenses this file to You under the Apache License, Version 2.0\n\ |
| * (the \"License\"); you may not use this file except in compliance with\n\ |
| * the License. You may obtain a copy of the License at\n\ |
| *\n\ |
| * http://www.apache.org/licenses/LICENSE-2.0\n\ |
| *\n\ |
| * Unless required by applicable law or agreed to in writing, software\n\ |
| * distributed under the License is distributed on an \"AS IS\" BASIS,\n\ |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\ |
| * See the License for the specific language governing permissions and\n\ |
| * limitations under the License.\n\ |
| *\n\ |
| \n\ |
| /* \n\ |
| * ErrorConstants.java defines the ID's of error messages output\n\ |
| * by the compiler. Localized tables of strings exist for\n\ |
| * each language supported. These ids are used to reference \n\ |
| * the error message without regard to language \n\ |
| */\n\ |
| \n"; |
| |
| s += "package macromedia.asc.embedding;\n"; |
| |
| s += "public interface ErrorConstants\n"; |
| s += "{\n"; |
| s += " static final int " + LANG_COUNT_NAME + " = " + numLanguages + ";\n"; |
| s += " static final int " + COUNT_NAME + " = " + numErrors + ";\n"; |
| s += "\n"; |
| s += "\n"; |
| |
| for each (var w:ErrorMessage in localizedMessages["EN"].messages) |
| { |
| s += " public static final int " + w.label + " = " + w.id + ";\n"; |
| } |
| |
| s += " \n"; |
| s += " public class AscError\n"; |
| s += " {\n"; |
| s += " public int code; // enum used to identify or lookup this message/problem\n"; |
| s += " public String errorMsg; // a particular error message '\n"; |
| s += " public AscError(int c, String s) { code = c; errorMsg = s; }\n"; |
| s += " } ;\n"; |
| s += " \n"; |
| |
| var englishMessages:Array = localizedMessages["EN"].messages; |
| for ( i=0; i < languageNames.length; i++ ) |
| { |
| var thisLang:String = languageNames[i]; |
| var messages:Array = localizedMessages[thisLang].messages; |
| |
| s += " public static final AscError[] errorConstants" + thisLang + " = { \n"; |
| if (thisLang == "EN") |
| { |
| for (var j:int = 0; j<messages.length; j++) |
| { |
| if (messages[j] != undefined) |
| s += " new AscError(" + messages[j].label + ", \"" + quote(messages[j].message) + "\" ),\n"; |
| } |
| } |
| else |
| { |
| |
| for (j=0; j<messages.length; j++) |
| { |
| if ( messages[j] != undefined && englishMessages[ messages[j].id ] != undefined ) // don't add if it was removed from the English list |
| s += " new AscError(" + messages[j].label + ", \"" + quote(messages[j].message) + "\" ),\n"; |
| /* |
| else |
| { |
| trace("m: " + messages[j]); |
| if (messages[j] != undefined) |
| { |
| trace("leaving out: " + messages[j].id); |
| trace("em: " + englishMessages[ messages[j].id ]); |
| } |
| } |
| */ |
| } |
| // add the new ones recently added to English but not yet translated |
| for (j=0;j<englishMessages.length; j++) |
| { |
| if (englishMessages[j] != undefined && messages[j] == undefined) |
| { |
| s += " new AscError(" + englishMessages[j].label + ", \"" + quote(englishMessages[j].message) + "\" ),\n"; |
| } |
| } |
| } |
| s += " };\n\n"; |
| } |
| |
| s += " public static final AscError[][] " + ARRAY_NAME + " =\n"; |
| s += " {\n"; |
| |
| for ( var i:int=0; i < languageNames.length; i++ ) |
| { |
| s += " errorConstants" + languageNames[i] + ",\n"; |
| } |
| s += " };\n"; |
| |
| |
| s += " \n"; |
| s += " \n"; |
| s += " \n"; |
| s += "};\n"; |
| |
| File.write(OUTPUT_JAVA_FILE, s); |
| |
| /* disable c++ output for now |
| s += "\n"; |
| s += "\n"; |
| s += "#ifndef " + IFDEF + "\n"; |
| s += "#define " + IFDEF + "\n"; |
| s += "\n"; |
| s += "namespace asc {\n"; |
| s += "namespace v1 {\n\n"; |
| s += "struct " + STRUCT_NAME + " {\n"; |
| s += " static const int " + LANG_COUNT_NAME + " = " + numLanguages + ";\n"; |
| s += " static const int " + COUNT_NAME + " = " + numErrors + ";\n"; |
| |
| s += "\n"; |
| s += " typedef enum\n"; |
| s += " {\n"; |
| |
| var first = true; |
| for (var i=0; i<errors.length; i++) |
| { |
| if ( errors[i].language == "EN") |
| { |
| if (!first) { |
| s += ",\n"; |
| } |
| s += " " + pad(errors[i].label, maxLength) + " = " + errors[i].id; |
| first = false; |
| } |
| } |
| |
| s += "\n"; |
| s += " } ErrorCode;\n\n"; |
| s += "\n"; |
| s += "\n"; |
| s += " typedef struct {\n"; |
| s += " ErrorCode code; // enum used to identify and lookup the string for this error\n"; |
| s += " std::string errorMsg; // a particular error message \n"; |
| s += " } AscError;\n"; |
| s += "\n"; |
| s += " enum LangID\n"; |
| s += " {\n"; |
| for ( var i=0; i < languageNames.length; i++ ) |
| { |
| s += " LANG_" + languageNames[i] + "="+i+",\n"; |
| } |
| s += " };\n"; |
| s += "\n"; |
| s += " static AscError* allErrorConstants[" + numLanguages + "];\n"; |
| for ( var i=0; i < languageNames.length; i++ ) |
| { |
| s += " static AscError errorConstants"+ languageNames[i] + "[" + numErrors + "];\n"; |
| } |
| s += "};\n\n"; |
| |
| |
| s += "}\n"; |
| s += "}\n"; |
| s += "#endif //" + IFDEF + "\n"; |
| s += "\n"; |
| |
| |
| |
| File.write(OUTPUT_H_FILE, s); |
| |
| s += "\n"; |
| s += "#include \"" + MAIN_INCLUDE + "\"\n"; |
| s += "\n"; |
| s += "namespace asc {\n"; |
| s += "namespace v1 {\n"; |
| //s += "namespace " + STRUCT_NAME + "{\n"; // Uncomment if we want a new namespace for just the errors |
| for ( var i=0; i < languageNames.length; i++ ) |
| { |
| s += " " + STRUCT_NAME + "::AscError " + STRUCT_NAME + "::" + "errorConstants" + languageNames[i]+ "[" + COUNT_NAME + "] =\n"; |
| s += " {\n"; |
| |
| for (var j=0; j<errors.length; j++) |
| { |
| if ( errors[j].language == languageNames[i] && removedErrors[errors[j].id] == undefined ) |
| { |
| s += " { " + errors[j].label + ", \"" + quote(errors[j].message) + "\" },\n"; |
| } |
| } |
| // If the current output language is not English add on each of the newly added error strings that have not been localized |
| for (var k=0; k < nonLocalizedErrors.length; k++) |
| { |
| if ( languageNames[i] != "EN" ) |
| { |
| s += " { " + nonLocalizedErrors[k].label + ", \"" + quote(nonLocalizedErrors[k].message) + "\" },\n"; |
| } |
| } |
| |
| s += " };\n\n"; |
| } |
| s += " " + STRUCT_NAME + "::AscError* " + STRUCT_NAME + "::" + ARRAY_NAME + "[" + LANG_COUNT_NAME + "] =\n"; |
| s += " {\n"; |
| |
| for ( var i=0; i < languageNames.length; i++ ) |
| { |
| s += " " + STRUCT_NAME + "::errorConstants" + languageNames[i] + ",\n"; |
| } |
| s += " };\n"; |
| |
| s += "}\n"; |
| s += "}\n"; |
| |
| File.write(OUTPUT_CPP_FILE, s); |
| |
| */ |
| |
| |
| |
| print("errorGen completed successfully"); |
| |
| function pad(s:Object, len:int):String |
| { |
| var s2:String = String(s); |
| while (s2.length < len) { |
| s2 += ' '; |
| } |
| return s2; |
| } |
| |
| function quote(s:String):String |
| { |
| var r:String = ""; |
| for (var i:int=0; i<s.length; i++) { |
| var c:String = s.charAt(i); |
| if (c == '"') { |
| r += "\\"; |
| } |
| r += c; |
| } |
| return r; |
| } |
| |