Update the admin/ directory.
[kdbg.git] / kdbg / typetable.cpp
blobe89e80be6049c4500daac0f89d6fcaf9c691fe9f
1 /*
2 * Copyright Johannes Sixt
3 * This file is licensed under the GNU General Public License Version 2.
4 * See the file COPYING in the toplevel directory of the source directory.
5 */
7 #include <qdir.h>
8 #include <qptrlist.h>
9 #include <kglobal.h>
10 #include <kstddirs.h>
11 #include <ksimpleconfig.h>
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15 #include "typetable.h"
16 #include "mydebug.h"
18 // the TypeTables of all known libraries
19 static QList<TypeTable> typeTables;
20 bool typeTablesInited = false;
23 // an indentifier for wchar_t
24 TypeInfo TypeInfo::m_wchartType("");
25 // the unknown type
26 TypeInfo TypeInfo::m_unknownType("");
29 void TypeTable::initTypeLibraries()
31 if (!typeTablesInited) {
32 TypeTable::loadTypeTables();
36 void TypeTable::loadTypeTables()
38 typeTablesInited = true;
40 const QStringList files = KGlobal::dirs()->findAllResources("types", "*.kdbgtt");
42 if (files.isEmpty()) {
43 TRACE("no type tables found");
44 return;
47 QString fileName;
48 for (QValueListConstIterator<QString> p = files.begin(); p != files.end(); ++p) {
49 fileName = *p;
50 TypeTable* newTable = new TypeTable;
51 newTable->loadFromFile(fileName);
52 typeTables.append(newTable);
57 TypeTable::TypeTable() :
58 m_printQStringDataCmd(0)
60 m_typeDict.setAutoDelete(true);
61 // aliasDict keeps only pointers to items into typeDict
62 m_aliasDict.setAutoDelete(false);
65 TypeTable::~TypeTable()
67 delete[] m_printQStringDataCmd;
71 static const char TypeTableGroup[] = "Type Table";
72 static const char LibDisplayName[] = "LibDisplayName";
73 static const char ShlibRE[] = "ShlibRE";
74 static const char EnableBuiltin[] = "EnableBuiltin";
75 static const char PrintQStringCmd[] = "PrintQStringCmd";
76 static const char TypesEntryFmt[] = "Types%d";
77 static const char DisplayEntry[] = "Display";
78 static const char AliasEntry[] = "Alias";
79 static const char ExprEntryFmt[] = "Expr%d";
80 static const char FunctionGuardEntryFmt[] = "FunctionGuard%d";
83 void TypeTable::loadFromFile(const QString& fileName)
85 TRACE("reading file " + fileName);
86 KSimpleConfig cf(fileName, true); /* read-only */
89 * Read library name and properties.
91 cf.setGroup(TypeTableGroup);
92 m_displayName = cf.readEntry(LibDisplayName);
93 if (m_displayName.isEmpty()) {
94 // use file name instead
95 int slash = fileName.findRev('\\');
96 m_displayName =
97 slash >= 0 ? fileName.mid(slash+1, fileName.length()) : fileName;
98 int dot = m_displayName.findRev('.');
99 if (dot > 0) {
100 m_displayName.truncate(dot);
104 m_shlibNameRE = QRegExp(cf.readEntry(ShlibRE));
105 cf.readListEntry(EnableBuiltin, m_enabledBuiltins);
107 QString printQString = cf.readEntry(PrintQStringCmd);
108 const char* ascii = printQString.ascii();
109 if (ascii == 0)
110 ascii = "";
111 m_printQStringDataCmd = new char[strlen(ascii)+1];
112 strcpy(m_printQStringDataCmd, ascii);
115 * Get the types. We search for entries of kind Types1, Types2, etc.
116 * because a single entry Types could get rather long for large
117 * libraries.
119 QStrList typeNames;
120 QString typesEntry;
121 for (int i = 1; ; i++) {
122 // next bunch of types
123 cf.setGroup(TypeTableGroup);
124 typesEntry.sprintf(TypesEntryFmt, i);
125 if (!cf.hasKey(typesEntry))
126 break;
127 cf.readListEntry(typesEntry, typeNames, ',');
129 // now read them
130 QString alias;
131 for (QListIterator<char> it(typeNames); it != 0; ++it) {
132 cf.setGroup(it.current());
133 // check if this is an alias
134 alias = cf.readEntry(AliasEntry);
135 if (alias.isEmpty()) {
136 readType(cf, it);
137 } else {
138 // look up the alias type and insert it
139 TypeInfo* info = m_typeDict[alias];
140 if (info == 0) {
141 TRACE(QString().sprintf("<%s>: alias %s not found",
142 it.operator char*(), alias.data()));
143 } else {
144 m_aliasDict.insert(alias, info);
145 TRACE(QString().sprintf("<%s>: alias <%s>",
146 it.operator char*(), alias.data()));
150 } // for all Types%d
153 void TypeTable::readType(KConfigBase& cf, const char* type)
155 // the display string
156 QString expr = cf.readEntry(DisplayEntry);
158 TypeInfo* info = new TypeInfo(expr);
159 if (info->m_numExprs == 0) {
160 TRACE(QString().sprintf("bogus type %s: no %% in Display: '%s'",
161 type, expr.data()));
162 delete info;
163 return;
166 // Expr1, Expr2, etc...
167 QString exprEntry;
168 QString funcGuardEntry;
169 for (int j = 0; j < info->m_numExprs; j++) {
170 exprEntry.sprintf(ExprEntryFmt, j+1);
171 expr = cf.readEntry(exprEntry);
172 info->m_exprStrings[j] = expr;
174 funcGuardEntry.sprintf(FunctionGuardEntryFmt, j+1);
175 expr = cf.readEntry(funcGuardEntry);
176 info->m_guardStrings[j] = expr;
179 // add the new type
180 m_typeDict.insert(type, info);
181 TRACE(QString().sprintf("<%s>: %d exprs", type,
182 info->m_numExprs));
185 void TypeTable::copyTypes(QDict<TypeInfo>& dict)
187 for (QDictIterator<TypeInfo> it = m_typeDict; it != 0; ++it) {
188 dict.insert(it.currentKey(), it);
190 for (QDictIterator<TypeInfo> it = m_aliasDict; it != 0; ++it) {
191 dict.insert(it.currentKey(), it);
195 bool TypeTable::isEnabledBuiltin(const char* feature)
197 char* f = m_enabledBuiltins.first();
198 while (f) {
199 if (strcmp(feature, f) == 0)
200 return true;
201 f = m_enabledBuiltins.next();
203 return false;
206 TypeInfo::TypeInfo(const QString& displayString)
208 // decompose the input into the parts
209 int i = 0;
210 int startIdx = 0;
211 int idx;
212 while (i < typeInfoMaxExpr &&
213 (idx = displayString.find('%', startIdx)) >= 0)
215 m_displayString[i] = displayString.mid(startIdx, idx-startIdx);
216 startIdx = idx+1;
217 i++;
219 m_numExprs = i;
221 * Remaining string; note that there's one more display string than
222 * sub-expressions.
224 m_displayString[i] = displayString.right(displayString.length()-startIdx);
227 TypeInfo::~TypeInfo()
232 ProgramTypeTable::ProgramTypeTable() :
233 m_parseQt2QStrings(false),
234 m_QCharIsShort(false),
235 m_printQStringDataCmd(0)
237 m_types.setAutoDelete(false); /* paranoia */
238 m_aliasDict.setAutoDelete(false); /* paranoia */
241 ProgramTypeTable::~ProgramTypeTable()
245 void ProgramTypeTable::clear()
247 m_types.clear();
250 void ProgramTypeTable::loadTypeTable(TypeTable* table)
252 table->copyTypes(m_types);
253 // check whether to enable builtin QString support
254 if (!m_parseQt2QStrings) {
255 m_parseQt2QStrings = table->isEnabledBuiltin("QString::Data");
257 if (!m_QCharIsShort) {
258 m_QCharIsShort = table->isEnabledBuiltin("QCharIsShort");
260 if (!m_printQStringDataCmd && *table->printQStringDataCmd()) {
261 m_printQStringDataCmd = table->printQStringDataCmd();
265 TypeInfo* ProgramTypeTable::lookup(const char* type)
267 TypeInfo* result = m_types[type];
268 if (result == 0) {
269 result = m_aliasDict[type];
271 return result;
274 void ProgramTypeTable::registerAlias(const QString& name, TypeInfo* type)
276 ASSERT(lookup(name) == 0 || lookup(name) == type);
277 m_aliasDict.insert(name, type);
280 void ProgramTypeTable::loadLibTypes(const QStrList& libs)
282 QStrListIterator it = libs;
285 * We use a copy of the list of known libraries, from which we delete
286 * those libs that we already have added. This way we avoid to load a
287 * library twice.
289 QList<TypeTable> allTables = typeTables; /* shallow copy! */
290 allTables.setAutoDelete(false); /* important! */
292 for (; it && allTables.count() > 0; ++it)
294 // look up the library
295 repeatLookup:;
296 for (TypeTable* t = allTables.first(); t != 0; t = allTables.next())
298 if (t->matchFileName(it))
300 TRACE("adding types for " + QString(it));
301 loadTypeTable(t);
302 // remove the table
303 allTables.remove();
305 * continue the search (due to remove's unpredictable
306 * behavior of setting the current item we simply go
307 * through the whole list again)
309 goto repeatLookup;