Need config.h to see debug output.
[kdbg.git] / kdbg / typetable.cpp
blob2f001c334cf72f6f6c0b9e3d89a72d35f1f368aa
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include <qdir.h>
7 #include <qlist.h>
8 #include <kglobal.h>
9 #include <kstddirs.h>
10 #include <ksimpleconfig.h>
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14 #include "typetable.h"
15 #include "mydebug.h"
17 // the TypeTables of all known libraries
18 static QList<TypeTable> typeTables;
19 bool typeTablesInited = false;
22 // the unknown type
23 TypeInfo TypeInfo::m_unknownType("");
26 void TypeTable::initTypeLibraries()
28 if (!typeTablesInited) {
29 TypeTable::loadTypeTables();
33 void TypeTable::loadTypeTables()
35 typeTablesInited = true;
37 const QStringList files = KGlobal::dirs()->findAllResources("types", "*.kdbgtt");
39 if (files.isEmpty()) {
40 TRACE("no type tables found");
41 return;
44 QString fileName;
45 for (QValueListConstIterator<QString> p = files.begin(); p != files.end(); ++p) {
46 fileName = *p;
47 TypeTable* newTable = new TypeTable;
48 newTable->loadFromFile(fileName);
49 typeTables.append(newTable);
54 TypeTable::TypeTable()
56 m_typeDict.setAutoDelete(true);
57 // aliasDict keeps only pointers to items into typeDict
58 m_aliasDict.setAutoDelete(false);
61 TypeTable::~TypeTable()
66 static const char TypeTableGroup[] = "Type Table";
67 static const char LibDisplayName[] = "LibDisplayName";
68 static const char ShlibRE[] = "ShlibRE";
69 static const char EnableBuiltin[] = "EnableBuiltin";
70 static const char TypesEntryFmt[] = "Types%d";
71 static const char DisplayEntry[] = "Display";
72 static const char AliasEntry[] = "Alias";
73 static const char ExprEntryFmt[] = "Expr%d";
74 static const char FunctionGuardEntryFmt[] = "FunctionGuard%d";
77 void TypeTable::loadFromFile(const QString& fileName)
79 TRACE("reading file " + fileName);
80 KSimpleConfig cf(fileName, true); /* read-only */
83 * Read library name and properties.
85 cf.setGroup(TypeTableGroup);
86 m_displayName = cf.readEntry(LibDisplayName);
87 if (m_displayName.isEmpty()) {
88 // use file name instead
89 int slash = fileName.findRev('\\');
90 m_displayName =
91 slash >= 0 ? fileName.mid(slash+1, fileName.length()) : fileName;
92 int dot = m_displayName.findRev('.');
93 if (dot > 0) {
94 m_displayName.truncate(dot);
98 m_shlibNameRE = QRegExp(cf.readEntry(ShlibRE));
99 cf.readListEntry(EnableBuiltin, m_enabledBuiltins);
102 * Get the types. We search for entries of kind Types1, Types2, etc.
103 * because a single entry Types could get rather long for large
104 * libraries.
106 QStrList typeNames;
107 QString typesEntry;
108 for (int i = 1; ; i++) {
109 // next bunch of types
110 cf.setGroup(TypeTableGroup);
111 typesEntry.sprintf(TypesEntryFmt, i);
112 if (!cf.hasKey(typesEntry))
113 break;
114 cf.readListEntry(typesEntry, typeNames, ',');
116 // now read them
117 QString alias;
118 for (QListIterator<char> it(typeNames); it != 0; ++it) {
119 cf.setGroup(it.current());
120 // check if this is an alias
121 alias = cf.readEntry(AliasEntry);
122 if (alias.isEmpty()) {
123 readType(cf, it);
124 } else {
125 // look up the alias type and insert it
126 TypeInfo* info = m_typeDict[alias];
127 if (info == 0) {
128 TRACE(QString().sprintf("<%s>: alias %s not found",
129 it.operator char*(), alias.data()));
130 } else {
131 m_aliasDict.insert(alias, info);
132 TRACE(QString().sprintf("<%s>: alias <%s>",
133 it.operator char*(), alias.data()));
137 } // for all Types%d
140 void TypeTable::readType(KConfigBase& cf, const char* type)
142 // the display string
143 QString expr = cf.readEntry(DisplayEntry);
145 TypeInfo* info = new TypeInfo(expr);
146 if (info->m_numExprs == 0) {
147 TRACE(QString().sprintf("bogus type %s: no %% in Display: '%s'",
148 type, expr.data()));
149 delete info;
150 return;
153 // Expr1, Expr2, etc...
154 QString exprEntry;
155 QString funcGuardEntry;
156 for (int j = 0; j < info->m_numExprs; j++) {
157 exprEntry.sprintf(ExprEntryFmt, j+1);
158 expr = cf.readEntry(exprEntry);
159 info->m_exprStrings[j] = expr;
161 funcGuardEntry.sprintf(FunctionGuardEntryFmt, j+1);
162 expr = cf.readEntry(funcGuardEntry);
163 info->m_guardStrings[j] = expr;
166 // add the new type
167 m_typeDict.insert(type, info);
168 TRACE(QString().sprintf("<%s>: %d exprs", type,
169 info->m_numExprs));
172 void TypeTable::copyTypes(QDict<TypeInfo>& dict)
174 for (QDictIterator<TypeInfo> it = m_typeDict; it != 0; ++it) {
175 dict.insert(it.currentKey(), it);
177 for (QDictIterator<TypeInfo> it = m_aliasDict; it != 0; ++it) {
178 dict.insert(it.currentKey(), it);
182 bool TypeTable::isEnabledBuiltin(const char* feature)
184 char* f = m_enabledBuiltins.first();
185 while (f) {
186 if (strcmp(feature, f) == 0)
187 return true;
188 f = m_enabledBuiltins.next();
190 return false;
193 TypeInfo::TypeInfo(const QString& displayString)
195 // decompose the input into the parts
196 int i = 0;
197 int startIdx = 0;
198 int idx;
199 while (i < typeInfoMaxExpr &&
200 (idx = displayString.find('%', startIdx)) >= 0)
202 m_displayString[i] = displayString.mid(startIdx, idx-startIdx);
203 startIdx = idx+1;
204 i++;
206 m_numExprs = i;
208 * Remaining string; note that there's one more display string than
209 * sub-expressions.
211 m_displayString[i] = displayString.right(displayString.length()-startIdx);
214 TypeInfo::~TypeInfo()
219 ProgramTypeTable::ProgramTypeTable() :
220 m_parseQt2QStrings(false),
221 m_QCharIsShort(false)
223 m_types.setAutoDelete(false); /* paranoia */
224 m_aliasDict.setAutoDelete(false); /* paranoia */
227 ProgramTypeTable::~ProgramTypeTable()
231 void ProgramTypeTable::clear()
233 m_types.clear();
236 void ProgramTypeTable::loadTypeTable(TypeTable* table)
238 table->copyTypes(m_types);
239 // check whether to enable builtin QString support
240 if (!m_parseQt2QStrings) {
241 m_parseQt2QStrings = table->isEnabledBuiltin("QString::Data");
243 if (!m_QCharIsShort) {
244 m_QCharIsShort = table->isEnabledBuiltin("QCharIsShort");
248 TypeInfo* ProgramTypeTable::lookup(const char* type)
250 TypeInfo* result = m_types[type];
251 if (result == 0) {
252 result = m_aliasDict[type];
254 return result;
257 void ProgramTypeTable::registerAlias(const QString& name, TypeInfo* type)
259 ASSERT(lookup(name) == 0 || lookup(name) == type);
260 m_aliasDict.insert(name, type);
263 void ProgramTypeTable::loadLibTypes(const QStrList& libs)
265 QStrListIterator it = libs;
268 * We use a copy of the list of known libraries, from which we delete
269 * those libs that we already have added. This way we avoid to load a
270 * library twice.
272 QList<TypeTable> allTables = typeTables; /* shallow copy! */
273 allTables.setAutoDelete(false); /* important! */
275 for (; it && allTables.count() > 0; ++it)
277 // look up the library
278 repeatLookup:;
279 for (TypeTable* t = allTables.first(); t != 0; t = allTables.next())
281 if (t->matchFileName(it))
283 TRACE("adding types for " + QString(it));
284 loadTypeTable(t);
285 // remove the table
286 allTables.remove();
288 * continue the search (due to remove's unpredictable
289 * behavior of setting the current item we simply go
290 * through the whole list again)
292 goto repeatLookup;