1 /* vi:set ts=8 sts=4 sw=4:
2 *
3 * Copyright (C) 2004 Xavier de Gaye.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program (see the file COPYING); if not, write to the
17 * Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 *
20 * $Id: gdb_lvl3.c 222 2008-10-13 14:38:07Z xavier $
21 */
22
23 # ifdef HAVE_CLEWN
24 # include <config.h>
25 # include "obstack.h"
26 # include "clewn.h"
27 static int got_int; /* not used with Clewn */
28 # else
29 # include "vim.h"
30 # include "clewn/obstack.h"
31 # endif
32
33 #if defined(FEAT_GDB) || defined(HAVE_CLEWN)
34
35 # include "gdb.h"
36 # include "misc.h"
37
38 # if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
39
40 static char gdb_buf[MAX_BUFFSIZE]; /* general purpose buffer */
41
42 typedef struct
43 {
44 int id; /* annoted identifier */
45 char_u *str; /* GDB annotation */
46 } annotation_T;
47
48 static annotation_T annotations[] = {
49 {ANO_PREPROMPT, (char_u *)"pre-prompt"},
50 {ANO_PROMPT, (char_u *)"prompt"},
51 {ANO_POSTPROMPT, (char_u *)"post-prompt"},
52 {ANO_PRECMDS, (char_u *)"pre-commands"},
53 {ANO_CMDS, (char_u *)"commands"},
54 {ANO_PREOVERLOAD, (char_u *)"pre-overload-choice"},
55 {ANO_OVERLOAD, (char_u *)"overload-choice"},
56 {ANO_PREQUERY, (char_u *)"pre-query"},
57 {ANO_QUERY, (char_u *)"query"},
58 {ANO_PREPMT_FORMORE, (char_u *)"pre-prompt-for-continue"},
59 {ANO_PMT_FORMORE, (char_u *)"prompt-for-continue"},
60 {ANO_POSTPMT_FORMORE, (char_u *)"post-prompt-for-continue"},
61 {ANO_QUIT, (char_u *)"quit"},
62 {ANO_ERROR_BEG, (char_u *)"error-begin"},
63 {ANO_FRAME_INVALID, (char_u *)"frames-invalid"},
64 {ANO_BP_INVALID, (char_u *)"breakpoints-invalid"},
65 {ANO_STARTING, (char_u *)"starting"},
66 {ANO_STOPPED, (char_u *)"stopped"},
67 {ANO_EXITED, (char_u *)"exited"},
68 {ANO_SIGNALLED, (char_u *)"signalled"},
69 {ANO_BREAKPOINT, (char_u *)"breakpoint"},
70 # ifdef GDB_LVL2_SUPPORT
71 {ANO_SOURCE, (char_u *)"source"},
72 {ANO_FRAME_BEGIN, (char_u *)"frame-begin"},
73 {ANO_FRAME_END, (char_u *)"frame-end"},
74 {ANO_BP_HEADER, (char_u *)"breakpoints-headers"},
75 {ANO_BP_TABLE, (char_u *)"breakpoints-table"},
76 {ANO_BP_RECORD, (char_u *)"record"},
77 {ANO_BP_FIELD0, (char_u *)"field 0"},
78 {ANO_BP_FIELD1, (char_u *)"field 1"},
79 {ANO_BP_FIELD2, (char_u *)"field 2"},
80 {ANO_BP_FIELD3, (char_u *)"field 3"},
81 {ANO_BP_FIELD4, (char_u *)"field 4"},
82 {ANO_BP_FIELD5, (char_u *)"field 5"},
83 {ANO_BP_FIELD6, (char_u *)"field 6"},
84 {ANO_BP_FIELD7, (char_u *)"field 7"},
85 {ANO_BP_FIELD8, (char_u *)"field 8"},
86 {ANO_BP_FIELD9, (char_u *)"field 9"},
87 {ANO_BP_END, (char_u *)"breakpoints-table-end"},
88 {ANO_DISP_BEG, (char_u *)"display-begin"},
89 {ANO_DISP_NUMEND, (char_u *)"display-number-end"},
90 {ANO_DISP_FMT, (char_u *)"display-format"},
91 {ANO_DISP_EXP, (char_u *)"display-expression"},
92 {ANO_DISP_EXPEND, (char_u *)"display-expression-end"},
93 {ANO_DISP_VALUE, (char_u *)"display-value"},
94 {ANO_DISP_END, (char_u *)"display-end"},
95 {ANO_FIELD_BEG, (char_u *)"field-begin"},
96 {ANO_FIELD_NAMEND, (char_u *)"field-name-end"},
97 {ANO_FIELD_VALUE, (char_u *)"field-value"},
98 {ANO_FIELD_END, (char_u *)"field-end"},
99 {ANO_ARRAY_BEG, (char_u *)"array-section-begin"},
100 {ANO_ARRAY_ELT, (char_u *)"elt"},
101 {ANO_ARRAY_ELTREP, (char_u *)"elt-rep"},
102 {ANO_ARRAY_ELTEND, (char_u *)"elt-rep-end"},
103 {ANO_ARRAY_END, (char_u *)"array-section-end"},
104 # endif
105 {0, NULL}
106 };
107
108 /* User interface */
109 static char_u *process_cmd __ARGS((gdb_T *, char_u *));
110
111 /* Vim low level hook */
112 /* Not allowed after ^O in INS REP mode or from the input-line window */
113 static char_u *process_annotation __ARGS((gdb_T *, char_u *, struct obstack *));
114 static char_u * process_completion __ARGS((cli_cmd_T *, char_u *, struct obstack *));
115 static char_u * eol_choices __ARGS((cli_cmd_T *, struct obstack *));
116
117 # ifdef GDB_LVL3_SUPPORT
118 /* Gdb process mgmt */
119 static void clear_gdb_T __ARGS((gdb_T *));
120
121 /* Out Of Band */
122 static char *get_lastbp __ARGS((gdb_T *, int, char_u *, struct obstack *));
123 static char *get_bp __ARGS((gdb_T *, int, char_u *, struct obstack *));
124 static void process_record __ARGS((gdb_T *, char_u *, struct obstack *));
125 static char *varobj_update __ARGS((gdb_T *, int, char_u *, struct obstack *));
126 static char *varobj_complete __ARGS((gdb_T *, struct obstack *));
127 static void varobj_hilite __ARGS((gdb_T *, varobj_T *, int, struct obstack *));
128 static void varobj_replace __ARGS((gdb_T *, varobj_T *, char_u *, struct obstack *));
129 static void remove_object __ARGS((gdb_T *, varobj_T *));
130 # endif
131
132 /* Utilities */
133 static char_u * parse_note __ARGS((gdb_T *, char_u *));
134 # ifndef FEAT_GDB
135 static int get_note __ARGS((gdb_T *, char_u *));
136 # endif
137
138 # ifdef GDB_LVL3_SUPPORT
139 /* The function ordering in this array is important as some of
140 * these functions must be invoked in the right order */
141 static oobfunc_T oobfunc[] = {
142 {gdb_get_pc},
143 {gdb_get_frame},
144 {gdb_get_sourcedir},
145 #ifndef FEAT_GDB
146 {gdb_source_project},
147 {gdb_get_pwd},
148 {gdb_get_args},
149 #endif
150 {gdb_source_cur},
151 {gdb_source_list},
152 {gdb_get_sfile},
153 {gdb_info_frame},
154 {gdb_stack_frame}, /* after gdb_info_frame */
155 {get_lastbp}, /* after gdb_get_frame */
156 {gdb_get_asmfunc}, /* after get_lastbp */
157 {gdb_get_asmfunc_hack}, /* after gdb_get_asmfunc */
158 {gdb_get_asm}, /* after gdb_get_asmfunc */
159 {get_bp}, /* after gdb_get_asm and get_lastbp */
160 {varobj_update},
161 {NULL}
162 };
163 # endif
164
165 /** Send a cmd to gdb */
166 void
gdb_docmd_cli(this,cmd)167 gdb_docmd_cli(this, cmd)
168 gdb_T *this;
169 char_u *cmd; /* gdb cmd */
170 {
171 # ifdef GDB_LVL3_SUPPORT
172 char_u *expression = NULL;
173 varobj_T *varobj;
174 # endif
175 char_u *res;
176 char_u *ptr;
177 char_u *last;
178 int len;
179
180 /* make a copy so we can mess with it */
181 if (cmd == NULL)
182 {
183 this->cmd_type = CMD_ANY;
184 goto empty_cmd;
185 }
186 cmd = (char_u *)clewn_strsave((char *)cmd);
187
188 /* remove illegal characters */
189 for (ptr = last = cmd; *last != NUL; last++)
190 if (*last == NL
191 || *last == TAB
192 || *last == KEY_INTERUPT
193 || !iscntrl((int)(*last)))
194 *ptr++ = *last;
195 *ptr = NUL;
196
197 /* remove backslash at last position */
198 if (ptr != cmd && *(ptr - 1) == '\\')
199 *(ptr - 1) = NUL;
200
201 if (this->cli_cmd.state == CS_QUERY || this->note == ANO_QUERY)
202 {
203 if (*cmd == NUL)
204 goto empty_cmd;
205 goto send;
206 }
207
208 /* now we can forget last cmd */
209 this->cmd_type = CMD_ANY;
210
211 /* an interrupt */
212 if (STRCHR(cmd, KEY_INTERUPT) != NULL)
213 goto send;
214
215 /* a TAB */
216 if (STRCHR(cmd, TAB) != NULL)
217 {
218 gdb_cmd_type(this, cmd); /* get cmd type */
219
220 /* handle completion for all non-gdb commands */
221 if (this->cmd_type == CMD_RESTART) {
222 gdb_setwinput((gdb_handle_T *)this, (char_u *)"cl_restart ");
223 xfree(cmd);
224 this->oob.state &= ~OS_CMD;
225 return;
226 }
227 else if (this->cmd_type == CMD_CREATEVAR)
228 {
229 gdb_setwinput((gdb_handle_T *)this, (char_u *)"createvar ");
230 xfree(cmd);
231 this->oob.state &= ~OS_CMD;
232 return;
233 }
234 goto send;
235 }
236
237 if ((res = gdb_regexec(cmd, PAT_CHG_ANNO, 0, NULL)) != NULL)
238 {
239 EMSG(_("Sorry, cannot change annotation level"));
240 xfree(res);
241 goto empty_cmd;
242 }
243
244 # ifndef FEAT_GDB /* Clewn follows GDB behavior with empty commands */
245 if (*cmd == NUL)
246 {
247 gdb_send_cmd(this, (char_u *)"\n");
248 xfree(cmd);
249 return;
250 }
251 # endif
252
253 /* process the cmd */
254 if ((res = process_cmd(this, cmd)) != NULL)
255 {
256 xfree(cmd);
257 cmd = res;
258
259 # ifdef GDB_LVL3_SUPPORT
260 /* a |+gdb| createvar command is processed later in oob varobj_update() */
261 if (this->mode == GDB_MODE_LVL3 && this->cmd_type == CMD_CREATEVAR)
262 {
263 # ifdef FEAT_GDB
264 if (this->var_buf == NULL)
265 # else
266 if (this->var_buf <= 0)
267 # endif
268 {
269 EMSG(_("Variables buffer does not exist anymore: unable to create variable"));
270 goto empty_cmd;
271 }
272
273 if (
274 # ifdef FEAT_GDB
275 (expression = gdb_regexec(cmd, PAT_CRVAR_FMT, 2, NULL)) != NULL
276 # else
277 (expression = gdb_regexec(cmd, PAT_CRVAR_FMT, 3, NULL)) != NULL
278 # endif
279 && *expression != NUL)
280 {
281 varobj = (varobj_T *)xcalloc(sizeof(varobj_T));
282
283 /* create a new varobj_T element and link it to the list */
284 varobj->state = VS_INIT;
285 varobj->children = FALSE;
286 # ifdef FEAT_GDB
287 varobj->format = gdb_regexec(cmd, PAT_CRVAR_FMT, 1, NULL);
288 # else
289 varobj->format = gdb_regexec(cmd, PAT_CRVAR_FMT, 2, NULL);
290 # endif
291 varobj->expression = expression;
292 varobj->next = this->lvl3.varlist;
293 this->lvl3.varlist = varobj;
294
295 goto empty_cmd;
296 }
297
298 xfree(expression);
299 EMSG(_("Unvalid arguments to \"createvar\" command"));
300 goto empty_cmd;
301 }
302 # endif
303 }
304 else
305 goto empty_cmd;
306
307 /* add a newline to cmd if needed */
308 len = STRLEN(cmd);
309 if (len == 0 || *(cmd + len - 1) != NL)
310 {
311 res = NULL;
312 gdb_cat(&res, cmd);
313 gdb_cat(&res, (char_u *)"\n");
314 xfree(cmd);
315 cmd = res;
316 }
317 send:
318 gdb_send_cmd(this, cmd);
319 xfree(cmd);
320 return;
321 empty_cmd:
322 gdb_send_cmd(this, (char_u *)" \n");
323 xfree(cmd);
324 return;
325 }
326
327 /*
328 * Process a gdb cmd according to its type.
329 * Return an allocated sanitized cmd or NULL if error.
330 */
331 static char_u *
process_cmd(this,cmd)332 process_cmd(this, cmd)
333 gdb_T *this;
334 char_u *cmd; /* user's gdb cmd */
335 {
336 char_u *delete = NULL;
337 char_u *range = NULL;
338 char_u *res;
339 # ifdef FEAT_GDB
340 int i;
341 buf_T *buf = NULL;
342 win_T *oldwin = curwin;
343 # endif
344
345 /* make a copy so we can mess with it */
346 if (cmd == NULL || *cmd == NUL)
347 return NULL;
348 cmd = (char_u *)clewn_strsave((char *)cmd);
349
350 gdb_cmd_type(this, cmd); /* get cmd type */
351
352 # ifdef GDB_LVL2_SUPPORT
353 /* Replace "createvar" command with GDB "display" command */
354 if (this->mode == GDB_MODE_LVL2 && this->cmd_type == CMD_CREATEVAR)
355 {
356 # ifdef FEAT_GDB
357 if ((res = gdb_regexec(cmd, PAT_CREATEVAR, 1, NULL)) != NULL)
358 # else
359 if ((res = gdb_regexec(cmd, PAT_CREATEVAR, 2, NULL)) != NULL)
360 # endif
361 {
362 /* replace */
363 this->cmd_type = CMD_DISPLAY;
364 FREE(cmd);
365 gdb_cat(&cmd, (char_u *)"display ");
366 gdb_cat(&cmd, res);
367 xfree(res);
368
369 if (cmd == NULL)
370 {
371 this->cmd_type = CMD_ANY;
372 return NULL;
373 }
374 }
375 }
376 # endif
377
378 # ifndef FEAT_GDB
379 /* Prevent use of a low height size because of "prompt-for-continue" messages.
380 * The annotations lines printed by GDB are part of the lines count that
381 * is used by GDB for "prompt-for-continue" messages, however we do not
382 * display them. */
383 if ((res = gdb_regexec(cmd, PAT_HEIGHT, 2, NULL)) != NULL)
384 {
385 fprintf(stderr, "Cannot change the screen size\n");
386 xfree(cmd);
387 xfree(res);
388 return NULL;
389 }
390 # endif
391
392 /* Cannot attach to oneself */
393 # ifdef FEAT_GDB
394 if ((res = gdb_regexec(cmd, PAT_PID, 1, NULL)) != NULL)
395 # else
396 if ((res = gdb_regexec(cmd, PAT_PID, 2, NULL)) != NULL)
397 # endif
398 {
399 if (getpid() == atoi((char *)res))
400 {
401 EMSG(_("I refuse to debug myself!"));
402 xfree(cmd);
403 xfree(res);
404 return NULL;
405 }
406 xfree(res);
407 }
408
409 /* no processing for 'define' type cmds */
410 if (this->note == ANO_CMDS || this->note == ANO_OVERLOAD)
411 return cmd;
412
413 switch (this->cmd_type)
414 {
415 # ifdef GDB_LVL2_SUPPORT
416 case CMD_DISPLAY:
417 /* A "display" command without argument is equivalent to the
418 * debuggee being stopped */
419 if ((res = gdb_regexec(cmd, PAT_DISPLAY, 0, NULL)) != NULL)
420 {
421 xfree(res);
422 this->cmd_type = CMD_ANY;
423 # ifdef FEAT_GDB
424 if (this->var_buf != NULL)
425 # else
426 if (this->var_buf > 0)
427 # endif
428 this->lvl2.varlist.state = DSP_STOPPED;
429 }
430 break;
431 # endif
432
433 case CMD_SHELL:
434 EMSG(_("Sorry, cannot spawn a shell"));
435 xfree(cmd);
436 return NULL;
437
438 /* unlite frame on 'detach' */
439 case CMD_DETACH:
440 gdb_fr_unlite(this);
441 break;
442
443 /* clear dirty asm buffers */
444 case CMD_EXECF:
445 # ifdef FEAT_GDB
446 for (i = 0; i < this->pool.max; i++)
447 {
448 if ((curbuf = this->pool.buf[i]) == NULL)
449 continue;
450
451 /* clear the buffer */
452 gdb_clear_asmbuf(this, curbuf);
453
454 /* asm buffer is displayed */
455 if ((curwin = gdb_btowin(curbuf)) != NULL)
456 {
457 check_cursor();
458 buf = curbuf;
459 }
460 curwin = oldwin;
461 }
462 curbuf = curwin->w_buffer;
463 gdb_redraw(buf); /* redraw only if one asm displayed */
464 # else
465 /* unlink all asm buffers */
466 cnb_unlink_asm();
467 # endif
468
469 # ifdef GDB_LVL3_SUPPORT
470 /* get source files list */
471 this->lvl3.get_source_list = TRUE;
472 # endif
473 break;
474
475 case CMD_SYMF:
476 # ifdef GDB_LVL3_SUPPORT
477 /* get source files list */
478 this->lvl3.get_source_list = TRUE;
479 # endif
480 break;
481
482 case CMD_UP:
483 case CMD_UP_SILENT:
484 case CMD_DOWN:
485 case CMD_DOWN_SILENT:
486 case CMD_FRAME:
487 case CMD_SLECT_FRAME:
488 if (this->mode != GDB_MODE_LVL3)
489 {
490 this->pool.hilite = TRUE;
491
492 /* this should not be necessary but sometimes we
493 * don't get the ANO_FRAME_INVALID */
494 this->bp_state |= BPS_FR_INVALID;
495 }
496 break;
497
498 case CMD_DELETE:
499 case CMD_DISABLE:
500 /* keep BPS_FR_INVALID state */
501 this->bp_state &= BPS_FR_INVALID;
502 this->bp_state |= BPS_INVALID;
503 break;
504
505 /* the restart command is mapped to the gdb 'quit' command,
506 * and that will cause gdb to be restarted (the 'quit'
507 * command itself is trapped and
508 * causes a clean termination of clewn and vim) */
509 case CMD_RESTART:
510 xfree(cmd);
511 cmd = (char_u *)clewn_strsave("quit");
512 break;
513
514 /* terminate clewn and vim */
515 case CMD_QUIT:
516 this->state |= GS_QUITTING;
517 break;
518
519 default:
520 break;
521 }
522 xfree(range);
523 xfree(delete);
524 return cmd;
525 }
526
527 /* Send a cmd to gdb */
528 void
gdb_send_cmd(this,cmd)529 gdb_send_cmd(this, cmd)
530 gdb_T *this;
531 char_u *cmd; /* gdb cmd */
532 {
533 int do_free = TRUE; /* TRUE when readline must be freed */
534 int offset = 0;
535 char_u *res;
536 char_u *start;
537 int len;
538 int l;
539
540 if ( ! GDB_STATE(this, GS_UP))
541 return;
542
543 this->intr_sent = FALSE;
544
545 /* make a copy so we can mess with it */
546 if (cmd == NULL || (len = STRLEN(cmd)) == 0 )
547 return;
548 cmd = (char_u *)clewn_strsave((char *)cmd);
549
550 /* paranoia: trim after NL */
551 if ((res = STRCHR(cmd, (int)NL)) != NULL)
552 *(res + 1) = NUL;
553
554 /* answering to a query: any stuff not 'y[es]' is converted to 'no' */
555 if (this->cli_cmd.state == CS_QUERY || this->note == ANO_QUERY)
556 {
557 len = 1;
558 if ((res = gdb_regexec(cmd, PAT_YES, 0, NULL)) != NULL)
559 {
560 *cmd = 'y';
561 xfree(res);
562 }
563 else
564 *cmd = 'n';
565
566 # ifdef FEAT_GDB
567 /* CMD_DIR is acted upon when parsing gdb output */
568 if (this->cmd_type != CMD_DIR)
569 this->cmd_type = CMD_ANY;
570 # endif
571
572 if (this->cli_cmd.state == CS_QUERY) /* no NL when a completion */
573 {
574 this->cli_cmd.state = CS_CHOICE;
575 do_free = FALSE;
576
577 /* a standalone <Tab> */
578 if (this->cli_cmd.readline == NULL
579 && this->cli_cmd.gdb != NULL && *(this->cli_cmd.gdb) == NUL)
580 this->oob.state &= ~OS_CMD;
581 }
582 else
583 {
584 this->cli_cmd.state = CS_START;
585 *(cmd + 1) = NL;
586 len = 2; /* enough room since cmd length not zero */
587 }
588 goto write_answer;
589 }
590
591 /* an interrupt */
592 if (STRCHR(cmd, KEY_INTERUPT) != NULL)
593 {
594 this->intr_sent = TRUE;
595 this->cli_cmd.state = CS_START;
596 goto write_answer;
597 }
598
599 /* a cmd following a completion response by gdb */
600 if (this->cli_cmd.state == CS_DONE && this->cli_cmd.readline != NULL)
601 {
602 /* readline matches start of cmd: send 'user cmd - readline' */
603 if (STRSTR(cmd, this->cli_cmd.readline) == cmd)
604 {
605 offset = STRLEN(this->cli_cmd.readline);
606 len -= offset;
607 do_free = FALSE;
608 }
609 /* no match */
610 else
611 {
612 /* send KEY_KILL to erase gdb's readline */
613 gdb_buf[0] = KEY_KILL;
614 write(this->fd, gdb_buf, 1);
615
616 /* discard gdb answer:
617 * '\r' plus the termcap entry 'ce' (clear to end of line) */
618 l = gdb_read(this, (char_u *)gdb_buf, MAX_BUFFSIZE, 1000);
619
620 /* do what the discarded stuff above was meant to do:
621 * replace last line by getting rid of readline */
622 /* find the rightmost match */
623 res = NULL;
624 for (start = this->line; *start != NUL; start++)
625 if ((start = STRSTR(start, this->cli_cmd.readline)) != NULL)
626 res = start;
627 else
628 break;
629
630 if (res != NULL)
631 {
632 *res = NUL;
633 gdb_write_buf(this, this->line, FALSE);
634 }
635 FREE(this->cli_cmd.echoed);
636 }
637 }
638
639 this->cli_cmd.state = CS_START;
640
641 /* a completion request */
642 if (*(cmd + offset + len - 1) == TAB)
643 {
644 this->cli_cmd.state = CS_PENDING;
645
646 xfree(this->cli_cmd.gdb);
647 this->cli_cmd.gdb = (char_u *)clewn_strsave((char *)(cmd + offset));
648 *(this->cli_cmd.gdb + len - 1) = NUL; /* remove <Tab> */
649 }
650 write_answer:
651 if (do_free)
652 FREE(this->cli_cmd.readline);
653 write(this->fd, (char *)cmd + offset, len);
654 xfree(cmd);
655 return;
656 }
657
658 # ifdef FEAT_GDB
659 # if defined(MACOS_X) || defined(MACOS_X_UNIX)
660 /* Strip terminating carriage return from a line */
661 static void
strip_cr(line)662 strip_cr(line)
663 char_u *line;
664 {
665 int len = STRLEN(line);
666
667 if (len != 0 && line[len - 1] == '\r')
668 line[len - 1] = NUL;
669 }
670 # endif
671 # endif
672
673 # ifndef FEAT_GDB
674 /* Handle "prompt-for-continue" annotations.
675 * This is not needed by VimGDB as the screen height is very large. */
676 # define MANAGE_PRMPT_FORMORE
677
678 /* The fix for writing through readline the concatenation of multiple
679 * lines output by gdb, is only correctly implemented for clewn */
680 # define FIX_CONCATENATION_WRITE
681 # endif
682 /*
683 * Parse gdb output for annotation and completion. Update gdb console.
684 * Return TRUE when the user must be prompted by the input-line window.
685 */
686 int
gdb_parse_output_cli(this)687 gdb_parse_output_cli(this)
688 gdb_T *this;
689 {
690 # ifdef FIX_CONCATENATION_WRITE
691 static int pending_write = FALSE; /* TRUE, this->line content has not been written yet */
692 # endif
693 struct obstack obs; /* use an obstack for temporary allocated memory */
694 char_u *start;
695 char_u *end;
696 char_u *line;
697 char_u *res;
698 int rc;
699 int len;
700 # ifdef MANAGE_PRMPT_FORMORE
701 int do_newline;
702 # endif
703
704 /* read gdb data */
705 if (this == NULL || ! GDB_STATE(this, GS_UP)
706 || gdb_read(this, (char_u *)gdb_buf, MAX_BUFFSIZE, 0) <= 0)
707 return FALSE;
708
709 (void)obstack_init(&obs);
710
711 /* Process line after line */
712 for (start = end = (char_u *)gdb_buf; end != NULL; start = end)
713 {
714 /* Get next line */
715 if ((end = STRCHR(start, NL)) != NULL)
716 *end++ = NUL;
717 else if (*start == NUL) /* nothing left to read */
718 break;
719
720 /* concatenate with incomplete annotation */
721 if (this->annotation != NULL)
722 {
723 obstack_strcat(&obs, this->annotation);
724 obstack_strcat0(&obs, start);
725 line = (char_u *)obstack_finish(&obs);
726 }
727 else
728 line = obstack_strsave(&obs, start);
729
730 # ifdef FEAT_GDB
731 # if defined(MACOS_X) || defined(MACOS_X_UNIX)
732 strip_cr(line);
733 # endif
734 # endif
735
736 /* With GDB 6.0, completion giving as a result a long list of items causes
737 * a "--More--" prompt to be issued after what GDB (or readline) considers
738 * the height of the terminal (unfortunately not using the GDB height
739 * settings). In case we could not size the terminal to a very big height
740 * with an ioctl call in exec_gdb(), we must answer to the prompt. */
741 if (this->height == 0 /* height not set */
742 && this->cli_cmd.state == CS_CHOICE /* a completion list */
743 && end == NULL
744 && STRCMP(line, "--More--") == 0) /* standalone prompt */
745 {
746 write(this->fd, " ", 1); /* prompt for more */
747 this->annoted = FALSE;
748 break;
749 }
750
751 # ifdef FEAT_GDB /* Clewn does not use hiliting */
752 /* some fuzzy gdb annotation corner: rewrite '(gdb) Quit' so that
753 * it gets highlited (must be done before the newline stuff) */
754 if (parse_note(this, line) != NULL && this->note == ANO_QUIT)
755 gdb_write_buf(this, this->line, FALSE);
756 # endif
757
758 /* two consecutive NL: start a new line except when this annotation
759 * just follows another annotation
760 * IS_ANNOTATION() does not handle a standalone '\032' */
761 if (this->newline && (*line != '\032' || !this->annoted))
762 {
763 # ifdef MANAGE_PRMPT_FORMORE
764 do_newline = TRUE;
765
766 /* do not start a new line when parsing annotations and
767 * . the next chunk is a "pre-prompt-for-continue" and
768 * the previous chunk was an annotation
769 * . or this is a "pre-prompt-for-continue" annotation */
770 if (this->mode == GDB_MODE_LVL2
771 && ! IS_OOBACTIVE(this) && (this->state & GS_ANO))
772 {
773 if (end != NULL && get_note(this, end) == ANO_PREPMT_FORMORE
774 && this->prev_note != ANO_NONE)
775 do_newline = FALSE;
776 if (line != NULL && get_note(this, line) == ANO_PREPMT_FORMORE)
777 do_newline = FALSE;
778 }
779
780 if (do_newline)
781 # endif
782 {
783 if (this->line == NULL && *line != '\032')
784 {
785 if (IS_OOBACTIVE(this))
786 gdb_oob_receive(this, (char_u *)"", &obs);
787 else
788 gdb_write_buf(this, (char_u *)"", TRUE);
789 }
790
791 # ifdef FIX_CONCATENATION_WRITE
792 if (pending_write)
793 gdb_write_buf(this, this->line, TRUE);
794 # endif
795
796 FREE(this->line); /* start a new line */
797 this->note = ANO_NONE;
798 }
799 }
800 this->newline = FALSE;
801
802 /* Parse for annotations */
803 /* we cannot parse "\n\032\032annotation\n" directly
804 * as any stuff may be split across two buff read;
805 * must concatenate line when interleaved with annotations */
806 if (*line == NUL)
807 {
808 /* ignore echoed NL after ANO_PMT_FORMORE msg */
809 if (this->note != ANO_PMT_FORMORE)
810 this->newline = TRUE;
811
812 # ifdef MANAGE_PRMPT_FORMORE
813 /* start a new line */
814 if (this->mode == GDB_MODE_LVL2 && this->prev_note == ANO_POSTPMT_FORMORE)
815 {
816 FREE(this->line);
817 this->note = ANO_NONE;
818 }
819 # endif
820 }
821 /* a complete annotation */
822 else if (IS_ANNOTATION(line) && end != NULL)
823 {
824 /* remember last annotation type */
825 if (this->note != ANO_PREPMT_FORMORE
826 && this->note != ANO_PMT_FORMORE
827 && this->note != ANO_POSTPMT_FORMORE)
828 this->valid_note = this->note;
829
830 res = parse_note(this, line); /* assert != NULL */
831
832 if ((res = process_annotation(this, res, &obs)) != NULL)
833 {
834 gdb_setwinput((gdb_handle_T *)this, res);
835 xfree(res);
836
837 /* fake an interrupt: will empty stuff and typeahead
838 * buffers aborting insert mode, pending mappings
839 * and operations */
840 got_int = TRUE;
841 }
842
843 FREE(this->annotation);
844 this->annoted = TRUE;
845
846 # ifdef GDB_LVL2_SUPPORT
847 /* ANO_DISP_END has no content and must be trapped here */
848 if (
849 # ifdef FEAT_GDB
850 this->mode == GDB_MODE_LVL2 && this->var_buf != NULL
851 # else
852 this->mode == GDB_MODE_LVL2 && this->var_buf > 0
853 # endif
854 && this->note == ANO_DISP_END)
855 {
856 gdb_process_display(this, (char_u *)"", &obs);
857 }
858 # endif
859
860 # ifdef MANAGE_PRMPT_FORMORE
861 /* start a new line when end of annotation list or table */
862 if (this->mode == GDB_MODE_LVL2
863 && this->prev_note == ANO_POSTPMT_FORMORE
864 && (this->note == ANO_BP_TABLE
865 || this->note == ANO_BP_RECORD
866 || this->note == ANO_BP_END
867 || this->note == ANO_FRAME_END
868 || this->note == ANO_DISP_END))
869 {
870 FREE(this->line); /* start a new line */
871 this->note = ANO_NONE;
872 }
873 # endif
874
875 /* store current annotation type */
876 this->prev_note = this->note;
877
878 /* restore annotation type */
879 if (this->note == ANO_POSTPMT_FORMORE)
880 this->note = this->valid_note;
881 }
882 /* a partial annotation */
883 else if (*line == '\032'
884 && (*(line + 1) == NUL || *(line + 1) == '\032')
885 && end == NULL)
886 {
887 xfree(this->annotation);
888 this->annotation = (char_u *)clewn_strsave((char *)line);
889 break;
890 }
891 else
892 {
893 # ifdef MANAGE_PRMPT_FORMORE
894 /* The breakpoint table:
895 * start a new line when line starts with <TAB>.*/
896 if (this->mode == GDB_MODE_LVL2
897 && this->prev_note == ANO_POSTPMT_FORMORE
898 && line != NULL && *line == TAB)
899 {
900 FREE(this->line); /* start a new line */
901 this->note = ANO_NONE;
902 }
903 # endif
904
905 if (this->note == ANO_PREPMT_FORMORE)
906 {
907 # ifdef MANAGE_PRMPT_FORMORE
908 if (! IS_OOBACTIVE(this))
909 {
910 /* Starting with GDB 6.0, GDB sends an ANO_PREPMT_FORMORE
911 * whenever ^C have been typed more that gdb_screen_height/2. */
912 if (this->state & GS_ANO || this->intr_sent)
913 {
914 write(this->fd, "\n", 1); /* prompt for more */
915 }
916 else
917 {
918 this->oob.state &= ~OS_CMD; /* enable next command */
919 xfree(this->prompt);
920 if (line != NULL)
921 this->prompt = (char_u *)clewn_strsave((char *)line);
922 else
923 this->prompt = (char_u *)clewn_strsave(
924 "---type <return> to continue, or q <return> to quit---");
925 }
926 this->intr_sent = FALSE;
927 }
928 # endif
929 line = NULL; /* remove ANO_PMT_FORMORE msg */
930 }
931
932 # ifdef GDB_LVL2_SUPPORT
933 /* handle a display annotation content
934 * take care of nested structures and arrays in value content */
935 # ifdef FEAT_GDB
936 if (this->mode == GDB_MODE_LVL2 && this->var_buf != NULL)
937 # else
938 if (this->mode == GDB_MODE_LVL2 && this->var_buf > 0)
939 # endif
940 {
941 if ((this->note >= ANO_DISP_BEG && this->note <= ANO_DISP_END)
942 || (this->lvl2.doing_value && this->note >= ANO_FIELD_BEG
943 && this->note <= ANO_FIELD_END)
944 || (this->lvl2.doing_value && this->note >= ANO_ARRAY_BEG
945 && this->note <= ANO_ARRAY_END))
946 {
947 gdb_process_display(this, line, &obs);
948 line = NULL;
949 }
950 }
951 # endif
952
953 if (IS_OOBACTIVE(this))
954 {
955 gdb_oob_receive(this, line, &obs);
956 }
957 else
958 {
959 if (this->note == ANO_PROMPT || this->note == ANO_CMDS)
960 gdb_cat(&(this->cli_cmd.echoed), line);
961
962 /* update line cnt before doing cpltn */
963 if (this->line == NULL || !this->annoted)
964 this->cli_cmd.cnt++;
965
966 /* Parse for completion */
967 if ((res = process_completion( &(this->cli_cmd), line, &obs)) != NULL)
968 {
969 gdb_setwinput((gdb_handle_T *)this, res);
970 xfree(res);
971 got_int = TRUE;
972 }
973
974 if (line != NULL && (len = STRLEN(line)) != 0
975 && *(line + len - 1) == BELL)
976 *(line + len - 1) = NUL;
977
978 /* concatenate after an annotation and replace, otherwise add */
979 if (this->line != NULL && this->annoted)
980 {
981 if (this->note == ANO_ERROR_BEG && STRCMP(line, "Quit") == 0)
982 this->syntax = TRUE;
983
984 obstack_strcat(&obs, this->line);
985 obstack_strcat0(&obs, line);
986 line = (char_u *)obstack_finish(&obs);
987
988 # ifndef FEAT_GDB /* do not write "(gdb) Quit" with Clewn (already done) */
989 if (this->note != ANO_ERROR_BEG)
990 # endif
991 {
992 # ifdef FIX_CONCATENATION_WRITE
993 /* write a complete line */
994 if (end != NULL)
995 {
996 if (pending_write)
997 gdb_write_buf(this, line, TRUE);
998 else
999 gdb_write_buf(this, line, FALSE);
1000 }
1001 # else
1002 gdb_write_buf(this, line, FALSE);
1003 # endif
1004 }
1005
1006 }
1007 else
1008 {
1009 # ifdef FEAT_GDB /* no need to map T_CE when running Clewn */
1010 /* a completion list */
1011 if (this->height == 0 /* height not set */
1012 && this->cli_cmd.state == CS_CHOICE)
1013 {
1014 char_u *ptr;
1015
1016 /* discard "^\rT_CE\r" which is sent by readline
1017 * after answering to a prompt in a completion list
1018 * (not needed on systems where TIOCSWINSZ ioctls are
1019 * available) */
1020 if (STRSTR(line, T_CE) == line + 1
1021 && STRLEN(line) >= STRLEN(T_CE) + 2)
1022 {
1023 ptr = line + STRLEN(T_CE) + 2;
1024 line = obstack_strsave(&obs, ptr);
1025 }
1026 }
1027 gdb_write_buf(this, line, TRUE);
1028 # else
1029 /* do not write the query prompt */
1030 if (this->cli_cmd.state == CS_QUERY)
1031 gdb_write_buf(this, (char_u *)"", TRUE);
1032 else
1033 {
1034 # ifdef FIX_CONCATENATION_WRITE
1035 /* write a complete line */
1036 if (end != NULL)
1037 {
1038 gdb_write_buf(this, line, TRUE);
1039 }
1040 # else
1041 gdb_write_buf(this, line, TRUE);
1042 # endif
1043 }
1044 # endif
1045 }
1046
1047 xfree(this->line);
1048 this->line = (line != NULL ? (char_u *)clewn_strsave((char *)line) : NULL);
1049 }
1050
1051 # ifdef FIX_CONCATENATION_WRITE
1052 pending_write = FALSE;
1053 if (end == NULL) /* incomplete line */
1054 {
1055 pending_write = TRUE;
1056 this->annoted = TRUE; /* force concatenation on next read */
1057 break;
1058 }
1059 # else
1060 if (end == NULL) /* incomplete line */
1061 {
1062 this->annoted = TRUE; /* force concatenation on next read */
1063 break;
1064 }
1065 # endif
1066 this->annoted = FALSE;
1067 this->note = ANO_NONE;
1068 }
1069 } /* for (...) */
1070
1071 obstack_free(&obs, NULL);
1072
1073 if (IS_OOBACTIVE(this))
1074 return FALSE;
1075
1076 # ifdef FEAT_GDB
1077 /* redraw gdb console window when displayed */
1078 gdb_redraw(this->buf);
1079 # endif
1080
1081 /* Wait till we get the prompt to send the first cmd */
1082 if (this->firstcmd != NULL && this->note == ANO_PROMPT)
1083 {
1084 gdb_docmd((gdb_handle_T *)this, this->firstcmd);
1085 FREE(this->firstcmd);
1086 }
1087
1088 if ((rc = gdb_iswinput((gdb_handle_T *)this)) == TRUE)
1089 this->oob.state &= ~OS_CMD;
1090 return rc;
1091 }
1092
1093 /*
1094 * Process an annotation.
1095 * Return cmd to prompt the user with or NULL if none.
1096 */
1097 static char_u *
process_annotation(this,str,obs)1098 process_annotation(this, str, obs)
1099 gdb_T *this;
1100 char_u *str; /* annotation's content */
1101 struct obstack *obs;
1102 {
1103 int s_a = (this->state & GS_ALLOWED);
1104 char_u *file = NULL;
1105 char_u *line = NULL;
1106 linenr_T linenumber;
1107 char_u *cpn;
1108 int bp_number;
1109 bpinfo_T *r;
1110
1111 this->syntax = FALSE;
1112 this->parser = PS_ANY;
1113
1114 switch (this->note)
1115 {
1116 /* Output end: run directory function */
1117 case ANO_PREPROMPT:
1118 this->syntax = TRUE;
1119 this->parser = PS_PREPROMPT;
1120 this->cmd_type = CMD_ANY;
1121 this->state &= ~GS_ANO;
1122 break;
1123
1124 /* Send out of band cmd */
1125 case ANO_PROMPT:
1126 this->syntax = TRUE;
1127 this->parser = PS_PROMPT;
1128 this->cli_cmd.cnt = 1;
1129 FREE(this->cli_cmd.echoed);
1130 # ifndef FEAT_GDB /* store the prompt */
1131 if (! IS_OOBACTIVE(this) || (this->oob.state & OS_INTR))
1132 {
1133 xfree(this->prompt);
1134 if (this->line != NULL)
1135 this->prompt = (char_u *)clewn_strsave((char *)this->line);
1136 else
1137 this->prompt = (char_u *)clewn_strsave("(gdb) ");
1138 }
1139 # endif
1140 if (this->cli_cmd.state == CS_START) {
1141 gdb_oob_send(this, obs);
1142
1143 /* reset the standard oobfunc table after invocation
1144 * of a one function oobfunc array */
1145 this->oobfunc = this->std_oobfunc;
1146 }
1147 break;
1148
1149 case ANO_CMDS:
1150 this->syntax = TRUE;
1151 this->cli_cmd.cnt = 1;
1152 this->oob.state &= ~OS_CMD;
1153 FREE(this->cli_cmd.echoed);
1154 # ifndef FEAT_GDB /* store the prompt */
1155 if (! IS_OOBACTIVE(this) || (this->oob.state & OS_INTR))
1156 {
1157 xfree(this->prompt);
1158 if (this->line != NULL)
1159 this->prompt = (char_u *)clewn_strsave((char *)this->line);
1160 else
1161 this->prompt = (char_u *)clewn_strsave("> ");
1162 }
1163 # endif
1164
1165 /* should be in process_completion, but bug in gdb
1166 * annotations where 'pre-commands' is missing in completions */
1167 if (this->cli_cmd.state == CS_CHOICE
1168 && (cpn = eol_choices(&(this->cli_cmd), obs)) != NULL)
1169 return cpn;
1170
1171 /* a lone <Tab> does not prompt the user except in define mode */
1172 if ((this->cli_cmd.state != CS_PENDING
1173 && this->cli_cmd.state != CS_CHOICE)
1174 || (this->cli_cmd.readline == NULL && this->cli_cmd.gdb != NULL
1175 && *(this->cli_cmd.gdb) == NUL))
1176 return (char_u *)clewn_strsave("");
1177 break;
1178
1179 case ANO_OVERLOAD:
1180 case ANO_QUERY:
1181 this->oob.state &= ~OS_CMD;
1182 # ifndef FEAT_GDB /* store the prompt */
1183 if (! IS_OOBACTIVE(this) || (this->oob.state & OS_INTR))
1184 {
1185 xfree(this->prompt);
1186 if (this->line != NULL)
1187 this->prompt = (char_u *)clewn_strsave((char *)this->line);
1188 else
1189 this->prompt = (char_u *)clewn_strsave("> ");
1190 }
1191 # endif
1192 return (char_u *)clewn_strsave("");
1193
1194 case ANO_PMT_FORMORE:
1195 # ifndef FEAT_GDB /* handle ANO_PMT_FORMORE when IS_OOBACTIVE */
1196 if (IS_OOBACTIVE(this))
1197 # endif
1198 {
1199 if (this->oob.state & OS_INTR)
1200 {
1201 clewn_beep();
1202 gdb_send_cmd(this, (char_u *)"q\n"); /* abort */
1203 }
1204 else
1205 gdb_send_cmd(this, (char_u *)"\n"); /* get more lines */
1206 }
1207 break;
1208
1209 case ANO_QUIT:
1210 this->syntax = TRUE;
1211 this->oob.state |= OS_QUIT;
1212 break;
1213
1214 case ANO_ERROR_BEG:
1215 this->pool.hilite = FALSE;
1216 # ifdef GDB_LVL2_SUPPORT
1217 /* a display expression parse error */
1218 this->lvl2.doing_value = FALSE;
1219 FREE(this->lvl2.dentry.num);
1220 FREE(this->lvl2.dentry.expression);
1221 FREE(this->lvl2.dentry.value);
1222 # endif
1223 # ifdef GDB_LVL3_SUPPORT
1224 if (this->lvl3.varitem != NULL)
1225 this->lvl3.varitem->state |= VS_ERROR;
1226 # endif
1227 break;
1228
1229 case ANO_STARTING:
1230 this->frame_curlvl = -1;
1231 this->frame_lnum = (linenr_T) -1;
1232 FREE(this->frame_fname);
1233
1234 FREE(this->frame_pc);
1235 this->state &= ~GS_STOPPED;
1236 gdb_status(this, (char_u *)"running...", obs);
1237
1238 if (this->mode == GDB_MODE_LVL3)
1239 {
1240 this->pool.hilite = FALSE;
1241 if (p_asm != 0 && this->cmd_type == CMD_STEPI) /* asm frame highlite: when stepi nexti */
1242 this->pool.hilite = TRUE;
1243 }
1244 else
1245 {
1246 this->pool.hilite = TRUE;
1247 }
1248 case ANO_FRAME_INVALID:
1249 gdb_fr_unlite(this);
1250 this->bp_state |= BPS_FR_INVALID;
1251 break;
1252
1253 case ANO_BP_INVALID:
1254 /* keep BPS_FR_INVALID state */
1255 this->bp_state &= BPS_FR_INVALID;
1256 this->bp_state |= BPS_INVALID;
1257
1258 /* note the fact that the user is setting a
1259 * breakpoint */
1260 if (p_asm != 0 && this->cmd_type == CMD_BREAK)
1261 this->bp_state |= BPS_BP_SET;
1262 break;
1263
1264 case ANO_STOPPED:
1265 this->state |= GS_STOPPED;
1266 gdb_status(this, (char_u *)"stopped", obs);
1267 # ifdef GDB_LVL2_SUPPORT
1268 # ifdef FEAT_GDB
1269 if (this->var_buf != NULL)
1270 # else
1271 if (this->var_buf > 0)
1272 # endif
1273 this->lvl2.varlist.state = DSP_STOPPED;
1274 # endif
1275 break;
1276
1277 case ANO_EXITED:
1278 case ANO_SIGNALLED:
1279 FREE(this->frame_pc);
1280
1281 this->state |= GS_STOPPED;
1282 gdb_status(this, (char_u *)"exited", obs);
1283
1284 # ifdef FEAT_GDB
1285 /* remove phantom highlite */
1286 gdb_unlite(PHANTOM_SIGN);
1287 # endif
1288 break;
1289
1290 /* Breakpoint hit */
1291 case ANO_BREAKPOINT:
1292 /* Look for this breakpoint in bpinfo list */
1293 if (str != NULL && (bp_number = atoi((char *)str)) > 0)
1294 {
1295 for (r = this->bpinfo; r != NULL; r = r->next)
1296 {
1297 if (r->id == bp_number)
1298 {
1299 /* Set this->cont TRUE if this breakpoint's 'commands'
1300 * includes a 'continue' as last statement */
1301 if (r->cont)
1302 this->cont = TRUE;
1303
1304 # ifdef BP_INVALID_ANO_MISSING
1305 /* Trigger get_bp(): the breakpoint we hit is
1306 * 'enable once' */
1307 if (r->enabled && ! r->disposition)
1308 {
1309 /* keep BPS_FR_INVALID state */
1310 this->bp_state &= BPS_FR_INVALID;
1311 this->bp_state |= BPS_INVALID | BPS_BP_HIT;
1312 }
1313 # endif
1314 break;
1315 }
1316 }
1317
1318 /* Not found in the list. An asm buffer holding this bp
1319 * can possibly be disassembled next by oob get_asm().
1320 * Trigger oob get_bp() */
1321 if (r == NULL && p_asm != 0)
1322 {
1323 /* keep BPS_FR_INVALID state */
1324 this->bp_state &= BPS_FR_INVALID;
1325 this->bp_state |= BPS_INVALID | BPS_BP_HIT;
1326 }
1327 }
1328 break;
1329
1330 # ifdef GDB_LVL2_SUPPORT
1331 case ANO_SOURCE:
1332 /* gdb stats the file when doing ANO_SOURCE, so we can't rely on
1333 * that annotation for remote debugging with clewn when the source
1334 * files are on the host and not on the target
1335 * => use ANO_BREAKPOINT instead in level 3
1336 */
1337
1338 if (! IS_OOBACTIVE(this) && this->mode == GDB_MODE_LVL2)
1339 {
1340 /* Uncomment next line to print source text in gdb buffer */
1341 /* gdb_write_buf(this, str, TRUE); */
1342
1343 # ifdef FEAT_GDB
1344 gdb_popup_console(this);
1345 # endif
1346
1347 this->pool.hilite = FALSE;
1348
1349 /* asm frame highlite: when stepi nexti */
1350 if (p_asm != 0 && this->cmd_type == CMD_STEPI)
1351 this->pool.hilite = TRUE;
1352 else
1353 {
1354 /* prevent recursive calls to parse_output() since breakpoint
1355 * or frame highlighting may cause Vim to query the user when
1356 * changes have been made in the previous buffer */
1357 this->state &= ~GS_ALLOWED;
1358
1359 if ((line = gdb_regexec(str, PAT_SOURCE, 2, obs)) != NULL)
1360 {
1361 file = gdb_regexec(str, PAT_SOURCE, 1, obs);
1362 linenumber = atoi((char *)line);
1363 gdb_fr_set(this, file, &linenumber, obs);
1364 }
1365
1366 this->state &= ~GS_ALLOWED;
1367 if (s_a)
1368 this->state |= GS_ALLOWED;
1369 }
1370 }
1371 break;
1372
1373 case ANO_FRAME_BEGIN:
1374 case ANO_BP_HEADER:
1375 case ANO_DISP_BEG:
1376 this->state |= GS_ANO;
1377 break;
1378
1379 case ANO_FRAME_END:
1380 case ANO_DISP_END:
1381 break;
1382
1383 /* Get the source for this frame */
1384 case ANO_BP_RECORD:
1385 this->bp_state |= BPS_RECORD;
1386 this->bp_state |= BPS_START;
1387 break;
1388
1389 case ANO_BP_FIELD0:
1390 case ANO_BP_FIELD1:
1391 case ANO_BP_FIELD2:
1392 case ANO_BP_FIELD3:
1393 case ANO_BP_FIELD4:
1394 case ANO_BP_FIELD5:
1395 case ANO_BP_FIELD6:
1396 case ANO_BP_FIELD7:
1397 case ANO_BP_FIELD8:
1398 case ANO_BP_FIELD9:
1399 this->bp_state = SET_RECORD_IDX(this->bp_state,
1400 (this->note - ANO_BP_FIELD0) + BI_NUM);
1401 break;
1402
1403 case ANO_BP_END:
1404 /* Initialize state but do not forget some of them.
1405 * ANO_BP_END can be the one we get when fetching the
1406 * table with oob function get_lastbp(): get_bp() still
1407 * needs those states */
1408 this->bp_state &= (BPS_INVALID | BPS_BP_HIT | BPS_FR_INVALID);
1409 break;
1410 # endif
1411 }
1412 return NULL;
1413 }
1414
1415 /*
1416 * Parse gdb output for completion.
1417 * Return cmd to prompt the user with or NULL if none.
1418 */
1419 static char_u *
process_completion(cmd,line,obs)1420 process_completion(cmd, line, obs)
1421 cli_cmd_T *cmd;
1422 char_u *line; /* line to parse */
1423 struct obstack *obs;
1424 {
1425 char_u *res;
1426 char_u *start;
1427 int len;
1428
1429 if (line == NULL || *line == NUL)
1430 return NULL;
1431
1432 switch (cmd->state)
1433 {
1434 case CS_PENDING:
1435 /* A completion query */
1436 if (cmd->cnt == 2 && gdb_regexec(line, PAT_QUERY, 0, obs) != NULL)
1437 {
1438 cmd->state = CS_QUERY;
1439 return (char_u *)clewn_strsave("");
1440 }
1441
1442 /* A positive completion */
1443 if (cmd->cnt == 1 && cmd->echoed != NULL
1444 && (len = (cmd->gdb != NULL ? STRLEN(cmd->gdb) : 0)) > 0)
1445 {
1446 /* find the rightmost match */
1447 res = NULL;
1448 for (start = cmd->echoed; *start != NUL; start++)
1449 if ((start = STRSTR(start, cmd->gdb)) != NULL)
1450 res = start;
1451 else
1452 break;
1453
1454 /* strictly greater and not followed by NL */
1455 if (res != NULL && *(res + len) != NL
1456 && cmd->echoed + STRLEN(cmd->echoed) > res + len)
1457 {
1458 if (*(res + len) == BELL)
1459 {
1460 clewn_beep();
1461 *(res + len) = NUL;
1462 }
1463 xfree(cmd->readline);
1464 cmd->readline = (char_u *)clewn_strsave((char *)cmd->echoed);
1465 cmd->state = CS_DONE;
1466 return (char_u *)clewn_strsave((char *)cmd->readline);
1467 }
1468 }
1469
1470 /* A BELL: first character */
1471 if (cmd->cnt == 1 && *line == BELL)
1472 {
1473 *line = NUL;
1474 clewn_beep();
1475 cmd->state = CS_DONE;
1476 return (cmd->readline != NULL ?
1477 (char_u *)clewn_strsave((char *)cmd->readline) : NULL);
1478 }
1479
1480 if (cmd->cnt > 1)
1481 cmd->state = CS_CHOICE;
1482 break;
1483
1484 case CS_CHOICE:
1485 /* The end of a list of completion choices */
1486 if (cmd->cnt == 1 && (res = eol_choices(cmd, obs)) != NULL)
1487 return res;
1488 break;
1489 }
1490 return NULL;
1491 }
1492
1493 /*
1494 * The end of a list of completion choices.
1495 * Return cmd to prompt the user with.
1496 */
1497 static char_u *
eol_choices(cmd,obs)1498 eol_choices(cmd, obs)
1499 cli_cmd_T *cmd;
1500 struct obstack *obs;
1501 {
1502 char_u *new;
1503
1504 obstack_strcat(obs, cmd->readline);
1505 obstack_strcat0(obs, cmd->gdb);
1506 new = (char_u *)obstack_finish(obs);
1507
1508 /* a match with the new readline */
1509 if (cmd->echoed != NULL && STRSTR(cmd->echoed, new) == cmd->echoed)
1510 {
1511 xfree(cmd->readline);
1512 cmd->readline = (char_u *)clewn_strsave((char *)cmd->echoed);
1513 cmd->state = CS_DONE;
1514 return (char_u *)clewn_strsave((char *)cmd->echoed);
1515 }
1516 return NULL;
1517 }
1518
1519 # ifdef GDB_LVL3_SUPPORT
1520 /* Initialize the gdb_T structure lvl3 component that lvl3 is responsible for */
1521 static void
clear_gdb_T(this)1522 clear_gdb_T(this)
1523 gdb_T *this;
1524 {
1525 varobj_T *item, *next;
1526
1527 if (this != NULL)
1528 {
1529 FREE(this->lvl3.result);
1530
1531 this->lvl3.get_source_list = TRUE;
1532 FREE(this->lvl3.source_cur);
1533 FREE(this->lvl3.source_list);
1534
1535 for (item = this->lvl3.varlist; item != NULL; item = next)
1536 {
1537 next = item->next;
1538 xfree(item->name);
1539 xfree(item->format);
1540 xfree(item->expression);
1541 xfree(item);
1542 }
1543 this->lvl3.varlist = NULL;
1544 this->lvl3.varitem = NULL;
1545 }
1546 }
1547
1548 /* Initialize lvl3 function pointers */
1549 void
gdb_lvl3_init(this)1550 gdb_lvl3_init(this)
1551 gdb_T *this;
1552 {
1553 this->mode = GDB_MODE_LVL3;
1554 this->oobfunc = oobfunc;
1555 this->std_oobfunc = oobfunc;
1556 this->parse_output = gdb_parse_output_cli;
1557 this->gdb_docmd = gdb_docmd_cli;
1558 this->var_delete = NULL;
1559 this->clear_gdb_T = clear_gdb_T;
1560 }
1561 # endif /* GDB_LVL3_SUPPORT */
1562
1563 # ifdef FEAT_GDB
1564 # define SG_INTRO_2 "Vim |+gdb| level 2 mode\n\n"
1565 # define SG_INTRO_3 "Vim |+gdb| level 3 mode\n\n"
1566 # else
1567 # define SG_INTRO_2 "... \
1568 \n... Clewn running GDB in level 2 mode\n...\n"
1569 # define SG_INTRO_3 "... \
1570 \n... Clewn %s running GDB in level 3 mode\n...\n"
1571 # endif
1572 # define SG_INTERP "server interpreter-exec mi -gdb-version\n"
1573 # define SG_LVL_2 "server set annotate 2\n"
1574 # define SG_LVL_3 "server set annotate 3\n"
1575 # define SG_HEIGHT "server set height "
1576 # define SG_WIDTH "server set width 0\n "
1577 # define SG_EDITING "server set editing on\n"
1578 # define SG_VERSION "server show version\n"
1579
1580 /* SG_TIMEOUT must be quite big as we may have Clewn, Vim and GDB all
1581 * starting at the same time. Unless things go pretty bad in the parsing, we
1582 * always find the needle, so the user never wait SG_TIMEOUT. */
1583 # define SG_TIMEOUT 120000 /* msecs for when the needle cannot be found */
1584 /*
1585 * Initialize gdb CLI (command line interface)
1586 * return OK when sucess, FAIL otherwise
1587 */
1588 int
gdb_setup_cli(this)1589 gdb_setup_cli(this)
1590 gdb_T *this;
1591 {
1592 char *err = NULL;
1593 int needle = FALSE; /* defines when we can start writing to gdb console */
1594 int gdb_cnt = 0; /* count of received "(gdb)" prompts */
1595 int lvl3_mode = FALSE; /* level */
1596 char_u *buff = (char_u *)gdb_buf;/* can't add an int to the reference to an array */
1597 char * tty_name = NULL;
1598 # ifndef FEAT_GDB
1599 char tmp[128];
1600 # endif
1601 char_u *last;
1602 char_u *ptr;
1603 char_u *lpp_lines;
1604 char_u *line;
1605 int len;
1606
1607 this->note = ANO_NONE;
1608
1609 /* Does this GDB process supports "interpreter-exec" command ?
1610 * if yes we will use level 3 mode, otherwise level 2 mode */
1611 write(this->fd, SG_INTERP, strlen(SG_INTERP));
1612
1613 /* discard gdb output till we find the needle SG_VERSION
1614 * MAX_BUFFSIZE must be greater than max gdb line length */
1615 for (last = (char_u *)gdb_buf; buff + MAX_BUFFSIZE - last > 1; )
1616 {
1617 if ((len = gdb_read(this, last,
1618 buff + MAX_BUFFSIZE - last, SG_TIMEOUT)) < 0)
1619 {
1620 err = "Unable to read from GDB pseudo tty";
1621 goto fail;
1622 }
1623 else if (len == 0) /* needle not found */
1624 break;
1625
1626 last += len;
1627 ptr = (char_u *)gdb_buf;
1628
1629 /* First step: determine which level, process line by line */
1630 do
1631 {
1632 if (gdb_cnt >= 2)
1633 break;
1634
1635 if (*ptr == NL)
1636 ptr++;
1637
1638 if (STRSTR(ptr, "^done") == ptr)
1639 lvl3_mode = TRUE;
1640
1641 /* the first prompt is newline terminated (count it only once) */
1642 if (STRSTR(ptr, "(gdb) ") == ptr
1643 && (gdb_cnt == 1 || STRCHR(ptr, NL) != NULL))
1644 gdb_cnt++;
1645
1646 if (gdb_cnt == 2)
1647 {
1648 # ifdef GDB_LVL3_SUPPORT
1649 /* set annotation level 3 */
1650 if (lvl3_mode)
1651 write(this->fd, SG_LVL_3, strlen(SG_LVL_3));
1652 else
1653 # ifdef GDB_LVL2_SUPPORT
1654 write(this->fd, SG_LVL_2, strlen(SG_LVL_2));
1655 # else
1656 {
1657 err = "This |+gdb| version does not support level 2 mode";
1658 goto fail;
1659 }
1660 # endif
1661 # else /* LVL3 */
1662 lvl3_mode = FALSE;
1663 # ifdef GDB_LVL2_SUPPORT
1664 /* set annotation level 2 */
1665 if (! lvl3_mode)
1666 write(this->fd, SG_LVL_2, strlen(SG_LVL_2));
1667 # endif
1668 # endif /* LVL3 */
1669
1670 # ifdef FEAT_GDB /* Clewn does not need this */
1671 /* ANO_PMT_FORMORE happen every LPP_LINES and provide us a mean to abort
1672 * large output (in get_asm for example or any user cmd) */
1673 write(this->fd, SG_HEIGHT, strlen(SG_HEIGHT));
1674 lpp_lines = gdb_itoa(LPP_LINES);
1675 write(this->fd, (char *)lpp_lines, strlen((char *)lpp_lines));
1676 write(this->fd, "\n", 1);
1677 write(this->fd, SG_WIDTH, strlen(SG_WIDTH));
1678 write(this->fd, SG_EDITING, strlen(SG_EDITING));
1679 # else
1680 /* number of lines in a page is unlimited */
1681 write(this->fd, SG_HEIGHT, strlen(SG_HEIGHT));
1682 lpp_lines = gdb_itoa(0);
1683 write(this->fd, lpp_lines, strlen(lpp_lines));
1684 write(this->fd, "\n", 1);
1685 write(this->fd, SG_WIDTH, strlen(SG_WIDTH));
1686 write(this->fd, SG_EDITING, strlen(SG_EDITING));
1687 write(this->fd, " \n", 2); /* avoid Undefined command: "server". Try "help". */
1688
1689 /* `run' commands do input and output on clewn own terminal when possible */
1690 if (isatty(1) && (tty_name=ttyname(1)) != NULL) {
1691 char_u * res = NULL;
1692
1693 gdb_cat(&res, (char_u *)"server tty ");
1694 gdb_cat(&res, tty_name);
1695 gdb_cat(&res, (char_u *)"\n");
1696 write(this->fd, res, STRLEN(res));
1697 xfree(res);
1698 }
1699 # endif
1700 write(this->fd, SG_VERSION, strlen(SG_VERSION));
1701 }
1702 } while ((ptr = STRCHR(ptr, NL)) != NULL);
1703
1704 /* Second step: find the needle, process line by line */
1705 do
1706 {
1707 if (ptr == NULL)
1708 break;
1709
1710 if (*ptr == NL)
1711 ptr++;
1712
1713 /* looking for the needle after a prompt */
1714 if (this->note == ANO_PROMPT && STRSTR(ptr, SG_VERSION) == ptr)
1715 {
1716 ptr += strlen(SG_VERSION);
1717 needle = TRUE;
1718 }
1719
1720 /* discard post-prompt */
1721 if (needle && this->note == ANO_POSTPROMPT)
1722 {
1723 /* store a partial last line for later parse_output */
1724 if ((line = (char_u *)strrchr(gdb_buf, (int)NL)) != NULL
1725 && *(line + 1) != NUL)
1726 {
1727 xfree(this->line);
1728 this->line = (char_u *)clewn_strsave((char *)(line + 1));
1729 this->annoted = TRUE;
1730 }
1731
1732 if (lvl3_mode)
1733 # ifdef GDB_LVL3_SUPPORT
1734 {
1735 # ifdef FEAT_GDB
1736 gdb_popup_console(this);
1737 # endif
1738
1739 this->syntax = TRUE; /* force syntax highlite */
1740 # ifdef FEAT_GDB
1741 gdb_write_buf(this, (char_u *)SG_INTRO_3, TRUE);
1742 # else
1743 sprintf(tmp, SG_INTRO_3, this->version);
1744 gdb_write_buf(this, tmp, TRUE);
1745 # endif
1746 this->syntax = FALSE;
1747
1748 # ifdef FEAT_GDB /* write unconditionally with Clewn */
1749 /* write the remaining part and display it */
1750 if (*ptr != NUL)
1751 # endif
1752 gdb_write_buf(this, ptr, TRUE);
1753
1754 # ifdef FEAT_GDB
1755 /* redraw gdb console window when displayed */
1756 gdb_redraw(this->buf);
1757 # endif
1758
1759 gdb_lvl3_init(this);
1760 }
1761 # else
1762 {
1763 err = "This |+gdb| version does not support level 3 mode";
1764 goto fail;
1765 }
1766 # endif
1767 else
1768 # ifdef GDB_LVL2_SUPPORT
1769 {
1770 # ifdef FEAT_GDB
1771 gdb_popup_console(this);
1772 # endif
1773
1774 this->syntax = TRUE; /* force syntax highlite */
1775 gdb_write_buf(this, (char_u *)SG_INTRO_2, TRUE);
1776 this->syntax = FALSE;
1777
1778 # ifdef FEAT_GDB /* write unconditionally with Clewn */
1779 /* write the remaining part and display it */
1780 if (*ptr != NUL)
1781 # endif
1782 gdb_write_buf(this, ptr, TRUE);
1783
1784 # ifdef FEAT_GDB
1785 /* redraw gdb console window when displayed */
1786 gdb_redraw(this->buf);
1787 # endif
1788
1789 gdb_lvl2_init(this);
1790 }
1791 # else
1792 {
1793 err = "This |+gdb| version does not support level 2 mode";
1794 goto fail;
1795 }
1796 # endif
1797 if (tty_name)
1798 fprintf(stderr, "`run' commands do input and output on the terminal %s\n", tty_name);
1799
1800 return OK;
1801 }
1802 } while ((ptr = parse_note(this, ptr)) != NULL);
1803
1804 /* left shift buffer to last start of line */
1805 if ((ptr = (char_u *)strrchr((char *)gdb_buf, (int)NL)) != NULL)
1806 {
1807 len = STRLEN(ptr + 1);
1808 clewn_memmove(gdb_buf, ptr + 1, len);
1809 last = (char_u *)gdb_buf + len;
1810 }
1811 }
1812
1813 # ifdef GDB_LVL2_SUPPORT
1814 /* could not find the needle: hope for the best and fall back
1815 * to annotation level 2 and send version again */
1816 write(this->fd, SG_LVL_2, strlen(SG_LVL_2));
1817 write(this->fd, SG_VERSION, strlen(SG_VERSION));
1818 # ifdef FEAT_GDB
1819 gdb_popup_console(this);
1820 # endif
1821
1822 this->syntax = TRUE; /* force syntax highlite */
1823 gdb_write_buf(this, (char_u *)SG_INTRO_2, TRUE);
1824 this->syntax = FALSE;
1825
1826 gdb_lvl2_init(this);
1827 return OK;
1828 # else
1829 err = "This |+gdb| version does not support level 2 mode";
1830 goto fail;
1831 # endif
1832 fail:
1833 gdb_close(this);
1834
1835 if (err != NULL)
1836 EMSG(_(err));
1837
1838 return FAIL;
1839 }
1840
1841 # ifdef GDB_LVL3_SUPPORT
1842 /* Print a value in a netbeans balloon */
1843 # define PRINT_VALUE "^done,value=\""
1844 char *
gdb_print_value(this,state,line,obs)1845 gdb_print_value(this, state, line, obs)
1846 gdb_T *this;
1847 int state;
1848 char_u *line;
1849 struct obstack *obs;
1850 {
1851 # ifdef HAVE_CLEWN
1852 char_u * res = NULL;
1853 char_u * ptr;
1854 char_u * quote;
1855
1856 switch(state)
1857 {
1858 case OOB_CMD:
1859 if (this->balloon_txt != NULL) {
1860 obstack_strcat(obs, "server interpreter-exec mi \"-data-evaluate-expression ");
1861 obstack_strcat(obs, this->balloon_txt);
1862 obstack_strcat0(obs, "\"\n");
1863
1864 FREE(this->lvl3.result);
1865 return (char_u *)obstack_finish(obs);
1866 }
1867 break;
1868
1869 case OOB_COLLECT:
1870 gdb_cat(&res, this->lvl3.result);
1871 gdb_cat(&res, line);
1872 xfree(this->lvl3.result);
1873 this->lvl3.result = res;
1874 break;
1875
1876 case OOB_COMPLETE:
1877 if (this->lvl3.result != NULL
1878 && (ptr = STRSTR(this->lvl3.result, PRINT_VALUE)) != NULL
1879 && (ptr += strlen(PRINT_VALUE))
1880 && (quote = (char_u *)strrchr(ptr, '"')) != NULL)
1881 {
1882 *quote = NUL;
1883 obstack_strcat(obs, "\" ");
1884 obstack_strcat(obs, this->balloon_txt);
1885 obstack_strcat(obs, " = ");
1886 obstack_strcat(obs, ptr);
1887 obstack_strcat0(obs, " \"");
1888
1889 res = (char_u *)obstack_finish(obs);
1890 gdb_showBalloon(res, obs);
1891 }
1892
1893 FREE(this->balloon_txt);
1894 FREE(this->lvl3.result);
1895 break;
1896 }
1897 # endif /* HAVE_CLEWN*/
1898 return NULL;
1899 }
1900 # endif /* GDB_LVL3_SUPPORT */
1901
1902 /* Get instruction at $pc */
1903 char *
gdb_get_pc(this,state,line,obs)1904 gdb_get_pc(this, state, line, obs)
1905 gdb_T *this;
1906 int state;
1907 char_u *line;
1908 struct obstack *obs;
1909 {
1910 char_u *ptr;
1911
1912 if (obs) {} /* keep compiler happy */
1913
1914 switch(state)
1915 {
1916 case OOB_CMD:
1917 FREE(this->pc);
1918
1919 if (this->state & GS_STOPPED)
1920 {
1921 this->state &= ~GS_STOPPED;
1922 return "server x/i $pc\n";
1923 }
1924 break;
1925
1926 case OOB_COLLECT:
1927 if ((this->pc = gdb_regexec(line, PAT_ADD, 1, NULL)) != NULL)
1928 {
1929 /* Replace TAB with a space */
1930 for (ptr = line; *ptr != NUL; ptr++)
1931 if (*ptr == TAB)
1932 *ptr = ' ';
1933
1934 gdb_status(this, line, obs);
1935 }
1936 break;
1937 }
1938 return NULL;
1939 }
1940
1941 /* Get frame info */
1942 char *
gdb_get_frame(this,state,line,obs)1943 gdb_get_frame(this, state, line, obs)
1944 gdb_T *this;
1945 int state;
1946 char_u *line;
1947 struct obstack *obs;
1948 {
1949 char_u *res = NULL;
1950
1951 if (obs) {} /* keep compiler happy */
1952
1953 switch(state)
1954 {
1955 case OOB_CMD:
1956 FREE(this->oob_result);
1957 return "server frame\n";
1958
1959 case OOB_COLLECT:
1960 gdb_cat(&res, this->oob_result);
1961 gdb_cat(&res, line);
1962 xfree(this->oob_result);
1963 this->oob_result = res;
1964 break;
1965
1966 case OOB_COMPLETE:
1967 xfree(this->frame_pc);
1968 if (this->oob_result != NULL
1969 && (this->frame_pc = gdb_regexec(this->oob_result, PAT_FRAME, 1, NULL)) != NULL) {
1970 xfree(this->asm_add);
1971 this->asm_add = (char_u *)clewn_strsave((char *)this->frame_pc);
1972 }
1973 else {
1974 if (this->pc != NULL) {
1975 this->frame_pc = (char_u *)clewn_strsave((char *)this->pc);
1976 xfree(this->asm_add);
1977 this->asm_add = (char_u *)clewn_strsave((char *)this->frame_pc);
1978 }
1979 }
1980
1981 FREE(this->oob_result);
1982 break;
1983 }
1984 return NULL;
1985 }
1986
1987 # ifdef GDB_LVL3_SUPPORT
1988 /* Stack info frame */
1989 char *
gdb_info_frame(this,state,line,obs)1990 gdb_info_frame(this, state, line, obs)
1991 gdb_T *this;
1992 int state;
1993 char_u *line;
1994 struct obstack *obs;
1995 {
1996 char_u *res = NULL;
1997
1998 if (obs) {} /* keep compiler happy */
1999
2000 switch(state)
2001 {
2002 case OOB_CMD:
2003 FREE(this->lvl3.result);
2004 return "server info frame\n";
2005
2006 case OOB_COLLECT:
2007 gdb_cat(&res, this->lvl3.result);
2008 gdb_cat(&res, line);
2009 xfree(this->lvl3.result);
2010 this->lvl3.result = res;
2011 break;
2012
2013 case OOB_COMPLETE:
2014 this->frame_curlvl = -1;
2015 if (this->lvl3.result != NULL
2016 && (res = gdb_regexec(this->lvl3.result, PAT_INFO_FRAME, 1, NULL)) != NULL) {
2017 this->frame_curlvl = atoi((char *)res);
2018 xfree(res);
2019 }
2020
2021 FREE(this->lvl3.result);
2022 break;
2023 }
2024 return NULL;
2025 }
2026
2027 # define SOURCE_FILENAME "\",file=\""
2028 # define SOURCE_LINENUM "\",line=\""
2029 /* Change frame highlight according to new frame level */
2030 char *
gdb_stack_frame(this,state,line,obs)2031 gdb_stack_frame(this, state, line, obs)
2032 gdb_T *this;
2033 int state;
2034 char_u *line;
2035 struct obstack *obs;
2036 {
2037 char_u * res = NULL;
2038 int rc = -1;
2039 char tmp[32];
2040 char_u * fname;
2041 char_u * pnum;
2042 char_u * quote;
2043 char_u * ptr;
2044 linenr_T lnum;
2045
2046 switch(state)
2047 {
2048 case OOB_CMD:
2049 /* get info about frame_curlvl:
2050 * ^done,stack=[frame={level="1",addr="0x080483bb",func="main",file="cltest_main.c",line="12"}] */
2051 if (this->frame_curlvl >= 0) {
2052 FREE(this->lvl3.result);
2053
2054 sprintf(tmp, "%d %d", this->frame_curlvl, this->frame_curlvl);
2055 obstack_strcat(obs, "server interpreter-exec mi \"-stack-list-frames ");
2056 obstack_strcat(obs, tmp);
2057 obstack_strcat0(obs, "\"\n");
2058 return (char *)obstack_finish(obs);
2059 }
2060 break;
2061
2062 case OOB_COLLECT:
2063 gdb_cat(&res, this->lvl3.result);
2064 gdb_cat(&res, line);
2065 xfree(this->lvl3.result);
2066 this->lvl3.result = res;
2067 break;
2068
2069 case OOB_COMPLETE:
2070 if (this->lvl3.result != NULL
2071 && (ptr = STRSTR(this->lvl3.result, SOURCE_FILENAME)) != NULL
2072 && (pnum = STRSTR(this->lvl3.result, SOURCE_LINENUM)) != NULL)
2073 {
2074 pnum += strlen(SOURCE_FILENAME);
2075 lnum = atoi((char *)pnum);
2076
2077 ptr += strlen(SOURCE_FILENAME);
2078
2079 if ((quote = STRCHR(ptr, '"')) != NULL) {
2080 fname = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
2081
2082 rc = 0;
2083
2084 /* set frame sign only if this is a new fname/lnum position */
2085 if (this->frame_fname == NULL
2086 || STRCMP(this->frame_fname, fname) != 0 || this->frame_lnum != lnum) {
2087 FREE(this->frame_fname);
2088 this->frame_fname = (char_u *)clewn_strsave((char *)fname);
2089 this->frame_lnum = lnum;
2090 rc = gdb_fr_set(this, fname, &lnum, obs);
2091 }
2092 }
2093 }
2094
2095 if (rc != 0 && p_asm != 0)
2096 this->pool.hilite = TRUE; /* do asm frame highliting */
2097 FREE(this->lvl3.result);
2098 break;
2099 }
2100 return NULL;
2101 }
2102 # endif /* GDB_LVL3_SUPPORT */
2103
2104 /* Get symbol file name */
2105 char *
gdb_get_sfile(this,state,line,obs)2106 gdb_get_sfile(this, state, line, obs)
2107 gdb_T *this;
2108 int state;
2109 char_u *line;
2110 struct obstack *obs;
2111 {
2112 char_u *res = NULL;
2113
2114 switch(state)
2115 {
2116 case OOB_CMD:
2117 return "server info target\n";
2118
2119 case OOB_COLLECT:
2120 if (this->oob.cnt == 1
2121 && (res = gdb_regexec(line, PAT_SFILE, 1, obs)) != NULL
2122 && (this->sfile == NULL || STRCMP(res, this->sfile) != 0))
2123 {
2124 gdb_status(this, (char_u *)"new symbols", obs);
2125 xfree(this->sfile);
2126 this->sfile = (char_u *)clewn_strsave((char *)res);
2127 }
2128 break;
2129
2130 case OOB_COMPLETE:
2131 if (this->oob.cnt == 0)
2132 {
2133 gdb_status(this, (char_u *)"empty target", obs);
2134 FREE(this->sfile);
2135 }
2136 break;
2137 }
2138 return NULL;
2139 }
2140
2141 /* Get GDB source directories */
2142 char *
gdb_get_sourcedir(this,state,line,obs)2143 gdb_get_sourcedir(this, state, line, obs)
2144 gdb_T *this;
2145 int state;
2146 char_u *line;
2147 struct obstack *obs;
2148 {
2149 char_u *res = NULL;
2150
2151 if (obs) {} /* keep compiler happy */
2152
2153 switch(state)
2154 {
2155 case OOB_CMD:
2156 FREE(this->lvl3.result);
2157 return "server show directories\n";
2158
2159 case OOB_COLLECT:
2160 gdb_cat(&res, this->lvl3.result);
2161 gdb_cat(&res, line);
2162 xfree(this->lvl3.result);
2163 this->lvl3.result = res;
2164 break;
2165
2166 case OOB_COMPLETE:
2167 if (this->lvl3.result != NULL)
2168 {
2169 xfree(this->directories);
2170 this->directories = gdb_regexec(this->lvl3.result, PAT_DIR, 1, NULL);
2171 FREE(this->lvl3.result);
2172 }
2173 break;
2174 }
2175 return NULL;
2176 }
2177
2178 #ifdef GDB_LVL3_SUPPORT
2179 # ifndef FEAT_GDB
2180 /* Source the project file */
2181 char *
gdb_source_project(this,state,line,obs)2182 gdb_source_project(this, state, line, obs)
2183 gdb_T *this;
2184 int state;
2185 char_u *line;
2186 struct obstack *obs;
2187 {
2188 switch(state)
2189 {
2190 case OOB_CMD:
2191 if (this->project_file != NULL
2192 && cnb_state()
2193 && this->project_state == PROJ_SOURCEIT)
2194 {
2195 this->project_state = PROJ_DONE;
2196 fprintf(stderr, "source %s\n", this->project_file);
2197
2198 if (this->sfile != NULL)
2199 fprintf(stderr, "Warning: symbol table \"%s\" was loaded before sourcing the project file\n", this->sfile);
2200
2201 obstack_strcat(obs, "server source ");
2202 obstack_strcat(obs, this->project_file);
2203 obstack_strcat0(obs, "\n");
2204 return (char_u *)obstack_finish(obs);
2205 }
2206 break;
2207
2208 case OOB_COLLECT:
2209 if (line != NULL)
2210 fprintf(stderr, "%s\n", line);
2211 break;
2212
2213 case OOB_COMPLETE:
2214 /* force getting the source file list from gdb */
2215 this->lvl3.get_source_list = TRUE;
2216
2217 /* this is required after 'restart' to display the gdb prompt */
2218 fprintf(stderr, this->prompt);
2219 break;
2220 }
2221
2222 return NULL;
2223 }
2224
2225 # define CWD_VALUE "^done,cwd=\""
2226 /* Get current working directory */
2227 char *
gdb_get_pwd(this,state,line,obs)2228 gdb_get_pwd(this, state, line, obs)
2229 gdb_T *this;
2230 int state;
2231 char_u *line;
2232 struct obstack *obs;
2233 {
2234 char_u * res = NULL;
2235 char_u * ptr;
2236 char_u * quote;
2237
2238 if (obs) {} /* keep compiler happy */
2239
2240 switch(state)
2241 {
2242 case OOB_CMD:
2243 if (this->mode != GDB_MODE_LVL2) {
2244 FREE(this->lvl3.result);
2245 return "server interpreter-exec mi \"-environment-pwd\"\n";
2246 }
2247 break;
2248
2249 case OOB_COLLECT:
2250 gdb_cat(&res, this->lvl3.result);
2251 gdb_cat(&res, line);
2252 xfree(this->lvl3.result);
2253 this->lvl3.result = res;
2254 break;
2255
2256 case OOB_COMPLETE:
2257 if (this->lvl3.result != NULL
2258 && (ptr = STRSTR(this->lvl3.result, CWD_VALUE)) != NULL
2259 && (ptr += strlen(CWD_VALUE))
2260 && (quote = (char_u *)strrchr(ptr, '"')) != NULL)
2261 {
2262 *quote = NUL;
2263 gdb_cat(&res, (char_u *)"cd ");
2264 gdb_cat(&res, ptr);
2265 gdb_cat(&res, (char_u *)"\n");
2266 xfree(this->pwd);
2267 this->pwd = res;
2268 }
2269
2270 FREE(this->lvl3.result);
2271 break;
2272 }
2273 return NULL;
2274 }
2275
2276 # define ARGS_VALUE "Argument list to give program being debugged when it is started is \""
2277 /* Get args */
2278 char *
gdb_get_args(this,state,line,obs)2279 gdb_get_args(this, state, line, obs)
2280 gdb_T *this;
2281 int state;
2282 char_u *line;
2283 struct obstack *obs;
2284 {
2285 char_u * res = NULL;
2286 char_u * ptr;
2287 char_u * quote;
2288
2289 if (obs) {} /* keep compiler happy */
2290
2291 switch(state)
2292 {
2293 case OOB_CMD:
2294 FREE(this->lvl3.result);
2295 return "server show args\n";
2296
2297 case OOB_COLLECT:
2298 gdb_cat(&res, this->lvl3.result);
2299 gdb_cat(&res, line);
2300 xfree(this->lvl3.result);
2301 this->lvl3.result = res;
2302 break;
2303
2304 case OOB_COMPLETE:
2305 if (this->lvl3.result != NULL
2306 && (ptr = STRSTR(this->lvl3.result, ARGS_VALUE)) != NULL
2307 && (ptr += strlen(ARGS_VALUE))
2308 && (quote = (char_u *)strrchr(ptr, '"')) != NULL)
2309 {
2310 *quote = NUL;
2311 gdb_cat(&res, "set args ");
2312 gdb_cat(&res, ptr);
2313 gdb_cat(&res, "\n");
2314 xfree(this->args);
2315 this->args = res;
2316 }
2317
2318 FREE(this->lvl3.result);
2319 break;
2320 }
2321 return NULL;
2322 }
2323 # endif
2324
2325 /* Get GDB current source file */
2326 char *
gdb_source_cur(this,state,line,obs)2327 gdb_source_cur(this, state, line, obs)
2328 gdb_T *this;
2329 int state;
2330 char_u *line;
2331 struct obstack *obs;
2332 {
2333 char_u *res = NULL;
2334
2335 if (obs) {} /* keep compiler happy */
2336
2337 switch(state)
2338 {
2339 case OOB_CMD:
2340 FREE(this->lvl3.source_cur);
2341 return "server interpreter-exec mi \"-file-list-exec-source-file\"\n";
2342
2343 case OOB_COLLECT:
2344 gdb_cat(&res, this->lvl3.source_cur);
2345 gdb_cat(&res, line);
2346 xfree(this->lvl3.source_cur);
2347 this->lvl3.source_cur = res;
2348 break;
2349
2350 case OOB_COMPLETE:
2351 break;
2352 }
2353 return NULL;
2354 }
2355
2356 /* Get GDB current source file */
2357 char *
gdb_source_list(this,state,line,obs)2358 gdb_source_list(this, state, line, obs)
2359 gdb_T *this;
2360 int state;
2361 char_u *line;
2362 struct obstack *obs;
2363 {
2364 char_u *res = NULL;
2365
2366 if (obs) {} /* keep compiler happy */
2367
2368 switch(state)
2369 {
2370 case OOB_CMD:
2371 if (this->lvl3.get_source_list || this->lvl3.source_list == NULL) {
2372 FREE(this->lvl3.source_list);
2373 this->lvl3.get_source_list = FALSE;
2374 return "server interpreter-exec mi \"-file-list-exec-source-files\"\n";
2375 }
2376 break;
2377
2378 case OOB_COLLECT:
2379 gdb_cat(&res, this->lvl3.source_list);
2380 gdb_cat(&res, line);
2381 xfree(this->lvl3.source_list);
2382 this->lvl3.source_list = res;
2383 break;
2384
2385 case OOB_COMPLETE:
2386 break;
2387 }
2388 return NULL;
2389 }
2390 #endif /* GDB_LVL3_SUPPORT */
2391
2392 # ifdef GDB_LVL3_SUPPORT
2393 # define BKPT_RECORD "bkpt={number=\""
2394 # define BKPT_ADDR "\",addr=\""
2395 /*
2396 * When a breakpoint is being set and asm option is on, get the
2397 * instruction address of the last breakpoint, the one being set.
2398 * This address is used in get_asm() to disassemble the function
2399 * containing this address.
2400 */
2401 static char *
get_lastbp(this,state,line,obs)2402 get_lastbp(this, state, line, obs)
2403 gdb_T *this;
2404 int state;
2405 char_u *line;
2406 struct obstack *obs;
2407 {
2408 char_u *res = NULL;
2409 int found = FALSE;
2410 char_u *record = NULL;
2411 char_u *ptr;
2412 char_u *addr;
2413 bpinfo_T *p;
2414 int bp_num;
2415
2416 if (obs) {} /* keep compiler happy */
2417
2418 switch (state)
2419 {
2420 case OOB_CMD:
2421 /* GDB sends sometimes ANO_BP_INVALID when stepping, even
2422 * though no breakpoints have been changed.
2423 * Avoid checking for last bp in this case, because this
2424 * may cause hiliting a bp in a new buffer when what is
2425 * expected is a new frame */
2426 if (this->bp_state & BPS_FR_INVALID)
2427 return NULL;
2428
2429 /* A breakpoint is being set in assembly */
2430 if (p_asm != 0 && (this->bp_state & BPS_INVALID)
2431 && (this->bp_state & BPS_BP_SET))
2432 {
2433 this->bp_state &= ~BPS_BP_SET;
2434 FREE(this->lvl3.result);
2435
2436 /* fetch GDB bp table info */
2437 return "server interpreter-exec mi -break-list\n";
2438 }
2439 break;
2440
2441 case OOB_COLLECT:
2442 gdb_cat(&res, this->lvl3.result);
2443 gdb_cat(&res, line);
2444 xfree(this->lvl3.result);
2445 this->lvl3.result = res;
2446 break;
2447
2448 case OOB_COMPLETE:
2449 if ((ptr = this->lvl3.result) != NULL)
2450 {
2451 /* search for last record in breakpoint table */
2452 do
2453 {
2454 if ((ptr = STRSTR(ptr, BKPT_RECORD)) != NULL)
2455 {
2456 record = ptr;
2457 ptr++;
2458 }
2459 }
2460 while (ptr != NULL);
2461
2462 /* last record */
2463 if (record != NULL
2464 && (bp_num = atoi((char *)(record + strlen(BKPT_RECORD)))) > 0)
2465 {
2466 /* look it up in bpinfo list */
2467 for (p = this->bpinfo; p != NULL; p = p->next)
2468 {
2469 if (bp_num == p->id)
2470 {
2471 found = TRUE;
2472 break;
2473 }
2474 }
2475
2476 /* not found: set asm_add so that get_asm will
2477 * do the disassembling */
2478 if (! found && (addr = STRSTR(record, BKPT_ADDR)) != NULL)
2479 {
2480 xfree(this->asm_add);
2481 this->asm_add =
2482 gdb_regexec(addr + strlen(BKPT_ADDR), PAT_ADD, 1, NULL);
2483 }
2484 }
2485
2486 FREE(this->lvl3.result);
2487 }
2488 break;
2489 }
2490 return NULL;
2491 }
2492 # endif /* GDB_LVL3_SUPPORT */
2493
2494 /* Get the function name corresponding to asm_add */
2495 char *
gdb_get_asmfunc(this,state,line,obs)2496 gdb_get_asmfunc(this, state, line, obs)
2497 gdb_T *this;
2498 int state;
2499 char_u *line;
2500 struct obstack *obs;
2501 {
2502 switch(state)
2503 {
2504 case OOB_CMD:
2505 if (this->asm_add != NULL)
2506 {
2507 obstack_strcat(obs, "server info symbol 0x");
2508 obstack_strcat(obs, this->asm_add);
2509 obstack_strcat0(obs, "\n");
2510 return (char *)obstack_finish(obs);
2511 }
2512 FREE(this->asm_func);
2513 break;
2514
2515 case OOB_COLLECT:
2516 xfree(this->asm_func);
2517 this->asm_func = gdb_regexec(line, PAT_ASM_FUNC, 1, NULL);
2518 break;
2519 }
2520 return NULL;
2521 }
2522
2523 /*
2524 * This function is a hack to fix errors occuring in GDB command
2525 * "info symbol ADDR" that sometimes cannot find the symbol corresponding to
2526 * a given ADDR, when GDB command "print/a ADDR" can.
2527 * "print/a ADDR" is used as a last resort because it changes the value history.
2528 * "output/a ADDR" does not change the value history, but the output of this
2529 * command misses a newline.
2530 */
2531 char *
gdb_get_asmfunc_hack(this,state,line,obs)2532 gdb_get_asmfunc_hack(this, state, line, obs)
2533 gdb_T *this;
2534 int state;
2535 char_u *line;
2536 struct obstack *obs;
2537 {
2538 switch(state)
2539 {
2540 case OOB_CMD:
2541 if (this->asm_add != NULL && this->asm_func == NULL)
2542 {
2543 obstack_strcat(obs, "server print/a 0x");
2544 obstack_strcat(obs, this->asm_add);
2545 obstack_strcat0(obs, "\n");
2546 return (char *)obstack_finish(obs);
2547 }
2548 break;
2549
2550 case OOB_COLLECT:
2551 xfree(this->asm_func);
2552 this->asm_func = gdb_regexec(line, PAT_ASM_FUNC_P, 1, NULL);
2553 break;
2554 }
2555 return NULL;
2556 }
2557
2558 # define ASM_ABORTED "DISASSEMBLY ABORTED"
2559
2560 /*
2561 * Disassemble new function containing asm_add and highlight asm_add
2562 * if this->pool.hilite is TRUE
2563 */
2564 char *
gdb_get_asm(this,state,line,obs)2565 gdb_get_asm(this, state, line, obs)
2566 gdb_T *this;
2567 int state;
2568 char_u *line;
2569 struct obstack *obs;
2570 # ifdef FEAT_GDB
2571 {
2572 buf_T *buf = this->pool.buf[this->pool.idx];
2573 buf_T *oldbuf = curbuf;
2574 char_u *res = NULL;
2575 int oldest = 0;
2576 int age = 0;
2577 linenr_T lnum;
2578 win_T *win;
2579 int i;
2580
2581 if (p_asm == 0)
2582 {
2583 FREE(this->asm_add);
2584 return NULL;
2585 }
2586
2587 lnum = (buf != NULL ? BUFLASTL(buf) : 0);
2588
2589 switch (state)
2590 {
2591 case OOB_CMD:
2592 if (this->asm_add != NULL && !gdb_as_frset(this, obs))
2593 {
2594 /* pickup least recent buffer */
2595 for (i = this->pool.max; i > 0; )
2596 {
2597 i--;
2598 if (this->pool.age[i] >= age && this->pool.buf[i] != NULL)
2599 {
2600 age = this->pool.age[i];
2601 oldest = i;
2602 }
2603 }
2604
2605 /* no buffers in pool */
2606 if ((buf = this->pool.buf[oldest]) == NULL)
2607 {
2608 this->pool.hilite = FALSE;
2609 FREE(this->asm_add);
2610 return NULL;
2611 }
2612 this->pool.idx = oldest;
2613
2614 /* clear the buffer */
2615 gdb_clear_asmbuf(this, buf);
2616
2617 /* init msg_busy */
2618 obstack_strcat(obs, "Disassembling 0x");
2619 obstack_strcat0(obs, this->asm_add);
2620 res = (char_u *)obstack_finish(obs);
2621 gdb_msg_busy(res);
2622
2623 /* send cmd */
2624 obstack_strcat(obs, "server disassemble 0x");
2625 obstack_strcat(obs, this->asm_add);
2626 obstack_strcat0(obs, "\n");
2627 return (char *)obstack_finish(obs);
2628 }
2629 this->pool.hilite = FALSE;
2630 break;
2631
2632 case OOB_COLLECT:
2633 if (buf == NULL)
2634 return NULL;
2635 curbuf = buf;
2636
2637 /* concatenate with line after an annotation
2638 * and replace line, otherwise add */
2639 if (this->line != NULL && this->annoted)
2640 {
2641 obstack_strcat(obs, this->line);
2642 obstack_strcat0(obs, line);
2643 line = (char_u *)obstack_finish(obs);
2644 ml_delete(lnum--, FALSE);
2645 }
2646
2647 /* first line: remove empty line after the inserted one */
2648 if (ml_append(lnum, line, 0, 0) == OK && lnum == 0)
2649 ml_delete(buf->b_ml.ml_line_count, FALSE);
2650 curbuf = oldbuf;
2651
2652 if ((this->oob.cnt % 1000) == 0)
2653 gdb_msg_busy(NULL);
2654
2655 xfree(this->line);
2656 this->line = (char_u *)clewn_strsave((char *)line);
2657 break;
2658
2659 case OOB_COMPLETE:
2660 if (buf == NULL)
2661 return NULL;
2662 curbuf = buf;
2663
2664 if (this->oob.state & OS_INTR)
2665 {
2666 if (lnum >= 1 && STRCMP(ASM_ABORTED, ml_get(1)) != 0)
2667 {
2668 /* Clear buffer when interrupted */
2669 while (lnum-- > 0)
2670 ml_delete(buf->b_ml.ml_line_count, FALSE);
2671
2672 ml_append(0, (char_u *)ASM_ABORTED, 0, 0);
2673 lnum = buf->b_ml.ml_line_count;
2674 changed_lines(1, 0, lnum, lnum);
2675 curbuf = oldbuf;
2676
2677 this->pool.age[this->pool.idx] = ASM_OLD;
2678 gdb_edit_file(this, buf, NULL, 1, obs);
2679 }
2680
2681 /* write the prompt */
2682 gdb_write_buf(this, this->line, TRUE);
2683 gdb_redraw(buf);
2684 }
2685 else
2686 {
2687 changed_lines(1, 0, lnum, lnum);
2688
2689 /* set buffer name to function name */
2690 if (this->asm_func != NULL)
2691 {
2692 obstack_strcat(obs, this->asm_func);
2693 obstack_strcat0(obs, "-asm");
2694 res = (char_u *)obstack_finish(obs);
2695 gdb_as_setname(res);
2696 }
2697 curbuf = oldbuf;
2698
2699 /* highlite $asm_add and update window if displayed */
2700 if (! gdb_as_frset(this, obs) && (win = gdb_btowin(buf)) != NULL)
2701 {
2702 gdb_set_cursor(win, 1);
2703 redraw_win_later(win, NOT_VALID);
2704 }
2705 }
2706
2707 msg_clr_cmdline();
2708 FREE(this->asm_add);
2709 this->pool.hilite = FALSE;
2710 break;
2711 }
2712 return NULL;
2713 }
2714 # else
2715 {
2716 char_u *res = NULL;
2717 char_u *fname;
2718
2719 if (p_asm == 0)
2720 {
2721 FREE(this->asm_add);
2722 return NULL;
2723 }
2724
2725 switch (state)
2726 {
2727 case OOB_CMD:
2728 if (this->asm_add != NULL && ! gdb_as_frset(this, obs))
2729 {
2730 FREE(this->pool.name);
2731
2732 /* get a unique file name for this disassembled function
2733 * and open the file for creation
2734 * the file name suffix is '.clasm' so that it can be set
2735 * to 'autoread' by the runtime file clewn.vim */
2736 if (this->asm_func != NULL) {
2737 obstack_strcat(obs, this->asm_func);
2738 obstack_strcat0(obs, ".clasm");
2739 fname = (char_u *)obstack_finish(obs);
2740 }
2741 if (this->asm_func == NULL || (this->pool.fd = clewn_opentmpfile(fname,
2742 &(this->pool.name), 1)) == NULL)
2743 {
2744 this->pool.hilite = FALSE;
2745 return NULL;
2746 }
2747 this->pool.line_offset = 0L;
2748
2749 /* create the buffer */
2750 if ((this->pool.buf = cnb_create_buf(this->pool.name)) == -1)
2751 {
2752 this->pool.hilite = FALSE;
2753
2754 fclose(this->pool.fd);
2755 this->pool.fd = NULL;
2756 if (this->pool.name != NULL)
2757 (void)unlink(this->pool.name);
2758 FREE(this->pool.name);
2759 return NULL;
2760 }
2761
2762 /* init msg_busy */
2763 obstack_strcat(obs, "Disassembling 0x");
2764 obstack_strcat0(obs, this->asm_add);
2765 res = (char_u *)obstack_finish(obs);
2766 gdb_msg_busy(res);
2767
2768 /* send cmd */
2769 this->lastline = 0;
2770 obstack_strcat(obs, "server disassemble 0x");
2771 obstack_strcat(obs, this->asm_add);
2772 obstack_strcat0(obs, "\n");
2773 return (char_u *)obstack_finish(obs);
2774 }
2775 this->pool.hilite = FALSE;
2776 break;
2777
2778 case OOB_COLLECT:
2779 if (this->pool.fd == NULL)
2780 goto fail;
2781
2782 /* ignore when interrupted */
2783 if (this->oob.state & OS_INTR)
2784 return NULL;
2785
2786 /* concatenate with line after an annotation
2787 * and replace line, otherwise add */
2788 if (this->line != NULL && this->annoted)
2789 {
2790 obstack_strcat(obs, this->line);
2791 obstack_strcat0(obs, line);
2792 line = (char_u *)obstack_finish(obs);
2793
2794 this->lastline--;
2795 if (fseek(this->pool.fd, this->pool.line_offset, SEEK_SET) != 0)
2796 goto fail;
2797 }
2798
2799 /* write a newline except at first line */
2800 if (this->lastline != 0)
2801 {
2802 if ((this->pool.line_offset = ftell(this->pool.fd)) == -1
2803 || fputs("\n", this->pool.fd) < 0)
2804 goto fail;
2805 }
2806 this->lastline++;
2807
2808 /* write the line */
2809 if (fputs(line, this->pool.fd) < 0)
2810 goto fail;
2811
2812 if ((this->oob.cnt % 400) == 0)
2813 gdb_msg_busy(NULL);
2814
2815 xfree(this->line);
2816 this->line = (char_u *)clewn_strsave((char *)line);
2817 break;
2818
2819 case OOB_COMPLETE:
2820 if (this->pool.fd == NULL)
2821 goto fail;
2822
2823 if (this->oob.state & OS_INTR)
2824 {
2825 FREE(this->asm_add);
2826 this->pool.hilite = FALSE;
2827 goto fail;
2828 }
2829 else
2830 {
2831 /* highlite $asm_add */
2832 (void)gdb_as_frset(this, obs);
2833
2834 /* write last new line */
2835 if (fputs("\n", this->pool.fd) < 0)
2836 goto fail;
2837
2838 /* clear the line */
2839 gdb_msg_busy("FIN");
2840
2841 /* set the buffer as an asm buffer */
2842 cnb_set_asm(this->pool.buf);
2843 }
2844
2845 FREE(this->asm_add);
2846
2847 this->pool.buf = -1;
2848 fclose(this->pool.fd);
2849 this->pool.fd = NULL;
2850 FREE(this->pool.name);
2851 this->pool.hilite = FALSE;
2852 break;
2853 }
2854 return NULL;
2855 fail:
2856 /* clear the line */
2857 gdb_msg_busy("FIN");
2858
2859 cnb_kill(this->pool.buf);
2860 this->pool.buf = -1;
2861
2862 if (this->pool.fd != NULL)
2863 fclose(this->pool.fd);
2864 this->pool.fd = NULL;
2865
2866 if (this->pool.name != NULL)
2867 (void)unlink(this->pool.name);
2868 FREE(this->pool.name);
2869 return NULL;
2870 }
2871 # endif /* FEAT_GDB */
2872
2873 # ifdef GDB_LVL3_SUPPORT
2874 /*
2875 * Get the breakpoints info record table.
2876 */
2877 static char *
get_bp(this,state,line,obs)2878 get_bp(this, state, line, obs)
2879 gdb_T *this;
2880 int state;
2881 char_u *line;
2882 struct obstack *obs;
2883 {
2884 char_u *res = NULL;
2885 char_u *record = NULL;
2886 char_u *ptr;
2887 bpinfo_T *p;
2888
2889 switch (state)
2890 {
2891 case OOB_CMD:
2892 /* gdb 6.4 does not provide anymore the right annotations for breakpoints
2893 * when in level 3 (note that they are still there when setting annotate
2894 * level 2, I thought level 2 was deprecated, what a zoo !), so we look
2895 * for new or changed breakpoints systematically now */
2896 if (this->mode == GDB_MODE_LVL3)
2897 this->bp_state = BPS_INVALID;
2898
2899 /* When an ANO_BP_INVALID annotation has been received,
2900 * or when we are stepping (more accurately: got a new frame):
2901 * fetch bp table */
2902 if (this->bp_state & BPS_INVALID || this->bp_state & BPS_FR_INVALID)
2903 {
2904 FREE(this->lvl3.result);
2905 this->bufIsChanged = FALSE;
2906
2907 /* handle case where an error occured last time */
2908 FREE(this->record);
2909 gdb_free_bplist(&(this->tmplist));
2910
2911 /* fetch GDB bp table info */
2912 return "server interpreter-exec mi -break-list\n";
2913 }
2914
2915 this->bp_state &= ~BPS_INVALID;
2916 this->bp_state &= ~BPS_FR_INVALID;
2917 this->bp_state &= ~BPS_BP_HIT;
2918 break;
2919
2920 case OOB_COLLECT:
2921 gdb_cat(&res, this->lvl3.result);
2922 gdb_cat(&res, line);
2923 xfree(this->lvl3.result);
2924 this->lvl3.result = res;
2925 break;
2926
2927 case OOB_COMPLETE:
2928 if ((ptr = this->lvl3.result) != NULL)
2929 {
2930 /* process all records except last */
2931 do
2932 {
2933 if ((ptr = STRSTR(ptr, BKPT_RECORD)) != NULL
2934 && ptr > this->lvl3.result)
2935 {
2936 *(ptr - 1) = NUL;
2937 if (record != NULL)
2938 process_record(this, record, obs);
2939
2940 record = ptr;
2941 ptr++;
2942 }
2943 }
2944 while (ptr != NULL);
2945
2946 /* process last record */
2947 if (record != NULL)
2948 process_record(this, record, obs);
2949
2950 FREE(this->record);
2951
2952 /* All records left in the old table are breakpoints that have
2953 * been deleted: delete the corresponding highliting sign */
2954 for (p = this->bpinfo; p != NULL; p = p->next)
2955 gdb_unlite(BP_SIGN_ID(p->id));
2956
2957 this->bp_state &= ~BPS_INVALID;
2958 this->bp_state &= ~BPS_FR_INVALID;
2959 this->bp_state &= ~BPS_BP_HIT;
2960
2961 /* replace with new table */
2962 gdb_free_bplist(&(this->bpinfo));
2963 this->bpinfo = this->tmplist;
2964 this->tmplist = NULL;
2965
2966 FREE(this->lvl3.result);
2967 }
2968 break;
2969 }
2970 return NULL;
2971 }
2972
2973 # define BKPT_ENABLED "\",enabled=\""
2974 # define BKPT_DISP "\",disp=\""
2975 # define BKPT_SCRIPT "\",script={"
2976 # define BKPT_TYPE "\",type=\"breakpoint\""
2977 # define BKPT_LINE "\",line=\""
2978 # define BKPT_SOURCE "\",file=\""
2979 # define BKPT_AT "\",at=\"<"
2980 /* Process the current info record */
2981 static void
process_record(this,record,obs)2982 process_record(this, record, obs)
2983 gdb_T *this;
2984 char_u *record;
2985 struct obstack *obs;
2986 {
2987 char_u *bp_add = NULL;
2988 char_u *bp_line = NULL;
2989 char_u *bp_source = NULL;
2990 char_u *bp_at = NULL;
2991 char_u *ptr;
2992 char_u *end;
2993 char_u *quote;
2994 char_u *plus;
2995
2996 /* allocate a new record or reuse an existing one
2997 * and initialize its fields */
2998 if (this->record == NULL)
2999 this->record = (bpinfo_T *)xcalloc(sizeof(bpinfo_T));
3000
3001 this->record->id = -1;
3002 this->record->enabled = TRUE;
3003 # ifdef BP_INVALID_ANO_MISSING
3004 this->record->disposition = TRUE;
3005 # endif
3006 this->record->cont = FALSE;
3007 # ifdef FEAT_GDB
3008 this->record->buf = NULL;
3009 # else
3010 this->record->buf = -1;
3011 this->record->typenr_en = -1;
3012 this->record->typenr_dis = -1;
3013 # endif
3014 this->record->lnum = 0;
3015 this->record->next = NULL;
3016
3017 /* breakpoint number */
3018 this->record->id = atoi((char *)(record + strlen(BKPT_RECORD)));
3019
3020 /* enabled state */
3021 if ((ptr = STRSTR(record, BKPT_ENABLED)) != NULL
3022 && *(ptr + strlen(BKPT_ENABLED)) == 'n')
3023 this->record->enabled = FALSE;
3024
3025 # ifdef BP_INVALID_ANO_MISSING
3026 /* disposition */
3027 if ((ptr = STRSTR(record, BKPT_DISP)) != NULL
3028 && STRSTR(ptr + strlen(BKPT_DISP), "keep") == NULL)
3029 this->record->disposition = FALSE;
3030 # endif
3031
3032 /* parse script for 'continue' as last statement */
3033 if ((ptr = STRSTR(record, BKPT_SCRIPT)) != NULL)
3034 {
3035 ptr += strlen(BKPT_SCRIPT);
3036 if ((end = STRCHR(ptr, '}')) != NULL)
3037 {
3038 while ((ptr = STRCHR(ptr, '"')) != NULL && ptr < end)
3039 {
3040 ptr++;
3041 if (gdb_regexec(ptr, PAT_BP_CONT, 1, obs) != NULL
3042 || gdb_regexec(ptr, PAT_BP_CONT, 2, obs) != NULL)
3043 {
3044 this->record->cont = TRUE; /* continue */
3045 break;
3046 }
3047 }
3048 }
3049 }
3050
3051 /* sanity check and discard watchpoints and others */
3052 if (this->record->id <= 0 || STRSTR(record, BKPT_TYPE) == NULL)
3053 return;
3054
3055 /* address */
3056 if ((ptr = STRSTR(record, BKPT_ADDR)) != NULL)
3057 bp_add = gdb_regexec(ptr + strlen(BKPT_ADDR), PAT_ADD, 1, obs);
3058
3059 /* line */
3060 if ((ptr = STRSTR(record, BKPT_LINE)) != NULL)
3061 {
3062 ptr += strlen(BKPT_LINE);
3063 if ((quote = STRCHR(ptr, '"')) != NULL)
3064 bp_line = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
3065 }
3066
3067 /* source */
3068 if ((ptr = STRSTR(record, BKPT_SOURCE)) != NULL)
3069 {
3070 ptr += strlen(BKPT_SOURCE);
3071 if ((quote = STRCHR(ptr, '"')) != NULL)
3072 bp_source = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
3073 }
3074
3075 /* at */
3076 if ((ptr = STRSTR(record, BKPT_AT)) != NULL)
3077 {
3078 ptr += strlen(BKPT_AT);
3079 if ((quote = STRCHR(ptr, '>')) != NULL)
3080 {
3081 if ((plus = STRCHR(ptr, '+')) != NULL && plus < quote)
3082 bp_at = (char_u *)obstack_copy0(obs, ptr, (plus - ptr));
3083 else
3084 bp_at = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
3085 }
3086 }
3087
3088 gdb_process_record(this, bp_add, bp_at, bp_line, bp_source, obs);
3089 }
3090
3091 /* Update the variables objects and the variables window */
3092 static char *
varobj_update(this,state,line,obs)3093 varobj_update(this, state, line, obs)
3094 gdb_T *this;
3095 int state;
3096 char_u *line;
3097 struct obstack *obs;
3098 {
3099 # ifdef FEAT_GDB
3100 char_u *ptrn;
3101 # else
3102 static char *result = NULL; /* mark the start and end of object operations */
3103 # endif
3104 char_u *res = NULL;
3105 varobj_T *obj;
3106
3107 switch (state)
3108 {
3109 case OOB_CMD:
3110 if (this->lvl3.varitem == NULL)
3111 {
3112 /* start with first in list */
3113 this->lvl3.varitem = this->lvl3.varlist;
3114 this->lvl3.varnext_cmd = VCMD_INIT;
3115 }
3116 oob_cmd:
3117 /* next OOB_CMD */
3118 if ((obj = this->lvl3.varitem) != NULL)
3119 {
3120 FREE(this->lvl3.result);
3121
3122 /* create a new object and give it a name */
3123 if (this->lvl3.varnext_cmd == VCMD_INIT && obj->name == NULL)
3124 {
3125 if (
3126 # ifdef FEAT_GDB
3127 this->var_buf != NULL
3128 # else
3129 this->var_buf > 0
3130 # endif
3131 )
3132 {
3133 if (obj->format != NULL)
3134 this->lvl3.varnext_cmd = VCMD_FORMAT;
3135 else
3136 this->lvl3.varnext_cmd = VCMD_PRINT;
3137
3138 this->lvl3.varcmd = VCMD_CREATE;
3139
3140 obstack_strcat(obs, "server interpreter-exec mi \"-var-create - * (");
3141 obstack_strcat(obs, obj->expression);
3142 obstack_strcat0(obs, ")\"\n");
3143 return (char *)obstack_finish(obs);
3144 }
3145 else
3146 {
3147 /* remove silently from list */
3148 remove_object(this, obj);
3149 goto oob_cmd;
3150 }
3151 }
3152
3153 /* sanity check: an object must have a name
3154 * this should never occur */
3155 if (obj->name == NULL)
3156 {
3157 /* silently ignore this error */
3158 this->lvl3.varnext_cmd = VCMD_INIT;
3159 this->lvl3.varitem = obj->next;
3160 goto oob_cmd;
3161 }
3162
3163 /* search for the object in the variables window
3164 * if it does not exist, then -var-delete it */
3165 if (this->lvl3.varnext_cmd == VCMD_INIT)
3166 {
3167 # ifdef FEAT_GDB
3168 pos_T pos;
3169
3170 pos.lnum = 1;
3171 pos.col = 0;
3172
3173 obstack_strcat(obs, "^\\s*");
3174 obstack_strcat(obs, obj->name);
3175 obstack_strcat0(obs, ":");
3176 ptrn = (char_u *)obstack_finish(obs);
3177
3178 if (this->var_buf == NULL
3179 || (this->var_buf->b_ml.ml_flags & ML_EMPTY)
3180 || (searchit(NULL, this->var_buf, &pos,
3181 FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) == FAIL))
3182 # else
3183 int lnum;
3184
3185 if (this->var_buf <= 0 || cnb_search_obj(obj->name, &lnum) == NULL)
3186 # endif
3187 {
3188 /* not in gdb variables window, delete it */
3189 this->lvl3.varcmd = VCMD_DELETE;
3190
3191 obstack_strcat(obs, "server interpreter-exec mi \"-var-delete var");
3192 obstack_strcat(obs, obj->name);
3193 obstack_strcat0(obs, "\"\n");
3194 return (char *)obstack_finish(obs);
3195 }
3196 }
3197
3198 /* list children if any (need to run this cmd before update) */
3199 if (this->lvl3.varnext_cmd == VCMD_INIT)
3200 {
3201 this->lvl3.varnext_cmd = VCMD_UPDATE;
3202
3203 if (obj->children)
3204 {
3205 this->lvl3.varcmd = VCMD_CHILDREN;
3206
3207 obstack_strcat(obs, "server interpreter-exec mi \"-var-list-children var");
3208 obstack_strcat(obs, obj->name);
3209 obstack_strcat0(obs, "\"\n");
3210 return (char *)obstack_finish(obs);
3211 }
3212 }
3213
3214 /* set the format */
3215 if (this->lvl3.varnext_cmd == VCMD_FORMAT)
3216 {
3217 if (obj->format != NULL && STRLEN(obj->format) == 2)
3218 {
3219 obstack_strcat(obs, "server interpreter-exec mi \"-var-set-format var");
3220 obstack_strcat(obs, obj->name);
3221
3222 switch(*(obj->format + 1))
3223 {
3224 case 't':
3225 obstack_strcat0(obs, " binary\"\n");
3226 break;
3227 case 'd':
3228 obstack_strcat0(obs, " decimal\"\n");
3229 break;
3230 case 'x':
3231 obstack_strcat0(obs, " hexadecimal\"\n");
3232 break;
3233 case 'o':
3234 obstack_strcat0(obs, " octal\"\n");
3235 break;
3236 default:
3237 obstack_strcat0(obs, " natural\"\n");
3238 break;
3239 }
3240
3241 this->lvl3.varnext_cmd = VCMD_PRINT;
3242 this->lvl3.varcmd = VCMD_FORMAT;
3243
3244 return (char *)obstack_finish(obs);
3245 }
3246 else
3247 {
3248 this->lvl3.varnext_cmd = VCMD_INIT;
3249 this->lvl3.varitem = obj->next;
3250 goto oob_cmd;
3251 }
3252 }
3253
3254 /* update object */
3255 if (this->lvl3.varnext_cmd == VCMD_UPDATE)
3256 {
3257 this->lvl3.varnext_cmd = VCMD_PRINT;
3258 this->lvl3.varcmd = VCMD_UPDATE;
3259
3260 obstack_strcat(obs, "server interpreter-exec mi \"-var-update var");
3261 obstack_strcat(obs, obj->name);
3262 obstack_strcat0(obs, "\"\n");
3263 return (char *)obstack_finish(obs);
3264 }
3265
3266 /* print */
3267 if (this->lvl3.varnext_cmd == VCMD_PRINT)
3268 {
3269 obj->state &= ~VS_ERROR;
3270 this->lvl3.varcmd = VCMD_PRINT;
3271
3272 obstack_strcat(obs, "server output ");
3273 obstack_strcat(obs, obj->format);
3274 obstack_strcat(obs, " ");
3275 obstack_strcat(obs, obj->expression);
3276 obstack_strcat0(obs, "\n");
3277 return (char *)obstack_finish(obs);
3278 }
3279
3280 /* evaluate object expression */
3281 if (this->lvl3.varnext_cmd == VCMD_EVALUATE)
3282 {
3283 this->lvl3.varcmd = VCMD_EVALUATE;
3284
3285 obstack_strcat(obs, "server interpreter-exec mi \"-var-evaluate-expression var");
3286 obstack_strcat(obs, obj->name);
3287 obstack_strcat0(obs, "\"\n");
3288 return (char *)obstack_finish(obs);
3289 }
3290 }
3291 break;
3292
3293 case OOB_COLLECT:
3294 gdb_cat(&res, this->lvl3.result);
3295 gdb_cat(&res, line);
3296 xfree(this->lvl3.result);
3297 this->lvl3.result = res;
3298 break;
3299
3300 case OOB_COMPLETE:
3301 # ifdef FEAT_GDB
3302 return varobj_complete(this, obs);
3303 # else
3304 /* start of object operations */
3305 if (result == NULL && this->var_buf > 0)
3306 cnb_startAtomic(this->var_buf);
3307
3308 result = varobj_complete(this, obs);
3309
3310 /* end of object operations */
3311 if (result == NULL && this->var_buf > 0)
3312 cnb_endAtomic(this->var_buf);
3313
3314 return result;
3315 # endif
3316 }
3317
3318 return NULL;
3319 }
3320
3321 # define VOBJ_NAME "^done,name=\"var"
3322 # define VOBJ_CHILD "\",numchild=\""
3323 # define VOBJ_SCOPE "\",in_scope=\""
3324 # define VOBJ_VALUE "^done,value=\""
3325 /*
3326 * Process the OOB_COMPLETE part of varobj_update()
3327 * Return anything not NULL except when last object in varlist
3328 * and after the last varcmd which may be: a failed VCMD_CREATE,
3329 * VCMD_DELETE, highlighted VCMD_UPDATE, VCMD_PRINT, VCMD_EVALUATE
3330 */
3331 static char *
varobj_complete(this,obs)3332 varobj_complete(this, obs)
3333 gdb_T *this;
3334 struct obstack *obs;
3335 {
3336 char_u *displine; /* the new display item line */
3337 char_u *res;
3338 # ifdef FEAT_GDB
3339 buf_T *oldbuf = curbuf;
3340 linenr_T lnum;
3341 win_T *win;
3342 # endif
3343 varobj_T *obj;
3344 char_u *ptr;
3345 char_u *last;
3346 char_u *child;
3347 char_u *quote;
3348
3349 if ((obj = this->lvl3.varitem) != NULL)
3350 {
3351 switch (this->lvl3.varcmd)
3352 {
3353 case VCMD_CREATE:
3354 /* result of object creation */
3355 if (this->lvl3.result != NULL
3356 && (ptr = STRSTR(this->lvl3.result, VOBJ_NAME)) != NULL
3357 && (ptr += strlen(VOBJ_NAME))
3358 && (quote = STRCHR(ptr, '"')) != NULL
3359 && (child = STRSTR(this->lvl3.result, VOBJ_CHILD)) != NULL)
3360 {
3361 obj->name = (char_u *)clewn_strnsave((char *)ptr, (quote - ptr));
3362 obj->children = (atoi((char *)(child + strlen(VOBJ_CHILD))) > 0);
3363
3364 FREE(this->lvl3.result);
3365 return (char *)obj; /* next command */
3366 }
3367 else
3368 {
3369 EMSG(_("Unable to create variable object"));
3370 remove_object(this, obj);
3371 FREE(this->lvl3.result);
3372 this->lvl3.varnext_cmd = VCMD_INIT;
3373 return (char *)this->lvl3.varitem; /* next object */
3374 }
3375 break;
3376
3377 case VCMD_DELETE:
3378 remove_object(this, obj);
3379 FREE(this->lvl3.result);
3380 this->lvl3.varnext_cmd = VCMD_INIT;
3381 return (char *)this->lvl3.varitem; /* next object */
3382
3383 case VCMD_CHILDREN:
3384 FREE(this->lvl3.result);
3385 return (char *)obj; /* next command */
3386
3387 case VCMD_FORMAT:
3388 FREE(this->lvl3.result);
3389 return (char *)obj; /* next command */
3390
3391 case VCMD_UPDATE:
3392 if (this->lvl3.result != NULL
3393 &&(ptr = STRSTR(this->lvl3.result, VOBJ_SCOPE)) != NULL)
3394 {
3395 ptr += strlen(VOBJ_SCOPE);
3396 if ((STRSTR(ptr, "false")) == ptr)
3397 {
3398 /* set "out of scope" highlighting (={-}) */
3399 varobj_hilite(this, obj, (int)'-', obs);
3400 goto nextobj;
3401 }
3402 else
3403 {
3404 /* object needs updating */
3405 FREE(this->lvl3.result);
3406 return (char *)obj; /* next command */
3407 }
3408 }
3409 else
3410 {
3411 /* turn off highlighting */
3412 varobj_hilite(this, obj, (int)'=', obs);
3413 goto nextobj;
3414 }
3415 break;
3416
3417 case VCMD_PRINT:
3418 /* fall back to GDB/MI when unable to print expression
3419 * because it's not the right frame */
3420 if (obj->state & VS_ERROR)
3421 {
3422 obj->state &= ~VS_ERROR;
3423 this->lvl3.varnext_cmd = VCMD_EVALUATE;
3424 FREE(this->lvl3.result);
3425 return (char *)obj; /* next command */
3426 }
3427
3428 /* build the display line including ={*}, the hiliting sign */
3429 obstack_strcat(obs, obj->name);
3430 obstack_strcat(obs, ":");
3431 obstack_strcat(obs, obj->format);
3432 obstack_strcat(obs, " ");
3433 obstack_strcat(obs, obj->expression);
3434 obstack_strcat(obs, " ={*} ");
3435 if (this->lvl3.result != NULL) {
3436 obstack_strcat0(obs, this->lvl3.result);
3437 }
3438 displine = (char_u *)obstack_finish(obs);
3439
3440 /* add the newly created object to variables window */
3441 if (obj->state & VS_INIT)
3442 {
3443 # ifdef FEAT_GDB
3444 if (this->var_buf != NULL)
3445 {
3446 lnum = BUFLASTL(this->var_buf);
3447
3448 /* edit variables buffer in available window */
3449 if (gdb_edit_file(this, this->var_buf, NULL, lnum, obs) != NULL)
3450 {
3451 /* add to variables buffer */
3452 if (ml_append(lnum, displine, 0, 0) == OK)
3453 {
3454 /* first line ever: remove empty line after the
3455 * one just inserted */
3456 if (lnum == 0)
3457 ml_delete(this->var_buf->b_ml.ml_line_count, FALSE);
3458
3459 changed_lines(this->var_buf->b_ml.ml_line_count - 1,
3460 0, this->var_buf->b_ml.ml_line_count, 1);
3461 }
3462
3463 /* update top line */
3464 curwin->w_cursor.lnum = this->var_buf->b_ml.ml_line_count;
3465 update_topline();
3466
3467 /* status line changed */
3468 curwin->w_redr_status = TRUE;
3469
3470 /* move back to previous window if still there */
3471 if ((win = gdb_btowin(oldbuf)) != NULL)
3472 win_goto(win);
3473 }
3474 obj->state &= ~VS_INIT;
3475 }
3476 # else
3477 if (this->var_buf > 0)
3478 {
3479 cnb_append(this->var_buf, displine, obs);
3480 obj->state &= ~VS_INIT;
3481 }
3482 # endif
3483 }
3484
3485 /* update and highlight object value */
3486 else
3487 varobj_replace(this, obj, displine, obs);
3488
3489 goto nextobj;
3490
3491 case VCMD_EVALUATE:
3492 if (this->lvl3.result != NULL
3493 && (ptr = STRSTR(this->lvl3.result, VOBJ_VALUE)) != NULL
3494 && (ptr += strlen(VOBJ_VALUE))
3495 && (quote = (char_u *)strrchr((char *)ptr, '"')) != NULL)
3496 {
3497 res = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
3498
3499 /* remove all `\' in `\"' */
3500 for (ptr = last = res; *ptr; ptr++)
3501 {
3502 if (*ptr != '\\' || *(ptr + 1) != '"')
3503 *last++ = *ptr;
3504 }
3505 *last = NUL;
3506
3507 /* build the display line including ={*}, the hiliting sign */
3508 obstack_strcat(obs, obj->name);
3509 obstack_strcat(obs, ":");
3510 obstack_strcat(obs, obj->format);
3511 obstack_strcat(obs, " ");
3512 obstack_strcat(obs, obj->expression);
3513 obstack_strcat(obs, " ={*} ");
3514 obstack_strcat0(obs, res);
3515 displine = (char_u *)obstack_finish(obs);
3516
3517
3518 /* update and highlight object value */
3519 varobj_replace(this, obj, displine, obs);
3520
3521 }
3522 goto nextobj;
3523 }
3524 }
3525
3526 return NULL;
3527 nextobj:
3528 FREE(this->lvl3.result);
3529 this->lvl3.varitem = obj->next;
3530 this->lvl3.varnext_cmd = VCMD_INIT;
3531
3532 /* When not at the end of varlist, return a non null object
3533 * to get gdb_oob_send() to call again varobj_update() for
3534 * the next object */
3535 return (char *)this->lvl3.varitem;
3536 }
3537
3538 # define OBHI_CHANGED " ={*} "
3539 # define OBHI_UNCHANGED " ={=} "
3540 # define OBHI_DESCOPED " ={-} "
3541 /* Change object highlighting to type */
3542 static void
varobj_hilite(this,obj,type,obs)3543 varobj_hilite(this, obj, type, obs)
3544 gdb_T *this;
3545 varobj_T *obj;
3546 int type; /* hiliting type, may be '*', '=' or '-' */
3547 struct obstack *obs;
3548 # ifdef FEAT_GDB
3549 {
3550 buf_T *oldbuf = curbuf;
3551 char_u *ptrn;
3552 char_u *line;
3553 char_u *oldline;
3554 char_u *ptr;
3555 pos_T pos;
3556 win_T *win;
3557
3558 pos.lnum = 1;
3559 pos.col = 0;
3560
3561 /* search for obj in variables window */
3562 obstack_strcat(obs, "^\\s*");
3563 obstack_strcat(obs, obj->name);
3564 obstack_strcat0(obs, ":");
3565 ptrn = (char_u *)obstack_finish(obs);
3566
3567 if (this->var_buf != NULL && obj != NULL && obj->name != NULL
3568 && ! (this->var_buf->b_ml.ml_flags & ML_EMPTY)
3569 && searchit(NULL, this->var_buf, &pos,
3570 FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
3571 {
3572 line = ml_get_buf(this->var_buf, pos.lnum, FALSE);
3573 oldline = obstack_strsave(obs, line);
3574
3575 if ((type == '-' && ((ptr = STRSTR(oldline, OBHI_CHANGED)) != NULL
3576 || (ptr = STRSTR(oldline, OBHI_UNCHANGED)) != NULL))
3577 || (type == '*' && ((ptr = STRSTR(oldline, OBHI_UNCHANGED)) != NULL
3578 || (ptr = STRSTR(oldline, OBHI_DESCOPED)) != NULL))
3579 || (type == '=' && ((ptr = STRSTR(oldline, OBHI_DESCOPED)) != NULL
3580 || (ptr = STRSTR(oldline, OBHI_CHANGED)) != NULL)))
3581 {
3582 *(ptr + 3) = type;
3583
3584 /* replace line */
3585 curbuf = this->var_buf;
3586 ml_replace(pos.lnum, oldline, TRUE);
3587 changed_lines(pos.lnum, 0, pos.lnum + 1, 0);
3588 curbuf = oldbuf;
3589
3590 if ((win = gdb_btowin(this->var_buf)) != NULL)
3591 redraw_win_later(win, NOT_VALID);
3592 }
3593 }
3594 }
3595 # else
3596 {
3597 char_u *oldline;
3598 char_u *line;
3599 char_u *ptr;
3600 int lnum;
3601
3602 /* search for obj in variables buffer */
3603 if (this->var_buf > 0 && obj != NULL && obj->name != NULL
3604 && (oldline = cnb_search_obj(obj->name, &lnum)) != NULL)
3605 {
3606 line = obstack_strsave(obs, oldline);
3607
3608 if ((type == '-' && ((ptr = STRSTR(line, OBHI_CHANGED)) != NULL
3609 || (ptr = STRSTR(line, OBHI_UNCHANGED)) != NULL))
3610 || (type == '*' && ((ptr = STRSTR(line, OBHI_UNCHANGED)) != NULL
3611 || (ptr = STRSTR(line, OBHI_DESCOPED)) != NULL))
3612 || (type == '=' && ((ptr = STRSTR(line, OBHI_DESCOPED)) != NULL
3613 || (ptr = STRSTR(line, OBHI_CHANGED)) != NULL)))
3614 {
3615 *(ptr + 3) = type;
3616
3617 /* replace line */
3618 cnb_replace(this->var_buf, line, lnum, obs);
3619 }
3620 }
3621 }
3622 # endif
3623
3624 /* Replace object line in variables buffer with line */
3625 static void
varobj_replace(this,obj,line,obs)3626 varobj_replace(this, obj, line, obs)
3627 gdb_T *this;
3628 varobj_T *obj;
3629 char_u *line;
3630 struct obstack *obs;
3631 # ifdef FEAT_GDB
3632 {
3633 buf_T *oldbuf = curbuf;
3634 win_T *oldwin = curwin;
3635 char_u *ptrn;
3636 linenr_T lnum;
3637 win_T *win;
3638 pos_T pos;
3639
3640 pos.lnum = 1;
3641 pos.col = 0;
3642
3643 /* search for object in variables window */
3644 obstack_strcat(obs, "^\\s*");
3645 obstack_strcat(obs, obj->name);
3646 obstack_strcat0(obs, ":");
3647 ptrn = (char_u *)obstack_finish(obs);
3648
3649 if (this->var_buf != NULL && obj != NULL && obj->name != NULL
3650 && ! (this->var_buf->b_ml.ml_flags & ML_EMPTY)
3651 && searchit(NULL, this->var_buf, &pos,
3652 FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
3653 {
3654 lnum = pos.lnum;
3655
3656 /* replace line */
3657 curbuf = this->var_buf;
3658 ml_replace(lnum, line, TRUE);
3659 changed_lines(lnum, 0, lnum + 1, 0);
3660
3661 if ((win = gdb_btowin(this->var_buf)) != NULL)
3662 {
3663 win->w_cursor.lnum = lnum;
3664
3665 curwin = win;
3666 check_cursor();
3667 update_topline();
3668 curwin = oldwin;
3669
3670 win->w_redr_status = TRUE;
3671
3672 redraw_win_later(win, NOT_VALID);
3673 }
3674 curbuf = oldbuf;
3675 }
3676 }
3677 # else
3678 {
3679 int lnum;
3680
3681 /* search for object in variables buffer */
3682 if (this->var_buf > 0 && obj != NULL && obj->name != NULL
3683 && cnb_search_obj(obj->name, &lnum) != NULL)
3684 cnb_replace(this->var_buf, line, lnum, obs);
3685 }
3686 # endif
3687
3688 /* Remove varobj item from valist */
3689 static void
remove_object(this,item)3690 remove_object(this, item)
3691 gdb_T *this;
3692 varobj_T *item;
3693 {
3694 varobj_T **pt;
3695 varobj_T *next;
3696
3697 for (pt = &(this->lvl3.varlist); *pt != NULL; pt = &((*pt)->next))
3698 if (*pt == item)
3699 {
3700 next = (*pt)->next;
3701 this->lvl3.varitem = next;
3702
3703 xfree(item->name);
3704 xfree(item->format);
3705 xfree(item->expression);
3706 xfree(item);
3707 *pt = next;
3708 return;
3709 }
3710 }
3711 # endif /* GDB_LVL3_SUPPORT */
3712
3713 /*
3714 * Add a breakpoint record to the head of the tmp list and highlite
3715 * the corresponding sign if the record refers to a loaded buffer
3716 * or to an editable file, and in this case load it.
3717 */
3718 void
gdb_process_record(this,address,at,line,source,obs)3719 gdb_process_record(this, address, at, line, source, obs)
3720 gdb_T *this;
3721 char_u *address; /* breakpoint address */
3722 char_u *at; /* breakpoint function */
3723 char_u *line; /* breakpoint line in source */
3724 char_u *source; /* breakpoint source file name */
3725 struct obstack *obs;
3726 # ifdef FEAT_GDB
3727 {
3728 win_T *oldwin = curwin;
3729 bpinfo_T *record = this->record;
3730 char_u *bp_file = NULL;
3731 buf_T *buf = NULL;
3732 char_u *ptrn;
3733 bpinfo_T *p, **pt;
3734 pos_T pos;
3735 int i;
3736 int lnum;
3737
3738 /*
3739 * Look for this breakpoint in previous list
3740 */
3741 for (pt = &(this->bpinfo); *pt != NULL; pt = &((*pt)->next))
3742 {
3743 p = *pt;
3744
3745 /* The breakpoint number exists in the old table:
3746 * update the highliting sign and do not even parse
3747 * the line (assume the file and line of a breakpoint
3748 * are immutable)
3749 * move the old record to tmplist and update its sign
3750 */
3751 if (record->id == p->id)
3752 {
3753 /* update enabled */
3754 if (record->enabled != p->enabled)
3755 {
3756 p->enabled = record->enabled;
3757 if ((p->typenr = gdb_define_sign(p->id, p->enabled)) != -1)
3758 {
3759 buf_addsign(p->buf, BP_SIGN_ID(p->id), p->lnum, p->typenr);
3760 update_debug_sign(p->buf, p->lnum);
3761 }
3762 }
3763
3764 # ifdef BP_INVALID_ANO_MISSING
3765 /* update disposition */
3766 p->disposition = record->disposition;
3767 # endif
3768
3769 /* update 'continue' */
3770 p->cont = record->cont;
3771
3772 /* move from old list to new list */
3773 *pt = p->next; /* unlink from old list */
3774 p->next = this->tmplist; /* link to head of new table */
3775 this->tmplist = p;
3776 return; /* record may be reused */
3777 }
3778 }
3779
3780 /*
3781 * A new breakpoint number: edit the file if possible
3782 */
3783 /* An asm breakpoint */
3784 if (address != NULL && at != NULL)
3785 {
3786 bp_file = obstack_strsave(obs, at);
3787
3788 /* Search all buffers in the asm buffer pool whose name starts
3789 * with bp_file and find the one containing a line starting
3790 * with address */
3791 obstack_strcat(obs, "^\\s*0x0*");
3792 obstack_strcat0(obs, address);
3793 ptrn = (char_u *)obstack_finish(obs);
3794
3795 for (i = 0; i < this->pool.max; i++)
3796 {
3797 pos.lnum = 1;
3798 pos.col = 0;
3799
3800 if (this->pool.buf[i] != NULL
3801 && STRSTR(this->pool.buf[i]->b_fname, bp_file) != NULL
3802 && !(this->pool.buf[i]->b_ml.ml_flags & ML_EMPTY)
3803 && searchit(NULL, this->pool.buf[i], &pos,
3804 FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
3805 {
3806 this->pool.age[i] = 0;
3807 record->lnum = pos.lnum;
3808 buf = this->pool.buf[i];
3809 break;
3810 }
3811 }
3812
3813 bp_file = NULL;
3814 }
3815
3816 /* A plain breakpoint */
3817 else if (line != NULL && (record->lnum = atoi((char *)line)) > 0
3818 && source != NULL)
3819 {
3820 bp_file = obstack_strsave(obs, source);
3821 }
3822
3823 /*
3824 * Edit the file or asm buffer
3825 * when the table is reported by GDB as having changed
3826 * or when this buffer is the frame buffer and the frame
3827 * is invalid (because: we might be setting a frame in
3828 * a newly disassembled buffer and must set again all
3829 * its breakpoints)
3830 */
3831 if ((bp_file != NULL || buf != NULL)
3832 && (this->bp_state & BPS_INVALID
3833 || (p_asm != 0
3834 && buf != NULL
3835 && buf == this->fr_buf
3836 && (this->bp_state & BPS_FR_INVALID)))
3837 )
3838 {
3839 /* bufIsChanged is TRUE when previous gdb_edit_file() failed because
3840 * the user cancelled the operation after having been warned the
3841 * buffer is changed. In this case, do not try to gdb_edit_file()
3842 * again for the next new breakpoints
3843 * (as the operation is cancelled). */
3844 if (! this->bufIsChanged)
3845 {
3846 if (gdb_edit_file(this, buf, bp_file, record->lnum, obs) != NULL)
3847 {
3848 /* MUST redraw the screen before calling update_debug_sign():
3849 * update_debug_sign() invokes win_update()
3850 * the screen might have been scrolled when Vim ask the
3851 * user to confirm changes made to the previous buffer */
3852 gdb_redraw(curwin->w_buffer);
3853
3854 record->buf = curwin->w_buffer;
3855
3856 if ((record->typenr =
3857 gdb_define_sign(record->id, record->enabled)) != -1)
3858 {
3859 /* add bp sign */
3860 buf_addsign(record->buf, BP_SIGN_ID(record->id),
3861 record->lnum, record->typenr);
3862 update_debug_sign(record->buf, record->lnum);
3863
3864 /* Set the frame sign again in case this is
3865 * a newly disassembled buffer */
3866 if (this->frame_pc != NULL
3867 && p_asm != 0
3868 && this->fr_buf == NULL
3869 && ! (record->buf->b_ml.ml_flags & ML_EMPTY))
3870 {
3871 pos.lnum = 1;
3872 pos.col = 0;
3873
3874 obstack_strcat(obs, "^\\s*0x0*");
3875 obstack_strcat0(obs, this->frame_pc);
3876 ptrn = (char_u *)obstack_finish(obs);
3877
3878 if (ptrn != NULL
3879 && searchit(NULL, record->buf, &pos, FORWARD,
3880 ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
3881 {
3882 gdb_fr_lite(this, record->buf, pos.lnum, obs);
3883 }
3884 }
3885
3886 /* Handle the case where bps are set after the frame sign:
3887 * new disassembled code or reediting a wiped-out plain
3888 * buffer or stepping in a newly disassembled buffer */
3889 if (record->buf == this->fr_buf
3890 && (this->bp_state & BPS_BP_HIT
3891 || (p_asm != 0
3892 && (this->bp_state & BPS_FR_INVALID)))
3893 && (lnum =
3894 buf_findsign(this->fr_buf, FRAME_SIGN)) != 0)
3895 {
3896 /* remove frame sign and add it again on top
3897 * of this new breakpoint */
3898 if (lnum == record->lnum)
3899 gdb_fr_lite(this, this->fr_buf, lnum, obs);
3900
3901 /* move back cursor to frame */
3902 gdb_set_cursor(gdb_btowin(this->fr_buf), lnum);
3903 }
3904 }
3905
3906 record->next = this->tmplist; /* link to head of new table */
3907 this->tmplist = record;
3908 this->record = NULL; /* forget record */
3909 }
3910 else
3911 {
3912 this->bufIsChanged = bufIsChanged(curbuf);
3913 win_goto(oldwin);
3914 }
3915 }
3916 }
3917
3918 return;
3919 }
3920 # else
3921 {
3922 bpinfo_T *record = this->record;
3923 char_u *bp_file = NULL;
3924 int buf = -1;
3925 bpinfo_T *p, **pt;
3926 char_u *fname;
3927 linenr_T lnum;
3928 int bufno;
3929
3930 /*
3931 * Look for this breakpoint in previous list
3932 */
3933 for (pt = &(this->bpinfo); *pt != NULL; pt = &((*pt)->next))
3934 {
3935 p = *pt;
3936
3937 /* The breakpoint number exists in the old table:
3938 * remove old sign and replace by new one
3939 * move the old record to tmplist and update its sign
3940 */
3941 if (record->id == p->id)
3942 {
3943 /* update enabled */
3944 if (record->enabled != p->enabled)
3945 {
3946 p->enabled = record->enabled;
3947 if ((p->typenr = gdb_define_bpsign(p, obs)) != -1)
3948 {
3949 cnb_buf_delsign(p->buf, BP_SIGN_ID(p->id));
3950 cnb_buf_addsign(p->buf, BP_SIGN_ID(p->id), p->typenr, p->lnum, obs);
3951 }
3952 }
3953
3954 # ifdef BP_INVALID_ANO_MISSING
3955 /* update disposition */
3956 p->disposition = record->disposition;
3957 # endif
3958
3959 /* update 'continue' */
3960 p->cont = record->cont;
3961
3962 /* move from old list to new list */
3963 *pt = p->next; /* unlink from old list */
3964 p->next = this->tmplist; /* link to head of new table */
3965 this->tmplist = p;
3966 return; /* record may be reused */
3967 }
3968 }
3969
3970 /*
3971 * A new breakpoint number: edit the file if possible
3972 */
3973 /* An asm breakpoint */
3974 if (address != NULL && at != NULL)
3975 {
3976 bp_file = obstack_strsave(obs, at);
3977
3978 /* Search all buffers in the asm buffer pool whose name starts
3979 * with bp_file and find the one containing a line starting
3980 * with address */
3981 for (bufno = 1; ! cnb_outofbounds(bufno); bufno++)
3982 {
3983 if ((fname = cnb_filename(bufno)) != NULL
3984 && STRSTR(fname, bp_file) != NULL
3985 && (lnum = searchfor(fname, address)) > 0)
3986 {
3987 record->lnum = lnum;
3988 buf = bufno;
3989 break;
3990 }
3991 }
3992
3993 bp_file = NULL;
3994 }
3995
3996 /* A plain breakpoint */
3997 else if (line != NULL && (record->lnum = atoi((char *)line)) > 0
3998 && source != NULL)
3999 {
4000 bp_file = obstack_strsave(obs, source);
4001 }
4002
4003 /*
4004 * Edit the file or asm buffer
4005 * when the table is reported by GDB as having changed
4006 * or when this buffer is the frame buffer and the frame
4007 * is invalid (because: we might be setting a frame in
4008 * a newly disassembled buffer and must set again all
4009 * its breakpoints)
4010 */
4011 if ((bp_file != NULL || cnb_isvalid_buffer(buf))
4012 && (this->bp_state & BPS_INVALID
4013 || (p_asm != 0
4014 && cnb_isvalid_buffer(buf)
4015 && buf == this->fr_buf
4016 && (this->bp_state & BPS_FR_INVALID)))
4017 )
4018 {
4019 if ((record->buf = gdb_edit_file(buf, bp_file, record->lnum, 1, obs)) > 0)
4020 {
4021 if ((record->typenr = gdb_define_bpsign(record, obs)) != -1)
4022 {
4023 /* add bp sign */
4024 cnb_buf_addsign(record->buf, BP_SIGN_ID(record->id),
4025 record->typenr, record->lnum, obs);
4026
4027 /* Set the frame sign again in case this is
4028 * a newly disassembled buffer */
4029 if (this->frame_pc != NULL
4030 && p_asm != 0
4031 && ! cnb_isvalid_buffer(this->fr_buf)
4032 && (fname = cnb_filename(record->buf)) != NULL
4033 && (lnum = searchfor(fname, this->frame_pc)) > 0)
4034 {
4035 gdb_fr_lite(this, record->buf, lnum, obs);
4036 }
4037
4038 /* Handle the case where bps are set after the frame sign:
4039 * new disassembled code or reediting a wiped-out plain
4040 * buffer or stepping in a newly disassembled buffer */
4041 if (record->buf == this->fr_buf
4042 && (this->bp_state & BPS_BP_HIT
4043 || (p_asm != 0
4044 && (this->bp_state & BPS_FR_INVALID)))
4045 && (lnum = find_fr_sign(this->fr_buf)) != 0)
4046 {
4047 /* remove frame sign and add it again on top
4048 * of this new breakpoint */
4049 if (lnum == record->lnum)
4050 gdb_fr_lite(this, this->fr_buf, lnum, obs);
4051 }
4052 }
4053
4054 record->next = this->tmplist; /* link to head of new table */
4055 this->tmplist = record;
4056 this->record = NULL; /* forget record */
4057 }
4058 }
4059
4060 return;
4061 }
4062 # endif /* FEAT_GDB */
4063
4064 /*
4065 * Parse str for annotation, set this->note.
4066 * Return byte address following annotation, NULL if none found.
4067 * Return byte address following ^Z^Z when unknown annotation.
4068 */
4069 static char_u *
parse_note(this,str)4070 parse_note(this, str)
4071 gdb_T *this;
4072 char_u *str; /* string to parse */
4073 {
4074 char_u *note = NULL;
4075 annotation_T *pt;
4076 int len;
4077
4078 if (str != NULL && (note = STRSTR(str, "\032\032")) != NULL)
4079 {
4080 this->note = ANO_ANY;
4081 note += 2;
4082
4083 for (pt = annotations; pt->str != NULL; pt++)
4084 {
4085 len = STRLEN(pt->str);
4086
4087 if (STRSTR(note, pt->str) == note
4088 && (*(note + len) == NUL || isspace(*(note + len))))
4089 {
4090 this->note = pt->id;
4091 return note + strlen((char *)pt->str);
4092 }
4093 }
4094 }
4095 return note;
4096 }
4097
4098 # ifndef FEAT_GDB
4099 /* Return annotation type of 'str' or ANO_NONE when not found. */
4100 static int
get_note(this,str)4101 get_note(this, str)
4102 gdb_T *this;
4103 char_u *str; /* string to parse */
4104 {
4105 int oldnote = this->note;
4106 int note = ANO_NONE;
4107
4108 if (IS_ANNOTATION(str) && parse_note(this, str) != NULL)
4109 note = this->note;
4110
4111 this->note = oldnote;
4112 return note;
4113 }
4114 # endif /* FEAT_GDB */
4115 # endif /* defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT) */
4116 #endif /* defined(FEAT_GDB) || defined(HAVE_CLEWN) */
4117