3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
10 #include <ksimpleconfig.h>
14 #include "typetable.h"
17 // the TypeTables of all known libraries
18 static QList
<TypeTable
> typeTables
;
19 bool typeTablesInited
= false;
22 // an indentifier for wchar_t
23 TypeInfo
TypeInfo::m_wchartType("");
25 TypeInfo
TypeInfo::m_unknownType("");
28 void TypeTable::initTypeLibraries()
30 if (!typeTablesInited
) {
31 TypeTable::loadTypeTables();
35 void TypeTable::loadTypeTables()
37 typeTablesInited
= true;
39 const QStringList files
= KGlobal::dirs()->findAllResources("types", "*.kdbgtt");
41 if (files
.isEmpty()) {
42 TRACE("no type tables found");
47 for (QValueListConstIterator
<QString
> p
= files
.begin(); p
!= files
.end(); ++p
) {
49 TypeTable
* newTable
= new TypeTable
;
50 newTable
->loadFromFile(fileName
);
51 typeTables
.append(newTable
);
56 TypeTable::TypeTable() :
57 m_printQStringDataCmd(0)
59 m_typeDict
.setAutoDelete(true);
60 // aliasDict keeps only pointers to items into typeDict
61 m_aliasDict
.setAutoDelete(false);
64 TypeTable::~TypeTable()
66 delete[] m_printQStringDataCmd
;
70 static const char TypeTableGroup
[] = "Type Table";
71 static const char LibDisplayName
[] = "LibDisplayName";
72 static const char ShlibRE
[] = "ShlibRE";
73 static const char EnableBuiltin
[] = "EnableBuiltin";
74 static const char PrintQStringCmd
[] = "PrintQStringCmd";
75 static const char TypesEntryFmt
[] = "Types%d";
76 static const char DisplayEntry
[] = "Display";
77 static const char AliasEntry
[] = "Alias";
78 static const char ExprEntryFmt
[] = "Expr%d";
79 static const char FunctionGuardEntryFmt
[] = "FunctionGuard%d";
82 void TypeTable::loadFromFile(const QString
& fileName
)
84 TRACE("reading file " + fileName
);
85 KSimpleConfig
cf(fileName
, true); /* read-only */
88 * Read library name and properties.
90 cf
.setGroup(TypeTableGroup
);
91 m_displayName
= cf
.readEntry(LibDisplayName
);
92 if (m_displayName
.isEmpty()) {
93 // use file name instead
94 int slash
= fileName
.findRev('\\');
96 slash
>= 0 ? fileName
.mid(slash
+1, fileName
.length()) : fileName
;
97 int dot
= m_displayName
.findRev('.');
99 m_displayName
.truncate(dot
);
103 m_shlibNameRE
= QRegExp(cf
.readEntry(ShlibRE
));
104 cf
.readListEntry(EnableBuiltin
, m_enabledBuiltins
);
106 QString printQString
= cf
.readEntry(PrintQStringCmd
);
107 const char* ascii
= printQString
.ascii();
110 m_printQStringDataCmd
= new char[strlen(ascii
)+1];
111 strcpy(m_printQStringDataCmd
, ascii
);
114 * Get the types. We search for entries of kind Types1, Types2, etc.
115 * because a single entry Types could get rather long for large
120 for (int i
= 1; ; i
++) {
121 // next bunch of types
122 cf
.setGroup(TypeTableGroup
);
123 typesEntry
.sprintf(TypesEntryFmt
, i
);
124 if (!cf
.hasKey(typesEntry
))
126 cf
.readListEntry(typesEntry
, typeNames
, ',');
130 for (QListIterator
<char> it(typeNames
); it
!= 0; ++it
) {
131 cf
.setGroup(it
.current());
132 // check if this is an alias
133 alias
= cf
.readEntry(AliasEntry
);
134 if (alias
.isEmpty()) {
137 // look up the alias type and insert it
138 TypeInfo
* info
= m_typeDict
[alias
];
140 TRACE(QString().sprintf("<%s>: alias %s not found",
141 it
.operator char*(), alias
.data()));
143 m_aliasDict
.insert(alias
, info
);
144 TRACE(QString().sprintf("<%s>: alias <%s>",
145 it
.operator char*(), alias
.data()));
152 void TypeTable::readType(KConfigBase
& cf
, const char* type
)
154 // the display string
155 QString expr
= cf
.readEntry(DisplayEntry
);
157 TypeInfo
* info
= new TypeInfo(expr
);
158 if (info
->m_numExprs
== 0) {
159 TRACE(QString().sprintf("bogus type %s: no %% in Display: '%s'",
165 // Expr1, Expr2, etc...
167 QString funcGuardEntry
;
168 for (int j
= 0; j
< info
->m_numExprs
; j
++) {
169 exprEntry
.sprintf(ExprEntryFmt
, j
+1);
170 expr
= cf
.readEntry(exprEntry
);
171 info
->m_exprStrings
[j
] = expr
;
173 funcGuardEntry
.sprintf(FunctionGuardEntryFmt
, j
+1);
174 expr
= cf
.readEntry(funcGuardEntry
);
175 info
->m_guardStrings
[j
] = expr
;
179 m_typeDict
.insert(type
, info
);
180 TRACE(QString().sprintf("<%s>: %d exprs", type
,
184 void TypeTable::copyTypes(QDict
<TypeInfo
>& dict
)
186 for (QDictIterator
<TypeInfo
> it
= m_typeDict
; it
!= 0; ++it
) {
187 dict
.insert(it
.currentKey(), it
);
189 for (QDictIterator
<TypeInfo
> it
= m_aliasDict
; it
!= 0; ++it
) {
190 dict
.insert(it
.currentKey(), it
);
194 bool TypeTable::isEnabledBuiltin(const char* feature
)
196 char* f
= m_enabledBuiltins
.first();
198 if (strcmp(feature
, f
) == 0)
200 f
= m_enabledBuiltins
.next();
205 TypeInfo::TypeInfo(const QString
& displayString
)
207 // decompose the input into the parts
211 while (i
< typeInfoMaxExpr
&&
212 (idx
= displayString
.find('%', startIdx
)) >= 0)
214 m_displayString
[i
] = displayString
.mid(startIdx
, idx
-startIdx
);
220 * Remaining string; note that there's one more display string than
223 m_displayString
[i
] = displayString
.right(displayString
.length()-startIdx
);
226 TypeInfo::~TypeInfo()
231 ProgramTypeTable::ProgramTypeTable() :
232 m_parseQt2QStrings(false),
233 m_QCharIsShort(false),
234 m_printQStringDataCmd(0)
236 m_types
.setAutoDelete(false); /* paranoia */
237 m_aliasDict
.setAutoDelete(false); /* paranoia */
240 ProgramTypeTable::~ProgramTypeTable()
244 void ProgramTypeTable::clear()
249 void ProgramTypeTable::loadTypeTable(TypeTable
* table
)
251 table
->copyTypes(m_types
);
252 // check whether to enable builtin QString support
253 if (!m_parseQt2QStrings
) {
254 m_parseQt2QStrings
= table
->isEnabledBuiltin("QString::Data");
256 if (!m_QCharIsShort
) {
257 m_QCharIsShort
= table
->isEnabledBuiltin("QCharIsShort");
259 if (!m_printQStringDataCmd
&& *table
->printQStringDataCmd()) {
260 m_printQStringDataCmd
= table
->printQStringDataCmd();
264 TypeInfo
* ProgramTypeTable::lookup(const char* type
)
266 TypeInfo
* result
= m_types
[type
];
268 result
= m_aliasDict
[type
];
273 void ProgramTypeTable::registerAlias(const QString
& name
, TypeInfo
* type
)
275 ASSERT(lookup(name
) == 0 || lookup(name
) == type
);
276 m_aliasDict
.insert(name
, type
);
279 void ProgramTypeTable::loadLibTypes(const QStrList
& libs
)
281 QStrListIterator it
= libs
;
284 * We use a copy of the list of known libraries, from which we delete
285 * those libs that we already have added. This way we avoid to load a
288 QList
<TypeTable
> allTables
= typeTables
; /* shallow copy! */
289 allTables
.setAutoDelete(false); /* important! */
291 for (; it
&& allTables
.count() > 0; ++it
)
293 // look up the library
295 for (TypeTable
* t
= allTables
.first(); t
!= 0; t
= allTables
.next())
297 if (t
->matchFileName(it
))
299 TRACE("adding types for " + QString(it
));
304 * continue the search (due to remove's unpredictable
305 * behavior of setting the current item we simply go
306 * through the whole list again)