diff --git a/build.gradle.kts b/build.gradle.kts index 69b7fe617..8538aaa1b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -82,7 +82,7 @@ allprojects { pom { configureMavenCentralPom(project) } - signPublication(project) +// signPublication(project) } } } diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/base/CompilerMessages.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/base/CompilerMessages.kt new file mode 100644 index 000000000..62ed0af8a --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/base/CompilerMessages.kt @@ -0,0 +1,37 @@ +// Generated by msggen from CompilerMessages.xml +package org.kopi.compiler.base + +import org.kopi.galite.util.base.MessageDescription + +interface CompilerMessages { + companion object { + val FORMATTED_ERROR: MessageDescription = MessageDescription("{0}", null, 0) + val FORMATTED_CAUTION: MessageDescription = MessageDescription("{0}", null, 1) + val FORMATTED_WARNING: MessageDescription = MessageDescription("{0}", null, 2) + val FORMATTED_NOTICE: MessageDescription = MessageDescription("{0}", null, 3) + val FORMATTED_INFO: MessageDescription = MessageDescription("{0}", null, 4) + val NO_INPUT_FILE: MessageDescription = MessageDescription("No input file given", null, 0) + val FILE_NOT_FOUND: MessageDescription = MessageDescription("File \"{0}\" not found", null, 0) + val IO_EXCEPTION: MessageDescription = MessageDescription("I/O Exception on file \"{0}\": {1}", null, 0) + val UNSUPPORTED_ENCODING: MessageDescription = MessageDescription("Character encoding \"{0}\" is not supported on this platform", null, 0) + val CANNOT_CREATE: MessageDescription = MessageDescription("Cannot create file \"{0}\"", null, 0) + val INVALID_LIST_FILE: MessageDescription = MessageDescription("Invalid list file \"{0}\" : {1}", null, 0) + val NO_VIABLE_ALT_FOR_CHAR: MessageDescription = MessageDescription("Unexpected char \"{0}\"", null, 0) + val UNEXPECTED_EOF: MessageDescription = MessageDescription("Unexpected end of file", null, 0) + val EOF_IN_TRADITIONAL_COMMENT: MessageDescription = MessageDescription("End of file in comment", null, 0) + val EOF_IN_ENDOFLINE_COMMENT: MessageDescription = MessageDescription("End of file in comment", null, 1) + val ILLEGAL_CHAR: MessageDescription = MessageDescription("Unexpected char \"{0}\"", null, 0) + val BAD_ESCAPE_SEQUENCE: MessageDescription = MessageDescription("Illegal escape sequence \"{0}\"", null, 0) + val BAD_END_OF_LINE: MessageDescription = MessageDescription("Unexpected end of line in {0}", null, 0) + val SYNTAX_ERROR: MessageDescription = MessageDescription("Syntax error: {0}", null, 0) + val COMPILATION_STARTED: MessageDescription = MessageDescription("[ start compilation in verbose mode ]", null, 4) + val FILE_PARSED: MessageDescription = MessageDescription("[ parsed {0} in {1} ms ]", null, 4) + val INTERFACES_CHECKED: MessageDescription = MessageDescription("[ checked interfaces in {0} ms ]", null, 4) + val BODY_CHECKED: MessageDescription = MessageDescription("[ checked body of {0} in {1} ms ]", null, 4) + val CONDITION_CHECKED: MessageDescription = MessageDescription("[ checked condition of {0} in {1} ms ]", null, 4) + val CLASSFILE_GENERATED: MessageDescription = MessageDescription("[ optimized and generated {0} in {1} ms ]", null, 4) + val JAVA_CODE_GENERATED: MessageDescription = MessageDescription("[ generated {0} ]", null, 4) + val CLASS_LOADED: MessageDescription = MessageDescription("[ loaded {0} ]", null, 4) + val COMPILATION_ENDED: MessageDescription = MessageDescription("[ compilation ended ]", null, 4) + } +} \ No newline at end of file diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/base/FormattedException.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/base/FormattedException.kt new file mode 100644 index 000000000..4ae3829a6 --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/base/FormattedException.kt @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013-2024 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2024 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.galite.kopi.util.base + +import org.kopi.galite.util.base.Message +import org.kopi.galite.util.base.MessageDescription + +/** + * This class defines exceptions formatted using message descriptions. + */ +open class FormattedException(private val messageDetail: Message) : Exception(messageDetail.description.format) { + + /** + * An exception with an arbitrary number of parameters + * @param description the message description + * @param parameters the array of parameters + */ + constructor(description: MessageDescription, vararg parameters: Any) : this(Message(description, parameters)) + + /** + * An exception with no parameters + * @param description the message description + */ + constructor(description: MessageDescription) : this(description, *emptyArray()) + + // ---------------------------------------------------------------------- + // ACCESSORS + // ---------------------------------------------------------------------- + /** + * Returns a string explaining the exception. + */ + fun getFormattedMessage(): String { + return messageDetail.description.format // Returning the formatted message + } + /** + * Returns the formatted message. + */ + val formattedMessage: Message + get() = messageDetail + + /** + * Returns true if the error has the specified description. + */ + fun hasDescription(description: MessageDescription): Boolean { + return messageDetail.description === description + } + + // ---------------------------------------------------------------------- + // DATA MEMBERS + // ---------------------------------------------------------------------- + override val message: String? + get() = messageDetail.description.format // Return the formatted message as String + + companion object { + /** + * Comment for `serialVersionUID` + */ + private const val serialVersionUID = 6590654347028052938L + } +} diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/base/Message.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/base/Message.kt new file mode 100644 index 000000000..85c90e720 --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/base/Message.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013-2024 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2024 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.util.base + +class Message(val description: MessageDescription, vararg parameters: Any?) { + /** + * An exception with an arbitrary number of parameters + * @param description the message description + * @param parameters the vararg parameters + */ + val params: Array = arrayOf(*parameters) + + /** + * An exception with no parameters + * @param description the message description + */ + constructor(description: MessageDescription) : this(description, *emptyArray()) + + // ---------------------------------------------------------------------- + // ACCESSORS + // ---------------------------------------------------------------------- + val severityLevel: Int + /** + * Returns the severity level + */ + get() = description.level + + val message: String + /** + * Returns the string explaining the error + */ + get() = description.format(this.params) + +} diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/base/MessageDescription.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/base/MessageDescription.kt new file mode 100644 index 000000000..3122fdf2d --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/base/MessageDescription.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013-2024 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2024 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.util.base + +import java.text.MessageFormat + +/** + * This class defines message descriptions (errors, warnings, notices, ...) + * + * The message format is a text message with placeholders for its arguments + * of the form {0}, {1}, ... . Each placeholder will be replaced by the string + * representation of the corresponding argument. + */ +class MessageDescription( val format: String, val reference: String?, val level: Int) { + + /** + * Returns a string explaining the error. + * + * @param parameters the array of parameters + */ + fun format(parameters: Array): String { + val prefix = when (level) { + LVL_UNDEFINED -> "" // no qualifier + LVL_ERROR -> "error:" + LVL_CAUTION -> "caution:" + LVL_WARNING -> "warning:" + LVL_NOTICE -> "notice:" + LVL_INFO -> "" + else -> // unknown: mark as error + "error:" + } // the text for the severity level + + var body = try { + MessageFormat.format(format, *parameters) + } catch (e: RuntimeException) { + // wrong number of parameters: give at least message text with placeholders + format + } // the formatted message + + val suffix = if (reference == null) "" else " [$reference]" // the reference + + return prefix + body + suffix + } + + // ---------------------------------------------------------------------- + // CONSTRUCTORS + // ---------------------------------------------------------------------- + + companion object { + const val LVL_UNDEFINED: Int = -1 + const val LVL_ERROR: Int = 0 + const val LVL_CAUTION: Int = 1 + const val LVL_WARNING: Int = 2 + const val LVL_NOTICE: Int = 3 + const val LVL_INFO: Int = 4 + } +} \ No newline at end of file diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/OptgenMain.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/OptgenMain.kt new file mode 100644 index 000000000..9a7bfc838 --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/OptgenMain.kt @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2013-2024 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2024 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.util.optionGenerator + +import java.io.BufferedWriter +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.io.PrintWriter +import java.io.OutputStreamWriter +import org.kopi.compiler.base.CompilerMessages.Companion.NO_INPUT_FILE +import org.kopi.galite.util.optionGenerator.definition.DefinitionFile +import org.kopi.galite.util.optionGenerator.options.OptgenOptions +import org.kopi.galite.util.optionGenerator.utils.OptgenError + +/** + * This class is the entry point for the Message generator. + */ +class OptgenMain +{ + /** + * Runs a compilation session. + * + * @param args the command line arguments + */ + fun run(args: Array): Boolean { + if (!parseArguments(args)) { + return false + } + var errorsFound = false + + for (i in 0 until options.nonOptions.size) { + errorsFound = !processFile(options.nonOptions.get(i)!!) + } + + return !errorsFound + } + + /* + * Parse command line arguments. + */ + private fun parseArguments(args: Array): Boolean { + options = OptgenOptions() + if (!options.parseCommandLine(args)) { + return false + } + if (options.nonOptions.size === 0) { + System.err.println(NO_INPUT_FILE) + options.usage() + return false + } + return true + } + + private fun processFile(sourceFile: String): Boolean { + if (!parseSource(sourceFile)) { + return false + } + if (options.release != null) { + definition.setVersion(options.release) + } + if (!checkIdentifiers()) { + return false + } + if (!checkShortcuts()) { + return false + } + if (!buildInterfaceFile()) { + return false + } + return true + } + + private fun parseSource(sourceFile: String): Boolean { + var errorsFound = false + + try { + definition = DefinitionFile.read(sourceFile) + } catch (e: OptgenError) { + System.err.println(e.getFormattedMessage()) + errorsFound = true + } + + return !errorsFound + } + + private fun checkIdentifiers(): Boolean { + var errorsFound = false + + try { + definition.checkIdentifiers() + } catch (e: OptgenError) { + System.err.println(e.getFormattedMessage()) + errorsFound = true + } + + return !errorsFound + } + + /** + * + */ + private fun checkShortcuts(): Boolean { + var errorsFound = false + + try { + definition.checkShortcuts() + } catch (e: OptgenError) { + System.err.println(e.getFormattedMessage()) + errorsFound = true + } + + return !errorsFound + } + + /** + * + */ + private fun buildInterfaceFile(): Boolean { + val prefix: String = definition.prefix + val outputFile = File(prefix + "Options.java") + var errorsFound = false + + try { + val out= PrintWriter(BufferedWriter(OutputStreamWriter(FileOutputStream(outputFile), "UTF-8"))) + + definition.printFile(out) + + out.flush() + out.close() + } catch (e: IOException) { + System.err.println("I/O Exception on " + outputFile.path + ": " + e.message) + errorsFound = true + } + + return !errorsFound + } + + // -------------------------------------------------------------------- + // DATA MEMBERS + // -------------------------------------------------------------------- + private lateinit var options: OptgenOptions + private lateinit var definition: DefinitionFile + + companion object { + + /** + * Program entry point. + */ + @JvmStatic + fun main(args: Array) { + val success = OptgenMain().run(args) + + System.exit(if (success) 0 else 1) + } + } +} \ No newline at end of file diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/definition/Definition.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/definition/Definition.kt new file mode 100644 index 000000000..9d47cae92 --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/definition/Definition.kt @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2013-2024 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2024 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.util.optionGenerator.definition + +import java.io.File +import java.io.PrintWriter +import java.util.* +import org.jdom2.Document +import org.jdom2.Element +import org.jdom2.input.SAXBuilder +import org.kopi.galite.util.base.InconsistencyException +import org.kopi.galite.util.optionGenerator.utils.OptgenError + +internal class DefinitionFile(private val sourceFile: String, + private val fileHeader: String?, + val packageName: String, + private val parent: String?, + val prefix: String, + private var version: String?, + private val usage: String?, + private val definitions: Array) { + + fun setVersion(version: String?) { + this.version = version + } + + @Throws(OptgenError::class) + fun checkIdentifiers() { + val identifiers = Hashtable() + definitions.forEach { it?.checkIdentifiers(identifiers, sourceFile) } + } + + @Throws(OptgenError::class) + fun checkShortcuts() { + val shortcuts = Hashtable() + definitions.forEach { it?.checkShortcuts(shortcuts, sourceFile) } + } + + /** + * Generates the option parser. + * + * @param out the output stream + */ + fun printFile(out: PrintWriter) { + if (fileHeader != null) { + out.println(fileHeader) + } + out.print("// Generated by optgen from $sourceFile") + out.println() + out.println("package $packageName;") + out.println() + out.println("import gnu.getopt.Getopt;") + out.println("import gnu.getopt.LongOpt;") + out.println() + out.print("public class " + prefix + "Options") + out.print(if (parent == null) "" else " extends $parent") + out.println(" {") + + // CONSTRUCTORS + out.println() + out.println(" public " + prefix + "Options(String name) {") + out.println(" super(name);") + out.println(" }") + out.println() + out.println(" public " + prefix + "Options() {") + out.println(" this(\"$prefix\");") + out.println(" }") + out.println() + + // FIELDS + for (i in definitions.indices) { + definitions[i]!!.printFields(out) + } + + // PROCESSOPTION + out.println() + out.println(" public boolean processOption(int code, Getopt g) {") + out.println(" switch (code) {") + for (i in definitions.indices) { + definitions[i]!!.printParseArgument(out) + } + out.println(" default:") + out.println(" return super.processOption(code, g);") + out.println(" }") + out.println(" }") + + + // GETOPTIONS + out.println() + out.println(" public String[] getOptions() {") + out.println(" String[] parent = super.getOptions();") + out.println(" String[] total = new String[parent.length + " + definitions.size + "];") + out.println(" System.arraycopy(parent, 0, total, 0, parent.length);") + for (i in definitions.indices) { + out.print(" total[parent.length + $i] = ") + definitions[i]!!.printUsage(out) + out.println(";") + } + out.println(" ") + out.println(" return total;") + out.println(" }") + + // GETSHORTOPTIONS + out.println("\n") + out.println(" public String getShortOptions() {") + out.print(" return \"") + for (i in definitions.indices) { + definitions[i]!!.printShortOption(out) + } + out.println("\" + super.getShortOptions();") + out.println(" }") + + // VERSION + out.println("\n") + out.println(" public void version() {") + out.print(" System.out.println(") + out.print(if (version == null) "" else "\"" + version + "\"") + out.println(");") + out.println(" }") + + // USAGE + out.println("\n") + out.println(" public void usage() {") + if (usage != null) { + out.print(" System.err.println(") + out.print("\"" + usage + "\"") + out.println(");") + } + out.println(" }") + + // GETLONGOPTIONS + out.println() + out.println(" public LongOpt[] getLongOptions() {") + out.println(" LongOpt[] parent = super.getLongOptions();") + out.println(" LongOpt[] total = new LongOpt[parent.length + LONGOPTS.length];") + out.println(" ") + out.println(" System.arraycopy(parent, 0, total, 0, parent.length);") + out.println(" System.arraycopy(LONGOPTS, 0, total, parent.length, LONGOPTS.length);") + out.println(" ") + out.println(" return total;") + out.println(" }") + + // LONGOPTS + out.println() + out.println(" private static final LongOpt[] LONGOPTS = {") + for (i in definitions.indices) { + if (i != 0) { + out.println(",") + } + definitions[i]!!.printLongOpts(out) + } + out.println() + out.println(" };") + + out.println("}") + } + + val className: String + get() = "$packageName.${prefix}Options" + + companion object { + @Throws(OptgenError::class) + fun read(sourceFile: String): DefinitionFile { + val document: Document + val builder = SAXBuilder() + try { + document = builder.build(File(sourceFile)) + } catch (e: Exception) { + throw InconsistencyException("Cannot load file $sourceFile: ${e.message}") + } + val root = document.rootElement + + return DefinitionFile( + sourceFile, + root.getAttributeValue("fileHeader"), + root.getAttributeValue("package"), + root.getAttributeValue("parent"), + root.getAttributeValue("prefix"), + root.getAttributeValue("version"), + root.getAttributeValue("usage"), + getOptions(root) + ) + } + + fun getOptions(element: Element): Array { + val params = element.getChildren("param") + return Array(params.size) { i -> + val current = params[i] as Element + val type = current.getAttributeValue("type") + val isMultiple = current.getAttributeValue("multiple") != null + val arg = current.getAttributeValue("optionalDefault") ?: if (type != "boolean") "" else null + OptionDefinition( + current.getAttributeValue("longname"), + current.getAttributeValue("shortname"), + type, + isMultiple, + current.getAttributeValue("default"), + arg, + current.getAttributeValue("help") + ) + } + } + } +} diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/definition/OptionDefinition.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/definition/OptionDefinition.kt new file mode 100644 index 000000000..237d4c789 --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/definition/OptionDefinition.kt @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.util.optionGenerator.definition + +import org.kopi.galite.util.base.InconsistencyException +import org.kopi.galite.util.optionGenerator.utils.OptgenError +import org.kopi.galite.util.optionGenerator.utils.OptgenMessages +import java.io.PrintWriter +import java.util.* + +class OptionDefinition(private val longname: String, + private val shortname: String, + private val type: String, + private val isMultiple: Boolean, + private val defaultValue: String, + private val argument: String?, + private val help: String?) { + + @Throws(OptgenError::class) + fun checkIdentifiers(identifiers: Hashtable, sourceFile: String) { + val stored = identifiers[longname] + if (stored != null) { + throw OptgenError(OptgenMessages.DUPLICATE_DEFINITION, longname, sourceFile, stored) + } + identifiers[longname] = sourceFile + } + + @Throws(OptgenError::class) + fun checkShortcuts(shortcuts: Hashtable, sourceFile: String) { + val stored = shortcuts[shortname] + if (stored != null) { + throw OptgenError(OptgenMessages.DUPLICATE_SHORTCUT, shortname, sourceFile, stored) + } + shortcuts[shortname] = sourceFile + } + + /** + * Prints the case statement for the parseArgument method + * + * @param out the output stream + */ + fun printParseArgument(out: PrintWriter) { + out.print(" case \'") + out.print(shortname) + out.println("\':") + out.print(" ") + out.print(longname) + out.print(" = ") + if (argument == null) { + if (isMultiple) { + throw InconsistencyException("multiple arguments support for type $type is not yet implemented.") + } + out.print("!$defaultValue") + out.print(";") + } else { + val methodName: String + var arg = this.argument + if (type == "int") { + methodName = "getInt" + if (arg == null || arg == "") { + arg = "0" + } + } else { + methodName = "getString" + arg = "\"" + arg + "\"" + } + if (isMultiple) { + if (type == "int") { + out.print("addInt($longname, $methodName(g, $arg))") + } else if (type == "String") { + out.print("addString($longname, $methodName(g, $arg))") + } else { + throw InconsistencyException("multiple arguments support for type $type is not yet implemented.") + } + } else { + out.print("$methodName(g, $arg)") + } + out.print(";") + } + out.println(" return true;") + } + + /** + * Prints the field declaration + * + * @param out the output stream + */ + fun printFields(out: PrintWriter) { + out.print(" public ") + out.print(if (!isMultiple) type else "$type[]") + out.print(" ") + out.print(longname) + out.print(" = ") + if (type != "String" || defaultValue == "null") { + if (defaultValue == "null") { + out.print(defaultValue) + } else { + out.print(if (!isMultiple) defaultValue else "{ $defaultValue }") + } + } else { + out.print(if (!isMultiple) "\"" + defaultValue + "\"" else "{ \"$defaultValue\" }") + } + out.println(";") + } + + /** + * Prints the usage message + * + * @param out the output stream + */ + fun printUsage(out: PrintWriter) { + val prefix = StringBuffer("\" --") + + prefix.append(longname) + prefix.append(", -") + prefix.append(shortname) + if (argument != null) { + prefix.append("<$type>") + } + prefix.append(": ") + for (i in prefix.length..24) { + prefix.append(" ") + } + out.print(prefix.toString() + (help?.replace("\"".toRegex(), "\\\\\"") ?: "")) + if (defaultValue != "null") { + out.print(" [") + out.print(defaultValue) + out.print("]") + } + out.print("\"") + } + + /** + * Prints the LongOpt instantiation + * + * @param out the output stream + */ + fun printLongOpts(out: PrintWriter) { + out.print(" new LongOpt(\"") + out.print(longname) + out.print("\", ") + if (argument == null) { + out.print("LongOpt.NO_ARGUMENT") + } else if (argument == "") { + out.print("LongOpt.REQUIRED_ARGUMENT") + } else { + out.print("LongOpt.OPTIONAL_ARGUMENT") + } + out.print(", null, \'") + out.print(shortname) + out.print("\')") + } + + /** + * Prints the short option + * + * @param out the output stream + */ + fun printShortOption(out: PrintWriter) { + out.print(shortname) + if (argument != null) { + if (argument == "") { + out.print(":") + } else { + out.print("::") + } + } + } + + companion object { + private fun trail(s: String?): String? { + return when { + s == null -> null + s.length < 2 -> s + else -> s.substring(1, s.length - 1) + } + } + } +} diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/options/OptgenOptions.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/options/OptgenOptions.kt new file mode 100644 index 000000000..1b5344db5 --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/options/OptgenOptions.kt @@ -0,0 +1,56 @@ +package org.kopi.galite.util.optionGenerator.options + +import gnu.getopt.Getopt +import gnu.getopt.LongOpt + +class OptgenOptions @JvmOverloads constructor(name: String? = "Optgen") : org.kopi.galite.util.base.Options(name) { + var release: String? = null + + override fun processOption(code: Int, g: Getopt): Boolean { + when (code) { + 'r'.code -> { + release = getString(g, "") + return true + } + else -> return super.processOption(code, g) + } + } + + override val options: Array + get() { + val parent: Array = super.options + val total = arrayOfNulls(parent.size + 1) + System.arraycopy(parent, 0, total, 0, parent.size) + total[parent.size + 0] = " --release, -r: Sets the release version of the program" + + return total + } + + override val shortOptions: String + get() = "r:" + super.shortOptions + + override fun version() { + println("Version 2.1B released 17. July 2002") + } + + public override fun usage() { + System.err.println("usage: org.kopi.galite.util.optionGenerator.optgenMain [option]* [--help] +") + } + + override val longOptions: Array + get() { + val parent: Array = super.longOptions + val total = arrayOfNulls(parent.size + LONGOPTS.size) + + System.arraycopy(parent, 0, total, 0, parent.size) + System.arraycopy(LONGOPTS, 0, total, parent.size, LONGOPTS.size) + + return total + } + + companion object { + private val LONGOPTS = arrayOf( + LongOpt("release", LongOpt.REQUIRED_ARGUMENT, null, 'r'.code) + ) + } +} \ No newline at end of file diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/utils/OptgenError.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/utils/OptgenError.kt new file mode 100644 index 000000000..4eafbdc32 --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/utils/OptgenError.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013-2024 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2024 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.util.optionGenerator.utils + +import org.galite.kopi.util.base.FormattedException +import org.kopi.galite.util.base.Message +import org.kopi.galite.util.base.MessageDescription + +/** + * Error thrown on problems encountered while running the program. + */ +class OptgenError : FormattedException { + // -------------------------------------------------------------------- + // CONSTRUCTORS + // -------------------------------------------------------------------- + + /** + * An exception with a formatted message as argument + * @param message the formatted message + */ + constructor(message: Message) : super(message) + + /** + * Primary constructor for creating an exception with a Message + * An exception with an arbitrary number of parameters + * @param description the message description + * @param parameters the array of parameters + */ + constructor(description: MessageDescription, vararg parameters: Any?) : this(Message(description, parameters)) + + companion object { + /** + * Comment for `serialVersionUID` + */ + private const val serialVersionUID = -1940949686284187233L + } +} \ No newline at end of file diff --git a/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/utils/OptgenMessages.kt b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/utils/OptgenMessages.kt new file mode 100644 index 000000000..c8636157f --- /dev/null +++ b/galite-util/src/main/kotlin/org/kopi/galite/util/optionGenerator/utils/OptgenMessages.kt @@ -0,0 +1,14 @@ +// Generated by msggen from OptgenMessages.xml +package org.kopi.galite.util.optionGenerator.utils + +import org.kopi.compiler.base.CompilerMessages +import org.kopi.galite.util.base.MessageDescription + +interface OptgenMessages : CompilerMessages { + companion object { + val DUPLICATE_DEFINITION: MessageDescription = + MessageDescription("Option \"{0}\" redefined in \"{1}\": previous definition in \"{2}\"", null, 0) + val DUPLICATE_SHORTCUT: MessageDescription = + MessageDescription("Shortcut \"{0}\" redefined in \"{1}\": previous definition in \"{2}\"", null, 0) + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 0cfaf2472..57d1a4f3e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx4g # group=org.kopi -version=1.5.6 +version=1.5.6-02AJ