Implemented orphaned breakpoints to simplify debuggin of dynamic modules.
[kdbg.git] / kdbg / typetable.cpp
blob7a95393bf3c9c2c98664b415f6a7754d0e374d41
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 #include "typetable.h"
12 #include "mydebug.h"
14 // the TypeTables of all known libraries
15 static QList<TypeTable> typeTables;
16 bool typeTablesInited = false;
19 // the unknown type
20 TypeInfo TypeInfo::m_unknownType("");
23 void TypeTable::initTypeLibraries()
25 if (!typeTablesInited) {
26 TypeTable::loadTypeTables();
30 void TypeTable::loadTypeTables()
32 typeTablesInited = true;
34 const QStringList files = KGlobal::dirs()->findAllResources("types", "*.kdbgtt");
36 if (files.isEmpty()) {
37 TRACE("no type tables found");
38 return;
41 QString fileName;
42 for (QValueListConstIterator<QString> p = files.begin(); p != files.end(); ++p) {
43 fileName = *p;
44 TypeTable* newTable = new TypeTable;
45 newTable->loadFromFile(fileName);
46 typeTables.append(newTable);
51 TypeTable::TypeTable()
53 m_typeDict.setAutoDelete(true);
54 // aliasDict keeps only pointers to items into typeDict
55 m_aliasDict.setAutoDelete(false);
58 TypeTable::~TypeTable()
63 static const char TypeTableGroup[] = "Type Table";
64 static const char LibDisplayName[] = "LibDisplayName";
65 static const char ShlibRE[] = "ShlibRE";
66 static const char EnableBuiltin[] = "EnableBuiltin";
67 static const char TypesEntryFmt[] = "Types%d";
68 static const char DisplayEntry[] = "Display";
69 static const char AliasEntry[] = "Alias";
70 static const char ExprEntryFmt[] = "Expr%d";
71 static const char FunctionGuardEntryFmt[] = "FunctionGuard%d";
74 void TypeTable::loadFromFile(const QString& fileName)
76 TRACE("reading file " + fileName);
77 KSimpleConfig cf(fileName, true); /* read-only */
80 * Read library name and properties.
82 cf.setGroup(TypeTableGroup);
83 m_displayName = cf.readEntry(LibDisplayName);
84 if (m_displayName.isEmpty()) {
85 // use file name instead
86 int slash = fileName.findRev('\\');
87 m_displayName =
88 slash >= 0 ? fileName.mid(slash+1, fileName.length()) : fileName;
89 int dot = m_displayName.findRev('.');
90 if (dot > 0) {
91 m_displayName.truncate(dot);
95 m_shlibNameRE = QRegExp(cf.readEntry(ShlibRE));
96 cf.readListEntry(EnableBuiltin, m_enabledBuiltins);
99 * Get the types. We search for entries of kind Types1, Types2, etc.
100 * because a single entry Types could get rather long for large
101 * libraries.
103 QStrList typeNames;
104 QString typesEntry;
105 for (int i = 1; ; i++) {
106 // next bunch of types
107 cf.setGroup(TypeTableGroup);
108 typesEntry.sprintf(TypesEntryFmt, i);
109 if (!cf.hasKey(typesEntry))
110 break;
111 cf.readListEntry(typesEntry, typeNames, ',');
113 // now read them
114 QString alias;
115 for (QListIterator<char> it(typeNames); it != 0; ++it) {
116 cf.setGroup(it.current());
117 // check if this is an alias
118 alias = cf.readEntry(AliasEntry);
119 if (alias.isEmpty()) {
120 readType(cf, it);
121 } else {
122 // look up the alias type and insert it
123 TypeInfo* info = m_typeDict[alias];
124 if (info == 0) {
125 TRACE(QString().sprintf("<%s>: alias %s not found",
126 it.operator char*(), alias.data()));
127 } else {
128 m_aliasDict.insert(alias, info);
129 TRACE(QString().sprintf("<%s>: alias <%s>",
130 it.operator char*(), alias.data()));
134 } // for all Types%d
137 void TypeTable::readType(KConfigBase& cf, const char* type)
139 // the display string
140 QString expr = cf.readEntry(DisplayEntry);
142 TypeInfo* info = new TypeInfo(expr);
143 if (info->m_numExprs == 0) {
144 TRACE(QString().sprintf("bogus type %s: no %% in Display: '%s'",
145 type, expr.data()));
146 delete info;
147 return;
150 // Expr1, Expr2, etc...
151 QString exprEntry;
152 QString funcGuardEntry;
153 for (int j = 0; j < info->m_numExprs; j++) {
154 exprEntry.sprintf(ExprEntryFmt, j+1);
155 expr = cf.readEntry(exprEntry);
156 info->m_exprStrings[j] = expr;
158 funcGuardEntry.sprintf(FunctionGuardEntryFmt, j+1);
159 expr = cf.readEntry(funcGuardEntry);
160 info->m_guardStrings[j] = expr;
163 // add the new type
164 m_typeDict.insert(type, info);
165 TRACE(QString().sprintf("<%s>: %d exprs", type,
166 info->m_numExprs));
169 void TypeTable::copyTypes(QDict<TypeInfo>& dict)
171 for (QDictIterator<TypeInfo> it = m_typeDict; it != 0; ++it) {
172 dict.insert(it.currentKey(), it);
174 for (QDictIterator<TypeInfo> it = m_aliasDict; it != 0; ++it) {
175 dict.insert(it.currentKey(), it);
179 bool TypeTable::isEnabledBuiltin(const char* feature)
181 char* f = m_enabledBuiltins.first();
182 while (f) {
183 if (strcmp(feature, f) == 0)
184 return true;
185 f = m_enabledBuiltins.next();
187 return false;
190 TypeInfo::TypeInfo(const QString& displayString)
192 // decompose the input into the parts
193 int i = 0;
194 int startIdx = 0;
195 int idx;
196 while (i < typeInfoMaxExpr &&
197 (idx = displayString.find('%', startIdx)) >= 0)
199 m_displayString[i] = displayString.mid(startIdx, idx-startIdx);
200 startIdx = idx+1;
201 i++;
203 m_numExprs = i;
205 * Remaining string; note that there's one more display string than
206 * sub-expressions.
208 m_displayString[i] = displayString.right(displayString.length()-startIdx);
211 TypeInfo::~TypeInfo()
216 ProgramTypeTable::ProgramTypeTable() :
217 m_parseQt2QStrings(false),
218 m_QCharIsShort(false)
220 m_types.setAutoDelete(false); /* paranoia */
221 m_aliasDict.setAutoDelete(false); /* paranoia */
224 ProgramTypeTable::~ProgramTypeTable()
228 void ProgramTypeTable::clear()
230 m_types.clear();
233 void ProgramTypeTable::loadTypeTable(TypeTable* table)
235 table->copyTypes(m_types);
236 // check whether to enable builtin QString support
237 if (!m_parseQt2QStrings) {
238 m_parseQt2QStrings = table->isEnabledBuiltin("QString::Data");
240 if (!m_QCharIsShort) {
241 m_QCharIsShort = table->isEnabledBuiltin("QCharIsShort");
245 TypeInfo* ProgramTypeTable::lookup(const char* type)
247 TypeInfo* result = m_types[type];
248 if (result == 0) {
249 result = m_aliasDict[type];
251 return result;
254 void ProgramTypeTable::registerAlias(const QString& name, TypeInfo* type)
256 ASSERT(lookup(name) == 0 || lookup(name) == type);
257 m_aliasDict.insert(name, type);
260 void ProgramTypeTable::loadLibTypes(const QStrList& libs)
262 QStrListIterator it = libs;
265 * We use a copy of the list of known libraries, from which we delete
266 * those libs that we already have added. This way we avoid to load a
267 * library twice.
269 QList<TypeTable> allTables = typeTables; /* shallow copy! */
270 allTables.setAutoDelete(false); /* important! */
272 for (; it && allTables.count() > 0; ++it)
274 // look up the library
275 repeatLookup:;
276 for (TypeTable* t = allTables.first(); t != 0; t = allTables.next())
278 if (t->matchFileName(it))
280 TRACE("adding types for " + QString(it));
281 loadTypeTable(t);
282 // remove the table
283 allTables.remove();
285 * continue the search (due to remove's unpredictable
286 * behavior of setting the current item we simply go
287 * through the whole list again)
289 goto repeatLookup;