QByteArray K3BookmarkDrag::encodedData( const char* mime ) const { QByteArray a; Q3CString mimetype( mime ); if ( mimetype == "text/uri-list" ) return Q3UriDrag::encodedData( mime ); else if ( mimetype == "application/x-xbel" ) { a = m_doc.toByteArray(); //kDebug(7043) << "K3BookmarkDrag::encodedData " << m_doc.toCString(); } else if ( mimetype == "text/plain" ) { KUrl::List m_lstDragURLs; if ( K3URLDrag::decode( this, m_lstDragURLs ) ) { QStringList uris; KUrl::List::ConstIterator uit = m_lstDragURLs.constBegin(); KUrl::List::ConstIterator uEnd = m_lstDragURLs.constEnd(); for ( ; uit != uEnd ; ++uit ) uris.append( (*uit).prettyUrl() ); Q3CString s = uris.join( "\n" ).toLocal8Bit(); a.resize( s.length() + 1 ); // trailing zero memcpy( a.data(), s.data(), s.length() + 1 ); } } return a; }
bool nequal(const Q3CString & s1, const Q3CString & s2) { // don't take into account first and last white spaces (like a stripWhiteSpace()) const char * p1 = (s1.isNull()) ? "" : (const char *) s1; const char * p2 = (s2.isNull()) ? "" : (const char *) s2; const char * e1 = p1 + s1.length(); const char * e2 = p2 + s2.length(); while ((p1 != e1) && is_white_space(p1[0])) p1 += 1; while ((p2 != e2) && is_white_space(p2[0])) p2 += 1; while ((e1 != p1) && is_white_space(e1[-1])) e1 -= 1; while ((e2 != p2) && is_white_space(e2[-1])) e2 -= 1; for (;;) { if (p1 >= e1) return (p2 < e2); if (*p1 != *p2) return TRUE; while (*++p1 == '\r') ; while (*++p2 == '\r') ; } }
static void manage_decorators(QTextOStream & f, const Q3CString & decorators, QString indent, BooL & indent_needed) { if (! decorators.isEmpty()) { int index = 0; int index2; while ((index2 = decorators.find("\n", index)) != -1){ if (indent_needed) f << indent; else indent_needed = TRUE; f << decorators.mid(index, index2 + 1 - index); index = index2 + 1; } if (index != (int) decorators.length()) { if (indent_needed) { f << indent; indent_needed = FALSE; } f << decorators.mid(index); } } }
void Q3Url::encode( QString& url ) { if ( url.isEmpty() ) return; Q3CString curl = url.utf8(); int oldlen = curl.length(); const Q3CString special( "+<>#@\"&%$:,;?={}|^~[]\'`\\ \n\t\r" ); QString newUrl; int newlen = 0; for ( int i = 0; i < oldlen ;++i ) { uchar inCh = (uchar)curl[ i ]; if ( inCh >= 128 || special.contains(inCh) ) { newUrl[ newlen++ ] = QLatin1Char( '%' ); ushort c = inCh / 16; c += c > 9 ? 'A' - 10 : '0'; newUrl[ newlen++ ] = c; c = inCh % 16; c += c > 9 ? 'A' - 10 : '0'; newUrl[ newlen++ ] = c; } else { newUrl[ newlen++ ] = inCh; } } url = newUrl; }
bool UmlClass::replaceType(UmlTypeSpec & t, Q3CString & target_id, const Q3CString & ts) { UmlClass * cl = (UmlClass *) findItem(target_id, aClass); bool result = FALSE; if (cl != 0) { int index = 0; const Q3CString & s = cl->name(); unsigned ln1 = s.length(); unsigned ln2 = ts.length(); while ((index = t.explicit_type.find(s, index)) != -1) { if (((index == 0) || isSep(((const char *) t.explicit_type)[index - 1])) && isSep(((const char *) t.explicit_type)[index + (int) ln1])) { t.explicit_type.replace((unsigned) index, ln1, ts); index += ln2; result = TRUE; } else index += 1; } } if (result) { target_id = t.explicit_type; t.explicit_type = 0; t.type = cl; } return result; }
void UmlItem::replace_alias(Q3CString & s) { int index = 0; while ((index = s.find("@{", index)) != -1) { int index2 = s.find('}', index + 2); if (index2 == -1) return; UmlBaseItem * obj = this; Q3CString key = s.mid(index + 2, index2 - index - 2); Q3CString value; for (;;) { if (obj->propertyValue(key, value)) { s.replace(index, index2 - index + 1, value); index += value.length(); break; } else if ((obj = obj->parent()) == 0) { index = index2 + 1; break; } } } }
int XmlProtocol::internalWriteString(const QString &s, TrackItem::Type t, int id) { QString out=ensureGTEncoded(s); Q3CString cs = s.utf8(); QByteArray a(cs.length()); memcpy(a.data(), cs.data(), a.size()); return internalWriteData(a, t, id); }
void UmlClass::write(QTextOStream & f, const UmlTypeSpec & t, bool with_formals, BooL * is_template) { if (t.type != 0) t.type->write(f, with_formals, is_template); else { Q3CString s = CppSettings::type(t.explicit_type); f << s; if (is_template != 0) *is_template = (!s.isEmpty() && (s.at(s.length() - 1) == '>')); } }
// remove first and last line in comment if non significant Q3CString Lex::simplify_comment(Q3CString & comment) { if (comment.isEmpty()) return comment; const char * s = comment; const char * p = s; for (;;) { switch (*p) { case 0: return comment; case ' ': case '\t': p += 1; break; case '\n': comment.remove(0, p - s + 1); if (comment.isEmpty()) return comment; s = comment; // no break default: p = s + comment.length() - 1; while (p != s) { switch(*p) { case ' ': case '\t': p -= 1; break; case '\n': comment.resize(p - s + 1); // no break default: return comment; } } if (*p == '\n') comment = ""; return comment; } } }
void UmlItem::manage_docstring(const char *& p, const char *& pp, BooL & indent_needed, Q3CString & indent, Q3CString & saved_indent) { static Q3CString the_comment; p += 12; the_comment = description(); if ((pp != 0) || // comment contains ${description} ! the_comment.isEmpty()) return; int index = 0; while ((index = the_comment.find("\"\"\"", index)) != -1) { the_comment.insert(index, "\\"); index += 2; } if (!indent.isEmpty()) { int len = indent.length() + 1; index = 0; while ((index = the_comment.find('\n', index)) != -1) { the_comment.insert(index + 1, (const char*)indent); index += len; } } the_comment = "\"\"\"" + the_comment + "\"\"\"\n"; if (indent_needed) { indent_needed = FALSE; the_comment = indent + the_comment; } pp = p; p = the_comment; saved_indent = indent; indent = ""; }
void Q3Url::decode( QString& url ) { if ( url.isEmpty() ) return; int newlen = 0; Q3CString curl = url.utf8(); int oldlen = curl.length(); Q3CString newUrl(oldlen); int i = 0; while ( i < oldlen ) { uchar c = (uchar)curl[ i++ ]; if ( c == '%' && i <= oldlen - 2 ) { c = hex_to_int( (uchar)curl[ i ] ) * 16 + hex_to_int( (uchar)curl[ i + 1 ] ); i += 2; } newUrl [ newlen++ ] = c; } newUrl.truncate( newlen ); url = QString::fromUtf8(newUrl.data()); }
void ClassContainer::compute_type(Q3CString type, UmlTypeSpec & typespec, Q3CString & typeform, bool get_first_template_actual, const Q3ValueList<FormalParameterList> & tmplts) { typespec.type = 0; typespec.explicit_type = 0; if (!strncmp((const char *) type, "struct ", 7) || !strncmp((const char *) type, "union ", 6) || !strncmp((const char *) type, "enum ", 5)) { typespec.explicit_type = "<complex type>"; typeform = type; return; } int index; if (get_first_template_actual && ((index = type.find('<')) != -1)) { type = Lex::normalize(type); index = type.find('<'); const char * p = type; if (strncmp(p + index + 1, "const ", 6) == 0) index += 6; // look at each actual in <> unsigned level = 1; int index2; Q3CString tf1; Q3CString t1; for (;;) { // earch for the current arg end for (index2 = index + 1; p[index2]; index2 += 1) { char c = p[index2]; if ((c == ',') || (c == '*') || (c == '[') || (c == '&')) { if (level == 1) break; } else if (c == '<') level += 1; else if ((c == '>') && (--level == 0)) break; } if (p[index2]) { Q3CString tf = type.left(index + 1) + typeform + type.mid(index2); Q3CString t = type.mid(index + 1, index2 - index - 1).stripWhiteSpace(); #ifdef DEBUG_BOUML cout << "typeform '" << tf << "' type '" << t << "'\n"; #endif UmlTypeSpec ts; Q3CString normalized = Lex::normalize(t); if (!find_type(normalized, ts) && (Namespace::current().isEmpty() || (normalized.at(0) == ':') || !find_type("::" + normalized, ts))) { if (get_first_template_actual) { get_first_template_actual = FALSE; tf1 = tf; t1 = t; } index = index2; } else { // find a class typeform = tf; type = t; typespec.type = ts.type; break; } } else if (!get_first_template_actual) { // has first actual typeform = tf1; type = t1; break; } else { typespec.explicit_type = type; return; } } } if (! tmplts.isEmpty()) { Q3ValueList<FormalParameterList>::ConstIterator it1; for (it1 = tmplts.begin(); it1 != tmplts.end(); ++it1) { FormalParameterList::ConstIterator it2; for (it2 = (*it1).begin(); it2 != (*it1).end(); ++it2) { if ((*it2).name() == type) { typespec.type = 0; typespec.explicit_type = type; return; } } } } Q3CString normalized; if (typespec.type == 0) { normalized = Lex::normalize(type); if (!find_type(normalized, typespec) && (Namespace::current().isEmpty() || (normalized.at(0) == ':') || !find_type("::" + normalized, typespec))) { typespec.explicit_type = CppSettings::umlType(type); if (typespec.explicit_type.isEmpty()) { // search for equivalent forms if (type == "long int") typespec.explicit_type = CppSettings::umlType("long"); else if (type == "long") typespec.explicit_type = CppSettings::umlType("long int"); else if (type == "unsigned long int") typespec.explicit_type = CppSettings::umlType("unsigned long"); else if (type == "unsigned long") typespec.explicit_type = CppSettings::umlType("unsigned long int"); else if (type == "unsigned") typespec.explicit_type = CppSettings::umlType("unsigned int"); else if (type == "unsigned int") typespec.explicit_type = CppSettings::umlType("unsigned"); else if ((type == "signed") || (type == "signed int")) typespec.explicit_type = CppSettings::umlType("int"); } if (typespec.explicit_type.isEmpty()) { typespec.explicit_type = type; /* if (!Lex::identifierp(type, TRUE)) typespec.explicit_type = type; else { Q3CString t = type; while ((index = t.find(':')) == 0) t = t.mid(1); ClassContainer * cc = Package::unknown(); while (index != -1) { if ((cc = cc->declare_if_needed(t.left(index))) == 0) { typespec.explicit_type = type; return; } while (t[index] == ':') index += 1; t = t.mid(index); index = t.find(':'); } if (((cc = cc->declare_if_needed(t)) == 0) || ((typespec.type = ((Class *) cc)->get_uml()) == 0)) typespec.explicit_type = type; }*/ } typespec.type = 0; } } if ((typespec.type != 0) && !typespec.type->formals().isEmpty() && (type.at(type.length() - 1) == '>') && (!typespec.type->inside_its_definition() || !typespec.type->is_itself((normalized.isEmpty()) ? Lex::normalize(type) : normalized))) { typespec.type = 0; typespec.explicit_type = type; } }
void UmlClass::write(QTextOStream & f, bool with_formals, BooL * is_template, const Q3ValueList<UmlActualParameter> & actuals) { if (context.findRef(this) == -1) { if (parent()->kind() == aClass) { if (context.findRef((UmlClass *) parent()) == -1) { // parent cannot have formals, but may have actuals ((UmlClass *) parent())->write(f, FALSE, 0, actuals); f << "::"; } } else { UmlArtifact * cp = associatedArtifact(); Q3CString nasp = ((UmlPackage *) ((cp != 0) ? (UmlItem *) cp : (UmlItem *) this)->package()) ->cppNamespace(); if (CppSettings::isForceNamespacePrefixGeneration() || (nasp != UmlArtifact::generation_package()->cppNamespace())) f << nasp << "::"; } } Q3CString s; if (isCppExternal()) { s = cppDecl(); int index = s.find('\n'); s = (index == -1) ? s.stripWhiteSpace() : s.left(index).stripWhiteSpace(); if ((index = s.find("${name}")) != -1) s.replace(index, 7, name()); else if ((index = s.find("${Name}")) != -1) s.replace(index, 7, capitalize(name())); else if ((index = s.find("${NAME}")) != -1) s.replace(index, 7, name().upper()); else if ((index = s.find("${nAME}")) != -1) s.replace(index, 7, name().lower()); } else s = name(); // true_name if (! s.isEmpty()){ f << s; if (is_template != 0) *is_template = (s.at(s.length() - 1) == '>'); } else if (is_template != 0) *is_template = FALSE; if (with_formals) { Q3ValueList<UmlFormalParameter> formals = this->formals(); if (! formals.isEmpty()) { const char * sep = "<"; Q3ValueList<UmlFormalParameter>::ConstIterator it; for (it = formals.begin(); it != formals.end(); ++it) { f << sep << (*it).name(); sep = ", "; } f << '>'; if (is_template != 0) *is_template = TRUE; } } else if (!actuals.isEmpty()) { Q3ValueList<UmlActualParameter>::ConstIterator ita; BooL need_space = FALSE; bool used = FALSE; for (ita = actuals.begin(); ita != actuals.end(); ++ita) { if ((*ita).superClass() == this) { used = TRUE; (*ita).generate(f, need_space); } } if (used) { if (need_space) f << " >"; else f << '>'; if (is_template != 0) *is_template = TRUE; } } }
// Between template < and > I suppose that a type is not included // because I cannot know how the type is used and I do not want to // produce circular #include bool UmlClassMember::compute_dependency(Q3PtrList<CppRefType> & dependencies, Q3CString decl, const UmlTypeSpec & t, bool force_incl) { remove_comments(decl); remove_preprocessor(decl); remove_arrays(decl); int template_level = 0; bool have_type = FALSE; const char * p = decl; const char * dontsubstituteuntil = 0; for (;;) { UmlTypeSpec ts; char c; bool dontsearchend = FALSE; // search word beginning while ((c = *p) != 0) { if ((c == '_') || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) break; else if (dontsubstituteuntil != 0) { if (p >= dontsubstituteuntil) dontsubstituteuntil = 0; else p += 1; } else if (c == '=') // init, all is done return have_type; else if (!strncmp(p, "${type}", 7)) { p += 7; ts = t; if (ts.type != 0) { dontsearchend = TRUE; break; } else { decl = ts.explicit_type + p; p = decl; } } else { switch (c) { case '<': template_level += 1; break; case '>': template_level -= 1; } p += 1; } } if (c == 0) return have_type; if (!dontsearchend) { // search word end const char * p2 = p; ts.type = 0; ts.explicit_type = p2; p += 1; while ((c = *p) != 0) { if ((c == '_') || (c == ':') || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9'))) p += 1; else { ts.explicit_type.truncate(p - p2); break; } } //#warning NAMESPACE if (dontsubstituteuntil == 0) { Q3CString subst = CppSettings::type(ts.explicit_type); if (subst != ts.explicit_type) { decl = subst + ' ' + p; p = decl; dontsubstituteuntil = p + subst.length(); continue; } } } // check manually added keyword if ((ts.explicit_type == "const") || (ts.explicit_type == "static")) continue; // search for a * or & or < after the typename bool incl = (template_level == 0); while ((c = *p) != 0) { if ((c == '*') || (c == '&')) { incl = FALSE; p += 1; break; } if ((c == '<') || (c == '>') || (c == '(') || (c == ')') || (c == ',') || (c == '_') || (c == '$') || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) { break; } p += 1; } if (CppRefType::add(ts, dependencies, force_incl || incl)) have_type = TRUE; } return have_type; }
void tst_Q3CString::acc_01() { Q3CString a; Q3CString b; //b(10); Q3CString bb; //bb((int)0); Q3CString c("String C"); char tmp[10]; tmp[0] = 'S'; tmp[1] = 't'; tmp[2] = 'r'; tmp[3] = 'i'; tmp[4] = 'n'; tmp[5] = 'g'; tmp[6] = ' '; tmp[7] = 'D'; tmp[8] = 'X'; tmp[9] = '\0'; Q3CString d(tmp,8); Q3CString ca(a); Q3CString cb(b); Q3CString cc(c); Q3CString n; Q3CString e("String E"); Q3CString f; f = e; f.detach(); f[7]='F'; QCOMPARE(e,(Q3CString)"String E"); char text[]="String f"; f = text; text[7]='!'; QCOMPARE(f,(Q3CString)"String f"); f[7]='F'; QCOMPARE(text[7],'!'); #if 0 a=""; a[0]='A'; Q3CString res = "A"; QCOMPARE(a,res); QCOMPARE(a.length(),(uint)1); compare(a.length(),(uint)1); a[1]='B'; QCOMPARE(a,(Q3CString)"AB"); QCOMPARE(a.length(),(uint)2); a[2]='C'; QCOMPARE(a,(Q3CString)"ABC"); QCOMPARE(a.length(),(uint)3); a = Q3CString(); QVERIFY(a.isNull()); a[0]='A'; QCOMPARE(a,(Q3CString)"A"); QCOMPARE(a.length(),(uint)1); a[1]='B'; QCOMPARE(a,(Q3CString)"AB"); QCOMPARE(a.length(),(uint)2); a[2]='C'; QCOMPARE(a,(Q3CString)"ABC"); QCOMPARE(a.length(),(uint)3); #endif a="123"; b="456"; a[0]=a[1]; QCOMPARE(a,(Q3CString)"223"); a[1]=b[1]; QCOMPARE(b,(Q3CString)"456"); QCOMPARE(a,(Q3CString)"253"); char t[]="TEXT"; a="A"; a=t; QCOMPARE(a,(Q3CString)"TEXT"); QCOMPARE(a,(Q3CString)t); a[0]='X'; QCOMPARE(a,(Q3CString)"XEXT"); QCOMPARE(t[0],'T'); t[0]='Z'; QCOMPARE(a,(Q3CString)"XEXT"); a="ABC"; QCOMPARE(((const char*)a)[1],'B'); QCOMPARE(strcmp(a,(Q3CString)"ABC"),0); a += "DEF"; QCOMPARE(a, (Q3CString)"ABCDEF"); a += 'G'; QCOMPARE(a, (Q3CString)"ABCDEFG"); a += ((const char*)(0)); QCOMPARE(a, (Q3CString)"ABCDEFG"); // non-member operators a="ABC"; b="ABC"; c="ACB"; d="ABCD"; QVERIFY(a==b); QVERIFY(!(a==d)); QVERIFY(!(a!=b)); QVERIFY(a!=d); QVERIFY(!(a<b)); QVERIFY(a<c); QVERIFY(a<d); QVERIFY(!(d<a)); QVERIFY(!(c<a)); QVERIFY(a<=b); QVERIFY(a<=d); QVERIFY(a<=c); QVERIFY(!(c<=a)); QVERIFY(!(d<=a)); QCOMPARE(a+b,(Q3CString)"ABCABC"); QCOMPARE(a +"XXXX",(Q3CString)"ABCXXXX"); QCOMPARE(a+'X',(Q3CString)"ABCX"); QCOMPARE("XXXX"+a,(Q3CString)"XXXXABC"); QCOMPARE('X'+a,(Q3CString)"XABC"); a = (const char*)0; QVERIFY(a.isNull()); QVERIFY(*((const char *)a) == 0); { QFile f("COMPARE.txt"); f.open( QIODevice::WriteOnly ); QTextStream ts( &f ); ts.setEncoding(QTextStream::Unicode); ts << "Abc"; } }
void UmlArtifact::gen_app(const Q3CString & path) { Q3CString target; Q3CString pro; propertyValue("genpro target", target); propertyValue("genpro pro", pro); if (target.isEmpty()) { if ((target = name()) == "executable") target = UmlPackage::getProject()->name(); #ifdef WIN32 target += ".exe"; #endif } if (pro.isEmpty()) { pro = target; #ifdef WIN32 if (pro.right(4) == ".exe") pro.resize(pro.length() - 4); #endif QDir d(path); pro = d.absFilePath(pro + ".pro"); } Q3CString tmplt; Q3CString config; Q3CString defines; Q3CString includepath; Q3CString dependpath; Q3CString objectsdir; Q3CString footer; if (!propertyValue("genpro tmplt", tmplt)) tmplt = "app"; if (!propertyValue("genpro config", config)) config = "debug warn_on qt"; if (!propertyValue("genpro defines", defines)) defines = "WITHCPP WITHJAVA WITHPHP WITHPYTHON WITHIDL"; else if (defines.find("WITHPHP") == -1) { int n = 0; if (defines.find("WITHCPP") != -1) n += 1; if (defines.find("WITHJAVA") != -1) n += 1; if (defines.find("WITHIDL") != -1) n += 1; if (n > 1) defines += " WITHPHP WITHPYTHON"; } else if (defines.find("WITHPYTHON") == -1) { int n = 0; if (defines.find("WITHCPP") != -1) n += 1; if (defines.find("WITHJAVA") != -1) n += 1; if (defines.find("WITHIDL") != -1) n += 1; if (defines.find("WITHPHP") != -1) n += 1; if (n > 1) defines += " WITHPYTHON"; } propertyValue("genpro includepath", includepath); propertyValue("genpro dependpath", dependpath); propertyValue("genpro objectsdir", objectsdir); propertyValue("genpro footer", footer); for (;;) { Dialog dialog(this, path, pro, target, tmplt, config, defines, includepath, dependpath, objectsdir, footer); if (dialog.exec() != QDialog::Accepted) return; set_PropertyValue("genpro pro", pro); set_PropertyValue("genpro path", path); set_PropertyValue("genpro target", target); set_PropertyValue("genpro tmplt", tmplt); set_PropertyValue("genpro config", config); set_PropertyValue("genpro defines", defines); set_PropertyValue("genpro includepath", includepath); set_PropertyValue("genpro dependpath", dependpath); set_PropertyValue("genpro objectsdir", objectsdir); set_PropertyValue("genpro footer", footer); QFile f(pro); if (! f.open(QIODevice::WriteOnly)) QMessageBox::critical((QWidget *) 0, "Error", "Cannot open " + QString(pro)); else { Q3TextStream t(&f); QFileInfo tfi(target); QFileInfo pfi(pro); t << "TEMPLATE\t= " << tmplt << '\n'; t << "TARGET\t\t= " << tfi.fileName() << '\n'; if ((target.find('/') != -1) && (pro.find('/') != -1) && (tfi.dirPath(TRUE) != pfi.dirPath(TRUE))) t << "DESTDIR\t\t= " << tfi.dirPath(TRUE) << '\n'; if (! objectsdir.isEmpty()) t << "OBJECTS_DIR\t= " << objectsdir << '\n'; t << "CONFIG\t\t+= " << config << '\n'; if (!includepath.isEmpty()) t << "INCLUDEPATH\t= " << includepath << '\n'; if (!dependpath.isEmpty()) t << "DEPENDPATH\t= " << dependpath << '\n'; if (!defines.isEmpty()) t << "DEFINES\t\t= " << defines << '\n'; QString prodir = pfi.dirPath(TRUE); const Q3PtrVector<UmlArtifact> & arts = associatedArtifacts(); unsigned index; const char * sep; Q3CString ext; ext = CppSettings::headerExtension(); sep = "HEADERS\t\t= "; for (index = 0; index != arts.count(); index += 1) { UmlArtifact * art = arts[index]; if ((art->stereotype() == "source") && !art->cppHeader().isEmpty()) { QString s = art->way(prodir, TRUE); if (! s.isEmpty()) { t << sep << s << art->name() << '.' << ext; sep = " \\\n\t\t "; } } } t << '\n'; ext = CppSettings::sourceExtension(); sep = "SOURCES\t\t= "; for (index = 0; index != arts.count(); index += 1) { UmlArtifact * art = arts[index]; if ((art->stereotype() != "source") || !art->cppSource().isEmpty()) { QString s = art->way(prodir, FALSE); if (! s.isEmpty()) { t << sep << s << art->name(); if (art->stereotype() == "source") t << '.' << ext; sep = " \\\n\t\t "; } } } t << '\n' << footer << '\n'; f.close(); return; } } }
Q3CString Lex::normalize(const Q3CString & s) { int index = s.find('<'); if (index == -1) return s; Q3CString r; const char * p = s; index = 0; for (;;) { char c = *p++; switch (c) { case 0: return r; case '<': if (!r.isEmpty() && (r.at(r.length() - 1) == ' ')) r.truncate(r.length() - 1); r += '<'; break; case '>': if (!r.isEmpty() && (r.at(r.length() - 1) == '>')) r += " >"; else r += '>'; break; case '/': if (*p == '/') { // comment p += 1; do p += 1; while (*p && (*p != '\n')); } else if (*p == '*') { /* comment */ p += 1; do p += 1; while (*p && ((*p != '*') || (p[1] != '/'))); p += 2; } else { if (!r.isEmpty() && (r.at(r.length() - 1) == ' ')) r.truncate(r.length() - 1); } break; case '#': do { if (*++p == '\\') p += 2; else if ((*p == '/') && (p[1] == '*')) { /* comment */ p += 1; do p += 1; while (*p && ((*p != '*') || (p[1] != '/'))); p += 2; } } while (*p && (*p != '\n')); break; case '"': if (!r.isEmpty() && (r.at(r.length() - 1) == '"') && (p[-2] != '"')) r += ' '; do { if (*++p == '\\') p += 2; } while (*p && (*p != '"')); break; case '\'': if (!r.isEmpty() && (r.at(r.length() - 1) == ' ')) r.truncate(r.length() - 1); do { if (*++p == '\\') p += 2; } while (*p && (*p != '\'')); break; case ':': if (!r.isEmpty() && (p[-2] <= ' ')) r += " :"; else r += ':'; break; default: if (c > ' ') { if (::identifierp(c)) { if (!r.isEmpty() && ::identifierp(r.at(r.length() - 1))) r += ' '; r += c; while ((*p == ':') || ::identifierp(*p)) r += *p++; } else r += c; } } } return r; }
bool UmlOperation::new_one(Class * container, aVisibility visibility, bool finalp, bool abstractp, bool staticp, Q3CString comment, Q3CString description) { // 'function' was read, it is followed by : // ['&'] name'(' {'array' | <classname>] ['&'] '$'<varname> ['=' <value>]}* ')' '{' ... '}' Q3CString s = Lex::read_word(); bool refp; if (s == "&") { refp = TRUE; s = Lex::read_word(); } else refp = FALSE; if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } Q3CString name = s; #ifdef TRACE QLOG_INFO() <<"OPERATION '" << name << "'\n"; #endif s = Lex::read_word(); if (s != "(") { Lex::syntax_error("'(' expected rather than '" + s + "'"); return FALSE; } UmlClass * cl = container->get_uml(); UmlOperation * op; #ifndef REVERSE if (visibility == PrivateVisibility) op = 0; else #endif { op = UmlBaseOperation::create(cl, name); if (op == 0) { PhpCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); return FALSE; } #ifdef REVERSE Statistic::one_operation_more(); #endif } Q3CString def; if (op != 0) { op->set_Visibility(visibility); if (staticp) op->set_isClassMember(TRUE); if (finalp) op->set_isPhpFinal(TRUE); def = PhpSettings::operationDef(); int index; if (((index = def.find("${(}")) == -1) || (def.find("${)}", index + 4) == -1) || ((index = def.find("${name}")) == -1) || (def.find("${body}") == -1)) { // use a definition where ${body] is not indented def = " ${comment}${final}${visibility}${abstract}${static}function ${name}${(}${)}\n{\n ${body}}\n"; index = def.find("${name}"); } if (refp) def.insert(index, "&"); if ((name == cl->name()) || (name == "__construct")) { // constructor, remove useless ${} if ((index = def.find("${static}")) != -1) def.remove(index, 9); if ((index = def.find("${final}")) != -1) def.remove(index, 8); if ((index = def.find("${abstract}")) != -1) def.remove(index, 11); } if (abstractp) { op->set_isAbstract(TRUE); def = def.left(def.find("${)}") + 4) + ";"; } } // parameters unsigned rank = 0; UmlParameter param; while (read_param(container, rank, param, def, op == 0)) { if ((op != 0) && ! op->addParameter(rank++, param)) { PhpCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add param <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); #ifdef TRACE QLOG_INFO() <<"ERROR cannot add param '" << param.name << '\n'; #endif return FALSE; } } s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } // definition if (abstractp || (cl->stereotype() == "interface")) { if (s != ";") { Lex::error_near(s); return FALSE; } #ifdef REVERSE if (op != 0) op->set_PhpBody(0); #endif } else if (s != "{") { Lex::error_near(s); return FALSE; } else { Lex::mark(); // goto the end of the body char c; int level = 1; // '{' already read for (;;) { if ((c = Lex::read_word_bis()) == 0) return FALSE; else if (c == '{') level += 1; else if ((c == '}') && (--level == 0)) break; } #ifdef REVERSE if (op != 0) { Q3CString e = Lex::region(); e.truncate(e.length() - 1); // remove } // remove fist \n if (*((const char *) e) == '\n') e.remove(0, 1); // remove last spaces and tabs int ln = e.length(); while (ln && ((e[ln - 1] == ' ') || (e[ln - 1] == '\t'))) ln -= 1; e.truncate(ln); op->set_PhpBody(e); op->set_PhpContextualBodyIndent(FALSE); } #endif } if ((op != 0) && (def != op->phpDecl())) op->set_PhpDecl(def); Lex::clear_comments(); // params & body comments Lex::finish_line(); if ((op != 0) && !comment.isEmpty()) { s = (def.find("${description}") != -1) ? description : comment; UmlTypeSpec t; int index1; if (! (t.explicit_type = value_of(s, "@return", index1)).isEmpty()) { op->set_ReturnType(t); s.replace(index1, t.explicit_type.length(), "${type}"); } Q3ValueList<UmlParameter> l = op->params(); unsigned nparams = l.count(); if (nparams != 0) { Q3CString varname; int index2; char xn[16]; index1 = 0; rank = 0; while (!((t.explicit_type = value_of(s, "@param", index1, varname, index2)) .isEmpty())) { if (varname.isEmpty() || (varname[0] != '$')) { if (rank < nparams) { UmlParameter & p = l[rank]; p.type = t; op->replaceParameter(rank, p); } } else { varname = varname.mid(1); Q3ValueList<UmlParameter>::Iterator it; for (it = l.begin(), rank = 0; it != l.end(); ++it, rank += 1) { if ((*it).name == varname) { (*it).type = t; op->replaceParameter(rank, *it); sprintf(xn, "${p%d}", rank); s.replace(index2, varname.length() + 1, xn); break; } } } sprintf(xn, "${t%d}", rank++); s.replace(index1, t.explicit_type.length(), xn); } } op->set_Description(s); } return TRUE; }
void UmlRelation::generate(QTextOStream & f, const Q3CString & cl_stereotype, Q3CString indent) { switch (relationKind()) { case aDependency: case aGeneralisation: case aRealization: break; default: if (!javaDecl().isEmpty()) { if (cl_stereotype == "enum_pattern") { write_trace_header(); UmlCom::trace(" <font color=\"red\"><b>an <i>enum_pattern</i> cannot have relation</b></font><br>"); incr_warning(); return; } const char * p = javaDecl(); const char * pp = 0; Q3CString s; while ((*p == ' ') || (*p == '\t')) indent += *p++; f << indent; for (;;) { if (*p == 0) { if (pp == 0) break; // comment management done p = pp; pp = 0; if (*p == 0) break; f << indent; } if (*p == '\n') { f << *p++; if (*p) f << indent; } else if (*p == '@') manage_alias(p, f); else if (*p != '$') f << *p++; else if (!strncmp(p, "${comment}", 10)) manage_comment(p, pp, JavaSettings::isGenerateJavadocStyleComment()); else if (!strncmp(p, "${description}", 14)) manage_description(p, pp); else if (!strncmp(p, "${visibility}", 13)) { p += 13; generate_visibility(f, cl_stereotype); } else if (!strncmp(p, "${static}", 9)) { p += 9; if (isClassMember()) f << "static "; } else if (!strncmp(p, "${final}", 8)) { p += 8; if (isReadOnly()) f << "final "; } else if (!strncmp(p, "${transient}", 12)) { p += 12; if (isJavaTransient()) f << "transient "; } else if (!strncmp(p, "${volatile}", 11)) { p += 11; if (isVolatile()) f << "volatile "; } else if (!strncmp(p, "${type}", 7)) { p += 7; roleType()->write(f); } else if (!strncmp(p, "${stereotype}", 13)) { p += 13; f << JavaSettings::relationAttributeStereotype(stereotype()); } else if (!strncmp(p, "${name}", 7)) { p += 7; f << roleName(); } else if (!strncmp(p, "${inverse_name}", 15)) { p += 15; switch (relationKind()) { case anAssociation: case anAggregation: case anAggregationByValue: f << side(side(TRUE) != this)->roleName(); default: break; } } else if (!strncmp(p, "${multiplicity}", 15)) { p += 15; Q3CString m = multiplicity(); if (*m != '[') f << "[]"; else { for (unsigned index = 0; index != m.length(); index += 1) { switch (m.at(index)) { case '[': f << '['; break; case ']': f << ']'; default: break; } } } } else if (!strncmp(p, "${value}", 8)) { if (!defaultValue().isEmpty()) { if (need_equal(p, defaultValue())) f << " = "; f << defaultValue(); } p += 8; } else if (!strncmp(p, "${association}", 14)) { p += 14; UmlClass::write(f, association()); } else if (!strncmp(p, "${@}", 4)) { p += 4; if (pp != 0) f << "${@}"; else if (! javaAnnotations().isEmpty()) { pp =p; p = javaAnnotations(); } } else // strange f << *p++; } f << '\n'; } } }
bool Q3Process::start( QStringList *env ) { #if defined(QT_Q3PROCESS_DEBUG) qDebug( "Q3Process::start()" ); #endif reset(); if ( _arguments.isEmpty() ) return false; // Open the pipes. Make non-inheritable copies of input write and output // read handles to avoid non-closable handles (this is done by the // DuplicateHandle() call). SECURITY_ATTRIBUTES secAtt = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE }; #ifndef Q_OS_WINCE // I guess there is no stdin stdout and stderr on Q_OS_WINCE to dup // CreatePipe and DupilcateHandle aren't available for Q_OS_WINCE HANDLE tmpStdin, tmpStdout, tmpStderr; if ( comms & Stdin ) { if ( !CreatePipe( &d->pipeStdin[0], &tmpStdin, &secAtt, 0 ) ) { d->closeHandles(); return false; } if ( !DuplicateHandle( GetCurrentProcess(), tmpStdin, GetCurrentProcess(), &d->pipeStdin[1], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { d->closeHandles(); return false; } if ( !CloseHandle( tmpStdin ) ) { d->closeHandles(); return false; } } if ( comms & Stdout ) { if ( !CreatePipe( &tmpStdout, &d->pipeStdout[1], &secAtt, 0 ) ) { d->closeHandles(); return false; } if ( !DuplicateHandle( GetCurrentProcess(), tmpStdout, GetCurrentProcess(), &d->pipeStdout[0], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { d->closeHandles(); return false; } if ( !CloseHandle( tmpStdout ) ) { d->closeHandles(); return false; } } if ( comms & Stderr ) { if ( !CreatePipe( &tmpStderr, &d->pipeStderr[1], &secAtt, 0 ) ) { d->closeHandles(); return false; } if ( !DuplicateHandle( GetCurrentProcess(), tmpStderr, GetCurrentProcess(), &d->pipeStderr[0], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { d->closeHandles(); return false; } if ( !CloseHandle( tmpStderr ) ) { d->closeHandles(); return false; } } if ( comms & DupStderr ) { CloseHandle( d->pipeStderr[1] ); d->pipeStderr[1] = d->pipeStdout[1]; } #endif // construct the arguments for CreateProcess() QString args; QString appName; QStringList::Iterator it = _arguments.begin(); args = *it; ++it; if ( args.endsWith( QLatin1String(".bat") ) && args.contains( QLatin1Char(' ') ) ) { // CreateProcess() seems to have a strange semantics (see also // http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_11138647.html): // If you start a batch file with spaces in the filename, the first // argument to CreateProcess() must be the name of the batchfile // without quotes, but the second argument must start with the same // argument with quotes included. But if the same approach is used for // .exe files, it doesn't work. appName = args; args = QLatin1Char('"') + args + QLatin1Char('"'); } for ( ; it != _arguments.end(); ++it ) { QString tmp = *it; // escape a single " because the arguments will be parsed tmp.replace( QLatin1String("\""), QLatin1String("\\\"") ); if ( tmp.isEmpty() || tmp.contains( QLatin1Char(' ') ) || tmp.contains( QLatin1Char('\t') ) ) { // The argument must not end with a \ since this would be interpreted // as escaping the quote -- rather put the \ behind the quote: e.g. // rather use "foo"\ than "foo\" QString endQuote( QLatin1String("\"") ); int i = tmp.length(); while ( i>0 && tmp.at( i-1 ) == QLatin1Char('\\') ) { --i; endQuote += QLatin1String("\\"); } args += QString( QLatin1String(" \"") ) + tmp.left( i ) + endQuote; } else { args += QLatin1Char(' ') + tmp; } } #if defined(QT_Q3PROCESS_DEBUG) qDebug( "Q3Process::start(): args [%s]", args.latin1() ); #endif // CreateProcess() bool success; d->newPid(); #ifdef UNICODE if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, STARTF_USESTDHANDLES, 0, 0, 0, d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1] }; TCHAR *applicationName; if ( appName.isNull() ) applicationName = 0; else applicationName = _wcsdup( (TCHAR*)appName.ucs2() ); TCHAR *commandLine = _wcsdup( (TCHAR*)args.ucs2() ); QByteArray envlist; if ( env != 0 ) { int pos = 0; // add PATH if necessary (for DLL loading) QByteArray path = qgetenv( "PATH" ); if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) { QString tmp = QString( QLatin1String("PATH=%1") ).arg(QString::fromLatin1(path.constData())); uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); envlist.resize( envlist.size() + tmpSize ); memcpy( envlist.data()+pos, tmp.ucs2(), tmpSize ); pos += tmpSize; } // add the user environment for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) { QString tmp = *it; uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); envlist.resize( envlist.size() + tmpSize ); memcpy( envlist.data()+pos, tmp.ucs2(), tmpSize ); pos += tmpSize; } // add the 2 terminating 0 (actually 4, just to be on the safe side) envlist.resize( envlist.size()+4 ); envlist[pos++] = 0; envlist[pos++] = 0; envlist[pos++] = 0; envlist[pos++] = 0; } success = CreateProcessW( applicationName, commandLine, 0, 0, TRUE, ( comms==0 ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW ) #ifndef Q_OS_WINCE | CREATE_UNICODE_ENVIRONMENT #endif , env==0 ? 0 : envlist.data(), (TCHAR*)QDir::toNativeSeparators(workingDir.absPath()).ucs2(), &startupInfo, d->pid ); free( applicationName ); free( commandLine ); } else #endif // UNICODE { #ifndef Q_OS_WINCE STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, STARTF_USESTDHANDLES, 0, 0, 0, d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1] }; QByteArray envlist; if ( env != 0 ) { int pos = 0; // add PATH if necessary (for DLL loading) QByteArray path = qgetenv( "PATH" ); if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) { Q3CString tmp = QString( QLatin1String("PATH=%1") ).arg(QString::fromLatin1(path.constData())).local8Bit(); uint tmpSize = tmp.length() + 1; envlist.resize( envlist.size() + tmpSize ); memcpy( envlist.data()+pos, tmp.data(), tmpSize ); pos += tmpSize; } // add the user environment for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) { Q3CString tmp = (*it).local8Bit(); uint tmpSize = tmp.length() + 1; envlist.resize( envlist.size() + tmpSize ); memcpy( envlist.data()+pos, tmp.data(), tmpSize ); pos += tmpSize; } // add the terminating 0 (actually 2, just to be on the safe side) envlist.resize( envlist.size()+2 ); envlist[pos++] = 0; envlist[pos++] = 0; } char *applicationName; if ( appName.isNull() ) applicationName = 0; else applicationName = const_cast<char *>(appName.toLocal8Bit().data()); success = CreateProcessA( applicationName, const_cast<char *>(args.toLocal8Bit().data()), 0, 0, TRUE, comms==0 ? CREATE_NEW_CONSOLE : DETACHED_PROCESS, env==0 ? 0 : envlist.data(), (const char*)QDir::toNativeSeparators(workingDir.absPath()).local8Bit(), &startupInfo, d->pid ); #endif // Q_OS_WINCE } if ( !success ) { d->deletePid(); return false; } #ifndef Q_OS_WINCE if ( comms & Stdin ) CloseHandle( d->pipeStdin[0] ); if ( comms & Stdout ) CloseHandle( d->pipeStdout[1] ); if ( (comms & Stderr) && !(comms & DupStderr) ) CloseHandle( d->pipeStderr[1] ); #endif if ( ioRedirection || notifyOnExit ) { d->lookup->start( 100 ); } // cleanup and return return true; }
Q3CString UmlPackage::text_path(const Q3CString & f) { Q3CString r = path(f); return r.left(r.length() - 1 - IdlSettings::sourceExtension().length()); }
bool UmlAttribute::new_one(Class * container, const Q3CString & name, const Q3CString & type, const Q3CString & modifier, const Q3CString & pretype, const Q3CString & array, aVisibility visibility, bool staticp, bool constp, bool typenamep, bool mutablep, bool volatilep, const Q3CString & bitfield, const Q3CString & value, Q3CString comment, Q3CString description #ifdef ROUNDTRIP , bool roundtrip, Q3PtrList<UmlItem> & expected_order #endif ) { #ifdef DEBUG_BOUML cout << "ATTRIBUTE '" << name << "' type '" << type << "' modifier '" << modifier << "' array '" << array << "'\n"; #endif if ( #ifdef REVERSE container->from_libp() && #endif (visibility == PrivateVisibility)) { Lex::finish_line(); Lex::clear_comments(); return TRUE; } UmlClass * cl = container->get_uml(); UmlAttribute * at; #ifdef ROUNDTRIP bool created; if (!roundtrip || ((at = search_attr(cl, name)) == 0)) { #endif at = UmlBaseAttribute::create(cl, name); if (at == 0) { UmlCom::trace(Q3CString("<font face=helvetica><b>cannot add attribute <i>") + name + "</i> in <i>" + Q3CString(cl->name()) + "</i></b></font><br><hr>"); return FALSE; } #ifdef REVERSE # ifndef ROUNDTRIP Statistic::one_attribute_more(); # else if (roundtrip) container->set_updated(); created = TRUE; } else created = FALSE; # endif #endif Lex::finish_line(); comment = Lex::get_comments(comment); description = Lex::get_description(description); bool pfunc = (type.find('$') != -1); UmlTypeSpec typespec; Q3CString typeform; Q3CString stereotype; if (! pfunc) { typeform = (pretype.isEmpty()) ? Q3CString("${type}") : pretype + " ${type}"; container->compute_type(type, typespec, typeform); } else { typespec.explicit_type = type.simplifyWhiteSpace(); int index = typespec.explicit_type.find("${name}"); if (index != -1) typespec.explicit_type.remove(index, 7); } Q3CString decl = CppSettings::attributeDecl(""); int index = decl.find("${type}"); if ((index == -1) || (decl.find("${const}") == -1) || (decl.find("${name}") == -1) || (decl.find("${mutable}") == -1) || (decl.find("${volatile}") == -1) || (decl.find(';') == -1)) { decl = " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value};"; index = decl.find("${type}"); } if (pfunc) decl.replace(index, decl.find("${name}") + 7 - index, type); else { if (!modifier.isEmpty()) decl.insert(index + 7, (const char*)(Q3CString(" ") + modifier)); if (typeform != "${type}") decl.replace(index, 7, typeform); else if (typespec.type == 0) { Q3CString t = typespec.explicit_type; int index2; if (!t.isEmpty() && (t.at(t.length() - 1) == '>') && ((index2 = t.find('<')) > 0)) { stereotype = t.left(index2); typespec.explicit_type = // may be a,b ... t.mid(index2 + 1, t.length() - 2 - index2); decl.replace(index, 7, "${stereotype}<${type}>"); } } if (!array.isEmpty()) decl.insert(decl.find("${name}") + 7, "${multiplicity}"); if (!bitfield.isEmpty()) decl.insert(decl.find(';'), (const char *)(Q3CString(" : ") + bitfield)); } if (typenamep) { int index = decl.find("${const}") + 8; // find cannot return -1 int index2 = decl.find("${mutable}") + 10; // find cannot return -1 int index3 = decl.find("${volatile}") + 11; // find cannot return -1 if (index2 > index) index = index2; if (index3 > index) index = index3; decl.insert(index, "typename "); } if (!value.isEmpty() && ((index = decl.find("${value}")) != -1)) decl.insert(index + 2, "h_"); #ifdef ROUNDTRIP if (roundtrip && !created) { if (decl.find("${description}") != -1) { if (nequal(at->description(), description)) { at->set_Description(description); container->set_updated(); } } else if (nequal(at->description(), Lex::simplify_comment(comment))) { at->set_Description(comment); // comment was set container->set_updated(); } if (at->isReadOnly() != constp) { at->set_isReadOnly(constp); container->set_updated(); } if (at->isCppMutable() != mutablep) { at->set_isCppMutable(mutablep); container->set_updated(); } if (at->isVolatile() != volatilep) { at->set_isVolatile(volatilep); container->set_updated(); } if (at->isClassMember() != staticp) { at->set_isClassMember(staticp); container->set_updated(); } if (neq(at->multiplicity(), array)) { at->set_Multiplicity(array); container->set_updated(); } if (!staticp) { Q3CString v = at->defaultValue(); if (!v.isEmpty() && (((const char *) v)[0] == '=')) v = v.mid(1); if (nequal(v, value)) { at->set_DefaultValue(value); container->set_updated(); } } if (at->visibility() != visibility) { at->set_Visibility(visibility); container->set_updated(); } if (!stereotype.isEmpty()) { Q3CString cppst; if (!at->stereotype().isEmpty()) cppst = CppSettings::relationAttributeStereotype(at->stereotype()); if (cppst != stereotype) { at->set_Stereotype(stereotype); container->set_updated(); } } if (!at->type().equal(typespec)) { at->set_Type(typespec); container->set_updated(); } if (neq(at->cppDecl(), decl)) { at->set_CppDecl(decl); container->set_updated(); } at->set_usefull(); expected_order.append(at); } else { #endif if (!comment.isEmpty()) at->set_Description((decl.find("${description}") != -1) ? description : Lex::simplify_comment(comment)); if (constp) at->set_isReadOnly(TRUE); if (mutablep) at->set_isCppMutable(TRUE); if (volatilep) at->set_isVolatile(TRUE); if (staticp) at->set_isClassMember(TRUE); if (!array.isEmpty()) at->set_Multiplicity(array); if (! value.isEmpty()) at->set_DefaultValue(value); at->set_Visibility(visibility); if (! stereotype.isEmpty()) at->set_Stereotype(stereotype); at->set_Type(typespec); at->set_CppDecl(decl); #ifdef ROUNDTRIP if (roundtrip) expected_order.append(at); } #endif return TRUE; }
void UmlCollaborationMessage::write(FileOut & out, UmlItem * diagram, const Q3PtrVector< UmlCollaborationMessage > & msgs, unsigned & index) { unsigned sup = msgs.size(); UmlPackage * prj = UmlPackage::getProject(); while (index != sup) { const UmlCollaborationMessage * msg = msgs[index++]; Q3CString pfix = msg->hrank() + "."; unsigned pfixlen = pfix.length(); #define MSG "MSG", msg->itsrank #define SEND "MSGOCCSPECSEND", msg->itsrank #define REC "MSGOCCSPECREC", msg->itsrank #define BEH "BEHEXECSPEC", msg->itsrank #define EXEC "EXECOCCSPEC", msg->itsrank out.indent(); out << "<fragment xmi:type=\"uml:MessageOccurrenceSpecification\""; out.id_prefix(diagram, SEND); out.ref(diagram, "covered", msg->from()->lifeline()); out.ref(prj, "event", (msg->operation() != 0) ? msg->operation()->event(FALSE) : UmlOperation::event("SEND", msg->form())); out.ref(diagram, "message", MSG); out << "/>\n"; out.indent(); out << "<message xmi:type=\"uml:Message\""; out.id_prefix(diagram, MSG); out << " name=\""; out.quote((const char*)((msg->operation() != 0) ? msg->operation()->name() : msg->form()));//[jasa] ambiguous call out << '"'; out.ref(diagram, "sendEvent", SEND); out.ref(diagram, "receiveEvent", REC); out.ref(diagram, "connector", msg->from()->connector(msg->to())); out << "/>\n"; out.indent(); out << "<fragment xmi:type=\"uml:MessageOccurrenceSpecification\""; out.id_prefix(diagram, REC); out.ref(diagram, "covered", msg->to()->lifeline()); out.ref(prj, "event", (msg->operation() != 0) ? msg->operation()->event(TRUE) : UmlOperation::event("REC", msg->form())); out.ref(diagram, "message", MSG); out << "/>\n"; out.indent(); out << "<fragment xmi:type=\"uml:BehaviorExecutionSpecification\""; out.id_prefix(diagram, BEH); out.ref(diagram, "covered", msg->to()->lifeline()); out.ref(diagram, "start", REC); out.ref(diagram, "finish", EXEC); out << "/>\n"; if (index != sup) { Q3CString pfix2 = msgs[index]->hrank() + "."; if ((pfix2.length() > pfixlen) && !strncmp(pfix, pfix2, pfixlen)) write(out, diagram, msgs, index); } out.indent(); out << "<fragment xmi:type=\"uml:ExecutionOccurrenceSpecification\""; out.id_prefix(diagram, EXEC); out.ref(diagram, "covered", msg->to()->lifeline()); out.ref(prj, "event", UmlOperation::event("EXEC", (msg->operation() != 0) ? msg->operation()->name() : msg->form())); out.ref(diagram, "execution", BEH); out << "/>\n"; } }
bool UmlOperation::new_one(Class * container, const Q3CString & name, const Q3ValueList<FormalParameterList> & tmplts, const Q3CString & oper_templ, UmlTypeSpec & type, Q3CString str_actuals, UmlClass * first_actual_class, Q3CString type_def, aVisibility visibility, bool finalp, bool abstractp, bool staticp, bool nativep, bool strictfp, bool synchronizedp, const Q3CString & array, Q3CString comment, Q3CString description, Q3CString annotation #ifdef ROUNDTRIP , bool roundtrip, Q3PtrList<UmlItem> & expected_order #endif ) { // the "(" was read #ifdef TRACE QLOG_INFO() <<"OPERATION '" << name << "'\n"; #endif UmlClass * cl = container->get_uml(); UmlOperation * op; #ifdef ROUNDTRIP bool may_roundtrip = roundtrip && (!container->from_libp() || (visibility != PrivateVisibility)); UmlTypeSpec return_type; Q3ValueList<UmlParameter> params; Q3ValueList<UmlTypeSpec> exceptions; Q3CString body; if (may_roundtrip) #else if ( # ifdef REVERSE container->from_libp() && # endif (visibility == PrivateVisibility)) #endif op = 0; else { op = UmlBaseOperation::create(cl, name); if (op == 0) { JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); return FALSE; } #ifndef ROUNDTRIP # if defined(REVERSE) Statistic::one_operation_more(); # endif #endif } Q3CString def; #ifdef ROUNDTRIP if (may_roundtrip || (op != 0)) { #else if (op != 0) { op->set_Visibility(visibility); if (staticp) op->set_isClassMember(TRUE); if (abstractp) op->set_isAbstract(TRUE); if (finalp) op->set_isJavaFinal(TRUE); if (synchronizedp) op->set_isJavaSynchronized(TRUE); if (! annotation.isEmpty()) op->set_JavaAnnotations(annotation); #endif def = JavaSettings::operationDef(); int index; if (((index = def.find("${(}")) == -1) || ((index = def.find("${)}", index + 4)) == -1) || ((index = def.find("${throws}", index + 4)) == -1) || (def.find("${body}", index + 9) == -1) || ((index = def.find("${type}")) == -1)) { // use a definition where ${body] is not indented def = " ${comment}${@}${visibility}${final}${static}${abstract}${synchronized}${type} ${name}${(}${)}${throws}${staticnl}{\n${body}}\n"; index = def.find("${type}"); } if (!array.isEmpty()) def.insert(index + 7, (const char *)array); if (nativep) { def.insert(index, "native "); index += 7; // no body int index2 = def.find("${throws}", index+7); if (index2 != -1) { def.resize(index2 + 12); def[index2 + 9] = ';'; def[index2 + 10] = '\n'; } } if (strictfp) { def.insert(index, "strictfp "); index += 9; } if (! oper_templ.isEmpty()) def.insert(index, (const char *)(oper_templ + " ")); if (name == cl->name()) { // constructor, remove useless ${} if ((index = def.find("${static}")) != -1) def.remove(index, 9); if ((index = def.find("${type}")) != -1) def.remove(index, (((const char *) def)[index + 7] == ' ') ? 8 : 7); if ((index = def.find("${final}")) != -1) def.remove(index, 8); if ((index = def.find("${abstract}")) != -1) def.remove(index, 11); } if (type.type != 0) { UmlClass::manage_generic(def, type, str_actuals, "${type}"); #ifdef ROUNDTRIP return_type = type; #else op->set_ReturnType(type); #endif } else if (first_actual_class != 0) { #ifndef ROUNDTRIP UmlTypeSpec return_type; #endif return_type.type = first_actual_class; def.replace(def.find("${type}"), 7, type_def); #ifndef ROUNDTRIP op->set_ReturnType(return_type); #endif } else if (!type.explicit_type.isEmpty()) { // not a contructor #ifdef ROUNDTRIP return_type = type; #else op->set_ReturnType(type); #endif } } // parameters unsigned rank = 0; UmlParameter param; #ifdef ROUNDTRIP if (may_roundtrip) while (read_param(container, rank++, tmplts, param, def, FALSE)) params.append(param); else #endif while (read_param(container, rank, tmplts, param, def, op == 0)) { if ((op != 0) && ! op->addParameter(rank, param)) { JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add param <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); # ifdef TRACE QLOG_INFO() <<"ERROR cannot add param '" << param.name << "' type '" << param.type.Type() << '\n'; # endif return FALSE; } rank += 1; } Q3CString s = Lex::read_word(); if (!s.isEmpty() && (*((const char *) s) == '[')) { #ifdef ROUNDTRIP if (may_roundtrip) #else if (op != 0) #endif // do not place it at the same place def.insert(def.find("${type}") + 7, (const char *)s); s = Lex::read_word(); } if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } if (s == "throws") { // throws rank = 0; for (;;) { if ((s = Lex::read_word()).isEmpty()) { Lex::premature_eof(); return FALSE; } #ifdef ROUNDTRIP if (may_roundtrip) { UmlTypeSpec typespec; container->compute_type(s, typespec, tmplts); exceptions.append(typespec); } else #endif if (op != 0) { UmlTypeSpec typespec; container->compute_type(s, typespec, tmplts); if (! op->addException(rank++, typespec)) { # ifdef TRACE QLOG_INFO() <<"cannot add exception " << s << '\n'; # endif return FALSE; } } if (((s = Lex::read_word()) == "{") || (s == ";")) break; if (s != ",") { Lex::error_near(s, " ',' expected"); return FALSE; } } } // definition if (abstractp || nativep || (cl->stereotype() == "interface") || (cl->stereotype() == "@interface")) { if ((s == "default") && (cl->stereotype() == "@interface")) { int index = def.find("${)}"); Lex::mark(); s = Lex::read_word(); if (s == "{") { int level = 1; char c; for (;;) { if ((c = Lex::read_word_bis()) == 0) return FALSE; else if (c == '{') level += 1; else if ((c == '}') && (--level == 0)) break; } s = Lex::region(); } def.insert(index + 4, (const char *)(" default" + s)); s = Lex::read_word(); } if (s != ";") { Lex::error_near(s, " ';' expected"); return FALSE; } #ifdef REVERSE # ifndef ROUNDTRIP if ((op != 0) && !container->from_libp()) op->set_JavaBody(0); # endif #endif } else if (s != "{") { Lex::error_near(s, " '{' expected"); return FALSE; } else { Lex::mark(); // goto the end of the body #ifndef ROUNDTRIP Q3CString body; #endif int level = 1; // '{' already read char c; for (;;) { if ((c = Lex::read_word_bis()) == 0) return FALSE; else if (c == '{') level += 1; else if ((c == '}') && (--level == 0)) break; } #ifdef REVERSE if ( # ifdef ROUNDTRIP may_roundtrip || (op != 0) # else (op != 0) && !container->from_libp() # endif ) { body = Lex::region(); body.truncate(body.length() - 1); // remove } // remove fist \n if (*((const char *) body) == '\n') body.remove(0, 1); // remove last spaces and tabs int ln = body.length(); while (ln && ((body[ln - 1] == ' ') || (body[ln - 1] == '\t'))) ln -= 1; body.truncate(ln); if (!body.isEmpty() && (body[ln - 1] != '\n')) body += "\n"; # ifndef ROUNDTRIP op->set_JavaBody(body); op->set_JavaContextualBodyIndent(FALSE); # endif } #endif } #ifdef ROUNDTRIP if (may_roundtrip) { if (((op = already_exist_from_id(container, body)) != 0) || ((op = already_exist(container, name, params)) != 0)) { // update already existing operation op->set_usefull(); { // remove \r in case of preserve body Q3CString current_body = op->javaBody(); int index = 0; while ((index = current_body.find('\r', index)) != -1) current_body.remove(index, 1); if (nequal(current_body, body)) { container->set_updated(); op->set_JavaBody(body); op->set_JavaContextualBodyIndent(FALSE); } } if (op->visibility() != visibility) { container->set_updated(); op->set_Visibility(visibility); } if (op->isClassMember() != staticp) { container->set_updated(); op->set_isClassMember(staticp); } if (op->isAbstract() != abstractp) { container->set_updated(); op->set_isAbstract(abstractp); } if (op->isJavaFinal() != finalp) { container->set_updated(); op->set_isJavaFinal(finalp); } if (op->isJavaSynchronized() != synchronizedp) { container->set_updated(); op->set_isJavaSynchronized(synchronizedp); } if (nequal(op->javaAnnotations(), annotation)) { container->set_updated(); op->set_JavaAnnotations(annotation); } if (!op->returnType().equal(return_type)) { container->set_updated(); op->set_ReturnType(return_type); } Q3ValueList<UmlParameter>::Iterator itp1; const Q3ValueList<UmlParameter> old_params = op->params(); Q3ValueList<UmlParameter>::ConstIterator itp2; for (rank = 0, itp1 = params.begin(), itp2 = old_params.begin(); (itp1 != params.end()) && (itp2 != old_params.end()); ++itp1, ++itp2, rank += 1) { UmlParameter & p1 = *itp1; const UmlParameter & p2 = *itp2; if ((p1.name != p2.name) || nequal(p1.default_value, p2.default_value) || !p1.type.equal(p2.type)) { if (p1.dir != InputDirection) p1.dir = p2.dir; op->replaceParameter(rank, p1); container->set_updated(); } else if ((p1.dir == InputDirection) && (p2.dir != InputDirection)) { op->replaceParameter(rank, p1); container->set_updated(); } } if (itp1 != params.end()) { // have missing params container->set_updated(); do { op->addParameter(rank, *itp1); itp1++; rank += 1; } while (itp1 != params.end()); } else if (itp2 != old_params.end()) { // have extra params container->set_updated(); do { op->removeParameter(rank); itp2++; } while (itp2 != old_params.end()); } Q3ValueList<UmlTypeSpec>::ConstIterator ite1; const Q3ValueList<UmlTypeSpec> old_exceptions = op->exceptions(); Q3ValueList<UmlTypeSpec>::ConstIterator ite2; for (rank = 0, ite1 = exceptions.begin(), ite2 = old_exceptions.begin(); (ite1 != exceptions.end()) && (ite2 != old_exceptions.end()); ++ite1, ++ite2, rank += 1) { const UmlTypeSpec & e1 = *ite1; if (!e1.equal(*ite2)) { op->replaceException(rank, e1); container->set_updated(); } } if (ite1 != exceptions.end()) { // have missing exceptions container->set_updated(); do { op->addException(rank, *ite1); ite1++; rank += 1; } while (ite1 != exceptions.end()); } else if (ite2 != old_exceptions.end()) { // have extra exceptions container->set_updated(); do { op->removeException(rank); ite2++; } while (ite2 != old_exceptions.end()); } if (neq(def, op->javaDecl())) { container->set_updated(); op->set_JavaDecl(def); } Lex::clear_comments(); // params & body comments Lex::finish_line(); if (def.find("${description}") != -1) { if (nequal(op->description(), description)) { container->set_updated(); op->set_Description(description); } } else if (nequal(op->description(), Lex::simplify_comment(comment))) { op->set_Description(comment); // comment was set container->set_updated(); } expected_order.append(op); return TRUE; } // operation doesn't yet exist container->set_updated(); op = UmlBaseOperation::create(cl, name); if (op == 0) { JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); throw 0; } expected_order.append(op); Q3ValueList<UmlParameter>::ConstIterator itp; for (rank = 0, itp = params.begin(); itp != params.end(); ++itp) op->addParameter(rank++, *itp); Q3ValueList<UmlTypeSpec>::ConstIterator ite; for (rank = 0, ite = exceptions.begin(); ite != exceptions.end(); ++ite) op->addException(rank++, *ite); } if (op != 0) { op->set_JavaContextualBodyIndent(FALSE); op->set_Visibility(visibility); if (staticp) op->set_isClassMember(TRUE); if (abstractp) op->set_isAbstract(TRUE); if (finalp) op->set_isJavaFinal(TRUE); if (synchronizedp) op->set_isJavaSynchronized(TRUE); if (! annotation.isEmpty()) op->set_JavaAnnotations(annotation); op->set_JavaBody(body); op->set_ReturnType(return_type); if (def != JavaSettings::operationDef()) op->set_JavaDecl(def); } #else if ((op != 0) && (def != JavaSettings::operationDef())) op->set_JavaDecl(def); #endif Lex::clear_comments(); // params & body comments Lex::finish_line(); if (!comment.isEmpty()) if (op != 0) op->set_Description((def.find("${description}") != -1) ? description : Lex::simplify_comment(comment)); return TRUE; } bool UmlOperation::read_param(Class * container, unsigned rank, const Q3ValueList<FormalParameterList> & tmplts, UmlParameter & param, Q3CString & def, bool bypass) { #ifdef TRACE QLOG_INFO() <<"UmlOperation::manage_param " << rank << "\n"; #endif bool finalp = FALSE; bool in = FALSE; bool ellipsis = FALSE; Q3CString array; bool type_read = FALSE; Q3ValueList<UmlTypeSpec> actuals; Q3CString str_actuals; Q3CString annotation; param.name = param.default_value = 0; Q3CString s = Lex::read_word(); #ifdef TRACE QLOG_INFO() <<"commence par " << s << '\n'; #endif if (s == ")") return FALSE; for (;;) { if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } else if (s == "final") finalp = TRUE; else if ((s == "void") || (s == "byte") || (s == "char") || (s == "short") || (s == "int") || (s == "long") || (s == "float") || (s == "double")) { if (type_read) { Lex::error_near(s); return FALSE; } param.type.type = 0; param.type.explicit_type = s; type_read = TRUE; in = TRUE; } else if ((s == ")") || (s == ",")) { if (param.name.isEmpty() && !type_read) { Lex::error_near(s); return FALSE; } if (s == ")") Lex::unread_word(s); if (! bypass) { param.dir = (finalp || in) ? InputDirection : InputOutputDirection; Q3CString s; if (rank != 0) s = ", "; if (! annotation.isEmpty()) s += annotation + " "; if (finalp) s += "final "; if ((param.type.type != 0) && !param.type.explicit_type.isEmpty()) s += param.type.explicit_type; else { s += "${t"; s += Q3CString().setNum(rank); s += "}"; if (param.type.type != 0) s += str_actuals; } s += array; s += (ellipsis) ? " ... ${p": " ${p"; s += Q3CString().setNum(rank); s += "}"; def.insert(def.find("${)}"), // cannot be -1 (const char *)s); } return TRUE; } else if (Lex::identifierp(s)) { if (!type_read) { while (s.at(s.length() - 1) == '.') { // type on several lines, managed in this case Q3CString s2 = Lex::read_word(); if (Lex::identifierp(s2)) s += s2; else { Lex::error_near(s, " identifier expected"); return FALSE; } } #ifdef TRACE QLOG_INFO() <<"type = '" << s << "...'\n"; #endif if (! bypass) { Q3CString dummy; container->read_type(param.type, 0, tmplts, 0, str_actuals, s, 0, dummy, dummy); if (param.type.explicit_type == "String") // at least for it ! in = TRUE; } else Lex::bypass_type(s); type_read = TRUE; } else if (param.name.isEmpty()) { if (s == "...") ellipsis = TRUE; else { param.name = s; #ifdef TRACE QLOG_INFO() <<"name = '" << param.name << "'\n"; #endif } } else { Lex::error_near(s); #ifdef TRACE QLOG_INFO() <<"ERROR '" << s << "' alors qu a deja le type et le nom '" << param.name << "'\n"; #endif return FALSE; } } else if (*((const char *) s) == '@') annotation = s; else if (*((const char *) s) == '[') { in = FALSE; array = s; } else { Lex::error_near(s); #ifdef TRACE QLOG_INFO() <<"ERROR : '" << s << "'\n"; #endif return FALSE; } s = Lex::read_word(); } }
bool UmlOperation::read_param(Class * container, unsigned rank, UmlParameter & param, Q3CString & def, bool bypass) { #ifdef TRACE QLOG_INFO() <<"UmlOperation::manage_param " << rank << "\n"; #endif Q3CString s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } else if (s == ")") return FALSE; #ifdef TRACE QLOG_INFO() <<"commence par " << s << '\n'; #endif param.type.type = 0; param.type.explicit_type = 0; param.dir = InputOutputDirection; bool arrayp = FALSE; if (s == "array") { arrayp = TRUE; s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } } else if ((((const char *) s)[0] != '&') && (((const char *) s)[0] != '$')) { // a type container->compute_type(s, param.type, 0); s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } } bool refp; if (s == "&") { refp = TRUE; s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } } else refp = FALSE; if (((const char *) s)[0] != '$') { Lex::syntax_error("invalid parameter name : " + s); return FALSE; } if (! bypass) { Q3CString n_close = Q3CString().setNum(rank) + "}"; param.name = s.mid(1); s = (rank == 0) ? "" : ", "; if (arrayp) s += "array "; else if ((param.type.type != 0) || !param.type.explicit_type.isEmpty()) { s += "${t" + n_close + " "; } if (refp) s += "& "; s += "${p" + n_close + "${v" + n_close; def.insert(def.find("${)}"), // cannot be -1 (const char *)s); } s = Lex::read_word(); if (s == "=") { Lex::mark(); s = skip_expr(0); param.default_value = Lex::region(); param.default_value.truncate(param.default_value.length() - s.length()); if (*((const char *) param.default_value) == ' ') param.default_value = param.default_value.mid(1); } else if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } else param.default_value = 0; if (s == ")") Lex::unread_word(s); return TRUE; }