blob: ba9bbd30eb6d2430bc1df3b8d2408b0479658fe1 [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001/*
njn9a0cba42007-04-15 22:15:57 +00002 This file is part of Callgrind, a Valgrind tool for call graph
weidendoa17f2a32006-03-20 10:27:30 +00003 profiling programs.
4
sewardj4d474d02008-02-11 11:34:59 +00005 Copyright (C) 2002-2008, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +00006
njn9a0cba42007-04-15 22:15:57 +00007 This tool is derived from and contains lot of code from Cachegrind
8 Copyright (C) 2002 Nicholas Nethercote (njn@valgrind.org)
weidendoa17f2a32006-03-20 10:27:30 +00009
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 02111-1307, USA.
24
25 The GNU General Public License is contained in the file COPYING.
26*/
27
28/*
29 * Functions related to interactive commands via "callgrind.cmd"
30 */
31
32#include "config.h"
33#include "global.h"
34
35#include <pub_tool_threadstate.h> // VG_N_THREADS
36
weidendo4e28a852006-04-21 00:58:58 +000037// Version for the syntax in command/result files for interactive control
38#define COMMAND_VERSION "1.0"
39
weidendoa17f2a32006-03-20 10:27:30 +000040static Char outbuf[FILENAME_LEN + FN_NAME_LEN + OBJ_NAME_LEN];
41
42static Char* command_file = 0;
43static Char* command_file2 = 0;
weidendo4e28a852006-04-21 00:58:58 +000044static Char* current_command_file = 0;
weidendoa17f2a32006-03-20 10:27:30 +000045static Char* result_file = 0;
weidendo4e28a852006-04-21 00:58:58 +000046static Char* result_file2 = 0;
47static Char* current_result_file = 0;
weidendoa17f2a32006-03-20 10:27:30 +000048static Char* info_file = 0;
weidendocbf4e192007-11-27 01:27:12 +000049static Char* out_file = 0;
weidendoa17f2a32006-03-20 10:27:30 +000050
weidendo4ce5e792006-09-20 21:29:39 +000051static Int thisPID = 0;
weidendoa17f2a32006-03-20 10:27:30 +000052
weidendo4ce5e792006-09-20 21:29:39 +000053/**
54 * Setup for interactive control of a callgrind run
55 */
56static void setup_control(void)
weidendoa17f2a32006-03-20 10:27:30 +000057{
weidendo4ce5e792006-09-20 21:29:39 +000058 Int fd, size;
weidendoa17f2a32006-03-20 10:27:30 +000059 SysRes res;
weidendocbf4e192007-11-27 01:27:12 +000060 Char* dir;
weidendoa17f2a32006-03-20 10:27:30 +000061
weidendo4ce5e792006-09-20 21:29:39 +000062 CLG_ASSERT(thisPID != 0);
weidendoa17f2a32006-03-20 10:27:30 +000063
weidendo4ce5e792006-09-20 21:29:39 +000064 fd = -1;
weidendocbf4e192007-11-27 01:27:12 +000065 dir = CLG_(get_out_directory)();
66 out_file = CLG_(get_out_file)();
weidendo4ce5e792006-09-20 21:29:39 +000067
68 /* name of command file */
weidendoa17f2a32006-03-20 10:27:30 +000069 size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_COMMANDNAME) +10;
sewardj9c606bd2008-09-18 18:12:50 +000070 command_file = (char*) CLG_MALLOC("cl.command.sc.1", size);
weidendoa17f2a32006-03-20 10:27:30 +000071 CLG_ASSERT(command_file != 0);
72 VG_(sprintf)(command_file, "%s/%s.%d",
weidendo4ce5e792006-09-20 21:29:39 +000073 dir, DEFAULT_COMMANDNAME, thisPID);
weidendoa17f2a32006-03-20 10:27:30 +000074
75 /* This is for compatibility with the "Force Now" Button of current
76 * KCachegrind releases, as it doesn't use ".pid" to distinguish
77 * different callgrind instances from same base directory.
weidendoa17f2a32006-03-20 10:27:30 +000078 */
sewardj9c606bd2008-09-18 18:12:50 +000079 command_file2 = (char*) CLG_MALLOC("cl.command.sc.2", size);
weidendoa17f2a32006-03-20 10:27:30 +000080 CLG_ASSERT(command_file2 != 0);
81 VG_(sprintf)(command_file2, "%s/%s",
82 dir, DEFAULT_COMMANDNAME);
83
84 size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_RESULTNAME) +10;
sewardj9c606bd2008-09-18 18:12:50 +000085 result_file = (char*) CLG_MALLOC("cl.command.sc.3", size);
weidendoa17f2a32006-03-20 10:27:30 +000086 CLG_ASSERT(result_file != 0);
87 VG_(sprintf)(result_file, "%s/%s.%d",
weidendo4ce5e792006-09-20 21:29:39 +000088 dir, DEFAULT_RESULTNAME, thisPID);
weidendoa17f2a32006-03-20 10:27:30 +000089
weidendo4e28a852006-04-21 00:58:58 +000090 /* If we get a command from a command file without .pid, use
91 * a result file without .pid suffix
92 */
sewardj9c606bd2008-09-18 18:12:50 +000093 result_file2 = (char*) CLG_MALLOC("cl.command.sc.4", size);
weidendo4e28a852006-04-21 00:58:58 +000094 CLG_ASSERT(result_file2 != 0);
95 VG_(sprintf)(result_file2, "%s/%s",
96 dir, DEFAULT_RESULTNAME);
97
sewardj9c606bd2008-09-18 18:12:50 +000098 info_file = (char*) CLG_MALLOC("cl.command.sc.5",
99 VG_(strlen)(DEFAULT_INFONAME) + 10);
weidendoa17f2a32006-03-20 10:27:30 +0000100 CLG_ASSERT(info_file != 0);
weidendo4ce5e792006-09-20 21:29:39 +0000101 VG_(sprintf)(info_file, "%s.%d", DEFAULT_INFONAME, thisPID);
weidendoa17f2a32006-03-20 10:27:30 +0000102
weidendo4ce5e792006-09-20 21:29:39 +0000103 CLG_DEBUG(1, "Setup for interactive control (PID: %d):\n", thisPID);
weidendocbf4e192007-11-27 01:27:12 +0000104 CLG_DEBUG(1, " output file: '%s'\n", out_file);
weidendoa17f2a32006-03-20 10:27:30 +0000105 CLG_DEBUG(1, " command file: '%s'\n", command_file);
106 CLG_DEBUG(1, " result file: '%s'\n", result_file);
107 CLG_DEBUG(1, " info file: '%s'\n", info_file);
108
109 /* create info file to indicate that we are running */
110 res = VG_(open)(info_file, VKI_O_WRONLY|VKI_O_TRUNC, 0);
111 if (res.isError) {
112 res = VG_(open)(info_file, VKI_O_CREAT|VKI_O_WRONLY,
113 VKI_S_IRUSR|VKI_S_IWUSR);
114 if (res.isError) {
115 VG_(message)(Vg_DebugMsg,
116 "warning: can't write info file '%s'", info_file);
117 info_file = 0;
118 fd = -1;
119 }
120 }
121 if (!res.isError)
sewardje8089302006-10-17 02:15:17 +0000122 fd = (Int) res.res;
weidendoa17f2a32006-03-20 10:27:30 +0000123 if (fd>=0) {
124 Char buf[512];
125 Int i;
weidendo5bd7eca2007-02-26 00:16:09 +0000126
127 WRITE_STR3(fd,
128 "# This file is generated by Callgrind-" VERSION ".\n"
129 "# It is used to enable controlling the supervision of\n"
130 "# '", VG_(args_the_exename), "'\n"
131 "# by external tools.\n\n");
weidendoa17f2a32006-03-20 10:27:30 +0000132
weidendo4e28a852006-04-21 00:58:58 +0000133 VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000134 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
135
weidendo5bd7eca2007-02-26 00:16:09 +0000136 WRITE_STR3(fd, "base: ", dir, "\n");
weidendocbf4e192007-11-27 01:27:12 +0000137 WRITE_STR3(fd, "dumps: ", out_file, "\n");
weidendo5bd7eca2007-02-26 00:16:09 +0000138 WRITE_STR3(fd, "control: ", command_file, "\n");
139 WRITE_STR3(fd, "result: ", result_file, "\n");
140
141 WRITE_STR2(fd, "cmd: ", VG_(args_the_exename));
sewardj14c7cc52007-02-25 15:08:24 +0000142 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
143 HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
144 if (!arg) continue;
weidendo5bd7eca2007-02-26 00:16:09 +0000145 WRITE_STR2(fd, " ", arg);
weidendoa17f2a32006-03-20 10:27:30 +0000146 }
weidendoa17f2a32006-03-20 10:27:30 +0000147 VG_(write)(fd, "\n", 1);
148 VG_(close)(fd);
149 }
weidendo4ce5e792006-09-20 21:29:39 +0000150}
weidendoa17f2a32006-03-20 10:27:30 +0000151
weidendo4ce5e792006-09-20 21:29:39 +0000152void CLG_(init_command)()
153{
154 thisPID = VG_(getpid)();
155 setup_control();
weidendoa17f2a32006-03-20 10:27:30 +0000156}
157
158void CLG_(finish_command)()
159{
160 /* unlink info file */
161 if (info_file) VG_(unlink)(info_file);
162}
163
164
165static Int createRes(Int fd)
166{
167 SysRes res;
168
169 if (fd > -2) return fd;
170
171 /* fd == -2: No error, but we need to create the file */
weidendo4e28a852006-04-21 00:58:58 +0000172 CLG_ASSERT(current_result_file != 0);
173 res = VG_(open)(current_result_file,
weidendoa17f2a32006-03-20 10:27:30 +0000174 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
175 VKI_S_IRUSR|VKI_S_IWUSR);
176
177 /* VG_(open) can return any negative number on error. Remap errors to -1,
178 * to not confuse it with our special value -2
179 */
180 if (res.isError) fd = -1;
sewardje8089302006-10-17 02:15:17 +0000181 else fd = (Int) res.res;
weidendoa17f2a32006-03-20 10:27:30 +0000182
183 return fd;
184}
185
weidendo4e28a852006-04-21 00:58:58 +0000186/* Run Info: Persistant information of the callgrind run */
weidendoa17f2a32006-03-20 10:27:30 +0000187static Int dump_info(Int fd)
188{
189 Char* buf = outbuf;
190 int i;
191
192 if ( (fd = createRes(fd)) <0) return fd;
193
weidendo4e28a852006-04-21 00:58:58 +0000194 /* creator */
195 VG_(sprintf)(buf, "creator: callgrind-" VERSION "\n");
196 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
197
weidendoa17f2a32006-03-20 10:27:30 +0000198 /* version */
weidendo4e28a852006-04-21 00:58:58 +0000199 VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000200 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
201
202 /* "pid:" line */
203 VG_(sprintf)(buf, "pid: %d\n", VG_(getpid)());
204 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
205
206 /* "base:" line */
weidendocbf4e192007-11-27 01:27:12 +0000207 WRITE_STR3(fd, "base: ", out_file, "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000208
209 /* "cmd:" line */
weidendo5bd7eca2007-02-26 00:16:09 +0000210 WRITE_STR2(fd, "cmd: ", VG_(args_the_exename));
sewardj14c7cc52007-02-25 15:08:24 +0000211 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
212 HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
213 if (!arg) continue;
weidendo5bd7eca2007-02-26 00:16:09 +0000214 WRITE_STR2(fd, " ", arg);
weidendoa17f2a32006-03-20 10:27:30 +0000215 }
weidendo4e28a852006-04-21 00:58:58 +0000216 VG_(write)(fd, "\n", 1);
weidendoa17f2a32006-03-20 10:27:30 +0000217
218 return fd;
219}
220
221
222/* Helper for dump_state */
223
224Int dump_fd;
225
226void static dump_state_of_thread(thread_info* ti)
227{
228 Char* buf = outbuf;
229 int t = CLG_(current_tid);
230 Int p, i;
231 static FullCost sum = 0, tmp = 0;
232 BBCC *from, *to;
233 call_entry* ce;
234
235 p = VG_(sprintf)(buf, "events-%d: ", t);
236 CLG_(init_cost_lz)( CLG_(sets).full, &sum );
237 CLG_(copy_cost_lz)( CLG_(sets).full, &tmp, ti->lastdump_cost );
238 CLG_(add_diff_cost)( CLG_(sets).full, sum,
239 ti->lastdump_cost,
240 ti->states.entry[0]->cost);
241 CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost, tmp );
242 p += CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum);
243 p += VG_(sprintf)(buf+p, "\n");
244 VG_(write)(dump_fd, (void*)buf, p);
245
246 p = VG_(sprintf)(buf, "frames-%d: %d\n", t,
247 CLG_(current_call_stack).sp);
248 VG_(write)(dump_fd, (void*)buf, p);
249 ce = 0;
250 for(i = 0; i < CLG_(current_call_stack).sp; i++) {
251 ce = CLG_(get_call_entry)(i);
252 /* if this frame is skipped, we don't have counters */
253 if (!ce->jcc) continue;
254
255 from = ce->jcc->from;
256 p = VG_(sprintf)(buf, "function-%d-%d: %s\n",t, i,
257 from->cxt->fn[0]->name);
258 VG_(write)(dump_fd, (void*)buf, p);
259
260 p = VG_(sprintf)(buf, "calls-%d-%d: ",t, i);
261 p+= VG_(sprintf)(buf+p, "%llu\n", ce->jcc->call_counter);
262 VG_(write)(dump_fd, (void*)buf, p);
263
264 /* FIXME: EventSets! */
265 CLG_(copy_cost)( CLG_(sets).full, sum, ce->jcc->cost );
266 CLG_(copy_cost)( CLG_(sets).full, tmp, ce->enter_cost );
267 CLG_(add_diff_cost)( CLG_(sets).full, sum,
268 ce->enter_cost, CLG_(current_state).cost );
269 CLG_(copy_cost)( CLG_(sets).full, ce->enter_cost, tmp );
270
271 p = VG_(sprintf)(buf, "events-%d-%d: ",t, i);
272 p += CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum );
273 p += VG_(sprintf)(buf+p, "\n");
274 VG_(write)(dump_fd, (void*)buf, p);
275 }
276 if (ce && ce->jcc) {
277 to = ce->jcc->to;
278 p = VG_(sprintf)(buf, "function-%d-%d: %s\n",t, i,
279 to->cxt->fn[0]->name );
280 VG_(write)(dump_fd, (void*)buf, p);
281 }
282}
283
284/* Dump info on current callgrind state */
285static Int dump_state(Int fd)
286{
287 Char* buf = outbuf;
288 thread_info** th;
289 int t, p;
290 Int orig_tid = CLG_(current_tid);
291
292 if ( (fd = createRes(fd)) <0) return fd;
293
294 VG_(sprintf)(buf, "instrumentation: %s\n",
295 CLG_(instrument_state) ? "on":"off");
296 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
297
298 if (!CLG_(instrument_state)) return fd;
299
300 VG_(sprintf)(buf, "executed-bbs: %llu\n", CLG_(stat).bb_executions);
301 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
302
303 VG_(sprintf)(buf, "executed-calls: %llu\n", CLG_(stat).call_counter);
304 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
305
306 VG_(sprintf)(buf, "distinct-bbs: %d\n", CLG_(stat).distinct_bbs);
307 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
308
309 VG_(sprintf)(buf, "distinct-calls: %d\n", CLG_(stat).distinct_jccs);
310 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
311
312 VG_(sprintf)(buf, "distinct-functions: %d\n", CLG_(stat).distinct_fns);
313 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
314
315 VG_(sprintf)(buf, "distinct-contexts: %d\n", CLG_(stat).distinct_contexts);
316 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
317
318 /* "events:" line. Given here because it will be dynamic in the future */
319 p = VG_(sprintf)(buf, "events: ");
320 CLG_(sprint_eventmapping)(buf+p, CLG_(dumpmap));
321 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
322 VG_(write)(fd, "\n", 1);
323
324 /* "part:" line (number of last part. Is 0 at start */
325 VG_(sprintf)(buf, "\npart: %d\n", CLG_(get_dump_counter)());
326 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
327
328 /* threads */
329 th = CLG_(get_threads)();
330 p = VG_(sprintf)(buf, "threads:");
331 for(t=1;t<VG_N_THREADS;t++) {
332 if (!th[t]) continue;
333 p += VG_(sprintf)(buf+p, " %d", t);
334 }
335 p += VG_(sprintf)(buf+p, "\n");
336 VG_(write)(fd, (void*)buf, p);
337
338 VG_(sprintf)(buf, "current-tid: %d\n", orig_tid);
339 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
340
341 /* current event counters */
342 dump_fd = fd;
343 CLG_(forall_threads)(dump_state_of_thread);
344
345 return fd;
346}
347
348void CLG_(check_command)()
349{
350 /* check for dumps needed */
351 static Char buf[512];
352 static Char cmdBuffer[512];
353 Char *cmdPos = 0, *cmdNextLine = 0;
354 Int fd, bytesRead = 0, do_kill = 0;
weidendoa17f2a32006-03-20 10:27:30 +0000355 SysRes res;
weidendo4ce5e792006-09-20 21:29:39 +0000356 Int currentPID;
357 static Int check_counter = 0;
weidendoa17f2a32006-03-20 10:27:30 +0000358
weidendo4ce5e792006-09-20 21:29:39 +0000359 /* Check for PID change, i.e. whether we run as child after a fork.
360 * If yes, we setup interactive control for the new process
361 */
362 currentPID = VG_(getpid)();
363 if (thisPID != currentPID) {
364 thisPID = currentPID;
365 setup_control();
366 }
weidendoa17f2a32006-03-20 10:27:30 +0000367
weidendo4ce5e792006-09-20 21:29:39 +0000368 /* Toggle between 2 command files, with/without ".pid" postfix
369 * (needed for compatibility with KCachegrind, which wants to trigger
370 * a dump by writing into a command file without the ".pid" postfix)
371 */
372 check_counter++;
373 if (check_counter % 2) {
374 current_command_file = command_file;
375 current_result_file = result_file;
376 }
377 else {
378 current_command_file = command_file2;
379 current_result_file = result_file2;
380 }
weidendoa17f2a32006-03-20 10:27:30 +0000381
weidendo4e28a852006-04-21 00:58:58 +0000382 res = VG_(open)(current_command_file, VKI_O_RDONLY,0);
weidendoa17f2a32006-03-20 10:27:30 +0000383 if (!res.isError) {
sewardje8089302006-10-17 02:15:17 +0000384 fd = (Int) res.res;
weidendoa17f2a32006-03-20 10:27:30 +0000385 bytesRead = VG_(read)(fd,cmdBuffer,500);
386 cmdBuffer[500] = 0; /* no command overrun please */
387 VG_(close)(fd);
388 /* don't delete command file on read error (e.g. EAGAIN) */
389 if (bytesRead>0) {
390 cmdPos = cmdBuffer;
391 }
392 }
393
394 /* force creation of result file if needed */
395 fd = -2;
396
397 while((bytesRead>0) && *cmdPos) {
398
399 /* Calculate pointer for next line */
400 cmdNextLine = cmdPos+1;
401 while((bytesRead>0) && *cmdNextLine && (*cmdNextLine != '\n')) {
402 cmdNextLine++;
403 bytesRead--;
404 }
405 if ((bytesRead>0) && (*cmdNextLine == '\n')) {
406 *cmdNextLine = 0;
407 cmdNextLine++;
408 bytesRead--;
409 }
410
411 /* Command with integer option */
412 if ((*cmdPos >= '0') && (*cmdPos <='9')) {
413 int value = *cmdPos-'0';
414 cmdPos++;
415 while((*cmdPos >= '0') && (*cmdPos <='9')) {
416 value = 10*value + (*cmdPos-'0');
417 cmdPos++;
418 }
419 while((*cmdPos == ' ') || (*cmdPos == '\t')) cmdPos++;
420
421 switch(*cmdPos) {
422#if CLG_ENABLE_DEBUG
423 /* verbosity */
424 case 'V':
425 case 'v':
426 CLG_(clo).verbose = value;
427 break;
428#endif
429 default:
430 break;
431 }
432
433 cmdPos = cmdNextLine;
434 continue;
435 }
436
437 /* Command with boolean/switch option */
438 if ((*cmdPos=='+') ||
439 (*cmdPos=='-')) {
440 int value = (cmdPos[0] == '+');
441 cmdPos++;
442 while((*cmdPos == ' ') || (*cmdPos == '\t')) cmdPos++;
443
444 switch(*cmdPos) {
445 case 'I':
446 case 'i':
447 CLG_(set_instrument_state)("Command", value);
448 break;
449
450 default:
451 break;
452 }
453
454 cmdPos = cmdNextLine;
455 continue;
456 }
457
458 /* regular command */
459 switch(*cmdPos) {
460 case 'D':
461 case 'd':
462 /* DUMP */
463
464 /* skip command */
465 while(*cmdPos && (*cmdPos != ' ')) cmdPos++;
466 if (*cmdPos)
467 VG_(sprintf)(buf, "Dump Command:%s", cmdPos);
468 else
469 VG_(sprintf)(buf, "Dump Command");
470 CLG_(dump_profile)(buf, False);
471 break;
472
473 case 'Z':
474 case 'z':
475 CLG_(zero_all_cost)(False);
476 break;
477
478 case 'K':
479 case 'k':
480 /* Kill: Delay to be able to remove command file before. */
481 do_kill = 1;
482 break;
483
484 case 'I':
485 case 'i':
486 fd = dump_info(fd);
487 break;
488
489 case 's':
490 case 'S':
491 fd = dump_state(fd);
492 break;
493
494 case 'O':
495 case 'o':
496 /* Options Info */
497 if ( (fd = createRes(fd)) <0) break;
498
499 VG_(sprintf)(buf, "\ndesc: Option: --skip-plt=%s\n",
500 CLG_(clo).skip_plt ? "yes" : "no");
501 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
502 VG_(sprintf)(buf, "desc: Option: --collect-jumps=%s\n",
503 CLG_(clo).collect_jumps ? "yes" : "no");
504 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
505 VG_(sprintf)(buf, "desc: Option: --separate-recs=%d\n",
506 CLG_(clo).separate_recursions);
507 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
508 VG_(sprintf)(buf, "desc: Option: --separate-callers=%d\n",
509 CLG_(clo).separate_callers);
510 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
511
512 break;
513
514 default:
515 break;
516 }
517
518 cmdPos = cmdNextLine;
519 }
520
521 /* If command executed, delete command file */
weidendo4e28a852006-04-21 00:58:58 +0000522 if (cmdPos) VG_(unlink)(current_command_file);
weidendoa17f2a32006-03-20 10:27:30 +0000523 if (fd>=0) VG_(close)(fd);
524
525 if (do_kill) {
526 VG_(message)(Vg_UserMsg,
weidendo4e28a852006-04-21 00:58:58 +0000527 "Killed because of command from %s", current_command_file);
weidendoa17f2a32006-03-20 10:27:30 +0000528 CLG_(fini)(0);
529 VG_(exit)(1);
530 }
531}