blob: 68ad1c51e2a29a5abd440cd77dd615e697b6b435 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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;
}