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  */
6 
7 #include "gdbdriver.h"
8 #include "exprwnd.h"
9 #include <QFileInfo>
10 #include <QRegExp>
11 #include <QStringList>
12 #include <klocalizedstring.h>		/* i18n */
13 #include <ctype.h>
14 #include <signal.h>
15 #include <stdlib.h>			/* strtol, atoi */
16 #include <string.h>			/* strcpy */
17 
18 #include "assert.h"
19 #include "mydebug.h"
20 
21 static void skipString(const char*& p);
22 static void skipNested(const char*& s, char opening, char closing);
23 static ExprValue* parseVar(const char*& s);
24 static bool parseName(const char*& s, QString& name, VarTree::NameKind& kind);
25 static bool parseValue(const char*& s, ExprValue* variable);
26 static bool parseNested(const char*& s, ExprValue* variable);
27 static bool parseVarSeq(const char*& s, ExprValue* variable);
28 static bool parseValueSeq(const char*& s, ExprValue* variable);
29 
30 #define PROMPT "(kdbg)"
31 #define PROMPT_LEN 6
32 
33 // TODO: make this cmd info stuff non-static to allow multiple
34 // simultaneous gdbs to run!
35 
36 struct GdbCmdInfo {
37     DbgCommand cmd;
38     const char* fmt;			/* format string */
39     enum Args {
40 	argNone, argString, argNum,
41 	argStringNum, argNumString,
42 	argString2, argNum2
43     } argsNeeded;
44 };
45 
46 #if 0
47 // This is  how the QString data print statement generally looks like.
48 // It is set by KDebugger via setPrintQStringDataCmd().
49 
50 static const char printQStringStructFmt[] =
51 		// if the string data is junk, fail early
52 		"print ($qstrunicode=($qstrdata=(%s))->unicode)?"
53 		// print an array of shorts
54 		"(*(unsigned short*)$qstrunicode)@"
55 		// limit the length
56 		"(($qstrlen=(unsigned int)($qstrdata->len))>100?100:$qstrlen)"
57 		// if unicode data is 0, report a special value
58 		":1==0\n";
59 #endif
60 static const char printQStringStructFmt[] = "print (0?\"%s\":$kdbgundef)\n";
61 
62 /*
63  * The following array of commands must be sorted by the DC* values,
64  * because they are used as indices.
65  */
66 static GdbCmdInfo cmds[] = {
67     { DCinitialize, "", GdbCmdInfo::argNone },
68     { DCtty, "tty %s\n", GdbCmdInfo::argString },
69     { DCexecutable, "file \"%s\"\n", GdbCmdInfo::argString },
70     { DCtargetremote, "target remote %s\n", GdbCmdInfo::argString },
71 #ifdef __FreeBSD__
72     { DCcorefile, "target FreeBSD-core %s\n", GdbCmdInfo::argString },
73 #else
74     { DCcorefile, "target core %s\n", GdbCmdInfo::argString },
75 #endif
76     { DCattach, "attach %s\n", GdbCmdInfo::argString },
77     { DCinfolinemain, "kdbg_infolinemain\n", GdbCmdInfo::argNone },
78     { DCinfolocals, "kdbg__alllocals\n", GdbCmdInfo::argNone },
79     { DCinforegisters, "info all-registers\n", GdbCmdInfo::argNone},
80     { DCexamine, "x %s %s\n", GdbCmdInfo::argString2 },
81     { DCinfoline, "info line %s:%d\n", GdbCmdInfo::argStringNum },
82     { DCdisassemble, "disassemble %s %s\n", GdbCmdInfo::argString2 },
83     { DCsetargs, "set args %s\n", GdbCmdInfo::argString },
84     { DCsetenv, "set env %s %s\n", GdbCmdInfo::argString2 },
85     { DCunsetenv, "unset env %s\n", GdbCmdInfo::argString },
86     { DCsetoption, "setoption %s %d\n", GdbCmdInfo::argStringNum},
87     { DCcd, "cd %s\n", GdbCmdInfo::argString },
88     { DCbt, "bt\n", GdbCmdInfo::argNone },
89     { DCrun, "run\n", GdbCmdInfo::argNone },
90     { DCcont, "cont\n", GdbCmdInfo::argNone },
91     { DCstep, "step\n", GdbCmdInfo::argNone },
92     { DCstepi, "stepi\n", GdbCmdInfo::argNone },
93     { DCnext, "next\n", GdbCmdInfo::argNone },
94     { DCnexti, "nexti\n", GdbCmdInfo::argNone },
95     { DCfinish, "finish\n", GdbCmdInfo::argNone },
96     { DCuntil, "until %s:%d\n", GdbCmdInfo::argStringNum },
97     { DCkill, "kill\n", GdbCmdInfo::argNone },
98     { DCdetach, "detach\n", GdbCmdInfo::argNone },
99     { DCbreaktext, "break %s\n", GdbCmdInfo::argString },
100     { DCbreakline, "break %s:%d\n", GdbCmdInfo::argStringNum },
101     { DCtbreakline, "tbreak %s:%d\n", GdbCmdInfo::argStringNum },
102     { DCbreakaddr, "break *%s\n", GdbCmdInfo::argString },
103     { DCtbreakaddr, "tbreak *%s\n", GdbCmdInfo::argString },
104     { DCwatchpoint, "watch %s\n", GdbCmdInfo::argString },
105     { DCdelete, "delete %d\n", GdbCmdInfo::argNum },
106     { DCenable, "enable %d\n", GdbCmdInfo::argNum },
107     { DCdisable, "disable %d\n", GdbCmdInfo::argNum },
108     { DCprint, "print %s\n", GdbCmdInfo::argString },
109     { DCprintDeref, "print *(%s)\n", GdbCmdInfo::argString },
110     { DCprintStruct, "print %s\n", GdbCmdInfo::argString },
111     { DCprintQStringStruct, printQStringStructFmt, GdbCmdInfo::argString},
112     { DCprintPopup, "print %s\n", GdbCmdInfo::argString },
113     { DCframe, "frame %d\n", GdbCmdInfo::argNum },
114     { DCfindType, "whatis %s\n", GdbCmdInfo::argString },
115     { DCinfosharedlib, "info sharedlibrary\n", GdbCmdInfo::argNone },
116     { DCthread, "thread %d\n", GdbCmdInfo::argNum },
117     { DCinfothreads, "info threads\n", GdbCmdInfo::argNone },
118     { DCinfobreak, "info breakpoints\n", GdbCmdInfo::argNone },
119     { DCcondition, "condition %d %s\n", GdbCmdInfo::argNumString},
120     { DCsetpc, "set variable $pc=%s\n", GdbCmdInfo::argString },
121     { DCignore, "ignore %d %d\n", GdbCmdInfo::argNum2},
122     { DCprintWChar, "print ($s=%s)?*$s@wcslen($s):0x0\n", GdbCmdInfo::argString },
123     { DCsetvariable, "set variable %s=%s\n", GdbCmdInfo::argString2 },
124 };
125 
126 #define NUM_CMDS (int(sizeof(cmds)/sizeof(cmds[0])))
127 #define MAX_FMTLEN 200
128 
GdbDriver()129 GdbDriver::GdbDriver() :
130 	DebuggerDriver()
131 {
132 #ifndef NDEBUG
133     // check command info array
134     const char* perc;
135     for (int i = 0; i < NUM_CMDS; i++) {
136 	// must be indexable by DbgCommand values, i.e. sorted by DbgCommand values
137 	assert(i == cmds[i].cmd);
138 	// a format string must be associated
139 	assert(cmds[i].fmt != 0);
140 	assert(strlen(cmds[i].fmt) <= MAX_FMTLEN);
141 	// format string must match arg specification
142 	switch (cmds[i].argsNeeded) {
143 	case GdbCmdInfo::argNone:
144 	    assert(strchr(cmds[i].fmt, '%') == 0);
145 	    break;
146 	case GdbCmdInfo::argString:
147 	    perc = strchr(cmds[i].fmt, '%');
148 	    assert(perc != 0 && perc[1] == 's');
149 	    assert(strchr(perc+2, '%') == 0);
150 	    break;
151 	case GdbCmdInfo::argNum:
152 	    perc = strchr(cmds[i].fmt, '%');
153 	    assert(perc != 0 && perc[1] == 'd');
154 	    assert(strchr(perc+2, '%') == 0);
155 	    break;
156 	case GdbCmdInfo::argStringNum:
157 	    perc = strchr(cmds[i].fmt, '%');
158 	    assert(perc != 0 && perc[1] == 's');
159 	    perc = strchr(perc+2, '%');
160 	    assert(perc != 0 && perc[1] == 'd');
161 	    assert(strchr(perc+2, '%') == 0);
162 	    break;
163 	case GdbCmdInfo::argNumString:
164 	    perc = strchr(cmds[i].fmt, '%');
165 	    assert(perc != 0 && perc[1] == 'd');
166 	    perc = strchr(perc+2, '%');
167 	    assert(perc != 0 && perc[1] == 's');
168 	    assert(strchr(perc+2, '%') == 0);
169 	    break;
170 	case GdbCmdInfo::argString2:
171 	    perc = strchr(cmds[i].fmt, '%');
172 	    assert(perc != 0 && perc[1] == 's');
173 	    perc = strchr(perc+2, '%');
174 	    assert(perc != 0 && perc[1] == 's');
175 	    assert(strchr(perc+2, '%') == 0);
176 	    break;
177 	case GdbCmdInfo::argNum2:
178 	    perc = strchr(cmds[i].fmt, '%');
179 	    assert(perc != 0 && perc[1] == 'd');
180 	    perc = strchr(perc+2, '%');
181 	    assert(perc != 0 && perc[1] == 'd');
182 	    assert(strchr(perc+2, '%') == 0);
183 	    break;
184 	}
185     }
186     assert(strlen(printQStringStructFmt) <= MAX_FMTLEN);
187 #endif
188 }
189 
~GdbDriver()190 GdbDriver::~GdbDriver()
191 {
192 }
193 
194 
driverName() const195 QString GdbDriver::driverName() const
196 {
197     return "GDB";
198 }
199 
defaultGdb()200 QString GdbDriver::defaultGdb()
201 {
202     return
203 	"gdb"
204 	" --fullname"	/* to get standard file names each time the prog stops */
205 	" --nx";	/* do not execute initialization files */
206 }
207 
defaultInvocation() const208 QString GdbDriver::defaultInvocation() const
209 {
210     if (m_defaultCmd.isEmpty()) {
211 	return defaultGdb();
212     } else {
213 	return m_defaultCmd;
214     }
215 }
216 
boolOptionList() const217 QStringList GdbDriver::boolOptionList() const
218 {
219     // no options
220     return QStringList();
221 }
222 
startup(QString cmdStr)223 bool GdbDriver::startup(QString cmdStr)
224 {
225     if (!DebuggerDriver::startup(cmdStr))
226 	return false;
227 
228     static const char gdbInitialize[] =
229 	/*
230 	 * Work around buggy gdbs that do command line editing even if they
231 	 * are not on a tty. The readline library echos every command back
232 	 * in this case, which is confusing for us.
233 	 */
234 	"set editing off\n"
235 	"set confirm off\n"
236 	"set print static-members off\n"
237 	"set print asm-demangle on\n"
238 	/*
239 	 * Sometimes, gdb prints [New Thread ...] during 'info threads';
240 	 * we will not look at thread events anyway, so turn them off.
241 	 */
242 	"set print thread-events off\n"
243 	/*
244 	 * We do not want Python pretty printer support, because their
245 	 * output is unpredictable, and we cannot parse it.
246 	 */
247 	"set auto-load python off\n"
248 	/*
249 	 * Nevertheless, some Python messages get through, for example,
250 	 * when a backtrace is printed without the Python gdb module loaded.
251 	 */
252 	"set python print-stack none\n"
253 	/*
254 	 * Don't assume that program functions invoked from a watch expression
255 	 * always succeed.
256 	 */
257 	"set unwindonsignal on\n"
258 	/*
259 	 * Write a short macro that prints all locals: local variables and
260 	 * function arguments.
261 	 */
262 	"define kdbg__alllocals\n"
263 	"info locals\n"			/* local vars supersede args with same name */
264 	"info args\n"			/* therefore, arguments must come last */
265 	"end\n"
266 	/*
267 	 * Work around a bug in gdb-6.3: "info line main" crashes gdb.
268 	 */
269 	"define kdbg_infolinemain\n"
270 	"list\n"
271 	"info line\n"
272 	"end\n"
273 	// check endianness for memory dumps
274 	"show endian\n"
275 	// change prompt string and synchronize with gdb
276 	"set prompt " PROMPT "\n"
277 	;
278 
279     executeCmdString(DCinitialize, gdbInitialize, false);
280 
281     // assume that QString::null is ok
282     cmds[DCprintQStringStruct].fmt = printQStringStructFmt;
283 
284     return true;
285 }
286 
commandFinished(CmdQueueItem * cmd)287 void GdbDriver::commandFinished(CmdQueueItem* cmd)
288 {
289     // command string must be committed
290     if (!cmd->m_committed) {
291 	// not commited!
292 	TRACE("calling " + (__PRETTY_FUNCTION__ + (" with uncommited command:\n\t" +
293 	      cmd->m_cmdString)));
294 	return;
295     }
296 
297     switch (cmd->m_cmd) {
298     case DCinitialize:
299 	{
300 	    /*
301 	     * Check for GDB 7.1 or later; the syntax for the disassemble
302 	     * command has changed.
303 	     * This RE picks the last version number in the first line,
304 	     * because at least OpenSUSE writes its own version number
305 	     * in the first line (but before GDB's version number).
306 	     */
307 	    QRegExp re(
308 		" "			// must be preceded by space
309 		"[(]?"			// SLES 10 embeds in parentheses
310 		"(\\d+)\\.(\\d+)"	// major, minor
311 		"[^ ]*\\n"		// no space until end of line
312 		);
313 	    int pos = re.indexIn(m_output);
314 	    const char* disass = "disassemble %s %s\n";
315 	    if (pos >= 0) {
316 		int major = re.cap(1).toInt();
317 		int minor = re.cap(2).toInt();
318 		if (major > 7 || (major == 7 && minor >= 1))
319 		{
320 		    disass = "disassemble %s, %s\n";
321 		}
322 	    }
323 	    cmds[DCdisassemble].fmt = disass;
324 
325 	    m_littleendian = m_output.contains("little endian");
326 	}
327 	break;
328     default:;
329     }
330 
331     /* ok, the command is ready */
332     emit commandReceived(cmd, m_output.constData());
333 
334     switch (cmd->m_cmd) {
335     case DCcorefile:
336     case DCinfolinemain:
337     case DCinfoline:
338     case DCframe:
339     case DCattach:
340     case DCrun:
341     case DCcont:
342     case DCstep:
343     case DCstepi:
344     case DCnext:
345     case DCnexti:
346     case DCfinish:
347     case DCuntil:
348 	parseMarker(cmd);
349     default:;
350     }
351 }
352 
findPrompt(const QByteArray & output) const353 int GdbDriver::findPrompt(const QByteArray& output) const
354 {
355     /*
356      * If there's a prompt string in the collected output, it must be at
357      * the very end.
358      *
359      * Note: It could nevertheless happen that a character sequence that is
360      * equal to the prompt string appears at the end of the output,
361      * although it is very, very unlikely (namely as part of a string that
362      * lingered in gdb's output buffer due to some timing/heavy load
363      * conditions for a very long time such that that buffer overflowed
364      * exactly at the end of the prompt string look-a-like).
365      */
366     int len = output.length();
367     if (len >= PROMPT_LEN &&
368 	strncmp(output.data()+len-PROMPT_LEN, PROMPT, PROMPT_LEN) == 0)
369     {
370 	return len-PROMPT_LEN;
371     }
372     return -1;
373 }
374 
375 /*
376  * The --fullname option makes gdb send a special normalized sequence print
377  * each time the program stops and at some other points. The sequence has
378  * the form "\032\032filename:lineno:charoffset:(beg|middle):address".
379  */
parseMarker(CmdQueueItem * cmd)380 void GdbDriver::parseMarker(CmdQueueItem* cmd)
381 {
382     char* startMarker = strstr(m_output.data(), "\032\032");
383     if (startMarker == 0)
384 	return;
385 
386     // extract the marker
387     startMarker += 2;
388     TRACE(QString("found marker: ") + startMarker);
389     char* endMarker = strchr(startMarker, '\n');
390     if (endMarker == 0)
391 	return;
392 
393     *endMarker = '\0';
394 
395     // extract filename and line number
396     static QRegExp MarkerRE(":(\\d+):\\d+:[begmidl]+:0x");
397 
398     int lineNoStart = MarkerRE.indexIn(startMarker);
399     if (lineNoStart >= 0) {
400 	int lineNo = MarkerRE.cap(1).toInt();
401 
402 	// get address unless there is one in cmd
403 	DbgAddr address = cmd->m_addr;
404 	if (address.isEmpty()) {
405 	    const char* addrStart = startMarker + lineNoStart +
406 				    MarkerRE.matchedLength() - 2;
407 	    address = QString(addrStart).trimmed();
408 	}
409 
410 	// now show the window
411 	startMarker[lineNoStart] = '\0';   /* split off file name */
412 	emit activateFileLine(startMarker, lineNo-1, address);
413     }
414 }
415 
416 
417 /*
418  * Escapes characters that might lead to problems when they appear on gdb's
419  * command line.
420  */
normalizeStringArg(QString & arg)421 static void normalizeStringArg(QString& arg)
422 {
423     /*
424      * Remove trailing backslashes. This approach is a little simplistic,
425      * but we know that there is at the moment no case where a trailing
426      * backslash would make sense.
427      */
428     while (!arg.isEmpty() && arg[arg.length()-1] == '\\') {
429 	arg = arg.left(arg.length()-1);
430     }
431 }
432 
433 
makeCmdString(DbgCommand cmd,QString strArg)434 QString GdbDriver::makeCmdString(DbgCommand cmd, QString strArg)
435 {
436     assert(cmd >= 0 && cmd < NUM_CMDS);
437     assert(cmds[cmd].argsNeeded == GdbCmdInfo::argString);
438 
439     normalizeStringArg(strArg);
440 
441     if (cmd == DCcd) {
442 	// need the working directory when parsing the output
443 	m_programWD = strArg;
444     } else if (cmd == DCsetargs && !m_redirect.isEmpty()) {
445 	/*
446 	 * Use saved redirection. We prepend it in front of the user's
447 	 * arguments so that the user can override the redirections.
448 	*/
449 	strArg = m_redirect + " " + strArg;
450     }
451 
452     QString cmdString;
453     cmdString.sprintf(cmds[cmd].fmt, strArg.toUtf8().constData());
454     return cmdString;
455 }
456 
makeCmdString(DbgCommand cmd,int intArg)457 QString GdbDriver::makeCmdString(DbgCommand cmd, int intArg)
458 {
459     assert(cmd >= 0 && cmd < NUM_CMDS);
460     assert(cmds[cmd].argsNeeded == GdbCmdInfo::argNum);
461 
462     QString cmdString;
463     cmdString.sprintf(cmds[cmd].fmt, intArg);
464     return cmdString;
465 }
466 
makeCmdString(DbgCommand cmd,QString strArg,int intArg1,int intArg2)467 QString GdbDriver::makeCmdString(DbgCommand cmd, QString strArg, int intArg1, int intArg2)
468 {
469     assert(cmd == DCexamine);
470 
471     normalizeStringArg(strArg);
472 
473     QString cmdString;
474 
475     if (cmd == DCexamine) {
476 	// make a format specifier from the intArg
477 	static const char size[16] = {
478 	    '\0', 'b', 'h', 'w', 'g'
479 	};
480 	static const char format[16] = {
481 	    '\0', 'x', 'd', 'u', 'o', 't',
482 	    'a',  'c', 'f', 's', 'i'
483 	};
484 	assert(MDTsizemask == 0xf);	/* lowest 4 bits */
485 	assert(MDTformatmask == 0xf0);	/* next 4 bits */
486 	int count = intArg2;			/* number of entities to print */
487 	char sizeSpec = size[intArg1 & MDTsizemask];
488 	char formatSpec = format[(intArg1 & MDTformatmask) >> 4];
489 	assert(sizeSpec != '\0');
490 	assert(formatSpec != '\0');
491 
492 	QString spec;
493 	spec.sprintf("/%d%c%c", count, sizeSpec, formatSpec);
494 	cmdString = makeCmdString(DCexamine, spec, strArg);
495     }
496 
497     return cmdString;
498 }
499 
makeCmdString(DbgCommand cmd,QString strArg,int intArg)500 QString GdbDriver::makeCmdString(DbgCommand cmd, QString strArg, int intArg)
501 {
502     assert(cmd >= 0 && cmd < NUM_CMDS);
503     assert(cmds[cmd].argsNeeded == GdbCmdInfo::argStringNum ||
504 	   cmds[cmd].argsNeeded == GdbCmdInfo::argNumString ||
505 	   cmd == DCtty);
506 
507     normalizeStringArg(strArg);
508 
509     QString cmdString;
510 
511     if (cmd == DCtty)
512     {
513 	/*
514 	 * intArg specifies which channels should be redirected to
515 	 * /dev/null. It is a value or'ed together from RDNstdin,
516 	 * RDNstdout, RDNstderr. We store the value for a later DCsetargs
517 	 * command.
518 	 *
519 	 * Note: We rely on that after the DCtty a DCsetargs will follow,
520 	 * which will ultimately apply the redirection.
521 	 */
522 	static const char* const runRedir[8] = {
523 	    "",
524 	    "</dev/null",
525 	    ">/dev/null",
526 	    "</dev/null >/dev/null",
527 	    "2>/dev/null",
528 	    "</dev/null 2>/dev/null",
529 	    ">/dev/null 2>&1",
530 	    "</dev/null >/dev/null 2>&1"
531 	};
532 	if (strArg.isEmpty())
533 	    intArg = 7;			/* failsafe if no tty */
534 	m_redirect = runRedir[intArg & 7];
535 
536 	return makeCmdString(DCtty, strArg);   /* note: no problem if strArg empty */
537     }
538 
539     if (cmds[cmd].argsNeeded == GdbCmdInfo::argStringNum)
540     {
541 	// line numbers are zero-based
542 	if (cmd == DCuntil || cmd == DCbreakline ||
543 	    cmd == DCtbreakline || cmd == DCinfoline)
544 	{
545 	    intArg++;
546 	}
547 	if (cmd == DCinfoline)
548 	{
549 	    // must split off file name part
550 	    strArg = QFileInfo(strArg).fileName();
551 	}
552 	cmdString.sprintf(cmds[cmd].fmt, strArg.toUtf8().constData(), intArg);
553     }
554     else
555     {
556 	cmdString.sprintf(cmds[cmd].fmt, intArg, strArg.toUtf8().constData());
557     }
558     return cmdString;
559 }
560 
makeCmdString(DbgCommand cmd,QString strArg1,QString strArg2)561 QString GdbDriver::makeCmdString(DbgCommand cmd, QString strArg1, QString strArg2)
562 {
563     assert(cmd >= 0 && cmd < NUM_CMDS);
564     assert(cmds[cmd].argsNeeded == GdbCmdInfo::argString2);
565 
566     normalizeStringArg(strArg1);
567     normalizeStringArg(strArg2);
568 
569     QString cmdString;
570     cmdString.sprintf(cmds[cmd].fmt,
571 		      strArg1.toUtf8().constData(),
572 		      strArg2.toUtf8().constData());
573     return cmdString;
574 }
575 
makeCmdString(DbgCommand cmd,int intArg1,int intArg2)576 QString GdbDriver::makeCmdString(DbgCommand cmd, int intArg1, int intArg2)
577 {
578     assert(cmd >= 0 && cmd < NUM_CMDS);
579     assert(cmds[cmd].argsNeeded == GdbCmdInfo::argNum2);
580 
581     QString cmdString;
582     cmdString.sprintf(cmds[cmd].fmt, intArg1, intArg2);
583     return cmdString;
584 }
585 
makeCmdString(DbgCommand cmd)586 QString GdbDriver::makeCmdString(DbgCommand cmd)
587 {
588     assert(cmd >= 0 && cmd < NUM_CMDS);
589     assert(cmds[cmd].argsNeeded == GdbCmdInfo::argNone);
590 
591     return cmds[cmd].fmt;
592 }
593 
terminate()594 void GdbDriver::terminate()
595 {
596     if (m_state != DSidle)
597     {
598 	::kill(pid(), SIGINT);
599 	m_state = DSinterrupted;
600     }
601     flushCommands();
602     closeWriteChannel();
603 }
604 
detachAndTerminate()605 void GdbDriver::detachAndTerminate()
606 {
607     ::kill(pid(), SIGINT);
608     flushCommands();
609     executeCmdString(DCinitialize, "detach\nquit\n", true);
610 }
611 
interruptInferior()612 void GdbDriver::interruptInferior()
613 {
614     ::kill(pid(), SIGINT);
615     // remove accidentally queued commands
616     flushHiPriQueue();
617 }
618 
isErrorExpr(const char * output)619 static bool isErrorExpr(const char* output)
620 {
621     return
622 	strncmp(output, "Cannot access memory at", 23) == 0 ||
623 	strncmp(output, "Attempt to dereference a generic pointer", 40) == 0 ||
624 	strncmp(output, "Attempt to take contents of ", 28) == 0 ||
625 	strncmp(output, "Attempt to use a type name as an expression", 43) == 0 ||
626 	strncmp(output, "There is no member or method named", 34) == 0 ||
627 	strncmp(output, "A parse error in expression", 27) == 0 ||
628 	strncmp(output, "No symbol \"", 11) == 0 ||
629 	strncmp(output, "Internal error: ", 16) == 0;
630 }
631 
skipSpace(const char * & p)632 static void skipSpace(const char*& p)
633 {
634     while (isspace(*p))
635 	p++;
636 }
637 
skipDecimal(const char * & p)638 static void skipDecimal(const char*& p)
639 {
640     while (isdigit(*p))
641 	p++;
642 }
643 
644 /**
645  * Returns true if the output is an error message. If wantErrorValue is
646  * true, a new ExprValue object is created and filled with the error message.
647  * If there are warnings, they are skipped and output points past the warnings
648  * on return (even if there \e are errors).
649  */
parseErrorMessage(const char * & output,ExprValue * & variable,bool wantErrorValue)650 static bool parseErrorMessage(const char*& output,
651 			      ExprValue*& variable, bool wantErrorValue)
652 {
653     skipSpace(output);
654 
655     // skip warnings
656     while (strncmp(output, "warning:", 8) == 0)
657     {
658 	const char* end = strchr(output+8, '\n');
659 	if (end == 0)
660 	    output += strlen(output);
661 	else
662 	    output = end+1;
663         skipSpace(output);
664     }
665 
666     if (isErrorExpr(output))
667     {
668 	if (wantErrorValue) {
669 	    // put the error message as value in the variable
670 	    variable = new ExprValue(QString(), VarTree::NKplain);
671 	    const char* endMsg = strchr(output, '\n');
672 	    if (endMsg == 0)
673 		endMsg = output + strlen(output);
674 	    variable->m_value = QString::fromLatin1(output, endMsg-output);
675 	} else {
676 	    variable = 0;
677 	}
678 	return true;
679     }
680     return false;
681 }
682 
683 #if QT_VERSION >= 300
684 union Qt2QChar {
685     short s;
686     struct {
687 	uchar row;
688 	uchar cell;
689     } qch;
690 };
691 #endif
692 
setPrintQStringDataCmd(const char * cmd)693 void GdbDriver::setPrintQStringDataCmd(const char* cmd)
694 {
695     // don't accept the command if it is empty
696     if (cmd == 0 || *cmd == '\0')
697 	return;
698     assert(strlen(cmd) <= MAX_FMTLEN);
699     cmds[DCprintQStringStruct].fmt = cmd;
700 }
701 
parseQCharArray(const char * output,bool wantErrorValue,bool qt3like)702 ExprValue* GdbDriver::parseQCharArray(const char* output, bool wantErrorValue, bool qt3like)
703 {
704     ExprValue* variable = 0;
705 
706     /*
707      * Parse off white space. gdb sometimes prints white space first if the
708      * printed array leaded to an error.
709      */
710     skipSpace(output);
711 
712     // special case: empty string (0 repetitions)
713     if (strncmp(output, "Invalid number 0 of repetitions", 31) == 0)
714     {
715 	variable = new ExprValue(QString(), VarTree::NKplain);
716 	variable->m_value = "\"\"";
717 	return variable;
718     }
719 
720     // check for error conditions
721     if (parseErrorMessage(output, variable, wantErrorValue))
722 	return variable;
723 
724     // parse the array
725 
726     // find '='
727     const char* p = output;
728     p = strchr(p, '=');
729     if (p == 0) {
730 	goto error;
731     }
732     p++;
733     skipSpace(p);
734 
735     if (*p == '{')
736     {
737 	// this is the real data
738 	p++;				/* skip '{' */
739 
740 	// parse the array
741 	QString result;
742 	QString repeatCount;
743 	enum { wasNothing, wasChar, wasRepeat } lastThing = wasNothing;
744 	/*
745 	 * A matrix for separators between the individual "things"
746 	 * that are added to the string. The first index is a bool,
747 	 * the second index is from the enum above.
748 	 */
749 	static const char* separator[2][3] = {
750 	    { "\"", 0,       ", \"" },	/* normal char is added */
751 	    { "'",  "\", '", ", '" }	/* repeated char is added */
752 	};
753 
754 	while (isdigit(*p)) {
755 	    // parse a number
756 	    char* end;
757 	    unsigned short value = (unsigned short) strtoul(p, &end, 0);
758 	    if (end == p)
759 		goto error;		/* huh? no valid digits */
760 	    // skip separator and search for a repeat count
761 	    p = end;
762 	    while (isspace(*p) || *p == ',')
763 		p++;
764 	    bool repeats = strncmp(p, "<repeats ", 9) == 0;
765 	    if (repeats) {
766 		const char* start = p;
767 		p = strchr(p+9, '>');	/* search end and advance */
768 		if (p == 0)
769 		    goto error;
770 		p++;			/* skip '>' */
771 		repeatCount = QString::fromLatin1(start, p-start);
772 		while (isspace(*p) || *p == ',')
773 		    p++;
774 	    }
775 	    // p is now at the next char (or the end)
776 
777 	    // interpret the value as a QChar
778 	    // TODO: make cross-architecture compatible
779 	    QChar ch;
780 	    if (qt3like) {
781 		ch = QChar(value);
782 	    } else {
783 #if QT_VERSION < 300
784 		(unsigned short&)ch = value;
785 #else
786 		Qt2QChar c;
787 		c.s = value;
788 		ch.setRow(c.qch.row);
789 		ch.setCell(c.qch.cell);
790 #endif
791 	    }
792 
793 	    // escape a few frequently used characters
794 	    char escapeCode = '\0';
795 	    switch (ch.toLatin1()) {
796 	    case '\n': escapeCode = 'n'; break;
797 	    case '\r': escapeCode = 'r'; break;
798 	    case '\t': escapeCode = 't'; break;
799 	    case '\b': escapeCode = 'b'; break;
800 	    case '\"': escapeCode = '\"'; break;
801 	    case '\\': escapeCode = '\\'; break;
802 	    case '\0': if (value == 0) { escapeCode = '0'; } break;
803 	    }
804 
805 	    // add separator
806 	    result += separator[repeats][lastThing];
807 	    // add char
808 	    if (escapeCode != '\0') {
809 		result += '\\';
810 		ch = escapeCode;
811 	    }
812 	    result += ch;
813 
814 	    // fixup repeat count and lastThing
815 	    if (repeats) {
816 		result += "' ";
817 		result += repeatCount;
818 		lastThing = wasRepeat;
819 	    } else {
820 		lastThing = wasChar;
821 	    }
822 	}
823 	if (*p != '}')
824 	    goto error;
825 
826 	// closing quote
827 	if (lastThing == wasChar)
828 	    result += "\"";
829 
830 	// assign the value
831 	variable = new ExprValue(QString(), VarTree::NKplain);
832 	variable->m_value = result;
833     }
834     else if (strncmp(p, "true", 4) == 0)
835     {
836 	variable = new ExprValue(QString(), VarTree::NKplain);
837 	variable->m_value = "QString::null";
838     }
839     else if (strncmp(p, "false", 5) == 0)
840     {
841 	variable = new ExprValue(QString(), VarTree::NKplain);
842 	variable->m_value = "(null)";
843     }
844     else
845 	goto error;
846     return variable;
847 
848 error:
849     if (wantErrorValue) {
850 	variable = new ExprValue(QString(), VarTree::NKplain);
851 	variable->m_value = "internal parse error";
852     }
853     return variable;
854 }
855 
parseVar(const char * & s)856 static ExprValue* parseVar(const char*& s)
857 {
858     const char* p = s;
859 
860     skipSpace(p);
861 
862     QString name;
863     VarTree::NameKind kind;
864     /*
865      * Detect anonymouse struct values: The 'name =' part is missing:
866      *    s = { a = 1, { b = 2 }}
867      * Note that this detection works only inside structs when the anonymous
868      * struct is not the first member:
869      *    s = {{ a = 1 }, b = 2}
870      * This is misparsed (by parseNested()) because it is mistakenly
871      * interprets the second opening brace as the first element of an array
872      * of structs.
873      */
874     if (*p == '{')
875     {
876 	name = i18n("<anonymous struct or union>");
877 	kind = VarTree::NKanonymous;
878     }
879     else
880     {
881 	if (!parseName(p, name, kind)) {
882 	    return 0;
883 	}
884 
885 	// go for '='
886 	skipSpace(p);
887 	if (*p != '=') {
888 	    TRACE("parse error: = not found after " + name);
889 	    return 0;
890 	}
891 	// skip the '=' and more whitespace
892 	p++;
893 	skipSpace(p);
894     }
895 
896     ExprValue* variable = new ExprValue(name, kind);
897 
898     if (!parseValue(p, variable)) {
899 	delete variable;
900 	return 0;
901     }
902     s = p;
903     return variable;
904 }
905 
skipNested(const char * & s,char opening,char closing)906 static void skipNested(const char*& s, char opening, char closing)
907 {
908     const char* p = s;
909 
910     // parse a nested type
911     int nest = 1;
912     p++;
913     /*
914      * Search for next matching `closing' char, skipping nested pairs of
915      * `opening' and `closing'.
916      */
917     while (*p && nest > 0) {
918 	if (*p == opening) {
919 	    nest++;
920 	} else if (*p == closing) {
921 	    nest--;
922 	}
923 	p++;
924     }
925     if (nest != 0) {
926 	TRACE(QString().sprintf("parse error: mismatching %c%c at %-20.20s", opening, closing, s));
927     }
928     s = p;
929 }
930 
931 /**
932  * This function skips text that is delimited by nested angle bracktes, '<>'.
933  * A complication arises because the delimited text can contain the names of
934  * operator<<, operator>>, operator<, and operator>, which have to be treated
935  * specially so that they do not count towards the nesting of '<>'.
936  * This function assumes that the delimited text does not contain strings.
937  */
skipNestedAngles(const char * & s)938 static void skipNestedAngles(const char*& s)
939 {
940     const char* p = s;
941 
942     int nest = 1;
943     p++;		// skip the initial '<'
944     while (*p && nest > 0)
945     {
946 	// Below we can check for p-s >= 9 instead of 8 because
947 	// *s is '<' and cannot be part of "operator".
948 	if (*p == '<')
949 	{
950 	    if (p-s >= 9 && strncmp(p-8, "operator", 8) == 0) {
951 		if (p[1] == '<')
952 		    p++;
953 	    } else {
954 		nest++;
955 	    }
956 	}
957 	else if (*p == '>')
958 	{
959 	    if (p-s >= 9 && strncmp(p-8, "operator", 8) == 0) {
960 		if (p[1] == '>')
961 		    p++;
962 	    } else {
963 		nest--;
964 	    }
965 	}
966 	p++;
967     }
968     if (nest != 0) {
969 	TRACE(QString().sprintf("parse error: mismatching <> at %-20.20s", s));
970     }
971     s = p;
972 }
973 
974 /**
975  * Find the end of line that is not inside braces
976  */
findEnd(const char * & s)977 static void findEnd(const char*& s)
978 {
979     const char* p = s;
980     while (*p && *p!='\n') {
981 	while (*p && *p!='\n' && *p!='{')
982 	    p++;
983 	if (*p=='{') {
984 	    p++;
985 	    skipNested(p, '{', '}'); p--;
986 	}
987     }
988     s = p;
989 }
990 
isNumberish(const char ch)991 static bool isNumberish(const char ch)
992 {
993     return (ch>='0' && ch<='9') || ch=='.' || ch=='x';
994 }
995 
skipString(const char * & p)996 void skipString(const char*& p)
997 {
998     // wchar_t strings begin with L
999     if (*p == 'L')
1000 	++p;
1001 
1002 moreStrings:
1003     // opening quote
1004     char quote = *p++;
1005     while (*p != quote) {
1006 	if (*p == '\\') {
1007 	    // skip escaped character
1008 	    // no special treatment for octal values necessary
1009 	    p++;
1010 	}
1011 	// simply return if no more characters
1012 	if (*p == '\0')
1013 	    return;
1014 	p++;
1015     }
1016     // closing quote
1017     p++;
1018     /*
1019      * Strings can consist of several parts, some of which contain repeated
1020      * characters.
1021      */
1022     if (quote == '\'') {
1023 	// look ahaead for <repeats 123 times>
1024 	const char* q = p+1;
1025 	skipSpace(q);
1026 	if (strncmp(q, "<repeats ", 9) == 0) {
1027 	    p = q+9;
1028 	    while (*p != '\0' && *p != '>')
1029 		p++;
1030 	    if (*p != '\0') {
1031 		p++;			/* skip the '>' */
1032 	    }
1033 	}
1034     }
1035     // Is the string continued? If so, there is no L in wchar_t strings
1036     if (*p == ',')
1037     {
1038 	// look ahead for another quote
1039 	const char* q = p+1;
1040 	skipSpace(q);
1041 	if (*q == '"' || *q == '\'') {
1042 	    // yes!
1043 	    p = q;
1044 	    goto moreStrings;
1045 	}
1046 
1047 	// some strings can end in <incomplete sequence ...>
1048 	if (strncmp(q, "<incomplete sequence", 20) == 0)
1049 	{
1050 	    p = q+20;
1051 	    while (*p != '\0' && *p != '>')
1052 		p++;
1053 	    if (*p != '\0') {
1054 		p++;		/* skip the '>' */
1055 	    }
1056 	}
1057     }
1058     /*
1059      * There's a bug in gdb where it prints the beginning of the string
1060      * continuation and the comma-blank in the wrong order if the new string
1061      * begins with an incomplete multi-byte character. For now, let's check
1062      * for this in a very narrow condition, particularly, where the next
1063      * character is given in octal notation. Example:
1064      *     'a' <repeats 20 times>"\240, b"
1065      */
1066     if (*p == '"' && p[1] == '\\' && isdigit(p[2])) {
1067 	int i = 3;
1068 	while (isdigit(p[i]))
1069 	    ++i;
1070 	if (p[i] == ',' && p[i+1] == ' ') {
1071 	    // just treat everything beginning at the dquote as string
1072 	    goto moreStrings;
1073 	}
1074     }
1075     /* very long strings are followed by `...' */
1076     if (*p == '.' && p[1] == '.' && p[2] == '.') {
1077 	p += 3;
1078     }
1079 }
1080 
skipNestedWithString(const char * & s,char opening,char closing)1081 static void skipNestedWithString(const char*& s, char opening, char closing)
1082 {
1083     const char* p = s;
1084 
1085     // parse a nested expression
1086     int nest = 1;
1087     p++;
1088     /*
1089      * Search for next matching `closing' char, skipping nested pairs of
1090      * `opening' and `closing' as well as strings.
1091      */
1092     while (*p && nest > 0) {
1093 	if (*p == opening) {
1094 	    nest++;
1095 	} else if (*p == closing) {
1096 	    nest--;
1097 	} else if (*p == '\'' || *p == '\"') {
1098 	    skipString(p);
1099 	    continue;
1100 	}
1101 	p++;
1102     }
1103     if (nest > 0) {
1104 	TRACE(QString().sprintf("parse error: mismatching %c%c at %-20.20s", opening, closing, s));
1105     }
1106     s = p;
1107 }
1108 
skipName(const char * & p)1109 static void skipName(const char*& p)
1110 {
1111     // allow : (for enumeration values) and $ and . (for _vtbl.)
1112     while (isalnum(*p) || *p == '_' || *p == ':' || *p == '$' || *p == '.')
1113 	p++;
1114 }
1115 
skipFunctionName(const char * & p)1116 static void skipFunctionName(const char*& p)
1117 {
1118     while (*p)
1119     {
1120 	if (*p == '<') {
1121 	    // skip template parameter list
1122 	    skipNestedAngles(p);
1123 	} else if (*p == '(') {
1124 	    // this skips "(anonymous namespace)" as well as the formal
1125 	    // parameter list of the containing function if this is a member
1126 	    // of a nested class
1127 	    skipNestedWithString(p, '(', ')');
1128 	} else if (isalnum(*p) || *p == '_' || *p == ':') {
1129 	    const char* start = p;
1130 	    skipName(p);
1131 	    // check for operator
1132 	    if (p-start >= 8 &&
1133 		strncmp(p-8, "operator", 8) == 0 &&
1134 		// do  not mistake this as the tail of some identifier
1135 		(p-start == 8 || !(isalnum(p[-9]) || p[-9] == '_')))
1136 	    {
1137 		// skip forward until we find the opening parenthesis
1138 		// this catches both operator()(...) as well as
1139 		// type conversion operators, e.g.
1140 		//  operator char const*() const
1141 		//  operator void(*)()
1142 		while (*p && *p != '(')
1143 		    p++;
1144 	    }
1145 	} else if (strncmp(p, " const", 6) == 0 &&
1146 		    // must not mistake "const" as the beginning of
1147 		    // a subequent identifier
1148 		    !isalnum(p[6]) &&  p[6] != '_') {
1149 	    p += 6;
1150 	} else {
1151 	    break;
1152 	}
1153     }
1154 }
1155 
parseName(const char * & s,QString & name,VarTree::NameKind & kind)1156 static bool parseName(const char*& s, QString& name, VarTree::NameKind& kind)
1157 {
1158     kind = VarTree::NKplain;
1159 
1160     const char* p = s;
1161     // examples of names:
1162     //  name
1163     //  <Object>
1164     //  <string<a,b<c>,7> >
1165 
1166     if (*p == '<') {
1167 	skipNestedAngles(p);
1168 	name = QString::fromLatin1(s, p - s);
1169 	kind = VarTree::NKtype;
1170     }
1171     else
1172     {
1173 	// name, which might be "static"; allow dot for "_vtbl."
1174 	skipName(p);
1175 	if (p == s) {
1176 	    TRACE(QString().sprintf("parse error: not a name %-20.20s", s));
1177 	    return false;
1178 	}
1179 	int len = p - s;
1180 	if (len == 6 && strncmp(s, "static", 6) == 0) {
1181 	    kind = VarTree::NKstatic;
1182 
1183 	    // its a static variable, name comes now
1184 	    skipSpace(p);
1185 	    s = p;
1186 	    skipName(p);
1187 	    if (p == s) {
1188 		TRACE(QString().sprintf("parse error: not a name after static %-20.20s", s));
1189 		return false;
1190 	    }
1191 	    len = p - s;
1192 	}
1193 	name = QString::fromLatin1(s, len);
1194     }
1195     // return the new position
1196     s = p;
1197     return true;
1198 }
1199 
parseValue(const char * & s,ExprValue * variable)1200 static bool parseValue(const char*& s, ExprValue* variable)
1201 {
1202     variable->m_value = "";
1203 
1204 repeat:
1205     if (*s == '{') {
1206 	// Sometimes we find the following output:
1207 	//  {<text variable, no debug info>} 0x40012000 <access>
1208 	//  {<data variable, no debug info>}
1209 	//  {<variable (not text or data), no debug info>}
1210 	if (strncmp(s, "{<text variable, ", 17) == 0 ||
1211 	    strncmp(s, "{<data variable, ", 17) == 0 ||
1212 	    strncmp(s, "{<variable (not text or data), ", 31) == 0)
1213 	{
1214 	    const char* start = s;
1215 	    skipNested(s, '{', '}');
1216 	    variable->m_value = QString::fromLatin1(start, s-start);
1217 	    variable->m_value += ' ';	// add only a single space
1218 	    skipSpace(s);
1219 	    goto repeat;
1220 	}
1221 	else
1222 	{
1223 	    s++;
1224 	    if (!parseNested(s, variable)) {
1225 		return false;
1226 	    }
1227 	    // must be the closing brace
1228 	    if (*s != '}') {
1229 		TRACE("parse error: missing } of " +  variable->m_name);
1230 		return false;
1231 	    }
1232 	    s++;
1233 	    // final white space
1234 	    skipSpace(s);
1235 	}
1236     }
1237     // Sometimes we find a warning; it ends at the next LF
1238     else if (strncmp(s, "warning: ", 9) == 0) {
1239 	const char* end = strchr(s, '\n');
1240 	s = end ? end : s+strlen(s);
1241 	// skip space at start of next line
1242 	skipSpace(s);
1243 	goto repeat;
1244     } else {
1245 	// examples of leaf values (cannot be the empty string):
1246 	//  123
1247 	//  -123
1248 	//  23.575e+37
1249 	//  0x32a45
1250 	//  @0x012ab4
1251 	//  (DwContentType&) @0x8123456: {...}
1252 	//  0x32a45 "text"
1253 	//  10 '\n'
1254 	//  <optimized out>
1255 	//  0x823abc <Array<int> virtual table>
1256 	//  0x40240f <globarstr> "test"
1257 	//  (void (*)()) 0x8048480 <f(E *, char)>
1258 	//  (E *) 0xbffff450
1259 	//  red
1260 	//  &parseP (HTMLClueV *, char *)
1261 	//  &virtual table offset 0, this adjustment 140737488346016
1262 	//  &virtual Dl::operator char const*() const
1263 	//  Variable "x" is not available.
1264 	//  The value of variable 'x' is distributed...
1265 	//  -nan(0xfffff081defa0)
1266 	//  @0x100400f08: <error reading variable>
1267 	//  (void (Templated<double>::*)(Templated<double> * const)) 0x400d74 <MostDerived::PrintV()>, this adjustment -16
1268 
1269 	const char*p = s;
1270 
1271 	// check for type
1272 	QString type;
1273 	if (*p == '(') {
1274 	    skipNested(p, '(', ')');
1275 
1276 	    skipSpace(p);
1277 	    variable->m_value = QString::fromLatin1(s, p - s);
1278 	}
1279 
1280 	bool reference = false;
1281 	if (*p == '@') {
1282 	    // skip reference marker
1283 	    p++;
1284 	    reference = true;
1285 	}
1286 	const char* start = p;
1287 	if (*p == '-')
1288 	    p++;
1289 
1290 	// some values consist of more than one token
1291 	bool checkMultiPart = false;
1292 
1293 	if (p[0] == '0' && p[1] == 'x') {
1294 	    // parse hex number
1295 	    p += 2;
1296 	    while (isxdigit(*p))
1297 		p++;
1298 
1299 	    /*
1300 	     * Assume this is a pointer, but only if it's not a reference, since
1301 	     * references can't be expanded.
1302 	     */
1303 	    if (!reference) {
1304 		variable->m_varKind = VarTree::VKpointer;
1305 	    } else {
1306 		/*
1307 		 * References are followed by a colon, in which case we'll
1308 		 * find the value following the reference address.
1309 		 */
1310 		if (*p == ':') {
1311 		    p++;
1312 		} else {
1313 		    // Paranoia. (Can this happen, i.e. reference not followed by ':'?)
1314 		    reference = false;
1315 		}
1316 	    }
1317 	    checkMultiPart = true;
1318 	} else if (isdigit(*p)) {
1319 	    // parse decimal number, possibly a float
1320 	    skipDecimal(p);
1321 	    if (*p == '.') {		/* TODO: obey i18n? */
1322 		// In long arrays an integer may be followed by '...'.
1323 		// We test for this situation and don't gobble the '...'.
1324 		if (p[1] != '.' || p[0] != '.') {
1325 		    // fractional part
1326 		    p++;
1327 		    skipDecimal(p);
1328 		}
1329 	    }
1330 	    if (*p == 'e' || *p == 'E') {
1331 		p++;
1332 		// exponent
1333 		if (*p == '-' || *p == '+')
1334 		    p++;
1335 		skipDecimal(p);
1336 	    }
1337 
1338 	    // for char variables there is the char, eg. 10 '\n'
1339 	    checkMultiPart = true;
1340 	} else if (*p == '<') {
1341 	    // e.g. <optimized out>
1342 	    skipNestedAngles(p);
1343 	} else if (*p == '"' || *p == '\'') {
1344 	    // character may have multipart: '\000' <repeats 11 times>
1345 	    checkMultiPart = *p == '\'';
1346 	    // found a string
1347 	    skipString(p);
1348 	} else if (*p == 'L' && (p[1] == '"' || p[1] == '\'')) {
1349 	    // ditto for wchar_t strings
1350 	    checkMultiPart = p[1] == '\'';
1351 	    skipString(p);
1352 	} else if (*p == '&') {
1353 	    p++;
1354 	    if (strncmp(p, "virtual ", 8) == 0) {
1355 		p += 8;
1356 		if (strncmp(p, "table offset ", 13) == 0) {
1357 		    p += 13;
1358 		    skipDecimal(p);
1359 		    checkMultiPart = true;
1360 		} else {
1361 		    skipFunctionName(p);
1362 		}
1363 	    } else {
1364 		// function pointer
1365 		skipName(p);
1366 		skipSpace(p);
1367 		if (*p == '(') {
1368 		    skipNested(p, '(', ')');
1369 		}
1370 	    }
1371 	} else if (strncmp(p, "Variable \"", 10) == 0) {
1372 	    // Variable "x" is not available.
1373 	    p += 10;		// skip to "
1374 	    skipName(p);
1375 	    if (strncmp(p, "\" is not available.", 19) == 0) {
1376 		p += 19;
1377 	    }
1378 	} else if (strncmp(p, "The value of variable '", 23) == 0) {
1379 	    p += 23;
1380 	    skipName(p);
1381 	    const char* e = strchr(p, '.');
1382 	    if (e == 0) {
1383 		p += strlen(p);
1384 	    } else {
1385 		p = e+1;
1386 	    }
1387 	} else {
1388 	moreEnum:
1389 	    // must be an enumeration value
1390 	    skipName(p);
1391 	    // nan (floating point Not a Number) is followed by a number in ()
1392 	    // enum values can look like A::(anonymous namespace)::blue
1393 	    if (*p == '(') {
1394 		bool isAnonNS = strncmp(p+1, "anonymous namespace)", 20) == 0;
1395 		skipNested(p, '(', ')');
1396 		if (isAnonNS)
1397 		    goto moreEnum;
1398 	    }
1399 	}
1400 	variable->m_value += QString::fromLatin1(start, p - start);
1401 
1402 	// remove line breaks from the value; this is ok since
1403 	// string values never contain a literal line break
1404 	variable->m_value.replace('\n', ' ');
1405 
1406 	while (checkMultiPart) {
1407 	    // white space
1408 	    skipSpace(p);
1409 	    // may be followed by a string or <...>
1410 	    // if this was a pointer with a string,
1411 	    // reset that pointer flag since we have now a value
1412 	    start = p;
1413 	    checkMultiPart = false;
1414 
1415 	    if (*p == '"' || *p == '\'') {
1416 		skipString(p);
1417 		variable->m_varKind = VarTree::VKsimple;
1418 	    } else if (*p == 'L' && (p[1] == '"' || p[1] == '\'')) {
1419 		skipString(p);	// wchar_t string
1420 		variable->m_varKind = VarTree::VKsimple;
1421 	    } else if (*p == '<') {
1422 		// if this value is part of an array, it might be followed
1423 		// by <repeats 15 times>, which we don't skip here
1424 		if (strncmp(p, "<repeats ", 9) == 0)
1425 		    ;
1426 		// sometimes, a reference is followed by an error message:
1427 		//  @0x100400f08: <error reading variable>
1428 		// in this case, we do not skip the text here, but leave it
1429 		// for the subsequent parsing pass induced by the reference
1430 		else if (reference && strncmp(p, "<error reading", 14) == 0)
1431 		    ;
1432 		else {
1433 		    skipNestedAngles(p);
1434 		    checkMultiPart = true;
1435 		}
1436 	    } else if (strncmp(p, ", this adjustment ", 18) == 0) {
1437 		// pointers-to-member are sometimes followed by
1438 		// a "this adjustment" hint
1439 		p += 18;
1440 		if (*p == '-')
1441 		    p++;
1442 		skipDecimal(p);
1443 		// we know that this is not a dereferencable pointer
1444 		variable->m_varKind = VarTree::VKsimple;
1445 		++start;	// skip ',', will be picked up below
1446 	    }
1447 	    if (p != start) {
1448 		// there is always a blank before the string,
1449 		// which we will include in the final string value
1450 		variable->m_value += QString::fromLatin1(start-1, (p - start)+1);
1451 	    }
1452 	}
1453 
1454 	if (variable->m_value.length() == 0) {
1455 	    TRACE("parse error: no value for " + variable->m_name);
1456 	    return false;
1457 	}
1458 
1459 	// final white space
1460 	skipSpace(p);
1461 	s = p;
1462 
1463 	/*
1464 	 * If this was a reference, the value follows. It might even be a
1465 	 * composite variable!
1466 	 */
1467 	if (reference) {
1468 	    goto repeat;
1469 	}
1470     }
1471 
1472     return true;
1473 }
1474 
parseNested(const char * & s,ExprValue * variable)1475 static bool parseNested(const char*& s, ExprValue* variable)
1476 {
1477     // could be a structure or an array
1478     skipSpace(s);
1479 
1480     const char* p = s;
1481     bool isStruct = false;
1482     /*
1483      * If there is a name followed by an = or an < -- which starts a type
1484      * name -- or "static", it is a structure
1485      */
1486     if (*p == '<' || *p == '}') {
1487 	isStruct = true;
1488     } else if (strncmp(p, "static ", 7) == 0) {
1489 	isStruct = true;
1490     } else if (isalpha(*p) || *p == '_' || *p == '$') {
1491 	// look ahead for a comma after the name
1492 	skipName(p);
1493 	skipSpace(p);
1494 	if (*p == '=') {
1495 	    isStruct = true;
1496 	}
1497 	p = s;				/* rescan the name */
1498     }
1499     if (isStruct) {
1500 	if (!parseVarSeq(p, variable)) {
1501 	    return false;
1502 	}
1503 	variable->m_varKind = VarTree::VKstruct;
1504     } else {
1505 	if (!parseValueSeq(p, variable)) {
1506 	    return false;
1507 	}
1508 	variable->m_varKind = VarTree::VKarray;
1509     }
1510     s = p;
1511     return true;
1512 }
1513 
parseVarSeq(const char * & s,ExprValue * variable)1514 static bool parseVarSeq(const char*& s, ExprValue* variable)
1515 {
1516     // parse a comma-separated sequence of variables
1517     ExprValue* var = variable;		/* var != 0 to indicate success if empty seq */
1518     for (;;) {
1519 	if (*s == '}')
1520 	    break;
1521 	if (strncmp(s, "<No data fields>}", 17) == 0)
1522 	{
1523 	    // no member variables, so break out immediately
1524 	    s += 16;			/* go to the closing brace */
1525 	    break;
1526 	}
1527 	var = parseVar(s);
1528 	if (var == 0)
1529 	    break;			/* syntax error */
1530 	variable->appendChild(var);
1531 	if (*s != ',')
1532 	    break;
1533 	// skip the comma and whitespace
1534 	s++;
1535 	skipSpace(s);
1536     }
1537     return var != 0;
1538 }
1539 
parseValueSeq(const char * & s,ExprValue * variable)1540 static bool parseValueSeq(const char*& s, ExprValue* variable)
1541 {
1542     // parse a comma-separated sequence of variables
1543     int index = 0;
1544     bool good;
1545     for (;;) {
1546 	QString name;
1547 	name.sprintf("[%d]", index);
1548 	ExprValue* var = new ExprValue(name, VarTree::NKplain);
1549 	good = parseValue(s, var);
1550 	if (!good) {
1551 	    delete var;
1552 	    return false;
1553 	}
1554 	// a value may be followed by "<repeats 45 times>"
1555 	if (strncmp(s, "<repeats ", 9) == 0) {
1556 	    s += 9;
1557 	    char* end;
1558 	    int l = strtol(s, &end, 10);
1559 	    if (end == s || strncmp(end, " times>", 7) != 0) {
1560 		// should not happen
1561 		delete var;
1562 		return false;
1563 	    }
1564 	    TRACE(QString().sprintf("found <repeats %d times> in array", l));
1565 	    // replace name and advance index
1566 	    name.sprintf("[%d .. %d]", index, index+l-1);
1567 	    var->m_name = name;
1568 	    index += l;
1569 	    // skip " times>" and space
1570 	    s = end+7;
1571 	    // possible final space
1572 	    skipSpace(s);
1573 	} else {
1574 	    index++;
1575 	}
1576 	variable->appendChild(var);
1577 	// long arrays may be terminated by '...'
1578 	if (strncmp(s, "...", 3) == 0) {
1579 	    s += 3;
1580 	    ExprValue* var = new ExprValue("...", VarTree::NKplain);
1581 	    var->m_value = i18n("<additional entries of the array suppressed>");
1582 	    variable->appendChild(var);
1583 	    break;
1584 	}
1585 	if (*s != ',') {
1586 	    break;
1587 	}
1588 	// skip the comma and whitespace
1589 	s++;
1590 	skipSpace(s);
1591 	// sometimes there is a closing brace after a comma
1592 //	if (*s == '}')
1593 //	    break;
1594     }
1595     return true;
1596 }
1597 
1598 /**
1599  * Parses a stack frame.
1600  */
parseFrameInfo(const char * & s,QString & func,QString & file,int & lineNo,DbgAddr & address)1601 static void parseFrameInfo(const char*& s, QString& func,
1602 			   QString& file, int& lineNo, DbgAddr& address)
1603 {
1604     const char* p = s;
1605 
1606     // next may be a hexadecimal address
1607     if (*p == '0') {
1608 	const char* start = p;
1609 	p++;
1610 	if (*p == 'x')
1611 	    p++;
1612 	while (isxdigit(*p))
1613 	    p++;
1614 	address = QString::fromLatin1(start, p-start);
1615 	if (strncmp(p, " in ", 4) == 0)
1616 	    p += 4;
1617     } else {
1618 	address = DbgAddr();
1619     }
1620     const char* start = p;
1621     // check for special signal handler frame
1622     if (strncmp(p, "<signal handler called>", 23) == 0) {
1623 	func = QString::fromLatin1(start, 23);
1624 	file = QString();
1625 	lineNo = -1;
1626 	s = p+23;
1627 	if (*s == '\n')
1628 	    s++;
1629 	return;
1630     }
1631 
1632     /*
1633      * Skip the function name. It is terminated by a left parenthesis
1634      * which does not delimit "(anonymous namespace)" and which is
1635      * outside the angle brackets <> of template parameter lists
1636      * and is preceded by a space.
1637      */
1638     while (*p != '\0')
1639     {
1640 	if (*p == '<') {
1641 	    // check for operator<< and operator<
1642 	    if (p-start >= 8 && strncmp(p-8, "operator", 8) == 0)
1643 	    {
1644 		p++;
1645 		if (*p == '<')
1646 		    p++;
1647 	    }
1648 	    else
1649 	    {
1650 		// skip template parameter list
1651 		skipNestedAngles(p);
1652 	    }
1653 	} else if (*p == '(') {
1654 	    // this skips "(anonymous namespace)" as well as the formal
1655 	    // parameter list of the containing function if this is a member
1656 	    // of a nested class
1657 	    skipNestedWithString(p, '(', ')');
1658 	} else if (*p == ' ') {
1659 	    ++p;
1660 	    if (*p == '(')
1661 		break; // parameter list found
1662 	} else {
1663 	    p++;
1664 	}
1665     }
1666 
1667     if (*p == '\0') {
1668 	func = start;
1669 	file = QString();
1670 	lineNo = -1;
1671 	s = p;
1672 	return;
1673     }
1674     /*
1675      * Skip parameters. But notice that for complicated conversion
1676      * functions (eg. "operator int(**)()()", ie. convert to pointer to
1677      * pointer to function) as well as operator()(...) we have to skip
1678      * additional pairs of parentheses. Furthermore, recent gdbs write the
1679      * demangled name followed by the arguments in a pair of parentheses,
1680      * where the demangled name can end in "const".
1681      */
1682     do {
1683 	skipNestedWithString(p, '(', ')');
1684 	skipSpace(p);
1685 	// skip "const"
1686 	if (strncmp(p, "const", 5) == 0) {
1687 	    p += 5;
1688 	    skipSpace(p);
1689 	}
1690     } while (*p == '(');
1691 
1692     // check for file position
1693     if (strncmp(p, "at ", 3) == 0) {
1694 	p += 3;
1695 	const char* fileStart = p;
1696 	// go for the end of the line
1697 	while (*p != '\0' && *p != '\n')
1698 	    p++;
1699 	// search back for colon
1700 	const char* colon = p;
1701 	do {
1702 	    --colon;
1703 	} while (*colon != ':');
1704 	file = QString::fromLatin1(fileStart, colon-fileStart);
1705 	lineNo = atoi(colon+1)-1;
1706 	// skip new-line
1707 	if (*p != '\0')
1708 	    p++;
1709     } else {
1710 	// check for "from shared lib"
1711 	if (strncmp(p, "from ", 5) == 0) {
1712 	    p += 5;
1713 	    // go for the end of the line
1714 	    while (*p != '\0' && *p != '\n')
1715 		p++;
1716 	    // skip new-line
1717 	    if (*p != '\0')
1718 		p++;
1719 	}
1720 	file = "";
1721 	lineNo = -1;
1722     }
1723     // construct the function name (including file info)
1724     if (*p == '\0') {
1725 	func = start;
1726     } else {
1727 	func = QString::fromLatin1(start, p-start-1);	/* don't include \n */
1728     }
1729     s = p;
1730 
1731     /*
1732      * Replace \n (and whitespace around it) in func by a blank. We cannot
1733      * use QString::simplified() for this because this would also
1734      * simplify space that belongs to a string arguments that gdb sometimes
1735      * prints in the argument lists of the function.
1736      */
1737     ASSERT(!isspace(func[0].toLatin1()));	// there must be non-white before first \n
1738     int nl = 0;
1739     while ((nl = func.indexOf('\n', nl)) >= 0) {
1740 	// search back to the beginning of the whitespace
1741 	int startWhite = nl;
1742 	do {
1743 	    --startWhite;
1744 	} while (isspace(func[startWhite].toLatin1()));
1745 	startWhite++;
1746 	// search forward to the end of the whitespace
1747 	do {
1748 	    nl++;
1749 	} while (isspace(func[nl].toLatin1()));
1750 	// replace
1751 	func.replace(startWhite, nl-startWhite, " ");
1752 	/* continue searching for more \n's at this place: */
1753 	nl = startWhite+1;
1754     }
1755 }
1756 
1757 
1758 /**
1759  * Parses a stack frame including its frame number
1760  */
parseFrame(const char * & s,int & frameNo,QString & func,QString & file,int & lineNo,DbgAddr & address)1761 static bool parseFrame(const char*& s, int& frameNo, QString& func,
1762 		       QString& file, int& lineNo, DbgAddr& address)
1763 {
1764     // Example:
1765     //  #1  0x8048881 in Dl::Dl (this=0xbffff418, r=3214) at testfile.cpp:72
1766     //  Breakpoint 3, Cl::f(int) const (this=0xbffff3c0, x=17) at testfile.cpp:155
1767 
1768     // must start with a hash mark followed by number
1769     // or with "Breakpoint " followed by number and comma
1770     if (s[0] == '#') {
1771 	if (!isdigit(s[1]))
1772 	    return false;
1773 	s++;				/* skip the hash mark */
1774     } else if (strncmp(s, "Breakpoint ", 11) == 0) {
1775 	if (!isdigit(s[11]))
1776 	    return false;
1777 	s += 11;			/* skip "Breakpoint" */
1778     } else
1779 	return false;
1780 
1781     // frame number
1782     frameNo = atoi(s);
1783     skipDecimal(s);
1784     // space and comma
1785     while (isspace(*s) || *s == ',')
1786 	s++;
1787     parseFrameInfo(s, func, file, lineNo, address);
1788     return true;
1789 }
1790 
parseBackTrace(const char * output,std::list<StackFrame> & stack)1791 void GdbDriver::parseBackTrace(const char* output, std::list<StackFrame>& stack)
1792 {
1793     QString func, file;
1794     int lineNo, frameNo;
1795     DbgAddr address;
1796 
1797     while (::parseFrame(output, frameNo, func, file, lineNo, address)) {
1798 	stack.push_back(StackFrame());
1799 	StackFrame* frm = &stack.back();
1800 	frm->frameNo = frameNo;
1801 	frm->fileName = file;
1802 	frm->lineNo = lineNo;
1803 	frm->address = address;
1804 	frm->var = new ExprValue(func, VarTree::NKplain);
1805     }
1806 }
1807 
parseFrameChange(const char * output,int & frameNo,QString & file,int & lineNo,DbgAddr & address)1808 bool GdbDriver::parseFrameChange(const char* output, int& frameNo,
1809 				 QString& file, int& lineNo, DbgAddr& address)
1810 {
1811     QString func;
1812     return ::parseFrame(output, frameNo, func, file, lineNo, address);
1813 }
1814 
1815 
parseBreakList(const char * output,std::list<Breakpoint> & brks)1816 bool GdbDriver::parseBreakList(const char* output, std::list<Breakpoint>& brks)
1817 {
1818     // skip first line, which is the headline
1819     const char* p = strchr(output, '\n');
1820     if (p == 0)
1821 	return false;
1822     p++;
1823     if (*p == '\0')
1824 	return false;
1825 
1826     // split up a line
1827     const char* end;
1828     char* dummy;
1829     while (*p != '\0') {
1830 	Breakpoint bp;
1831 	// get Num
1832 	bp.id = strtol(p, &dummy, 10);	/* don't care about overflows */
1833 	p = dummy;
1834 	// check for continued <MULTIPLE> breakpoint
1835 	if (*p == '.' && isdigit(p[1]))
1836 	{
1837 	    // continuation: skip type and disposition
1838 	}
1839 	else
1840 	{
1841 	    // get Type
1842 	    skipSpace(p);
1843 	    if (strncmp(p, "breakpoint", 10) == 0) {
1844 		p += 10;
1845 	    } else if (strncmp(p, "hw watchpoint", 13) == 0) {
1846 		bp.type = Breakpoint::watchpoint;
1847 		p += 13;
1848 	    } else if (strncmp(p, "watchpoint", 10) == 0) {
1849 		bp.type = Breakpoint::watchpoint;
1850 		p += 10;
1851 	    }
1852 	    skipSpace(p);
1853 	    if (*p == '\0')
1854 		break;
1855 	    // get Disp
1856 	    bp.temporary = *p++ == 'd';
1857 	}
1858 	while (*p != '\0' && !isspace(*p))	/* "keep" or "del" */
1859 	    p++;
1860 	skipSpace(p);
1861 	if (*p == '\0')
1862 	    break;
1863 	// get Enb
1864 	bp.enabled = *p++ == 'y';
1865 	while (*p != '\0' && !isspace(*p))	/* "y" or "n" */
1866 	    p++;
1867 	skipSpace(p);
1868 	if (*p == '\0')
1869 	    break;
1870 	// the address, if present
1871 	if (bp.type == Breakpoint::breakpoint &&
1872 	    strncmp(p, "0x", 2) == 0)
1873 	{
1874 	    const char* start = p;
1875 	    while (*p != '\0' && !isspace(*p))
1876 		p++;
1877 	    bp.address = QString::fromLatin1(start, p-start);
1878 	    while (isspace(*p) && *p != '\n')
1879 		p++;
1880 	    if (*p == '\0')
1881 		break;
1882 	}
1883 	// remainder is location, hit and ignore count, condition
1884 	end = strchr(p, '\n');
1885 	if (end == 0) {
1886 	    bp.location = p;
1887 	    p += bp.location.length();
1888 	} else {
1889 	    // location of a <MULTIPLE> filled in from subsequent breakpoints
1890 	    if (strncmp(p, "<MULTIPLE>", 10) != 0)
1891 		bp.location = QString::fromLatin1(p, end-p).trimmed();
1892 	    p = end+1;			/* skip over \n */
1893 	}
1894 
1895 	// may be continued in next line
1896 	while (isspace(*p)) {	/* p points to beginning of line */
1897 	    // skip white space at beginning of line
1898 	    skipSpace(p);
1899 
1900 	    // seek end of line
1901 	    end = strchr(p, '\n');
1902 	    if (end == 0)
1903 		end = p+strlen(p);
1904 
1905 	    if (strncmp(p, "breakpoint already hit", 22) == 0) {
1906 		// extract the hit count
1907 		p += 22;
1908 		bp.hitCount = strtol(p, &dummy, 10);
1909 		TRACE(QString("hit count %1").arg(bp.hitCount));
1910 	    } else if (strncmp(p, "stop only if ", 13) == 0) {
1911 		// extract condition
1912 		p += 13;
1913 		bp.condition = QString::fromLatin1(p, end-p).trimmed();
1914 		TRACE("condition: "+bp.condition);
1915 	    } else if (strncmp(p, "ignore next ", 12) == 0) {
1916 		// extract ignore count
1917 		p += 12;
1918 		bp.ignoreCount = strtol(p, &dummy, 10);
1919 		TRACE(QString("ignore count %1").arg(bp.ignoreCount));
1920 	    } else {
1921 		// indeed a continuation
1922 		bp.location += " " + QString::fromLatin1(p, end-p).trimmed();
1923 	    }
1924 	    p = end;
1925 	    if (*p != '\0')
1926 		p++;			/* skip '\n' */
1927 	}
1928 
1929 	if (brks.empty() || brks.back().id != bp.id) {
1930 	    brks.push_back(bp);
1931 	} else {
1932 	    // this is a continuation; fill in location if not yet set
1933 	    // otherwise, drop this breakpoint
1934 	    Breakpoint& mbp = brks.back();
1935 	    if (mbp.location.isEmpty() && !bp.location.isEmpty()) {
1936 		mbp.location = bp.location;
1937 		mbp.address = bp.address;
1938 	    } else if (mbp.address.isEmpty() && !bp.address.isEmpty()) {
1939 		mbp.address = bp.address;
1940 	    }
1941 	}
1942     }
1943     return true;
1944 }
1945 
parseThreadList(const char * output)1946 std::list<ThreadInfo> GdbDriver::parseThreadList(const char* output)
1947 {
1948     std::list<ThreadInfo> threads;
1949     if (strcmp(output, "\n") == 0 ||
1950 	strncmp(output, "No stack.", 9) == 0 ||
1951 	strncmp(output, "No threads.", 11) == 0) {
1952 	// no threads
1953 	return threads;
1954     }
1955 
1956     bool newFormat = false;
1957     const char* p = output;
1958     while (*p != '\0') {
1959 	ThreadInfo thr;
1960 	// seach look for thread id, watching out for  the focus indicator
1961 	thr.hasFocus = false;
1962 	skipSpace(p);			/* may be \n from prev line: see "No stack" below */
1963 
1964 	// recent GDBs write a header line; skip it
1965 	if (threads.empty() && strncmp(p, "Id   Target", 11) == 0) {
1966 	    p = strchr(p, '\n');
1967 	    if (p == NULL)
1968 		break;
1969 	    newFormat = true;
1970 	    continue;	// next line please, '\n' is skipped above
1971 	}
1972 
1973 	if (*p == '*') {
1974 	    thr.hasFocus = true;
1975 	    p++;
1976 	    // there follows only whitespace
1977 	}
1978 	const char* end;
1979 	char *temp_end = NULL; /* we need a non-const 'end' for strtol to use...*/
1980 	thr.id = strtol(p, &temp_end, 10);
1981 	end = temp_end;
1982 	if (p == end) {
1983 	    // syntax error: no number found; bail out
1984 	    return threads;
1985 	}
1986 	p = end;
1987 
1988 	skipSpace(p);
1989 
1990 	/*
1991 	 * Now follows the thread's SYSTAG.
1992 	 */
1993 	if (!newFormat) {
1994 	    // In the old format, it is terminated by two blanks.
1995 	    end = strstr(p, "  ");
1996 	    if (end == 0) {
1997 		// syntax error; bail out
1998 		return threads;
1999 	    }
2000 	    end += 2;
2001 	} else {
2002 	    // In the new format lies crazyness: there is no definitive
2003 	    // end marker. At best we can guess when the SYSTAG ends.
2004 	    // A typical thread list on Linux looks like this:
2005 	    //
2006 	    //   Id   Target Id         Frame
2007 	    //   2    Thread 0x7ffff7854700 (LWP 10827) "thrserver" 0x00007ffff7928631 in clone () from /lib64/libc.so.6
2008 	    // * 1    Thread 0x7ffff7fcc700 (LWP 10808) "thrserver" main () at thrserver.c:84
2009 	    //
2010 	    // Looking at GDB's code, the Target Id ends in tokens that
2011 	    // are bracketed by parentheses or quotes. Therefore,
2012 	    // we skip (at most) two tokens ('Thread' and the address),
2013 	    // and then all parts that are in parentheses or quotes.
2014 	    int n = 0;
2015 	    end = p;
2016 	    while (*end) {
2017 		if (*end == '"') {
2018 		    skipString(end);
2019 		    n = 2;
2020 		} else if (*end == '(') {
2021 		    skipNested(end, '(', ')');
2022 		    n = 2;
2023 		} else if (n < 2) {
2024 		    while (*end && !isspace(*end))
2025 			++end;
2026 		    ++n;
2027 		} else {
2028 		    break;
2029 		}
2030 		skipSpace(end);
2031 	    }
2032 	}
2033 	thr.threadName = QString::fromLatin1(p, end-p).trimmed();
2034 	p = end;
2035 
2036 	/*
2037 	 * Now follows a standard stack frame. Sometimes, however, gdb
2038 	 * catches a thread at an instant where it doesn't have a stack.
2039 	 */
2040 	if (strncmp(p, "[No stack.]", 11) != 0) {
2041 	    ::parseFrameInfo(p, thr.function, thr.fileName, thr.lineNo, thr.address);
2042 	} else {
2043 	    thr.function = "[No stack]";
2044 	    thr.lineNo = -1;
2045 	    p += 11;			/* \n is skipped above */
2046 	}
2047 
2048 	threads.push_back(thr);
2049     }
2050     return threads;
2051 }
2052 
2053 static bool parseNewBreakpoint(const char* o, int& id,
2054 			       QString& file, int& lineNo, QString& address);
2055 static bool parseNewWatchpoint(const char* o, int& id,
2056 			       QString& expr);
2057 
parseBreakpoint(const char * output,int & id,QString & file,int & lineNo,QString & address)2058 bool GdbDriver::parseBreakpoint(const char* output, int& id,
2059 				QString& file, int& lineNo, QString& address)
2060 {
2061     // skip lines of that begin with "(Cannot find"
2062     while (strncmp(output, "(Cannot find", 12) == 0 ||
2063 	   strncmp(output, "Note: breakpoint", 16) == 0)
2064     {
2065 	output = strchr(output, '\n');
2066 	if (output == 0)
2067 	    return false;
2068 	output++;			/* skip newline */
2069     }
2070 
2071     if (strncmp(output, "Breakpoint ", 11) == 0) {
2072 	output += 11;			/* skip "Breakpoint " */
2073 	return ::parseNewBreakpoint(output, id, file, lineNo, address);
2074     } else if (strncmp(output, "Temporary breakpoint ", 21) == 0) {
2075 	output += 21;
2076 	return ::parseNewBreakpoint(output, id, file, lineNo, address);
2077     } else if (strncmp(output, "Hardware watchpoint ", 20) == 0) {
2078 	output += 20;
2079 	return ::parseNewWatchpoint(output, id, address);
2080     } else if (strncmp(output, "Watchpoint ", 11) == 0) {
2081 	output += 11;
2082 	return ::parseNewWatchpoint(output, id, address);
2083     }
2084     return false;
2085 }
2086 
parseNewBreakpoint(const char * o,int & id,QString & file,int & lineNo,QString & address)2087 static bool parseNewBreakpoint(const char* o, int& id,
2088 			       QString& file, int& lineNo, QString& address)
2089 {
2090     // breakpoint id
2091     char* p;
2092     id = strtoul(o, &p, 10);
2093     if (p == o)
2094 	return false;
2095 
2096     // check for the address
2097     if (strncmp(p, " at 0x", 6) == 0) {
2098 	char* start = p+4;	       /* skip " at ", but not 0x */
2099 	p += 6;
2100 	while (isxdigit(*p))
2101 	    ++p;
2102 	address = QString::fromLatin1(start, p-start);
2103     }
2104 
2105     /*
2106      * Mostly, GDB responds with this syntax:
2107      *
2108      * Breakpoint 1 at 0x400b94: file multibrkpt.cpp, line 9. (2 locations)
2109      *
2110      * but sometimes it uses this syntax:
2111      *
2112      * Breakpoint 4 at 0x804f158: lotto739.cpp:95. (3 locations)
2113      */
2114     const char* fileEnd, *numStart = 0;
2115     const char* fileStart = strstr(p, "file ");
2116     if (fileStart != 0)
2117     {
2118 	fileStart += 5;
2119 	fileEnd = strstr(fileStart, ", line ");
2120 	if (fileEnd != 0)
2121 	    numStart = fileEnd + 7;
2122     }
2123     if (numStart == 0 && p[0] == ':' && p[1] == ' ')
2124     {
2125 	fileStart = p+2;
2126 	skipSpace(fileStart);
2127 	fileEnd = strchr(fileStart, ':');
2128 	if (fileEnd != 0)
2129 	    numStart = fileEnd + 1;
2130     }
2131     if (numStart == 0)
2132 	return !address.isEmpty();	/* parse error only if there's no address */
2133 
2134     QString fileName = QString::fromLatin1(fileStart, fileEnd-fileStart);
2135     int line = strtoul(numStart, &p, 10);
2136     if (numStart == p)
2137 	return false;
2138 
2139     file = fileName;
2140     lineNo = line-1;			/* zero-based! */
2141     return true;
2142 }
2143 
parseNewWatchpoint(const char * o,int & id,QString & expr)2144 static bool parseNewWatchpoint(const char* o, int& id,
2145 			       QString& expr)
2146 {
2147     // watchpoint id
2148     char* p;
2149     id = strtoul(o, &p, 10);
2150     if (p == o)
2151 	return false;
2152 
2153     if (strncmp(p, ": ", 2) != 0)
2154 	return false;
2155     p += 2;
2156 
2157     // all the rest on the line is the expression
2158     expr = QString::fromLatin1(p, strlen(p)).trimmed();
2159     return true;
2160 }
2161 
parseLocals(const char * output,std::list<ExprValue * > & newVars)2162 void GdbDriver::parseLocals(const char* output, std::list<ExprValue*>& newVars)
2163 {
2164     // check for possible error conditions
2165     if (strncmp(output, "No symbol table", 15) == 0)
2166     {
2167 	return;
2168     }
2169 
2170     while (*output != '\0') {
2171 	skipSpace(output);
2172 	if (*output == '\0')
2173 	    break;
2174 	// skip occurrences of "No locals" and "No args"
2175 	if (strncmp(output, "No locals", 9) == 0 ||
2176 	    strncmp(output, "No arguments", 12) == 0)
2177 	{
2178 	    output = strchr(output, '\n');
2179 	    if (output == 0) {
2180 		break;
2181 	    }
2182 	    continue;
2183 	}
2184 
2185 	ExprValue* variable = parseVar(output);
2186 	if (variable == 0) {
2187 	    break;
2188 	}
2189 	// do not add duplicates
2190 	for (std::list<ExprValue*>::iterator o = newVars.begin(); o != newVars.end(); ++o) {
2191 	    if ((*o)->m_name == variable->m_name) {
2192 		delete variable;
2193 		goto skipDuplicate;
2194 	    }
2195 	}
2196 	newVars.push_back(variable);
2197     skipDuplicate:;
2198     }
2199 }
2200 
parsePrintExpr(const char * output,bool wantErrorValue)2201 ExprValue* GdbDriver::parsePrintExpr(const char* output, bool wantErrorValue)
2202 {
2203     ExprValue* var = 0;
2204     // check for error conditions
2205     if (!parseErrorMessage(output, var, wantErrorValue))
2206     {
2207 	// parse the variable
2208 	var = parseVar(output);
2209     }
2210     return var;
2211 }
2212 
parseChangeWD(const char * output,QString & message)2213 bool GdbDriver::parseChangeWD(const char* output, QString& message)
2214 {
2215     bool isGood = false;
2216     message = QString(output).simplified();
2217     if (message.isEmpty()) {
2218 	message = i18n("New working directory: ") + m_programWD;
2219 	isGood = true;
2220     }
2221     return isGood;
2222 }
2223 
parseChangeExecutable(const char * output,QString & message)2224 bool GdbDriver::parseChangeExecutable(const char* output, QString& message)
2225 {
2226     message = output;
2227 
2228     /*
2229      * Lines starting with the following do not indicate errors:
2230      *     Using host libthread_db
2231      *     (no debugging symbols found)
2232      *     Reading symbols from
2233      */
2234     while (strncmp(output, "Reading symbols from", 20) == 0 ||
2235 	   strncmp(output, "done.", 5) == 0 ||
2236 	   strncmp(output, "Missing separate debuginfo", 26) == 0 ||
2237 	   strncmp(output, "Try: ", 5) == 0 ||
2238 	   strncmp(output, "Using host libthread_db", 23) == 0 ||
2239 	   strncmp(output, "(no debugging symbols found)", 28) == 0)
2240     {
2241 	// this line is good, go to the next one
2242 	const char* end = strchr(output, '\n');
2243 	if (end == 0)
2244 	    output += strlen(output);
2245 	else
2246 	    output = end+1;
2247     }
2248 
2249     /*
2250      * If we've parsed all lines, there was no error.
2251      */
2252     return output[0] == '\0';
2253 }
2254 
parseCoreFile(const char * output)2255 bool GdbDriver::parseCoreFile(const char* output)
2256 {
2257     // if command succeeded, gdb emits a line starting with "#0 "
2258     return strstr(output, "\n#0 ") != 0;
2259 }
2260 
parseProgramStopped(const char * output,bool haveCoreFile,QString & message)2261 uint GdbDriver::parseProgramStopped(const char* output, bool haveCoreFile,
2262 				    QString& message)
2263 {
2264     // optionally: "program changed, rereading symbols",
2265     // followed by:
2266     // "Program exited normally"
2267     // "Program terminated with wignal SIGSEGV"
2268     // "Program received signal SIGINT" or other signal
2269     // "Breakpoint..."
2270     // GDB since 7.3 prints
2271     // "[Inferior 1 (process 13400) exited normally]"
2272     // "[Inferior 1 (process 14698) exited with code 01]"
2273 
2274     // go through the output, line by line, checking what we have
2275     const char* start = output - 1;
2276     uint flags = SFprogramActive;
2277     message = QString();
2278     do {
2279 	start++;			/* skip '\n' */
2280 
2281 	if (strncmp(start, "Program ", 8) == 0 ||
2282 	    strncmp(start, "ptrace: ", 8) == 0) {
2283 	    /*
2284 	     * When we receive a signal, the program remains active.
2285 	     *
2286 	     * Special: If we "stopped" in a corefile, the string "Program
2287 	     * terminated with signal"... is displayed. (Normally, we see
2288 	     * "Program received signal"... when a signal happens.)
2289 	     */
2290 	    if (strncmp(start, "Program exited", 14) == 0 ||
2291 		(strncmp(start, "Program terminated", 18) == 0 && !haveCoreFile) ||
2292 		strncmp(start, "ptrace: ", 8) == 0)
2293 	    {
2294 		flags &= ~SFprogramActive;
2295 	    }
2296 
2297 	    // set message
2298 	    const char* endOfMessage = strchr(start, '\n');
2299 	    if (endOfMessage == 0)
2300 		endOfMessage = start + strlen(start);
2301 	    message = QString::fromLatin1(start, endOfMessage-start);
2302 	} else if (strncmp(start, "[Inferior ", 10) == 0) {
2303 	    const char* p = start + 10;
2304 	    // skip number and space
2305 	    while (*p && !isspace(*p))
2306 		++p;
2307 	    skipSpace(p);
2308 	    if (*p == '(') {
2309 		skipNested(p, '(', ')');
2310 		if (strncmp(p, " exited ", 8) == 0) {
2311 		    flags &= ~SFprogramActive;
2312 
2313 		    // set message
2314 		    const char* end = strchr(p, '\n');
2315 		    if (end == 0)
2316 			end = p + strlen(p);
2317 		    // strip [] from the message
2318 		    message = QString::fromLatin1(start+1, end-start-2);
2319 		}
2320 	    }
2321 	} else if (strncmp(start, "Breakpoint ", 11) == 0) {
2322 	    /*
2323 	     * We stopped at a (permanent) breakpoint (gdb doesn't tell us
2324 	     * that it stopped at a temporary breakpoint).
2325 	     */
2326 	    flags |= SFrefreshBreak;
2327 	} else if (strstr(start, "re-reading symbols.") != 0) {
2328 	    flags |= SFrefreshSource;
2329 	}
2330 
2331 	// next line, please
2332 	start = strchr(start, '\n');
2333     } while (start != 0);
2334 
2335     /*
2336      * Gdb only notices when new threads have appeared, but not when a
2337      * thread finishes. So we always have to assume that the list of
2338      * threads has changed.
2339      */
2340     flags |= SFrefreshThreads;
2341 
2342     return flags;
2343 }
2344 
parseSharedLibs(const char * output)2345 QStringList GdbDriver::parseSharedLibs(const char* output)
2346 {
2347     QStringList shlibs;
2348     if (strncmp(output, "No shared libraries loaded", 26) == 0)
2349 	return shlibs;
2350 
2351     // parse the table of shared libraries
2352 
2353     // strip off head line
2354     output = strchr(output, '\n');
2355     if (output == 0)
2356 	return shlibs;
2357     output++;				/* skip '\n' */
2358     QString shlibName;
2359     while (*output != '\0') {
2360 	// format of a line is
2361 	// 0x404c5000  0x40580d90  Yes         /lib/libc.so.5
2362 	// 3 blocks of non-space followed by space
2363 	for (int i = 0; *output != '\0' && i < 3; i++) {
2364 	    while (*output != '\0' && !isspace(*output)) {	/* non-space */
2365 		output++;
2366 	    }
2367 	    skipSpace(output);		/* space */
2368 	}
2369 	if (*output == '\0')
2370 	    return shlibs;
2371 	const char* start = output;
2372 	output = strchr(output, '\n');
2373 	if (output == 0)
2374 	    output = start + strlen(start);
2375 	shlibName = QString::fromLatin1(start, output-start);
2376 	if (*output != '\0')
2377 	    output++;
2378 	shlibs.append(shlibName);
2379 	TRACE("found shared lib " + shlibName);
2380     }
2381     return shlibs;
2382 }
2383 
parseFindType(const char * output,QString & type)2384 bool GdbDriver::parseFindType(const char* output, QString& type)
2385 {
2386     if (strncmp(output, "type = ", 7) != 0)
2387 	return false;
2388 
2389     /*
2390      * Everything else is the type. We strip off any leading "const" and any
2391      * trailing "&" on the grounds that neither affects the decoding of the
2392      * object. We also strip off all white-space from the type.
2393      */
2394     output += 7;
2395     if (strncmp(output, "const ", 6) == 0)
2396         output += 6;
2397     type = output;
2398     type.replace(QRegExp("\\s+"), "");
2399     if (type.endsWith("&"))
2400         type.truncate(type.length() - 1);
2401     return true;
2402 }
2403 
parseRegisters(const char * output)2404 std::list<RegisterInfo> GdbDriver::parseRegisters(const char* output)
2405 {
2406     std::list<RegisterInfo> regs;
2407     if (strncmp(output, "The program has no registers now", 32) == 0) {
2408 	return regs;
2409     }
2410 
2411     // parse register values
2412     while (*output != '\0')
2413     {
2414 	RegisterInfo reg;
2415 	// skip space at the start of the line
2416 	skipSpace(output);
2417 
2418 	// register name
2419 	const char* start = output;
2420 	while (*output != '\0' && !isspace(*output))
2421 	    output++;
2422 	if (*output == '\0')
2423 	    break;
2424 	reg.regName = QString::fromLatin1(start, output-start);
2425 
2426 	skipSpace(output);
2427 
2428 	QString value;
2429 
2430 	/*
2431 	 * If we find a brace now, this is a vector register. We look for
2432 	 * the closing brace and treat the result as cooked value.
2433 	 */
2434 	if (*output == '{')
2435 	{
2436 	    start = output;
2437 	    skipNested(output, '{', '}');
2438 	    value = QString::fromLatin1(start, output-start).simplified();
2439 	    // skip space, but not the end of line
2440 	    while (isspace(*output) && *output != '\n')
2441 		output++;
2442 	    // get rid of the braces at the begining and the end
2443 	    value.remove(0, 1);
2444 	    if (value[value.length()-1] == '}') {
2445 		value = value.left(value.length()-1);
2446 	    }
2447 	    // gdb 5.3 doesn't print a separate set of raw values
2448 	    if (*output == '{') {
2449 		// another set of vector follows
2450 		// what we have so far is the raw value
2451 		reg.rawValue = value;
2452 
2453 		start = output;
2454 		skipNested(output, '{', '}');
2455 		value = QString::fromLatin1(start, output-start).simplified();
2456 	    } else {
2457 		// for gdb 5.3
2458 		// find first type that does not have an array, this is the RAW value
2459 		const char* end=start;
2460 		findEnd(end);
2461 		const char* cur=start;
2462 		while (cur<end) {
2463 		    while (*cur != '=' && cur<end)
2464 			cur++;
2465 		    cur++;
2466 		    while (isspace(*cur) && cur<end)
2467 			cur++;
2468 		    if (isNumberish(*cur)) {
2469 			end=cur;
2470 			while (*end && (*end!='}') && (*end!=',') && (*end!='\n'))
2471 			    end++;
2472 			QString rawValue = QString::fromLatin1(cur, end-cur).simplified();
2473 			reg.rawValue = rawValue;
2474 
2475 			if (rawValue.left(2)=="0x") {
2476 			    // ok we have a raw value, now get it's type
2477 			    end=cur-1;
2478 			    while (isspace(*end) || *end=='=') end--;
2479 			    end++;
2480 			    cur=end-1;
2481 			    while (*cur!='{' && *cur!=' ')
2482 				cur--;
2483 			    cur++;
2484 			    reg.type = QString::fromLatin1(cur, end-cur);
2485 			}
2486 
2487 			// end while loop
2488 			cur=end;
2489 		    }
2490 		}
2491 		// skip to the end of line
2492 		while (*output != '\0' && *output != '\n')
2493 		    output++;
2494 		// get rid of the braces at the begining and the end
2495 		value.remove(0, 1);
2496 		if (value[value.length()-1] == '}') {
2497 		    value.truncate(value.length()-1);
2498 		}
2499 	    }
2500 	    reg.cookedValue = value;
2501 	}
2502 	else
2503 	{
2504 	continuation:
2505 	    // the rest of the line is the register value
2506 	    start = output;
2507 	    output = strchr(output,'\n');
2508 	    if (output == 0)
2509 		output = start + strlen(start);
2510 	    value += QString::fromLatin1(start, output-start).simplified();
2511 
2512 	    /*
2513 	     * Look ahead: if the subsequent line is indented, it continues
2514 	     * the current register value.
2515 	     */
2516 	    if (output != 0 && isspace(output[1]))
2517 	    {
2518 		++output;
2519 		value += ' ';
2520 		goto continuation;
2521 	    }
2522 
2523 	    /*
2524 	     * We split the raw from the cooked values.
2525 	     * Some modern gdbs explicitly say: "0.1234 (raw 0x3e4567...)".
2526 	     * Here, the cooked value comes first, and the raw value is in
2527 	     * the second part.
2528 	     */
2529 	    int pos = value.indexOf(" (raw ");
2530 	    if (pos >= 0)
2531 	    {
2532 		reg.cookedValue = value.left(pos);
2533 		reg.rawValue = value.mid(pos+6);
2534 		if (reg.rawValue.right(1) == ")")	// remove closing bracket
2535 		    reg.rawValue.truncate(reg.rawValue.length()-1);
2536 	    }
2537 	    else
2538 	    {
2539 		/*
2540 		* In other cases we split off the first token (separated by
2541 		* whitespace). It is the raw value. The remainder of the line
2542 		* is the cooked value.
2543 		*/
2544 		int pos = value.indexOf(' ');
2545 		if (pos < 0) {
2546 		    reg.rawValue = value;
2547 		    reg.cookedValue = QString();
2548 		} else {
2549 		    reg.rawValue = value.left(pos);
2550 		    reg.cookedValue = value.mid(pos+1);
2551 		}
2552 	    }
2553 	}
2554 	if (*output != '\0')
2555 	    output++;			/* skip '\n' */
2556 
2557 	regs.push_back(reg);
2558     }
2559     return regs;
2560 }
2561 
parseInfoLine(const char * output,QString & addrFrom,QString & addrTo)2562 bool GdbDriver::parseInfoLine(const char* output, QString& addrFrom, QString& addrTo)
2563 {
2564     // "is at address" or "starts at address"
2565     const char* start = strstr(output, "s at address ");
2566     if (start == 0)
2567 	return false;
2568 
2569     start += 13;
2570     const char* p = start;
2571     while (*p != '\0' && !isspace(*p))
2572 	p++;
2573     addrFrom = QString::fromLatin1(start, p-start);
2574 
2575     start = strstr(p, "and ends at ");
2576     if (start == 0) {
2577 	addrTo = addrFrom;
2578 	return true;
2579     }
2580 
2581     start += 12;
2582     p = start;
2583     while (*p != '\0' && !isspace(*p))
2584 	p++;
2585     addrTo = QString::fromLatin1(start, p-start);
2586 
2587     return true;
2588 }
2589 
parseDisassemble(const char * output)2590 std::list<DisassembledCode> GdbDriver::parseDisassemble(const char* output)
2591 {
2592     std::list<DisassembledCode> code;
2593 
2594     if (strncmp(output, "Dump of assembler", 17) != 0) {
2595 	// error message?
2596 	DisassembledCode c;
2597 	c.code = output;
2598 	code.push_back(c);
2599 	return code;
2600     }
2601 
2602     // remove first line
2603     const char* p = strchr(output, '\n');
2604     if (p == 0)
2605 	return code;			/* not a regular output */
2606 
2607     p++;
2608 
2609     // remove last line
2610     const char* end = strstr(output, "End of assembler");
2611     if (end == 0)
2612 	end = p + strlen(p);
2613 
2614     // remove function offsets from the lines
2615     while (p != end)
2616     {
2617 	DisassembledCode c;
2618 	// skip initial space or PC pointer ("=>", since gdb 7.1)
2619 	while (p != end) {
2620 	    if (isspace(*p))
2621 		++p;
2622 	    else if (p[0] == '=' && p[1] == '>')
2623 		p += 2;
2624 	    else
2625 		break;
2626 	}
2627 	const char* start = p;
2628 	// address
2629 	while (p != end && !isspace(*p))
2630 	    p++;
2631 	c.address = QString::fromLatin1(start, p-start);
2632 
2633 	// function name (enclosed in '<>', followed by ':')
2634 	while (p != end && *p != '<')
2635 	    p++;
2636 	if (*p == '<')
2637 	    skipNestedAngles(p);
2638 	if (*p == ':')
2639 	    p++;
2640 
2641 	// space until code
2642 	while (p != end && isspace(*p))
2643 	    p++;
2644 
2645 	// code until end of line
2646 	start = p;
2647 	while (p != end && *p != '\n')
2648 	    p++;
2649 	if (p != end)			/* include '\n' */
2650 	    p++;
2651 
2652 	c.code = QString::fromLatin1(start, p-start);
2653 	code.push_back(c);
2654     }
2655     return code;
2656 }
2657 
parseMemoryDump(const char * output,std::list<MemoryDump> & memdump)2658 QString GdbDriver::parseMemoryDump(const char* output, std::list<MemoryDump>& memdump)
2659 {
2660     if (isErrorExpr(output)) {
2661 	// error; strip space
2662 	QString msg = output;
2663 	return msg.trimmed();
2664     }
2665 
2666     const char* p = output;		/* save typing */
2667     const char* end_output = p + strlen(p);
2668 
2669     // check if there is end of memory region
2670     const char* end_region = strstr(p, "Cannot access memory at address");
2671     if (end_region)
2672 	end_output = end_region;
2673 
2674     while (p < end_output)
2675     {
2676 	MemoryDump md;
2677 
2678 	// the address
2679 	skipSpace(p);			/* remove leading space, detected on instructions output format */
2680 
2681 	const char* start = p;
2682 
2683 	while (*p != '\0' && *p != ':' && !isspace(*p))
2684 	    p++;
2685 	md.address = QString::fromLatin1(start, p-start);
2686 
2687 	if (*p != ':') {
2688 	    // parse function offset
2689 	    skipSpace(p);
2690 	    start = p;
2691 	    while (*p != '\0' && !(*p == ':' && isspace(p[1])))
2692 		p++;
2693 	    md.address.fnoffs = QString::fromLatin1(start, p-start);
2694 	}
2695 	if (*p == ':')
2696 	    p++;
2697 	// skip space; this may skip a new-line char!
2698 	skipSpace(p);
2699 	// everything to the end of the line is the memory dump
2700 	const char* end = strchr(p, '\n');
2701 	if (!end || (end_region && end > end_region))
2702 	    end = end_output;
2703 	md.dump = QString::fromLatin1(p, end-p);
2704 	p = end;
2705 	if (*p)
2706 	    ++p;	// skip '\n' or 'C' of "Cannot access..."
2707 
2708 	md.littleendian = m_littleendian;
2709 	memdump.push_back(md);
2710     }
2711 
2712     if (end_region && !memdump.empty())
2713 	memdump.back().endOfDump = true;
2714 
2715     return QString();
2716 }
2717 
editableValue(VarTree * value)2718 QString GdbDriver::editableValue(VarTree* value)
2719 {
2720     QByteArray ba = value->value().toLatin1();
2721     const char* s = ba.constData();
2722 
2723     // if the variable is a pointer value that contains a cast,
2724     // remove the cast
2725     if (*s == '(') {
2726 	skipNested(s, '(', ')');
2727 	// skip space
2728 	skipSpace(s);
2729     }
2730 
2731 repeat:
2732     const char* start = s;
2733 
2734     if (strncmp(s, "0x", 2) == 0)
2735     {
2736 	s += 2;
2737 	while (isxdigit(*s))
2738 	    ++s;
2739 
2740 	/*
2741 	 * What we saw so far might have been a reference. If so, edit the
2742 	 * referenced value. Otherwise, edit the pointer.
2743 	 */
2744 	if (*s == ':') {
2745 	    // a reference
2746 	    ++s;
2747 	    goto repeat;
2748 	}
2749 	// a pointer
2750 	// if it's a pointer to a string, remove the string
2751 	const char* end = s;
2752 	skipSpace(s);
2753 	if (*s == '"') {
2754 	    // a string
2755 	    return QString::fromLatin1(start, end-start);
2756 	} else {
2757 	    // other pointer
2758 	    return QString::fromLatin1(start, strlen(start));
2759 	}
2760     }
2761 
2762     // else leave it unchanged (or stripped of the reference preamble)
2763     return s;
2764 }
2765 
parseSetVariable(const char * output)2766 QString GdbDriver::parseSetVariable(const char* output)
2767 {
2768     // if there is any output, it is an error message
2769     QString msg = output;
2770     return msg.trimmed();
2771 }
2772 
2773 
2774 #include "gdbdriver.moc"
2775