summaryrefslogtreecommitdiffstats
path: root/umbrello/umbrello/codegenerators/pascalwriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'umbrello/umbrello/codegenerators/pascalwriter.cpp')
-rw-r--r--umbrello/umbrello/codegenerators/pascalwriter.cpp542
1 files changed, 542 insertions, 0 deletions
diff --git a/umbrello/umbrello/codegenerators/pascalwriter.cpp b/umbrello/umbrello/codegenerators/pascalwriter.cpp
new file mode 100644
index 00000000..92a45bd2
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/pascalwriter.cpp
@@ -0,0 +1,542 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#include "pascalwriter.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+
+#include "../umldoc.h"
+#include "../uml.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../classifierlistitem.h"
+#include "../umlclassifierlistitemlist.h"
+#include "../umltemplatelist.h"
+#include "../folder.h"
+#include "../association.h"
+#include "../attribute.h"
+#include "../operation.h"
+#include "../template.h"
+#include "../umlnamespace.h"
+#include "classifierinfo.h"
+
+const QString PascalWriter::defaultPackageSuffix = "_Holder";
+
+PascalWriter::PascalWriter() {
+}
+
+PascalWriter::~PascalWriter() {}
+
+/**
+ * returns "Pascal"
+ */
+Uml::Programming_Language PascalWriter::getLanguage() {
+ return Uml::pl_Pascal;
+}
+
+
+bool PascalWriter::isOOClass(UMLClassifier *c) {
+ Uml::Object_Type ot = c->getBaseType();
+ if (ot == Uml::ot_Interface)
+ return true;
+ if (ot == Uml::ot_Enum)
+ return false;
+ if (ot != Uml::ot_Class) {
+ kDebug() << "PascalWriter::isOOClass: unknown object type " << ot << endl;
+ return false;
+ }
+ QString stype = c->getStereotype();
+ if (stype == "CORBAConstant" || stype == "CORBATypedef" ||
+ stype == "CORBAStruct" || stype == "CORBAUnion")
+ return false;
+ // CORBAValue, CORBAInterface, and all empty/unknown stereotypes are
+ // assumed to be OO classes.
+ return true;
+}
+
+QString PascalWriter::qualifiedName(UMLPackage *p, bool withType, bool byValue) {
+ UMLPackage *umlPkg = p->getUMLPackage();
+ QString className = cleanName(p->getName());
+ QString retval;
+
+ if (umlPkg == UMLApp::app()->getDocument()->getRootFolder(Uml::mt_Logical))
+ umlPkg = NULL;
+
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(p);
+ if (umlPkg == NULL) {
+ retval = className;
+ if (c == NULL || !isOOClass(c))
+ retval.append(defaultPackageSuffix);
+ } else {
+ retval = umlPkg->getFullyQualifiedName(".");
+ if (isOOClass(c)) {
+ retval.append(".");
+ retval.append(className);
+ }
+ }
+ if (! withType)
+ return retval;
+ if (c && isOOClass(c)) {
+ retval.append(".Object");
+ if (! byValue)
+ retval.append("_Ptr");
+ } else {
+ retval.append(".");
+ retval.append(className);
+ }
+ return retval;
+}
+
+void PascalWriter::computeAssocTypeAndRole
+(UMLAssociation *a, QString& typeName, QString& roleName) {
+ roleName = a->getRoleName(Uml::A);
+ if (roleName.isEmpty()) {
+ if (a->getMulti(Uml::A).isEmpty()) {
+ roleName = "M_";
+ roleName.append(typeName);
+ } else {
+ roleName = typeName;
+ roleName.append("_Vector");
+ }
+ }
+ UMLClassifier* c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
+ if (c == NULL)
+ return;
+ typeName = cleanName(c->getName());
+ if (! a->getMulti(Uml::A).isEmpty())
+ typeName.append("_Array_Access");
+}
+
+void PascalWriter::writeClass(UMLClassifier *c) {
+ if (!c) {
+ kDebug() << "Cannot write class of NULL concept!" << endl;
+ return;
+ }
+
+ const bool isClass = !c->isInterface();
+ QString classname = cleanName(c->getName());
+ QString fileName = qualifiedName(c).lower();
+ fileName.replace('.', '-');
+
+ //find an appropriate name for our file
+ fileName = overwritableName(c, fileName, ".pas");
+ if (fileName.isEmpty()) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ QFile file;
+ if (!openFile(file, fileName)) {
+ emit codeGenerated(c, false);
+ return;
+ }
+
+ // Start generating the code.
+
+ QTextStream pas(&file);
+ //try to find a heading file(license, comments, etc)
+ QString str;
+ str = getHeadingFile(".pas");
+ if (!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"), fileName);
+ str.replace(QRegExp("%filepath%"), file.name());
+ pas << str << endl;
+ }
+
+ QString unit = qualifiedName(c);
+ pas << "unit " << unit << ";" << m_endl << m_endl;
+ pas << "INTERFACE" << m_endl << m_endl;
+ // Use referenced classes.
+ UMLPackageList imports;
+ findObjectsRelated(c, imports);
+ if (imports.count()) {
+ pas << "uses" << m_endl;
+ bool first = true;
+ for (UMLPackage *con = imports.first(); con; con = imports.next()) {
+ if (con->getBaseType() != Uml::ot_Datatype) {
+ if (first)
+ first = false;
+ else
+ pas << "," << m_endl;
+ pas << " " << qualifiedName(con);
+ }
+ }
+ pas << ";" << m_endl << m_endl;
+ }
+
+ pas << "type" << m_endl;
+ m_indentLevel++;
+ if (c->getBaseType() == Uml::ot_Enum) {
+ UMLEnum *ue = static_cast<UMLEnum*>(c);
+ UMLClassifierListItemList litList = ue->getFilteredList(Uml::ot_EnumLiteral);
+ uint i = 0;
+ pas << getIndent() << classname << " = (" << m_endl;
+ m_indentLevel++;
+ for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) {
+ QString enumLiteral = cleanName(lit->getName());
+ pas << getIndent() << enumLiteral;
+ if (++i < litList.count())
+ pas << "," << m_endl;
+ }
+ m_indentLevel--;
+ pas << ");" << m_endl << m_endl;
+ m_indentLevel--;
+ pas << "end." << m_endl << m_endl;
+ return;
+ }
+ UMLAttributeList atl = c->getAttributeList();
+ if (! isOOClass(c)) {
+ QString stype = c->getStereotype();
+ if (stype == "CORBAConstant") {
+ pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else if(stype == "CORBAStruct") {
+ if (isClass) {
+ UMLAttribute *at;
+ pas << getIndent() << classname << " = record" << m_endl;
+ m_indentLevel++;
+ for (at = atl.first(); at; at = atl.next()) {
+ QString name = cleanName(at->getName());
+ QString typeName = at->getTypeName();
+ pas << getIndent() << name << " : " << typeName;
+ QString initialVal = at->getInitialValue();
+ if (initialVal.latin1() && ! initialVal.isEmpty())
+ pas << " := " << initialVal;
+ pas << ";" << m_endl;
+ }
+ m_indentLevel--;
+ pas << "end;" << m_endl << m_endl;
+ }
+ } else if(stype == "CORBAUnion") {
+ pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else if(stype == "CORBATypedef") {
+ pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
+ } else {
+ pas << getIndent() << "// " << stype << ": Unknown stereotype" << m_endl << m_endl;
+ }
+ m_indentLevel--;
+ pas << getIndent() << "end." << m_endl << m_endl;
+ return;
+ }
+
+ // Write class Documentation if non-empty or if force option set.
+ if (forceDoc() || !c->getDoc().isEmpty()) {
+ pas << "//" << m_endl;
+ pas << "// class " << classname << endl;
+ pas << formatDoc(c->getDoc(), "// ");
+ pas << m_endl;
+ }
+
+ UMLClassifierList superclasses = c->getSuperClasses();
+
+ pas << getIndent() << classname << " = object";
+ if (!superclasses.isEmpty()) {
+ // FIXME: Multiple inheritance is not yet supported
+ UMLClassifier* parent = superclasses.first();
+ pas << "(" << qualifiedName(parent) << ")";
+ }
+ pas << m_endl;
+
+ ClassifierInfo info(c);
+ UMLAttributeList atpub = info.atpub;
+ if (isClass && (forceSections() || atpub.count())) {
+ pas << getIndent() << "// Public attributes:" << m_endl;
+ UMLAttribute *at;
+ for (at = atpub.first(); at; at = atpub.next()) {
+ // if (at->getStatic())
+ // continue;
+ pas << getIndent() << cleanName(at->getName()) << " : "
+ << at->getTypeName();
+ if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
+ pas << " := " << at->getInitialValue();
+ pas << ";" << m_endl;
+ }
+ }
+ bool haveAttrs = (isClass && atl.count());
+
+ // Generate public operations.
+ UMLOperationList opl(c->getOpList());
+ UMLOperationList oppub;
+ oppub.setAutoDelete(false);
+ UMLOperation *op;
+ for (op = opl.first(); op; op = opl.next()) {
+ if (op->getVisibility() == Uml::Visibility::Public)
+ oppub.append(op);
+ }
+ if (forceSections() || oppub.count())
+ pas << getIndent() << "// Public methods:" << m_endl << m_endl;
+ for (op = oppub.first(); op; op = oppub.next())
+ writeOperation(op, pas);
+
+ if (info.atprot.count()) {
+ pas << "protected" << m_endl << m_endl;
+ UMLAttribute *at;
+ UMLAttributeList atprot = info.atprot;
+ for (at = atprot.first(); at; at = atprot.next()) {
+ // if (at->getStatic())
+ // continue;
+ pas << getIndent() << cleanName(at->getName()) << " : "
+ << at->getTypeName();
+ if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
+ pas << " := " << at->getInitialValue();
+ pas << ";" << m_endl;
+ }
+ pas << m_endl;
+ }
+ if (info.atpriv.count()) {
+ pas << "private" << m_endl << m_endl;
+ UMLAttribute *at;
+ UMLAttributeList atpriv = info.atpriv;
+ for (at = atpriv.first(); at; at = atpriv.next()) {
+ // if (at->getStatic())
+ // continue;
+ pas << getIndent() << cleanName(at->getName()) << " : "
+ << at->getTypeName();
+ if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
+ pas << " := " << at->getInitialValue();
+ pas << ";" << m_endl;
+ }
+ pas << m_endl;
+ }
+ pas << getIndent() << "end;" << m_endl << m_endl;
+
+ pas << getIndent() << "P" << classname << " = ^" << classname <<";" << m_endl << m_endl;
+
+ m_indentLevel--;
+ pas << "end;" << m_endl << m_endl;
+ file.close();
+ emit codeGenerated(c, true);
+}
+
+
+void PascalWriter::writeOperation(UMLOperation *op, QTextStream &pas, bool is_comment) {
+ if (op->getStatic()) {
+ pas << "// TODO: generate status method " << op->getName() << m_endl;
+ return;
+ }
+ UMLAttributeList atl = op->getParmList();
+ QString rettype = op->getTypeName();
+ bool use_procedure = (rettype.isEmpty() || rettype == "void");
+
+ pas << getIndent();
+ if (is_comment)
+ pas << "// ";
+ if (use_procedure)
+ pas << "procedure ";
+ else
+ pas << "function ";
+ pas << cleanName(op->getName()) << " ";
+ if (atl.count()) {
+ pas << "(" << m_endl;
+ uint i = 0;
+ m_indentLevel++;
+ for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
+ pas << getIndent();
+ if (is_comment)
+ pas << "// ";
+ pas << cleanName(at->getName()) << " : ";
+ Uml::Parameter_Direction pk = at->getParmKind();
+ if (pk != Uml::pd_In)
+ pas << "var ";
+ pas << at->getTypeName();
+ if (! at->getInitialValue().isEmpty())
+ pas << " := " << at->getInitialValue();
+ if (++i < (uint)atl.count())
+ pas << ";" << m_endl;
+ }
+ m_indentLevel--;
+ pas << ")";
+ }
+ if (! use_procedure)
+ pas << " : " << rettype;
+ pas << "; virtual; abstract;" << m_endl << m_endl;
+ // TBH, we make the methods abstract here because we don't have the means
+ // for generating meaningful implementations.
+}
+
+QStringList PascalWriter::defaultDatatypes() {
+ QStringList l;
+ l.append("AnsiString");
+ l.append("Boolean");
+ l.append("Byte");
+ l.append("ByteBool");
+ l.append("Cardinal");
+ l.append("Character");
+ l.append("Currency");
+ l.append("Double");
+ l.append("Extended");
+ l.append("Int64");
+ l.append("Integer");
+ l.append("Longint");
+ l.append("LongBool");
+ l.append("Longword");
+ l.append("QWord");
+ l.append("Real");
+ l.append("Shortint");
+ l.append("ShortString");
+ l.append("Single");
+ l.append("Smallint");
+ l.append("String");
+ l.append("WideString");
+ l.append("Word");
+ return l;
+}
+
+/**
+ * Check whether the given string is a reserved word for the
+ * language of this code generator
+ *
+ * @param rPossiblyReservedKeyword The string to check.
+ */
+bool PascalWriter::isReservedKeyword(const QString & rPossiblyReservedKeyword) {
+
+ const QStringList keywords = reservedKeywords();
+
+ QStringList::ConstIterator it;
+ for (it = keywords.begin(); it != keywords.end(); ++it)
+ if ((*it).lower() == rPossiblyReservedKeyword.lower())
+ return true;
+
+ return false;
+}
+
+/**
+ * get list of reserved keywords
+ */
+const QStringList PascalWriter::reservedKeywords() const {
+
+ static QStringList keywords;
+
+ if ( keywords.isEmpty() ) {
+ keywords.append( "absolute" );
+ keywords.append( "abstract" );
+ keywords.append( "and" );
+ keywords.append( "array" );
+ keywords.append( "as" );
+ keywords.append( "asm" );
+ keywords.append( "assembler" );
+ keywords.append( "automated" );
+ keywords.append( "begin" );
+ keywords.append( "case" );
+ keywords.append( "cdecl" );
+ keywords.append( "class" );
+ keywords.append( "const" );
+ keywords.append( "constructor" );
+ keywords.append( "contains" );
+ keywords.append( "default" );
+ keywords.append( "deprecated" );
+ keywords.append( "destructor" );
+ keywords.append( "dispid" );
+ keywords.append( "dispinterface" );
+ keywords.append( "div" );
+ keywords.append( "do" );
+ keywords.append( "downto" );
+ keywords.append( "dynamic" );
+ keywords.append( "else" );
+ keywords.append( "end" );
+ keywords.append( "except" );
+ keywords.append( "export" );
+ keywords.append( "exports" );
+ keywords.append( "external" );
+ keywords.append( "far" );
+ keywords.append( "file" );
+ keywords.append( "final" );
+ keywords.append( "finalization" );
+ keywords.append( "finally" );
+ keywords.append( "for" );
+ keywords.append( "forward" );
+ keywords.append( "function" );
+ keywords.append( "goto" );
+ keywords.append( "if" );
+ keywords.append( "implementation" );
+ keywords.append( "implements" );
+ keywords.append( "in" );
+ keywords.append( "index" );
+ keywords.append( "inherited" );
+ keywords.append( "initialization" );
+ keywords.append( "inline" );
+ keywords.append( "inline" );
+ keywords.append( "interface" );
+ keywords.append( "is" );
+ keywords.append( "label" );
+ keywords.append( "library" );
+ keywords.append( "library" );
+ keywords.append( "local" );
+ keywords.append( "message" );
+ keywords.append( "mod" );
+ keywords.append( "name" );
+ keywords.append( "near" );
+ keywords.append( "nil" );
+ keywords.append( "nodefault" );
+ keywords.append( "not" );
+ keywords.append( "object" );
+ keywords.append( "of" );
+ keywords.append( "or" );
+ keywords.append( "out" );
+ keywords.append( "overload" );
+ keywords.append( "override" );
+ keywords.append( "package" );
+ keywords.append( "packed" );
+ keywords.append( "pascal" );
+ keywords.append( "platform" );
+ keywords.append( "private" );
+ keywords.append( "procedure" );
+ keywords.append( "program" );
+ keywords.append( "property" );
+ keywords.append( "protected" );
+ keywords.append( "public" );
+ keywords.append( "published" );
+ keywords.append( "raise" );
+ keywords.append( "read" );
+ keywords.append( "readonly" );
+ keywords.append( "record" );
+ keywords.append( "register" );
+ keywords.append( "reintroduce" );
+ keywords.append( "repeat" );
+ keywords.append( "requires" );
+ keywords.append( "resident" );
+ keywords.append( "resourcestring" );
+ keywords.append( "safecall" );
+ keywords.append( "sealed" );
+ keywords.append( "set" );
+ keywords.append( "shl" );
+ keywords.append( "shr" );
+ keywords.append( "static" );
+ keywords.append( "stdcall" );
+ keywords.append( "stored" );
+ keywords.append( "string" );
+ keywords.append( "then" );
+ keywords.append( "threadvar" );
+ keywords.append( "to" );
+ keywords.append( "try" );
+ keywords.append( "type" );
+ keywords.append( "unit" );
+ keywords.append( "unsafe" );
+ keywords.append( "until" );
+ keywords.append( "uses" );
+ keywords.append( "var" );
+ keywords.append( "varargs" );
+ keywords.append( "virtual" );
+ keywords.append( "while" );
+ keywords.append( "with" );
+ keywords.append( "write" );
+ keywords.append( "writeonly" );
+ keywords.append( "xor" );
+ }
+
+ return keywords;
+}
+
+#include "pascalwriter.moc"